SECTION_LEVEL annotations support for prefix, suffix #3399

also added support for "show only description" for section_level
This commit is contained in:
Andrej730
2023-07-11 15:30:10 +05:00
parent e5c5c18d8d
commit 3d96187a91
3 changed files with 112 additions and 101 deletions
@@ -295,7 +295,7 @@ class DecoratorData:
return result return result
element = tool.Ifc.get_entity(obj) element = tool.Ifc.get_entity(obj)
supported_object_types = ("DIMENSION", "DIAMETER") supported_object_types = ("DIMENSION", "DIAMETER", "SECTION_LEVEL")
if not element or not element.is_a("IfcAnnotation") or element.ObjectType not in supported_object_types: if not element or not element.is_a("IfcAnnotation") or element.ObjectType not in supported_object_types:
return None return None
@@ -312,8 +312,8 @@ class DecoratorData:
pset_data = ifcopenshell.util.element.get_pset(element, "BBIM_Dimension") or {} pset_data = ifcopenshell.util.element.get_pset(element, "BBIM_Dimension") or {}
show_description_only = pset_data.get("ShowDescriptionOnly", False) show_description_only = pset_data.get("ShowDescriptionOnly", False)
suppress_zero_inches = pset_data.get("SuppressZeroInches", False) suppress_zero_inches = pset_data.get("SuppressZeroInches", False)
text_prefix = pset_data.get("TextPrefix", "") text_prefix = pset_data.get("TextPrefix", None) or ""
text_suffix = pset_data.get("TextSuffix", "") text_suffix = pset_data.get("TextSuffix", None) or ""
dimension_data = { dimension_data = {
"dimension_style": dimension_style, "dimension_style": dimension_style,
@@ -363,7 +363,7 @@ class BaseDecorator:
""" """
if multiline: if multiline:
line_no = 0 line_no = line_no
lines = text.split("\\n") lines = text.split("\\n")
lines = lines if multiline_to_bottom else lines[::-1] lines = lines if multiline_to_bottom else lines[::-1]
for line in lines: for line in lines:
@@ -637,39 +637,33 @@ class DimensionDecorator(BaseDecorator):
perpendicular = Vector((-text_dir.y, text_dir.x)).normalized() perpendicular = Vector((-text_dir.y, text_dir.x)).normalized()
text_offset = perpendicular * text_offset_value text_offset = perpendicular * text_offset_value
common_label_attrs = {
"context": context,
"multiline": True,
"text_dir": text_dir,
}
base_pos = p0 + text_dir * 0.5
if not show_description_only: if not show_description_only:
length = (v1 - v0).length length = (v1 - v0).length
text = self.format_value(context, length) text = self.format_value(context, length)
text = text_prefix + text + text_suffix text = text_prefix + text + text_suffix
else:
if not description:
continue
text = description
self.draw_label( self.draw_label(
context, text=text,
text, pos=base_pos + text_offset,
p0 + text_dir * 0.5 + text_offset, box_alignment="bottom-middle",
text_dir, multiline_to_bottom=False,
box_alignment="bottom-middle", **common_label_attrs,
multiline=True, )
multiline_to_bottom=False,
)
if description:
self.draw_label(
context,
description,
p0 + text_dir * 0.5 - text_offset,
text_dir,
box_alignment="top-middle",
multiline=True,
)
elif show_description_only and description: if not show_description_only and description:
self.draw_label( self.draw_label(
context, text=description, pos=base_pos - text_offset, box_alignment="top-middle", **common_label_attrs
description,
p0 + text_dir * 0.5 + text_offset,
text_dir,
box_alignment="bottom-middle",
multiline=True,
multiline_to_bottom=False,
) )
@@ -1129,25 +1123,40 @@ class SectionLevelDecorator(BaseDecorator):
storey = tool.Drawing.get_annotation_element(element) storey = tool.Drawing.get_annotation_element(element)
tag = storey.Name if storey else element.Description tag = storey.Name if storey else 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: for verts in splines:
z = verts[0].z / unit_scale z = verts[0].z / unit_scale
z = ifcopenshell.util.geolocation.auto_z2e(tool.Ifc.get(), z) z = ifcopenshell.util.geolocation.auto_z2e(tool.Ifc.get(), z)
z *= unit_scale z *= unit_scale
text_lines = ["RL " + self.format_value(context, z)] common_label_attrs = {
if tag: "context": context,
text_lines.append(tag) "multiline": True,
"text_dir": text_dir,
}
line_number_start = 0
if not show_description_only:
text = "RL " + self.format_value(context, z)
full_prefix = ((tag + "\\n") if tag else "") + text_prefix
text = full_prefix + text + text_suffix
line_number_start -= full_prefix.count("\\n")
else:
if not tag:
break
text = tag
self.draw_label(
text=text,
pos=text_position,
box_alignment="bottom-left",
line_no=line_number_start,
**common_label_attrs,
)
for line_i, line in zip((0, -1), text_lines):
self.draw_label(
context,
line,
text_position,
text_dir,
center=False,
vcenter=False,
line_no=line_i,
)
break # support only 1 label break # support only 1 label
@@ -221,30 +221,26 @@ class SvgWriter:
return self return self
def draw_section_level_annotation(self, obj): def draw_section_level_annotation(self, obj):
x_offset = self.raw_width / 2 offset = Vector([self.raw_width, self.raw_height]) / 2
y_offset = self.raw_height / 2
matrix_world = obj.matrix_world matrix_world = obj.matrix_world
classes = self.get_attribute_classes(obj) classes = self.get_attribute_classes(obj)
element = tool.Ifc.get_entity(obj) element = tool.Ifc.get_entity(obj)
storey = tool.Drawing.get_annotation_element(element) storey = tool.Drawing.get_annotation_element(element)
tag = storey.Name if storey else element.Description tag = storey.Name if storey else 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 = 3.5
for spline in obj.data.splines: for spline in obj.data.splines:
points = self.get_spline_points(spline) points = self.get_spline_points(spline)
projected_points = [self.project_point_onto_camera(matrix_world @ p.co.xyz) for p in points] projected_points = [self.project_point_onto_camera(matrix_world @ p.co.xyz) for p in points]
d = " ".join( 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])
"L {} {}".format((x_offset + p.x) * self.svg_scale, (y_offset - p.y) * self.svg_scale)
for p in projected_points
]
)
d = "M{}".format(d[1:]) d = "M{}".format(d[1:])
path = self.svg.add(self.svg.path(d=d, class_=" ".join(classes))) path = self.svg.add(self.svg.path(d=d, class_=" ".join(classes)))
text_position = Vector( text_position = projected_points_svg[0] - Vector((0, base_offset_y))
(
(x_offset + projected_points[0].x) * self.svg_scale,
((y_offset - projected_points[0].y) * self.svg_scale) - 3.5,
)
)
# TODO: allow metric to be configurable # TODO: allow metric to be configurable
rl_value = (matrix_world @ points[0].co.xyz).z rl_value = (matrix_world @ points[0].co.xyz).z
if bpy.context.scene.unit_settings.system == "IMPERIAL": if bpy.context.scene.unit_settings.system == "IMPERIAL":
@@ -255,17 +251,28 @@ class SvgWriter:
rl = ifcopenshell.util.geolocation.auto_z2e(tool.Ifc.get(), rl) rl = ifcopenshell.util.geolocation.auto_z2e(tool.Ifc.get(), rl)
rl *= unit_scale rl *= unit_scale
rl = "{:.3f}m".format(rl) rl = "{:.3f}m".format(rl)
text_style = SvgWriter.get_box_alignment_parameters("bottom-left") text_tags = []
self.svg.add(
self.svg.text( line_number_start = 0
"RL {}{}".format("" if rl_value < 0 else "+", rl), if not show_description_only:
insert=tuple(text_position), text = "RL {}{}".format("" if rl_value < 0 else "+", rl)
class_="SECTIONLEVEL", full_prefix = ((tag + "\\n") if tag else "") + prefix
**text_style, text = full_prefix + text + suffix
) line_number_start -= full_prefix.count("\\n")
else:
if not tag:
continue
text = tag
text_tags += self.create_text_tag(
text,
text_position,
class_str="SECTIONLEVEL",
line_number_start=line_number_start,
) )
if tag:
self.svg.add(self.svg.text(tag, insert=(text_position[0], text_position[1] - 5), **text_style)) for text in text_tags:
self.svg.add(text)
def draw_stair_annotation(self, obj): def draw_stair_annotation(self, obj):
x_offset = self.raw_width / 2 x_offset = self.raw_width / 2
@@ -835,7 +842,6 @@ class SvgWriter:
angle, angle,
text_literal.BoxAlignment, text_literal.BoxAlignment,
classes_str, classes_str,
multiline=True,
fill_bg="fill-bg" in classes, fill_bg="fill-bg" in classes,
line_number_start=line_number, line_number_start=line_number,
) )
@@ -913,7 +919,7 @@ class SvgWriter:
def draw_angle_annotations(self, obj): def draw_angle_annotations(self, obj):
points = obj.data.splines[0].points points = obj.data.splines[0].points
region = bpy.context.region region = bpy.context.region
area = tool.Blender.get_viewport_context()['area'] area = tool.Blender.get_viewport_context()["area"]
region_3d = area.spaces.active.region_3d region_3d = area.spaces.active.region_3d
points_chunked = [points[i : i + 3] for i in range(len(points) - 2)] points_chunked = [points[i : i + 3] for i in range(len(points) - 2)]
@@ -1243,13 +1249,6 @@ class SvgWriter:
mid = ((end - start) / 2) + start mid = ((end - start) / 2) + start
vector = end - start vector = end - start
perpendicular = Vector((vector.y, -vector.x)).normalized() perpendicular = Vector((vector.y, -vector.x)).normalized()
dimension = (v1_global - v0_global).length
dimension = helper.format_distance(
dimension,
precision=self.precision,
decimal_places=self.decimal_places,
suppress_zero_inches=suppress_zero_inches,
)
sheet_dimension = (end - start).length sheet_dimension = (end - start).length
# if annotation can't fit offset text to the right of marker # if annotation can't fit offset text to the right of marker
@@ -1264,34 +1263,37 @@ class SvgWriter:
"angle": angle, "angle": angle,
"class_str": "DIMENSION", "class_str": "DIMENSION",
"text_format": text_format, "text_format": text_format,
"multiline": True,
"fill_bg": fill_bg, "fill_bg": fill_bg,
} }
if not show_description_only: if not show_description_only:
text = f"{text_prefix}{str(dimension)}{text_suffix}" dimension = (v1_global - v0_global).length
text_tags += self.create_text_tag( dimension = helper.format_distance(
text, dimension,
text_position + perpendicular, precision=self.precision,
box_alignment="bottom-middle", decimal_places=self.decimal_places,
multiline_to_bottom=False, suppress_zero_inches=suppress_zero_inches,
**text_tag_kwargs,
) )
if dimension_text: text = text_prefix + str(dimension) + text_suffix
text_tags += self.create_text_tag( else:
dimension_text, if not dimension_text:
text_position - perpendicular, return
box_alignment="top-middle", text = dimension_text
multiline_to_bottom=True,
**text_tag_kwargs,
)
elif show_description_only and dimension_text: text_tags += self.create_text_tag(
text_tags.extend += self.create_text_tag( text,
text_position + perpendicular,
box_alignment="bottom-middle",
multiline_to_bottom=False,
**text_tag_kwargs,
)
if not show_description_only and dimension_text:
text_tags += self.create_text_tag(
dimension_text, dimension_text,
text_position + perpendicular, text_position - perpendicular,
box_alignment="bottom-middle", box_alignment="top-middle",
multiline_to_bottom=False, multiline_to_bottom=True,
**text_tag_kwargs, **text_tag_kwargs,
) )
@@ -1302,11 +1304,11 @@ class SvgWriter:
self, self,
text, text,
text_position, text_position,
angle, angle=0,
box_alignment, box_alignment="bottom-left",
class_str, class_str="",
text_format=lambda x: x, text_format=lambda x: x,
multiline=False, multiline=True,
multiline_to_bottom=True, multiline_to_bottom=True,
fill_bg=False, fill_bg=False,
line_number_start=0, line_number_start=0,