Shortest Line between two Lines
Windows only
Overview
Two lines in three dimensions generally do not intersect at a point. They may be parallel (no intersections) or they may be coincident (infinite intersections) but most often only their projection onto a plane intersects. When they do not exactly intersect at a point they can be connected by a line segment, the shortest line segment is unique and is often considered to be their intersection in 3D.
Example
The following example code demonstrates how to calculate the shortest line between two line segments using RhinoScript…
Option Explicit
' Description:
' Returns the shortest line segment between
' two infinite line segments.
' Parameters:
' p1 - the starting point of the first line
' p2 - the ending point of the first line
' p3 - the starting point of the second line
' p4 - the ending point of the second line
' Returns
' Array - the shortest line segment if successful
' Null - if not successful or on error
Function LineLineIntersect(p1, p2, p3, p4)
LineLineIntersect = Null
Const EPS = 2.2204460492503131e-016
Dim p13(2), p43(2), p21(2)
Dim d1343, d4321, d1321, d4343, d2121, numer, denom, mua, mub
Dim pa(2), pb(2)
p13(0) = p1(0) - p3(0)
p13(1) = p1(1) - p3(1)
p13(2) = p1(2) - p3(2)
p43(0) = p4(0) - p3(0)
p43(1) = p4(1) - p3(1)
p43(2) = p4(2) - p3(2)
If Abs(p43(0)) < EPS And Abs(p43(1)) < EPS And Abs(p43(2)) < EPS Then Exit Function
p21(0) = p2(0) - p1(0)
p21(1) = p2(1) - p1(1)
p21(2) = p2(2) - p1(2)
If Abs(p21(0)) < EPS And Abs(p21(1)) < EPS And Abs(p21(2)) < EPS Then Exit Function
d1343 = p13(0) * p43(0) + p13(1) * p43(1) + p13(2) * p43(2)
d4321 = p43(0) * p21(0) + p43(1) * p21(1) + p43(2) * p21(2)
d1321 = p13(0) * p21(0) + p13(1) * p21(1) + p13(2) * p21(2)
d4343 = p43(0) * p43(0) + p43(1) * p43(1) + p43(2) * p43(2)
d2121 = p21(0) * p21(0) + p21(1) * p21(1) + p21(2) * p21(2)
denom = d2121 * d4343 - d4321 * d4321
If Abs(denom) < EPS Then Exit Function
numer = d1343 * d4321 - d1321 * d4343
mua = numer / denom
mub = (d1343 + d4321 * mua) / d4343
pa(0) = p1(0) + mua * p21(0)
pa(1) = p1(1) + mua * p21(1)
pa(2) = p1(2) + mua * p21(2)
pb(0) = p3(0) + mub * p43(0)
pb(1) = p3(1) + mub * p43(1)
pb(2) = p3(2) + mub * p43(2)
LineLineIntersect = Array(pa, pb)
End Function
You can test the above function as follows:
Sub Test
Dim l0 : l0 = Rhino.GetObject("Select first line", 4)
Dim l1 : l1 = Rhino.GetObject("Select second line", 4)
Dim p1 : p1 = Rhino.CurveStartPoint(l0)
Dim p2 : p2 = Rhino.CurveEndPoint(l0)
Dim p3 : p3 = Rhino.CurveStartPoint(l1)
Dim p4 : p4 = Rhino.CurveEndPoint(l1)
Dim rc : rc = LineLineIntersect(p1, p2, p3, p4)
If IsArray(rc) Then
Rhino.AddPoints rc
End If
End Sub