def build(self, board: pcbnew.BOARD, external_signals: dict[str, pcbnew.NETINFO_ITEM] = {}, path: list[str] = []): # Populate signal map creating new signals where required local_signals = {} for name in self.public_signals: if name in external_signals: local_signals[name] = external_signals[name] else: net = pcbnew.NETINFO_ITEM(board, "/".join( (*path, self.id, name))) board.Add(net) local_signals[name] = net for name in self.private_signals: net = pcbnew.NETINFO_ITEM(board, "/".join((*path, self.id, name))) board.Add(net) local_signals[name] = net # TODO: Warn about unused signals? for component, signal_mapping in self.components: component.build( board, { inner_name: local_signals[signal_name] for (inner_name, signal_name) in signal_mapping.items() }, (*path, self.id))
def build(self, board: pcbnew.BOARD, external_signals: dict[str, pcbnew.NETINFO_ITEM] = {}, path: list[str] = []): """Create and return a KiCad circle centered at x, y.""" item = pcbnew.PCB_SHAPE() item.SetShape(pcbnew.S_CIRCLE) item.SetStart(pcbnew.wxPointMM(self.x, self.y)) item.SetEnd(pcbnew.wxPointMM(self.x + self.diameter / 2, self.y)) item.SetLayer(self.layer) board.Add(item)
def build(self, board: pcbnew.BOARD, external_signals: dict[str, pcbnew.NETINFO_ITEM] = {}, path: list[str] = []): o = pcbnew.PCB_TEXT(board) o.SetText(self.text) o.SetHorizJustify(pcbnew.GR_TEXT_HJUSTIFY_CENTER) o.SetTextSize( pcbnew.wxSize(pcbnew.FromMM(self.size), pcbnew.FromMM(self.size))) o.SetTextThickness(pcbnew.FromMM(self.size * self.thickness * 0.15)) o.SetLayer(self.layer) set_pcb_position(o, self.pcbpos) board.Add(o)
def build(self, board: pcbnew.BOARD, external_signals: dict[str, pcbnew.NETINFO_ITEM] = {}, path: list[str] = []): """Yield a sequence of KiCad segments from the provided Shapely polygon. A Shapely polygon may have interior polygons representing holes in the larger polygon. The hole polygons are emitted as additional segments so they appear as pcb cutouts. """ # coerce to polygon in case input is a ring geom = shapely.geometry.polygon.Polygon(self.geom) def make_point(p): x, y = p return pcbnew.wxPointMM(x, y) def make_seg(p1, p2): seg = pcbnew.PCB_SHAPE() seg.SetShape(pcbnew.S_SEGMENT) seg.SetStart(make_point(p1)) seg.SetEnd(make_point(p2)) seg.SetLayer(self.layer) return seg points = geom.exterior.coords for p1, p2 in [(points[i], points[(i + 1) % len(points)]) for i in range(len(points))]: board.Add(make_seg(p1, p2)) for interior in geom.interiors: points = interior.coords for p1, p2 in [(points[i], points[(i + 1) % len(points)]) for i in range(len(points))]: board.Add(make_seg(p1, p2))
def build(self, board: pcbnew.BOARD, external_signals: dict[str, pcbnew.NETINFO_ITEM] = {}, path: list[str] = []): def load_footprint(ref: str): """Load a footprint otherwise raise exception""" library, name = ref.split(":") footprint = pcbnew.FootprintLoad( os.path.join(os.environ.get("RUNFILES_DIR", "external/"), library), name) if not footprint: raise ValueError( f"can not load footprint {name} from library {library}") return footprint fp = load_footprint(self.ref) fp.SetValue(self.value) set_pcb_position(fp, self.pose) fp.Value().SetVisible(self.value_visible) fp.Reference().SetVisible(self.reference_visible) fp.Reference().SetKeepUpright(self.keep_upright) if self.clear_top: for g in fp.GraphicalItems(): layer = g.GetLayer() if layer == 37: if isinstance(g, pcbnew.EDA_TEXT): g.SetVisible(False) else: g.DeleteStructure() other = [x.GetReference() for x in board.GetFootprints()] x = 1 while f"{self.reference_prefix}{x}" in other: x = x + 1 fp.SetReference(f"{self.reference_prefix}{x}") board.Add(fp) for i, pin_name in enumerate(self.pins, start=1): if pin_name in external_signals: fp.FindPadByName(i).SetNet(external_signals[pin_name]) for name in external_signals.keys(): if name not in self.pins: raise RuntimeError( f"no pin '{name}' in {path} ({self.reference_prefix}{x})")