mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user