Refactor AM aperture handling and add unit conversion support

* Add support to convert between metric/impertial
* AM primitives are now properly created and can be
  converted between metric/imperial.
  (only Outline primitive is supported, no rendering yet)
This commit is contained in:
Paulo Henrique Silva 2015-01-14 03:15:52 -02:00
parent 53ee756609
commit cbb662491c
2 changed files with 129 additions and 9 deletions

View file

@ -259,13 +259,19 @@ class ADParamStmt(ParamStmt):
self.d = d
self.shape = shape
if modifiers is not None:
self.modifiers = [[x for x in m.split("X")] for m in modifiers.split(",") if len(m)]
self.modifiers = [[float(x) for x in m.split("X")] for m in modifiers.split(",") if len(m)]
else:
self.modifiers = []
def to_inch(self):
self.modifiers = [[x / 25.4 for x in modifier] for modifier in self.modifiers]
def to_metric(self):
self.modifiers = [[x * 25.4 for x in modifier] for modifier in self.modifiers]
def to_gerber(self, settings=None):
if len(self.modifiers):
return '%ADD{0}{1},{2}*%'.format(self.d, self.shape, ','.join(['X'.join(e) for e in self.modifiers]))
return '%ADD{0}{1},{2}*%'.format(self.d, self.shape, ','.join(['X'.join(["%.4f" % x for x in modifier]) for modifier in self.modifiers]))
else:
return '%ADD{0}{1}*%'.format(self.d, self.shape)
@ -282,6 +288,77 @@ class ADParamStmt(ParamStmt):
return '<Aperture Definition: %d: %s>' % (self.d, shape)
class AMPrimitive(object):
def __init__(self, code, exposure):
self.code = code
self.exposure = exposure
def to_inch(self):
pass
def to_metric(self):
pass
class AMOutlinePrimitive(AMPrimitive):
@classmethod
def from_gerber(cls, primitive):
modifiers = primitive.split(",")
code = int(modifiers[0])
exposure = "on" if modifiers[1] == "1" else "off"
n = int(modifiers[2])
start_point = (float(modifiers[3]), float(modifiers[4]))
points = []
for i in range(n):
points.append((float(modifiers[5 + i*2]), float(modifiers[5 + i*2 + 1])))
rotation = float(modifiers[-1])
return cls(code, exposure, start_point, points, rotation)
def __init__(self, code, exposure, start_point, points, rotation):
super(AMOutlinePrimitive, self).__init__(code, exposure)
self.start_point = start_point
self.points = points
self.rotation = rotation
def to_inch(self):
self.start_point = tuple([x / 25.4 for x in self.start_point])
self.points = tuple([(x / 25.4, y / 25.4) for x, y in self.points])
def to_metric(self):
self.start_point = tuple([x * 25.4 for x in self.start_point])
self.points = tuple([(x * 25.4, y * 25.4) for x, y in self.points])
def to_gerber(self, settings=None):
data = dict(
code=self.code,
exposure="1" if self.exposure == "on" else "0",
n_points=len(self.points),
start_point="%.4f,%.4f" % self.start_point,
points=",".join(["%.4f,%.4f" % point for point in self.points]),
rotation=str(self.rotation)
)
return "{code},{exposure},{n_points},{start_point},{points},{rotation}".format(**data)
class AMUnsupportPrimitive:
@classmethod
def from_gerber(cls, primitive):
return cls(primitive)
def __init__(self, primitive):
self.primitive = primitive
def to_gerber(self, settings=None):
return self.primitive
class AMParamStmt(ParamStmt):
""" AM - Aperture Macro Statement
"""
@ -312,10 +389,29 @@ class AMParamStmt(ParamStmt):
"""
ParamStmt.__init__(self, param)
self.name = name
self.macro = macro
self.primitives = self._parsePrimitives(macro)
def _parsePrimitives(self, macro):
primitives = []
for primitive in macro.split("*"):
if primitive[0] == "4":
primitives.append(AMOutlinePrimitive.from_gerber(primitive))
else:
primitives.append(AMUnsupportPrimitive.from_gerber(primitive))
return primitives
def to_inch(self):
for primitive in self.primitives:
primitive.to_inch()
def to_metric(self):
for primitive in self.primitives:
primitive.to_metric()
def to_gerber(self, settings=None):
return '%AM{0}*{1}*%'.format(self.name, self.macro)
return '%AM{0}*{1}*%'.format(self.name, "".join([primitive.to_gerber(settings) for primitive in self.primitives]))
def __str__(self):
return '<Aperture Macro %s: %s>' % (self.name, self.macro)
@ -726,6 +822,30 @@ class CoordStmt(Statement):
ret += self.op
return ret + '*'
def to_inch(self):
if self.x is not None:
self.x = self.x / 25.4
if self.y is not None:
self.y = self.y / 25.4
if self.i is not None:
self.i = self.i / 25.4
if self.j is not None:
self.j = self.j / 25.4
if self.function == "G71":
self.function = "G70"
def to_metric(self):
if self.x is not None:
self.x = self.x * 25.4
if self.y is not None:
self.y = self.y * 25.4
if self.i is not None:
self.i = self.i * 25.4
if self.j is not None:
self.j = self.j * 25.4
if self.function == "G70":
self.function = "G71"
def __str__(self):
coord_str = ''
if self.function:

View file

@ -361,15 +361,15 @@ class GerberParser(object):
def _define_aperture(self, d, shape, modifiers):
aperture = None
if shape == 'C':
diameter = float(modifiers[0][0])
diameter = modifiers[0][0]
aperture = Circle(position=None, diameter=diameter)
elif shape == 'R':
width = float(modifiers[0][0])
height = float(modifiers[0][1])
width = modifiers[0][0]
height = modifiers[0][1]
aperture = Rectangle(position=None, width=width, height=height)
elif shape == 'O':
width = float(modifiers[0][0])
height = float(modifiers[0][1])
width = modifiers[0][0]
height = modifiers[0][1]
aperture = Obround(position=None, width=width, height=height)
self.apertures[d] = aperture