Persist settings

This commit is contained in:
jaseg 2020-12-29 12:03:52 +01:00
parent ecde8f1c8f
commit 8913c91e83
3 changed files with 278 additions and 5 deletions

View file

@ -863,6 +863,203 @@
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="1">
<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="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">Board edge clearance</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_staticText261</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="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizer51</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxSpinCtrlDouble" expanded="1">
<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="digits">3</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</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="inc">0.1</property>
<property name="initial">1.500000</property>
<property name="max">1000</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min">0</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_edgeClearanceSpin</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">wxSP_ARROW_KEYS</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="value"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="1">
<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="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">mm</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_staticText61</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>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL</property>

View file

@ -1,10 +1,12 @@
from collections import defaultdict
from dataclasses import dataclass
import dataclasses
from contextlib import contextmanager
import textwrap
import random
import math
from itertools import count, islice
import json
from os import path
import wx
@ -25,12 +27,14 @@ class GeneratorError(ValueError):
class AbortError(SystemError):
pass
@dataclass
@dataclasses.dataclass
class GeneratorSettings:
mesh_angle: float = 0.0 # deg
trace_width: float = 0.127 # mm
space_width: float = 0.127 # mm
edge_clearance: float = 1.5 # mm
anchor_exit: float = 0.0 # deg
anchor: str = None # Footprint designator
num_traces: int = 2
offset_x: float = 0.0 # mm
offset_y: float = 0.0 # mm
@ -40,6 +44,24 @@ class GeneratorSettings:
random_seed: str = None
randomness: float = 1.0
def serialize(self):
d = dataclasses.asdict(self)
d['kimesh_settings_version'] = '1.0.0'
return json.dumps(d).encode()
@classmethod
def deserialize(cls, data):
d = json.loads(data.decode())
version = d.pop('kimesh_settings_version')
vtup = tuple(map(int, version.split('.')))
if vtup > (2, 0, 0):
raise cls.VersionError("Project kimesh settings file is too new for this plugin's version.")
return cls(**d)
class VersionError(ValueError):
pass
class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog):
def __init__(self, board):
mesh_plugin_dialog.MainDialog.__init__(self, None)
@ -67,9 +89,32 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog):
self.m_maskLayerChoice.Append(name)
if name == 'User.Eco1':
self.m_maskLayerChoice.SetSelection(i)
elif name == 'F.Cu':
elif name == 'B.Cu':
self.m_layerChoice.SetSelection(i)
if path.isfile(self.settings_fn()):
with open(self.settings_fn(), 'rb') as f:
try:
settings = GeneratorSettings.deserialize(f.read())
self.m_angleSpin.Value = settings.mesh_angle
self.m_traceSpin.Value = settings.trace_width
self.m_spaceSpin.Value = settings.space_width
self.m_exitSpin.Value = settings.anchor_exit
self.m_anchorInput.Value = settings.anchor
self.m_traceCountSpin.Value = settings.num_traces
self.m_offsetXSpin.Value = settings.offset_x
self.m_offsetYSpin.Value = settings.offset_y
self.m_chamferSpin.Value = settings.chamfer*100.0
self.m_layerChoice.SetSelection(settings.target_layer_id)
self.m_maskLayerChoice.SetSelection(settings.mask_layer_id)
self.m_seedInput.Value = settings.random_seed or ''
self.m_randomnessSpin.Value = settings.randomness*100.0
self.m_edgeClearanceSpin.Value = settings.edge_clearance
except GeneratorSettings.VersionError as e:
wx.MessageDialog(self, "Cannot load settings: {}.".format(e), "File I/O error").ShowModal()
self.SetMinSize(self.GetSize())
def get_matching_nets(self):
@ -120,13 +165,18 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog):
self.board.Remove(track)
print(f'Tore up {count} trace segments.')
def settings_fn(self):
return path.join(path.dirname(self.board.GetFileName()), 'last_kimesh_settings.json')
def generate_mesh(self, evt):
try:
settings = GeneratorSettings(
mesh_angle = float(self.m_angleSpin.Value),
trace_width = float(self.m_traceSpin.Value),
space_width = float(self.m_spaceSpin.Value),
edge_clearance = float(self.m_edgeClearanceSpin.Value),
anchor_exit = float(self.m_exitSpin.Value),
anchor = str(self.m_anchorInput.Value),
num_traces = int(self.m_traceCountSpin.Value),
offset_x = float(self.m_offsetXSpin.Value),
offset_y = float(self.m_offsetYSpin.Value),
@ -138,6 +188,13 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog):
except ValueError as e:
return wx.MessageDialog(self, "Invalid input value: {}.".format(e), "Invalid input").ShowModal()
try:
with open(self.settings_fn(), 'wb') as f:
f.write(settings.serialize())
print('Saved settings to', f.name)
except:
wx.MessageDialog(self, "Cannot save settings: {}.".format(e), "File I/O error").ShowModal()
mesh_zones = []
for drawing in self.board.GetDrawings():
if drawing.GetLayer() == settings.mask_layer_id:
@ -151,13 +208,14 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog):
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)
zone_outlines = [ outline for zone in mesh_zones for outline in self.poly_set_to_shapely(zone.GetPolyShape()) ]
zone_mask = shapely.ops.unary_union(zone_outlines)
mask = zone_mask.intersection(board_mask)
anchor = [ mod for mod in self.board.GetModules() if mod.GetReference() == self.m_anchorInput.Value ]
anchor = [ mod for mod in self.board.GetModules() if mod.GetReference() == settings.anchor ]
if len(anchor) == 0:
return wx.MessageDialog(self, f'Error: Could not find anchor footprint "{self.m_anchorInput.Value}".').ShowModal()
if len(anchor) > 1:
@ -546,7 +604,6 @@ def virihex(val, max=1.0, alpha=1.0):
@contextmanager
def DebugOutput(filename):
from os import path
filename = path.join('/tmp', filename)
with open(filename, 'w') as f:
wrapper = DebugOutputWrapper(f)

View file

@ -101,6 +101,25 @@ class MainDialog ( wx.Dialog ):
fgSizer1.Add( bSizer6, 1, wx.EXPAND, 5 )
self.m_staticText261 = wx.StaticText( self, wx.ID_ANY, u"Board edge clearance", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText261.Wrap( -1 )
fgSizer1.Add( self.m_staticText261, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT|wx.ALL, 5 )
bSizer51 = wx.BoxSizer( wx.HORIZONTAL )
self.m_edgeClearanceSpin = wx.SpinCtrlDouble( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.SP_ARROW_KEYS, 0, 1000, 1.500000, 0.1 )
self.m_edgeClearanceSpin.SetDigits( 3 )
bSizer51.Add( self.m_edgeClearanceSpin, 0, wx.ALL, 5 )
self.m_staticText61 = wx.StaticText( self, wx.ID_ANY, u"mm", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText61.Wrap( -1 )
bSizer51.Add( self.m_staticText61, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
fgSizer1.Add( bSizer51, 1, wx.EXPAND, 5 )
self.m_staticText11 = wx.StaticText( self, wx.ID_ANY, u"Anchor exit direction", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText11.Wrap( -1 )