Philip R Brenan

# Vector

Manipulate 3D vectors

PhilipRBrenan@yahoo.com, 2004, Perl licence

## Synopsis

Example t/vector.t

`````` #_ Vector _____________________________________________________________
# Test 3d vectors
#______________________________________________________________________

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

``````

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

``````

`````` use overload
'-'        => \&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;

``````

`````` sub add3
{my (\$a, \$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     (@)
);

#______________________________________________________________________
#______________________________________________________________________

1;

``````

## Credits

### Author

philiprbrenan@yahoo.com

philiprbrenan@yahoo.com, 2004