Line circle intersection: Difference between revisions

Content added Content deleted
Line 2,149: Line 2,149:
[(8.0000, 5.0000)]
[(8.0000, 5.0000)]
</pre>
</pre>

=={{header|Visual Basic .NET}}==
{{trans|C#}}
<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</lang>
{{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|zkl}}==
=={{header|zkl}}==