from pcbnew import *
class AddAutomaticBorder(ActionPlugin):
"""
Automatically creates or updates PCB edges to include all elements
"""
def defaults(self):
self.name = "Add or update automatic PCB edges"
self.category = "Modify PCB"
self.description = "Automatically add or update edges on an existing PCB"
# Offset between elements and edge (2.54mm)
self.offset = FromMM(2.54)
# Snap to grid (2.54mm)
self.grid = FromMM(2.54)
def min(self, a, b):
"""Helper to find minimum, handling None values"""
if a is None:
return b
if b is None:
return a
return a if a < b else b
def max(self, a, b):
"""Helper to find maximum, handling None values"""
if a is None:
return b
if b is None:
return a
return a if a > b else b
def Run(self):
pcb = GetBoard()
min_x = min_y = max_x = max_y = None
# Find bounding box of all zones
for i in range(pcb.GetAreaCount()):
bbox = pcb.GetArea(i).GetBoundingBox()
min_x = self.min(min_x, bbox.GetX())
min_y = self.min(min_y, bbox.GetY())
max_x = self.max(max_x, bbox.GetX() + bbox.GetWidth())
max_y = self.max(max_y, bbox.GetY() + bbox.GetHeight())
# Include all tracks
for track in pcb.GetTracks():
min_x = self.min(min_x, track.GetStart().x)
min_y = self.min(min_y, track.GetStart().y)
max_x = self.max(max_x, track.GetEnd().x)
max_y = self.max(max_y, track.GetEnd().y)
# Include all footprints
for footprint in pcb.GetFootprints():
bbox = footprint.GetBoundingBox()
min_x = self.min(min_x, bbox.GetX())
min_y = self.min(min_y, bbox.GetY())
max_x = self.max(max_x, bbox.GetX() + bbox.GetWidth())
max_y = self.max(max_y, bbox.GetY() + bbox.GetHeight())
# Add offset
min_x -= self.offset
min_y -= self.offset
max_x += self.offset
max_y += self.offset
# Snap to grid
min_x = min_x - (min_x % self.grid)
min_y = min_y - (min_y % self.grid)
if (max_x % self.grid) != 0:
max_x = max_x - (max_x % self.grid) + self.grid
if (max_y % self.grid) != 0:
max_y = max_y - (max_y % self.grid) + self.grid
# Create edge shapes
self._create_edge(pcb, min_x, min_y, min_x, max_y) # West
self._create_edge(pcb, min_x, min_y, max_x, min_y) # North
self._create_edge(pcb, max_x, min_y, max_x, max_y) # East
self._create_edge(pcb, min_x, max_y, max_x, max_y) # South
def _create_edge(self, pcb, x1, y1, x2, y2):
"""Create or update an edge line"""
edge = PCB_SHAPE()
edge.SetLayer(Edge_Cuts)
edge.SetStart(wxPoint(x1, y1))
edge.SetEnd(wxPoint(x2, y2))
pcb.Add(edge)
AddAutomaticBorder().register()