Python parsing and printing edge cut layer outline area

I am trying to figure out how to parse and printout the pcb width, height, thickness, top_left, top_right, bottom_right and bottom_left information from the kicad 7 pcb files.

I thought I could find at least some of that information from the PCB_SHAPE via python API the values printed does not look right.


import pcbnew
import sys

pcb_input_filename = sys.argv[1]

# Load board and initialize plot controller
board = pcbnew.LoadBoard(pcb_input_filename)
pc = pcbnew.PLOT_CONTROLLER(board)
po = pc.GetPlotOptions()
po.SetPlotFrameRef(False)

# Set current layer
pc.SetLayer(pcbnew.Edge_Cuts)
pcb_shape	= pcbnew.PCB_SHAPE(board)
bounding_box = pcb_shape.GetBoundingBox()

print("box.x " + str(bounding_box.GetX()))
print("box.height " + str(bounding_box.GetHeight()))

I found one closed answer for same topic from 2018, but I could not understand the answer for it.

Also the kicad_pcb parsing seems to be broken in this project that try to implement similar type of function. (parsing of edge cutr gerber file works on it)

https://bitbucket.org/igor_b/stencilframer/src/master/

If you open the PCB file in a Text-Editor (or other) you will see the info you want.

You can create a Plugin to search for the data using code calls or simply use the info from the file (seen in Text Editor) for your search strings…

Depends on what you intend to do with the results…

Example from PCB file…
Top-Left and Btm-Right are shown so you can infer PCB size unless it’s not Rectangular/Square…

Screen Shot 2023-09-21 at 08.09.20

Tried it, same problem, GetBoundingBox() always returns a box around -50000,-50000,50000,50000.

printout the pcb width, height, thickness, top_left, top_right, bottom_right and bottom_left information from the kicad 7 pcb files.

You know that this information may not exist or maybe not meaningful? The PCB does not have to be a rectangle, it can be any polygon (as long as the range of numbers and the RAM you have can support it) and can include arcs.
Do i understand it correct that you want the data of the axis-aligned minimum bounding box of the PCB?

If no one with more knowledge about the python API than i have and parsing the .kicad_pcb file is not a option, then maybe this bad Python code gives you an idea how you can get that information from the Python API:

import pcbnew
import sys

board=pcbnew.LoadBoard(sys.argv[1])

startX= (1<<33)
startY= (1<<33)
endX  =-(1<<33)
endY  =-(1<<33)
foundAtLeastOneDrawing=0
for d in board.GetDrawings():
  if d.GetLayerName()=="Edge.Cuts":
    foundAtLeastOneDrawing=1
    box = d.GetBoundingBox()

    startX = min(box.GetLeft(),startX)
    startY = min(box.GetTop(),startY)
    endX   = max(box.GetRight(),endX)
    endY   = max(box.GetBottom(),endY)

if not foundAtLeastOneDrawing:
  raise Exception("No Edge.Cuts Element found")


print(startX,startY,endX,endY)

Edit: A bit more pythonic but less readable version:

b=pcbnew.LoadBoard("/tmp/k/a/a.kicad_pcb")

def apply(minMax,f):
  return minMax( f(d.GetBoundingBox()) for d in b.GetDrawings() if d.GetLayerName()=="Edge.Cuts" )

print("Xmin", apply(min,pcbnew.BOX2I.GetLeft) )
print("Ymin", apply(min,pcbnew.BOX2I.GetTop) )
print("Xmax", apply(max,pcbnew.BOX2I.GetRight) )
print("Ymax", apply(max,pcbnew.BOX2I.GetBottom) )
1 Like

You can use the code posted by @johannespfister It will require a few tweaks but, it’s good code otherwise.

Video shows it in action with it displaying Correct result in Message panel…

This does what you want, I think

1 Like

There may be at least one problem here: the shape hasn’t been added to the board. Creating a shape with parent isn’t enough for using it in the board. Maybe it affects even calculating the bounding box?

There may be at least one problem here: the shape hasn’t been added to the board. Creating a shape with parent isn’t enough for using it in the board. Maybe it affects even calculating the bounding box?

How to add it to the board?

I tried

board.add( pcb_shape ) #Added this line
bounding_box = pcb_shape.GetBoundingBox()
print(bounding_box.GetX()) # still -50000
print(bounding_box.L.GetPosition()) # still VECTOR2I(-50000, -50000)
print(bounding_box.L.GetEnd()) # still VECTOR2I(50000, 50000)

Doesn’t work.

(It isn’t my problem, but i guess @lamikr will also not know how to add it in a way that it works)

Thanks for the responses, I had finally time to try the suggested solutions and I used couple of them for now to have the code below that seems to work.

Am I right in my assumptions that the coordinate returned for example by GetBoundingBox().getLeft() is in one millions of millimeter?

#!/bin/python

# code to find the pcb board max width and height in millimeters
# it uses the kicad_pcb file as a parameter, for example:
# ./get_kicad_pcb_size.py ldo_test_pcb.kicad_pcb
# 
# and will output results like:
# width: 60.2 mm
# height: 29.0 mm

import sys
import pcbnew

edge_found	= 0
if len(sys.argv) == 2:
	f_name	= sys.argv[1]
	board	= pcbnew.LoadBoard(f_name)
	min_x	= (1<<33)
	min_y	= (1<<33)
	max_x	=-(1<<33)
	max_y	=-(1<<33)
	for d in board.GetDrawings():
		if d.GetLayer() == pcbnew.Edge_Cuts:
			edge_found	= 1
			box			= d.GetBoundingBox()
			min_x		= min(box.GetLeft(), min_x)
			min_y		= min(box.GetTop(), min_y)
			max_x		= max(box.GetRight(), max_x)
			max_y   	= max(box.GetBottom(), max_y)
	if edge_found:
		#print("min_x", min_x)
		#print("min_y", min_y)
		#print("max_x", max_x)
		#print("max_y", max_y)
		size_w_mm	= (max_x - min_x) / 1000000;
		size_h_mm	= (max_y - min_y) / 1000000;
		print("width:", round(size_w_mm, 1), "mm")
		print("height:", round(size_h_mm, 1), "mm")
	else:
		raise Exception("No Edge.Cuts Element found")
else:
	print("One parameter needed: path to kicad_pcb file with 'Edge.Cuts' layer to find pcp file dimensions")

Also known among the common folks as a nanometer, yes.

Ok, thanks for the help. I have now created a github project which can be used to generate PCB stencil jig which can be printed with 3d printer to assist the holding of stencil when spreading the soldering paste to pcb.

The project with some description and pics can be found from here:

What is still missing is the z-size for PCB for hole. I use now by default 1.6mm. Also the pocket generated for holding the PCB is now rectangular based on the min/max values so at the moment is does not support more excotic pcb layouts.

I plan to release this as a kicad plugin at some point.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.