File Coverage

blib/lib/Math/Zap/Vector2.pm
Criterion Covered Total %
statement 66 80 82.5
branch 11 18 61.1
condition n/a
subroutine 27 33 81.8
pod 18 28 64.2
total 122 159 76.7


line stmt bran cond sub pod time code
1            
2             =head1 Vector2
3            
4             Manipulate 2D vectors
5            
6             PhilipRBrenan@yahoo.com, 2004, Perl License
7            
8            
9             =head2 Synopsis
10            
11             Example t/vector2.t
12            
13             #_ Vector _____________________________________________________________
14             # Test 2d vectors
15             # philiprbrenan@yahoo.com, 2004, Perl License
16             #______________________________________________________________________
17            
18             use Math::Zap::Vector2 vector2=>v, units=>u;
19             use Test::Simple tests=>7;
20            
21             my ($x, $y) = u();
22            
23             ok(!$x == 1);
24             ok(2*$x+3*$y == v( 2, 3));
25             ok(-$x-$y == v(-1, -1));
26             ok((2*$x+3*$y) + (-$x-$y) == v( 1, 2));
27             ok((2*$x+3*$y) * (-$x-$y) == -5);
28             ok($x*2 == v( 2, 0));
29             ok($y/2 == v( 0, 0.5));
30            
31            
32            
33             =head2 Description
34            
35             Manipulate 2D vectors
36            
37             =cut
38            
39            
40             package Math::Zap::Vector2;
41             $VERSION=1.07;
42 7     7   5884 use Math::Trig;
  7         133574  
  7         1503  
43 7     7   65 use Carp;
  7         14  
  7         467  
44 7     7   43 use constant debug => 0; # Debugging level
  7         11  
  7         10646  
45            
46            
47             =head2 Constructors
48            
49            
50             =head3 new
51            
52             Create a vector from numbers
53            
54             =cut
55            
56            
57 661     661 1 6371 sub new($$)
58             {return bless {x=>$_[0], y=>$_[1]} unless debug;
59 0         0 my ($x, $y) = @_;
60 0         0 round(bless({x=>$x, y=>$y}));
61             }
62            
63            
64             =head3 vector2
65            
66             Create a vector from numbers - synonym for L
67            
68             =cut
69            
70            
71 288     288 1 613 sub vector2($$) {new($_[0],$_[1])}
72            
73            
74             =head3 units
75            
76             Unit vectors
77            
78             =cut
79            
80            
81             $x = new(1,0);
82             $y = new(0,1);
83            
84 1     1 1 4 sub units() {($x, $y)}
85            
86            
87             =head2 Methods
88            
89            
90             =head3 check
91            
92             Check its a vector
93            
94             =cut
95            
96            
97             sub check(@)
98 248     248 1 354 {if (debug)
99             {for my $v(@_)
100             {confess "$v is not a vector2" unless ref($v) eq __PACKAGE__;
101             }
102             }
103 248         430 return (@_)
104             }
105            
106            
107             =head3 is
108            
109             Test its a vector
110            
111             =cut
112            
113            
114 66 100       248 sub is(@)
115 66     66 1 119 {for my $v(@_)
116             {return 0 unless ref($v) eq __PACKAGE__;
117             }
118 59         276 1;
119             }
120            
121            
122             =head3 accuracy
123            
124             Get/Set accuracy for comparisons
125            
126             =cut
127            
128            
129             my $accuracy = 1e-10;
130            
131             sub accuracy
132 0 0   0 1 0 {return $accuracy unless scalar(@_);
133 0         0 $accuracy = shift();
134             }
135            
136            
137             =head3 round
138            
139             Round: round to nearest integer if within accuracy of that integer
140            
141             =cut
142            
143            
144 0         0 sub round($)
145 0     0 1 0 {unless (debug)
146             {return $_[0];
147             }
148             else
149             {my ($a) = @_;
150             for my $k(keys(%$a))
151             {my $n = $a->{$k};
152             my $N = int($n);
153             $a->{$k} = $N if abs($n-$N) < $accuracy;
154             }
155             return $a;
156             }
157             }
158            
159            
160             =head3 components
161            
162             x,y components of vector
163            
164             =cut
165            
166            
167 449     449 0 435 sub x($) {check(@_) if debug; $_[0]->{x}}
  449         1554  
168 430     430 0 441 sub y($) {check(@_) if debug; $_[0]->{y}}
  430         1666  
169            
170            
171             =head3 clone
172            
173             Create a vector from another vector
174            
175             =cut
176            
177            
178 0     0 1 0 sub clone($)
179             {my ($v) = check(@_); # Vectors
180 0         0 round bless {x=>$v->x, y=>$v->y};
181             }
182            
183            
184             =head3 length
185            
186             Length of a vector
187            
188             =cut
189            
190            
191 118     118 1 220 sub length($)
192             {check(@_[0..0]) if debug; # Vectors
193 118         392 sqrt($_[0]->{x}**2+$_[0]->{y}**2);
194             }
195            
196            
197             =head3 print
198            
199             Print vector
200            
201             =cut
202            
203            
204 6     6 1 11 sub print($)
205             {my ($v) = check(@_); # Vectors
206 6         12 my ($x, $y) = ($v->x, $v->y);
207            
208 6         42 "vector2($x, $y)";
209             }
210            
211            
212             =head3 normalize
213            
214             Normalize vector
215            
216             =cut
217            
218            
219 108     108 0 204 sub norm($)
220             {my ($v) = check(@_); # Vectors
221 108         211 my $l = $v->length;
222            
223 108 50       250 $l > 0 or confess "Cannot normalize zero length vector $v";
224            
225 108         201 new($v->x / $l, $v->y / $l);
226             }
227            
228            
229             =head3 rightAngle
230            
231             At right angles
232            
233             =cut
234            
235            
236 2     2 1 8 sub rightAngle($)
237             {my ($v) = check(@_); # Vectors
238 2         6 new(-$v->y, $v->x);
239             }
240            
241            
242             =head3 dot
243            
244             Dot product
245            
246             =cut
247            
248            
249 55     55 1 143 sub dot($$)
250             {my ($a, $b) = check(@_); # Vectors
251 55         119 $a->x*$b->x+$a->y*$b->y;
252             }
253            
254            
255             =head3 angle
256            
257             Angle between two vectors
258            
259             =cut
260            
261            
262 0     0 1 0 sub angle($$)
263             {my ($a, $b) = check(@_); # Vectors
264 0         0 acos($a->norm->dot($b->norm));
265             }
266            
267            
268             =head3 add
269            
270             Add vectors
271            
272             =cut
273            
274            
275 30     30 1 52 sub add($$)
276             {my ($a, $b) = check(@_); # Vectors
277 30         63 new($a->x+$b->x, $a->y+$b->y);
278             }
279            
280            
281             =head3 subtract
282            
283             Subtract vectors
284            
285             =cut
286            
287            
288 0     0 1 0 sub subtract($$)
289             {check(@_) if debug; # Vectors
290 0         0 new($_[0]->{x}-$_[1]->{x}, $_[0]->{y}-$_[1]->{y});
291             }
292            
293            
294             =head3 multiply
295            
296             Vector times a scalar
297            
298             =cut
299            
300            
301 26     26 1 63 sub multiply($$)
302             {my ($a) = check(@_[0..0]); # Vector
303 26         51 my ($b) = @_[1..1]; # Scalar
304            
305 26 50       65 confess "$b is not a scalar" if ref($b);
306 26         54 new($a->x*$b, $a->y*$b);
307             }
308            
309            
310             =head3 divide
311            
312             Vector divided by a non zero scalar
313            
314             =cut
315            
316            
317 2     2 1 7 sub divide($$)
318             {my ($a) = check(@_[0..0]); # Vector
319 2         6 my ($b) = @_[1..1]; # Scalar
320            
321 2 50       6 confess "$b is not a scalar" if ref($b);
322 2 50       8 confess "$b is zero" if $b == 0;
323 2         9 new($a->x/$b, $a->y/$b);
324             }
325            
326            
327             =head3 equals
328            
329             Equals to within accuracy
330            
331             =cut
332            
333            
334 16     16 1 48 sub equals($$)
335             {my ($a, $b) = check(@_); # Vectors
336 16 50       47 abs($a->x-$b->x) < $accuracy and
337             abs($a->y-$b->y) < $accuracy;
338             }
339            
340            
341             =head2 Operators
342            
343             # Operator overloads
344            
345             =cut
346            
347            
348             use overload
349 7         111 '+' => \&add3, # Add two vectors
350             '-' => \&subtract3, # Subtract one vector from another
351             '*' => \&multiply3, # Times by a scalar, or vector dot product
352             '/' => \÷3, # Divide by a scalar
353             '<' => \&angle3, # Angle in radians between two vectors
354             '>' => \&angle3, # Angle in radians between two vectors
355             '==' => \&equals3, # Equals
356             '""' => \&print3, # Print
357             '!' => \&length, # Length
358 7     7   65 'fallback' => FALSE;
  7         13  
359            
360            
361             =head3 add
362            
363             Add operator.
364            
365             =cut
366            
367            
368             sub add3
369 30     30 0 46 {my ($a, $b) = @_;
370 30         78 $a->add($b);
371             }
372            
373            
374             =head3 subtract
375            
376             Subtract operator.
377            
378             =cut
379            
380            
381             sub subtract3
382             {#my ($a, $b, $c) = @_;
383             #return $a->subtract($b) if ref($b);
384 191 100   191 0 928 return new($_[0]->{x}-$_[1]->{x}, $_[0]->{y}-$_[1]->{y}) if ref($_[1]);
385 8         26 new(-$_[0]->{x}, -$_[0]->{y});
386             }
387            
388            
389             =head3 multiply
390            
391             Multiply operator.
392            
393             =cut
394            
395            
396             sub multiply3
397 81     81 0 133 {my ($a, $b) = @_;
398 81 100       232 return $a->dot ($b) if ref($b);
399 26         65 return $a->multiply($b);
400             }
401            
402            
403             =head3 divide
404            
405             Divide operator.
406            
407             =cut
408            
409            
410             sub divide3
411 2     2 0 6 {my ($a, $b, $c) = @_;
412 2         8 return $a->divide($b);
413             }
414            
415            
416             =head3 angle
417            
418             Angle between two vectors.
419            
420             =cut
421            
422            
423             sub angle3
424 0     0 0 0 {my ($a, $b, $c) = @_;
425 0         0 return $a->angle($b);
426             }
427            
428            
429             =head3 equals
430            
431             Equals operator.
432            
433             =cut
434            
435            
436             sub equals3
437 16     16 0 40 {my ($a, $b, $c) = @_;
438 16         59 return $a->equals($b);
439             }
440            
441            
442             =head3 print
443            
444             Print a vector.
445            
446             =cut
447            
448            
449             sub print3
450 6     6 0 7 {my ($a) = @_;
451 6         10 return $a->print;
452             }
453            
454            
455             =head2 Exports
456            
457             Export L, L, L, L
458            
459             =cut
460            
461            
462 7         44 use Math::Zap::Exports qw(
463             vector2 ($$)
464             units ()
465             check (@)
466             is (@)
467 7     7   6339 );
  7         15  
468            
469             #_ Vector2 ____________________________________________________________
470             # Package loaded successfully
471             #______________________________________________________________________
472            
473             1;
474            
475            
476             =head2 Credits
477            
478             =head3 Author
479            
480             philiprbrenan@yahoo.com
481            
482             =head3 Copyright
483            
484             philiprbrenan@yahoo.com, 2004
485            
486             =head3 License
487            
488             Perl License.
489            
490            
491             =cut