mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Add manual drawing reference annotation operator
Adds operator to place manual elevation/section drawing reference tags that survive drawing regeneration. Includes core function, tool methods, type-selection dialog, default horizontal rotation for elevation tags, and SVG null guard for unassigned references. Generated with the assistance of an AI coding tool.
This commit is contained in:
@@ -30,6 +30,7 @@ classes = (
|
||||
operator.ActivateModel,
|
||||
operator.AddAnnotation,
|
||||
operator.AddAnnotationType,
|
||||
operator.AddManualDrawingReference,
|
||||
operator.AddDrawing,
|
||||
operator.AddDrawingStyle,
|
||||
operator.AddDrawingToSheet,
|
||||
|
||||
@@ -1761,6 +1761,49 @@ class AddAnnotation(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", existing_object_by_name=obj.name)
|
||||
|
||||
|
||||
class AddManualDrawingReference(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_manual_drawing_reference"
|
||||
bl_label = "Add Manual Drawing Reference"
|
||||
bl_description = "Place a manual elevation or section tag that will not be moved or deleted during drawing regeneration"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
annotation_type: bpy.props.EnumProperty(
|
||||
name="Type",
|
||||
items=[
|
||||
("ELEVATION", "Elevation", "Place a manual elevation tag"),
|
||||
("SECTION", "Section", "Place a manual section tag"),
|
||||
],
|
||||
default="ELEVATION",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not tool.Ifc.get():
|
||||
return False
|
||||
if not context.scene.camera:
|
||||
cls.poll_message_set("No active drawing.")
|
||||
return False
|
||||
return True
|
||||
|
||||
def invoke(self, context, event):
|
||||
return context.window_manager.invoke_props_dialog(self)
|
||||
|
||||
def draw(self, context):
|
||||
self.layout.prop(self, "annotation_type")
|
||||
|
||||
def _execute(self, context):
|
||||
dprops = tool.Drawing.get_document_props()
|
||||
if not (drawing := dprops.get_active_drawing()):
|
||||
self.report({"WARNING"}, "No active drawing.")
|
||||
return
|
||||
core.add_manual_drawing_reference(
|
||||
tool.Ifc,
|
||||
tool.Collector,
|
||||
tool.Drawing,
|
||||
drawing=drawing,
|
||||
annotation_type=self.annotation_type,
|
||||
)
|
||||
|
||||
|
||||
class AddSheet(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_sheet"
|
||||
bl_label = "Add Sheet"
|
||||
|
||||
@@ -895,6 +895,8 @@ class SvgWriter:
|
||||
reference_id = "-"
|
||||
sheet_id = "-"
|
||||
drawing = tool.Drawing.get_annotation_element(element)
|
||||
if not drawing:
|
||||
return ("-", "-")
|
||||
reference = tool.Drawing.get_drawing_reference(drawing)
|
||||
if reference:
|
||||
for sheet_reference in tool.Ifc.get().by_type("IfcDocumentReference"):
|
||||
|
||||
@@ -506,6 +506,28 @@ def add_annotation(
|
||||
return obj
|
||||
|
||||
|
||||
def add_manual_drawing_reference(
|
||||
ifc: type[tool.Ifc],
|
||||
collector: type[tool.Collector],
|
||||
drawing_tool: type[tool.Drawing],
|
||||
drawing: ifcopenshell.entity_instance,
|
||||
annotation_type: str,
|
||||
) -> bpy.types.Object:
|
||||
if annotation_type == "ELEVATION":
|
||||
element = drawing_tool.create_manual_elevation_reference(drawing)
|
||||
else: # SECTION
|
||||
target_view = drawing_tool.get_drawing_target_view(drawing)
|
||||
context = drawing_tool.get_annotation_context(target_view)
|
||||
if not context:
|
||||
context = drawing_tool.create_annotation_context(target_view, annotation_type)
|
||||
element = drawing_tool.create_manual_section_reference(drawing, context)
|
||||
drawing_tool.set_manual_drawing_reference(element)
|
||||
ifc.run("group.assign_group", group=drawing_tool.get_drawing_group(drawing), products=[element])
|
||||
obj = ifc.get_object(element)
|
||||
collector.assign(obj)
|
||||
return obj
|
||||
|
||||
|
||||
def build_schedule(drawing: type[tool.Drawing], schedule: ifcopenshell.entity_instance) -> None:
|
||||
drawing.create_svg_schedule(schedule)
|
||||
drawing.open_svg(drawing.get_path_with_ext(drawing.get_document_uri(schedule), "svg"))
|
||||
|
||||
@@ -1864,6 +1864,48 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
element.Name = elevation.Name or "Unnamed"
|
||||
return element
|
||||
|
||||
@classmethod
|
||||
def create_manual_elevation_reference(cls, drawing: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance:
|
||||
cursor_location = bpy.context.scene.cursor.location.copy()
|
||||
obj = bpy.data.objects.new("Unnamed", None)
|
||||
obj.empty_display_size = 0.1
|
||||
obj.matrix_world = Matrix.Translation(cursor_location) @ Matrix.Rotation(math.radians(90), 4, "X")
|
||||
element = cls.run_root_assign_class(
|
||||
obj=obj, ifc_class="IfcAnnotation", predefined_type="ELEVATION", should_add_representation=False
|
||||
)
|
||||
element.Name = "Unnamed"
|
||||
return element
|
||||
|
||||
@classmethod
|
||||
def create_manual_section_reference(
|
||||
cls, drawing: ifcopenshell.entity_instance, context: ifcopenshell.entity_instance
|
||||
) -> ifcopenshell.entity_instance:
|
||||
cursor_location = bpy.context.scene.cursor.location.copy()
|
||||
mesh = bpy.data.meshes.new("Mesh")
|
||||
obj = bpy.data.objects.new("Unnamed", mesh)
|
||||
obj.matrix_world = Matrix.Translation(cursor_location)
|
||||
element = cls.run_root_assign_class(
|
||||
obj=obj, ifc_class="IfcAnnotation", predefined_type="SECTION", should_add_representation=False
|
||||
)
|
||||
element.Name = "Unnamed"
|
||||
builder = ShapeBuilder(tool.Ifc.get())
|
||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
p1 = cursor_location + Vector((-0.5, 0, 0))
|
||||
p2 = cursor_location + Vector((0.5, 0, 0))
|
||||
points = [p1 / unit_scale, p2 / unit_scale]
|
||||
representation = builder.get_representation(context, [builder.polyline(points)])
|
||||
ifcopenshell.api.geometry.assign_representation(tool.Ifc.get(), element, representation)
|
||||
bonsai.core.geometry.switch_representation(tool.Ifc, tool.Geometry, obj=obj, representation=representation)
|
||||
return element
|
||||
|
||||
@classmethod
|
||||
def set_manual_drawing_reference(cls, element: ifcopenshell.entity_instance) -> None:
|
||||
ifc_file = tool.Ifc.get()
|
||||
pset = tool.Pset.get_element_pset(element, "EPset_Annotation")
|
||||
if not pset:
|
||||
pset = ifcopenshell.api.pset.add_pset(ifc_file, product=element, name="EPset_Annotation")
|
||||
ifcopenshell.api.pset.edit_pset(ifc_file, pset=pset, properties={"IsManualDrawingReference": True})
|
||||
|
||||
@classmethod
|
||||
def regenerate_elevation_reference_annotation(
|
||||
cls,
|
||||
|
||||
Reference in New Issue
Block a user