summaryrefslogtreecommitdiff
path: root/gerbonara/graphic_primitives.py
diff options
context:
space:
mode:
Diffstat (limited to 'gerbonara/graphic_primitives.py')
-rw-r--r--gerbonara/graphic_primitives.py23
1 files changed, 15 insertions, 8 deletions
diff --git a/gerbonara/graphic_primitives.py b/gerbonara/graphic_primitives.py
index 072a98a..7dc1126 100644
--- a/gerbonara/graphic_primitives.py
+++ b/gerbonara/graphic_primitives.py
@@ -26,7 +26,7 @@ from .utils import *
prec = lambda x: f'{float(x):.6}'
-@dataclass
+@dataclass(frozen=True)
class GraphicPrimitive:
# hackety hack: Work around python < 3.10 not having dataclasses.KW_ONLY.
@@ -63,7 +63,7 @@ class GraphicPrimitive:
raise NotImplementedError()
-@dataclass
+@dataclass(frozen=True)
class Circle(GraphicPrimitive):
#: Center X coordinate
x : float
@@ -80,7 +80,7 @@ class Circle(GraphicPrimitive):
return tag('circle', cx=prec(self.x), cy=prec(self.y), r=prec(self.r), style=f'fill: {color}')
-@dataclass
+@dataclass(frozen=True)
class ArcPoly(GraphicPrimitive):
""" Polygon whose sides may be either straight lines or circular arcs. """
@@ -132,7 +132,7 @@ class ArcPoly(GraphicPrimitive):
""" Return ``True`` if this polygon has any outline points. """
return bool(len(self))
- def _path_d(self):
+ def path_d(self):
if len(self.outline) == 0:
return
@@ -147,10 +147,10 @@ class ArcPoly(GraphicPrimitive):
def to_svg(self, fg='black', bg='white', tag=Tag):
color = fg if self.polarity_dark else bg
- return tag('path', d=' '.join(self._path_d()), style=f'fill: {color}')
+ return tag('path', d=' '.join(self.path_d()), style=f'fill: {color}')
-@dataclass
+@dataclass(frozen=True)
class Line(GraphicPrimitive):
""" Straight line with round end caps. """
#: Start X coordinate. As usual in modern graphics APIs, this is at the center of the half-circle capping off this
@@ -165,6 +165,9 @@ class Line(GraphicPrimitive):
#: Line width
width : float
+ def flip(self):
+ return replace(self, x1=self.x2, y1=self.y2, x2=self.x1, y2=self.y1)
+
@classmethod
def from_obround(kls, x:float, y:float, w:float, h:float, rotation:float=0, polarity_dark:bool=True):
""" Convert a gerber obround into a :py:class:`~.graphic_primitives.Line`. """
@@ -188,7 +191,7 @@ class Line(GraphicPrimitive):
return tag('path', d=f'M {self.x1:.6} {self.y1:.6} L {self.x2:.6} {self.y2:.6}',
style=f'fill: none; stroke: {color}; stroke-width: {width}; stroke-linecap: round')
-@dataclass
+@dataclass(frozen=True)
class Arc(GraphicPrimitive):
""" Circular arc with line width ``width`` going from ``(x1, y1)`` to ``(x2, y2)`` around center at ``(cx, cy)``. """
#: Start X coodinate
@@ -209,6 +212,10 @@ class Arc(GraphicPrimitive):
#: Line width of this arc.
width : float
+ def flip(self):
+ return replace(self, x1=self.x2, y1=self.y2, x2=self.x1, y2=self.y1,
+ cx=(self.x + self.cx) - self.x2, cy=(self.y + self.cy) - self.y2, clockwise=not self.clockwise)
+
def bounding_box(self):
r = self.width/2
endpoints = add_bounds(Circle(self.x1, self.y1, r).bounding_box(), Circle(self.x2, self.y2, r).bounding_box())
@@ -236,7 +243,7 @@ class Arc(GraphicPrimitive):
return tag('path', d=f'M {self.x1:.6} {self.y1:.6} {arc}',
style=f'fill: none; stroke: {color}; stroke-width: {width}; stroke-linecap: round; fill: none')
-@dataclass
+@dataclass(frozen=True)
class Rectangle(GraphicPrimitive):
#: **Center** X coordinate
x : float