@ -1,4 +1,5 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# FillArea.py
|
||||
#
|
||||
@ -28,8 +29,8 @@ import os
|
||||
import random
|
||||
import pprint
|
||||
|
||||
"""# This script fill all areas with Via (Via Stitching) is the area is on
|
||||
# a specific net (by default /GND fallback to GND)
|
||||
"""
|
||||
# This script fills all areas of a specific net with Vias (Via Stitching)
|
||||
#
|
||||
#
|
||||
# Usage in pcbnew's python console:
|
||||
@ -42,7 +43,7 @@ FillArea.FillArea().Run()
|
||||
|
||||
|
||||
# Other example:
|
||||
# You can add modifications to parameters by adding functions call:
|
||||
# You can add modifications to parameters by adding functions calls:
|
||||
FillArea.FillArea().SetDebug().SetNetname("GND").SetStepMM(1.27).SetSizeMM(0.6).SetDrillMM(0.3).SetClearanceMM(0.2).Run()
|
||||
|
||||
# with
|
||||
@ -59,6 +60,17 @@ FillArea.FillArea().SetDebug().SetNetname("GND").SetStepMM(1.27).SetSizeMM(0.6).
|
||||
|
||||
"""
|
||||
|
||||
class ViaObject:
|
||||
|
||||
"""
|
||||
ViaObject holds all information of a single Via
|
||||
"""
|
||||
|
||||
def __init__(self, x, y, pos_x, pos_y):
|
||||
self.X = x
|
||||
self.Y = y
|
||||
self.PosX = pos_x
|
||||
self.PosY = pos_y
|
||||
|
||||
class FillArea:
|
||||
|
||||
@ -67,6 +79,15 @@ class FillArea:
|
||||
pads and keepout areas
|
||||
"""
|
||||
|
||||
REASON_OK = 0
|
||||
REASON_NO_SIGNAL = 1
|
||||
REASON_OTHER_SIGNAL = 2
|
||||
REASON_KEEPOUT = 3
|
||||
REASON_TRACK = 4
|
||||
REASON_PAD = 5
|
||||
REASON_DRAWING = 6
|
||||
REASON_STEP = 7
|
||||
|
||||
def __init__(self, filename=None):
|
||||
self.filename = None
|
||||
self.clearance = 0
|
||||
@ -124,7 +145,7 @@ class FillArea:
|
||||
return self
|
||||
|
||||
def SetNetname(self, netname):
|
||||
self.netname = netname
|
||||
self.netname = netname.upper()
|
||||
return self
|
||||
|
||||
def SetStepMM(self, s):
|
||||
@ -150,23 +171,48 @@ class FillArea:
|
||||
def SetClearanceMM(self, s):
|
||||
self.clearance = float(FromMM(s))
|
||||
return self
|
||||
|
||||
|
||||
def GetReasonSymbol(self, reason):
|
||||
if isinstance(reason, ViaObject):
|
||||
return "X"
|
||||
if reason == self.REASON_NO_SIGNAL:
|
||||
return " "
|
||||
if reason == self.REASON_OTHER_SIGNAL:
|
||||
return "O"
|
||||
if reason == self.REASON_KEEPOUT:
|
||||
return "K"
|
||||
if reason == self.REASON_TRACK:
|
||||
return "T"
|
||||
if reason == self.REASON_PAD:
|
||||
return "P"
|
||||
if reason == self.REASON_DRAWING:
|
||||
return "D"
|
||||
if reason == self.REASON_STEP:
|
||||
return "-"
|
||||
|
||||
return str(reason)
|
||||
|
||||
def PrintRect(self, rectangle):
|
||||
"""debuging tool
|
||||
Print board in ascii art
|
||||
"""
|
||||
for y in range(rectangle[0].__len__()):
|
||||
for x in range(rectangle.__len__()):
|
||||
print("%X" % rectangle[x][y], end='')
|
||||
print()
|
||||
print()
|
||||
|
||||
def CleanupFootprint(self):
|
||||
"""
|
||||
cleanup temp footprint
|
||||
"""
|
||||
if self.tmp_dir and os.path.isdir(self.tmp_dir):
|
||||
shutil.rmtree(self.tmp_dir)
|
||||
print("_" * (len(rectangle)+2))
|
||||
for y in range(len(rectangle[0])):
|
||||
print("|", end='')
|
||||
for x in range(len(rectangle)):
|
||||
print("%s" % self.GetReasonSymbol(rectangle[x][y]), end='')
|
||||
print("|")
|
||||
print("_" * (len(rectangle)+2))
|
||||
print('''
|
||||
OK = 'X'
|
||||
NO_SIGNAL = ' '
|
||||
OTHER_SIGNAL = 'O'
|
||||
KEEPOUT = 'K'
|
||||
TRACK = 'T'
|
||||
PAD = 'P'
|
||||
DRAWING = 'D'
|
||||
STEP = '-'
|
||||
''')
|
||||
|
||||
def AddVia(self, position, x, y):
|
||||
m = VIA(self.pcb)
|
||||
@ -186,116 +232,192 @@ class FillArea:
|
||||
if not area.GetIsKeepout():
|
||||
area.BuildFilledSolidAreasPolygons(self.pcb)
|
||||
|
||||
def CheckViaInAllAreas(self, via, all_areas):
|
||||
'''
|
||||
Checks if an existing Via collides with another area
|
||||
'''
|
||||
# Enum all area
|
||||
for area in all_areas:
|
||||
area_layer = area.GetLayer()
|
||||
area_clearance = area.GetClearance()
|
||||
area_priority = area.GetPriority()
|
||||
is_keepout_area = area.GetIsKeepout()
|
||||
is_target_net = (area.GetNetname().upper() == self.netname)
|
||||
|
||||
if (not is_target_net): # Only process areas that are not in the target net
|
||||
offset = max(self.clearance, area_clearance) + self.size / 2 # Offset is half the size of the via plus the clearance of the via or the area
|
||||
for dx in [-offset, offset]:
|
||||
for dy in [-offset, offset]: # All 4 corners of the via are testet (upper, lower, left, right) but not the center
|
||||
point_to_test = wxPoint(via.PosX + dx, via.PosY + dy)
|
||||
|
||||
hit_test_area = area.HitTestFilledArea(point_to_test) # Collides with a filled area
|
||||
hit_test_edge = area.HitTestForEdge(point_to_test) # Collides with an edge/corner
|
||||
hit_test_zone = area.HitTestInsideZone(point_to_test) # Is inside a zone (e.g. KeepOut)
|
||||
|
||||
if is_keepout_area and (hit_test_area or hit_test_edge or hit_test_zone):
|
||||
return self.REASON_KEEPOUT # Collides with keepout
|
||||
|
||||
elif (hit_test_area or hit_test_edge):
|
||||
return self.REASON_OTHER_SIGNAL # Collides with another signal (e.g. on another layer)
|
||||
|
||||
elif hit_test_zone:
|
||||
# Check if the zone is higher priority than other zones of the target net in the same point
|
||||
target_areas_on_same_layer = filter(lambda x: ((x.GetPriority() > area_priority) and (x.GetLayer() == area_layer) and (x.GetNetname().upper() == self.netname)), all_areas)
|
||||
for area_with_higher_priority in target_areas_on_same_layer:
|
||||
if area_with_higher_priority.HitTestInsideZone(point_to_test):
|
||||
break # Area of target net has higher priority on this layer
|
||||
else:
|
||||
return self.REASON_OTHER_SIGNAL # Collides with another signal (e.g. on another layer)
|
||||
|
||||
return self.REASON_OK
|
||||
|
||||
def ClearViaInStepSize(self, rectangle, x, y, distance):
|
||||
'''
|
||||
Stepsize==0
|
||||
O O O O O O O O O
|
||||
O O O O O O O O O
|
||||
O O O O O O O O O
|
||||
O O O O O O O O O
|
||||
O O O O O O O O O
|
||||
O O O O O O O O O
|
||||
O O O O O O O O O
|
||||
|
||||
Standard
|
||||
O O O O O
|
||||
|
||||
O O O O O
|
||||
|
||||
O O O O O
|
||||
|
||||
O O O O O
|
||||
|
||||
Star
|
||||
O O O O O
|
||||
O O O O
|
||||
O O O O O
|
||||
O O O O
|
||||
O O O O O
|
||||
O O O O
|
||||
O O O O O
|
||||
'''
|
||||
for x_pos in range(x-distance, x+distance+1):
|
||||
if (x_pos >= 0) and (x_pos < len(rectangle)):
|
||||
distance_y = distance-abs(x-x_pos) if self.star else distance # Star or Standard shape
|
||||
for y_pos in range(y-distance_y, y+distance_y+1):
|
||||
if (y_pos >= 0) and (y_pos < len(rectangle[0])):
|
||||
if (x_pos == x) and (y_pos == y):
|
||||
continue
|
||||
rectangle[x_pos][y_pos] = self.REASON_STEP
|
||||
|
||||
def Run(self):
|
||||
"""
|
||||
Launch the process
|
||||
"""
|
||||
|
||||
if self.delete_vias:
|
||||
for via in self.pcb.GetTracks():
|
||||
target_tracks = filter(lambda x: (x.GetNetname().upper() == self.netname), self.pcb.GetTracks())
|
||||
for via in target_tracks:
|
||||
if via.Type() == PCB_VIA_T:
|
||||
if via.GetTimeStamp() == 33:
|
||||
if self.debug:
|
||||
print("* Deleting via %u" % via.GetTimeStamp())
|
||||
self.pcb.RemoveNative(via)
|
||||
self.RefillBoardAreas()
|
||||
return # no need to run the rest of logic
|
||||
return # no need to run the rest of logic
|
||||
|
||||
lboard = self.pcb.ComputeBoundingBox()
|
||||
rectangle = []
|
||||
lboard = self.pcb.ComputeBoundingBox(True)
|
||||
origin = lboard.GetPosition()
|
||||
|
||||
# Create an initial rectangle: all is off
|
||||
# Create an initial rectangle: all is set to "REASON_NO_SIGNAL"
|
||||
# get a margin to avoid out of range
|
||||
# Values:
|
||||
# 0 => position is ok for via
|
||||
# != 0 => position is not ok.
|
||||
# Number is for debuging: check what feature is disabling this position
|
||||
l_clearance = self.step + self.clearance + self.size
|
||||
x_limit = int((lboard.GetWidth() + l_clearance) / self.step) + 1
|
||||
y_limit = int((lboard.GetHeight() + l_clearance) / self.step) + 1
|
||||
for x in range(0, x_limit):
|
||||
rectangle.append([])
|
||||
for y in range(0, y_limit):
|
||||
rectangle[x].append(0x8)
|
||||
l_clearance = self.clearance + self.size
|
||||
x_limit = int((lboard.GetWidth() + l_clearance) / l_clearance) + 1
|
||||
y_limit = int((lboard.GetHeight() + l_clearance) / l_clearance) + 1
|
||||
|
||||
rectangle = [[self.REASON_NO_SIGNAL]*y_limit for i in xrange(x_limit)]
|
||||
|
||||
if self.debug:
|
||||
print("Initial rectangle")
|
||||
self.PrintRect(rectangle)
|
||||
all_pads = self.pcb.GetPads()
|
||||
all_tracks = self.pcb.GetTracks()
|
||||
all_drawings = filter(lambda x: x.GetClass() == 'PTEXT' and self.pcb.GetLayerID(x.GetLayerName()) in (F_Cu, B_Cu), self.pcb.DrawingsList())
|
||||
all_areas = [self.pcb.GetArea(i) for i in xrange(self.pcb.GetAreaCount())]
|
||||
target_areas = filter(lambda x: (x.GetNetname().upper() == self.netname), all_areas) # KeepOuts are filtered because they have no name
|
||||
|
||||
# Enum all area
|
||||
for i in range(self.pcb.GetAreaCount()):
|
||||
area = self.pcb.GetArea(i)
|
||||
# If use only selected area mode
|
||||
# only_selected_area | is selected | keepout | result
|
||||
# False | X | X | True
|
||||
# True | True | X | True
|
||||
# True | False | True | True
|
||||
# True | False | False | False
|
||||
if not (self.only_selected_area and not area.IsSelected() and not area.GetIsKeepout()):
|
||||
# Handle only area on same target net of keepout are
|
||||
if area.GetNetname() == self.netname or area.GetIsKeepout():
|
||||
keepOutMode = area.GetIsKeepout()
|
||||
for y in range(rectangle[0].__len__()):
|
||||
for x in range(rectangle.__len__()):
|
||||
testResult = not keepOutMode # = False if is Keepout
|
||||
offset = (self.clearance) + self.size / 2
|
||||
# For keepout area: Deny Via
|
||||
# For same net area: Allow if not denied by keepout
|
||||
current_x = origin.x + (x * self.step)
|
||||
current_y = origin.y + (y * self.step)
|
||||
via_list = [] # Create a list of existing vias => faster than scanning through the whole rectangle
|
||||
max_target_area_clearance = 0
|
||||
|
||||
# Enum all target areas (Search possible positions for vias on the target net)
|
||||
for area in target_areas:
|
||||
print ("Processing Target Area: %s, LayerName: %s..." % (area.GetNetname(), area.GetLayerName()))
|
||||
|
||||
is_selected_area = area.IsSelected()
|
||||
area_clearance = area.GetClearance()
|
||||
if max_target_area_clearance < area_clearance:
|
||||
max_target_area_clearance = area_clearance
|
||||
|
||||
if (not self.only_selected_area) or (self.only_selected_area and is_selected_area): # All areas or only the selected area
|
||||
for x in xrange(len(rectangle)): # Check every possible point in the virtual coordinate system
|
||||
for y in xrange(len(rectangle[0])):
|
||||
if rectangle[x][y] == self.REASON_NO_SIGNAL: # No other "target area" found yet => go on with processing
|
||||
current_x = origin.x + (x * l_clearance) # Center of the via
|
||||
current_y = origin.y + (y * l_clearance)
|
||||
|
||||
test_result = True # Start with true, if a check fails, it is set to false
|
||||
|
||||
offset = max(self.clearance, area_clearance) + self.size / 2 # Offset is half the size of the via plus the clearance of the via or the area
|
||||
for dx in [-offset, offset]:
|
||||
for dy in [-offset, offset]:
|
||||
point_to_test = wxPoint(current_x + dx,
|
||||
current_y + dy)
|
||||
r = area.HitTestInsideZone(point_to_test)
|
||||
t = area.HitTestForEdge(point_to_test)
|
||||
r = r and not t
|
||||
if keepOutMode:
|
||||
testResult |= r
|
||||
else:
|
||||
testResult &= r
|
||||
|
||||
if testResult:
|
||||
if keepOutMode:
|
||||
rectangle[x][y] = 0x1
|
||||
else:
|
||||
# Allow only if it's first step disabling
|
||||
# ie: keepout are keeped
|
||||
if rectangle[x][y] == 0x8:
|
||||
rectangle[x][y] = 0
|
||||
for dy in [-offset, offset]: # All 4 corners of the via are testet (upper, lower, left, right) but not the center
|
||||
point_to_test = wxPoint(current_x + dx, current_y + dy)
|
||||
hit_test_area = area.HitTestFilledArea(point_to_test) # Collides with a filled area
|
||||
hit_test_edge = area.HitTestForEdge(point_to_test) # Collides with an edge/corner
|
||||
|
||||
test_result &= (hit_test_area and not hit_test_edge) # test_result only remains true if the via is inside an area and not on an edge
|
||||
|
||||
if test_result:
|
||||
via_obj = ViaObject(x=x, y=y, pos_x=current_x, pos_y=current_y) # Create a via object with information about the via and place it in the rectangle
|
||||
rectangle[x][y] = via_obj
|
||||
via_list.append(via_obj)
|
||||
|
||||
if self.debug:
|
||||
print("Post Area handling")
|
||||
print("\nPost target areas:")
|
||||
self.PrintRect(rectangle)
|
||||
|
||||
# Enum all vias
|
||||
print ("Processing all vias of target area...")
|
||||
for via in via_list:
|
||||
reason = self.CheckViaInAllAreas(via, all_areas)
|
||||
if reason != self.REASON_OK:
|
||||
rectangle[via.X][via.Y] = reason
|
||||
|
||||
if self.debug:
|
||||
print("\nPost areas:")
|
||||
self.PrintRect(rectangle)
|
||||
|
||||
# Same job with all pads => all pads on all layers
|
||||
print ("Processing all pads...")
|
||||
for pad in all_pads:
|
||||
local_offset = max(pad.GetClearance(), self.clearance, max_target_area_clearance) + (self.size / 2)
|
||||
max_size = max(pad.GetSize().x, pad.GetSize().y)
|
||||
|
||||
start_x = int(floor(((pad.GetPosition().x - (max_size / 2.0 + local_offset)) - origin.x) / l_clearance))
|
||||
stop_x = int(ceil(((pad.GetPosition().x + (max_size / 2.0 + local_offset)) - origin.x) / l_clearance))
|
||||
|
||||
# Same job with all pads
|
||||
for pad in self.pcb.GetPads():
|
||||
local_offset = max(pad.GetClearance(),
|
||||
self.clearance) + self.size / 2
|
||||
max_size = max(pad.GetSize().x, pad.GetSize().y)
|
||||
start_x = int(floor(((pad.GetPosition().x - (max_size / 2.0 +
|
||||
local_offset)) - origin.x) / self.step))
|
||||
stop_x = int(ceil(((pad.GetPosition().x + (max_size / 2.0 +
|
||||
local_offset)) - origin.x) / self.step))
|
||||
|
||||
start_y = int(floor(((pad.GetPosition().y - (max_size / 2.0 +
|
||||
local_offset)) - origin.y) / self.step))
|
||||
stop_y = int(ceil(((pad.GetPosition().y + (max_size / 2.0 +
|
||||
local_offset)) - origin.y) / self.step))
|
||||
start_y = int(floor(((pad.GetPosition().y - (max_size / 2.0 + local_offset)) - origin.y) / l_clearance))
|
||||
stop_y = int(ceil(((pad.GetPosition().y + (max_size / 2.0 + local_offset)) - origin.y) / l_clearance))
|
||||
|
||||
for x in range(start_x, stop_x + 1):
|
||||
for y in range(start_y, stop_y + 1):
|
||||
start_rect = wxPoint(origin.x + (self.step * x) -
|
||||
local_offset,
|
||||
origin.y + (self.step * y) -
|
||||
local_offset)
|
||||
size_rect = wxSize(2 * local_offset, 2 * local_offset)
|
||||
if pad.HitTest(EDA_RECT(start_rect, size_rect), False):
|
||||
rectangle[x][y] |= 0x2
|
||||
|
||||
# Same job with tracks
|
||||
for track in self.pcb.GetTracks():
|
||||
if isinstance(rectangle[x][y], ViaObject):
|
||||
start_rect = wxPoint(origin.x + (l_clearance * x) - local_offset,
|
||||
origin.y + (l_clearance * y) - local_offset)
|
||||
size_rect = wxSize(2 * local_offset, 2 * local_offset)
|
||||
if pad.HitTest(EDA_RECT(start_rect, size_rect), False):
|
||||
rectangle[x][y] = self.REASON_PAD
|
||||
|
||||
if self.debug:
|
||||
print("\nPost pads:")
|
||||
self.PrintRect(rectangle)
|
||||
|
||||
# Same job with tracks => all tracks on all layers
|
||||
print ("Processing all tracks...")
|
||||
for track in all_tracks:
|
||||
start_x = track.GetStart().x
|
||||
start_y = track.GetStart().y
|
||||
|
||||
@ -317,89 +439,77 @@ class FillArea:
|
||||
opx = stop_x
|
||||
opy = stop_y
|
||||
|
||||
clearance = max(track.GetClearance(), self.clearance) + \
|
||||
self.size / 2 + track.GetWidth() / 2
|
||||
clearance = max(track.GetClearance(), self.clearance, max_target_area_clearance) + (self.size / 2) + (track.GetWidth() / 2)
|
||||
|
||||
start_x = int(floor(((start_x - clearance) - origin.x) / l_clearance))
|
||||
stop_x = int(ceil(((stop_x + clearance) - origin.x) / l_clearance))
|
||||
|
||||
start_x = int(floor(((start_x - clearance) -
|
||||
origin.x) / self.step))
|
||||
stop_x = int(ceil(((stop_x + clearance) - origin.x) / self.step))
|
||||
|
||||
start_y = int(floor(((start_y - clearance) -
|
||||
origin.y) / self.step))
|
||||
stop_y = int(ceil(((stop_y + clearance) - origin.y) / self.step))
|
||||
start_y = int(floor(((start_y - clearance) - origin.y) / l_clearance))
|
||||
stop_y = int(ceil(((stop_y + clearance) - origin.y) / l_clearance))
|
||||
|
||||
for x in range(start_x, stop_x + 1):
|
||||
for y in range(start_y, stop_y + 1):
|
||||
start_rect = wxPoint(origin.x + (self.step * x) -
|
||||
clearance,
|
||||
origin.y + (self.step * y) -
|
||||
clearance)
|
||||
size_rect = wxSize(2 * clearance, 2 * clearance)
|
||||
if track.HitTest(EDA_RECT(start_rect, size_rect), False):
|
||||
rectangle[x][y] |= 0x4
|
||||
|
||||
if isinstance(rectangle[x][y], ViaObject):
|
||||
start_rect = wxPoint(origin.x + (l_clearance * x) - clearance,
|
||||
origin.y + (l_clearance * y) - clearance)
|
||||
size_rect = wxSize(2 * clearance, 2 * clearance)
|
||||
if track.HitTest(EDA_RECT(start_rect, size_rect), False):
|
||||
rectangle[x][y] = self.REASON_TRACK
|
||||
|
||||
if self.debug:
|
||||
print("Post Pad + tracks")
|
||||
print("\nPost tracks:")
|
||||
self.PrintRect(rectangle)
|
||||
|
||||
|
||||
# Same job with existing text
|
||||
for draw in self.pcb.DrawingsList():
|
||||
if (draw.GetClass() == 'PTEXT' and
|
||||
self.pcb.GetLayerID(draw.GetLayerName()) in (F_Cu, B_Cu)):
|
||||
inter = float(self.clearance + self.size)
|
||||
bbox = draw.GetBoundingBox()
|
||||
start_x = int(floor(((bbox.GetPosition().x - inter) -
|
||||
origin.x) / self.step))
|
||||
stop_x = int(ceil(((bbox.GetPosition().x +
|
||||
(bbox.GetSize().x + inter)) -
|
||||
origin.x) / self.step))
|
||||
print ("Processing all existing drawings...")
|
||||
for draw in all_drawings:
|
||||
inter = float(self.clearance + self.size)
|
||||
bbox = draw.GetBoundingBox()
|
||||
|
||||
start_x = int(floor(((bbox.GetPosition().x - inter) - origin.x) / l_clearance))
|
||||
stop_x = int(ceil(((bbox.GetPosition().x + (bbox.GetSize().x + inter)) - origin.x) / l_clearance))
|
||||
|
||||
start_y = int(floor(((bbox.GetPosition().y - inter) -
|
||||
origin.y) / self.step))
|
||||
stop_y = int(ceil(((bbox.GetPosition().y +
|
||||
(bbox.GetSize().y + inter)) -
|
||||
origin.y) / self.step))
|
||||
|
||||
for x in range(start_x, stop_x + 1):
|
||||
for y in range(start_y, stop_y + 1):
|
||||
rectangle[x][y] |= 0xA
|
||||
start_y = int(floor(((bbox.GetPosition().y - inter) - origin.y) / l_clearance))
|
||||
stop_y = int(ceil(((bbox.GetPosition().y + (bbox.GetSize().y + inter)) - origin.y) / l_clearance))
|
||||
|
||||
for x in range(start_x, stop_x + 1):
|
||||
for y in range(start_y, stop_y + 1):
|
||||
rectangle[x][y] = self.REASON_DRAWING
|
||||
|
||||
if self.debug:
|
||||
print("Post Drawnings: final result (0: mean ok for a via)")
|
||||
print("Post Drawnings:")
|
||||
self.PrintRect(rectangle)
|
||||
|
||||
for y in range(rectangle[0].__len__()):
|
||||
for x in range(rectangle.__len__()):
|
||||
if rectangle[x][y] == 0:
|
||||
ran_x = 0
|
||||
ran_y = 0
|
||||
|
||||
print ("Remove vias to guarantee step size...")
|
||||
clear_distance = 0
|
||||
if self.step != 0.0:
|
||||
clear_distance = int((self.step+l_clearance) / l_clearance) # How much "via steps" should be removed around a via (round up)
|
||||
|
||||
for x in xrange(len(rectangle)):
|
||||
for y in xrange(len(rectangle[0])):
|
||||
if isinstance(rectangle[x][y], ViaObject):
|
||||
if clear_distance:
|
||||
self.ClearViaInStepSize(rectangle, x, y, clear_distance)
|
||||
|
||||
via = rectangle[x][y]
|
||||
ran_x = 0
|
||||
ran_y = 0
|
||||
|
||||
if self.random:
|
||||
ran_x = (random.random() * self.step / 2.0) - \
|
||||
(self.step / 4.0)
|
||||
ran_y = (random.random() * self.step / 2.0) - \
|
||||
(self.step / 4.0)
|
||||
if self.star:
|
||||
if y % 2:
|
||||
if ((x + 1) % 2):
|
||||
self.AddVia(
|
||||
wxPoint(origin.x + (self.step * x) + ran_x,
|
||||
origin.y + (self.step * y) + ran_y), x, y)
|
||||
else:
|
||||
if (x % 2):
|
||||
self.AddVia(
|
||||
wxPoint(origin.x + (self.step * x) + ran_x,
|
||||
origin.y + (self.step * y) + ran_y), x, y)
|
||||
else:
|
||||
self.AddVia(
|
||||
wxPoint(origin.x + (self.step * x) + ran_x,
|
||||
origin.y + (self.step * y) + ran_y), x, y)
|
||||
ran_x = (random.random() * l_clearance / 2.0) - (l_clearance / 4.0)
|
||||
ran_y = (random.random() * l_clearance / 2.0) - (l_clearance / 4.0)
|
||||
|
||||
self.AddVia(wxPoint(via.PosX + ran_x, via.PosY + ran_y), via.X, via.Y)
|
||||
|
||||
if self.debug:
|
||||
print("\nFinal result:")
|
||||
self.PrintRect(rectangle)
|
||||
|
||||
self.RefillBoardAreas()
|
||||
|
||||
if self.filename:
|
||||
self.pcb.Save(self.filename)
|
||||
self.CleanupFootprint()
|
||||
|
||||
print ("Done!")
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) < 2:
|
||||
|
@ -41,19 +41,18 @@ class FillAreaAction(pcbnew.ActionPlugin):
|
||||
a.m_SizeMM.SetValue("0.46")
|
||||
a.m_StepMM.SetValue("2.54")
|
||||
a.m_DrillMM.SetValue("0.2")
|
||||
a.m_Netname.SetValue("auto")
|
||||
a.m_Netname.SetValue("GND")
|
||||
a.m_ClearanceMM.SetValue("0.2")
|
||||
a.m_Star.SetValue(True)
|
||||
modal_result = a.ShowModal()
|
||||
if modal_result == wx.ID_OK:
|
||||
fill = FillArea.FillArea()
|
||||
try:
|
||||
fill = FillArea.FillArea()
|
||||
fill.SetStepMM(float(a.m_StepMM.GetValue()))
|
||||
fill.SetSizeMM(float(a.m_SizeMM.GetValue()))
|
||||
fill.SetDrillMM(float(a.m_DrillMM.GetValue()))
|
||||
fill.SetClearanceMM(float(a.m_ClearanceMM.GetValue()))
|
||||
if a.m_Netname.GetValue() != "auto":
|
||||
fill.SetNetname(a.m_Netname.GetValue())
|
||||
fill.SetNetname(a.m_Netname.GetValue())
|
||||
if a.m_Debug.IsChecked():
|
||||
fill.SetDebug()
|
||||
if a.m_Random.IsChecked():
|
||||
@ -68,6 +67,7 @@ class FillAreaAction(pcbnew.ActionPlugin):
|
||||
elif modal_result == wx.ID_DELETE:
|
||||
try:
|
||||
fill = FillArea.FillArea()
|
||||
fill.SetNetname(a.m_Netname.GetValue())
|
||||
if a.m_Debug.IsChecked():
|
||||
fill.SetDebug()
|
||||
fill.DeleteVias()
|
||||
|
Reference in New Issue
Block a user