mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
You can now filter and search in the spatial decomposition panel
This commit is contained in:
@@ -249,8 +249,6 @@ class SelectDecomposedElements(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
should_filter: bpy.props.BoolProperty(name="Should Filter", default=True, options={"SKIP_SAVE"})
|
should_filter: bpy.props.BoolProperty(name="Should Filter", default=True, options={"SKIP_SAVE"})
|
||||||
container: bpy.props.IntProperty()
|
container: bpy.props.IntProperty()
|
||||||
ifc_class: bpy.props.StringProperty()
|
|
||||||
relating_type: bpy.props.IntProperty()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def description(cls, context, operator):
|
def description(cls, context, operator):
|
||||||
@@ -262,20 +260,25 @@ class SelectDecomposedElements(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
return self.execute(context)
|
return self.execute(context)
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
|
ifc_class = relating_type = is_untyped = None
|
||||||
if self.should_filter:
|
if self.should_filter:
|
||||||
ifc_class = self.ifc_class
|
active_element = context.scene.BIMSpatialDecompositionProperties.active_element
|
||||||
relating_type = tool.Ifc.get().by_id(self.relating_type) if self.relating_type else None
|
if active_element.is_class:
|
||||||
is_untyped = self.relating_type == 0
|
ifc_class = active_element.name
|
||||||
else:
|
elif relating_type := active_element.ifc_definition_id:
|
||||||
ifc_class = ""
|
ifc_class = active_element.ifc_class
|
||||||
relating_type = None
|
relating_type = tool.Ifc.get().by_id(relating_type)
|
||||||
is_untyped = False
|
else:
|
||||||
|
ifc_class = active_element.ifc_class
|
||||||
|
is_untyped = True
|
||||||
|
element_filter = context.scene.BIMSpatialDecompositionProperties.element_filter
|
||||||
core.select_decomposed_elements(
|
core.select_decomposed_elements(
|
||||||
tool.Spatial,
|
tool.Spatial,
|
||||||
container=tool.Ifc.get().by_id(self.container),
|
container=tool.Ifc.get().by_id(self.container),
|
||||||
ifc_class=ifc_class,
|
ifc_class=ifc_class,
|
||||||
relating_type=relating_type,
|
relating_type=relating_type,
|
||||||
is_untyped=is_untyped,
|
is_untyped=is_untyped,
|
||||||
|
element_filter = element_filter
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ class BIMContainer(PropertyGroup):
|
|||||||
|
|
||||||
class Element(PropertyGroup):
|
class Element(PropertyGroup):
|
||||||
name: StringProperty(name="Name")
|
name: StringProperty(name="Name")
|
||||||
|
ifc_class: StringProperty(name="Name")
|
||||||
is_class: BoolProperty(name="Is Class", default=False)
|
is_class: BoolProperty(name="Is Class", default=False)
|
||||||
is_type: BoolProperty(name="Is Type", default=False)
|
is_type: BoolProperty(name="Is Type", default=False)
|
||||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||||
@@ -118,6 +119,7 @@ class BIMSpatialDecompositionProperties(PropertyGroup):
|
|||||||
contracted_containers: StringProperty(name="Contracted containers", default="[]")
|
contracted_containers: StringProperty(name="Contracted containers", default="[]")
|
||||||
expanded_containers: StringProperty(name="Expanded containers", default="[]")
|
expanded_containers: StringProperty(name="Expanded containers", default="[]")
|
||||||
active_container_index: IntProperty(name="Active Container Index", update=update_active_container_index)
|
active_container_index: IntProperty(name="Active Container Index", update=update_active_container_index)
|
||||||
|
element_filter: StringProperty(name="Element Filter", default="", options={"TEXTEDIT_UPDATE"})
|
||||||
elements: CollectionProperty(name="Elements", type=Element)
|
elements: CollectionProperty(name="Elements", type=Element)
|
||||||
active_element_index: IntProperty(name="Active Element Index")
|
active_element_index: IntProperty(name="Active Element Index")
|
||||||
total_elements: IntProperty(name="Total Elements")
|
total_elements: IntProperty(name="Total Elements")
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import bpy
|
||||||
from bpy.types import Panel, UIList
|
from bpy.types import Panel, UIList
|
||||||
from bonsai.bim.module.spatial.data import SpatialData, SpatialDecompositionData
|
from bonsai.bim.module.spatial.data import SpatialData, SpatialDecompositionData
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
@@ -169,12 +170,6 @@ class BIM_PT_spatial_decomposition(Panel):
|
|||||||
)
|
)
|
||||||
row.prop(self.props, "should_include_children", text="", icon="OUTLINER")
|
row.prop(self.props, "should_include_children", text="", icon="OUTLINER")
|
||||||
op = row.operator("bim.select_decomposed_elements", icon="RESTRICT_SELECT_OFF", text="")
|
op = row.operator("bim.select_decomposed_elements", icon="RESTRICT_SELECT_OFF", text="")
|
||||||
if self.props.active_element.is_class:
|
|
||||||
op.ifc_class = self.props.active_element.name
|
|
||||||
op.relating_type = 0
|
|
||||||
elif self.props.active_element.is_type:
|
|
||||||
op.ifc_class = ""
|
|
||||||
op.relating_type = self.props.active_element.ifc_definition_id
|
|
||||||
op.container = ifc_definition_id
|
op.container = ifc_definition_id
|
||||||
|
|
||||||
self.layout.template_list(
|
self.layout.template_list(
|
||||||
@@ -184,6 +179,7 @@ class BIM_PT_spatial_decomposition(Panel):
|
|||||||
"elements",
|
"elements",
|
||||||
self.props,
|
self.props,
|
||||||
"active_element_index",
|
"active_element_index",
|
||||||
|
sort_lock=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -229,6 +225,9 @@ class BIM_UL_containers_manager(UIList):
|
|||||||
|
|
||||||
|
|
||||||
class BIM_UL_elements(UIList):
|
class BIM_UL_elements(UIList):
|
||||||
|
def __init__(self):
|
||||||
|
self.use_filter_show = True
|
||||||
|
|
||||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||||
if item:
|
if item:
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
@@ -244,3 +243,16 @@ class BIM_UL_elements(UIList):
|
|||||||
col = row.column()
|
col = row.column()
|
||||||
col.alignment = "RIGHT"
|
col.alignment = "RIGHT"
|
||||||
col.label(text=str(item.total))
|
col.label(text=str(item.total))
|
||||||
|
|
||||||
|
def draw_filter(self, context, layout):
|
||||||
|
row = layout.row()
|
||||||
|
row.prop(context.scene.BIMSpatialDecompositionProperties, "element_filter", text="", icon="VIEWZOOM")
|
||||||
|
|
||||||
|
def filter_items(self, context, data, propname):
|
||||||
|
items = getattr(data, propname)
|
||||||
|
filter_name = context.scene.BIMSpatialDecompositionProperties.element_filter
|
||||||
|
filtered = bpy.types.UI_UL_list.filter_items_by_name(filter_name, self.bitflag_filter_item, items, "name")
|
||||||
|
return filtered, []
|
||||||
|
|
||||||
|
def get_filter_name(self):
|
||||||
|
return self.filter_name
|
||||||
|
|||||||
@@ -147,14 +147,10 @@ def select_decomposed_elements(
|
|||||||
ifc_class: str | None = None,
|
ifc_class: str | None = None,
|
||||||
relating_type: ifcopenshell.entity_instance | None = None,
|
relating_type: ifcopenshell.entity_instance | None = None,
|
||||||
is_untyped: bool = False,
|
is_untyped: bool = False,
|
||||||
|
element_filter: str | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
elements = spatial.get_decomposed_elements(container)
|
elements = spatial.get_decomposed_elements(container)
|
||||||
if ifc_class:
|
elements = spatial.filter_elements(elements, ifc_class, relating_type, is_untyped, element_filter)
|
||||||
elements = spatial.filter_elements_by_class(elements, ifc_class)
|
|
||||||
elif relating_type:
|
|
||||||
elements = spatial.filter_elements_by_relating_type(elements, relating_type)
|
|
||||||
elif is_untyped:
|
|
||||||
elements = spatial.filter_elements_by_untyped(elements)
|
|
||||||
spatial.select_products(elements)
|
spatial.select_products(elements)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -233,6 +233,7 @@ class Spatial(bonsai.core.tool.Spatial):
|
|||||||
new2 = props.elements.add()
|
new2 = props.elements.add()
|
||||||
new2.is_type = True
|
new2.is_type = True
|
||||||
new2.name = results[ifc_class][ifc_definition_id]["type_name"]
|
new2.name = results[ifc_class][ifc_definition_id]["type_name"]
|
||||||
|
new2.ifc_class = ifc_class
|
||||||
new2.total = results[ifc_class][ifc_definition_id]["total"]
|
new2.total = results[ifc_class][ifc_definition_id]["total"]
|
||||||
new2.ifc_definition_id = ifc_definition_id
|
new2.ifc_definition_id = ifc_definition_id
|
||||||
total += new2.total
|
total += new2.total
|
||||||
@@ -242,18 +243,32 @@ class Spatial(bonsai.core.tool.Spatial):
|
|||||||
props.total_elements = total_elements
|
props.total_elements = total_elements
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def filter_elements_by_class(cls, elements: List[ifcopenshell.entity_instance], ifc_class: str):
|
def filter_elements(
|
||||||
return [e for e in elements if e.is_a(ifc_class)]
|
cls,
|
||||||
|
elements: List[ifcopenshell.entity_instance],
|
||||||
@classmethod
|
ifc_class: str | None,
|
||||||
def filter_elements_by_relating_type(
|
relating_type: ifcopenshell.entity_instance | None,
|
||||||
cls, elements: List[ifcopenshell.entity_instance], relating_type: ifcopenshell.entity_instance
|
is_untyped: bool | None,
|
||||||
):
|
keyword: str | None,
|
||||||
return [e for e in elements if ifcopenshell.util.element.get_type(e) == relating_type]
|
) -> filter[ifcopenshell.entity_instance]:
|
||||||
|
keyword = keyword.lower() if keyword else keyword
|
||||||
@classmethod
|
def filter_element(element):
|
||||||
def filter_elements_by_untyped(cls, elements: List[ifcopenshell.entity_instance]):
|
if ifc_class:
|
||||||
return [e for e in elements if not ifcopenshell.util.element.get_type(e)]
|
if not element.is_a(ifc_class):
|
||||||
|
return False
|
||||||
|
element_type = ifcopenshell.util.element.get_type(element)
|
||||||
|
if relating_type:
|
||||||
|
if relating_type != element_type:
|
||||||
|
return False
|
||||||
|
if is_untyped:
|
||||||
|
if element_type is not None:
|
||||||
|
return False
|
||||||
|
if keyword:
|
||||||
|
type_name = getattr(element_type, "Name", "") or ""
|
||||||
|
if keyword not in f"{element.is_a()} {type_name}".lower():
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
return filter(filter_element, elements)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def import_spatial_decomposition(cls) -> None:
|
def import_spatial_decomposition(cls) -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user