def export_footprint(self, interim, timestamp = None): if timestamp is None: timestamp = time.time() meta = inter.get_meta(interim) name = eget(meta, 'name', 'Name not found') # make name kicad compatible name = re.sub(' ','_',name) self.name = name desc = oget(meta, 'desc', '') parent_idx = oget(meta, 'parent', None) d = [] # generate kicad-old for individual footprint # use metric; convert to imperial in "save" if needed d.append("$MODULE %s" % (name)) d.append("Po 0 0 0 15 %x 00000000 ~~" % timestamp) d.append("Li %s" % (name)) d.append("Cd %s" % (desc.replace('\n',' '))) # ugly # assuming Kw is optional d.append("Sc 0") # d.append("AR ") assume AR is optional d.append("Op 0 0 0") # if no T0 or T1 are specified, kicad defaults to this: # right now I'm assuming this is optional # T0 0 0 1.524 1.524 0 0.15 N V 21 N "" # T1 0 0 1.524 1.524 0 0.15 N V 21 N "" def pad(shape, smd=False): l = ['$PAD'] # Sh "<pad name>" shape Xsize Ysize Xdelta Ydelta Orientation # octagons are not supported by kicad if shape['shape'] == 'disc' or shape['shape'] == 'octagon': sh = 'C' dx = shape['r']*2 dy = dx elif shape['shape'] == 'rect': dx = shape['dx'] dy = shape['dy'] sh = 'R' # any rect with roundness >= 50 is considered kicad 'oblong' if 'ro' in shape: if shape['ro'] >= 50: sh = 'O' rot = fget(shape, 'rot')*10 l.append("Sh \"%s\" %s %s %s %s %s %s" % (shape['name'], sh, dx, dy, 0, 0, rot)) # Dr <Pad drill> Xoffset Yoffset (round hole) if not smd: l.append("Dr %s %s %s" % (fget(shape, 'drill'), fget(shape, 'drill_off_dx'), fc(-fget(shape, 'drill_off_dy')))) # Po <x> <y> l.append("Po %s %s" % (fget(shape,'x'), fc(-fget(shape,'y')))) # At <Pad type> N <layer mask> t = 'STD' layer_mask = '00E0FFFF' if smd: t = 'SMD' layer_mask = '00888000' l.append("At %s N %s" % (t, layer_mask)) l.append('Ne 0 ""') l.append("$ENDPAD") return l # DS Xstart Ystart Xend Yend Width Layer # DS 6000 1500 6000 -1500 120 21 # DA Xcentre Ycentre Xstart_point Ystart_point angle width layer def vertex(shape, layer): l = [] x1 = fget(shape, 'x1') y1 = fget(shape, 'y1') x2 = fget(shape, 'x2') y2 = fget(shape, 'y2') w = fget(shape, 'w') if not 'curve' in shape or shape['curve'] == 0.0: line = "DS %s %s %s %s %s %s" % (x1, fc(-y1), x2, fc(-y2), w, layer) l.append(line) else: curve = fget(shape, 'curve') angle = curve*math.pi/180.0 ((x0, y0), r, a1, a2) = mutil.calc_center_r_a1_a2((x1,y1),(x2,y2),angle) arc = "DA %f %f %f %f %s %s %s" % (x0, fc(-y0), x1, fc(-y1), int(round((-10.0)*(a2-a1))), w, layer) l.append(arc) return l # DC Xcentre Ycentre Xpoint Ypoint Width Layer def circle(shape, layer): l = [] x = fget(shape, 'x') y = fget(shape, 'y') r = fget(shape, 'r') w = fget(shape, 'w') if not 'a1' in shape and not 'a2' in shape: circle = "DC %s %s %s %s %s %s" % (x, fc(-y), fc(x+(r/math.sqrt(2))), fc(-y+(r/math.sqrt(2))), w, layer) l.append(circle) else: # start == center point # end == start point of arc # angle == angled part in that direction a1 = fget(shape, 'a1') a2 = fget(shape, 'a2') a1rad = a1 * math.pi/180.0 ex = x + r*math.cos(a1rad) ey = y + r*math.sin(a1rad) arc = "DA %f %f %f %f %s %s %s" % (x, fc(-y), ex, fc(-ey), int(round((-10)*(a2-a1))), w, layer) l.append(arc) return l def disc(shape, layer): l = [] x = fget(shape, 'x') y = -fget(shape, 'y') r = fget(shape, 'r') rad = r/2 ex = x+(rad/math.sqrt(2)) ey = y+(rad/math.sqrt(2)) circle = "DC %s %s %s %s %s %s" % (x, fc(y), fc(ex), fc(ey), rad, layer) l.append(circle) return l def hole(shape): layer = type_to_num(shape['type']) shape['r'] = shape['drill'] / 2 return circle(shape, layer) # T0 -79 -3307 600 600 0 120 N V 21 N "XT" def label(shape, layer): s = shape['value'].upper() t = 'T2' visible = 'V' if s == 'VALUE': t = 'T1' visible = 'I' if s == 'NAME': t = 'T0' dy = fget(shape, 'dy', 1/1.6) w = fget(shape, 'w', 0.1) x = fget(shape, 'x') y = fc(-fget(shape, 'y')) # T0 -7 -3 60 60 0 10 N V 21 N "XT" line = "%s %s %s %s %s 0 %s N %s %s N \"%s\"" % (t, x, y, dy, dy, w, visible, layer, shape['value']) return [line] def rect(shape, layer): print "rect", shape, layer l = [] w = fget(shape,'w') rot = abs(fget(shape, 'rot')) l.append("DP 0 0 0 0 %s %s %s" % (5, w, layer)) x = fget(shape, 'x') y = -fget(shape, 'y') dx = fget(shape, 'dx') dy = fget(shape, 'dy') if rot == 90 or rot == 270: (dx,dy) = (dy,dx) def add(x1, y1): l.append("Dl %f %f" % (fc(x1), fc(y1))) add(x - dx/2, y - dy/2) add(x - dx/2, y + dy/2) add(x + dx/2, y + dy/2) add(x + dx/2, y - dy/2) add(x - dx/2, y - dy/2) return l # DP 0 0 0 0 corners_count width layer # DP 0 0 0 0 5 0.1 24 # Dl corner_posx corner_posy # Dl 0 -1 def polygon(shape, layer): l = [] n = len(shape['v']) w = shape['w'] l.append("DP 0 0 0 0 %s %s %s" % (n + 1, w, layer)) for v in shape['v']: l.append("Dl %g %g" % (fc(v['x1']), fc(-v['y1']))) l.append("Dl %g %g" % (fc(shape['v'][0]['x1']), fc(-shape['v'][0]['y1']))) return l def silk(shape): if not 'shape' in shape: return None layer = type_to_num(shape['type']) s = shape['shape'] if s == 'line': return vertex(shape, layer) if s == 'vertex': return vertex(shape, layer) elif s == 'circle': return circle(shape, layer) elif s == 'disc': return disc(shape, layer) elif s == 'label': return label(shape, layer) elif s == 'rect': return rect(shape, layer) elif s == 'polygon': return polygon(shape, layer) def unknown(shape): return None for shape in interim: if 'type' in shape: l = { 'pad': pad, 'cu': silk, 'silk': silk, 'docu': silk, 'keepout': unknown, 'stop': silk, 'glue': silk, 'restrict': unknown, 'vrestrict': unknown, 'smd': lambda s: pad(s, smd=True), 'hole': hole, }.get(shape['type'], unknown)(shape) if l != None: d += l d.append("$EndMODULE %s" % (name)) self.data = d return name
def export_footprint(self, interim): meta = inter.get_meta(interim) name = eget(meta, 'name', 'Name not found') descr = oget(meta, 'desc', '') parent_idx = oget(meta, 'parent', None) l = [ S('module'), S(name), [S('layer'), S('F.Cu')], [S('descr'), descr], ] def pad_line(x1, y1, x2, y2, width, layer): l = [S('fp_line')] l.append([S('start'), x1, y1]) l.append([S('end'), x2, y2]) l.append([S('layer'), S(layer)]) l.append([S('width'), width]) return l def pad_lines(s, x1, y1, x2, y2, width): s.append(pad_line(x1, y1, x2, y2, width, 'F.Cu')) s.append(pad_line(x1, y1, x2, y2, width, 'F.Paste')) s.append(pad_line(x1, y1, x2, y2, width, 'F.Mask')) def gen_lines(l, x, y, rot, radius, dx, dy): # 4 corners xo = dx / 2 - radius yo = dy / 2 - radius rot = math.radians(rot) xp = math.cos(rot) * xo - math.sin(rot) * yo yp = math.cos(rot) * yo + math.sin(rot) * xo x1 = x - xp x2 = x + xp y1 = y - yp y2 = y + yp pad_lines(l, x1, y1, x2, y1, radius * 2) pad_lines(l, x2, y1, x2, y2, radius * 2) pad_lines(l, x2, y2, x1, y2, radius * 2) pad_lines(l, x1, y2, x1, y1, radius * 2) def pad(shape, smd=False): want_paste = True if 'paste' in shape: want_paste = shape['paste'] if 'name' in shape: name = shape['name'] if name is None or name == "": name = "" else: name = S(name) else: name = "" l = [S('pad'), name] shapes = [l] if smd: l.append(S('smd')) else: l.append(S('thru_hole')) shape2 = 'disc' # disc is the default if 'shape' in shape: shape2 = shape['shape'] r = fget(shape, 'r') if shape2 == 'disc': l.append(S('circle')) l.append([S('size'), r * 2, r * 2]) elif shape2 == 'rect': ro = iget(shape, 'ro') dx = fget(shape, 'dx') dy = fget(shape, 'dy') if ro == 100: l.append(S('oval')) l.append([S('size'), dx, dy]) else: l.append(S('rect')) if ro == 0: l.append([S('size'), dx, dy]) else: #find the smallest dimension and create a rectangular pad squished by that amount #TODO: the rectangular pad is simple with 4 lines, 1 rect and guaranteed no holes #however it can create arbitrarily small pad which will make text in kicad hard to #read. may be better to use a oval pad, which can be not shrunk and is still guaranteed #to not overrun the pad, however it is tricky to make sure the 4 lines don't create any holes. small = dx if dy < dx: small = dy radius = small / 2 * ro / 100.0 l.append([S('size'), dx - radius * 2, dy - radius * 2]) gen_lines(shapes, fget(shape, 'x'), -fget(shape, 'y'), iget(shape, 'rot'), radius, dx, dy) else: raise Exception("%s shaped pad not supported in kicad" % (shape2)) l.append([ S('at'), fget(shape, 'x'), -fget(shape, 'y'), iget(shape, 'rot') ]) if smd: if shape['type'] != 'smd': l.append([S('layers'), S('F.Paste')]) else: if want_paste: l.append([ S('layers'), S('F.Cu'), S('F.Paste'), S('F.Mask') ]) else: l.append([S('layers'), S('F.Cu'), S('F.Mask')]) else: l.append([S('layers'), S('*.Cu'), S('*.Mask')]) if not smd: if 'drill_dx' in shape or 'drill_dy' in shape: drill_dx = fget(shape, 'drill_dx') drill_dy = fget(shape, 'drill_dy') l2 = [S('drill'), S('oval'), drill_dx, drill_dy] else: l2 = [S('drill'), fget(shape, 'drill')] if 'drill_off_dx' in shape or 'drill_off_dy' in shape: l2.append([ S('offset'), fget(shape, 'drill_off_dx'), fget(shape, 'drill_off_dy') ]) l.append(l2) l.append([S('solder_mask_margin'), fget(shape, 'mask_swell')]) l.append( [S('solder_paste_margin_ratio'), fget(shape, 'paste_ratio')]) return shapes #(fp_line (start -2.54 -1.27) (end 2.54 -1.27) (layer F.SilkS) (width 0.381)) # (fp_arc (start 7.62 0) (end 7.62 -2.54) (angle 90) (layer F.SilkS) (width 0.15)) def vertex(shape, layer): if not 'curve' in shape or shape['curve'] == 0.0: l = [S('fp_line')] l.append([S('start'), fget(shape, 'x1'), -fget(shape, 'y1')]) l.append([S('end'), fget(shape, 'x2'), -fget(shape, 'y2')]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) else: l = [S('fp_arc')] # start == center point # end == start point of arc # angle == angled part in that direction x1 = fget(shape, 'x1') y1 = fget(shape, 'y1') x2 = fget(shape, 'x2') y2 = fget(shape, 'y2') curve = fget(shape, 'curve') angle = curve * math.pi / 180.0 ((x0, y0), r, a1, a2) = calc_center_r_a1_a2((x1, y1), (x2, y2), angle) l.append([S('start'), fc(x0), fc(-y0)]) l.append([S('end'), fc(x1), fc(-y1)]) # also invert angle because of y inversion l.append([S('angle'), -(a2 - a1)]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) return [l] # (fp_circle (center 5.08 0) (end 6.35 -1.27) (layer F.SilkS) (width 0.15)) def circle(shape, layer): x = fget(shape, 'x') y = -fget(shape, 'y') r = fget(shape, 'r') if not 'a1' in shape and not 'a2' in shape: l = [S('fp_circle')] l.append([S('center'), fc(x), fc(y)]) l.append([ S('end'), fc(x + (r / math.sqrt(2))), fc(y + (r / math.sqrt(2))) ]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) else: l = [S('fp_arc')] l.append([S('start'), fc(x), fc(y)]) # start == center point # end == start point of arc # angle == angled part in that direction a1 = fget(shape, 'a1') a2 = fget(shape, 'a2') a1rad = a1 * math.pi / 180.0 ex = x + r * math.cos(a1rad) ey = y + r * math.sin(a1rad) l.append([S('end'), fc(ex), fc(-ey)]) l.append([S('angle'), -(a2 - a1)]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) return [l] # a disc is just a circle with a clever radius and width def disc(shape, layer): l = [S('fp_circle')] x = fget(shape, 'x') y = -fget(shape, 'y') l.append([S('center'), fc(x), fc(y)]) r = fget(shape, 'r') rad = r / 2 l.append( [S('end'), x + (rad / math.sqrt(2)), y + (rad / math.sqrt(2))]) l.append([S('layer'), S(layer)]) l.append([S('width'), rad]) return [l] def hole(shape): l = [S('pad'), ""] l.append(S('np_thru_hole')) l.append(S('circle')) l.append([S('at'), fget(shape, 'x'), -fget(shape, 'y')]) drill = fget(shape, 'drill') l.append([S('size'), drill, drill]) l.append([S('drill'), drill]) l.append([S('layers'), S('*.Cu'), S('*.Mask'), S('F.SilkS')]) return [l] # (fp_poly (pts (xy 6.7818 1.6002) (xy 6.6294 1.6002) (xy 6.6294 1.4478) (xy 6.7818 1.4478) (xy 6.7818 1.6002)) (layer F.Cu) (width 0.00254)) # kicad doesn't do arced vertex in polygon :( def polygon(shape, layer): l = [S('fp_poly')] lxy = [S('pts')] for v in shape['v']: xy = [S('xy'), fc(v['x1']), fc(-v['y1'])] lxy.append(xy) xy = [S('xy'), fc(shape['v'][0]['x1']), fc(-shape['v'][0]['y1'])] lxy.append(xy) l.append(lxy) l.append([S('layer'), S(layer)]) l.append([S('width'), shape['w']]) return [l] def rect(shape, layer): l = [S('fp_poly')] x = fget(shape, 'x') y = -fget(shape, 'y') dx = fget(shape, 'dx') dy = fget(shape, 'dy') rot = fget(shape, 'rot') if rot == 90 or rot == 270: (dx, dy) = (dy, dx) lxy = [S('pts')] def add(x1, y1): lxy.append([S('xy'), fc(x1), fc(y1)]) add(x - dx / 2, y - dy / 2) add(x - dx / 2, y + dy / 2) add(x + dx / 2, y + dy / 2) add(x + dx / 2, y - dy / 2) add(x - dx / 2, y - dy / 2) l.append(lxy) l.append([S('layer'), S(layer)]) l.append([S('width'), 0]) return [l] # (fp_text reference MYCONN3 (at 0 -2.54) (layer F.SilkS) # (effects (font (size 1.00076 1.00076) (thickness 0.25146))) # ) # (fp_text value SMD (at 0 2.54) (layer F.SilkS) hide # (effects (font (size 1.00076 1.00076) (thickness 0.25146))) # ) def label(shape, layer): s = shape['value'].upper() t = "user" if s == "VALUE": t = "value" l = [S('fp_text'), S(t), 'VAL**'] elif s == "NAME": t = "reference" l = [S('fp_text'), S(t), 'REF**'] else: l = [S('fp_text'), S(t), shape['value']] if (('rot' in shape) and (fget(shape, 'rot') != 0.0)): l.append([ S('at'), fget(shape, 'x'), fc(-fget(shape, 'y')), fget(shape, 'rot') ]) else: l.append([S('at'), fget(shape, 'x'), fc(-fget(shape, 'y'))]) l.append([S('layer'), S(layer)]) if s == 'VALUE': l.append(S('hide')) dy = fget(shape, 'dy', 1 / 1.6) th = fget(shape, 'w', 0.1) l.append([ S('effects'), [S('font'), [S('size'), dy, dy], [S('thickness'), th]] ]) return [l] def silk(shape): if not 'shape' in shape: return None layer = type_to_layer_name(shape['type']) s = shape['shape'] if s == 'line': return vertex(shape, layer) if s == 'vertex': return vertex(shape, layer) elif s == 'circle': return circle(shape, layer) elif s == 'disc': return disc(shape, layer) elif s == 'label': return label(shape, layer) elif s == 'rect': return rect(shape, layer) elif s == 'polygon': return polygon(shape, layer) def unknown(shape): return None for shape in interim: if 'type' in shape: l2 = { 'pad': pad, 'cu': silk, 'silk': silk, 'bsilk': silk, 'docu': silk, 'keepout': silk, 'bkeepout': silk, 'stop': silk, 'bstop': silk, 'glue': silk, 'paste': silk, 'bpaste': silk, 'restrict': unknown, 'vrestrict': unknown, 'comments': silk, 'user1': silk, 'user2': silk, 'margin': silk, 'assembly': silk, 'bassembly': silk, 'smd': lambda s: pad(s, smd=True), 'hole': hole, 'edge': silk, }.get(shape['type'], unknown)(shape) if l2 != None: l.extend(l2) self.data = l self.name = name return name
def export_footprint(self, interim): meta = inter.get_meta(interim) name = eget(meta, 'name', 'Name not found') idx = eget(meta, 'id', 'Id not found') descr = oget(meta, 'desc', '') parent_idx = oget(meta, 'parent', None) l = [ S('module'), name, [S('layer'), S('F.Cu')], [S('descr'), descr], ] def pad(shape, smd=False): l = [S('pad'), S(shape['name'])] if smd: l.append(S('smd')) else: l.append(S('thru_hole')) shape2 = 'disc' # disc is the default if 'shape' in shape: shape2 = shape['shape'] r = fget(shape, 'r') if shape2 == 'disc': l.append(S('circle')) l.append([S('size'), r*2, r*2]) elif shape2 == 'rect': ro = iget(shape, 'ro') if ro == 0: l.append(S('rect')) else: l.append(S('oval')) l.append([S('size'), fget(shape, 'dx'), fget(shape, 'dy')]) else: raise Exception("%s shaped pad not supported in kicad" % (shape2)) l.append([S('at'), fget(shape, 'x'), -fget(shape, 'y'), iget(shape, 'rot')]) if smd: l.append([S('layers'), S('F.Cu'), S('F.Paste'), S('F.Mask')]) else: l.append([S('layers'), S('*.Cu'), S('*.Mask')]) if not smd: l2 = [S('drill'), fget(shape, 'drill')] if 'drill_dx' in shape or 'drill_dy' in shape: l2.append([S('offset'), fget(shape, 'drill_dx'), fget(shape, 'drill_dy')]) l.append(l2) return l #(fp_line (start -2.54 -1.27) (end 2.54 -1.27) (layer F.SilkS) (width 0.381)) # (fp_arc (start 7.62 0) (end 7.62 -2.54) (angle 90) (layer F.SilkS) (width 0.15)) def vertex(shape, layer): if not 'curve' in shape or shape['curve'] == 0.0: l = [S('fp_line')] l.append([S('start'), fget(shape, 'x1'), -fget(shape, 'y1')]) l.append([S('end'), fget(shape, 'x2'), -fget(shape, 'y2')]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) else: l = [S('fp_arc')] # start == center point # end == start point of arc # angle == angled part in that direction x1 = fget(shape, 'x1') y1 = fget(shape, 'y1') x2 = fget(shape, 'x2') y2 = fget(shape, 'y2') curve = fget(shape, 'curve') angle = curve*math.pi/180.0 ((x0, y0), r, a1, a2) = calc_center_r_a1_a2((x1,y1),(x2,y2),angle) l.append([S('start'), fc(x0), fc(-y0)]) l.append([S('end'), fc(x1), fc(-y1)]) # also invert angle because of y inversion l.append([S('angle'), -(a2-a1)]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) return l # (fp_circle (center 5.08 0) (end 6.35 -1.27) (layer F.SilkS) (width 0.15)) def circle(shape, layer): x = fget(shape, 'x') y = -fget(shape, 'y') r = fget(shape, 'r') if not 'a1' in shape and not 'a2' in shape: l = [S('fp_circle')] l.append([S('center'),fc(x),fc(y)]) l.append([S('end'), fc(x+(r/math.sqrt(2))), fc(y+(r/math.sqrt(2)))]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) else: l = [S('fp_arc')] l.append([S('start'),fc(x),fc(y)]) # start == center point # end == start point of arc # angle == angled part in that direction a1 = fget(shape, 'a1') a2 = fget(shape, 'a2') a1rad = a1 * math.pi/180.0 ex = x + r*math.cos(a1rad) ey = y + r*math.sin(a1rad) l.append([S('end'), fc(ex), fc(-ey)]) l.append([S('angle'), -(a2-a1)]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) return l # a disc is just a circle with a clever radius and width def disc(shape, layer): l = [S('fp_circle')] x = fget(shape, 'x') y = -fget(shape, 'y') l.append([S('center'), fc(x), fc(y)]) r = fget(shape, 'r') rad = r/2 l.append([S('end'), x+(rad/math.sqrt(2)), y+(rad/math.sqrt(2))]) l.append([S('layer'), S(layer)]) l.append([S('width'), rad]) return l def hole(shape): layer = type_to_layer_name(shape['type']) # aka 'hole' shape['r'] = shape['drill'] / 2 return circle(shape, layer) # (fp_poly (pts (xy 6.7818 1.6002) (xy 6.6294 1.6002) (xy 6.6294 1.4478) (xy 6.7818 1.4478) (xy 6.7818 1.6002)) (layer F.Cu) (width 0.00254)) # kicad doesn't do arced vertex in polygon :( def polygon(shape, layer): l = [S('fp_poly')] lxy = [S('pts')] for v in shape['v']: xy = [S('xy'), fc(v['x1']), fc(-v['y1'])] lxy.append(xy) xy = [S('xy'), fc(shape['v'][0]['x1']), fc(-shape['v'][0]['y1'])] lxy.append(xy) l.append(lxy) l.append([S('layer'), S(layer)]) l.append([S('width'), shape['w']]) return l def rect(shape, layer): l = [S('fp_poly')] x = fget(shape, 'x') y = - fget(shape, 'y') dx = fget(shape, 'dx') dy = fget(shape, 'dy') lxy = [S('pts')] def add(x1, y1): lxy.append([S('xy'), fc(x1), fc(y1)]) add(x - dx/2, y - dy/2) add(x - dx/2, y + dy/2) add(x + dx/2, y + dy/2) add(x + dx/2, y - dy/2) add(x - dx/2, y - dy/2) l.append(lxy) l.append([S('layer'), S(layer)]) l.append([S('width'), 0]) return l # (fp_text reference MYCONN3 (at 0 -2.54) (layer F.SilkS) # (effects (font (size 1.00076 1.00076) (thickness 0.25146))) # ) # (fp_text value SMD (at 0 2.54) (layer F.SilkS) hide # (effects (font (size 1.00076 1.00076) (thickness 0.25146))) # ) def label(shape, layer): s = shape['value'].upper() t = 'user' if s == 'VALUE': t = 'value' if s == 'NAME': t = 'reference' l = [S('fp_text'), S(t), S(shape['value'])] if (('rot' in shape) and (fget(shape, 'rot') != 0.0)): l.append([S('at'), fget(shape, 'x'), fc(-fget(shape, 'y')), fget(shape, 'rot')]) else: l.append([S('at'), fget(shape, 'x'), fc(-fget(shape, 'y'))]) l.append([S('layer'), S(layer)]) if s == 'VALUE': l.append(S('hide')) dy = fget(shape, 'dy', 1/1.6) th = fget(shape, 'w', 0.1) l.append([S('effects'), [S('font'), [S('size'), dy, dy], [S('thickness'), th]]]) return l def silk(shape): if not 'shape' in shape: return None layer = type_to_layer_name(shape['type']) s = shape['shape'] if s == 'line': return vertex(shape, layer) if s == 'vertex': return vertex(shape, layer) elif s == 'circle': return circle(shape, layer) elif s == 'disc': return disc(shape, layer) elif s == 'label': return label(shape, layer) elif s == 'rect': return rect(shape, layer) elif s == 'polygon': return polygon(shape, layer) def unknown(shape): return None for shape in interim: if 'type' in shape: l2 = { 'pad': pad, 'cu': silk, 'silk': silk, 'docu': silk, 'keepout': unknown, 'stop': silk, 'glue': silk, 'restrict': unknown, 'vrestrict': unknown, 'smd': lambda s: pad(s, smd=True), 'hole': hole, }.get(shape['type'], unknown)(shape) if l2 != None: l.append(l2) self.data = l self.name = name return name
def export_footprint(self, interim): # make a deep copy so we can make mods without harm interim = copy.deepcopy(interim) interim = self.add_ats_to_names(interim) meta = inter.get_meta(interim) name = eget(meta, 'name', 'Name not found') # make name eagle compatible name = re.sub(' ','_',name) # check if there is an existing package # and if so, replace it packages = self.soup.eagle.drawing.packages('package') package = None for some_package in packages: if some_package['name'].lower() == name.lower(): package = some_package package.clear() break if package == None: package = self.soup.new_tag('package') self.soup.eagle.drawing.packages.append(package) package['name'] = name def pad(shape): pad = self.soup.new_tag('pad') pad['name'] = shape['name'] # don't set layer in a pad, it is implicit pad['x'] = fget(shape, 'x') pad['y'] = fget(shape, 'y') drill = fget(shape, 'drill') pad['drill'] = drill pad['rot'] = "R%d" % (fget(shape, 'rot')) r = fget(shape, 'r') shape2 = 'disc' # disc is the default if 'shape' in shape: shape2 = shape['shape'] if shape2 == 'disc': pad['shape'] = 'round' if f_neq(r, drill*1.5): pad['diameter'] = r*2 elif shape2 == 'octagon': pad['shape'] = 'octagon' if f_neq(r, drill*1.5): pad['diameter'] = r*2 elif shape2 == 'rect': ro = iget(shape, 'ro') if ro == 0: pad['shape'] = 'square' if f_neq(shape['dx'], drill*1.5): pad['diameter'] = float(shape['dx']) elif 'drill_dx' in shape: pad['shape'] = 'offset' if f_neq(shape['dy'], drill*1.5): pad['diameter'] = float(shape['dy']) else: pad['shape'] = 'long' if f_neq(shape['dy'], drill*1.5): pad['diameter'] = float(shape['dy']) package.append(pad) def smd(shape): smd = self.soup.new_tag('smd') smd['name'] = shape['name'] smd['x'] = fget(shape, 'x') smd['y'] = fget(shape, 'y') smd['dx'] = fget(shape, 'dx') smd['dy'] = fget(shape, 'dy') smd['roundness'] = iget(shape, 'ro') smd['rot'] = "R%d" % (fget(shape, 'rot')) smd['layer'] = type_to_layer_number('smd') package.append(smd) def rect(shape, layer): rect = self.soup.new_tag('rectangle') x = fget(shape, 'x') y = fget(shape, 'y') dx = fget(shape, 'dx') dy = fget(shape, 'dy') rect['x1'] = x - dx/2 rect['x2'] = x + dx/2 rect['y1'] = y - dy/2 rect['y2'] = y + dy/2 rect['rot'] = "R%d" % (fget(shape, 'rot')) rect['layer'] = layer package.append(rect) def label(shape, layer): label = self.soup.new_tag('text') x = fget(shape,'x') y = fget(shape,'y') dy = fget(shape,'dy', 1) s = shape['value'] if s.upper() == "NAME": s = ">NAME" layer = type_to_layer_number('name') if s.upper() == "VALUE": s = ">VALUE" layer = type_to_layer_number('value') label['x'] = x label['y'] = y label['size'] = dy label['layer'] = layer label['align'] = 'center' label.string = s package.append(label) def disc(shape, layer): r = fget(shape, 'r') rx = fget(shape, 'rx', r) ry = fget(shape, 'ry', r) x = fget(shape,'x') y = fget(shape,'y') # a disc is just a circle with a # clever radius and width disc = self.soup.new_tag('circle') disc['x'] = x disc['y'] = y disc['radius'] = r/2 disc['width'] = r/2 disc['layer'] = layer package.append(disc) def circle(shape, layer): r = fget(shape, 'r') rx = fget(shape, 'rx', r) ry = fget(shape, 'ry', r) x = fget(shape,'x') y = fget(shape,'y') w = fget(shape,'w') circle = self.soup.new_tag('circle') circle['x'] = x circle['y'] = y circle['radius'] = r circle['width'] = w circle['layer'] = layer package.append(circle) def line(shape, layer): x1 = fget(shape, 'x1') y1 = fget(shape, 'y1') x2 = fget(shape, 'x2') y2 = fget(shape, 'y2') w = fget(shape, 'w') line = self.soup.new_tag('wire') line['x1'] = x1 line['y1'] = y1 line['x2'] = x2 line['y2'] = y2 line['width'] = w line['layer'] = layer package.append(line) def silk(shape): if not 'shape' in shape: return layer = type_to_layer_number(shape['type']) s = shape['shape'] if s == 'line': line(shape, layer) elif s == 'circle': circle(shape, layer) elif s == 'disc': disc(shape, layer) elif s == 'label': label(shape, layer) elif s == 'rect': rect(shape, layer) def unknown(shape): pass idx = eget(meta, 'id', 'Id not found') desc = oget(meta, 'desc', '') parent_idx = oget(meta, 'parent', None) description = self.soup.new_tag('description') package.append(description) parent_str = "" if parent_idx != None: parent_str = " parent: %s" % parent_idx description.string = desc + "\n<br/><br/>\nGenerated by 'madparts'.<br/>\nId: " + idx +"\n" + parent_str # TODO rework to be shape+type based ? for shape in interim: if 'type' in shape: { 'pad': pad, 'silk': silk, 'docu': silk, 'keepout': silk, 'stop': silk, 'restrict': silk, 'vrestrict': silk, 'smd': smd, }.get(shape['type'], unknown)(shape) return name
def export_footprint(self, interim, timestamp=None): if timestamp is None: timestamp = time.time() meta = inter.get_meta(interim) name = eget(meta, 'name', 'Name not found') # make name kicad compatible name = re.sub(' ', '_', name) self.name = name desc = oget(meta, 'desc', '') parent_idx = oget(meta, 'parent', None) d = [] # generate kicad-old for individual footprint # use metric; convert to imperial in "save" if needed d.append("$MODULE %s" % (name)) d.append("Po 0 0 0 15 %x 00000000 ~~" % timestamp) d.append("Li %s" % (name)) d.append("Cd %s" % (desc.replace('\n', ' '))) # ugly # assuming Kw is optional d.append("Sc 0") # d.append("AR ") assume AR is optional d.append("Op 0 0 0") # if no T0 or T1 are specified, kicad defaults to this: # right now I'm assuming this is optional # T0 0 0 1.524 1.524 0 0.15 N V 21 N "" # T1 0 0 1.524 1.524 0 0.15 N V 21 N "" def pad(shape, smd=False): l = ['$PAD'] # Sh "<pad name>" shape Xsize Ysize Xdelta Ydelta Orientation # octagons are not supported by kicad if shape['shape'] == 'disc' or shape['shape'] == 'octagon': sh = 'C' dx = shape['r'] * 2 dy = dx elif shape['shape'] == 'rect': dx = shape['dx'] dy = shape['dy'] sh = 'R' # any rect with roundness >= 50 is considered kicad 'oblong' if 'ro' in shape: if shape['ro'] >= 50: sh = 'O' rot = fget(shape, 'rot') * 10 l.append("Sh \"%s\" %s %s %s %s %s %s" % (shape['name'], sh, dx, dy, 0, 0, rot)) # Dr <Pad drill> Xoffset Yoffset (round hole) if not smd: l.append("Dr %s %s %s" % (fget(shape, 'drill'), fget(shape, 'drill_off_dx'), fc(-fget(shape, 'drill_off_dy')))) # Po <x> <y> l.append("Po %s %s" % (fget(shape, 'x'), fc(-fget(shape, 'y')))) # At <Pad type> N <layer mask> t = 'STD' layer_mask = '00E0FFFF' if smd: t = 'SMD' layer_mask = '00888000' l.append("At %s N %s" % (t, layer_mask)) l.append('Ne 0 ""') l.append("$ENDPAD") return l # DS Xstart Ystart Xend Yend Width Layer # DS 6000 1500 6000 -1500 120 21 # DA Xcentre Ycentre Xstart_point Ystart_point angle width layer def vertex(shape, layer): l = [] x1 = fget(shape, 'x1') y1 = fget(shape, 'y1') x2 = fget(shape, 'x2') y2 = fget(shape, 'y2') w = fget(shape, 'w') if not 'curve' in shape or shape['curve'] == 0.0: line = "DS %s %s %s %s %s %s" % (x1, fc(-y1), x2, fc(-y2), w, layer) l.append(line) else: curve = fget(shape, 'curve') angle = curve * math.pi / 180.0 ((x0, y0), r, a1, a2) = mutil.calc_center_r_a1_a2( (x1, y1), (x2, y2), angle) arc = "DA %f %f %f %f %s %s %s" % ( x0, fc(-y0), x1, fc(-y1), int(round( (-10.0) * (a2 - a1))), w, layer) l.append(arc) return l # DC Xcentre Ycentre Xpoint Ypoint Width Layer def circle(shape, layer): l = [] x = fget(shape, 'x') y = fget(shape, 'y') r = fget(shape, 'r') w = fget(shape, 'w') if not 'a1' in shape and not 'a2' in shape: circle = "DC %s %s %s %s %s %s" % ( x, fc(-y), fc(x + (r / math.sqrt(2))), fc(-y + (r / math.sqrt(2))), w, layer) l.append(circle) else: # start == center point # end == start point of arc # angle == angled part in that direction a1 = fget(shape, 'a1') a2 = fget(shape, 'a2') a1rad = a1 * math.pi / 180.0 ex = x + r * math.cos(a1rad) ey = y + r * math.sin(a1rad) arc = "DA %f %f %f %f %s %s %s" % (x, fc(-y), ex, fc(-ey), int(round( (-10) * (a2 - a1))), w, layer) l.append(arc) return l def disc(shape, layer): l = [] x = fget(shape, 'x') y = -fget(shape, 'y') r = fget(shape, 'r') rad = r / 2 ex = x + (rad / math.sqrt(2)) ey = y + (rad / math.sqrt(2)) circle = "DC %s %s %s %s %s %s" % (x, fc(y), fc(ex), fc(ey), rad, layer) l.append(circle) return l def hole(shape): layer = type_to_num(shape['type']) shape['r'] = shape['drill'] / 2 return circle(shape, layer) # T0 -79 -3307 600 600 0 120 N V 21 N "XT" def label(shape, layer): s = shape['value'].upper() t = 'T2' visible = 'V' if s == 'VALUE': t = 'T1' visible = 'I' if s == 'NAME': t = 'T0' dy = fget(shape, 'dy', 1 / 1.6) w = fget(shape, 'w', 0.1) x = fget(shape, 'x') y = fc(-fget(shape, 'y')) # T0 -7 -3 60 60 0 10 N V 21 N "XT" line = "%s %s %s %s %s 0 %s N %s %s N \"%s\"" % ( t, x, y, dy, dy, w, visible, layer, shape['value']) return [line] def rect(shape, layer): print "rect", shape, layer l = [] w = fget(shape, 'w') rot = abs(fget(shape, 'rot')) l.append("DP 0 0 0 0 %s %s %s" % (5, w, layer)) x = fget(shape, 'x') y = -fget(shape, 'y') dx = fget(shape, 'dx') dy = fget(shape, 'dy') if rot == 90 or rot == 270: (dx, dy) = (dy, dx) def add(x1, y1): l.append("Dl %f %f" % (fc(x1), fc(y1))) add(x - dx / 2, y - dy / 2) add(x - dx / 2, y + dy / 2) add(x + dx / 2, y + dy / 2) add(x + dx / 2, y - dy / 2) add(x - dx / 2, y - dy / 2) return l # DP 0 0 0 0 corners_count width layer # DP 0 0 0 0 5 0.1 24 # Dl corner_posx corner_posy # Dl 0 -1 def polygon(shape, layer): l = [] n = len(shape['v']) w = shape['w'] l.append("DP 0 0 0 0 %s %s %s" % (n + 1, w, layer)) for v in shape['v']: l.append("Dl %g %g" % (fc(v['x1']), fc(-v['y1']))) l.append("Dl %g %g" % (fc(shape['v'][0]['x1']), fc(-shape['v'][0]['y1']))) return l def silk(shape): if not 'shape' in shape: return None layer = type_to_num(shape['type']) s = shape['shape'] if s == 'line': return vertex(shape, layer) if s == 'vertex': return vertex(shape, layer) elif s == 'circle': return circle(shape, layer) elif s == 'disc': return disc(shape, layer) elif s == 'label': return label(shape, layer) elif s == 'rect': return rect(shape, layer) elif s == 'polygon': return polygon(shape, layer) def unknown(shape): return None for shape in interim: if 'type' in shape: l = { 'pad': pad, 'cu': silk, 'silk': silk, 'docu': silk, 'keepout': unknown, 'stop': silk, 'glue': silk, 'restrict': unknown, 'vrestrict': unknown, 'smd': lambda s: pad(s, smd=True), 'hole': hole, }.get(shape['type'], unknown)(shape) if l != None: d += l d.append("$EndMODULE %s" % (name)) self.data = d return name
def export_footprint(self, interim): # make a deep copy so we can make mods without harm interim = copy.deepcopy(interim) interim = self.add_ats_to_names(interim) interim = clean_floats(interim) meta = inter.get_meta(interim) name = eget(meta, 'name', 'Name not found') # make name eagle compatible name = re.sub(' ','_',name) # check if there is an existing package # and if so, replace it packages = self.soup.eagle.drawing.packages('package') package = None for some_package in packages: if some_package['name'].lower() == name.lower(): package = some_package package.clear() break if package == None: package = self.soup.new_tag('package') self.soup.eagle.drawing.packages.append(package) package['name'] = name def pad(shape): pad = self.soup.new_tag('pad') pad['name'] = shape['name'] # don't set layer in a pad, it is implicit pad['x'] = fget(shape, 'x') pad['y'] = fget(shape, 'y') drill = fget(shape, 'drill') pad['drill'] = drill pad['rot'] = "R%d" % (fget(shape, 'rot')) r = fget(shape, 'r') shape2 = 'disc' # disc is the default if 'shape' in shape: shape2 = shape['shape'] if shape2 == 'disc': pad['shape'] = 'round' if f_neq(r, drill*1.5): pad['diameter'] = r*2 elif shape2 == 'octagon': pad['shape'] = 'octagon' if f_neq(r, drill*1.5): pad['diameter'] = r*2 elif shape2 == 'rect': ro = iget(shape, 'ro') if ro == 0: pad['shape'] = 'square' if f_neq(shape['dx'], drill*1.5): pad['diameter'] = float(shape['dx']) elif 'drill_off_dx' in shape: pad['shape'] = 'offset' if f_neq(shape['dy'], drill*1.5): pad['diameter'] = float(shape['dy']) else: pad['shape'] = 'long' if f_neq(shape['dy'], drill*1.5): pad['diameter'] = float(shape['dy']) package.append(pad) def smd(shape): smd = self.soup.new_tag('smd') smd['name'] = shape['name'] smd['x'] = fget(shape, 'x') smd['y'] = fget(shape, 'y') smd['dx'] = fget(shape, 'dx') smd['dy'] = fget(shape, 'dy') smd['roundness'] = iget(shape, 'ro') smd['rot'] = "R%d" % (fget(shape, 'rot')) smd['layer'] = type_to_layer_number('smd') package.append(smd) def hole(shape): hole = self.soup.new_tag('hole') hole['drill'] = fget(shape, 'drill') hole['x'] = fget(shape, 'x') hole['y'] = fget(shape, 'y') package.append(hole) def rect(shape, layer): rect = self.soup.new_tag('rectangle') x = fget(shape, 'x') y = fget(shape, 'y') dx = fget(shape, 'dx') dy = fget(shape, 'dy') rect['x1'] = x - dx/2 rect['x2'] = x + dx/2 rect['y1'] = y - dy/2 rect['y2'] = y + dy/2 rect['rot'] = "R%d" % (fget(shape, 'rot')) rect['layer'] = layer package.append(rect) def label(shape, layer): label = self.soup.new_tag('text') x = fget(shape,'x') y = fget(shape,'y') dy = fget(shape,'dy', 1) s = shape['value'].upper() if s == "NAME": s = ">NAME" layer = type_to_layer_number('name') if s == "VALUE": s = ">VALUE" layer = type_to_layer_number('value') label['x'] = x label['y'] = y label['size'] = dy label['layer'] = layer label['align'] = 'center' label.string = s package.append(label) # a disc is just a circle with a clever radius and width def disc(shape, layer): r = fget(shape, 'r') rx = fget(shape, 'rx', r) ry = fget(shape, 'ry', r) x = fget(shape,'x') y = fget(shape,'y') disc = self.soup.new_tag('circle') disc['x'] = x disc['y'] = y disc['radius'] = r/2 disc['width'] = r/2 disc['layer'] = layer package.append(disc) def circle(shape, layer): r = fget(shape, 'r') rx = fget(shape, 'rx', r) ry = fget(shape, 'ry', r) x = fget(shape,'x') y = fget(shape,'y') w = fget(shape,'w') if 'a1' in shape or 'a2' in shape: wire = self.soup.new_tag('wire') a1 = fget(shape, 'a1') a2 = fget(shape, 'a2') wire['width'] = w wire['curve'] = a2-a1 a1 = a1 * math.pi / 180 a2 = a2 * math.pi / 180 wire['x1'] = x + r * math.cos(a1) wire['y1'] = y + r * math.sin(a1) wire['x2'] = x + r * math.cos(a2) wire['y2'] = y + r * math.sin(a2) wire['layer'] = layer package.append(wire) else: circle = self.soup.new_tag('circle') circle['x'] = x circle['y'] = y circle['radius'] = r circle['width'] = w circle['layer'] = layer package.append(circle) def line(shape, layer): x1 = fget(shape, 'x1') y1 = fget(shape, 'y1') x2 = fget(shape, 'x2') y2 = fget(shape, 'y2') w = fget(shape, 'w') line = self.soup.new_tag('wire') line['x1'] = x1 line['y1'] = y1 line['x2'] = x2 line['y2'] = y2 line['width'] = w line['layer'] = layer if 'curve' in shape: if shape['curve'] != 0.0: line['curve'] = fget(shape, 'curve') package.append(line) # eagle polygon format is somewhat wierd # each vertex is actually a starting point towards the next # where the last one is a starting point around towards the first # <polygon width="0.127" layer="21"> # <vertex x="-1" y="-1"/> # <vertex x="-1" y="1"/> # <vertex x="0" y="1" curve="-90"/> # <vertex x="1" y="0" curve="-90"/> # <vertex x="0" y="-1"/> # </polygon> def polygon(shape, layer): p = self.soup.new_tag('polygon') p['width'] = fget(shape, 'w') p['layer'] = layer for v in shape['v']: vert = self.soup.new_tag('vertex') vert['x'] = fget(v, 'x1') vert['y'] = fget(v, 'y1') curve = fget(v, 'curve') if curve != 0.0: vert['curve'] = fget(v, 'curve') p.append(vert) package.append(p) def silk(shape): if not 'shape' in shape: return layer = type_to_layer_number(shape['type']) s = shape['shape'] if s == 'line' or s == 'vertex': line(shape, layer) elif s == 'circle': circle(shape, layer) elif s == 'disc': disc(shape, layer) elif s == 'label': label(shape, layer) elif s == 'rect': rect(shape, layer) elif s == 'polygon': polygon(shape, layer) def unknown(shape): pass desc = oget(meta, 'desc', '') parent_idx = oget(meta, 'parent', None) description = self.soup.new_tag('description') package.append(description) description.string = desc + "\n<br/><br/>\nGenerated by 'madparts'.<br/>\n" # TODO rework to be shape+type based ? for shape in interim: if 'type' in shape: { 'pad': pad, 'silk': silk, 'cu': silk, 'docu': silk, 'keepout': silk, 'stop': silk, 'restrict': silk, 'vrestrict': silk, 'smd': smd, 'hole': hole, }.get(shape['type'], unknown)(shape) return name
def export_footprint(self, interim): meta = inter.get_meta(interim) name = eget(meta, 'name', 'Name not found') idx = eget(meta, 'id', 'Id not found') descr = oget(meta, 'desc', '') parent_idx = oget(meta, 'parent', None) l = [ S('module'), S(name), [S('layer'), S('F.Cu')], [S('descr'), descr], ] def pad(shape, smd=False): l = [S('pad'), S(shape['name'])] if smd: l.append(S('smd')) else: l.append(S('thru_hole')) shape2 = 'disc' # disc is the default if 'shape' in shape: shape2 = shape['shape'] r = fget(shape, 'r') if shape2 == 'disc': l.append(S('circle')) l.append([S('size'), r, r]) elif shape2 == 'rect': ro = iget(shape, 'ro') if ro == 0: l.append(S('rect')) else: l.append(S('oval')) l.append([S('size'), fget(shape, 'dx'), fget(shape, 'dy')]) else: raise Exception("%s shaped pad not supported in kicad" % (shape2)) l.append([S('at'), fget(shape, 'x'), -fget(shape, 'y'), iget(shape, 'rot')]) if smd: l.append([S('layers'), S('F.Cu'), S('F.Paste'), S('F.Mask')]) else: l.append([S('layers'), S('*.Cu'), S('*.Mask')]) if not smd: l2 = [S('drill'), fget(shape, 'drill')] if 'drill_dx' in shape or 'drill_dy' in shape: l2.append([S('offset'), fget(shape, 'drill_dx'), fget(shape, 'drill_dy')]) l.append(l2) return l #(fp_line (start -2.54 -1.27) (end 2.54 -1.27) (layer F.SilkS) (width 0.381)) def line(shape, layer): l = [S('fp_line')] l.append([S('start'), fget(shape, 'x1'), -fget(shape, 'y1')]) l.append([S('end'), fget(shape, 'x2'), -fget(shape, 'y2')]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) return l # (fp_circle (center 5.08 0) (end 6.35 -1.27) (layer F.SilkS) (width 0.15)) def circle(shape, layer): l = [S('fp_circle')] x = fget(shape, 'x') y = -fget(shape, 'y') l.append([S('center'), x, y]) r = fget(shape, 'r') l.append([S('end'), x+(r/math.sqrt(2)), y+(r/math.sqrt(2))]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) return l # a disc is just a circle with a clever radius and width def disc(shape, layer): l = [S('fp_circle')] x = fget(shape, 'x') y = -fget(shape, 'y') l.append([S('center'), x, y]) r = fget(shape, 'r') rad = r/2 l.append([S('end'), x+(rad/math.sqrt(2)), y+(rad/math.sqrt(2))]) l.append([S('layer'), S(layer)]) l.append([S('width'), rad]) return l # (fp_arc (start 7.62 0) (end 7.62 -2.54) (angle 90) (layer F.SilkS) (width 0.15)) def arc(shape, layer): l = [S('fp_arc')] l.append([S('start'), fget(shape, 'x1'), -fget(shape, 'y1')]) l.append([S('end'), fget(shape, 'x2'), -fget(shape, 'y2')]) l.append([S('angle'), fget(shape, 'a')]) l.append([S('layer'), S(layer)]) l.append([S('w'), fget(shape, 'w')]) return l # (pad "" smd rect (at 1.27 0) (size 0.39878 0.8001) (layers F.SilkS)) def rect(shape, layer): # TODO: Don't do this with a pad. Use a polygon l = [S('pad'), "", S('smd'), S('rect')] l.append([S('at'), fget(shape, 'x'), -fget(shape, 'y'), iget(shape, 'rot')]) l.append([S('size'), fget(shape, 'dx'), fget(shape, 'dy')]) l.append([S('layers'), S(layer)]) return l # (fp_text reference MYCONN3 (at 0 -2.54) (layer F.SilkS) # (effects (font (size 1.00076 1.00076) (thickness 0.25146))) # ) # (fp_text value SMD (at 0 2.54) (layer F.SilkS) hide # (effects (font (size 1.00076 1.00076) (thickness 0.25146))) # ) def label(shape, layer): s = shape['value'].upper() t = 'user' if s == 'VALUE': t = 'value' if s == 'NAME': t = 'reference' l = [S('fp_text'), S(t), S(shape['value'])] if (('rot' in shape) and (fget(shape, 'rot') != 0.0)): l.append([S('at'), fget(shape, 'x'), -fget(shape, 'y'), fget(shape, 'rot')]) else: l.append([S('at'), fget(shape, 'x'), -fget(shape, 'y')]) l.append([S('layer'), S(layer)]) if s == 'VALUE': l.append(S('hide')) dy = fget(shape, 'dy', 1/1.6) th = fget(shape, 'w', 0.1) l.append([S('effects'), [S('font'), [S('size'), dy, dy], [S('thickness'), th]]]) return l def silk(shape): if not 'shape' in shape: return None layer = type_to_layer_name(shape['type']) s = shape['shape'] if s == 'line': return line(shape, layer) elif s == 'arc': return arc(shape, layer) elif s == 'circle': return circle(shape, layer) elif s == 'disc': return disc(shape, layer) elif s == 'label': return label(shape, layer) elif s == 'rect': return rect(shape, layer) def unknown(shape): return None for shape in interim: if 'type' in shape: l2 = { 'pad': pad, 'silk': silk, 'docu': silk, 'keepout': unknown, 'stop': silk, 'glue': silk, 'restrict': unknown, 'vrestrict': unknown, 'smd': lambda s: pad(s, smd=True), }.get(shape['type'], unknown)(shape) if l2 != None: l.append(l2) self.data = l self.name = name return name
def export_footprint(self, interim): meta = inter.get_meta(interim) name = eget(meta, 'name', 'Name not found') descr = oget(meta, 'desc', '') parent_idx = oget(meta, 'parent', None) l = [ S('module'), name, [S('layer'), S('F.Cu')], [S('descr'), descr], ] def pad_line(x1,y1,x2,y2,width,layer): l = [S('fp_line')] l.append([S('start'), x1,y1]) l.append([S('end'), x2,y2]) l.append([S('layer'), S(layer)]) l.append([S('width'), width]) return l def pad_lines(s,x1,y1,x2,y2,width): s.append(pad_line(x1,y1,x2,y2,width,'F.Cu')) s.append(pad_line(x1,y1,x2,y2,width,'F.Paste')) s.append(pad_line(x1,y1,x2,y2,width,'F.Mask')) def gen_lines(l,x,y,rot,radius,dx,dy): # 4 corners xo = dx/2 - radius yo = dy/2 - radius rot = math.radians(rot) xp = math.cos(rot)*xo - math.sin(rot)*yo yp = math.cos(rot)*yo + math.sin(rot)*xo x1 = x - xp x2 = x + xp y1 = y - yp y2 = y + yp pad_lines(l,x1,y1,x2,y1,radius*2) pad_lines(l,x2,y1,x2,y2,radius*2) pad_lines(l,x2,y2,x1,y2,radius*2) pad_lines(l,x1,y2,x1,y1,radius*2) def pad(shape, smd=False): want_paste = True if 'paste' in shape: want_paste = shape['paste'] if 'name' in shape: name = shape['name'] if name is None or name == "": name = "" else: name = S(name) else: name = "" l = [S('pad'), name] shapes = [l] if smd: l.append(S('smd')) else: l.append(S('thru_hole')) shape2 = 'disc' # disc is the default if 'shape' in shape: shape2 = shape['shape'] r = fget(shape, 'r') if shape2 == 'disc': l.append(S('circle')) l.append([S('size'), r*2, r*2]) elif shape2 == 'rect': ro = iget(shape, 'ro') dx = fget(shape, 'dx') dy = fget(shape, 'dy') if ro == 100: l.append(S('oval')) l.append([S('size'), dx, dy]) else: l.append(S('rect')) if ro == 0: l.append([S('size'), dx, dy]) else: #find the smallest dimension and create a rectangular pad squished by that amount #TODO: the rectangular pad is simple with 4 lines, 1 rect and guaranteed no holes #however it can create arbitrarily small pad which will make text in kicad hard to #read. may be better to use a oval pad, which can be not shrunk and is still guaranteed #to not overrun the pad, however it is tricky to make sure the 4 lines don't create any holes. small = dx if dy < dx : small = dy radius = small/2 * ro / 100.0; l.append([S('size'), dx-radius*2, dy-radius*2]) gen_lines(shapes, fget(shape, 'x'), -fget(shape, 'y'), iget(shape, 'rot'), radius, dx, dy) else: raise Exception("%s shaped pad not supported in kicad" % (shape2)) l.append([S('at'), fget(shape, 'x'), -fget(shape, 'y'), iget(shape, 'rot')]) if smd: if shape['type'] != 'smd': l.append([S('layers'), S('F.Paste')]) else: if want_paste: l.append([S('layers'), S('F.Cu'), S('F.Paste'), S('F.Mask')]) else: l.append([S('layers'), S('F.Cu'), S('F.Mask')]) else: l.append([S('layers'), S('*.Cu'), S('*.Mask')]) if not smd: if 'drill_dx' in shape or 'drill_dy' in shape: drill_dx = fget(shape, 'drill_dx') drill_dy = fget(shape, 'drill_dy') l2 = [S('drill'), S('oval'), drill_dx, drill_dy] else: l2 = [S('drill'), fget(shape, 'drill')] if 'drill_off_dx' in shape or 'drill_off_dy' in shape: l2.append([S('offset'), fget(shape, 'drill_off_dx'), fget(shape, 'drill_off_dy')]) l.append(l2) l.append([S('solder_mask_margin'), fget(shape, 'mask_swell')]) l.append([S('solder_paste_margin_ratio'), fget(shape, 'paste_ratio')]) return shapes #(fp_line (start -2.54 -1.27) (end 2.54 -1.27) (layer F.SilkS) (width 0.381)) # (fp_arc (start 7.62 0) (end 7.62 -2.54) (angle 90) (layer F.SilkS) (width 0.15)) def vertex(shape, layer): if not 'curve' in shape or shape['curve'] == 0.0: l = [S('fp_line')] l.append([S('start'), fget(shape, 'x1'), -fget(shape, 'y1')]) l.append([S('end'), fget(shape, 'x2'), -fget(shape, 'y2')]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) else: l = [S('fp_arc')] # start == center point # end == start point of arc # angle == angled part in that direction x1 = fget(shape, 'x1') y1 = fget(shape, 'y1') x2 = fget(shape, 'x2') y2 = fget(shape, 'y2') curve = fget(shape, 'curve') angle = curve*math.pi/180.0 ((x0, y0), r, a1, a2) = calc_center_r_a1_a2((x1,y1),(x2,y2),angle) l.append([S('start'), fc(x0), fc(-y0)]) l.append([S('end'), fc(x1), fc(-y1)]) # also invert angle because of y inversion l.append([S('angle'), -(a2-a1)]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) return [l] # (fp_circle (center 5.08 0) (end 6.35 -1.27) (layer F.SilkS) (width 0.15)) def circle(shape, layer): x = fget(shape, 'x') y = -fget(shape, 'y') r = fget(shape, 'r') if not 'a1' in shape and not 'a2' in shape: l = [S('fp_circle')] l.append([S('center'),fc(x),fc(y)]) l.append([S('end'), fc(x+(r/math.sqrt(2))), fc(y+(r/math.sqrt(2)))]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) else: l = [S('fp_arc')] l.append([S('start'),fc(x),fc(y)]) # start == center point # end == start point of arc # angle == angled part in that direction a1 = fget(shape, 'a1') a2 = fget(shape, 'a2') a1rad = a1 * math.pi/180.0 ex = x + r*math.cos(a1rad) ey = y + r*math.sin(a1rad) l.append([S('end'), fc(ex), fc(-ey)]) l.append([S('angle'), -(a2-a1)]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) return [l] # a disc is just a circle with a clever radius and width def disc(shape, layer): l = [S('fp_circle')] x = fget(shape, 'x') y = -fget(shape, 'y') l.append([S('center'), fc(x), fc(y)]) r = fget(shape, 'r') rad = r/2 l.append([S('end'), x+(rad/math.sqrt(2)), y+(rad/math.sqrt(2))]) l.append([S('layer'), S(layer)]) l.append([S('width'), rad]) return [l] def hole(shape): l = [S('pad'), ""] l.append(S('np_thru_hole')) l.append(S('circle')) l.append([S('at'), fget(shape, 'x'), -fget(shape, 'y')]) drill = fget(shape, 'drill') l.append([S('size'), drill, drill]) l.append([S('drill'), drill]) l.append([S('layers'), S('*.Cu'), S('*.Mask'), S('F.SilkS')]) return [l] # (fp_poly (pts (xy 6.7818 1.6002) (xy 6.6294 1.6002) (xy 6.6294 1.4478) (xy 6.7818 1.4478) (xy 6.7818 1.6002)) (layer F.Cu) (width 0.00254)) # kicad doesn't do arced vertex in polygon :( def polygon(shape, layer): l = [S('fp_poly')] lxy = [S('pts')] for v in shape['v']: xy = [S('xy'), fc(v['x1']), fc(-v['y1'])] lxy.append(xy) xy = [S('xy'), fc(shape['v'][0]['x1']), fc(-shape['v'][0]['y1'])] lxy.append(xy) l.append(lxy) l.append([S('layer'), S(layer)]) l.append([S('width'), shape['w']]) return [l] def rect(shape, layer): l = [S('fp_poly')] x = fget(shape, 'x') y = - fget(shape, 'y') dx = fget(shape, 'dx') dy = fget(shape, 'dy') rot = fget(shape, 'rot') if rot == 90 or rot == 270: (dx, dy) = (dy, dx) lxy = [S('pts')] def add(x1, y1): lxy.append([S('xy'), fc(x1), fc(y1)]) add(x - dx/2, y - dy/2) add(x - dx/2, y + dy/2) add(x + dx/2, y + dy/2) add(x + dx/2, y - dy/2) add(x - dx/2, y - dy/2) l.append(lxy) l.append([S('layer'), S(layer)]) l.append([S('width'), 0]) return [l] # (fp_text reference MYCONN3 (at 0 -2.54) (layer F.SilkS) # (effects (font (size 1.00076 1.00076) (thickness 0.25146))) # ) # (fp_text value SMD (at 0 2.54) (layer F.SilkS) hide # (effects (font (size 1.00076 1.00076) (thickness 0.25146))) # ) def label(shape, layer): s = shape['value'].upper() t = "user" if s == "VALUE": t = "value" l = [S('fp_text'), S(t), 'VAL**'] elif s == "NAME": t = "reference" l = [S('fp_text'), S(t), 'REF**'] else: l = [S('fp_text'), S(t), shape['value']] if (('rot' in shape) and (fget(shape, 'rot') != 0.0)): l.append([S('at'), fget(shape, 'x'), fc(-fget(shape, 'y')), fget(shape, 'rot')]) else: l.append([S('at'), fget(shape, 'x'), fc(-fget(shape, 'y'))]) l.append([S('layer'), S(layer)]) if s == 'VALUE': l.append(S('hide')) dy = fget(shape, 'dy', 1/1.6) th = fget(shape, 'w', 0.1) l.append([S('effects'), [S('font'), [S('size'), dy, dy], [S('thickness'), th]]]) return [l] def silk(shape): if not 'shape' in shape: return None layer = type_to_layer_name(shape['type']) s = shape['shape'] if s == 'line': return vertex(shape, layer) if s == 'vertex': return vertex(shape, layer) elif s == 'circle': return circle(shape, layer) elif s == 'disc': return disc(shape, layer) elif s == 'label': return label(shape, layer) elif s == 'rect': return rect(shape, layer) elif s == 'polygon': return polygon(shape, layer) def unknown(shape): return None for shape in interim: if 'type' in shape: l2 = { 'pad': pad, 'cu': silk, 'silk': silk, 'bsilk': silk, 'docu': silk, 'keepout': silk, 'bkeepout': silk, 'stop': silk, 'bstop': silk, 'glue': silk, 'paste': silk, 'bpaste': silk, 'restrict': unknown, 'vrestrict': unknown, 'comments': silk, 'user1': silk, 'user2': silk, 'margin': silk, 'assembly': silk, 'bassembly': silk, 'smd': lambda s: pad(s, smd=True), 'hole': hole, 'edge': silk, }.get(shape['type'], unknown)(shape) if l2 != None: l.extend(l2) self.data = l self.name = name return name
def export_footprint(self, interim): meta = inter.get_meta(interim) name = eget(meta, 'name', 'Name not found') idx = eget(meta, 'id', 'Id not found') descr = oget(meta, 'desc', '') parent_idx = oget(meta, 'parent', None) l = [ S('module'), name, [S('layer'), S('F.Cu')], [S('descr'), descr], ] def pad(shape, smd=False): l = [S('pad'), S(shape['name'])] if smd: l.append(S('smd')) else: l.append(S('thru_hole')) shape2 = 'disc' # disc is the default if 'shape' in shape: shape2 = shape['shape'] r = fget(shape, 'r') if shape2 == 'disc': l.append(S('circle')) l.append([S('size'), r * 2, r * 2]) elif shape2 == 'rect': ro = iget(shape, 'ro') if ro == 0: l.append(S('rect')) else: l.append(S('oval')) l.append([S('size'), fget(shape, 'dx'), fget(shape, 'dy')]) else: raise Exception("%s shaped pad not supported in kicad" % (shape2)) l.append([ S('at'), fget(shape, 'x'), -fget(shape, 'y'), iget(shape, 'rot') ]) if smd: l.append([S('layers'), S('F.Cu'), S('F.Paste'), S('F.Mask')]) else: l.append([S('layers'), S('*.Cu'), S('*.Mask')]) if not smd: l2 = [S('drill'), fget(shape, 'drill')] if 'drill_dx' in shape or 'drill_dy' in shape: l2.append([ S('offset'), fget(shape, 'drill_dx'), fget(shape, 'drill_dy') ]) l.append(l2) return l #(fp_line (start -2.54 -1.27) (end 2.54 -1.27) (layer F.SilkS) (width 0.381)) # (fp_arc (start 7.62 0) (end 7.62 -2.54) (angle 90) (layer F.SilkS) (width 0.15)) def vertex(shape, layer): if not 'curve' in shape or shape['curve'] == 0.0: l = [S('fp_line')] l.append([S('start'), fget(shape, 'x1'), -fget(shape, 'y1')]) l.append([S('end'), fget(shape, 'x2'), -fget(shape, 'y2')]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) else: l = [S('fp_arc')] # start == center point # end == start point of arc # angle == angled part in that direction x1 = fget(shape, 'x1') y1 = fget(shape, 'y1') x2 = fget(shape, 'x2') y2 = fget(shape, 'y2') curve = fget(shape, 'curve') angle = curve * math.pi / 180.0 ((x0, y0), r, a1, a2) = calc_center_r_a1_a2((x1, y1), (x2, y2), angle) l.append([S('start'), fc(x0), fc(-y0)]) l.append([S('end'), fc(x1), fc(-y1)]) # also invert angle because of y inversion l.append([S('angle'), -(a2 - a1)]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) return l # (fp_circle (center 5.08 0) (end 6.35 -1.27) (layer F.SilkS) (width 0.15)) def circle(shape, layer): x = fget(shape, 'x') y = -fget(shape, 'y') r = fget(shape, 'r') if not 'a1' in shape and not 'a2' in shape: l = [S('fp_circle')] l.append([S('center'), fc(x), fc(y)]) l.append([ S('end'), fc(x + (r / math.sqrt(2))), fc(y + (r / math.sqrt(2))) ]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) else: l = [S('fp_arc')] l.append([S('start'), fc(x), fc(y)]) # start == center point # end == start point of arc # angle == angled part in that direction a1 = fget(shape, 'a1') a2 = fget(shape, 'a2') a1rad = a1 * math.pi / 180.0 ex = x + r * math.cos(a1rad) ey = y + r * math.sin(a1rad) l.append([S('end'), fc(ex), fc(-ey)]) l.append([S('angle'), -(a2 - a1)]) l.append([S('layer'), S(layer)]) l.append([S('width'), fget(shape, 'w')]) return l # a disc is just a circle with a clever radius and width def disc(shape, layer): l = [S('fp_circle')] x = fget(shape, 'x') y = -fget(shape, 'y') l.append([S('center'), fc(x), fc(y)]) r = fget(shape, 'r') rad = r / 2 l.append( [S('end'), x + (rad / math.sqrt(2)), y + (rad / math.sqrt(2))]) l.append([S('layer'), S(layer)]) l.append([S('width'), rad]) return l def hole(shape): layer = type_to_layer_name(shape['type']) # aka 'hole' shape['r'] = shape['drill'] / 2 return circle(shape, layer) # (fp_poly (pts (xy 6.7818 1.6002) (xy 6.6294 1.6002) (xy 6.6294 1.4478) (xy 6.7818 1.4478) (xy 6.7818 1.6002)) (layer F.Cu) (width 0.00254)) # kicad doesn't do arced vertex in polygon :( def polygon(shape, layer): l = [S('fp_poly')] lxy = [S('pts')] for v in shape['v']: xy = [S('xy'), fc(v['x1']), fc(-v['y1'])] lxy.append(xy) xy = [S('xy'), fc(shape['v'][0]['x1']), fc(-shape['v'][0]['y1'])] lxy.append(xy) l.append(lxy) l.append([S('layer'), S(layer)]) l.append([S('width'), shape['w']]) return l def rect(shape, layer): l = [S('fp_poly')] x = fget(shape, 'x') y = -fget(shape, 'y') dx = fget(shape, 'dx') dy = fget(shape, 'dy') lxy = [S('pts')] def add(x1, y1): lxy.append([S('xy'), fc(x1), fc(y1)]) add(x - dx / 2, y - dy / 2) add(x - dx / 2, y + dy / 2) add(x + dx / 2, y + dy / 2) add(x + dx / 2, y - dy / 2) add(x - dx / 2, y - dy / 2) l.append(lxy) l.append([S('layer'), S(layer)]) l.append([S('width'), 0]) return l # (fp_text reference MYCONN3 (at 0 -2.54) (layer F.SilkS) # (effects (font (size 1.00076 1.00076) (thickness 0.25146))) # ) # (fp_text value SMD (at 0 2.54) (layer F.SilkS) hide # (effects (font (size 1.00076 1.00076) (thickness 0.25146))) # ) def label(shape, layer): s = shape['value'].upper() t = 'user' if s == 'VALUE': t = 'value' if s == 'NAME': t = 'reference' l = [S('fp_text'), S(t), S(shape['value'])] if (('rot' in shape) and (fget(shape, 'rot') != 0.0)): l.append([ S('at'), fget(shape, 'x'), fc(-fget(shape, 'y')), fget(shape, 'rot') ]) else: l.append([S('at'), fget(shape, 'x'), fc(-fget(shape, 'y'))]) l.append([S('layer'), S(layer)]) if s == 'VALUE': l.append(S('hide')) dy = fget(shape, 'dy', 1 / 1.6) th = fget(shape, 'w', 0.1) l.append([ S('effects'), [S('font'), [S('size'), dy, dy], [S('thickness'), th]] ]) return l def silk(shape): if not 'shape' in shape: return None layer = type_to_layer_name(shape['type']) s = shape['shape'] if s == 'line': return vertex(shape, layer) if s == 'vertex': return vertex(shape, layer) elif s == 'circle': return circle(shape, layer) elif s == 'disc': return disc(shape, layer) elif s == 'label': return label(shape, layer) elif s == 'rect': return rect(shape, layer) elif s == 'polygon': return polygon(shape, layer) def unknown(shape): return None for shape in interim: if 'type' in shape: l2 = { 'pad': pad, 'cu': silk, 'silk': silk, 'docu': silk, 'keepout': unknown, 'stop': silk, 'glue': silk, 'restrict': unknown, 'vrestrict': unknown, 'smd': lambda s: pad(s, smd=True), 'hole': hole, }.get(shape['type'], unknown)(shape) if l2 != None: l.append(l2) self.data = l self.name = name return name
def export_footprint(self, interim): # make a deep copy so we can make mods without harm interim = copy.deepcopy(interim) interim = self.add_ats_to_names(interim) meta = inter.get_meta(interim) name = eget(meta, 'name', 'Name not found') # make name eagle compatible name = re.sub(' ', '_', name) # check if there is an existing package # and if so, replace it packages = self.soup.eagle.drawing.packages('package') package = None for some_package in packages: if some_package['name'].lower() == name.lower(): package = some_package package.clear() break if package == None: package = self.soup.new_tag('package') self.soup.eagle.drawing.packages.append(package) package['name'] = name def pad(shape): pad = self.soup.new_tag('pad') pad['name'] = shape['name'] # don't set layer in a pad, it is implicit pad['x'] = fget(shape, 'x') pad['y'] = fget(shape, 'y') drill = fget(shape, 'drill') pad['drill'] = drill pad['rot'] = "R%d" % (fget(shape, 'rot')) r = fget(shape, 'r') shape2 = 'disc' # disc is the default if 'shape' in shape: shape2 = shape['shape'] if shape2 == 'disc': pad['shape'] = 'round' if f_neq(r, drill * 1.5): pad['diameter'] = r * 2 elif shape2 == 'octagon': pad['shape'] = 'octagon' if f_neq(r, drill * 1.5): pad['diameter'] = r * 2 elif shape2 == 'rect': ro = iget(shape, 'ro') if ro == 0: pad['shape'] = 'square' if f_neq(shape['dx'], drill * 1.5): pad['diameter'] = float(shape['dx']) elif 'drill_dx' in shape: pad['shape'] = 'offset' if f_neq(shape['dy'], drill * 1.5): pad['diameter'] = float(shape['dy']) else: pad['shape'] = 'long' if f_neq(shape['dy'], drill * 1.5): pad['diameter'] = float(shape['dy']) package.append(pad) def smd(shape): smd = self.soup.new_tag('smd') smd['name'] = shape['name'] smd['x'] = fget(shape, 'x') smd['y'] = fget(shape, 'y') smd['dx'] = fget(shape, 'dx') smd['dy'] = fget(shape, 'dy') smd['roundness'] = iget(shape, 'ro') smd['rot'] = "R%d" % (fget(shape, 'rot')) smd['layer'] = type_to_layer_number('smd') package.append(smd) def rect(shape, layer): rect = self.soup.new_tag('rectangle') x = fget(shape, 'x') y = fget(shape, 'y') dx = fget(shape, 'dx') dy = fget(shape, 'dy') rect['x1'] = x - dx / 2 rect['x2'] = x + dx / 2 rect['y1'] = y - dy / 2 rect['y2'] = y + dy / 2 rect['rot'] = "R%d" % (fget(shape, 'rot')) rect['layer'] = layer package.append(rect) def label(shape, layer): label = self.soup.new_tag('text') x = fget(shape, 'x') y = fget(shape, 'y') dy = fget(shape, 'dy', 1) s = shape['value'] if s.upper() == "NAME": s = ">NAME" layer = type_to_layer_number('name') if s.upper() == "VALUE": s = ">VALUE" layer = type_to_layer_number('value') label['x'] = x label['y'] = y label['size'] = dy label['layer'] = layer label['align'] = 'center' label.string = s package.append(label) def disc(shape, layer): r = fget(shape, 'r') rx = fget(shape, 'rx', r) ry = fget(shape, 'ry', r) x = fget(shape, 'x') y = fget(shape, 'y') # a disc is just a circle with a # clever radius and width disc = self.soup.new_tag('circle') disc['x'] = x disc['y'] = y disc['radius'] = r / 2 disc['width'] = r / 2 disc['layer'] = layer package.append(disc) def circle(shape, layer): r = fget(shape, 'r') rx = fget(shape, 'rx', r) ry = fget(shape, 'ry', r) x = fget(shape, 'x') y = fget(shape, 'y') w = fget(shape, 'w') circle = self.soup.new_tag('circle') circle['x'] = x circle['y'] = y circle['radius'] = r circle['width'] = w circle['layer'] = layer package.append(circle) def line(shape, layer): x1 = fget(shape, 'x1') y1 = fget(shape, 'y1') x2 = fget(shape, 'x2') y2 = fget(shape, 'y2') w = fget(shape, 'w') line = self.soup.new_tag('wire') line['x1'] = x1 line['y1'] = y1 line['x2'] = x2 line['y2'] = y2 line['width'] = w line['layer'] = layer package.append(line) def silk(shape): if not 'shape' in shape: return layer = type_to_layer_number(shape['type']) s = shape['shape'] if s == 'line': line(shape, layer) elif s == 'circle': circle(shape, layer) elif s == 'disc': disc(shape, layer) elif s == 'label': label(shape, layer) elif s == 'rect': rect(shape, layer) def unknown(shape): pass idx = eget(meta, 'id', 'Id not found') desc = oget(meta, 'desc', '') parent_idx = oget(meta, 'parent', None) description = self.soup.new_tag('description') package.append(description) parent_str = "" if parent_idx != None: parent_str = " parent: %s" % parent_idx description.string = desc + "\n<br/><br/>\nGenerated by 'madparts'.<br/>\nId: " + idx + "\n" + parent_str # TODO rework to be shape+type based ? for shape in interim: if 'type' in shape: { 'pad': pad, 'silk': silk, 'docu': silk, 'keepout': silk, 'stop': silk, 'restrict': silk, 'vrestrict': silk, 'smd': smd, }.get(shape['type'], unknown)(shape) return name