Line circle intersection: Difference between revisions

Content added Content deleted
Line 2,149:
[(8.0000, 5.0000)]
</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}}==