- Vector2

- Synopsis
- Description
- Constructors

- new
- vector2
- units

- Methods

- check
- is
- accuracy
- round
- components
- clone
- length
- print
- normalize
- rightAngle
- dot
- angle
- add
- subtract
- multiply
- divide
- equals

- Operators

- add
- subtract
- multiply
- divide
- angle
- equals
- print

- Exports
- Credits

- Author
- Copyright
- License

# Vector2

Manipulate 2D vectors

    PhilipRBrenan@yahoo.com, 2004, Perl License

## Synopsis

Example t/vector2.t

     #_ Vector _____________________________________________________________
     # Test 2d vectors
     # philiprbrenan@yahoo.com, 2004, Perl License
     #______________________________________________________________________

     use Math::Zap::Vector2 vector2=>v, units=>u;
     use Test::Simple tests=>7;

     my ($x, $y) = u();

     ok(!$x                    == 1);
     ok(2*$x+3*$y              == v( 2,  3));
     ok(-$x-$y                 == v(-1, -1));
     ok((2*$x+3*$y) + (-$x-$y) == v( 1,  2));
     ok((2*$x+3*$y) * (-$x-$y) == -5);
     ok($x*2                   == v( 2,  0));
     ok($y/2                   == v( 0,  0.5));

## Description

Manipulate 2D vectors

     package Math::Zap::Vector2;
     $VERSION=1.03;
     use Math::Trig;
     use Carp;
     use constant debug => 0; # Debugging level

## Constructors

### new

Create a vector from numbers

     sub new($$)
      {return bless {x=>$_[0], y=>$_[1]} unless debug;
       my ($x, $y) = @_;
       round(bless({x=>$x, y=>$y}));
      }

### vector2

Create a vector from numbers - synonym for new

     sub vector2($$) {new($_[0],$_[1])}

### units

Unit vectors

     $x = new(1,0);
     $y = new(0,1);

     sub units() {($x, $y)}

## Methods

### check

Check its a vector

     sub check(@)
      {if (debug)
        {for my $v(@_)
          {confess "$v is not a vector2" unless ref($v) eq __PACKAGE__;
          }
        }
       return (@_)
      }

### is

Test its a vector

     sub is(@)
      {for my $v(@_)
        {return 0 unless ref($v) eq __PACKAGE__;
        }
       1;
      }

### accuracy

Get/Set accuracy for comparisons

     my $accuracy = 1e-10;

     sub accuracy
      {return $accuracy unless scalar(@_);
       $accuracy = shift();
      }

### round

Round: round to nearest integer if within accuracy of that integer

     sub round($)
      {unless (debug)
        {return $_[0];
        }
       else
        {my ($a) = @_;
         for my $k(keys(%$a))
          {my $n = $a->{$k};
           my $N = int($n);
           $a->{$k} = $N if abs($n-$N) < $accuracy;
          }
         return $a;
        }
      }

### components

x,y components of vector

     sub x($) {check(@_) if debug; $_[0]->{x}}
     sub y($) {check(@_) if debug; $_[0]->{y}}

### clone

Create a vector from another vector

     sub clone($)
      {my ($v) = check(@_); # Vectors
       round bless {x=>$v->x, y=>$v->y};
      }

### length

Length of a vector

     sub length($)
      {check(@_[0..0]) if debug; # Vectors
       sqrt($_[0]->{x}**2+$_[0]->{y}**2);
      }

### print

Print vector

     sub print($)
      {my ($v) = check(@_); # Vectors
       my ($x, $y) = ($v->x, $v->y);

       "vector2($x, $y)";
      }

### normalize

Normalize vector

     sub norm($)
      {my ($v) = check(@_); # Vectors
       my $l = $v->length;

       $l > 0 or confess "Cannot normalize zero length vector $v";

       new($v->x / $l, $v->y / $l);
      }

### rightAngle

At right angles

     sub rightAngle($)
      {my ($v) = check(@_); # Vectors
       new(-$v->y, $v->x);
      }

### dot

Dot product

     sub dot($$)
      {my ($a, $b) = check(@_); # Vectors
       $a->x*$b->x+$a->y*$b->y;
      }

### angle

Angle between two vectors

     sub angle($$)
      {my ($a, $b) = check(@_); # Vectors
       acos($a->norm->dot($b->norm));
      }

### add

Add vectors

     sub add($$)
      {my ($a, $b) = check(@_); # Vectors
       new($a->x+$b->x, $a->y+$b->y);
      }

### subtract

Subtract vectors

     sub subtract($$)
      {check(@_) if debug; # Vectors
       new($_[0]->{x}-$_[1]->{x}, $_[0]->{y}-$_[1]->{y});
      }

### multiply

Vector times a scalar

     sub multiply($$)
      {my ($a) = check(@_[0..0]); # Vector
       my ($b) =       @_[1..1];  # Scalar

       confess "$b is not a scalar" if ref($b);
       new($a->x*$b, $a->y*$b);
      }

### divide

Vector divided by a non zero scalar

     sub divide($$)
      {my ($a) = check(@_[0..0]); # Vector
       my ($b) =       @_[1..1];  # Scalar

       confess "$b is not a scalar" if ref($b);
       confess "$b is zero"         if $b == 0;
       new($a->x/$b, $a->y/$b);
      }

### equals

Equals to within accuracy

     sub equals($$)
      {my ($a, $b) = check(@_); # Vectors
       abs($a->x-$b->x) < $accuracy and
       abs($a->y-$b->y) < $accuracy;
      }

## Operators

# Operator overloads

     use overload
      '+'        => \&add3,      # Add two vectors
      '-'        => \&subtract3, # Subtract one vector from another
      '*'        => \&multiply3, # Times by a scalar, or vector dot product
      '/'        => \&divide3,   # Divide by a scalar
      '<'        => \&angle3,    # Angle in radians between two vectors
      '>'        => \&angle3,    # Angle in radians between two vectors
      '=='       => \&equals3,   # Equals
      '""'       => \&print3,    # Print
      '!'        => \&length,    # Length
      'fallback' => FALSE;

### add

Add operator.

     sub add3
      {my ($a, $b) = @_;
       $a->add($b);
      }

### subtract

Subtract operator.

     sub subtract3
      {#my ($a, $b, $c) = @_;
       #return $a->subtract($b) if ref($b);
       return new($_[0]->{x}-$_[1]->{x}, $_[0]->{y}-$_[1]->{y}) if ref($_[1]);
       new(-$_[0]->{x}, -$_[0]->{y});
      }

### multiply

Multiply operator.

     sub multiply3
      {my ($a, $b) = @_;
       return $a->dot     ($b) if ref($b);
       return $a->multiply($b);
      }

### divide

Divide operator.

     sub divide3
      {my ($a, $b, $c) = @_;
       return $a->divide($b);
      }

### angle

Angle between two vectors.

     sub angle3
      {my ($a, $b, $c) = @_;
       return $a->angle($b);
      }

### equals

Equals operator.

     sub equals3
      {my ($a, $b, $c) = @_;
       return $a->equals($b);
      }

### print

Print a vector.

     sub print3
      {my ($a) = @_;
       return $a->print;
      }

## Exports

Export vector2, units, check, is

     use Math::Zap::Exports qw(
       vector2 ($$)
       units   ()
       check   (@)
       is      (@)
      );

     #_ Vector2 ____________________________________________________________
     # Package loaded successfully
     #______________________________________________________________________

     1;

## Credits

### Author

philiprbrenan@yahoo.com

### Copyright

philiprbrenan@yahoo.com, 2004

### License

Perl License.