def __init__(self, nx, ny, pitch, xpitch, ypitch, pin1Pos): #left row pin1Pos = pcbnew.wxPoint(-h_pitch / 2, -row_len / 2) array = PadLineArray(h_pad, pads_per_row, pad_pitch, True, pin1Pos) array.SetFirstPadInArray(1) array.AddPadsToModule() #bottom row pin1Pos = pcbnew.wxPoint(-row_len / 2, v_pitch / 2) array = PA.PadLineArray(v_pad, pads_per_row, pad_pitch, False, pin1Pos) array.SetFirstPadInArray(pads_per_row + 1) array.AddPadsToModule() #right row pin1Pos = pcbnew.wxPoint(h_pitch / 2, row_len / 2) array = PadLineArray(h_pad, pads_per_row, -pad_pitch, True, pin1Pos) array.SetFirstPadInArray(2*pads_per_row + 1) array.AddPadsToModule() #top row pin1Pos = pcbnew.wxPoint(row_len / 2, -v_pitch / 2) array = PadLineArray(v_pad, pads_per_row, -pad_pitch, False, pin1Pos) array.SetFirstPadInArray(3*pads_per_row + 1) array.AddPadsToModule()
def BuildThisFootprint(self): pads = self.parameters["Pads"] name = self.parameters["FootprintName"] ipc = self.parameters["IPC"] _module_prefix = name["*Prefix"] _pad_pitch = pads["Pitch"] _pad_length = pads["Pad length"] _pad_width = pads["Pad width"] _v_pitch = pads["Vertical pitch"] _h_pitch = pads["Horizontal pitch"] _family = pads["*Family: SOT23, SOT89, SOT143, SOT223, SOTFL"] _density = ipc["*Density, M(Most), N(Nominal), L(Least)"] _pin1mark = ipc["Pin 1 mark, c(circle), l(line)"] self.DrawOriginGravityCenter() self.DrawPinOneMark(_pin1mark) self.CheckNoPins() _padDimentions = self.CalculatePadDimentions(_density, _family) _toePos = 0 _heelPos = 1 _sidePos = 2 _roundOffPos = 3 _courtyardPos = 4 # Get the number of pins _pinsNo = self.CheckNoPins(self.parameters["Pads"]["*n"]) if _pinsNo % 2 == 0: # even number of pins _pads_left_row = _pinsNo // 2 _pads_right_row = _pinsNo // 2 # Calculate the length of both sides of the IC _left_row_len = (_pads_left_row - 1) * _pad_pitch _right_row_len = _left_row_len else: # odd number of pins _pads_left_row = pads["*n"] - 1 _pads_right_row = 1 # Calculate the length of both sides of the IC _left_row_len = (_pads_left_row - 1) * _pad_pitch _right_row_len = 1 # Oval pad shape is IPC recommended left_pad = PA.PadMaker(self.module).SMDPad(_pad_width, _pad_length, shape = pcbnew.PAD_SHAPE_OVAL) right_pad = PA.PadMaker(self.module).SMDPad(_pad_width, _pad_length, shape = pcbnew.PAD_SHAPE_OVAL) ############################################################################################### #left row _pin1Pos = pcbnew.wxPoint(- _h_pitch / 2, 0) _array = PA.PadLineArray(_h_pad, _pads_per_row, _pad_pitch, True, _pin1Pos) _array.SetFirstPadInArray(1) _array.AddPadsToModule(self.draw) #right row _pin1Pos = pcbnew.wxPoint(_h_pitch / 2, 0)
def BuildThisFootprint(self): pads = self.parameters["Pads"] pad_pitch = pads["pad pitch"] pad_length = self.parameters["Pads"]["pad length"] pad_width = self.parameters["Pads"]["pad width"] v_pitch = pads["vertical pitch"] h_pitch = pads["horizontal pitch"] pads_per_row = pads["*n"] // 4 row_len = (pads_per_row - 1) * pad_pitch pad_shape = pcbnew.PAD_OVAL if pads["*oval"] else pcbnew.PAD_RECT h_pad = PA.PadMaker(self.module).SMDPad(pad_width, pad_length, shape = pad_shape) v_pad = PA.PadMaker(self.module).SMDPad(pad_length, pad_width, shape = pad_shape) #left row pin1Pos = pcbnew.wxPoint(-h_pitch / 2, -row_len / 2) array = PA.PadLineArray(h_pad, pads_per_row, pad_pitch, True, pin1Pos) array.SetFirstPadInArray(1) array.AddPadsToModule() #bottom row pin1Pos = pcbnew.wxPoint(-row_len / 2, v_pitch / 2) array = PA.PadLineArray(v_pad, pads_per_row, pad_pitch, False, pin1Pos) array.SetFirstPadInArray(pads_per_row + 1) array.AddPadsToModule() #right row pin1Pos = pcbnew.wxPoint(h_pitch / 2, row_len / 2) array = PA.PadLineArray(h_pad, pads_per_row, -pad_pitch, True, pin1Pos) array.SetFirstPadInArray(2*pads_per_row + 1) array.AddPadsToModule() #top row pin1Pos = pcbnew.wxPoint(row_len / 2, -v_pitch / 2) array = PA.PadLineArray(v_pad, pads_per_row, -pad_pitch, False, pin1Pos) array.SetFirstPadInArray(3*pads_per_row + 1) array.AddPadsToModule() limX = pads["package width"] / 2 limY = pads["package height"] / 2 inner = (row_len / 2) + pad_pitch #top left - diagonal self.draw.Line(-limX, -inner, -inner, -limY) # top right self.draw.Polyline([(inner, -limY), (limX, -limY), (limX, -inner)]) # bottom left self.draw.Polyline([(-inner, limY), (-limX, limY), (-limX, inner)]) # bottom right self.draw.Polyline([(inner, limY), (limX, limY), (limX, inner)])
def Line(self, x1, y1, x2, y2): outline = pcbnew.EDGE_MODULE(self.module) outline.SetWidth(self.dc['width']) outline.SetLayer(self.dc['layer']) outline.SetShape(pcbnew.S_SEGMENT) start = pcbnew.wxPoint(x1, y1) end = pcbnew.wxPoint(x2, y2) outline.SetStartEnd(start, end) self.module.Add(outline)
def drawSquareArea( self, layer, size, xposition, yposition): # creates a EDGE_MODULE of polygon type. The polygon is a square polygon = pcbnew.EDGE_MODULE(self.module) polygon.SetShape(pcbnew.S_POLYGON) polygon.SetWidth( 0 ) polygon.SetLayer(layer) halfsize = size/2 pos = pcbnew.wxPoint(xposition, yposition) polygon.GetPolyPoints().push_back( pcbnew.wxPoint( halfsize, halfsize ) + pos ) polygon.GetPolyPoints().push_back( pcbnew.wxPoint( halfsize, -halfsize ) + pos ) polygon.GetPolyPoints().push_back( pcbnew.wxPoint( -halfsize, -halfsize ) + pos ) polygon.GetPolyPoints().push_back( pcbnew.wxPoint( -halfsize, halfsize ) + pos ) return polygon
def BuildThisFootprint(self): if self.border >= 0: # Adding border: Create a new array larger than the self.qr.modules sz = self.qr.modules.__len__() + (self.border * 2) arrayToDraw = [ [ 0 for a in range(sz) ] for b in range(sz) ] lineposition = self.border for i in self.qr.modules: columnposition = self.border for j in i: arrayToDraw[lineposition][columnposition] = j columnposition += 1 lineposition += 1 else: # No border: using array as is arrayToDraw = self.qr.modules # used many times... half_number_of_elements = arrayToDraw.__len__() / 2 # Center position of QrCode yposition = - int(half_number_of_elements * self.X) for line in arrayToDraw: xposition = - int(half_number_of_elements * self.X) for pixel in line: # Trust table for drawing a pixel # Negative is a boolean; # each pixel is a boolean (need to draw of not) # Negative | Pixel | Result # 0 | 0 | 0 # 0 | 1 | 1 # 1 | 0 | 1 # 1 | 1 | 0 # => Draw as Xor if self.negative != pixel: # Xor... self._drawPixel(xposition, yposition) xposition += self.X yposition += self.X #int((5 + half_number_of_elements) * self.X)) textPosition = int((self.textHeight) + ((1 + half_number_of_elements) * self.X)) self.module.Value().SetPosition(pcbnew.wxPoint(0, - textPosition)) self.module.Value().SetTextHeight(self.textHeight) self.module.Value().SetTextWidth(self.textWidth) self.module.Value().SetThickness(self.textThickness) self.module.Reference().SetPosition(pcbnew.wxPoint(0, textPosition)) self.module.Reference().SetTextHeight(self.textHeight) self.module.Reference().SetTextWidth(self.textWidth) self.module.Reference().SetThickness(self.textThickness) self.module.Value().SetLayer(pcbnew.F_SilkS)
def plot_drill(self): board_name = os.path.splitext(os.path.basename(self.board.GetFileName()))[0] logger.info('Plotting drill file') drill_writer = pcbnew.EXCELLON_WRITER(self.board) drill_writer.SetMapFileFormat(pcbnew.PLOT_FORMAT_PDF) mirror = False minimalHeader = False offset = pcbnew.wxPoint(0, 0) merge_npth = True drill_writer.SetOptions(mirror, minimalHeader, offset, merge_npth) metric_format = True drill_writer.SetFormat(metric_format) generate_drill = True generate_map = True drill_writer.CreateDrillandMapFilesSet(self.build_directory, generate_drill, generate_map) drill_file_name = os.path.join( self.build_directory, '%s.drl' % (board_name,) ) map_file_name = os.path.join( self.build_directory, '%s-drl_map.pdf' % (board_name,) ) return drill_file_name, map_file_name
def BuildThisFootprint(self): pads = self.parameters["Pads"] rows = pads["*row count"] cols = pads["*column count"] pad_size = pads["pad size"] pad_size = pcbnew.wxSize(pad_size, pad_size) pad_pitch = pads["pad pitch"] # add in the pads pad = PA.PadMaker(self.module).SMTRoundPad(pads["pad size"]) pin1_pos = pcbnew.wxPoint(-((cols - 1) * pad_pitch) / 2, -((rows - 1) * pad_pitch) / 2) array = BGAPadGridArray(pad, cols, rows, pad_pitch, pad_pitch) array.AddPadsToModule(self.draw) #box ssx = -pin1_pos.x + pads["outline x margin"] ssy = -pin1_pos.y + pads["outline y margin"] self.draw.BoxWithDiagonalAtCorner(0, 0, ssx*2, ssy*2, pads["outline x margin"]) #reference and value text_size = pcbnew.FromMM(1.2) # IPC nominal self.draw.Value(0, - ssy - text_size, text_size) self.draw.Reference(0, ssy + text_size, text_size)
def BuildThisFootprint(self): prm = self.parameters['Pads'] pad_size = prm['pad width'] pad = PA.PadMaker(self.module).THPad( prm['pad width'], prm['pad width'], prm['drill']) array = PA.PadCircleArray( pad, prm['*n'], prm['circle diameter'] / 2, angle_offset=prm["*first pad angle"], centre=pcbnew.wxPoint(0, 0), clockwise=prm["*number clockwise"]) array.SetFirstPadInArray(prm["*first pad number"]) array.AddPadsToModule(self.draw) body_radius = (prm['circle diameter'] + prm['pad width'])/2 + self.draw.GetLineThickness() self.draw.Circle(0, 0, body_radius) text_size = self.GetTextSize() # IPC nominal thickness = self.GetTextThickness() textposy = body_radius + self.draw.GetLineThickness()/2 + self.GetTextSize()/2 + thickness self.draw.Value( 0, textposy, text_size ) self.draw.Reference( 0, -textposy, text_size )
def __init__(self, pad, n, pitch, isVertical, centre=pcbnew.wxPoint(0, 0)): if isVertical: PadGridArray.__init__(self, pad, 1, n, 0, pitch, centre) else: PadGridArray.__init__(self, pad, n, 1, pitch, 0, centre)
def Value(self, x, y, size): """ As for references, draw the module's value """ text_size = pcbnew.wxSize(size, size) self.module.Value().SetPos0(pcbnew.wxPoint(x, y)) self.module.Value().SetTextPosition(self.module.Value().GetPos0()) self.module.Value().SetSize(text_size)
def __init__(self, pad, nx, ny, px, py, centre=pcbnew.wxPoint(0, 0)): PadArray.__init__(self) # this pad is more of a "context", we will use it as a source of # pad data, but not actually add it self.pad = pad self.nx = int(nx) self.ny = int(ny) self.px = px self.py = py self.centre = centre
def placeComponentFamily(prefix, radius): for index in range(1,13): name = prefix + str(index) r = pcb.FindModuleByReference(name) angle = GetAngle(index) #print angle r.SetOrientation(int(angle * -10)) x = GetPositionX(angle, radius) y = GetPositionY(angle, radius) #print '{0},{1}'.format(x,y) r.SetPosition(pcbnew.wxPoint(x, y))
def __init__(self, pad, pad_count, line_count, line_pitch, pad_pitch, centre=pcbnew.wxPoint(0, 0)): PadArray.__init__(self) # this pad is more of a "context", we will use it as a source of # pad data, but not actually add it self.pad = pad self.pad_count = int(pad_count) self.line_count = int(line_count) self.line_pitch = line_pitch self.pad_pitch = pad_pitch self.centre = centre
def __init__(self, pad, n, r, angle_offset=0, centre=pcbnew.wxPoint(0, 0), clockwise=True): PadArray.__init__(self) # this pad is more of a "context", we will use it as a source of # pad data, but not actually add it self.pad = pad self.n = int(n) self.r = r self.angle_offset = angle_offset self.centre = centre self.clockwise = clockwise
def TransformPoint(self, x, y, mat=None): """ Return a point (x, y) transformed by the given matrix, or if that is not given, the drawing context transform """ if not mat: mat = self.dc['transform'] return pcbnew.wxPoint(x * mat[0] + y * mat[1] + mat[2], x * mat[3] + y * mat[4] + mat[5])
def Reference(self, x, y, size): """ Draw the module's reference as the given point. The actual setting of the reference is not done in this drawing aid - that is up to the wizard """ text_size = pcbnew.wxSize(size, size) self.module.Reference().SetPos0(pcbnew.wxPoint(x, y)) self.module.Reference().SetTextPosition(self.module.Reference().GetPos0()) self.module.Reference().SetSize(text_size)
def place_footprint(pcb, x, y, reference=None, i=None): # Place the switch fp = kicad.FootprintLoad(mx_lib, mx_part) pcb.Add(fp) fp.Rotate(pcbnew.wxPoint(0, 0), 1800) fp.SetPosition(pcbnew.wxPoint(x * spacing, y * spacing)) if reference is None: reference = "SW%d_%d" % (x, y) fp.SetReference(reference) fp.SetValue(reference) fp.SetLocked(True) # Place the diode fp = kicad.FootprintLoad(diode_lib, diode_part) pcb.Add(fp) fp.Rotate(pcbnew.wxPoint(0, 0), 2700) fp.SetPosition(pcbnew.wxPoint(x * spacing + diode_x_offset, y * spacing + diode_y_offset)) if i is not None: reference = "D%d" % (i) if reference is None: reference = "D%d_%d" % (x, y) fp.SetReference(reference) fp.SetValue(reference) fp.SetLocked(True)
def __init__(self, pad, n, pitch, isVertical, centre=pcbnew.wxPoint(0, 0)): """! @param pad: the prototypical pad @param n: number of pads in array @param pitch: distance between pad centres @param isVertical: horizontal or vertical array (can also use the drawing contexts transforms for more control) @param centre: array centre """ if isVertical: super(PadLineArray, self).__init__(pad, 1, n, 0, pitch, centre) else: super(PadLineArray, self).__init__(pad, n, 1, pitch, 0, centre)
def BuildThisFootprint(self): pads = self.parameters["Pads"] num_pads = pads["*n"] pad_length = pads["pad length"] pad_width = pads["pad width"] row_pitch = pads["row spacing"] pad_pitch = pads["pad pitch"] num_rows = pads["*row count"] pads_per_row = num_pads // num_rows row_length = pad_pitch * (pads_per_row - 1) # fenceposts # add in the pads pad = self.GetPad() pin1_pos = pcbnew.wxPoint( -((num_rows - 1) * row_pitch) / 2, -row_length / 2) array = RowedGridArray(pad, num_rows, pads_per_row, row_pitch, pad_pitch) array.AddPadsToModule(self.draw) # draw the Silk Screen pad_length = pads["pad length"] pad_width = pads["pad width"] ssx_offset = -pad_length / 2 - pads["outline x margin"] ssy_offset = -pad_width / 2 - pads["outline y margin"] if pads["*silk screen inside"]: ssx_offset *= -1 ssx = -pin1_pos.x - ssx_offset ssy = -pin1_pos.y - ssy_offset self.DrawBox(ssx, ssy) #reference and value text_size = pcbnew.FromMM(1.2) # IPC nominal self.draw.Value(0, - ssy - text_size, text_size) self.draw.Reference(0, ssy + text_size, text_size)
def BuildThisFootprint(self): pads = self.parameters["Pads"] rows = pads["*row count"] cols = pads["*column count"] pad_size = pads["pad size"] pad_size = pcbnew.wxSize(pad_size, pad_size) pad_pitch = pads["pad pitch"] # add in the pads pad = PA.PadMaker(self.module).SMTRoundPad(pads["pad size"]) pin1_pos = pcbnew.wxPoint(-((cols - 1) * pad_pitch) / 2, -((rows - 1) * pad_pitch) / 2) array = BGAPadGridArray(pad, cols, rows, pad_pitch, pad_pitch) array.AddPadsToModule(self.draw) #box ssx = -pin1_pos.x + pads["outline x margin"] ssy = -pin1_pos.y + pads["outline y margin"] self.draw.BoxWithDiagonalAtCorner(0, 0, ssx*2, ssy*2, pads["outline x margin"]) # Courtyard cmargin = self.draw.GetLineThickness() self.draw.SetLayer(pcbnew.F_CrtYd) sizex = (ssx + cmargin) * 2 sizey = (ssy + cmargin) * 2 # round size to nearest 0.1mm, rectangle will thus land on a 0.05mm grid sizex = self.PutOnGridMM(sizex, 0.1) sizey = self.PutOnGridMM(sizey, 0.1) # set courtyard line thickness to the one defined in KLC self.draw.SetLineThickness(pcbnew.FromMM(0.05)) self.draw.Box(0, 0, sizex, sizey) # restore line thickness to previous value self.draw.SetLineThickness(pcbnew.FromMM(cmargin)) #reference and value text_size = self.GetTextSize() # IPC nominal ypos = ssy + text_size self.draw.Value(0, ypos, text_size) self.draw.Reference(0, -ypos, text_size) # set SMD attribute self.module.SetAttributes(pcbnew.MOD_CMS)
def BuildThisFootprint(self): pads = self.parameters['Pads'] numbering = self.parameters['Numbering'] outline = self.parameters['Outline'] padRotation = self.parameters['Pad rotation'] pad_size = pads['diameter'] pad_shape = pcbnew.PAD_SHAPE_RECT if pads["rectangle"] else pcbnew.PAD_SHAPE_OVAL pad = PA.PadMaker(self.module).THPad(pads['diameter'], pads['diameter'], pads['drill'], shape=pad_shape) array = PA.PadCircleArray( pad, pads['count'], pads['center diameter'] / 2, angle_offset=pads["angle"], centre=pcbnew.wxPoint(0, 0), clockwise=numbering["clockwise"], padRotationEnable= padRotation["pad rotation"], padRotationOffset = padRotation["pad angle offset"]) array.SetFirstPadInArray(numbering["initial"]) array.AddPadsToModule(self.draw) # Draw the outline body_radius = outline['diameter'] / 2 self.draw.SetLayer(pcbnew.F_Fab) self.draw.SetLineThickness( pcbnew.FromMM( 0.1 ) ) #Default per KLC F5.2 as of 12/2018 self.draw.Circle(0, 0, body_radius) #silkscreen body_radius += pcbnew.FromMM(0.12) self.draw.SetLineThickness( pcbnew.FromMM( 0.12 ) ) #Default per KLC F5.1 as of 12/2018 self.draw.SetLayer(pcbnew.F_SilkS) self.draw.Circle(0, 0, body_radius) # courtyard self.draw.SetLayer(pcbnew.F_CrtYd) self.draw.SetLineThickness(pcbnew.FromMM(0.05)) self.draw.Circle(0, 0, body_radius + outline['margin']) # Text size text_size = self.GetTextSize() # IPC nominal thickness = self.GetTextThickness() textposy = body_radius + self.draw.GetLineThickness()/2 + self.GetTextSize()/2 + thickness + + outline['margin'] self.draw.Value( 0, textposy, text_size ) self.draw.Reference( 0, -textposy, text_size )
def TransformPoint(self, x, y, mat=None): """! Return a point (x, y) transformed by the given matrix, or if that is not given, the drawing context transform @param x: the x co-ordinate of the point to transform @param y: the y co-ordinate of the point to transform @param mat: the transform matrix to use or None to use the current DC's @return: the transformed point as a wxPoint """ if not mat: mat = self.dc['transform'] return pcbnew.wxPoint(x * mat[0] + y * mat[1] + mat[2], x * mat[3] + y * mat[4] + mat[5])
def __init__(self, pad, nx, ny, px, py, centre=pcbnew.wxPoint(0, 0)): """! @param pad: the prototypical pad of the array @param nx: number of pads in x-direction @param ny: number of pads in y-direction @param px: pitch in x-direction @param py: pitch in y-direction @param centre: array centre point """ super(PadGridArray, self).__init__(pad) self.nx = int(nx) self.ny = int(ny) self.px = px self.py = py self.centre = centre
def __init__(self, pad, pad_count, line_count, line_pitch, pad_pitch, centre=pcbnew.wxPoint(0, 0)): """! @param pad: the prototypical pad @param pad_count: total pad count @param line_count: number of staggered lines @param line_pitch: distance between lines @param pad_pitch: distance between pads in a line @param centre: array centre point """ super(PadZGridArray, self).__init__(pad) self.pad_count = int(pad_count) self.line_count = int(line_count) self.line_pitch = line_pitch self.pad_pitch = pad_pitch self.centre = centre
def _drawPixel(self, xposition, yposition): # build a rectangular pad as a dot on copper layer, # and a polygon (a square) on silkscreen if self.UseCu: pad = pcbnew.D_PAD(self.module) pad.SetSize(pcbnew.wxSize(self.X, self.X)) pad.SetPosition(pcbnew.wxPoint(xposition,yposition)) pad.SetShape(pcbnew.PAD_SHAPE_RECT) pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD) pad.SetName("") layerset = pcbnew.LSET() layerset.AddLayer(pcbnew.F_Cu) layerset.AddLayer(pcbnew.F_Mask) pad.SetLayerSet( layerset ) self.module.Add(pad) if self.UseSilkS: polygon=self.drawSquareArea(pcbnew.F_SilkS, self.X, xposition, yposition) self.module.Add(polygon)
def AddPadsToModule(self): for x in range(0, self.nx): for y in range(self.ny): posX = self.pin1Pos.x + (self.px * x) posY = self.pin1Pos.y + (self.py * y) pos = pcbnew.wxPoint(posX, posY) # create a new pad with same characteristics pad = self.pad.Duplicate() pad.SetPos0(pos) pad.SetPosition(pos) pad.SetPadName(str(self.NamingFunction(x,y))) self.AddPad(pad)
def AddPadsToModule(self): for x in range(0, self.nx): for y in range(self.ny): posX = self.pin1Pos.x + (self.px * x) posY = self.pin1Pos.y + (self.py * y) pos = pcbnew.wxPoint(posX, posY) # THIS DOESN'T WORK yet! #pad = self.pad.Clone() pad = self.ClonePad() pad.SetPos0(pos) pad.SetPosition(pos) pad.SetPadName(str(self.NamingFunction(x,y))) self.AddPad(pad)
def BuildThisFootprint(self): pads = self.parameters['Pads'] numbering = self.parameters['Numbering'] outline = self.parameters['Outline'] pad_size = pads['diameter'] pad = PA.PadMaker(self.module).THPad(pads['diameter'], pads['diameter'], pads['drill']) array = PA.PadCircleArray( pad, pads['count'], pads['center diameter'] / 2, angle_offset=pads["angle"], centre=pcbnew.wxPoint(0, 0), clockwise=numbering["clockwise"]) array.SetFirstPadInArray(numbering["initial"]) array.AddPadsToModule(self.draw) # Draw the outline body_radius = outline['diameter'] / 2 self.draw.SetLayer(pcbnew.F_Fab) self.draw.GetLineThickness() self.draw.Circle(0, 0, body_radius) #silkscreen body_radius += pcbnew.FromMM(0.15) self.draw.SetLayer(pcbnew.F_SilkS) self.draw.Circle(0, 0, body_radius) # courtyard self.draw.SetLayer(pcbnew.F_CrtYd) self.draw.SetLineThickness(pcbnew.FromMM(0.05)) self.draw.Circle(0, 0, body_radius + outline['margin']) # Text size text_size = self.GetTextSize() # IPC nominal thickness = self.GetTextThickness() textposy = body_radius + self.draw.GetLineThickness()/2 + self.GetTextSize()/2 + thickness + + outline['margin'] self.draw.Value( 0, textposy, text_size ) self.draw.Reference( 0, -textposy, text_size )
def get_via_module(board, drill, diameter, net): n = 'VIA-{}-{}'.format(fmt(drill), fmt(diameter)) # instantiate new module m = pcbnew.MODULE(board) m.SetReference('REF**') m.SetValue(n) m.SetLastEditTime(pcbnew.GetNewTimeStamp()) # adjust reference and value display settings r = m.Reference() r.SetVisible(False) r.SetTextSize(pcbnew.wxSize(mm2kicad(0.3), mm2kicad(0.3))) r.SetThickness(mm2kicad(0.075)) v = m.Value() v.SetVisible(False) v.SetTextSize(pcbnew.wxSize(mm2kicad(0.3), mm2kicad(0.3))) v.SetThickness(mm2kicad(0.075)) #v.SetLayer() # TODO: Move value to F.Fab layer (F.SilkS is default) lib_id = pcbnew.LIB_ID(n) m.SetFPID(lib_id) # create through-hole pad pad = pcbnew.D_PAD(m) pad.SetPadName('1') pad.SetNet(net) pad.SetPosition(pcbnew.wxPoint(0, 0)) pad.SetShape(pcbnew.PAD_SHAPE_CIRCLE) pad.SetSize(pcbnew.wxSize(diameter, diameter)) pad.SetDrillShape(pcbnew.PAD_DRILL_SHAPE_CIRCLE) pad.SetDrillSize(pcbnew.wxSize(drill, drill)) pad.SetLayerSet(pcbnew.LSET.AllCuMask()) pad.SetZoneConnection(pcbnew.PAD_ZONE_CONN_FULL) # add pad to module m.Add(pad) return m
def makeMouseBites(self, cuts, diameter, spacing, offset=fromMm(0.25)): """ Take a list of cuts and perform mouse bites. """ bloatedSubstrate = prep( self.boardSubstrate.substrates.buffer(fromMm(0.01))) for cut in cuts: cut = cut.simplify( fromMm(0.001)) # Remove self-intersecting geometry offsetCut = cut.parallel_offset(offset, "left") length = offsetCut.length count = int(length / spacing) + 1 for i in range(count): if count == 1: hole = offsetCut.interpolate(0.5, normalized=True) else: hole = offsetCut.interpolate(i * length / (count - 1)) if bloatedSubstrate.intersects(hole.buffer(0.8 * diameter / 2)): self.addNPTHole(wxPoint(hole.x, hole.y), diameter)
def BuildThisFootprint(self): prm = self.parameters['Pads'] pad_size = prm['pad width'] pad = PA.PadMaker(self.module).THPad( prm['pad width'], prm['pad width'], prm['drill']) array = PA.PadCircleArray( pad, prm['*n'], prm['circle diameter'] / 2, angle_offset=prm["*first pad angle"], centre=pcbnew.wxPoint(0, 0), clockwise=prm["*number clockwise"]) array.SetFirstPadInArray(prm["*first pad number"]) array.AddPadsToModule(self.draw)
def get_modules_bounding_box(self, modules): # get the pivot bounding box bounding_box = modules[0].mod.GetFootprintRect() top = bounding_box.GetTop() bottom = bounding_box.GetBottom() left = bounding_box.GetLeft() right = bounding_box.GetRight() for mod in modules: mod_box = mod.mod.GetFootprintRect() top = min(top, mod_box.GetTop()) bottom = max(bottom, mod_box.GetBottom()) left = min(left, mod_box.GetLeft()) right = max(right, mod_box.GetRight()) position = pcbnew.wxPoint(left, top) size = pcbnew.wxSize(right - left, bottom - top) bounding_box = pcbnew.EDA_RECT(position, size) height = (bottom - top) / 1000000.0 width = (right - left) / 1000000.0 return height, width
def get_modules_bounding_box_center(self, modules): # get the pivot bounding box bounding_box = modules[0].mod.GetFootprintRect() top = bounding_box.GetTop() bottom = bounding_box.GetBottom() left = bounding_box.GetLeft() right = bounding_box.GetRight() for mod in modules: mod_box = mod.mod.GetFootprintRect() top = min(top, mod_box.GetTop()) bottom = max(bottom, mod_box.GetBottom()) left = min(left, mod_box.GetLeft()) right = max(right, mod_box.GetRight()) position = pcbnew.wxPoint(left, top) size = pcbnew.wxSize(right - left, bottom - top) bounding_box = pcbnew.EDA_RECT(position, size) pos_y = (bottom + top) / 2 pos_x = (right + left) / 2 return (pos_x, pos_y)
def __init__(self, first_pad, yoff, pad, nx, ny, px, py, centre=pcbnew.wxPoint(0, 0)): PA.PadArray.__init__(self) # this pad is more of a "context", we will use it as a source of # pad data, but not actually add it self.SetFirstPadType(first_pad) self.yoff = yoff self.pad = pad self.nx = int(nx) self.ny = int(ny) self.px = px self.py = py self.centre = centre
def __init__(self, aPad, aPadCount, aLineCount, aLinePitch, aPadPitch, aStagger=0, aCentre=pcbnew.wxPoint(0, 0)): """ @param aPad Template for all pads @param aPadCount Overall pad count @param aLineCount Number of lines @param aLinePitch distance between lines @param aPadPitch distance between pads @param aStagger X stagger value for all odd lines @param aCentre Center position """ super(PadStaggeredZGridArray, self).__init__(aPad) self.padCount = int(aPadCount) self.lineCount = int(aLineCount) self.linePitch = aLinePitch self.padPitch = aPadPitch self.stagger = aStagger self.centre = aCentre
def __init__(self, pad, nx, ny, px, py, centre=pcbnew.wxPoint(0, 0)): """! @param pad: the prototypical pad of the array @param nx: number of pads in x-direction @param ny: number of pads in y-direction @param px: pitch in x-direction @param py: pitch in y-direction @param centre: array centre point """ try: super().__init__(pad) except TypeError: super(PadGridArray, self).__init__(pad) self.nx = int(nx) self.ny = int(ny) self.px = px self.py = py self.centre = centre
def _drawQrPixel(self, xposition, yposition): # build a rectangular pad as a dot on copper layer, # and a polygon (a square) on silkscreen if self.UseCu: pad = pcbnew.D_PAD(self.module) pad.SetSize(pcbnew.wxSize(self.X, self.X)) pad_pos = pcbnew.wxPoint(xposition, yposition) pad.SetPosition(pad_pos) pad.SetPos0(pad_pos) pad.SetShape(pcbnew.PAD_SHAPE_RECT) pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD) pad.SetName("") layerset = pcbnew.LSET() layerset.AddLayer(pcbnew.F_Cu) pad.SetLayerSet(layerset) self.module.Add(pad) if self.UseSilkS: polygon = self.drawPixelSquareArea(pcbnew.F_SilkS, self.X, xposition, yposition) self.module.Add(polygon)
def createPad(self, number, name): top = number % 2 == 1 if self.omitPin(number): return None padTotalHeight = topPadHeight if top else bottomPadHeight padHeight = padTotalHeight - padVerticalOffset padSize = pcbnew.wxSize(padWidth, padHeight) padOneCenterX = pcbnew.FromMM(18 * 0.5 + 0.25) padTwoCenterX = padOneCenterX + pcbnew.FromMM(0.25) pad = pcbnew.D_PAD(self.module) layerSet = pcbnew.LSET() if top: # On the top, 0.0 is centered between pads 35 and 37. padOffset = (number - 1) / 2 padCenterX = padOneCenterX - pcbnew.FromMM(padOffset * 0.5) layerSet.AddLayer(pcbnew.F_Cu) else: # On the bottom, 0.0 is the center of pad 36. padOffset = (number) / 2 padCenterX = padTwoCenterX - pcbnew.FromMM(padOffset * 0.5) layerSet.AddLayer(pcbnew.B_Cu) padCenterY = -(padVerticalOffset + padHeight / 2.0) padCenter = pcbnew.wxPoint(padCenterX, padCenterY) pad.SetSize(padSize) pad.SetPos0(padCenter) pad.SetPosition(padCenter) pad.SetShape(pcbnew.PAD_SHAPE_RECT) pad.SetAttribute(pcbnew.PAD_ATTRIB_SMD) pad.SetLayerSet(layerSet) pad.SetPadName(name) return pad
def drawBarcode(self, text, pos): self.position = pos #todo : height and thickness should be parameters self.X = 0.20 self.H = 3 self.Q = 10 * self.X if self.Q < 6.35: self.Q = 6.35 self.Vmargin = self.X * 2 # Draw bars width = self.drawBars(text) # Draw quiet zone self.drawQuietZone(self.Q, self.Vmargin, width, self.H) # add text corresponding to actual barcode data, including guard characters textSize = self.module.Value().GetTextSize() x1 = width + self.Q * 2 y1 = self.H + self.Vmargin * 2 + pcbnew.ToMM(textSize[1]) * 1.1 + 0.5 p = self.module.GetPosition() px = p[0] py = p[1] text = pcbnew.TEXTE_MODULE(self.module) text.SetPosition( pcbnew.wxPoint(px + pcbnew.FromMM(x1 / 2), py + pcbnew.FromMM(y1 - 0.25) - textSize[1] / 2)) text.SetLayer(self.layer) text.SetVisible(True) text.SetTextSize(textSize) text.SetText(self.labelText) self.module.Add(text) # add an outline on courtyard layer self.layer = pcbnew.F_CrtYd self.X = 0.05 self.Line(0, 0, x1, 0) self.Line(x1, 0, x1, y1) self.Line(x1, y1, 0, y1) self.Line(0, y1, 0, 0)
def drill( self, dest, global_suffix='', merge_npth=False, extension=None, mirror=False, aux_origin=True, minimal_header=False, metric=True, ): dctl = pcbnew.EXCELLON_WRITER(self._board) if aux_origin: offset = self._board.GetAuxOrigin() else: offset = pcbnew.wxPoint(0, 0) dctl.SetOptions(mirror, minimal_header, offset, merge_npth) dctl.SetFormat(metric) dctl.CreateDrillandMapFilesSet(dest, aGenDrill=True, aGenMap=False) oldname = os.path.join(dest, self._name) if len(global_suffix): newname = os.path.join(dest, self._name + '-' + global_suffix) else: newname = oldname oldext = '.drl' if extension is not None: newext = extension else: newext = oldext if newname != oldname or newext != oldext: if merge_npth: os.rename(oldname + oldext, newname + newext) else: for s in ['-PTH', '-NPTH']: os.rename(oldname + s + oldext, newname + s + newext)
def place_diodes(): for i_hand in range(2): for i_diode in range(60): modref = "D%01d%02d" % (i_hand, i_diode) print(modref) mod = board.FindModuleByReference(modref) 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)) theta = i_diode * 6 mod.SetPosition(polar(diodeRad, theta)) if (mod.IsFlipped() != (i_hand == 1)): mod.Flip(pcbnew.wxPoint(diodex * mil, diodey * mil)) mod.SetOrientation(-theta * 10 + 1800) pcbnew.Refresh()
def DrawText(board, text_str, layer, pos, size=int(1.5 * pcbnew.IU_PER_MM), thickness=None, h_align=pcbnew.GR_TEXT_HJUSTIFY_CENTER): if thickness == None: thickness = int(size / 7.5) text = pcbnew.TEXTE_PCB(board) text.SetText(text_str) text.SetPosition(pcbnew.wxPoint(*pos)) try: # this fails in version 4.0.x text.SetTextSize(pcbnew.wxSize(size, size)) except AttributeError: # this fails in nightly 20171105 version text.SetSize(pcbnew.wxSize(size, size)) text.SetThickness(thickness) text.SetHorizJustify(h_align) text.SetLayer(layer) board.Add(text)
def createVias(self, viaPoints, viaDrill, viaSize, netCode): newVias = [] for viaPoint in viaPoints: newVia = pcbnew.VIA(self.boardObj) if hasattr(newVia, 'SetTimeStamp'): ts = 55 newVia.SetTimeStamp( ts ) # adding a unique number as timestamp to mark this via as generated by this script self.boardObj.Add(newVia) newVia.SetPosition(pcbnew.wxPoint(viaPoint[0], viaPoint[1])) newVia.SetWidth(viaSize) newVia.SetDrill(viaDrill) if hasattr(pcbnew, 'VIA_THROUGH'): newVia.SetViaType(pcbnew.VIA_THROUGH) else: newVia.SetViaType(pcbnew.VIATYPE_THROUGH) newVia.SetNetCode(netCode) newVias += [newVia] return newVias
def move_modules(components, board, offsets, kicad_v6=False): for module in board.GetModules( ) if kicad_v6 is False else board.GetFootprints(): old_pos = module.GetPosition() ref = module.GetReference() path = module.GetPath() if kicad_v6 is False else '/' + '/'.join( [x.AsString() for x in module.GetPath()]) print(ref, path, file=DEBUG) if path in components: ref, pos, sheet = components[path] if module.IsLocked(): print(' path =', path, ' sheet =', sheet, ' ref =', ref, ' is locked, skip', file=DEBUG) continue offset = offsets[sheet] new_pos = pcbnew.wxPoint(pos[0] * POS_SCALE, (pos[1] + offset) * POS_SCALE) print(' path =', path, ' sheet =', sheet, ' ref =', ref, ' pos =', pos, ' new_pos =', new_pos, file=DEBUG) module.SetPosition(new_pos) else: print(' NOT FOUND', file=DEBUG)
def __init__(self, pad, n, r, angle_offset=0, centre=pcbnew.wxPoint(0, 0), clockwise=True, padRotationEnable=False, padRotationOffset=0): """! @param pad: the prototypical pad @param n: number of pads in array @param r: the circle radius @param angle_offset: angle of the first pad @param centre: array centre point @param clockwise: array increases in a clockwise direction @param padRotationEnable: also rotate pads when placing @param padRotationOffset: rotation of first pad """ super(PadCircleArray, self).__init__(pad) self.n = int(n) self.r = r self.angle_offset = angle_offset self.centre = centre self.clockwise = clockwise self.padRotationEnable = padRotationEnable self.padRotationOffset = padRotationOffset
def place_circular(self, modules_to_place, radius, delta_angle, by_sheet): logger.info("Starting placing with circular layout") # get proper module_list modules = [] for mod_ref in modules_to_place: modules.append(self.get_mod_by_ref(mod_ref)) # get first module position first_module = modules[0] first_module_pos = first_module.mod.GetPosition() # get bounding_box_center if by_sheet: modules_on_sheet = self.get_modules_on_sheet(first_module.sheet_id) bbox_center = self.get_modules_bounding_box_center( modules_on_sheet) height, _ = self.get_modules_bounding_box(modules_on_sheet) else: bbox_center = self.get_modules_bounding_box_center([first_module]) height, _ = self.get_modules_bounding_box([first_module]) # point of rotation is below bounding box point_of_rotation = (bbox_center[0], bbox_center[1] + (height / 2 + radius) * SCALE) for mod in modules[1:]: index = modules.index(mod) new_position = rotate_around_pivot_point(first_module_pos, point_of_rotation, index * delta_angle) new_position = [int(x) for x in new_position] mod.mod.SetPosition(pcbnew.wxPoint(*new_position)) mod.mod.SetOrientationDegrees( first_module.mod.GetOrientationDegrees() - index * delta_angle) first_mod_flipped = first_module.mod.IsFlipped() if (mod.mod.IsFlipped() and not first_mod_flipped) or ( first_mod_flipped and not mod.mod.IsFlipped()): mod.mod.Flip(mod.mod.GetPosition())
def BuildThisFootprint(self): pads = self.parameters["Pads"] rows = pads["*row count"] cols = pads["*column count"] pad_size = pads["pad size"] pad_size = pcbnew.wxSize(pad_size, pad_size) pad_pitch = pads["pad pitch"] # add in the pads pad = PA.PadMaker(self.module).SMTRoundPad(pads["pad size"]) pin1_pos = pcbnew.wxPoint(-((cols - 1) * pad_pitch) / 2, -((rows - 1) * pad_pitch) / 2) array = BGAPadGridArray(pad, cols, rows, pad_pitch, pad_pitch) array.AddPadsToModule(self.draw) #box ssx = -pin1_pos.x + pads["outline x margin"] ssy = -pin1_pos.y + pads["outline y margin"] self.draw.BoxWithDiagonalAtCorner(0, 0, ssx * 2, ssy * 2, pads["outline x margin"]) # Courtyard cmargin = self.draw.GetLineTickness() self.draw.SetLayer(pcbnew.F_CrtYd) sizex = (ssx + cmargin) * 2 sizey = (ssy + cmargin) * 2 self.draw.Box(0, 0, sizex, sizey) #reference and value text_size = self.GetTextSize() # IPC nominal ypos = ssy + text_size self.draw.Value(0, ypos, text_size) self.draw.Reference(0, -ypos, text_size)
def mounting(): cx = 3.937007874 cy = 3.937007874 d = 5.118110236 - 3.937007874 n = 3 def rad(d): return math.pi * d / 180. for i in xrange(n): print print i j = 'J%u' % (i + 2, ) m = get_module(j) angle = rad(360 / n * i - 5) dx = d * math.sin(angle) dy = d * math.cos(angle) print dx, dy x = cx + dx y = cy + dy print 'X %0.3f' % x print 'Y %0.3f' % y m.SetPosition(pcbnew.wxPoint(boardxy(x), boardxy(y)))
def CreateSMTClone(board, mod, footprintLib, footprintName, rot=0, offset=None): if offset is None: offset = pcbnew.wxPoint(0, 0) new_mod = pcbnew.PCB_IO().FootprintLoad(footprintLib, footprintName) new_mod.SetPosition(ModuleMidPoint(mod) + offset) new_mod.SetOrientation(mod.GetOrientation() + rot) 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()) return new_mod
def get_bounding_box(module_list): top = None bottom = None left = None right = None for mod in module_list: if top == None: bounding_box = mod.GetBoundingBox() top = bounding_box.GetTop() bottom = bounding_box.GetBottom() left = bounding_box.GetLeft() right = bounding_box.GetRight() else: mod_box = mod.GetBoundingBox() top = min(top, mod_box.GetTop()) bottom = max(bottom, mod_box.GetBottom()) left = min(left, mod_box.GetLeft()) right = max(right, mod_box.GetRight()) position = pcbnew.wxPoint(left, top) size = pcbnew.wxSize(right - left, bottom - top) bounding_box = pcbnew.EDA_RECT(position, size) return bounding_box
def place_circular(self, modules_to_place, reference_footprint, radius, delta_angle, by_sheet): logger.info("Starting placing with circular layout") # get proper module_list modules = [] for mod_ref in modules_to_place: modules.append(self.get_mod_by_ref(mod_ref)) reference_module = self.get_mod_by_ref(reference_footprint) # get first module position reference_module_pos = reference_module.mod.GetPosition() logger.info("reference module position at: " + repr(reference_module_pos)) reference_index = modules.index(reference_module) point_of_rotation = (reference_module_pos[0], reference_module_pos[1] + radius * SCALE) logger.info("rotation center at: " + repr(point_of_rotation)) for mod in modules: index = modules.index(mod) delta_index = index - reference_index new_position = rotate_around_pivot_point(reference_module_pos, point_of_rotation, delta_index * delta_angle) new_position = [int(x) for x in new_position] mod.mod.SetPosition(pcbnew.wxPoint(*new_position)) mod.mod.SetOrientationDegrees( reference_module.mod.GetOrientationDegrees() - delta_index * delta_angle) first_mod_flipped = reference_module.mod.IsFlipped() if (mod.mod.IsFlipped() and not first_mod_flipped) or ( first_mod_flipped and not mod.mod.IsFlipped()): mod.mod.Flip(mod.mod.GetPosition())
def run(self, output_dir, board): # dialog_gendrill.cpp:357 if self.use_aux_axis_as_origin: offset = get_aux_origin(board) else: offset = wxPoint(0, 0) drill_writer, ext = self._configure_writer(board, offset) logger.debug("Generating drill files in "+output_dir) gen_map = self.map is not None if gen_map: drill_writer.SetMapFileFormat(self.map) logger.debug("Generating drill map type {} in {}".format(self.map, output_dir)) # We always generate the drill file drill_writer.CreateDrillandMapFilesSet(output_dir, True, gen_map) # Rename the files files = [''] if self._unified_output else ['PTH', 'NPTH'] for d in files: kicad_id = '-'+d if d else d kibot_id = d+'_drill' if d else 'drill' if self.output: if ext == 'drl': k_file = self.expand_filename(output_dir, '%f'+kicad_id+'.%x', '', ext) else: # gbr k_file = self.expand_filename(output_dir, '%f'+kicad_id+'-drl.%x', '', ext) file = self.expand_filename(output_dir, self.output, kibot_id, ext) os.rename(k_file, file) if gen_map and self.map_output: k_file = self.expand_filename(output_dir, '%f'+kicad_id+'-drl_map.%x', '', self.map_ext) file = self.expand_filename(output_dir, self.map_output, kibot_id+'_map', self.map_ext) os.rename(k_file, file) # Generate the report if self.report: drill_report_file = self.expand_filename(output_dir, self.report, 'drill_report', 'txt') logger.debug("Generating drill report: "+drill_report_file) drill_writer.GenDrillReportFile(drill_report_file)
def run_buzzard(dlg, p_buzzard): if len(dlg.polys) == 0: dlg.EndModal(wx.ID_CANCEL) return if '5.1' in self.kicad_build_version or '5.0' in self.kicad_build_version: # Handle KiCad 5.1 filepath = self.filepath with open(filepath, 'w+') as f: f.write(p_buzzard.create_v5_footprint()) print(os.path.dirname(filepath)) board = pcbnew.GetBoard() footprint = pcbnew.FootprintLoad(os.path.dirname(filepath), 'label') footprint.SetPosition(pcbnew.wxPoint(0, 0)) board.Add(footprint) pcbnew.Refresh() # Zoom doesn't seem to work. #b = footprint.GetBoundingBox() #pcbnew.WindowZoom(b.GetX(), b.GetY(), b.GetWidth(), b.GetHeight()) elif '5.99' in self.kicad_build_version or '6.0' in self.kicad_build_version: footprint_string = p_buzzard.create_v6_footprint() clipboard = wx.Clipboard.Get() if clipboard.Open(): clipboard.SetData(wx.TextDataObject(footprint_string)) clipboard.Close() dlg.EndModal(wx.ID_OK)
def plot_drill_map(self): board_name = os.path.splitext( os.path.basename(self.board.GetFileName()))[0] drill_writer = pcbnew.EXCELLON_WRITER(self.board) drill_writer.SetMapFileFormat(pcbnew.PLOT_FORMAT_PDF) mirror = False minimalHeader = False offset = pcbnew.wxPoint(0, 0) merge_npth = True # TODO: do we want this? drill_writer.SetOptions(mirror, minimalHeader, offset, merge_npth) metric_format = True drill_writer.SetFormat(metric_format) generate_drill = False generate_map = True drill_writer.CreateDrillandMapFilesSet(self.plot_directory, generate_drill, generate_map) map_file_name = os.path.join(self.plot_directory, '%s-drl_map.pdf' % (board_name, )) return map_file_name
def plot_drill(self): board_name = os.path.splitext( os.path.basename(self.board.GetFileName()))[0] logger.info('Plotting drill file') drill_writer = pcbnew.EXCELLON_WRITER(self.board) mirror = False minimalHeader = False offset = pcbnew.wxPoint(0, 0) merge_npth = True # TODO: do we want this? drill_writer.SetOptions(mirror, minimalHeader, offset, merge_npth) metric_format = True drill_writer.SetFormat(metric_format) generate_drill = True generate_map = False drill_writer.CreateDrillandMapFilesSet(self.plot_directory, generate_drill, generate_map) drill_file_name = os.path.join(self.plot_directory, '%s.drl' % (board_name, )) return drill_file_name
def place_linear(self, modules_to_place, step_x, step_y): logger.info("Starting placing with linear layout") # get proper module_list modules = [] for mod_ref in modules_to_place: modules.append(self.get_mod_by_ref(mod_ref)) # get first module position first_module = modules[0] first_module_pos = first_module.mod.GetPosition() for mod in modules[1:]: index = modules.index(mod) new_position = (first_module_pos.x + index * step_x * SCALE, first_module_pos.y + index * step_y * SCALE) new_position = [int(x) for x in new_position] mod.mod.SetPosition(pcbnew.wxPoint(*new_position)) mod.mod.SetOrientationDegrees( first_module.mod.GetOrientationDegrees()) first_mod_flipped = first_module.mod.IsFlipped() if (mod.mod.IsFlipped() and not first_mod_flipped) or ( first_mod_flipped and not mod.mod.IsFlipped()): mod.mod.Flip(mod.mod.GetPosition())
def get_bounding_box_of_modules(module_list): """ get bounding box encompasing all modules """ top = None bottom = None left = None right = None for mod in module_list: if top is None: bounding_box = mod.GetFootprintRect() top = bounding_box.GetTop() bottom = bounding_box.GetBottom() left = bounding_box.GetLeft() right = bounding_box.GetRight() else: mod_box = mod.GetFootprintRect() top = min(top, mod_box.GetTop()) bottom = max(bottom, mod_box.GetBottom()) left = min(left, mod_box.GetLeft()) right = max(right, mod_box.GetRight()) position = pcbnew.wxPoint(left, top) size = pcbnew.wxSize(right - left, bottom - top) bounding_box = pcbnew.EDA_RECT(position, size) return bounding_box