Here is the link for the new spline: https://drive.google.com/open?id=166UMWuDjtOIT90VSx0EmPB5tJRN8PLKG
Accuracy of 0,01 is enough for me.
Here is the link for the new spline: https://drive.google.com/open?id=166UMWuDjtOIT90VSx0EmPB5tJRN8PLKG
Accuracy of 0,01 is enough for me.
OK, I seeā¦
The problem is the float mantissa. Your spline is too long! 
Type in the listener for example 127356.5632: youāll get 127357.0
You should scale your model to get fine results. As it is, you just can get accuracy to the unit (1 ).
Thereās nothing other to do, either working with double values as Point3 has float values.
Edit:
Float numbers: -1S Ć M Ć 2E
| Bit No | Size | Field Name |
|---|---|---|
| 31 | 1 bit | Sign (S) |
| 23-30 | 8 bits | Exponent (E) |
| 0-22 | 23 bits | Mantissa (M) |
You have 23 bits for the mantissa (significant numbers): 2^23=8388608
Thank you.
So the script will check the length of the spline and if it is too long(too many numbers before the decimal point) it will use smaller value of accuracy.
But even with this long spline the script works when the numSubSeg is calculated and not predefined.
No, taking 34sec is not to work. It shouldnāt take more than 0,1sec (in a slow computer for a spline like this one). I wouldnāt trust in the results you get. Scaling it gives the result in 60ms.
But thereās still a problem in some isolated verts that I canāt solve. I think itās a ābugā of interpBezier3D or interpCurve3D, but Iām not sure.
letās bring the test to a unified form of solutionā¦
it has to be a function with at least two parameters - the spline and the fixed distance between points on the spline.
The function has to return all found points in the world space. The function can have any extra optional arguments to make calculation more accurate.
fn scatterPointsOnSpline sp dist tolerance:0.001 =
(
-- ...
points
)
here is my solution:
fn scatterPointsOnSpline sp dist tolerance:0.001 =
(
len = curveLength sp
t = 0.0
d = 0.0
current = interpCurve3D sp 1 t pathParam:off
points = #(current)
while t < 1.0 do
(
t += (dist - d)/len
t = amin t 1.0
p = interpCurve3D sp 1 t pathParam:off
d = distance current p
if d >= dist - tolerance do
(
current = p
append points current
d = 0.0
)
)
points
)
/***************** TEST *****************/
(
delete helpers
t0 = timestamp()
h0 = heapfree
points = scatterPointsOnSpline $ 33.0 tolerance:0.001
format "time:% heap:%" (timestamp() - t0) (h0 - heapfree)
dd = for k=1 to points.count collect
(
point pos:points[k] wirecolor:orange
if k > 1 then distance points[k-1] points[k] else dontcollect
)
format " >> %\n" #(dd.count, amin dd, amax dd)
)
PS. spline index set to 1 (of course we can pass the index to the function)
The āone step closerā solution! 
Really clever. Fast and few memory. As always, you win.
I just see two problems⦠well, two and a half.
Yes, thatās the solution to avoid freezing
fn scatterPointsOnSpline sp dist tolerance:0.001 =
(
tolerance = tolerance as double
len = (curveLength sp) as double
t = 0.0 as double
d = 0.0 as double
current = interpCurve3D sp 1 t pathParam:off
points = #(current)
while t < 1.0 do
(
t += (dist - d)/len
t = amin t 1.0
p = interpCurve3D sp 1 t pathParam:off
d = (distance current p) as double
if d >= dist - tolerance do
(
current = p
append points current
d = 0.0
)
)
points
)
/***************** TEST *****************/
(
delete helpers
t0 = timestamp()
h0 = heapfree
points = scatterPointsOnSpline $ 33 tolerance:0.000001
format "time:% heap:%" (timestamp() - t0) (h0 - heapfree)
dd = for k=1 to points.count collect
(
point pos:points[k] wirecolor:orange
if k > 1 then distance points[k-1] points[k] else dontcollect
)
format " >> %\n" #(dd.count, amin dd, amax dd)
)
Hereās a mixing of the DenisTās āone step closerā and my bisection way.
Seems not to freeze and supports scaled splines:
fn scatterPointsOnSpline sp dist tolerance:0.001 =
(
tolerance = tolerance as double
len = (curveLength sp) as double
sc = sp.scale[1]
x = len / (numSegments sp 1) / dist * 10 / sc;
step0 = (1.0/ (numSegments sp 1) / x) as double
t = 0.0 as double
d = 0.0 as double
current = interpCurve3D sp 1 t pathParam:on
points = #(current)
step = step0 as double
counter = 0
while t < 1.0 do
(
counter += 1
t += step
t = amin t 1.0
p = interpCurve3D sp 1 t pathParam:on
d = (distance current p) as double
error = (dist - d) as double
if abs error <= tolerance then
(
current = p
append points current
step = step0
counter = 0
)
else
(
if error < 0 do
(
t -= step
step *= 0.5 as double
)
if counter > 1000 do
(
current = p
append points current
step = step0
counter = 0
)
)
)
points
)
/***************** TEST *****************/
(
delete helpers
t0 = timestamp()
h0 = heapfree
points = scatterPointsOnSpline $ 33 tolerance:0.000001
format "time:% heap:%" (timestamp() - t0) (h0 - heapfree)
dd = for k=1 to points.count collect
(
point pos:points[k] wirecolor:orange
if k > 1 then distance points[k-1] points[k] else dontcollect
)
format " >> %\n" #(dd.count, amin dd, amax dd)
)
if scale is uniform itās probably enough to make it work as expected
local isUniformScale = sp.scale[1] == sp.scale[2] and sp.scale[2] == sp.scale[3]
local factor = if isUniformScale then abs sp.scale[1] else 1
local len = curveLength sp * factor
and the test
for i=1 to 4 do
(
c = circle radius:20
convertToSplineShape c
c.scale = [0.5 * i, 0.5 * i, 0.5 * i]
gc();t1=timestamp();hf = heapfree
pts = scatterPointsOnSpline c 3.0
for p in pts do point pos:p centermarker:on cross:off wirecolor:yellow
format "count %\n" pts.count
format "Time: %sec. Mem: %\n\n" ((timestamp()-t1)/1000 as float) (hf-heapfree)
)
I canāt test it until tomorrow, but have you tried scaling Kostadinās spline? Functions based on length doesnāt work fine generally when thereās a scale (check result distances).
If I remember well (Iām not in my desktop), take the second example spline and run the script with dist=300 & tolerance=0.01 (or lesser). Or the first example spline with dist=33 & tolerance=0.000001. Other combinations too.
With double precision it seems to work.
this version doesnāt hang for me⦠at least i couldnāt find settings to hang:
fn scatterPointsOnSpline sp dist tolerance:0.001 =
(
dist = dist as double
len = (curveLength sp) as double
tolerance = amax tolerance (len * 0.000001d0)
t = 0.0
d = 0.0
current = interpCurve3D sp 1 t pathParam:off
points = #(current)
while t < 1.0 and not esc_ do
(
t += (dist - d)/len
t = amin t 1.0
p = interpCurve3D sp 1 t pathParam:off
d = distance current p
if d >= dist - tolerance do
(
current = p
append points current
d = 0.0
)
)
points
)
/***************** TEST *****************/
(
delete helpers
c = random red green
t0 = timestamp()
h0 = heapfree
points = scatterPointsOnSpline $ 30.0 tolerance:0.0001
format "time:% heap:%" (timestamp() - t0) (h0 - heapfree)
dd = for k=1 to points.count collect
(
--point pos:points[k] wirecolor:c
if k > 1 then distance points[k-1] points[k] else dontcollect
)
--format " >> %\n" dd
format " >> %\n" #(dd.count, amin dd, amax dd)
)
we have to understand that most of MAX SDK functions are made in Float precision.
so there is no sense to ask tolerance to be smaller than āallowable errorā
because of that iāve added tolerance correction in case of very long splines. which limits tolerance by minimum as 0.000001 of spline length
now couple words about using fixed step in the algorithm.
i wanted to avoid it because there is no absolutely accurate way to define the step. Anyway it might be a situation that making a step we pass a āon distanceā point or might be more than one point inside a step.
in the second case we canāt use bi-search because you can find the second point instead of the first.
as i told many times i always find something interesting and useful in every thread on this forum.
here is very interesting founding⦠the maxscript doesnāt provide current length for scaled splineshapes.
also it gives the right 3d points for scaled splineshapes in methods: interpCurve3D, interpBezier3D, etc.
but only for pathParam
thanks for this founding! Iāve added to my MXS extension several methods and options to take shape node scale into account. Also Iāve added snapshotAsSplineShape method
Denis, thank you for the code. Now I have two working codes with two different solutions.
Merry Christmas to all of you and all the best to you and your families.
Merry Christmas to you and everyone in this forum!
Note: if you donāt expect scaled splines, DenisTās solution is far better than mine.