Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
#
# # An object oriented module for working with vectors. # Note that 'scalar' refers to the mathmatical definition, not Perl's +;) # package Math::Vector; use strict; use Carp; use Math::Trig; use vars qw($VERSION); $VERSION = '0.01'; use overload "=" => \&assign, "+=" => \&add_assign, "-=" => \&subtract_assign, "+" => \&add, "-" => \&subtract, "x" => \&cross_product, "." => \&dot_product, "*" => \&multiply_scalar, "/" => \&divide_scalar, "*=" => \&multiply_scalar_assign, "/=" => \&divide_scalar_assign; sub new { my ($package, %args) = @_; return bless { _i => $args{i} || 0, _j => $args{j} || 0, _k => $args{k} || 0, }, $package; } # $v_1 = $v_2; sub assign { my ($self, $other) = @_; carp ('Operation only permitted on Math::Vector objects') && retur +n undef unless (ref $other eq 'Math::Vector'); $self->set_i($other->i); $self->set_j($other->j); $self->set_k($other->k); return $self; } # $v_1 += $v_2; sub add_assign { my ($self, $other) = @_; carp ('Operation only permitted on Math::Vector objects') && retur +n undef unless (ref $other eq 'Math::Vector'); $self->set_i($other->i + $self->i); $self->set_j($other->j + $self->j); $self->set_k($other->k + $self->k); return $self; } # $v_1 -= $v_2; sub subtract_assign { my ($self, $other) = @_; carp ('Operation only permitted on Math::Vector objects') && retur +n undef unless (ref $other eq 'Math::Vector'); $self->set_i($other->i - $self->i); $self->set_j($other->j - $self->j); $self->set_k($other->k - $self->k); return $self; } # $v_new = $v_1 + $v_2; # $v_new = $v_1->add($v_2); sub add { my ($self, $other) = @_; carp ('Operation only permitted on Math::Vector objects') && retur +n undef unless (ref $other eq 'Math::Vector'); return new Math::Vector ( i => $self->i + $other->i, j => $self->j + $other->j, k => $self->k + $other->k, ); } # $v_new = $v_1 - $v_2; # $v_new = $v_1->subtract($v_2); sub subtract { my ($self, $other) = @_; carp ('Operation only permitted on Math::Vector objects') && retur +n undef unless (ref $other eq 'Math::Vector'); return new Math::Vector ( i => $self->i - $other->i, j => $self->j - $other->j, k => $self->k - $other->k, ); } # $v *= $scalar; sub multiply_scalar_assign { my ($self, $scalar) = @_; $self->set_i($self->i * $scalar); $self->set_j($self->j * $scalar); $self->set_k($self->k * $scalar); return $self; } # $v /= $scalar; sub divide_scalar_assign { my ($self, $scalar) = @_; carp ('Cannot divide by zero') && return undef unless ($scalar); $self->set_i($self->i / $scalar); $self->set_j($self->j / $scalar); $self->set_k($self->k / $scalar); return $self; } # $v_new = $v_1 * $scalar; # $v_new = $v_1->multiply_scalar($scalar); sub multiply_scalar { my ($self, $scalar) = @_; return new Math::Vector ( i => $self->i * $scalar, j => $self->j * $scalar, k => $self->k * $scalar, ); } # $v_new = $v_1 / $scalar; # $v_new = $v_1->divide_scalar($scalar); sub divide_scalar { my ($self, $scalar) = @_; carp ('Cannot divide by zero') && return undef unless ($scalar); return new Math::Vector ( i => $self->i / $scalar, j => $self->j / $scalar, k => $self->k / $scalar, ); } # $v_new = $v_1 x $v_2; # $v_new = $v_1->cross_product($v_2); sub cross_product { my ($self, $other) = @_; carp ('Operation only permitted on Math::Vector objects') && retur +n undef unless (ref $other eq 'Math::Vector'); return new Math::Vector ( i => $self->j * $other->k - $self->k * $other->j, j => $self->k * $other->i - $self->i * $other->k, z => $self->i * $other->j - $self->j * $other->i, ); } # $dot_product = $v_1 . $v_2; # $v_new = $v_1->dot_product($v_2); sub dot_product { my ($self, $other) = @_; carp ('Operation only permitted on Math::Vector objects') && retur +n undef unless (ref $other eq 'Math::Vector'); return $self->i * $other->i + $self->j * $other->j + $self->k * $o +ther->k; } # $magnitude = $v->magnitude(); sub magnitude { my $self = shift; return sqrt($self->i * $self->i + $self->j * $self->j + $self->k * + $self->k); } # Converts the vector to its normal # $v->normalize(); sub normalize { my $self = shift; my $m = $self->magnitude; carp('Cannot normalize a zero vector') && return undef unless ($m) +; $self->set_i( $self->i / $m ); $self->set_j( $self->j / $m ); $self->set_k( $self->k / $m ); } # $v_normalized = $v->normal(); sub normal { my $self = shift; my $normal = new Math::Vector (i=>$self->i, j=>$self->j, k=>$self- +>k); $normal->normalize(); return $normal; } # $angle_in_radians = $v_1->angle($v_2); sub angle { my ($self, $other) = @_; carp ('Operation only permitted on Math::Vector objects') && retur +n undef unless (ref $other eq 'Math::Vector'); my $self_m = $self->magnitude; my $other_m = $other->magnitude; carp('Vectors must be non-zero') && return undef unless ($self_m && $other_m); return (acos ( $self->dot_product($other) / ($self_m * $other_m) )); } sub orthogonal { my ($self, $other) = @_; carp ('Operation only permitted on Math::Vector objects') && retur +n undef unless (ref $other eq 'Math::Vector'); carp('Vectors must be non-zero') && return undef unless ($self->magnitude && $other->magnitude); # v1 is perpendicular to v2 if (v1 . v2 == 0) return ($self->dot_product($other) ? 0 : 1); } sub i { return $_[0]->{_i}; } sub j { return $_[0]->{_j}; } sub k { return $_[0]->{_k}; } sub set_i { my $self = shift; $self->{_i} = shift || 0; } sub set_j { my $self = shift; $self->{_j} = shift || 0; } sub set_k { my $self = shift; $self->{_k} = shift || 0; } 1; __END__ =head1 NAME Math::Vector - Object oriented vectors =head1 SYNOPSIS use Math::Vector; my $vector = new Math::Vector (i => $i, j => $j, k => $k); =head1 DESCRIPTION C<Math::Vector> provides an object oriented approach to working with v +ectors. Vectors created with this module are three-dimentional, although two-dimentional vectors are effectively achieved by omitting the 'k' c +omponent (which simply sets it to zero). It is important to note that this module will carp() if operations inv +olving division are attempted on zero values. A basic understanding of vecto +rs is expected, and the programmer should check the magnitude of a vector be +fore performing operations such as normalization or finding the angle. =head2 Conventions used in this document =over 10 The term 'scalar' is used in the mathmatical sense, and is a number re +presenting the amount by which a vector is scaled. Vector objects will always begin with a 'v'. (Example: $v, $v_1, $v_ne +w) =back =head1 OPERATORS C<Math::Vector> objects override many default operators. =item '=' $v_1 = $v_2; =item '+' $v_new = $v_1 + $v_2; =item '+=' $v_1 += $v_2 =item '-' $v_new = $v_1 - $v_2; =item '-=' $v_1 -= $v_2; =item 'x' $v_cross_product = $v_1 x $v_2; =item '.' $dot_product = $v_1 . $v_2; =item '*' $v_new = $v_1 * $scalar_multiple =item '*=' $v_1 *= $scalar_multiple; =item '/' $v_new = $v_1 / $scalar_multiple =item '/=' $v_1 /= $scalar_multiple; =head1 METHODS =head2 Creation =over 4 =item new Math::Vector (i => $i, j => $j, k => $k) Creates a new vector object with components ($i, $j, $k). =back =head2 Access =over 4 =item i Returns the value of the 'i' (first) component of the vector. =item j Returns the value of the 'j' (second) component of the vector. =item k Returns the value of the 'k' (third) component of the vector. =item ijk Returns a list of the three component values. This is included for co +nvenience, and is the same as: ($v->i, $v->j, $v->k); =back =head2 Direct Modifications =over 4 =item set_i (I) Sets the value for the 'i' component of the vector. $v->set_i($new_i_value) =item set_j (J) Sets the value for the 'j' component of the vector. $v->set_j($new_j_value) =item set_k (K) Sets the value for the 'k' component of the vector. $v->set_k($new_k_value) =back =head2 Calculations =over 4 =item dot_product (VECTOR) Returns the dot product of two vectors. $dot_product = $v_1->dot_product( $v_2 ); # Note this is equivalent: $dot_product = $v_1 . $v_2; =item cross_product (VECTOR) Returns the cross product of two vectors as a vector object. Note: yo +u cannot take the cross product of 2d vectors. $v_cross = $v_1->cross_product( $v_2 ); # Note this is equivalent: $v_cross = $v_1 x $v_2; =item magnitude Returns the magnitude of the vector. $magnitude = $v->magnitude; =item normalize Normalizes the vector. $v->normalize; =item normal Returns the normal of a vector as a new vector object. $v_normalized = $v->normal; # Note the following is similar, but does not preserve $v : $v->normalize; $v_normalized = $v; =item angle (VECTOR) Returns the angle in radians between two vectors. $angle = $v_1->angle( $v_2 ); =item orthogonal (VECTOR) Returns 1 if vectors are orthogonal (or perpendicular), 0 if they are not, and undef if either is a zero vector. $orthogonal = $v_1->orthogonal( $v_2 ); if ($orthogonal) { # $v_1 and $v_2 are perpendicular } elsif (defined $orthogonal) { # they are not } else { # you tried to test a zero vector } =back =head1 SEE ALSO Math::Trig, Carp =head1 BUGS Please email the author (E<lt>mark@sporkstorms.orgE<gt>) with any. =head1 FEEDBACK Feel free to email the author with any questions, comments, or request +s. This module was initially written for personal use, and may be lacking some desired features. I (Mark) would be glad to add anything to it that you might need. =head1 AUTHOR Mark Stratman, E<lt>mark@sporkstorms.orgE<gt> =head1 COPYRIGHT Copyright (c) 2001, Mark Stratman. All Rights Reserved. This modules is free software. It may be used, redistributed and/or modified under the same terms as Perl itself. =cut #

In reply to Math::Vector - request for comments by count0

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2024-03-29 01:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found