Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.
First time visiting? Here are some places to start:- Looking for a certain topic? Check out the categories filter or use Search (upper right).
- Need support? Ask a question to our Community Support category.
- Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
- 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.
Querying for the [other] part given two faces that touch each other? (with one face from each part)
Emily_Qi_Wang
Member Posts: 13 EDU
See situation below. The blue part and green part each have one face that touches the other. In my current Feature dialog, the user is prompted to choose the relatively small/skinny face of the blue part that happens to intersect the green part. I do not want to have to prompt the user to select the green part in the Feature dialog because typically the green part is hidden while this Feature is being used.
I would like to eventually do some boolean operations involving the green part. Without making extra assumptions about the corners or edges (this is a very simple case and not necessarily representative of how the edges/corners will look in other scenarios), can I query for the green part somehow given just the small blue face?
I combed through FsDoc and did not find a satisfying solution to this. I have attempted some strategies with qEdgeAdjacent, qTangentConnectedFaces, qFaceOrEdgeBoundedFaces, qIntersectsPlane, and qContainsPoint; all to varying levels of success and making additional assumptions. This seems like a simple query but I have not found a simple solution. I'm happy to supply more sample code for the queries above to explain them in more detail.
EDIT: Another idea that recently came to mind is querying for all the faces and finding which face is 0 meters away (maybe using evDistance?) from the known small blue face. However it seems like overkill to do a qEverything for all the faces, especially if there are many parts in the Part Studio.
Any suggestions on what to try next would be greatly appreciated. Thanks in advance!
I would like to eventually do some boolean operations involving the green part. Without making extra assumptions about the corners or edges (this is a very simple case and not necessarily representative of how the edges/corners will look in other scenarios), can I query for the green part somehow given just the small blue face?
I combed through FsDoc and did not find a satisfying solution to this. I have attempted some strategies with qEdgeAdjacent, qTangentConnectedFaces, qFaceOrEdgeBoundedFaces, qIntersectsPlane, and qContainsPoint; all to varying levels of success and making additional assumptions. This seems like a simple query but I have not found a simple solution. I'm happy to supply more sample code for the queries above to explain them in more detail.
EDIT: Another idea that recently came to mind is querying for all the faces and finding which face is 0 meters away (maybe using evDistance?) from the known small blue face. However it seems like overkill to do a qEverything for all the faces, especially if there are many parts in the Part Studio.
Any suggestions on what to try next would be greatly appreciated. Thanks in advance!
0
Best Answer
-
kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 565Two things: First, there are half-decent ways of getting the entity you want in this specific scenario, but second, the geometry in the general case may be unfriendly to this kind of search, so you may be better off not relying on the search succeeding.
To form the query:
evDistance is probably the best tool for the job. A good heuristic is probably to select the face closest to the center of the first face, like:const distanceResult is DistanceResult = evDistance(context, { "side0" : centerPoint, // Vector "side1" : qEverything(EntityType.FACE) }); const indexOfClosestEntity is number = distanceResult.sides[1].index; const closestFace is Query = qNthElement(subQuery, indexOfClosestEntity); // use immediately
Performance in this case would actually be pretty good – certainly faster than a FeatureScript loop checking each face, possibly comparable to a native query for, say, qClosestElement (which does not yet exist).
Or not to form the query:
While something like qCoplanarFaces might get made at some point, there are simple cases where that wouldn't return the right thing for this feature. What if that face curves off at the other end (e.g. isn't planar)? What if that face is offset slightly to allow room for glue? What if that part is actually four separate parts, all coplanar, all of which need to be cut?
To me there seem to be two separate things you might be using that face for:- Positioning new geometry:
If you're using the face to, say, position a sketch to make a cut in, that's starting to feel like fishing for redundant information (After all, there already exists a known, coplanar face). Rather than being dependent on a second geometric source of information to make your features (problematic if the sources disagree), why not define the second sketch in terms of the first? That is, make geometry based on positions in the coordinate system you already have.
Notably, you don't need a planar entity to create a sketch. You can just make a Plane data type, and use newSketchOnPlane() instead of newSketch(). - Defining which part to merge with:
If you're using the face to define which part you're adding to or subtracting from, you can look for a body rather than a face. For this, I'd take a look at what's done in an extrude feature in the ADD and REMOVE modes, where "merge with all" is a boolean, and if it's unchecked, the user populates the merge scope manually. Defaulting to "merge with all" seems like a pretty decent strategy for something like this.
5 - Positioning new geometry:
Answers
To form the query:
evDistance is probably the best tool for the job. A good heuristic is probably to select the face closest to the center of the first face, like:
Or not to form the query:
While something like qCoplanarFaces might get made at some point, there are simple cases where that wouldn't return the right thing for this feature. What if that face curves off at the other end (e.g. isn't planar)? What if that face is offset slightly to allow room for glue? What if that part is actually four separate parts, all coplanar, all of which need to be cut?
To me there seem to be two separate things you might be using that face for:
If you're using the face to, say, position a sketch to make a cut in, that's starting to feel like fishing for redundant information (After all, there already exists a known, coplanar face). Rather than being dependent on a second geometric source of information to make your features (problematic if the sources disagree), why not define the second sketch in terms of the first? That is, make geometry based on positions in the coordinate system you already have.
Notably, you don't need a planar entity to create a sketch. You can just make a Plane data type, and use newSketchOnPlane() instead of newSketch().
If you're using the face to define which part you're adding to or subtracting from, you can look for a body rather than a face. For this, I'd take a look at what's done in an extrude feature in the ADD and REMOVE modes, where "merge with all" is a boolean, and if it's unchecked, the user populates the merge scope manually. Defaulting to "merge with all" seems like a pretty decent strategy for something like this.