Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.

First time visiting? Here are some places to start:

  1. Looking for a certain topic? Check out the categories filter or use Search (upper right).
  2. Need support? Ask a question to our Community Support category.
  3. Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
  4. Be respectful, on topic and if you see a problem, Flag it.

If you would like to contact our Community Manager personally, feel free to send a private message or an email.

AddInstance import issues with Configuration Table Part Studio

eric_ma454eric_ma454 Member Posts: 14
Hi all,
Recently, we have had issues with a specific part studio that we have been trying to import and rotate at multiple points. The part studio is a pipe elbow with specific configurations that dictate its diameter and size. We have been having trouble since the part studio seems to not import correctly. Furthermore, we're unsure how to create a precondition that lets the user choose the configuration to import. If anyone has any insight onto the importing issues, as well as the configuration steps, that would be greatly appreciated.

Elbow(part studio called "elbow):


Instantiator:
https://cad.onshape.com/documents/740e6a14f9b0e5df6b16a58a/w/ce74bd2e6b57ecc8bb2a6914/e/0ca08a2379ad29306245682f


Best,
Eric Ma
AguaClara Cornell

Best Answers

  • MBartlett21MBartlett21 EDU Posts: 1,640 EDU
    Accepted Answer
    For the configuration parameter, you need to edit the featurescript ids and use them with "_conf" added onto the end.
    Please see this post by @kevin_o_toole_1
    https://forum.onshape.com/discussion/9001/configurations-update-edit-featurescript-ids
    It has an example document that uses configs
    MB - I make FeatureScripts: view FS (My FS's have "Official" beside them)
  • Jake_RosenfeldJake_Rosenfeld Posts: 1,393
    Accepted Answer
    @eric_ma454

    Personally, I find that the `vector(x, y, z)` interface is easier to use than `vector(value is array)`, but it just depends on how your input is coming.

    The difference I was trying to point out is the following:
    const positionVector = vector(1, 2, 3) * inch; // This is the position vector of a point in space
    const anotherPositionVector = vector(1 * inch, 2 * millimeter, 3 * centimeter); // Another position vector
    
    const directionVector = normalize(vector(1, 2, 3)) ; // This is a direction vector
    const anotherDirectionVector vector(5, 6, 7);  // This is another unitless direction vector, it's just not normalized.

    The addInstance function takes a Transform, which can be constructed using a rotation matrix and vector translation, but the toWorld and fromWorld will allow you to construct these Transforms directly (all my apologies for mentioning the wrong functions in my above comment, I've gone back and edited it to use the correct function calls).

    Here is to code that I was proposing you use:
    // --The inputs you've mentioned you already have--
    const sourcePoint = ...;
    const destinationPoint = ...;
    const sourceDirection = ...;
    const destinationDirection = ...;
    
    // --Constructing the transform and using it--
    
    // Use the direction you already have as the Z direction (for alignment) of the coordinate system, and pick an arbitrary perpendicular vector
    // as the X direction (to determine the spin).
    const sourceCSys = coordSystem(sourcePoint, perpendicularVector(sourceDirection), sourceDirection);
    const destinationCSys = coordSystem(destinationPoint, perpendicularVector(destinationDirection), destinationDirection);
    
    // There is a shorthand to construct a coordinate system if you do not care about the x direction:
    // const sourceCSys = coordSystem(plane(sourcePoint, sourceDirection));
    // This shorthand could be useful if you don't end up caring about the spin, but I wanted to show you the longhand in case 
    // you want to start playing around with the X direction to determine spin.
    
    
    const xform = toWorld(destinationCSys) * fromWorld(sourceCSys);
    
    addInstance(..., {
                ...,
                "transform" : xform,
                ...
            });
    

    Hopefully it is a little clearer now what to do.  Once you use the code above, you may find that the spin of your instanced part is all wrong.  If that is the case, you will want to be more explicit about the X direction in `sourceCSys` and `destinationCSys`, either by making your user define a mate connector, or by doing some smart inferencing.  If you get stuck on that step, we can discuss again :)
    Jake Rosenfeld - Modeling Team

Answers

  • MBartlett21MBartlett21 EDU Member Posts: 1,640 EDU
    Please see https://forum.onshape.com/discussion/comment/49762/#Comment_49762
    With the FeatureScript I linked, it shows examples of how to import to a custom coordinate system and how to implement configurations
    MB - I make FeatureScripts: view FS (My FS's have "Official" beside them)
  • eric_ma454eric_ma454 Member Posts: 14
    Please see https://forum.onshape.com/discussion/comment/49762/#Comment_49762
    With the FeatureScript I linked, it shows examples of how to import to a custom coordinate system and how to implement configurations
    I was more interested in transformations in the form of a transform matrix, as one of the AddInstance parameters takes a matrix and point to transform. How would I create the transformation matrix from two Vector types? I specifically have the two vectors that the elbow pipe aligns with, but no way to properly rotate it into the right direction.

    Furthermore, I had a few questions on how you create the precondition for the configurations, specifically where Size_conf comes from, and where I would find that for a specific configuration.
  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,393
    edited February 11
    Hi @eric_ma454

    When you say "Vector type", I am unsure of what you mean.  A vector can hold a position OR a direction (based on whether it is a vector whose members have length units, or the members are unitless, respectively).  In either case, this is not enough to fully define a transformation.  Based on context, I assume that the two vectors you have are direction vectors?

    Two direction vectors do not fully define a transformation for the following reason.  If you imagine a part with an associated source vector, and then have another destination vector, once you get to the destination, you can have any possible spin around that vector.  Additionally, because there is no associated position, there is no information about the translation involved in the transformation.

    What you need here are two coordinate systems (CoordSystem in FeatureScript).  The coordinate systems will have an origin (to determine translation) a z direction (to determine orientation) and an x direction (to determine spin).  The simplest way to generate a coordinate system in FeatureScript is by having the user place a mate connector, consume that mate connector as a parameter to the feature, and then to evaluate the mate connector; but there are also interfaces that will allow you to create a coordinate system by hand.  Once you have two coordinate systems, transforming points is simple: 

    const destinationPoint = toWorld(destinationCSys) * fromWorld(sourceCSys) * sourcePoint;
    (Note that this math is meant to be read from right-to-left: Take the source point, change its basis to the source coordinate system, then take that intermediate representation and change its basis back to the global coordinate system assuming that the basis was the destination basis rather than the source basis.)

    So the transform you desire is:
    const transform = toWorld(destinationCSys) * fromWorld(sourceCSys);


    @ilya_baran or @kevin_o_toole_1 may be able to help with the other part of the question if @MBartlett21 does not reply (I think you'll hear back soon though :) ).  I am not as knowledgeable about that part of the system.
    Jake Rosenfeld - Modeling Team
  • eric_ma454eric_ma454 Member Posts: 14
    @Jake_Rosenfeld
    Thank you for your reply! The Vector I was referencing is the Vector type I found on the SLD, where for instance the function vector(value is array) does the function "make a Vector from an array."  The main goal was to align the two pipes of an elbow pipe along two drawn out sketch lines. The code I already have currently has the location, and I have the vectors of the two lines that the pipe should follow. The main reason for looking for a matrix is because in the AddInstance, there's a transform parameter that take in a matrix, for rotation, and a vector, for translation. My main issue is how to convert the two vectors and their normal into a rotation matrix not unlike the math that you mentioned, and use it in the context of the "transform" function found in addinstance.
    Thank you!
  • MBartlett21MBartlett21 EDU Member Posts: 1,640 EDU
    Accepted Answer
    For the configuration parameter, you need to edit the featurescript ids and use them with "_conf" added onto the end.
    Please see this post by @kevin_o_toole_1
    https://forum.onshape.com/discussion/9001/configurations-update-edit-featurescript-ids
    It has an example document that uses configs
    MB - I make FeatureScripts: view FS (My FS's have "Official" beside them)
  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,393
    Accepted Answer
    @eric_ma454

    Personally, I find that the `vector(x, y, z)` interface is easier to use than `vector(value is array)`, but it just depends on how your input is coming.

    The difference I was trying to point out is the following:
    const positionVector = vector(1, 2, 3) * inch; // This is the position vector of a point in space
    const anotherPositionVector = vector(1 * inch, 2 * millimeter, 3 * centimeter); // Another position vector
    
    const directionVector = normalize(vector(1, 2, 3)) ; // This is a direction vector
    const anotherDirectionVector vector(5, 6, 7);  // This is another unitless direction vector, it's just not normalized.

    The addInstance function takes a Transform, which can be constructed using a rotation matrix and vector translation, but the toWorld and fromWorld will allow you to construct these Transforms directly (all my apologies for mentioning the wrong functions in my above comment, I've gone back and edited it to use the correct function calls).

    Here is to code that I was proposing you use:
    // --The inputs you've mentioned you already have--
    const sourcePoint = ...;
    const destinationPoint = ...;
    const sourceDirection = ...;
    const destinationDirection = ...;
    
    // --Constructing the transform and using it--
    
    // Use the direction you already have as the Z direction (for alignment) of the coordinate system, and pick an arbitrary perpendicular vector
    // as the X direction (to determine the spin).
    const sourceCSys = coordSystem(sourcePoint, perpendicularVector(sourceDirection), sourceDirection);
    const destinationCSys = coordSystem(destinationPoint, perpendicularVector(destinationDirection), destinationDirection);
    
    // There is a shorthand to construct a coordinate system if you do not care about the x direction:
    // const sourceCSys = coordSystem(plane(sourcePoint, sourceDirection));
    // This shorthand could be useful if you don't end up caring about the spin, but I wanted to show you the longhand in case 
    // you want to start playing around with the X direction to determine spin.
    
    
    const xform = toWorld(destinationCSys) * fromWorld(sourceCSys);
    
    addInstance(..., {
                ...,
                "transform" : xform,
                ...
            });
    

    Hopefully it is a little clearer now what to do.  Once you use the code above, you may find that the spin of your instanced part is all wrong.  If that is the case, you will want to be more explicit about the X direction in `sourceCSys` and `destinationCSys`, either by making your user define a mate connector, or by doing some smart inferencing.  If you get stuck on that step, we can discuss again :)
    Jake Rosenfeld - Modeling Team
  • eric_ma454eric_ma454 Member Posts: 14
    Please see https://forum.onshape.com/discussion/comment/49762/#Comment_49762
    With the FeatureScript I linked, it shows examples of how to import to a custom coordinate system and how to implement configurations
    @MBartlett21
    Is there any way to import more than one part studio? I understand the form of variablename::import exists, but is it possible to export import multiple part studios in one document, and instantiate/access their configurations separately?
  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 449
    @owen_sparks recently posted in the forum an example of a feature switching between multiple part studios:
    https://forum.onshape.com/discussion/11161/drive-an-instantiator-via-an-enum-input#latest

    Is that type of functionality what you're looking for?

  • eric_ma454eric_ma454 Member Posts: 14
    @kevin_o_toole_1
    Hi Kevin, this is similar to what I was looking for, but both of the imports have configurations. The only way I've found so far to be able to have users choose configuration is to export the imported part studio, but when I use the format of 
    PartStudioName::import(...)
    I'm not able to export the part studio, and can't specify which part studio I'm instantiating at a specific point.


  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 449
    edited February 21
    Ah, you mean using the configuration enum directly as a parameter. Yes, the hangup right now is that you cannot import two Part Studios without a namespace, but you cannot use an enum for a feature parameter with a namespace.

    This is not a use case we had in mind when originally implementing configs but I think can see the value. If this is important to you please create an improvement request (for a bonus, link us to a version of a document that demonstrates why this would be useful!)

    For now, the best you can do is
    1. Add enum declarations for everything (e.g. export enum Foo {  /* redeclare all the Part Studios options */} )
    2. Add inputs for those enums (e.g. definition.foo is Foo)
    3. Remap those enums back to the Part Studio enums (e.g. { "MyInput" : MyInput_conf[definition.foo as string] } )
    Naturally, this duplicates some work, but it should otherwise give you the feature you need.
  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 449
    It's also possible that Part Studio reference parameters will give you something closer to what you want. This provides an input that allows selecting any Part Studio, and creates inputs for the configuration of the selected Part Studio. With reference parameters, you don't need any imports of Part Studios in your feature studios at all (in the end, the Part Studio imports end up in the Part Studio that uses your feature, not in the Feature Studio that defines the feature itself).

    Features with references parameters are more flexible and end up with much less frequent changes to the feature code. Depending on your desired feature, you might be able to come up with a workflow that uses one instead.
Sign In or Register to comment.