From a0e8aa16e1a34a8309f9fefed90fd5ddf6b33709 Mon Sep 17 00:00:00 2001
From: jaseg <git@jaseg.de>
Date: Wed, 29 Dec 2021 22:34:01 +0100
Subject: More fixes

---
 gerbonara/gerber/aperture_macros/expression.py |  2 +-
 gerbonara/gerber/gerber_statements.py          |  4 ++--
 gerbonara/gerber/graphic_objects.py            | 19 ++++++++++++++-----
 gerbonara/gerber/graphic_primitives.py         |  6 ++++++
 gerbonara/gerber/rs274x.py                     | 14 ++++++++------
 5 files changed, 31 insertions(+), 14 deletions(-)

diff --git a/gerbonara/gerber/aperture_macros/expression.py b/gerbonara/gerber/aperture_macros/expression.py
index 73a2a36..390b7b7 100644
--- a/gerbonara/gerber/aperture_macros/expression.py
+++ b/gerbonara/gerber/aperture_macros/expression.py
@@ -158,7 +158,7 @@ class OperatorExpression(Expression):
 
         op = {operator.add: '+',
               operator.sub: '-',
-              operator.mul: 'x',
+              operator.mul: 'X',
               operator.truediv: '/'} [self.op]
 
         return f'{lval}{op}{rval}'
diff --git a/gerbonara/gerber/gerber_statements.py b/gerbonara/gerber/gerber_statements.py
index 2bf909f..06aee7a 100644
--- a/gerbonara/gerber/gerber_statements.py
+++ b/gerbonara/gerber/gerber_statements.py
@@ -170,11 +170,11 @@ class SingleQuadrantModeStmt(InterpolationModeStmt):
     """ G75 single-quadrant arc interpolation mode statement """
     code = 'G75'
 
-class RegionStartStatement(InterpolationModeStmt):
+class RegionStartStmt(InterpolationModeStmt):
     """ G36 Region Mode Start Statement. """
     code = 'G36'
 
-class RegionEndStatement(InterpolationModeStmt):
+class RegionEndStmt(InterpolationModeStmt):
     """ G37 Region Mode End Statement. """
     code = 'G37'
 
diff --git a/gerbonara/gerber/graphic_objects.py b/gerbonara/gerber/graphic_objects.py
index 9902dee..8ee8f57 100644
--- a/gerbonara/gerber/graphic_objects.py
+++ b/gerbonara/gerber/graphic_objects.py
@@ -34,9 +34,17 @@ class Flash(GerberObject):
         yield FlashStmt(self.x, self.y)
 
 class Region(GerberObject):
-    def __init__(self, outline=[], arc_centers=None, *, polarity_dark):
-        super().__init__(self, polarity_dark=polarity_dark)
-        self.poly = gp.ArcPoly()
+    def __init__(self, outline=None, arc_centers=None, *, polarity_dark):
+        super().__init__(polarity_dark=polarity_dark)
+        outline = [] if outline is None else outline
+        arc_centers = [] if arc_centers is None else arc_centers
+        self.poly = gp.ArcPoly(outline, arc_centers)
+
+    def __len__(self):
+        return len(self.poly)
+
+    def __bool__(self):
+        return bool(self.poly)
 
     def with_offset(self, dx, dy):
         return Region([ (x+dx, y+dy) for x, y in outline ], radii, polarity_dark=self.polarity_dark)
@@ -46,7 +54,8 @@ class Region(GerberObject):
         self.poly.arc_centers = [ gp.rotate_point(x, y, angle, cx, cy) for x, y in self.poly.arc_centers ]
 
     def append(self, obj):
-        if not self.outline:
+        print('append', obj)
+        if not self.poly.outline:
             self.poly.outline.append(obj.p1)
         self.poly.outline.append(obj.p2)
 
@@ -64,7 +73,7 @@ class Region(GerberObject):
 
         yield from gs.set_current_point(self.poly.outline[0])
 
-        for point, arc_center in zip(self.poly.outline, self.poly.arc_centers):
+        for point, arc_center in zip(self.poly.outline[1:], self.poly.arc_centers):
             if arc_center is None:
                 yield from gs.set_interpolation_mode(LinearModeStmt)
                 yield InterpolateStmt(*point)
diff --git a/gerbonara/gerber/graphic_primitives.py b/gerbonara/gerber/graphic_primitives.py
index 4810066..c917365 100644
--- a/gerbonara/gerber/graphic_primitives.py
+++ b/gerbonara/gerber/graphic_primitives.py
@@ -82,6 +82,12 @@ class ArcPoly(GraphicPrimitive):
         for (x1, y1), (x2, y2), radius in self.segments:
             return 
 
+    def __len__(self):
+        return len(self.outline)
+
+    def __bool__(self):
+        return bool(len(self))
+
 
 @dataclass
 class Line(GraphicPrimitive):
diff --git a/gerbonara/gerber/rs274x.py b/gerbonara/gerber/rs274x.py
index 364cb43..8715497 100644
--- a/gerbonara/gerber/rs274x.py
+++ b/gerbonara/gerber/rs274x.py
@@ -297,12 +297,10 @@ class GraphicsState:
 
         if not relative:
             rx, ry = (a*x + b*y + self.image_offset[0]), (c*x + d*y + self.image_offset[1])
-            print(f'map {x},{y} to {rx},{ry}')
             return rx, ry
         else:
             # Apply mirroring, scale and rotation, but do not apply offset
             rx, ry = (a*x + b*y), (c*x + d*y)
-            print(f'map {x},{y} to {rx},{ry}')
             return rx, ry
 
     def flash(self, x, y):
@@ -344,7 +342,6 @@ class GraphicsState:
                 flipped=(direction == 'cw'), aperture=(self.aperture if aperture else None), polarity_dark=self.polarity_dark)
 
     def update_point(self, x, y):
-        print(f'update_point {x=} {y=}')
         old_point = self.point
         if x is None:
             x = self.point[0]
@@ -383,7 +380,7 @@ class GerberParser:
 
     STATEMENT_REGEXES = {
         'unit_mode': r"MO(?P<unit>(MM|IN))",
-        'interpolation_mode': r"(?P<code>G0?[123]|G74|G75)",
+        'interpolation_mode': r"(?P<code>G0?[123]|G74|G75)$",
         'coord': fr"(X(?P<x>{NUMBER}))?(Y(?P<y>{NUMBER}))?" \
             fr"(I(?P<i>{NUMBER}))?(J(?P<j>{NUMBER}))?" \
             fr"(?P<operation>D0?[123])$",
@@ -472,6 +469,7 @@ class GerberParser:
 
             for name, le_regex in self.STATEMENT_REGEXES.items():
                 if (match := le_regex.match(line)):
+                    print(f'match {name}')
                     getattr(self, f'_parse_{name}')(match.groupdict())
                     line = line[match.end(0):]
                     break
@@ -526,8 +524,10 @@ class GerberParser:
                     raise SyntaxError('Circular arc interpolation in multi-quadrant mode (G74) is not implemented.')
 
             if self.current_region is None:
+                print('D01 outside region') 
                 self.target.objects.append(self.graphics_state.interpolate(x, y, i, j))
             else:
+                print(f'D01 inside region {id(self.current_region)} of length {len(self.current_region)}') 
                 self.current_region.append(self.graphics_state.interpolate(x, y, i, j))
 
         else:
@@ -540,7 +540,7 @@ class GerberParser:
                     # Start a new region for every outline. As gerber has no concept of fill rules or winding numbers,
                     # it does not make a graphical difference, and it makes the implementation slightly easier.
                     self.target.objects.append(self.current_region)
-                    self.current_region = gp.Region(polarity_dark=gp.polarity_dark)
+                    self.current_region = go.Region(polarity_dark=self.graphics_state.polarity_dark)
 
             else: # D03
                 if self.current_region is None:
@@ -673,13 +673,15 @@ class GerberParser:
         self.target.comments.append(match["comment"])
 
     def _parse_region_start(self, _match):
-        self.current_region = gp.Region(polarity_dark=gp.polarity_dark)
+        self.current_region = go.Region(polarity_dark=self.graphics_state.polarity_dark)
+        print(f'Region start of {id(self.current_region)}')
 
     def _parse_region_end(self, _match):
         if self.current_region is None:
             raise SyntaxError('Region end command (G37) outside of region')
         
         if self.current_region: # ignore empty regions
+            print(f'Region end of {id(self.current_region)}')
             self.target.objects.append(self.current_region)
         self.current_region = None
 
-- 
cgit