diff --git a/src/bonsai/bonsai/bim/module/drawing/operator.py b/src/bonsai/bonsai/bim/module/drawing/operator.py index 8c7ea0c65d..23198c60d7 100644 --- a/src/bonsai/bonsai/bim/module/drawing/operator.py +++ b/src/bonsai/bonsai/bim/module/drawing/operator.py @@ -313,16 +313,15 @@ class CreateDrawing(bpy.types.Operator): # Reassign props as data is recreated during the update. self.cprops = tool.Drawing.get_camera_props(self.camera) - self.svg_writer = svgwriter.SvgWriter() - self.svg_writer.human_scale = self.human_scale - self.svg_writer.scale = self.scale - 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)) + camera_dims = self.get_camera_dimensions() + self.svg_writer = svgwriter.SvgWriter( + camera_width=camera_dims[0], + camera_height=camera_dims[1], + camera=self.camera, + camera_projection=(self.camera.matrix_world.to_quaternion() @ Vector((0, 0, -1))), + scale=self.scale, + human_scale=self.human_scale, ) - self.svg_writer.calculate_scale() - self.svg_writer.setup_drawing_resource_paths(self.camera_element) underlay_svg = None @@ -358,8 +357,10 @@ class CreateDrawing(bpy.types.Operator): bpy.ops.bim.activate_drawing(drawing=original_drawing_id, should_view_from_camera=False) return {"FINISHED"} - def get_camera_dimensions(self): + def get_camera_dimensions(self) -> tuple[float, float]: + assert bpy.context.scene render = bpy.context.scene.render + assert isinstance(self.camera.data, bpy.types.Camera) if self.is_landscape(render): width = self.camera.data.ortho_scale height = width / render.resolution_x * render.resolution_y diff --git a/src/bonsai/bonsai/bim/module/drawing/svgwriter.py b/src/bonsai/bonsai/bim/module/drawing/svgwriter.py index 9b42b01c54..f372fdf60c 100644 --- a/src/bonsai/bonsai/bim/module/drawing/svgwriter.py +++ b/src/bonsai/bonsai/bim/module/drawing/svgwriter.py @@ -61,15 +61,28 @@ class External(svgwrite.container.Group): class SvgWriter: metadata: list[str] + resource_paths: dict[tool.Drawing.ResourceType, Union[str, None]] - def __init__(self): + def __init__( + self, + *, + camera_width: float, + camera_height: float, + camera: bpy.types.Object, + camera_projection: Vector, + scale: float = 1 / 100, # 1:100 + human_scale: str = "NTS", + ): self.data_dir = None - self.human_scale = "NTS" + self.human_scale = human_scale self.metadata = [] - self.scale = 1 / 100 # 1:100 - self.camera_width = None - self.camera_height = None + self.scale = scale + self.camera = camera + self.camera_width = camera_width + self.camera_height = camera_height + self.camera_projection = camera_projection self.resource_paths = {} + self.calculate_scale() def create_blank_svg(self, output_path: str) -> Self: self.calculate_scale() @@ -93,7 +106,7 @@ class SvgWriter: def setup_drawing_resource_paths(self, element: ifcopenshell.entity_instance) -> None: pset = ifcopenshell.util.element.get_pset(element, "EPset_Drawing") - for resource in ("Stylesheet", "Markers", "Symbols", "Patterns", "ShadingStyles"): + for resource in tool.Drawing.RESOURCE_TYPES: resource_path = pset.get(resource) if not resource_path: self.resource_paths[resource] = None @@ -1085,7 +1098,7 @@ class SvgWriter: # When rewriting to use polylines, we should use this normal instead. # center = tool.Cad.get_center_of_arc([p.to_3d() for p in arc_points], None).to_2d() # normal = mathutils.geometry.normal([arc_end_pts[0], arc_end_pts[1], center]) - # normal = Vector(self.camera_projection) + # normal = self.camera_projection # dir1 = (arc_end_pts[0] - center).normalized() # arc_mid_dir = (arc_end_pts[1] - center).normalized() @@ -1462,9 +1475,9 @@ class SvgWriter: # TODO is this needlessly complex? return self.camera.matrix_world.inverted() @ geometry.intersect_line_plane( point.xyz, - point.xyz - Vector(self.camera_projection), + point.xyz - self.camera_projection, self.camera.location, - Vector(self.camera_projection), + self.camera_projection, ) def get_spline_points(self, spline: bpy.types.Spline) -> Union[SplineBezierPoints, SplinePoints]: diff --git a/src/bonsai/bonsai/tool/drawing.py b/src/bonsai/bonsai/tool/drawing.py index 41f5ebc356..e6721ae53d 100644 --- a/src/bonsai/bonsai/tool/drawing.py +++ b/src/bonsai/bonsai/tool/drawing.py @@ -1285,6 +1285,9 @@ class Drawing(bonsai.core.tool.Drawing): def sanitise_filename(cls, name: str) -> str: return "".join(x for x in name if (x.isalnum() or x in "._- ")) + ResourceType = Literal["Stylesheet", "Markers", "Symbols", "Patterns", "ShadingStyles"] + RESOURCE_TYPES = ("Stylesheet", "Markers", "Symbols", "Patterns", "ShadingStyles") + @classmethod def get_default_drawing_resource_path(cls, resource: str) -> Union[str, None]: project = tool.Ifc.get().by_type("IfcProject")[0]