Finding the closest points between 2 lines

As the title suggests, I want to find the closest points between 2 lines in 3D space, so I created a small module with the object Line. Here is a 2D simplified diagram of the math that I used:

(Of course, the lines extend infinitely in both directions. This is just a bad diagram)

Unfortunately, I’m also bad at math. Currently, the function generates two points that are close, but not the closest. I don’t know where I messed up. The similar tutorials that there are, I don’t understand, as I’m terrible at math.

Here are the main functions that are responsible. (Zero unit = 1, 0, 0)

``````--Subtract unit sphere
function Lines.sub(Unit1, Unit2, ZeroUnit)
if ZeroUnit then
Unit1 = Lines.sub(Unit1, ZeroUnit)
end

--Get X angles
local Horizon1 = math.acos(Unit1.X)
local Horizon2 = math.acos(Unit2.X)

--Get Y angles
local Zenith1 = math.asin(Unit1.Y)
local Zenith2 = math.asin(Unit2.Y)

--Get Z angles
local Zed1 = math.asin(Unit1.Z)
local Zed2 = math.asin(Unit2.Z)

--Subtract angles
local Horizon = Horizon1 - Horizon2
local Zenith = Zenith1 - Zenith2
local Zed = Zed1 - Zed2

--Convert angles back to unit vector
return Vector3.new(math.cos(Horizon), math.sin(Zenith), math.sin(Zed)).unit
end

--Rotates the line1 to zerounit
function Lines.relrot(Line_1, Line_2)
--Rotate origins and directions
local Direction1 = Lines.sub(Lines.clone(Line_1).Direction, Lines.clone(Line_1).Direction)
local Direction2 = Lines.sub(Lines.clone(Line_2).Direction, Lines.clone(Line_1).Direction)

--Distance between the origins of 2 lines
local Origin2_DistMag = Line_2.Origin.magnitude

--Copy of line2 origin
local Origin2_Copy = Vector3.new(Line_2.Origin.X, Line_2.Origin.Y, Line_2.Origin.Z).unit
local Origin2 = Lines.sub(Origin2_Copy, Lines.clone(Line_1).Direction)*Origin2_DistMag

--Create new lines
local Line1 = Lines.new(Line_1.Origin, Direction1)
local Line2 = Lines.new(Origin2, Direction2)

return Line1, Line2
end

--Find the closest points between two lines
function Lines:FindClosest(Line)
local Line1, Line2 = Lines.relrot(self, Line)

--Get the opposite difference of the line1 and line2 y position
local Line_H = Line1.Origin.Y - Line2.Origin.Y

--Get the difference between the intersection and line2 x position
local Line2_xLen = (Line_H*Line2.Direction.X)/Line2.Direction.Y

--Get the closest point for line1 by getting the relative distance of Line2_xLen to Line1 Origin
local Line1_Closest = Line2_xLen + Line2.Origin.X - Line1.Origin.X

--Get the intersection x and y position distance
local Line2_XyDist = math.sqrt(Line2_xLen^2 + Line_H^2)

--Get the distance between line1 and line2 z position
local Line2_zLen = Line2.Direction.Z*Line_H

--Get the closest point for line2 by pythagoras the xy value and z position intersect
local Line2_Closest = math.sqrt(Line2_XyDist^2 + Line2_zLen^2)

local Line1_Pos = self:GetPosition(Line1_Closest)
local Line2_Pos = Line:GetPosition(Line2_Closest)
local IntersectDist = (Line1_Pos - Line2_Pos).magnitude

return Line1_Closest, Line2_Closest, IntersectDist
end

function Lines:GetPosition(Movement)
return self.Origin + self.Direction*Movement
end
``````
3 Likes