mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Old annotation systems now creates IFC elements again. Also text and misc annotations now work again with new system. See #1153.
This commit is contained in:
@@ -14,14 +14,14 @@ def mode_callback(obj, data):
|
||||
if (
|
||||
obj.mode != "EDIT"
|
||||
or not obj.data
|
||||
or not isinstance(obj.data, bpy.types.Mesh)
|
||||
or not isinstance(obj.data, (bpy.types.Mesh, bpy.types.Curve, bpy.types.TextCurve))
|
||||
or not obj.BIMObjectProperties.ifc_definition_id
|
||||
or not bpy.context.scene.BIMProjectProperties.is_authoring
|
||||
):
|
||||
return
|
||||
if obj.data.BIMMeshProperties.ifc_definition_id:
|
||||
representation = IfcStore.get_file().by_id(obj.data.BIMMeshProperties.ifc_definition_id)
|
||||
if representation.RepresentationType == "Tessellation" or representation.RepresentationType == "Brep":
|
||||
if representation.RepresentationType in ["Tessellation", "Brep", "Annotation2D"]:
|
||||
IfcStore.edited_objs.add(obj.name)
|
||||
elif IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id).is_a("IfcGridAxis"):
|
||||
IfcStore.edited_objs.add(obj.name)
|
||||
|
||||
@@ -17,9 +17,9 @@ class Annotator:
|
||||
|
||||
@staticmethod
|
||||
def add_text(related_element=None):
|
||||
curve = bpy.data.curves.new(type="FONT", name="Plan/Annotation/PLAN_VIEW/Text")
|
||||
curve = bpy.data.curves.new(type="FONT", name="Text")
|
||||
curve.body = "TEXT"
|
||||
obj = bpy.data.objects.new("IfcAnnotation/Text", curve)
|
||||
obj = bpy.data.objects.new("Text", curve)
|
||||
obj.matrix_world = bpy.context.scene.camera.matrix_world
|
||||
if related_element is None:
|
||||
location, _, _, _ = Annotator.get_placeholder_coords()
|
||||
@@ -138,12 +138,12 @@ class Annotator:
|
||||
if name in obj.name:
|
||||
return obj
|
||||
if data_type == "mesh":
|
||||
data = bpy.data.meshes.new("Plan/Annotation/PLAN_VIEW/" + name)
|
||||
data = bpy.data.meshes.new(name)
|
||||
elif data_type == "curve":
|
||||
data = bpy.data.curves.new("Plan/Annotation/PLAN_VIEW/" + name, type="CURVE")
|
||||
data = bpy.data.curves.new(name, type="CURVE")
|
||||
data.dimensions = "3D"
|
||||
data.resolution_u = 2
|
||||
obj = bpy.data.objects.new("IfcAnnotation/" + name, data)
|
||||
obj = bpy.data.objects.new(name, data)
|
||||
collection.objects.link(obj)
|
||||
return obj
|
||||
|
||||
@@ -164,4 +164,4 @@ class Annotator:
|
||||
return (camera.location + z_offset,
|
||||
camera.location + z_offset + y_offset,
|
||||
camera.location + z_offset + x_offset,
|
||||
camera.location + z_offset + x_offset + y_offset)
|
||||
camera.location + z_offset + x_offset + y_offset)
|
||||
|
||||
@@ -3,6 +3,7 @@ import bpy
|
||||
import json
|
||||
import subprocess
|
||||
import webbrowser
|
||||
import ifcopenshell.util.representation
|
||||
import blenderbim.bim.module.drawing.svgwriter as svgwriter
|
||||
import blenderbim.bim.module.drawing.annotation as annotation
|
||||
from mathutils import Vector, Matrix, Euler, geometry
|
||||
@@ -13,6 +14,7 @@ from ifcopenshell.api.pset.data import Data as PsetData
|
||||
|
||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
|
||||
class AddDrawing(bpy.types.Operator):
|
||||
bl_idname = "bim.add_drawing"
|
||||
bl_label = "Add Drawing"
|
||||
@@ -69,7 +71,7 @@ class CreateDrawing(bpy.types.Operator):
|
||||
def combine_svgs(self, context, base, annotation):
|
||||
# Hacky :)
|
||||
svg_path = context.scene.BIMProperties.ifc_file[0:-4] + ".svg"
|
||||
with open(svg_path, 'w') as outfile:
|
||||
with open(svg_path, "w") as outfile:
|
||||
with open(base) as infile:
|
||||
for line in infile:
|
||||
if "</svg>" in line:
|
||||
@@ -197,6 +199,11 @@ class AddAnnotation(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
if not bpy.context.scene.camera:
|
||||
return {"FINISHED"}
|
||||
subcontext = ifcopenshell.util.representation.get_context(
|
||||
IfcStore.get_file(), "Plan", "Annotation", context.scene.camera.data.BIMCameraProperties.target_view
|
||||
)
|
||||
if not subcontext:
|
||||
return {"FINISHED"}
|
||||
if self.data_type == "text":
|
||||
if bpy.context.selected_objects:
|
||||
for selected_object in bpy.context.selected_objects:
|
||||
@@ -209,7 +216,14 @@ class AddAnnotation(bpy.types.Operator):
|
||||
obj = annotation.Annotator.add_plane_to_annotation(obj)
|
||||
else:
|
||||
obj = annotation.Annotator.add_line_to_annotation(obj)
|
||||
|
||||
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||
bpy.ops.bim.assign_class(obj=obj.name, ifc_class="IfcAnnotation", context_id=subcontext.id())
|
||||
else:
|
||||
bpy.ops.bim.update_mesh_representation(obj=obj.name)
|
||||
|
||||
bpy.ops.object.select_all(action="DESELECT")
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
obj.select_set(True)
|
||||
bpy.ops.object.mode_set(mode="EDIT")
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -3,6 +3,7 @@ import numpy as np
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.representation
|
||||
import logging
|
||||
import ifcopenshell.api
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
@@ -105,7 +106,7 @@ class AddRepresentation(bpy.types.Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
box_context_id = get_context_id("Model", "Box", "MODEL_VIEW")
|
||||
old_box = ifcopenshell.util.element.get_representation(product, "Model", "Box", "MODEL_VIEW")
|
||||
old_box = ifcopenshell.util.representation.get_representation(product, "Model", "Box", "MODEL_VIEW")
|
||||
if (
|
||||
box_context_id
|
||||
and context_of_items.ContextType == "Model"
|
||||
@@ -358,7 +359,7 @@ class UpdateMeshRepresentation(bpy.types.Operator):
|
||||
new_representation = ifcopenshell.api.run("geometry.add_representation", self.file, **representation_data)
|
||||
|
||||
box_context_id = get_context_id("Model", "Box", "MODEL_VIEW")
|
||||
old_box = ifcopenshell.util.element.get_representation(product, "Model", "Box", "MODEL_VIEW")
|
||||
old_box = ifcopenshell.util.representation.get_representation(product, "Model", "Box", "MODEL_VIEW")
|
||||
if (
|
||||
box_context_id
|
||||
and old_box
|
||||
|
||||
@@ -11,6 +11,7 @@ import ifcopenshell
|
||||
import ifcopenshell.util.selector
|
||||
import ifcopenshell.util.geolocation
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.representation
|
||||
import ifcopenshell.util.schema
|
||||
import numpy as np
|
||||
from . import export_ifc
|
||||
@@ -617,7 +618,7 @@ class CutSection(bpy.types.Operator):
|
||||
if not element.Representation:
|
||||
return False
|
||||
for representation in element.Representation.Representations:
|
||||
if ifcopenshell.util.element.is_representation_of_context(
|
||||
if ifcopenshell.util.representation.is_representation_of_context(
|
||||
representation, "Plan", "Annotation", camera.data.BIMCameraProperties.target_view
|
||||
):
|
||||
return True
|
||||
|
||||
@@ -48,7 +48,7 @@ class Usecase:
|
||||
for modifier in self.settings["blender_object"].modifiers:
|
||||
if modifier.type == "BOOLEAN":
|
||||
modifier.show_viewport = False
|
||||
|
||||
|
||||
if self.settings["should_force_triangulation"]:
|
||||
mesh = self.settings["blender_object"].evaluated_get(bpy.context.evaluated_depsgraph_get()).to_mesh()
|
||||
bm = bmesh.new()
|
||||
@@ -119,6 +119,41 @@ class Usecase:
|
||||
elif self.settings["context"].ContextIdentifier == "SurveyPoints":
|
||||
pass
|
||||
|
||||
def create_text_representation(self):
|
||||
return self.file.createIfcShapeRepresentation(
|
||||
self.settings["context"],
|
||||
self.settings["context"].ContextIdentifier,
|
||||
"Annotation2D",
|
||||
[self.create_text()],
|
||||
)
|
||||
|
||||
def create_text(self):
|
||||
text = self.settings["geometry"]
|
||||
if text.align_y in ["TOP_BASELINE", "BOTTOM_BASELINE", "BOTTOM"]:
|
||||
y = "bottom"
|
||||
elif text.align_y == "CENTER":
|
||||
y = "middle"
|
||||
elif text.align_y == "TOP":
|
||||
y = "top"
|
||||
|
||||
if text.align_x == "LEFT":
|
||||
x = "left"
|
||||
elif text.align_x == "CENTER":
|
||||
x = "middle"
|
||||
elif text.align_x == "RIGHT":
|
||||
x = "right"
|
||||
|
||||
origin = self.file.createIfcAxis2Placement3D(
|
||||
self.file.createIfcCartesianPoint((0.0, 0.0, 0.0)),
|
||||
self.file.createIfcDirection((0.0, 0.0, 1.0)),
|
||||
self.file.createIfcDirection((1.0, 0.0, 0.0)),
|
||||
)
|
||||
|
||||
# TODO: Planar extent right now is wrong ...
|
||||
return self.file.createIfcTextLiteralWithExtent(
|
||||
text.body, origin, "RIGHT", self.file.createIfcPlanarExtent(1000, 1000), f"{y}-{x}"
|
||||
)
|
||||
|
||||
def create_variable_representation(self):
|
||||
if self.settings["is_wireframe"]:
|
||||
return self.create_wireframe_representation()
|
||||
|
||||
@@ -108,24 +108,6 @@ def replace_attribute(element, old, new):
|
||||
element[i] = new_attribute
|
||||
|
||||
|
||||
def is_representation_of_context(representation, context, subcontext=None, target_view=None):
|
||||
if target_view is not None:
|
||||
return (
|
||||
representation.ContextOfItems.is_a("IfcGeometricRepresentationSubContext")
|
||||
and representation.ContextOfItems.TargetView == target_view
|
||||
and representation.ContextOfItems.ContextIdentifier == subcontext
|
||||
and representation.ContextOfItems.ContextType == context
|
||||
)
|
||||
elif subcontext is not None:
|
||||
return (
|
||||
representation.ContextOfItems.is_a("IfcGeometricRepresentationSubContext")
|
||||
and representation.ContextOfItems.ContextIdentifier == subcontext
|
||||
and representation.ContextOfItems.ContextType == context
|
||||
)
|
||||
elif representation.ContextOfItems.ContextType == context:
|
||||
return True
|
||||
|
||||
|
||||
def remove_deep(ifc_file, element):
|
||||
# @todo maybe some sort of try-finally mechanism.
|
||||
ifc_file.batch()
|
||||
@@ -159,14 +141,3 @@ def copy_deep(ifc_file, element):
|
||||
attribute[j] = copy_deep(ifc_file, item)
|
||||
new[i] = attribute
|
||||
return new
|
||||
|
||||
|
||||
def get_representation(element, context, subcontext=None, target_view=None):
|
||||
if element.is_a("IfcProduct") and element.Representation:
|
||||
for r in element.Representation.Representations:
|
||||
if is_representation_of_context(r, context, subcontext, target_view):
|
||||
return r
|
||||
elif element.is_a("IfcTypeProduct") and element.RepresentationMaps:
|
||||
for r in element.RepresentationMaps:
|
||||
if is_representation_of_context(r.MappedRepresentation, context, subcontext, target_view):
|
||||
return r.MappedRepresentation
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
def get_context(ifc_file, context, subcontext=None, target_view=None):
|
||||
if subcontext or target_view:
|
||||
elements = ifc_file.by_type("IfcGeometricRepresentationSubContext")
|
||||
else:
|
||||
elements = ifc_file.by_type("IfcGeometricRepresentationContext", include_subtypes=False)
|
||||
for element in elements:
|
||||
if context and element.ContextType != context:
|
||||
continue
|
||||
if subcontext and getattr(element, "ContextIdentifier") != subcontext:
|
||||
continue
|
||||
if target_view and getattr(element, "TargetView") != target_view:
|
||||
continue
|
||||
return element
|
||||
|
||||
|
||||
def is_representation_of_context(representation, context, subcontext=None, target_view=None):
|
||||
if target_view is not None:
|
||||
return (
|
||||
representation.ContextOfItems.is_a("IfcGeometricRepresentationSubContext")
|
||||
and representation.ContextOfItems.TargetView == target_view
|
||||
and representation.ContextOfItems.ContextIdentifier == subcontext
|
||||
and representation.ContextOfItems.ContextType == context
|
||||
)
|
||||
elif subcontext is not None:
|
||||
return (
|
||||
representation.ContextOfItems.is_a("IfcGeometricRepresentationSubContext")
|
||||
and representation.ContextOfItems.ContextIdentifier == subcontext
|
||||
and representation.ContextOfItems.ContextType == context
|
||||
)
|
||||
elif representation.ContextOfItems.ContextType == context:
|
||||
return True
|
||||
|
||||
|
||||
def get_representation(element, context, subcontext=None, target_view=None):
|
||||
if element.is_a("IfcProduct") and element.Representation:
|
||||
for r in element.Representation.Representations:
|
||||
if is_representation_of_context(r, context, subcontext, target_view):
|
||||
return r
|
||||
elif element.is_a("IfcTypeProduct") and element.RepresentationMaps:
|
||||
for r in element.RepresentationMaps:
|
||||
if is_representation_of_context(r.MappedRepresentation, context, subcontext, target_view):
|
||||
return r.MappedRepresentation
|
||||
Reference in New Issue
Block a user