Line circle intersection: Difference between revisions

Added FreeBASIC
(Added FreeBASIC)
 
(15 intermediate revisions by 10 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 405 ⟶ 472:
a segment starting at (7, 4) and ending at (11, 8) is/are:
[(8, 5)]</pre>
 
=={{header|C#}}==
{{trans|C++}}
<syntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
 
public class Program
{
public static void Main()
{
Circle circle = ((3, -5), 3);
Line[] lines = {
((-10, 11), (10, -9)),
((-10, 11), (-11, 12), true),
((3, -2), (7, -2))
};
Print(circle, lines);
circle = ((0, 0), 4);
lines = new Line[] {
((0, -3), (0, 6)),
((0, -3), (0, 6), true)
};
Print(circle, lines);
circle = ((4, 2), 5);
lines = new Line[] {
((6, 3), (10, 7)),
((7, 4), (11, 8), true)
};
Print(circle, lines);
}
static void Print(Circle circle, Line[] lines)
{
Console.WriteLine($"Circle: {circle}");
foreach (var line in lines) {
Console.WriteLine($"\t{(line.IsSegment ? "Segment:" : "Line:")} {line}");
var points = Intersection(circle, line).ToList();
Console.WriteLine(points.Count == 0 ? "\t\tdo not intersect" : "\t\tintersect at " + string.Join(" and ", points));
}
Console.WriteLine();
}
static IEnumerable<Point> Intersection(Circle circle, Line line)
{
var intersection = LineIntersection(circle, line);
return line.IsSegment
? intersection.Where(p => p.CompareTo(line.P1) >= 0 && p.CompareTo(line.P2) <= 0)
: intersection;
 
static IEnumerable<Point> LineIntersection(Circle circle, Line line)
{
double x, y, A, B, C, D;
var (m, c) = (line.Slope, line.YIntercept);
var (p, q, r) = (circle.X, circle.Y, circle.Radius);
 
if (line.IsVertical) {
x = line.P1.X;
B = -2 * q;
C = p * p + q * q - r * r + x * x - 2 * p * x;
D = B * B - 4 * C;
if (D == 0) yield return (x, -q);
else if (D > 0) {
D = Math.Sqrt(D);
yield return (x, (-B - D) / 2);
yield return (x, (-B + D) / 2);
}
} else {
A = m * m + 1;
B = 2 * (m * c - m * q - p);
C = p * p + q * q - r * r + c * c - 2 * c * q;
D = B * B - 4 * A * C;
if (D == 0) {
x = -B / (2 * A);
y = m * x + c;
yield return (x, y);
} else if (D > 0) {
D = Math.Sqrt(D);
x = (-B - D) / (2 * A);
y = m * x + c;
yield return (x, y);
x = (-B + D) / (2 * A);
y = m * x + c;
yield return (x, y);
}
}
}
 
}
readonly struct Point : IComparable<Point>
{
public Point(double x, double y) => (X, Y) = (x, y);
public static implicit operator Point((double x, double y) p) => new Point(p.x, p.y);
public double X { get; }
public double Y { get; }
public int CompareTo(Point other)
{
int c = X.CompareTo(other.X);
if (c != 0) return c;
return Y.CompareTo(other.Y);
}
public override string ToString() => $"({X}, {Y})";
}
readonly struct Line
{
public Line(Point p1, Point p2, bool isSegment = false)
{
(P1, P2) = p2.CompareTo(p1) < 0 ? (p2, p1) : (p1, p2);
IsSegment = isSegment;
if (p1.X == p2.X) (Slope, YIntercept) = (double.PositiveInfinity, double.NaN);
else {
Slope = (P2.Y - P1.Y) / (P2.X - P1.X);
YIntercept = P2.Y - Slope * P2.X;
}
}
public static implicit operator Line((Point p1, Point p2) l) => new Line(l.p1, l.p2);
public static implicit operator Line((Point p1, Point p2, bool isSegment) l) => new Line(l.p1, l.p2, l.isSegment);
public Point P1 { get; }
public Point P2 { get; }
public double Slope { get; }
public double YIntercept { get; }
public bool IsSegment { get; }
public bool IsVertical => P1.X == P2.X;
public override string ToString() => $"[{P1}, {P2}]";
}
readonly struct Circle
{
public Circle(Point center, double radius) => (Center, Radius) = (center, radius);
public static implicit operator Circle((Point center, double radius) c) => new Circle(c.center, c.radius);
public Point Center { get; }
public double Radius { get; }
public double X => Center.X;
public double Y => Center.Y;
public override string ToString() => $"{{ C:{Center}, R:{Radius} }}";
}
}</syntaxhighlight>
{{out}}
<pre>Circle: { C:(3, -5), R:3 }
Line: [(-10, 11), (10, -9)]
intersect at (3, -2) and (6, -5)
Segment: [(-11, 12), (-10, 11)]
do not intersect
Line: [(3, -2), (7, -2)]
intersect at (3, -2)
 
Circle: { C:(0, 0), R:4 }
Line: [(0, -3), (0, 6)]
intersect at (0, -4) and (0, 4)
Segment: [(0, -3), (0, 6)]
intersect at (0, 4)
 
Circle: { C:(4, 2), R:5 }
Line: [(6, 3), (10, 7)]
intersect at (1, -2) and (8, 5)
Segment: [(7, 4), (11, 8)]
intersect at (8, 5)
</pre>
 
=={{header|D}}==
{{trans|C++}}
<langsyntaxhighlight lang="d">import std.format;
import std.math;
import std.stdio;
Line 592 ⟶ 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 612 ⟶ 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 743 ⟶ 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 775 ⟶ 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 852 ⟶ 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 876 ⟶ 1,269:
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">import java.util.*;
import java.awt.geom.*;
 
Line 982 ⟶ 1,375:
return str.toString();
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,018 ⟶ 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,036 ⟶ 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,052 ⟶ 1,445:
=={{header|Kotlin}}==
{{trans|Go}}
<langsyntaxhighlight lang="scala">import kotlin.math.absoluteValue
import kotlin.math.sqrt
 
Line 1,207 ⟶ 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,230 ⟶ 1,623:
=={{header|Lua}}==
{{trans|C++}}
<langsyntaxhighlight lang="lua">EPS = 1e-14
 
function pts(p)
Line 1,387 ⟶ 1,780:
end
 
main()</langsyntaxhighlight>
{{out}}
<pre>The intersection points (if any) between:
Line 1,407 ⟶ 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,449 ⟶ 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,475 ⟶ 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,583 ⟶ 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,619 ⟶ 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,642 ⟶ 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,684 ⟶ 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,694 ⟶ 2,242:
=={{header|Ruby}}==
{{trans|C++}}
<langsyntaxhighlight lang="ruby">EPS = 1e-14
 
def sq(x)
Line 1,833 ⟶ 2,381:
end
 
main()</langsyntaxhighlight>
{{out}}
<pre>The intersection points (if any) between:
Line 1,853 ⟶ 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 1,944 ⟶ 2,681:
center: center, radius: radius,
segment: true)
print(" \(toString(points: points))")</langsyntaxhighlight>
 
{{out}}
Line 1,976 ⟶ 2,713:
a segment starting at (7, 4) and ending at (11, 8) is/are:
[(8.0000, 5.0000)]
</pre>
 
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<syntaxhighlight lang="vbnet">Module Module1
 
Structure Point
Implements IComparable(Of Point)
 
Public Sub New(mx As Double, my As Double)
X = mx
Y = my
End Sub
 
Public ReadOnly Property X As Double
Public ReadOnly Property Y As Double
 
Public Function CompareTo(other As Point) As Integer Implements IComparable(Of Point).CompareTo
Dim c = X.CompareTo(other.X)
If c <> 0 Then
Return c
End If
Return Y.CompareTo(other.Y)
End Function
 
Public Overrides Function ToString() As String
Return String.Format("({0}, {1})", X, Y)
End Function
End Structure
 
Structure Line
Public Sub New(mp1 As Point, mp2 As Point, Optional segment As Boolean = False)
If P2.CompareTo(P1) < 0 Then
P1 = mp2
P2 = mp1
Else
P1 = mp1
P2 = mp2
End If
IsSegment = segment
If P1.X = P2.X Then
Slope = Double.PositiveInfinity
YIntercept = Double.NaN
Else
Slope = (P2.Y - P1.Y) / (P2.X - P1.X)
YIntercept = P2.Y - Slope * P2.X
End If
End Sub
 
Public ReadOnly Property P1 As Point
Public ReadOnly Property P2 As Point
Public ReadOnly Property Slope As Double
Public ReadOnly Property YIntercept As Double
Public ReadOnly Property IsSegment As Boolean
 
Public Function IsVertical() As Boolean
Return P1.X = P2.X
End Function
 
Public Overrides Function ToString() As String
Return String.Format("[{0}, {1}]", P1, P2)
End Function
End Structure
 
Structure Circle
Public Sub New(c As Point, r As Double)
Center = c
Radius = r
End Sub
 
Public ReadOnly Property Center As Point
Public ReadOnly Property Radius As Double
 
Public Function X() As Double
Return Center.X
End Function
 
Public Function Y() As Double
Return Center.Y
End Function
 
Public Overrides Function ToString() As String
Return String.Format("{{ C:{0}, R:{1} }}", Center, Radius)
End Function
End Structure
 
Function Intersection(oc As Circle, ol As Line) As IEnumerable(Of Point)
Dim LineIntersection = Iterator Function(ic As Circle, il As Line) As IEnumerable(Of Point)
Dim m = il.Slope
Dim c = il.YIntercept
Dim p = ic.X
Dim q = ic.Y
Dim r = ic.Radius
 
If il.IsVertical Then
Dim x = il.P1.X
Dim B = -2 * q
Dim CC = p * p + q * q - r * r + x * x - 2 * p * x
Dim D = B * B - 4 * CC
If D = 0 Then
Yield New Point(x, -q)
ElseIf D > 0 Then
D = Math.Sqrt(D)
Yield New Point(x, (-B - D) / 2)
Yield New Point(x, (-B + D) / 2)
End If
Else
Dim A = m * m + 1
Dim B = 2 * (m * c - m * q - p)
Dim CC = p * p + q * q - r * r + c * c - 2 * c * q
Dim D = B * B - 4 * A * CC
If D = 0 Then
Dim x = -B / (2 * A)
Dim y = m * x + c
Yield New Point(x, y)
ElseIf D > 0 Then
D = Math.Sqrt(D)
Dim x = (-B - D) / (2 * A)
Dim y = m * x + c
Yield New Point(x, y)
x = (-B + D) / (2 * A)
y = m * x + c
Yield New Point(x, y)
End If
End If
End Function
 
Dim int = LineIntersection(oc, ol)
If ol.IsSegment Then
Return int.Where(Function(p) p.CompareTo(ol.P1) >= 0 AndAlso p.CompareTo(ol.P2) <= 0)
Else
Return int
End If
End Function
 
Sub Print(c As Circle, lines() As Line)
Console.WriteLine("Circle: {0}", c)
For Each line In lines
Console.Write(vbTab)
If line.IsSegment Then
Console.Write("Segment: ")
Else
Console.Write("Line: ")
End If
Console.WriteLine(line)
 
Dim points = Intersection(c, line).ToList
 
Console.Write(vbTab + vbTab)
If points.Count = 0 Then
Console.WriteLine("do not intersect")
Else
Console.WriteLine("intersect at {0}", String.Join(" and ", points))
End If
Next
Console.WriteLine()
End Sub
 
Sub Main()
Dim c = New Circle(New Point(3, -5), 3)
Dim lines() As Line = {
New Line(New Point(-10, 11), New Point(10, -9)),
New Line(New Point(-10, 11), New Point(-11, 12), True),
New Line(New Point(3, -2), New Point(7, -2))
}
Print(c, lines)
 
c = New Circle(New Point(0, 0), 4)
lines = {
New Line(New Point(0, -3), New Point(0, 6)),
New Line(New Point(0, -3), New Point(0, 6), True)
}
Print(c, lines)
 
c = New Circle(New Point(4, 2), 5)
lines = {
New Line(New Point(6, 3), New Point(10, 7)),
New Line(New Point(7, 4), New Point(11, 8), True)
}
Print(c, lines)
End Sub
 
End Module</syntaxhighlight>
{{out}}
<pre>Circle: { C:(3, -5), R:3 }
Line: [(-10, 11), (10, -9)]
intersect at (3, -2) and (6, -5)
Segment: [(-10, 11), (-11, 12)]
do not intersect
Line: [(3, -2), (7, -2)]
intersect at (3, -2)
 
Circle: { C:(0, 0), R:4 }
Line: [(0, -3), (0, 6)]
intersect at (0, -4) and (0, 4)
Segment: [(0, -3), (0, 6)]
intersect at (0, 4)
 
Circle: { C:(4, 2), R:5 }
Line: [(6, 3), (10, 7)]
intersect at (1, -2) and (8, 5)
Segment: [(7, 4), (11, 8)]
intersect at (8, 5)</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-dynamic}}
<syntaxhighlight lang="wren">import "./dynamic" for Tuple
 
var Point = Tuple.create("Point", ["x", "y"])
 
var eps = 1e-14
 
var intersects = Fn.new { |p1, p2, cp, r, segment|
var res = []
var x0 = cp.x
var y0 = cp.y
var x1 = p1.x
var y1 = p1.y
var x2 = p2.x
var y2 = p2.y
var A = y2 - y1
var B = x1 - x2
var C = x2 * y1 - x1 * y2
var a = A * A + B * B
var b
var c
var bnz = true
if (B.abs >= eps) {
b = 2 * (A * C + A * B * y0 - B * B * x0)
c = C * C + 2 * B * C * y0 - B * B * (r * r - x0 * x0 - y0 * y0)
} else {
b = 2 * (B * C + A * B * x0 - A * A * y0)
c = C * C + 2 * A * C * x0 - A * A * (r * r - x0 * x0 - y0 * y0)
bnz = false
}
var d = b * b - 4 * a * c // discriminant
if (d < 0) {
return "[]"
}
 
// checks whether a point is within a segment
var within = Fn.new { |x0, y0|
var d1 = ((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)).sqrt // distance between end-points
var d2 = ((x0 - x1)*(x0 - x1) + (y0 - y1)*(y0 - y1)).sqrt // distance from point to one end
var d3 = ((x2 - x0)*(x2 - x0) + (y2 - y0)*(y2 - y0)).sqrt // distance from point to other end
var delta = d1 - d2 - d3
return delta.abs < eps // true if delta is less than a small tolerance
}
 
var x = 0
var fx = Fn.new { -(A * x + C) / B }
 
var y = 0
var fy = Fn.new { -(B * y + C) / A }
 
var rxy = Fn.new {
if (!segment || within.call(x, y)) {
res.add(Point.new(x, y))
}
}
if (d == 0) {
// line is tangent to circle, so just one intersect at most
if (bnz) {
x = -b / (2 * a)
y = fx.call()
} else {
y = -b / (2 * a)
x = fy.call()
}
rxy.call()
} else {
// two intersects at most
d = d.sqrt
if (bnz) {
x = (-b + d) / (2 * a)
y = fx.call()
rxy.call()
x = (-b - d) / (2 * a)
y = fx.call()
rxy.call()
} else {
y = (-b + d) / (2 * a)
x = fy.call()
rxy.call()
y = (-b - d) / (2 * a)
x = fy.call()
rxy.call()
}
}
 
// get rid of any negative zeros and return as a string
return res.toString.replace("-0,", "0,").replace("-0]", "0]")
}
 
System.print("The intersection points (if any) between:")
 
var cp = Point.new(3, -5)
var r = 3
System.print(" A circle, center %(cp) with radius %(r), and:")
 
var p1 = Point.new(-10, 11)
var p2 = Point.new( 10, -9)
System.print(" a line containing the points %(p1) and %(p2) is/are:")
System.print(" %(intersects.call(p1, p2, cp, r, false))")
 
p2 = Point.new(-10, 12)
System.print(" a segment starting at %(p1) and ending at %(p2) is/are:")
System.print(" %(intersects.call(p1, p2, cp, r, true))")
 
p1 = Point.new(3, -2)
p2 = Point.new(7, -2)
System.print(" a horizontal line containing the points %(p1) and %(p2) is/are:")
System.print(" %(intersects.call(p1, p2, cp, r, false))")
 
cp = Point.new(0, 0)
r = 4
System.print(" A circle, center %(cp) with radius %(r), and:")
 
p1 = Point.new(0, -3)
p2 = Point.new(0, 6)
System.print(" a vertical line containing the points %(p1) and %(p2) is/are:")
System.print(" %(intersects.call(p1, p2, cp, r, false))")
System.print(" a vertical segment containing the points %(p1) and %(p2) is/are:")
System.print(" %(intersects.call(p1, p2, cp, r, true))")
 
cp = Point.new(4, 2)
r = 5
System.print(" A circle, center %(cp) with radius %(r), and:")
 
p1 = Point.new( 6, 3)
p2 = Point.new(10, 7)
System.print(" a line containing the points %(p1) and %(p2) is/are:")
System.print(" %(intersects.call(p1, p2, cp, r, false))")
 
p1 = Point.new( 7, 4)
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))")
 
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}}
<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, -5), (3, -2)]
a segment starting at (-10, 11) and ending at (-10, 12) is/are:
[]
a horizontal line containing the points (3, -2) and (7, -2) is/are:
[(3, -2)]
A circle, center (0, 0) with radius 4, and:
a vertical line containing the points (0, -3) and (0, 6) is/are:
[(0, 4), (0, -4)]
a vertical segment containing the points (0, -3) and (0, 6) is/are:
[(0, 4)]
A circle, center (4, 2) with radius 5, and:
a line containing the points (6, 3) and (10, 7) is/are:
[(8, 5), (1, -2)]
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,028 ⟶ 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,048 ⟶ 3,165:
.fmt(segment and "Segment" or "Line ",
p1,p2,intersectLineCircle(p1,p2, circle,segment)));
}</langsyntaxhighlight>
{{out}}
<pre>
2,161

edits