mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-23 14:16:22 +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.EnableEditingText,
|
||||||
operator.EnableEditingTextProduct,
|
operator.EnableEditingTextProduct,
|
||||||
operator.ExpandSheet,
|
operator.ExpandSheet,
|
||||||
operator.GenerateReferences,
|
|
||||||
operator.LoadDrawings,
|
operator.LoadDrawings,
|
||||||
operator.LoadSheets,
|
operator.LoadSheets,
|
||||||
operator.OpenSheet,
|
operator.OpenSheet,
|
||||||
|
|||||||
@@ -738,68 +738,6 @@ class SelectDocIfcFile(bpy.types.Operator):
|
|||||||
return {"RUNNING_MODAL"}
|
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):
|
class ResizeText(bpy.types.Operator):
|
||||||
bl_idname = "bim.resize_text"
|
bl_idname = "bim.resize_text"
|
||||||
bl_label = "Resize Text"
|
bl_label = "Resize Text"
|
||||||
|
|||||||
@@ -62,8 +62,6 @@ class BIM_PT_camera(Panel):
|
|||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(props, "is_nts")
|
row.prop(props, "is_nts")
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
row.operator("bim.generate_references")
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.operator("bim.resize_text")
|
row.operator("bim.resize_text")
|
||||||
|
|
||||||
|
|||||||
@@ -408,6 +408,10 @@ class Drawing(blenderbim.core.tool.Drawing):
|
|||||||
elements.append(element)
|
elements.append(element)
|
||||||
for element in tool.Ifc.get().by_type("IfcGridAxis"):
|
for element in tool.Ifc.get().by_type("IfcGridAxis"):
|
||||||
elements.append(element)
|
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
|
return elements
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -437,6 +441,72 @@ class Drawing(blenderbim.core.tool.Drawing):
|
|||||||
return cls.generate_elevation_reference_annotation(drawing, reference_element, context)
|
return cls.generate_elevation_reference_annotation(drawing, reference_element, context)
|
||||||
elif target_view == "SECTION_VIEW":
|
elif target_view == "SECTION_VIEW":
|
||||||
return cls.generate_section_reference_annotation(drawing, reference_element, context)
|
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
|
@classmethod
|
||||||
def generate_section_reference_annotation(cls, drawing, reference_element, context):
|
def generate_section_reference_annotation(cls, drawing, reference_element, context):
|
||||||
|
|||||||
Reference in New Issue
Block a user