mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
#1153 Boilerplate styles and definitions now can be used with any drawing layer combination
This commit is contained in:
@@ -124,6 +124,17 @@ class CreateDrawing(bpy.types.Operator):
|
||||
self.get_scale()
|
||||
if self.cprops.update_representation(self.camera):
|
||||
bpy.ops.bim.update_representation(obj=self.camera.name, ifc_representation_class="")
|
||||
|
||||
self.svg_writer = svgwriter.SvgWriter()
|
||||
self.svg_writer.human_scale = self.human_scale
|
||||
self.svg_writer.scale = self.scale
|
||||
self.svg_writer.data_dir = context.scene.BIMProperties.data_dir
|
||||
drawing_style = context.scene.DocProperties.drawing_styles[self.cprops.active_drawing_style_index]
|
||||
self.svg_writer.vector_style = drawing_style.vector_style
|
||||
self.svg_writer.camera = self.camera
|
||||
self.svg_writer.camera_width, self.svg_writer.camera_height = self.get_camera_dimensions()
|
||||
self.svg_writer.camera_projection = tuple(self.camera.matrix_world.to_quaternion() @ Vector((0, 0, -1)))
|
||||
|
||||
underlay_svg = self.generate_underlay(context)
|
||||
self.profile_code("Generate underlay")
|
||||
linework_svg = self.generate_linework(context)
|
||||
@@ -136,6 +147,16 @@ class CreateDrawing(bpy.types.Operator):
|
||||
print("Total Time: {:.2f}".format(time.time() - start))
|
||||
return {"FINISHED"}
|
||||
|
||||
def get_camera_dimensions(self):
|
||||
render = bpy.context.scene.render
|
||||
if self.is_landscape(render):
|
||||
width = self.camera.data.ortho_scale
|
||||
height = width / render.resolution_x * render.resolution_y
|
||||
else:
|
||||
height = self.camera.data.ortho_scale
|
||||
width = height / render.resolution_y * render.resolution_x
|
||||
return width, height
|
||||
|
||||
def profile_code(self, message):
|
||||
if not self.time:
|
||||
self.time = time.time()
|
||||
@@ -146,22 +167,22 @@ class CreateDrawing(bpy.types.Operator):
|
||||
# Hacky :)
|
||||
svg_path = os.path.join(context.scene.BIMProperties.data_dir, "diagrams", self.drawing_name + ".svg")
|
||||
with open(svg_path, "w") as outfile:
|
||||
has_boilerplate = False
|
||||
boilerplate = self.svg_writer.create_blank_svg(svg_path).define_boilerplate().svg.tostring()
|
||||
outfile.write(boilerplate.replace("</svg>", ""))
|
||||
if underlay:
|
||||
with open(underlay) as infile:
|
||||
for line in infile:
|
||||
if "<svg " in line:
|
||||
line = line.replace('">', '" xmlns:ifc="http://www.ifcopenshell.org/ns">')
|
||||
if "</svg>" in line:
|
||||
for line in enumerate(infile):
|
||||
if i < 2:
|
||||
continue
|
||||
elif "</svg>" in line:
|
||||
continue
|
||||
outfile.write(line)
|
||||
shutil.copyfile(underlay[0:-4] + ".png", svg_path[0:-4] + "-underlay.png")
|
||||
has_boilerplate = True
|
||||
if linework:
|
||||
with open(linework) as infile:
|
||||
should_skip = False
|
||||
for i, line in enumerate(infile):
|
||||
if has_boilerplate and i == 0:
|
||||
if i == 0:
|
||||
continue
|
||||
if "</svg>" in line:
|
||||
continue
|
||||
@@ -174,11 +195,10 @@ class CreateDrawing(bpy.types.Operator):
|
||||
elif should_skip:
|
||||
continue
|
||||
outfile.write(line)
|
||||
has_boilerplate = True
|
||||
if annotation:
|
||||
with open(annotation) as infile:
|
||||
for i, line in enumerate(infile):
|
||||
if has_boilerplate and i in [0, 1]:
|
||||
if i < 2:
|
||||
continue
|
||||
if "</svg>" in line:
|
||||
continue
|
||||
@@ -223,25 +243,7 @@ class CreateDrawing(bpy.types.Operator):
|
||||
for name, value in previous_visibility.items():
|
||||
bpy.data.objects[name].hide_set(value)
|
||||
|
||||
svg_writer = svgwriter.SvgWriter()
|
||||
render = context.scene.render
|
||||
if self.is_landscape(render):
|
||||
width = self.camera.data.ortho_scale
|
||||
height = width / render.resolution_x * render.resolution_y
|
||||
else:
|
||||
height = self.camera.data.ortho_scale
|
||||
width = height / render.resolution_y * render.resolution_x
|
||||
svg_writer.human_scale = self.human_scale
|
||||
svg_writer.scale = self.scale
|
||||
svg_writer.output = svg_path
|
||||
svg_writer.data_dir = context.scene.BIMProperties.data_dir
|
||||
svg_writer.vector_style = drawing_style.vector_style
|
||||
svg_writer.camera = self.camera
|
||||
svg_writer.camera_width = width
|
||||
svg_writer.camera_height = height
|
||||
svg_writer.camera_projection = tuple(self.camera.matrix_world.to_quaternion() @ Vector((0, 0, -1)))
|
||||
svg_writer.background_image = context.scene.render.filepath
|
||||
svg_writer.write("underlay")
|
||||
self.svg_writer.create_blank_svg(svg_path).draw_underlay(context.scene.render.filepath).save()
|
||||
return svg_path
|
||||
|
||||
def generate_linework(self, context):
|
||||
@@ -415,35 +417,13 @@ class CreateDrawing(bpy.types.Operator):
|
||||
if os.path.isfile(svg_path) and self.props.should_use_annotation_cache:
|
||||
return svg_path
|
||||
|
||||
camera = self.camera
|
||||
svg_writer = svgwriter.SvgWriter()
|
||||
|
||||
drawing_style = context.scene.DocProperties.drawing_styles[self.cprops.active_drawing_style_index]
|
||||
|
||||
render = context.scene.render
|
||||
if self.is_landscape(render):
|
||||
width = camera.data.ortho_scale
|
||||
height = width / render.resolution_x * render.resolution_y
|
||||
else:
|
||||
height = camera.data.ortho_scale
|
||||
width = height / render.resolution_y * render.resolution_x
|
||||
|
||||
svg_writer.human_scale = self.human_scale
|
||||
svg_writer.scale = self.scale
|
||||
svg_writer.output = svg_path
|
||||
svg_writer.data_dir = context.scene.BIMProperties.data_dir
|
||||
svg_writer.vector_style = drawing_style.vector_style
|
||||
svg_writer.camera = camera
|
||||
svg_writer.camera_width = width
|
||||
svg_writer.camera_height = height
|
||||
svg_writer.camera_projection = tuple(camera.matrix_world.to_quaternion() @ Vector((0, 0, -1)))
|
||||
|
||||
elements = tool.Drawing.get_group_elements(tool.Drawing.get_drawing_group(self.camera_element))
|
||||
svg_writer.annotations = sorted(elements, key=lambda a: tool.Drawing.get_annotation_z_index(a))
|
||||
svg_writer.metadata = tool.Drawing.get_drawing_metadata(self.camera_element)
|
||||
annotations = sorted(elements, key=lambda a: tool.Drawing.get_annotation_z_index(a))
|
||||
|
||||
svg_writer.write("annotation")
|
||||
return svg_writer.output
|
||||
self.svg_writer.metadata = tool.Drawing.get_drawing_metadata(self.camera_element)
|
||||
self.svg_writer.create_blank_svg(svg_path).draw_annotations(annotations).save()
|
||||
|
||||
return svg_path
|
||||
|
||||
def get_scale(self):
|
||||
if self.camera.data.BIMCameraProperties.diagram_scale == "CUSTOM":
|
||||
|
||||
@@ -36,14 +36,6 @@ from mathutils import geometry
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
def load_occ():
|
||||
# Don't import until we really need to, as a temporary step before we can purge OCC
|
||||
try:
|
||||
from OCC.Core import BRep, BRepTools, TopExp, TopAbs
|
||||
except ImportError:
|
||||
from OCC import BRep, BRepTools, TopExp, TopAbs
|
||||
|
||||
|
||||
class External(svgwrite.container.Group):
|
||||
def __init__(self, xml, **extra):
|
||||
self.xml = xml
|
||||
@@ -63,44 +55,51 @@ class External(svgwrite.container.Group):
|
||||
|
||||
class SvgWriter:
|
||||
def __init__(self):
|
||||
self.output = "out.svg"
|
||||
self.data_dir = None
|
||||
self.vector_style = None
|
||||
self.human_scale = "NTS"
|
||||
self.annotations = []
|
||||
self.metadata = []
|
||||
self.background_image = None
|
||||
self.scale = 1 / 100 # 1:100
|
||||
self.camera_width = None
|
||||
self.camera_height = None
|
||||
|
||||
def write(self, layer):
|
||||
def create_blank_svg(self, output_path):
|
||||
self.calculate_scale()
|
||||
self.svg = svgwrite.Drawing(
|
||||
self.output,
|
||||
debug=False,
|
||||
output_path,
|
||||
size=("{}mm".format(self.width), "{}mm".format(self.height)),
|
||||
viewBox=("0 0 {} {}".format(self.width, self.height)),
|
||||
id="root",
|
||||
data_scale=self.human_scale,
|
||||
debug=False, # Disable validation so that we can insert the IFC namespace
|
||||
)
|
||||
self.svg.attribs["xmlns:ifc"] = "http://www.ifcopenshell.org/ns"
|
||||
return self
|
||||
|
||||
if layer == "underlay":
|
||||
self.draw_background_image()
|
||||
elif layer == "annotation":
|
||||
self.add_stylesheet()
|
||||
self.add_markers()
|
||||
self.add_symbols()
|
||||
self.add_patterns()
|
||||
# self.draw_background_elements()
|
||||
# self.draw_cut_polygons()
|
||||
self.draw_annotations()
|
||||
def save(self):
|
||||
self.svg.save(pretty=True)
|
||||
|
||||
def draw_underlay(self, image):
|
||||
self.svg.add(
|
||||
self.svg.image(
|
||||
os.path.join("..", "diagrams", os.path.basename(image)), width=self.width, height=self.height,
|
||||
)
|
||||
)
|
||||
return self
|
||||
|
||||
def define_boilerplate(self):
|
||||
self.add_stylesheet()
|
||||
self.add_markers()
|
||||
self.add_symbols()
|
||||
self.add_patterns()
|
||||
return self
|
||||
|
||||
def calculate_scale(self):
|
||||
self.scale *= 1000 # IFC is in meters, SVG is in mm
|
||||
self.svg_scale = self.scale * 1000 # IFC is in meters, SVG is in mm
|
||||
self.raw_width = self.camera_width
|
||||
self.raw_height = self.camera_height
|
||||
self.width = self.raw_width * self.scale
|
||||
self.height = self.raw_height * self.scale
|
||||
self.width = self.raw_width * self.svg_scale
|
||||
self.height = self.raw_height * self.svg_scale
|
||||
|
||||
def add_stylesheet(self):
|
||||
with open(os.path.join(self.data_dir, "styles", f"{self.vector_style}.css"), "r") as stylesheet:
|
||||
@@ -124,26 +123,8 @@ class SvgWriter:
|
||||
for child in root:
|
||||
self.svg.defs.add(External(child))
|
||||
|
||||
def draw_background_image(self):
|
||||
self.svg.add(
|
||||
self.svg.image(
|
||||
os.path.join("..", "diagrams", os.path.basename(self.background_image)),
|
||||
**{"width": self.width, "height": self.height},
|
||||
)
|
||||
)
|
||||
|
||||
def draw_background_elements(self):
|
||||
return # TODO purge?
|
||||
for element in self.ifc_cutter.background_elements:
|
||||
if element["type"] == "polygon":
|
||||
self.draw_polygon(element, "background")
|
||||
elif element["type"] == "polyline":
|
||||
self.draw_polyline(element, "background")
|
||||
elif element["type"] == "line":
|
||||
self.draw_line(element, "background")
|
||||
|
||||
def draw_annotations(self):
|
||||
for element in self.annotations:
|
||||
def draw_annotations(self, annotations):
|
||||
for element in annotations:
|
||||
obj = tool.Ifc.get_object(element)
|
||||
if not obj or element.ObjectType == "DRAWING":
|
||||
continue
|
||||
@@ -180,6 +161,7 @@ class SvgWriter:
|
||||
|
||||
# Experimental integration with the MeasureIt-ARCH Add-on
|
||||
self.draw_measureit_arch_dimension_annotations()
|
||||
return self
|
||||
|
||||
def draw_section_level_annotation(self, obj):
|
||||
x_offset = self.raw_width / 2
|
||||
@@ -194,7 +176,7 @@ class SvgWriter:
|
||||
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.scale, (y_offset - p.y) * self.scale)
|
||||
"L {} {}".format((x_offset + p.x) * self.svg_scale, (y_offset - p.y) * self.svg_scale)
|
||||
for p in projected_points
|
||||
]
|
||||
)
|
||||
@@ -202,8 +184,8 @@ class SvgWriter:
|
||||
path = self.svg.add(self.svg.path(d=d, class_=" ".join(classes)))
|
||||
text_position = Vector(
|
||||
(
|
||||
(x_offset + projected_points[0].x) * self.scale,
|
||||
((y_offset - projected_points[0].y) * self.scale) - 3.5,
|
||||
(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
|
||||
@@ -233,14 +215,14 @@ class SvgWriter:
|
||||
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.scale, (y_offset - p.y) * self.scale)
|
||||
"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:])
|
||||
start = Vector(((x_offset + projected_points[0].x), (y_offset - projected_points[0].y)))
|
||||
next_point = Vector(((x_offset + projected_points[1].x), (y_offset - projected_points[1].y)))
|
||||
text_position = (start * self.scale) - ((next_point - start).normalized() * 5)
|
||||
text_position = (start * self.svg_scale) - ((next_point - start).normalized() * 5)
|
||||
path = self.svg.add(self.svg.path(d=d, class_=" ".join(classes)))
|
||||
self.svg.add(
|
||||
self.svg.text(
|
||||
@@ -270,14 +252,14 @@ class SvgWriter:
|
||||
end = Vector(((x_offset + v1.x), (y_offset - v1.y)))
|
||||
vector = end - start
|
||||
line = self.svg.add(
|
||||
self.svg.line(start=tuple(start * self.scale), end=tuple(end * self.scale), class_=" ".join(classes))
|
||||
self.svg.line(start=tuple(start * self.svg_scale), end=tuple(end * self.svg_scale), class_=" ".join(classes))
|
||||
)
|
||||
line["stroke-dasharray"] = "12.5, 3, 3, 3"
|
||||
axis_tag = tool.Ifc.get_entity(obj).Name
|
||||
self.svg.add(
|
||||
self.svg.text(
|
||||
axis_tag,
|
||||
insert=tuple(start * self.scale),
|
||||
insert=tuple(start * self.svg_scale),
|
||||
**{
|
||||
"font-size": annotation.Annotator.get_svg_text_size(5.0),
|
||||
"font-family": "OpenGost Type B TT",
|
||||
@@ -290,7 +272,7 @@ class SvgWriter:
|
||||
self.svg.add(
|
||||
self.svg.text(
|
||||
axis_tag,
|
||||
insert=tuple(end * self.scale),
|
||||
insert=tuple(end * self.svg_scale),
|
||||
**{
|
||||
"font-size": annotation.Annotator.get_svg_text_size(5.0),
|
||||
"font-family": "OpenGost Type B TT",
|
||||
@@ -320,7 +302,7 @@ class SvgWriter:
|
||||
projected_points.append(projected_points[0])
|
||||
d = " ".join(
|
||||
[
|
||||
"L {} {}".format((x_offset + p.x) * self.scale, (y_offset - p.y) * self.scale)
|
||||
"L {} {}".format((x_offset + p.x) * self.svg_scale, (y_offset - p.y) * self.svg_scale)
|
||||
for p in projected_points
|
||||
]
|
||||
)
|
||||
@@ -357,7 +339,7 @@ class SvgWriter:
|
||||
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.scale, (y_offset - p.y) * self.scale)
|
||||
"L {} {}".format((x_offset + p.x) * self.svg_scale, (y_offset - p.y) * self.svg_scale)
|
||||
for p in projected_points
|
||||
]
|
||||
)
|
||||
@@ -379,7 +361,7 @@ class SvgWriter:
|
||||
end = Vector(((x_offset + v1.x), (y_offset - v1.y)))
|
||||
vector = end - start
|
||||
line = self.svg.add(
|
||||
self.svg.line(start=tuple(start * self.scale), end=tuple(end * self.scale), class_=" ".join(classes))
|
||||
self.svg.line(start=tuple(start * self.svg_scale), end=tuple(end * self.svg_scale), class_=" ".join(classes))
|
||||
)
|
||||
|
||||
def draw_leader_annotation(self, obj):
|
||||
@@ -408,17 +390,17 @@ class SvgWriter:
|
||||
symbol_position = Vector(((x_offset + symbol_position.x), (y_offset - symbol_position.y)))
|
||||
transform = "rotate({}, {}, {})".format(
|
||||
angle,
|
||||
(symbol_position * self.scale)[0],
|
||||
(symbol_position * self.scale)[1],
|
||||
(symbol_position * self.svg_scale)[0],
|
||||
(symbol_position * self.svg_scale)[1],
|
||||
)
|
||||
|
||||
self.svg.add(
|
||||
self.svg.use("#section-arrow", insert=tuple(symbol_position * self.scale), transform=transform)
|
||||
self.svg.use("#section-arrow", insert=tuple(symbol_position * self.svg_scale), transform=transform)
|
||||
)
|
||||
self.svg.add(self.svg.use("#section-tag", insert=tuple(symbol_position * self.scale)))
|
||||
self.svg.add(self.svg.use("#section-tag", insert=tuple(symbol_position * self.svg_scale)))
|
||||
|
||||
reference_id, sheet_id = self.get_reference_and_sheet_id_from_annotation(tool.Ifc.get_entity(obj))
|
||||
text_position = list(symbol_position * self.scale)
|
||||
text_position = list(symbol_position * self.svg_scale)
|
||||
text_style = {
|
||||
"font-size": annotation.Annotator.get_svg_text_size(2.5),
|
||||
"font-family": "OpenGost Type B TT",
|
||||
@@ -441,15 +423,15 @@ class SvgWriter:
|
||||
|
||||
transform = "rotate({}, {}, {})".format(
|
||||
angle,
|
||||
(symbol_position * self.scale)[0],
|
||||
(symbol_position * self.scale)[1],
|
||||
(symbol_position * self.svg_scale)[0],
|
||||
(symbol_position * self.svg_scale)[1],
|
||||
)
|
||||
|
||||
self.svg.add(self.svg.use("#elevation-arrow", insert=tuple(symbol_position * self.scale), transform=transform))
|
||||
self.svg.add(self.svg.use("#elevation-tag", insert=tuple(symbol_position * self.scale)))
|
||||
self.svg.add(self.svg.use("#elevation-arrow", insert=tuple(symbol_position * self.svg_scale), transform=transform))
|
||||
self.svg.add(self.svg.use("#elevation-tag", insert=tuple(symbol_position * self.svg_scale)))
|
||||
|
||||
reference_id, sheet_id = self.get_reference_and_sheet_id_from_annotation(tool.Ifc.get_entity(obj))
|
||||
text_position = list(symbol_position * self.scale)
|
||||
text_position = list(symbol_position * self.svg_scale)
|
||||
text_style = {
|
||||
"font-size": annotation.Annotator.get_svg_text_size(2.5),
|
||||
"font-family": "OpenGost Type B TT",
|
||||
@@ -497,13 +479,13 @@ class SvgWriter:
|
||||
|
||||
transform = "rotate({}, {}, {})".format(
|
||||
angle,
|
||||
(text_position * self.scale)[0],
|
||||
(text_position * self.scale)[1],
|
||||
(text_position * self.svg_scale)[0],
|
||||
(text_position * self.svg_scale)[1],
|
||||
)
|
||||
|
||||
symbol = tool.Drawing.get_annotation_symbol(element)
|
||||
if symbol:
|
||||
self.svg.add(self.svg.use(f"#{symbol}", insert=tuple(text_position * self.scale)))
|
||||
self.svg.add(self.svg.use(f"#{symbol}", insert=tuple(text_position * self.svg_scale)))
|
||||
|
||||
if text_literal.BoxAlignment == "top-left":
|
||||
alignment_baseline = "hanging"
|
||||
@@ -535,7 +517,7 @@ class SvgWriter:
|
||||
|
||||
literal = text_literal.Literal
|
||||
|
||||
product = tool.Drawing.get_text_product(element)
|
||||
product = tool.Drawing.get_assigned_product(element)
|
||||
selector = ifcopenshell.util.selector.Selector
|
||||
variables = {}
|
||||
for variable in re.findall("{{.*?}}", literal):
|
||||
@@ -545,7 +527,7 @@ class SvgWriter:
|
||||
self.svg.add(
|
||||
self.svg.text(
|
||||
text_line,
|
||||
insert=tuple((text_position * self.scale) + Vector((0, 3.5 * line_number))),
|
||||
insert=tuple((text_position * self.svg_scale) + Vector((0, 3.5 * line_number))),
|
||||
class_=" ".join(self.get_attribute_classes(text_obj)),
|
||||
**{
|
||||
"font-size": annotation.Annotator.get_svg_text_size(text_obj.BIMTextProperties.font_size),
|
||||
@@ -574,7 +556,7 @@ class SvgWriter:
|
||||
]
|
||||
d = " ".join(
|
||||
[
|
||||
"L {} {}".format((x_offset + p.x) * self.scale, (y_offset - p.y) * self.scale)
|
||||
"L {} {}".format((x_offset + p.x) * self.svg_scale, (y_offset - p.y) * self.svg_scale)
|
||||
for p in projected_points
|
||||
]
|
||||
)
|
||||
@@ -591,7 +573,7 @@ class SvgWriter:
|
||||
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.scale, (y_offset - p.y) * self.scale)
|
||||
"L {} {}".format((x_offset + p.x) * self.svg_scale, (y_offset - p.y) * self.svg_scale)
|
||||
for p in projected_points
|
||||
]
|
||||
)
|
||||
@@ -599,8 +581,8 @@ class SvgWriter:
|
||||
path = self.svg.add(self.svg.path(d=d, class_=" ".join(classes)))
|
||||
text_position = Vector(
|
||||
(
|
||||
(x_offset + projected_points[0].x) * self.scale,
|
||||
((y_offset - projected_points[0].y) * self.scale) - 2.5,
|
||||
(x_offset + projected_points[0].x) * self.svg_scale,
|
||||
((y_offset - projected_points[0].y) * self.svg_scale) - 2.5,
|
||||
)
|
||||
)
|
||||
# TODO: allow metric to be configurable
|
||||
@@ -698,11 +680,11 @@ class SvgWriter:
|
||||
arc_midpoint = center + ((cog - center).normalized() * radius)
|
||||
|
||||
text_position = self.project_point_onto_camera(arc_midpoint)
|
||||
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.svg_scale, (y_offset - text_position.y) * self.svg_scale))
|
||||
|
||||
center_projected = self.project_point_onto_camera(center)
|
||||
center_position = Vector(
|
||||
((x_offset + center_projected.x) * self.scale, (y_offset - center_projected.y) * self.scale)
|
||||
((x_offset + center_projected.x) * self.svg_scale, (y_offset - center_projected.y) * self.svg_scale)
|
||||
)
|
||||
text_offset = (text_position - center_position).xy.normalized() * 5
|
||||
text_position += text_offset
|
||||
@@ -722,9 +704,9 @@ class SvgWriter:
|
||||
|
||||
# Draw SVG arc, see for details: http://xahlee.info/js/svg_circle_arc.html
|
||||
arc_proj_end_pts = [self.project_point_onto_camera(v) for v in arc_end_pts]
|
||||
p1 = Vector(((x_offset + arc_proj_end_pts[0].x) * self.scale, (y_offset - arc_proj_end_pts[0].y) * self.scale))
|
||||
p2 = Vector(((x_offset + arc_proj_end_pts[1].x) * self.scale, (y_offset - arc_proj_end_pts[1].y) * self.scale))
|
||||
r = radius * self.scale
|
||||
p1 = Vector(((x_offset + arc_proj_end_pts[0].x) * self.svg_scale, (y_offset - arc_proj_end_pts[0].y) * self.svg_scale))
|
||||
p2 = Vector(((x_offset + arc_proj_end_pts[1].x) * self.svg_scale, (y_offset - arc_proj_end_pts[1].y) * self.svg_scale))
|
||||
r = radius * self.svg_scale
|
||||
# reflex = 1 if angle > math.pi else 0
|
||||
reflex = is_reflex
|
||||
if reflex:
|
||||
@@ -745,7 +727,7 @@ class SvgWriter:
|
||||
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.scale, (y_offset - p.y) * self.scale)
|
||||
"L {} {}".format((x_offset + p.x) * self.svg_scale, (y_offset - p.y) * self.svg_scale)
|
||||
for p in projected_points
|
||||
]
|
||||
)
|
||||
@@ -753,15 +735,15 @@ class SvgWriter:
|
||||
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)
|
||||
((x_offset + projected_points[0].x) * self.svg_scale, (y_offset - projected_points[0].y) * self.svg_scale)
|
||||
)
|
||||
p1 = Vector(
|
||||
((x_offset + projected_points[1].x) * self.scale, (y_offset - projected_points[1].y) * self.scale)
|
||||
((x_offset + projected_points[1].x) * self.svg_scale, (y_offset - projected_points[1].y) * self.svg_scale)
|
||||
)
|
||||
text_offset = (p0 - p1).xy.normalized() * 5
|
||||
text_position = projected_points[0]
|
||||
text_position = Vector(
|
||||
((x_offset + text_position.x) * self.scale, (y_offset - text_position.y) * self.scale)
|
||||
((x_offset + text_position.x) * self.svg_scale, (y_offset - text_position.y) * self.svg_scale)
|
||||
)
|
||||
text_position += text_offset
|
||||
|
||||
@@ -833,15 +815,15 @@ class SvgWriter:
|
||||
perpendicular = Vector((vector.y, -vector.x)).normalized()
|
||||
dimension = (v1_global - v0_global).length
|
||||
dimension = helper.format_distance(dimension)
|
||||
sheet_dimension = ((end * self.scale) - (start * self.scale)).length
|
||||
sheet_dimension = ((end * self.svg_scale) - (start * self.svg_scale)).length
|
||||
if sheet_dimension < 5: # annotation can't fit
|
||||
# offset text to right of marker
|
||||
text_position = (end * self.scale) + perpendicular + (3 * vector.normalized())
|
||||
text_position = (end * self.svg_scale) + perpendicular + (3 * vector.normalized())
|
||||
else:
|
||||
text_position = (mid * self.scale) + perpendicular
|
||||
text_position = (mid * self.svg_scale) + perpendicular
|
||||
rotation = math.degrees(vector.angle_signed(Vector((1, 0))))
|
||||
line = self.svg.add(
|
||||
self.svg.line(start=tuple(start * self.scale), end=tuple(end * self.scale), class_=" ".join(classes))
|
||||
self.svg.line(start=tuple(start * self.svg_scale), end=tuple(end * self.svg_scale), class_=" ".join(classes))
|
||||
)
|
||||
if text_override is not None:
|
||||
text = text_override
|
||||
@@ -873,35 +855,8 @@ class SvgWriter:
|
||||
def get_spline_points(self, spline):
|
||||
return spline.bezier_points if spline.bezier_points else spline.points
|
||||
|
||||
def draw_cut_polygons(self):
|
||||
return # deprecate?
|
||||
for polygon in self.ifc_cutter.cut_polygons:
|
||||
self.draw_polygon(polygon, "cut")
|
||||
|
||||
def draw_polyline(self, element, position):
|
||||
load_occ()
|
||||
classes = self.get_classes(element["raw"], position)
|
||||
exp = BRepTools.BRepTools_WireExplorer(element["geometry"])
|
||||
points = []
|
||||
while exp.More():
|
||||
point = BRep.BRep_Tool.Pnt(exp.CurrentVertex())
|
||||
points.append((point.X() * self.scale, -point.Y() * self.scale))
|
||||
exp.Next()
|
||||
self.svg.add(self.svg.polyline(points=points, class_=" ".join(classes)))
|
||||
|
||||
def draw_line(self, element, position):
|
||||
load_occ()
|
||||
classes = self.get_classes(element["raw"], position)
|
||||
exp = TopExp.TopExp_Explorer(element["geometry"], TopAbs.TopAbs_VERTEX)
|
||||
points = []
|
||||
while exp.More():
|
||||
point = BRep.BRep_Tool.Pnt(topods.Vertex(exp.Current()))
|
||||
points.append((point.X() * self.scale, -point.Y() * self.scale))
|
||||
exp.Next()
|
||||
self.svg.add(self.svg.line(start=points[0], end=points[1], class_=" ".join(classes)))
|
||||
|
||||
def draw_polygon(self, polygon, position):
|
||||
points = [(p[0] * self.scale, p[1] * self.scale) for p in polygon["points"]]
|
||||
points = [(p[0] * self.svg_scale, p[1] * self.svg_scale) for p in polygon["points"]]
|
||||
if "classes" in polygon["metadata"]:
|
||||
classes = " ".join(polygon["metadata"]["classes"])
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user