Skip to content

init

SVGGenerator(output_folder, svg_writer, shape_context, units='mm', style=None)

Generates SVGs for slices.

Attributes:

Name Type Description
output_folder str

The folder to output the SVGs to.

svg_writer SVGWriter

The SVG writer to use.

shape_context StrategyContext

The shape strategy context to use.

units str

The unit of the model's numbers: mm, cm or in. It is the unit of the width and height of every SVG.

style SVGStyle

The colours and the hairline width of every SVG (TR-14).

Parameters:

Name Type Description Default
output_folder str

The folder to output the SVGs to.

required
svg_writer SVGWriter

The SVG writer to use.

required
shape_context StrategyContext

The shape strategy context to use.

required
units str

The unit of the model's numbers, used for the size of every SVG.

'mm'
style SVGStyle

The colours and the hairline width, in units. Without it, the default style, with the hairline of 0.01 mm stated in units.

None
Source code in src/layerforge/svg/svg_generator.py
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
def __init__(
    self,
    output_folder: str,
    svg_writer: SVGWriter,
    shape_context: StrategyContext,
    units: str = "mm",
    style: SVGStyle | None = None,
):
    """Initializes the SVG generator.

    Parameters
    ----------
    output_folder : str
        The folder to output the SVGs to.
    svg_writer : SVGWriter
        The SVG writer to use.
    shape_context : StrategyContext
        The shape strategy context to use.
    units : str
        The unit of the model's numbers, used for the size of every SVG.
    style : SVGStyle, optional
        The colours and the hairline width, in ``units``. Without it, the default style,
        with the hairline of 0.01 mm stated in ``units``.
    """
    self.output_folder = output_folder
    self.svg_writer = svg_writer
    self.shape_context = shape_context
    self.units = units
    self.style = style or SVGStyle.for_units(units)

generate_svgs(slices)

Generates SVGs for slices.

Parameters:

Name Type Description Default
slices List[Slice]

The slices to generate SVGs for.

required

Returns:

Type Description
None
Source code in src/layerforge/svg/svg_generator.py
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
def generate_svgs(self, slices: list[Slice]) -> None:
    """Generates SVGs for slices.

    Parameters
    ----------
    slices : List[Slice]
        The slices to generate SVGs for.

    Returns
    -------
    None
    """
    view_box = self._view_box(slices)
    for slice_obj in slices:
        if view_box is None:
            dwg = svgwrite.Drawing(profile="tiny")
        else:
            x, y, width, height = view_box
            # The size is the view box size in the unit, as text: the tiny profile
            # rounds a float attribute, so a number would differ from the view box.
            size = (f"{width}{self.units}", f"{height}{self.units}")
            dwg = svgwrite.Drawing(profile="tiny", size=size)
            dwg.viewbox(x, y, width, height)
        SliceSVGDrawer.draw_slice(dwg, slice_obj, self.shape_context, style=self.style)
        self.svg_writer.write(dwg, self.output_folder, slice_obj.index)

SliceSVGDrawer

Draws SVGs for slices.

The model's y axis points up and SVG's points down, so everything is drawn at (x, -y). Seen in a viewer, the slice then has the same handedness as the model seen from above.

Everything that is cut, the outlines and the marks, gets the cut colour, a hairline stroke and no fill (TR-14). The two kinds differ by their class, not by colour. The number of a piece is text with the engrave colour and no stroke (TR-11).

draw_contour(dwg, contour, style=None) staticmethod

Draws a contour: its outer outline and the outline of each hole.

Parameters:

Name Type Description Default
dwg Drawing

The SVG drawing.

required
contour Polygon

The contour to draw.

required
style SVGStyle

The colours and the stroke. Without it, the default style in millimetres.

None

Returns:

Type Description
None
Source code in src/layerforge/svg/slice_svg_drawer.py
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
@staticmethod
def draw_contour(dwg: Drawing, contour: Polygon, style: SVGStyle | None = None) -> None:
    """Draws a contour: its outer outline and the outline of each hole.

    Parameters
    ----------
    dwg : Drawing
        The SVG drawing.
    contour : Polygon
        The contour to draw.
    style : SVGStyle, optional
        The colours and the stroke. Without it, the default style in millimetres.

    Returns
    -------
    None
    """
    attribs = SliceSVGDrawer._cut_attribs(style or SVGStyle(), "outline")
    for ring in [contour.exterior, *contour.interiors]:
        points = [(x, -y) for x, y in ring.coords]
        dwg.add(dwg.polygon(points, **attribs))

draw_reference_marks(dwg, ref_marks, shape_context, style=None) staticmethod

Draws reference marks.

Parameters:

Name Type Description Default
dwg Drawing

The SVG drawing.

required
ref_marks list

The reference marks to draw.

required
shape_context StrategyContext

The shape drawing context.

required
style SVGStyle

The colours and the stroke. Without it, the default style in millimetres.

None

Returns:

Type Description
None
Source code in src/layerforge/svg/slice_svg_drawer.py
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
@staticmethod
def draw_reference_marks(
    dwg: Drawing,
    ref_marks: list[ReferenceMark],
    shape_context: StrategyContext,
    style: SVGStyle | None = None,
) -> None:
    """Draws reference marks.

    Parameters
    ----------
    dwg : Drawing
        The SVG drawing.
    ref_marks : list
        The reference marks to draw.
    shape_context : StrategyContext
        The shape drawing context.
    style : SVGStyle, optional
        The colours and the stroke. Without it, the default style in millimetres.

    Returns
    -------
    None
    """
    attribs = SliceSVGDrawer._cut_attribs(style or SVGStyle(), "mark")
    for mark in ref_marks:
        shape_instance = ShapeFactory.get_shape(
            mark.shape,
            mark.x,
            -mark.y,
            size=mark.size,
            angle=-mark.angle,
        )
        shape_context.draw(dwg, shape_instance, **attribs)

draw_slice(dwg, slice_obj, shape_context, *, style=None) staticmethod

Draws a slice: the outlines, the marks and the number of each piece.

The number is the slice index. It goes where its box is farthest from every cut (:func:place_number). When it fits nowhere, it is drawn at the middle of the piece and one warning names the slice.

Parameters:

Name Type Description Default
dwg Drawing

The SVG drawing.

required
slice_obj Slice

The slice to draw.

required
shape_context StrategyContext

The shape drawing context.

required
style SVGStyle

The colours, the stroke and the number. Without it, the default style in millimetres.

None

Returns:

Type Description
None
Source code in src/layerforge/svg/slice_svg_drawer.py
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
@staticmethod
def draw_slice(
    dwg: Drawing,
    slice_obj: Slice,
    shape_context: StrategyContext,
    *,
    style: SVGStyle | None = None,
) -> None:
    """Draws a slice: the outlines, the marks and the number of each piece.

    The number is the slice index. It goes where its box is farthest from every cut
    (:func:`place_number`). When it fits nowhere, it is drawn at the middle of the piece and
    one warning names the slice.

    Parameters
    ----------
    dwg : Drawing
        The SVG drawing.
    slice_obj : Slice
        The slice to draw.
    shape_context : StrategyContext
        The shape drawing context.
    style : SVGStyle, optional
        The colours, the stroke and the number. Without it, the default style in millimetres.

    Returns
    -------
    None
    """
    style = style or SVGStyle()
    for contour in slice_obj.contours:
        SliceSVGDrawer.draw_contour(dwg, contour, style)

    SliceSVGDrawer.draw_reference_marks(dwg, slice_obj.ref_marks, shape_context, style)

    label = str(slice_obj.index)
    misfits: list[Polygon] = []
    for contour in slice_obj.contours:
        placement = place_number(
            contour,
            slice_obj.ref_marks,
            digits=len(label),
            height=style.number_height,
            width_factor=style.number_width_factor,
            clearance=style.number_clearance,
        )
        if not placement.fits:
            misfits.append(contour)
        dwg.add(
            dwg.text(
                label,
                insert=(
                    placement.x,
                    -placement.y + SliceSVGDrawer._BASELINE_SHIFT * style.number_height,
                ),
                text_anchor="middle",
                fill=style.engrave_color,
                font_size=plain_number(style.number_height),
                font_family="sans-serif",
                font_weight="bold",
            )
        )
    if misfits:
        SliceSVGDrawer._warn_number_does_not_fit(slice_obj, misfits, len(label), style)