mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
#1153 Storey level annotations are now automatically generated for sections and elevations
This commit is contained in:
@@ -47,7 +47,6 @@ classes = (
|
||||
operator.EnableEditingText,
|
||||
operator.EnableEditingTextProduct,
|
||||
operator.ExpandSheet,
|
||||
operator.GenerateReferences,
|
||||
operator.LoadDrawings,
|
||||
operator.LoadSheets,
|
||||
operator.OpenSheet,
|
||||
|
||||
@@ -738,68 +738,6 @@ class SelectDocIfcFile(bpy.types.Operator):
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
|
||||
class GenerateReferences(bpy.types.Operator):
|
||||
bl_idname = "bim.generate_references"
|
||||
bl_label = "Generate References"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
self.camera = context.scene.camera
|
||||
self.filter_potential_references()
|
||||
if self.camera.data.BIMCameraProperties.target_view == "PLAN_VIEW":
|
||||
self.generate_grids()
|
||||
if self.camera.data.BIMCameraProperties.target_view == "ELEVATION_VIEW":
|
||||
self.generate_grids()
|
||||
self.generate_levels(context)
|
||||
if self.camera.data.BIMCameraProperties.target_view == "SECTION_VIEW":
|
||||
self.generate_grids()
|
||||
self.generate_levels(context)
|
||||
return {"FINISHED"}
|
||||
|
||||
def filter_potential_references(self):
|
||||
for name in ["grids", "levels"]:
|
||||
setattr(self, name, [])
|
||||
for obj in bpy.data.objects:
|
||||
if "IfcGridAxis/" in obj.name:
|
||||
self.grids.append(obj)
|
||||
if "IfcBuildingStorey/" in obj.name:
|
||||
self.levels.append(obj)
|
||||
|
||||
def generate_grids(self):
|
||||
# TODO
|
||||
pass
|
||||
|
||||
def generate_levels(self, context):
|
||||
if self.camera.data.BIMCameraProperties.raster_x > self.camera.data.BIMCameraProperties.raster_y:
|
||||
width = self.camera.data.ortho_scale
|
||||
height = (
|
||||
width / self.camera.data.BIMCameraProperties.raster_x * self.camera.data.BIMCameraProperties.raster_y
|
||||
)
|
||||
else:
|
||||
height = self.camera.data.ortho_scale
|
||||
width = (
|
||||
height / self.camera.data.BIMCameraProperties.raster_y * self.camera.data.BIMCameraProperties.raster_x
|
||||
)
|
||||
level_obj = annotation.Annotator.get_annotation_obj("Section Level", "curve", context)
|
||||
|
||||
width_in_mm = width * 1000
|
||||
real_world_width_in_mm = width_in_mm * scale
|
||||
offset_in_mm = 20
|
||||
offset_percentage = offset_in_mm / real_world_width_in_mm
|
||||
|
||||
for obj in self.levels:
|
||||
projection = self.project_point_onto_camera(obj.location)
|
||||
co1 = self.camera.matrix_world @ Vector((width / 2 - (offset_percentage * width), projection[1], -1))
|
||||
co2 = self.camera.matrix_world @ Vector((-(width / 2), projection[1], -1))
|
||||
annotation.Annotator.add_line_to_annotation(level_obj, context, co1, co2)
|
||||
|
||||
def project_point_onto_camera(self, point):
|
||||
projection = self.camera.matrix_world.to_quaternion() @ Vector((0, 0, -1))
|
||||
return self.camera.matrix_world.inverted() @ geometry.intersect_line_plane(
|
||||
point.xyz, point.xyz - projection, self.camera.location, projection
|
||||
)
|
||||
|
||||
|
||||
class ResizeText(bpy.types.Operator):
|
||||
bl_idname = "bim.resize_text"
|
||||
bl_label = "Resize Text"
|
||||
|
||||
@@ -62,8 +62,6 @@ class BIM_PT_camera(Panel):
|
||||
row = layout.row()
|
||||
row.prop(props, "is_nts")
|
||||
|
||||
row = layout.row()
|
||||
row.operator("bim.generate_references")
|
||||
row = layout.row()
|
||||
row.operator("bim.resize_text")
|
||||
|
||||
|
||||
@@ -408,6 +408,10 @@ class Drawing(blenderbim.core.tool.Drawing):
|
||||
elements.append(element)
|
||||
for element in tool.Ifc.get().by_type("IfcGridAxis"):
|
||||
elements.append(element)
|
||||
target_view = tool.Drawing.get_drawing_target_view(drawing)
|
||||
if target_view in ("SECTION_VIEW", "ELEVATION_VIEW"):
|
||||
for element in tool.Ifc.get().by_type("IfcBuildingStorey"):
|
||||
elements.append(element)
|
||||
return elements
|
||||
|
||||
@classmethod
|
||||
@@ -437,6 +441,72 @@ class Drawing(blenderbim.core.tool.Drawing):
|
||||
return cls.generate_elevation_reference_annotation(drawing, reference_element, context)
|
||||
elif target_view == "SECTION_VIEW":
|
||||
return cls.generate_section_reference_annotation(drawing, reference_element, context)
|
||||
elif reference_element.is_a("IfcBuildingStorey"):
|
||||
return cls.generate_storey_annotation(drawing, reference_element, context)
|
||||
|
||||
@classmethod
|
||||
def generate_storey_annotation(cls, drawing, reference_element, context):
|
||||
camera = tool.Ifc.get_object(drawing)
|
||||
bounds = helper.ortho_view_frame(camera.data) if camera.data.type == "ORTHO" else None
|
||||
reference_obj = tool.Ifc.get_object(reference_element)
|
||||
|
||||
def to_camera_coords(camera, reference_obj):
|
||||
mat = reference_obj.matrix_world.copy()
|
||||
xyz = camera.matrix_world.inverted() @ reference_obj.matrix_world.translation
|
||||
xyz[2] = 0
|
||||
xyz = camera.matrix_world @ xyz
|
||||
mat[0][3] = xyz[0]
|
||||
mat[1][3] = xyz[1]
|
||||
mat[2][3] = xyz[2]
|
||||
annotation_offset = mathutils.Vector((0, 0, -camera.data.clip_start - 0.05))
|
||||
annotation_offset = camera.matrix_world.to_quaternion() @ annotation_offset
|
||||
mat[0][3] += annotation_offset[0]
|
||||
mat[1][3] += annotation_offset[1]
|
||||
mat[2][3] += annotation_offset[2]
|
||||
return mat
|
||||
|
||||
def project_point_onto_camera(point, camera):
|
||||
projection = camera.matrix_world.to_quaternion() @ mathutils.Vector((0, 0, -1))
|
||||
return camera.matrix_world.inverted() @ mathutils.geometry.intersect_line_plane(
|
||||
point.xyz, point.xyz - projection, camera.location, projection
|
||||
)
|
||||
|
||||
obj_matrix = to_camera_coords(camera, reference_obj)
|
||||
|
||||
if camera.data.BIMCameraProperties.raster_x > camera.data.BIMCameraProperties.raster_y:
|
||||
width = camera.data.ortho_scale
|
||||
height = width / camera.data.BIMCameraProperties.raster_x * camera.data.BIMCameraProperties.raster_y
|
||||
else:
|
||||
height = camera.data.ortho_scale
|
||||
width = height / camera.data.BIMCameraProperties.raster_y * camera.data.BIMCameraProperties.raster_x
|
||||
|
||||
projection = project_point_onto_camera(reference_obj.location, camera)
|
||||
co1 = camera.matrix_world @ mathutils.Vector((width / 2, projection[1], -1))
|
||||
co2 = camera.matrix_world @ mathutils.Vector((-(width / 2), projection[1], -1))
|
||||
co1 = obj_matrix.inverted() @ co1
|
||||
co2 = obj_matrix.inverted() @ co2
|
||||
|
||||
data = bpy.data.curves.new("Annotation", type="CURVE")
|
||||
data.dimensions = "3D"
|
||||
data.resolution_u = 2
|
||||
|
||||
polyline = data.splines.new("POLY")
|
||||
polyline.points.add(1)
|
||||
polyline.points[-2].co = list(co1) + [1]
|
||||
polyline.points[-1].co = list(co2) + [1]
|
||||
|
||||
obj = bpy.data.objects.new(reference_obj.name, data)
|
||||
obj.matrix_world = obj_matrix
|
||||
|
||||
element = cls.run_root_assign_class(
|
||||
obj=obj,
|
||||
ifc_class="IfcAnnotation",
|
||||
predefined_type="SECTION_LEVEL",
|
||||
should_add_representation=True,
|
||||
context=context,
|
||||
ifc_representation_class=None,
|
||||
)
|
||||
return element
|
||||
|
||||
@classmethod
|
||||
def generate_section_reference_annotation(cls, drawing, reference_element, context):
|
||||
|
||||
Reference in New Issue
Block a user