Notifications
Clear all

[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]
31 Replies

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.

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

hopefully this will be useful for everyone.

i think i may have done something like this before but are we talking about re-creating the entire spline or just one segment ?

2 Replies
(@denist)
Joined: 11 months ago

Posts: 0

we are talking about one segment…

(@denist)
Joined: 11 months ago

Posts: 0

oh… of course i’m talking about the entire spline… it’s too easy for one segment. as Ruramuq pointed it’s just refineSegment.
for entire spline it’s easy too… but many people are asking how to do it. let’s make them happy

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

max doesn’t have a built-in function like this

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.

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

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
)




  
Page 1 / 3