SamIWas Posted December 11, 2004 Share Posted December 11, 2004 Hi all, I have been trying to create a script which will take a selection and insert a range of numbers into a record field based on the number of items in the selection. This is so I can more quickly number units on a lighting pipe from one end to the other. I have gotten the script to work perfectly except for one problem. It always numbers the units in the order in which they were added to the drawing. I want the script to number them from left to right, right to left, bottom to top...whatever. Here is a copy of the script: code: PROCEDURE RenumberLR; VAR h : HANDLE; unitbase : INTEGER; unitnum : DYNARRAY[] of CHAR; BEGIN unitbase:= 1; h:= FSActLayer; WHILE (h <> NIL) DO BEGIN unitnum := Num2Str(0,unitbase); SetRField(h,'LightInfo','Unit',unitnum); h:= NextSObj(h); unitbase:= unitbase+1; END; END; Run(RenumberLR);[/code] Can anyone suggest a script line that may help select the units in a visual order rather than time order? Thanks! [ 12-11-2004, 03:03 PM: Message edited by: SamIWas ] Quote Link to comment
ccroft Posted December 11, 2004 Share Posted December 11, 2004 Isn't there an existing tool in Spotlight to do this?(I don't own a copy) I think I can safely say it will require much more than a line or two of code to do this. You need a sort routine that gets an objects position,compares that to the positions of the other selected objects and numbers accordingly. You'll probably want a dialogue so you can set the start number and select which sort routine to use....left/right,up/down etc. If you can get your hands on a copy of V-works 8, you can look at a PIO that does all this....it's about 500 lines of double spaced code and uses a couple include files to boot. Charles. Quote Link to comment
MullinRJ Posted December 12, 2004 Share Posted December 12, 2004 PastTenseSam, This may not be what you want, but if the stacking order of the lighting units on the layer is not important to you, it is easier to reorder them than to reorder the unit numbers. If you can live with it, here is a quick and dirty Bubble Sort routine that orders the units from Left to Right before you number them. You can modify it for other directional sorting as your needs require. code: PROCEDURE RenumberLR; VAR h : HANDLE; unitbase : INTEGER; procedure SortLtoR; { Change the ordering of objects on the layer based on the object's horizontal position } { using a short, left to right, bubble sort - can take a while if the list is long. } Var swap :BOOLEAN; X1, X2, Y :REAL; Begin swap := True; while swap do begin { repeat until no more swaps occur } swap := False; h:= FSActLayer; while (NextSObj(h)<>nil) do begin hCenter(h, X1, Y); hCenter(NextSObj(h), X2, Y); if (X1>X2) then begin hMoveForward(h, false); { swap object stacking order } swap := True; end; { if } h:= NextSObj(h); end; { while } end; { while } End; { SortLtoR } BEGIN SortLtoR; { order the units from L to R first, then number them } unitbase:= 0; h:= FSActLayer; WHILE (h <> NIL) DO BEGIN unitbase:= unitbase+1; { on loop exit, unitbase = number of units } SetRField(h, 'LightInfo', 'Unit', Num2Str(0, unitbase)); h:= NextSObj(h); END; { while } END; Run(RenumberLR);[/code] HTH, Raymond (aka SamIAint) [ 12-11-2004, 09:16 PM: Message edited by: MullinRJ ] Quote Link to comment
SamIWas Posted December 12, 2004 Author Share Posted December 12, 2004 Raymond, THANK YOU! That was exactly what was needed. The stacking order doesn't matter at all to me, as I don't think I ever have two lights on top of each other. I didn't realize that it was ordering things based on their stacking level, rather than the time in which they were placed into the document (usually the same, but things get moved around). This works perfectly now, and I can easily take the code from here and modify it for right to left, up to down, etc. You have saved me hours per week! Quote Link to comment
ccroft Posted December 12, 2004 Share Posted December 12, 2004 If you don't want to change the stacking order you can use something like: PROCEDURE numberLtoR; VAR Hobj,Hobject:HANDLE; currentX,X,Y:REAL; numobjects,num:INTEGER; FUNCTION objCount:INTEGER; Begin objCount:=0; Hobject:=FSActLayer; WHILE Hobject<>NIL DO Begin objCount:=objCount+1; Hobject:=NextSObj(Hobject); End; End; FUNCTION FindPlace(H:HANDLE):BOOLEAN; Begin HCenter(H,X,Y); IF X>currentX THEN num:= num+1; End; BEGIN Hobj:=FSActLayer; WHILE Hobj<>NIL DO Begin num:=0; HCenter(Hobj,currentX,Y); ForEachObjectInLayer(FindPlace,2,0,0); num:= objCount-num; SetRField(Hobj,'inf','name',Num2Str(0,num)); Hobj:=NextSObj(Hobj); End; END; run(numberLtoR); (you'd have to modify for your variables and record names) Quote Link to comment
MullinRJ Posted December 13, 2004 Share Posted December 13, 2004 quote: The stacking order doesn't matter at all to me, as I don't think I ever have two lights on top of each other.Sam, That is kind of what I was thinking. Glad it worked for you. Charles script looks like it would work if you ever needed to keep the stacking order intact, but I would put the call to "objCount" outside the while loop and reference it with a variable, since the count won't change during program's execution. It's an easier approach than I originally tried before I decided to shuffle the objects instead of the ID's. Happy scripting, Raymond Quote Link to comment
ccroft Posted December 14, 2004 Share Posted December 14, 2004 Hi Ray Good point on the count. When I first read his post I was thinking (possible as you did) about reading the x/y stuff into an array,sorting that,matching objects to the array and writing to record based on position in array....hence my warning-like post. Later that day I saw a different approach and by the time I had a working example you already posted your solution which is cool.I always like it when you can solve a problem by coming up with a simpler strategy. Thanks for posting C. Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.