def getStyleString(self): return utils.dictToStyleText(self._style_dict)
def _placeDrillIndex(self): """ Adds a drill index """ # Get the drills sheet / SVG layer drill_layer = self._layers['drills']['layer'] ns = {'pcbmode':config.cfg['ns']['pcbmode'], 'svg':config.cfg['ns']['svg']} drills = drill_layer.findall(".//*[@pcbmode:diameter]", namespaces=ns) drills_dict = {} longest_text = 0 largest_drill = 0 drill_count = 0 for drill in drills: diameter = drill.get('{'+config.cfg['ns']['pcbmode']+'}diameter') diameter = round(float(diameter), 2) if diameter not in drills_dict: drills_dict[diameter] = 1 else: drills_dict[diameter] += 1 if diameter > largest_drill: largest_drill = diameter drill_count += 1 if len(str(diameter)) > longest_text: longest_text = len(str(diameter)) # Get location, or generate one try: location = config.brd['drill-index']['location'] except: # If not location is specified, put the drill index at the # bottom left of the board. The 'gap' defines the extra # spcae between the top of the largest drill and the # board's edge gap = 2 location = [-self._width/2, -(self._height/2+gap)] location = utils.toPoint(location) # Create group for placing index transform = "translate(%s,%s)" % (location.x, config.cfg['invert-y']*location.y) group = et.SubElement(drill_layer, 'g', transform=transform) group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'drill-index') text_style_dict = config.stl['layout']['drill-index'].get('text') text_style = utils.dictToStyleText(text_style_dict) count_style_dict = config.stl['layout']['drill-index'].get('count-text') count_style = utils.dictToStyleText(count_style_dict) count_style_dict['font-size'] /= 2 drill_size_style = utils.dictToStyleText(count_style_dict) if drill_count == 0: text = 'No drills' elif drill_count == 1: text = '1 drill: ' else: text = '%s drills: ' % drill_count t = et.SubElement(group, 'text', x=str(0), y=str(0), style=text_style) t.text = text # "new line" location.y = -(largest_drill/2 + 1.5) # TODO: this hack'ish thing for aligning the text isn't going # to work when the font is changed in the stylesheet if float(longest_text*0.5) > largest_drill: location.x = longest_text*0.3 else: location.x = largest_drill/2 gap = 2 for diameter in reversed(sorted(drills_dict)): path = svg.drillPath(diameter) transform = "translate(%s,%s)" % (location.x, config.cfg['invert-y']*location.y) element = et.SubElement(group, 'path', d=path, transform=transform) element.set("fill-rule", "evenodd") t = et.SubElement(group, 'text', x=str(location.x), y=str(-location.y), dy="%s" % (config.cfg['invert-y']*0.25), style=count_style) t.text = str(drills_dict[diameter]) t = et.SubElement(group, 'text', x=str(location.x), y=str(-location.y), dy="%s" % (config.cfg['invert-y']*-0.5), style=drill_size_style) t.text = "%s mm" % diameter location.x += max(diameter, 2.5)
def _placeComponents(self, components, component_type, print_refdef=False): """ """ for component in components: shapes_dict = component.getShapes() location = component.getLocation() refdef = component.getRefdef() if print_refdef == True: print refdef, # If the component is placed on the bottom layer we need # to invert the shapes AND their 'x' coordinate. This is # done using the 'invert' indicator set below placement_layer = component.getPlacementLayer() if placement_layer == 'bottom': invert = True else: invert = False for pcb_layer in utils.getSurfaceLayers(): there_are_pours = utils.checkForPoursInLayer(pcb_layer) # Copper shapes = shapes_dict['copper'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['copper']['pads'][ 'layer'] transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) if component_type == 'components': group.set( '{' + config.cfg['ns']['pcbmode'] + '}refdef', component.getRefdef()) elif component_type == 'vias': group.set('{' + config.cfg['ns']['pcbmode'] + '}type', 'via') group.set('{' + config.cfg['ns']['pcbmode'] + '}via', component.getFootprintName()) else: pass for shape in shapes: place.placeShape(shape, group, invert) if there_are_pours == True: mask_group = et.SubElement(self._masks[pcb_layer], 'g', transform=transform) self._placeMask(mask_group, shape, 'pad', original=False, mirror=invert) # Add pin labels # There's a bit of a hack here that won't work in # all possible cases (where pads are placed on # bottom layer in a component that has pins placed # both on the top and on the bottom -- a rare # case). Good enough for now labels = shapes_dict['pin-labels']['top'] #[pcb_layer] if labels != []: style = utils.dictToStyleText( config.stl['layout']['board']['pad-labels']) label_group = et.SubElement( group, 'g', transform="rotate(%s)" % (((1, -1)[invert]) * component.getRotation()), style=style) for label in labels: t = et.SubElement(label_group, 'text', x=str(((1, -1)[invert]) * label['location'][0]), y=str(config.cfg['invert-y'] * label['location'][1])) t.text = label['text'] # Soldermask shapes = shapes_dict['soldermask'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['soldermask']['layer'] transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{' + config.cfg['ns']['pcbmode'] + '}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group, invert) # Solderpaste shapes = shapes_dict['solderpaste'][pcb_layer] svg_layer = self._layers[pcb_layer]['solderpaste']['layer'] transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{' + config.cfg['ns']['pcbmode'] + '}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group, invert) # Silkscreen shapes = shapes_dict['silkscreen'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['silkscreen']['layer'] transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) shape_group = et.SubElement(svg_layer, 'g', transform=transform) shape_group.set( '{' + config.cfg['ns']['pcbmode'] + '}type', 'component-shapes') for shape in shapes: # Refdefs need to be in their own groups so that their # location can later be extracted, hence this... try: is_refdef = getattr(shape, 'is_refdef') except: is_refdef = False if is_refdef == True: refdef_group = et.SubElement(svg_layer, 'g', transform=transform) refdef_group.set( '{' + config.cfg['ns']['pcbmode'] + '}type', 'refdef') refdef_group.set( '{' + config.cfg['ns']['pcbmode'] + '}refdef', refdef) placed_element = place.placeShape( shape, refdef_group, invert) else: placed_element = place.placeShape( shape, shape_group, invert) # Assembly shapes = shapes_dict['assembly'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['assembly']['layer'] transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) for shape in shapes: placed_element = place.placeShape(shape, group, invert) # Drills shapes = shapes_dict['drills'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers['drills']['layer'] transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{' + config.cfg['ns']['pcbmode'] + '}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group, invert) placed_element.set( '{' + config.cfg['ns']['pcbmode'] + '}diameter', str(shape.getDiameter()))
def _placeComponents(self, components, component_type, print_refdef=False): """ """ for component in components: shapes_dict = component.getShapes() location = component.getLocation() # If the component is placed on the bottom layer we need # to invert the shapes AND their 'x' coordinate. This is # sone using the 'invert' indicator set below refdef = component.getRefdef() if print_refdef == True: print refdef, placement_layer = component.getPlacementLayer() if placement_layer == 'bottom': invert = True else: invert = False for pcb_layer in utils.getSurfaceLayers(): there_are_pours = utils.checkForPoursInLayer(pcb_layer) # Copper shapes = shapes_dict['copper'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['copper']['pads'][ 'layer'] transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) if component_type == 'components': group.set( '{' + config.cfg['ns']['pcbmode'] + '}refdef', component.getRefdef()) elif component_type == 'vias': group.set('{' + config.cfg['ns']['pcbmode'] + '}type', 'via') group.set('{' + config.cfg['ns']['pcbmode'] + '}via', component.getFootprintName()) else: pass for shape in shapes: place.placeShape(shape, group) if there_are_pours == True: mask_group = et.SubElement(self._masks[pcb_layer], 'g', transform=transform) self._placeMask(mask_group, shape, 'pad') # Add pin labels labels = shapes_dict['pin-labels'][pcb_layer] if labels != []: style = utils.dictToStyleText( config.stl['layout']['board']['pad-labels']) label_group = et.SubElement(group, 'g', transform="rotate(%s)" % component.getRotation(), style=style) for label in labels: t = et.SubElement( label_group, 'text', x=str(label['location'][0]), # TODO: get rid of this hack y=str(-label['location'][1])) #y=str(-pin_location.y + pad_numbers_font_size/3), #refdef=self._refdef) t.text = label['text'] # Soldermask shapes = shapes_dict['soldermask'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['soldermask']['layer'] transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{' + config.cfg['ns']['pcbmode'] + '}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group) # Solderpaste shapes = shapes_dict['solderpaste'][pcb_layer] svg_layer = self._layers[pcb_layer]['solderpaste']['layer'] transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{' + config.cfg['ns']['pcbmode'] + '}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group) # Silkscreen shapes = shapes_dict['silkscreen'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['silkscreen']['layer'] transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) shape_group = et.SubElement(svg_layer, 'g', transform=transform) shape_group.set( '{' + config.cfg['ns']['pcbmode'] + '}type', 'component-shapes') for shape in shapes: # Refdefs need to be in their own groups so that their # location can later be extracted, hence this... try: is_refdef = getattr(shape, 'is_refdef') except: is_refdef = False if is_refdef == True: refdef_group = et.SubElement(svg_layer, 'g', transform=transform) refdef_group.set( '{' + config.cfg['ns']['pcbmode'] + '}type', 'refdef') refdef_group.set( '{' + config.cfg['ns']['pcbmode'] + '}refdef', refdef) placed_element = place.placeShape( shape, refdef_group) else: placed_element = place.placeShape( shape, shape_group) # Assembly shapes = shapes_dict['assembly'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['assembly']['layer'] transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) for shape in shapes: placed_element = place.placeShape(shape, group) # Drills shapes = shapes_dict['drills'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers['drills']['layer'] transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{' + config.cfg['ns']['pcbmode'] + '}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group) placed_element.set( '{' + config.cfg['ns']['pcbmode'] + '}diameter', str(shape.getDiameter()))
def _placeComponents(self, components, component_type, print_refdef=False): """ Places the component on the board. 'component_type' is the content of the 'type' fiels of the placed group. This is used by the extractor to identify the type of component ('component', 'via', 'shape') """ htmlpar = HTMLParser.HTMLParser() for component in components: shapes_dict = component.getShapes() location = component.getLocation() rotation = component.getRotation() refdef = component.getRefdef() if print_refdef == True: print refdef, # If the component is placed on the bottom layer we need # to invert the shapes AND their 'x' coordinate. This is # done using the 'invert' indicator set below placement_layer = component.getPlacementLayer() if placement_layer == 'bottom': invert = True else: invert = False for pcb_layer in config.stk['layer-names']: there_are_pours = utils.checkForPoursInLayer(pcb_layer) # Copper shapes = shapes_dict['conductor'].get(pcb_layer) or [] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['conductor']['pads']['layer'] transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) shape_group = et.SubElement(svg_layer, 'g', transform=transform) shape_group.set('{'+config.cfg['ns']['pcbmode']+'}type', component_type) # Add the reference designator as well if it's a # 'component' if component_type == 'component': shape_group.set('{'+config.cfg['ns']['pcbmode']+'}refdef', component.getRefdef()) style = utils.dictToStyleText(config.stl['layout']['conductor']['pads']['labels']) label_group = et.SubElement(shape_group, 'g', style=style) for shape in shapes: place.placeShape(shape, shape_group, invert) # Add pin labels # TODO: This isn't perfect, but good enough for now label = shape.getLabel() if label != None: label_location = shape.getLocation() label_rotation = shape.getRotation() label_transform = "rotate(%s)" % label_rotation t = et.SubElement(label_group, 'text', x=str(((1,-1)[invert])*label_location.x), y=str(config.cfg['invert-y']*label_location.y), transform=label_transform) t.text = label if there_are_pours == True: mask_group = et.SubElement(self._masks[pcb_layer], 'g', transform=transform) self._placeMask(mask_group, shape, 'pad', original=False, mirror=invert) # Pours shapes = shapes_dict['pours'].get(pcb_layer) or [] try: svg_layer = self._layers[pcb_layer]['conductor']['pours']['layer'] shape_group = et.SubElement(svg_layer, 'g', mask='url(#mask-%s)' % pcb_layer) except: svg_layer = None if len(shapes) > 0 and svg_layer != None: transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) group = et.SubElement(shape_group, 'g', transform=transform) group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'pours') for shape in shapes: placed_element = place.placeShape(shape, group, invert) # Soldermask shapes = shapes_dict['soldermask'].get(pcb_layer) or [] try: svg_layer = self._layers[pcb_layer]['soldermask']['layer'] except: svg_layer = None if len(shapes) > 0 and svg_layer != None: transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group, invert) # Solderpaste shapes = shapes_dict['solderpaste'].get(pcb_layer) or [] try: svg_layer = self._layers[pcb_layer]['solderpaste']['layer'] except: svg_layer = None if len(shapes) > 0 and svg_layer != None: transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group, invert) # Silkscreen shapes = shapes_dict['silkscreen'].get(pcb_layer) or [] try: svg_layer = self._layers[pcb_layer]['silkscreen']['layer'] except: svg_layer = None if len(shapes) > 0 and svg_layer != None: transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) shape_group = et.SubElement(svg_layer, 'g', transform=transform) shape_group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'component-shapes') for shape in shapes: # Refdefs need to be in their own groups so that their # location can later be extracted, hence this... try: is_refdef = getattr(shape, 'is_refdef') except: is_refdef = False if is_refdef == True: # Shapes don't need to have silkscreen # reference designators if component_type != 'shape': refdef_group = et.SubElement(svg_layer, 'g', transform=transform) refdef_group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'refdef') refdef_group.set('{'+config.cfg['ns']['pcbmode']+'}refdef', refdef) placed_element = place.placeShape(shape, refdef_group, invert) else: placed_element = place.placeShape(shape, shape_group, invert) # Assembly shapes = shapes_dict['assembly'].get(pcb_layer) or [] try: svg_layer = self._layers[pcb_layer]['assembly']['layer'] except: svg_layer = None if len(shapes) > 0 and svg_layer != None: transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) for shape in shapes: placed_element = place.placeShape(shape, group, invert) # Drills shapes = shapes_dict['drills'].get(pcb_layer) or [] if len(shapes) > 0: svg_layer = self._layers['drills']['layer'] transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group, invert) placed_element.set('{'+config.cfg['ns']['pcbmode']+'}diameter', str(shape.getDiameter())) # Place component origin marker svg_layer = self._layers[placement_layer]['placement']['layer'] # Here pcb_layer may not exist for components that define # shapes for internal layers but only surface layers are # defined in the stackup try: group = et.SubElement(svg_layer, 'g', transform=transform) except: return group.set('{'+config.cfg['ns']['pcbmode']+'}type', component_type) group.set('{'+config.cfg['ns']['pcbmode']+'}footprint', component.getFootprintName()) if (component_type == 'component') or (component_type == 'shape'): group.set('{'+config.cfg['ns']['pcbmode']+'}refdef', refdef) path = svg.placementMarkerPath() transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) if placement_layer == 'bottom': rotation *= -1 marker_element = et.SubElement(group, 'path', d=path, transform="rotate(%s)" % rotation) if (component_type == 'component'): style = utils.dictToStyleText(config.stl['layout']['placement']['text']) t = et.SubElement(group, 'text', x="0", y="-0.17", style=style) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = "%s" % (refdef) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = htmlpar.unescape("%s°" % (rotation)) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = "[%.2f,%.2f]" % (location[0], location[1]) elif (component_type == 'shape'): style = utils.dictToStyleText(config.stl['layout']['placement']['text']) t = et.SubElement(group, 'text', x="0", y="-0.17", style=style) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = "%s" % (refdef) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = htmlpar.unescape("%s°" % (rotation)) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = "[%.2f,%.2f]" % (location[0], location[1]) elif (component_type == 'via'): style = utils.dictToStyleText(config.stl['layout']['placement']['text']) t = et.SubElement(group, 'text', x="0", y="-0.11", style=style) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = htmlpar.unescape("%s°" % (rotation)) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = "[%.2f,%.2f]" % (location[0], location[1]) else: continue
def _placeComponents(self, components, component_type, print_refdef=False): """ """ for component in components: shapes_dict = component.getShapes() location = component.getLocation() refdef = component.getRefdef() if print_refdef == True: print refdef, # If the component is placed on the bottom layer we need # to invert the shapes AND their 'x' coordinate. This is # done using the 'invert' indicator set below placement_layer = component.getPlacementLayer() if placement_layer == 'bottom': invert = True else: invert = False for pcb_layer in utils.getSurfaceLayers(): there_are_pours = utils.checkForPoursInLayer(pcb_layer) # Copper shapes = shapes_dict['copper'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['copper']['pads']['layer'] transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) if component_type == 'components': group.set('{'+config.cfg['ns']['pcbmode']+'}refdef', component.getRefdef()) elif component_type == 'vias': group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'via') group.set('{'+config.cfg['ns']['pcbmode']+'}via', component.getFootprintName()) else: pass for shape in shapes: place.placeShape(shape, group, invert) if there_are_pours == True: mask_group = et.SubElement(self._masks[pcb_layer], 'g', transform=transform) self._placeMask(mask_group, shape, 'pad', original=False, mirror=invert) # Add pin labels # There's a bit of a hack here that won't work in # all possible cases (where pads are placed on # bottom layer in a component that has pins placed # both on the top and on the bottom -- a rare # case). Good enough for now labels = shapes_dict['pin-labels']['top']#[pcb_layer] if labels != []: style = utils.dictToStyleText(config.stl['layout']['board']['pad-labels']) label_group = et.SubElement(group, 'g', transform="rotate(%s)" % (((1,-1)[invert])*component.getRotation()), style=style) for label in labels: t = et.SubElement(label_group, 'text', x=str(((1,-1)[invert])*label['location'][0]), y=str(config.cfg['invert-y']*label['location'][1])) t.text = label['text'] # Soldermask shapes = shapes_dict['soldermask'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['soldermask']['layer'] transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group, invert) # Solderpaste shapes = shapes_dict['solderpaste'][pcb_layer] svg_layer = self._layers[pcb_layer]['solderpaste']['layer'] transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group, invert) # Silkscreen shapes = shapes_dict['silkscreen'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['silkscreen']['layer'] transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) shape_group = et.SubElement(svg_layer, 'g', transform=transform) shape_group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'component-shapes') for shape in shapes: # Refdefs need to be in their own groups so that their # location can later be extracted, hence this... try: is_refdef = getattr(shape, 'is_refdef') except: is_refdef = False if is_refdef == True: refdef_group = et.SubElement(svg_layer, 'g', transform=transform) refdef_group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'refdef') refdef_group.set('{'+config.cfg['ns']['pcbmode']+'}refdef', refdef) placed_element = place.placeShape(shape, refdef_group, invert) else: placed_element = place.placeShape(shape, shape_group, invert) # Assembly shapes = shapes_dict['assembly'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['assembly']['layer'] transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) for shape in shapes: placed_element = place.placeShape(shape, group, invert) # Drills shapes = shapes_dict['drills'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers['drills']['layer'] transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group) placed_element.set('{'+config.cfg['ns']['pcbmode']+'}diameter', str(shape.getDiameter()))
def _placeDrillIndex(self): """ Adds a drill index """ # Get the drills sheet / SVG layer drill_layer = self._layers['drills']['layer'] ns = { 'pcbmode': config.cfg['ns']['pcbmode'], 'svg': config.cfg['ns']['svg'] } drills = drill_layer.findall(".//*[@pcbmode:diameter]", namespaces=ns) drills_dict = {} longest_text = 0 largest_drill = 0 drill_count = 0 for drill in drills: diameter = drill.get('{' + config.cfg['ns']['pcbmode'] + '}diameter') diameter = round(float(diameter), 2) if diameter not in drills_dict: drills_dict[diameter] = 1 else: drills_dict[diameter] += 1 if diameter > largest_drill: largest_drill = diameter drill_count += 1 if len(str(diameter)) > longest_text: longest_text = len(str(diameter)) # Get location, or generate one try: location = config.brd['drill-index']['location'] except: # If not location is specified, put the drill index at the # bottom left of the board. The 'gap' defines the extra # spcae between the top of the largest drill and the # board's edge gap = 2 location = [-self._width / 2, -(self._height / 2 + gap)] location = utils.toPoint(location) # Create group for placing index transform = "translate(%s,%s)" % (location.x, config.cfg['invert-y'] * location.y) group = et.SubElement(drill_layer, 'g', transform=transform) group.set('{' + config.cfg['ns']['pcbmode'] + '}type', 'drill-index') text_style_dict = config.stl['layout']['drill-index'].get('text') text_style = utils.dictToStyleText(text_style_dict) count_style_dict = config.stl['layout']['drill-index'].get( 'count-text') count_style = utils.dictToStyleText(count_style_dict) count_style_dict['font-size'] /= 2 drill_size_style = utils.dictToStyleText(count_style_dict) if drill_count == 0: text = 'No drills' elif drill_count == 1: text = '1 drill: ' else: text = '%s drills: ' % drill_count t = et.SubElement(group, 'text', x=str(0), y=str(0), style=text_style) t.text = text # "new line" location.y = -(largest_drill / 2 + 1.5) # TODO: this hack'ish thing for aligning the text isn't going # to work when the font is changed in the stylesheet if float(longest_text * 0.5) > largest_drill: location.x = longest_text * 0.3 else: location.x = largest_drill / 2 gap = 2 for diameter in reversed(sorted(drills_dict)): path = svg.drillPath(diameter) transform = "translate(%s,%s)" % ( location.x, config.cfg['invert-y'] * location.y) element = et.SubElement(group, 'path', d=path, transform=transform) element.set("fill-rule", "evenodd") t = et.SubElement(group, 'text', x=str(location.x), y=str(-location.y), dy="%s" % (config.cfg['invert-y'] * 0.25), style=count_style) t.text = str(drills_dict[diameter]) t = et.SubElement(group, 'text', x=str(location.x), y=str(-location.y), dy="%s" % (config.cfg['invert-y'] * -0.5), style=drill_size_style) t.text = "%s mm" % diameter location.x += max(diameter, 2.5)
def _placeComponents(self, components, component_type, print_refdef=False): """ Places the component on the board. 'component_type' is the content of the 'type' fiels of the placed group. This is used by the extractor to identify the type of component ('component', 'via', 'shape') """ htmlpar = HTMLParser.HTMLParser() for component in components: shapes_dict = component.getShapes() location = component.getLocation() rotation = component.getRotation() refdef = component.getRefdef() if print_refdef == True: print refdef, # If the component is placed on the bottom layer we need # to invert the shapes AND their 'x' coordinate. This is # done using the 'invert' indicator set below placement_layer = component.getPlacementLayer() if placement_layer == 'bottom': invert = True else: invert = False for pcb_layer in config.stk['layer-names']: there_are_pours = utils.checkForPoursInLayer(pcb_layer) # Copper shapes = shapes_dict['conductor'].get(pcb_layer) or [] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['conductor']['pads'][ 'layer'] transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) shape_group = et.SubElement(svg_layer, 'g', transform=transform) shape_group.set( '{' + config.cfg['ns']['pcbmode'] + '}type', component_type) # Add the reference designator as well if it's a # 'component' if component_type == 'component': shape_group.set( '{' + config.cfg['ns']['pcbmode'] + '}refdef', component.getRefdef()) style = utils.dictToStyleText( config.stl['layout']['conductor']['pads']['labels']) label_group = et.SubElement(shape_group, 'g', style=style) for shape in shapes: place.placeShape(shape, shape_group, invert) # Add pin labels # TODO: This isn't perfect, but good enough for now label = shape.getLabel() if label != None: label_location = shape.getLocation() label_rotation = shape.getRotation() label_transform = "rotate(%s)" % label_rotation t = et.SubElement(label_group, 'text', x=str(((1, -1)[invert]) * label_location.x), y=str(config.cfg['invert-y'] * label_location.y), transform=label_transform) t.text = label if there_are_pours == True: mask_group = et.SubElement(self._masks[pcb_layer], 'g', transform=transform) self._placeMask(mask_group, shape, 'pad', original=False, mirror=invert) # Pours shapes = shapes_dict['pours'].get(pcb_layer) or [] try: svg_layer = self._layers[pcb_layer]['conductor']['pours'][ 'layer'] shape_group = et.SubElement(svg_layer, 'g', mask='url(#mask-%s)' % pcb_layer) except: svg_layer = None if len(shapes) > 0 and svg_layer != None: transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) group = et.SubElement(shape_group, 'g', transform=transform) group.set('{' + config.cfg['ns']['pcbmode'] + '}type', 'pours') for shape in shapes: placed_element = place.placeShape(shape, group, invert) # Soldermask shapes = shapes_dict['soldermask'].get(pcb_layer) or [] try: svg_layer = self._layers[pcb_layer]['soldermask']['layer'] except: svg_layer = None if len(shapes) > 0 and svg_layer != None: transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{' + config.cfg['ns']['pcbmode'] + '}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group, invert) # Solderpaste shapes = shapes_dict['solderpaste'].get(pcb_layer) or [] try: svg_layer = self._layers[pcb_layer]['solderpaste']['layer'] except: svg_layer = None if len(shapes) > 0 and svg_layer != None: transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{' + config.cfg['ns']['pcbmode'] + '}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group, invert) # Silkscreen shapes = shapes_dict['silkscreen'].get(pcb_layer) or [] try: svg_layer = self._layers[pcb_layer]['silkscreen']['layer'] except: svg_layer = None if len(shapes) > 0 and svg_layer != None: transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) shape_group = et.SubElement(svg_layer, 'g', transform=transform) shape_group.set( '{' + config.cfg['ns']['pcbmode'] + '}type', 'component-shapes') for shape in shapes: # Refdefs need to be in their own groups so that their # location can later be extracted, hence this... try: is_refdef = getattr(shape, 'is_refdef') except: is_refdef = False if is_refdef == True: # Shapes don't need to have silkscreen # reference designators if component_type != 'shape': refdef_group = et.SubElement( svg_layer, 'g', transform=transform) refdef_group.set( '{' + config.cfg['ns']['pcbmode'] + '}type', 'refdef') refdef_group.set( '{' + config.cfg['ns']['pcbmode'] + '}refdef', refdef) placed_element = place.placeShape( shape, refdef_group, invert) else: placed_element = place.placeShape( shape, shape_group, invert) # Assembly shapes = shapes_dict['assembly'].get(pcb_layer) or [] try: svg_layer = self._layers[pcb_layer]['assembly']['layer'] except: svg_layer = None if len(shapes) > 0 and svg_layer != None: transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) for shape in shapes: placed_element = place.placeShape(shape, group, invert) # Drills shapes = shapes_dict['drills'].get(pcb_layer) or [] if len(shapes) > 0: svg_layer = self._layers['drills']['layer'] transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{' + config.cfg['ns']['pcbmode'] + '}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group, invert) placed_element.set( '{' + config.cfg['ns']['pcbmode'] + '}diameter', str(shape.getDiameter())) # Place component origin marker svg_layer = self._layers[placement_layer]['placement']['layer'] # Here pcb_layer may not exist for components that define # shapes for internal layers but only surface layers are # defined in the stackup try: group = et.SubElement(svg_layer, 'g', transform=transform) except: return group.set('{' + config.cfg['ns']['pcbmode'] + '}type', component_type) group.set('{' + config.cfg['ns']['pcbmode'] + '}footprint', component.getFootprintName()) if (component_type == 'component') or (component_type == 'shape'): group.set('{' + config.cfg['ns']['pcbmode'] + '}refdef', refdef) path = svg.placementMarkerPath() transform = "translate(%s,%s)" % ( location[0], config.cfg['invert-y'] * location[1]) if placement_layer == 'bottom': rotation *= -1 marker_element = et.SubElement(group, 'path', d=path, transform="rotate(%s)" % rotation) if (component_type == 'component'): style = utils.dictToStyleText( config.stl['layout']['placement']['text']) t = et.SubElement(group, 'text', x="0", y="-0.17", style=style) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = "%s" % (refdef) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = htmlpar.unescape("%s°" % (rotation)) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = "[%.2f,%.2f]" % (location[0], location[1]) elif (component_type == 'shape'): style = utils.dictToStyleText( config.stl['layout']['placement']['text']) t = et.SubElement(group, 'text', x="0", y="-0.17", style=style) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = "%s" % (refdef) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = htmlpar.unescape("%s°" % (rotation)) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = "[%.2f,%.2f]" % (location[0], location[1]) elif (component_type == 'via'): style = utils.dictToStyleText( config.stl['layout']['placement']['text']) t = et.SubElement(group, 'text', x="0", y="-0.11", style=style) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = htmlpar.unescape("%s°" % (rotation)) ts = et.SubElement(t, 'tspan', x="0", dy="0.1") ts.text = "[%.2f,%.2f]" % (location[0], location[1]) else: continue
def _placeComponents(self, components, component_type, print_refdef=False): """ """ for component in components: shapes_dict = component.getShapes() location = component.getLocation() # If the component is placed on the bottom layer we need # to invert the shapes AND their 'x' coordinate. This is # sone using the 'invert' indicator set below refdef = component.getRefdef() if print_refdef == True: print refdef, placement_layer = component.getPlacementLayer() if placement_layer == 'bottom': invert = True else: invert = False for pcb_layer in utils.getSurfaceLayers(): there_are_pours = utils.checkForPoursInLayer(pcb_layer) # Copper shapes = shapes_dict['copper'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['copper']['pads']['layer'] transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) if component_type == 'components': group.set('{'+config.cfg['ns']['pcbmode']+'}refdef', component.getRefdef()) elif component_type == 'vias': group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'via') group.set('{'+config.cfg['ns']['pcbmode']+'}via', component.getFootprintName()) else: pass for shape in shapes: place.placeShape(shape, group) if there_are_pours == True: mask_group = et.SubElement(self._masks[pcb_layer], 'g', transform=transform) self._placeMask(mask_group, shape, 'pad') # Add pin labels labels = shapes_dict['pin-labels'][pcb_layer] if labels != []: style = utils.dictToStyleText(config.stl['layout']['board']['pad-labels']) label_group = et.SubElement(group, 'g', transform="rotate(%s)" % component.getRotation(), style=style) for label in labels: t = et.SubElement(label_group, 'text', x=str(label['location'][0]), # TODO: get rid of this hack y=str(-label['location'][1])) #y=str(-pin_location.y + pad_numbers_font_size/3), #refdef=self._refdef) t.text = label['text'] # Soldermask shapes = shapes_dict['soldermask'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['soldermask']['layer'] transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group) # Solderpaste shapes = shapes_dict['solderpaste'][pcb_layer] svg_layer = self._layers[pcb_layer]['solderpaste']['layer'] transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group, invert) # Silkscreen shapes = shapes_dict['silkscreen'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['silkscreen']['layer'] transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) shape_group = et.SubElement(svg_layer, 'g', transform=transform) shape_group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'component-shapes') for shape in shapes: # Refdefs need to be in their own groups so that their # location can later be extracted, hence this... try: is_refdef = getattr(shape, 'is_refdef') except: is_refdef = False if is_refdef == True: refdef_group = et.SubElement(svg_layer, 'g', transform=transform) refdef_group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'refdef') refdef_group.set('{'+config.cfg['ns']['pcbmode']+'}refdef', refdef) placed_element = place.placeShape(shape, refdef_group) else: placed_element = place.placeShape(shape, shape_group) # Assembly shapes = shapes_dict['assembly'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers[pcb_layer]['assembly']['layer'] transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) for shape in shapes: placed_element = place.placeShape(shape, group) # Drills shapes = shapes_dict['drills'][pcb_layer] if len(shapes) > 0: svg_layer = self._layers['drills']['layer'] transform = "translate(%s,%s)" % (location[0], config.cfg['invert-y']*location[1]) group = et.SubElement(svg_layer, 'g', transform=transform) group.set('{'+config.cfg['ns']['pcbmode']+'}type', 'component-shapes') for shape in shapes: placed_element = place.placeShape(shape, group) placed_element.set('{'+config.cfg['ns']['pcbmode']+'}diameter', str(shape.getDiameter()))