I’m working on a rail placement system, but i have run into a road block and i don’t know what to do here.
When placing rails at the moment, it allows you to make extremely sharp curves, and what i am looking to do is prevent that, but denying placement if the curve is too sharp.

The problem is, i’m unsure exactly how to go about checking the rotation from the start of the rail to the end of the rail. Once i do that, the rail may be, say, 90 degrees, but it must require that the length of the track is say 150 studs.

What i have tried to do, is using the CFrame at the beginning point of the track and the CFrame at the end point of the track, then get the look vectors of them and work out the difference, but that is giving me a Vector3. I just need a value of the turn the track has made in degrees, say, a 37 degree turn.

Do you use inverse trig functions anywhere in your code? You need to keep on mind that due to floating point errors the arguments you pass to inverse trig functions may be slightly out of range (eg: Acos(1.0000165)), so you should be clamping any values you pass to inverse trig functions to the appropriate range explicitly.

That might be the problem. I am using math.acos, and at some times, the number is just a little over or under what it should be. How would i go about fixing that?

Here is the relevant code:

b = Bezier.new(unpack(allPoints))
local lengt = b:GetLength()
if lengt > maxlen then toolong = true else toolong = false end
local curve = allPoints[1]
local fa, ba = b:Get((0+1)/lengt), b:Get((0)/lengt)
local fb, bb = b:Get((1)/lengt), b:Get((lengt-1)/lengt)
local ac, bc = CFrame.new((fa+ba)/2, fa), CFrame.new((fb+bb)/2, fb)
local fac = ac.LookVector
local vec = (bc.Position - ac.Position).unit
local angl = math.acos(fac:Dot(vec))
print(angl)
if angl/lengt > maxlen then
toolong = true
else
toolong = false
end

Thank you, that fixed it up.
Here is my updated code:

b = Bezier.new(unpack(allPoints))
local lengt = b:GetLength()
if lengt > maxlen then toolong = true else toolong = false end
local curve = allPoints[1]
local fa, ba = b:Get((0+1)/lengt), b:Get((0)/lengt)
local fb, bb = b:Get((1)/lengt), b:Get((lengt-1)/lengt)
local ac, bc = CFrame.new((fa+ba)/2, fa), CFrame.new((fb+bb)/2, fb)
local fac = ac.LookVector
local vec = (bc.Position - ac.Position).unit
local angl = math.acos(math.max(-1, math.min(1, fac:Dot(vec))))
print(angl)
if angl/lengt > maxrot then toosharp = true else toosharp = false end

It seems that this code is now giving me just the rotation of the track relative to the word, and not the rotation difference between the two points:

local a, b = allPoints[1], allPoints[#allPoints]
local fac = b.LookVector
local vec = (a.p - b.p).unit
local angl = math.deg(math.acos(math.max(-1, math.min(1, fac:Dot(vec)))))
Any idea what i have done wrong?