1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
|
# add_automatic_border.py
#
# Copyright (C) 2017 KiCad Developers, see AUTHORS.TXT for contributors.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
#
from pcbnew import *
import re
import datetime
class add_automatic_border( ActionPlugin ):
"""
add_automatic_border: An other sample plugin as an example of ActionPlugin
Build PCB edges to include all PCB elements
How to use:
- add all your modules/track/area/text...
- Call the plugin
- An including PCB edge will be created automatically
"""
def defaults( self ):
"""
Method defaults must be redefined
self.name should be the menu label to use
self.category should be the category (not yet used)
self.description should be a comprehensive description
of the plugin
"""
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 existing elements and edge we will add/update (fixed at 2.54mm)
self.offset = FromMM( 2.54 )
# Attach to a grid step (fixed at 2.54mm)
self.grid = FromMM( 2.54 )
def min( self, a, b ):
"""
Method min: Found min between a and b even is one is None
"""
if a is None:
return b
if b is None:
return a
if a < b:
return a
return b
def max( self, a, b ):
"""
Method max: Found max between a and b even is one is None
"""
if a is None:
return b
if b is None:
return a
if a > b:
return a
return b
def Run( self ):
"""
Method Run is called by Action menu
"""
pcb = GetBoard()
# Find including area on min/max x/y
min_x = None
max_x = None
min_y = None
max_y = None
# Enum all area
for i in range( pcb.GetAreaCount() ):
min_x = self.min( min_x, pcb.GetArea( i ).GetBoundingBox().GetX() )
min_y = self.min( min_y, pcb.GetArea( i ).GetBoundingBox().GetY() )
max_x = self.max( max_x, \
pcb.GetArea( i ).GetBoundingBox().GetX() \
+ pcb.GetArea( i ).GetBoundingBox().GetWidth() )
max_y = self.max( max_y, \
pcb.GetArea( i ).GetBoundingBox().GetY() \
+ pcb.GetArea( i ).GetBoundingBox().GetHeight() )
# Same with track
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 )
min_x = self.min( min_x, track.GetEnd().x )
min_y = self.min( min_y, track.GetEnd().y )
max_x = self.max( max_x, track.GetStart().x )
max_y = self.max( max_y, track.GetStart().y )
# Variable to store PCB edges we found
west = None
north = None
east = None
south = None
for draw in pcb.GetDrawings():
edge_candidate = False
# Detect if current drawing is a PCB edge
# and a candicate for north/south/east or west
if draw.GetClass() == 'PCB_SHAPE' \
and draw.GetLayer() == Edge_Cuts:
# Try candicate for east/west ?
if draw.GetStart().x == draw.GetEnd().x:
if west is None and east is None:
west = draw
edge_candidate = True
elif west is None: # east is not none
if draw.GetStart().x < east.GetStart().x:
west = draw
edge_candidate = True
else:
west = east
east = draw
edge_candidate = True
elif east is None: # west is not none
if draw.GetStart().x > west.GetStart().x:
east = draw
edge_candidate = True
else:
east = west
west = draw
edge_candidate = True
else:
None # west and east are already found...
# Try candicate for north/south ?
if draw.GetStart().y == draw.GetEnd().y:
if north is None and south is None:
north = draw
edge_candidate = True
elif north is None: # south is not none
if draw.GetStart().y < south.GetStart().y:
north = draw
edge_candidate = True
else:
north = south
south = draw
edge_candidate = True
elif south is None: # north is not none
if draw.GetStart().y > north.GetStart().y:
south = draw
edge_candidate = True
else:
south = north
north = draw
edge_candidate = True
else:
None # north and south are already found...
# Not a edge candidate: use it to find including edges
if not edge_candidate:
bbox = draw.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() )
# Same with modules: Find including area
for module in pcb.GetFootprints():
bbox = module.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 a space between including area and edge (3mm)
min_x = min_x - self.offset
min_y = min_y - self.offset
max_x = max_x + self.offset
max_y = max_y + self.offset
# Fix on the defined 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
# Add or update all edges
need_add = False
if west is None:
need_add = True
west = PCB_SHAPE()
west.SetLayer( Edge_Cuts )
west.SetStart( wxPoint( min_x, min_y ) )
west.SetEnd( wxPoint( min_x, max_y ) )
if need_add:
pcb.Add( west )
need_add = False
if north is None:
need_add = True
north = PCB_SHAPE()
north.SetLayer( Edge_Cuts )
north.SetStart( wxPoint( min_x, min_y ) )
north.SetEnd( wxPoint( max_x, min_y ) )
if need_add:
pcb.Add( north )
need_add = False
if east is None:
need_add = True
east = PCB_SHAPE()
east.SetLayer( Edge_Cuts )
east.SetStart( wxPoint( max_x, min_y ) )
east.SetEnd( wxPoint( max_x, max_y ) )
if need_add:
pcb.Add( east )
need_add = False
if south is None:
need_add = True
south = PCB_SHAPE()
south.SetLayer( Edge_Cuts )
south.SetStart( wxPoint( min_x, max_y ) )
south.SetEnd( wxPoint( max_x, max_y ) )
if need_add:
pcb.Add( south )
# Register the action
add_automatic_border().register()
|