PLAN_LEVEL annotations support for prefix, suffix #3399

Viewport - https://i.imgur.com/XRa3oJO.png
SVG - https://i.imgur.com/C8PjoiO.png
This commit is contained in:
Andrej730
2023-07-11 17:00:43 +05:00
parent 4da7b355bf
commit 298568d3ea
3 changed files with 86 additions and 43 deletions
@@ -287,15 +287,18 @@ class DecoratorData:
cls.data[obj.name] = text_data
return text_data
# used by Ifc Annotations with ObjectType = "DIMENSION" / "DIAMETER"
@classmethod
def get_dimension_data(cls, obj):
"""used by Ifc Annotations with ObjectType:
DIMENSION / DIAMETER / SECTION_LEVEL / PLAN_LEVEL
"""
result = cls.data.get(obj.name, None)
if result is not None:
return result
element = tool.Ifc.get_entity(obj)
supported_object_types = ("DIMENSION", "DIAMETER", "SECTION_LEVEL")
supported_object_types = ("DIMENSION", "DIAMETER", "SECTION_LEVEL", "PLAN_LEVEL")
if not element or not element.is_a("IfcAnnotation") or element.ObjectType not in supported_object_types:
return None
@@ -1054,23 +1054,51 @@ class PlanLevelDecorator(BaseDecorator):
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
region = context.region
region3d = context.region_data
element = tool.Ifc.get_entity(obj)
description = element.Description
dimension_data = DecoratorData.get_dimension_data(obj)
show_description_only = dimension_data["show_description_only"]
text_prefix = dimension_data["text_prefix"]
text_suffix = dimension_data["text_suffix"]
for verts in splines:
p0, p1 = [location_3d_to_region_2d(region, region3d, v) for v in verts[:2]]
dir = p1 - p0
if dir.length < 1:
text_dir = p1 - p0
if text_dir.length < 1:
continue
if dir.x > 0:
if text_dir.x > 0:
box_alignment = "bottom-left"
else:
box_alignment = "bottom-right"
dir *= -1
text_dir *= -1
z = verts[0].z / unit_scale
z = ifcopenshell.util.geolocation.auto_z2e(tool.Ifc.get(), z)
z *= unit_scale
text = "RL " + self.format_value(context, z)
self.draw_label(context, text, p0, dir, gap=8, center=False, box_alignment=box_alignment)
line_number_start = 0
if not show_description_only:
z = verts[0].z / unit_scale
z = ifcopenshell.util.geolocation.auto_z2e(tool.Ifc.get(), z)
z *= unit_scale
text = "RL " + self.format_value(context, z)
full_prefix = ((description + "\\n") if description else "") + text_prefix
text = full_prefix + text + text_suffix
line_number_start -= full_prefix.count("\\n")
else:
if not description:
break
text = description
self.draw_label(
context,
text=text,
pos=p0,
text_dir=text_dir,
box_alignment=box_alignment,
line_no=line_number_start,
multiline=True,
gap=8,
center=False,
)
class SectionLevelDecorator(BaseDecorator):
@@ -1129,17 +1157,11 @@ class SectionLevelDecorator(BaseDecorator):
text_suffix = dimension_data["text_suffix"]
for verts in splines:
z = verts[0].z / unit_scale
z = ifcopenshell.util.geolocation.auto_z2e(tool.Ifc.get(), z)
z *= unit_scale
common_label_attrs = {
"context": context,
"multiline": True,
"text_dir": text_dir,
}
line_number_start = 0
if not show_description_only:
z = verts[0].z / unit_scale
z = ifcopenshell.util.geolocation.auto_z2e(tool.Ifc.get(), z)
z *= unit_scale
text = "RL " + self.format_value(context, z)
full_prefix = ((tag + "\\n") if tag else "") + text_prefix
text = full_prefix + text + text_suffix
@@ -1150,11 +1172,13 @@ class SectionLevelDecorator(BaseDecorator):
text = tag
self.draw_label(
context,
text=text,
pos=text_position,
text_dir=text_dir,
box_alignment="bottom-left",
line_no=line_number_start,
**common_label_attrs,
multiline=True,
)
break # support only 1 label
@@ -241,6 +241,7 @@ class SvgWriter:
d = "M{}".format(d[1:])
path = self.svg.add(self.svg.path(d=d, class_=" ".join(classes)))
text_position = projected_points_svg[0] - Vector((0, base_offset_y))
# TODO: allow metric to be configurable
rl_value = (matrix_world @ points[0].co.xyz).z
if bpy.context.scene.unit_settings.system == "IMPERIAL":
@@ -873,27 +874,28 @@ class SvgWriter:
path = self.svg.add(self.svg.path(d=d, class_=" ".join(classes)))
def draw_plan_level_annotation(self, obj):
x_offset = self.raw_width / 2
y_offset = self.raw_height / 2
offset = Vector([self.raw_width, self.raw_height]) / 2
matrix_world = obj.matrix_world
classes = self.get_attribute_classes(obj)
element = tool.Ifc.get_entity(obj)
description = element.Description
dimension_data = DecoratorData.get_dimension_data(obj)
prefix = dimension_data["text_prefix"]
suffix = dimension_data["text_suffix"]
show_description_only = dimension_data["show_description_only"]
base_offset_y = 1.0
for spline in obj.data.splines:
points = self.get_spline_points(spline)
projected_points = [self.project_point_onto_camera(matrix_world @ p.co.xyz) for p in points]
d = " ".join(
[
"L {} {}".format((x_offset + p.x) * self.svg_scale, (y_offset - p.y) * self.svg_scale)
for p in projected_points
]
)
projected_points_svg = [(offset + p.xy * Vector((1, -1))) * self.svg_scale for p in projected_points]
d = " ".join(["L {} {}".format(*p) for p in projected_points_svg])
d = "M{}".format(d[1:])
path = self.svg.add(self.svg.path(d=d, class_=" ".join(classes)))
text_position = Vector(
(
(x_offset + projected_points[0].x) * self.svg_scale,
((y_offset - projected_points[0].y) * self.svg_scale) - 1.0,
)
)
text_position = projected_points_svg[0] - Vector((0, base_offset_y))
# TODO: allow metric to be configurable
rl_value = (matrix_world @ points[0].co).z
if bpy.context.scene.unit_settings.system == "IMPERIAL":
@@ -905,17 +907,31 @@ class SvgWriter:
rl *= unit_scale
rl = "{:.3f}m".format(rl)
text_tags = []
box_alignment = "bottom-left" if projected_points[0].x <= projected_points[-1].x else "bottom-right"
text_style = SvgWriter.get_box_alignment_parameters(box_alignment)
self.svg.add(
self.svg.text(
"{}{}".format("" if rl_value < 0 else "+", rl),
insert=tuple(text_position),
class_="PLANLEVEL",
**text_style,
)
line_number_start = 0
if not show_description_only:
text = "{}{}".format("" if rl_value < 0 else "+", rl)
full_prefix = ((description + "\\n") if description else "") + prefix
text = full_prefix + text + suffix
line_number_start -= full_prefix.count("\\n")
else:
if not description:
continue
text = description
text_tags += self.create_text_tag(
text,
text_position,
class_str="PLANLEVEL",
line_number_start=line_number_start,
box_alignment=box_alignment,
)
for text in text_tags:
self.svg.add(text)
def draw_angle_annotations(self, obj):
points = obj.data.splines[0].points
region = bpy.context.region