mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 22:50:21 +00:00
IFCCSV now supports queries for inverse spatial or type relationships
This commit is contained in:
+33
-6
@@ -17,7 +17,7 @@ class IfcSelectorParser():
|
|||||||
l = lark.Lark('''start: query (lfunction query)*
|
l = lark.Lark('''start: query (lfunction query)*
|
||||||
query: selector | group
|
query: selector | group
|
||||||
group: "(" query (lfunction query)* ")"
|
group: "(" query (lfunction query)* ")"
|
||||||
selector: guid_selector | class_selector
|
selector: (inverse_relationship)? guid_selector | (inverse_relationship)? class_selector
|
||||||
guid_selector: "#" /[0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$]{22}/
|
guid_selector: "#" /[0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$]{22}/
|
||||||
class_selector: "." WORD filter ?
|
class_selector: "." WORD filter ?
|
||||||
filter: "[" filter_key (comparison filter_value)? "]"
|
filter: "[" filter_key (comparison filter_value)? "]"
|
||||||
@@ -25,6 +25,9 @@ class IfcSelectorParser():
|
|||||||
filter_value: ESCAPED_STRING
|
filter_value: ESCAPED_STRING
|
||||||
pset_or_qto: /[A-Za-z0-9_]+/ "." /[A-Za-z0-9_]+/
|
pset_or_qto: /[A-Za-z0-9_]+/ "." /[A-Za-z0-9_]+/
|
||||||
lfunction: and | or
|
lfunction: and | or
|
||||||
|
inverse_relationship: types | contains_elements
|
||||||
|
types: "*"
|
||||||
|
contains_elements: "@"
|
||||||
and: "&"
|
and: "&"
|
||||||
or: "|"
|
or: "|"
|
||||||
comparison: contains | morethanequalto | lessthanequalto | equal | morethan | lessthan
|
comparison: contains | morethanequalto | lessthanequalto | equal | morethan | lessthan
|
||||||
@@ -90,11 +93,35 @@ class IfcSelectorParser():
|
|||||||
return self.get_group(child)
|
return self.get_group(child)
|
||||||
|
|
||||||
def get_selector(self, selector):
|
def get_selector(self, selector):
|
||||||
for child in selector.children:
|
if len(selector.children) == 1:
|
||||||
if child.data == 'class_selector':
|
inverse_relationship = None
|
||||||
return self.get_class_selector(child)
|
class_or_guid_selector = selector.children[0]
|
||||||
elif child.data == 'guid_selector':
|
else:
|
||||||
return self.get_guid_selector(child)
|
inverse_relationship = selector.children[0]
|
||||||
|
class_or_guid_selector = selector.children[1]
|
||||||
|
|
||||||
|
if class_or_guid_selector.data == 'class_selector':
|
||||||
|
results = self.get_class_selector(class_or_guid_selector)
|
||||||
|
elif class_or_guid_selector.data == 'guid_selector':
|
||||||
|
results = self.get_guid_selector(class_or_guid_selector)
|
||||||
|
|
||||||
|
if not inverse_relationship:
|
||||||
|
return results
|
||||||
|
return self.parse_inverse_relationship(results, inverse_relationship.children[0].data)
|
||||||
|
|
||||||
|
def parse_inverse_relationship(self, elements, inverse_relationship):
|
||||||
|
results = []
|
||||||
|
for element in elements:
|
||||||
|
if inverse_relationship == 'types':
|
||||||
|
if hasattr(element, 'Types') and element.Types:
|
||||||
|
results.extend(element.Types[0].RelatedObjects)
|
||||||
|
elif hasattr(element, 'ObjectTypeOf') and element.ObjectTypeOf:
|
||||||
|
results.extend(element.ObjectTypeOf[0].RelatedObjects)
|
||||||
|
elif inverse_relationship == 'contains_elements' \
|
||||||
|
and hasattr(element, 'ContainsElements'):
|
||||||
|
for relationship in element.ContainsElements:
|
||||||
|
results.extend(relationship.RelatedElements)
|
||||||
|
return results
|
||||||
|
|
||||||
def get_class_selector(self, class_selector):
|
def get_class_selector(self, class_selector):
|
||||||
elements = self.file.by_type(class_selector.children[0])
|
elements = self.file.by_type(class_selector.children[0])
|
||||||
|
|||||||
Reference in New Issue
Block a user