See #5972. You can now add half space solid items in item mode.

This commit is contained in:
Dion Moult
2025-01-17 23:02:26 +11:00
parent 1f436bcec6
commit 7ee055f4f3
4 changed files with 88 additions and 1 deletions
@@ -22,6 +22,7 @@ from bpy.app.handlers import persistent
classes = (
operator.AddCurvelikeItem,
operator.AddHalfSpaceSolidItem,
operator.AddMeshlikeItem,
operator.AddRepresentation,
operator.AddSweptAreaSolidItem,
@@ -57,6 +57,8 @@ class ItemDecorator:
verts = []
edges = []
tris = []
special_verts = []
special_edges = []
if len(obj.data.loop_triangles) > 0:
verts = [tuple(obj.matrix_world @ v.co) for v in obj.data.vertices]
@@ -81,7 +83,26 @@ class ItemDecorator:
]
edges = bbox_edges
verts.extend(bbox_verts)
return {"verts": verts, "edges": edges, "tris": tris}
if "HalfSpaceSolid" in obj.name:
# Arrow shape
special_verts = [
tuple(obj.matrix_world @ Vector((0, 0, 0))),
tuple(obj.matrix_world @ Vector((0, 0, 0.5))),
tuple(obj.matrix_world @ Vector((0.05, 0, 0.45))),
tuple(obj.matrix_world @ Vector((-0.05, 0, 0.45))),
tuple(obj.matrix_world @ Vector((0, 0.05, 0.45))),
tuple(obj.matrix_world @ Vector((0, -0.05, 0.45))),
]
special_edges = [(0, 1), (1, 2), (1, 3), (1, 4), (1, 5)]
return {
"verts": verts,
"edges": edges,
"tris": tris,
"special_verts": special_verts,
"special_edges": special_edges,
}
@classmethod
def uninstall(cls):
@@ -157,11 +178,14 @@ class ItemDecorator:
continue
self.draw_batch("LINES", data["verts"], selected_elements_color, data["edges"])
self.draw_batch("TRIS", data["verts"], transparent_color(selected_elements_color), data["tris"])
self.draw_batch("LINES", data["special_verts"], selected_elements_color, data["special_edges"])
elif self.obj_is_boolean[obj_name]:
self.draw_batch("LINES", data["verts"], special_elements_color, data["edges"])
self.draw_batch("TRIS", data["verts"], transparent_color(special_elements_color), data["tris"])
self.draw_batch("LINES", data["special_verts"], special_elements_color, data["special_edges"])
else:
self.draw_batch(
"LINES", data["verts"], transparent_color(unselected_elements_color, alpha=0.2), data["edges"]
)
self.draw_batch("TRIS", data["verts"], transparent_color(special_elements_color), data["tris"])
self.draw_batch("LINES", data["special_verts"], special_elements_color, data["special_edges"])
@@ -2933,6 +2933,64 @@ class AddCurvelikeItem(bpy.types.Operator, tool.Ifc.Operator):
tool.Geometry.import_item_attributes(obj)
class AddHalfSpaceSolidItem(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_half_space_solid_item"
bl_label = "Add Half Space Solid Item"
bl_options = {"REGISTER", "UNDO"}
def _execute(self, context):
if (
not tool.Blender.get_selected_objects()
or not (active_obj := tool.Blender.get_active_object())
or not tool.Geometry.is_representation_item(active_obj)
):
# In theory we can have half space solid as a top level item but let's not go there today.
self.report({"ERROR"}, "Select an item to apply the half space solid to.")
return {"CANCELLED"}
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.show_in_front = True
obj.matrix_world = matrix
tool.Geometry.record_object_position(obj)
ifc_file = tool.Ifc.get()
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
local_z = ifc_file.createIfcDirection((0.0, 0.0, 1.0))
local_x = ifc_file.createIfcDirection((1.0, 0.0, 0.0))
point = ifc_file.createIfcCartesianPoint((np.array(local_matrix.translation) / unit_scale).tolist())
placement = ifc_file.createIfcAxis2Placement3D(point, local_z, local_x)
plane = ifc_file.createIfcPlane(placement)
item = ifc_file.createIfcHalfSpaceSolid(plane, AgreementFlag=False)
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)
# TODO refactor to core and not rely on selection
tool.Blender.select_and_activate_single_object(context, active_obj)
tool.Blender.select_object(obj)
bpy.ops.bim.add_boolean()
class OverrideMoveAggregateMacro(bpy.types.Macro):
bl_idname = "bim.override_move_aggregate_macro"
bl_label = "IFC Move Aggregate"
@@ -309,6 +309,8 @@ class BIM_MT_add_representation_item(Menu):
"ICOSPHERE"
)
self.layout.operator("bim.add_meshlike_item", icon="MESH_CYLINDER", text="Mesh Cylinder").shape = "CYLINDER"
self.layout.separator()
self.layout.operator("bim.add_half_space_solid_item", icon="ORIENTATION_NORMAL", text="Half Space Solid")
if ItemData.data["representation_type"] in ("SolidModel", "SweptSolid"):
self.layout.operator(
@@ -317,6 +319,8 @@ class BIM_MT_add_representation_item(Menu):
self.layout.operator(
"bim.add_swept_area_solid_item", icon="MESH_CYLINDER", text="Extruded Area Solid Cylinder"
).shape = "CYLINDER"
self.layout.separator()
self.layout.operator("bim.add_half_space_solid_item", icon="ORIENTATION_NORMAL", text="Half Space Solid")
if ItemData.data["representation_type"] in ("Annotation2D"):
self.layout.operator("bim.add_curvelike_item", icon="IPO_CONSTANT", text="Polycurve").shape = "LINE"