add bt_player
This commit is contained in:
141
kicad_plugins/round_tracks/RoundTrackDlg.py
Normal file
141
kicad_plugins/round_tracks/RoundTrackDlg.py
Normal 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
|
||||
|
||||
|
||||
1175
kicad_plugins/round_tracks/Track_Rounder.fbp
Normal file
1175
kicad_plugins/round_tracks/Track_Rounder.fbp
Normal file
File diff suppressed because it is too large
Load Diff
2
kicad_plugins/round_tracks/__init__.py
Normal file
2
kicad_plugins/round_tracks/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from .round_trk import Tracks_Rounder
|
||||
Tracks_Rounder().register()
|
||||
BIN
kicad_plugins/round_tracks/round_track.png
Normal file
BIN
kicad_plugins/round_tracks/round_track.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
108
kicad_plugins/round_tracks/round_track.svg
Normal file
108
kicad_plugins/round_tracks/round_track.svg
Normal 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 |
BIN
kicad_plugins/round_tracks/round_track_help.png
Normal file
BIN
kicad_plugins/round_tracks/round_track_help.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.7 KiB |
196
kicad_plugins/round_tracks/round_track_help.svg
Normal file
196
kicad_plugins/round_tracks/round_track_help.svg
Normal 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 |
813
kicad_plugins/round_tracks/round_trk.py
Executable file
813
kicad_plugins/round_tracks/round_trk.py
Executable 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)
|
||||
#
|
||||
Reference in New Issue
Block a user