Jump to content
Sign in to follow this  
Pat Stanford

Replace Selected Objects with Symbol

Recommended Posts

This script will replace every selected object with the active symbol definition. It was designed to replace circles with a symbol located at their center. Check carefully for other objects before depending on it.

Use in Good Health,

Pat

(*********** Copy between Here ************)

Procedure ReplaceWithSymbol;

{Replaces every selected object with the active symbol definition}

{Displays a message if no symbol definition is active.}

{November 17, 2008}

{? 2008, Coviana, Inc - Pat Stanford pat@coviana.com}

{Licensed under the GNU Lesser General Public License}

Var

X1, Y1: Real;

Procedure ReplaceObject(H1:Handle);

Begin

Get2DPt(H1,1,X1,Y1);

Symbol(GetSDName(ActSymDef),X1,Y1,0);

SetDSelect(LNewObj);

DelObject(H1);

End;

Begin

If ActSymDef<>Nil then ForEachObject(ReplaceObject,SEL=True)

Else Message('No Symbol Definition Selected.');

End;

Run(ReplaceWithSymbol);

(********** And Here ***********)

Edited by Pat Stanford

Share this post


Link to post

Dear Pat

Could this script be amended to replace any object with a symbol but with the center of the selected object(s) as the insertion point of the symbol?

Regards

Steven Shorter

Share this post


Link to post

It probably could be modified to do that, but might it not be easier to modify the symbols so that their insertion point is at the center of the symbol?

What exactly are you trying to do and why?

Share this post


Link to post

Pat,

This is great. I will use it often. Is it possible to have the inserted symbol be selected after replacement?

Thanks again for sharing your knowledge.

Heath

Share this post


Link to post

You can't leave them selected based on the way it is currently written. It replaces the selected objects one at a time and then deselects each as it is done. If you were to select the new objects, the script would just continue to churn forever.

It could easily be modified to go back and select every instance of the given symbol, but there is no easy way to select just the ones that have be replaced. This one does just that.

Procedure ReplaceWithSymbol;

{Replaces every selected object with the active symbol definition}

{Displays a message if no symbol definition is active.}

{November 17, 2008}

{? 2008, Coviana, Inc - Pat Stanford pat@coviana.com}

{Licensed under the GNU Lesser General Public License}

{February 26, 2009}

{modified to select all symbols of the type used in the replace}

Var

X1, Y1: Real;

S1 : String;

Procedure ReplaceObject(H1:Handle);

Begin

Get2DPt(H1,1,X1,Y1);

Symbol(GetSDName(ActSymDef),X1,Y1,0);

SetDSelect(LNewObj);

DelObject(H1);

End;

Begin

If ActSymDef<>Nil then

begin

ForEachObject(ReplaceObject,SEL=True);

S1:=concat('S=',CHR(39),GetSDName(ActSymDef),CHR(39));

SelectObj(S1)

end

Else Message('No Symbol Definition Selected.');

End;

Run(ReplaceWithSymbol);

Share this post


Link to post

It could easily be modified to go back and select every instance of the given symbol, but there is no easy way to select just the ones that have be replaced. This one does just that.

Depends on the definition of easy. One could read the locations into an array while deleting the selected items, then place the symbols to these stored locations.

Share this post


Link to post

Of course it's an adjective, but I didn't know that it is measurable in time.

In an easy-chair, is one supposed to sit only less than 10 minutes?

Share this post


Link to post

So, how long is easy-as-pie? My guess is 2+ hours.

OK, this appeared easier that it was, but with a little bit of effort, you can have your cake ? I mean pie ? and eat it, too.

I think Petri's suggestion of using an array would have been easier, but we hates arrayssss.

Raymond

Procedure ReplaceWithSymbol;

{Replaces every selected object with the active symbol definition}

{Displays a message if no symbol definition is active.}

{November 17, 2008}

{? 2008, Coviana, Inc - Pat Stanford pat@coviana.com}

{Licensed under the GNU Lesser General Public License}

{February 26, 2009}

{modified to select all symbols of the type used in the replace}

{February 27, 2009 - RJM}

{Move new symbols to back, so they stay selected.}

{Uses HCenter to place symbol at center of selected object.}

{Optionally, move symbols to front, so they keep relative stacking order.}

Const

???SQ = chr(39);??????{ Single Quote }

Var

???H, Hfo : Handle;

???X1, Y1 : Real;

???S1 : String;

???Procedure ReplaceObject(H1:Handle);

???Begin

??????HCenter(H1, X1, Y1);

??????Symbol(S1, X1, Y1, 0);

??????HMoveBackward(LNewObj, True);????????????{ move to back instead of deselect }

??????DelObject(H1);

???End;??????{ ReplaceObject }

Begin

???if (ActSymDef <> nil) then begin

??????Hfo := FActLayer;??????????????????????????????{ handle to first object on layer }

??????if Selected(Hfo) then Hfo := nil;

??????S1 := GetSDName(ActSymDef);

??????ForEachObject(ReplaceObject, SEL);

??????{ omit the following if stacking order is not important, }

??????{ otherwise this moves all new symbols to the front. }

??????if (FSActLayer <> nil) then begin????????????{ there were selected objects converted }

?????????if (Hfo = nil) then Hfo := NextDObj(FActLayer);???{ first deselected obj }

?????????if (Hfo = nil) then Hfo := LActLayer;??????{ top selected symbol }

?????????H := PrevObj(Hfo);

?????????while (H <> nil) do begin

????????????HMoveForward(H, True);

????????????H := PrevObj(Hfo);

?????????end;??????{ while }

??????end;??????{ if (FSActLayer <> nil) }

???end

???else Message('No Symbol Definition Selected.');

End;

Run(ReplaceWithSymbol);

Share this post


Link to post

Well, here's another take on the subject. I've totally forgotten the circumstances, but obviously the 3D & rotation aspects are there for a reason.

PROCEDURE Sel2Syms; { ? Petri Sakkinen 1998-2009 }

{ This macro replaces selected objects on the active layer with instances of the active symbol }

VAR

i, n, objType : INTEGER;

x, y, z, a : REAL;

xi, yi, zi, ai: ARRAY[1..1000] OF REAL;

theSymbol : STRING;

obHd, sdHd : HANDLE;

BEGIN

theSymbol := GETSDNAME(ACTSYMDEF);

IF (theSymbol > '') THEN BEGIN

obHd := FSACTLAYER;

WHILE obHd <> NIL DO BEGIN

i := i+1;

x := 0; y := 0; a := 0; z := 0;

objType := GETTYPE(obHd);

CASE objType OF

9 : GETLOCUS3D(obHd, x, y, z); { found a 3D locus }

15 : BEGIN { found a symbol }

GETSYMLOC3D(obHd, x, y, z);

a := GETSYMROT(obHd);

END;

17 : GETLOCPT(obHd, x, y); { found a 2D locus }

OTHERWISE HCENTER(obHd, x, y); { found something else}

END; { case }

xi := x; yi := y; zi := z; ai := a;

obHd := NEXTSOBJ(obHd);

END;

IF YNDIALOG('Delete selected objects?') THEN DELETEOBJS;

FOR n := 1 TO i DO BEGIN

SYMBOL(theSymbol, xi[n], yi[n], ai[n]);

IF (zi[n] <> 0) THEN MOVE3DOBJ(LNEWOBJ, 0, 0, zi[n]);

END;

END

ELSE ALRTDIALOG('You must have an active symbol');

END;

RUN(Sel2Syms);

Share this post


Link to post

This is an interesting thread. I always enjoy seeing how different minds come up with different means to the same end.

Myself, I've had selection status get in my way a few times before. What's served me well is to build an array of the selected object's handles, and then make the procedures handle based instead of selection based.

So here's yet another take on it:

PROCEDURE replace_it;

???VAR

??????objX,objY,symX,symY:REAL;

??????index:INTEGER;

??????handleBin:ARRAY[1..1000] of HANDLE;

FUNCTION loadBin(h:HANDLE): BOOLEAN;

???Begin

??????index:=index+1;

??????handleBin[index]:=h;

???End;

PROCEDURE change_it(objectHand:HANDLE);

???Begin

??????HCenter(objectHand, objX, objY);

??????Symbol(GetSDName(ActSymDef), objX, objY, 0);

??????HCenter(LNewObj, symX, symY);

??????HMove(LNewObj, objX-symX, objY-symY); ???

??????DelObject(objectHand);

???End;??????

BEGIN

???IF (ActSymDef <> nil) THEN

??????Begin

?????????index:=0;

?????????ForEachObjectInLayer(loadBin,2,0,2);

?????????index:=1;

??????WHILE handleBin[index]<>NIL

?????????Begin

?????????change_it(handleBin[index]);

?????????index:=index+1;

?????????End;

??????End

???Else AlrtDialog('Make a Symbol Active, DUMB-ASS!');

END;

RUN(replace_it);

If anyone wants to actually use this script, you might want to edit the alert message depending on the work environment. This is my standard alert, cause the only time I get it is when I'm pushing hard on a deadline and it usually lightens my mood a bit.

As per an early request, I added a couple lines to move the symbol center to the old objects center. Works great in my drawing environment, but I'm quessing there might be situations where it fails. Seems too simple to be correct.

I'd like to thank everyone who asked or answered in this thread. Contrary to what I thought when I first read it, the end result is actually gonna be very useful to me.

(I wish you could cut and paste a script in here without messing up the formatting)

Share this post


Link to post
(I wish you could cut and paste a script in here without messing up the formatting)

Hi Charles,

???You can, if you indent your source code with tabs. First, replace all tabs with three option-space (NBS = non-breaking space) characters, select all and copy, then undo (to restore your tabs). You can then paste on the tech-board and your indents remain. If you indent with spaces, it will be a bit trickier. (It appears you indented some of your code this way, just not all of it. I used NBS characters in my pasted code above and in my paragraph indents here.)

???The only issue I have with using arrays, especially static arrays, is that the code is not general enough. It will fail at the 1001'st object (citing yours and Petri's examples.) This is easy to adjust for us programmer types, but there are a lot of people who cringe at thought of modifying a script.

???The use of dynamic arrays can get around the static array limit, but you have to count everything first then declare your array size, and even then you are limited to 32K elements, which should be enough for most everything, but it's still not bullet proof.

???The method I used does not have a well defined upper limit, but speed may be the limiting factor for it. Remove the italicized lines and it will run faster, but then the replaced objects will be on the bottom of the stacking order instead of on the top. This may or may not be an issue. Tagging everything with a record for reselection is another way to tackle this problem, but it's also cumbersome to write and debug.

???The best part of this thread is there are four examples (actually five with Pat's two posts) of the same idea that a beginning scripter can compare. Happy scripting, y'all.

Raymond

Share this post


Link to post

???You can, if you indent your source code with tabs. First, replace all tabs with three option-space (NBS = non-breaking space) characters,

Nice! Have to try...

The use of dynamic arrays can get around the static array limit, but you have to count everything first then declare your array size, and even then you are limited to 32K elements, which should be enough for most everything, but it's still not bullet proof.

Duly noted, but I think we can quite safely assume that few scripts need to handle more than 32K elements.

Counting is not that bad. In my example this would have been the better approach:

VAR

i, n, objType : INTEGER;

x, y, z, a : REAL;

xi, yi, zi, ai: DYNARRAY[] OF REAL;

theSymbol, lName : STRING;

obHd, sdHd : HANDLE;

????

BEGIN

????????????theSymbol := GETSDNAME(ACTSYMDEF);

????????????IF (theSymbol > '') THEN BEGIN

???????????? lName := GETLNAME(ACTLAYER);

???????????? n := COUNT(SEL & (L=lName));

???????????? ALLOCATE xi[1..n];

??????????? ?ALLOCATE yi[1..n];

???????????? ALLOCATE zi[1..n];

??????????? ?ALLOCATE ai[1..n];

???????????? obHd := FSACTLAYER;

etc.

Share this post


Link to post

???The only issue I have with using arrays, especially static arrays, is that the code is not general enough. It will fail at the 1001'st object (citing yours and Petri's examples.) This is easy to adjust for us programmer types, but there are a lot of people who cringe at thought of modifying a script.

Hello Ray,

Very true, but that's the beauty of the programmer and end-user being the same person! I've always just created an array sufficiently over-size for my own purposes. In fact I'll never use it on more than 100 objects, so I just forgo the dynamic. I guess I'm not a good vScript citizen...

It's very good that you pointed this out for the benefit of others.

I thought your approach was most interesting. I never would have thought of doing this by manipulating the stacking order, and it took me quite a while to see how this works. Somehow arrays just make a lot of sense to me. (My mind must resemble an old time post-office sort station or something....lots of little boxes in a grid.)

And thanks for the formatting tip. I think you mentioned that before, but I couldn't remember the correct key stroke. BTW, you can also go back and edit using option/space to get indents as I did. (hope I didn't accidently erase a semi-colon or something)

So to sum it all up, we have three ways to get around the infinite loop of selection. One is stacking order based, one is position based, and one is handle based.

Carry on!

Share this post


Link to post

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

 

7150 Riverwood Drive, Columbia, Maryland 21046, USA   |   Contact Us:   410-290-5114

 

© 2018 Vectorworks, Inc. All Rights Reserved. Vectorworks, Inc. is part of the Nemetschek Group.

×
×
  • Create New...