mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-24 16:29:57 +00:00
SECTION_LEVEL annotations support for prefix, suffix #3399
also added support for "show only description" for section_level
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user