Line circle intersection: Difference between revisions

Added FreeBASIC
(Added Wren)
(Added FreeBASIC)
 
(11 intermediate revisions by 8 users not shown)
Line 17:
 
Illustrate your method with some examples (or use the Go examples below).
 
;Stretch Task
 
Include results for a circle with center at (10, 10) and radius 5 combined with a line through points (5, 0) and (5, 20) and that same circle combined with a line segment from (-5, 10) to (5, 10).
 
 
;References
Line 23 ⟶ 28:
*See [https://mathworld.wolfram.com/Circle-LineIntersection.html Wolfram] for the formulae needed.
 
=={{header|AutoHotkey}}==
<syntaxhighlight lang="autohotkey">data := [[[3, -5], 3, [-10, 11], [10, -9], 0]
, [[3, -5], 3, [-10, 11], [-11, 12], 1]
, [[3, -5], 3, [3, -2], [7, -2], 1]
, [[0, 0], 4, [0, -3], [0, 6], 0]
, [[0, 0], 4, [0, -3], [0, 6], 1]
, [[4, 2], 5, [6, 3], [10, 7], 0]
, [[4, 2], 5, [7, 4], [11, 8], 1]]
 
Result := "Center`tRad`tP1`tP2`tSegment`tintersect 1`tIntersect 2`n"
for i, obj in data
{
x := Line_circle_intersection(center := obj.1, radius := obj.2, P1 := obj.3, P2 := obj.4, Segment := obj.5)
Result .= "[" center.1 "," center.2 "]`t" radius "`t[" p1.1 "," p1.2 "]`t[" p2.1 "," p2.2 "]`t" Segment
for i, v in x
Result .= "`t[" i "]"
Result .= "`n"
}
MsgBox % Result
return
 
Line_circle_intersection(c, r, p1, p2, segment:=0){
global result
p1.1 -= c.1, p2.1 -= c.1, p1.2 -= c.2, p2.2 -= c.2
dx := p2.1 - p1.1, dy := p2.2 - p1.2
dr := Sqrt(dx**2 + dy**2)
D := p1.1*p2.2 - p2.1*p1.2
x1 := (D * dy + sgn(dy) * dx * Sqrt(r**2 * dr**2 - D**2)) / dr**2
x2 := (D * dy - sgn(dy) * dx * Sqrt(r**2 * dr**2 - D**2)) / dr**2
y1 := (0-D * dx + Abs(dy) * Sqrt(r**2 * dr**2 - D**2)) / dr**2
y2 := (0-D * dx - Abs(dy) * Sqrt(r**2 * dr**2 - D**2)) / dr**2
 
p1.1 += c.1, p2.1 += c.1, p1.2 += c.2, p2.2 += c.2
x1 += c.1, x2 += c.1, y1 += c.2, y2 += c.2
 
res := []
if segment
{
if !((x1 < p1.1 && x1 < p2.1) || (x1 > p1.1 && x1 > p2.1)
|| (y1 < p1.2 && y1 < p2.2) || (y1 > p1.2 && y1 > p2.2))
res[x1 ", " y1] := true
if !((x2 < p1.1 && x2 < p2.1) || (x2 > p1.1 && x2 > p2.1)
|| (y2 < p1.2 && y2 < p2.2) || (y2 > p1.2 && y2 > p2.2))
res[x2 ", " y2] := true
}
else
res[x1 ", " y1] := true, res[x2 ", " y2] := true
return res
}
sgn(x){
return x<0?-1:1
}</syntaxhighlight>
{{out}}
<pre>Center Rad P1 P2 Segment intersect 1 Intersect 2
[3,-5] 3 [-10,11] [10,-9] 0 [3.000000, -2.000000] [6.000000, -5.000000]
[3,-5] 3 [-10,11] [-11,12] 1
[3,-5] 3 [3,-2] [7,-2] 1 [3.000000, -2.000000]
[0,0] 4 [0,-3] [0,6] 0 [0.000000, -4.000000] [0.000000, 4.000000]
[0,0] 4 [0,-3] [0,6] 1 [0.000000, 4.000000]
[4,2] 5 [6,3] [10,7] 0 [1.000000, -2.000000] [8.000000, 5.000000]
[4,2] 5 [7,4] [11,8] 1 [8.000000, 5.000000]</pre>
 
=={{header|C}}==
{{trans|Go}}
<langsyntaxhighlight lang="c">#include <math.h>
#include <stdbool.h>
#include <stdio.h>
Line 190 ⟶ 257:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>The intersection points (if any) between:
Line 213 ⟶ 280:
=={{header|C++}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <utility>
#include <vector>
Line 385 ⟶ 452:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>The intersection points (if any) between:
Line 408 ⟶ 475:
=={{header|C#}}==
{{trans|C++}}
<langsyntaxhighlight Csharplang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 555 ⟶ 622:
public override string ToString() => $"{{ C:{Center}, R:{Radius} }}";
}
}</langsyntaxhighlight>
{{out}}
<pre>Circle: { C:(3, -5), R:3 }
Line 580 ⟶ 647:
=={{header|D}}==
{{trans|C++}}
<langsyntaxhighlight lang="d">import std.format;
import std.math;
import std.stdio;
Line 764 ⟶ 831:
writeln(" a segment starting at ", p1, " and ending at ", p2, " is/are:");
writeln(" ", intersects(p1, p2, cp, r, true));
}</langsyntaxhighlight>
{{out}}
<pre>The intersection points (if any) between:
Line 784 ⟶ 851:
a segment starting at (7, 4) and ending at (11, 8) is/are:
[(8, 5)]</pre>
 
=={{header|FreeBASIC}}==
{{trans|C}}
<syntaxhighlight lang="vbnet">#define eps 1e-14
#define fx(a, b, c, d) -(a * d + c) / b
#define fy(a, b, c, d) -(b * d + c) / a
 
Type puntoT
Dim As Double x, y
End Type
 
Function construye_punto(x As Double, y As Double) As puntoT
Dim As puntoT p1 = (x, y)
Return p1
End Function
 
Sub imprime_punto(p As puntoT)
Dim As Double x = p.x
Dim As Double y = p.y
If x = 0 Then x = 0
If y = 0 Then y = 0
Print Using "(&, &)"; x; y;
End Sub
 
Function sq(x As Double) As Double
Return x * x
End Function
 
Function dentro(x1 As Double, y1 As Double, x2 As Double, y2 As Double, x As Double, y As Double) As Boolean
Dim d1 As Double = Sqr(sq(x2 - x1) + sq(y2 - y1)) ' distance between end-points
Dim d2 As Double = Sqr(sq(x - x1) + sq(y - y1)) ' distance from point to one end
Dim d3 As Double = Sqr(sq(x2 - x) + sq(y2 - y)) ' distance from point to other end
Dim delta As Double = d1 - d2 - d3
Return Abs(delta) < eps ' true if delta is less than a small tolerance
End Function
 
Function rxy(x1 As Double, y1 As Double, x2 As Double, y2 As Double, x As Double, y As Double, segmento As Boolean) As Integer
If Not segmento Or dentro(x1, y1, x2, y2, x, y) Then
imprime_punto(construye_punto(x, y))
Return 1
Else
Return 0
End If
End Function
 
' Prints the intersection puntos (if any) of a circle, center 'cp' with radius 'r',
' and either an infinite line containing the puntos 'p1' and 'p2'
' or a segmento drawn between those puntos.
Sub interseccion(p1 As puntoT, p2 As puntoT, cp As puntoT, r As Double, segmento As Boolean)
Dim As Double x0 = cp.x, y0 = cp.y
Dim As Double x1 = p1.x, y1 = p1.y
Dim As Double x2 = p2.x, y2 = p2.y
Dim As Double A1 = y2 - y1, B1 = x1 - x2, C1 = x2 * y1 - x1 * y2
Dim As Double a = sq(A1) + sq(B1)
Dim As Double b, c, d, x ,y
Dim As Boolean bnz = True
Dim As Integer cnt = 0
If Abs(B1) >= eps Then
' if B1 isn't zero or close to it
b = 2 * (A1 * C1 + A1 * B1 * y0 - B1 * B1 * x0)
c = sq(C1) + 2 * B1 * C1 * y0 - sq(B1) * (sq(r) - sq(x0) - sq(y0))
Else
b = 2 * (B1 * C1 + A1 * B1 * x0 - sq(A1) * y0)
c = sq(C1) + 2 * A1 * C1 * x0 - sq(A1) * (sq(r) - sq(x0) - sq(y0))
bnz = False
End If
d = sq(b) - 4 * a * c ' discriminant
Select Case d
Case Is < 0
' line & circle don't intersect
Print "[]";
Case 0
' line is tangent to circle, so just one intersect at most
If bnz Then
x = -b / (2 * a)
y = fx(A1, B1, C1, x)
cnt = rxy(x1, y1, x2, y2, x, y, segmento)
Else
y = -b / (2 * a)
x = fy(A1, B1, C1, y)
cnt = rxy(x1, y1, x2, y2, x, y, segmento)
End If
Case Else
' two interseccion at most
d = Sqr(d)
If bnz Then
x = (-b + d) / (2 * a)
y = fx(A1, B1, C1, x)
cnt = rxy(x1, y1, x2, y2, x, y, segmento)
x = (-b - d) / (2 * a)
y = fx(A1, B1, C1, x)
cnt += rxy(x1, y1, x2, y2, x, y, segmento)
Else
y = (-b + d) / (2 * a)
x = fy(A1, B1, C1, y)
cnt = rxy(x1, y1, x2, y2, x, y, segmento)
y = (-b - d) / (2 * a)
x = fy(A1, B1, C1, y)
cnt += rxy(x1, y1, x2, y2, x, y, segmento)
End If
End Select
If cnt <= 0 Then Print "[]";
End Sub
 
Dim As puntoT cp = construye_punto(3, -5)
Dim As Double r = 3.0
Print "The intersection puntos (if any) between:"
Print " A circle, center (3, -5) with radius 3, and:"
Print " a line containing the points (-10, 11) and (10, -9) is/are:"
Print Spc(6); : interseccion(construye_punto(-10, 11), construye_punto(10, -9), cp, r, False)
Print !"\n a segment starting at (-10, 11) and ending at (-11, 12) is/are"
Print Spc(6); : interseccion(construye_punto(-10, 11), construye_punto(-11, 12), cp, r, True)
Print !"\n a horizontal line containing the points (3, -2) and (7, -2) is/are:"
Print Spc(6); : interseccion(construye_punto(3, -2), construye_punto(7, -2), cp, r, False)
 
cp = construye_punto(0, 0)
r = 4.0
Print !"\n A circle, center (0, 0) with radius 4, and:"
Print " a vertical line containing the points (0, -3) and (0, 6) is/are:"
Print Spc(6); : interseccion(construye_punto(0, -3), construye_punto(0, 6), cp, r, False)
Print !"\n a vertical segmento starting at (0, -3) and ending at (0, 6) is/are:"
Print Spc(6); : interseccion(construye_punto(0, -3), construye_punto(0, 6), cp, r, True)
 
cp = construye_punto(4,2)
r = 5.0
Print !"\n A circle, center (4, 2) with radius 5, and:"
Print " a line containing the points (6, 3) and (10, 7) is/are:"
Print Spc(6); : interseccion(construye_punto(6, 3), construye_punto(10, 7), cp, r, False)
Print !"\n a segment starting at (7, 4) and ending at (11, 8) is/are:"
Print Spc(6); : interseccion(construye_punto(7, 4), construye_punto(11, 8), cp, r, True)
 
Sleep</syntaxhighlight>
{{out}}
<pre>Same as C entry.</pre>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 915 ⟶ 1,121:
fmt.Println("\n a segment starting at (7, 4) and ending at (11, 8) is/are:")
fmt.Println(" ", intersects(point{7, 4}, point{11, 8}, cp, r, true))
cp = point{10, 10}
}</lang>
r = 5.0
fmt.Println("\n A circle, center (10, 10) with radius 5, and:")
fmt.Println("\n a vertical line containing the points (5, 0) and (5, 20) is/are:")
fmt.Println(" ", intersects(point{5, 0}, point{5, 20}, cp, r, false))
fmt.Println("\n a horizontal segment starting at (-5, 10) and ending at (5, 10) is/are:")
fmt.Println(" ", intersects(point{-5, 10}, point{5, 10}, cp, r, true))
}</syntaxhighlight>
 
{{out}}
Line 947 ⟶ 1,160:
a segment starting at (7, 4) and ending at (11, 8) is/are:
[(8, 5)]
 
A circle, center (10, 10) with radius 5, and:
 
a vertical line containing the points (5, 0) and (5, 20) is/are:
[(5, 10)]
 
a horizontal segment starting at (-5, 10) and ending at (5, 10) is/are:
[(5, 10)]
</pre>
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">import Data.Tuple.Curry
 
main :: IO ()
Line 1,024 ⟶ 1,245:
sgn x
| 0 > x = -1
| otherwise = 1</langsyntaxhighlight>
{{out}}
<pre>Intersection: Circle (3.0,-5.0) 3.0 and Line (-10.0,11.0) (10.0,-9.0): [(3.0,-2.0),(6.0,-5.0)]
Line 1,048 ⟶ 1,269:
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">import java.util.*;
import java.awt.geom.*;
 
Line 1,154 ⟶ 1,375:
return str.toString();
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,190 ⟶ 1,411:
=={{header|Julia}}==
Uses the circles and points from the Go example.
<langsyntaxhighlight lang="julia">using Luxor
 
const centers = [Point(3, -5), Point(0, 0), Point(4, 2)]
Line 1,208 ⟶ 1,429:
println(rpad(centers[cr], 17), rads[cr], " "^3, rpad(lins[l][1], 21),
rpad(lins[l][2], 19), rpad(!extended, 8), isempty(v) ? "" :
length(v) == 2 && tup[1] == 2 ? rpad(v[1], 18) * string(v[2]) : v[1])
end
</langsyntaxhighlight>{{out}}
<pre>
Center Radius Line P1 Line P2 Segment? Intersect 1 Intersect 2
Line 1,224 ⟶ 1,445:
=={{header|Kotlin}}==
{{trans|Go}}
<langsyntaxhighlight lang="scala">import kotlin.math.absoluteValue
import kotlin.math.sqrt
 
Line 1,379 ⟶ 1,600:
println(" a segment starting at $p1 and ending at $p2 is/are:")
println(" ${intersects(p1, p2, cp, r, true)}")
}</langsyntaxhighlight>
{{out}}
<pre>The intersection points (if any) between:
Line 1,402 ⟶ 1,623:
=={{header|Lua}}==
{{trans|C++}}
<langsyntaxhighlight lang="lua">EPS = 1e-14
 
function pts(p)
Line 1,559 ⟶ 1,780:
end
 
main()</langsyntaxhighlight>
{{out}}
<pre>The intersection points (if any) between:
Line 1,579 ⟶ 1,800:
a segment starting at (7, 4) and ending at (11, 8) is/are:
[(8, 5)]</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">LineCircleIntersections[p1_, p2_, c_, r_, type_] := RegionIntersection[Circle[c, r], type[{p1, p2}]]
LineCircleIntersections[{-1, 1}, {1, 1}, {0, 0}, 1, Line]
LineCircleIntersections[{-1, 0}, {2, 0.4}, {0, 0}, 1, Line]
LineCircleIntersections[{-1.5, 0}, {-2, 0.4}, {0, 0}, 1, Line]
LineCircleIntersections[{-1.5, 0}, {-2, 0.4}, {0, 0}, 1, InfiniteLine]</syntaxhighlight>
{{out}}
<pre>Point[{{0,1}}]
Point[{{-1,0},{0.965066,0.262009}}]
EmptyRegion[2]
Point[{{-0.858057,-0.513554},{-0.312675,-0.94986}}]</pre>
 
=={{header|Nim}}==
{{trans|Go}}
<syntaxhighlight lang="nim">import math, strutils
 
const Eps = 1e-14
 
type Point = tuple[x, y: float]
 
func `$`(p: Point): string =
let x = if p.x == 0.0: 0.0 else: p.x
let y = if p.y == 0.0: 0.0 else: p.y
"($1, $2)".format(x, y)
 
 
func intersects(p1, p2, cp: Point; r: float; segment: bool): seq[Point] =
let
(x0, y0) = cp
(x1, y1) = p1
(x2, y2) = p2
A = y2 - y1
B = x1 - x2
C = x2 * y1 - x1 * y2
var
a = A^2 + B^2
b, c: float
bnz = true
if abs(B) >= Eps:
b = 2 * (A * C + A * B * y0 - B^2 * x0)
c = C^2 + 2 * B * C * y0 - B^2 * (r^2 - x0^2 - y0^2)
else:
b = 2 * (B * C + A * B * x0 - A^2 * y0)
c = C^2 + 2 * A * C * x0 - A^2 * (r^2 - x0^2 - y0^2)
bnz = false
let d = b^2 - 4 * a * c
if d < 0: return # Line & circle don't intersect.
 
func within(x, y: float): bool =
## Checks whether a point is within a segment.
let
d1 = sqrt((x2 - x1)^2 + (y2 - y1)^2) # Distance between end-points.
d2 = sqrt((x - x1)^2 + (y - y1)^2) # Distance from point to one end.
d3 = sqrt((x2 - x)^2 + (y2 - y)^2) # Distance from point to other end.
delta = d1 - d2 - d3
result = abs(delta) < Eps # True if delta is less than a small tolerance.
 
var x, y: float
template fx: float = -(A * x + C) / B
template fy: float = -(B * y + C) / A
template rxy() =
if not segment or within(x, y):
result.add (x, y)
 
if d == 0:
# Line is tangent to circle, so just one intersect at most.
if bnz:
x = -b / (2 * a)
y = fx()
rxy()
else:
y = -b / (2 * a)
x = fy()
rxy()
else:
# Two intersects at most.
let d = sqrt(d)
if bnz:
x = (-b + d) / (2 * a)
y = fx()
rxy()
x = (-b - d) / (2 * a)
y = fx()
rxy()
else:
y = (-b + d) / (2 * a)
x = fy()
rxy()
y = (-b - d) / (2 * a)
x = fy()
rxy()
 
 
when isMainModule:
 
var cp: Point = (3.0, -5.0)
var r = 3.0
echo "The intersection points (if any) between:"
echo "\n A circle, center (3, -5) with radius 3, and:"
echo "\n a line containing the points (-10, 11) and (10, -9) is/are:"
echo " ", intersects((-10.0, 11.0), (10.0, -9.0), cp, r, false)
echo "\n a segment starting at (-10, 11) and ending at (-11, 12) is/are"
echo " ", intersects((-10.0, 11.0), (-11.0, 12.0), cp, r, true)
echo "\n a horizontal line containing the points (3, -2) and (7, -2) is/are:"
echo " ", intersects((3.0, -2.0), (7.0, -2.0), cp, r, false)
cp = (0.0, 0.0)
r = 4.0
echo "\n A circle, center (0, 0) with radius 4, and:"
echo "\n a vertical line containing the points (0, -3) and (0, 6) is/are:"
echo " ", intersects((0.0, -3.0), (0.0, 6.0), cp, r, false)
echo "\n a vertical segment starting at (0, -3) and ending at (0, 6) is/are:"
echo " ", intersects((0.0, -3.0), (0.0, 6.0), cp, r, true)
cp = (4.0, 2.0)
r = 5.0
echo "\n A circle, center (4, 2) with radius 5, and:"
echo "\n a line containing the points (6, 3) and (10, 7) is/are:"
echo " ", intersects((6.0, 3.0), (10.0, 7.0), cp, r, false)
echo "\n a segment starting at (7, 4) and ending at (11, 8) is/are:"
echo " ", intersects((7.0, 4.0), (11.0, 8.0), cp, r, true)</syntaxhighlight>
 
{{out}}
<pre>The intersection points (if any) between:
 
A circle, center (3, -5) with radius 3, and:
 
a line containing the points (-10, 11) and (10, -9) is/are:
@[(6.0, -5.0), (3.0, -2.0)]
 
a segment starting at (-10, 11) and ending at (-11, 12) is/are
@[]
 
a horizontal line containing the points (3, -2) and (7, -2) is/are:
@[(3.0, -2.0)]
 
A circle, center (0, 0) with radius 4, and:
 
a vertical line containing the points (0, -3) and (0, 6) is/are:
@[(0.0, 4.0), (0.0, -4.0)]
 
a vertical segment starting at (0, -3) and ending at (0, 6) is/are:
@[(0.0, 4.0)]
 
A circle, center (4, 2) with radius 5, and:
 
a line containing the points (6, 3) and (10, 7) is/are:
@[(8.0, 5.0), (1.0, -2.0)]
 
a segment starting at (7, 4) and ending at (11, 8) is/are:
@[(8.0, 5.0)]</pre>
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
Line 1,621 ⟶ 1,992:
say 'Solutions: ' . (@solution > 1 ? join ', ', map { '('. join(',', rnd @$_) .')' } @solution : 'None');
say '';
}</langsyntaxhighlight>
{{out}}
<pre>For input: (-10,11), (10,-9), (3,-5), 3
Line 1,647 ⟶ 2,018:
{{trans|Go}}
{{trans|zkl}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>constant epsilon = 1e-14 -- say
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
atom cx, cy, r, x1, y1, x2, y2
<span style="color: #008080;">constant</span> <span style="color: #000000;">epsilon</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1e-14</span> <span style="color: #000080;font-style:italic;">-- say</span>
 
<span style="color: #004080;">atom</span> <span style="color: #000000;">cx</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cy</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y2</span>
function sq(atom x) return x*x end function
 
<span style="color: #008080;">function</span> <span style="color: #000000;">sq</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">*</span><span style="color: #000000;">x</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function within(atom x, y)
--
<span style="color: #008080;">function</span> <span style="color: #000000;">within</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">)</span>
-- checks whether a point is within a segment
<span style="color: #000080;font-style:italic;">--
-- ie: <-------d1------->
-- checks whether a point <--d2--><---d3---> --is within, d2+d3 ~=a d1segment
-- ie: x1,y1^ ^x,y ^x2,y2&lt;-------d1-------&gt;
-- &lt;--d2--&gt;&lt;---d3---&gt; -- within, d2+d3 ~= d1
-- vs:
-- <-d2-> x1,y1^ ^x,y ^x2,y2
-- vs:
-- <-----------d3---------> -- not "", d2+d3 > d1
-- &lt;-d2-&gt;
-- ^x,y - and obviously ditto when x,y is (say) out here^
-- &lt;-----------d3---------&gt; -- not "", d2+d3 &gt; d1
--
-- (obviously only works when ^x,y is- onand theobviously sameditto linewhen as x1x,y1y tois x2,y2(say) out here^
--
-- (obviously only works when x,y is on the same line as x1,y1 to x2,y2)
atom d1 := sqrt(sq(x2-x1) + sq(y2-y1)), -- distance between end-points
--</span>
d2 := sqrt(sq(x -x1) + sq(y -y1)), -- distance from point to one end
<span style="color: #004080;">atom</span> <span style="color: #000000;">d1</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sq</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x2</span><span style="color: #0000FF;">-</span><span style="color: #000000;">x1</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">sq</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y2</span><span style="color: #0000FF;">-</span><span style="color: #000000;">y1</span><span style="color: #0000FF;">)),</span> <span style="color: #000080;font-style:italic;">-- distance between end-points</span>
d3 := sqrt(sq(x2-x ) + sq(y2-y )), -- distance from point to other end
<span style="color: #000000;">d2</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sq</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">x1</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">sq</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">y1</span><span style="color: #0000FF;">)),</span> <span style="color: #000080;font-style:italic;">-- distance from point to one end</span>
delta := (d2 + d3) - d1
<span style="color: #000000;">d3</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sq</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x2</span><span style="color: #0000FF;">-</span><span style="color: #000000;">x</span> <span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">sq</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y2</span><span style="color: #0000FF;">-</span><span style="color: #000000;">y</span> <span style="color: #0000FF;">)),</span> <span style="color: #000080;font-style:italic;">-- distance from point to other end</span>
return abs(delta) < epsilon -- true if delta is less than a small tolerance
<span style="color: #000000;">delta</span> <span style="color: #0000FF;">:=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">d2</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">d3</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">d1</span>
end function
<span style="color: #008080;">return</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">delta</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">epsilon</span> <span style="color: #000080;font-style:italic;">-- true if delta is less than a small tolerance</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function pf(atom x,y)
return sprintf("(%g,%g)",{x,y})
<span style="color: #008080;">function</span> <span style="color: #000000;">pf</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"(%g,%g)"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">})</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function intersects(bool bSegment)
--
<span style="color: #008080;">function</span> <span style="color: #000000;">intersects</span><span style="color: #0000FF;">(</span><span style="color: #004080;">bool</span> <span style="color: #000000;">bSegment</span><span style="color: #0000FF;">)</span>
-- Returns the intersection points (if any) of a circle, center (cx,cy) with radius r,
<span style="color: #000080;font-style:italic;">--
-- and line containing the points (x1,y1) and (x2,y2) being either infinite or limited
-- Returns the intersection points (if any) of a circle, center (cx,cy) with radius r,
-- to the segment drawn between those points.
-- and line containing the points (x1,y1) and (x2,y2) being either infinite or limited
--
-- to the segment drawn between those points.
sequence res = {}
--</span>
atom A = y2 - y1, sqA = sq(A),
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
B = x1 - x2, sqB = sq(B),
<span style="color: #004080;">atom</span> <span style="color: #000000;">A</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y2</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">y1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">sqA</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sq</span><span style="color: #0000FF;">(</span><span style="color: #000000;">A</span><span style="color: #0000FF;">),</span>
C = x2*y1 - x1*y2, sqC = sq(C),
<span style="color: #000000;">B</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x1</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">x2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">sqB</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sq</span><span style="color: #0000FF;">(</span><span style="color: #000000;">B</span><span style="color: #0000FF;">),</span>
sqr = r*r-cx*cx-cy*cy,
<span style="color: #000000;">C</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x2</span><span style="color: #0000FF;">*</span><span style="color: #000000;">y1</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">x1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">y2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">sqC</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sq</span><span style="color: #0000FF;">(</span><span style="color: #000000;">C</span><span style="color: #0000FF;">),</span>
a := sqA + sqB,
<span style="color: #000000;">sqr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">*</span><span style="color: #000000;">r</span><span style="color: #0000FF;">-</span><span style="color: #000000;">cx</span><span style="color: #0000FF;">*</span><span style="color: #000000;">cx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">cy</span><span style="color: #0000FF;">*</span><span style="color: #000000;">cy</span><span style="color: #0000FF;">,</span>
b, c
<span style="color: #000000;">a</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">sqA</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">sqB</span><span style="color: #0000FF;">,</span>
bool bDivA = false
<span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span>
if abs(B)<epsilon then -- B is zero or close to it
<span style="color: #004080;">bool</span> <span style="color: #000000;">bDivA</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
b = 2 * (B*C + A*B*cx - sqA*cy)
<span style="color: #008080;">if</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">B</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">epsilon</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- B is zero or close to it</span>
c = sqC + 2*A*C*cx - sqA*sqr
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span> <span style="color: #0000FF;">*</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">B</span><span style="color: #0000FF;">*</span><span style="color: #000000;">C</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">A</span><span style="color: #0000FF;">*</span><span style="color: #000000;">B</span><span style="color: #0000FF;">*</span><span style="color: #000000;">cx</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">sqA</span><span style="color: #0000FF;">*</span><span style="color: #000000;">cy</span><span style="color: #0000FF;">)</span>
bDivA = true -- (and later divide by A instead!)
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sqC</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">*</span><span style="color: #000000;">A</span><span style="color: #0000FF;">*</span><span style="color: #000000;">C</span><span style="color: #0000FF;">*</span><span style="color: #000000;">cx</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">sqA</span><span style="color: #0000FF;">*</span><span style="color: #000000;">sqr</span>
else
<span style="color: #000000;">bDivA</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span> <span style="color: #000080;font-style:italic;">-- (and later divide by A instead!)</span>
b = 2 * (A*C + A*B*cy - sqB*cx)
<span style="color: #008080;">else</span>
c = sqC + 2*B*C*cy - sqB*sqr
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span> <span style="color: #0000FF;">*</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">A</span><span style="color: #0000FF;">*</span><span style="color: #000000;">C</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">A</span><span style="color: #0000FF;">*</span><span style="color: #000000;">B</span><span style="color: #0000FF;">*</span><span style="color: #000000;">cy</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">sqB</span><span style="color: #0000FF;">*</span><span style="color: #000000;">cx</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sqC</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">*</span><span style="color: #000000;">B</span><span style="color: #0000FF;">*</span><span style="color: #000000;">C</span><span style="color: #0000FF;">*</span><span style="color: #000000;">cy</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">sqB</span><span style="color: #0000FF;">*</span><span style="color: #000000;">sqr</span>
atom d := b*b - 4*a*c -- discriminant
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if d>=0 then -- (-ve means line & circle do not intersect)
<span style="color: #004080;">atom</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">*</span><span style="color: #000000;">b</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">*</span><span style="color: #000000;">a</span><span style="color: #0000FF;">*</span><span style="color: #000000;">c</span> <span style="color: #000080;font-style:italic;">-- discriminant</span>
d = sqrt(d)
<span style="color: #008080;">if</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (-ve means line & circle do not intersect)</span>
atom ux,uy, vx,vy
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
if bDivA then
<span style="color: #004080;">atom</span> <span style="color: #000000;">ux</span><span style="color: #0000FF;">,</span><span style="color: #000000;">uy</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">vx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">vy</span>
{uy,vy} = sq_div(sq_sub({+d,-d},b),2*a)
<span style="color: #008080;">if</span> <span style="color: #000000;">bDivA</span> <span style="color: #008080;">then</span>
{ux,vx} = sq_div(sq_sub(sq_mul(-B,{uy,vy}),C),A)
<span style="color: #0000FF;">{</span><span style="color: #000000;">uy</span><span style="color: #0000FF;">,</span><span style="color: #000000;">vy</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_div</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">({+</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">d</span><span style="color: #0000FF;">},</span><span style="color: #000000;">b</span><span style="color: #0000FF;">),</span><span style="color: #000000;">2</span><span style="color: #0000FF;">*</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
else
<span style="color: #0000FF;">{</span><span style="color: #000000;">ux</span><span style="color: #0000FF;">,</span><span style="color: #000000;">vx</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_div</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_mul</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">B</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">uy</span><span style="color: #0000FF;">,</span><span style="color: #000000;">vy</span><span style="color: #0000FF;">}),</span><span style="color: #000000;">C</span><span style="color: #0000FF;">),</span><span style="color: #000000;">A</span><span style="color: #0000FF;">)</span>
{ux,vx} = sq_div(sq_sub({+d,-d},b),2*a)
<span style="color: #008080;">else</span>
{uy,vy} = sq_div(sq_sub(sq_mul(-A,{ux,vx}),C),B)
<span style="color: #0000FF;">{</span><span style="color: #000000;">ux</span><span style="color: #0000FF;">,</span><span style="color: #000000;">vx</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_div</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">({+</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">d</span><span style="color: #0000FF;">},</span><span style="color: #000000;">b</span><span style="color: #0000FF;">),</span><span style="color: #000000;">2</span><span style="color: #0000FF;">*</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #0000FF;">{</span><span style="color: #000000;">uy</span><span style="color: #0000FF;">,</span><span style="color: #000000;">vy</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_div</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_mul</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">A</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">ux</span><span style="color: #0000FF;">,</span><span style="color: #000000;">vx</span><span style="color: #0000FF;">}),</span><span style="color: #000000;">C</span><span style="color: #0000FF;">),</span><span style="color: #000000;">B</span><span style="color: #0000FF;">)</span>
if not bSegment or within(ux,uy) then
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
res = append(res,pf(ux,uy))
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">bSegment</span> <span style="color: #008080;">or</span> <span style="color: #000000;">within</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ux</span><span style="color: #0000FF;">,</span><span style="color: #000000;">uy</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ux</span><span style="color: #0000FF;">,</span><span style="color: #000000;">uy</span><span style="color: #0000FF;">))</span>
if d!=0 and (not bSegment or within(vx,vy)) then
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
res = append(res,pf(vx,vy))
<span style="color: #008080;">if</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #0000FF;">(</span><span style="color: #008080;">not</span> <span style="color: #000000;">bSegment</span> <span style="color: #008080;">or</span> <span style="color: #000000;">within</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">vy</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">vy</span><span style="color: #0000FF;">))</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return res
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
-- cx cy r x1 y1 x2 y2 bSegment
constant tests = {{3,-5,3,{{-10,11, 10,-9,false},
<span style="color: #000080;font-style:italic;">-- cx cy r x1 y1 {-10,11,-11,12,true},x2 y2 bSegment</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,{{-</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">},</span>
{ 3,-2, 7,-2,false}}},
<span style="color: #0000FF;">{-</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">},</span>
{0, 0,4,{{ 0,-3, 0, 6,false},
<span style="color: #0000FF;">{</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">}}},</span>
{ 0,-3, 0, 6,true}}},
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,{{</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">},</span>
{4, 2,5,{{ 6, 3, 10, 7,false},
<span style="color: #0000FF;">{</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">}}},</span>
{ 7, 4, 11, 8,true}}}}
<span style="color: #0000FF;">{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,{{</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">},</span>
 
<span style="color: #0000FF;">{</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">}}}}</span>
for t=1 to length(tests) do
{cx, cy, r, sequence lines} = tests[t]
<span style="color: #008080;">for</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
string circle = sprintf("Circle at %s radius %d",{pf(cx,cy),r})
<span style="color: #004080;">sequence</span> <span style="color: #000000;">lines</span>
for l=1 to length(lines) do
<span style="color: #0000FF;">{</span><span style="color: #000000;">cx</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cy</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lines</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">t</span><span style="color: #0000FF;">]</span>
{x1, y1, x2, y2, bool bSegment} = lines[l]
<span style="color: #004080;">string</span> <span style="color: #000000;">circle</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Circle at %s radius %d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cy</span><span style="color: #0000FF;">),</span><span style="color: #000000;">r</span><span style="color: #0000FF;">})</span>
sequence res = intersects(bSegment)
<span style="color: #008080;">for</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
string ls = iff(bSegment?"segment":" line"),
<span style="color: #004080;">bool</span> <span style="color: #000000;">bSegment</span>
at = iff(length(res)?"intersect at "&join(res," and ")
<span style="color: #0000FF;">{</span><span style="color: #000000;">x1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">bSegment</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">l</span><span style="color: #0000FF;">]</span>
:"do not intersect")
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">intersects</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bSegment</span><span style="color: #0000FF;">)</span>
printf(1,"%s and %s %s to %s %s.\n",{circle,ls,pf(x1,y1),pf(x2,y2),at})
<span style="color: #004080;">string</span> <span style="color: #000000;">ls</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bSegment</span><span style="color: #0000FF;">?</span><span style="color: #008000;">"segment"</span><span style="color: #0000FF;">:</span><span style="color: #008000;">" line"</span><span style="color: #0000FF;">),</span>
circle = repeat(' ',length(circle))
<span style="color: #000000;">at</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)?</span><span style="color: #008000;">"intersect at "</span><span style="color: #0000FF;">&</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" and "</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #0000FF;">:</span><span style="color: #008000;">"do not intersect"</span><span style="color: #0000FF;">)</span>
end for</lang>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s and %s %s to %s %s.\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">circle</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ls</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y1</span><span style="color: #0000FF;">),</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y2</span><span style="color: #0000FF;">),</span><span style="color: #000000;">at</span><span style="color: #0000FF;">})</span>
<span style="color: #000000;">circle</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">circle</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,755 ⟶ 2,131:
(formerly Perl 6)
Extend solution space to 3D. Reference: this [https://stackoverflow.com/questions/1073336/ SO question and answers]
<syntaxhighlight lang="raku" perl6line>sub LineCircularOBJintersection(@P1, @P2, @Centre, \Radius) {
my @d = @P2 »-« @P1 ; # d
my @f = @P1 »-« @Centre ; # c
Line 1,791 ⟶ 2,167:
say "For data set: ", $_;
say "Solution(s) is/are: ", @solution.Bool ?? @solution !! "None";
}</langsyntaxhighlight>
{{out}}
<pre>For data set: [(-10 11) (10 -9) (3 -5) 3]
Line 1,814 ⟶ 2,190:
The formulae used for this REXX version were taken from the MathWorld
webpage: &nbsp; [https://mathworld.wolfram.com/Circle-LineIntersection.html circle line intersection].
<langsyntaxhighlight lang="rexx">/*REXX program calculates where (or if) a line intersects (or tengents) a cirle. */
/*───────────────────────────────────── line= x1,y1 x2,y2; circle is at 0,0, radius=r*/
parse arg x1 y1 x2 y2 cx cy r . /*obtain optional arguments from the CL*/
Line 1,856 ⟶ 2,232:
numeric form; m.=9; parse value format(x,2,1,,0) 'E0' with g "E" _ .; g=g *.5'e'_ %2
do j=0 while h>9; m.j= h; h= h%2 + 1; end /*j*/
do k=j+5 to 0 by -1; numeric digits m.k; g= (g+x/g) *.5; end /*k*/; return g</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
Line 1,866 ⟶ 2,242:
=={{header|Ruby}}==
{{trans|C++}}
<langsyntaxhighlight lang="ruby">EPS = 1e-14
 
def sq(x)
Line 2,005 ⟶ 2,381:
end
 
main()</langsyntaxhighlight>
{{out}}
<pre>The intersection points (if any) between:
Line 2,025 ⟶ 2,401:
a segment starting at [7.0, 4.0] and ending at [11.0, 8.0] is/are:
[[8.0, 5.0]]</pre>
 
=={{header|Rust}}==
{{trans|C++}}
<syntaxhighlight lang="rust">
use assert_approx_eq::assert_approx_eq;
 
const EPS: f64 = 1e-14;
 
pub struct Point {
x: f64,
y: f64,
}
 
pub struct Line {
p1: Point,
p2: Point,
}
 
impl Line {
pub fn circle_intersections(&self, mx: f64, my: f64, r: f64, segment: bool) -> Vec<Point> {
let mut intersections: Vec<Point> = Vec::new();
 
let x0 = mx;
let y0 = my;
let x1 = self.p1.x;
let y1 = self.p1.y;
let x2 = self.p2.x;
let y2 = self.p2.y;
 
let ca = y2 - y1;
let cb = x1 - x2;
let cc = x2 * y1 - x1 * y2;
 
let a = ca.powi(2) + cb.powi(2);
let mut b = 0.0;
let mut c = 0.0;
let mut bnz = true;
 
if cb.abs() >= EPS {
b = 2.0 * (ca * cc + ca * cb * y0 - cb.powi(2) * x0);
c = cc.powi(2) + 2.0 * cb * cc * y0
- cb.powi(2) * (r.powi(2) - x0.powi(2) - y0.powi(2));
} else {
b = 2.0 * (cb * cc + ca * cb * x0 - ca.powi(2) * y0);
c = cc.powi(2) + 2.0 * ca * cc * x0
- ca.powi(2) * (r.powi(2) - x0.powi(2) - y0.powi(2));
bnz = false;
}
let mut d = b.powi(2) - 4.0 * a * c;
if d < 0.0 {
return intersections;
}
 
fn within(x: f64, y: f64, x1: f64, y1: f64, x2: f64, y2: f64) -> bool {
let d1 = ((x2 - x1).powi(2) + (y2 - y1).powi(2)).sqrt(); // distance between end-points
let d2 = ((x - x1).powi(2) + (y - y1).powi(2)).sqrt(); // distance from point to one end
let d3 = ((x2 - x).powi(2) + (y2 - y).powi(2)).sqrt(); // distance from point to other end
let delta = d1 - d2 - d3;
return delta.abs() < EPS;
}
 
fn fx(x: f64, ca: f64, cb: f64, cc: f64) -> f64 {
-(ca * x + cc) / cb
}
 
fn fy(y: f64, ca: f64, cb: f64, cc: f64) -> f64 {
-(cb * y + cc) / ca
}
 
fn rxy(
x: f64,
y: f64,
x1: f64,
y1: f64,
x2: f64,
y2: f64,
segment: bool,
intersections: &mut Vec<Point>,
) {
if !segment || within(x, y, x1, y1, x2, y2) {
let point = Point { x: x, y: y };
intersections.push(point);
}
}
 
if d == 0.0 {
if bnz {
let x = -b / (2.0 * a);
let y = fx(x, ca, cb, cc);
rxy(x, y, x1, y1, x2, y2, segment, &mut intersections);
} else {
let y = -b / (2.0 * a);
let x = fy(y, ca, cb, cc);
rxy(x, y, x1, y1, x2, y2, segment, &mut intersections);
}
} else {
d = d.sqrt();
if bnz {
let x = (-b + d) / (2.0 * a);
let y = fx(x, ca, cb, cc);
rxy(x, y, x1, y1, x2, y2, segment, &mut intersections);
let x = (-b - d) / (2.0 * a);
let y = fx(x, ca, cb, cc);
rxy(x, y, x1, y1, x2, y2, segment, &mut intersections);
} else {
let y = (-b + d) / (2.0 * a);
let x = fy(y, ca, cb, cc);
rxy(x, y, x1, y1, x2, y2, segment, &mut intersections);
let y = (-b - d) / (2.0 * a);
let x = fy(y, ca, cb, cc);
rxy(x, y, x1, y1, x2, y2, segment, &mut intersections);
}
}
 
intersections.sort_unstable_by(|a, b| a.x.partial_cmp(&b.x).unwrap());
intersections
}
}
 
#[cfg(test)]
mod tests {
use super::*;
 
#[test]
fn test_circle_line_intersections() {
let mut p1 = Point { x: -10.0, y: 11.0 };
let mut p2 = Point { x: 10.0, y: -9.0 };
let mut line = Line { p1: p1, p2: p2 };
 
let result1 = line.circle_intersections(3.0, -5.0, 3.0, false);
assert_eq!(result1.len(), 2);
assert_approx_eq!(result1[0].x, 3.0);
assert_approx_eq!(result1[0].y, -2.0);
assert_approx_eq!(result1[1].x, 6.0);
assert_approx_eq!(result1[1].y, -5.0);
 
p1 = Point { x: -10.0, y: 11.0 };
p2 = Point { x: -11.0, y: -12.0 };
line = Line { p1: p1, p2: p2 };
let result2 = line.circle_intersections(3.0, -5.0, 3.0, true);
assert_eq!(result2.len(), 0);
 
p1 = Point { x: 3.0, y: -2.0 };
p2 = Point { x: 7.0, y: -2.0 };
line = Line { p1, p2 };
let result3 = line.circle_intersections(3.0, -5.0, 3.0, true);
assert_eq!(result3.len(), 1);
assert_approx_eq!(result3[0].x, 3.0);
assert_approx_eq!(result3[0].y, -2.0);
 
p1 = Point { x: 0.0, y: -3.0 };
p2 = Point { x: 0.0, y: 6.0 };
line = Line { p1, p2 };
let result4 = line.circle_intersections(0.0, 0.0, 4.0, false);
assert_eq!(result4.len(), 2);
assert_approx_eq!(result4[0].x, 0.0);
assert_approx_eq!(result4[1].x, 0.0);
 
let result5 = line.circle_intersections(0.0, 0.0, 4.0, true);
assert_eq!(result5.len(), 1);
 
p1 = Point { x: 6.0, y: 3.0 };
p2 = Point { x: 10.0, y: 7.0 };
line = Line { p1, p2 };
let result6 = line.circle_intersections(4.0, 2.0, 5.0, false);
assert_eq!(result6.len(), 2);
assert_approx_eq!(result6[0].x, 1.0);
assert_approx_eq!(result6[0].y, -2.0);
assert_approx_eq!(result6[1].x, 8.0);
assert_approx_eq!(result6[1].y, 5.0);
 
p1 = Point { x: 7.0, y: 4.0 };
p2 = Point { x: 11.0, y: 8.0 };
line = Line { p1, p2 };
let result7 = line.circle_intersections(4.0, 2.0, 5.0, true);
assert_eq!(result7.len(), 1);
assert_approx_eq!(result7[0].x, 8.0);
assert_approx_eq!(result7[0].y, 5.0);
}
}
</syntaxhighlight>
 
{{out}}
<pre>
running 1 test
test tests::test_circle_line_intersections ... ok
test result: ok. 1
</pre>
 
 
=={{header|Swift}}==
{{trans|Java}}
<langsyntaxhighlight lang="swift">import Foundation
import CoreGraphics
 
Line 2,116 ⟶ 2,681:
center: center, radius: radius,
segment: true)
print(" \(toString(points: points))")</langsyntaxhighlight>
 
{{out}}
Line 2,152 ⟶ 2,717:
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<langsyntaxhighlight lang="vbnet">Module Module1
 
Structure Point
Line 2,330 ⟶ 2,895:
End Sub
 
End Module</langsyntaxhighlight>
{{out}}
<pre>Circle: { C:(3, -5), R:3 }
Line 2,355 ⟶ 2,920:
{{trans|Kotlin}}
{{libheader|Wren-dynamic}}
<langsyntaxhighlight ecmascriptlang="wren">import "./dynamic" for Tuple
 
var Point = Tuple.create("Point", ["x", "y"])
Line 2,487 ⟶ 3,052:
p2 = Point.new(11, 8)
System.print(" a segment starting at %(p1) and ending at %(p2) is/are:")
System.print(" %(intersects.call(p1, p2, cp, r, true))")</lang>
 
cp = Point.new(10, 10)
r = 5
System.print(" A circle, center %(cp) with radius %(r), and:")
 
p1 = Point.new( 5, 0)
p2 = Point.new( 5, 20)
System.print(" a vertical line containing the points %(p1) and %(p2) is/are:")
System.print(" %(intersects.call(p1, p2, cp, r, false))")
 
p1 = Point.new(-5, 10)
p2 = Point.new( 5, 10)
System.print(" a horizontal segment starting at %(p1) and ending at %(p2) is/are:")
System.print(" %(intersects.call(p1, p2, cp, r, true))")</syntaxhighlight>
 
{{out}}
Line 2,509 ⟶ 3,088:
a segment starting at (7, 4) and ending at (11, 8) is/are:
[(8, 5)]
A circle, center (10, 10) with radius 5, and:
a vertical line containing the points (5, 0) and (5, 20) is/are:
[(5, 10)]
a horizontal segment starting at (-5, 10) and ending at (5, 10) is/are:
[(5, 10)]
</pre>
 
=={{header|zkl}}==
{{trans|Go}}
<langsyntaxhighlight lang="zkl">const EPS=1e-14; // a close-ness to zero
// p1,p2 are (x,y), circle is ( (x,y),r )
fcn intersectLineCircle(p1,p2, circle, segment=False) // assume line
Line 2,561 ⟶ 3,145:
if(d==0) return( T( T(ux,uy) ) );
return( T(ux,uy), T(vx,vy) )
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">circle:=T( T(3,-5),3 ); p1,p2 := T(-10,11), T( 10,-9);
println("Circle @ ",circle); lcpp(p1,p2,circle);
p2:=T(-11,12); lcpp(p1,p2,circle,True);
Line 2,581 ⟶ 3,165:
.fmt(segment and "Segment" or "Line ",
p1,p2,intersectLineCircle(p1,p2, circle,segment)));
}</langsyntaxhighlight>
{{out}}
<pre>
2,122

edits