diff --git a/src/ifcblenderexport/blenderbim/bim/ifc.py b/src/ifcblenderexport/blenderbim/bim/ifc.py index b5f4712065..ac07c7b4d6 100644 --- a/src/ifcblenderexport/blenderbim/bim/ifc.py +++ b/src/ifcblenderexport/blenderbim/bim/ifc.py @@ -33,12 +33,14 @@ class IfcStore: @staticmethod def link_element(element, obj): IfcStore.id_map[element.id()] = obj - IfcStore.guid_map[element.GlobalId] = obj + if hasattr(element, "GlobalId"): + IfcStore.guid_map[element.GlobalId] = obj obj.BIMObjectProperties.ifc_definition_id = element.id() @staticmethod def unlink_element(element, obj=None): del IfcStore.id_map[element.id()] - del IfcStore.guid_map[element.GlobalId] + if hasattr(element, "GlobalId"): + del IfcStore.guid_map[element.GlobalId] if obj: obj.BIMObjectProperties.ifc_definition_id = 0 diff --git a/src/ifcblenderexport/blenderbim/bim/module/grid/create_grid_axis.py b/src/ifcblenderexport/blenderbim/bim/module/grid/create_grid_axis.py new file mode 100644 index 0000000000..24cdfee09a --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/grid/create_grid_axis.py @@ -0,0 +1,53 @@ +import ifcopenshell +import ifcopenshell.util.unit +import ifcopenshell.util.placement +from mathutils import Matrix # For now, we depend on Blender +from blenderbim.bim.module.owner.api import create_owner_history + + +class Usecase: + def __init__(self, file, settings=None): + self.file = file + self.settings = { + "AxisTag": "A", + "AxisCurve": None, # A Blender object + "SameSense": True, + "UVWAxes": "UAxes", # Choose which axes + "Grid": None, + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file) + points = [ + Matrix(ifcopenshell.util.placement.get_local_placement(self.settings["Grid"].ObjectPlacement)).inverted() + @ (self.settings["AxisCurve"].matrix_world @ v.co) + for v in self.settings["AxisCurve"].data.vertices[0:2] + ] + self.settings["AxisCurve"] = self.file.createIfcPolyline( + [ + self.create_cartesian_point(points[0][0], points[0][1], points[0][2]), + self.create_cartesian_point(points[1][0], points[1][1], points[1][2]), + ] + ) + element = self.file.create_entity("IfcGridAxis", **{ + "AxisTag": self.settings["AxisTag"], + "AxisCurve": self.settings["AxisCurve"], + "SameSense": self.settings["SameSense"] + }) + axes = list(getattr(self.settings["Grid"], self.settings["UVWAxes"]) or []) + axes.append(element) + setattr(self.settings["Grid"], self.settings["UVWAxes"], axes) + return element + + def create_cartesian_point(self, x, y, z=None): + x = self.convert_si_to_unit(x) + y = self.convert_si_to_unit(y) + if z is None: + return self.file.createIfcCartesianPoint((x, y)) + z = self.convert_si_to_unit(z) + return self.file.createIfcCartesianPoint((x, y, z)) + + def convert_si_to_unit(self, co): + return co / self.settings["unit_scale"] diff --git a/src/ifcblenderexport/blenderbim/bim/module/model/door.py b/src/ifcblenderexport/blenderbim/bim/module/model/door.py index e8ff0bd46d..585031a342 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/model/door.py +++ b/src/ifcblenderexport/blenderbim/bim/module/model/door.py @@ -3,8 +3,8 @@ import math import ifcopenshell from bpy.types import Operator from bpy.props import FloatProperty -from bpy_extras.object_utils import AddObjectHelper, object_data_add from mathutils import Vector +from blenderbim.bim.ifc import IfcStore def add_object(self, context): @@ -79,7 +79,11 @@ def add_object(self, context): faces = [[0, 1, 2, 3, 4, 5]] mesh = bpy.data.meshes.new(name="Dumb Door Profile") mesh.from_pydata(verts, edges, faces) - obj = object_data_add(context, mesh, operator=self) + obj = bpy.data.objects.new("Door Profile", mesh) + + context.view_layer.active_layer_collection.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) bpy.ops.object.convert(target="CURVE") # Door lining sweep @@ -93,7 +97,11 @@ def add_object(self, context): faces = [] mesh = bpy.data.meshes.new(name="Dumb Door") mesh.from_pydata(verts, edges, faces) - obj2 = object_data_add(context, mesh, operator=self) + obj2 = bpy.data.objects.new("Door", mesh) + + context.view_layer.active_layer_collection.collection.objects.link(obj2) + bpy.context.view_layer.objects.active = obj2 + obj2.select_set(True) bpy.ops.object.convert(target="CURVE") obj2.data.dimensions = "2D" @@ -116,10 +124,14 @@ def add_object(self, context): faces = [[0, 1, 2, 3]] mesh = bpy.data.meshes.new(name="Dumb Door Panel") mesh.from_pydata(verts, edges, faces) - obj3 = object_data_add(context, mesh, operator=self) + obj3 = bpy.data.objects.new("Door Panel", mesh) modifier = obj3.modifiers.new("Panel Height", "SOLIDIFY") modifier.offset = 1 modifier.thickness = self.overall_height - 0.045 + + context.view_layer.active_layer_collection.collection.objects.link(obj3) + bpy.context.view_layer.objects.active = obj3 + obj3.select_set(True) bpy.ops.object.convert(target="MESH") ctx = bpy.context.copy() @@ -138,11 +150,16 @@ def add_object(self, context): faces = [[0, 1, 2, 3]] mesh = bpy.data.meshes.new(name="Dumb Door Opening") mesh.from_pydata(verts, edges, faces) - obj4 = object_data_add(context, mesh, operator=self) + obj4 = bpy.data.objects.new("Door Opening", mesh) modifier = obj4.modifiers.new("Panel Height", "SOLIDIFY") modifier.offset = -1 modifier.thickness = self.overall_height + 0.1 + + context.view_layer.active_layer_collection.collection.objects.link(obj4) + bpy.context.view_layer.objects.active = obj4 + obj4.select_set(True) bpy.ops.object.convert(target="MESH") + obj4.display_type = "WIRE" obj4.parent = obj2 obj4.matrix_parent_inverse = obj2.matrix_world.inverted() @@ -150,6 +167,9 @@ def add_object(self, context): obj4.name = "Door Opening" obj2.name = "Door" + + if IfcStore.get_file(): + bpy.ops.bim.assign_class(obj=obj2.name, ifc_class="IfcDoor") #obj2.data.name = "Model/Body/MODEL_VIEW/" + guid #obj2.data.use_fake_user = True @@ -165,10 +185,9 @@ def add_object(self, context): #rep.target_view = "PLAN_VIEW" -class BIM_OT_add_object(Operator, AddObjectHelper): +class BIM_OT_add_object(Operator): bl_idname = "mesh.add_door" bl_label = "Dumb Door" - bl_options = {"REGISTER", "UNDO"} overall_width: FloatProperty(name="Overall Width", default=0.85) overall_height: FloatProperty(name="Overall Height", default=2.1) diff --git a/src/ifcblenderexport/blenderbim/bim/module/model/grid.py b/src/ifcblenderexport/blenderbim/bim/module/model/grid.py index bc99dff616..728176737a 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/model/grid.py +++ b/src/ifcblenderexport/blenderbim/bim/module/model/grid.py @@ -1,19 +1,16 @@ import bpy +import blenderbim.bim.module.grid.create_grid_axis as create_grid_axis from bpy.types import Operator from bpy.props import FloatProperty, IntProperty -from bpy_extras.object_utils import AddObjectHelper, object_data_add from mathutils import Vector +from blenderbim.bim.ifc import IfcStore def add_object(self, context): - obj = object_data_add(context, None, operator=self) - obj.name = "IfcGrid/Grid" - name = obj.name.split("/")[1] + obj = bpy.data.objects.new("Grid", None) + obj.name = "Grid" - default_collection = obj.users_collection[0] - default_collection.objects.unlink(obj) - - collection = bpy.data.collections.new("IfcGrid/" + name) + collection = bpy.data.collections.new(obj.name) has_site_collection = False for child in bpy.context.view_layer.layer_collection.children: if "IfcProject/" not in child.name: @@ -28,6 +25,13 @@ def add_object(self, context): bpy.context.view_layer.active_layer_collection.collection.children.link(collection) collection.objects.link(obj) + self.file = IfcStore.get_file() + if self.file: + bpy.ops.bim.assign_class(obj=obj.name, ifc_class="IfcGrid") + grid = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) + if has_site_collection: + bpy.ops.bim.assign_container(relating_structure=grandchild.name, related_element=obj.name) + axes_collection = bpy.data.collections.new("UAxes") collection.children.link(axes_collection) for i in range(0, self.total_u): @@ -39,14 +43,16 @@ def add_object(self, context): faces = [] mesh = bpy.data.meshes.new(name="Grid Axis") mesh.from_pydata(verts, edges, faces) - obj = object_data_add(context, mesh, operator=self) tag = chr(ord("A") + i) - obj.name = "IfcGridAxis/" + tag - default_collection.objects.unlink(obj) + obj = bpy.data.objects.new(f"IfcGridAxis/{tag}", mesh) + axes_collection.objects.link(obj) - attribute = obj.BIMObjectProperties.attributes.add() - attribute.name = "AxisTag" - attribute.string_value = tag + + if self.file: + result = create_grid_axis.Usecase( + self.file, {"AxisTag": tag, "AxisCurve": obj, "UVWAxes": "UAxes", "Grid": grid} + ).execute() + obj.BIMObjectProperties.ifc_definition_id = result.id() axes_collection = bpy.data.collections.new("VAxes") collection.children.link(axes_collection) @@ -59,17 +65,19 @@ def add_object(self, context): faces = [] mesh = bpy.data.meshes.new(name="Grid Axis") mesh.from_pydata(verts, edges, faces) - obj = object_data_add(context, mesh, operator=self) tag = str(i + 1).zfill(2) - obj.name = "IfcGridAxis/" + tag - default_collection.objects.unlink(obj) + obj = bpy.data.objects.new(f"IfcGridAxis/{tag}", mesh) + axes_collection.objects.link(obj) - attribute = obj.BIMObjectProperties.attributes.add() - attribute.name = "AxisTag" - attribute.string_value = tag + + if IfcStore.get_file(): + result = create_grid_axis.Usecase( + self.file, {"AxisTag": tag, "AxisCurve": obj, "UVWAxes": "VAxes", "Grid": grid} + ).execute() + obj.BIMObjectProperties.ifc_definition_id = result.id() -class BIM_OT_add_object(Operator, AddObjectHelper): +class BIM_OT_add_object(Operator): bl_idname = "mesh.add_grid" bl_label = "Grid" bl_options = {"REGISTER", "UNDO"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/model/slab.py b/src/ifcblenderexport/blenderbim/bim/module/model/slab.py index 09efbb6b3b..f082d24a6b 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/model/slab.py +++ b/src/ifcblenderexport/blenderbim/bim/module/model/slab.py @@ -1,8 +1,8 @@ import bpy from bpy.types import Operator from bpy.props import FloatProperty -from bpy_extras.object_utils import AddObjectHelper, object_data_add from mathutils import Vector +from blenderbim.bim.ifc import IfcStore def add_object(self, context): @@ -17,18 +17,20 @@ def add_object(self, context): mesh = bpy.data.meshes.new(name="Dumb Slab") mesh.from_pydata(verts, edges, faces) - obj = object_data_add(context, mesh, operator=self) + obj = bpy.data.objects.new("Slab", mesh) modifier = obj.modifiers.new("Slab Depth", "SOLIDIFY") modifier.use_even_offset = True modifier.offset = 1 modifier.thickness = self.depth obj.name = "Slab" + context.view_layer.active_layer_collection.collection.objects.link(obj) + if IfcStore.get_file(): + bpy.ops.bim.assign_class(obj=obj.name, ifc_class="IfcSlab") -class BIM_OT_add_object(Operator, AddObjectHelper): +class BIM_OT_add_object(Operator): bl_idname = "mesh.add_slab" bl_label = "Dumb Slab" - bl_options = {"REGISTER", "UNDO"} length: FloatProperty(name="Length", default=2) width: FloatProperty(name="Width", default=2) diff --git a/src/ifcblenderexport/blenderbim/bim/module/model/wall.py b/src/ifcblenderexport/blenderbim/bim/module/model/wall.py index da8db6400a..1204eea00c 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/model/wall.py +++ b/src/ifcblenderexport/blenderbim/bim/module/model/wall.py @@ -1,8 +1,8 @@ import bpy from bpy.types import Operator from bpy.props import FloatProperty, BoolProperty -from bpy_extras.object_utils import AddObjectHelper, object_data_add from mathutils import Vector +from blenderbim.bim.ifc import IfcStore def add_object(self, context): @@ -25,7 +25,8 @@ def add_object(self, context): mesh = bpy.data.meshes.new(name="Dumb Wall") mesh.from_pydata(verts, edges, faces) - obj = object_data_add(context, mesh, operator=self) + obj = bpy.data.objects.new("Wall", mesh) + context.view_layer.active_layer_collection.collection.objects.link(obj) if not self.use_plane: modifier = obj.modifiers.new("Wall Height", "SCREW") modifier.angle = 0 @@ -39,13 +40,14 @@ def add_object(self, context): modifier.use_even_offset = True modifier.thickness = self.width obj.name = "Wall" + if IfcStore.get_file(): + bpy.ops.bim.assign_class(obj=obj.name, ifc_class="IfcWall") return obj -class BIM_OT_add_object(Operator, AddObjectHelper): +class BIM_OT_add_object(Operator): bl_idname = "mesh.add_wall" bl_label = "Dumb Wall" - bl_options = {"REGISTER", "UNDO"} height: FloatProperty(name="Height", default=3) length: FloatProperty(name="Length", default=1) diff --git a/src/ifcblenderexport/blenderbim/bim/module/model/window.py b/src/ifcblenderexport/blenderbim/bim/module/model/window.py index d9ca131f46..1872dbdbb9 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/model/window.py +++ b/src/ifcblenderexport/blenderbim/bim/module/model/window.py @@ -3,8 +3,8 @@ import math import ifcopenshell from bpy.types import Operator from bpy.props import FloatProperty -from bpy_extras.object_utils import AddObjectHelper, object_data_add from mathutils import Vector +from blenderbim.bim.ifc import IfcStore def add_object(self, context): @@ -64,7 +64,11 @@ def add_object(self, context): faces = [[0, 1, 2, 3]] mesh = bpy.data.meshes.new(name="Dumb Window Profile") mesh.from_pydata(verts, edges, faces) - obj = object_data_add(context, mesh, operator=self) + obj = bpy.data.objects.new("Window Profile", mesh) + + context.view_layer.active_layer_collection.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) bpy.ops.object.convert(target="CURVE") # Window lining sweep @@ -78,7 +82,11 @@ def add_object(self, context): faces = [] mesh = bpy.data.meshes.new(name="Dumb Window") mesh.from_pydata(verts, edges, faces) - obj2 = object_data_add(context, mesh, operator=self) + obj2 = bpy.data.objects.new("Window", mesh) + + context.view_layer.active_layer_collection.collection.objects.link(obj2) + bpy.context.view_layer.objects.active = obj2 + obj2.select_set(True) bpy.ops.object.convert(target="CURVE") obj2.data.splines[0].use_cyclic_u = True @@ -102,10 +110,14 @@ def add_object(self, context): faces = [[0, 1, 2, 3]] mesh = bpy.data.meshes.new(name="Dumb Window Panel") mesh.from_pydata(verts, edges, faces) - obj3 = object_data_add(context, mesh, operator=self) + obj3 = bpy.data.objects.new("Window Panel", mesh) modifier = obj3.modifiers.new("Panel Height", "SOLIDIFY") modifier.offset = 1 modifier.thickness = self.overall_height - 0.08 + + context.view_layer.active_layer_collection.collection.objects.link(obj3) + bpy.context.view_layer.objects.active = obj3 + obj3.select_set(True) bpy.ops.object.convert(target="MESH") ctx = bpy.context.copy() @@ -124,10 +136,14 @@ def add_object(self, context): faces = [[0, 1, 2, 3]] mesh = bpy.data.meshes.new(name="Dumb Window Opening") mesh.from_pydata(verts, edges, faces) - obj4 = object_data_add(context, mesh, operator=self) + obj4 = bpy.data.objects.new("Window Opening", mesh) modifier = obj4.modifiers.new("Panel Height", "SOLIDIFY") modifier.offset = -1 modifier.thickness = self.overall_height + + context.view_layer.active_layer_collection.collection.objects.link(obj4) + bpy.context.view_layer.objects.active = obj4 + obj4.select_set(True) bpy.ops.object.convert(target="MESH") obj4.display_type = "WIRE" obj4.parent = obj2 @@ -135,6 +151,8 @@ def add_object(self, context): obj4.hide_render = True obj4.name = "Window Opening" + if IfcStore.get_file(): + bpy.ops.bim.assign_class(obj=obj2.name, ifc_class="IfcWindow") obj2.name = "Window" #obj2.data.name = "Model/Body/MODEL_VIEW/" + guid #obj2.data.use_fake_user = True @@ -150,10 +168,9 @@ def add_object(self, context): #rep.target_view = "PLAN_VIEW" -class BIM_OT_add_object(Operator, AddObjectHelper): +class BIM_OT_add_object(Operator): bl_idname = "mesh.add_window" bl_label = "Dumb Window" - bl_options = {"REGISTER", "UNDO"} overall_width: FloatProperty(name="Overall Width", default=0.7) overall_height: FloatProperty(name="Overall Height", default=1) diff --git a/src/ifcblenderexport/blenderbim/bim/svgwriter.py b/src/ifcblenderexport/blenderbim/bim/svgwriter.py index 1d8968397e..3006ac3d98 100644 --- a/src/ifcblenderexport/blenderbim/bim/svgwriter.py +++ b/src/ifcblenderexport/blenderbim/bim/svgwriter.py @@ -10,6 +10,7 @@ from . import annotation from . import helper from mathutils import Vector from mathutils import geometry +from blenderbim.bim.ifc import IfcStore try: from OCC.Core import BRep, BRepTools, TopExp, TopAbs @@ -140,11 +141,7 @@ class SvgWriter: line["marker-start"] = "url(#grid-marker)" line["marker-end"] = "url(#grid-marker)" line["stroke-dasharray"] = "12.5, 3, 3, 3" - axis_tag = grid_obj.BIMObjectProperties.attributes.get("AxisTag") - if axis_tag: - axis_tag = axis_tag.string_value - else: - axis_tag = grid_obj.name.split("/")[1] + axis_tag = IfcStore.get_file().by_id(grid_obj.BIMObjectProperties.ifc_definition_id).AxisTag self.svg.add( self.svg.text( axis_tag, diff --git a/win/run-cmake.bat b/win/run-cmake.bat index a824abb87b..4a1d2cddf4 100755 --- a/win/run-cmake.bat +++ b/win/run-cmake.bat @@ -132,9 +132,9 @@ if not (%1)==() if exist CMakeCache.txt. del /Q CMakeCache.txt call cecho.cmd 0 13 "Running CMake for %PROJECT_NAME%." IF DEFINED VS_TOOLSET ( - cmake.exe %CMAKELISTS_DIR% -G %GENERATOR% -A %VS_PLATFORM% -T %VS_TOOLSET% -DCMAKE_INSTALL_PREFIX="%CMAKE_INSTALL_PREFIX%" %ARGUMENTS% + cmake.exe %CMAKELISTS_DIR% -G %GENERATOR% -A %VS_PLATFORM% -T %VS_TOOLSET% -DCMAKE_INSTALL_PREFIX="%CMAKE_INSTALL_PREFIX%" -DBoost_NO_BOOST_CMAKE=On %ARGUMENTS% ) ELSE ( - cmake.exe %CMAKELISTS_DIR% -G %GENERATOR% -A %VS_PLATFORM% -DCMAKE_INSTALL_PREFIX="%CMAKE_INSTALL_PREFIX%" %ARGUMENTS% + cmake.exe %CMAKELISTS_DIR% -G %GENERATOR% -A %VS_PLATFORM% -DCMAKE_INSTALL_PREFIX="%CMAKE_INSTALL_PREFIX%" -DBoost_NO_BOOST_CMAKE=On %ARGUMENTS% ) IF NOT %ERRORLEVEL%==0 GOTO :Error