def _init(self): top_leds = [] bottom_leds = [] def dt(a, b): t = self.add(Trace(thickness=20 * MIL)) t.set_endpoints(a, b) for x in xrange(self.cols): prev = None for y in xrange(self.rows): l = Led(id=Id('LED%s_%s' % (str(x), str(y)))) translate( l, V((x * self.spacing) - ((self.cols - 1) * self.spacing / 2), (y * self.spacing) - ((self.rows - 0) * self.spacing / 2))) l = self.add(l) if prev is None: top_leds.append(l) else: dt(prev.footprint._2, l.footprint._1) prev = l bottom_leds.append(prev) # Create offset points for the common anodes and cathodes. top_points = [] for t in top_leds: p = Point() translate(p, centerof(t.footprint._1) + V(0, -self.spacing / 2)) p = self.add(p) dt(t.footprint._1, p) top_points.append(p) bottom_points = [] for t in bottom_leds: p = Point() translate(p, centerof(t.footprint._2) + V(0, self.spacing / 2)) p = self.add(p) dt(t.footprint._2, p) bottom_points.append(p) # Link common anodes and cathodes p = None for i in top_points: if p is not None: dt(p, i) p = i p = None for i in bottom_points: if p is not None: dt(p, i) p = i
def _init(self): top_leds = [] bottom_leds = [] def dt(a,b): t = self.add(Trace(thickness=20 * MIL)) t.set_endpoints(a,b) for x in xrange(self.cols): prev = None for y in xrange(self.rows): l = Led(id=Id('LED%s_%s' % (str(x),str(y)))) translate(l,V((x * self.spacing) - ((self.cols - 1) * self.spacing / 2), (y * self.spacing) - ((self.rows - 0) * self.spacing / 2))) l = self.add(l) if prev is None: top_leds.append(l) else: dt(prev.footprint._2,l.footprint._1) prev = l bottom_leds.append(prev) # Create offset points for the common anodes and cathodes. top_points = [] for t in top_leds: p = Point() translate(p,centerof(t.footprint._1) + V(0,-self.spacing / 2)) p = self.add(p) dt(t.footprint._1,p) top_points.append(p) bottom_points = [] for t in bottom_leds: p = Point() translate(p,centerof(t.footprint._2) + V(0,self.spacing / 2)) p = self.add(p) dt(t.footprint._2,p) bottom_points.append(p) # Link common anodes and cathodes p = None for i in top_points: if p is not None: dt(p,i) p = i p = None for i in bottom_points: if p is not None: dt(p,i) p = i
def iterlayout(self, layer_mask): if self.layer in layer_mask: if not self.a or not self.b: raise NotImplementedError # FIXME: try: yield self.copper except AttributeError: self.add( Line(a=centerof(self.a()), b=centerof(self.b()), thickness=self.thickness, layer=self.layer, id=Id('copper'))) yield self.copper
def iterlayout(self, layer_mask): if self.layer in layer_mask: if not self.a or not self.b: raise NotImplementedError # FIXME: try: yield self.copper except AttributeError: self.add( Line( a=centerof(self.a()), b=centerof(self.b()), thickness=self.thickness, layer=self.layer, id=Id("copper"), ) ) yield self.copper
def testElementIdAttr(self): """Auto-magical attribute lookup from sub-element Id's""" a = Element(id=Id('a')) translate(a,V(1,1)) foo = Element(id=Id('foo')) translate(foo,V(2,1)) bar = Element(id=Id('bar')) translate(bar,V(1,2)) a.add(foo) a.add(bar) self.assert_(a.foo.id == Id('a/foo')) self.assert_(repr(centerof(a.foo)) == repr(V(3,2))) self.assert_(a.bar.id == Id('a/bar')) self.assert_(repr(centerof(a.bar)) == repr(V(2,3))) self.assertRaises(AttributeError,lambda: a.foobar) foo.foo = 'foo' self.assert_(a.foo.foo is foo.foo) a.foo.bar = 'bar' self.assert_(a.foo.bar is foo.bar)
def to_gerber(elem): """Exports an element to gerber RS274X Returns a dict of the different layers encountered. """ layers = {} # key is size, value is list of vertexes drill_hits = {} for g in elem.iterlayout(): def s(n): """Convert float n meters to gerber 3.5 format, (inches) leading zeros removed""" n = (n / IN) * 1e+5 # The int() effectively removes tailing decimals and leading zeros. return str(int(n)) if hasattr(g,'render'): (coords,ext_coords) = g.render() l = str(g.layer) # convert coords to mm def t(v): return (s(v[0,0]),s(v[0,1])) coords = [t(v) for v in coords] # Create gerber layers for each element layer. if not layers.has_key(l): layers[l] = '' # Comment for debugging layers[l] += 'G04 id: %s *\n' % str(g.id) # start Polygon Area Fill code layers[l] += 'G36*\n' # first vertex gets repeated to close the polygon layers[l] += 'X%sY%sD02\n' % (str(coords[0][1]),str(coords[0][1])) # rest of the vertexes are handled normally for (x,y) in coords: layers[l] += 'X%sY%sD01*\n' % (str(x),str(y)) layers[l] += 'G37*\n' elif isinstance(g,Hole): l = None # dia is expressed as 0.000 in inches dia = str(round(g.dia / IN,3)) try: l = drill_hits[dia] except KeyError: l = [] drill_hits[dia] = l l.append(centerof(g)) # add program end markers to all layers for l in layers.keys(): layers[l] += 'M02*\n' # prepend parameter blocks to all layers for l in layers.keys(): comment = 'G04 layer: %s *\n' % l layers[l] = comment + \ """ %MOIN*% %FSLAX35Y35*% %ADD11C,0.0200*% """ + layers[l] # Create drill layer drill = [] drill.append('M48') drill.append('INCH,TZ') for n,dia in enumerate(sorted(drill_hits.keys())): drill.append('T%dC%s' % (n + 11,dia)) drill.append('%') for n,dia in enumerate(sorted(drill_hits.keys())): drill.append('T%d' % (n + 11)) for v in drill_hits[dia]: # Gerber drill file stores drill locations in to 4 decimal points # in inches, but with the decimal point dropped. # # 12.3456 in -> 123456 # # Note that there must be exactly six digits, padding with leading # zeros. def s(x): return '%0.6d' % ((x / IN) * 10000) x = s(v[0,0]) y = s(v[0,1]) drill.append('X%sY%s' % (x,y)) drill.append('M30') layers['drill'] = '\n'.join(drill) return layers