diff options
Diffstat (limited to 'gerber/cam.py')
-rw-r--r-- | gerber/cam.py | 121 |
1 files changed, 111 insertions, 10 deletions
diff --git a/gerber/cam.py b/gerber/cam.py index 051c3b5..c5b8938 100644 --- a/gerber/cam.py +++ b/gerber/cam.py @@ -27,9 +27,36 @@ class FileSettings(object): """ CAM File Settings Provides a common representation of gerber/excellon file settings + + Parameters + ---------- + notation: string + notation format. either 'absolute' or 'incremental' + + units : string + Measurement units. 'inch' or 'metric' + + zero_suppression: string + 'leading' to suppress leading zeros, 'trailing' to suppress trailing zeros. + This is the convention used in Gerber files. + + format : tuple (int, int) + Decimal format + + zeros : string + 'leading' to include leading zeros, 'trailing to include trailing zeros. + This is the convention used in Excellon files + + Notes + ----- + Either `zeros` or `zero_suppression` should be specified, there is no need to + specify both. `zero_suppression` will take on the opposite value of `zeros` + and vice versa """ + def __init__(self, notation='absolute', units='inch', - zero_suppression='trailing', format=(2, 5)): + zero_suppression=None, format=(2, 5), zeros=None, + angle_units='degrees'): if notation not in ['absolute', 'incremental']: raise ValueError('Notation must be either absolute or incremental') self.notation = notation @@ -38,15 +65,52 @@ class FileSettings(object): raise ValueError('Units must be either inch or metric') self.units = units - if zero_suppression not in ['leading', 'trailing']: - raise ValueError('Zero suppression must be either leading or \ - trailling') - self.zero_suppression = zero_suppression + if zero_suppression is None and zeros is None: + self.zero_suppression = 'trailing' + + elif zero_suppression == zeros: + raise ValueError('Zeros and Zero Suppression must be different. \ + Best practice is to specify only one.') + + elif zero_suppression is not None: + if zero_suppression not in ['leading', 'trailing']: + # This is a common problem in Eagle files, so just suppress it + self.zero_suppression = 'leading' + else: + self.zero_suppression = zero_suppression + + elif zeros is not None: + if zeros not in ['leading', 'trailing']: + raise ValueError('Zeros must be either leading or trailling') + self.zeros = zeros if len(format) != 2: raise ValueError('Format must be a tuple(n=2) of integers') self.format = format + if angle_units not in ('degrees', 'radians'): + raise ValueError('Angle units may be degrees or radians') + self.angle_units = angle_units + + @property + def zero_suppression(self): + return self._zero_suppression + + @zero_suppression.setter + def zero_suppression(self, value): + self._zero_suppression = value + self._zeros = 'leading' if value == 'trailing' else 'trailing' + + @property + def zeros(self): + return self._zeros + + @zeros.setter + def zeros(self, value): + + self._zeros = value + self._zero_suppression = 'leading' if value == 'trailing' else 'trailing' + def __getitem__(self, key): if key == 'notation': return self.notation @@ -54,8 +118,12 @@ class FileSettings(object): return self.units elif key == 'zero_suppression': return self.zero_suppression + elif key == 'zeros': + return self.zeros elif key == 'format': return self.format + elif key == 'angle_units': + return self.angle_units else: raise KeyError() @@ -69,22 +137,41 @@ class FileSettings(object): if value not in ['inch', 'metric']: raise ValueError('Units must be either inch or metric') self.units = value + elif key == 'zero_suppression': if value not in ['leading', 'trailing']: raise ValueError('Zero suppression must be either leading or \ trailling') self.zero_suppression = value + + elif key == 'zeros': + if value not in ['leading', 'trailing']: + raise ValueError('Zeros must be either leading or trailling') + self.zeros = value + elif key == 'format': if len(value) != 2: raise ValueError('Format must be a tuple(n=2) of integers') self.format = value + elif key == 'angle_units': + if value not in ('degrees', 'radians'): + raise ValueError('Angle units may be degrees or radians') + self.angle_units = value + + else: + raise KeyError('%s is not a valid key' % key) + def __eq__(self, other): return (self.notation == other.notation and self.units == other.units and self.zero_suppression == other.zero_suppression and - self.format == other.format) - + self.format == other.format and + self.angle_units == other.angle_units) + + def __str__(self): + return ('<Settings: %s %s %s %s %s>' % + (self.units, self.notation, self.zero_suppression, self.format, self.angle_units)) class CamFile(object): @@ -131,14 +218,17 @@ class CamFile(object): self.notation = settings['notation'] self.units = settings['units'] self.zero_suppression = settings['zero_suppression'] + self.zeros = settings['zeros'] self.format = settings['format'] else: self.notation = 'absolute' self.units = 'inch' self.zero_suppression = 'trailing' + self.zeros = 'leading' self.format = (2, 5) self.statements = statements if statements is not None else [] - self.primitives = primitives + if primitives is not None: + self.primitives = primitives self.filename = filename self.layer_name = layer_name @@ -156,11 +246,17 @@ class CamFile(object): @property def bounds(self): - """ File baundaries + """ File boundaries """ pass - def render(self, ctx, filename=None): + def to_inch(self): + pass + + def to_metric(self): + pass + + def render(self, ctx, invert=False, filename=None): """ Generate image of layer. Parameters @@ -172,7 +268,12 @@ class CamFile(object): If provided, save the rendered image to `filename` """ ctx.set_bounds(self.bounds) + ctx._paint_background() + ctx.invert = invert + ctx._new_render_layer() for p in self.primitives: ctx.render(p) + ctx._flatten() + if filename is not None: ctx.dump(filename) |