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