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
|
from collections import defaultdict
import wx
import pcbnew
import shapely
from . import mesh_plugin_dialog
# Implementing MainDialog
class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog):
def __init__(self, board):
mesh_plugin_dialog.MainDialog.__init__(self, None)
self.board = board
self.m_cancelButton.Bind(wx.EVT_BUTTON, self.quit)
self.m_removeButton.Bind(wx.EVT_BUTTON, self.tearup_mesh)
self.m_generateButton.Bind(wx.EVT_BUTTON, self.generate_mesh)
self.m_net_prefix.Bind(wx.EVT_TEXT, self.update_net_label)
self.m_traceSpin.Bind(wx.EVT_SPIN_UP, lambda evt: self.spin(self.m_traceInput, 1.0))
self.m_traceSpin.Bind(wx.EVT_SPIN_DOWN, lambda evt: self.spin(self.m_traceInput, -1.0))
self.m_spaceSpin.Bind(wx.EVT_SPIN_UP, lambda evt: self.spin(self.m_spaceInput, 1.0))
self.m_spaceSpin.Bind(wx.EVT_SPIN_DOWN, lambda evt: self.spin(self.m_spaceInput, -1.0))
self.tearup_confirm_dialog = wx.MessageDialog(self, "", style=wx.YES_NO | wx.NO_DEFAULT)
self.nets = { str(wxs) for wxs, netinfo in board.GetNetsByName().items() }
self.update_net_label(None)
self.SetMinSize(self.GetSize())
def spin(self, le_input, delta):
try:
current = float(le_input.Value)
current += delta
le_input.Value = '{:.03f}'.format(current)
except ValueError:
pass
def get_matching_nets(self):
prefix = self.m_net_prefix.Value
return { net for net in self.nets if net.startswith(prefix) }
def tearup_mesh(self, evt):
matching = self.get_matching_nets()
if not str(self.m_net_prefix.Value):
message = "You have set an empty net prefix. This will match ALL {} nets on the board. Do you really want to tear up all autorouted tracks? This cannot be undone!"
else:
message = "Do you really want to tear up all autorouted traces of the {} matching nets on this board? This step cannot be undone!"
message = message.format(len(matching)) + "\n\nMatching nets:\n" + ", ".join(
'""' if not netname else (netname[:16] + '...' if len(netname) > 16 else netname)
for netname in (sorted(matching)[:5] + ['...'] if len(matching) > 5 else [])
)
self.tearup_confirm_dialog.SetMessage(message)
self.tearup_confirm_dialog.SetYesNoLabels("Tear up {} nets".format(len(matching)), "Close")
if self.tearup_confirm_dialog.ShowModal() == wx.ID_YES:
for track in self.board.GetTracks():
if not (track.GetStatus() & pcbnew.TRACK_AR):
continue
if not track.GetNet().GetNetname() in matching:
continue
board.Remove(track)
def generate_mesh(self, evt):
nets = self.get_matching_nets()
pads = defaultdict(lambda: [])
for module in self.board.GetModules():
for pad in module.Pads():
net = pad.GetNetname()
if net in nets:
pads[net].append(pad)
for net in nets:
if net not in pads:
return wx.MessageDialog(self, "Error: No connection pads found for net {}.".format(net)).ShowModal()
if len(pads[net]) == 1:
return wx.MessageDialog(self, "Error: Only one of two connection pads found for net {}.".format(net)).ShowModal()
if len(pads[net]) > 2:
return wx.MessageDialog(self, "Error: More than two connection pads found for net {}.".format(net)).ShowModal()
eco1_id = self.board.GetLayerID('Eco1.User')
mesh_zones = []
for drawing in self.board.GetDrawings():
if drawing.GetLayer() == eco1_id:
mesh_zones.append(drawing)
if not mesh_zones:
return wx.MessageDialog(self, "Error: Could not find any mesh zones on the Eco1.User layer.").ShowModal()
for zone in mesh_zones:
anchors = []
for module in self.board.GetModules():
for foo in module.GraphicalItems():
if not isinstance(foo, pcbnew.TEXTE_MODULE):
continue
if foo.GetText() == "mesh_anchor":
anchors.append(module)
break
if not anchors:
return wx.MessageDialog(self, "Error: No anchor found for mesh zone centered on {:.3f}, {:.3f} mm".format(
zone.GetCenter().x / pcbnew.IU_PER_MM, zone.GetCenter().y / pcbnew.IU_PER_MM
)).ShowModal()
if len(anchors) > 1:
return wx.MessageDialog(self, "Error: Currently, only a single anchor is supported.").ShowModal()
self.generate_mesh(zone, anchors)
def generate_mesh(self, zone, anchors):
anchor, = anchors
def update_net_label(self, evt):
self.m_netLabel.SetLabel('{} matching nets'.format(len(self.get_matching_nets())))
def quit(self, evt):
self.Destroy()
def show_dialog(board):
dialog = MeshPluginMainDialog(board)
dialog.ShowModal()
return dialog
|