mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-24 20:50:02 +00:00
#1153 Implement diameter annotation
This commit is contained in:
@@ -32,6 +32,7 @@ text { fill: black; stroke: none; }
|
|||||||
.PredefinedType-PLANLEVEL { marker-end: url(#plan-level-marker); }
|
.PredefinedType-PLANLEVEL { marker-end: url(#plan-level-marker); }
|
||||||
.PredefinedType-DIMENSION { marker-start: url(#dimension-marker-start); marker-end: url(#dimension-marker-end); }
|
.PredefinedType-DIMENSION { marker-start: url(#dimension-marker-start); marker-end: url(#dimension-marker-end); }
|
||||||
.PredefinedType-RADIUS { marker-end: url(#radius-marker-end); }
|
.PredefinedType-RADIUS { marker-end: url(#radius-marker-end); }
|
||||||
|
.PredefinedType-DIAMETER { marker-start: url(#diameter-marker-start); marker-end: url(#diameter-marker-end); }
|
||||||
.PredefinedType-HIDDENLINE { stroke-dasharray: 3, 2; }
|
.PredefinedType-HIDDENLINE { stroke-dasharray: 3, 2; }
|
||||||
.PredefinedType-STAIR { marker-start: url(#stair-marker-start); marker-end: url(#stair-marker-end); }
|
.PredefinedType-STAIR { marker-start: url(#stair-marker-start); marker-end: url(#stair-marker-end); }
|
||||||
.PredefinedType-BOUNDARY { fill: none; stroke: red; stroke-width: 1; stroke-dasharray: 12, 4, 3, 4, 3, 4; }
|
.PredefinedType-BOUNDARY { fill: none; stroke: red; stroke-width: 1; stroke-dasharray: 12, 4, 3, 4, 3, 4; }
|
||||||
|
|||||||
@@ -21,6 +21,18 @@
|
|||||||
<path d="M 0 3.5 L 0 10.5 L 10 7" class="annotation" style="fill:black;" />
|
<path d="M 0 3.5 L 0 10.5 L 10 7" class="annotation" style="fill:black;" />
|
||||||
</g>
|
</g>
|
||||||
</marker>
|
</marker>
|
||||||
|
<marker id="diameter-marker-start" markerHeight="14" markerWidth="11" orient="auto" refX="1" refY="7">
|
||||||
|
<g>
|
||||||
|
<path d="M 11 3.5 L 11 10.5 L 1 7" class="annotation" style="fill:black;" />
|
||||||
|
<path d="M 1 0 L 1 14" class="annotation" style="stroke-width:1;" />
|
||||||
|
</g>
|
||||||
|
</marker>
|
||||||
|
<marker id="diameter-marker-end" markerHeight="14" markerWidth="11" orient="auto" refX="10" refY="7">
|
||||||
|
<g>
|
||||||
|
<path d="M 0 3.5 L 0 10.5 L 10 7" class="annotation" style="fill:black;" />
|
||||||
|
<path d="M 10 0 L 10 14" class="annotation" style="stroke-width:1;" />
|
||||||
|
</g>
|
||||||
|
</marker>
|
||||||
<marker id="dimension-marker-start" markerHeight="30" markerWidth="20" refX="10" refY="15" orient="auto">
|
<marker id="dimension-marker-start" markerHeight="30" markerWidth="20" refX="10" refY="15" orient="auto">
|
||||||
<g>
|
<g>
|
||||||
<path d="M 0 15 L 20 15" class="annotation" style="stroke-width:1;" />
|
<path d="M 0 15 L 20 15" class="annotation" style="stroke-width:1;" />
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.8 KiB |
@@ -378,11 +378,11 @@ class BaseDecorator:
|
|||||||
elif "/" in precision:
|
elif "/" in precision:
|
||||||
precision = int(precision.split("/")[1])
|
precision = int(precision.split("/")[1])
|
||||||
elif unit_system == "METRIC":
|
elif unit_system == "METRIC":
|
||||||
precision = 3
|
precision = 4
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
return bpy.utils.units.to_string(unit_system, "LENGTH", value, precision=precision, split_unit=True)
|
return bpy.utils.units.to_string(unit_system, "LENGTH", value, precision=precision)
|
||||||
|
|
||||||
|
|
||||||
class DimensionDecorator(BaseDecorator):
|
class DimensionDecorator(BaseDecorator):
|
||||||
@@ -480,6 +480,10 @@ class DimensionDecorator(BaseDecorator):
|
|||||||
self.draw_label(context, text, p0 + (dir) * 0.5, dir)
|
self.draw_label(context, text, p0 + (dir) * 0.5, dir)
|
||||||
|
|
||||||
|
|
||||||
|
class DiameterDecorator(DimensionDecorator):
|
||||||
|
objecttype = "DIAMETER"
|
||||||
|
|
||||||
|
|
||||||
class LeaderDecorator(BaseDecorator):
|
class LeaderDecorator(BaseDecorator):
|
||||||
"""Decorating text with arrows
|
"""Decorating text with arrows
|
||||||
- head point with arrow
|
- head point with arrow
|
||||||
@@ -1585,6 +1589,7 @@ class DecorationsHandler:
|
|||||||
HiddenDecorator,
|
HiddenDecorator,
|
||||||
LeaderDecorator,
|
LeaderDecorator,
|
||||||
RadiusDecorator,
|
RadiusDecorator,
|
||||||
|
DiameterDecorator,
|
||||||
MiscDecorator,
|
MiscDecorator,
|
||||||
PlanLevelDecorator,
|
PlanLevelDecorator,
|
||||||
SectionLevelDecorator,
|
SectionLevelDecorator,
|
||||||
|
|||||||
@@ -155,6 +155,8 @@ class SvgWriter:
|
|||||||
self.draw_dimension_annotations(obj)
|
self.draw_dimension_annotations(obj)
|
||||||
elif element.ObjectType == "RADIUS":
|
elif element.ObjectType == "RADIUS":
|
||||||
self.draw_radius_annotations(obj)
|
self.draw_radius_annotations(obj)
|
||||||
|
elif element.ObjectType == "DIAMETER":
|
||||||
|
self.draw_diameter_annotations(obj)
|
||||||
elif element.ObjectType == "ELEVATION":
|
elif element.ObjectType == "ELEVATION":
|
||||||
self.draw_elevation_annotation(obj)
|
self.draw_elevation_annotation(obj)
|
||||||
elif element.ObjectType == "SECTION":
|
elif element.ObjectType == "SECTION":
|
||||||
@@ -217,7 +219,6 @@ class SvgWriter:
|
|||||||
if tag:
|
if tag:
|
||||||
self.svg.add(self.svg.text(tag, insert=(text_position[0], text_position[1] - 5), **text_style))
|
self.svg.add(self.svg.text(tag, insert=(text_position[0], text_position[1] - 5), **text_style))
|
||||||
|
|
||||||
|
|
||||||
def draw_stair_annotation(self, obj):
|
def draw_stair_annotation(self, obj):
|
||||||
x_offset = self.raw_width / 2
|
x_offset = self.raw_width / 2
|
||||||
y_offset = self.raw_height / 2
|
y_offset = self.raw_height / 2
|
||||||
@@ -265,9 +266,7 @@ class SvgWriter:
|
|||||||
end = Vector(((x_offset + v1.x), (y_offset - v1.y)))
|
end = Vector(((x_offset + v1.x), (y_offset - v1.y)))
|
||||||
vector = end - start
|
vector = end - start
|
||||||
line = self.svg.add(
|
line = self.svg.add(
|
||||||
self.svg.line(
|
self.svg.line(start=tuple(start * self.scale), end=tuple(end * self.scale), class_=" ".join(classes))
|
||||||
start=tuple(start * self.scale), end=tuple(end * self.scale), class_=" ".join(classes)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
line["stroke-dasharray"] = "12.5, 3, 3, 3"
|
line["stroke-dasharray"] = "12.5, 3, 3, 3"
|
||||||
axis_tag = tool.Ifc.get_entity(obj).Name
|
axis_tag = tool.Ifc.get_entity(obj).Name
|
||||||
@@ -298,7 +297,6 @@ class SvgWriter:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def draw_misc_annotation(self, obj):
|
def draw_misc_annotation(self, obj):
|
||||||
# We have to decide whether this should come from Blender or from IFC.
|
# We have to decide whether this should come from Blender or from IFC.
|
||||||
# For the moment, for convenience of experimenting with ideas, it comes
|
# For the moment, for convenience of experimenting with ideas, it comes
|
||||||
@@ -565,7 +563,11 @@ class SvgWriter:
|
|||||||
for edge in obj.data.edges:
|
for edge in obj.data.edges:
|
||||||
points = [obj.data.vertices[v] for v in edge.vertices]
|
points = [obj.data.vertices[v] for v in edge.vertices]
|
||||||
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]
|
||||||
projected_points = [projected_points[0], (projected_points[0] + projected_points[1]) / 2, projected_points[1]]
|
projected_points = [
|
||||||
|
projected_points[0],
|
||||||
|
(projected_points[0] + projected_points[1]) / 2,
|
||||||
|
projected_points[1],
|
||||||
|
]
|
||||||
d = " ".join(
|
d = " ".join(
|
||||||
[
|
[
|
||||||
"L {} {}".format((x_offset + p.x) * self.scale, (y_offset - p.y) * self.scale)
|
"L {} {}".format((x_offset + p.x) * self.scale, (y_offset - p.y) * self.scale)
|
||||||
@@ -575,7 +577,6 @@ class SvgWriter:
|
|||||||
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)))
|
||||||
|
|
||||||
|
|
||||||
def draw_plan_level_annotation(self, obj):
|
def draw_plan_level_annotation(self, obj):
|
||||||
x_offset = self.raw_width / 2
|
x_offset = self.raw_width / 2
|
||||||
y_offset = self.raw_height / 2
|
y_offset = self.raw_height / 2
|
||||||
@@ -640,11 +641,17 @@ class SvgWriter:
|
|||||||
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)))
|
||||||
|
|
||||||
p0 = Vector(((x_offset + projected_points[0].x) * self.scale, (y_offset - projected_points[0].y) * self.scale))
|
p0 = Vector(
|
||||||
p1 = Vector(((x_offset + projected_points[1].x) * self.scale, (y_offset - projected_points[1].y) * self.scale))
|
((x_offset + projected_points[0].x) * self.scale, (y_offset - projected_points[0].y) * self.scale)
|
||||||
|
)
|
||||||
|
p1 = Vector(
|
||||||
|
((x_offset + projected_points[1].x) * self.scale, (y_offset - projected_points[1].y) * self.scale)
|
||||||
|
)
|
||||||
text_offset = (p0 - p1).xy.normalized() * 5
|
text_offset = (p0 - p1).xy.normalized() * 5
|
||||||
text_position = projected_points[0]
|
text_position = projected_points[0]
|
||||||
text_position = Vector(((x_offset + text_position.x) * self.scale, (y_offset - text_position.y) * self.scale))
|
text_position = Vector(
|
||||||
|
((x_offset + text_position.x) * self.scale, (y_offset - text_position.y) * self.scale)
|
||||||
|
)
|
||||||
text_position += text_offset
|
text_position += text_offset
|
||||||
|
|
||||||
text_style = {
|
text_style = {
|
||||||
@@ -661,6 +668,22 @@ class SvgWriter:
|
|||||||
|
|
||||||
self.svg.add(self.svg.text(tag, insert=tuple(text_position), **text_style))
|
self.svg.add(self.svg.text(tag, insert=tuple(text_position), **text_style))
|
||||||
|
|
||||||
|
def draw_diameter_annotations(self, obj):
|
||||||
|
classes = self.get_attribute_classes(obj)
|
||||||
|
matrix_world = obj.matrix_world
|
||||||
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
text_override = element.Description
|
||||||
|
for spline in obj.data.splines:
|
||||||
|
points = self.get_spline_points(spline)
|
||||||
|
for i, p in enumerate(points):
|
||||||
|
if i + 1 >= len(points):
|
||||||
|
continue
|
||||||
|
v0_global = matrix_world @ points[i].co.xyz
|
||||||
|
v1_global = matrix_world @ points[i + 1].co.xyz
|
||||||
|
self.draw_dimension_annotation(
|
||||||
|
v0_global, v1_global, classes, text_override, text_format=lambda x: "D" + x
|
||||||
|
)
|
||||||
|
|
||||||
def draw_dimension_annotations(self, obj):
|
def draw_dimension_annotations(self, obj):
|
||||||
classes = self.get_attribute_classes(obj)
|
classes = self.get_attribute_classes(obj)
|
||||||
matrix_world = obj.matrix_world
|
matrix_world = obj.matrix_world
|
||||||
@@ -687,7 +710,7 @@ class SvgWriter:
|
|||||||
Vector(coord[0]), Vector(coord[1]), ["IfcAnnotation", "PredefinedType-DIMENSION"]
|
Vector(coord[0]), Vector(coord[1]), ["IfcAnnotation", "PredefinedType-DIMENSION"]
|
||||||
)
|
)
|
||||||
|
|
||||||
def draw_dimension_annotation(self, v0_global, v1_global, classes, text_override=None):
|
def draw_dimension_annotation(self, v0_global, v1_global, classes, text_override=None, text_format=lambda x: x):
|
||||||
x_offset = self.raw_width / 2
|
x_offset = self.raw_width / 2
|
||||||
y_offset = self.raw_height / 2
|
y_offset = self.raw_height / 2
|
||||||
v0 = self.project_point_onto_camera(v0_global)
|
v0 = self.project_point_onto_camera(v0_global)
|
||||||
@@ -713,6 +736,7 @@ class SvgWriter:
|
|||||||
text = text_override
|
text = text_override
|
||||||
else:
|
else:
|
||||||
text = str(dimension)
|
text = str(dimension)
|
||||||
|
text = text_format(text)
|
||||||
self.svg.add(
|
self.svg.add(
|
||||||
self.svg.text(
|
self.svg.text(
|
||||||
text,
|
text,
|
||||||
|
|||||||
@@ -320,7 +320,7 @@ class BIM_PT_annotation_utilities(Panel):
|
|||||||
self.props = context.scene.DocProperties
|
self.props = context.scene.DocProperties
|
||||||
|
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
op = row.operator("bim.add_annotation", text="Dim", icon="FIXED_SIZE")
|
op = row.operator("bim.add_annotation", text="Dimension", icon="FIXED_SIZE")
|
||||||
op.object_type = "DIMENSION"
|
op.object_type = "DIMENSION"
|
||||||
op.data_type = "curve"
|
op.data_type = "curve"
|
||||||
op = row.operator("bim.add_annotation", text="Angle", icon="DRIVER_ROTATIONAL_DIFFERENCE")
|
op = row.operator("bim.add_annotation", text="Angle", icon="DRIVER_ROTATIONAL_DIFFERENCE")
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ class Drawing(blenderbim.core.tool.Drawing):
|
|||||||
data_type = {
|
data_type = {
|
||||||
"DIMENSION": "curve",
|
"DIMENSION": "curve",
|
||||||
"RADIUS": "curve",
|
"RADIUS": "curve",
|
||||||
|
"DIAMETER": "curve",
|
||||||
"TEXT": "empty",
|
"TEXT": "empty",
|
||||||
"TEXT_LEADER": "curve",
|
"TEXT_LEADER": "curve",
|
||||||
"STAIR_ARROW": "curve",
|
"STAIR_ARROW": "curve",
|
||||||
|
|||||||
Reference in New Issue
Block a user