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.

Options

Create Alternative Extrude Command, using as many OOTB elements as possible.

Jonathan_HutchinsonJonathan_Hutchinson Member Posts: 65 PRO
I have created an extrude command which just deals in segmented side cylinders. How could I incorporate all the goodies (in the standard extrude.fs, presumably) so that I'm not reinventing the wheel?

For instance, adding the 'Up To' overloads and so forth would be really helpful. I fell at the first hurdle just trying to add the BoundingType enum as input within a feature precondition:

        annotation { "Name" : "Bounding Type" }
        definition.boundingType is BoundingType;

Gives the warning: 'enum used as a parameter must be exported' - which is a bit vague for me. I tried just redeclaring the BoundingType, which autocompletes anyway, so was a bit of a loss there.

Effectively, all that my feature does is specifiy a point, direction via plane input, blind depth (which would be nice to overload) and segments for the sides.

Any help would be greatly appreciated!

Comments

  • Options
    mahirmahir Member, Developers Posts: 1,291 ✭✭✭✭✭
    You can start by just making a copy of the official extrude.fs. At that point you can add/modify whatever you want.
  • Options
    Evan_ReeseEvan_Reese Member Posts: 2,066 PRO
    Your question is very timely. I just finished a project that re-uses a lot of extrude code. A few tips:
    1. import the extrude code to your feature studio from here. This will give you access to the extrude() function which is the full extrude feature you're used to (as opposed to opExtrude(), which is paired back a lot). You can also import the extrude precondition (user interface), or copy/paste it to modify it for your needs
    2. Pay attention to the fields on the definition for extrude(). Remember that the definition is just a map of key-value pairings, which you can edit as you like. For example, you're going to be creating your own sketch for the region instead of letting the user pick one, so you'd make the sketch with FS like normal, query the region to extrude with qSketchRegion(), then make definition.entities equal that.
    3. Once it's edited, you can just call extrude(definition) to get it to work, without having to re-code the extrude feature.
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • Options
    Jonathan_HutchinsonJonathan_Hutchinson Member Posts: 65 PRO
    Thanks already for the help, both. Glad you think so, Evan! So, what I'm discovering is that the classic 'import(path : "onshape/std/common.fs", version : "2066.0");' isn't a blanket for everything?

    Starting with a light stroll, before an eventual jog (hopefully), my fix was as follows:

    import(path : "onshape/std/common.fs", version : "2066.0");
    export import(path : "onshape/std/boolean.fs", version : "2066.0");

    alternatively, just the below also worked:
    export import(path : "onshape/std/common.fs", version : "2066.0");

    Now, call me old fashioned, but I'm one of those folks who likes to know why they're doing something way, so even just 'import this' can leave me with multiple slightly different interpretations. Even in the course of writing this post I've ended up going to the start and thinking, 'hey, but that contradicts what I thought 5 minutes ago!'  :D my hunch is that exporting all of the importing of common.fs is unnecessarily weighty?

    I suppose the notion of exporting an import semantically sounds backwards to me, because I'm importing it for use in a place that I've chosen.

    Going back to the extrude, there's a tonne in the extrude command that I certainly don't and won't need to sift through. Does it make sense to be going through copying/pasting/cherrypicking bit's I'd like?
  • Options
    NeilCookeNeilCooke Moderator, Onshape Employees Posts: 5,416
    Change common.fs to geometry.fs and that should cover most things.
    Senior Director, Technical Services, EMEAI
  • Options
    Jonathan_HutchinsonJonathan_Hutchinson Member Posts: 65 PRO
    edited June 2023
    Thanks Neil. Is this considered best practice? In a similar example I want to reproduce a version of the transform command, which takes as input a featureId and represents all the entities that a feature has spat out. To be able to offer up the TransformType enum I see that I can do optionally:

    FeatureScript 2045;
    import(path : "onshape/std/geometry.fs", version : "2045.0");
    export import(path : "onshape/std/transformCopy.fs", version : "2045.0");

    Or:
    FeatureScript 2045;
    export import(path : "onshape/std/geometry.fs", version : "2045.0");

    This is maybe a good exercise for 'importing' the transform function. In 'transformCopy.fs' there are quite a few things I can see that I could try to import. Using Evans advice, my hunch is that I essentially force a certain definition where definition.entities is specified within a duplicate of the transform feature? 
  • Options
    Evan_ReeseEvan_Reese Member Posts: 2,066 PRO
    @Jonathan_Hutchinson

    For any of them all that has to be paired back is the UI, which you can make yourself. You can still call the full feature function in the code, even if the user doesn't have a chance to edit most of the definition. I made an example called "stupid extrude" which takes away all user control except whether it has draft. You could do this for any feature so you get all of the power and robustness of native features, but can control the UI and perform some additional logic in the code that creates the definition of those features. https://cad.onshape.com/documents/94dffb8d7b5b37a28b775459/w/510169e58d0d699e9cdf0893/e/d40e04a484a681c4cbc09feb

    @NeilCooke
    Thanks, I'll remember that method.
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • Options
    Jonathan_HutchinsonJonathan_Hutchinson Member Posts: 65 PRO
    edited July 2023
    Okay, I've made some headway with this!

    With the extrude command, which has a lot of permutations, I'm trying to work out the best way of creating the maps based on conditionals from the input.

    Am I right in thinking that I can't 'blanket' all the fields, even if one isn't relevant for the condition in mind? In the below example, I've added all the 'second direction bound entity' types, knowing in advance that only one of these will be populated based upon the 'secondDirectionBound' choice. Does that make sense? From my fiddling around so far, I am seeing that having fields (that I expect will be undefined) tends to not be working.

    The alternative to this looks like it will be a lot of conditionals and maybe some map merging to have a bit less repeated code.

    OR: in the feature action, just pass extrude(context, id, definition), and that means only the map fields used based on input are passed?

            if (definition.endBound == BoundingType.BLIND)
            {
                if (definition.hasSecondDirection)
                {
                    //def = merge this and that
                    extrude(context, id + "extrude1", {
                                "entities" : definition.entities,
                                "endBound" : definition.endBound,
                                "depth" : definition.depth,
                                "oppositeDirection" : definition.oppositeDirection,
                                "hasSecondDirection" : definition.hasSecondDirection,
                                "secondDirectionBound" : definition.secondDirectionBound,
                                "secondDirectionDepth" : definition.secondDirectionDepth,
                                "secondDirectionOppositeDirection" : definition.secondDirectionOppositeDirection,
                               "secondDirectionBoundEntityFace" : definition.secondDirectionBoundEntityFace,
                               "secondDirectionBoundEntityBody" : definition.secondDirectionBoundEntityBody,
                               "secondDirectionBoundEntityVertex" : definition.secondDirectionBoundEntityVertex
                            });
                }
            }
  • Options
    Evan_ReeseEvan_Reese Member Posts: 2,066 PRO
    I believe that a lot of the fields will have a default if they aren't assigned. So instead of most booleans being read as "undefined" they will be taken as "false" or whatever the default is. I'm not sure, but I'd start simple and follow error messages to tell which ones are essential to define. I'd go for your second option where you just type.
    extrude(context, id, definition)
    which should be based on a pre-defined variable called definition containing a map. Or it could be called extrudeDef or anything you want so it doesn't get confused with your main feature definition.
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • Options
    Jonathan_HutchinsonJonathan_Hutchinson Member Posts: 65 PRO
    Yeah this seems the way to go! Then doing some mergeMap operations.

    The extrude command is proving tough to get that right balance of simplification but also all the good options, but I've made headway.
Sign In or Register to comment.