add bt_player

This commit is contained in:
2021-11-24 17:00:32 +01:00
parent 3bc6987c3b
commit 880e936dc3
92 changed files with 16476 additions and 0 deletions

View File

@@ -0,0 +1,141 @@
# -*- coding: utf-8 -*-
###########################################################################
## Python code generated with wxFormBuilder (version Oct 26 2018)
## http://www.wxformbuilder.org/
##
## PLEASE DO *NOT* EDIT THIS FILE!
###########################################################################
import wx
import wx.xrc
###########################################################################
## Class RoundTrackDlg
###########################################################################
class RoundTrackDlg ( wx.Dialog ):
def __init__( self, parent ):
wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"Round Track parameters", pos = wx.DefaultPosition, size = wx.Size( 432,532 ), style = wx.CAPTION|wx.CLOSE_BOX|wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER )
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
bSizer3 = wx.BoxSizer( wx.VERTICAL )
self.m_comment = wx.StaticText( self, wx.ID_ANY, u"Select Two angled Tracks\n", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_comment.Wrap( -1 )
bSizer3.Add( self.m_comment, 0, wx.ALL|wx.EXPAND, 5 )
bSizer31 = wx.BoxSizer( wx.HORIZONTAL )
self.m_staticText3 = wx.StaticText( self, wx.ID_ANY, u"Distance from Intersection (mm)", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText3.Wrap( -1 )
bSizer31.Add( self.m_staticText3, 1, wx.ALL|wx.EXPAND, 5 )
self.m_distanceMM = wx.TextCtrl( self, wx.ID_ANY, u"5", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_distanceMM.SetMinSize( wx.Size( 1000,-1 ) )
bSizer31.Add( self.m_distanceMM, 1, wx.ALL|wx.EXPAND, 5 )
bSizer3.Add( bSizer31, 0, 0, 5 )
bSizer311 = wx.BoxSizer( wx.HORIZONTAL )
self.m_staticText31 = wx.StaticText( self, wx.ID_ANY, u"Number of segments .. (1-32)", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText31.Wrap( -1 )
bSizer311.Add( self.m_staticText31, 1, wx.ALL|wx.EXPAND, 5 )
self.m_segments = wx.TextCtrl( self, wx.ID_ANY, u"16", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_segments.SetMinSize( wx.Size( 1000,-1 ) )
bSizer311.Add( self.m_segments, 1, wx.ALL, 5 )
bSizer3.Add( bSizer311, 1, wx.EXPAND, 5 )
self.m_staticline1 = wx.StaticLine( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
bSizer3.Add( self.m_staticline1, 0, wx.EXPAND |wx.ALL, 5 )
bSizer12 = wx.BoxSizer( wx.HORIZONTAL )
self.m_staticText1013 = wx.StaticText( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText1013.Wrap( -1 )
bSizer12.Add( self.m_staticText1013, 1, wx.ALL, 5 )
self.m_bitmap1 = wx.StaticBitmap( self, wx.ID_ANY, wx.NullBitmap, wx.DefaultPosition, wx.Size( 180,100 ), 0 )
bSizer12.Add( self.m_bitmap1, 1, wx.EXPAND, 5 )
bSizer3.Add( bSizer12, 1, wx.EXPAND, 5 )
bSizer1 = wx.BoxSizer( wx.HORIZONTAL )
self.m_buttonRound = wx.Button( self, wx.ID_OK, u"Round", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_buttonRound.SetDefault()
bSizer1.Add( self.m_buttonRound, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_buttonCancel = wx.Button( self, wx.ID_CANCEL, u"Cancel", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer1.Add( self.m_buttonCancel, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
bSizer3.Add( bSizer1, 0, wx.ALIGN_RIGHT|wx.EXPAND, 5 )
sbSizer1 = wx.StaticBoxSizer( wx.StaticBox( self, wx.ID_ANY, u"Reconnecting" ), wx.VERTICAL )
bSizer611 = wx.BoxSizer( wx.VERTICAL )
self.m_staticText81 = wx.StaticText( sbSizer1.GetStaticBox(), wx.ID_ANY, u"Select a Track to delete round segments", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText81.Wrap( -1 )
bSizer611.Add( self.m_staticText81, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.EXPAND, 5 )
self.m_buttonDelete = wx.Button( sbSizer1.GetStaticBox(), wx.ID_OK, u"Delete", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer611.Add( self.m_buttonDelete, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_staticline2 = wx.StaticLine( sbSizer1.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL )
bSizer611.Add( self.m_staticline2, 0, wx.EXPAND |wx.ALL, 5 )
sbSizer1.Add( bSizer611, 1, wx.EXPAND, 5 )
bSizer111 = wx.BoxSizer( wx.HORIZONTAL )
bSizer8 = wx.BoxSizer( wx.VERTICAL )
self.m_buttonReconnect = wx.Button( sbSizer1.GetStaticBox(), wx.ID_OK, u"Connect", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer8.Add( self.m_buttonReconnect, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )
self.m_checkBoxDelete = wx.CheckBox( sbSizer1.GetStaticBox(), wx.ID_ANY, u"clean path", wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer8.Add( self.m_checkBoxDelete, 0, wx.ALL, 5 )
bSizer111.Add( bSizer8, 1, wx.EXPAND, 5 )
self.m_staticText10111 = wx.StaticText( sbSizer1.GetStaticBox(), wx.ID_ANY, u"Select tracks including one round corner to be straighten", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText10111.Wrap( -1 )
bSizer111.Add( self.m_staticText10111, 1, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 5 )
sbSizer1.Add( bSizer111, 1, wx.EXPAND, 5 )
bSizer3.Add( sbSizer1, 1, wx.EXPAND, 5 )
self.SetSizer( bSizer3 )
self.Layout()
self.Centre( wx.BOTH )
def __del__( self ):
pass

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
from .round_trk import Tracks_Rounder
Tracks_Rounder().register()

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="26"
width="26"
version="1.1"
id="svg2"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="round_track.svg">
<metadata
id="metadata50">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1600"
inkscape:window-height="824"
id="namedview48"
showgrid="true"
inkscape:zoom="16.23626"
inkscape:cx="15.481167"
inkscape:cy="17.524039"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2"
inkscape:snap-to-guides="false"
inkscape:snap-grids="true"
showguides="true"
inkscape:guide-bbox="true">
<inkscape:grid
type="xygrid"
id="grid3006"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<defs
id="defs4" />
<path
sodipodi:nodetypes="ccc"
inkscape:connector-curvature="0"
id="path3783"
d="M 22.079265,22.989018 22,4 3.669302,3.8797396"
style="fill:none;fill-opacity:1;stroke:#4d4d4d;stroke-width:1.72992396;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:type="arc"
style="fill:none;stroke:#008000;stroke-width:2.16862085;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path2986"
sodipodi:cx="4"
sodipodi:cy="22"
sodipodi:rx="19.517588"
sodipodi:ry="19.517588"
d="M 4.0006035,2.4824123 A 19.517588,19.517588 0 0 1 23.517584,21.988092"
sodipodi:start="4.7124199"
sodipodi:end="6.2825752"
sodipodi:open="true"
transform="matrix(0.92224512,0,0,0.92224512,0.3110195,1.7106073)" />
<rect
style="fill:#2ac23c;fill-opacity:1;fill-rule:evenodd;stroke:#666666;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3776"
width="5"
height="5.0000005"
x="1.5"
y="1.4999995"
ry="2.5"
rx="2.5" />
<rect
rx="2.5"
ry="2.5"
y="1.4999995"
x="19.5"
height="5.0000005"
width="5"
id="rect3761"
style="fill:#2ac23c;fill-opacity:1;fill-rule:evenodd;stroke:#666666;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="fill:#2ac23c;fill-opacity:1;fill-rule:evenodd;stroke:#666666;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3763"
width="5"
height="5.0000005"
x="19.5"
y="19.5"
ry="2.5"
rx="2.5" />
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@@ -0,0 +1,196 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="40.120056"
width="65.120071"
version="1.1"
id="svg2"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="round_track_help.svg"
inkscape:export-filename="/home/mau/.kicad_plugins/round_tracks/round_track_help.png"
inkscape:export-xdpi="220.90854"
inkscape:export-ydpi="220.90854">
<metadata
id="metadata50">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1600"
inkscape:window-height="824"
id="namedview48"
showgrid="true"
inkscape:zoom="10.165207"
inkscape:cx="28.451364"
inkscape:cy="21.719276"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2"
inkscape:snap-to-guides="false"
inkscape:snap-grids="true"
showguides="true"
inkscape:guide-bbox="true"
fit-margin-top="1"
fit-margin-left="5"
fit-margin-right="2"
fit-margin-bottom="1">
<inkscape:grid
type="xygrid"
id="grid3006"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
originx="16.060028"
originy="9.0600291" />
</sodipodi:namedview>
<defs
id="defs4" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="path3872"
d="M 7.0600278,3.0600278 V 37.060029 H 61.060044 l -1.6e-5,-34.0000012 z"
style="opacity:0.69599998;fill:#dfbd8a;fill-opacity:1;stroke:#b3b3b3;stroke-width:4.12005568;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:export-xdpi="82.105263"
inkscape:export-ydpi="82.105263" />
<path
sodipodi:nodetypes="ccc"
inkscape:connector-curvature="0"
id="path3783"
d="M 38.139293,33.060029 38.031313,9.0915631 13.060028,8.9397666"
style="fill:none;fill-opacity:1;stroke:#4d934d;stroke-width:2.26843739;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:type="arc"
style="fill:none;stroke:#008000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path2986"
sodipodi:cx="20.060026"
sodipodi:cy="27.060026"
sodipodi:rx="18"
sodipodi:ry="18"
d="M 20.060583,9.0600262 A 18,18 0 0 1 38.060023,27.049044"
sodipodi:start="4.7124199"
sodipodi:end="6.2825752"
sodipodi:open="true" />
<rect
style="fill:#2ac23c;fill-opacity:1;fill-rule:evenodd;stroke:#666666;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect3776"
width="5"
height="5.0000005"
x="17.560028"
y="6.5600266"
ry="2.5"
rx="2.5" />
<rect
rx="2.5"
ry="2.5"
y="6.5600266"
x="35.560028"
height="5.0000005"
width="5"
id="rect3761"
style="fill:#2ac23c;fill-opacity:1;fill-rule:evenodd;stroke:#666666;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="fill:#2ac23c;fill-opacity:1;fill-rule:evenodd;stroke:#666666;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect3763"
width="5"
height="5.0000005"
x="35.560028"
y="24.560026"
ry="2.5"
rx="2.5" />
<g
id="g835"
transform="rotate(-90,32.060026,0.60752525)">
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path5185"
d="M 22.607525,15.607526 H 6.6075245"
style="fill:#333333;stroke:#333333;stroke-width:0.89442718px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path5191"
d="m 16.607525,17.607526 6,-2 -6,-2"
style="fill:#333333;stroke:#333333;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
sodipodi:nodetypes="ccc" />
<path
inkscape:connector-curvature="0"
id="path5195"
d="m 12.607525,13.607526 -6.0000005,2 6.0000005,2"
style="fill:#333333;stroke:#333333;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
sodipodi:nodetypes="ccc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path3088"
d="m 5.6075245,12.107526 v 7"
style="fill:#333333;stroke:#333333;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path3088-3"
d="m 23.607525,12.107526 v 7"
style="fill:#333333;stroke:#333333;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
</g>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:29.68499756px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#333333;fill-opacity:1;stroke:#333333;stroke-width:0.74212497"
x="50.686302"
y="20.711531"
id="text872"><tspan
sodipodi:role="line"
id="tspan870"
x="50.686302"
y="20.711531"
style="font-size:9.8949995px;fill:#333333;stroke:#333333;stroke-width:0.74212497">d</tspan></text>
<g
id="g918"
transform="rotate(-45,5.0662856,2.9738479)">
<path
inkscape:connector-curvature="0"
id="path5191-1"
d="m 9.6075245,32.607525 5.9999995,-2 -5.9999995,-2"
style="fill:#333333;stroke:#333333;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
sodipodi:nodetypes="ccc" />
</g>
<path
style="fill:#333333;stroke:#333333;stroke-width:0.89442718px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 30.060028,17.060027 -11.31371,11.31371"
id="path5185-4"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.5511179px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#333333;fill-opacity:1;stroke:#333333;stroke-width:0.65944487"
x="18.22471"
y="23.864855"
id="text942"><tspan
sodipodi:role="line"
id="tspan940"
x="18.22471"
y="23.864855"
style="fill:#333333;stroke:#333333;stroke-width:0.65944487">r</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@@ -0,0 +1,813 @@
#!/usr/bin/env python
# Copyright 2019 Maurice https://github.com/easyw/
# some source tips @
# https://github.com/bpkempke/kicad-scripts
# https://github.com/MitjaNemec/Kicad_action_plugins
# https://github.com/jsreynaud/kicad-action-scripts
# GNU GENERAL PUBLIC LICENSE
# Version 3, 29 June 2007
#
# Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
# Everyone is permitted to copy and distribute verbatim copies
# of this license document, but changing it is not allowed.
#
# 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.
#
# 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.
# import round_trk; reload(round_trk)
## todo:
# 1) insert check drc for rounding & fencing
# 2) add radius as text to rounded curve
# 3) add selected track lenght
import sys
import os
from pcbnew import *
import wx
import pcbnew
import math
import cmath
#from .RoundTrackDlg import RoundTrackDlg
from . import RoundTrackDlg
ToUnits=pcbnew.ToMM #ToMils
FromUnits=pcbnew.FromMM #Mils
debug = False #True
debug2 = False
show_points = False
show_points2 = False
global delete_before_connect
delete_before_connect = False
# N_SEGMENTS = 32 #4#32
# distI = FromMM(10)
# import pcbnew; print (pcbnew.PLUGIN_DIRECTORIES_SEARCH)
# Python plugin stuff
class RoundTrack_Dlg(RoundTrackDlg.RoundTrackDlg):
# from https://github.com/MitjaNemec/Kicad_action_plugins
# hack for new wxFormBuilder generating code incompatible with old wxPython
# noinspection PyMethodOverriding
def SetSizeHints(self, sz1, sz2):
if wx.__version__ < '4.0':
self.SetSizeHintsSz(sz1, sz2)
else:
super(RoundTrack_Dlg, self).SetSizeHints(sz1, sz2)
def onDeleteClick(self, event):
return self.EndModal(wx.ID_DELETE)
def onConnectClick(self, event):
return self.EndModal(wx.ID_REVERT)
def __init__(self, parent):
global delete_before_connect
import wx
RoundTrackDlg.RoundTrackDlg.__init__(self, parent)
#self.GetSizer().Fit(self)
self.SetMinSize(self.GetSize())
self.m_buttonDelete.Bind(wx.EVT_BUTTON, self.onDeleteClick)
self.m_buttonReconnect.Bind(wx.EVT_BUTTON, self.onConnectClick)
if wx.__version__ < '4.0':
self.m_buttonReconnect.SetToolTipString( u"Select two converging Tracks to re-connect them\nor Select tracks including one round corner to be straighten" )
self.m_buttonRound.SetToolTipString( u"Select two connected Tracks to round the corner\nThen choose distance from intersection and the number of segments" )
else:
self.m_buttonReconnect.SetToolTip( u"Select two converging Tracks to re-connect them\nor Select tracks including one round corner to be straighten" )
self.m_buttonRound.SetToolTip( u"Select two connected Tracks to round the corner\nThen choose distance from intersection and the number of segments" )
if self.m_checkBoxDelete.IsChecked():
delete_before_connect = True
#
class Tracks_Rounder(pcbnew.ActionPlugin):
def defaults(self):
self.name = "Rounder for Tracks\n version 2.5"
self.category = "Modify PCB"
self.description = "Rounder for selected Traces on the PCB"
self.icon_file_name = os.path.join(os.path.dirname(__file__), "./round_track.png")
self.show_toolbar_button = True
def Warn(self, message, caption='Warning!'):
dlg = wx.MessageDialog(
None, message, caption, wx.OK | wx.ICON_WARNING)
dlg.ShowModal()
dlg.Destroy()
def CheckDistanceInput(self, value, data):
val = None
try:
val = float(value.replace(',','.'))
if val <= 0:
raise Exception("Invalid")
except:
self.Warn(
"Invalid parameter for %s: Must be a positive number" % data)
val = None
return val
def CheckSegmentsInput(self, value, data):
val = None
try:
val = int(value)
if (val < 2) or (val >32):
raise Exception("Invalid")
except:
self.Warn(
"Invalid parameter for %s: Must be bigger than 2" % data)
val = None
return val
def Run(self):
global delete_before_connect
#self.pcb = GetBoard()
# net_name = "GND"
pcb = pcbnew.GetBoard()
#from https://github.com/MitjaNemec/Kicad_action_plugins
#hack wxFormBuilder py2/py3
# _pcbnew_frame = [x for x in wx.GetTopLevelWindows() if x.GetTitle().lower().startswith('pcbnew')][0]
_pcbnew_frame = [x for x in wx.GetTopLevelWindows() if x.GetName() == 'PcbFrame'][0]
#aParameters = RoundTrackDlg(None)
aParameters = RoundTrack_Dlg(_pcbnew_frame)
if hasattr (pcb, 'm_Uuid'):
aParameters.m_buttonDelete.Disable()
aParameters.m_checkBoxDelete.Disable()
#aParameters = RoundTrack_DlgEx(_pcbnew_frame)
aParameters.Show()
#end hack
aParameters.m_distanceMM.SetValue("5")
aParameters.m_segments.SetValue("16")
aParameters.m_bitmap1.SetBitmap(wx.Bitmap( os.path.join(os.path.dirname(os.path.realpath(__file__)), "round_track_help.png") ) )
modal_result = aParameters.ShowModal()
segments = self.CheckSegmentsInput(
aParameters.m_segments.GetValue(), "number of segments")
distI = FromMM(self.CheckDistanceInput(aParameters.m_distanceMM.GetValue(), "distance from intersection"))
if aParameters.m_checkBoxDelete.IsChecked():
delete_before_connect = True
else:
delete_before_connect = False
if segments is not None and distI is not None:
if modal_result == wx.ID_OK:
Round_Selection(pcb, distI, segments)
pcbnew.Refresh()
elif modal_result == wx.ID_DELETE:
Delete_Segments(pcb)
#wx.LogMessage('Round Segments on Track Net Deleted')
elif modal_result == wx.ID_REVERT:
wxLogDebug('Connecting Tracks',debug)
Connect_Segments(pcb)
else:
None # Cancel
#pcbnew.Refresh()
else:
None # Invalid input
aParameters.Destroy()
#Round_Selection(pcb)
#
def wxLogDebug(msg,show):
"""printing messages only if show is omitted or True"""
if show:
wx.LogMessage(msg)
#
def distance (p1,p2):
return math.hypot(p1.y-p2.y,p1.x-p2.x)
#
#gets the angle of a track
def getTrackAngle(t1,center):
#use atan2 so the correct quadrant is returned
if t1.GetStart().x == center.x and t1.GetStart().y == center.y:
wxLogDebug("Start = Center",debug)
return math.atan2((t1.GetEnd().y - t1.GetStart().y), (t1.GetEnd().x - t1.GetStart().x))
else:
wxLogDebug("End = Center",debug)
return math.atan2((t1.GetStart().y - t1.GetEnd().y), (t1.GetStart().x - t1.GetEnd().x));
#
#track length
def GetTrackLength(t1):
return t1.GetLength()
#
def create_Track(pcb,p1,p2,lyr=None,w=None,Nn=None,Ts=None):
#draw segment to test
#new_line = pcbnew.DRAWSEGMENT(pcb)
if hasattr(pcbnew,'TRACK'):
new_line = pcbnew.TRACK(pcb)
else:
new_shape = PCB_SHAPE()
new_line = PCB_TRACK(new_shape)
new_line.SetStart(p1)
new_line.SetEnd(p2)
if w is None:
new_line.SetWidth(FromUnits(1.5)) #FromUnits(int(mask_width)))
else:
new_line.SetWidth(FromUnits(w))
if lyr is None:
lyr = F_SilkS
if Nn is not None:
new_line.SetNet(Nn)
#new_line.SetNetname(Nn)
new_line.SetLayer(lyr) #pcbnew.F_SilkS) #pcb.GetLayerID(mask_layer))
if Ts is not None:
tsc = 0
Nname = new_line.GetNetname()
for c in Nname:
tsc = tsc + ord(c)
if hasattr(new_line, 'SetTimeStamp'):
new_line.SetTimeStamp(tsc) # adding a unique number (this netname) as timestamp to mark this segment as generated by this script on this netname
pcb.Add(new_line)
return new_line
#
def create_Arc(pcb,p1,p2,mp,lyr=None,w=None,Nn=None,Ts=None):
#import pcbnew
#from pcbnew import *
#b = pcbnew.GetBoard()
#new_shape = PCB_SHAPE()
#new_arc = PCB_ARC(new_shape)
#p1= wxPoint(203200000, 127000000)
#md= wxPoint(221160512, 134439488)
#p2= wxPoint(228600000, 152400000)
#new_arc.SetStart(p1)
#new_arc.SetMid(md)
#new_arc.SetEnd(p2)
#new_arc.SetWidth(250000)
#new_arc.SetLayer(pcbnew.B_Cu)
#b.Add(new_arc)
#pcbnew.Refresh()
#draw segment to test
#new_line = pcbnew.DRAWSEGMENT(pcb)
if hasattr(pcbnew,'TRACK'):
new_arc = pcbnew.TRACK(pcb)
else:
#new_shape = PCB_SHAPE()
#new_arc = PCB_ARC(new_shape)
new_trk = PCB_TRACK(pcb)
new_arc = PCB_ARC(new_trk)
new_arc.SetStart(p1)
new_arc.SetEnd(p2)
new_arc.SetMid(mp)
if w is None:
new_arc.SetWidth(FromUnits(1.5)) #FromUnits(int(mask_width)))
else:
new_arc.SetWidth(FromUnits(w))
if lyr is None:
lyr = F_SilkS
if Nn is not None:
new_arc.SetNet(Nn)
#new_arc.SetNetname(Nn)
new_arc.SetLayer(lyr) #pcbnew.F_SilkS) #pcb.GetLayerID(mask_layer))
if Ts is not None:
tsc = 0
Nname = new_arc.GetNetname()
for c in Nname:
tsc = tsc + ord(c)
if hasattr(new_arc, 'SetTimeStamp'):
new_arc.SetTimeStamp(tsc) # adding a unique number (this netname) as timestamp to mark this segment as generated by this script on this netname
pcb.Add(new_arc)
return new_arc
#
def create_Draw(pcb,p1,p2,lyr=None,w=None):
#draw segment to test
if hasattr(pcbnew,'DRAWSEGMENT'):
new_line = pcbnew.DRAWSEGMENT(pcb)
else:
new_line = PCB_SHAPE()
#new_line = pcbnew.TRACK(pcb)
new_line.SetStart(p1)
new_line.SetEnd(p2)
if w is None:
new_line.SetWidth(FromUnits(1.5)) #FromUnits(int(mask_width)))
else:
new_line.SetWidth(FromUnits(w))
if lyr is None:
lyr = F_SilkS
new_line.SetLayer(lyr) #pcbnew.F_SilkS) #pcb.GetLayerID(mask_layer))
pcb.Add(new_line)
return new_line
#
def create_Text(pcb, txt, p, w, lyr):
if hasattr(pcbnew,'TEXTE_PCB'):
mytxt = pcbnew.TEXTE_PCB(pcb)
else:
mytxt = pcbnew.PCB_TEXT(EDA_TEXT) #Cast_to_PCB_TEXT(EDA_TEXT)
mytxt.SetText(txt)
mytxt.SetLayer(lyr)
mytxt.SetPosition(p)
mytxt.SetHorizJustify(pcbnew.GR_TEXT_HJUSTIFY_CENTER)
mytxt.SetTextSize(pcbnew.wxSize(w,w))
if hasattr(mytext, 'SetThickness'):
mytxt.SetThickness(int(w/4))
else:
mytxt.SetTextThickness(int(w/4))
pcb.Add(mytxt)
#
def getAngleRadians(p1,p2):
#return math.degrees(math.atan2((p1.y-p2.y),(p1.x-p2.x)))
return (math.atan2((p1.y-p2.y),(p1.x-p2.x)))
#
def rotatePoint(r,sa,da,c):
# sa, da in radians
x = c.x - math.cos(sa+da) * r
y = c.y - math.sin(sa+da) * r
return wxPoint(x,y)
def create_round_segments(pcb,sp,a1,ep,a2,cntr,rad,layer,width,Nn,N_SEGMENTS):
start_point = sp
end_point = ep
pos = sp
next_pos = ep
a1 = getAngleRadians(cntr,sp)
a2 = getAngleRadians(cntr,ep)
wxLogDebug('a1:'+str(math.degrees(a1))+' a2:'+str(math.degrees(a2))+' a2-a1:'+str(math.degrees(a2-a1)),debug)
if (a2-a1) > 0 and abs(a2-a1) > math.radians(180):
deltaA = -(math.radians(360)-(a2-a1))/N_SEGMENTS
wxLogDebug('deltaA reviewed:'+str(math.degrees(deltaA)),debug)
elif (a2-a1) < 0 and abs(a2-a1) > math.radians(180):
deltaA = (math.radians(360)-abs(a2-a1))/N_SEGMENTS
wxLogDebug('deltaA reviewed2:'+str(math.degrees(deltaA)),debug)
else:
deltaA = (a2-a1)/N_SEGMENTS
delta=deltaA
wxLogDebug('delta:'+str(math.degrees(deltaA))+' radius:'+str(ToMM(rad)),debug)
points = []
#import round_trk; import importlib; importlib.reload(round_trk)
for ii in range (N_SEGMENTS+1): #+1):
points.append(pos)
#t = create_Track(pos,pos)
prv_pos = pos
#pos = pos + fraction_delta
#posPolar = cmath.polar(pos)
#(rad) * cmath.exp(math.radians(deltaA)*1j) #cmath.rect(r, phi) : Return the complex number x with polar coordinates r and phi.
#pos = wxPoint(posPolar.real+sp.x,posPolar.imag+sp.y)
pos = rotatePoint(rad,a1,delta,cntr)
delta=delta+deltaA
wxLogDebug("pos:"+str(ToUnits(prv_pos.x))+":"+str(ToUnits(prv_pos.y))+";"+str(ToUnits(pos.x))+":"+str(ToUnits(pos.y)),debug)
if hasattr(pcbnew,'TRACK'):
for i, p in enumerate(points):
#if i < len (points)-1:
if i < len (points)-2:
t = create_Track(pcb,p,points[i+1],layer,width,Nn,True) #adding ts code to segments
t = create_Track(pcb,points[-2],ep,layer,width,Nn,True) #avoiding rounding on last segment
else:
# for i, p in enumerate(points):
# #if i < len (points)-1:
# if i < len (points)-2:
# t = create_Arc(pcb,p,points[i+1],layer,width,Nn,True) #adding ts code to segments
#t = create_Track(pcb,points[-2],ep,layer,width,Nn,True) #avoiding rounding on last segment
p1 = points[0]
p2 = points[-1]
mp = mid_point(points[0],points[-1],(a2-a1))
# #t = create_Arc(pcb,points[0],points[-1],mp,layer,width,Nn,True)
#p1= wxPoint(203200000, 127000000)
#mp= wxPoint(221160512, 134439488)
#p2= wxPoint(228600000, 152400000)
#mp = mid_point(p1,p2,math.pi/2)
#wx.LogMessage(str(mp))
t = create_Arc(pcb,p1,p2,mp,layer,width,Nn,True)
#t = create_Arc(pcb,points[-2],ep,layer,width,Nn,True)
return points[-1]
#
def mid_point(p1,p2,angle): #wxpoints,angle in radians
"""mid_point(prev_vertex,vertex,angle)-> mid_vertex
returns mid point on arc of angle between prev_vertex and vertex"""
#angle=math.radians(angle/2)
angle=(angle/2)
basic_angle=math.atan2(p2.y-p1.y,p2.x-p1.x)-math.pi/2
shift=(1-math.cos(angle))*math.hypot(p2.y-p1.y,p2.x-p1.x)/2/math.sin(angle)
midpoint=wxPoint((p2.x+p1.x)/2+shift*math.cos(basic_angle),(p2.y+p1.y)/2+shift*math.sin(basic_angle))
return midpoint
###
def create_round_points(pcb,sp,a1,ep,a2,cntr,rad,N_SEGMENTS):
#TODO: Put some error checking in here...
#Re-order the two converging tracks if we're selecting the startpoint
start_point = sp
end_point = ep
pos = sp
next_pos = ep
wxLogDebug('sp:'+str(ToMM(sp))+';ep:'+str(ToMM(ep))+';cntr:'+str(ToMM(cntr)),debug)
a1 = getAngleRadians(cntr,sp)
a2 = getAngleRadians(cntr,ep)
wxLogDebug('sp:'+str(ToMM(sp))+';ep:'+str(ToMM(ep))+';cntr:'+str(ToMM(cntr)),debug)
wxLogDebug('a1:'+str(math.degrees(a1))+' a2:'+str(math.degrees(a2))+' a2-a1:'+str(math.degrees(a2-a1)),debug)
#if a1 < 0:
# a1 = math.radians(180) -a1
#if a2 < 0:
# a2 = math.radians(180) -a2
if (a2-a1) > 0 and abs(a2-a1) > math.radians(180):
deltaA = -(math.radians(360)-(a2-a1))/N_SEGMENTS
wxLogDebug('deltaA reviewed:'+str(math.degrees(deltaA)),debug)
elif (a2-a1) < 0 and abs(a2-a1) > math.radians(180):
deltaA = (math.radians(360)-abs(a2-a1))/N_SEGMENTS
wxLogDebug('deltaA reviewed2:'+str(math.degrees(deltaA)),debug)
else:
deltaA = (a2-a1)/N_SEGMENTS
delta=deltaA
wxLogDebug('delta:'+str(math.degrees(deltaA))+' radius:'+str(ToMM(rad)),debug)
points = []
#import round_trk; import importlib; importlib.reload(round_trk)
for ii in range (N_SEGMENTS+1):
points.append(pos)
#t = create_Track(pos,pos)
prv_pos = pos
#pos = pos + fraction_delta
#posPolar = cmath.polar(pos)
#(rad) * cmath.exp(math.radians(deltaA)*1j) #cmath.rect(r, phi) : Return the complex number x with polar coordinates r and phi.
#pos = wxPoint(posPolar.real+sp.x,posPolar.imag+sp.y)
pos = rotatePoint(rad,a1,delta,cntr)
delta=delta+deltaA
wxLogDebug("pos:"+str(ToUnits(prv_pos.x))+":"+str(ToUnits(prv_pos.y))+";"+str(ToUnits(pos.x))+":"+str(ToUnits(pos.y)),debug)
for i, p in enumerate(points):
if i < len (points):
t = create_Draw(pcb,p,p,B_CrtYd,0.5+i*0.05)
#
def not_eq(a,b):
if abs(a-b) >= 1: #1nm
return True
else:
return False
#
def getCircleCenterRadius(sp,ep,ip):
#center
# NB add always set float even if values are pcb internal Units!!!
x1 = float(sp.x); y1 = float(sp.y)
x2 = float(ep.x); y2 = float(ep.y)
xi = float(ip.x); yi = float(ip.y)
# mg formula
cxN = (y2-y1)*(yi-y1)*(yi-y2)-(xi-x1)*x1*(yi-y2)+(xi-x2)*x2*(yi-y1)
cxD = -x2*yi-xi*y1+x2*y1+xi*y2+x1*yi-x1*y2
if cxD != 0:
Cx = cxN/cxD
else:
#stop
Cx= FromMM(100)
wxLogDebug(str(ToMM(y1))+':'+str(ToMM(yi))+':'+str(ToMM(y2)),debug)
wxLogDebug(str(ToMM(x1))+':'+str(ToMM(xi))+':'+str(ToMM(x2)),debug)
if not_eq(yi,y1):
Cy = y1 - (xi-x1)/(yi-y1)*(Cx-x1)
elif yi==y1 and (yi!=y2):
Cx = x1
Cy = y2 - (xi-x2)/(yi-y2)*(Cx-x2)
elif yi==y2 and (yi!=y1):
Cx = x2
Cy = y1 - (xi-x1)/(yi-y1)*(Cx-x1)
else:
Cy = FromMM(100)
# import round_trk; reload(round_trk)
# import round_trk; import importlib; importlib.reload(round_trk)
radius = math.hypot(Cx-sp.x,Cy-sp.y)
return wxPoint(Cx,Cy), radius
#
def deleteSelectedTracks(pcb):
tracks = pcb.GetTracks()
tracks_cp = list(tracks)
l = len (tracks_cp)
if hasattr(pcbnew,'TRACK'):
track_item = pcbnew.TRACK
else:
track_item = pcbnew.PCB_TRACK
for i in range(l):
if type(tracks_cp[i]) is track_item and tracks_cp[i].IsSelected(): #item.GetNetname() == net_name:
pcb.RemoveNative(tracks_cp[i])
#for item in pcb.GetTracks():
# if type(item) is TRACK and item.IsSelected(): #item.GetNetname() == net_name:
# pcb.RemoveNative(item)
# #pcb.Delete(item)
#
def deleteListTracks(pcb,tracks):
tracksToDel_cp = list(tracks)
l = len (tracksToDel_cp)
if hasattr(pcbnew,'TRACK'):
track_item = pcbnew.TRACK
else:
track_item = pcbnew.PCB_TRACK
for i in range(l):
if type(tracksToDel_cp[i]) is track_item: #item.GetNetname() == net_name:
pcb.RemoveNative(tracksToDel_cp[i])
#for item in tracks:
# if type(item) is TRACK: #item.GetNetname() == net_name:
# pcb.RemoveNative(item)
# #pcb.Delete(item)
#
def selectListTracks(pcb,tracks):
if hasattr(pcbnew,'TRACK'):
track_item = pcbnew.TRACK
else:
track_item = pcbnew.PCB_TRACK
for item in tracks:
if type(item) is track_item:
item.SetSelected()
#
def getSelTracksLength(pcb):
ln = 0.
if hasattr(pcbnew,'TRACK'):
track_item = pcbnew.TRACK
else:
track_item = pcbnew.PCB_TRACK
for item in pcb.GetTracks():
if type(item) is track_item and item.IsSelected():
ln+=(item.GetLength())
return(ln)
#print(pcbnew.ToMM(ln))
#
## def HitTest(self, *args): for Tracks and Vias
##-----------------------------------------------------------------------------------------------------
def Round_Selection(pcb,distI,segments):
global delete_before_connect
tracks = []
#print ("TRACKS WHICH MATCH CRITERIA:")
if hasattr(pcbnew,'TRACK'):
track_item = pcbnew.TRACK
else:
track_item = pcbnew.PCB_TRACK
for item in pcb.GetTracks():
if type(item) is track_item and item.IsSelected(): #item.GetNetname() == net_name:
tracks.append(item)
wxLogDebug(str(len(tracks)),debug)
if len (tracks) == 2:
#add all the possible intersections to a unique set, for iterating over later
intersections = set();
for t1 in range(len(tracks)):
for t2 in range(t1+1, len(tracks)):
#check if these two tracks share an endpoint
# reduce it to a 2-part tuple so there are not multiple objects of the same point in the set
if(tracks[t1].IsPointOnEnds(tracks[t2].GetStart())):
intersections.add((tracks[t2].GetStart().x, tracks[t2].GetStart().y))
if(tracks[t1].IsPointOnEnds(tracks[t2].GetEnd())):
intersections.add((tracks[t2].GetEnd().x, tracks[t2].GetEnd().y))
if len(intersections)==1:
for ip in intersections:
(x,y) = ip
wxLogDebug("intersections: "+str(ToUnits(x))+":"+str(ToUnits(y)),debug)
#wx.LogMessage(str(tracks[0].GetStart()))
intersection = wxPoint(x,y)
if tracks[0].GetStart() == pcbnew.wxPoint(x,y):
first_trk_extNode = tracks[0].GetEnd()
#wx.LogMessage("tracks[0] external node="+str(ToUnits(tracks[0].GetEnd().x))+";"+str(ToUnits(tracks[0].GetEnd().y)))
else:
first_trk_extNode = tracks[0].GetStart()
#wx.LogMessage("tracks[0] external node="+str(ToUnits(tracks[0].GetStart().x))+";"+str(ToUnits(tracks[0].GetStart().y)))
if tracks[1].GetStart() == pcbnew.wxPoint(x,y):
last_trk_extNode = tracks[1].GetEnd()
#wx.LogMessage("tracks[1] external node="+str(ToUnits(tracks[1].GetEnd().x))+";"+str(ToUnits(tracks[1].GetEnd().y)))
else:
last_trk_extNode = tracks[1].GetStart()
#wx.LogMessage("tracks[1] external node="+str(ToUnits(tracks[1].GetStart().x))+";"+str(ToUnits(tracks[1].GetStart().y)))
angle1 = math.degrees((getTrackAngle(tracks[0],intersection)))
angle2 = math.degrees((getTrackAngle(tracks[1],intersection)))
end_coord1 = (distI) * cmath.exp(math.radians(angle1)*1j) #cmath.rect(r, phi) : Return the complex number x with polar coordinates r and phi.
end_coord2 = (distI) * cmath.exp(math.radians(angle2)*1j)
startP = wxPoint(end_coord1.real+x,end_coord1.imag+y)
endP = wxPoint(end_coord2.real+x,end_coord2.imag+y)
layer = tracks[0].GetLayer()
width = ToMM(tracks[0].GetWidth())
Nname = tracks[0].GetNet() #.GetNetname()
wxLogDebug("offset1 = "+str(ToUnits(startP)),debug) #+":"+str(ToUnits(endP)),debug)
wxLogDebug("offset2 = "+str(ToUnits(endP)),debug) #end_coord2.real+x))+":"+str(ToUnits(end_coord2.imag+y)))
center,radius = getCircleCenterRadius( startP,endP,intersection )
#rad = math.hypot(center.x-startP.x,center.y-startP.y)
wxLogDebug('radius'+str(ToMM(radius)),debug)
wxLogDebug('center'+str(ToMM(center)),debug)
# import round_trk; import importlib; importlib.reload(round_trk)
lenT1 = GetTrackLength(tracks[0])
dist1 = math.hypot(startP.y-intersection.y,startP.x-intersection.x)
lenT2 = GetTrackLength(tracks[1])
dist2 = math.hypot(endP.y-intersection.y,endP.x-intersection.x)
wxLogDebug('Len T1 {0:.3f} mm, dist1 {1:.3f} mm, LenT2 {2:.3f} mm, dist2 {3:.3f} mm'.format(ToMM(lenT1),ToMM(dist1),ToMM(lenT2),ToMM(dist2)),debug)
if show_points:
create_Draw(pcb,startP,startP,F_Mask,0.2)
create_Draw(pcb,intersection,intersection,Eco1_User,1.5)
create_Draw(pcb,endP,endP,B_Mask,0.2)
create_Draw(pcb,center,center,F_SilkS,2.)
create_round_points(pcb,startP,angle1,endP,angle2,center,radius,segments)
pcbnew.Refresh()
selectListTracks(pcb,tracks)
if (lenT1 < dist1) or (lenT2 < dist2):
wxLogDebug('Segments too short compared to selected distance {0:.3f} mm'.format(ToMM(distI)),True)
else:
#create_Track(pcb,first_trk_extNode,startP,layer,width,Nname) #B_Cu,0.2)
#if delete_before_connect:
deleteListTracks(pcb,tracks)
create_Track(pcb,startP,first_trk_extNode,layer,width,Nname) #B_Cu,0.2)
#create_Draw(pcb,startP,startP,F_Mask,1.5)
newEP = create_round_segments(pcb,startP,angle1,endP,angle2,center,radius,layer,width,Nname,segments) #B_Cu,0.2)
#wxLogDebug(str(newEP)+':'+str(endP),True)
#create_Draw(pcb,endP,endP,B_Mask,1.9)
create_Track(pcb,endP,last_trk_extNode,layer,width,Nname) # B_Cu,0.2)
#create_Track(pcb,last_trk_extNode,endP,layer,width,Nname) # B_Cu,0.2)
#deleteSelectedTracks(pcb)
#selectListTracks(pcb,tracks)
w3 = 3*float(width)
rad = float(ToMM(radius))
wxLogDebug(str(w3),debug)
msg = u'Corner Radius: {0:.3f} mm'.format(rad)
msg+= u'\nAngle between tracks: {0:.1f} deg'.format(angle1-angle2)
if rad < w3:
msg += u'\n\u2718 ALERT: Radius < 3 *(track width) !!!\n[{0:.3f}mm < 3*{1:.3f}mm]'.format(rad,width)
#else:
# #msg = u'\n\u2714 Radius > 3 * (track width)'
# msg = u'\u2714 Corner Radius: {0:.3f} mm'.format(rad)
wxLogDebug(msg,True)
pcbnew.Refresh()
# import round_trk; reload(round_trk)
# import round_trk; import importlib; importlib.reload(round_trk)
else:
wxLogDebug("you must select two tracks (only)",not debug)
#
def Delete_Segments(pcb, track=None):
global delete_before_connect
tracks = []
tracksToKeep = []
if track is None:
if hasattr(pcbnew,'TRACK'):
track_item = pcbnew.TRACK
else:
track_item = pcbnew.PCB_TRACK
for item in pcb.GetTracks():
if type(item) is track_item and item.IsSelected():
tracks.append(item)
wxLogDebug('tracks selected: '+str(len(tracks)),debug2)
else:
tracks.append(track)
if len (tracks) == 1 and delete_before_connect:
Netname = tracks[0].GetNetname()
tsc = 0
for c in Netname:
tsc = tsc + ord(c)
nseg = 0
tracksToDel = []
for track in pcb.GetTracks():
if hasattr(track,'GetTimeStamp'):
tsd = track.GetTimeStamp()
else:
tsd = track.m_Uuid.AsLegacyTimestamp()
wxLogDebug('tracks ts: '+str(tsc)+';'+str(tsd),debug2)
if tsd == tsc and tsd != 0:
tracksToDel.append(track)
#pcb.RemoveNative(track)
nseg+=1
if nseg > 0:
tracksToDel_cp = list(tracksToDel)
l = len (tracksToDel_cp)
#for track in tracksToDel:
for i in range(l):
pcb.RemoveNative(tracksToDel_cp[i])
wxLogDebug(u'\u2714 Round Segments on Track Net Deleted',True)
else:
Netname = tracks[0].GetNetname()
tsc = 0
for c in Netname:
tsc = tsc + ord(c)
nseg = 0
tracksToDel = []
if hasattr(pcbnew,'TRACK'):
track_item = pcbnew.TRACK
else:
track_item = pcbnew.PCB_TRACK
for track in pcb.GetTracks():
if type(track) is track_item and track.IsSelected():
if hasattr(track,'GetTimeStamp'):
tsd = track.GetTimeStamp()
else:
tsd = track.m_Uuid.AsLegacyTimestamp()
wxLogDebug('tracks ts: '+str(tsc)+';'+str(tsd),debug2)
if tsd == tsc and tsd != 0:
tracksToDel.append(track)
#pcb.RemoveNative(track)
nseg+=1
else:
tracksToKeep.append(track)
if nseg > 0:
tracksToDel_cp = list(tracksToDel)
l = len (tracksToDel_cp)
for i in range(l):
pcb.RemoveNative(tracksToDel_cp[i])
#for track in tracksToDel:
# pcb.RemoveNative(track)
wxLogDebug(u'\u2714 Round Segments on Selected Track deleted',True)
elif delete_before_connect:
wxLogDebug(u'\u2718 you must select One track only',not debug)
return tracksToKeep
#
def Connect_Segments(pcb):
tracks = []
tracksToKeep = []
if hasattr(pcbnew,'TRACK'):
track_item = pcbnew.TRACK
else:
track_item = pcbnew.PCB_TRACK
for item in pcb.GetTracks():
if type(item) is track_item and item.IsSelected():
tracks.append(item)
wxLogDebug(str(len(tracks)),debug)
if len (tracks) >= 2:
pi_exists = True
if len (tracks) > 2:
tracksToKeep = Delete_Segments(pcb)
if len (tracksToKeep) == 2:
tracks[0] = tracksToKeep[0]
tracks[1] = tracksToKeep[1]
else:
wxLogDebug(u'\u2718 wrong selection (error)\nselect Only one corner to be straighten',not debug)
else:
Delete_Segments(pcb,tracks[0])
#getting points
if tracks[0].GetStart().x < tracks[0].GetEnd().x:
first_trk_startP = tracks[0].GetStart()
first_trk_endP = tracks[0].GetEnd()
else:
first_trk_startP = tracks[0].GetEnd()
first_trk_endP = tracks[0].GetStart()
if tracks[1].GetStart().x < tracks[1].GetEnd().x:
last_trk_startP = tracks[1].GetStart()
last_trk_endP = tracks[1].GetEnd()
else:
last_trk_startP = tracks[1].GetEnd()
last_trk_endP = tracks[1].GetStart()
wxLogDebug('sp1:'+str(first_trk_startP)+';'+str(first_trk_endP),debug2)
wxLogDebug('sp2:'+str(last_trk_startP)+';'+str(last_trk_endP),debug2)
x1 = float(first_trk_startP.x); y1 = float(first_trk_startP.y)
x3 = float(first_trk_endP.x); y3 = float(first_trk_endP.y)
x2 = float(last_trk_startP.x); y2 = float(last_trk_startP.y)
x4 = float(last_trk_endP.x); y4 = float(last_trk_endP.y)
if (x3!=x1) and (x4!=x2):
N = y2-y1-x2*(y4-y2)/(x4-x2)+x1*(y3-y1)/(x3-x1)
D = (y3-y1)/(x3-x1)-(y4-y2)/(x4-x2)
xi = N/D
yi = y1+(y3-y1)/(x3-x1)*(xi-x1)
elif (x3==x1):
xi = x1
yi = y2+(y4-y2)/(x4-x2)*(x1-x2)
elif (x4 == x2):
xi = x2
yi = y1 + (y3-y1)/(x3-x1)*(x2-x1)
else:
pi_exists = False
wxLogDebug(u'\u2718 intersection point doesn\'t exist',not debug)
if pi_exists:
wxLogDebug('pi:'+str(wxPoint(xi,yi)),debug2) #xi)+';'+str(yi),debug1)
wxLogDebug('sp1:('+str(ToMM(x1))+','+str(ToMM(y1))+')'+\
';('+str(ToMM(x2))+','+str(ToMM(y2))+')',debug2)
wxLogDebug('sp2:('+str(ToMM(x3))+','+str(ToMM(y3))+')'+\
';('+str(ToMM(x4))+','+str(ToMM(y4))+')',debug2)
wxLogDebug('pi:('+str(ToMM(xi))+','+str(ToMM(yi))+')',debug2)
pi = wxPoint(xi,yi)
if show_points2:
#create_Text(pcb, txt, p, w)
create_Text(pcb,'1',wxPoint(x1,y1),FromMM(1.0),pcbnew.F_SilkS)
create_Text(pcb,'2',wxPoint(x2,y2),FromMM(1.0),pcbnew.F_SilkS)
create_Text(pcb,'3',wxPoint(x3,y3),FromMM(1.0),pcbnew.F_SilkS)
create_Text(pcb,'4',wxPoint(x4,y4),FromMM(1.0),pcbnew.F_SilkS)
create_Text(pcb,'C',wxPoint(xi,yi),FromMM(2.0),pcbnew.B_SilkS)
wxLogDebug('dp1,pi)'+str(distance(wxPoint(x1,y1),pi)),debug2)
wxLogDebug('dp3,pi)'+str(distance(wxPoint(x3,y3),pi)),debug2)
if distance(wxPoint(x1,y1),pi) > distance(wxPoint(x3,y3),pi):
tracks[0].SetStart(wxPoint(x1,y1))
tracks[0].SetEnd(pi)
else:
tracks[0].SetStart(wxPoint(x3,y3))
tracks[0].SetEnd(pi)
wxLogDebug('dp2,pi)'+str(distance(wxPoint(x2,y2),pi)),debug2)
wxLogDebug('dp4,pi)'+str(distance(wxPoint(x4,y4),pi)),debug2)
if distance(wxPoint(x2,y2),pi) > distance(wxPoint(x4,y4),pi):
tracks[1].SetStart(wxPoint(x2,y2))
tracks[1].SetEnd(pi)
else:
tracks[1].SetStart(wxPoint(x4,y4))
tracks[1].SetEnd(pi)
pcbnew.Refresh()
else:
wxLogDebug(u'\u2718 you must select two tracks only',not debug)
#