I have made a module script that can create a triangle when given three positions by using two right triangles (wedge parts). However, I have only managed to get the correct size and positions so far, and do not know how to rotate the triangles to match the points. Here is the desired result, achieved by manually rotating the triangles myself:
And here is what is currently outputted:
This is the module script I have made, named ‘Triangle’. As a side note, I know that the script does not check if the points form a right triangle already. I can fix that later.
-- In the command bar
local triangulate = require(game.ServerScriptService.Triangle)
triangulate( workspace.A.Position, workspace.B.Position, workspace.C.Position )
-- In a module script
local function cosineRule( a:number, b:number, c:number )
--// Given lengths a, b, and c, return the Theta of angle BAC/CAB
--// https://www.onlinemathlearning.com/image-files/law-of-cosines.png
--// NOTE: b & c can be swapped without altering the algorithm
--// cosA = ( -a^2 + b^2 + c^2 ) / 2bc
--// A = arccos[ (-a^2 + b^2 + c^2 ) / 2bc ]
return math.acos( (-a^2 + b^2 + c^2) / (2*b*c) )
end
local function triangulateThreePoints( A:Vector3, B:Vector3, C:Vector3 )
local vecAB = B - A
local vecAC = C - A
local vecBC = C - B
local lineAB = (B - A).Magnitude
local lineAC = (C - A).Magnitude
local lineBC = (C - B).Magnitude
--// Organize the lines from longest to shortest
local longestLine = math.max( lineAB, lineAC, lineBC )
--// Always make it so LineBC is the longest line. This will remove the
--// reduntant code that would have been made to account for each side.
if longestLine ~= lineBC then
local temp = lineBC
lineBC = longestLine
if longestLine == lineAB then
lineAB = temp --// Point A <--> Point C
print 'a <--> c'
elseif longestLine == lineAC then
lineAC = temp --// Point A <--> Point B
print 'a <--> b'
end
longestLine = math.max( lineAB, lineAC, lineBC )
end
--// LineH divides the triangle into two right triangles.
--// It is perpendicular to the longest line and goes towards
--// the point that does not form the longest time.
--// (Perpendicular to LineBC means it will go towards Point A.)
--// Due to my swapping earlier, LineH (now denoted as LineAH) will
--// always perpedicularly intersect LineBC and goes toward point A.
--// Get angle ABC to calc length of LineAH
--// sinT = opp / hyp
--// T[heta] is found via consineRule
--// opp = sinT * hyp
local T = cosineRule( lineAC, lineAB, lineBC )
local lineAH = math.sin( T ) * lineAB
--// Create the first right triangle
--// I got LineAB, LineAH, I still need LineBH
local lineBH = math.cos( T ) * lineAB
local triangleABH = Instance.new("WedgePart")
triangleABH.Size = Vector3.new( 0.1, lineAH, lineBH )
triangleABH.Position = A:Lerp( B, 0.5 )
--// triangleABH.CFrame = triangleABH.CFrame * CFrame.Angles( ??? )
triangleABH.BrickColor = BrickColor.new("Deep orange")
triangleABH.Parent = workspace
--// Second right triangle
T = cosineRule( lineAB, lineAC, lineBC )
local lineCH = math.cos( T ) * lineAC
local triangleACH = Instance.new("WedgePart")
triangleACH.Size = Vector3.new( 0.1, lineAH, lineCH )
triangleACH.Position = A:Lerp( C, 0.5 )
--// triangleACH.CFrame = triangleACH.CFrame * CFrame.Angles( ??? )
triangleACH.BrickColor = BrickColor.new("Cyan")
triangleACH.Parent = workspace
print({
["lineAB"] = lineAB
,["lineAC"] = lineAC
,["lineBC"] = lineBC
,["AngABC"] = math.deg(cosineRule( lineAC, lineBC, lineAB ))
,["AngACB"] = math.deg(cosineRule( lineAB, lineBC, lineAC ))
,["AngBAC"] = math.deg(cosineRule( lineBC, lineAC, lineAB ))
,["LongestLine"] = longestLine
,["LineAH"] = lineAH
})
end
return triangulateThreePoints