add bt_player
This commit is contained in:
235
kicad_plugins/trace_clearance/trace_clearance.py
Executable file
235
kicad_plugins/trace_clearance/trace_clearance.py
Executable file
@@ -0,0 +1,235 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright 2019 Maurice https://github.com/easyw/
|
||||
# Copyright 2020 Matt Huszagh https://github.com/matthuszagh
|
||||
|
||||
# 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 os
|
||||
import pcbnew
|
||||
import wx
|
||||
# import numpy as np
|
||||
from . import TraceClearanceDlg
|
||||
import math
|
||||
|
||||
class TraceClearance_Dlg(TraceClearanceDlg.TraceClearanceDlg):
|
||||
"""
|
||||
"""
|
||||
|
||||
def SetSizeHints(self, sz1, sz2):
|
||||
if wx.__version__ < '4.0':
|
||||
self.SetSizeHintsSz(sz1, sz2)
|
||||
else:
|
||||
super(TraceClearance_Dlg, self).SetSizeHints(sz1, sz2)
|
||||
|
||||
def __init__(self, parent):
|
||||
"""
|
||||
"""
|
||||
TraceClearanceDlg.TraceClearanceDlg.__init__(self, parent)
|
||||
self.SetMinSize(self.GetSize())
|
||||
|
||||
|
||||
class TraceClearance(pcbnew.ActionPlugin):
|
||||
"""
|
||||
"""
|
||||
|
||||
def defaults(self):
|
||||
"""
|
||||
"""
|
||||
self.name = "Trace Clearance Generator\n version 1.4"
|
||||
self.category = ""
|
||||
self.description = (
|
||||
"Generate a copper pour keepout for a selected trace."
|
||||
)
|
||||
self.show_toolbar_button = True
|
||||
self.icon_file_name = os.path.join(
|
||||
os.path.dirname(__file__), "./trace_clearance.png"
|
||||
)
|
||||
|
||||
def Run(self):
|
||||
"""
|
||||
"""
|
||||
_pcbnew_frame = [x for x in wx.GetTopLevelWindows() if x.GetName() == 'PcbFrame'][0]
|
||||
# _pcbnew_frame = [
|
||||
# x
|
||||
# for x in wx.GetTopLevelWindows()
|
||||
# if x.GetTitle().lower().startswith("pcbnew")
|
||||
# ][0]
|
||||
wx_params = TraceClearance_Dlg(_pcbnew_frame)
|
||||
wx_params.m_clearance.SetValue("0.2")
|
||||
wx_params.m_bitmap.SetBitmap(
|
||||
wx.Bitmap(
|
||||
os.path.join(
|
||||
os.path.dirname(os.path.realpath(__file__)),
|
||||
"trace_clearance_dialog.png",
|
||||
)
|
||||
)
|
||||
)
|
||||
modal_res = wx_params.ShowModal()
|
||||
clearance = pcbnew.FromMM(
|
||||
self.InputValid(wx_params.m_clearance.GetValue())
|
||||
)
|
||||
if clearance is not None:
|
||||
pcb = pcbnew.GetBoard()
|
||||
if modal_res == wx.ID_OK:
|
||||
tracks = selected_tracks(pcb)
|
||||
if len(tracks) > 0:
|
||||
set_keepouts(pcb, tracks, clearance)
|
||||
else:
|
||||
self.Warn("At least one track must be selected.")
|
||||
elif modal_res == wx.ID_CANCEL:
|
||||
wx_params.Destroy()
|
||||
|
||||
def Warn(self, message, caption="Warning!"):
|
||||
"""
|
||||
"""
|
||||
dlg = wx.MessageDialog(None, message, caption, wx.OK | wx.ICON_WARNING)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
def InputValid(self, value):
|
||||
"""
|
||||
"""
|
||||
try:
|
||||
float_val = float(value)
|
||||
except:
|
||||
self.Warn("Clearance must be a floating point number.")
|
||||
|
||||
if float_val <= 0:
|
||||
self.Warn("Clearance must be positive.")
|
||||
|
||||
return float_val
|
||||
|
||||
|
||||
def selected_tracks(pcb):
|
||||
"""
|
||||
TODO should we use a common import with solder expander to avoid
|
||||
redundant functionality?
|
||||
"""
|
||||
tracks = []
|
||||
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)
|
||||
return tracks
|
||||
|
||||
|
||||
def set_keepouts(pcb, tracks, clearance):
|
||||
"""
|
||||
"""
|
||||
for track in tracks:
|
||||
track_start = track.GetStart()
|
||||
track_end = track.GetEnd()
|
||||
if track_start.x == track_end.x and track_start.y == track_end.y:
|
||||
continue
|
||||
track_width = track.GetWidth()
|
||||
layer = track.GetLayerSet()
|
||||
|
||||
if hasattr(pcbnew,'ZONE_CONTAINER'):
|
||||
keepout = pcbnew.ZONE_CONTAINER(pcb)
|
||||
pts = poly_points(track_start, track_end, track_width, clearance)
|
||||
keepout.AddPolygon(pts)
|
||||
keepout.SetIsKeepout(True)
|
||||
keepout.SetDoNotAllowCopperPour(True)
|
||||
keepout.SetDoNotAllowVias(False)
|
||||
keepout.SetDoNotAllowTracks(False)
|
||||
keepout.SetLayerSet(layer)
|
||||
else:
|
||||
keepout = pcbnew.ZONE(pcb)
|
||||
pts = poly_points(track_start, track_end, track_width, clearance)
|
||||
# wx.LogMessage(str(pts))
|
||||
keepout.AddPolygon(pts)
|
||||
#keepout.SetIsKeepout(True)
|
||||
keepout.SetIsRuleArea(True) # was SetIsKeepout
|
||||
keepout.SetDoNotAllowCopperPour(True)
|
||||
keepout.SetDoNotAllowVias(False)
|
||||
keepout.SetDoNotAllowTracks(False)
|
||||
keepout.SetLayerSet(layer)
|
||||
pcb.Add(keepout)
|
||||
|
||||
pcbnew.Refresh()
|
||||
|
||||
|
||||
def poly_points(track_start, track_end, track_width, clearance):
|
||||
"""
|
||||
"""
|
||||
delta = track_width / 2 + clearance
|
||||
dx = track_end.x - track_start.x
|
||||
dy = track_end.y - track_start.y
|
||||
# theta = np.arctan2(dy, dx)
|
||||
theta = math.atan2(dy, dx)
|
||||
# len = np.sqrt(np.power(dx, 2) + np.power(dy, 2))
|
||||
len = math.sqrt(math.pow(dx, 2) + math.pow(dy, 2))
|
||||
dx_norm = dx / len
|
||||
dy_norm = dy / len
|
||||
|
||||
delta_x = delta * -dy_norm
|
||||
delta_y = delta * dx_norm
|
||||
pt_delta = pcbnew.wxPoint(delta_x, delta_y)
|
||||
|
||||
pts = []
|
||||
pts.append(track_start + pt_delta)
|
||||
for pt in semicircle_points(track_start, delta, theta, True):
|
||||
pts.append(pt)
|
||||
pts.append(track_start - pt_delta)
|
||||
pts.append(track_end - pt_delta)
|
||||
for pt in semicircle_points(track_end, delta, theta, False):
|
||||
pts.append(pt)
|
||||
pts.append(track_end + pt_delta)
|
||||
return pcbnew.wxPoint_Vector(pts)
|
||||
|
||||
|
||||
def semicircle_points(circle_center, radius, angle_norm, is_start=True):
|
||||
"""
|
||||
"""
|
||||
num_points = 20
|
||||
|
||||
# angles = np.linspace(
|
||||
# angle_norm + np.pi / 2, angle_norm + 3 * np.pi / 2, num_points + 2
|
||||
# )
|
||||
start = angle_norm + math.pi / 2
|
||||
stop = angle_norm + 3 * math.pi / 2
|
||||
num_vals = num_points
|
||||
delta = (stop-start)/(num_vals-1)
|
||||
evenly_spaced = [start + i * delta for i in range(num_vals)]
|
||||
# print(evenly_spaced)
|
||||
angles = evenly_spaced
|
||||
# wx.LogMessage(str(angles))
|
||||
angles = angles[1:-1]
|
||||
# wx.LogMessage(str(angles)+'1')
|
||||
if not is_start:
|
||||
# angles = np.add(angles, np.pi)
|
||||
angles.append(math.pi)
|
||||
pts = []
|
||||
for ang in angles:
|
||||
# pts.append(
|
||||
# circle_center
|
||||
# + pcbnew.wxPoint(radius * np.cos(ang), radius * np.sin(ang))
|
||||
# )
|
||||
pts.append(
|
||||
circle_center
|
||||
+ pcbnew.wxPoint(radius * math.cos(ang), radius * math.sin(ang))
|
||||
)
|
||||
return pcbnew.wxPoint_Vector(pts)
|
||||
Reference in New Issue
Block a user