[Closed] Mini-challenge #7: Divide bezier spline
how to divide a spline shape with path/length param?
it’s a frequently asking question
the function's pattern is:
divideSplineShape <splineShape> <spline_index> <param_float> [pathParam:<boolean>]
the [b]length [/b]param is default
well... first come, first win.
[i] "[i]Let's get ready to rumble[/i]!"[/i][b]©[/b]
Would this be useful for what I was asking about in my other thread?
Trying to divide a spline, while keeping its curve? I got a response, but I was wanting to do what he said, take 2 end knots, remove them all inside and insert new ones, while keeping the curve.
i think i may have done something like this before but are we talking about re-creating the entire spline or just one segment ?
don’t wanna spoil the fun, I like curves math, a lot…
but, MAX already allows this, isn’t it…?
and I suppose it uses something like DeCasteljau Algorithm
I see, I tried with refineSegment, but how to convert path to length param, without going through the whole spline measuring… or breaking the spline ?
I guess you’re not talking about simple division (subdivideSegment) but more like normalize_spline mod with evenly spaced verts?
A possible solution is findLengthSegAndParam + refineSegment,
param for refineSegment could be (curveLength/vertCount)/curveLength,
then iterate through vertCount.
it’s the right idea, but could you post a code please…
here a test spline:
sp = splineShape name:"sp" wirecolor:orange
sp.vertexticks = on
addnewSpline sp
addKnot sp 1 #corner #curve [0,0,0]
addKnot sp 1 #corner #curve [100,0,0]
setknottype sp 1 1 #bezierCorner
setoutvec sp 1 1 [0,40,0]
updateShape sp
GOAL: divide the spline on 6 equal by length segments
(6 * 19.7093 = 118.256)
does it sound too simple? try…
what if you add more verts with uneven seglengths to the test spline?
close enough.
fn subDSpline tSpline count=
(
cLength = curveLength tSpline
interp = (cLength/count)/cLength
spline = splineShape name:"sp" wirecolor:green
spline.vertexticks = on
addnewSpline spline
for i = 0 to count do
(
pos = interpCurve3D tSpline 1 (interp*i) pathParam:false
addKnot spline 1 #corner #curve pos
)
updateShape spline
segLengths = getseglengths spline 1
segLengths = for i = (count+1) to (count*2) collect segLengths[i]
format "segLengths: %
" segLengths
)
hm…
cLength = curveLength tSpline
interp = (cLength/count)/cLength
is the same as:
interp = 1./count
isn’t it?
your method can’t guaranty the same newly created knot’s IN and OUT tangents as the original.
well i’m not sure, i was just trying to get it into normalized space. Good to know.
That’s right, i tried findLengthsegAndParam and refineSegment, but it didn’t work very well for uneven segments.
Could possibly use tangentBezier3D to get the outvectors and rebuild the beziers… atleast the vector is correct, how to get the length of the vector is beyond me.
macroscript subdivideSpline
category:"splineTools"
tooltip:"subdivide spline"
(
try(DestroyDialog divideSpline)catch()
rollout divideSpline "divideSpline" width:200 height:32
(
spinner spn1 "" type:#integer pos:[8,8] width:50 height:16 across:4
checkbox linear "linear" checked:false offset:[8,4]
button btnOK "ok" align:#right
button btnCancel "cancel" align:#right offset:[6,0]
local spline, oSpline, oKnots
fn setLinear state=
(
if state==on then
(
for i = 1 to (numknots spline) do
(
setKnotType spline 1 i #corner
updateShape spline
)
)
else
(
for i = 1 to (numknots spline) do
(
setKnotType spline 1 i #bezier
updateShape spline
)
)
)
fn subDSpline tSpline count=
(
spline = copy tSpline wirecolor:green
spline.vertexticks = on
setKnotSelection spline 1 (#{1..(numKnots spline)}as array) keep:true
count -= 1--(numknots spline)
cLength = curveLength spline
param = (cLength/count)/cLength
for i = 0 to count do
(
lparam = (FindLengthSegAndParam spline 1 (param*i))
refineSegment spline 1 lparam[1] lparam[2]
)
setLinear linear.checked
)
on divideSpline open do
(
if ($!=undefined) do
(
max create mode
oSpline = $
spn1.range=[numknots oSpline,1000,0]
-- hide oSpline
)
)
on spn1 buttondown do
(
)
on spn1 buttonup do
(
if (spline!=undefined and not spline.isdeleted and spn1.value>(numknots oSpline)) do
(
knots = getKnotSelection spline 1
j=0
for i = 1 to knots.count do
(
deleteKnot spline 1 (knots[i]-j)
j+=1
)
updateshape spline
)
)
on spn1 changed val do
(
if (oSpline!=undefined) do
(
if (spline!=undefined and not spline.isdeleted) do delete spline
subDSpline oSpline val
)
)
on btnOK pressed do
(
if (spline!=undefined) do
(
spline.vertexticks = off
select spline
spline.wirecolor = gray
delete oSpline
spline = undefined
)
DestroyDialog divideSpline
)
on btnCancel pressed do
(
if (spline!=undefined) do
(
delete spline
spline = undefined
-- unhide oSpline
)
DestroyDialog divideSpline
)
on linear changed state do
(
setLinear state
)
)
if $!=undefined do CreateDialog divideSpline style:#(#style_toolwindow) modal:false
)