Jump to content

Multiple Extrude as "plugin-object"


Recommended Posts

Hello! We are currently working with VW2021 basic english.

I would like to investigate the possibilities of the plugin-objects, which can be done via Vector-script as far as I know.

As a first object I would like to have a multiple extrude which is the result of two concentric circles of different diameters and a "length". The result should be a rotationally symmetric cone with one diameter at one end end the other diameter at the distance "length" at the other end. (In the piping industry this is called a concentric reducer).

Concerning plugin-objects I am a total newbie.

 

1) Can someone guide me how to start with this?

2) Does somebody know a link where I can download some simple files (vectorscript-objects) which enable me to begin to understand?

3) Helpful also would be a link to a movie where first basic steps are explained.

 

Thanks a lot for any help.

Link to comment

You’ll find the plug-in editor in the tools menu.

In the plug-in editor you can create an additional plug-in.

I think the reducer would be a point object or a line object.

You ‘ll need to add a few parameters to the plug-in object. This can be done in the plug-in editor.

Last but certainly not least, you’ll need to write the script. This can be Vectorscript or Python. The script can be written in the plug-in editor or referenced to an external text file (.px for Vectorscript, .py for Python).

 

Also, check the developer website for reference. developer.vectorworks.net

 

Of course there are at least a thousand more things to tell about scripting in Vectorworks.

Link to comment

A point object plugin would behave like the 3D W-Flange and 3d HSS objects in that there is no option to change the length and orientation by grabbing an end point with the mouse and dragging it to is new location. Whereas a line object has this functionality built into it by providing a start and end point for its length and behave like a line.

The rest of the functionality is adjusted through variables you declare to display in the Object Info Palette with the script using this data to create your object in a step by step fashion. Program coding. The coding options being Python or Pascal like as mention earlier. All the VW specific functions and procedures are listed within the Plug-in manager. You refer to the language guide for it's functions, formatting and procedures.

Link to comment

There used to be a pretty good primer for Vectorscript in the native help file for Vectorworks, but they removed it at some point.  I've attached it below.  It's old, but Vectorscript hasn't changed much in the last 10 years since it's based on Pascal, which first appeared in 1970.  Vectorworks has incorporated Python, which is a much less esoteric and more powerful language, but you're still hamstrung by the Vectorscript function library when you want to interact with VW, so it only really helps for data management.

 

Another terrific resource is the Vectorscript Function Reference, of which an offline version is installed alongside Vectorworks.  No idea about where it ends up on a Mac, but on windows it can be found in C:\Program Files\Vectorworks 20XX\VWHelp\Script Reference\ScriptFunctionReference.hml.  I usually have this open on a second monitor any time I'm working in Vectorscript.  I will warn that it's not exactly complete, some functions have no information at all other than outlining the constructor, and some are fully fleshed out with examples (though sometimes the examples can be less than helpful).  The Developer Wiki site that others have posted about is also a good resource, as it can sometimes fill in the holes in the local version, but I find the local version much easier to navigate.

VectorScript_LanguageGuide.pdf

Link to comment

Based on your example file, I think a sweep would be a better option than a multiple extrude.  Based on past experience, sweeps generate better wireframe meshes than multiple extrudes, important for Hidden Line drawings.  The only time I would use a multiple extrude for something like this would be for an eccentric reducer, where a sweep would not be possible.

 

With that in mind, on to the code.  For a simple solid 3D cone, the coding is very simple.  Steps are outlined below.

  1. You will need to create a new plug-in by going to the Plug-in Manager (Tools - Plug-ins - Plug-in Manager) and clicking on the "New" button.  This will open a dialog asking for the plug-in type.  In this instance, I think a Linear Object is the best type, which will be used to set the length of the reducer.  Name it and click OK.
  2. With any Plug-in Object types, you will need to define some parameters before starting in on the code.  To do this, select your script and click on the "Edit Definition" button.
  3. In the General tab, assign a category for your plug-in.  This is where you will find the plug-in to add it to your workspace.
  4. In the Parameters tab, you will assign additional parameters above the given ones of your plug-in type.  Important things to note is the Name vs. Alternate Name.  The parameter name in the Name column is going to be what the code itself references, while the Alternate Name is the one that Vectorworks is going to show in the Object Info Palette.  Having these separate allows plug-ins to be localized for different languages without needing access to the source code of the plug-in.
  5. In this instance, I would create two Dimension parameters, named diameter1 and diameter2 with alternate names being Diameter 1 and Diameter 2.  There's no defined rules for parameter naming, but I tend to set their Names based on how they will appear in the code, so I tend to do uncapitalized, camel case with no spaces and use the Alternate Name to make something a little more friendly.  Any Dimension type parameters MUST have a default value, so set this based on what the most common reducer you tend to use (such as 3/4" x 1/2").
  6. The other tabs don't really matter for this particular instance, but I'll detail them anyway.  The Strings tab is used to define strings for localization purposes.  If your object has text that appears outside of parameter names, such as dialog boxes or warnings and such, the strings should be defined here and called into the script using GetPluginString.  I tend to build categories like "Dialog Strings", "Dialog Help Strings", "Messages", and "Miscellaneous Strings".  Having these outside the actual code allows your plug-ins to be localized even when they are encrypted.
  7. The Properties tab allows you to select an icon, set projection requirements, and write out the tooltip help for your plug-in.
  8. The Options tab lets you set a couple of options in terms of how your plug-in will operate.  Event-Based plug-ins allow you to customize the OIP with buttons or more aware parameters (such as a drop-down list populated with items from a particular drawing rather than being hard-coded into the plug-in).  Events-based plug-ins are a whole different beast with a relatively much more complicated coding to get them to work correctly.  The current documentation surrounding events isn't great, but there has been some discussion of filling it out with some helpful articles from a now-defunct website called VectorLab, so stay tuned if you are interested in events-based plug-ins.
  9. Other options include Reset on Move or Reset on Rotate, these are used if your plug-in does things regarding its location.  If it creates a text box displaying its X and Y value as an example, you will want Reset on Move to be checked.
  10. Other than that, the Options tab has the standard Insert in Walls functions that symbols can have.
  11. Click OK to close out the dialog box.
  12. One more step before you can really get coding is to insert your new tool into the workspace.  To do this, exit out of the Plug-in Manager and open up the Workspace Editor by going to Tools - Workspaces - Edit Current Workspace.  You will find your new tool in the "Tools" tab in the left box under the category that you specified (or "Miscellaneous" if you did not specify a category).  Click and drag your tool from the left box into the desired toolset in the right box.  Click OK to close the editor and reset the workspace with your added tool.

The code I used is listed below and also attached it to this post as "Concentric Reducer Simple.vso".  I've added comments explaining how it is set up.  Vectorscript is based on Pascal, so there's a couple of things that can be odd if you're used to more modern languages like Python or Java.

 

PROCEDURE ConcentricReducer; {All methods in VS are either Functions or Procedures.  Functions return a value, procedures perform a set of operations, though they can also return a value if you need to.  To do so, specify a variable in the constructor with a VAR flag in front of it}

{*	Creates a 3D Solid object representing a Concentric Reducer pipe fitting
	Developed by: Jesse Cogswell
	VW Version: 2019
	Date: 5/1/2021
	Revisions:
*}

CONST {This is the constant declaration block.  All constants in VS must be declared and initialized in one of these blocks.  You do not need to specify types here, VS will determine the type based on the entered value.  This block is not necessary if you have no constants, it's provided here by way of example}

	DUMMY = 0;

VAR {This is the variable declaration block.  All variables in VS must be declared in one of these blocks before it can be used.  This particular one is the global variable block.  Here, we'll declare the parameter variables}

	lineLength,diameter1,diameter2:REAL;
	
{Between this point and the main driver block, you can specify any number of procedures and functions as necessary.  VS compiles from top to bottom, so if you call a procedure, make sure the definition appears above the call}
	
PROCEDURE CreateReducer(length,dia1,dia2:REAL); {Here is the procedure that actually creates the 3D solid.  It takes in the length and two diameters and creates the object}

{Creates 3D Solid based on given variables}

	VAR {Just as above, this procedure has its own variable declaration block.  The variables declared can only be used within this procedure definition}
	
		Origin,A,B:POINT;
		sweepHd:HANDLE;
		
	BEGIN
		{I usually specify an Origin point but don't initialize it, this ensures that it will read as (0,0)}
		{Point types are a special Structure within VS which contains an X and a Y value.  This information can be accessed by calling <point name>.x or <point name>.y}
		{Other special Structures include POINT3D, VECTOR, and RGBCOLOR types}
		{You can define your own Structures in the TYPE declaration block, though it's a bit more of an advanced usage. Information can be found in the Language Guide in the "Structures" chapter} 
		A.x:=Origin.x+(dia1*0.5);
		A.y:=Origin.y;
		B.x:=Origin.x+(dia2*0.5);
		B.y:=Origin.y-length;
		
		BeginSweep(0,360,10,0);
			Poly(Origin.x,Origin.y,A.x,A.y,B.x,B.y,Origin.x,B.y,Origin.x,Origin.y);
		EndSweep;
		sweepHd:=LNewObj;
		
		HRotate(sweepHd,Origin.x,Origin.y,90);
		{Because of the nature of Sweep command, the outlining shape is created 90 degrees off from the created line and then rotated in place}
	END;
	
FUNCTION CreateReducerH(length,dia1,dia2:REAL) : HANDLE; {Here is the same code as above but as a function to return a handle to the resulting object.  This is useful if you wanted to use another procedure to change the object later, such as setting color}

{Creates 3D Solid based on given variables and returns a handle to the resulting 3D Solid}

	VAR
	
		Origin,A,B:POINT;
		sweepHd:HANDLE;
		
	BEGIN
		A.x:=Origin.x+(dia1*0.5);
		A.y:=Origin.y;
		B.x:=Origin.x+(dia2*0.5);
		B.y:=Origin.y-length;
		
		BeginSweep(0,360,10,0);
			Poly(Origin.x,Origin.y,A.x,A.y,B.x,B.y,Origin.x,B.y,Origin.x,Origin.y);
		EndSweep;
		sweepHd:=LNewObj;
		
		HRotate(sweepHd,Origin.x,Origin.y,90);

		CreateReducerH:=sweepHd; {This is how you specify the returned value, it's <Function Name>:= <variable>}
	END;

{MAIN DRIVER BLOCK}

BEGIN
	{At the beginning of the Main Driver Block, I will always transfer the OIP parameters, accessed using the syntax "P<parameter name>" into global variables.  This is a personal preference, and you're welcome to just use the P<parameter name> call everytime you need the variable}
	lineLength:=PLineLength;
	diameter1:=Pdiameter1;
	diameter2:=Pdiameter2;
	
	CreateReducer(lineLength,diameter1,diameter2);
	
	{Best practice is to think in a modular fashion, with most operations being outside of the main driver}
	
	{Below is an example of the using the function instead of the procedure to create the object.  Note that the handle would need to be declared in the global variable declaration block before this code could be used}
	{reducerHd:=CreateReducerH(lineLength,diameter1,diameter2);}
END;

Run(ConcentricReducer); {Final run statement to execute the script}

Also attached is a similar script, "Concentric Reducer.vso" that will incorporate wall thickness to draw a more realistic tube shape.  I won't go into the code here, but you are welcome to open it and noodle with it.  There is probably a much more simple mathematic method of determining points for wall thickness, but as someone who hasn't studied trigonometry since high school, I opted to use an OffsetPolyN and IntersectSurface solution instead.

 

Let me know if you need any help installing or opening these plug-ins, as the process is a bit complicated.

Concentric Reducer Simple.vso Concentric Reducer.vso

  • Like 2
Link to comment

Thank you all for your contributions; especially Jesse: Should you ever come to Aachen/Germany, be sure you get a free beer from me: Yesterday I investigated your post. Finally I made it run (changed "LineLength" by "lineLength" once and changed the 90° by -90°).

I adjusted the code in a way that the cone now has got two different wall thicknesses for the two different diameters. For this I created a closed polygon which is swept afterwards:

The code is here (only small adjustments compared to yours, and "CreateReducerH" not changed):

PROCEDURE ConcentricReducer; {All methods in VS are either Functions or Procedures.  Functions return a value, procedures perform a set of operations, though they can also return a value if you need to.  To do so, specify a variable in the constructor with a VAR flag in front of it}
{*    Creates a 3D Solid object representing a Concentric Reducer pipe fitting
    Developed by: Jesse Cogswell
    VW Version: 2019
    Date: 5/1/2021
    Revisions:
*}
CONST {This is the constant declaration block.  All constants in VS must be declared and initialized in one of these blocks.  You do not need to specify types here, VS will determine the type based on the entered value.  This block is not necessary if you have no constants, it's provided here by way of example}
    DUMMY = 0;
VAR {This is the variable declaration block.  All variables in VS must be declared in one of these blocks before it can be used.  This particular one is the global variable block.  Here, we'll declare the parameter variables}
    lineLength,diameter1,diameter2,thick1,thick2:REAL;
    {reducerHD: HANDLE;}
    
{Between this point and the main driver block, you can specify any number of procedures and functions as necessary.  VS compiles from top to bottom, so if you call a procedure, make sure the definition appears above the call}
    
PROCEDURE CreateReducer(length,dia1,dia2,thick1,thick2:REAL); {Here is the procedure that actually creates the 3D solid.  It takes in the length and two diameters and creates the object}
{Creates 3D Solid based on given variables}
    VAR {Just as above, this procedure has its own variable declaration block.  The variables declared can only be used within this procedure definition}
    
        Origin,A,B,C,D:POINT;
        sweepHd:HANDLE;
        
    BEGIN
        {I usually specify an Origin point but don't initialize it, this ensures that it will read as (0,0)}
        {Point types are a special Structure within VS which contains an X and a Y value.  This information can be accessed by calling <point name>.x or <point name>.y}
        {Other special Structures include POINT3D, VECTOR, and RGBCOLOR types}
        {You can define your own Structures in the TYPE declaration block, though it's a bit more of an advanced usage. Information can be found in the Language Guide in the "Structures" chapter} 
        A.x:=Origin.x+(dia1*0.5)-thick1;
        A.y:=Origin.y;
        B.x:=Origin.x+(dia1*0.5);
        B.y:=Origin.y;
        C.x:=Origin.x+(dia2*0.5);
        C.y:=Origin.y+length;
        D.x:=Origin.x+(dia2*0.5)-thick2;
        D.y:=Origin.y+length;
        
        BeginSweep(0,360,15,0);
             Locus(0,0);
            {Locus(Origin.x,Origin.y);}
            {Poly(Origin.x,Origin.y,A.x,A.y,B.x,B.y,Origin.x,B.y,Origin.x,Origin.y);}
            {Poly(dia1/2-thick1,0,dia1/2,0,dia2/2,length,dia2/2-thick2,length,dia1/2-thick1,0);}
            Poly(A.x,A.y,B.x,B.y,C.x,C.y,D.x,D.y,A.x,A.y);
        EndSweep;
        sweepHd:=LNewObj;
        
        HRotate(sweepHd,Origin.x,Origin.y,-90);
        {Because of the nature of Sweep command, the outlining shape is created 90 degrees off from the created line and then rotated in place}
    END;
    
FUNCTION CreateReducerH(length,dia1,dia2,thick1,thick2:REAL) : HANDLE; {Here is the same code as above but as a function to return a handle to the resulting object.  This is useful if you wanted to use another procedure to change the object later, such as setting color}
{Creates 3D Solid based on given variables and returns a handle to the resulting 3D Solid}
    VAR
    
        Origin,A,B:POINT;
        sweepHd:HANDLE;
        
    BEGIN
        A.x:=Origin.x+(dia1*0.5);
        A.y:=Origin.y;
        B.x:=Origin.x+(dia2*0.5);
        B.y:=Origin.y-length;
        
        BeginSweep(0,360,15,0);
            Poly(Origin.x,Origin.y,A.x,A.y,B.x,B.y,Origin.x,B.y,Origin.x,Origin.y);
        EndSweep;
        sweepHd:=LNewObj;
        
        HRotate(sweepHd,Origin.x,Origin.y,90);
        CreateReducerH:=sweepHd; {This is how you specify the returned value, it's <Function Name>:= <variable>}
    END;
{MAIN DRIVER BLOCK}
BEGIN
    {At the beginning of the Main Driver Block, I will always transfer the OIP parameters, accessed using the syntax "P<parameter name>" into global variables.  This is a personal preference, and you're welcome to just use the P<parameter name> call everytime you need the variable}
    lineLength:=PLineLength;
    diameter1 :=Pdiameter1;
    thick1    :=Pthick1;
    diameter2 :=Pdiameter2;
    thick2    :=Pthick2;
    
    CreateReducer(lineLength,diameter1,diameter2,thick1,thick2);
    {Best practice is to think in a modular fashion, with most operations being outside of the main driver}
    
    {Below is an example of the using the function instead of the procedure to create the object.  Note that the handle would need to be declared in the global variable declaration block before this code could be used}
    {reducerHd:=CreateReducerH(lineLength,diameter1,diameter2);}
END;
Run(ConcentricReducer); {Final run statement to execute the script}

I could not make your "Concentric reducer" run; the code here did not display anything 🙂

 

I have some more questions:

1) Are all definitions (f.e. "Edit definition....") stored in the vso-file?

2) Should I place 10,100,1000 concentric reducers looking all the same (diameters, length, wall thicknesses, color, etc.), what is the most efficient way to do? Should I cut, copy, paste the concentric reducer made by the VS-code or should I make a symbol of it and cut, copy, paste the symbol?

Link to comment

I'll take a look at the code in VW2021.  I use 2019 primarily as I find it to be the most stable on my machine, and there are some rather annoying and persistent bugs in 2021.  For as much as Vectorscript generally doesn't change, every once in a while they will change a command and cause scripts from earlier versions to break, and I seem to recall OffsetPolyN to be one of those commands.  I also didn't try using it in a metric drawing, there is a chance that OffsetPolyN doesn't respect document units (as you get deeper into the weeds of Vectorscript, you'll come to realize that there's not always a rhyme or reason to which units functions and procedures use, and it's not usually detailed in the Function Reference.

 

I'm glad that you were able to get this working.  Scripting in VW is incredibly powerful and one of the major reasons that I have stuck with VW in spite of the quirks and bugs.  To answer your questions:

  1. All of the information from the Edit Definition dialog box is stored in the vso file including parameter defaults, plug-in strings, and tool-tip information.  The only thing not stored in the vso file would be an external resource file (like if you wanted to have a drop-down menu to select common wall thicknesses, all of that data could be stored in a tab or space delimited text file), but any changes you make on a script through the Plug-in Manager stays with the file.
  2. Vectorworks will be far happier with you if you store the plug-in object into a symbol if you're going to have that many.  The Concentric Reducer that you have outlined is very lightweight in terms of processing and memory usage, but each instance would be individually computed even though they're identical.  Symbols are about as lightweight as you can get in VW, with each instance only needing to compute X, Y, Z, and rotation data while the symbol definition is computed just once.  I'm a huge proponent of symbols for this reason, even if you might only have one instance in the drawing.  I work with a lot of designers who seem to favor using Groups instead, and it drives me up the wall.
Link to comment

Yes, concentric reducer now shows up correctly 🙂

 

One further question: I tried to "make" an elbow. Main code is as follows:

	BEGIN	
          BeginSweep(0,90,seg,0);
             Locus(radius,0);
             ArcByCenter(0,0,diameter/2,0,360);
          EndSweep;
          sweepHd:=CreateShell(sweepHd,thick);
          Locus3D(0,0,0);
          Locus3D(radius,0,-radius);		
	END;

The "CreateShell" line is wrong. Does anybody know, how to correctly apply a "wall thickness" to this sweeped elbow? With Vectorworks itself I can do it by just selecting the sweeped circle, apply "Shell Solid Tool", Shift-click both edge surfaces of this sweeped circle and click the green "hook" for completing the operation.

 

 

Link to comment

I've created a flat ring by using two circles and clip surface, subsequently deleting the inner circle before sweeping the ring.

Then swept that ring along a path in the past. (I always forget how to create the correct inside radius for the 1/4 torus using the basic sweep command.)

Link to comment

@virk I've never been able to get the CreateShell function to work.  It's looking for a NURBS surface, but I have no idea on how to properly extract the specific surfaces from a sweep object to use for CreateShell.

 

Theoretically, for an elbow could use an CreateExtrudeAlongPath function using a circle representing outer dimension and another using inner dimension with the same path object, then a SubtractSolid command to create your shell.

Link to comment

This is my elbow code:

 

        BeginSweep(0,90,seg,0);
            Locus(radius,0);
           ArcByCenter(0,0,diameter/2,0,360);
           arc1:=LNewObj;
           ArcByCenter(0,0,diameter/2-thick,0,360);
           arc2:=LNewObj;
           sweepHd:=ClipSurfaceN(arc1,arc2);
           DelObject(arc1);
           DelObject(arc2);
        EndSweep;
 

Link to comment

You don't say if your code was successful (I've not checked), but if you are not seeing the final object then it could be that either arc1 or arc2 will be sweepHd.

When using Clipsurface from the menu the furthest back object is altered. There is no option for the original unclipped object to remain.

There would also be the possibility where the diameter of arc1 is smaller than arc2 leaving nothing behind after the clip process.

Link to comment

Sorry, yes my code is successful 🙂

And you may be right; if any input values are not "correct", output will also be corrupt somehow. But currently the code outputs exactly what I want it to be.

Further: I think, if you copied the code manually: create two arcs, ClipSurface them, delete the arcs and sweep the clipped surface, you will lose the ability to later change the diameter somehow, because the original arcs are deleted. But because of the plugin-character, - the elbow will be calculated newly when required-, you can make/configure any elbow with just the parameters in the object info palette. For me as a total Vectorscript-newbie this is quite interesting 🙂

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...