File Coverage

blib/lib/Math/Intersection/Circle/Line.pm
Criterion Covered Total %
statement 15 17 88.2
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 21 23 91.3


line stmt bran cond sub pod time code
1             =pod
2              
3             =encoding utf8
4              
5             =head1 Name
6              
7             Math::Intersection::Circle::Line - Find the points at which circles and lines
8             intersect and the area of these intersections.
9              
10             =head1 Synopsis
11              
12             use Math::Intersection::Circle::Line q(:all);
13             use Test::More q(no_plan);
14             use utf8;
15              
16             # Euler Line, see: https://en.wikipedia.org/wiki/Euler_line
17              
18             if (1)
19             {my @t = (0, 0, 4, 0, 0, 3); # Corners of the triangle
20             &areaOfPolygon(sub {ok !$_[0]}, # Polygon formed by these points has zero area and so is a line or a point
21             &circumCircle (sub {@_[0,1]}, @t), # green
22             &ninePointCircle(sub {@_[0,1]}, @t), # red
23             &orthoCentre (sub {@_[0,1]}, @t), # blue
24             ¢roid (sub {@_[0,1]}, @t)); # orange
25             }
26              
27             # An isosceles tringle with an apex height of 3/4 of the radius of its
28             # circumcircle divides Euler's line into 6 equal pieces
29              
30             if (1)
31             {my $r = 400; # Arbitrary but convenient radius
32             intersectionCircleLine # Find coordinates of equiangles of isoceles triangle
33             {my ($x, $y, $๐•ฉ, $๐•ช) = @_; # Coordinates of equiangles
34             my ($๐˜…, $๐˜†) = (0, $r); # Coordinates of apex
35             my ($nx, $ny, $nr) = ninePointCircle {@_} $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช; # Coordinates of centre and radius of nine point circle
36             my ($cx, $cy) = centroid {@_} $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช; # Coordinates of centroid
37             my ($ox, $oy) = orthoCentre {@_} $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช; # Coordinates of orthocentre
38             ok join(' ', $y, $cy, $y+$nr, $๐˜†, $y+2*$nr, $oy) eq # Calculated points along Euler's line
39             join(' ', 100, 200, 300, 400, 500, 600); # The actual six equally spaced points along Euler's line
40             } 0, 0, $r, 0, $r/4, 1, $r/4; # Chord at 1/4 radius
41             }
42              
43             # A line segment across a circle is never longer than the diameter
44              
45             if (1) # Random circle and random line
46             {my ($x, $y, $r, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = map {rand()} 1..7;
47             intersectionCircleLine # Find intersection of a circle and a line
48             {return ok 1 unless @_ == 4; # Ignore line unless it crosses circle
49             ok &vectorLength(@_) <= 2*$r; # Length if line segment is less than or equal to that of a diameter
50             } $x, $y, $r, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช; # Circle and line to be intersected
51             }
52              
53             # The length of a side of a hexagon is the radius of a circle inscribed through
54             # its vertices
55              
56             if (1)
57             {my ($x, $y, $r) = map {rand()} 1..3; # Random circle
58             my @p = intersectionCircles {@_} $x, $y, $r, $x+$r, $y, $r; # First step of one radius
59             my @๐—ฝ = intersectionCircles {@_} $x, $y, $r, $p[0], $p[1], $r; # Second step of one radius
60             my @q = !&near($x+$r, $y, @๐—ฝ[0,1]) ? @๐—ฝ[0,1] : @๐—ฝ[2,3]; # Away from start point
61             my @๐—พ = intersectionCircles {@_} $x, $y, $r, $q[0], $q[1], $r; # Third step of one radius
62             ok &near2(@๐—พ[0,1], $x-$r, $y) or # Brings us to a point
63             &near2(@๐—พ[2,3], $x-$r, $y); # opposite to the start point
64             }
65              
66             # Circle through three points chosen at random has the same centre regardless of
67             # the pairing of the points
68              
69             sub circleThrough3
70             {my ($x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_; # Three points
71             &intersectionLines
72             (sub # Intersection of bisectors is the centre of the circle
73             {my @r =(&vectorLength(@_, $x, $y), # Radii from centre of circle to each point
74             &vectorLength(@_, $๐˜…, $๐˜†),
75             &vectorLength(@_, $๐•ฉ, $๐•ช));
76             ok &near(@r[0,1]); # Check radii are equal
77             ok &near(@r[1,2]);
78             @_ # Return centre
79             }, rotate90AroundMidPoint($x, $y, $๐˜…, $๐˜†), # Bisectors between pairs of points
80             rotate90AroundMidPoint($๐•ฉ, $๐•ช, $๐˜…, $๐˜†));
81             }
82              
83             if (1)
84             {my (@points) = map {rand()} 1..6; # Three points chosen at random
85             ok &near2(circleThrough3(@points), circleThrough3(@points[2..5, 0..1])); # Circle has same centre regardless
86             ok &near2(circleThrough3(@points), circleThrough3(@points[4..5, 0..3])); # of the pairing of the points
87             }
88              
89             =cut
90             # Since 1.005
91             # 2015/12/21 Zero radius circle intersects with a line if the centre is collinear with the line
92             package Math::Intersection::Circle::Line;
93             #-------------------------------------------------------------------------------
94             # Locate the points at which lines and circles cross in two dimensions
95             # Philip R Brenan at gmail dot com, Appa Apps Ltd, 2015
96             #-------------------------------------------------------------------------------
97              
98 1     1   1882 use v5.18;
  1         3  
99 1     1   5 use warnings FATAL => qw(all);
  1         1  
  1         46  
100 1     1   5 use strict;
  1         5  
  1         22  
101 1     1   927 use utf8;
  1         11  
  1         5  
102 1     1   28 use Carp;
  1         2  
  1         102  
103 1     1   17849 use Data::Dump qw(dump);
  0            
  0            
104              
105             #-------------------------------------------------------------------------------
106             # Our definition of nearness
107             #-------------------------------------------------------------------------------
108              
109             our $near = 1e-6; # Define nearness
110              
111             sub near($;$) {return abs(($_[1]//0) - $_[0]) < $near} # Values this close are considered identical
112              
113             sub near2($$;$$) # Check that we are near enough
114             {my ($a, $b, $A, $B) = @_;
115             near($A//0, $a) &&
116             near($B//0, $b)
117             }
118              
119             sub near3($$$;$$$) # Check that we are near enough
120             {my ($a, $b, $c, $A, $B, $C) = @_;
121             near($A//0, $a) &&
122             near($B//0, $b) &&
123             near($C//0, $c)
124             }
125              
126             sub near4($$$$;$$$$) # Check that we are near enough
127             {my ($a, $b, $c, $d, $A, $B, $C, $D) = @_;
128             near($A//0, $a) &&
129             near($B//0, $b) &&
130             near($C//0, $c) &&
131             near($D//0, $d)
132             }
133              
134             #-------------------------------------------------------------------------------
135             # Trigonometric functions
136             #-------------------------------------------------------------------------------
137              
138             sub ๐ฟ {4*atan2(1,1)} # Pi
139              
140             #-------------------------------------------------------------------------------
141             # Length of a vector
142             #-------------------------------------------------------------------------------
143              
144             sub vectorSquaredLength($$;$$) # Length of a vector or distance between two vectors squared - useful for finding out which is longest without having to take a square root
145             {my ($x, $y, $๐˜…, $๐˜†) = @_;
146             my $r = ($x-($๐˜…//0))**2+($y-($๐˜†//0))**2;
147             $r
148             }
149              
150             sub vectorLength($$;$$) {sqrt(&vectorSquaredLength(@_))} # Length of a vector or distance between two vectors
151              
152             #-------------------------------------------------------------------------------
153             # Lengths of the sides of a polygon
154             #-------------------------------------------------------------------------------
155              
156             sub lengthsOfTheSidesOfAPolygon($$@)
157             {my ($x, $y, @vertices) = @_;
158             @_% 2 == 0 or confess "Odd number of coordinates!";
159             @_> 4 or confess "Must have at least two vertices!";
160             my @l;
161             my ($๐˜…, $๐˜†);
162             for(;scalar(@vertices);)
163             {($๐˜…, $๐˜†, @vertices) = @vertices;
164             push @l, vectorLength($x, $y, $๐˜…, $๐˜†);
165             ($x, $y) = ($๐˜…, $๐˜†)
166             }
167             push @l, vectorLength($_[-2]-$_[0], $_[-1]-$_[1]);
168             @l
169             }
170              
171             #-------------------------------------------------------------------------------
172             # Check whether three points are close to collinear by the Schwartz inequality
173             #-------------------------------------------------------------------------------
174              
175             sub threeCollinearPoints($$$$$$) # Three points to be tested
176             {my ($x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_;
177             @_ == 6 or confess "Wrong number of parameters";
178             return 1 if near($x, $๐˜…) && near($y, $๐˜†) or near($x, $๐•ฉ) && near($y, $๐•ช); # When two points are close the points are effectively collinear - although we should really check that all three points are not close sa this would identify either a number representation problem or a bad definition of nearness for this application
179             my $d = vectorLength($๐˜…, $๐˜†, $๐•ฉ, $๐•ช);
180             my $๐—ฑ = vectorLength($x, $y, $๐•ฉ, $๐•ช); # Lengths of sides opposite corners
181             my $๐•• = vectorLength($x, $y, $๐˜…, $๐˜†);
182             return 1 if near($d, $๐—ฑ) && near($๐••); # Two sides equal and the other small makes the lines effectively collinear
183             return 1 if near($d, $๐••) && near($๐—ฑ);
184             return 1 if near($๐—ฑ, $๐••) && near($d);
185             near($d, $๐—ฑ+$๐••) or near($๐—ฑ, $๐••+$d) or near($๐••, $d+$๐—ฑ) # One side is almost as long as the other two combined
186             }
187              
188             #-------------------------------------------------------------------------------
189             # Average of two vectors = coordinates of the mid point on the line between them
190             #-------------------------------------------------------------------------------
191              
192             sub midPoint($$$$)
193             {my ($x, $y, $๐˜…, $๐˜†) = @_;
194             @_ == 4 or confess "Wrong number of parameters";
195             (($x+$๐˜…) / 2, ($y+$๐˜†) / 2)
196             }
197              
198             #-------------------------------------------------------------------------------
199             # Rotations
200             #-------------------------------------------------------------------------------
201              
202             sub rotate90CW ($$) {my ($x, $y) = @_; (+$y, -$x)} # Clockwise
203             sub rotate90CCW($$) {my ($x, $y) = @_; (-$y, +$x)} # Counter clockwise
204              
205             sub rotate90AroundMidPoint($$$$)
206             {my ($x, $y, $๐˜…, $๐˜†) = @_;
207             @_ == 4 or confess "Wrong number of parameters";
208             my ($๐•ฉ, $๐•ช) = map {$_/2} rotate90CW($๐˜… - $x, $๐˜† - $y);
209             my ($X, $Y) = &midPoint(@_);
210             ($X - $๐•ฉ, $Y - $๐•ช, $X + $๐•ฉ, $Y + $๐•ช)
211             }
212              
213             #-------------------------------------------------------------------------------
214             # ๐—œntersection of a circle A, with a circle B.
215             #
216             # ๐—žnown: coordinates of the centre and radius of each circle x, y, r, ๐˜…, ๐˜†, ๐—ฟ
217             #
218             # ๐—™ind: the coordinates of the points at which the circles intersect.
219             #
220             # ๐— ethod: Two different circles either do not intersect, or if they do, they
221             # intersect at one or two points. If they intersect at two points, the
222             # intersections are mirror images of each other in the line that connects the
223             # centres of the two circles.
224             #
225             # Let ๐—Ÿ be the line joining the two centres with length ๐—น = a + ๐—ฎ where a is the
226             # distance from (x, y) along ๐—Ÿ to the point closest to the intersections. Then:
227             #
228             # r*r-a*a == ๐—ฟ*๐—ฟ-๐—ฎ*๐—ฎ
229             # r*r-๐—ฟ*๐—ฟ == a*a-๐—ฎ*๐—ฎ
230             # == a*a-๐—ฎ*๐—ฎ = (a+๐—ฎ)(a-๐—ฎ) == ๐—น*(a-๐—ฎ) == ๐—น*(a - (๐—น - a)) = 2*a*๐—น - ๐—น*๐—น
231             #
232             # a == (r*r-๐—ฟ*๐—ฟ + ๐—น*๐—น)/ (2*๐—น)
233             #
234             # The distance ๐—ฎ at right angles to ๐—Ÿ to an intersection is sqrt(r*r-a*a)
235             #
236             # The unit vector ๐•• == (๐•ฉ, ๐•ช) along line ๐—Ÿ from (x,y) to (๐˜…, ๐˜†) is the unit in
237             # direction: (๐˜…-x, ๐˜†-y)
238             #
239             # The unit vectors d, ๐—ฑ at right angles to ๐—Ÿ are (-๐•ช, ๐•ฉ) and (๐•ช, -๐•ฉ)
240             #-------------------------------------------------------------------------------
241              
242             sub intersectionCircles(&$$$$$$)
243             {my ($sub, # Sub routine to process intersection
244             $x, $y, $r, # First circle centre, radius
245             $๐˜…, $๐˜†, $๐—ฟ) = @_; # Second circle centre, radius
246             @_ == 7 or confess "Wrong number of parameters";
247             return &$sub("Duplicate circles!") if # Complain if the two circles are in fact the same circle within the definition of nearness
248             near($x, $๐˜…) and near($y, $๐˜†) and near($r, $๐—ฟ);
249              
250             my ($๐•, $๐•) = ($๐˜… - $x, $๐˜† - $y); # Vector between centres
251             my $๐—น = vectorLength($๐•, $๐•); # Distance between centres
252             return &$sub("No intersection!") if $๐—น > $r + $๐—ฟ or $๐—น < abs($r - $๐—ฟ); # The circles are too far apart or too close to intersect
253              
254             my ($๐•ฉ, $๐•ช) = ($๐• / $๐—น, $๐• / $๐—น); # Unit vector between centres
255             my $a = ($r*$r - $๐—ฟ*$๐—ฟ + $๐—น*$๐—น)/ (2*$๐—น); # Length of the common side
256              
257             return &$sub($x+$๐•ฉ*$a, $y+$๐•ช*$a) if near($๐—น, $r + $๐—ฟ) or # The circles touch at one point if within the definition of nearness
258             near($๐—น, abs($r - $๐—ฟ));
259              
260             my $๐—ฎ = sqrt($r*$r-$a*$a);
261             &$sub($x+$๐•ฉ*$a-$๐•ช*$๐—ฎ, $y+$๐•ช*$a+$๐•ฉ*$๐—ฎ, # The circles touch at two points
262             $x+$๐•ฉ*$a+$๐•ช*$๐—ฎ, $y+$๐•ช*$a-$๐•ฉ*$๐—ฎ);
263             }
264              
265             #-------------------------------------------------------------------------------
266             # ๐—”rea of intersection of two circles.
267             #
268             # ๐—žnown: two circles specified by ($x, $y, $r) and ($๐˜…, $๐˜†, $๐—ฟ)
269             #
270             # ๐—™ind: the area of intersection expressed as a fraction of the area
271             # of the smaller circle
272             #
273             # ๐— ethod: the area of a triangle is (base * height) / 2, the area of a slice is
274             # ๐ฐ๐—ฟ๐—ฟ/2 where ๐ฐ is the angle of a slice.
275             #-------------------------------------------------------------------------------
276              
277             sub intersectionCirclesArea(&$$$$$$)
278             {my ($sub, # Sub routine to process area
279             $x, $y, $r, # First circle centre, radius
280             $๐˜…, $๐˜†, $๐—ฟ) = @_; # Second circle centre, radius
281             @_ == 7 or confess "Wrong number of parameters";
282             near($r) and confess "Radius of first circle is too small!";
283             near($๐—ฟ) and confess "Radius of second circle is too small!";
284             my $l = vectorLength($๐˜… - $x, $๐˜† - $y); # Distance between centres
285             return &$sub(0) if $l >= $r + $๐—ฟ; # The circles are too far apart to overlap
286             my $๐•ฃ = $r < $๐—ฟ ? $r : $๐—ฟ; # Radius of smaller circle
287             return &$sub(1) if $l <= abs($r - $๐—ฟ); # The larger circle overlaps the smaller circle completely
288              
289             intersectionCircles
290             {my ($X, $Y, $๐—ซ, $๐—ฌ) = @_;
291             my $h = vectorLength($X - $๐—ซ, $Y - $๐—ฌ) / 2; # Height of triangles
292             my $R = sqrt($r**2 - $h**2); # Base of triangle in first circle
293             my $๐—ฅ = sqrt($๐—ฟ**2 - $h**2); # Base of triangle in second circle
294             &$sub(($r**2*atan2($h, $R) + $๐—ฟ**2*atan2($h, $๐—ฅ) - $h*($R+$๐—ฅ))/(๐ฟ()*$๐•ฃ**2)) # Fraction of smaller circle overlapped
295             } $x, $y, $r, $๐˜…, $๐˜†, $๐—ฟ;
296             }
297              
298             #-------------------------------------------------------------------------------
299             # ๐—ฃosition on a line closest to a specified point
300             #
301             # ๐—žnown: two points on the line ๐—Ÿ such that: ๐—น = (๐˜…, ๐˜†), ๐• = (๐•ฉ, ๐•ช) and the
302             # specified point ๐—ฝ = (x, y).
303             #
304             # ๐—™ind ๐—ฐ the point on ๐—Ÿ closest to ๐—ฝ.
305             #
306             # ๐— ethod: a circle with centre ๐—น through ๐—ฝ will intersect a circle with centre ๐•
307             # through ๐—ฝ at ๐—พ. ๐—ฐ is then the average of ๐—ฝ and ๐—พ.
308             #-------------------------------------------------------------------------------
309              
310             sub intersectionLinePoint(&$$$$$$)
311             {my ($sub, # Sub routine to process intersection
312             $๐˜…, $๐˜†, $๐•ฉ, $๐•ช, # Two points on line ๐—น
313             $x, $y) = @_; # The point ๐—ฝ
314             @_ == 7 or confess "Wrong number of parameters";
315             near($๐˜…, $๐•ฉ) and near($๐˜†, $๐•ช) and confess "Points on line are too close!"; # Line not well defined
316              
317             return &$sub($x, $y) if near($x, $๐˜…) && near($y, $๐˜†) or # Point in question is near an end of the line segment
318             near($x, $๐•ฉ) && near($y, $๐•ช);
319              
320             return &$sub($x, $y) if threeCollinearPoints($๐˜…, $๐˜†, $๐•ฉ, $๐•ช, $x, $y); # Collinear
321             # Points known not to be collinear
322             my $๐—ฟ = vectorLength($๐˜… - $x, $๐˜† - $y); # Radius of first circle
323             my $๐•ฃ = vectorLength($๐•ฉ - $x, $๐•ช - $y); # Radius of second circle
324             intersectionCircles
325             {return &$sub(@_) if @_ == 2; # Point is on line
326             my ($x, $y, $๐˜…, $๐˜†) = @_;
327             &$sub(($x+$๐˜…) / 2, ($y+$๐˜†) / 2) # Average intersection of intersection points
328             } $๐˜…, $๐˜†, $๐—ฟ, $๐•ฉ, $๐•ช, $๐•ฃ;
329             }
330              
331             sub unsignedDistanceFromLineToPoint(&$$$$$$) # Unsigned distance from point to line
332             {my ($sub, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช, $x, $y) = @_; # Parameters are the same as for intersectionLinePoint()
333             @_ == 7 or confess "Wrong number of parameters";
334             intersectionLinePoint {&$sub(&vectorLength($x, $y, @_))} $๐˜…,$๐˜†, $๐•ฉ,$๐•ช, $x,$y; # Distance from point to nearest point on line
335             }
336              
337             #-------------------------------------------------------------------------------
338             # ๐—œntersection of two lines
339             #
340             # ๐—žnown: two lines l specified by two points ๐—น = (๐˜…, ๐˜†), ๐• = (๐•ฉ, ๐•ช) and
341             # L specified by two points ๐—Ÿ = (๐—ซ, ๐—ฌ), ๐•ƒ = (๐•, ๐•)
342             # ๐—™ind ๐—ฐ the point where the two lines intersect else $sub is called empty
343             #
344             # ๐— ethod: Let the closest point to point ๐—Ÿ on line l be ๐—ฎ and the closest point
345             # to point ๐—ฎ on line L be ๐—ฏ. L๐—ฎ๐—ฏ is similar to L๐—ฎ๐—ฐ.
346             #-------------------------------------------------------------------------------
347              
348             sub intersectionLines(&$$$$$$$$)
349             {my ($sub, # Sub routine to process intersection
350             $๐˜…, $๐˜†, $๐•ฉ, $๐•ช, # Two points on line l
351             $๐—ซ, $๐—ฌ, $๐•, $๐•) = @_; # Two points on line L
352             @_ == 9 or confess "Wrong number of parameters";
353             near($๐˜…, $๐•ฉ) and near($๐˜†, $๐•ช) and confess "Points on first line are too close!";
354             near($๐—ซ, $๐•) and near($๐—ฌ, $๐•) and confess "Points on second line are too close!";
355             return &$sub("Parallel lines!") if # Lines are parallel if they have the same gradient
356             near(atan2($๐˜†-$๐•ช, $๐˜…-$๐•ฉ), atan2($๐—ฌ-$๐•, $๐—ซ-$๐•));
357              
358             intersectionLinePoint # Find ๐—ฎ
359             {my ($๐—ฎx, $๐—ฎy) = @_;
360              
361             intersectionLinePoint # Find ๐—ฏ
362             {my ($๐—ฏx, $๐—ฏy) = @_;
363             my $La = vectorSquaredLength($๐—ซ - $๐—ฎx, $๐—ฌ - $๐—ฎy); # Squared distance from ๐—Ÿ to ๐—ฎ
364             return &$sub($๐—ซ, $๐—ฌ) if near($La); # End point of second line is on first line but the lines are not parallel
365             my $Lb = vectorSquaredLength($๐—ซ - $๐—ฏx, $๐—ฌ - $๐—ฏy); # Squared distance from ๐—Ÿ to ๐—ฏ
366             near($Lb) and confess "Parallel lines!"; # Although this should not happen as we have already checked that the lines are not parallel
367             my $s = $La / $Lb; # Scale factor for ๐—Ÿ๐—ฏ
368             &$sub($๐—ซ + $s * ($๐—ฏx - $๐—ซ), $๐—ฌ + $s * ($๐—ฏy - $๐—ฌ)) # Point of intersection
369             } $๐—ซ,$๐—ฌ, $๐•,$๐•, $๐—ฎx,$๐—ฎy; # Find ๐—ฏ on second line
370             } $๐˜…,$๐˜†, $๐•ฉ,$๐•ช, $๐—ซ,$๐—ฌ; # Find ๐—ฎ on first line
371             }
372              
373             #-------------------------------------------------------------------------------
374             # ๐—œntersection of a circle with a line
375             #
376             # ๐—žnown: a circle specified by its centre (x, y), and radius (r)
377             # and a line that passes through points: ($๐˜…, $๐˜†) and ($๐•ฉ, $๐•ช).
378             #
379             # ๐—™ind: the two points at which the line crosses the circle or the single point
380             # at which the line touches the circle or report that there are no points in
381             # common.
382             #
383             # ๐— ethod: If the line crosses the circle we can draw an isosceles triangle from
384             # the centre of the circle to the points of intersection, with the line forming
385             # the base of said triangle. The centre of the base is the closest point on the
386             # line to the centre of the circle. The line is at right angles to the line from
387             # the centre of the circle to the centre of the base.
388             #-------------------------------------------------------------------------------
389              
390             sub intersectionCircleLine(&$$$$$$$)
391             {my ($sub, # Sub routine to process intersection
392             $x, $y, $r, # Circle centre, radius
393             $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_; # Line goes through these two points
394             @_ == 8 or confess "Wrong number of parameters";
395             near($๐˜…, $๐•ฉ) and near($๐˜†, $๐•ช) and confess "Points on line are too close!";
396             if (near($r)) # Zero radius circle
397             {return &$sub($x, $y) if threeCollinearPoints($x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช); # Line passes through the centre of the circle
398             confess "Radius is too small!";
399             }
400              
401             intersectionLinePoint
402             {my ($X, $Y) = @_; # Midpoint on line
403             if (near($x, $X) and near($y, $Y)) # Line passes through centre of circle
404             {my ($๐—ซ, $๐—ฌ) = ($๐•ฉ - $๐˜…, $๐•ช - $๐˜†); # Vector along line
405             my $D = vectorLength($๐—ซ, $๐—ฌ); # Length of vector along line
406             my $s = $r/$D; # Length from midpoint along line to circumference relative to length from centre to midpoint
407             return &$sub($x + $s * $๐—ซ, $y + $s * $๐—ฌ, $x - $s * $๐—ซ, $y - $s * $๐—ฌ); # Intersection points
408             }
409             my ($๐—ซ, $๐—ฌ) = ($X - $x, $Y - $y); # Centre to midpoint
410             my $๐—— = vectorLength($๐—ซ, $๐—ฌ); # Distance to midpoint
411             return &$sub("No intersection!") if $๐—— > $r; # Midpoint outside circle
412             return &$sub($X, $Y) if near($๐——, $r); # Tangent
413             my $๐”ป = sqrt($r*$r - $๐——*$๐——); # Length from midpoint along line to circumference
414             my $s = $๐”ป/$๐——; # Length from midpoint along line to circumference relative to length from centre to midpoint
415             &$sub($X - $s * $๐—ฌ, $Y + $s * $๐—ซ, $X + $s * $๐—ฌ, $Y - $s * $๐—ซ) # Intersection points
416             } $๐˜…, $๐˜†, $๐•ฉ, $๐•ช, $x, $y; # Find point on line closest to centre of circle
417             }
418              
419             #-------------------------------------------------------------------------------
420             # ๐—”rea of intersection of a circle with a line
421             #
422             # ๐—žnown: a circle specified by its centre (x, y), and radius (r)
423             # and a line that passes through points: ($๐˜…, $๐˜†) and ($๐•ฉ, $๐•ช).
424             # ๐—™ind: the area of the smallest lune as a fraction of the area of the circle
425             # ๐— ethod:
426             #-------------------------------------------------------------------------------
427              
428             sub intersectionCircleLineArea(&$$$$$$$)
429             {my ($sub, # Sub routine to process area
430             $x, $y, $r, # Circle centre, radius
431             $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_; # Line goes through these two points
432             @_ == 8 or confess "Wrong number of parameters";
433             near($๐˜…, $๐•ฉ) and near($๐˜†, $๐•ช) and confess "Points on line are too close!";
434             near($r) and confess "Radius is too small!";
435              
436             intersectionCircleLine
437             {return &$sub(0) if @_ < 4;
438             my ($X, $Y, $๐—ซ, $๐—ฌ) = @_; # Intersection points
439             my $h = vectorLength($X - $๐—ซ, $Y - $๐—ฌ) / 2; # Height of triangle
440             my $w = sqrt($r**2 - $h**2); # Base of triangle
441             &$sub(($r**2*atan2($h, $w) - $h*$w)/(๐ฟ()*$r**2)) # Area of smallest lune as a fraction of circle
442             } $x, $y, $r, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช;
443             }
444              
445             #-------------------------------------------------------------------------------
446             # ๐—–ircumCentre: intersection of the sides of a triangle when rotated ๐ฟ/2 at
447             # their mid points - centre of the circumCircle
448             # ๐—žnown: coordinates of each corner of the triangle
449             #-------------------------------------------------------------------------------
450              
451             sub circumCentre(&$$$$$$)
452             {my ($sub, $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_; # Subroutine to process results, coordinates of corners
453             @_ == 7 or confess "Wrong number of parameters";
454             (near($x, $๐˜…) && near($y, $๐˜†) or near($๐˜…, $๐•ฉ) && near($๐˜†, $๐•ช)) and confess "Corners are too close!";
455              
456             &intersectionLines(sub{&$sub(@_)},
457             rotate90AroundMidPoint($x, $y, $๐˜…, $๐˜†),
458             rotate90AroundMidPoint($๐˜…, $๐˜†, $๐•ฉ, $๐•ช));
459             }
460              
461             #-------------------------------------------------------------------------------
462             # ๐—–ircle through three points: https://en.wikipedia.org/wiki/Circumscribed_circle
463             # ๐—žnown: coordinates of each point
464             # ๐—™ind: coordinates of the centre and radius of the circle through these three
465             # points
466             #-------------------------------------------------------------------------------
467              
468             sub circumCircle(&$$$$$$)
469             {my ($sub, $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_; # Subroutine to process results, coordinates of corners
470             @_ == 7 or confess "Wrong number of parameters";
471             (near($x, $๐˜…) && near($y, $๐˜†) or near($๐˜…, $๐•ฉ) && near($๐˜†, $๐•ช)) and confess "Points are too close!";
472              
473             circumCentre
474             {my ($X, $Y) = @_; # Centre
475             my @r = (vectorLength($x, $y, $X, $Y), # Radii
476             vectorLength($๐˜…, $๐˜†, $X, $Y),
477             vectorLength($๐•ฉ, $๐•ช, $X, $Y));
478             &near(@r[0,1]) && &near(@r[1,2]) or confess "Bad radius computed!";
479             &$sub($X, $Y, $r[0]) # Result
480             } $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช; # Centre lies at the intersection of
481             }
482              
483             #-------------------------------------------------------------------------------
484             # ๐—–entre of a circle inscribed inside a triangle so that the inscribed circle
485             # touches each side just once.
486             #
487             # ๐—žnown: coordinates of each corner of the triangle
488             # ๐—™ind: centre coordinates and radius of inscribed circle
489             # ๐— ethod: find the intersection of the lines bisecting two angles
490             #-------------------------------------------------------------------------------
491              
492             sub circleInscribedInTriangle(&$$$$$$)
493             {my ($sub, $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_; # Subroutine to process results, coordinates of corners
494             @_ == 7 or confess "Wrong number of parameters";
495             (near($x, $๐˜…) && near($y, $๐˜†) or near($๐˜…, $๐•ฉ) && near($๐˜†, $๐•ช)) and confess "Corners are too close!";
496             my $๐—ฑ = vectorLength($x, $y, $๐•ฉ, $๐•ช); # Lengths of sides opposite corners
497             my $๐•• = vectorLength($x, $y, $๐˜…, $๐˜†);
498             my $d = vectorLength($๐˜…, $๐˜†, $๐•ฉ, $๐•ช);
499              
500             intersectionLines
501             {my ($X, $Y) = @_; # Intersection point
502             my @r = ((unsignedDistanceFromLineToPoint {@_} $x, $y, $๐˜…, $๐˜†, $X, $Y),
503             (unsignedDistanceFromLineToPoint {@_} $๐˜…, $๐˜†, $๐•ฉ, $๐•ช, $X, $Y),
504             (unsignedDistanceFromLineToPoint {@_} $๐•ฉ, $๐•ช, $x, $y, $X, $Y));
505             &near(@r[0,1]) && &near(@r[1,2]) or confess "Bad radius computed!";
506             return &$sub($X, $Y, $r[0]); # Coordinates of the centre of the inscribed circle, plus three estimates of its radius
507             }
508             $x, $y, $x + ($๐˜…-$x)/$๐•• + ($๐•ฉ-$x)/$๐—ฑ, $y + ($๐˜†-$y)/$๐•• + ($๐•ช-$y)/$๐—ฑ, # Intersection of an angle bisector
509             $๐˜…, $๐˜†, $๐˜… + ($๐•ฉ-$๐˜…)/$d + ($x-$๐˜…)/$๐••, $๐˜† + ($๐•ช-$๐˜†)/$d + ($y-$๐˜†)/$๐••; # Intersection of an angle bisector
510             }
511              
512             #-------------------------------------------------------------------------------
513             # ๐—–entre of a circle inscribed through the midpoints of each side of a triangle
514             # == Nine point circle: https://en.wikipedia.org/wiki/Nine-point_circle
515             # ๐—žnown: coordinates of each corner of the triangle
516             # ๐—™ind: centre coordinates and radius of circle through midpoints
517             # ๐— ethod: use circumCircle on the midpoints
518             #-------------------------------------------------------------------------------
519              
520             sub ninePointCircle(&$$$$$$)
521             {my ($sub, $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_; # Subroutine to process results, coordinates of corners
522             @_ == 7 or confess "Wrong number of parameters";
523             (near($x, $๐˜…) && near($y, $๐˜†) or near($๐˜…, $๐•ฉ) && near($๐˜†, $๐•ช)) and confess "Corners are too close!";
524              
525             &circumCircle(sub{&$sub(@_)}, # Circle through mid points
526             midPoint($x, $y, $๐˜…, $๐˜†),
527             midPoint($๐˜…, $๐˜†, $๐•ฉ, $๐•ช),
528             midPoint($๐•ฉ, $๐•ช, $x, $y));
529             }
530              
531             #-------------------------------------------------------------------------------
532             # Bisect the first angle of a triangle
533             #-------------------------------------------------------------------------------
534              
535             sub bisectAnAngle(&$$$$$$)
536             {my ($sub, $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_; # Subroutine to process results, coordinates of corners
537             @_ == 7 or confess "Wrong number of parameters";
538             (near($x, $๐˜…) && near($y, $๐˜†) or near($๐˜…, $๐•ฉ) && near($๐˜†, $๐•ช)) and confess "Corners are too close!";
539             my $๐•• = vectorLength($x, $y, $๐•ฉ, $๐•ช); # Lengths to opposite corners
540             my $๐—ฑ = vectorLength($x, $y, $๐˜…, $๐˜†);
541             &$sub($x, $y, $x + ($๐˜…-$x)/$๐•• + ($๐•ฉ-$x)/$๐—ฑ, $y + ($๐˜†-$y)/$๐•• + ($๐•ช-$y)/$๐—ฑ) # Vector from vertex pointing along bisector
542             }
543              
544             #-------------------------------------------------------------------------------
545             # ๐—™ind the centres and radii of the excircles of a triangle
546             # https://en.wikipedia.org/wiki/Incircle_and_excircles_of_a_triangle
547             # ๐—žnown: coordinates of each corner of the triangle
548             # ๐— ethod: intersection of appropriate angles of the triangles
549             #-------------------------------------------------------------------------------
550              
551             sub exCircles(&$$$$$$)
552             {my ($sub, $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_; # Subroutine to process results, coordinates of corners
553             @_ == 7 or confess "Wrong number of parameters";
554             (near($x, $๐˜…) && near($y, $๐˜†) or near($๐˜…, $๐•ฉ) && near($๐˜†, $๐•ช)) and confess "Corners are too close!";
555              
556             my @c = &intersectionLines(sub{@_}, # Centres
557             (bisectAnAngle {@_} $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช),
558             (bisectAnAngle {@_} $๐˜…, $๐˜†, $๐•ฉ, $๐•ช, 2*$๐˜… - $x, 2*$๐˜† - $y));
559              
560             my @๐—ฐ = &intersectionLines(sub{@_},
561             (bisectAnAngle {@_} $๐˜…, $๐˜†, $๐•ฉ, $๐•ช, $x, $y),
562             (bisectAnAngle {@_} $๐•ฉ, $๐•ช, $x, $y, 2*$๐•ฉ - $๐˜…, 2*$๐•ช - $๐˜†));
563              
564             my @๐•” = &intersectionLines(sub{@_},
565             (bisectAnAngle {@_} $๐•ฉ, $๐•ช, $x, $y, $๐˜…, $๐˜†),
566             (bisectAnAngle {@_} $x, $y, $๐˜…, $๐˜†, 2*$x - $๐•ฉ, 2*$y - $๐•ช));
567              
568             my @r = (&unsignedDistanceFromLineToPoint(sub {@_}, $x, $y, $๐˜…, $๐˜†, @c),
569             &unsignedDistanceFromLineToPoint(sub {@_}, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช, @c),
570             &unsignedDistanceFromLineToPoint(sub {@_}, $๐•ฉ, $๐•ช, $x, $y, @c));
571              
572             my @๐—ฟ = (&unsignedDistanceFromLineToPoint(sub {@_}, $x, $y, $๐˜…, $๐˜†, @๐—ฐ),
573             &unsignedDistanceFromLineToPoint(sub {@_}, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช, @๐—ฐ),
574             &unsignedDistanceFromLineToPoint(sub {@_}, $๐•ฉ, $๐•ช, $x, $y, @๐—ฐ));
575              
576             my @๐•ฃ = (&unsignedDistanceFromLineToPoint(sub {@_}, $x, $y, $๐˜…, $๐˜†, @๐•”),
577             &unsignedDistanceFromLineToPoint(sub {@_}, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช, @๐•”),
578             &unsignedDistanceFromLineToPoint(sub {@_}, $๐•ฉ, $๐•ช, $x, $y, @๐•”));
579             ([@c, @r], [@๐—ฐ, @๐—ฟ], [@๐•”, @๐•ฃ]) # For each circle, the centre followed by the radii estimates
580             }
581              
582             #-------------------------------------------------------------------------------
583             # ๐—–entroid: intersection of lines between corners and mid points of opposite sides
584             # ๐—™ind: coordinates of centroid
585             # ๐—žnown: coordinates of each corner of the triangle
586             #-------------------------------------------------------------------------------
587              
588             sub centroid(&$$$$$$)
589             {my ($sub, $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_; # Subroutine to process results, coordinates of corners
590             @_ == 7 or confess "Wrong number of parameters";
591             (near($x, $๐˜…) && near($y, $๐˜†) or near($๐˜…, $๐•ฉ) && near($๐˜†, $๐•ช)) and confess "Corners are too close!";
592              
593             &intersectionLines(sub{&$sub(@_)},
594             $x, $y, midPoint($๐˜…, $๐˜†, $๐•ฉ, $๐•ช),
595             $๐˜…, $๐˜†, midPoint($๐•ฉ, $๐•ช, $x, $y));
596             }
597              
598             #-------------------------------------------------------------------------------
599             # ๐—ขrthocentre: intersection of altitudes
600             # ๐—™ind: coordinates of orthocentre
601             # ๐—žnown: coordinates of each corner of the triangle
602             #-------------------------------------------------------------------------------
603              
604             sub orthoCentre(&$$$$$$)
605             {my ($sub, $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_; # Subroutine to process results, coordinates of corners
606             @_ == 7 or confess "Wrong number of parameters";
607             (near($x, $๐˜…) && near($y, $๐˜†) or near($๐˜…, $๐•ฉ) && near($๐˜†, $๐•ช)) and confess "Corners are too close!";
608              
609             &intersectionLines(sub{&$sub(@_)},
610             $x, $y, (intersectionLinePoint {@_} $๐˜…, $๐˜†, $๐•ฉ, $๐•ช, $x, $y),
611             $๐˜…, $๐˜†, (intersectionLinePoint {@_} $๐•ฉ, $๐•ช, $x, $y, $๐˜…, $๐˜†));
612             }
613              
614             #-------------------------------------------------------------------------------
615             # ๐—”rea of a triangle
616             # ๐—žnown: coordinates of each corner of the triangle
617             # ๐—™ind: area
618             # ๐— ethod: height of one corner from line through other two corners
619             #-------------------------------------------------------------------------------
620              
621             sub areaOfTriangle(&$$$$$$)
622             {my ($sub, $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_; # Subroutine to process results, coordinates of corners
623             @_ == 7 or confess "Wrong number of parameters";
624             return &$sub(0) if near($x, $๐˜…) && near($y, $๐˜†) or near($๐˜…, $๐•ฉ) && near($๐˜†, $๐•ช); # A pair of corners are close, so the area of the triangle must be zero
625             my ($d) = unsignedDistanceFromLineToPoint(sub {@_}, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช, $x, $y); # Distance for first corner from opposite line
626             &$sub($d * vectorLength($๐˜…, $๐˜†, $๐•ฉ, $๐•ช)/2) # Area = half base * height
627             }
628              
629             #-------------------------------------------------------------------------------
630             # ๐—”rea of a polygon
631             # ๐—žnown: coordinates of each corner=vertex of the polygon
632             # ๐—™ind: area
633             # ๐— ethod: divide the polygon into triangles which all share the first vertex
634             #-------------------------------------------------------------------------------
635              
636             sub areaOfPolygon(&@)
637             {my ($sub, $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช, @vertices) = @_; # Subroutine to process results, coordinates of vertices
638             my ($area) = areaOfTriangle {@_} $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช; # Area of first triangle
639             for(;scalar @vertices;) # Each subsequent triangle
640             {($๐˜…, $๐˜†) = ($๐•ฉ, $๐•ช); # Move up one vertex at a time
641             ($๐•ฉ, $๐•ช) = splice @vertices, 0, 2; # Remove one vertex
642             my ($a) = areaOfTriangle {@_} $x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช; # Area of latest triangle
643             $area += $a; # Sum areas
644             }
645             &$sub($area) # Area of polygon
646             }
647              
648             #-------------------------------------------------------------------------------
649             # ๐—œs a triangle equilateral?
650             # ๐—žnown: coordinates of each corner=vertex of the triangle
651             # ๐— ethod: compare lengths of sides
652             #-------------------------------------------------------------------------------
653              
654             sub isEquilateralTriangle(@)
655             {my ($x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_; # Coordinates of vertices
656             @_ == 6 or confess "Wrong number of parameters";
657             my ($d, $๐—ฑ, $๐••) = &lengthsOfTheSidesOfAPolygon(@_); # Lengths of sides
658             near($d, $๐—ฑ) && near($๐—ฑ, $๐••) # Equal sided?
659             }
660              
661             #-------------------------------------------------------------------------------
662             # ๐—œs a triangle isosceles
663             # ๐—žnown: coordinates of each corner=vertex of the triangle
664             # ๐— ethod: compare lengths of sides
665             #-------------------------------------------------------------------------------
666              
667             sub isIsoscelesTriangle(@)
668             {my ($x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_; # Coordinates of vertices
669             @_ == 6 or confess "Wrong number of parameters";
670             my ($d, $๐—ฑ, $๐••) = &lengthsOfTheSidesOfAPolygon(@_); # Lengths of sides
671             near($d, $๐—ฑ) || near($๐—ฑ, $๐••) || near($d, $๐••) # Two sides with equal lengths
672             }
673              
674             #-------------------------------------------------------------------------------
675             # ๐—œs a right angled triangle
676             # ๐—žnown: coordinates of each corner=vertex of the triangle
677             # ๐— ethod: pythagoras on sides
678             #-------------------------------------------------------------------------------
679              
680             sub isRightAngledTriangle(@)
681             {my ($x, $y, $๐˜…, $๐˜†, $๐•ฉ, $๐•ช) = @_; # Coordinates of vertices
682             @_ == 6 or confess "Wrong number of parameters";
683             my ($d, $๐—ฑ, $๐••) = &lengthsOfTheSidesOfAPolygon(@_); # Lengths of sides
684             near($d**2,$๐—ฑ**2+$๐••**2)||near($๐—ฑ**2,$d**2+$๐••**2) || near($๐••**2,$d**2+$๐—ฑ**2) # Pythagoras
685             }
686              
687             #-------------------------------------------------------------------------------
688             # ๐—˜xport details
689             #-------------------------------------------------------------------------------
690              
691             require 5;
692             require Exporter;
693              
694             use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
695              
696             @ISA = qw(Exporter);
697              
698             @EXPORT = qw(exCircles intersectionCircles intersectionCirclesArea
699             intersectionCircleLine intersectionCircleLineArea intersectionLines
700             intersectionLinePoint circumCircle circumCentre circleInscribedInTriangle
701             ninePointCircle areaOfTriangle areaOfPolygon orthoCentre centroid
702             isEquilateralTriangle isIsoscelesTriangle isRightAngledTriangle);
703              
704             @EXPORT_OK = qw(midPoint near near2 near3 near4 rotate90CW rotate90CCW
705             rotate90AroundMidPoint vectorLength ๐ฟ lengthsOfTheSidesOfAPolygon
706             threeCollinearPoints);
707              
708             $EXPORT_TAGS{all} = [@EXPORT, @EXPORT_OK];
709             #$VERSION = '1.003'; # Sun 30 Aug 2015 - started Geometry app
710             #$VERSION = '1.005'; # Sun 20 Dec 2015 - still going!
711             $VERSION = '1.006'; # Sat 02 Jan 2016 - Euler's line divided into 6 equal pieces
712              
713             =head1 Description
714              
715             Find the points at which circles and lines intersect and the area of these
716             intersections.
717              
718             Fast, fun and easy to use these functions are written in 100% Pure Perl.
719              
720             =head2 areaOfTriangle sub triangle
721              
722             Calls sub($a) where $a is the area of the specified triangle:
723              
724             A triangle is specified by supplying a list of six numbers:
725              
726             (x, y, ๐˜…, ๐˜†, ๐•ฉ, ๐•ช)
727              
728             where (x, y), (๐˜…, ๐˜†) and (๐•ฉ, ๐•ช) are the coordinates of the vertices of the
729             triangle.
730              
731             =head2 areaOfPolygon sub points...
732              
733             Calls sub($a) where $a is the area of the polygon with vertices specified by
734             the point.
735              
736             A point is specified by supplying a list of two numbers:
737              
738             (๐˜…, ๐˜†)
739              
740             =head2 centroid sub triangle
741              
742             Calls sub($x,$y) where $x,$y are the coordinates of the centroid of the
743             specified triangle:
744              
745             See: https://en.wikipedia.org/wiki/Centroid
746              
747             A triangle is specified by supplying a list of six numbers:
748              
749             (x, y, ๐˜…, ๐˜†, ๐•ฉ, ๐•ช)
750              
751             where (x, y), (๐˜…, ๐˜†) and (๐•ฉ, ๐•ช) are the coordinates of the vertices of the
752             triangle.
753              
754             =head2 circumCentre sub triangle
755              
756             Calls sub($x,$y,$r) where $x,$y are the coordinates of the centre of the
757             circle drawn through the corners of the specified triangle and $r is its
758             radius:
759              
760             See: https://en.wikipedia.org/wiki/Circumscribed_circle
761              
762             A triangle is specified by supplying a list of six numbers:
763              
764             (x, y, ๐˜…, ๐˜†, ๐•ฉ, ๐•ช)
765              
766             where (x, y), (๐˜…, ๐˜†) and (๐•ฉ, ๐•ช) are the coordinates of the vertices of the
767             triangle.
768              
769             =head2 circumCircle sub triangle
770              
771             Calls sub($x,$y,$r) where $x,$y are the coordinates of the circum-centre of
772             the specified triangle and $r is its radius:
773              
774             See: https://en.wikipedia.org/wiki/Circumscribed_circle
775              
776             A triangle is specified by supplying a list of six numbers:
777              
778             (x, y, ๐˜…, ๐˜†, ๐•ฉ, ๐•ช)
779              
780             where (x, y), (๐˜…, ๐˜†) and (๐•ฉ, ๐•ช) are the coordinates of the vertices of the
781             triangle.
782              
783             =head2 exCircles sub triangle
784              
785             Calls sub([$x,$y,$r]...) where $x,$y are the coordinates of the centre of each
786             ex-circle and $r its radius for the specified triangle:
787              
788             See: https://en.wikipedia.org/wiki/Incircle_and_excircles_of_a_triangle
789              
790             A triangle is specified by supplying a list of six numbers:
791              
792             (x, y, ๐˜…, ๐˜†, ๐•ฉ, ๐•ช)
793              
794             where (x, y), (๐˜…, ๐˜†) and (๐•ฉ, ๐•ช) are the coordinates of the vertices of the
795             triangle.
796              
797             =head2 circleInscribedInTriangle sub triangle
798              
799             Calls sub($x,$y,$r) where $x,$y are the coordinates of the centre of
800             a circle which touches each side of the triangle just once and $r is its radius:
801              
802             See: https://en.wikipedia.org/wiki/Incircle_and_excircles_of_a_triangle#Incircle
803              
804             A triangle is specified by supplying a list of six numbers:
805              
806             (x, y, ๐˜…, ๐˜†, ๐•ฉ, ๐•ช)
807              
808             where (x, y), (๐˜…, ๐˜†) and (๐•ฉ, ๐•ช) are the coordinates of the vertices of the
809             triangle.
810              
811             =head2 intersectionCircles ๐˜€๐˜‚๐—ฏ circle1, circle2
812              
813             Find the points at which two circles intersect. Complains if the two circles
814             are identical.
815              
816             ๐˜€๐˜‚๐—ฏ specifies a subroutine to be called with the coordinates of the
817             intersection points if there are any or an empty parameter list if there are
818             no points of intersection.
819              
820             A circle is specified by supplying a list of three numbers:
821              
822             (๐˜…, ๐˜†, ๐—ฟ)
823              
824             where (๐˜…, ๐˜†) are the coordinates of the centre of the circle and (๐—ฟ) is its
825             radius.
826              
827             Returns whatever is returned by ๐˜€๐˜‚๐—ฏ.
828              
829             =head2 intersectionCirclesArea ๐˜€๐˜‚๐—ฏ circle1, circle2
830              
831             Find the area of overlap of two circles expressed as a fraction of the area of
832             the smallest circle. The fractional area is expressed as a number between 0
833             and 1.
834              
835             ๐˜€๐˜‚๐—ฏ specifies a subroutine to be called with the fractional area.
836              
837             A circle is specified by supplying a list of three numbers:
838              
839             (๐˜…, ๐˜†, ๐—ฟ)
840              
841             where (๐˜…, ๐˜†) are the coordinates of the centre of the circle and (๐—ฟ) is its
842             radius.
843              
844             Returns whatever is returned by ๐˜€๐˜‚๐—ฏ.
845              
846             =head2 intersectionCircleLine ๐˜€๐˜‚๐—ฏ circle, line
847              
848             Find the points at which a circle and a line intersect.
849              
850             ๐˜€๐˜‚๐—ฏ specifies a subroutine to be called with the coordinates of the
851             intersection points if there are any or an empty parameter list if there are
852             no points of intersection.
853              
854             A circle is specified by supplying a list of three numbers:
855              
856             (๐˜…, ๐˜†, ๐—ฟ)
857              
858             where (๐˜…, ๐˜†) are the coordinates of the centre of the circle and (๐—ฟ) is its
859             radius.
860              
861             A line is specified by supplying a list of four numbers:
862              
863             (x, y, ๐˜…, ๐˜†)
864              
865             where (x, y) and (๐˜…, ๐˜†) are the coordinates of two points on the line.
866              
867             Returns whatever is returned by ๐˜€๐˜‚๐—ฏ.
868              
869             =head2 intersectionCircleLineArea ๐˜€๐˜‚๐—ฏ circle, line
870              
871             Find the fractional area of a circle occupied by a lune produced by an
872             intersecting line. The fractional area is expressed as a number
873             between 0 and 1.
874              
875             ๐˜€๐˜‚๐—ฏ specifies a subroutine to be called with the fractional area.
876              
877             A circle is specified by supplying a list of three numbers:
878              
879             (๐˜…, ๐˜†, ๐—ฟ)
880              
881             where (๐˜…, ๐˜†) are the coordinates of the centre of the circle and (๐—ฟ) is its
882             radius.
883              
884             A line is specified by supplying a list of four numbers:
885              
886             (x, y, ๐˜…, ๐˜†)
887              
888             where (x, y) and (๐˜…, ๐˜†) are the coordinates of two points on the line.
889              
890             Returns whatever is returned by ๐˜€๐˜‚๐—ฏ.
891              
892             =head2 intersectionLines ๐˜€๐˜‚๐—ฏ line1, line2
893              
894             Finds the point at which two lines intersect.
895              
896             ๐˜€๐˜‚๐—ฏ specifies a subroutine to be called with the coordinates of the
897             intersection point or an empty parameter list if the two lines do not
898             intersect.
899              
900             Complains if the two lines are collinear.
901              
902             A line is specified by supplying a list of four numbers:
903              
904             (x, y, ๐˜…, ๐˜†)
905              
906             where (x, y) and (๐˜…, ๐˜†) are the coordinates of two points on the line.
907              
908             Returns whatever is returned by ๐˜€๐˜‚๐—ฏ.
909              
910             =head2 intersectionLinePoint ๐˜€๐˜‚๐—ฏ line, point
911              
912             Find the point on a line closest to a specified point.
913              
914             ๐˜€๐˜‚๐—ฏ specifies a subroutine to be called with the coordinates of the
915             intersection points if there are any.
916              
917             A line is specified by supplying a list of four numbers:
918              
919             (x, y, ๐˜…, ๐˜†)
920              
921             where (x, y) and (๐˜…, ๐˜†) are the coordinates of two points on the line.
922              
923             A point is specified by supplying a list of two numbers:
924              
925             (๐˜…, ๐˜†)
926              
927             where (๐˜…, ๐˜†) are the coordinates of the point.
928              
929             Returns whatever is returned by ๐˜€๐˜‚๐—ฏ.
930              
931             =head2 isEquilateralTriangle triangle
932              
933             Return true if the specified triangle is close to being equilateral within the
934             definition of nearness.
935              
936             A triangle is specified by supplying a list of six numbers:
937              
938             (x, y, ๐˜…, ๐˜†, ๐•ฉ, ๐•ช)
939              
940             where (x, y), (๐˜…, ๐˜†) and (๐•ฉ, ๐•ช) are the coordinates of the vertices of the
941             triangle.
942              
943             =head2 isIsoscelesTriangle triangle
944              
945             Return true if the specified triangle is close to being isosceles within the
946             definition of nearness.
947              
948             A triangle is specified by supplying a list of six numbers:
949              
950             (x, y, ๐˜…, ๐˜†, ๐•ฉ, ๐•ช)
951              
952             where (x, y), (๐˜…, ๐˜†) and (๐•ฉ, ๐•ช) are the coordinates of the vertices of the
953             triangle.
954              
955             =head2 isRightAngledTriangle triangle
956              
957             Return true if the specified triangle is close to being right angled within
958             the definition of nearness.
959              
960             A triangle is specified by supplying a list of six numbers:
961              
962             (x, y, ๐˜…, ๐˜†, ๐•ฉ, ๐•ช)
963              
964             where (x, y), (๐˜…, ๐˜†) and (๐•ฉ, ๐•ช) are the coordinates of the vertices of the
965             triangle.
966              
967             =head2 ninePointCircle sub triangle
968              
969             Calls sub($x,$y,$r) where $x,$y are the coordinates of the centre of the
970             circle drawn through the midpoints of each side of the specified triangle and
971             $r is its radius which guves the nine point circle:
972              
973             See: https://en.wikipedia.org/wiki/Nine-point_circle
974              
975             A triangle is specified by supplying a list of six numbers:
976              
977             (x, y, ๐˜…, ๐˜†, ๐•ฉ, ๐•ช)
978              
979             where (x, y), (๐˜…, ๐˜†) and (๐•ฉ, ๐•ช) are the coordinates of the vertices of the
980             triangle.
981              
982             =head2 orthoCentre sub triangle
983              
984             Calls sub($x,$y) where $x,$y are the coordinates of the ortho-centre of the
985             specified triangle:
986              
987             See: https://en.wikipedia.org/wiki/Altitude_%28triangle%29
988              
989             A triangle is specified by supplying a list of six numbers:
990              
991             (x, y, ๐˜…, ๐˜†, ๐•ฉ, ๐•ช)
992              
993             where (x, y), (๐˜…, ๐˜†) and (๐•ฉ, ๐•ช) are the coordinates of the vertices of the
994             triangle.
995              
996             =head2 $Math::Intersection::Circle::Line::near
997              
998             As a finite computer cannot represent an infinite plane of points it is
999             necessary to make the plane discrete by merging points closer than the
1000             distance contained in this variable, which is set by default to 1e-6.
1001              
1002             =head1 Export
1003              
1004             The following functions are exported by default:
1005              
1006             =over
1007              
1008             =item C
1009              
1010             =item C
1011              
1012             =item C
1013              
1014             =item C
1015              
1016             =item C
1017              
1018             =item C
1019              
1020             =item C
1021              
1022             =item C
1023              
1024             =item C
1025              
1026             =item C
1027              
1028             =item C
1029              
1030             =item C
1031              
1032             =item C
1033              
1034             =item C
1035              
1036             =item C
1037              
1038             =item C
1039              
1040             =item C
1041              
1042             =item C
1043              
1044             =item C
1045              
1046             =back
1047              
1048             Optionally some useful helper functions can also be exported either by
1049             specifying the tag :๐—ฎ๐—น๐—น or by naming the required functions individually:
1050              
1051             =over
1052              
1053             =item C
1054              
1055             =item C
1056              
1057             =item C
1058              
1059             =item C
1060              
1061             =item C
1062              
1063             =item C
1064              
1065             =item C
1066              
1067             =item C
1068              
1069             =item C
1070              
1071             =item C
1072              
1073             =item C
1074              
1075             =item C
1076              
1077             =item C<๐ฟ()>
1078              
1079             =back
1080              
1081             =head1 Installation
1082              
1083             Standard Module::Build process for building and installing modules:
1084              
1085             perl Build.PL
1086             ./Build
1087             ./Build test
1088             ./Build install
1089              
1090             Or, if you're on a platform (like DOS or Windows) that doesn't require
1091             the "./" notation, you can do this:
1092              
1093             perl Build.PL
1094             Build
1095             Build test
1096             Build install
1097              
1098             =head1 Author
1099              
1100             Philip R Brenan at gmail dot com
1101              
1102             http://www.appaapps.com
1103              
1104             =head1 Copyright
1105              
1106             Copyright (c) 2015 Philip R Brenan.
1107              
1108             This module is free software. It may be used, redistributed and/or
1109             modified under the same terms as Perl itself.
1110              
1111             =cut