From d3f22353463eda5ae6b7c402a94bb6ca112fb728 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 22 Jan 2022 21:06:33 +0100 Subject: Fix more gerber bugs --- gerbonara/gerber/rs274x.py | 21 +++++---- .../gerber/tests/resources/open_outline_altium.gbr | 55 ++++++++++++++++++++++ gerbonara/gerber/utils.py | 3 ++ 3 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 gerbonara/gerber/tests/resources/open_outline_altium.gbr (limited to 'gerbonara') diff --git a/gerbonara/gerber/rs274x.py b/gerbonara/gerber/rs274x.py index 6d373ba..2f41684 100644 --- a/gerbonara/gerber/rs274x.py +++ b/gerbonara/gerber/rs274x.py @@ -35,7 +35,7 @@ import textwrap import dataclasses from .cam import CamFile, FileSettings -from .utils import sq_distance, rotate_point, MM, Inch, units, InterpMode +from .utils import sq_distance, rotate_point, MM, Inch, units, InterpMode, UnknownStatementWarning from .aperture_macros.parse import ApertureMacro, GenericMacros from . import graphic_primitives as gp from . import graphic_objects as go @@ -171,6 +171,7 @@ class GerberFile(CamFile): return obj def generate_statements(self, settings, drop_comments=True): + yield 'G04 Gerber file generated by Gerbonara*' yield '%MOMM*%' if (settings.unit == 'mm') else '%MOIN*%' zeros = 'T' if settings.zeros == 'trailing' else 'L' # default to leading if "None" is specified @@ -182,9 +183,9 @@ class GerberFile(CamFile): yield '%LPD*%' if not drop_comments: - yield 'G04 File processed by Gerbonara. Original comments:' + yield 'G04 Comments from original gerber file:*' for cmt in self.comments: - yield f'G04{cmt}' + yield f'G04{cmt}*' # Always emit gerbonara's generic, rotation-capable aperture macro replacements for the standard C/R/O/P shapes. # Unconditionally emitting these here is easier than first trying to figure out if we need them later, @@ -453,7 +454,7 @@ class GerberParser: 'region_end': r'G37$', 'coord': fr"(?PG0?[123]|G74|G75)?(X(?P{NUMBER}))?(Y(?P{NUMBER}))?" \ fr"(I(?P{NUMBER}))?(J(?P{NUMBER}))?" \ - fr"(?PD0?[123])$", + fr"(?PD0?[123])?$", 'aperture': r"(G54|G55)?D(?P\d+)", 'comment': r"G0?4(?P[^*]*)", # Allegro combines format spec and unit into one long illegal extended command. @@ -549,7 +550,7 @@ class GerberParser: if (match := le_regex.match(line)): #print(f' match: {name} / {match}') try: - getattr(self, f'_parse_{name}')(match.groupdict()) + getattr(self, f'_parse_{name}')(match) except: print(f'Line {lineno}: {line}') print(f' match: {name} / {match}') @@ -558,7 +559,7 @@ class GerberParser: break else: - warnings.warn(f'Unknown statement found: "{line}", ignoring.', SyntaxWarning) + warnings.warn(f'Unknown statement found: "{line}", ignoring.', UnknownStatementWarning) self.target.comments.append(f'Unknown statement found: "{line}", ignoring.') self.target.apertures = list(self.aperture_map.values()) @@ -580,8 +581,12 @@ class GerberParser: elif match['interpolation'] == 'G75': self.multi_quadrant_mode = False - if match['interpolation'] in ('G74', 'G75') and match[0] != match['interpolation']: - raise SyntaxError('G74/G75 combined with coord') + if match['interpolation'] in ('G74', 'G75'): + if match[0] == match['interpolation']: + return # nothing else to do + + else: + raise SyntaxError('G74/G75 combined with coord') x = self.file_settings.parse_gerber_value(match['x']) y = self.file_settings.parse_gerber_value(match['y']) diff --git a/gerbonara/gerber/tests/resources/open_outline_altium.gbr b/gerbonara/gerber/tests/resources/open_outline_altium.gbr new file mode 100644 index 0000000..dc5a1d6 --- /dev/null +++ b/gerbonara/gerber/tests/resources/open_outline_altium.gbr @@ -0,0 +1,55 @@ +G04 From https://github.com/tracespace/tracespace/issues/365 +G04 Generated by Cuprum (2.1.4) at 2021-06-09T12:46:32+02:00* +%FSLAX66Y66*% +%MOMM*% +%TF.FileFunction,FabricationDrawing*% +%TF.SameCoordinates,1C0E9664-7553-46ED-9293-C2E7D2B0B53A*% +%TF.CreationDate,2021-06-09T12:46:32+02:00*% +%TF.GenerationSoftware,Wortum,Cuprum,2.1.4*% +%ADD10C,0.1*% +%ADD11C,0.254*% +G75* +D10* +X28008000Y22481000D02* +G03X26989000Y23500000I-1019000D01* +X24451000Y36745000D02* +X23451000Y37745000I-1000000D01* +X26989000Y0D02* +X28008000Y1019000J1019000D01* +X8000Y1034000D02* +X1042000Y0I1034000D01* +Y23500000D02* +X8000Y22466000J-1034000D01* +X17090000Y37745000D02* +X16090000Y36745000J-1000000D01* +X16078000Y36618000D02* +G01Y36830000D01* +X21133000Y0D02* +X27089000D01* +X20650000Y483000D02* +X21133000Y0D01* +X10719000Y483000D02* +X20650000D01* +X10236000Y0D02* +X10719000Y483000D01* +X1100000Y0D02* +X10236000D01* +X24451000Y23500000D02* +X26949000D01* +X28008000Y1019000D02* +Y22481000D01* +X1042000Y23500000D02* +X16078000D01* +X16951000Y37745000D02* +X23451000D01* +X24451000Y23500000D02* +Y36745000D01* +X8000Y1034000D02* +Y22466000D01* +X16078000Y23500000D02* +Y36618000D01* +D11* +X21519000Y18517000D02* +G03I-945000D01* +%TF.MD5,38bc3e94eca97f5a5e19c326598e4232*% +M02* diff --git a/gerbonara/gerber/utils.py b/gerbonara/gerber/utils.py index 0627a6b..100e968 100644 --- a/gerbonara/gerber/utils.py +++ b/gerbonara/gerber/utils.py @@ -28,6 +28,9 @@ import re from enum import Enum from math import radians, sin, cos, sqrt, atan2, pi +class UnknownStatementWarning(Warning): + pass + class RegexMatcher: def __init__(self): self.mapping = {} -- cgit