File Coverage

blib/lib/Math/Vectors2.pm
Criterion Covered Total %
statement 135 141 95.7
branch 12 16 75.0
condition n/a
subroutine 51 54 94.4
pod 28 32 87.5
total 226 243 93.0


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