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.
An implementation for qQueryCompoundFilter
MBartlett21
Member, OS Professional, Developers Posts: 2,064 ✭✭✭✭✭
I have always been annoyed by the lack of a filtering mechanism for
Please see the code below (It also requires
Query operators:
PS: The idea of using
QueryCompoundFilters, so I decided to build my own function to do the job.Please see the code below (It also requires
Query operators, an implementation of which can be found below that code)export function qQueryCompoundFilter(q is Query, filter is QueryFilterCompound) returns Query
{
return q * qUnion(switch (filter) {
(QueryFilterCompound.ALLOWS_AXIS) : [
qGeometry(q, GeometryType.LINE),
qGeometry(q, GeometryType.CIRCLE),
qGeometry(q, GeometryType.ARC),
qGeometry(q, GeometryType.CYLINDER),
qBodyType(q, BodyType.MATE_CONNECTOR)
],
(QueryFilterCompound.ALLOWS_DIRECTION) : [
qGeometry(q, GeometryType.LINE),
qGeometry(q, GeometryType.CIRCLE),
qGeometry(q, GeometryType.ARC),
qGeometry(q, GeometryType.PLANE),
qGeometry(q, GeometryType.CYLINDER),
qBodyType(q, BodyType.MATE_CONNECTOR)
],
(QueryFilterCompound.ALLOWS_PLANE) : [
qGeometry(q, GeometryType.PLANE),
qBodyType(q, BodyType.MATE_CONNECTOR)
],
(QueryFilterCompound.ALLOWS_VERTEX) : [
qEntityFilter(q, EntityType.VERTEX),
qBodyType(q, BodyType.MATE_CONNECTOR)
]
});
}Query operators:
// Actually, the + (Union) and - (Subtraction) operators are not needed for this feature, only the * (intersection). I just included them for completeness
export operator+(lhs is Query, rhs is Query) returns Query
{
if (lhs.queryType == QueryType.UNION)
{
lhs.subqueries = @resize(lhs.subqueries, @size(lhs.subqueries) + 1, rhs);
return lhs;
}
return qUnion([lhs, rhs]);
}
export operator-(lhs is Query, rhs is Query) returns Query
{
return qSubtraction(lhs, rhs);
}
export operator*(lhs is Query, rhs is Query) returns Query
{
if (lhs.queryType == QueryType.INTERSECTION)
{
lhs.subqueries = @resize(lhs.subqueries, @size(lhs.subqueries) + 1, rhs);
return lhs;
}
return qIntersection([lhs, rhs]);
}PS: The idea of using
Query operators stemmed from this discussion. As an example of their use, see my Australian Beams feature here, where they are used quite a lot. For instance, instead of making a Query by populating an array then using qUnion, I can just start off with qNothing() and then use query += stuff; 2
Comments
-
This looks very nice! I think it would help to see some example queries with your additions. I have resisted adding these operators to std so far, but if people feel writing queries that way is more intuitive, I may reconsider.
Why do you have theq *
in your qQueryCompoundFilter function? All of your subqueries in the qUnion filter q.Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc0 -
Great stuff @MBartlett21 . Solutions like this definitely ease the pain of writing queries, though we've yet to find the perfect one to include in the standard library.
In this case, using qIntersection more commonly is probably going to have performance implications. A qIntersection works by first evaluating both inputs, in their entirety, and then finding common entities. If the two queries are both filters of the same root query, then you save some work by replacing the slowqIntersection(qEntityFilter(q, EntityType.BODY), qBodyType(q, BodyType.SOLID))
with the fasterqBodyType(qEntityFilter(q, EntityType.BODY), BodyType.SOLID)
Even if qIntersection() itself were free to evaluate, the second query will be faster. The difference is: qBodyType in the latter is only filtering through the bodies, while qBodyType in the former it's filtering through all entities. The cost of this evaluation won't show up in your * code itself, but later, when that query needs to be evaluated (either directly with evaluateQuery(myQuery) or indirectly with e.g. opExtrude(... myQuery ...)). I don't see a great way of keeping the * syntax convenient while keeping the resulting queries fast (but that fact makes me like the -> syntax from the post you linked even more
).
0 -
kevin_o_toole_1 said:I don't see a great way of keeping the * syntax convenient while keeping the resulting queries fast (but that fact makes me like the -> syntax from the post you linked even more
).I you add a compact inline lambda syntax it would almost solve this problem. We would just unwrap nested construction into a sequence of functions. And this would be helpful for not only queries.One of the alternatives to the arrow syntax is an approach from Wolfram Language: they use f(#1,#2, ...)& for inline lambda definition.
0 -
@ilya_baranilya_baran said:This looks very nice! I think it would help to see some example queries with your additions. I have resisted adding these operators to std so far, but if people feel writing queries that way is more intuitive, I may reconsider.
Why do you have theq *
in your qQueryCompoundFilter function? All of your subqueries in the qUnion filter q.
The reason I have it in there is so that the Query evaluates in the proper order (see the documentation for qIntersection - "qIntersection preserves the order of the first subquery")
EDIT: Fixed @mention0 -
Also, another filter that we don't have an implementation for is SheetMetalDefinitionEntityType.
Currently, to filter by that, we need to get the internal body, then filter by an EntityType, then get the entities in the part.0



