Jump to content
Developer Wiki and Function Reference Links ×

Set LineWeight Logic


Recommended Posts

Hello,

 

I am modifying  Set LineWeight script we had in forum by adding an alert dialog, so it shows which part of code has been executed. However, I get multiply alerts even I thought the script ends. 

 

The script checked Lineweight, if lw is 10 mil then it set color, if lw is not 10mil, it will be set to 10 and assigned color. Then the code should end. I am not sure why I get multiple alerts.

 

Here is the code :

 

PROCEDURE LineWeightChange;
{ (c) twk based off of original code by Petri Sakkinen 2008 } 

CONST     newWeight = 10; 

PROCEDURE ChangeIt (h : HANDLE);     
VAR         oldLW : INTEGER;     


BEGIN          
  
If (oldLW <> 10) THEN          
	Begin
		oldLW := GetLW(h);  
		SetLW(h, newWeight); 
		SetPenFore(h, 0,11796,52428);
		AlrtDialog ('Grid set to blue with LW 0.25');
	End;
	
IF (oldLW = 10) THEN          
	Begin
		SetPenFore(h, 0,11796,52428);
		AlrtDialog ('Grid set to blue');
	End;
END; 

BEGIN     
DSelectAll; SelectObj((INSYMBOL & INVIEWPORT & (L='Grid')));   
FOREACHOBJECT(ChangeIt, ((SEL=TRUE))); 
END; 

RUN(LineWeightChange);

Thank you 

Edited by marioqi
Link to comment

SEL=TRUE returns every selected object in the drawing. Even those buried deep in groups, symbols and PIOs.

 

Try VSEL=TRUE to get the visible selected objects.

 

[Please blame any typos on the three glasses of champage I just had to try and celebrate my daughters's college graduation under these strange circumstances we are living in.]

 

Link to comment
If (oldLW <> 10) THEN          
	Begin
		oldLW := GetLW(h);  
		SetLW(h, newWeight); 
		SetPenFore(h, 0,11796,52428);
		AlrtDialog ('Grid set to blue with LW 0.25');
	End   {Make sure there is no semicolon to end this line before the else
	
Else

	Begin
		SetPenFore(h, 0,11796,52428);
		AlrtDialog ('Grid set to blue');
	End;  {Make sure this line does end with a semicolon}

You probably also want to move the line to set OldLW outside of the If Statement. 

Link to comment

A few things:

 

You don’t need to select objects — just pass your criteria to ForEachObject. 
 

I’m not sure what you mean about avoiding a loop. What you are saying is to process every object on the Grid layer, including objects in symbols and viewports. You will get an alert for each object. If you are trying to create an analog between selecting objects and changing an attribute, behind the scenes VW is actually iterating over each selected object, not performing a single action. 
 

You don’t actually retrieve the value of oldLW after you test for it. Having uninitialized numeric variables is bad practice, though likely vs will initialize it to 0 for you. That means that your first statement will always evaluate to true. Because your original code has a second if statement, it will still produce the expected results (though with two alerts), but will be less efficient, as you set the LW to 10 anyway, and unnecessary set the color. With Pat’s Else fix, the second evaluation will never be true. Move the GetLW statement to before your first if. 

Link to comment

Thank you Josh and Pat. 

 

I am still learning vs and Pscal structure, your responses help a lot. 

 

I didn't realized ForEachObject is iterating over each object and that casued the problem. Regarding selection in ForEachObject, it seems will not work if criteria is missing. It would be helpful if there is a referencing list of arguments we could pass in as a criteria. 

 

Taking all suggestions, I cleaned up the script and reconstructed it in python.  However, I am still not sure what is HANDLE doing in vs. Even the script does its thing, but I believe there is error on ForEachObjectInList.  Following is current script:

import vs

#class name needs to be assigned to
myClass = "none"  

vs.DSelectAll 
vs.SelectObj("INSYMBOL & INVIEWPORT & (L='Grid')")


# Assign color and lineweight to specified objects
def ChangeLw(h):  
	color = vs.RGBToColorIndex(0,11796,52428)
	vs.SetLW(h, 10); 
	vs.SetPenFore(h,color);

# Assign selected object to myClass
def AssignClass(h): 
	vs.SetClassN(h, myClass , True);

vs.ForEachObject(ChangeLw,"SEL=TRUE") 

# Create dummy item
vs.Locus(0,0)   
Dummy = vs.LNewObj  
#Assign each selected objects to myClass
vs.ForEachObjectInList(AssignClass, 2, 2, vs.FInGroup(vs.GetParent(Dummy)));
#Delete Dummy item
vs.DelObject(Dummy); 

Thank you

Edited by marioqi
Link to comment

Hi Mario,

 

ForEach Object and ForEachObject in List are similar procedures. They each call a function or procedure one time for each object that is defined by them. It passes the Handle (pointer) to each object as the identifier so the called procedure or function knows what to operate on.

 

ForEachObject uses Criteria to define the objects that will be passed to the procedure.

ForEachObjectInList takes a handle to the first object in the list and then iterates through every object in the list.

 

You can use the Criteria Builder in the Vectorscript Editor or in a Worksheet to help generate your criteria. You might need to surround your criteria with double Parentheses. ((  ))

 

I can't tell is you are mixing single and double quotes or just using double single quotes, and I don't know if Python cares, but Vectorscript only uses single quotes.

 

Change LW and AssignClass need to be subroutines that are called by ForEachObject and ForEachObjectInList.

  • Like 2
Link to comment

Python doesn't care whether you use double or single quotes to identify a string. VW *may* require single quotes in the criteria string, however.

 

Criteria strings are the same as the one you used to select objects. You can skip the DeSelect / Select steps (unless you want everything selected in the end) and just use:

vs.ForEachObject(ChangeLw,"(INSYMBOL & INVIEWPORT & (L='Grid'))") 

You can also avoid using the dummy locus. Assuming you want to act on all the objects in the current layer, pass vs.FActLayer() as the object. Alternatively, there is a ForEachObjectInLayer() command. If you want your script to work within a group or a symbol, then you do need the dummy object.

 

A handle is technically a pointer to the memory block that identifies each object. You can think of a handle as a UUID, however the value of the handle isn't guaranteed to be the same between sessions or even script runs, so you would never want to store or manually set the handle value.

  • Like 2
Link to comment

Thank you both for those details. 

 

After reading Pat's reply about criteria, I am with Josh to eliminate select object, which seems redundant. 

 

I ended up using ForEachObjectInLayer(), and  it works great.  

 

Python noramlly doesn't care about double quotes or single with fewer exceptions. 

 

Really appricate all the supports.

 

--Jiajing 

Link to comment
  • 2 weeks later...
On 5/18/2020 at 2:14 PM, Jiajing said:

 


import vs

#class name needs to be assigned to
myClass = "none"  

vs.DSelectAll 
vs.SelectObj("INSYMBOL & INVIEWPORT & (L='Grid')")


# Assign color and lineweight to specified objects
def ChangeLw(h):  
	color = vs.RGBToColorIndex(0,11796,52428)
	vs.SetLW(h, 10); 
	vs.SetPenFore(h,color);

# Assign selected object to myClass
def AssignClass(h): 
	vs.SetClassN(h, myClass , True);

vs.ForEachObject(ChangeLw,"SEL=TRUE") 

# Create dummy item
vs.Locus(0,0)   
Dummy = vs.LNewObj  
#Assign each selected objects to myClass
vs.ForEachObjectInList(AssignClass, 2, 2, vs.FInGroup(vs.GetParent(Dummy)));
#Delete Dummy item
vs.DelObject(Dummy); 

 

I am looking back this Locus method, I made it work in VS but for some reason it gives me error in python. I couldn't figure it out what I am off. Any insight or hint would be appreciated.

 

Edited by Jiajing
Link to comment
5 minutes ago, MullinRJ said:

@Jiajing 

   In Python you have to put "()" after VS function calls that do not have parameters.

 

These are two examples I spotted in your code:
vs.DSelectAll()
Dummy = vs.LNewObj()

 

That should clear your syntax problems.

 

Raymond
 

Thank you,Raymond.

 

You are right,  I fully forget to use VS syntax while writing python. 

 

Thanks agin for reminding.

Link to comment
On 5/27/2020 at 7:52 PM, MullinRJ said:

@Jiajing 

   In Python you have to put "()" after VS function calls that do not have parameters.

 

These are two examples I spotted in your code:
vs.DSelectAll()
Dummy = vs.LNewObj()

 

That should clear your syntax problems.

 

Raymond
 

Hello RayMond,

 

Following question about SetClass or SetClassN. 

 

If the design layer the object is in is grey out, both syntaxs will not work as it should be. Is there altanative way work around it.

 

Thank you

Link to comment

In a script the Layer Visibility should not matter. As long as you can get a handle to the object you should be able to work on it no matter where it is.

 

If you are trying to manually select the object and then run the script on it the selection step will definitely be impacted by the Layer Visibility options.

  • Like 1
Link to comment

Hi @Jiajing ,

   I just did some quick testing of your script. There are some side effects you need to be aware of.

 

   Short answer: vs.ForEachObjectInList() and ForEachObject() work differently. The first procedure walks through a list of handles where you supply the first object in the list. The second procedure walks through every object in the drawing. You change the selection state when you hide or gray objects by changing their class visibilities. I am assuming that is what you are doing.

 

   Your use of vs.ForEachObjectInList(AssignClass, 2, 2, vs.FInGroup(vs.GetParent(Dummy))) uses option 2, 2 which means Selected and Deep. If your group objects are grayed because they are in a Hidden Class they become unselected. Your script is using the SEL criteria to process objects, so unselected objects will not be processed as you walk through the list. If your groups are grayed another way, you'll have to see if this is still true. Notice your LW and color are set because ForEachObject() works differently from vs.ForEachObjectInList() and does not need the outer group to be selected to see selected objects inside that are selected.

 

   If you change your settings to vs.ForEachObjectInList(AssignClass, 0, 2, vs.FInGroup(vs.GetParent(Dummy)) you can enter grayed groups. This may not work exactly as you'd like so you may have to play with it.

 

HTH,

Raymond

 

  • Like 1
Link to comment

@Pat Stanford @MullinRJ 

I am changing layer visilibities, so this is what I am doing :

  1.  Grey out  design layer 1
  2.  Using vs.GetLayerByName to get  design layer 1's handle
  3. then vs.FActLayer () to get a first object handle on design layer 1
  4. Then using  vs.ForEachObjectInList to assign a class to all objects on design layer 1.

 

Change design layer 1 visibility does affect the handle of the first object. Need some help on this please

Edited by Jiajing
Link to comment

FActLayer gets the first object on the active layer. If you don't change the active layer to be design layer 1 then you are getting a handle to an object on a different layer and are then use ForEachObjectInList on the objects on a different layer.

 

Try using FInLayer(Handle to design layer 1) instead of the FActLayer and you might have better results.

  • Like 2
Link to comment

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.

×
×
  • Create New...