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.

Featurescript: Select all outer faces adjacent to a seed face

mahirmahir Member, Developers Posts: 862 ✭✭✭✭
edited July 2016 in FeatureScript
I've tried all sorts of variations of qLoopBoundedFaces, qFaceOrEdgeBoundedFaces, and qEdgeAdjacent... no cigar. For example, given the start face of an extruded ring, what combination of queries will retrieve the cylindrical outer surface? It seems whatever I try ends up with all the surfaces of the extrusion. This would would extend to the 4 outer surfaces of an extruded square channel and so on.Below is the closest I've gotten so far. I'm not sure what edge I'm selecting either. I guess that's another question worth answering. How to select the outer boundary of a face? Thanks for the help.

        var outerFaces = 
        qFaceOrEdgeBoundedFaces(
            qUnion([
                qEntityFilter(qCapEntity(id + "extrude1", true), EntityType.FACE),
                qNthElement(qCreatedBy(id + "extrude1", EntityType.EDGE), 0)
            ])
        );

or

        var outerFaces = 
        qLoopBoundedFaces(
            qUnion([
                qEntityFilter(qCapEntity(id + "extrude1", true), EntityType.FACE),
                qNthElement(qCreatedBy(id + "extrude1", EntityType.EDGE), 0)
            ])
        );

Comments

  • lemon1324lemon1324 Member, Developers Posts: 167 EDU
    I'm working on an equivalent problem to find all bounding edges of a face, not including edges bounding internal holes.  Note that the "Convert/Use" sketch tool does this, but the source for that isn't in the public FeatureScript source, probably because the interactive sketch definition is not quite FeatureScript. 

    As far as I've been able to determine, to find the outer loop you need to actually partition all adjacent edges/faces to the selected face and then go through the connected components and figure out which is the outside one.  Intuitively, you could probably get the bounding box of each connected component and look for the largest, and that's your outer loop (this is almost definitely not the most efficient way).
    Arul Suresh
    PhD Candidate at Stanford University
  • mahirmahir Member, Developers Posts: 862 ✭✭✭✭
    Yeah, I've looped through a few different methods, and nothing seems very efficient or robust. Outer faces/edges aren't necessarily larger than inner ones. I've thought about using surface normals relative to the surface centroid but can't wrap my head around how to implement it. I've thought about checking for convexity, but outer boundary isn't necessarily convex.

    I haven't implemented it yet, but I've thought about creating a more useful version of qLoopBoundedFaces that will at least let you toggle between inner/outer bounding surfaces, even if I can't figure out which is which without visual feedback. It would start with qEdgeAdjacent(face, EntityType.FACE), then select the first face and get all connected non-seed faces that were in the original query. If that doesn't work, change it to start from the last face instead.

    Any input from OnShape?
  • lemon1324lemon1324 Member, Developers Posts: 167 EDU
    Yes, the faces themselves aren't necessarily larger, but the bounding box of the union of all faces that form the outer loop has to be bigger in the plane than that of any single inner loop, simply by geometry--otherwise it wouldn't be the outer loop.  In your cylinder case, this boils down to "The bounding box of the outer cylindrical face has to be larger than the bounding box of the inner cylinder face in the plane of the start ring face."
    Arul Suresh
    PhD Candidate at Stanford University
  • mahirmahir Member, Developers Posts: 862 ✭✭✭✭
    Ah, gotcha. I was going to evaluate the surface area, but bounding box seems more efficient.
  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 449
    If you're the one making the original extrude sketch in FeatureScript, one way to get a robust reference would be to use sketchEntityQuery. The arguments needed are:
    1. The Id of the original sketch
    2. EntityType.FACE
    3. The sketch id of the edge extruded to that face

    Once you have one of the outer faces, you can either get the rest the same way (as a qUnion of a bunch of sketchEntityQueries), or use qFaceOrEdgeBoundedFaces, with the input being as a qUnion of:
    1. The seed face above
    2. The extrude's end cap face
    3. The extrude's start cap face
    None of this is specific to the "outside", it's just a robust way of referencing geometry you've created from an underlying sketch. With this method you can specify any contiguous loop of faces on the extrude using different sketch ids.

  • mahirmahir Member, Developers Posts: 862 ✭✭✭✭
    edited July 2016
    I think I got it working as desired. I ended up using @lemon1324's box3d method in conjunction with iterating seed faces through qFaceOrEdgeBoundedFaces. I also got it working by measuring surface area, but in theory that could yield incorrect results if the inner boundary happened to have more surface area. Thanks for the help.

            var flangeStart = qEntityFilter(qCapEntity(id + "flange", true), EntityType.FACE);
            var flangeEnd = qEntityFilter(qCapEntity(id + "flange", false), EntityType.FACE);
            var flangeCaps = qUnion([flangeStart, flangeEnd]);
            var adjFaces = qEdgeAdjacent(flangeStart, EntityType.FACE);
            var moveFaces;
            
            //Iterate over faces adjacent to flange start face to find the set of outer boundary faces
            var maxSize = 0;
            for (var tSeedFace in evaluateQuery(context, adjFaces) )
            {
                var tMoveFaces = qFaceOrEdgeBoundedFaces(qUnion([tSeedFace, flangeCaps]));
                var tBB = evBox3d(context, {"topology" : tMoveFaces});
                var tMaxSize = evDistance(context, {
                        "side0" : tBB.minCorner,
                        "side1" : tBB.maxCorner
                }).distance;
                
                if (tMaxSize > maxSize)
                {
                    maxSize = tMaxSize;
                    moveFaces = tMoveFaces;
                }
            }
       
  • lemon1324lemon1324 Member, Developers Posts: 167 EDU
    If you're the one making the original extrude sketch in FeatureScript ...
    Thanks for the pointer, that's a good way to find the loops I hadn't thought of.  I don't know about @mahir_abrahim, but I'm specifically looking to do this on geometry that I didn't create and on which I assume little apart from a planar part, so his solution seems like it'll work.
    Arul Suresh
    PhD Candidate at Stanford University
Sign In or Register to comment.