Line circle intersection: Difference between revisions

Added FreeBASIC
(→‎{{header|Go}}: Added stretch goal.)
(Added FreeBASIC)
 
(One intermediate revision by one other user not shown)
Line 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}}==
Line 2,781 ⟶ 2,920:
{{trans|Kotlin}}
{{libheader|Wren-dynamic}}
<syntaxhighlight lang="ecmascriptwren">import "./dynamic" for Tuple
 
var Point = Tuple.create("Point", ["x", "y"])
2,122

edits