mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 18:43:26 +00:00
Clever STAIR_ARROW annotation
Now adding STAIR_ARROW annotation is a bit more clever - if you have IfcStairFlight selected when adding this type of annotation it will automatically: 1) define stair as it's parent; 2) add the stair as it's product; 3) place itself along the stair (it's assumed that stair direction is X+) Example - https://i.imgur.com/Ze9DoK2.png
This commit is contained in:
@@ -286,6 +286,7 @@ def update_ifc_stair_props(obj):
|
||||
},
|
||||
)
|
||||
tool.Ifc.edit(obj)
|
||||
# TODO: update related STAIR_ARROW products
|
||||
|
||||
|
||||
class BIM_OT_add_clever_stair(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
@@ -232,6 +232,7 @@ def add_annotation(ifc, collector, drawing_tool, drawing=None, object_type=None)
|
||||
)
|
||||
ifc.run("group.assign_group", group=drawing_tool.get_drawing_group(drawing), products=[element])
|
||||
collector.assign(obj)
|
||||
drawing_tool.setup_annotation_object(obj, object_type)
|
||||
drawing_tool.enable_editing(obj)
|
||||
|
||||
|
||||
|
||||
@@ -71,16 +71,21 @@ class Aggregate:
|
||||
|
||||
|
||||
@interface
|
||||
class Blender: pass
|
||||
def create_ifc_object(cls, ifc_class, name, data): pass
|
||||
def get_name(cls, ifc_class, name): pass
|
||||
def get_obj_ifc_definition_id(cls, obj, obj_type): pass
|
||||
def get_selected_objects(cls): pass
|
||||
def set_active_object(cls, obj): pass
|
||||
def apply_bmesh(cls, mesh, bm): pass
|
||||
def get_bmesh_for_mesh(cls, mesh, clean=False): pass
|
||||
def get_viewport_context(cls): pass
|
||||
def update_viewport(cls): pass
|
||||
class Blender:
|
||||
def set_active_object(cls, obj): pass
|
||||
def get_name(cls, ifc_class, name): pass
|
||||
def get_selected_objects(cls): pass
|
||||
def create_ifc_object(cls, ifc_class: str, name: str = None, data=None): pass
|
||||
def get_obj_ifc_definition_id(cls, obj=None, obj_type=None): pass
|
||||
def is_ifc_object(cls, obj): pass
|
||||
def is_ifc_class_active(cls, ifc_class): pass
|
||||
def get_viewport_context(cls): pass
|
||||
def update_viewport(cls): pass
|
||||
def get_default_selection_keypmap(cls): pass
|
||||
def get_object_bounding_box(cls, obj): pass
|
||||
def apply_bmesh(cls, mesh, bm): pass
|
||||
def get_bmesh_for_mesh(cls, mesh, clean=False): pass
|
||||
def bmesh_join(cls, bm_a, bm_b, callback=None): pass
|
||||
|
||||
|
||||
@interface
|
||||
@@ -223,6 +228,7 @@ class Drawing:
|
||||
def activate_view(cls, camera): pass
|
||||
def copy_representation(cls, source, dest): pass
|
||||
def create_annotation_object(cls, drawing, object_type): pass
|
||||
def setup_annotation_object(cls, obj, object_type): pass
|
||||
def create_camera(cls, name, matrix): pass
|
||||
def create_svg_schedule(cls, schedule): pass
|
||||
def create_svg_sheet(cls, document, titleblock): pass
|
||||
|
||||
@@ -160,6 +160,24 @@ class Blender:
|
||||
)
|
||||
return keymap
|
||||
|
||||
@classmethod
|
||||
def get_object_bounding_box(cls, obj):
|
||||
"""Returns dict with local min and max x, y, z values for the object.
|
||||
|
||||
Careful with using this method for objects in EDIT mode because
|
||||
it requires all EDIT mode changes to be applied.
|
||||
"""
|
||||
bound_box = obj.bound_box
|
||||
bbox_dict = {
|
||||
"min_x": bound_box[0][0],
|
||||
"max_x": bound_box[6][0],
|
||||
"min_y": bound_box[0][1],
|
||||
"max_y": bound_box[6][1],
|
||||
"min_z": bound_box[0][2],
|
||||
"max_z": bound_box[6][2],
|
||||
}
|
||||
return bbox_dict
|
||||
|
||||
## BMESH UTILS ##
|
||||
@classmethod
|
||||
def apply_bmesh(cls, mesh, bm):
|
||||
|
||||
@@ -38,6 +38,8 @@ import blenderbim.bim.module.drawing.helper as helper
|
||||
from blenderbim.bim.module.drawing.data import FONT_SIZES, DecoratorData
|
||||
from blenderbim.bim.module.drawing.prop import get_diagram_scales, BOX_ALIGNMENT_POSITIONS
|
||||
|
||||
from mathutils import Vector
|
||||
|
||||
|
||||
class Drawing(blenderbim.core.tool.Drawing):
|
||||
@classmethod
|
||||
@@ -74,8 +76,27 @@ class Drawing(blenderbim.core.tool.Drawing):
|
||||
obj = annotation.Annotator.add_line_to_annotation(obj, co2, co1)
|
||||
elif object_type != "TEXT":
|
||||
obj = annotation.Annotator.add_line_to_annotation(obj)
|
||||
|
||||
return obj
|
||||
|
||||
@classmethod
|
||||
def setup_annotation_object(cls, obj, object_type):
|
||||
"""Finish object's adjustments after both object and entity are created"""
|
||||
if object_type == "STAIR_ARROW":
|
||||
stair = bpy.context.active_object
|
||||
stair_entity = tool.Ifc.get_entity(stair)
|
||||
if stair_entity and stair_entity.is_a("IfcStairFlight"):
|
||||
arrow = obj
|
||||
arrow_element = tool.Ifc.get_entity(arrow)
|
||||
arrow.parent = stair
|
||||
|
||||
# place the arrow
|
||||
bbox = tool.Blender.get_object_bounding_box(stair)
|
||||
arrow.location = Vector((bbox["min_x"], (bbox["max_y"] - bbox["min_y"]) / 2, bbox["max_z"]))
|
||||
arrow.data.splines[0].points[1].co = Vector((bbox["max_x"], 0, 0, 1))
|
||||
|
||||
tool.Ifc.run("drawing.assign_product", relating_product=stair_entity, related_object=arrow_element)
|
||||
|
||||
@classmethod
|
||||
def create_camera(cls, name, matrix):
|
||||
camera = bpy.data.objects.new(name, bpy.data.cameras.new(name))
|
||||
|
||||
@@ -321,6 +321,7 @@ class TestAddAnnotation:
|
||||
drawing.get_drawing_group("drawing").should_be_called().will_return("group")
|
||||
ifc.run("group.assign_group", group="group", products=["element"]).should_be_called()
|
||||
collector.assign("obj").should_be_called()
|
||||
drawing.setup_annotation_object("obj", "object_type").should_be_called()
|
||||
drawing.enable_editing("obj").should_be_called()
|
||||
subject.add_annotation(ifc, collector, drawing, drawing="drawing", object_type="object_type")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user