# Finding a arbitrary point on a Rope Constraint

Hello again, recently figured a way to find a arbitrary point on a Rope Constraint, as of right now I have not seen anyone accomplish this as there’s no native way of doing so, so I felt the need to challenge myself. I’ve provided a game link to demo it if you’re interested, and a video.

If you’re interested in this sort of tech you can check out the followings below.

https://devforum.roblox.com/t/bypassing-particle-lod-rate-throttle/2446042 - Removes the LOD from Particle Rate property

https://devforum.roblox.com/t/tracking-roblox-particles/2425825 - Can track actual particles from Particle Emitters in-engine.

https://devforum.roblox.com/t/bypassing-forced-beam-lod/2426888/1 - Removes the segment LOD for beams

The Code
Scroll down to where you find EvalPointOnRC function to see usage

``````-- credits to nurokoi
local function IsNan(value)
return type(value) == `number` and value ~= value
end

local function HyperSolver(t, d)
local N = 1e6
local EAppx = (1 + 1/N) ^ N
local PE = EAppx ^ t
local PEIn = 1 / PE
local TCt = PE + PEIn - 2
local TSt = t * (PE - PEIn)

return t * (2 * TCt - TSt) / (TCt - TSt + (t * t) * d)
end

local function UnitizeDist(dist)
local CatA = (dist < 0.1 and ((2.3e-1 * dist + 1.344e-1) * (dist ^ 1.15))
or (dist < 0.9 and ((9.071e-2 + 1.462e-1 * dist - 1.962e-1 * dist * dist) * (dist / (1 - dist)))
or (math.exp(-1.243) * (dist * dist) / math.sqrt(1 - dist * dist))))

local ApproxT, InverseSq = dist / CatA, 1 / (dist * dist)

for _ = 1, 4 do -- 4 guess attempts should be more than enough
ApproxT = HyperSolver(ApproxT, InverseSq)
end

return dist / ApproxT
end

local function EvalCurve(x, l, a)
return a * (math.cosh((x - l) / a) - 1)
end

local function EvalPointOnRC(ropeConstraint : RopeConstraint, alpha : number)
assert(ropeConstraint.Attachment0 and ropeConstraint.Attachment1, `RC Attachments not prepared for {ropeConstraint}`)

local A0 = (ropeConstraint.Attachment0 :: Attachment).WorldCFrame
local A1 = (ropeConstraint.Attachment1 :: Attachment).WorldCFrame
local Length = ropeConstraint.Length

local A0Pos = A0:ToObjectSpace(A0).Position
local A1Pos = A0:ToObjectSpace(A1).Position
local AVec = A1Pos - A0Pos

-- welcome to where i spent a few days working on, enjoy & expect more down the line.
-- would provide the papers i went by and desmos playgrounds to make sense of all this
-- but it's completely idiosyncratic in workflow, evidently...

local D = math.sqrt(AVec.X ^ 2 + AVec.Z ^ 2)
local H = AVec.Y
local S = math.sqrt(Length * Length - H * H)
local CatA  = S * UnitizeDist(D / S)
local XL = CatA * math.log(CatA * (math.exp(D / CatA) - 1) / (H + Length))
local ADs = A0Pos.Y - EvalCurve(0, XL, CatA)
local ADe = A1Pos.Y - EvalCurve(D, XL, CatA)
local X = D * alpha

local Trans = A0Pos + X * Vector3.new(AVec.X, 0, AVec.Z).Unit + Y * Vector3.yAxis
Trans = A0:ToWorldSpace(CFrame.new(Trans))

local IsLinear = IsNan(Trans.X) or IsNan(Trans.Y) or IsNan(Trans.Z)

return (IsLinear and A0:Lerp(A1, alpha) or Trans).Position
end

local function CPointSpacing(ropeConstraint : RopeConstraint, numPoints : number)
local Result = {}
local PreP = EvalPointOnRC(ropeConstraint, 0)
local PreH = PreP.Y

for i = 1, numPoints do
local CTrans = EvalPointOnRC(ropeConstraint, i / numPoints)
local CHeight = CTrans.Y

local HDiff = math.abs(CHeight - PreH)
local PDiff = CTrans - PreP
local LA = HDiff ^ 2 + PDiff.Magnitude ^ 2

PreH = CHeight
PreP = CTrans
table.insert(Result, math.sqrt(LA))
end

return Result
end

local function EvalFixedDistPointsOnRC(ropeConstraint : RopeConstraint, intervalDistance : number, resolution : number?)
assert(ropeConstraint.Attachment0 and ropeConstraint.Attachment1, `RC Attachments not prepared for {ropeConstraint}`)

local A0 = (ropeConstraint.Attachment0 :: Attachment).WorldPosition
local A1 = (ropeConstraint.Attachment1 :: Attachment).WorldPosition

local Result = {}
local PointRes = math.max(resolution or 1e3, ropeConstraint.Length / intervalDistance) -- increased for better precision

local Accu = 0
local LastA = 0

for i, distance in ipairs(CPointSpacing(ropeConstraint, PointRes)) do
Accu += distance

if Accu >= intervalDistance then
local Alpha = i / PointRes
local Trans = EvalPointOnRC(ropeConstraint, (Alpha + LastA) / 2)

if (Trans - A0).Magnitude + (Trans - A1).Magnitude <= ropeConstraint.Length then
table.insert(Result, Trans)
end

Accu = 0
LastA = Alpha
end
end

return Result
end
``````

(Multiple attachments sliding up & down)
Game Link : Ropeconstraint Point Finder - Roblox (Uncopylocked)

33 Likes

New feature added : Equidistant points
What does it do : You can find points that are a equal distant from each other on the catenary rope, returns a list of points

You can find the function being used in the place link that I’ve mentioned or in the code snippet where it’s called `EvalFixedDistPointsOnRC`

Can be used for light fixtures as such that require precise equal distance from one another.

9 Likes

This is really cool, making wires and such in games will be so much easier

Especially as you noted, christmas lights, so many uses