def draw_radial(i_hand, i_ring, theta, rad_ofs, theta_ofs): if i_hand == 0: outerRad = outerViaRad else: outerRad = diodeRad ringRad = outerRingRad - (i_ring - 1) * ringSpacing track = pcbnew.TRACK(board) track.SetStart(polar(ringRad, theta)) track.SetEnd(polar(outerRad + rad_ofs, theta)) track.SetWidth(ringWidth * mil) track.SetLayer(layerTable["B.Cu"]) net = board.GetNetsByName()["/Q%02d" % i_ring] board.Add(track) track.SetNet(net) via = pcbnew.VIA(board) via.SetLayerPair(layerTable["F.Cu"], layerTable["B.Cu"]) via.SetPosition(polar(ringRad, theta)) board.Add(via) via.SetNet(net) if i_hand == 0: via = pcbnew.VIA(board) via.SetLayerPair(layerTable["F.Cu"], layerTable["B.Cu"]) via.SetPosition(polar(outerRad + rad_ofs, theta)) board.Add(via) via.SetNet(net) track = pcbnew.TRACK(board) track.SetStart(polar(diodeRad, theta + theta_ofs)) track.SetEnd(polar(outerRad + rad_ofs, theta)) track.SetWidth(ringWidth * mil) track.SetLayer(layerTable["F.Cu"]) net = board.GetNetsByName()["/Q%02d" % i_ring] board.Add(track) track.SetNet(net)
def create_Track(pcb, p1, p2, lyr=None, w=None, Nn=None, Ts=None): #draw segment to test #new_line = pcbnew.DRAWSEGMENT(pcb) new_line = pcbnew.TRACK(pcb) new_line.SetStart(p1) new_line.SetEnd(p2) if w is None: new_line.SetWidth(FromUnits(1.5)) #FromUnits(int(mask_width))) else: new_line.SetWidth(FromUnits(w)) if lyr is None: lyr = F_SilkS if Nn is not None: new_line.SetNet(Nn) #new_line.SetNetname(Nn) new_line.SetLayer(lyr) #pcbnew.F_SilkS) #pcb.GetLayerID(mask_layer)) if Ts is not None: tsc = 0 Nname = new_line.GetNetname() for c in Nname: tsc = tsc + ord(c) if hasattr(new_line, 'SetTimeStamp'): new_line.SetTimeStamp( tsc ) # adding a unique number (this netname) as timestamp to mark this segment as generated by this script on this netname pcb.Add(new_line) return new_line
def new_track(self, coord, w, layer): t = pcbnew.TRACK(self.pcb) t.SetStart(coord[0]) t.SetEnd(coord[1]) t.SetWidth(w) t.SetLayer(layer) return t
def add_track_pos(board, layer, netcode, start_pos, end_pos, track_width, center=None, angle=0): """ Add track to the board. @param board Pcbnew board @param layer track is placed on @param netcode track netcode @param start_pos starting position of the track @param end_pos ending position of the track @param track_width width of this track @param center rotation center if required @param angle angle if rotated """ t = pcbnew.TRACK(board) t.SetNetCode(netcode, False) t.SetLayer(layer) t.SetWidth(track_width) t.SetStart(start_pos) t.SetEnd(end_pos) if not center is None and angle > 0: t.Rotate(center, angle) board.Add(t)
def newTrack(board, start, end): t = pcbnew.TRACK(board) t.SetStart(start) t.SetEnd(end) t.SetLayer(pcbnew.F_Cu) board.Add(t) return t
def draw_track_segment(board, start, end, net, layer=0): '''Returns a new pcbnew board with an added track.''' tseg = pcbnew.TRACK(board) tseg.SetStart(start) tseg.SetEnd(end) tseg.SetWidth(Layout.get_track_width()) tseg.SetLayer(layer) board.Add(tseg) return board
def make_track_segment(self, start, end, net_code, layer): t = pcb.TRACK(self.board) self.board.Add(t) t.SetStart(start) t.SetEnd(end) t.SetNetCode(net_code) t.SetLayer(layer) t.SetWidth(pcb.FromMM(DEFAULT_TRACK_WIDTH_MM)) return end
def track(p1, p2, layer, width): pcb = pcbnew.GetBoard() t = pcbnew.TRACK(pcb) pcb.Add(t) t.SetStart(p1) t.SetEnd(p2) t.SetLayer(layer) t.SetWidth(width) return t
def draw_track(start, end, layer, net, width=None): track = pcbnew.TRACK(board) track.SetStart(start) track.SetEnd(end) track.SetLayer(layer) board.Add(track) track.SetNet(net) if width: track.SetWidth(int(width)) return track
def add_tracks(): layertable = get_layertable() board = pcbnew.GetBoard() for i in range(100): track = pcbnew.TRACK(board) track.SetStart(pcbnew.wxPoint(0, SCALE * i)) track.SetEnd(pcbnew.wxPoint(SCALE * 200, SCALE * i)) track.SetWidth(int(SCALE * 0.7)) track.SetLayer(layertable["B.Cu"]) board.Add(track) pcbnew.Refresh()
def add_copper_trace(start, end, net): track = pcbnew.TRACK(board._obj) track.SetStart(start) track.SetEnd(end) track.SetLayer(layertable["F.Cu"]) track.SetWidth(int(.25 * 10**6)) track.SetNet(net) board._obj.Add(track) print("adding track from {} to {} on net {}".format( start, end, net.GetNetname())) return track
def add_track_segment(self, start, end, layer='F.Cu', width=None): """Create a track segment""" if width == None: width = self._board.GetDesignSettings().GetCurrentTrackWidth() else: width = _to_iu(width) t = pcbnew.TRACK(self._board) t.SetWidth(width) t.SetLayer(_get_layer(layer)) t.SetStart(_to_wxpoint(start[0], start[1])) t.SetEnd(_to_wxpoint(end[0], end[1])) self._board.Add(t) return t
def add_track(a, b, net, layer, width): pnt_a = pnt.to_unit(vec2.round(a, PointDigits), UnitMM) pnt_b = pnt.to_unit(vec2.round(b, PointDigits), UnitMM) track = pcbnew.TRACK(pcb) track.SetStart(pnt_a) track.SetEnd(pnt_b) if net != None: track.SetNet(net) track.SetLayer(layer) track.SetWidth(scalar_to_unit(width, UnitMM)) track.SetLocked(True) pcb.Add(track) return track
def replicate_tracks(self, x_offset, y_offset): """ method which replicates tracks""" global SCALE # start cloning for sheet in self.sheets_to_clone: sheet_index = self.sheets_to_clone.index(sheet) + 1 net_pairs, net_dict = self.get_net_pairs(sheet) # go through all the tracks for track in self.pivot_tracks: # get from which net we are clonning from_net_name = track.GetNetname() # find to net to_net_name = [item for item in net_pairs if item[0] == from_net_name][0][1] to_net = net_dict[to_net_name] # finally make a copy # this came from Miles Mccoo # https://github.com/mmccoo/kicad_mmccoo/blob/master/replicatelayout/replicatelayout.py if track.GetClass() == "VIA": oldvia = self.board.GetViaByPosition(track.GetPosition()) newvia = pcbnew.VIA(self.board) # need to add before SetNet will work, so just doing it first self.board.Add(newvia) toplayer = -1 bottomlayer = pcbnew.PCB_LAYER_ID_COUNT for l in range(pcbnew.PCB_LAYER_ID_COUNT): if not track.IsOnLayer(l): continue toplayer = max(toplayer, l) bottomlayer = min(bottomlayer, l) newvia.SetLayerPair(toplayer, bottomlayer) newvia.SetPosition(pcbnew.wxPoint(track.GetPosition().x + sheet_index*x_offset*SCALE, track.GetPosition().y + sheet_index*y_offset*SCALE)) newvia.SetViaType(oldvia.GetViaType()) newvia.SetWidth(oldvia.GetWidth()) newvia.SetNet(to_net) else: newtrack = pcbnew.TRACK(self.board) # need to add before SetNet will work, so just doing it first self.board.Add(newtrack) newtrack.SetStart(pcbnew.wxPoint(track.GetStart().x + sheet_index*x_offset*SCALE, track.GetStart().y + sheet_index*y_offset*SCALE)) newtrack.SetEnd(pcbnew.wxPoint(track.GetEnd().x + sheet_index*x_offset*SCALE, track.GetEnd().y + sheet_index*y_offset*SCALE)) newtrack.SetWidth(track.GetWidth()) newtrack.SetLayer(track.GetLayer()) newtrack.SetNet(to_net) pass
def ConnectModuleToNets(board, mod): for pad in mod.Pads(): padPos = pad.GetPosition() padNet = pad.GetNetCode() nearestPos, nearestTrack = GetNearestPointOnNet( board, padPos, padNet, pcbnew.F_Cu) print('nearest: {},{}'.format(nearestPos.x, nearestPos.y)) track = pcbnew.TRACK(board) board.Add(track) track.SetStart(padPos) track.SetEnd(nearestPos) track.SetNet(board.GetNetsByNetcode()[padNet]) track.SetWidth(nearestTrack.GetWidth()) track.SetLayer(pcbnew.F_Cu)
def trace_points(board, points, pad): net = pad.GetNet() width = pad.GetNetClass().GetDiffPairWidth() start = points[0] for end in points[1:]: track = pcbnew.TRACK(board) track.SetStart(start.asWxPoint()) track.SetEnd(end.asWxPoint()) track.SetLayer(0) # CHANGEME track.SetNet(net) track.SetWidth(width) board.Add(track) start = end
def _conv_track(track, net_code): if len(track.points) < 2: return old_pt = track.points[0] for pt in track.points[1:]: t = pcb.TRACK(pcb.GetBoard()) t.SetStart(ToPCB._conv_point(old_pt)) t.SetEnd(ToPCB._conv_point(pt)) t.SetNetCode(net_code) t.SetLayer(track.layer) if track.width is not None: t.SetWidth(track.width) # t.SetWidth(pcb.FromMM(DEFAULT_TRACK_WIDTH_MM)) pcb.GetBoard().Add(t) old_pt = pt
def draw_rings(): for i_ring in range(1, 17): for i_theta in range(240): thetam = i_theta * 1.5 thetap = thetam + 1.5 ringRad = outerRingRad - (i_ring - 1) * ringSpacing pm = polar(ringRad, thetam) pp = polar(ringRad, thetap) track = pcbnew.TRACK(board) track.SetStart(pm) track.SetEnd(pp) track.SetWidth(ringWidth * mil) net = board.GetNetsByName()["/Q%02d" % i_ring] print(net) board.Add(track) track.SetNet(net) pcbnew.Refresh()
def createTracks(x, y, wire_width=1000000): pcb = pcbnew.GetBoard() #get layer table layertable = {} numlayers = pcbnew.LAYER_ID_COUNT for i in range(numlayers): layertable[i] = pcb.GetLayerName(i) print("{} {}".format(i, pcb.GetLayerName(i))) # create tracks for lay in [0, 31]: for i in range(len(x)): t = pcbnew.TRACK(pcb) t.SetStart(pcbnew.wxPointMM(round(x[i - 1], 2), round(y[i - 1], 2))) t.SetEnd(pcbnew.wxPointMM(round(x[i], 2), round(y[i], 2))) t.SetWidth(int(wire_width)) t.SetLayer(lay) pcb.Add(t) print('Wire Generation Done!')
def add_track(self, posList=[[0, 0], [1, 1]], width=None, layerId=0, netName="/GND"): netcode = self._board.GetNetcodeFromNetname(netName) for i in xrange(len(posList) - 1): t = posList[i] p1 = pcbnew.wxPoint( t[0], t[1]) if type(t) == tuple or type(t) == list else t t = posList[i + 1] p2 = pcbnew.wxPoint( t[0], t[1]) if type(t) == tuple or type(t) == list else t if width == None: width = self._board.GetDesignSettings().GetCurrentTrackWidth() track = pcbnew.TRACK(self._board) track.SetStart(p1) track.SetEnd(p2) track.SetWidth(width) track.SetLayer(layerId) self._board.Add(track) track.SetNetCode(netcode)
def CreateSMTClone2(board, mod, footprintLib, footprintName): new_mod = pcbnew.PCB_IO().FootprintLoad(footprintLib, footprintName) new_mod.SetPosition(ModuleMidPoint(mod)) new_mod.SetOrientation(mod.GetOrientation()) new_mod.SetReference(mod.GetReference()) new_mod.SetValue(mod.GetValue()) new_mod.SetLocalClearance(mod.GetLocalClearance()) board.Add(new_mod) CopyText(mod.Reference(), new_mod.Reference()) CopyText(mod.Value(), new_mod.Value()) for newPad in new_mod.Pads(): oldPad = mod.FindPadByName(newPad.GetName()) net = oldPad.GetNet() newPad.SetNet(net) newPad.SetLocalClearance(oldPad.GetLocalClearance()) # Create via at some offset from the new pad in # the direction of the old pad. TRACK_WIDTH = int(12 * MIL) VIA_DISTANCE = int(30 * MIL) direction = Normalize(oldPad.GetPosition() - newPad.GetPosition()) offset = Scale(direction, VIA_DISTANCE) viaPos = newPad.GetPosition() + offset via = pcbnew.VIA(board) board.Add(via) via.SetPosition(viaPos) via.SetNet(net) via.SetWidth(net.GetNetClass().GetViaDiameter()) via.SetLayerPair(pcbnew.F_Cu, pcbnew.B_Cu) # Create track between new pad and the via. track = pcbnew.TRACK(board) board.Add(track) track.SetStart(newPad.GetPosition()) track.SetEnd(via.GetPosition()) track.SetNet(net) track.SetWidth(int(12 * MIL)) track.SetLayer(pcbnew.F_Cu) return new_mod
matrix[b][c] = numpy.hypot(*numpy.subtract(pts[b], pts[c])) matrix[c][a] = numpy.hypot(*numpy.subtract(pts[c], pts[a])) X = csr_matrix(matrix) Tcsr = minimum_spanning_tree(X) net = nettable[k] nc = net.GetNetClass() #print("for net {}".format(net.GetNetname())) # info about iterating the results: # https://stackoverflow.com/a/4319087/23630 rows,cols = Tcsr.nonzero() for row,col in zip(rows,cols): #print(" {} - {}".format(pts[row], pts[col])) newtrack = pcbnew.TRACK(board) # need to add before SetNet will work, so just doing it first board.Add(newtrack) newtrack.SetNet(net) newtrack.SetStart(pcbnew.wxPoint(*pts[row])) newtrack.SetEnd(pcbnew.wxPoint(*pts[col])) newtrack.SetWidth(nc.GetTrackWidth()) newtrack.SetLayer(layer) pcbnew.Refresh()
def replicate_sheet_trackst(fromnet, tonet, offset): board = tonet.GetParent() # remove tonet's old routing for track in board.TracksInNet(tonet.GetNet()): board.Remove(track) for track in board.TracksInNet(fromnet.GetNet()): if track.GetClass() == "VIA": # cloning is an easier way, but I want to ensure I # can create a Via from scratch #newvia = track.Clone() oldvia = board.GetViaByPosition(track.GetPosition()) newvia = pcbnew.VIA(board) # need to add before SetNet will work, so just doing it first board.Add(newvia) toplayer = -1 bottomlayer = pcbnew.PCB_LAYER_ID_COUNT for l in range(pcbnew.PCB_LAYER_ID_COUNT): if not track.IsOnLayer(l): continue toplayer = max(toplayer, l) bottomlayer = min(bottomlayer, l) newvia.SetLayerPair(toplayer, bottomlayer) newvia.SetPosition( pcbnew.wxPoint(track.GetPosition().x + offset[0], track.GetPosition().y + offset[1])) newvia.SetViaType(oldvia.GetViaType()) newvia.SetWidth(oldvia.GetWidth()) newvia.SetNet(tonet) else: newtrack = pcbnew.TRACK(board) # need to add before SetNet will work, so just doing it first board.Add(newtrack) newtrack.SetStart( pcbnew.wxPoint(track.GetStart().x + offset[0], track.GetStart().y + offset[1])) newtrack.SetEnd( pcbnew.wxPoint(track.GetEnd().x + offset[0], track.GetEnd().y + offset[1])) newtrack.SetWidth(track.GetWidth()) newtrack.SetLayer(track.GetLayer()) newtrack.SetNet(tonet) fromzones = [] tozones = [] for zoneid in range(board.GetAreaCount()): zone = board.GetArea(zoneid) if (zone.GetNet().GetNetname() == fromnet.GetNetname()): fromzones.append(zone) continue if (zone.GetNet().GetNetname() == tonet.GetNetname()): tozones.append(zone) continue for zone in tozones: board.Remove(zone) for zone in fromzones: coords = coordsFromPolySet(zone.Outline()) #pdb.set_trace() newzone = board.InsertArea(tonet.GetNet(), 0, zone.GetLayer(), coords[0][0] + int(offset[0]), coords[0][1] + int(offset[1]), pcbnew.CPolyLine.DIAGONAL_EDGE) newoutline = newzone.Outline() for pt in coords[1:]: newoutline.Append(int(pt[0] + offset[0]), int(pt[1] + offset[1])) newzone.Hatch()
def replicate_tracks(self, x_offset, y_offset, polar): """ method which replicates tracks""" global SCALE # start cloning for sheet in self.sheets_to_clone: sheet_index = self.sheets_to_clone.index(sheet) + 1 net_pairs, net_dict = self.get_net_pairs(sheet) # go through all the tracks for track in self.pivot_tracks: # get from which net we are clonning from_net_name = track.GetNetname() # find to net tup = [item for item in net_pairs if item[0] == from_net_name] # if net was not fount, then the track is not part of this sheet and should not be cloned if not tup: pass else: to_net_name = tup[0][1] to_net = net_dict[to_net_name] # finally make a copy # this came from Miles Mccoo, I only extended it with polar support # https://github.com/mmccoo/kicad_mmccoo/blob/master/replicatelayout/replicatelayout.py if track.GetClass() == "VIA": newvia = pcbnew.VIA(self.board) # need to add before SetNet will work, so just doing it first self.board.Add(newvia) toplayer = -1 bottomlayer = pcbnew.PCB_LAYER_ID_COUNT for l in range(pcbnew.PCB_LAYER_ID_COUNT): if not track.IsOnLayer(l): continue toplayer = max(toplayer, l) bottomlayer = min(bottomlayer, l) newvia.SetLayerPair(toplayer, bottomlayer) if polar: # get the pivot point pivot_point = (self.polar_center[0], self.polar_center[1] + x_offset * SCALE) newposition = rotate_around_pivot_point((track.GetPosition().x, track.GetPosition().y), pivot_point, sheet_index * y_offset) else: newposition = (track.GetPosition().x + sheet_index*x_offset*SCALE, track.GetPosition().y + sheet_index*y_offset*SCALE) # convert to tuple of integers newposition = [int(x) for x in newposition] newvia.SetPosition(pcbnew.wxPoint(*newposition)) newvia.SetViaType(track.GetViaType()) newvia.SetWidth(track.GetWidth()) newvia.SetDrill(track.GetDrill()) newvia.SetNet(to_net) else: newtrack = pcbnew.TRACK(self.board) # need to add before SetNet will work, so just doing it first self.board.Add(newtrack) if polar: # get the pivot point pivot_point = (self.polar_center[0], self.polar_center[1] + x_offset * SCALE) newposition = rotate_around_pivot_point((track.GetStart().x, track.GetStart().y), pivot_point, sheet_index * y_offset) # convert to tuple of integers newposition = [int(x) for x in newposition] newtrack.SetStart(pcbnew.wxPoint(*newposition)) newposition = rotate_around_pivot_point((track.GetEnd().x, track.GetEnd().y), pivot_point, sheet_index * y_offset) # convert to tuple of integers newposition = [int(x) for x in newposition] newtrack.SetEnd(pcbnew.wxPoint(*newposition)) else: newtrack.SetStart(pcbnew.wxPoint(track.GetStart().x + sheet_index*x_offset*SCALE, track.GetStart().y + sheet_index*y_offset*SCALE)) newtrack.SetEnd(pcbnew.wxPoint(track.GetEnd().x + sheet_index*x_offset*SCALE, track.GetEnd().y + sheet_index*y_offset*SCALE)) newtrack.SetWidth(track.GetWidth()) newtrack.SetLayer(track.GetLayer()) newtrack.SetNet(to_net)
def Run(self): board = pcbnew.GetBoard() tracks_selected = [] for track in board.GetTracks(): if track.IsSelected(): tracks_selected.append(track) if len(tracks_selected) != 2: msg = "Please select exact two tracks to create an arc." wx.MessageBox(msg, 'Error', wx.OK | wx.ICON_ERROR) return -1 # create parameter dialog (defaults hardcoded in wx python script) parameter_dialog = TrackArcGeneratorParameterDialog(None) button_result = parameter_dialog.ShowModal() # get values from parameter dialog arc_radius = float(parameter_dialog.input_radius.GetValue()) * 1000 n_circle_segments = float(parameter_dialog.input_segments.GetValue()) # destroy dialog handle parameter_dialog.Destroy() if button_result == wx.ID_OK: # track coordinates: [ [start_x, start_y], [end_x, end_y] ] track0 = [[ tracks_selected[0].GetStart().x, tracks_selected[0].GetStart().y ], [tracks_selected[0].GetEnd().x, tracks_selected[0].GetEnd().y]] track1 = [[ tracks_selected[1].GetStart().x, tracks_selected[1].GetStart().y ], [tracks_selected[1].GetEnd().x, tracks_selected[1].GetEnd().y]] track0_dist_to_intersect, track1_dist_to_intersect = self.calculate_line_intersect_point( track0, track1) # if intersect point is on origin or behind, change origin to far end point if track0_dist_to_intersect <= 0: track0 = [[ tracks_selected[0].GetEnd().x, tracks_selected[0].GetEnd().y ], [ tracks_selected[0].GetStart().x, tracks_selected[0].GetStart().y ]] if track1_dist_to_intersect <= 0: track1 = [[ tracks_selected[1].GetEnd().x, tracks_selected[1].GetEnd().y ], [ tracks_selected[1].GetStart().x, tracks_selected[1].GetStart().y ]] track0_dist_to_intersect, track1_dist_to_intersect = self.calculate_line_intersect_point( track0, track1) # normalize lines based on confirmed far end origin track0_orig, track0_dir, track0_phi, track0_len = self.twopointline_to_orig_dir_len( track0) track1_orig, track1_dir, track1_phi, track1_len = self.twopointline_to_orig_dir_len( track1) track0_dist_to_intersect = track0_dist_to_intersect * track0_len track1_dist_to_intersect = track1_dist_to_intersect * track1_len # calc arc angle arc_angle = math.pi - self.calc_intersect_angle( track0_dir, track1_dir) # construct first arc arc, segments_to_draw = self.construct_unit_arc( arc_angle, n_circle_segments, 0) # get arc end segment direction for side decision arc_end_orig, arc_end_dir, arc_end_phi, arc_end_len = self.twopointline_to_orig_dir_len( [arc[-2], arc[-1]]) # rotate it to target angle arc_end_dir = self.calc_coordinate_rotation( arc_end_dir, track0_phi) # get intersect angle and check arc_end_intersect_angle = self.calc_intersect_angle( arc_end_dir, track1_dir) if arc_end_intersect_angle < (math.pi * 3 / 4): arc, segments_to_draw = self.construct_unit_arc( arc_angle, n_circle_segments, 1) # rotate, scale and move to position relative to track0 origin for segment in range(0, segments_to_draw + 1): # scale arc[segment][0] = arc[segment][0] * arc_radius arc[segment][1] = arc[segment][1] * arc_radius # rotate arc[segment] = self.calc_coordinate_rotation( arc[segment], track0_phi) # place rounding_backoff_dist = arc_radius * math.tan(arc_angle / 2) arc[segment][0] = round( arc[segment][0] + track0_orig[0] + (track0_dist_to_intersect - rounding_backoff_dist) * track0_dir[0]) arc[segment][1] = round( arc[segment][1] + track0_orig[1] + (track0_dist_to_intersect - rounding_backoff_dist) * track0_dir[1]) # store information from old track and remove them track_width = tracks_selected[0].GetWidth() track_net = tracks_selected[0].GetNet() track_layer = tracks_selected[0].GetLayer() tracks_selected[0].DeleteStructure() tracks_selected[1].DeleteStructure() # add track segments according to coordinates # track0 origin to begin of arc track = pcbnew.TRACK(board) track.SetStart(pcbnew.wxPoint(track0_orig[0], track0_orig[1])) track.SetEnd(pcbnew.wxPoint(arc[0][0], arc[0][1])) track.SetWidth(track_width) track.SetLayer(track_layer) track.SetNet(track_net) board.Add(track) # track1 origin to end of arc track = pcbnew.TRACK(board) track.SetStart(pcbnew.wxPoint(track1_orig[0], track1_orig[1])) track.SetEnd(pcbnew.wxPoint(arc[-1][0], arc[-1][1])) track.SetWidth(track_width) track.SetLayer(track_layer) track.SetNet(track_net) board.Add(track) # arc segments for segment in range(0, segments_to_draw): track = pcbnew.TRACK(board) track.SetStart(pcbnew.wxPoint(arc[segment][0], arc[segment][1])) track.SetEnd( pcbnew.wxPoint(arc[segment + 1][0], arc[segment + 1][1])) track.SetWidth(track_width) track.SetLayer(track_layer) track.SetNet(track_net) board.Add(track) # update board pcbnew.Refresh() return 0 else: return 0
def replicate_tracks(self, pivot_anchor_mod, pivot_tracks, anchor_mod, net_pairs): logger.info("Replicating tracks") # get anchor angle with respect to pivot module anchor_angle = anchor_mod.mod.GetOrientationDegrees() # get exact anchor position anchor_pos = anchor_mod.mod.GetPosition() anchor_delta_angle = pivot_anchor_mod.mod.GetOrientationDegrees() - anchor_angle anchor_delta_pos = anchor_pos - pivot_anchor_mod.mod.GetPosition() net_pairs, net_dict = net_pairs # go through all the tracks for track in pivot_tracks: # get from which net we are clonning from_net_name = track.GetNetname() # find to net tup = [item for item in net_pairs if item[0] == from_net_name] # if net was not fount, then the track is not part of this sheet and should not be cloned if not tup: pass else: to_net_name = tup[0][1] to_net = net_dict[to_net_name] # finally make a copy # this came partially from Miles Mccoo # https://github.com/mmccoo/kicad_mmccoo/blob/master/replicatelayout/replicatelayout.py if track.GetClass() == "VIA": newvia = pcbnew.VIA(self.board) # need to add before SetNet will work, so just doing it first self.board.Add(newvia) toplayer = -1 bottomlayer = pcbnew.PCB_LAYER_ID_COUNT for l in range(pcbnew.PCB_LAYER_ID_COUNT): if not track.IsOnLayer(l): continue toplayer = max(toplayer, l) bottomlayer = min(bottomlayer, l) newvia.SetLayerPair(toplayer, bottomlayer) # get module to clone position pivot_track_pos = track.GetPosition() # get relative position with respect to pivot anchor pivot_anchor_pos = pivot_anchor_mod.mod.GetPosition() pivot_mod_delta_pos = pivot_track_pos - pivot_anchor_pos # new orientation is simple old_position = pivot_mod_delta_pos + anchor_pos newposition = rotate_around_pivot_point(old_position, anchor_pos, anchor_delta_angle) # convert to tuple of integers newposition = [int(x) for x in newposition] newvia.SetPosition(pcbnew.wxPoint(*newposition)) newvia.SetViaType(track.GetViaType()) newvia.SetWidth(track.GetWidth()) newvia.SetDrill(track.GetDrill()) newvia.SetNet(to_net) else: newtrack = pcbnew.TRACK(self.board) # need to add before SetNet will work, so just doing it first self.board.Add(newtrack) # get module to clone position pivot_track_pos = track.GetStart() # get relative position with respect to pivot anchor pivot_anchor_pos = pivot_anchor_mod.mod.GetPosition() pivot_mod_delta_pos = pivot_track_pos - pivot_anchor_pos # new orientation is simple old_position = pivot_mod_delta_pos + anchor_pos newposition = rotate_around_pivot_point(old_position, anchor_pos, anchor_delta_angle) newposition = [int(x) for x in newposition] newtrack.SetStart(pcbnew.wxPoint(*newposition)) pivot_track_pos = track.GetEnd() # get relative position with respect to pivot anchor pivot_anchor_pos = pivot_anchor_mod.mod.GetPosition() pivot_mod_delta_pos = pivot_track_pos - pivot_anchor_pos # new orientation is simple old_position = pivot_mod_delta_pos + anchor_pos newposition = rotate_around_pivot_point(old_position, anchor_pos, anchor_delta_angle) newposition = [int(x) for x in newposition] newtrack.SetEnd(pcbnew.wxPoint(*newposition)) newtrack.SetWidth(track.GetWidth()) newtrack.SetLayer(track.GetLayer()) newtrack.SetNet(to_net)
def addIntermediateTracks(): # most queries start with a board board = pcbnew.GetBoard() # returns a dictionary netcode:netinfo_item netcodes = board.GetNetsByNetcode() # list off all of the nets in the board. for netcode, net in netcodes.items(): #print("netcode {}, name {}".format(netcode, net.GetNetname())) tracks = board.TracksInNet( net.GetNet()) # get all the tracks in this net #add all the possible intersections to a unique set, for iterating over later intersections = set() for t1 in range(len(tracks)): for t2 in range(t1 + 1, len(tracks)): #check if these two tracks share an endpoint # reduce it to a 2-part tuple so there are not multiple objects of the same point in the set if (tracks[t1].IsPointOnEnds(tracks[t2].GetStart())): intersections.add( (tracks[t2].GetStart().x, tracks[t2].GetStart().y)) if (tracks[t1].IsPointOnEnds(tracks[t2].GetEnd())): intersections.add( (tracks[t2].GetEnd().x, tracks[t2].GetEnd().y)) ipsToRemove = set() # remove all of the intersections which occur over an ECO1 (stiffener) zone # we are not worried about rounding these traces. for ip in intersections: (newX, newY) = ip if stiffened(board, pcbnew.wxPoint(newX, newY)): ipsToRemove.add(ip) for ip in ipsToRemove: #print("removing", ip) intersections.remove(ip) #for each remaining intersection, shorten each track by the same amount, and place a track between. tracksToAdd = set() tracksToShorten = set() for ip in intersections: (newX, newY) = ip intersection = pcbnew.wxPoint(newX, newY) tracksHere = [] for t1 in tracks: # it seems vias are treated as tracks ???? this should take care of that if (t1.GetLength() > 0): if similarPoints(t1.GetStart(), intersection): tracksHere.append(t1) if similarPoints(t1.GetEnd(), intersection): #flip track such that all tracks start at the IP reverseTrack(t1) tracksHere.append(t1) # sometimes tracksHere is empty ??? if len(tracksHere) == 0: continue #sort tracks by length, just to find the shortest tracksHere.sort(key=GetTrackLength) #shorten all tracks by the same length, which is a function of existing shortest path length shortenLength = min(tracksHere[0].GetLength() * MAXLENGTH, SCALING * SCALE) #sort these tracks by angle, so new tracks can be drawn between them tracksHere.sort(key=getTrackAngle) #shorten all these tracks for t1 in range(len(tracksHere)): shortenTrack(tracksHere[t1], shortenLength) #connect the new startpoints in a circle around the old center point for t1 in range(len(tracksHere)): #dont add 2 new tracks in the 2 track case if not (len(tracksHere) == 2 and t1 == 1): newPoint1 = cloneWxPoint(tracksHere[t1].GetStart()) newPoint2 = cloneWxPoint( tracksHere[(t1 + 1) % len(tracksHere)].GetStart()) tracksToAdd.add( (newPoint1, newPoint2, tracksHere[t1].GetWidth(), tracksHere[t1].GetLayer(), tracksHere[t1].GetNet())) #add all the new tracks in post, so as not to cause problems with set iteration for trackpoints in tracksToAdd: (sp, ep, width, layer, net) = trackpoints track = pcbnew.TRACK(board) track.SetStart(sp) track.SetEnd(ep) track.SetWidth(width) track.SetLayer(layer) board.Add(track) track.SetNet(net)
def addIntermediateTracks( self, board, maxlength = 0.5, scaling = 0.5, netclass = None): MAXLENGTH = maxlength # % of length of track used for the arc SCALING = scaling # radius SCALE = 1000000.0 # returns a dictionary netcode:netinfo_item netcodes = board.GetNetsByNetcode() # list off all of the nets in the board. for netcode, net in netcodes.items(): # print(net.GetName(), net.GetClassName()) if netclass is not None and netclass == net.GetClassName(): #print("netcode {}, name {}".format(netcode, net.GetNetname())) allTracks = board.TracksInNet(net.GetNet()) # get all the tracks in this net tracksPerLayer = {} # separate track by layer for t in allTracks: layer = t.GetLayer() if t.GetStart() != t.GetEnd(): # ignore vias if layer not in tracksPerLayer: tracksPerLayer[layer] = [] tracksPerLayer[layer].append(t) for layer in tracksPerLayer: tracks = tracksPerLayer[layer] #add all the possible intersections to a unique set, for iterating over later intersections = set(); endings = set(); for t1 in range(len(tracks)): for t2 in range(t1+1, len(tracks)): #check if these two tracks share an endpoint # reduce it to a 2-part tuple so there are not multiple objects of the same point in the set if(tracks[t1].GetLayer() == tracks[t2].GetLayer()): if(tracks[t1].IsPointOnEnds(tracks[t2].GetStart())): intersections.add((tracks[t2].GetStart().x, tracks[t2].GetStart().y)) if(tracks[t1].IsPointOnEnds(tracks[t2].GetEnd())): intersections.add((tracks[t2].GetEnd().x, tracks[t2].GetEnd().y)) #for each remaining intersection, shorten each track by the same amount, and place a track between. tracksToAdd = [] tracksToShorten = set() for ip in intersections: (newX, newY) = ip; intersection = pcbnew.wxPoint(newX, newY) tracksHere = []; for t1 in tracks: # it seems vias are treated as tracks ???? this should take care of that if(t1.GetLength() > 0): if similarPoints(t1.GetStart(), intersection): tracksHere.append(t1) if similarPoints(t1.GetEnd(), intersection): #flip track such that all tracks start at the IP reverseTrack(t1) tracksHere.append(t1) # sometimes tracksHere is empty ??? if len(tracksHere) == 0: continue #sort tracks by length, just to find the shortest tracksHere.sort(key = GetTrackLength) #shorten all tracks by the same length, which is a function of existing shortest path length shortenLength = min(tracksHere[0].GetLength() * MAXLENGTH, SCALING*SCALE) #sort these tracks by angle, so new tracks can be drawn between them tracksHere.sort(key = getTrackAngle) #shorten all these tracks for t1 in range(len(tracksHere)): shortenTrack(tracksHere[t1], shortenLength) #connect the new startpoints in a circle around the old center point for t1 in range(len(tracksHere)): #dont add 2 new tracks in the 2 track case if not (len(tracksHere) == 2 and t1 == 1): newPoint1 = cloneWxPoint(tracksHere[t1].GetStart()) newPoint2 = cloneWxPoint(tracksHere[(t1+1)%len(tracksHere)].GetStart()) tracksToAdd.append((newPoint1, newPoint2, tracksHere[t1].GetWidth(), tracksHere[t1].GetLayer(), tracksHere[t1].GetNet())) #add all the new tracks in post, so as not to cause problems with set iteration for trackpoints in tracksToAdd: (sp, ep, width, layer, net) = trackpoints track = pcbnew.TRACK(board) track.SetStart(sp) track.SetEnd(ep) track.SetWidth(width) track.SetLayer(layer) board.Add(track) track.SetNet(net)
def GenMSTRoutes(nets, mods, layername): board = pcbnew.GetBoard() # force that nets and mods are sets. nets = Set(nets) mods = Set(mods) # generate a name->layer table so we can lookup layer numbers by name. layertable = {} numlayers = pcbnew.PCB_LAYER_ID_COUNT for i in range(numlayers): layertable[pcbnew.GetBoard().GetLayerName(i)] = i layer = layertable[layername] netpts = {} for mod in board.GetModules(): if (mod.GetReference() not in mods): continue for pad in mod.Pads(): if (pad.GetLayerName() != layername): continue netname = pad.GetNet().GetNetname() if (netname not in nets): continue if (netname not in netpts): netpts[netname] = [] netpts[netname].append(tuple(pad.GetCenter())) for via in board.GetTracks(): if not pcbnew.VIA.ClassOf(via): continue if (via.BottomLayer() != layer) and (via.TopLayer() != layer): continue netname = via.GetNet().GetNetname() if (netname not in nets): continue if (netname not in netpts): netpts[netname] = [] netpts[netname].append(tuple(via.GetPosition())) nettable = board.GetNetsByName() for netname in netpts: if (netname not in nets): continue pts = netpts[netname] matrix = np.zeros(shape=[len(pts), len(pts)]) tri = Delaunay(np.array(pts)) for simp in tri.simplices: (a, b, c) = simp matrix[a][b] = numpy.hypot(*numpy.subtract(pts[a], pts[b])) matrix[b][c] = numpy.hypot(*numpy.subtract(pts[b], pts[c])) matrix[c][a] = numpy.hypot(*numpy.subtract(pts[c], pts[a])) X = csr_matrix(matrix) Tcsr = minimum_spanning_tree(X) net = nettable[netname] nc = net.GetNetClass() #print("for net {}".format(net.GetNetname())) # info about iterating the results: # https://stackoverflow.com/a/4319087/23630 rows, cols = Tcsr.nonzero() for row, col in zip(rows, cols): #print(" {} - {}".format(pts[row], pts[col])) newtrack = pcbnew.TRACK(board) # need to add before SetNet will work, so just doing it first board.Add(newtrack) newtrack.SetNet(net) newtrack.SetStart(pcbnew.wxPoint(*pts[row])) newtrack.SetEnd(pcbnew.wxPoint(*pts[col])) newtrack.SetWidth(nc.GetTrackWidth()) newtrack.SetLayer(layer)
def generate(): # generate a LUT with shape integers to a string #padshapes = { # pcbnew.PAD_SHAPE_CIRCLE: "PAD_SHAPE_CIRCLE", # pcbnew.PAD_SHAPE_OVAL: "PAD_SHAPE_OVAL", # pcbnew.PAD_SHAPE_RECT: "PAD_SHAPE_RECT", # pcbnew.PAD_SHAPE_TRAPEZOID: "PAD_SHAPE_TRAPEZOID" #} ## new in the most recent kicad code #if hasattr(pcbnew, 'PAD_SHAPE_ROUNDRECT'): # padshapes[pcbnew.PAD_SHAPE_ROUNDRECT] = "PAD_SHAPE_ROUNDRECT" board = pcbnew.GetBoard() tracksToAdd = set() tracksToDelete = set() # get all "modules", seemingly identical to footprints for mod in board.GetModules(): #print(mod.GetReference()) #get all pads on this module for pad in mod.Pads(): #print("pad {}({}) on {}({}) at {},{} shape {} size {},{}" # .format(pad.GetPadName(), # pad.GetNet().GetNetname(), # mod.GetReference(), # mod.GetValue(), # pad.GetPosition().x, pad.GetPosition().y, # padshapes[pad.GetShape()], # pad.GetSize().x, pad.GetSize().y #)) # for simplicity, only consider the bounding box of the pad # future improved versions of the code should account for rotated pads and strange geometries boundingBox = pad.GetBoundingBox() # get all the tracks in this net tracks = board.TracksInNet(pad.GetNet().GetNet()) for track in tracks: # it seems vias are treated as tracks ???? this should take care of that if (track.GetLength() > 0): #angle = abs(normalizeAngleHalf(getTrackAngle(track) - pad.GetOrientationRadians())); # keep angle [-pi/2,pi/2] because start and end are placed arbitrarily # because we are using "bounding box", the orientation of the pad is already accounted for angle = abs(normalizeAngleHalf(getTrackAngle(track))) # if this track is the same layer, and has an endpoint within the bounding box of the pad, create 3 new traces, one to either side of the bounding box and one in the center # reverse this track if the endpoint is on the pad if (pad.HitTest(track.GetEnd())): reverseTrack(track) # if track and pad are on the same layer, intersect, and are not over stiffener material, make 3 new traces if (track.GetLayer() == pad.GetLayer() and pad.HitTest(track.GetStart()) and not stiffened(board, track.GetStart())): #print("intersect at start ", track.GetStart()) if (angle > math.pi / 4): # shorten this track by the X-dimension of the pad sp = shortenTrack(track, boundingBox.GetHeight() * .7) #if the new track is length 0, slate it for deletion if (track.GetLength() == 0): tracksToDelete.add(track) tracksToAdd.add((cloneWxPoint(sp), pcbnew.wxPoint( boundingBox.GetRight() - track.GetWidth() / 2, boundingBox.GetCenter().y), track.GetWidth(), pad.GetLayer(), pad.GetNet())) tracksToAdd.add((cloneWxPoint(sp), pcbnew.wxPoint( boundingBox.GetLeft() + track.GetWidth() / 2, boundingBox.GetCenter().y), track.GetWidth(), pad.GetLayer(), pad.GetNet())) tracksToAdd.add( (cloneWxPoint(sp), cloneWxPoint(boundingBox.GetCenter()), track.GetWidth(), pad.GetLayer(), pad.GetNet())) else: # shorten this track by the Y-dimension of the pad sp = shortenTrack(track, boundingBox.GetWidth() * .7) #if the new track is length 0, slate it for deletion if (track.GetLength() == 0): tracksToDelete.add(track) tracksToAdd.add( (cloneWxPoint(sp), pcbnew.wxPoint( boundingBox.GetCenter().x, boundingBox.GetTop() + track.GetWidth() / 2), track.GetWidth(), pad.GetLayer(), pad.GetNet())) tracksToAdd.add( (cloneWxPoint(sp), pcbnew.wxPoint( boundingBox.GetCenter().x, boundingBox.GetBottom() - track.GetWidth() / 2), track.GetWidth(), pad.GetLayer(), pad.GetNet())) tracksToAdd.add( (cloneWxPoint(sp), cloneWxPoint(boundingBox.GetCenter()), track.GetWidth(), pad.GetLayer(), pad.GetNet())) #add all the tracks in post, so as not to cause problems with set iteration for trackpoints in tracksToAdd: (sp, ep, width, layer, net) = trackpoints track = pcbnew.TRACK(board) track.SetStart(sp) track.SetEnd(ep) track.SetWidth(width) track.SetLayer(layer) board.Add(track) track.SetNet(net) for track in tracksToDelete: board.Remove(track)