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.

Parameter space vs World space when using evFaceTangentPlane

mahirmahir Member, Developers Posts: 1,309 ✭✭✭✭✭
edited September 2016 in FeatureScript
I'd like to modify @jon_sorrells' Curve Pattern FS to accept a reference surface. The intention is to maintain the position of seed features/bodies/faces relative to the face normal at each incremental point along a curve. The problem is I don't see a way to generate a normal vector at any given point on a surface. 

evFaceTangentPlane will let me generate a tangent plane, which in turn would contain the desired normal vector. However, evFaceTangentPlane requires the point definition in some face-specific parameter space. I'm guessing this would correspond to a point's position relative to U-V lines, but that doesn't help me. How do I convert a 3D vector from World csys to a face's parameter space?

Another option is evFaceNormalAtEdge, but that only works on edges. I'd have to split the surface with the curve before this would work, and I don't think that's an option, nor should it be that complicated.

If neither of the above functions will do the trick, how else can I get a face normal at an arbitrary point on the surface?
Tagged:

Comments

  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,215
    You can use evDistance between the 3D point and the surface -- it will return a 2D vector in the face's parameter space that you can pass to evFaceTangentPlane.
    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • mahirmahir Member, Developers Posts: 1,309 ✭✭✭✭✭
    edited September 2016
    Thanks @ilya_baran. I'll give it a try. Not super intuitive, though. So, assuming the face is side0 and the point is side1, what I'll need to feed into evFaceTangentPlane is DistanceResult.sides[0].parameter, right?


  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,215
    Yes, that's exactly right -- that's why the doc says it's "in the form that evFaceTangentPlane consumes."
    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • jon_sorrellsjon_sorrells Onshape Employees Posts: 51
    The Curve Pattern feature does a sweep along the path, and maintains the normal of the entities relative to the swept faces.
    If I understand correctly what you're trying to do, you should be able to just replace this part of the code
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // sweep along the path<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var sketch1 = newSketchOnPlane(context, id + "sketch", {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "sketchPlane" : plane(tangentLines[0].origin, tangentLines[0].direction)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const sweepSize is number = 0.01;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; skRectangle(sketch1, "rectangle1", {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "firstCorner" : vector(-sweepSize / 2, sweepSize) * inch,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "secondCorner" : vector(sweepSize / 2, 0) * inch<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; skSolve(sketch1);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; opSweep(context, id + "sweep1", {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "profiles" : qSketchRegion(id + "sketch", true),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "path" : definition.edges<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // query for the faces along the sweep<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var normalFaces is Query = qCreatedBy(id + "sweep1", EntityType.FACE);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; normalFaces = qSubtraction(normalFaces, qUnion([qCapEntity(id + "sweep1", true), qCapEntity(id + "sweep1", false)]));
    by setting normalFaces to a query for the surface that you want.  The code after that part will find the normal at the point closest to the curve
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var distanceResult is DistanceResult = evDistance(context, { "side0" : normalFaces, "side1" : tangentLine.origin });<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var index = distanceResult.sides[0].index;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var parameter = distanceResult.sides[0].parameter;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var tangentPlane is Plane = evFaceTangentPlane(context, {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "face" : qNthElement(normalFaces, index),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "parameter" : parameter<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });


  • mahirmahir Member, Developers Posts: 1,309 ✭✭✭✭✭
    edited October 2016
    Oops, I lied. Almost there though. Looks like there's something trippy going on with the first instance. @jon_sorrels@ilya_baran, can you guys catch why it's offsetting the first instance like that?

  • jon_sorrellsjon_sorrells Onshape Employees Posts: 51
    My code assumed that the face to make normal to would be touching the curve.  In your case, the curve is not touching the face at the point of the first instance (because there's already a hole there).  It uses the closest point on the surface to calculate the position and normal.  In this case, it chose directly below the hole as the closest point on the face.  That's why the first instance is shifted down.

    One way to get around this is to delete the faces from the hole, in between the hole feature and the curve pattern feature.  That way, when the curve pattern happens, there won't be a hole in the surface, so the first instance should end up in the right place.  I made a copy of your document and did that here: https://cad.onshape.com/documents/57ef1b8d93832a1090984d9f/w/1aa65960dbddcf3503587d2a/e/74b4e22402bc5136ec57fef2

    If you're often going to run into situations like this, you could add an option to the custom feature to skip the first instance.

  • mahirmahir Member, Developers Posts: 1,309 ✭✭✭✭✭
    edited October 2016
    Thanks. That worked. The FS isn't perfect though. In the case of a hole feature on a tangent plane, the transformed tangent planes are off just enough to create artifact surfaces. This can be alleviated by starting the first hole on a surface that is slightly offset from the surface, but it's still a shortcoming in precision.
Sign In or Register to comment.