More rendering of AMGroup to statements
This commit is contained in:
parent
223a010831
commit
20a9af279a
5 changed files with 133 additions and 7 deletions
|
|
@ -179,6 +179,10 @@ class AMCirclePrimitive(AMPrimitive):
|
|||
diameter = float(modifiers[2])
|
||||
position = (float(modifiers[3]), float(modifiers[4]))
|
||||
return cls(code, exposure, diameter, position)
|
||||
|
||||
@classmethod
|
||||
def from_primitive(cls, primitive):
|
||||
return cls(1, 'on', primitive.diameter, primitive.position)
|
||||
|
||||
def __init__(self, code, exposure, diameter, position):
|
||||
validate_coordinates(position)
|
||||
|
|
@ -247,6 +251,11 @@ class AMVectorLinePrimitive(AMPrimitive):
|
|||
------
|
||||
ValueError, TypeError
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def from_primitive(cls, primitive):
|
||||
return cls(2, 'on', primitive.aperture.width, primitive.start, primitive.end, 0)
|
||||
|
||||
@classmethod
|
||||
def from_gerber(cls, primitive):
|
||||
modifiers = primitive.strip(' *').split(',')
|
||||
|
|
@ -406,6 +415,9 @@ class AMOutlinePrimitive(AMPrimitive):
|
|||
lines.append(Line(prev_point, cur_point, Circle((0,0), 0)))
|
||||
|
||||
prev_point = cur_point
|
||||
|
||||
if lines[0].start != lines[-1].end:
|
||||
raise ValueError('Outline must be closed')
|
||||
|
||||
return Outline(lines, units=units)
|
||||
|
||||
|
|
@ -762,6 +774,8 @@ class AMThermalPrimitive(AMPrimitive):
|
|||
|
||||
points = (self._approximate_arc_cw(inner_start_angle, inner_end_angle, inner_radius, self.position)
|
||||
+ list(reversed(self._approximate_arc_cw(outer_start_angle, outer_end_angle, outer_radius, self.position))))
|
||||
# Add in the last point since outlines should be closed
|
||||
points.append(points[0])
|
||||
|
||||
# There are four outlines at rotated sections
|
||||
for rotation in [0, 90.0, 180.0, 270.0]:
|
||||
|
|
@ -818,6 +832,14 @@ class AMCenterLinePrimitive(AMPrimitive):
|
|||
------
|
||||
ValueError, TypeError
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def from_primitive(cls, primitive):
|
||||
width = primitive.width
|
||||
height = primitive.height
|
||||
center = primitive.position
|
||||
rotation = math.degrees(primitive.rotation)
|
||||
return cls(21, 'on', width, height, center, rotation)
|
||||
|
||||
@classmethod
|
||||
def from_gerber(cls, primitive):
|
||||
|
|
|
|||
|
|
@ -166,6 +166,10 @@ class FileSettings(object):
|
|||
self.zero_suppression == other.zero_suppression and
|
||||
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):
|
||||
|
|
|
|||
|
|
@ -93,6 +93,11 @@ class ParamStmt(Statement):
|
|||
class FSParamStmt(ParamStmt):
|
||||
""" FS - Gerber Format Specification Statement
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def from_settings(cls, settings):
|
||||
|
||||
return cls('FS', settings.zero_suppression, settings.notation, settings.format)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, stmt_dict):
|
||||
|
|
@ -278,6 +283,11 @@ class ADParamStmt(ParamStmt):
|
|||
'''Create a circular aperture definition statement'''
|
||||
return cls('AD', dcode, 'C', ([diameter],))
|
||||
|
||||
@classmethod
|
||||
def obround(cls, dcode, width, height):
|
||||
'''Create an obrou d aperture definition statement'''
|
||||
return cls('AD', dcode, 'O', ([width, height],))
|
||||
|
||||
@classmethod
|
||||
def macro(cls, dcode, name):
|
||||
return cls('AD', dcode, name, '')
|
||||
|
|
|
|||
|
|
@ -397,6 +397,19 @@ class Circle(Primitive):
|
|||
|
||||
def offset(self, x_offset=0, y_offset=0):
|
||||
self.position = tuple(map(add, self.position, (x_offset, y_offset)))
|
||||
|
||||
def equivalent(self, other, offset):
|
||||
'''Is this the same as the other circle, ignoring the offiset?'''
|
||||
|
||||
if not isinstance(other, Circle):
|
||||
return False
|
||||
|
||||
if self.diameter != other.diameter:
|
||||
return False
|
||||
|
||||
equiv_position = tuple(map(add, other.position, offset))
|
||||
|
||||
return nearly_equal(self.position, equiv_position)
|
||||
|
||||
|
||||
class Ellipse(Primitive):
|
||||
|
|
@ -487,6 +500,19 @@ class Rectangle(Primitive):
|
|||
return (math.cos(math.radians(self.rotation)) * self.height +
|
||||
math.sin(math.radians(self.rotation)) * self.width)
|
||||
|
||||
def equivalent(self, other, offset):
|
||||
'''Is this the same as the other rect, ignoring the offiset?'''
|
||||
|
||||
if not isinstance(other, Rectangle):
|
||||
return False
|
||||
|
||||
if self.width != other.width or self.height != other.height or self.rotation != other.rotation:
|
||||
return False
|
||||
|
||||
equiv_position = tuple(map(add, other.position, offset))
|
||||
|
||||
return nearly_equal(self.position, equiv_position)
|
||||
|
||||
|
||||
class Diamond(Primitive):
|
||||
"""
|
||||
|
|
@ -815,6 +841,9 @@ class Outline(Primitive):
|
|||
self.primitives = primitives
|
||||
self._to_convert = ['primitives']
|
||||
|
||||
if self.primitives[0].start != self.primitives[-1].end:
|
||||
raise ValueError('Outline must be closed')
|
||||
|
||||
@property
|
||||
def flashed(self):
|
||||
return True
|
||||
|
|
@ -833,6 +862,9 @@ class Outline(Primitive):
|
|||
def offset(self, x_offset=0, y_offset=0):
|
||||
for p in self.primitives:
|
||||
p.offset(x_offset, y_offset)
|
||||
|
||||
if self.primitives[0].start != self.primitives[-1].end:
|
||||
raise ValueError('Outline must be closed')
|
||||
|
||||
@property
|
||||
def width(self):
|
||||
|
|
|
|||
|
|
@ -22,6 +22,14 @@ class AMGroupContext(object):
|
|||
for primitive in nooffset_group.primitives:
|
||||
if isinstance(primitive, Outline):
|
||||
self._render_outline(primitive)
|
||||
elif isinstance(primitive, Circle):
|
||||
self._render_circle(primitive)
|
||||
elif isinstance(primitive, Rectangle):
|
||||
self._render_rectangle(primitive)
|
||||
elif isinstance(primitive, Line):
|
||||
self._render_line(primitive)
|
||||
else:
|
||||
raise ValueError('amgroup')
|
||||
|
||||
statement = AMParamStmt('AM', name, self._statements_to_string())
|
||||
return statement
|
||||
|
|
@ -33,10 +41,21 @@ class AMGroupContext(object):
|
|||
macro += statement.to_gerber()
|
||||
|
||||
return macro
|
||||
|
||||
def _render_circle(self, circle):
|
||||
self.statements.append(AMCirclePrimitive.from_primitive(circle))
|
||||
|
||||
def _render_rectangle(self, rectangle):
|
||||
self.statements.append(AMCenterLinePrimitive.from_primitive(rectangle))
|
||||
|
||||
def _render_line(self, line):
|
||||
self.statements.append(AMVectorLinePrimitive.from_primitive(line))
|
||||
|
||||
def _render_outline(self, outline):
|
||||
self.statements.append(AMOutlinePrimitive.from_primitive(outline))
|
||||
|
||||
|
||||
def _render_thermal(self, thermal):
|
||||
pass
|
||||
|
||||
|
||||
class Rs274xContext(GerberContext):
|
||||
|
|
@ -59,6 +78,8 @@ class Rs274xContext(GerberContext):
|
|||
self._next_dcode = 10
|
||||
self._rects = {}
|
||||
self._circles = {}
|
||||
self._obrounds = {}
|
||||
self._polygons = {}
|
||||
self._macros = {}
|
||||
|
||||
self._i_none = 0
|
||||
|
|
@ -67,9 +88,10 @@ class Rs274xContext(GerberContext):
|
|||
self.settings = settings
|
||||
|
||||
self._start_header(settings)
|
||||
self._define_dcodes()
|
||||
#self._define_dcodes()
|
||||
|
||||
def _start_header(self, settings):
|
||||
self.header.append(FSParamStmt.from_settings(settings))
|
||||
self.header.append(MOParamStmt.from_units(settings.units))
|
||||
|
||||
def _define_dcodes(self):
|
||||
|
|
@ -151,8 +173,12 @@ class Rs274xContext(GerberContext):
|
|||
# We already set the function, so the next command doesn't require that
|
||||
func = None
|
||||
|
||||
self.body.append(CoordStmt.line(func, self._simplify_point(line.end)))
|
||||
self._pos = line.end
|
||||
point = self._simplify_point(line.end)
|
||||
|
||||
# In some files, we see a lot of duplicated ponts, so omit those
|
||||
if point[0] != None or point[1] != None:
|
||||
self.body.append(CoordStmt.line(func, self._simplify_point(line.end)))
|
||||
self._pos = line.end
|
||||
|
||||
def _render_arc(self, arc, color):
|
||||
|
||||
|
|
@ -269,10 +295,33 @@ class Rs274xContext(GerberContext):
|
|||
aper = self._get_rectangle(rectangle.width, rectangle.height)
|
||||
self._render_flash(rectangle, aper)
|
||||
|
||||
def _get_obround(self, width, height, dcode = None):
|
||||
|
||||
key = (width, height)
|
||||
aper = self._obrounds.get(key, None)
|
||||
|
||||
if not aper:
|
||||
if not dcode:
|
||||
dcode = self._next_dcode
|
||||
self._next_dcode += 1
|
||||
else:
|
||||
self._next_dcode = max(dcode + 1, self._next_dcode)
|
||||
|
||||
aper = ADParamStmt.obround(dcode, width, height)
|
||||
self._obrounds[(width, height)] = aper
|
||||
self.header.append(aper)
|
||||
|
||||
return aper
|
||||
|
||||
def _render_obround(self, obround, color):
|
||||
|
||||
aper = self._get_obround(obround.width, obround.height)
|
||||
self._render_flash(obround, aper)
|
||||
|
||||
pass
|
||||
|
||||
def _render_polygon(self, polygon, color):
|
||||
raise NotImplementedError('Not implemented yet')
|
||||
pass
|
||||
|
||||
def _render_drill(self, circle, color):
|
||||
|
|
@ -285,8 +334,19 @@ class Rs274xContext(GerberContext):
|
|||
for primitive in amgroup.primitives:
|
||||
|
||||
hash += primitive.__class__.__name__[0]
|
||||
|
||||
bbox = primitive.bounding_box
|
||||
hash += str((bbox[0][1] - bbox[0][0]) * 100000)[0:2]
|
||||
hash += str((bbox[1][1] - bbox[1][0]) * 100000)[0:2]
|
||||
|
||||
if hasattr(primitive, 'primitives'):
|
||||
hash += str(len(primitive.primitives))
|
||||
|
||||
if isinstance(primitive, Rectangle):
|
||||
hash += str(primitive.width * 1000000)[0:2]
|
||||
hash += str(primitive.height * 1000000)[0:2]
|
||||
elif isinstance(primitive, Circle):
|
||||
hash += str(primitive.diameter * 1000000)[0:2]
|
||||
|
||||
return hash
|
||||
|
||||
|
|
@ -331,9 +391,7 @@ class Rs274xContext(GerberContext):
|
|||
|
||||
aper = self._get_amacro(amgroup)
|
||||
self._render_flash(amgroup, aper)
|
||||
|
||||
|
||||
|
||||
|
||||
def _render_inverted_layer(self):
|
||||
pass
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue