def positionFormater(element): if type(element) == type({}): if(not {"posx", "posy"}.issubset(element.keys())): raise Exception("missing keys 'posx' and 'posy' in"+str(element)) return "@ ({0}, {1})".format(mm_to_mil(element['posx']), mm_to_mil(element['posy'])) if 'posx' in element.__dict__ and 'posy' in element.__dict__: return "@ ({0}, {1})".format(mm_to_mil(element.posx), mm_to_mil(element.posy)) raise Exception("input type: ", type(element), "not supported, ", element)
def pinString(pin: Pin, loc: bool = True, unit=None, convert=None) -> str: return "Pin {name} ({num}){loc}{unit}".format( name=pin.name, num=pin.number, loc=" @ ({x},{y})".format(x=mm_to_mil(pin.posx), y=mm_to_mil(pin.posy)) if loc else "", unit=" in unit {n}".format(n=pin.unit) if unit else "", )
def positionFormater(element) -> str: if isinstance(element, dict): if not {"posx", "posy"}.issubset(element.keys()): raise Exception("missing keys 'posx' and 'posy' in" + str(element)) return "@ ({0}, {1})".format( mm_to_mil(element["posx"]), mm_to_mil(element["posy"]) ) if hasattr(element, "posx") and hasattr(element, "posy"): return "@ ({0}, {1})".format(mm_to_mil(element.posx), mm_to_mil(element.posy)) raise Exception("input type: ", type(element), "not supported, ", element)
def check(self) -> bool: """ Proceeds the checking of the rule. The following variables will be accessible after checking: * center_rect_polyline """ # no checks for power-symbols, graphical symbols or derived symbols if (self.component.is_power_symbol() or self.component.is_graphic_symbol() or self.component.extends is not None): return False # check if component has just one rectangle, if not, skip checking self.center_rect_polyline = self.component.get_center_rectangle( range(self.component.unit_count)) if self.center_rect_polyline is None: return False rectangle_need_fix = False if self.component.is_small_component_heuristics(): if not math.isclose(self.center_rect_polyline.stroke_width, mil_to_mm(10)): self.warning( "Component outline is thickness {0}mil, recommended is {1}mil for" " standard symbol".format( mm_to_mil(self.center_rect_polyline.stroke_width), 10)) self.warningExtra( "exceptions are allowed for small symbols like resistor," " transistor, ...") rectangle_need_fix = False else: if not math.isclose(self.center_rect_polyline.stroke_width, mil_to_mm(10)): self.error( "Component outline is thickness {0}mil, recommended is {1}mil" .format(mm_to_mil(self.center_rect_polyline.stroke_width), 10)) rectangle_need_fix = True if self.center_rect_polyline.fill_type != "background": msg = ( "Component background is filled with {0} color, recommended is filling" " with {1} color".format(self.center_rect_polyline.fill_type, "background")) if self.component.is_small_component_heuristics(): self.warning(msg) self.warningExtra( "exceptions are allowed for small symbols like resistor," " transistor, ...") else: self.error(msg) rectangle_need_fix = True return rectangle_need_fix
def check(self) -> bool: """ Calculate the 'bounds' of the symbol based on rectangle (if only a single filled rectangle is present) or on pin positions. """ # no need to check this for an if self.component.extends is not None: return False # Check units separately unit_count = self.component.unit_count for unit in range(1, unit_count + 1): # If there is only a single filled rectangle, we assume that it is the # main symbol outline. center_pl = self.component.get_center_rectangle([0, unit]) if center_pl is not None: (x, y) = center_pl.get_center_of_boundingbox() else: pins = [pin for pin in self.component.pins if (pin.unit in [unit, 0])] # No pins? Ignore check. # This can be improved to include graphical items too... if not pins: continue x_pos = [pin.posx for pin in pins] y_pos = [pin.posy for pin in pins] x_min = min(x_pos) x_max = max(x_pos) y_min = min(y_pos) y_max = max(y_pos) # Center point average x = (x_min + x_max) / 2 y = (y_min + y_max) / 2 # convert to mil x = mm_to_mil(x) y = mm_to_mil(y) # Right on the middle! if x == 0 and y == 0: continue elif math.fabs(x) <= 50 and math.fabs(y) <= 50: self.warning("Symbol unit {unit} slightly off-center".format(unit=unit)) self.warningExtra(" Center calculated @ ({x}, {y})".format(x=x, y=y)) else: self.error( "Symbol unit {unit} not centered on origin".format(unit=unit) ) self.errorExtra("Center calculated @ ({x}, {y})".format(x=x, y=y)) return False
def check(self) -> bool: """ Proceeds the checking of the rule. The following variables will be accessible after checking: * violating_pins * violating_properties """ self.violating_properties = [] for prop in self.component.properties: text_size = mm_to_mil(prop.effects.sizex) if text_size != 50: self.violating_properties.append(prop) message = "{0} at posx {1} posy {2}".format( prop.name, mm_to_mil(prop.posx), mm_to_mil(prop.posy)) self.error(" - Field {0} size {1}".format(message, text_size)) self.violating_pins = [] """ Pin number MUST be 50mils Pin name must be between 20mils and 50mils Pin name should be 50mils """ for pin in self.component.pins: name_text_size = mm_to_mil(pin.name_effect.sizex) num_text_size = mm_to_mil(pin.number_effect.sizex) if ((name_text_size < 20) or (name_text_size > 50) or (num_text_size < 20) or (num_text_size > 50)): self.violating_pins.append(pin) self.error( " - Pin {0} ({1}), text size {2}, number size {3}".format( pin.name, pin.number, name_text_size, num_text_size)) else: if name_text_size != 50: self.warning( "Pin {0} ({1}) name text size should be 50mils (or 20...50mils" " if required by the symbol geometry)".format( pin.name, pin.number)) if num_text_size != 50: self.warning( "Pin {0} ({1}) number text size should be 50mils (or" " 20...50mils if required by the symbol geometry)". format(pin.name, pin.number)) if self.violating_properties or self.violating_pins: return True return False
def checkPinOrigin(self, gridspacing: int = 100) -> bool: self.violating_pins = [] err = False for pin in self.component.pins: posx = mm_to_mil(pin.posx) posy = mm_to_mil(pin.posy) if (posx % gridspacing) != 0 or (posy % gridspacing) != 0: self.violating_pins.append(pin) if not err: self.error( "Pins not located on {0}mil (={1:.3}mm) grid:".format( gridspacing, gridspacing * 0.0254)) self.error(" - {0} ".format(pinString(pin, loc=True))) err = True return len(self.violating_pins) > 0
def checkPinLength(self, errorPinLength: int = 49, warningPinLength: int = 99) -> bool: self.violating_pins = [] for pin in self.component.pins: length = mm_to_mil(pin.length) err = False # ignore zero-length pins e.g. hidden power pins if length == 0: continue if length <= errorPinLength: self.error("{pin} length ({len}mils) is below {pl}mils".format( pin=pinString(pin), len=length, pl=errorPinLength + 1)) elif length <= warningPinLength: self.warning( "{pin} length ({len}mils) is below {pl}mils".format( pin=pinString(pin), len=length, pl=warningPinLength + 1)) if length % 50 != 0: self.warning( "{pin} length ({len}mils) is not a multiple of 50mils". format(pin=pinString(pin), len=length)) # length too long flags a warning if length > 300: err = True self.error( "{pin} length ({length}mils) is longer than maximum (300mils)" .format(pin=pinString(pin), length=length)) if err: self.violating_pins.append(pin) return len(self.violating_pins) > 0
def copy_icon_v5(dest_comp, src_comp, dest_unit, offset, variant=1, src_unit=0, src_variant=1, style=None): # TODO: source unit # pensize, fill? if type(src_comp) == Component: for p in src_comp.draw['arcs']: # TODO apply offset pos item = dict(p) if item['convert'] == str(src_variant) or item['convert'] == '0': item['unit'] = str(dest_unit) item['convert'] = str(variant) item['posy'] = str(int(item['posy']) + offset.y) item['starty'] = str(int(item['starty']) + offset.y) item['endy'] = str(int(item['endy']) + offset.y) item['fill'] = get_fill(item['fill'], style) dest_comp.drawOrdered.append(['A', item]) for p in src_comp.draw['circles']: item = copy.deepcopy(p) if item['convert'] == str(src_variant) or item['convert'] == '0': item['unit'] = str(dest_unit) item['convert'] = str(variant) item['posy'] = str(int(item['posy']) + offset.y) item['fill'] = get_fill(item['fill'], style) dest_comp.drawOrdered.append(['C', item]) for p in src_comp.draw['polylines']: item = dict(p) if item['convert'] == str(src_variant) or item['convert'] == '0': poly = PolyLine(convert_to_string(['P', p])) poly.unit = dest_unit poly.demorgan = variant poly.fill = get_fill(item['fill'], style) poly.pensize = item['thickness'] for pt in poly.points: pt.x += offset.x pt.y += offset.y dest_comp.drawOrdered.append(poly.get_element()) for p in src_comp.draw['rectangles']: # TODO apply offset pos item = dict(p) if item['convert'] == str(src_variant) or item['convert'] == '0': rect = Rect() rect.unit = dest_unit rect.demorgan = variant rect.fill = get_fill(item['fill'], style) rect.p1 = Point(int(item['startx']), int(item['starty'])).Add(offset) rect.p2 = Point(int(item['endx']), int(item['endy'])).Add(offset) dest_comp.drawOrdered.append(rect.get_element()) for p in src_comp.draw['texts']: item = copy.deepcopy(p) if item['convert'] == str(src_variant) or item['convert'] == '0': item['unit'] = str(dest_unit) item['convert'] = str(variant) item['posy'] = str(int(item['posy']) + offset.y) dest_comp.drawOrdered.append(['T', item]) elif type(src_comp) == kicad_sym.KicadSymbol: for p in src_comp.arcs: if p.demorgan == src_variant or p.demorgan == 0: item = {} item['unit'] = str(dest_unit) item['convert'] = str(variant) item['posx'] = str(kicad_sym.mm_to_mil(p.centerx)) item['posy'] = str(kicad_sym.mm_to_mil(p.centery)) item['radius'] = str(kicad_sym.mm_to_mil(p.length)) item['start_angle'] = str(math.floor(p.angle_start * 10.0)) item['end_angle'] = str(math.floor(p.angle_stop * 10.0)) item['startx'] = str(kicad_sym.mm_to_mil(p.startx)) item['starty'] = str(kicad_sym.mm_to_mil(p.starty)) item['endx'] = str(kicad_sym.mm_to_mil(p.endx)) item['endy'] = str(kicad_sym.mm_to_mil(p.endy)) item['thickness'] = str(kicad_sym.mm_to_mil(p.stroke_width)) item['fill'] = sweet.convert_fill_to_v5(p.fill_type) item['posy'] = str(int(item['posy']) + offset.y) item['starty'] = str(int(item['starty']) + offset.y) item['endy'] = str(int(item['endy']) + offset.y) item['fill'] = get_fill(item['fill'], style) dest_comp.drawOrdered.append(['A', item]) for p in src_comp.circles: if p.demorgan == src_variant or p.demorgan == 0: item = {} item['unit'] = str(dest_unit) item['convert'] = str(variant) item['posx'] = str(kicad_sym.mm_to_mil(p.centerx)) item['posy'] = str(kicad_sym.mm_to_mil(p.centery)) item['radius'] = str(kicad_sym.mm_to_mil(p.radius)) item['thickness'] = str(kicad_sym.mm_to_mil(p.stroke_width)) item['fill'] = sweet.convert_fill_to_v5(p.fill_type) item['posy'] = str(int(item['posy']) + offset.y) item['fill'] = get_fill(item['fill'], style) dest_comp.drawOrdered.append(['C', item]) for p in src_comp.polylines: if p.demorgan == src_variant or p.demorgan == 0: poly = PolyLine() poly.unit = dest_unit poly.demorgan = variant poly.fill = sweet.convert_fill_to_v5(p.fill_type) poly.fill = get_fill(poly.fill, style) poly.pensize = kicad_sym.mm_to_mil(p.stroke_width) for pt in p.points: mil_p = sym_utils_v6.point_to_mil(pt) poly.points.append(mil_p.Add(offset)) dest_comp.drawOrdered.append(poly.get_element()) for p in src_comp.rectangles: # TODO apply offset if p.demorgan == src_variant or p.demorgan == 0: rect = Rect() rect.unit = dest_unit rect.demorgan = variant rect.fill = sweet.convert_fill_to_v5(p.fill_type) rect.fill = get_fill(rect.fill, style) rect.pensize = kicad_sym.mm_to_mil(p.stroke_width) rect.p1 = sym_utils_v6.point_to_mil(Point( p.startx, p.starty)).Add(offset) rect.p2 = sym_utils_v6.point_to_mil(Point(p.endx, p.endy)).Add(offset) dest_comp.drawOrdered.append(rect.get_element()) for p in src_comp.texts: if p.demorgan == src_variant or p.demorgan == 0: item = {} item['unit'] = str(dest_unit) item['convert'] = str(variant) item['posx'] = str(kicad_sym.mm_to_mil(p.posx)) item['posy'] = str(kicad_sym.mm_to_mil(p.posy)) item['direction'] = str(math.floor(p.rotation * 10.0)) item['text_size'] = str(kicad_sym.mm_to_mil(p.effects.sizex)) item[ 'hjustify'] = "L" if p.effects.h_justify == "left" else "C" item[ 'vjustify'] = "B" if p.effects.v_justify == "bottom" else "C" item['bold'] = "1" if p.effects.is_bold else "0" item['italic'] = "Italic" if p.effects.is_italic else "Normal" item['text_type'] = "1" if p.effects.is_hidden else "0" item['text'] = p.text item['posy'] = str(int(item['posy']) + offset.y) dest_comp.drawOrdered.append(['T', item])
def pinString(pin, loc=True, unit=None, convert=None): return "Pin {name} ({num}){loc}{unit}".format( name=pin.name, num=pin.number, loc=' @ ({x},{y})'.format(x=mm_to_mil(pin.posx), y=mm_to_mil(pin.posy)) if loc else '', unit=' in unit {n}'.format(n=pin.unit) if unit else '')