Add support for adding curvelike items

This commit is contained in:
Dion Moult
2024-10-10 18:34:20 +11:00
parent bd42fc9cef
commit 47f013fc18
5 changed files with 69 additions and 9 deletions
@@ -20,6 +20,7 @@ import bpy
from . import ui, prop, operator
classes = (
operator.AddCurvelikeItem,
operator.AddMeshlikeItem,
operator.AddRepresentation,
operator.AddSweptAreaSolidItem,
@@ -2637,7 +2637,7 @@ class AddSweptAreaSolidItem(bpy.types.Operator, tool.Ifc.Operator):
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)
curve = builder.circle(radius=0.25 / unit_scale)
item = builder.extrude(
curve,
magnitude=0.5 / unit_scale,
@@ -2656,3 +2656,59 @@ class AddSweptAreaSolidItem(bpy.types.Operator, tool.Ifc.Operator):
obj.data.BIMMeshProperties.ifc_definition_id = item.id()
tool.Geometry.import_item(obj)
tool.Geometry.import_item_attributes(obj)
class AddCurvelikeItem(bpy.types.Operator, tool.Ifc.Operator):
bl_idname = "bim.add_curvelike_item"
bl_label = "Add Curvelike Item"
bl_options = {"REGISTER", "UNDO"}
shape: bpy.props.StringProperty(name="Shape")
def _execute(self, context):
props = context.scene.BIMGeometryProperties
representation = tool.Geometry.get_active_representation(props.representation_obj)
is_2d = representation.ContextOfItems.ContextType == "Plan"
representation = ifcopenshell.util.representation.resolve_representation(representation)
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
tool.Geometry.lock_object(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)
builder = ifcopenshell.util.shape_builder.ShapeBuilder(tool.Ifc.get())
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
offset = local_matrix.translation.to_2d() / unit_scale
if not is_2d:
offset = offset.to_3d()
if self.shape == "LINE":
if is_2d:
points = [Vector((0, 0)), Vector((0.5 / unit_scale, 0))]
else:
points = [Vector((0, 0, 0)), Vector((0.5 / unit_scale, 0, 0))]
item = builder.polyline(points=points, position_offset=offset)
elif self.shape == "CIRCLE":
item = builder.circle(radius=0.25 / unit_scale, center=offset)
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)
@@ -308,6 +308,10 @@ class BIM_MT_add_representation_item(Menu):
"bim.add_swept_area_solid_item", icon="MESH_CYLINDER", text="Extruded Area Solid Cylinder"
).shape = "CYLINDER"
if ItemData.data["representation_type"] in ("Annotation2D"):
self.layout.operator("bim.add_curvelike_item", icon="IPO_CONSTANT", text="Polycurve").shape = "LINE"
self.layout.operator("bim.add_curvelike_item", icon="MESH_CIRCLE", text="Circle").shape = "CIRCLE"
class CreateObjectUI:
@classmethod
+3 -3
View File
@@ -871,7 +871,7 @@ class Geometry(bonsai.core.tool.Geometry):
@classmethod
def is_movable(cls, item: ifcopenshell.entity_instance) -> bool:
return item.is_a("IfcSweptAreaSolid") or item.is_a("IfcConic")
return item.is_a("IfcSweptAreaSolid")
@classmethod
def is_profile_based(cls, data: bpy.types.Mesh) -> bool:
@@ -1471,7 +1471,7 @@ class Geometry(bonsai.core.tool.Geometry):
if not (obj := item_obj.obj):
continue
item = tool.Ifc.get().by_id(obj.data.BIMMeshProperties.ifc_definition_id)
if (is_swept_area := item.is_a("IfcSweptAreaSolid")) or item.is_a("IfcConic"):
if (is_swept_area := item.is_a("IfcSweptAreaSolid")):
if not tool.Ifc.is_moved(obj):
continue
has_changed = True
@@ -1529,7 +1529,7 @@ class Geometry(bonsai.core.tool.Geometry):
obj.matrix_world = rep_obj.matrix_world.copy()
if (is_swept_area := item.is_a("IfcSweptAreaSolid")) or item.is_a("IfcConic"):
if (is_swept_area := item.is_a("IfcSweptAreaSolid")):
position = item.Position
# Positional is optional only for SweptAreaSolid.
if position or not is_swept_area:
+4 -5
View File
@@ -455,14 +455,13 @@ class Model(bonsai.core.tool.Model):
if is_closed:
cls.edges.append([len(cls.vertices) - 1, offset]) # Close the loop
elif curve.is_a("IfcCircle"):
center = cls.convert_unit_to_si(
Matrix(ifcopenshell.util.placement.get_axis2placement(curve.Position).tolist()).translation
)
circle_position = Matrix(ifcopenshell.util.placement.get_axis2placement(curve.Position).tolist())
circle_position.translation *= cls.unit_scale
radius = cls.convert_unit_to_si(curve.Radius)
cls.vertices.extend(
[
position @ Vector((center[0], center[1] - radius, 0.0)),
position @ Vector((center[0], center[1] + radius, 0.0)),
position @ circle_position @ Vector((0, 0 - radius, 0.0)),
position @ circle_position @ Vector((0, 0 + radius, 0.0)),
]
)
cls.circles.append([offset, offset + 1])