diff --git a/src/blenderbim/blenderbim/bim/__init__.py b/src/blenderbim/blenderbim/bim/__init__.py index 6d2ef80a55..da0e078ee0 100644 --- a/src/blenderbim/blenderbim/bim/__init__.py +++ b/src/blenderbim/blenderbim/bim/__init__.py @@ -142,7 +142,7 @@ classes = [ ui.BIM_PT_tabs, # Project overview ui.BIM_PT_tab_project_info, - ui.BIM_PT_tab_project_tree, + ui.BIM_PT_tab_spatial_decomposition, ui.BIM_PT_tab_project_setup, ui.BIM_PT_tab_geometry, ui.BIM_PT_tab_stakeholders, diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index 90c06e2d51..83658f0b78 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -37,6 +37,7 @@ import ifcopenshell.util.placement import ifcopenshell.util.representation import ifcopenshell.util.shape import blenderbim.tool as tool +import blenderbim.core.spatial import ifcopenshell.ifcopenshell_wrapper as ifcopenshell_wrapper from itertools import chain, accumulate from blenderbim.bim.ifc import IfcStore, IFC_CONNECTED_TYPE @@ -301,6 +302,7 @@ class IfcImporter: self.setup_viewport_camera() self.setup_arrays() self.profile_code("Setup arrays") + blenderbim.core.spatial.import_spatial_decomposition(tool.Spatial) self.update_progress(100) bpy.context.window_manager.progress_end() diff --git a/src/blenderbim/blenderbim/bim/module/project/operator.py b/src/blenderbim/blenderbim/bim/module/project/operator.py index 8f44c76f8f..2e6cd2b164 100644 --- a/src/blenderbim/blenderbim/bim/module/project/operator.py +++ b/src/blenderbim/blenderbim/bim/module/project/operator.py @@ -36,6 +36,7 @@ import blenderbim.tool as tool import blenderbim.core.project as core import blenderbim.core.context import blenderbim.core.owner +import blenderbim.core.spatial from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ui import IFCFileSelector from blenderbim.bim import import_ifc @@ -122,6 +123,7 @@ class CreateProject(bpy.types.Operator): for mat in bpy.data.materials: bpy.data.materials.remove(mat) core.create_project(tool.Ifc, tool.Project, schema=props.export_schema, template=template) + blenderbim.core.spatial.import_spatial_decomposition(tool.Spatial) tool.Blender.register_toolbar() def rollback(self, data): diff --git a/src/blenderbim/blenderbim/bim/module/spatial/__init__.py b/src/blenderbim/blenderbim/bim/module/spatial/__init__.py index 3aab40cbfc..033d7349c0 100644 --- a/src/blenderbim/blenderbim/bim/module/spatial/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/spatial/__init__.py @@ -30,7 +30,7 @@ classes = ( operator.EditContainerAttributes, operator.EnableEditingContainer, operator.ExpandContainer, - operator.LoadContainerManager, + operator.ImportSpatialDecomposition, operator.ReferenceStructure, operator.RemoveContainer, operator.SelectContainer, @@ -42,12 +42,12 @@ classes = ( prop.BIMSpatialProperties, prop.BIMObjectSpatialProperties, prop.BIMContainer, - prop.BIMProjectTreeProperties, + prop.BIMSpatialDecompositionProperties, ui.BIM_PT_spatial, ui.BIM_UL_containers, ui.BIM_UL_containers_manager, ui.BIM_UL_elements, - ui.BIM_PT_project_tree, + ui.BIM_PT_spatial_decomposition, workspace.Hotkey, ) @@ -57,7 +57,7 @@ def register(): bpy.utils.register_tool(workspace.SpatialTool, after={"bim.annotation_tool"}, separator=False, group=False) bpy.types.Scene.BIMSpatialProperties = bpy.props.PointerProperty(type=prop.BIMSpatialProperties) bpy.types.Object.BIMObjectSpatialProperties = bpy.props.PointerProperty(type=prop.BIMObjectSpatialProperties) - bpy.types.Scene.BIMProjectTreeProperties = bpy.props.PointerProperty(type=prop.BIMProjectTreeProperties) + bpy.types.Scene.BIMSpatialDecompositionProperties = bpy.props.PointerProperty(type=prop.BIMSpatialDecompositionProperties) def unregister(): @@ -65,4 +65,4 @@ def unregister(): bpy.utils.unregister_tool(workspace.SpatialTool) del bpy.types.Scene.BIMSpatialProperties del bpy.types.Object.BIMObjectSpatialProperties - del bpy.types.Scene.BIMProjectTreeProperties + del bpy.types.Scene.BIMSpatialDecompositionProperties diff --git a/src/blenderbim/blenderbim/bim/module/spatial/data.py b/src/blenderbim/blenderbim/bim/module/spatial/data.py index b31545860d..5b82cdccad 100644 --- a/src/blenderbim/blenderbim/bim/module/spatial/data.py +++ b/src/blenderbim/blenderbim/bim/module/spatial/data.py @@ -23,7 +23,7 @@ import ifcopenshell.util.element def refresh(): SpatialData.is_loaded = False - ProjectTreeData.is_loaded = False + SpatialDecompositionData.is_loaded = False class SpatialData: @@ -84,7 +84,7 @@ class SpatialData: return bool(getattr(tool.Ifc.get_entity(bpy.context.active_object), "ContainedInStructure", False)) -class ProjectTreeData: +class SpatialDecompositionData: data = {} is_loaded = False @@ -98,7 +98,7 @@ class ProjectTreeData: @classmethod def subelement_class(cls): results = [] - props = bpy.context.scene.BIMProjectTreeProperties + props = bpy.context.scene.BIMSpatialDecompositionProperties if not (container := props.active_container): return results container_class = tool.Ifc.get().by_id(container.ifc_definition_id).is_a() diff --git a/src/blenderbim/blenderbim/bim/module/spatial/operator.py b/src/blenderbim/blenderbim/bim/module/spatial/operator.py index 1441bbc18a..9d4038c5e2 100644 --- a/src/blenderbim/blenderbim/bim/module/spatial/operator.py +++ b/src/blenderbim/blenderbim/bim/module/spatial/operator.py @@ -175,13 +175,13 @@ class SelectProduct(bpy.types.Operator): return {"FINISHED"} -class LoadContainerManager(bpy.types.Operator): - bl_idname = "bim.load_container_manager" +class ImportSpatialDecomposition(bpy.types.Operator): + bl_idname = "bim.import_spatial_decomposition" bl_label = "Load Container Manager" bl_options = {"REGISTER", "UNDO"} def execute(self, context): - core.load_container_manager(tool.Spatial) + core.import_spatial_decomposition(tool.Spatial) return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/spatial/prop.py b/src/blenderbim/blenderbim/bim/module/spatial/prop.py index b4586b01a0..b4badb994b 100644 --- a/src/blenderbim/blenderbim/bim/module/spatial/prop.py +++ b/src/blenderbim/blenderbim/bim/module/spatial/prop.py @@ -18,7 +18,7 @@ import bpy from blenderbim.bim.prop import StrProperty, Attribute -from blenderbim.bim.module.spatial.data import ProjectTreeData +from blenderbim.bim.module.spatial.data import SpatialDecompositionData from bpy.types import PropertyGroup from bpy.props import ( PointerProperty, @@ -35,9 +35,9 @@ import ifcopenshell def get_subelement_class(self, context): - if not ProjectTreeData.is_loaded: - ProjectTreeData.load() - return ProjectTreeData.data["subelement_class"] + if not SpatialDecompositionData.is_loaded: + SpatialDecompositionData.load() + return SpatialDecompositionData.data["subelement_class"] def update_elevation(self, context): @@ -55,7 +55,7 @@ def update_name(self, context): def update_active_container_index(self, context): - ProjectTreeData.data["subelement_class"] = ProjectTreeData.subelement_class() + SpatialDecompositionData.data["subelement_class"] = SpatialDecompositionData.subelement_class() tool.Spatial.load_contained_elements() @@ -122,7 +122,7 @@ class Element(PropertyGroup): total: IntProperty(name="Total") -class BIMProjectTreeProperties(PropertyGroup): +class BIMSpatialDecompositionProperties(PropertyGroup): containers: CollectionProperty(name="Containers", type=BIMContainer) contracted_containers: StringProperty(name="Contracted containers", default="[]") expanded_containers: StringProperty(name="Expanded containers", default="[]") diff --git a/src/blenderbim/blenderbim/bim/module/spatial/ui.py b/src/blenderbim/blenderbim/bim/module/spatial/ui.py index 9593cbeea1..da7a761af9 100644 --- a/src/blenderbim/blenderbim/bim/module/spatial/ui.py +++ b/src/blenderbim/blenderbim/bim/module/spatial/ui.py @@ -17,7 +17,7 @@ # along with BlenderBIM Add-on. If not, see . from bpy.types import Panel, UIList -from blenderbim.bim.module.spatial.data import SpatialData, ProjectTreeData +from blenderbim.bim.module.spatial.data import SpatialData, SpatialDecompositionData import blenderbim.tool as tool @@ -91,13 +91,13 @@ class BIM_UL_containers(UIList): ) -class BIM_PT_project_tree(Panel): - bl_label = "Project Tree" - bl_idname = "BIM_PT_project_tree" +class BIM_PT_spatial_decomposition(Panel): + bl_label = "Spatial Decomposition" + bl_idname = "BIM_PT_spatial_decomposition" bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "scene" - bl_parent_id = "BIM_PT_tab_project_tree" + bl_parent_id = "BIM_PT_tab_spatial_decomposition" bl_options = {"HIDE_HEADER"} @classmethod @@ -105,9 +105,9 @@ class BIM_PT_project_tree(Panel): return tool.Ifc.get() def draw(self, context): - if not ProjectTreeData.is_loaded: - ProjectTreeData.load() - self.props = context.scene.BIMProjectTreeProperties + if not SpatialDecompositionData.is_loaded: + SpatialDecompositionData.load() + self.props = context.scene.BIMSpatialDecompositionProperties if self.props.active_container: row = self.layout.row(align=True) @@ -115,7 +115,7 @@ class BIM_PT_project_tree(Panel): text=f"Active: {self.props.active_container.name}", icon="OUTLINER_COLLECTION", ) - row.operator("bim.load_container_manager", icon="FILE_REFRESH", text="") + row.operator("bim.import_spatial_decomposition", icon="FILE_REFRESH", text="") if self.props.active_container.ifc_class != "IfcProject": row = self.layout.row(align=True) @@ -132,7 +132,7 @@ class BIM_PT_project_tree(Panel): else: row = self.layout.row(align=True) row.label(text="Warning: No Active Container", icon="ERROR") - row.operator("bim.load_container_manager", icon="FILE_REFRESH", text="") + row.operator("bim.import_spatial_decomposition", icon="FILE_REFRESH", text="") self.layout.template_list( "BIM_UL_containers_manager", diff --git a/src/blenderbim/blenderbim/bim/ui.py b/src/blenderbim/blenderbim/bim/ui.py index 13e8096c5c..d38a3eea15 100644 --- a/src/blenderbim/blenderbim/bim/ui.py +++ b/src/blenderbim/blenderbim/bim/ui.py @@ -440,15 +440,15 @@ class BIM_PT_tab_project_info(Panel): pass -class BIM_PT_tab_project_tree(Panel): - bl_label = "Project Tree" +class BIM_PT_tab_spatial_decomposition(Panel): + bl_label = "Spatial Decomposition" bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "scene" @classmethod def poll(cls, context): - return tool.Blender.is_tab(context, "PROJECT") + return tool.Blender.is_tab(context, "PROJECT") and tool.Ifc.get() def draw(self, context): pass diff --git a/src/blenderbim/blenderbim/core/spatial.py b/src/blenderbim/blenderbim/core/spatial.py index 8a45ff8225..bc22396a28 100644 --- a/src/blenderbim/blenderbim/core/spatial.py +++ b/src/blenderbim/blenderbim/core/spatial.py @@ -120,28 +120,28 @@ def select_product(spatial, product): spatial.select_products([product]) -def load_container_manager(spatial): - spatial.load_container_manager() +def import_spatial_decomposition(spatial): + spatial.import_spatial_decomposition() def edit_container_attributes(spatial, entity=None): spatial.edit_container_attributes(entity) - spatial.load_container_manager() + spatial.import_spatial_decomposition() def contract_container(spatial, container=None): spatial.contract_container(container) - spatial.load_container_manager() + spatial.import_spatial_decomposition() def expand_container(spatial, container=None): spatial.expand_container(container) - spatial.load_container_manager() + spatial.import_spatial_decomposition() def delete_container(ifc, spatial, geometry, container=None): geometry.delete_ifc_object(ifc.get_object(container)) - spatial.load_container_manager() + spatial.import_spatial_decomposition() def select_decomposed_elements(spatial): diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index f995b81e49..59cdff7fc4 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -848,7 +848,7 @@ class Spatial: def get_selected_product_types(cls): pass def get_selected_products(cls): pass def import_containers(cls, parent=None): pass - def load_container_manager(cls): pass + def import_spatial_decomposition(cls): pass def run_root_copy_class(cls, obj=None): pass def run_spatial_assign_container(cls, structure_obj=None, element_obj=None): pass def select_object(cls, obj): pass diff --git a/src/blenderbim/blenderbim/tool/spatial.py b/src/blenderbim/blenderbim/tool/spatial.py index a0fc21364d..5c9fa44ff9 100644 --- a/src/blenderbim/blenderbim/tool/spatial.py +++ b/src/blenderbim/blenderbim/tool/spatial.py @@ -208,7 +208,7 @@ class Spatial(blenderbim.core.tool.Spatial): @classmethod def load_contained_elements(cls): - props = bpy.context.scene.BIMProjectTreeProperties + props = bpy.context.scene.BIMSpatialDecompositionProperties props.elements.clear() if not (container := props.active_container): return @@ -241,17 +241,17 @@ class Spatial(blenderbim.core.tool.Spatial): props.total_elements = total_elements @classmethod - def load_container_manager(cls): - props = bpy.context.scene.BIMProjectTreeProperties + def import_spatial_decomposition(cls): + props = bpy.context.scene.BIMSpatialDecompositionProperties previous_container_index = props.active_container_index props.containers.clear() cls.contracted_containers = json.loads(props.contracted_containers) - cls.import_spatial_structure(tool.Ifc.get().by_type("IfcProject")[0], 0) + cls.import_spatial_element(tool.Ifc.get().by_type("IfcProject")[0], 0) props.active_container_index = min(previous_container_index, len(props.containers) - 1) @classmethod - def import_spatial_structure(cls, element, level_index): - props = bpy.context.scene.BIMProjectTreeProperties + def import_spatial_element(cls, element, level_index): + props = bpy.context.scene.BIMSpatialDecompositionProperties new = props.containers.add() new.ifc_class = element.is_a() new.name = element.Name or "Unnamed" @@ -266,14 +266,14 @@ class Spatial(blenderbim.core.tool.Spatial): new.ifc_definition_id = element.id() if new.is_expanded: for child in children or []: - cls.import_spatial_structure(child, level_index + 1) + cls.import_spatial_element(child, level_index + 1) @classmethod def edit_container_attributes(cls, entity): # TODO obj = tool.Ifc.get_object(entity) blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj) - name = bpy.context.scene.BIMProjectTreeProperties.container_name + name = bpy.context.scene.BIMSpatialDecompositionProperties.container_name if name != entity.Name: cls.edit_container_name(entity, name) @@ -283,21 +283,21 @@ class Spatial(blenderbim.core.tool.Spatial): @classmethod def get_active_container(cls): - props = bpy.context.scene.BIMProjectTreeProperties + props = bpy.context.scene.BIMSpatialDecompositionProperties if props.active_container_index < len(props.containers): container = tool.Ifc.get().by_id(props.containers[props.active_container_index].ifc_definition_id) return container @classmethod def contract_container(cls, container): - props = bpy.context.scene.BIMProjectTreeProperties + props = bpy.context.scene.BIMSpatialDecompositionProperties contracted_containers = json.loads(props.contracted_containers) contracted_containers.append(container.id()) props.contracted_containers = json.dumps(contracted_containers) @classmethod def expand_container(cls, container): - props = bpy.context.scene.BIMProjectTreeProperties + props = bpy.context.scene.BIMSpatialDecompositionProperties contracted_containers = json.loads(props.contracted_containers) contracted_containers.remove(container.id()) props.contracted_containers = json.dumps(contracted_containers) @@ -322,6 +322,36 @@ class Spatial(blenderbim.core.tool.Spatial): space_polygon = shapely.force_3d(polygon) return space_polygon + @classmethod + def debug_shape(cls, foo): + coords = [(p[0], p[1], 0) for p in foo.exterior.coords] + mesh = bpy.data.meshes.new(name="NewMesh") + bm = bmesh.new() + for coord in coords: + bm.verts.new(coord) + bm.verts.ensure_lookup_table() + bm.faces.new(bm.verts) + bm.to_mesh(mesh) + bm.free() + obj = bpy.data.objects.new("NewObject", mesh) + bpy.context.collection.objects.link(obj) + bpy.context.view_layer.update() + + @classmethod + def debug_line(cls, start, end): + coords = [start, end] + mesh = bpy.data.meshes.new(name="NewMesh") + bm = bmesh.new() + for coord in coords: + bm.verts.new(coord) + bm.verts.ensure_lookup_table() + bm.edges.new(bm.verts) + bm.to_mesh(mesh) + bm.free() + obj = bpy.data.objects.new("NewLine", mesh) + bpy.context.collection.objects.link(obj) + bpy.context.view_layer.update() + @classmethod def get_boundary_lines_from_context_visible_objects(cls): calculation_rl = bpy.context.scene.BIMModelProperties.rl3