Notifications
Clear all

[Closed] Script for sorting out splines

Hi guys

Here’s a script that I wrote for fixing splines imported from autocad getting rid of most of the problems

It works fine for single objects, but bombs on selection sets for some reason…where is the updateShape function supposed to go exactly?

Any ideas?

SCRIPT:

–define arrays
spl = #()
lin = #()
rec = #()
cir = #()
ell = #()
–assign objects from the initial selection to the relevant array
for i in selection do
(
i.wirecolor = (random black white)
case classOf i of
(
SplineShape: append spl i
Line: append lin i
Rectangle: append rec i
Circle: append cir i
Ellipse: append ell i
)
)

max select none
–sort the splines out
for s in spl do
(
addModifier s (Edit_Spline())
maxOps.CollapseNode s off
updateShape s
subobjectLevel = 1
max select all
updateShape s
splineOps.weld $
subobjectLevel = 0
updateShape s
print s.name
)

–sort the lines out
for L in lin do
(
addModifier L (Edit_Spline())
maxOps.CollapseNode L off
updateShape L
subobjectLevel = 1
max select all
updateShape L
splineOps.weld $
subobjectLevel = 0
updateShape L
print L.name
)

–sort the rectangles out
for r in rec do
(
addModifier r (Edit_Spline())
maxOps.CollapseNode r off
updateShape r
setKnotType r 1 1 #corner
setKnotType r 1 2 #corner
setKnotType r 1 3 #corner
setKnotType r 1 4 #corner
updateShape r
print r.name
)

–sort the circles out
for c in cir do
(
addModifier c (Edit_Spline())
maxOps.CollapseNode c off
updateShape c
c.steps = stps
updateShape c
print c.name
)

–sort the ellipses out
for e in ell do
(
addModifier e (Edit_Spline())
maxOps.CollapseNode e off
updateShape e
e.steps = stps
updateShape e
print e.name
)

24 Replies

Hey there, Alex!

Thanks for posting your script, it’s good that things are getting going here in the new forum. I have some ideas about how you could optimize this, and fix it so that it works more reliably across a selection of objects. These days, I don’t have Max available to test stuff on during the daytime, so bear with me if some of the names and syntax in my sample code aren’t 100% correct:)

For starters, I don’t think it is necessary to construct separate arrays for each class of object. Pop open Max and create one of each class of object you’re after: a line, a rectangle, a circle, an ellipse, and a line collapsed into a splineShape. Select each one (individually) and evaluate superClassOf $ in the listener. If the result is the same for all of them (as I suspect it should be), then you can use this as criteria for collecting the objects you want to work with. Say you’ve found that the superclass is “Shape.” Now you can do this in your script:

splines = for obj in selection where superclassOf obj == Shape collect obj

This is called a for…collect loop, and it works much like a for…do loop except that it – get ready now – collects objects! The where clause lets you define criteria for what will be collected, and the result of the collection can be assigned to a variable as I’ve done here with splines. Now you can loop through splines and do all the other stuff you want to do. The commands you were previously doing once for each object class can instead be done once, period, and you can still use a conditional to do the class-specific stuff:

max select none
for s in splines do
(
original_class = classOf s
addModifier s (Edit_Spline())
maxOps.CollapseNode s off
case original_class of
(
splineShape: ( <do splineshape stuff here> )
Line: ( <do line stuff here> )
etc…


)
updateShape s
print s.name
)

Assuming all this works, you’ve now condensed umpteen lines of code into just a few, and made it easier to read and maintain as well. Not a bad deal, eh?

In answer to your updateShape question, you’ll typically want to call it after altering the subobjects of a spline. A good rule of thumb would be to use it after doing anything with splineOps. Note that you can do a bunch of splineOps stuff all together, and then call updateShape just once when you’re done.

RH

Thanks RH, thats really useful!
I’ll test it out over the next couple of days and repost the script.

I’m really glad that this section of the forum has started. I’ve been using Max since the beginning but have only really got my head around scripting over the last couple of months. Its really useful! But the max documentation leaves a lot to be desired if you dont have a programming background.

OK here it is rewritten

there seems to be a problem with collapse_nweld function which I can’t get to the bottom of: Here’s the listener return on a selection of one of each object:

#($Rectangle:Rectangle01 @ [133.493973,126.506027,0.000000], $Circle:Circle01 @ [36.867470,63.132530,0.000000], $Ellipse:Ellipse01 @ [112.771088,89.156624,0.000000], $Arc:Arc01 @ [-35.055008,49.649311,0.000000], $Line:Line02 @ [136.626511,43.132530,0.000000], $Editable_Spline:Line01 @ [-50.887184,99.189476,0.000000])
2
collapse_nweld()
fixrect()
fixcurve()
OK
“Rectangle01”
“Circle01”
“Ellipse01”
– Error occurred in fixcurve()
– Frame:
– s: undefined
– called in s loop
– Frame:
– ss: undefined
– s: $Editable_Spline:Arc01 @ [-35.055008,49.649311,0.000000]
– original_class: Arc
– No ““addModifier”” function for undefined
OK

I’ve tried running each line manually and it works fine

any ideas?

The listener output points to a typo where you referred to “ss” instead of “s” in the case handler for Arc. There is a problem with collapse_nweld(), though – you called splineOps.weld $ where you should have called splineOps.weld s.

Note: Adding the edit spline modifier and collapsing have already been handled by the main loop, so you can speed up your script a bit by leaving these steps out of the three functions. As it is, they’re just redundant.

Fix the above, and your script should run smoothly:thumbsup:

RH

Thanks again RH, just a quick question before I start coding again…

Can you just clarify why s instead of $?
s refers to the whole object, whereas $ refers to the vertices selected by select all.

$ never refers to a subobject selection – it always refers to the object selection. In your case it will always break if you have more than one object selected, or if the selected object is not an editable spline. Anyway, splineOps.weld() isn’t supposed to take a selection of knots as its argument; it takes the editable spline object and then just welds whatever subobjects are selected. Hope that makes sense.

RH

Ahh! Thanks RH.
That fixes a few other things I was having problems with.
Unfortunately it still stalls…

OK so now I get this in the listener:

#($Editable_Spline:Line01 @ [-50.887184,99.189476,0.000000], $Rectangle:Rectangle01 @ [133.493973,126.506027,0.000000], $Circle:Circle01 @ [36.867470,63.132530,0.000000], $Ellipse:Ellipse01 @ [112.771088,89.156624,0.000000], $Arc:Arc01 @ [-35.055008,49.649311,0.000000], $Line:Line02 @ [136.626511,43.132530,0.000000])
2
collapse_nweld()
fixrect()
fixcurve()
OK
– Error occurred in collapse_nweld()
– Frame:
– s: $Editable_Spline:Line01 @ [-50.887184,99.189476,0.000000]
– called in s loop
– Frame:
– s: $Editable_Spline:Line01 @ [-50.887184,99.189476,0.000000]
– original_class: SplineShape
– Runtime error: Requested sub-object level out of range: 1
OK

Again I checked it manually and it seems fine…incidentally I’m running Max 5.1

I overlooked this myself, but it’s quite simple! Since nothing is selected as execution enters collapse_nweld(), there’s no subobject level for it to enter into!

I’m thinking that there’s probably a better way to write this function, anyway, which will avoid the overhead of selecting objects and entering subobject level. Look in the docs, under splineOps, for a function that sets the knot selection. If my guess is correct, it will be something smart like splineOps.setKnotSelection(). If there is such a function, you can use it to select all the knots without even having to select the spline object! I wish I could be more specific, but again I don’t have Max here at work:(

If you don’t want to go that route, just make sure you select s in collapse_nweld() before setting subobjectlevel. Another thing I just remembered is that for subobjectlevel you need to be in modify mode, and your script doesn’t check for this. Before the main loop begins, you’ll probably want to call max modify mode. One more tip: wrap the main loop in calls to disableSceneRedraw()/enableSceneRedraw(). This cuts down on viewport redraws, which will both speed up your script and make it look cleaner when run. So,

max modify mode
disableSceneRedraw()
sel = getCurrentSelection()
max select none
for s in splines do
(

)
select sel
enableSceneRedraw()

The sel = getCurrentSelection()/select sel stuff is cosmetic; I generally consider it a good idea to leave things as much as possible in the state they were in when the user runs a script.

If you still haven’t got this stuff sorted out by tonight, I can probably be more helpful when I can at least open up the help docs. Until then, good luck – you’re on the right track so far:thumbsup:

RH

OK I’ve gone down the select s route and attached the script which now seems to work although I need to test it a bit more yet.

Below is a loop for selecting all the vertices in a spline, but I cant seem to find a way of welding the selected vertices without getting into modify mode:

–for shape called s
–store the number of splines in the shape
sp_n = s.numSplines
–create an array to store the knot index values
sp_v = #()
–loop through all the splines in the shape to create a spline index array and a knot index array
–sii is the spline index integer
for sii in 1 to sp_n do
(
–vn is the number of knots in each spline
spv_n = numKnots s sii
–loop through all the vertices in each spline to add them to a temp index array
for k in 1 to spv_n do
(
append sp_v k
)
–add the vertices for spline k to the selection
setKnotSelection s sii sp_v keep:true
–reset the index array for the next spline loop
sp_v = #()
–at this point all the vertices in the shape should be selected
)

Any ideas?

Page 1 / 3