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.

opdraft 101

Evan_ReeseEvan_Reese Member Posts: 2,060 PRO
I'm trying to understand the opdraft command, and I am sure I'm missing something simple. Why doesn't this code work? If I comment out the opdraft command it works again.

I can extrude a body, and I've queried the side face of the cylinder, but I can't seem to apply draft. I also have been looking at the code of the Onshape draft feature, especially really early versions of it (which is so awesome to be able to do to see the simpler beginning), but I don't understand how it's getting the info it needs since all I see is.
opDraft(context, id, draftDefinition);
I'm betting this is pretty straight forward once I understand it. Any tips on how I could troubleshoot this myself next time?

Evan Reese / Principal and Industrial Designer with Ovyl
Website: ovyl.io

Best Answers

  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,646
    Answer ✓
    @Evan_Reese

    To shed a bit more light on this.  Just because you have already made a sketch, does not mean that a plane actually exists in the part studio.

    Imagine the following scenario:
    • I create a part with a planar face
    • I sketch a single vertex on that face of the part
    • I delete the part
    • I use your custom feature, and select the sketched vertex
    There are lots of other ways you could get into a state like this, but the point is, the piece of planar geometry that you sketched on does not necessarily still exist just because the sketch vertex exists.  So the choices you have in your feature are: create a piece of planar geometry using opPlane, or add another selection box asking the user to identify a neutral plane.

    In general, though, opDraft should have an option to take the mathematical description of a plane rather than a query for a plane.  I agree with you that the interface is a bit lacking here, and you really shouldn't have to make a plane and delete it to do the draft.


    The main reason I wanted to reply here is that there is some confusion surrounding "evaluated plane".  This could mean two things:
    • A "Plane" object, either returned by "evPlane(...)" or constructed by calling one of the "plane(...)" constructors.  This is the mathematical description of a plane.  It holds information about the origin, the normal, and the x direction of the plane.  No geometry needs to exist in the context to create this.  It is just a variable describing a theoretical mathematical plane.
    • An evaluated Query for a planar face.  A Query is just a set of instructions telling the system how to find a piece of geometry.  "qCreatedBy(makeId("Top"), EntityType.FACE)" is an instruction saying "find all the faces created by the id 'Top'".  If you call "evaluateQuery(...)" on this query, you will get back an array with one item in it.  This item is an "evaluated Query", but all that means is that it's a very specific query that refers specifically to the face of the top plane.  The type of query is a "transient Query" and it refers to the top face of the plane using the face's "transient Id".  These are called transient because they are very specific references to one specific piece of geometry whose id could change any time the geometry present in the system changes (hence transient Queries are not very reliable once the geometry starts changing).  The qCreatedBy and its corresponding evaluated Query are both valid inputs to opDraft.  Both describe the same face, and there is nothing special about the evaluated query except that it is a different, more specific way of describing the same face.  Queries do not need to be evaluated before they are used.
    In any case, the point I'm trying to make is that a better distinction is "Plane object" and "Query for a planar face" rather than confusing ourselves with what evaluation we are talking about (evPlane vs evaluateQuery) when we say "evaluated plane".

    Sorry for being long-winded :)
    Jake Rosenfeld - Modeling Team

Answers

  • Evan_ReeseEvan_Reese Member Posts: 2,060 PRO
    @jakeramsley
    Thanks! that does explain a lot. opDraft is looking for a query, and I'm feeding it an evaluated plane. I'm new to this, so i'll ask a possibly ignorant question. Is it right to think of the evaluated plane as an array with only one index?

    Also, when I plug in your snippet for the neutral plane, it does work, but I don't understand what that bit is doing. It seems like it's querying the world top plane? If so, it only works if I have my original sketch on the top plane, otherwise my draft neutral plane is wrong. I need to use the sketch plane of my input point. How can I get a query for that plane? See the issue below

    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • Evan_ReeseEvan_Reese Member Posts: 2,060 PRO
    @jakeramsley
    I made some progress by using opPlane to make a new plane to use for my neutral plane, then deleting it afterward. (see how the bases of each extrusion line up with the sketch that created it) is there a better way, though? that version is here

    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • MBartlett21MBartlett21 Member, OS Professional, Developers Posts: 2,034 EDU
    @jakeramsley
    Is there any way that opDraft could be set to use an already-evaluated plane?
    mb - draftsman - also FS author: View FeatureScripts
    IR for AS/NZS 1100
  • Evan_ReeseEvan_Reese Member Posts: 2,060 PRO
    @jakeramsley
    Is there any way that opDraft could be set to use an already-evaluated plane?
    lol thanks for rephrasing my rambling into a single sentence! :D This is what I want to know.
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • Evan_ReeseEvan_Reese Member Posts: 2,060 PRO
    edited November 2019
    I'd still love to know if I'm doing it a roundabout way or not if @jakeramsley
    or anyone has a few minutes to clear that up.

    Since my sketch plane is already evaluated and opDraft needs a query, I'm using opPlane to make a new plane query to call, then deleting it after. It feels extra.

    I think it's big deal for this feature since i'm only doing it one time, but if I had to move the opPlane inside my for loop (for some reason) then it could weigh it down if it's not efficient. I want to instill good practice from the beginning of my learning.
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • NeilCookeNeilCooke Moderator, Onshape Employees Posts: 5,310
    @Evan_Reese - currently this is the only way to do it (since opDraft is designed to work from user-selected physical geometry). Please use "contact support" to log an IR.
    Senior Director, Technical Services, EMEAI
  • Evan_ReeseEvan_Reese Member Posts: 2,060 PRO
    thanks @NeilCooke That's what I wanted to know. I'm going to keep on learning what's here before I start throwing IRs around. I've got a ways to go before I can tell the difference between my knowledge gaps and actual Featurescript limitations.
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,646
    Answer ✓
    @Evan_Reese

    To shed a bit more light on this.  Just because you have already made a sketch, does not mean that a plane actually exists in the part studio.

    Imagine the following scenario:
    • I create a part with a planar face
    • I sketch a single vertex on that face of the part
    • I delete the part
    • I use your custom feature, and select the sketched vertex
    There are lots of other ways you could get into a state like this, but the point is, the piece of planar geometry that you sketched on does not necessarily still exist just because the sketch vertex exists.  So the choices you have in your feature are: create a piece of planar geometry using opPlane, or add another selection box asking the user to identify a neutral plane.

    In general, though, opDraft should have an option to take the mathematical description of a plane rather than a query for a plane.  I agree with you that the interface is a bit lacking here, and you really shouldn't have to make a plane and delete it to do the draft.


    The main reason I wanted to reply here is that there is some confusion surrounding "evaluated plane".  This could mean two things:
    • A "Plane" object, either returned by "evPlane(...)" or constructed by calling one of the "plane(...)" constructors.  This is the mathematical description of a plane.  It holds information about the origin, the normal, and the x direction of the plane.  No geometry needs to exist in the context to create this.  It is just a variable describing a theoretical mathematical plane.
    • An evaluated Query for a planar face.  A Query is just a set of instructions telling the system how to find a piece of geometry.  "qCreatedBy(makeId("Top"), EntityType.FACE)" is an instruction saying "find all the faces created by the id 'Top'".  If you call "evaluateQuery(...)" on this query, you will get back an array with one item in it.  This item is an "evaluated Query", but all that means is that it's a very specific query that refers specifically to the face of the top plane.  The type of query is a "transient Query" and it refers to the top face of the plane using the face's "transient Id".  These are called transient because they are very specific references to one specific piece of geometry whose id could change any time the geometry present in the system changes (hence transient Queries are not very reliable once the geometry starts changing).  The qCreatedBy and its corresponding evaluated Query are both valid inputs to opDraft.  Both describe the same face, and there is nothing special about the evaluated query except that it is a different, more specific way of describing the same face.  Queries do not need to be evaluated before they are used.
    In any case, the point I'm trying to make is that a better distinction is "Plane object" and "Query for a planar face" rather than confusing ourselves with what evaluation we are talking about (evPlane vs evaluateQuery) when we say "evaluated plane".

    Sorry for being long-winded :)
    Jake Rosenfeld - Modeling Team
  • Evan_ReeseEvan_Reese Member Posts: 2,060 PRO
    @Jake_Rosenfeld
    In my opinion, there aren't enough long-winded people in the world (who are friendly and actually know what they are talking about, anyway). Thanks for the detail.

    Let me try to paraphrase back to see if I'm getting it.

    the "plane object" is just a few vectors to describe a plane with math, but it isn't actually a "real plane" like I'd get from the plane feature ("real plane" just to call it something). opDraft doesn't know what to do with the "plane object".

    On the other hand, a plane query points to an existing "real plane", and even the evaluated query pretty much just returns another mini-query (aka transient) pointing to the same "real plane" not the mathematical description of it like the "plane object".

    Am I close? if so, why can't I query [whatever the sketch is sketched on] and just use that query?
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • Jake_RosenfeldJake_Rosenfeld Moderator, Onshape Employees, Developers Posts: 1,646
    Sounds right to me @Evan_Reese

    The reason you can't query what planar face a sketch entity was sketched on has to do with the first part of my answer.  There wouldn't really be a point of us making some kind of sketch plane query because there may not be any "real plane" backing that sketch.  It may have been deleted, or it may not have ever existed in the first place (when sketching in FeatureScript, you can use a Plane object rather than a plane Query as the sketch plane).

    I can't see your feature because it is no longer public, but I thought of a couple things that you could actually do pretty easily to avoid calling opPlane:
    • Does the feature take the circular face as input?  Or does it take a vertex and sketch the circular face on its own?  In either case, you can pass in a query for the circular sketch face as the neutral plane.  After all, it is a planar face coincident with the sketch plane that you care about.  Whatever query you are passing into the "entities" field of the extrude will do fine as the "neutralPlane" of the draft.
    • You could query for the start cap of the extruded body, and use that as the neutral plane.  The query is qCapEntity(...).  This works for the same reason as the previous (it is a planar face coincident with the plane that you care about).  This is akin using the Draft feature through the UI and selecting a planar face of the body as the neutral plane, which would be a very normal thing to do.
    • You could use extrude(...) instead of opExtrude(...).  `extrude` is the actual extrude feature that is invoked when you press the extrude button through the UI.  So, it has all the bells and whistles of extrude built-in including the draft.  I don't really recommend this approach, as calling our features (extrude) is a lot more complicated than calling the operations that back the features (opExtrude), and comes with a lot more overhead.  But if you have a clear idea of what needs to happen and want it done in one fell swoop, you could try this.
    Hope that helps!
    Jake Rosenfeld - Modeling Team
  • Evan_ReeseEvan_Reese Member Posts: 2,060 PRO
    Sounds right to me @Evan_Reese

    The reason you can't query what planar face a sketch entity was sketched on has to do with the first part of my answer.  There wouldn't really be a point of us making some kind of sketch plane query because there may not be any "real plane" backing that sketch.  It may have been deleted, or it may not have ever existed in the first place (when sketching in FeatureScript, you can use a Plane object rather than a plane Query as the sketch plane).

    I can't see your feature because it is no longer public, but I thought of a couple things that you could actually do pretty easily to avoid calling opPlane:
    • Does the feature take the circular face as input?  Or does it take a vertex and sketch the circular face on its own?  In either case, you can pass in a query for the circular sketch face as the neutral plane.  After all, it is a planar face coincident with the sketch plane that you care about.  Whatever query you are passing into the "entities" field of the extrude will do fine as the "neutralPlane" of the draft.
    • You could query for the start cap of the extruded body, and use that as the neutral plane.  The query is qCapEntity(...).  This works for the same reason as the previous (it is a planar face coincident with the plane that you care about).  This is akin using the Draft feature through the UI and selecting a planar face of the body as the neutral plane, which would be a very normal thing to do.
    • You could use extrude(...) instead of opExtrude(...).  `extrude` is the actual extrude feature that is invoked when you press the extrude button through the UI.  So, it has all the bells and whistles of extrude built-in including the draft.  I don't really recommend this approach, as calling our features (extrude) is a lot more complicated than calling the operations that back the features (opExtrude), and comes with a lot more overhead.  But if you have a clear idea of what needs to happen and want it done in one fell swoop, you could try this.
    Hope that helps!
    Thanks, Jake. I see what you mean now about how the sketch actually may not have a "real plane" associated with it for a number of reasons, so I can't always query for it.

    I think the idea here that best fits my needs are to use the cap face, but that would break if I ever wanted to update the feature to take a custom pattern body as input. I'll leave it as-is for now since calling one opPlane and one opDeleteBodies isn't a slowdown.

    Btw, I just moved it all to a new public document so I could leave behind some of the other experimental feature studios and part studios that I want to keep, but aren't relevant for the actual feature. The new doc is here.
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 565
    @Evan_Reese You've got it. Vocab-wise, what you call a "real plane" is what we'd just call an "entity". The entities live in the Part Studio (inside that opaque variable called context) and are referred to with queries.

    The best explanation of this difference is probably in the second tutorial, where this note talks about queries for entities vs. geometric data.

    Everyone here is right that taking a raw Plane in opDraft would be helpful, but Evan you're also right that creating the plane and deleting should be a very small overhead. To check this you can always profile a Part Studio in the workspace.
  • Evan_ReeseEvan_Reese Member Posts: 2,060 PRO
    @kevin_o_toole_1
    Thanks, that's a helpful distinction. "entity" is the word I was looking for. Hopefully if I leave some breadcrumbs of my own personal lay-speak around someone else reading it that understands this stuff as little as I do can benefit  :D

    I'm always checking my model rebuild time, so now I get to enjoy doing the same for my custom features.
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
Sign In or Register to comment.