Ok, I got somewhere:
- There is a
board.GetBoardEdgesBoundingBox()
which gives you the outer bounding size of the board’s Edge.Cuts (thus it cannot possibly handle the cutout/hole) - this is returned as EDA_RECT
- You can iterate through all pads of all modules/footprints on board, and then there is
pad.HitTest()
which accepts EDA_RECT
as argument
Seemingly, the pad.HitTest()
tells you if the pad itself lays within the EDA_RECT
or not - but cannot tell how that is determined (by position, or by area of solder mask, or … how?). So if that understanding is correct, then we can reduce the question “is footprint on board?” to “do all pads of the footprint pass hitTest with the outer bounds of board’s Edge.Cuts?”
So, I tried that with this script:
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# this script intended to be called from within KiCad's Pcbnew: Tools / Scripting Console (Python Shell)
# NB: that python shell might start from pwd: ~/kicad/kicommand
# >>> execfile('/path/to/kicad-pcbnew-checkonboard.py')
# (here CheckOnboard should end up in locals() namespace)
# >>> CheckOnboard()
import sys
import os
import pcbnew
board = pcbnew.GetBoard()
def CheckOnboard():
print("CheckOnboard from kicad-pcbnew-checkonboard.py:")
EdgeCutsId = board.GetLayerID("Edge.Cuts")
print("{} {} {} {} {} {} {}".format(
EdgeCutsId, board.GetLayerName(EdgeCutsId),
board.GetLayerType(EdgeCutsId), board.GetStandardLayerName(EdgeCutsId),
board.IsLayerEnabled(EdgeCutsId), board.IsLayerVisible(EdgeCutsId),
board.IsModuleLayerVisible(EdgeCutsId)
)) # 44 Edge.Cuts 0 Edge.Cuts True True True; PCB_LAYER_ID const/aLayer
#for drawing in board.GetDrawings(): # pcbnew.DRAWSEGMENT
# print(drawing)
print(board.DrawingsList()) # pcbnew.BOARD_ITEM_List
#for ix in board.DrawingsList(): # is also pcbnew.DRAWSEGMENT
# print(ix)
boardbbe = board.GetBoardEdgesBoundingBox() # pcbnew.EDA_RECT
print(" boardbbe: {},{} {},{}".format(boardbbe.GetLeft(), boardbbe.GetTop(), boardbbe.GetRight(),boardbbe.GetBottom() ))
for mod in board.GetModules(): # Modules(): 'SwigPyObject' object is not iterable # pcbnew.MODULE
pstrarr = []
isModuleInBoardBBEdges = True # if any of the tests below is false, this becomes false too
for pad in mod.Pads(): # pcbnew.D_PAD
padbb = pad.GetBoundingBox() #.GetBoundingBox(): pcbnew.EDA_RECT;
pstr = " pad: {},{} {},{}".format(padbb.GetLeft(), padbb.GetTop(), padbb.GetRight(),padbb.GetBottom() )
"""
[KiCAD pcbnew scripting: pcbnew.D_PAD Class Reference: pcbnew.D_PAD.HitTest](http://docs.kicad.org/doxygen-python/classpcbnew_1_1D__PAD.html#a1e511816b04dfe51160f308c78461aba)
HitTest(D_PAD self, wxPoint aPosition) -> bool
HitTest(D_PAD self, EDA_RECT aRect, bool aContained, int aAccuracy=0) -> bool
HitTest(D_PAD self, EDA_RECT aRect, bool aContained) -> bool
There is pcbnew.D_PAD.GetBoundingBox;
also board.HitTestForAnyFilledArea (self, aRefPos, aStartLayer, aEndLayer, aNetCode) (returns ZONE_CONTAINER)
"""
# these two seem to be always the same, regardless of how aContained is set
padHTt = pad.HitTest(boardbbe, True);
padHTf = pad.HitTest(boardbbe, False);
# note: {0: <10} prints a bool val as 0 or 1!
pstr += " ({: <6} , {})".format("{}".format(padHTt), "{}".format(padHTf))
pstrarr.append(pstr)
if not(padHTt):
isModuleInBoardBBEdges = False
print("{0: <10} {1}".format(mod.GetReference(), isModuleInBoardBBEdges))
print(os.linesep.join(pstrarr))
… I get this printout:
CheckOnboard()
CheckOnboard from kicad-pcbnew-checkonboard.py:
44 Edge.Cuts 0 Edge.Cuts True True True
<pcbnew.BOARD_ITEM_List; proxy of <Swig Object of type 'DLIST< BOARD_ITEM > *' at 0xe6fc0c80> >
boardbbe: 20244999,17704999 68655001,50875001
R1 True
pad: 23330000,38570000 24930000,40170000 (True , True)
pad: 23330000,28410000 24930000,30010000 (True , True)
P1 True
pad: 29310000,28200000 31650000,30540000 (True , True)
pad: 44310000,33200000 46650000,35540000 (True , True)
pad: 29310000,38200000 31650000,40540000 (True , True)
U1 True
pad: 55080000,29680000 56680000,31280000 (True , True)
pad: 62700000,37300000 64300000,38900000 (True , True)
pad: 55080000,32220000 56680000,33820000 (True , True)
pad: 62700000,34760000 64300000,36360000 (True , True)
pad: 55080000,34760000 56680000,36360000 (True , True)
pad: 62700000,32220000 64300000,33820000 (True , True)
pad: 55080000,37300000 56680000,38900000 (True , True)
pad: 62700000,29680000 64300000,31280000 (True , True)
LED1 False
pad: 72760000,29580000 74560000,31380000 (False , False)
pad: 75300000,29580000 77100000,31380000 (False , False)
So, it seems to detect generally inside or outside of the board fine - except it cannot handle the cutout/hole in the middle of the board (P1 should be false, but it’s still shown as True).
If anyone knows what criteria I could use to also detect that - that would be great to know!