Vector

Manipulate 3D vectors

PhilipRBrenan@yahoo.com, 2004, Perl licence

Synopsis

Example t/vector.t

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

use Math::Zap::Vector vector=>'v', units=>'u';
use Test::Simple tests=>7;

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

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

Description

Manipulate 3 dimensional vectors via operators.

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

Constructors

new

Create a vector from numbers

sub new($$$)
 {return round(bless({x=>$_[0], y=>$_[1], z=>$_[2]})) if debug; 
  bless {x=>$_[0], y=>$_[1], z=>$_[2]}; 
 }

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

units

Unit vectors

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

Methods

check

Check its a vector

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

is

Test its a vector

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

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;
   }
 }

x,y,z

x,y,z components of vector

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

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

clone

Create a vector from another vector

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

length

Length of a vector

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

print

Print vector

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

  "vector($x, $y, $z)";
 } 

norm

Normalize vector

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

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

  $v->{x} /= $l;
  $v->{y} /= $l;
  $v->{z} /= $l;
  $v;
 } 

dot

Dot product

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

angle

Angle between two vectors

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

cross

Cross product

sub cross($$)
 {my ($a, $b) = check(@_); # Vectors

	new
  ((($a->y * $b->z) - ($a->z * $b->y)),
	 (($a->z * $b->x) - ($a->x * $b->z)),
	 (($a->x * $b->y) - ($a->y * $b->x))
  );
 }

add

Add vectors

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

subtract

Subtract vectors

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

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, $a->z*$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, $a->z/$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 and
  abs($a->z-$b->z) < $accuracy;
 }

Operator Overloads

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
 'x'        => \&cross3,    # BEWARE LOW PRIORITY! Cross product
 '<'        => \&angle3,    # Angle in radians between two vectors
 '>'        => \&angle3,    # Angle in radians between two vectors
 '=='       => \&equals3,   # Equals
 '""'       => \&print3,    # Print
 '!'        => \&length,    # Length
 'fallback' => FALSE;

Add operator

Add operator, see "add"

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

Subtract Operator

Subtract operator.

sub subtract3
 {return new($_[0]->{x}-$_[1]->{x}, $_[0]->{y}-$_[1]->{y}, $_[0]->{z}-$_[1]->{z}) if ref($_[1]);
  new(-$_[0]->{x}, -$_[0]->{y}, -$_[0]->{z});
 }

Multiply Operator

Multiply operator, see "multiply"

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

Divide Operator

Divide operator, see "divide"

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

Cross Operator

Cross operator, see "cross"

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

Angle Operator

Angle operator, see "angle"

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

Equals Operator

Equals operator, see "equals"

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

Print a vector, see "print"

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

Export Definitions

Export "vector", "units", "check", "is"

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

#______________________________________________________________________
# Package loaded successfully
#______________________________________________________________________

1;

Credits

Author

philiprbrenan@yahoo.com

philiprbrenan@yahoo.com, 2004

License

Perl License.