Improve error handling, add runtime options
This commit is contained in:
parent
cac262ce37
commit
c4f176d3f4
3 changed files with 556 additions and 41 deletions
416
main_dialog.fbp
416
main_dialog.fbp
|
|
@ -48,7 +48,7 @@
|
|||
<property name="minimum_size"></property>
|
||||
<property name="name">MainDialog</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">632,458</property>
|
||||
<property name="size">632,580</property>
|
||||
<property name="style">wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxMINIMIZE_BOX|wxRESIZE_BORDER|wxSTAY_ON_TOP</property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="title">Security Mesh Generator Plugin</property>
|
||||
|
|
@ -62,6 +62,68 @@
|
|||
<property name="name">bSizer1</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label"><font color="red"><b>Warning: Board outline not found</b></font></property>
|
||||
<property name="markup">1</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_warningLabel</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxALIGN_CENTER_HORIZONTAL</property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
|
|
@ -1333,6 +1395,358 @@
|
|||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="spacer" expanded="true">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="checked">1</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Respect zone keepouts</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_useKeepoutCheckbox</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="spacer" expanded="true">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="checked">1</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Respect board outline</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_useOutlineCheckbox</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="spacer" expanded="true">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="checked">1</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Save layout visualizations</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_vizCheckbox</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Visualization output directory</property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_staticText14</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxTextCtrl" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="maxlength"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_vizTextfield</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="value"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
|
|
|
|||
142
mesh_dialog.py
142
mesh_dialog.py
|
|
@ -8,6 +8,7 @@ from itertools import count, islice
|
|||
import json
|
||||
import re
|
||||
from os import path
|
||||
import os
|
||||
|
||||
import wx
|
||||
|
||||
|
|
@ -30,16 +31,20 @@ class AbortError(SystemError):
|
|||
|
||||
@dataclasses.dataclass
|
||||
class GeneratorSettings:
|
||||
edge_clearance: float = 1.5 # mm
|
||||
anchor: str = None # Footprint designator
|
||||
chamfer: float = 0.0 # unit fraction
|
||||
mask_layer_id: int = 0 # kicad layer id, populated later
|
||||
random_seed: str = None
|
||||
randomness: float = 1.0
|
||||
edge_clearance: float = 1.5 # mm
|
||||
anchor: str = None # Footprint designator
|
||||
chamfer: float = 0.0 # unit fraction
|
||||
mask_layer_id: int = 0 # kicad layer id, populated later
|
||||
random_seed: str = None
|
||||
randomness: float = 1.0
|
||||
use_keepouts: bool = True
|
||||
use_outline: bool = True
|
||||
save_visualization: bool = True
|
||||
visualization_path: str = 'mesh_visualizations'
|
||||
|
||||
def serialize(self):
|
||||
d = dataclasses.asdict(self)
|
||||
d['kimesh_settings_version'] = '2.0.0'
|
||||
d['kimesh_settings_version'] = '2.1.0'
|
||||
return json.dumps(d).encode()
|
||||
|
||||
@classmethod
|
||||
|
|
@ -47,7 +52,7 @@ class GeneratorSettings:
|
|||
d = json.loads(data.decode())
|
||||
version = d.pop('kimesh_settings_version')
|
||||
vtup = tuple(map(int, version.split('.')))
|
||||
if vtup > (2, 0, 0):
|
||||
if vtup > (2, 1, 0):
|
||||
raise cls.VersionError("Project kimesh settings file is too new for this plugin's version.")
|
||||
return cls(**d)
|
||||
|
||||
|
|
@ -69,6 +74,7 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog):
|
|||
|
||||
self.nets = { str(wxs) for wxs, netinfo in board.GetNetsByName().items() }
|
||||
self.update_net_label(None)
|
||||
self.update_outline_warning()
|
||||
|
||||
self.Fit()
|
||||
|
||||
|
|
@ -104,9 +110,64 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog):
|
|||
self.m_seedInput.Value = settings.random_seed or ''
|
||||
self.m_randomnessSpin.Value = settings.randomness*100.0
|
||||
self.m_edgeClearanceSpin.Value = settings.edge_clearance
|
||||
self.m_useOutlineCheckbox.Value = settings.use_outline
|
||||
self.m_useKeepoutCheckbox.Value = settings.use_keepouts
|
||||
self.m_vizTextfield.Value = settings.visualization_path
|
||||
self.m_vizCheckbox.Value = settings.save_visualization
|
||||
|
||||
self.SetMinSize(self.GetSize())
|
||||
|
||||
@contextmanager
|
||||
def viz(self, filename):
|
||||
if self.m_vizCheckbox.Value:
|
||||
val = self.m_vizTextfield.Value
|
||||
project_dir = path.dirname(self.board.GetFileName())
|
||||
if val:
|
||||
val = path.join(project_dir, val)
|
||||
if not os.path.isdir(val):
|
||||
os.mkdir(val)
|
||||
filename = path.join(val, filename)
|
||||
|
||||
filename = path.join(project_dir, filename)
|
||||
with open(filename, 'w') as f:
|
||||
wrapper = DebugOutputWrapper(f)
|
||||
yield wrapper
|
||||
wrapper.save()
|
||||
|
||||
else:
|
||||
wrapper = DebugOutputWrapper(None)
|
||||
yield wrapper
|
||||
|
||||
def board_has_outline(self):
|
||||
# KiCad's API is absolutely insane. As long as the board has an outline, the board outline function works
|
||||
# alright. Now imagine the Edge.Cuts layer is empty. What would be a sane thing to do? I guess raising an error
|
||||
# would be the best, with the second best being to return something like the hull of all objects on the other
|
||||
# layers. Alas, KiCad doesn't do either. Instead, KiCad returns the union of the shapes of all objects on the
|
||||
# **VISIBLE** layers, so the result of that outline function changes with which layers the user has set to
|
||||
# visible. Whyyyyy :(
|
||||
#
|
||||
# We have to work around this to avoid presenting the user with a foot-gun in case they hide their mesh
|
||||
# definition layer.
|
||||
#
|
||||
edge_cuts = self.board.GetLayerID('Edge.Cuts')
|
||||
outline_objs = []
|
||||
for drawing in self.board.GetDrawings():
|
||||
if drawing.GetLayer() == edge_cuts:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def update_outline_warning(self):
|
||||
outlines = pcbnew.SHAPE_POLY_SET()
|
||||
self.board.GetBoardPolygonOutlines(outlines)
|
||||
board_outlines = list(self.poly_set_to_shapely(outlines))
|
||||
board_mask = shapely.ops.unary_union(board_outlines)
|
||||
|
||||
if not self.board_has_outline() or board_mask.is_empty:
|
||||
self.m_warningLabel.SetLabelMarkup('<b>Warning: Board outline not found</b>')
|
||||
else:
|
||||
self.m_warningLabel.SetLabelMarkup('')
|
||||
|
||||
def get_matching_nets(self):
|
||||
prefix = self.m_net_prefix.Value
|
||||
return { net for net in self.nets if net.startswith(prefix) }
|
||||
|
|
@ -170,7 +231,11 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog):
|
|||
chamfer = float(self.m_chamferSpin.Value)/100.0,
|
||||
mask_layer_id = self.m_maskLayerChoice.GetSelection(),
|
||||
random_seed = str(self.m_seedInput.Value) or None,
|
||||
randomness = float(self.m_randomnessSpin.Value)/100.0)
|
||||
randomness = float(self.m_randomnessSpin.Value)/100.0,
|
||||
use_outline = self.m_useOutlineCheckbox.Value,
|
||||
use_keepouts = self.m_useKeepoutCheckbox.Value,
|
||||
visualization_path = self.m_vizTextfield.Value,
|
||||
save_visualization = self.m_vizCheckbox.Value)
|
||||
except ValueError as e:
|
||||
return wx.MessageDialog(self, "Invalid input value: {}.".format(e), "Invalid input").ShowModal()
|
||||
|
||||
|
|
@ -198,29 +263,37 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog):
|
|||
keepouts.append(zone.Outline())
|
||||
print(f'Found {len(keepouts)} keepout areas.')
|
||||
|
||||
outlines = pcbnew.SHAPE_POLY_SET()
|
||||
self.board.GetBoardPolygonOutlines(outlines)
|
||||
board_outlines = list(self.poly_set_to_shapely(outlines))
|
||||
board_mask = shapely.ops.unary_union(board_outlines)
|
||||
board_mask = board_mask.buffer(-settings.edge_clearance)
|
||||
print('board outline bounds:', board_mask.bounds)
|
||||
if board_mask.is_empty:
|
||||
return wx.MessageDialog(self, "Error: Could not find the board outline, or board edge clearance is set too high.").ShowModal()
|
||||
if self.board_has_outline() and self.m_useOutlineCheckbox.Value: # Avoid foot-gun due to insane API. See note in the function.
|
||||
outlines = pcbnew.SHAPE_POLY_SET()
|
||||
self.board.GetBoardPolygonOutlines(outlines)
|
||||
board_outlines = list(self.poly_set_to_shapely(outlines))
|
||||
board_mask = shapely.ops.unary_union(board_outlines)
|
||||
mask = board_mask.buffer(-settings.edge_clearance)
|
||||
print('board outline bounds:', mask.bounds)
|
||||
if mask.is_empty:
|
||||
return wx.MessageDialog(self, "Error: Board edge clearance is set too high. There is nothing left for the mesh after applying clearance.").ShowModal()
|
||||
else:
|
||||
mask = None
|
||||
|
||||
zone_outlines = [ outline for zone in mesh_zones for outline in self.poly_set_to_shapely(zone) ]
|
||||
zone_mask = shapely.ops.unary_union(zone_outlines)
|
||||
if zone_mask.is_empty:
|
||||
mask = board_mask
|
||||
return wx.MessageDialog(self, "Error: Empty mesh outline on mesh outline layer. Make sure the mesh outline is defined with polygon objects only. Other shapes are not supported yet.").ShowModal()
|
||||
elif mask is None:
|
||||
mask = zone_mask
|
||||
else:
|
||||
mask = zone_mask.intersection(board_mask)
|
||||
mask = zone_mask.intersection(mask)
|
||||
print('Mesh mask bounds:', zone_mask.bounds)
|
||||
|
||||
keepout_outlines = [ outline for zone in keepouts for outline in self.poly_set_to_shapely(zone) ]
|
||||
keepout_mask = shapely.ops.unary_union(keepout_outlines)
|
||||
if not keepout_mask.is_empty:
|
||||
mask = shapely.difference(mask, keepout_mask)
|
||||
print('keepout mask bounds:', keepout_mask.bounds)
|
||||
print('resulting mask bounds:', mask.bounds)
|
||||
if self.m_useKeepoutCheckbox.Value:
|
||||
keepout_outlines = [ outline for zone in keepouts for outline in self.poly_set_to_shapely(zone) ]
|
||||
keepout_mask = shapely.ops.unary_union(keepout_outlines)
|
||||
if not keepout_mask.is_empty:
|
||||
mask = shapely.difference(mask, keepout_mask)
|
||||
print('keepout mask bounds:', keepout_mask.bounds)
|
||||
print('resulting mask bounds:', mask.bounds)
|
||||
if mask.is_empty:
|
||||
return wx.MessageDialog(self, "Error: After applying all keepouts, and intersecting with the board's outline, the mesh outline is empty.")
|
||||
|
||||
try:
|
||||
def warn(msg):
|
||||
|
|
@ -307,7 +380,7 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog):
|
|||
grid.append(row)
|
||||
|
||||
num_valid = 0
|
||||
with DebugOutput('dbg_grid.svg') as dbg:
|
||||
with self.viz('mesh_grid.svg') as dbg:
|
||||
dbg.add(mask, color='#00000020')
|
||||
|
||||
for y, row in enumerate(grid, start=grid_y0):
|
||||
|
|
@ -389,10 +462,10 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog):
|
|||
not_visited = { (x, y) for x in range(grid_x0, grid_x0+grid_cols) for y in range(grid_y0, grid_y0+grid_rows) if is_valid(grid[y-grid_y0][x-grid_x0]) }
|
||||
num_to_visit = len(not_visited)
|
||||
track_count = 0
|
||||
with DebugOutput('dbg_cells.svg') as dbg_cells,\
|
||||
DebugOutput('dbg_composite.svg') as dbg_composite,\
|
||||
DebugOutput('dbg_tiles.svg') as dbg_tiles,\
|
||||
DebugOutput('dbg_traces.svg') as dbg_traces:
|
||||
with self.viz('mesh_cells.svg') as dbg_cells,\
|
||||
self.viz('mesh_composite.svg') as dbg_composite,\
|
||||
self.viz('mesh_tiles.svg') as dbg_tiles,\
|
||||
self.viz('mesh_traces.svg') as dbg_traces:
|
||||
dbg_cells.add(mask, color='#00000020')
|
||||
dbg_composite.add(mask, color='#00000020')
|
||||
dbg_traces.add(mask, color='#00000020')
|
||||
|
|
@ -425,7 +498,7 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog):
|
|||
i = 0
|
||||
past_tiles = {}
|
||||
def dump_output(i):
|
||||
with DebugOutput(f'per-tile/step{i}.svg') as dbg_per_tile:
|
||||
with self.viz(f'per-tile/step{i}.svg') as dbg_per_tile:
|
||||
dbg_per_tile.add(mask, color='#00000020')
|
||||
for foo in anchor_outlines:
|
||||
dbg_per_tile.add(foo, color='#00000080', stroke_width=0.05, stroke_color='#00000000')
|
||||
|
|
@ -607,13 +680,6 @@ def virihex(val, max=1.0, alpha=1.0):
|
|||
r, g, b, a = [ int(round(0xff*c)) for c in [r, g, b, alpha] ]
|
||||
return f'#{r:02x}{g:02x}{b:02x}{a:02x}'
|
||||
|
||||
@contextmanager
|
||||
def DebugOutput(filename):
|
||||
with open(filename, 'w') as f:
|
||||
wrapper = DebugOutputWrapper(f)
|
||||
yield wrapper
|
||||
wrapper.save()
|
||||
|
||||
class DebugOutputWrapper:
|
||||
def __init__(self, f):
|
||||
self.f = f
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
###########################################################################
|
||||
## Python code generated with wxFormBuilder (version 3.10.1-367-gf0e67a69)
|
||||
## Python code generated with wxFormBuilder (version 3.10.1-380-gf48f2659)
|
||||
## http://www.wxformbuilder.org/
|
||||
##
|
||||
## PLEASE DO *NOT* EDIT THIS FILE!
|
||||
|
|
@ -17,12 +17,18 @@ import wx.xrc
|
|||
class MainDialog ( wx.Dialog ):
|
||||
|
||||
def __init__( self, parent ):
|
||||
wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"Security Mesh Generator Plugin", pos = wx.DefaultPosition, size = wx.Size( 632,458 ), style = wx.CLOSE_BOX|wx.DEFAULT_DIALOG_STYLE|wx.MINIMIZE_BOX|wx.RESIZE_BORDER|wx.STAY_ON_TOP )
|
||||
wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"Security Mesh Generator Plugin", pos = wx.DefaultPosition, size = wx.Size( 632,580 ), style = wx.CLOSE_BOX|wx.DEFAULT_DIALOG_STYLE|wx.MINIMIZE_BOX|wx.RESIZE_BORDER|wx.STAY_ON_TOP )
|
||||
|
||||
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
|
||||
|
||||
bSizer1 = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
self.m_warningLabel = wx.StaticText( self, wx.ID_ANY, u"<font color=\"red\"><b>Warning: Board outline not found</b></font>", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_CENTER_HORIZONTAL )
|
||||
self.m_warningLabel.SetLabelMarkup( u"<font color=\"red\"><b>Warning: Board outline not found</b></font>" )
|
||||
self.m_warningLabel.Wrap( -1 )
|
||||
|
||||
bSizer1.Add( self.m_warningLabel, 0, wx.ALL|wx.EXPAND, 5 )
|
||||
|
||||
fgSizer1 = wx.FlexGridSizer( 0, 2, 0, 0 )
|
||||
fgSizer1.AddGrowableCol( 1 )
|
||||
fgSizer1.SetFlexibleDirection( wx.BOTH )
|
||||
|
|
@ -138,6 +144,35 @@ class MainDialog ( wx.Dialog ):
|
|||
fgSizer1.Add( bSizer12, 1, wx.EXPAND, 5 )
|
||||
|
||||
|
||||
fgSizer1.Add( ( 0, 0), 1, wx.EXPAND, 5 )
|
||||
|
||||
self.m_useKeepoutCheckbox = wx.CheckBox( self, wx.ID_ANY, u"Respect zone keepouts", wx.DefaultPosition, wx.DefaultSize, 0 )
|
||||
self.m_useKeepoutCheckbox.SetValue(True)
|
||||
fgSizer1.Add( self.m_useKeepoutCheckbox, 0, wx.ALL, 5 )
|
||||
|
||||
|
||||
fgSizer1.Add( ( 0, 0), 1, wx.EXPAND, 5 )
|
||||
|
||||
self.m_useOutlineCheckbox = wx.CheckBox( self, wx.ID_ANY, u"Respect board outline", wx.DefaultPosition, wx.DefaultSize, 0 )
|
||||
self.m_useOutlineCheckbox.SetValue(True)
|
||||
fgSizer1.Add( self.m_useOutlineCheckbox, 0, wx.ALL, 5 )
|
||||
|
||||
|
||||
fgSizer1.Add( ( 0, 0), 1, wx.EXPAND, 5 )
|
||||
|
||||
self.m_vizCheckbox = wx.CheckBox( self, wx.ID_ANY, u"Save layout visualizations", wx.DefaultPosition, wx.DefaultSize, 0 )
|
||||
self.m_vizCheckbox.SetValue(True)
|
||||
fgSizer1.Add( self.m_vizCheckbox, 0, wx.ALL, 5 )
|
||||
|
||||
self.m_staticText14 = wx.StaticText( self, wx.ID_ANY, u"Visualization output directory", wx.DefaultPosition, wx.DefaultSize, 0 )
|
||||
self.m_staticText14.Wrap( -1 )
|
||||
|
||||
fgSizer1.Add( self.m_staticText14, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT|wx.ALL, 5 )
|
||||
|
||||
self.m_vizTextfield = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
|
||||
fgSizer1.Add( self.m_vizTextfield, 0, wx.ALL|wx.EXPAND, 5 )
|
||||
|
||||
|
||||
bSizer1.Add( fgSizer1, 1, wx.EXPAND, 5 )
|
||||
|
||||
bSizer99 = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue