File Coverage

blib/lib/Math/Vectors2.pm
Criterion Covered Total %
statement 131 137 95.6
branch 10 14 71.4
condition n/a
subroutine 50 53 94.3
pod 28 31 90.3
total 219 235 93.1


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -I/home/phil/perl/cpan/DataTableText/lib/
2             #-------------------------------------------------------------------------------
3             # Vectors in two dimensions
4             # Philip R Brenan at gmail dot com, Appa Apps Ltd Inc., 2017-2020
5             #-------------------------------------------------------------------------------
6             # podDocumentation
7             package Math::Vectors2;
8             require v5.16;
9             our $VERSION = 20200402;
10 1     1   696 use warnings FATAL => qw(all);
  1         7  
  1         39  
11 1     1   6 use strict;
  1         2  
  1         22  
12 1     1   4 use Carp qw(confess);
  1         2  
  1         85  
13 1     1   3514 use Data::Table::Text qw(genHash);
  1         147277  
  1         1382  
14 1     1   1099 use Math::Trig;
  1         17123  
  1         2055  
15              
16             my $nearness = 1e-6; # Definition of near
17              
18             sub near($$) # Check two scalars are near each other
19 384     384 0 3331 {my ($o, $p) = @_;
20 384         1312 abs($p-$o) < $nearness
21             }
22              
23             sub near2($$) # Check two vectors are near each other
24 13     13 0 21 {my ($o, $p) = @_;
25 13         28 $o->d($p) < $nearness
26             }
27              
28             #D1 Methods # Vector methods.
29              
30             sub new($$) #S Create new vector from components.
31 493     493 1 7895 {my ($x, $y) = @_; # X component, Y component
32 493         1376 genHash(__PACKAGE__, # Attributes of a vector
33             x => $x, # X coordinate
34             y => $y, # Y coordinate
35             );
36             }
37              
38             sub zeroAndUnits() #S Create the useful vectors: o=(0,0), x=(1,0), y=(0,1)
39 12     12 1 41 {map {&new(@$_)} ([0, 0], [1, 0], [0, 1])
  36         1097  
40             }
41              
42             sub eq($$) # Whether two vectors are equal to within the accuracy of floating point arithmetic
43 13     13 1 22 {my ($o, $p) = @_; # First vector, second vector
44 13         27 near2($o, $p)
45             }
46              
47             sub zero($) # Whether a vector is equal to zero within the accuracy of floating point arithmetic
48 3     3 1 8 {my ($o) = @_; # Vector
49 3 100       51 near($o->x, 0) && near($o->y, 0)
50             }
51              
52             sub print($@) # Print one or more vectors.
53 13     13 1 25 {my ($p, @p) = @_; # Vector to print, more vectors to print
54 13         26 join ', ', map {'('.$_->x.','.$_->y.')'} @_
  13         215  
55             }
56              
57             sub clone($) # Clone a vector.
58 59     59 1 89 {my ($o) = @_; # Vector to clone
59 59         1005 new($o->x, $o->y)
60             }
61              
62             sub Plus($@) # Add zero or more other vectors to the first vector and return the result.
63 23     23 1 745 {my ($o, @p) = @_; # First vector, other vectors
64 23         41 for(@p)
65 23         449 {$o->x += $_->x;
66 23         459 $o->y += $_->y;
67             }
68             $o
69 23         244 }
70              
71             sub plus($@) # Add zero or more other vectors to a copy of the first vector and return the result.
72 21     21 1 36 {my ($o, @p) = @_; # First vector, other vectors
73 21         45 $o->clone->Plus(@p)
74             }
75              
76             sub Minus($@) # Subtract zero or more vectors from the first vector and return the result.
77 7     7 1 216 {my ($o, @p) = @_; # First vector, other vectors
78 7         16 for(@p)
79 7         134 {$o->x -= $_->x;
80 7         146 $o->y -= $_->y;
81             }
82             $o
83 7         106 }
84              
85             sub minus($@) # Subtract zero or more vectors from a copy of the first vector and return the result.
86 5     5 1 11 {my ($o, @p) = @_; # First vector, other vectors
87 5         11 $o->clone->Minus(@p)
88             }
89              
90             sub Multiply($$) # Multiply a vector by a scalar and return the result.
91 29     29 1 901 {my ($o, $m) = @_; # Vector, scalar to multiply by
92 29         491 $o->x *= $m; $o->y *= $m;
  29         562  
93 29         271 $o
94             }
95              
96             sub multiply($$) # Multiply a copy of a vector by a scalar and return the result.
97 27     27 1 41 {my ($o, $m) = @_; # Vector, scalar to multiply by
98 27         53 $o->clone->Multiply($m)
99             }
100              
101             sub Divide($$) # Divide a vector by a scalar and return the result.
102 7     7 1 178 {my ($o, $d) = @_; # Vector, scalar to multiply by
103 7         119 $o->x /= $d; $o->y /= $d;
  7         134  
104 7         68 $o
105             }
106              
107             sub divide($$) # Divide a copy of a vector by a scalar and return the result.
108 5     5 1 10 {my ($o, $d) = @_; # Vector, scalar to divide by
109 5         10 $o->clone->Divide($d)
110             }
111              
112             sub l($) # Length of a vector.
113 1523     1523 1 40305 {my ($o) = @_; # Vector
114 1523         24093 sqrt($o->x**2 + $o->y**2)
115             }
116              
117             sub l2($) # Length squared of a vector.
118 2     2 1 5 {my ($o) = @_; # Vector
119 2         34 $o->x**2 + $o->y**2
120             }
121              
122             sub d($$) # Distance between the points identified by two vectors when placed on the same point.
123 14     14 1 23 {my ($o, $p) = @_; # Vector 1, vector 2
124 14         226 sqrt(($o->x-$p->x)**2 + ($o->y-$p->y)**2)
125             }
126              
127             sub d2($$) # Distance squared between the points identified by two vectors when placed on the same point.
128 1     1 1 5 {my ($o, $p) = @_; # Vector 1, vector 2
129 1         18 ($o->x-$p->x)**2 + ($o->y-$p->y)**2
130             }
131              
132             sub n($) # Return a normalized a copy of a vector.
133 1     1 1 3 {my ($o) = @_; # Vector
134 1         3 my $l = $o->l;
135 1 50       26 $l == 0 and confess;
136 1         18 new($o->x / $l, $o->y / $l)
137             }
138              
139             sub dot($$) # Dot product of two vectors.
140 383     383 1 613 {my ($o, $p) = @_; # Vector 1, vector 2
141 383         7366 $o->x * $p->x + $o->y * $p->y
142             }
143              
144             sub area($$) # Signed area of the parallelogram defined by the two vectors. The area is negative if the second vector appears to the right of the first if they are both placed at the origin and the observer stands against the z-axis in a left handed coordinate system.
145 383     383 1 584 {my ($o, $p) = @_; # Vector 1, vector 2
146 383         6163 $o->x * $p->y - $o->y * $p->x
147             }
148              
149             sub cosine($$) # cos(angle between two vectors)
150 379     379 1 590 {my ($o, $p) = @_; # Vector 1, vector 2
151 379         725 $o->dot($p) / $o->l / $p->l
152             }
153              
154             sub sine($$) # sin(angle between two vectors)
155 381     381 1 672 {my ($o, $p) = @_; # Vector 1, vector 2
156 381         680 $o->area($p) / $o->l / $p->l
157             }
158              
159             sub angle($$) # Angle in radians anticlockwise that the first vector must be rotated to point along the second vector normalized to the range: -pi to +pi.
160 375     375 1 832 {my ($o, $p) = @_; # Vector 1, vector 2
161 375         724 my $c = $o->cosine($p);
162 375         8161 my $s = $o->sine($p);
163 375         8619 my $a = Math::Trig::acos($c);
164 375 100       3402 $s > 0 ? $a : -$a
165             }
166              
167             sub r90($) # Rotate a vector by 90 degrees anticlockwise.
168 12     12 1 211 {my ($o) = @_; # Vector to rotate
169 12         203 new(-$o->y, $o->x)
170             }
171              
172             sub r180($) # Rotate a vector by 180 degrees.
173 0     0 1 0 {my ($o) = @_; # Vector to rotate
174 0         0 new(-$o->x, -$o->y)
175             }
176              
177             sub r270($) # Rotate a vector by 270 degrees anticlockwise.
178 0     0 1 0 {my ($o) = @_; # Vector to rotate
179 0         0 new($o->y, -$o->x)
180             }
181              
182             sub swap($) # Swap the components of a vector
183 1     1 1 3 {my ($o) = @_; # Vector
184 1         18 new($o->y, $o->x)
185             }
186              
187             use overload
188 13     13   155 '==' => sub {my ($o, $p) = @_; $o->eq ($p)},
  13         30  
189 20     20   115 '+' => sub {my ($o, $p) = @_; $o->plus ($p)},
  20         45  
190 1     1   39 '+=' => sub {my ($o, $p) = @_; $o->Plus ($p)},
  1         5  
191 10 100   10   143 '-' => sub {my ($o, $p) = @_; ref($p) ? $o->minus($p) : $o->multiply(-1)},
  10         35  
192 1     1   39 '-=' => sub {my ($o, $p) = @_; $o->Minus ($p)},
  1         4  
193 20     20   107 '*' => sub {my ($o, $p) = @_; $o->multiply($p)},
  20         50  
194 1     1   11 '*=' => sub {my ($o, $p) = @_; $o->Multiply($p)},
  1         10  
195 4     4   11 '/' => sub {my ($o, $p) = @_; $o->divide ($p)},
  4         12  
196 1     1   3 '/=' => sub {my ($o, $p) = @_; $o->Divide ($p)},
  1         5  
197 4     4   11 '.' => sub {my ($o, $p) = @_; $o->dot ($p)},
  4         12  
198 0     0   0 'x' => sub {my ($o, $p) = @_; $o->area ($p)},
  0         0  
199 367     367   13359 '<' => sub {my ($o, $p) = @_; $o->angle ($p)},
  367         805  
200 12     12   27 '""' => sub {my ($o) = @_; $o->print },
  12         30  
201 1     1   16 "fallback" => 1;
  1         3  
  1         27  
202              
203             #D0
204             #-------------------------------------------------------------------------------
205             # Export - eeee
206             #-------------------------------------------------------------------------------
207              
208 1     1   222 use Exporter qw(import);
  1         3  
  1         52  
209              
210 1     1   6 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  1         1  
  1         363  
211              
212             # containingFolder
213              
214             @ISA = qw(Exporter);
215             @EXPORT = qw();
216             @EXPORT_OK = qw();
217             %EXPORT_TAGS = (all=>[@EXPORT, @EXPORT_OK]);
218              
219             # podDocumentation
220              
221             =encoding utf-8
222              
223             =head1 Name
224              
225             Math::Vectors2 - Vectors in two dimensions
226              
227             =head1 Synopsis
228              
229             use Math::Vectors2;
230              
231             my ($zero, $x, $y) = Math::Vectors2::zeroAndUnits;
232              
233             ok near deg2rad(-60), $x + $y * sqrt(3) < $x;
234             ok near deg2rad(+30), ($x + $y * sqrt(3))->angle($y);
235              
236             =head1 Description
237              
238             Vectors in two dimensions
239              
240              
241             Version 20200402.
242              
243              
244             The following sections describe the methods in each functional area of this
245             module. For an alphabetic listing of all methods by name see L.
246              
247              
248              
249             =head1 Methods
250              
251             Vector methods.
252              
253             =head2 new($x, $y)
254              
255             Create new vector from components.
256              
257             Parameter Description
258             1 $x X component
259             2 $y Y component
260              
261             B
262              
263              
264             my ($zero, $x, $y) = zeroAndUnits;
265             ok near $y->angle(𝗻𝗲𝘄(+1, -1)), deg2rad(-135);
266             ok near $y->angle(𝗻𝗲𝘄(+1, 0)), deg2rad(-90);
267             ok near $y->angle(𝗻𝗲𝘄(+1, +1)), deg2rad(-45);
268             ok near $y->angle(𝗻𝗲𝘄( 0, +1)), deg2rad(+0);
269             ok near $y->angle(𝗻𝗲𝘄(-1, +1)), deg2rad(+45);
270             ok near $y->angle(𝗻𝗲𝘄(-1, 0)), deg2rad(+90);
271             ok near $y->angle(𝗻𝗲𝘄(-1, -1)), deg2rad(+135);
272              
273             ok near 𝗻𝗲𝘄(1,1) < 𝗻𝗲𝘄( 0, -1), deg2rad(-135);
274             ok near 𝗻𝗲𝘄(1,1) < 𝗻𝗲𝘄( 1, -1), deg2rad(-90);
275             ok near 𝗻𝗲𝘄(1,1) < 𝗻𝗲𝘄( 1, 0), deg2rad(-45);
276             ok near 𝗻𝗲𝘄(1,1) < 𝗻𝗲𝘄( 1, 1), deg2rad(0);
277             ok near 𝗻𝗲𝘄(1,1) < 𝗻𝗲𝘄( 0, 1), deg2rad(+45);
278             ok near 𝗻𝗲𝘄(1,1) < 𝗻𝗲𝘄(-1, 1), deg2rad(+90);
279             ok near 𝗻𝗲𝘄(1,1) < 𝗻𝗲𝘄(-1, 0), deg2rad(+135);
280              
281             ok near $x + $y * sqrt(3) < $x, deg2rad(-60);
282             ok near $x + $y * sqrt(3) < $y, deg2rad(+30);
283              
284             for my $i(-179..179)
285             {ok near $x < 𝗻𝗲𝘄(cos(deg2rad($i)), sin(deg2rad($i))), deg2rad($i);
286             }
287              
288              
289             This is a static method and so should either be imported or invoked as:
290              
291             Math::Vectors2::new
292              
293              
294             =head2 zeroAndUnits()
295              
296             Create the useful vectors: o=(0,0), x=(1,0), y=(0,1)
297              
298              
299             B
300              
301              
302             my ($z, $x, $y) = 𝘇𝗲𝗿𝗼𝗔𝗻𝗱𝗨𝗻𝗶𝘁𝘀;
303             ok $x + $y + $z == $x->plus($y);
304             ok $x - $y == $x->minus($y);
305             ok $x * 3 == $x->multiply(3);
306             ok $y / 2 == $y->divide(2);
307             ok $x + $y eq '(1,1)';
308             ok $x - $y eq '(1,-1)';
309             ok $x * 3 eq '(3,0)';
310             ok $y / 2 eq '(0,0.5)';
311             ok (($x * 2 + $y * 3)-> print eq '(2,3)');
312              
313              
314             This is a static method and so should either be imported or invoked as:
315              
316             Math::Vectors2::zeroAndUnits
317              
318              
319             =head2 eq($o, $p)
320              
321             Whether two vectors are equal to within the accuracy of floating point arithmetic
322              
323             Parameter Description
324             1 $o First vector
325             2 $p Second vector
326              
327             B
328              
329              
330             my ($z, $x, $y) = zeroAndUnits;
331             ok $x + $y + $z == $x->plus($y);
332             ok $x - $y == $x->minus($y);
333             ok $x * 3 == $x->multiply(3);
334             ok $y / 2 == $y->divide(2);
335             ok $x + $y 𝗲𝗾 '(1,1)';
336             ok $x - $y 𝗲𝗾 '(1,-1)';
337             ok $x * 3 𝗲𝗾 '(3,0)';
338             ok $y / 2 𝗲𝗾 '(0,0.5)';
339             ok (($x * 2 + $y * 3)-> print 𝗲𝗾 '(2,3)');
340              
341              
342             =head2 zero($o)
343              
344             Whether a vector is equal to zero within the accuracy of floating point arithmetic
345              
346             Parameter Description
347             1 $o Vector
348              
349             B
350              
351              
352             my ($𝘇𝗲𝗿𝗼, $x, $y) = zeroAndUnits;
353             ok $𝘇𝗲𝗿𝗼->𝘇𝗲𝗿𝗼;
354             ok !$x->𝘇𝗲𝗿𝗼;
355             ok !$y->𝘇𝗲𝗿𝗼;
356              
357              
358             =head2 print($p, @p)
359              
360             Print one or more vectors.
361              
362             Parameter Description
363             1 $p Vector to print
364             2 @p More vectors to print
365              
366             B
367              
368              
369             my ($z, $x, $y) = zeroAndUnits;
370             ok $x + $y + $z == $x->plus($y);
371             ok $x - $y == $x->minus($y);
372             ok $x * 3 == $x->multiply(3);
373             ok $y / 2 == $y->divide(2);
374             ok $x + $y eq '(1,1)';
375             ok $x - $y eq '(1,-1)';
376             ok $x * 3 eq '(3,0)';
377             ok $y / 2 eq '(0,0.5)';
378             ok (($x * 2 + $y * 3)-> 𝗽𝗿𝗶𝗻𝘁 eq '(2,3)');
379              
380              
381             =head2 clone($o)
382              
383             Clone a vector.
384              
385             Parameter Description
386             1 $o Vector to clone
387              
388             B
389              
390              
391             my ($z, $x, $y) = zeroAndUnits;
392             ok $x->swap == $y;
393             ok $x->𝗰𝗹𝗼𝗻𝗲 == $x;
394              
395              
396             =head2 Plus($o, @p)
397              
398             Add zero or more other vectors to the first vector and return the result.
399              
400             Parameter Description
401             1 $o First vector
402             2 @p Other vectors
403              
404             B
405              
406              
407             my ($zero, $x, $y) = zeroAndUnits;
408             $x->𝗣𝗹𝘂𝘀(new(1,1));
409             ok $x eq '(2,1)';
410             $y += new(1,1);
411             ok $y eq '(1,2)';
412              
413              
414              
415             =head2 plus($o, @p)
416              
417             Add zero or more other vectors to a copy of the first vector and return the result.
418              
419             Parameter Description
420             1 $o First vector
421             2 @p Other vectors
422              
423             B
424              
425              
426             my ($z, $x, $y) = zeroAndUnits;
427             ok $x + $y + $z == $x->𝗽𝗹𝘂𝘀($y);
428             ok $x - $y == $x->minus($y);
429             ok $x * 3 == $x->multiply(3);
430             ok $y / 2 == $y->divide(2);
431             ok $x + $y eq '(1,1)';
432             ok $x - $y eq '(1,-1)';
433             ok $x * 3 eq '(3,0)';
434             ok $y / 2 eq '(0,0.5)';
435             ok (($x * 2 + $y * 3)-> print eq '(2,3)');
436              
437              
438             =head2 Minus($o, @p)
439              
440             Subtract zero or more vectors from the first vector and return the result.
441              
442             Parameter Description
443             1 $o First vector
444             2 @p Other vectors
445              
446             B
447              
448              
449             my ($zero, $x, $y) = zeroAndUnits;
450             $x->𝗠𝗶𝗻𝘂𝘀(new(0, 1));
451             ok $x eq '(1,-1)';
452             $y -= new(1,1);
453             ok $y eq '(-1,0)';
454              
455              
456             =head2 minus($o, @p)
457              
458             Subtract zero or more vectors from a copy of the first vector and return the result.
459              
460             Parameter Description
461             1 $o First vector
462             2 @p Other vectors
463              
464             B
465              
466              
467             my ($z, $x, $y) = zeroAndUnits;
468             ok $x + $y + $z == $x->plus($y);
469             ok $x - $y == $x->𝗺𝗶𝗻𝘂𝘀($y);
470             ok $x * 3 == $x->multiply(3);
471             ok $y / 2 == $y->divide(2);
472             ok $x + $y eq '(1,1)';
473             ok $x - $y eq '(1,-1)';
474             ok $x * 3 eq '(3,0)';
475             ok $y / 2 eq '(0,0.5)';
476             ok (($x * 2 + $y * 3)-> print eq '(2,3)');
477              
478              
479             =head2 Multiply($o, $m)
480              
481             Multiply a vector by a scalar and return the result.
482              
483             Parameter Description
484             1 $o Vector
485             2 $m Scalar to multiply by
486              
487             B
488              
489              
490             my ($zero, $x, $y) = zeroAndUnits;
491             $x->𝗠𝘂𝗹𝘁𝗶𝗽𝗹𝘆(2);
492             ok $x eq '(2,0)';
493             $y *= 2;
494             ok $y eq '(0,2)';
495              
496              
497              
498             =head2 multiply($o, $m)
499              
500             Multiply a copy of a vector by a scalar and return the result.
501              
502             Parameter Description
503             1 $o Vector
504             2 $m Scalar to multiply by
505              
506             B
507              
508              
509             my ($z, $x, $y) = zeroAndUnits;
510             ok $x + $y + $z == $x->plus($y);
511             ok $x - $y == $x->minus($y);
512             ok $x * 3 == $x->𝗺𝘂𝗹𝘁𝗶𝗽𝗹𝘆(3);
513             ok $y / 2 == $y->divide(2);
514             ok $x + $y eq '(1,1)';
515             ok $x - $y eq '(1,-1)';
516             ok $x * 3 eq '(3,0)';
517             ok $y / 2 eq '(0,0.5)';
518             ok (($x * 2 + $y * 3)-> print eq '(2,3)');
519              
520              
521             =head2 Divide($o, $d)
522              
523             Divide a vector by a scalar and return the result.
524              
525             Parameter Description
526             1 $o Vector
527             2 $d Scalar to multiply by
528              
529             B
530              
531              
532             my ($zero, $x, $y) = zeroAndUnits;
533             $x->𝗗𝗶𝘃𝗶𝗱𝗲(1/2);
534             ok $x eq '(2,0)';
535             $y /= 1/2;
536             ok $y eq '(0,2)';
537              
538              
539              
540             =head2 divide($o, $d)
541              
542             Divide a copy of a vector by a scalar and return the result.
543              
544             Parameter Description
545             1 $o Vector
546             2 $d Scalar to divide by
547              
548             B
549              
550              
551             my ($z, $x, $y) = zeroAndUnits;
552             ok $x + $y + $z == $x->plus($y);
553             ok $x - $y == $x->minus($y);
554             ok $x * 3 == $x->multiply(3);
555             ok $y / 2 == $y->𝗱𝗶𝘃𝗶𝗱𝗲(2);
556             ok $x + $y eq '(1,1)';
557             ok $x - $y eq '(1,-1)';
558             ok $x * 3 eq '(3,0)';
559             ok $y / 2 eq '(0,0.5)';
560             ok (($x * 2 + $y * 3)-> print eq '(2,3)');
561              
562              
563             =head2 l($o)
564              
565             Length of a vector.
566              
567             Parameter Description
568             1 $o Vector
569              
570             B
571              
572              
573             my ($z, $x, $y) = zeroAndUnits;
574              
575             ok 5 == ($x * 3 + $y * 4)->𝗹;
576             ok 25 == ($x * 3 + $y * 4)->l2;
577              
578             ok 2 * ($x + $y)->𝗹 == ($x + $y)->d (-$x - $y);
579             ok 4 * ($x + $y)->l2 == ($x + $y)->d2(-$x - $y);
580              
581              
582             =head2 l2($o)
583              
584             Length squared of a vector.
585              
586             Parameter Description
587             1 $o Vector
588              
589             B
590              
591              
592             my ($z, $x, $y) = zeroAndUnits;
593              
594             ok 5 == ($x * 3 + $y * 4)->l;
595             ok 25 == ($x * 3 + $y * 4)->𝗹𝟮;
596              
597             ok 2 * ($x + $y)->l == ($x + $y)->d (-$x - $y);
598             ok 4 * ($x + $y)->𝗹𝟮 == ($x + $y)->d2(-$x - $y);
599              
600              
601             =head2 d($o, $p)
602              
603             Distance between the points identified by two vectors when placed on the same point.
604              
605             Parameter Description
606             1 $o Vector 1
607             2 $p Vector 2
608              
609             B
610              
611              
612             my ($z, $x, $y) = zeroAndUnits;
613              
614             ok 5 == ($x * 3 + $y * 4)->l;
615             ok 25 == ($x * 3 + $y * 4)->l2;
616              
617             ok 2 * ($x + $y)->l == ($x + $y)->𝗱 (-$x - $y);
618             ok 4 * ($x + $y)->l2 == ($x + $y)->d2(-$x - $y);
619              
620              
621             =head2 d2($o, $p)
622              
623             Distance squared between the points identified by two vectors when placed on the same point.
624              
625             Parameter Description
626             1 $o Vector 1
627             2 $p Vector 2
628              
629             B
630              
631              
632             my ($z, $x, $y) = zeroAndUnits;
633              
634             ok 5 == ($x * 3 + $y * 4)->l;
635             ok 25 == ($x * 3 + $y * 4)->l2;
636              
637             ok 2 * ($x + $y)->l == ($x + $y)->d (-$x - $y);
638             ok 4 * ($x + $y)->l2 == ($x + $y)->𝗱𝟮(-$x - $y);
639              
640              
641             =head2 n($o)
642              
643             Return a normalized a copy of a vector.
644              
645             Parameter Description
646             1 $o Vector
647              
648             B
649              
650              
651             my ($z, $x, $y) = zeroAndUnits;
652             ok (($x * 3 + $y * 4)->𝗻 == $x * 3/5 + $y * 4/5);
653              
654             ok 0 == $x . $y;
655             ok 1 == $x . $x;
656             ok 1 == $y . $y;
657             ok 8 == ($x * 1 + $y * 2) .($x * 2 + $y * 3);
658              
659              
660             =head2 dot($o, $p)
661              
662             Dot product of two vectors.
663              
664             Parameter Description
665             1 $o Vector 1
666             2 $p Vector 2
667              
668             B
669              
670              
671             my ($z, $x, $y) = zeroAndUnits;
672             ok (($x * 3 + $y * 4)->n == $x * 3/5 + $y * 4/5);
673              
674             ok 0 == $x . $y;
675             ok 1 == $x . $x;
676             ok 1 == $y . $y;
677             ok 8 == ($x * 1 + $y * 2) .($x * 2 + $y * 3);
678              
679              
680             =head2 area($o, $p)
681              
682             Signed area of the parallelogram defined by the two vectors. The area is negative if the second vector appears to the right of the first if they are both placed at the origin and the observer stands against the z-axis in a left handed coordinate system.
683              
684             Parameter Description
685             1 $o Vector 1
686             2 $p Vector 2
687              
688             B
689              
690              
691             my ($z, $x, $y) = zeroAndUnits;
692             ok +1 == $x->cosine($x);
693             ok +1 == $y->cosine($y);
694             ok 0 == $x->cosine($y);
695             ok 0 == $y->cosine($x);
696              
697             ok 0 == $x->sine($x);
698             ok 0 == $y->sine($y);
699             ok +1 == $x->sine($y);
700             ok -1 == $y->sine($x);
701              
702             ok near -sqrt(1/2), ($x + $y)->sine($x);
703             ok near +sqrt(1/2), ($x + $y)->sine($y);
704             ok near -2, ($x + $y)->𝗮𝗿𝗲𝗮($x * 2);
705             ok near +2, ($x + $y)->𝗮𝗿𝗲𝗮($y * 2);
706              
707              
708             =head2 cosine($o, $p)
709              
710             cos(angle between two vectors)
711              
712             Parameter Description
713             1 $o Vector 1
714             2 $p Vector 2
715              
716             B
717              
718              
719             my ($z, $x, $y) = zeroAndUnits;
720             ok +1 == $x->𝗰𝗼𝘀𝗶𝗻𝗲($x);
721             ok +1 == $y->𝗰𝗼𝘀𝗶𝗻𝗲($y);
722             ok 0 == $x->𝗰𝗼𝘀𝗶𝗻𝗲($y);
723             ok 0 == $y->𝗰𝗼𝘀𝗶𝗻𝗲($x);
724              
725             ok 0 == $x->sine($x);
726             ok 0 == $y->sine($y);
727             ok +1 == $x->sine($y);
728             ok -1 == $y->sine($x);
729              
730             ok near -sqrt(1/2), ($x + $y)->sine($x);
731             ok near +sqrt(1/2), ($x + $y)->sine($y);
732             ok near -2, ($x + $y)->area($x * 2);
733             ok near +2, ($x + $y)->area($y * 2);
734              
735              
736             =head2 sine($o, $p)
737              
738             sin(angle between two vectors)
739              
740             Parameter Description
741             1 $o Vector 1
742             2 $p Vector 2
743              
744             B
745              
746              
747             my ($z, $x, $y) = zeroAndUnits;
748             ok +1 == $x->cosine($x);
749             ok +1 == $y->cosine($y);
750             ok 0 == $x->cosine($y);
751             ok 0 == $y->cosine($x);
752              
753             ok 0 == $x->𝘀𝗶𝗻𝗲($x);
754             ok 0 == $y->𝘀𝗶𝗻𝗲($y);
755             ok +1 == $x->𝘀𝗶𝗻𝗲($y);
756             ok -1 == $y->𝘀𝗶𝗻𝗲($x);
757              
758             ok near -sqrt(1/2), ($x + $y)->𝘀𝗶𝗻𝗲($x);
759             ok near +sqrt(1/2), ($x + $y)->𝘀𝗶𝗻𝗲($y);
760             ok near -2, ($x + $y)->area($x * 2);
761             ok near +2, ($x + $y)->area($y * 2);
762              
763              
764             =head2 angle($o, $p)
765              
766             Angle in radians anticlockwise that the first vector must be rotated to point along the second vector normalized to the range: -pi to +pi.
767              
768             Parameter Description
769             1 $o Vector 1
770             2 $p Vector 2
771              
772             B
773              
774              
775             my ($zero, $x, $y) = zeroAndUnits;
776             ok near $y->𝗮𝗻𝗴𝗹𝗲(new(+1, -1)), deg2rad(-135);
777             ok near $y->𝗮𝗻𝗴𝗹𝗲(new(+1, 0)), deg2rad(-90);
778             ok near $y->𝗮𝗻𝗴𝗹𝗲(new(+1, +1)), deg2rad(-45);
779             ok near $y->𝗮𝗻𝗴𝗹𝗲(new( 0, +1)), deg2rad(+0);
780             ok near $y->𝗮𝗻𝗴𝗹𝗲(new(-1, +1)), deg2rad(+45);
781             ok near $y->𝗮𝗻𝗴𝗹𝗲(new(-1, 0)), deg2rad(+90);
782             ok near $y->𝗮𝗻𝗴𝗹𝗲(new(-1, -1)), deg2rad(+135);
783              
784             ok near new(1,1) < new( 0, -1), deg2rad(-135);
785             ok near new(1,1) < new( 1, -1), deg2rad(-90);
786             ok near new(1,1) < new( 1, 0), deg2rad(-45);
787             ok near new(1,1) < new( 1, 1), deg2rad(0);
788             ok near new(1,1) < new( 0, 1), deg2rad(+45);
789             ok near new(1,1) < new(-1, 1), deg2rad(+90);
790             ok near new(1,1) < new(-1, 0), deg2rad(+135);
791              
792             ok near $x + $y * sqrt(3) < $x, deg2rad(-60);
793             ok near $x + $y * sqrt(3) < $y, deg2rad(+30);
794              
795             for my $i(-179..179)
796             {ok near $x < new(cos(deg2rad($i)), sin(deg2rad($i))), deg2rad($i);
797             }
798              
799              
800             =head2 r90($o)
801              
802             Rotate a vector by 90 degrees anticlockwise.
803              
804             Parameter Description
805             1 $o Vector to rotate
806              
807             B
808              
809              
810             my ($z, $x, $y) = zeroAndUnits;
811             ok $x->𝗿𝟵𝟬 == $y;
812             ok $y->𝗿𝟵𝟬 == -$x;
813             ok $x->𝗿𝟵𝟬->𝗿𝟵𝟬 == -$x;
814             ok $y->𝗿𝟵𝟬->𝗿𝟵𝟬 == -$y;
815             ok $x->𝗿𝟵𝟬->𝗿𝟵𝟬->𝗿𝟵𝟬 == -$y;
816             ok $y->𝗿𝟵𝟬->𝗿𝟵𝟬->𝗿𝟵𝟬 == $x;
817              
818              
819             =head2 r180($o)
820              
821             Rotate a vector by 180 degrees.
822              
823             Parameter Description
824             1 $o Vector to rotate
825              
826             B
827              
828              
829             my ($z, $x, $y) = zeroAndUnits;
830             ok $x->r90 == $y;
831             ok $y->r90 == -$x;
832             ok $x->r90->r90 == -$x;
833             ok $y->r90->r90 == -$y;
834             ok $x->r90->r90->r90 == -$y;
835             ok $y->r90->r90->r90 == $x;
836              
837              
838             =head2 r270($o)
839              
840             Rotate a vector by 270 degrees anticlockwise.
841              
842             Parameter Description
843             1 $o Vector to rotate
844              
845             B
846              
847              
848             my ($z, $x, $y) = zeroAndUnits;
849             ok $x->r90 == $y;
850             ok $y->r90 == -$x;
851             ok $x->r90->r90 == -$x;
852             ok $y->r90->r90 == -$y;
853             ok $x->r90->r90->r90 == -$y;
854             ok $y->r90->r90->r90 == $x;
855              
856              
857             =head2 swap($o)
858              
859             Swap the components of a vector
860              
861             Parameter Description
862             1 $o Vector
863              
864             B
865              
866              
867             my ($z, $x, $y) = zeroAndUnits;
868             ok $x->𝘀𝘄𝗮𝗽 == $y;
869             ok $x->clone == $x;
870              
871              
872              
873             =head2 Math::Vectors2 Definition
874              
875              
876             Attributes of a vector
877              
878              
879              
880              
881             =head3 Output fields
882              
883              
884             B - X coordinate
885              
886             B - Y coordinate
887              
888              
889              
890             =head1 Index
891              
892              
893             1 L - Angle in radians anticlockwise that the first vector must be rotated to point along the second vector normalized to the range: -pi to +pi.
894              
895             2 L - Signed area of the parallelogram defined by the two vectors.
896              
897             3 L - Clone a vector.
898              
899             4 L - cos(angle between two vectors)
900              
901             5 L - Distance between the points identified by two vectors when placed on the same point.
902              
903             6 L - Distance squared between the points identified by two vectors when placed on the same point.
904              
905             7 L - Divide a copy of a vector by a scalar and return the result.
906              
907             8 L - Divide a vector by a scalar and return the result.
908              
909             9 L - Dot product of two vectors.
910              
911             10 L - Whether two vectors are equal to within the accuracy of floating point arithmetic
912              
913             11 L - Length of a vector.
914              
915             12 L - Length squared of a vector.
916              
917             13 L - Subtract zero or more vectors from the first vector and return the result.
918              
919             14 L - Subtract zero or more vectors from a copy of the first vector and return the result.
920              
921             15 L - Multiply a vector by a scalar and return the result.
922              
923             16 L - Multiply a copy of a vector by a scalar and return the result.
924              
925             17 L - Return a normalized a copy of a vector.
926              
927             18 L - Create new vector from components.
928              
929             19 L - Add zero or more other vectors to the first vector and return the result.
930              
931             20 L - Add zero or more other vectors to a copy of the first vector and return the result.
932              
933             21 L - Print one or more vectors.
934              
935             22 L - Rotate a vector by 180 degrees.
936              
937             23 L - Rotate a vector by 270 degrees anticlockwise.
938              
939             24 L - Rotate a vector by 90 degrees anticlockwise.
940              
941             25 L - sin(angle between two vectors)
942              
943             26 L - Swap the components of a vector
944              
945             27 L - Whether a vector is equal to zero within the accuracy of floating point arithmetic
946              
947             28 L - Create the useful vectors: o=(0,0), x=(1,0), y=(0,1)
948              
949             =head1 Installation
950              
951             This module is written in 100% Pure Perl and, thus, it is easy to read,
952             comprehend, use, modify and install via B:
953              
954             sudo cpan install Math::Vectors2
955              
956             =head1 Author
957              
958             L
959              
960             L
961              
962             =head1 Copyright
963              
964             Copyright (c) 2016-2019 Philip R Brenan.
965              
966             This module is free software. It may be used, redistributed and/or modified
967             under the same terms as Perl itself.
968              
969             =cut
970              
971              
972              
973             # Tests and documentation
974              
975             sub test
976 1     1 0 11 {my $p = __PACKAGE__;
977 1         8 binmode($_, ":utf8") for *STDOUT, *STDERR;
978 1 50       77 return if eval "eof(${p}::DATA)";
979 1         79 my $s = eval "join('', <${p}::DATA>)";
980 1 50       7 $@ and die $@;
981 1     1   654 eval $s;
  1         66692  
  1         12  
  1         60  
982 1 50       354 $@ and die $@;
983 1         134 1
984             }
985              
986             test unless caller;
987              
988             1;
989             # podDocumentation
990             __DATA__