Просмотр исходного кода

Fixes to gerber parser related to aperture macros and aperture definitions allowed characters in names.

Juan Pablo Caram 11 лет назад
Родитель
Сommit
20c381d510
2 измененных файлов с 316 добавлено и 291 удалено
  1. 315 290
      camlib.py
  2. 1 1
      recent.json

+ 315 - 290
camlib.py

@@ -6,6 +6,8 @@
 # MIT Licence                                              #
 # MIT Licence                                              #
 ############################################################
 ############################################################
 
 
+import traceback
+
 from numpy import arctan2, Inf, array, sqrt, pi, ceil, sin, cos
 from numpy import arctan2, Inf, array, sqrt, pi, ceil, sin, cos
 from matplotlib.figure import Figure
 from matplotlib.figure import Figure
 import re
 import re
@@ -31,7 +33,8 @@ import logging
 
 
 log = logging.getLogger('base2')
 log = logging.getLogger('base2')
 #log.setLevel(logging.DEBUG)
 #log.setLevel(logging.DEBUG)
-log.setLevel(logging.WARNING)
+#log.setLevel(logging.WARNING)
+log.setLevel(logging.INFO)
 formatter = logging.Formatter('[%(levelname)s] %(message)s')
 formatter = logging.Formatter('[%(levelname)s] %(message)s')
 handler = logging.StreamHandler()
 handler = logging.StreamHandler()
 handler.setFormatter(formatter)
 handler.setFormatter(formatter)
@@ -191,6 +194,16 @@ class Geometry(object):
 
 
 
 
 class ApertureMacro:
 class ApertureMacro:
+    """
+    Syntax of aperture macros.
+
+    <AM command>:           AM<Aperture macro name>*<Macro content>
+    <Macro content>:        {{<Variable definition>*}{<Primitive>*}}
+    <Variable definition>:  $K=<Arithmetic expression>
+    <Primitive>:            <Primitive code>,<Modifier>{,<Modifier>}|<Comment>
+    <Modifier>:             $M|< Arithmetic expression>
+    <Comment>:              0 <Text>
+    """
 
 
     ## Regular expressions
     ## Regular expressions
     am1_re = re.compile(r'^%AM([^\*]+)\*(.+)?(%)?$')
     am1_re = re.compile(r'^%AM([^\*]+)\*(.+)?(%)?$')
@@ -635,11 +648,11 @@ class Gerber (Geometry):
         self.comm_re = re.compile(r'^G0?4(.*)$')
         self.comm_re = re.compile(r'^G0?4(.*)$')
 
 
         # AD - Aperture definition
         # AD - Aperture definition
-        self.ad_re = re.compile(r'^%ADD(\d\d+)([a-zA-Z0-9]*)(?:,(.*))?\*%$')
+        self.ad_re = re.compile(r'^%ADD(\d\d+)([a-zA-Z_$\.][a-zA-Z0-9_$\.]*)(?:,(.*))?\*%$')
 
 
         # AM - Aperture Macro
         # AM - Aperture Macro
         # Beginning of macro (Ends with *%):
         # Beginning of macro (Ends with *%):
-        self.am_re = re.compile(r'^%AM([a-zA-Z0-9]*)\*')
+        #self.am_re = re.compile(r'^%AM([a-zA-Z0-9]*)\*')
 
 
         # Tool change
         # Tool change
         # May begin with G54 but that is deprecated
         # May begin with G54 but that is deprecated
@@ -694,7 +707,7 @@ class Gerber (Geometry):
         self.absrel_re = re.compile(r'^G9([01])\*$')
         self.absrel_re = re.compile(r'^G9([01])\*$')
 
 
         # Aperture macros
         # Aperture macros
-        self.am1_re = re.compile(r'^%AM([^\*]+)\*(.+)?(%)?$')
+        self.am1_re = re.compile(r'^%AM([^\*]+)\*([^%]+)?(%)?$')
         self.am2_re = re.compile(r'(.*)%$')
         self.am2_re = re.compile(r'(.*)%$')
 
 
         # TODO: This is bad.
         # TODO: This is bad.
@@ -915,344 +928,356 @@ class Gerber (Geometry):
 
 
         #### Parsing starts here ####
         #### Parsing starts here ####
         line_num = 0
         line_num = 0
-        for gline in glines:
-            line_num += 1
-
-            ### Cleanup
-            gline = gline.strip(' \r\n')
-
-            ### Aperture Macros
-            # Having this at the beggining will slow things down
-            # but macros can have complicated statements than could
-            # be caught by other ptterns.
-            if current_macro is None:  # No macro started yet
-                match = self.am1_re.search(gline)
-                # Start macro if match, else not an AM, carry on.
-                if match:
-                    current_macro = match.group(1)
-                    self.aperture_macros[current_macro] = ApertureMacro(name=current_macro)
-                    if match.group(2):  # Append
-                        self.aperture_macros[current_macro].append(match.group(2))
-                    if match.group(3):  # Finish macro
+        gline = ""
+        try:
+            for gline in glines:
+                line_num += 1
+
+                ### Cleanup
+                gline = gline.strip(' \r\n')
+
+                ### Aperture Macros
+                # Having this at the beggining will slow things down
+                # but macros can have complicated statements than could
+                # be caught by other ptterns.
+                if current_macro is None:  # No macro started yet
+                    match = self.am1_re.search(gline)
+                    # Start macro if match, else not an AM, carry on.
+                    if match:
+                        log.info("Starting macro. Line %d: %s" % (line_num, gline))
+                        current_macro = match.group(1)
+                        self.aperture_macros[current_macro] = ApertureMacro(name=current_macro)
+                        if match.group(2):  # Append
+                            self.aperture_macros[current_macro].append(match.group(2))
+                        if match.group(3):  # Finish macro
+                            #self.aperture_macros[current_macro].parse_content()
+                            current_macro = None
+                            log.info("Macro complete in 1 line.")
+                        continue
+                else:  # Continue macro
+                    log.info("Continuing macro. Line %d." % line_num)
+                    match = self.am2_re.search(gline)
+                    if match:  # Finish macro
+                        log.info("End of macro. Line %d." % line_num)
+                        self.aperture_macros[current_macro].append(match.group(1))
                         #self.aperture_macros[current_macro].parse_content()
                         #self.aperture_macros[current_macro].parse_content()
                         current_macro = None
                         current_macro = None
+                    else:  # Append
+                        self.aperture_macros[current_macro].append(gline)
                     continue
                     continue
-            else:  # Continue macro
-                match = self.am2_re.search(gline)
-                if match:  # Finish macro
-                    self.aperture_macros[current_macro].append(match.group(1))
-                    #self.aperture_macros[current_macro].parse_content()
-                    current_macro = None
-                else:  # Append
-                    self.aperture_macros[current_macro].append(gline)
-                continue
 
 
-            ### G01 - Linear interpolation plus flashes
-            # Operation code (D0x) missing is deprecated... oh well I will support it.
-            # REGEX: r'^(?:G0?(1))?(?:X(-?\d+))?(?:Y(-?\d+))?(?:D0([123]))?\*$'
-            match = self.lin_re.search(gline)
-            if match:
-                # Dxx alone?
-                # if match.group(1) is None and match.group(2) is None and match.group(3) is None:
-                #     try:
-                #         current_operation_code = int(match.group(4))
-                #     except:
-                #         pass  # A line with just * will match too.
-                #     continue
-                # NOTE: Letting it continue allows it to react to the
-                #       operation code.
-
-                # Parse coordinates
-                if match.group(2) is not None:
-                    current_x = parse_gerber_number(match.group(2), self.frac_digits)
-                if match.group(3) is not None:
-                    current_y = parse_gerber_number(match.group(3), self.frac_digits)
-
-                # Parse operation code
-                if match.group(4) is not None:
-                    current_operation_code = int(match.group(4))
-
-                # Pen down: add segment
-                if current_operation_code == 1:
-                    path.append([current_x, current_y])
-                    last_path_aperture = current_aperture
-
-                elif current_operation_code == 2:
-                    if len(path) > 1:
+                ### G01 - Linear interpolation plus flashes
+                # Operation code (D0x) missing is deprecated... oh well I will support it.
+                # REGEX: r'^(?:G0?(1))?(?:X(-?\d+))?(?:Y(-?\d+))?(?:D0([123]))?\*$'
+                match = self.lin_re.search(gline)
+                if match:
+                    # Dxx alone?
+                    # if match.group(1) is None and match.group(2) is None and match.group(3) is None:
+                    #     try:
+                    #         current_operation_code = int(match.group(4))
+                    #     except:
+                    #         pass  # A line with just * will match too.
+                    #     continue
+                    # NOTE: Letting it continue allows it to react to the
+                    #       operation code.
+
+                    # Parse coordinates
+                    if match.group(2) is not None:
+                        current_x = parse_gerber_number(match.group(2), self.frac_digits)
+                    if match.group(3) is not None:
+                        current_y = parse_gerber_number(match.group(3), self.frac_digits)
+
+                    # Parse operation code
+                    if match.group(4) is not None:
+                        current_operation_code = int(match.group(4))
+
+                    # Pen down: add segment
+                    if current_operation_code == 1:
+                        path.append([current_x, current_y])
+                        last_path_aperture = current_aperture
+
+                    elif current_operation_code == 2:
+                        if len(path) > 1:
+
+                            ## --- BUFFERED ---
+                            if making_region:
+                                geo = Polygon(path)
+                            else:
+                                if last_path_aperture is None:
+                                    log.warning("No aperture defined for curent path. (%d)" % line_num)
+                                width = self.apertures[last_path_aperture]["size"]
+                                geo = LineString(path).buffer(width/2)
+                            poly_buffer.append(geo)
+
+                        path = [[current_x, current_y]]  # Start new path
+
+                    # Flash
+                    elif current_operation_code == 3:
 
 
-                        ## --- BUFFERED ---
-                        if making_region:
-                            geo = Polygon(path)
-                        else:
-                            if last_path_aperture is None:
-                                log.warning("No aperture defined for curent path. (%d)" % line_num)
-                            width = self.apertures[last_path_aperture]["size"]
-                            geo = LineString(path).buffer(width/2)
-                        poly_buffer.append(geo)
+                        # --- BUFFERED ---
+                        flash = Gerber.create_flash_geometry(Point([current_x, current_y]),
+                                                             self.apertures[current_aperture])
+                        poly_buffer.append(flash)
 
 
-                    path = [[current_x, current_y]]  # Start new path
+                    continue
 
 
-                # Flash
-                elif current_operation_code == 3:
+                ### G02/3 - Circular interpolation
+                # 2-clockwise, 3-counterclockwise
+                match = self.circ_re.search(gline)
+                if match:
 
 
-                    # --- BUFFERED ---
-                    flash = Gerber.create_flash_geometry(Point([current_x, current_y]),
-                                                         self.apertures[current_aperture])
-                    poly_buffer.append(flash)
+                    mode, x, y, i, j, d = match.groups()
+                    try:
+                        x = parse_gerber_number(x, self.frac_digits)
+                    except:
+                        x = current_x
+                    try:
+                        y = parse_gerber_number(y, self.frac_digits)
+                    except:
+                        y = current_y
+                    try:
+                        i = parse_gerber_number(i, self.frac_digits)
+                    except:
+                        i = 0
+                    try:
+                        j = parse_gerber_number(j, self.frac_digits)
+                    except:
+                        j = 0
 
 
-                continue
+                    if quadrant_mode is None:
+                        log.error("Found arc without preceding quadrant specification G74 or G75. (%d)" % line_num)
+                        log.error(gline)
+                        continue
 
 
-            ### G02/3 - Circular interpolation
-            # 2-clockwise, 3-counterclockwise
-            match = self.circ_re.search(gline)
-            if match:
+                    if mode is None and current_interpolation_mode not in [2, 3]:
+                        log.error("Found arc without circular interpolation mode defined. (%d)" % line_num)
+                        log.error(gline)
+                        continue
+                    elif mode is not None:
+                        current_interpolation_mode = int(mode)
 
 
-                mode, x, y, i, j, d = match.groups()
-                try:
-                    x = parse_gerber_number(x, self.frac_digits)
-                except:
-                    x = current_x
-                try:
-                    y = parse_gerber_number(y, self.frac_digits)
-                except:
-                    y = current_y
-                try:
-                    i = parse_gerber_number(i, self.frac_digits)
-                except:
-                    i = 0
-                try:
-                    j = parse_gerber_number(j, self.frac_digits)
-                except:
-                    j = 0
-
-                if quadrant_mode is None:
-                    log.error("Found arc without preceding quadrant specification G74 or G75. (%d)" % line_num)
-                    log.error(gline)
-                    continue
+                    # Set operation code if provided
+                    if d is not None:
+                        current_operation_code = int(d)
 
 
-                if mode is None and current_interpolation_mode not in [2, 3]:
-                    log.error("Found arc without circular interpolation mode defined. (%d)" % line_num)
-                    log.error(gline)
-                    continue
-                elif mode is not None:
-                    current_interpolation_mode = int(mode)
+                    # Nothing created! Pen Up.
+                    if current_operation_code == 2:
+                        log.warning("Arc with D2. (%d)" % line_num)
+                        if len(path) > 1:
+                            if last_path_aperture is None:
+                                log.warning("No aperture defined for curent path. (%d)" % line_num)
 
 
-                # Set operation code if provided
-                if d is not None:
-                    current_operation_code = int(d)
+                            # --- BUFFERED ---
+                            width = self.apertures[last_path_aperture]["size"]
+                            buffered = LineString(path).buffer(width/2)
+                            poly_buffer.append(buffered)
 
 
-                # Nothing created! Pen Up.
-                if current_operation_code == 2:
-                    log.warning("Arc with D2. (%d)" % line_num)
-                    if len(path) > 1:
-                        if last_path_aperture is None:
-                            log.warning("No aperture defined for curent path. (%d)" % line_num)
+                        current_x = x
+                        current_y = y
+                        path = [[current_x, current_y]]  # Start new path
+                        continue
 
 
-                        # --- BUFFERED ---
-                        width = self.apertures[last_path_aperture]["size"]
-                        buffered = LineString(path).buffer(width/2)
-                        poly_buffer.append(buffered)
+                    # Flash should not happen here
+                    if current_operation_code == 3:
+                        log.error("Trying to flash within arc. (%d)" % line_num)
+                        continue
 
 
-                    current_x = x
-                    current_y = y
-                    path = [[current_x, current_y]]  # Start new path
-                    continue
+                    if quadrant_mode == 'MULTI':
+                        center = [i + current_x, j + current_y]
+                        radius = sqrt(i**2 + j**2)
+                        start = arctan2(-j, -i)
+                        stop = arctan2(-center[1] + y, -center[0] + x)
+                        arcdir = [None, None, "cw", "ccw"]
+                        this_arc = arc(center, radius, start, stop,
+                                       arcdir[current_interpolation_mode],
+                                       self.steps_per_circ)
 
 
-                # Flash should not happen here
-                if current_operation_code == 3:
-                    log.error("Trying to flash within arc. (%d)" % line_num)
-                    continue
+                        # Last point in path is current point
+                        current_x = this_arc[-1][0]
+                        current_y = this_arc[-1][1]
 
 
-                if quadrant_mode == 'MULTI':
-                    center = [i + current_x, j + current_y]
-                    radius = sqrt(i**2 + j**2)
-                    start = arctan2(-j, -i)
-                    stop = arctan2(-center[1] + y, -center[0] + x)
-                    arcdir = [None, None, "cw", "ccw"]
-                    this_arc = arc(center, radius, start, stop,
-                                   arcdir[current_interpolation_mode],
-                                   self.steps_per_circ)
+                        # Append
+                        path += this_arc
 
 
-                    # Last point in path is current point
-                    current_x = this_arc[-1][0]
-                    current_y = this_arc[-1][1]
+                        last_path_aperture = current_aperture
 
 
-                    # Append
-                    path += this_arc
+                        continue
 
 
-                    last_path_aperture = current_aperture
+                    if quadrant_mode == 'SINGLE':
+                        log.warning("Single quadrant arc are not implemented yet. (%d)" % line_num)
 
 
-                    continue
+                ### Operation code alone
+                match = self.opcode_re.search(gline)
+                if match:
+                    current_operation_code = int(match.group(1))
+                    if current_operation_code == 3:
 
 
-                if quadrant_mode == 'SINGLE':
-                    log.warning("Single quadrant arc are not implemented yet. (%d)" % line_num)
+                        ## --- Buffered ---
+                        flash = Gerber.create_flash_geometry(Point(path[-1]),
+                                                             self.apertures[current_aperture])
+                        poly_buffer.append(flash)
 
 
-            ### Operation code alone
-            match = self.opcode_re.search(gline)
-            if match:
-                current_operation_code = int(match.group(1))
-                if current_operation_code == 3:
+                    continue
 
 
-                    ## --- Buffered ---
-                    flash = Gerber.create_flash_geometry(Point(path[-1]),
-                                                         self.apertures[current_aperture])
-                    poly_buffer.append(flash)
+                ### G74/75* - Single or multiple quadrant arcs
+                match = self.quad_re.search(gline)
+                if match:
+                    if match.group(1) == '4':
+                        quadrant_mode = 'SINGLE'
+                    else:
+                        quadrant_mode = 'MULTI'
+                    continue
 
 
-                continue
+                ### G36* - Begin region
+                if self.regionon_re.search(gline):
+                    if len(path) > 1:
+                        # Take care of what is left in the path
 
 
-            ### G74/75* - Single or multiple quadrant arcs
-            match = self.quad_re.search(gline)
-            if match:
-                if match.group(1) == '4':
-                    quadrant_mode = 'SINGLE'
-                else:
-                    quadrant_mode = 'MULTI'
-                continue
+                        ## --- Buffered ---
+                        width = self.apertures[last_path_aperture]["size"]
+                        geo = LineString(path).buffer(width/2)
+                        poly_buffer.append(geo)
 
 
-            ### G36* - Begin region
-            if self.regionon_re.search(gline):
-                if len(path) > 1:
-                    # Take care of what is left in the path
+                        path = [path[-1]]
+
+                    making_region = True
+                    continue
 
 
-                    ## --- Buffered ---
-                    width = self.apertures[last_path_aperture]["size"]
-                    geo = LineString(path).buffer(width/2)
-                    poly_buffer.append(geo)
+                ### G37* - End region
+                if self.regionoff_re.search(gline):
+                    making_region = False
+
+                    # Only one path defines region?
+                    # This can happen if D02 happened before G37 and
+                    # is not and error.
+                    if len(path) < 3:
+                        # print "ERROR: Path contains less than 3 points:"
+                        # print path
+                        # print "Line (%d): " % line_num, gline
+                        # path = []
+                        #path = [[current_x, current_y]]
+                        continue
 
 
-                    path = [path[-1]]
+                    # For regions we may ignore an aperture that is None
+                    # self.regions.append({"polygon": Polygon(path),
+                    #                      "aperture": last_path_aperture})
 
 
-                making_region = True
-                continue
+                    # --- Buffered ---
+                    region = Polygon(path)
+                    if not region.is_valid:
+                        region = region.buffer(0)
+                    poly_buffer.append(region)
 
 
-            ### G37* - End region
-            if self.regionoff_re.search(gline):
-                making_region = False
-
-                # Only one path defines region?
-                # This can happen if D02 happened before G37 and
-                # is not and error.
-                if len(path) < 3:
-                    # print "ERROR: Path contains less than 3 points:"
-                    # print path
-                    # print "Line (%d): " % line_num, gline
-                    # path = []
-                    #path = [[current_x, current_y]]
+                    path = [[current_x, current_y]]  # Start new path
                     continue
                     continue
 
 
-                # For regions we may ignore an aperture that is None
-                # self.regions.append({"polygon": Polygon(path),
-                #                      "aperture": last_path_aperture})
+                ### Aperture definitions %ADD...
+                match = self.ad_re.search(gline)
+                if match:
+                    log.info("Found aperture definition. Line %d: %s" % (line_num, gline))
+                    self.aperture_parse(match.group(1), match.group(2), match.group(3))
+                    continue
 
 
-                # --- Buffered ---
-                region = Polygon(path)
-                if not region.is_valid:
-                    region = region.buffer(0)
-                poly_buffer.append(region)
+                ### G01/2/3* - Interpolation mode change
+                # Can occur along with coordinates and operation code but
+                # sometimes by itself (handled here).
+                # Example: G01*
+                match = self.interp_re.search(gline)
+                if match:
+                    current_interpolation_mode = int(match.group(1))
+                    continue
 
 
-                path = [[current_x, current_y]]  # Start new path
-                continue
-            
-            ### Aperture definitions %ADD...
-            match = self.ad_re.search(gline)
-            if match:
-                self.aperture_parse(match.group(1), match.group(2), match.group(3))
-                continue
+                ### Tool/aperture change
+                # Example: D12*
+                match = self.tool_re.search(gline)
+                if match:
+                    current_aperture = match.group(1)
+                    continue
 
 
-            ### G01/2/3* - Interpolation mode change
-            # Can occur along with coordinates and operation code but
-            # sometimes by itself (handled here).
-            # Example: G01*
-            match = self.interp_re.search(gline)
-            if match:
-                current_interpolation_mode = int(match.group(1))
-                continue
+                ### Polarity change
+                # Example: %LPD*% or %LPC*%
+                match = self.lpol_re.search(gline)
+                if match:
+                    if len(path) > 1 and current_polarity != match.group(1):
 
 
-            ### Tool/aperture change
-            # Example: D12*
-            match = self.tool_re.search(gline)
-            if match:
-                current_aperture = match.group(1)
-                continue
+                        # --- Buffered ----
+                        width = self.apertures[last_path_aperture]["size"]
+                        geo = LineString(path).buffer(width/2)
+                        poly_buffer.append(geo)
 
 
-            ### Polarity change
-            # Example: %LPD*% or %LPC*%
-            match = self.lpol_re.search(gline)
-            if match:
-                if len(path) > 1 and current_polarity != match.group(1):
+                        path = [path[-1]]
 
 
-                    # --- Buffered ----
-                    width = self.apertures[last_path_aperture]["size"]
-                    geo = LineString(path).buffer(width/2)
-                    poly_buffer.append(geo)
+                    # --- Apply buffer ---
+                    if current_polarity == 'D':
+                        self.solid_geometry = self.solid_geometry.union(cascaded_union(poly_buffer))
+                    else:
+                        self.solid_geometry = self.solid_geometry.difference(cascaded_union(poly_buffer))
+                    poly_buffer = []
 
 
-                    path = [path[-1]]
+                    current_polarity = match.group(1)
+                    continue
 
 
-                # --- Apply buffer ---
-                if current_polarity == 'D':
-                    self.solid_geometry = self.solid_geometry.union(cascaded_union(poly_buffer))
-                else:
-                    self.solid_geometry = self.solid_geometry.difference(cascaded_union(poly_buffer))
-                poly_buffer = []
+                ### Number format
+                # Example: %FSLAX24Y24*%
+                # TODO: This is ignoring most of the format. Implement the rest.
+                match = self.fmt_re.search(gline)
+                if match:
+                    absolute = {'A': True, 'I': False}
+                    self.int_digits = int(match.group(3))
+                    self.frac_digits = int(match.group(4))
+                    continue
 
 
-                current_polarity = match.group(1)
-                continue
+                ### Mode (IN/MM)
+                # Example: %MOIN*%
+                match = self.mode_re.search(gline)
+                if match:
+                    self.units = match.group(1)
+                    continue
 
 
-            ### Number format
-            # Example: %FSLAX24Y24*%
-            # TODO: This is ignoring most of the format. Implement the rest.
-            match = self.fmt_re.search(gline)
-            if match:
-                absolute = {'A': True, 'I': False}
-                self.int_digits = int(match.group(3))
-                self.frac_digits = int(match.group(4))
-                continue
+                ### Units (G70/1) OBSOLETE
+                match = self.units_re.search(gline)
+                if match:
+                    self.units = {'0': 'IN', '1': 'MM'}[match.group(1)]
+                    continue
 
 
-            ### Mode (IN/MM)
-            # Example: %MOIN*%
-            match = self.mode_re.search(gline)
-            if match:
-                self.units = match.group(1)
-                continue
+                ### Absolute/relative coordinates G90/1 OBSOLETE
+                match = self.absrel_re.search(gline)
+                if match:
+                    absolute = {'0': True, '1': False}[match.group(1)]
+                    continue
 
 
-            ### Units (G70/1) OBSOLETE
-            match = self.units_re.search(gline)
-            if match:
-                self.units = {'0': 'IN', '1': 'MM'}[match.group(1)]
-                continue
+                #### Ignored lines
+                ## Comments
+                match = self.comm_re.search(gline)
+                if match:
+                    continue
 
 
-            ### Absolute/relative coordinates G90/1 OBSOLETE
-            match = self.absrel_re.search(gline)
-            if match:
-                absolute = {'0': True, '1': False}[match.group(1)]
-                continue
+                ## EOF
+                match = self.eof_re.search(gline)
+                if match:
+                    continue
 
 
-            #### Ignored lines
-            ## Comments
-            match = self.comm_re.search(gline)
-            if match:
-                continue
+                ### Line did not match any pattern. Warn user.
+                log.warning("Line ignored (%d): %s" % (line_num, gline))
 
 
-            ## EOF
-            match = self.eof_re.search(gline)
-            if match:
-                continue
+            if len(path) > 1:
+                # EOF, create shapely LineString if something still in path
 
 
-            ### Line did not match any pattern. Warn user.
-            log.warning("Line ignored (%d): %s" % (line_num, gline))
-        
-        if len(path) > 1:
-            # EOF, create shapely LineString if something still in path
+                ## --- Buffered ---
+                width = self.apertures[last_path_aperture]["size"]
+                geo = LineString(path).buffer(width/2)
+                poly_buffer.append(geo)
 
 
-            ## --- Buffered ---
-            width = self.apertures[last_path_aperture]["size"]
-            geo = LineString(path).buffer(width/2)
-            poly_buffer.append(geo)
+            # --- Apply buffer ---
+            if current_polarity == 'D':
+                self.solid_geometry = self.solid_geometry.union(cascaded_union(poly_buffer))
+            else:
+                self.solid_geometry = self.solid_geometry.difference(cascaded_union(poly_buffer))
 
 
-        # --- Apply buffer ---
-        if current_polarity == 'D':
-            self.solid_geometry = self.solid_geometry.union(cascaded_union(poly_buffer))
-        else:
-            self.solid_geometry = self.solid_geometry.difference(cascaded_union(poly_buffer))
+        except Exception, err:
+            #print traceback.format_exc()
+            log.error("PARSING FAILED. Line %d: %s" % (line_num, gline))
+            raise
 
 
     @staticmethod
     @staticmethod
     def create_flash_geometry(location, aperture):
     def create_flash_geometry(location, aperture):

+ 1 - 1
recent.json

@@ -1 +1 @@
-[{"kind": "excellon", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/FlatCam_Drilling_Test/FlatCam_Drilling_Test.drl"}, {"kind": "excellon", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/Excellon_Planck/X-Y CONTROLLER - Drill Data - Through Hole.drl"}, {"kind": "gerber", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/7V-PSU/7V PSU.GTL"}, {"kind": "cncjob", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/output.gcode"}, {"kind": "project", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/project_copy.fcproj"}, {"kind": "project", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/a_project.fcproj"}, {"kind": "project", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/cirkuix/tests/FlatCAM_TestProject.fcproj"}, {"kind": "cncjob", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/cirkuix/tests/FlatCAM_TestGCode.gcode"}, {"kind": "cncjob", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/cirkuix/tests/CBS-B_Cu_ISOLATION_GCODE.ngc"}, {"kind": "excellon", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/cirkuix/tests/FlatCAM_TestDrill.drl"}]
+[{"kind": "gerber", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/WindMills - Bottom Copper 2.gbr"}, {"kind": "gerber", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/Example1_copper_bottom.gbr"}, {"kind": "gerber", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/7V-PSU.zip"}, {"kind": "gerber", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/Gerbers/AVR_Transistor_Tester_copper_top.GTL"}, {"kind": "gerber", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/XGerber/do-kotle.Bot"}, {"kind": "excellon", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/FlatCam_Drilling_Test/FlatCam_Drilling_Test.drl"}, {"kind": "excellon", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/Excellon_Planck/X-Y CONTROLLER - Drill Data - Through Hole.drl"}, {"kind": "gerber", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/7V-PSU/7V PSU.GTL"}, {"kind": "cncjob", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/output.gcode"}, {"kind": "project", "filename": "C:/Users/jpcaram/Dropbox/CNC/pcbcam/test_files/project_copy.fcproj"}]