Here’s the solution with subSegments for splines with very closed segments. I don’t think you’ll need more than 10 subsegments for really extrange splines.
This solution is coded with a struct, so more memory and time than with arrays, but more clear. If you want the array solution, I have it.
I get 2ms for your spline (memory 28680L) with 5 subsegments (they could be just 1 for this case) and an accuracy of 0.0001.
(
gc()
t1 = timeStamp()
m1 = heapfree
-- Catched functions
local interpCurve = interpCurve3D
local interpBezier = interpBezier3D
-- Input Data
curSpline = selection[1]
fixedDist = 33
numSubSeg = 5 -- Caution!!! Minimum 1
accuracy = 0.0001
-- Basic spline data for calculation
numK0 = numknots curSpline 1
closed = isClosed curSpline 1
if closed do numK0 +=1
numK = (numK0 - 1) * numSubSeg + 1
numSeg = numSegments curSpline 1
invNumSeg = 1.0 / numSeg
invNumSubSeg = 1.0 / numSubSeg
relStep = invNumSubSeg * invNumSeg
---------------------------------------
-- Data for each knot
struct Knot (coord, segment, relParam)
local knots = #()
local coord
local segment
local absParam
local relParam
ptsCounter = 0
for i = 1 to numK0 - 1 do
(
ptsCounter += 1
coord = getKnotPoint curSpline 1 i
segment = i - 1
absParam = invNumSeg * (i-1)
relParam = 0.0
knots[ptsCounter] = Knot coord segment relParam
for j = 1 to numSubSeg - 1 do
(
ptsCounter += 1
segment = i
absParam += relStep
relParam += invNumSubSeg
coord = (in coordsys world (interpCurve curSpline 1 absParam pathParam:true))
knots[ptsCounter] = Knot coord segment relParam
)
)
ptsCounter += 1
if closed then
(
coord = getKnotPoint curSpline 1 1
)
else
(
coord = getKnotPoint curSpline 1 numK0
)
knots[ptsCounter] = Knot coord numSeg 1.0
--------------------------------------
-- Calculation
pointsPosArr = #(knots[1].coord)
stopLoop = false
currentKnotIdx = 2
while stopLoop == false do
(
-- Get index of knot farthest than fixedDist from previous one
lastPoint = pointsPosArr[pointsPosArr.count]
morePoints = false
for i = currentKnotIdx to numK while not morePoints do
(
dist = distance lastPoint knots[i].coord
currentKnotIdx = i
if dist >= fixedDist do
(
morePoints = true
)
)
-- Calculation of the point by bisection (max 1000 iterations)
if morePoints then
(
segmentID = knots[currentKnotIdx].segment
pt
error = 1e6
a = knots[currentKnotIdx - 1].relParam
b = knots[currentKnotIdx].relParam
if b == 0.0 do b = 1.0
iterations = 0
while error > accuracy and iterations < 1000 do
(
iterations += 1
param = (a+b) * 0.5
pt = interpBezier curSpline 1 segmentID param pathParam:true
dist = distance lastPoint pt
if dist > fixedDist then b = param else a = param
error = abs(dist - fixedDist)
)
append pointsPosArr pt
)
else
(
stopLoop = true
)
)
t2 = timeStamp()
m2 = heapfree
format "Time: %ms; Mem: %\n" (t2-t1) (m1-m2)
-- Print and Plot results
for p in pointsPosArr do
(
point pos:p wirecolor:yellow
)
for i = 2 to pointsPosArr.count do
(
format "dist[%:%]= %\n" (i-1) i (distance pointsPosArr[i] pointsPosArr[i-1])
)
)
Hope it helps.

