mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Fix #4638. You can now filter by parent (in the spatial hierarchy)
This commit is contained in:
@@ -304,6 +304,9 @@ def draw_filter(layout, filter_groups, data, module):
|
||||
elif ifc_filter.type == "group":
|
||||
row = box.row(align=True)
|
||||
row.prop(ifc_filter, "value", text="", icon="OUTLINER_COLLECTION")
|
||||
elif ifc_filter.type == "parent":
|
||||
row = box.row(align=True)
|
||||
row.prop(ifc_filter, "value", text="", icon="FILE_PARENT")
|
||||
elif ifc_filter.type == "query":
|
||||
row = box.row(align=True)
|
||||
row.prop(ifc_filter, "name", text="", icon="POINTCLOUD_DATA")
|
||||
|
||||
@@ -118,8 +118,9 @@ class BIMSearchProperties(PropertyGroup):
|
||||
("location", "Location", "", "PACKAGE", 5),
|
||||
("type", "Type", "", "FILE_VOLUME", 6),
|
||||
("group", "Group", "", "OUTLINER_COLLECTION", 7),
|
||||
("query", "Query", "", "POINTCLOUD_DATA", 8),
|
||||
("instance", "GlobalId", "", "GRIP", 9),
|
||||
("parent", "Parent", "", "FILE_PARENT", 8),
|
||||
("query", "Query", "", "POINTCLOUD_DATA", 9),
|
||||
("instance", "GlobalId", "", "GRIP", 10),
|
||||
],
|
||||
)
|
||||
saved_searches: EnumProperty(items=get_saved_searches, name="Saved Searches")
|
||||
|
||||
@@ -86,6 +86,9 @@ class Search(blenderbim.core.tool.Search):
|
||||
elif ifc_filter.type == "group":
|
||||
comparison, value = cls.get_comparison_and_value(ifc_filter)
|
||||
filter_group_query.append(f"group{comparison}{value}")
|
||||
elif ifc_filter.type == "parent":
|
||||
comparison, value = cls.get_comparison_and_value(ifc_filter)
|
||||
filter_group_query.append(f"parent{comparison}{value}")
|
||||
elif ifc_filter.type == "query":
|
||||
keys = cls.wrap_value(ifc_filter, ifc_filter.name)
|
||||
comparison, value = cls.get_comparison_and_value(ifc_filter)
|
||||
@@ -201,6 +204,10 @@ class ImportFilterQueryTransformer(lark.Transformer):
|
||||
comparison, value = args
|
||||
return {"type": "group", "value": f"{comparison}{value}"}
|
||||
|
||||
def parent(self, args):
|
||||
comparison, value = args
|
||||
return {"type": "parent", "value": f"{comparison}{value}"}
|
||||
|
||||
def query(self, args):
|
||||
keys, comparison, value = args
|
||||
return {"type": "query", "name": keys, "value": f"{comparison}{value}"}
|
||||
|
||||
@@ -39,7 +39,7 @@ filter_elements_grammar = lark.Lark(
|
||||
filter_group: facet_list ("+" facet_list)*
|
||||
facet_list: facet ("," facet)*
|
||||
|
||||
facet: instance | entity | attribute | type | material | query | classification | location | property | group
|
||||
facet: instance | entity | attribute | type | material | query | classification | location | property | group | parent
|
||||
|
||||
instance: not? globalid
|
||||
globalid: /[0-3][a-zA-Z0-9_$]{21}/
|
||||
@@ -51,6 +51,7 @@ filter_elements_grammar = lark.Lark(
|
||||
classification: "classification" comparison value
|
||||
location: "location" comparison value
|
||||
group: "group" comparison value
|
||||
parent: "parent" comparison value
|
||||
query: "query:" keys comparison value
|
||||
|
||||
pset: quoted_string | regex_string | unquoted_string
|
||||
@@ -681,6 +682,25 @@ class FacetTransformer(lark.Transformer):
|
||||
|
||||
self.elements = set(filter(filter_function, self.elements))
|
||||
|
||||
def parent(self, args):
|
||||
comparison, value = args
|
||||
|
||||
def filter_function(element):
|
||||
parents = []
|
||||
result = False
|
||||
if parent := ifcopenshell.util.element.get_parent(element):
|
||||
parents.append(parent)
|
||||
while parents:
|
||||
parent = parents.pop()
|
||||
if self.compare(parent.Name, comparison, value):
|
||||
result = True
|
||||
break
|
||||
if grandparent := ifcopenshell.util.element.get_parent(parent):
|
||||
parents.append(grandparent)
|
||||
return result if comparison == "=" else not result
|
||||
|
||||
self.elements = set(filter(filter_function, self.elements))
|
||||
|
||||
def query(self, args):
|
||||
keys, comparison, value = args
|
||||
|
||||
|
||||
@@ -266,6 +266,25 @@ class TestFilterElements(test.bootstrap.IFC4):
|
||||
assert subject.filter_elements(self.file, "IfcWall, group=Foo") == {element}
|
||||
assert subject.filter_elements(self.file, "IfcWall, group!=Foo") == {element2}
|
||||
|
||||
def test_selecting_by_parent(self):
|
||||
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall", name="Element1")
|
||||
element2 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall", name="Element2")
|
||||
element3 = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall", name="Element3")
|
||||
space = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcSpace", name="Space")
|
||||
storey = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuildingStorey", name="G")
|
||||
building = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcBuilding", name="Building")
|
||||
project = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcProject", name="Project")
|
||||
ifcopenshell.api.run("spatial.assign_container", self.file, products=[element], relating_structure=space)
|
||||
ifcopenshell.api.run("spatial.assign_container", self.file, products=[element2], relating_structure=storey)
|
||||
ifcopenshell.api.run("aggregate.assign_object", self.file, products=[element3], relating_object=element2)
|
||||
ifcopenshell.api.run("aggregate.assign_object", self.file, products=[space], relating_object=storey)
|
||||
ifcopenshell.api.run("aggregate.assign_object", self.file, products=[storey], relating_object=building)
|
||||
ifcopenshell.api.run("aggregate.assign_object", self.file, products=[building], relating_object=project)
|
||||
assert subject.filter_elements(self.file, "IfcWall, parent=Project") == {element, element2, element3}
|
||||
assert subject.filter_elements(self.file, "IfcWall, parent=Space") == {element}
|
||||
assert subject.filter_elements(self.file, "IfcWall, parent=G") == {element, element2, element3}
|
||||
assert subject.filter_elements(self.file, "IfcWall, parent=Element2") == {element3}
|
||||
|
||||
def test_selecting_multiple_filter_groups(self):
|
||||
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
|
||||
element.Name = "Foo"
|
||||
|
||||
Reference in New Issue
Block a user