You can now add new swept area solid items

This commit is contained in:
Dion Moult
2024-09-21 21:27:17 +10:00
parent ce010f1e56
commit 9ea44f0a89
5 changed files with 81 additions and 25 deletions
@@ -22,6 +22,7 @@ from . import ui, prop, operator
classes = (
operator.AddMeshlikeItem,
operator.AddRepresentation,
operator.AddSweptAreaSolidItem,
operator.CopyRepresentation,
operator.DisableEditingRepresentationItemShapeAspect,
operator.DisableEditingRepresentationItemStyle,
@@ -20,6 +20,7 @@ import bpy
import bmesh
import shapely
import mathutils
import numpy as np
import ifcopenshell
import ifcopenshell.util.unit
import ifcopenshell.util.shape
@@ -294,6 +295,7 @@ class Helper:
for curve in curves:
geometry = ifcopenshell.geom.create_shape(settings, curve)
v = ifcopenshell.util.shape.get_vertices(geometry, is_2d=True)
v = np.round(v, 4) # Round to nearest 0.1mm, otherwise things like circles don't polygonise reliably
edges = ifcopenshell.util.shape.get_edges(geometry)
boundary_lines = [shapely.LineString([v[e[0]], v[e[1]]]) for e in edges]
unioned_boundaries = shapely.union_all(shapely.GeometryCollection(boundary_lines))
@@ -1774,7 +1774,6 @@ class OverrideModeSetObject(bpy.types.Operator, tool.Ifc.Operator):
return {"FINISHED"}
objs = context.selected_objects or [context.active_object]
print("objs are", objs)
self.edited_objs = []
self.unchanged_objs_with_openings = []
@@ -1874,7 +1873,6 @@ class OverrideModeSetObject(bpy.types.Operator, tool.Ifc.Operator):
ProfileDecorator.uninstall()
profile = tool.Model.export_profile(obj)
print("got profile", profile)
if not profile:
@@ -1892,19 +1890,8 @@ class OverrideModeSetObject(bpy.types.Operator, tool.Ifc.Operator):
ifcopenshell.util.element.remove_deep2(tool.Ifc.get(), old_profile)
tool.Geometry.reload_representation(bpy.context.scene.BIMGeometryProperties.representation_obj)
tool.Loader.settings.contexts = ifcopenshell.util.representation.get_prioritised_contexts(tool.Ifc.get())
tool.Loader.settings.context_settings = tool.Loader.create_settings()
tool.Loader.settings.gross_context_settings = tool.Loader.create_settings(is_gross=True)
geometry = tool.Loader.create_generic_shape(item)
obj.data.clear_geometry()
tool.Loader.convert_geometry_to_mesh(geometry, obj.data)
if item.Position:
position = Matrix(ifcopenshell.util.placement.get_axis2placement(item.Position).tolist())
position.translation *= unit_scale
position_i = position.inverted()
for vert in obj.data.vertices:
vert.co = position_i @ vert.co
tool.Geometry.import_item(obj)
tool.Geometry.import_item_attributes(obj)
element = tool.Ifc.get_entity(bpy.context.scene.BIMGeometryProperties.representation_obj)
# Only certain classes should have a footprint
@@ -2471,3 +2458,53 @@ class AddMeshlikeItem(bpy.types.Operator, tool.Ifc.Operator):
tool.Geometry.reload_representation(bpy.context.scene.BIMGeometryProperties.representation_obj)
obj.name = obj.data.name = f"Item/{item.is_a()}/{item.id()}"
obj.data.BIMMeshProperties.ifc_definition_id = item.id()
class AddSweptAreaSolidItem(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_swept_area_solid_item"
bl_label = "Add Swept Area Solid Item"
bl_options = {"REGISTER", "UNDO"}
shape: bpy.props.StringProperty(name="Shape")
def _execute(self, context):
props = context.scene.BIMGeometryProperties
mesh = bpy.data.meshes.new("Tmp")
obj = bpy.data.objects.new("Tmp", mesh)
scene = bpy.context.scene
scene.collection.objects.link(obj)
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
new = props.item_objs.add()
new.obj = obj
matrix = props.representation_obj.matrix_world.copy()
matrix.translation = context.scene.cursor.location
local_matrix = props.representation_obj.matrix_world.inverted() @ matrix
obj.matrix_world = matrix
tool.Geometry.record_object_position(obj)
builder = ifcopenshell.util.shape_builder.ShapeBuilder(tool.Ifc.get())
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
if self.shape == "CUBE":
curve = builder.rectangle(size=Vector((0.5, 0.5)) / unit_scale)
elif self.shape == "CYLINDER":
curve = builder.circle(radius=0.25)
item = builder.extrude(
curve,
magnitude=0.5 / unit_scale,
position=local_matrix.translation,
position_x_axis=local_matrix.col[0].to_3d(),
position_z_axis=local_matrix.col[2].to_3d(),
)
representation = tool.Geometry.get_active_representation(props.representation_obj)
representation = ifcopenshell.util.representation.resolve_representation(representation)
representation.Items = list(representation.Items) + [item]
tool.Geometry.reload_representation(bpy.context.scene.BIMGeometryProperties.representation_obj)
obj.name = obj.data.name = f"Item/{item.is_a()}/{item.id()}"
obj.data.BIMMeshProperties.ifc_definition_id = item.id()
tool.Geometry.import_item(obj)
tool.Geometry.import_item_attributes(obj)
@@ -64,7 +64,7 @@ classes = (
product.LoadTypeThumbnails,
product.MirrorElements,
workspace.Hotkey,
workspace.BIM_MT_add_meshlike_item,
workspace.BIM_MT_add_representation_item,
wall.AlignWall,
wall.ChangeExtrusionDepth,
wall.ChangeExtrusionXAngle,
@@ -272,7 +272,7 @@ class EditItemUI:
row.label(text="Context: " + ItemData.data["representation_identifier"], icon="SCENE_DATA")
row = cls.layout.row()
row.label(text="Type: " + ItemData.data["representation_type"], icon="OUTLINER_OB_MESH")
cls.layout.menu("BIM_MT_add_meshlike_item", icon="ADD")
cls.layout.menu("BIM_MT_add_representation_item", icon="ADD")
if not (obj := context.active_object) or not tool.Geometry.is_representation_item(obj):
return
for item_attribute in obj.data.BIMMeshProperties.item_attributes:
@@ -283,17 +283,33 @@ class EditItemUI:
row.operator("bim.update_item_attributes", icon="FILE_REFRESH", text="")
class BIM_MT_add_meshlike_item(Menu):
bl_idname = "BIM_MT_add_meshlike_item"
class BIM_MT_add_representation_item(Menu):
bl_idname = "BIM_MT_add_representation_item"
bl_label = "Add Item"
def draw(self, context):
self.layout.operator("bim.add_meshlike_item", icon="MESH_PLANE", text="Mesh Plane").shape = "PLANE"
self.layout.operator("bim.add_meshlike_item", icon="MESH_CUBE", text="Mesh Cube").shape = "CUBE"
self.layout.operator("bim.add_meshlike_item", icon="MESH_CIRCLE", text="Mesh Circle").shape = "CIRCLE"
self.layout.operator("bim.add_meshlike_item", icon="MESH_UVSPHERE", text="Mesh UV Sphere").shape = "UVSPHERE"
self.layout.operator("bim.add_meshlike_item", icon="MESH_ICOSPHERE", text="Mesh Icosphere").shape = "ICOSPHERE"
self.layout.operator("bim.add_meshlike_item", icon="MESH_CYLINDER", text="Mesh Cylinder").shape = "CYLINDER"
if not ItemData.is_loaded:
ItemData.load()
if ItemData.data["representation_type"] in ("Tessellation", "Brep", "AdvancedBrep"):
self.layout.operator("bim.add_meshlike_item", icon="MESH_PLANE", text="Mesh Plane").shape = "PLANE"
self.layout.operator("bim.add_meshlike_item", icon="MESH_CUBE", text="Mesh Cube").shape = "CUBE"
self.layout.operator("bim.add_meshlike_item", icon="MESH_CIRCLE", text="Mesh Circle").shape = "CIRCLE"
self.layout.operator("bim.add_meshlike_item", icon="MESH_UVSPHERE", text="Mesh UV Sphere").shape = (
"UVSPHERE"
)
self.layout.operator("bim.add_meshlike_item", icon="MESH_ICOSPHERE", text="Mesh Icosphere").shape = (
"ICOSPHERE"
)
self.layout.operator("bim.add_meshlike_item", icon="MESH_CYLINDER", text="Mesh Cylinder").shape = "CYLINDER"
if ItemData.data["representation_type"] in ("SolidModel", "SweptSolid"):
self.layout.operator(
"bim.add_swept_area_solid_item", icon="MESH_CUBE", text="Extruded Area Solid Cube"
).shape = "CUBE"
self.layout.operator(
"bim.add_swept_area_solid_item", icon="MESH_CYLINDER", text="Extruded Area Solid Cylinder"
).shape = "CYLINDER"
class CreateObjectUI: