michaelk Posted October 2, 2017 Share Posted October 2, 2017 Now I'm truly baffled. But that's not unusual. I'm trying to write a script that mirrors light fixtures around the X axis. I thought it would be easy. I should never think that. Here's the script: PROCEDURE MirrorFixtures; VAR x, y, z : REAL; InstRotation : REAL; PROCEDURE FlipIt(h : HANDLE); VAR hh : HANDLE; BEGIN hh := HDuplicate(h,0,0); GetSymLoc(hh, x, y); InstRotation:= GetSymRot(hh); HRotate(hh,x,y,-InstRotation - InstRotation); HMove(hh,(-x-x),0); DSelectObj(hh); DSelectObj(h); END; BEGIN {Main Program} ForEachObject(FlipIt,((NOTINDLVP & NOTINREFDLVP & (SEL=TRUE) & (PON='Lighting Device')))); END; RUN(MirrorFixtures); Here's what puzzles me: 1. If I insert a fixture and run the script it works! 2. If I delete the new fixture, select the original fixture and run the script again I get 3 fixtures ???!!!???!!??!! 3. If I select multiple fixtures and run the script it goes into an infinite loop, creating thousands of fixtures mirroring back and forth across the X axis. 4. In the HMove and HRotate functions -x-x and -InstRotation - InstRotation worked but (-2 * x) and (-2 * InstRotation) didn't work. Why? Thanks!! mk Mirror Fixtures Test.vwx Quote Link to comment
JBenghiat Posted October 3, 2017 Share Posted October 3, 2017 Your biggest issue is that DSelectObj() takes criteria. SetDSelect() takes a handle. Sub out those calls, and that should prevent your looping issues. There's no reason why -2* shouldn't work, and it does for me. Perhaps something else was wrong with the syntax. HRotate(hh,x,y,-2*InstRotation); HMove(hh,-2*x,0); It should work with or without the parentheses. In general when having a loop that duplicates or deletes, it's safer to load handles of the objects into an array using FEO, then step through the array. Quote Link to comment
michaelk Posted October 3, 2017 Author Share Posted October 3, 2017 Aha! SetDSelect instead of DSelect! Thanks Josh. I didn't notice that the argument was a criteria and not a handle. So far I've managed to avoid arrays. Just because I'm not sure of the syntax. But this seems like a good time to learn. mk Quote Link to comment
JBenghiat Posted October 3, 2017 Share Posted October 3, 2017 For VS, the Language Guide has a fairly good explanation of arrays: http://developer.vectorworks.net/images/7/72/VectorScriptGuide.pdf You can use Count() to get the number of object both for allocating the size of the array and for knowing when to stop looping through the array. If you make the leap to python, arrays (lists in py lingo) are even easier: Define the array insts = [] Add items insts.append(h) iterate through the array for h in insts: newH = vs.HDuplicate( h... Quote Link to comment
michaelk Posted October 3, 2017 Author Share Posted October 3, 2017 Josh Thanks for your help! I've been playing around with Python and I have a few working scripts that I use on a regular basis. But I often build new scripts out of existing scripts so my VS scripts, so I have more VS then Python. This script works. Is there a better way to do this? Should I have use a FEO again to do the flipping? PROCEDURE MirrorFixtures; VAR x, y, z : REAL; InstRotation : REAL; OriginalSystem : DYNARRAY[] OF HANDLE; HowMany,Index,IIndex : LONGINT; hh : HANDLE; PROCEDURE AllocateIt(h : HANDLE); BEGIN OriginalSystem[Index] := h; Index := Index + 1; SetDSelect(h); END; BEGIN {Main Program} HowMany := NumSelectedObjects; ALLOCATE OriginalSystem[1..HowMany]; Index := 1; ForEachObject(AllocateIt,((NOTINDLVP & NOTINREFDLVP & (SEL=TRUE) & (PON='Lighting Device')))); For IIndex := 1 to Howmany DO BEGIN hh := HDuplicate( OriginalSystem[IIndex],0,0); GetSymLoc(hh, x, y); InstRotation:= GetSymRot(hh); HRotate(hh,x,y,-2 * InstRotation); HMove(hh,(-2 * x),0); SetSelect(hh); END; END; RUN(MirrorFixtures); Quote Link to comment
JBenghiat Posted October 3, 2017 Share Posted October 3, 2017 One thing — HowMany is less strict than FEO, so you could get selected objects that aren’t Lighting Devices. Either define HowMany as Count(), using the same criteria as FEO, or iterate with IIndex := 1 to Index, where Index should also equal the number of stored objects. 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.