Squashed commit of the following:
commit7fda555fc0Author: Marius Stanciu <marius.adrian@gmail.com> Date: Wed May 24 17:46:25 2023 +0300 - for all Editors now there is a shortcut key (key "C") that will toggle the cursor data in case the cursor data is in the way - Geometry Editor: the Path tool now has a new behavior: when key modifier SHIFT is pressed and the Grid is OFF, when the line is drawn and it is near the 0, 45 and 90 degrees, in each quadrant, then the drawn line will follow the nearest target angle (0 or 45 or 90 degrees) allowing the drawing of straight lines. commite5dd294576Author: Marius Stanciu <marius.adrian@gmail.com> Date: Fri May 19 18:18:38 2023 +0300 - Film Tool: fixed the export to PNG to be done at correct DPI commita49f54d63fAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Fri May 19 13:09:08 2023 +0300 - the selection shapes are now moved from Move Plugin to AppMain - Fiducials Plugin: fixed errors due of changes in the Shapely module - Fiducials Plugin: fixed an error where in Basic mode the soldermask opening is added incorrectly commitba3152e5f9Author: Marius Stanciu <marius.adrian@gmail.com> Date: Fri May 19 02:23:40 2023 +0300 - CutOut Plugin - fixed the manual adding of gaps commit761b61668aAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Wed May 17 22:48:39 2023 +0300 - Thieving Plugin: fixed errors due of changes in the Shapely module commitdea367b185Author: Marius Stanciu <marius.adrian@gmail.com> Date: Tue May 16 04:34:32 2023 +0300 - NCC Plugin: fixed the Standard method of copper clearing (both normal and with Rest machining) commit6719e2ef8eAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Sun May 14 22:14:43 2023 +0300 - NCC Plugin - minor code refactoring commit5d274dd522Author: Marius Stanciu <marius.adrian@gmail.com> Date: Sun May 14 21:48:14 2023 +0300 - Isolation Plugin, NCC Plugin and Find Optimal Plugin: fixed not finding the optimal tool diameter (the one that will isolate completely a Gerber object) commit1d68dea61cAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Fri May 5 22:31:18 2023 +0300 - replaced some type hints with using the Union commit412872bc09Author: Marius Stanciu <marius.adrian@gmail.com> Date: Fri May 5 02:40:41 2023 +0300 - fixed an erroneous opening for a Gerber file generated by KiCAD 6.0.11, due of a rectangular flash being eliminated by the global unary_union operation commit765d7cc05bAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Sat Apr 15 22:15:33 2023 +0300 - when parsing a new Gerber object, I am "preparing" each geometry added therefore making the Gerber object geometry possible faster to process commit6a29bcbe7cAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Sat Apr 15 21:29:32 2023 +0300 - some code leftovers are commented commitb557df8fdcAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Sat Apr 15 21:08:48 2023 +0300 - minor fixes commitccc71eabc2Author: Marius Stanciu <marius.adrian@gmail.com> Date: Sat Apr 15 21:03:30 2023 +0300 - changed the shapely imports a bit according to the specifications of Shapely 2.0 - changed the requirements.txt file to reflect the need for at least Shapely in version 2.0 commit6f93734d3fAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Sat Apr 8 12:43:34 2023 +0300 - minor name changes commitfaf41d7bcaAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Sat Apr 8 12:29:45 2023 +0300 - major change: from now on the only dimensional units available are those from ISO METRIC system commitb446ded9abAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Sat Apr 8 12:10:02 2023 +0300 - fixed some really long strings in the Geometry Editor toolbar actions - modified the paint and buffer icons - optimized the editor menu/toolbar action names commit72dd81848fAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Wed Mar 22 16:43:27 2023 +0200 - in the toolbars now there is text under the icons (which can be turned off from the toolbar context menu) - the GUI state is now saved and restored through QSettings commit1dff9cc566Author: Marius Stanciu <marius.adrian@gmail.com> Date: Mon Mar 13 23:08:57 2023 +0200 - in Tcl Commands: export_dxf and export_gerber, fixed a mistake in declaring a wrong name of a required option - in Tcl Command set_path added an optional parameter which allows to create a directory where path is to be set, if the directory does not exist commit3b3c87e953Author: Marius Stanciu <marius.adrian@gmail.com> Date: Mon Mar 6 16:40:49 2023 +0200 - fixed some possible issues due of changes in version 2.0 of Shapely - removed the import * statement from most of the app commit33de5314b1Author: Marius Stanciu <marius.adrian@gmail.com> Date: Wed Mar 1 18:15:10 2023 +0200 - in Tool Milling made sure that deleting the only tool will not crash the application - added a new parameter in Preferences to control the number of processes created by the Pool() - more processes better performance but also a lot of memory consumed - made sure that the display of messages in the Status Bar is done asap commit9d8852e611Author: Marius Stanciu <marius.adrian@gmail.com> Date: Fri Jan 20 19:23:34 2023 +0200 - added a new method for bilinear interpolation commit9ce9c3cb54Author: Marius Stanciu <marius.adrian@gmail.com> Date: Wed Jan 18 18:22:33 2023 +0200 - in Autolevelling Plugin, preventing the add of a probe point on Excellon hole checkbox is not disabled except for the Manual mode - in Autolevelling Plugin, the status of soem checkoxes (avoid Excellon holes and plot points) is stored between app restarts - in Isolation Plugin, added an convenience shortcut button to launch the Milling Plugin. commitc85d04bc0aAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Wed Jan 18 01:32:28 2023 +0200 - in Autolevelling Tool, when adding manual probe points, added an option that prevent adding a probe point within a drill hole of an Excellon object that is plotted on canvas commitf42f05d93eAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Wed Jan 18 01:07:31 2023 +0200 - in Autolevelling Tool made sure that when adding manual probe points mouse dragging with the right button is not counted as end of adding operation commit220157641dAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Tue Jan 17 01:02:52 2023 +0200 - fixed the Voronoi generation in the Autolevelling Tool (removed the Foronoi package due of issues and now using the embedded functionality from Shapely) - fixed the enable of Levelling Tool only for CNCJob objects that were made from geometries that were segmented commit853b273e79Author: Marius Stanciu <marius.adrian@gmail.com> Date: Mon Jan 16 23:52:30 2023 +0200 - fixed the Voronoi generation in the Autolevelling Tool (removed the Foronoi package due of issues and now using the embedded functionality from Shapely) commita1b6f78d78Author: Marius Stanciu <marius.adrian@gmail.com> Date: Mon Jan 16 13:28:50 2023 +0200 - some PEP8 fixes commit6c5a468418Author: Marius Stanciu <marius.adrian@gmail.com> Date: Mon Jan 16 13:02:47 2023 +0200 - fixed a decoding error in the Excellon parser commitd6ebcef38dAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Sun Jan 15 22:31:11 2023 +0200 - PEP8 changes commit2d0ea65f1bAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Sun Jan 15 15:25:20 2023 +0200 - minor change commitc1377d5090Author: Marius Stanciu <marius.adrian@gmail.com> Date: Sat Nov 19 02:29:40 2022 +0200 - added a 'return' button when a fatal error is encountered allowing the user to continue the work - fixed a crash in Milling Plugin when trying to mill slots that do not have drills in the same file commit22f4d92be7Author: Marius Stanciu <marius.adrian@gmail.com> Date: Wed Nov 9 20:56:39 2022 +0200 - minor change in the requirements.txt file commit8b4423dc0fAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Wed Nov 9 19:55:59 2022 +0200 - when changing the style for the decorations from Preferences, now change is applied immediately commit9ec2ee2920Author: Marius Stanciu <marius.adrian@gmail.com> Date: Tue Nov 8 15:59:59 2022 +0200 - in Drilling Plugin fixed a situation when having tools with the same diameter will get them multiplied by the number of those tools commitd1a4de676eAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Sun Nov 6 00:43:34 2022 +0200 - if PikePDF module is not available then show an error but run the app (currently, for Python 3.11 is the only module not available) commit6509089dc4Author: Marius Stanciu <marius.adrian@gmail.com> Date: Wed Oct 19 16:59:05 2022 +0300 - fixed an issue when exporting huge SVG files from the Film Tool by adding a fallback and using a custom XML parser with the 'huge_tree' option set commit2c229d8677Author: Marius Stanciu <marius.adrian@gmail.com> Date: Wed Oct 19 02:35:19 2022 +0300 - added a hack so the Gerber files from Allegro 17.2 (which do not follow the Gerber specifications) can be loaded commit94901686b5Author: Marius Stanciu <marius.adrian@gmail.com> Date: Sun Oct 2 06:56:13 2022 +0300 - really small UI change in 2-Sided Plugin commit56033b8bc4Author: Marius Stanciu <marius.adrian@gmail.com> Date: Tue Sep 27 16:45:32 2022 +0300 - in Milling Plugin, for Excellon target, re-enabled the control over the Feedrate X-Y parameter commit8f774df30bAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Sun Sep 25 05:57:35 2022 +0300 - small fix in ToolCutout Plugin when trying to set a checkbox state with a float value which still works in Windows but creates issues in other OS's commit9b08191660Author: Marius Stanciu <marius.adrian@gmail.com> Date: Sun Sep 25 05:44:43 2022 +0300 - added a new setting in Preferences ("3D compatibility") controlled by a checkbox. If the checkbox is checked then multithreading is disabled for the 3D mode (lower performance but perhaps more compatibility, especially for Linux) - this was done from the research done by Matti Eiden on bitbucket commit565c839460Author: Marius Stanciu <marius.adrian@gmail.com> Date: Sat Sep 10 01:50:13 2022 +0300 - added insurance that the QThread where the ArgThread class is running, really receive the interruption request and it is finished commit71a3963c96Author: Marius Stanciu <marius.adrian@gmail.com> Date: Sat Sep 10 01:06:13 2022 +0300 - hided the main UI on application quit to create a user experience of a shutdown without lag - added a way to terminate QThreads safely by waiting; should be much safer - made sure that the ArgsThread class receive the signal to stop - made sure that on application shutdown, all workers will quit before the actual exit commit3c1349a6c4Author: Marius Stanciu <marius.adrian@gmail.com> Date: Thu Sep 1 13:08:06 2022 +0300 - added a new feature for Geometry export-as-SVG, the ability to export only the paths (outlines); the new feature is controlled from a new parameter in Preferences -> Geometry -> Export commit6eeac5312eMerge:419330ee2901afd9Author: Marius Stanciu <marius.adrian@gmail.com> Date: Mon Aug 1 09:29:44 2022 +0000 Merged Beta_8.995 into gerber_editor_upgrade commit419330ee93Author: Marius Stanciu <marius.adrian@gmail.com> Date: Mon Aug 1 12:27:14 2022 +0300 - fixed some bugs in Geometry Editor in regards of Buffer Tool - fixed some issues in the Cutout Plugin by adding more checks - fixed issues when loading files by dragging in the UI (caused by recent code refactoring) commit4c22e52b08Author: Marius Stanciu <marius.adrian@gmail.com> Date: Thu May 26 00:20:43 2022 +0300 - upgraded the UI of Region sub-tool in the Gerber Editor commit95066e352bAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Sun May 22 14:01:21 2022 +0300 - in Gerber Editor upgraded the Simplification sub-tool GUI commit5298a59372Author: Marius Stanciu <marius.adrian@gmail.com> Date: Sun May 22 04:37:16 2022 +0300 - in Gerber Editor upgraded the Track sub-tool GUI commit830d500d04Author: Marius Stanciu <marius.adrian@gmail.com> Date: Sun May 22 03:18:51 2022 +0300 - in Gerber Editor upgraded the PadArray GUI commit9055cc1230Author: Marius Stanciu <marius.adrian@gmail.com> Date: Sun May 22 01:40:55 2022 +0300 - in Gerber Editor upgraded the PadAdd GUI commitbfb3aa4118Author: Marius Stanciu <marius.adrian@gmail.com> Date: Sat May 21 02:13:47 2022 +0300 - added properties for the mouse position and mouse clicked position (and setters) and cleaned up the code regarding this data commit61325b7b5fAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Sat May 21 01:25:14 2022 +0300 - more code refactored in the appMain.py commit77c752701fAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Fri May 20 21:19:52 2022 +0300 - refactored the code for the file registration and for the keywords update into its own class to make the main class smaller - when creating new files the file names are added to the beginning of the keywords list for the usage of Qt auto-completer commit5125f475ebMerge:c3ab0b28037a72a5Author: Marius Stanciu <marius.adrian@gmail.com> Date: Fri May 20 01:51:59 2022 +0000 Merged Beta_8.995 into gerber_editor_upgrade commitc3ab0b28b3Merge:93c2ab43c0ff26dbAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Thu May 19 13:25:47 2022 +0000 Merged Beta_8.995 into gerber_editor_upgrade commit93c2ab43f4Merge:8bdaaa50f82d4a4bAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Wed May 18 21:00:48 2022 +0000 Merged Beta_8.995 into gerber_editor_upgrade commit8bdaaa5021Merge:1a0dfe6104bb0857Author: Marius Stanciu <marius.adrian@gmail.com> Date: Tue May 17 19:55:12 2022 +0000 Merged Beta_8.995 into gerber_editor_upgrade commit1a0dfe6143Merge:9a057a40b09c55daAuthor: Marius Stanciu <marius.adrian@gmail.com> Date: Tue May 17 11:39:28 2022 +0000 Merged Beta_8.995 into gerber_editor_upgrade commit9a057a40c5Merge:c1a532033a0247e7Author: Marius Stanciu <marius.adrian@gmail.com> Date: Tue May 17 09:54:28 2022 +0000 Merged Beta_8.995 into gerber_editor_upgrade commitc1a5320315Author: Marius Stanciu <marius.adrian@gmail.com> Date: Mon May 16 18:13:12 2022 +0300 - started to lay ground for upgrading the UI in the Gerber Editor - fixed and upgraded the Buffer sub-tool in the Gerber Editor - fixed adding same aperture multiple times
This commit is contained in:
@@ -1,95 +0,0 @@
|
||||
|
||||
import matplotlib
|
||||
matplotlib.use('Agg')
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import io
|
||||
from matplotlib.backends.backend_agg import FigureCanvasAgg
|
||||
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg
|
||||
from matplotlib.figure import Figure
|
||||
import cProfile
|
||||
import sys
|
||||
|
||||
|
||||
def gen_data():
|
||||
N = 100000
|
||||
x = np.random.rand(N) * 10
|
||||
y = np.random.rand(N) * 10
|
||||
colors = np.random.rand(N)
|
||||
area = np.pi * (15 * np.random.rand(N))**2 # 0 to 15 point radiuses
|
||||
data = x, y, area, colors
|
||||
return data
|
||||
|
||||
|
||||
# @profile
|
||||
def large_plot(data):
|
||||
x, y, area, colors = data
|
||||
|
||||
fig = Figure(figsize=(10, 10), dpi=80)
|
||||
axes = fig.add_axes([0.0, 0.0, 1.0, 1.0], alpha=1.0)
|
||||
axes.set_frame_on(False)
|
||||
axes.set_xticks([])
|
||||
axes.set_yticks([])
|
||||
# axes.set_xlim(0, 10)
|
||||
# axes.set_ylim(0, 10)
|
||||
|
||||
axes.scatter(x, y, s=area, c=colors, alpha=0.5)
|
||||
|
||||
axes.set_xlim(0, 10)
|
||||
axes.set_ylim(0, 10)
|
||||
|
||||
canvas = FigureCanvasAgg(fig)
|
||||
canvas.draw()
|
||||
# canvas = FigureCanvasQTAgg(fig)
|
||||
# buf = canvas.tostring_rgb()
|
||||
buf = fig.canvas.tostring_rgb()
|
||||
|
||||
ncols, nrows = fig.canvas.get_width_height()
|
||||
img = np.fromstring(buf, dtype=np.uint8).reshape(nrows, ncols, 3)
|
||||
|
||||
return img
|
||||
|
||||
|
||||
def small_plot(data):
|
||||
x, y, area, colors = data
|
||||
|
||||
fig = Figure(figsize=(3, 3), dpi=80)
|
||||
axes = fig.add_axes([0.0, 0.0, 1.0, 1.0], alpha=1.0)
|
||||
axes.set_frame_on(False)
|
||||
axes.set_xticks([])
|
||||
axes.set_yticks([])
|
||||
# axes.set_xlim(5, 6)
|
||||
# axes.set_ylim(5, 6)
|
||||
|
||||
axes.scatter(x, y, s=area, c=colors, alpha=0.5)
|
||||
|
||||
axes.set_xlim(4, 7)
|
||||
axes.set_ylim(4, 7)
|
||||
|
||||
canvas = FigureCanvasAgg(fig)
|
||||
canvas.draw()
|
||||
# canvas = FigureCanvasQTAgg(fig)
|
||||
# buf = canvas.tostring_rgb()
|
||||
buf = fig.canvas.tostring_rgb()
|
||||
|
||||
ncols, nrows = fig.canvas.get_width_height()
|
||||
img = np.fromstring(buf, dtype=np.uint8).reshape(nrows, ncols, 3)
|
||||
|
||||
return img
|
||||
|
||||
def doit():
|
||||
d = gen_data()
|
||||
img = large_plot(d)
|
||||
return img
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
d = gen_data()
|
||||
|
||||
if sys.argv[1] == 'large':
|
||||
cProfile.runctx('large_plot(d)', None, locals())
|
||||
else:
|
||||
cProfile.runctx('small_plot(d)', None, locals())
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "*** LARGE ***"
|
||||
python performance.py large | egrep "(\(scatter\))|(\(draw\))|(tostring_rgb)|(fromstring)"
|
||||
echo "*** SMALL ***"
|
||||
python performance.py small | egrep "(\(scatter\))|(\(draw\))|(tostring_rgb)|(fromstring)"
|
||||
@@ -1,125 +0,0 @@
|
||||
M48
|
||||
INCH
|
||||
T01C0.0200
|
||||
T02C0.0800
|
||||
T03C0.0600
|
||||
T04C0.0300
|
||||
T05C0.0650
|
||||
T06C0.0450
|
||||
T07C0.0400
|
||||
T08C0.1181
|
||||
T09C0.0500
|
||||
%
|
||||
T01
|
||||
X-018204Y+015551
|
||||
X-025842Y+015551
|
||||
T02
|
||||
X-000118Y+020629
|
||||
X-000118Y+016889
|
||||
X+012401Y+020629
|
||||
X+012401Y+016889
|
||||
X-010170Y+002440
|
||||
X-010110Y+011470
|
||||
X+018503Y+026574
|
||||
T03
|
||||
X+013060Y+010438
|
||||
X+013110Y+000000
|
||||
X-049015Y+002165
|
||||
X+018378Y+010433
|
||||
X+018317Y+000000
|
||||
X-049015Y+010039
|
||||
X-041141Y-000629
|
||||
X-041181Y+012992
|
||||
X-056496Y+012992
|
||||
X-056496Y-000590
|
||||
T04
|
||||
X-037560Y+030490
|
||||
X-036560Y+030490
|
||||
X-035560Y+030490
|
||||
X-034560Y+030490
|
||||
X-033560Y+030490
|
||||
X-032560Y+030490
|
||||
X-031560Y+030490
|
||||
X-030560Y+030490
|
||||
X-029560Y+030490
|
||||
X-028560Y+030490
|
||||
X-027560Y+030490
|
||||
X-026560Y+030490
|
||||
X-025560Y+030490
|
||||
X-024560Y+030490
|
||||
X-024560Y+036490
|
||||
X-025560Y+036490
|
||||
X-026560Y+036490
|
||||
X-027560Y+036490
|
||||
X-028560Y+036490
|
||||
X-029560Y+036490
|
||||
X-030560Y+036490
|
||||
X-031560Y+036490
|
||||
X-032560Y+036490
|
||||
X-033560Y+036490
|
||||
X-034560Y+036490
|
||||
X-035560Y+036490
|
||||
X-036560Y+036490
|
||||
X-037560Y+036490
|
||||
X-014590Y+030810
|
||||
X-013590Y+030810
|
||||
X-012590Y+030810
|
||||
X-011590Y+030810
|
||||
X-011590Y+033810
|
||||
X-012590Y+033810
|
||||
X-013590Y+033810
|
||||
X-014590Y+033810
|
||||
X-021260Y+034680
|
||||
X-020010Y+034680
|
||||
X-008390Y+035840
|
||||
X-008390Y+034590
|
||||
X-008440Y+031870
|
||||
X-008440Y+030620
|
||||
T05
|
||||
X-022504Y+019291
|
||||
X-020354Y+019291
|
||||
X-018204Y+019291
|
||||
X-030142Y+019291
|
||||
X-027992Y+019291
|
||||
X-025842Y+019291
|
||||
X-012779Y+019291
|
||||
X-010629Y+019291
|
||||
X-008479Y+019291
|
||||
T06
|
||||
X-028080Y+028230
|
||||
X-030080Y+028230
|
||||
X-034616Y+024409
|
||||
X-039616Y+024409
|
||||
X-045364Y+023346
|
||||
X-045364Y+018346
|
||||
X-045364Y+030157
|
||||
X-045364Y+025157
|
||||
X-008604Y+026983
|
||||
X-013604Y+026983
|
||||
X-016844Y+034107
|
||||
X-016844Y+029107
|
||||
T07
|
||||
X-041655Y+026456
|
||||
X-040655Y+026456
|
||||
X-039655Y+026456
|
||||
X-041640Y+022047
|
||||
X-040640Y+022047
|
||||
X-039640Y+022047
|
||||
X-049760Y+029430
|
||||
X-048760Y+029430
|
||||
X-047760Y+029430
|
||||
X-019220Y+037380
|
||||
X-020220Y+037380
|
||||
X-021220Y+037380
|
||||
T08
|
||||
X-024212Y+007751
|
||||
X-024212Y+004011
|
||||
X-035629Y+007874
|
||||
X-035629Y+004133
|
||||
T09
|
||||
X+007086Y+030708
|
||||
X+007086Y+032874
|
||||
X-000787Y+031889
|
||||
X-000787Y+035826
|
||||
X-000787Y+027952
|
||||
M30
|
||||
@@ -1,148 +0,0 @@
|
||||
import sys
|
||||
from PyQt5 import QtGui, QtWidgets
|
||||
from PyQt5 import QtCore
|
||||
from PyQt5.QtCore import Qt
|
||||
|
||||
|
||||
class TitleBar(QtWidgets.QDialog):
|
||||
def __init__(self, parent=None):
|
||||
QtWidgets.QWidget.__init__(self, parent)
|
||||
self.setWindowFlags(Qt.FramelessWindowHint)
|
||||
css = """
|
||||
QWidget{
|
||||
Background: #AA00AA;
|
||||
color:white;
|
||||
font:12px bold;
|
||||
font-weight:bold;
|
||||
border-radius: 1px;
|
||||
height: 11px;
|
||||
}
|
||||
QDialog{
|
||||
Background-image:url('img/titlebar bg.png');
|
||||
font-size:12px;
|
||||
color: black;
|
||||
|
||||
}
|
||||
QToolButton{
|
||||
Background:#AA00AA;
|
||||
font-size:11px;
|
||||
}
|
||||
QToolButton:hover{
|
||||
Background: #FF00FF;
|
||||
font-size:11px;
|
||||
}
|
||||
"""
|
||||
self.setAutoFillBackground(True)
|
||||
self.setBackgroundRole(QtGui.QPalette.Highlight)
|
||||
self.setStyleSheet(css)
|
||||
self.minimize=QtWidgets.QToolButton(self)
|
||||
self.minimize.setIcon(QtGui.QIcon('img/min.png'))
|
||||
self.maximize=QtWidgets.QToolButton(self);
|
||||
self.maximize.setIcon(QtGui.QIcon('img/max.png'))
|
||||
close=QtWidgets.QToolButton(self)
|
||||
close.setIcon(QtGui.QIcon('img/close.png'))
|
||||
self.minimize.setMinimumHeight(10)
|
||||
close.setMinimumHeight(10)
|
||||
self.maximize.setMinimumHeight(10)
|
||||
label=QtWidgets.QLabel(self)
|
||||
label.setText("Abracadabra")
|
||||
self.setWindowTitle("Alhambra")
|
||||
hbox=QtWidgets.QHBoxLayout(self)
|
||||
hbox.addWidget(label)
|
||||
hbox.addWidget(self.minimize)
|
||||
hbox.addWidget(self.maximize)
|
||||
hbox.addWidget(close)
|
||||
hbox.insertStretch(1,500)
|
||||
hbox.setSpacing(0)
|
||||
self.setSizePolicy(QtWidgets.QSizePolicy.Expanding,QtWidgets.QSizePolicy.Fixed)
|
||||
self.maxNormal=False
|
||||
close.clicked.connect(self.close)
|
||||
self.minimize.clicked.connect(self.showSmall)
|
||||
self.maximize.clicked.connect(self.showMaxRestore)
|
||||
|
||||
def showSmall(self):
|
||||
box.showMinimized()
|
||||
|
||||
def showMaxRestore(self):
|
||||
if(self.maxNormal):
|
||||
box.showNormal()
|
||||
self.maxNormal= False
|
||||
self.maximize.setIcon(QtGui.QIcon('img/max.png'))
|
||||
print(1)
|
||||
else:
|
||||
box.showMaximized()
|
||||
self.maxNormal= True
|
||||
print(2)
|
||||
self.maximize.setIcon(QtGui.QIcon('img/max2.png'))
|
||||
|
||||
def close(self):
|
||||
box.close()
|
||||
|
||||
def mousePressEvent(self,event):
|
||||
if event.button() == Qt.LeftButton:
|
||||
box.moving = True; box.offset = event.pos()
|
||||
|
||||
def mouseMoveEvent(self,event):
|
||||
if box.moving: box.move(event.globalPos()-box.offset)
|
||||
|
||||
|
||||
class Frame(QtWidgets.QFrame):
|
||||
def __init__(self, parent=None):
|
||||
QtWidgets.QFrame.__init__(self, parent)
|
||||
self.m_mouse_down= False
|
||||
self.setFrameShape(QtWidgets.QFrame.StyledPanel)
|
||||
css = """
|
||||
QFrame{
|
||||
Background: #D700D7;
|
||||
color:white;
|
||||
font:13px ;
|
||||
font-weight:bold;
|
||||
}
|
||||
"""
|
||||
self.setStyleSheet(css)
|
||||
self.setWindowFlags(Qt.FramelessWindowHint)
|
||||
self.setMouseTracking(True)
|
||||
self.m_titleBar= TitleBar(self)
|
||||
self.m_content= QtWidgets.QWidget(self)
|
||||
vbox=QtWidgets.QVBoxLayout(self)
|
||||
vbox.addWidget(self.m_titleBar)
|
||||
vbox.setContentsMargins(0, 0, 0, 0)
|
||||
vbox.setSpacing(0)
|
||||
layout=QtWidgets.QVBoxLayout(self)
|
||||
layout.addWidget(self.m_content)
|
||||
layout.setContentsMargins(5, 5, 5, 5)
|
||||
layout.setSpacing(0)
|
||||
vbox.addLayout(layout)
|
||||
# Allows you to access the content area of the frame
|
||||
# where widgets and layouts can be added
|
||||
|
||||
def contentWidget(self):
|
||||
return self.m_content
|
||||
|
||||
def titleBar(self):
|
||||
return self.m_titleBar
|
||||
|
||||
def mousePressEvent(self,event):
|
||||
self.m_old_pos = event.pos()
|
||||
self.m_mouse_down = event.button()== Qt.LeftButton
|
||||
|
||||
def mouseMoveEvent(self,event):
|
||||
x=event.x()
|
||||
y=event.y()
|
||||
|
||||
def mouseReleaseEvent(self,event):
|
||||
m_mouse_down=False
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
box = Frame()
|
||||
box.move(60,60)
|
||||
l = QtWidgets.QVBoxLayout(box.contentWidget())
|
||||
l.setContentsMargins(0, 0,0 ,0)
|
||||
edit = QtWidgets.QLabel("""I would've did anything for you to show you how much I adored you
|
||||
But it's over now, it's too late to save our loveJust promise me you'll think of me
|
||||
Every time you look up in the sky and see a star 'cuz I'm your star.""")
|
||||
l.addWidget(edit)
|
||||
box.show()
|
||||
app.exec_()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
||||
G04 MADE WITH FRITZING*
|
||||
G04 WWW.FRITZING.ORG*
|
||||
G04 DOUBLE SIDED*
|
||||
G04 HOLES PLATED*
|
||||
G04 CONTOUR ON CENTER OF CONTOUR VECTOR*
|
||||
%ASAXBY*%
|
||||
%FSLAX23Y23*%
|
||||
%MOIN*%
|
||||
%OFA0B0*%
|
||||
%SFA1.0B1.0*%
|
||||
%ADD10R,1.771650X1.181100*%
|
||||
%ADD11C,0.008000*%
|
||||
%ADD10C,0.008*%
|
||||
%LNCONTOUR*%
|
||||
G90*
|
||||
G70*
|
||||
G54D10*
|
||||
G54D11*
|
||||
X4Y1177D02*
|
||||
X1768Y1177D01*
|
||||
X1768Y4D01*
|
||||
X4Y4D01*
|
||||
X4Y1177D01*
|
||||
D02*
|
||||
G04 End of contour*
|
||||
M02*
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,71 +0,0 @@
|
||||
G04 MADE WITH FRITZING*
|
||||
G04 WWW.FRITZING.ORG*
|
||||
G04 DOUBLE SIDED*
|
||||
G04 HOLES PLATED*
|
||||
G04 CONTOUR ON CENTER OF CONTOUR VECTOR*
|
||||
%ASAXBY*%
|
||||
%FSLAX23Y23*%
|
||||
%MOIN*%
|
||||
%OFA0B0*%
|
||||
%SFA1.0B1.0*%
|
||||
%ADD10C,0.075000*%
|
||||
%ADD11C,0.099055*%
|
||||
%ADD12C,0.078740*%
|
||||
%ADD13R,0.075000X0.075000*%
|
||||
%ADD14C,0.024000*%
|
||||
%ADD15C,0.020000*%
|
||||
%LNCOPPER1*%
|
||||
G90*
|
||||
G70*
|
||||
G54D10*
|
||||
X1149Y872D03*
|
||||
X1349Y872D03*
|
||||
X749Y722D03*
|
||||
X749Y522D03*
|
||||
X1149Y522D03*
|
||||
X1449Y522D03*
|
||||
X1149Y422D03*
|
||||
X1449Y422D03*
|
||||
X1149Y322D03*
|
||||
X1449Y322D03*
|
||||
X1149Y222D03*
|
||||
X1449Y222D03*
|
||||
X949Y472D03*
|
||||
X949Y72D03*
|
||||
G54D11*
|
||||
X749Y972D03*
|
||||
X599Y972D03*
|
||||
X349Y322D03*
|
||||
X349Y472D03*
|
||||
X349Y672D03*
|
||||
X349Y822D03*
|
||||
G54D10*
|
||||
X699Y122D03*
|
||||
X699Y322D03*
|
||||
G54D12*
|
||||
X699Y222D03*
|
||||
X949Y972D03*
|
||||
X749Y622D03*
|
||||
X1049Y222D03*
|
||||
X1249Y872D03*
|
||||
G54D13*
|
||||
X1149Y872D03*
|
||||
X1149Y522D03*
|
||||
G54D14*
|
||||
X952Y946D02*
|
||||
X1045Y249D01*
|
||||
G54D15*
|
||||
X776Y695D02*
|
||||
X721Y695D01*
|
||||
X721Y750D01*
|
||||
X776Y750D01*
|
||||
X776Y695D01*
|
||||
D02*
|
||||
X671Y150D02*
|
||||
X726Y150D01*
|
||||
X726Y95D01*
|
||||
X671Y95D01*
|
||||
X671Y150D01*
|
||||
D02*
|
||||
G04 End of Copper1*
|
||||
M02*
|
||||
@@ -1,46 +0,0 @@
|
||||
; NON-PLATED HOLES START AT T1
|
||||
; THROUGH (PLATED) HOLES START AT T100
|
||||
M48
|
||||
INCH
|
||||
T1C0.125984
|
||||
T100C0.031496
|
||||
T101C0.035000
|
||||
T102C0.059055
|
||||
%
|
||||
T1
|
||||
X001488Y010223
|
||||
X001488Y001223
|
||||
X016488Y001223
|
||||
X016488Y010223
|
||||
T100
|
||||
X009488Y009723
|
||||
X007488Y006223
|
||||
X012488Y008723
|
||||
X010488Y002223
|
||||
X006988Y002223
|
||||
T101
|
||||
X014488Y004223
|
||||
X006988Y003223
|
||||
X013488Y008723
|
||||
X011488Y008723
|
||||
X007488Y005223
|
||||
X014488Y003223
|
||||
X014488Y002223
|
||||
X011488Y005223
|
||||
X009488Y000723
|
||||
X011488Y004223
|
||||
X006988Y001223
|
||||
X009488Y004723
|
||||
X007488Y007223
|
||||
X011488Y003223
|
||||
X014488Y005223
|
||||
X011488Y002223
|
||||
T102
|
||||
X003488Y008223
|
||||
X003488Y004723
|
||||
X007488Y009723
|
||||
X003488Y006723
|
||||
X005988Y009723
|
||||
X003488Y003223
|
||||
T00
|
||||
M30
|
||||
@@ -1,54 +0,0 @@
|
||||
G04 MADE WITH FRITZING*
|
||||
G04 WWW.FRITZING.ORG*
|
||||
G04 DOUBLE SIDED*
|
||||
G04 HOLES PLATED*
|
||||
G04 CONTOUR ON CENTER OF CONTOUR VECTOR*
|
||||
%ASAXBY*%
|
||||
%FSLAX23Y23*%
|
||||
%MOIN*%
|
||||
%OFA0B0*%
|
||||
%SFA1.0B1.0*%
|
||||
%ADD10R,0.047244X0.078740*%
|
||||
%ADD11C,0.024000*%
|
||||
%LNCOPPER1*%
|
||||
G90*
|
||||
G70*
|
||||
G54D10*
|
||||
X2940Y1051D03*
|
||||
X2940Y941D03*
|
||||
G54D11*
|
||||
X2438Y839D02*
|
||||
X2440Y1023D01*
|
||||
D02*
|
||||
X2940Y907D02*
|
||||
X2941Y839D01*
|
||||
D02*
|
||||
X2941Y839D02*
|
||||
X2438Y839D01*
|
||||
D02*
|
||||
X2941Y1239D02*
|
||||
X2940Y1085D01*
|
||||
D02*
|
||||
X2438Y1239D02*
|
||||
X2941Y1239D01*
|
||||
D02*
|
||||
X2440Y1126D02*
|
||||
X2438Y1239D01*
|
||||
G36*
|
||||
X2418Y1064D02*
|
||||
X2461Y1064D01*
|
||||
X2461Y1017D01*
|
||||
X2418Y1017D01*
|
||||
X2418Y1064D01*
|
||||
G37*
|
||||
D02*
|
||||
G36*
|
||||
X2418Y1131D02*
|
||||
X2461Y1131D01*
|
||||
X2461Y1084D01*
|
||||
X2418Y1084D01*
|
||||
X2418Y1131D01*
|
||||
G37*
|
||||
D02*
|
||||
G04 End of Copper1*
|
||||
M02*
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
||||
# This script is for profiling Gerber.parse_lines() line by line.
|
||||
# Run kernprof -l -v gerber_parsing_line_profile_1.py
|
||||
|
||||
import sys
|
||||
sys.path.append('../../')
|
||||
|
||||
from flatcamParsers.ParseGerber import *
|
||||
|
||||
log = logging.getLogger('base2')
|
||||
log.setLevel(logging.WARNING)
|
||||
|
||||
g = Gerber()
|
||||
g.parse_file("gerber1.gbr")
|
||||
@@ -1,17 +0,0 @@
|
||||
import cProfile
|
||||
import pstats
|
||||
import sys
|
||||
sys.path.append('../../')
|
||||
|
||||
from flatcamParsers.ParseGerber import *
|
||||
|
||||
log = logging.getLogger('base2')
|
||||
log.setLevel(logging.WARNING)
|
||||
|
||||
g = Gerber()
|
||||
|
||||
#cProfile.run('g.parse_file("gerber1.gbr")', 'gerber1_profile', sort='cumtime')
|
||||
cProfile.run('g.parse_file("/home/jpcaram/flatcam_test_files/Gerbers/AVR_Transistor_Tester_silkscreen_top.GTO")',
|
||||
'gerber1_profile', sort='cumtime')
|
||||
p = pstats.Stats('gerber1_profile')
|
||||
p.strip_dirs().sort_stats('cumulative').print_stats(.1)
|
||||
@@ -1,70 +0,0 @@
|
||||
import sys
|
||||
from PyQt5.Qt import *
|
||||
from PyQt5 import QtGui, QtWidgets
|
||||
|
||||
|
||||
class MyPopup(QWidget):
|
||||
def __init__(self):
|
||||
QWidget.__init__(self)
|
||||
lay = QtWidgets.QVBoxLayout()
|
||||
self.setLayout(lay)
|
||||
lay.setContentsMargins(0, 0, 0, 0)
|
||||
le = QtWidgets.QLineEdit()
|
||||
le.setText("Abracadabra")
|
||||
le.setReadOnly(True)
|
||||
# le.setStyleSheet("QLineEdit { qproperty-frame: false }")
|
||||
le.setFrame(False)
|
||||
le.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
|
||||
# lay.addStretch()
|
||||
but = QtWidgets.QPushButton("OK")
|
||||
hlay = QtWidgets.QHBoxLayout()
|
||||
hlay.setContentsMargins(0, 5, 5, 5)
|
||||
|
||||
hlay.addStretch()
|
||||
hlay.addWidget(but)
|
||||
|
||||
lay.addWidget(le)
|
||||
lay.addLayout(hlay)
|
||||
# def paintEvent(self, e):
|
||||
# dc = QtGui.QPainter(self)
|
||||
# dc.drawLine(0, 0, 100, 100)
|
||||
# dc.drawLine(100, 0, 0, 100)
|
||||
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
def __init__(self, *args):
|
||||
QtWidgets.QMainWindow.__init__(self, *args)
|
||||
self.cw = QtWidgets.QWidget(self)
|
||||
self.setCentralWidget(self.cw)
|
||||
self.btn1 = QtWidgets.QPushButton("Click me", self.cw)
|
||||
self.btn1.setGeometry(QRect(0, 0, 100, 30))
|
||||
self.btn1.clicked.connect(self.doit)
|
||||
self.w = None
|
||||
|
||||
def doit(self):
|
||||
print("Opening a new popup window...")
|
||||
self.w = MyPopup()
|
||||
self.w.setGeometry(QRect(100, 100, 400, 200))
|
||||
self.w.show()
|
||||
|
||||
|
||||
class App(QApplication):
|
||||
def __init__(self, *args):
|
||||
QtWidgets.QApplication.__init__(self, *args)
|
||||
self.main = MainWindow()
|
||||
# self.lastWindowClosed.connect(self.byebye)
|
||||
self.main.show()
|
||||
|
||||
def byebye(self):
|
||||
self.exit(0)
|
||||
|
||||
|
||||
def main(args):
|
||||
global app
|
||||
app = App(args)
|
||||
app.exec_()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv)
|
||||
@@ -1,34 +0,0 @@
|
||||
import sys
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class MyObj():
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def __del__(self):
|
||||
print("##### Destroyed ######")
|
||||
|
||||
|
||||
def parse():
|
||||
o = MyObj()
|
||||
raise Exception("Intentional Exception")
|
||||
|
||||
|
||||
class Example(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self):
|
||||
super(Example, self).__init__()
|
||||
|
||||
qbtn = QtWidgets.QPushButton('Raise', self)
|
||||
qbtn.clicked.connect(parse)
|
||||
|
||||
self.setWindowTitle('Quit button')
|
||||
self.show()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
ex = Example()
|
||||
sys.exit(app.exec_())
|
||||
@@ -1,8 +0,0 @@
|
||||
import os
|
||||
os.chdir('../')
|
||||
|
||||
from flatcamParsers.ParseGerber import *
|
||||
|
||||
g = Gerber()
|
||||
g.parse_file(r'C:\Users\jpcaram\Dropbox\CNC\pcbcam\test_files\PlacaReles-F_Cu.gtl')
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Sun Jan 05 13:30:47 2014
|
||||
|
||||
@author: jpcaram
|
||||
"""
|
||||
|
||||
import os
|
||||
os.chdir('../')
|
||||
|
||||
from flatcamParsers.ParseGerber import *
|
||||
from flatcamParsers.ParseExcellon import *
|
||||
|
||||
from matplotlib import pyplot
|
||||
|
||||
# Gerber. To see if the Excellon is correct
|
||||
project_dir = "tests/gerber_files"
|
||||
gerber_filename = project_dir + "KiCad_Squarer-F_Cu.gtl"
|
||||
g = Gerber()
|
||||
g.parse_file(gerber_filename)
|
||||
g.create_geometry()
|
||||
|
||||
excellon_filename = project_dir + "KiCad_Squarer.drl"
|
||||
ex = Excellon()
|
||||
ex.parse_file(excellon_filename)
|
||||
ex.create_geometry()
|
||||
|
||||
#fig = Figure()
|
||||
fig = pyplot.figure()
|
||||
ax = fig.add_subplot(111)
|
||||
ax.set_aspect(1)
|
||||
|
||||
# Plot gerber
|
||||
for geo in g.solid_geometry:
|
||||
x, y = geo.exterior.coords.xy
|
||||
pyplot.plot(x, y, 'k-')
|
||||
for ints in geo.interiors:
|
||||
x, y = ints.coords.xy
|
||||
ax.plot(x, y, 'k-')
|
||||
|
||||
# Plot excellon
|
||||
for geo in ex.solid_geometry:
|
||||
x, y = geo.exterior.coords.xy
|
||||
pyplot.plot(x, y, 'r-')
|
||||
for ints in geo.interiors:
|
||||
x, y = ints.coords.xy
|
||||
ax.plot(x, y, 'g-')
|
||||
|
||||
fig.show()
|
||||
@@ -1,37 +0,0 @@
|
||||
from camlib import *
|
||||
from shapely.geometry import LineString, LinearRing
|
||||
|
||||
s = FlatCAMRTreeStorage()
|
||||
|
||||
geoms = [
|
||||
LinearRing(((0.5699056603773586, 0.7216037735849057),
|
||||
(0.9885849056603774, 0.7216037735849057),
|
||||
(0.9885849056603774, 0.6689622641509434),
|
||||
(0.5699056603773586, 0.6689622641509434),
|
||||
(0.5699056603773586, 0.7216037735849057))),
|
||||
LineString(((0.8684952830188680, 0.6952830188679245),
|
||||
(0.8680655198743615, 0.6865349890935113),
|
||||
(0.8667803692948564, 0.6778712076279851),
|
||||
(0.8646522079829676, 0.6693751114229638),
|
||||
(0.8645044888670096, 0.6689622641509434))),
|
||||
LineString(((0.9874952830188680, 0.6952830188679245),
|
||||
(0.9864925023483531, 0.6748709493942936),
|
||||
(0.9856160316877274, 0.6689622641509434))),
|
||||
|
||||
]
|
||||
|
||||
for geo in geoms:
|
||||
s.insert(geo)
|
||||
|
||||
current_pt = (0, 0)
|
||||
pt, geo = s.nearest(current_pt)
|
||||
while geo is not None:
|
||||
print((pt, geo))
|
||||
print(("OBJECTS BEFORE:", s.objects))
|
||||
|
||||
#geo.coords = list(geo.coords[::-1])
|
||||
s.remove(geo)
|
||||
|
||||
print(("OBJECTS AFTER:", s.objects))
|
||||
current_pt = geo.coords[-1]
|
||||
pt, geo = s.nearest(current_pt)
|
||||
@@ -1,48 +0,0 @@
|
||||
from shapely.geometry import LineString, Polygon
|
||||
from shapely.ops import unary_union
|
||||
from matplotlib.pyplot import plot, subplot, show, axes
|
||||
from matplotlib.axes import *
|
||||
from camlib import *
|
||||
|
||||
|
||||
def plotg2(geo, solid_poly=False, color="black", linestyle='solid'):
|
||||
|
||||
try:
|
||||
for sub_geo in geo:
|
||||
plotg2(sub_geo, solid_poly=solid_poly, color=color, linestyle=linestyle)
|
||||
except TypeError:
|
||||
if type(geo) == Polygon:
|
||||
if solid_poly:
|
||||
patch = PolygonPatch(geo,
|
||||
#facecolor="#BBF268",
|
||||
facecolor=color,
|
||||
edgecolor="#006E20",
|
||||
alpha=0.5,
|
||||
zorder=2)
|
||||
ax = subplot(111)
|
||||
ax.add_patch(patch)
|
||||
else:
|
||||
x, y = geo.exterior.coords.xy
|
||||
plot(x, y, color=color, linestyle=linestyle)
|
||||
for ints in geo.interiors:
|
||||
x, y = ints.coords.xy
|
||||
plot(x, y, color=color, linestyle=linestyle)
|
||||
|
||||
if type(geo) == LineString or type(geo) == LinearRing:
|
||||
x, y = geo.coords.xy
|
||||
plot(x, y, color=color, linestyle=linestyle)
|
||||
|
||||
if type(geo) == Point:
|
||||
x, y = geo.coords.xy
|
||||
plot(x, y, 'o')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
p = Polygon([[0, 0], [0, 5], [5, 5], [5, 0]])
|
||||
paths = [
|
||||
LineString([[0.5, 2], [2, 4.5]]),
|
||||
LineString([[2, 0.5], [4.5, 2]])
|
||||
]
|
||||
plotg2(p, solid_poly=True)
|
||||
plotg2(paths, linestyle="dashed")
|
||||
show()
|
||||
@@ -1,24 +0,0 @@
|
||||
from rtree import index as rtindex
|
||||
|
||||
def pt2rect(pt):
|
||||
return pt[0], pt[1], pt[0], pt[1]
|
||||
|
||||
pts = [(0.0, 0.0), (1.0, 1.0), (0.0, 1.0)]
|
||||
|
||||
p = rtindex.Property()
|
||||
p.buffering_capacity = 1
|
||||
p.dimension = 2
|
||||
rt = rtindex.Index(properties=p)
|
||||
#rt = rtindex.Index()
|
||||
|
||||
# If interleaved is True, the coordinates must be in
|
||||
# the form [xmin, ymin, ..., kmin, xmax, ymax, ..., kmax].
|
||||
print((rt.interleaved))
|
||||
|
||||
[rt.add(0, pt2rect(pt)) for pt in pts]
|
||||
print([r.bbox for r in list(rt.nearest((0, 0), 10, True))])
|
||||
|
||||
for pt in pts:
|
||||
rt.delete(0, pt2rect(pt))
|
||||
print((pt2rect(pt), [r.bbox for r in list(rt.nearest((0, 0), 10, True))]))
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<!DOCTYPE svg>
|
||||
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="0.402778in" xml:space="preserve" xmlns:xml="http://www.w3.org/XML/1998/namespace" x="0px" version="1.2" y="0px" height="0.527778in" viewBox="0 0 29 38" baseProfile="tiny">
|
||||
|
||||
<g id="copper0">
|
||||
<g id="copper1">
|
||||
<rect x="1.362" y="2.091" fill="none" stroke="#F7BD13" stroke-width="1.224" width="4.104" height="4.104"/>
|
||||
<circle fill="none" cx="3.362" cy="4.091" stroke="#F7BD13" id="connector1pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="3.362" cy="11.29" stroke="#F7BD13" id="connector2pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="3.362" cy="18.491" stroke="#F7BD13" id="connector3pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="3.362" cy="25.69" stroke="#F7BD13" id="connector4pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="3.365" cy="32.81" stroke="#F7BD13" id="connector5pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="25.001" cy="32.821" stroke="#F7BD13" id="connector6pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="24.999" cy="25.702" stroke="#F7BD13" id="connector7pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="24.999" cy="18.503" stroke="#F7BD13" id="connector8pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="24.999" cy="11.302" stroke="#F7BD13" id="connector9pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="25.029" cy="4.077" stroke="#F7BD13" id="connector10pin" r="2.052" stroke-width="1.224"/>
|
||||
</g>
|
||||
<circle fill="none" cx="3.362" cy="4.091" stroke="#F7BD13" id="connector1pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="3.362" cy="11.29" stroke="#F7BD13" id="connector2pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="3.362" cy="18.491" stroke="#F7BD13" id="connector3pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="3.362" cy="25.69" stroke="#F7BD13" id="connector4pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="3.365" cy="32.81" stroke="#F7BD13" id="connector5pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="25.001" cy="32.821" stroke="#F7BD13" id="connector6pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="24.999" cy="25.702" stroke="#F7BD13" id="connector7pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="24.999" cy="18.503" stroke="#F7BD13" id="connector8pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="24.999" cy="11.302" stroke="#F7BD13" id="connector9pin" r="2.052" stroke-width="1.224"/>
|
||||
<circle fill="none" cx="25.029" cy="4.077" stroke="#F7BD13" id="connector10pin" r="2.052" stroke-width="1.224"/>
|
||||
</g>
|
||||
<g id="silkscreen">
|
||||
<rect width="28.347" x="0.024" y="0.024" height="36.851" fill="none" stroke="#FFFFFF" stroke-width="0.7087"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.9 KiB |
@@ -1,468 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="50.4px" height="122.448px" viewBox="0 0 50.4 122.448" enable-background="new 0 0 50.4 122.448" xml:space="preserve">
|
||||
<desc>Fritzing footprint generated by brd2svg</desc>
|
||||
<g id="silkscreen">
|
||||
<path fill="none" stroke="#FFFFFF" stroke-width="0.576" d="M0.288,122.136h49.824V0.288H0.288V122.136"/>
|
||||
<g>
|
||||
<title>element:J1</title>
|
||||
<g>
|
||||
<title>package:HEAD15-NOSS</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:J2</title>
|
||||
<g>
|
||||
<title>package:HEAD15-NOSS-1</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:U2</title>
|
||||
<g>
|
||||
<title>package:SSOP28</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:U3</title>
|
||||
<g>
|
||||
<title>package:SOT223</title>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="copper1">
|
||||
<g id="copper0">
|
||||
<circle id="connector16pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="10.8" r="1.908"/>
|
||||
<rect x="1.692" y="8.892" fill="none" stroke="#F7BD13" stroke-width="1.224" width="3.814" height="3.816"/>
|
||||
<circle id="connector17pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="18" r="1.908"/>
|
||||
<circle id="connector18pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="25.2" r="1.908"/>
|
||||
<circle id="connector19pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="32.4" r="1.908"/>
|
||||
<circle id="connector20pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="39.6" r="1.908"/>
|
||||
<circle id="connector21pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="46.8" r="1.908"/>
|
||||
<circle id="connector22pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="54" r="1.908"/>
|
||||
<circle id="connector23pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="61.2" r="1.908"/>
|
||||
<circle id="connector24pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="68.4" r="1.908"/>
|
||||
<circle id="connector25pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="75.6" r="1.908"/>
|
||||
<circle id="connector26pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="82.8" r="1.908"/>
|
||||
<circle id="connector27pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="90" r="1.908"/>
|
||||
<circle id="connector28pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="97.2" r="1.908"/>
|
||||
<circle id="connector29pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="104.4" r="1.908"/>
|
||||
<circle id="connector30pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="3.6" cy="111.6" r="1.908"/>
|
||||
<circle id="connector31pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="10.8" r="1.908"/>
|
||||
<circle id="connector32pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="18" r="1.908"/>
|
||||
<circle id="connector33pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="25.2" r="1.908"/>
|
||||
<circle id="connector34pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="32.4" r="1.908"/>
|
||||
<circle id="connector35pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="39.6" r="1.908"/>
|
||||
<circle id="connector36pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="46.8" r="1.908"/>
|
||||
<circle id="connector37pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="54" r="1.908"/>
|
||||
<circle id="connector38pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="61.2" r="1.908"/>
|
||||
<circle id="connector39pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="68.4" r="1.908"/>
|
||||
<circle id="connector40pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="75.6" r="1.908"/>
|
||||
<circle id="connector41pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="82.8" r="1.908"/>
|
||||
<circle id="connector42pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="90" r="1.908"/>
|
||||
<circle id="connector43pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="97.2" r="1.908"/>
|
||||
<circle id="connector44pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="104.4" r="1.908"/>
|
||||
<circle id="connector45pad" fill="none" stroke="#F7BD13" stroke-width="1.224" cx="46.8" cy="111.6" r="1.908"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>layer 21</title>
|
||||
<g>
|
||||
<title>text:TX1</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 9.216, 13.68)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -6.713867e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">TX1</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:RX0</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 9.216, 20.88)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 1.220703e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">RX0</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:RST</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 9.216, 28.008)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -7.934570e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">RST</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:GND</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 9.216, 35.208)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 0 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">GND</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:D2</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 9.216, 41.544)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 6.103516e-005 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D2</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:D3</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 9.216, 48.6)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -5.798340e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D3</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:D4</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 9.216, 55.872)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -6.103516e-005 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D4</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:D5</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 9.216, 62.928)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -7.019043e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D5</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:D6</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 9.216, 70.272)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -4.577637e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D6</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:D7</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 9.216, 77.544)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 6.103516e-005 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D7</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:D8</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 9.216, 84.6)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -5.798340e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D8</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:D9</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 9.216, 91.872)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -6.103516e-005 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D9</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:D10</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 9.216, 100.224)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -0.0016 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D10</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:D11</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 9.216, 107.352)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -5.493164e-004 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D11</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:D12</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 9.216, 114.552)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -0.0017 -4.272461e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D12</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:D13</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 43.488, 114.552)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -0.0017 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">D13</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:3V3</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 43.488, 107.28)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -2.746582e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">3V3</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:REF</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 43.488, 100.152)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -0.0013 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">REF</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:A0</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 43.488, 91.944)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -3.356934e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A0</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:A1</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 43.488, 84.672)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -8.544922e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A1</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:A2</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 43.488, 77.544)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 6.103516e-005 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A2</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:A3</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 43.488, 70.344)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -7.324219e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A3</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:A4</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 43.488, 63.216)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 1.831055e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A4</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:A5</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 43.488, 55.944)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -3.356934e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A5</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:A6</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 43.488, 48.744)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -0.0011 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A6</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:A7</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 43.488, 41.616)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -2.136230e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">A7</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:5V</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 43.488, 34.416)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -9.765625e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">5V</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:RST</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 43.488, 27.216)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 1.831055e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">RST</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:GND</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 43.488, 19.8)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 1.831055e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">GND</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:VIN</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 43.488, 12.672)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -8.544922e-004 -9.460449e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="2.6726">VIN</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:*</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 7.056, 92.664)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -0.001 -5.798340e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="1.6704">*</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:*</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 7.056, 99.936)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -5.187988e-004 -5.798340e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="1.6704">*</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:*</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 7.056, 107.064)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -0.0014 -5.798340e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="1.6704">*</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:*</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 7.056, 71.064)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 -0.0014 -5.798340e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="1.6704">*</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:*</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 7.056, 63.792)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 0 -5.798340e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="1.6704">*</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>text:*</title>
|
||||
<g transform="matrix(1, 0, 0, 1, 7.056, 49.464)">
|
||||
<g transform="rotate(270)">
|
||||
<text transform="matrix(1 0 0 1 1.220703e-004 -5.798340e-004)" fill="#FFFFFF" font-family="'OCRA'" font-size="1.6704">*</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:C1</title>
|
||||
<g>
|
||||
<title>package:CAP0805-NP</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:C2</title>
|
||||
<g>
|
||||
<title>package:TAN-A</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:C3</title>
|
||||
<g>
|
||||
<title>package:CAP0805-NP</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:C4</title>
|
||||
<g>
|
||||
<title>package:CAP0805-NP</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:C7</title>
|
||||
<g>
|
||||
<title>package:CAP0805-NP</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:C8</title>
|
||||
<g>
|
||||
<title>package:TAN-A</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:C9</title>
|
||||
<g>
|
||||
<title>package:CAP0805-NP</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:D1</title>
|
||||
<g>
|
||||
<title>package:SOD-123</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:J1</title>
|
||||
<g>
|
||||
<title>package:HEAD15-NOSS</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:J2</title>
|
||||
<g>
|
||||
<title>package:HEAD15-NOSS-1</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:RP1</title>
|
||||
<g>
|
||||
<title>package:RES4NT</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:RP2</title>
|
||||
<g>
|
||||
<title>package:RES4NT</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:U$4</title>
|
||||
<g>
|
||||
<title>package:FIDUCIAL-1X2</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:U$37</title>
|
||||
<g>
|
||||
<title>package:FIDUCIAL-1X2</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:U$53</title>
|
||||
<g>
|
||||
<title>package:FIDUCIAL-1X2</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:U$54</title>
|
||||
<g>
|
||||
<title>package:FIDUCIAL-1X2</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:U2</title>
|
||||
<g>
|
||||
<title>package:SSOP28</title>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>element:U3</title>
|
||||
<g>
|
||||
<title>package:SOT223</title>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 15 KiB |
@@ -1,126 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<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"
|
||||
width="744.09448819"
|
||||
height="1052.3622047"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="drawing.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4"
|
||||
inkscape:cx="436.65332"
|
||||
inkscape:cy="798.58794"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="968"
|
||||
inkscape:window-height="759"
|
||||
inkscape:window-x="1949"
|
||||
inkscape:window-y="142"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#999999;stroke-width:0.69999999;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="path2985"
|
||||
sodipodi:cx="210.11172"
|
||||
sodipodi:cy="201.81374"
|
||||
sodipodi:rx="70.710678"
|
||||
sodipodi:ry="70.710678"
|
||||
d="m 280.8224,201.81374 a 70.710678,70.710678 0 1 1 -141.42135,0 70.710678,70.710678 0 1 1 141.42135,0 z" />
|
||||
<rect
|
||||
style="fill:none;stroke:#999999;stroke-width:0.69999999;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect2987"
|
||||
width="82.832512"
|
||||
height="72.73098"
|
||||
x="343.45187"
|
||||
y="127.06245" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 261.70701,300.10548 137.14286,-68.57143 -13.57143,104.28572 105.71429,2.85714 -232.14286,29.28572 z"
|
||||
id="path2991"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
id="g3018"
|
||||
transform="translate(-37.142857,-103.57143)">
|
||||
<rect
|
||||
y="222.01678"
|
||||
x="508.10672"
|
||||
height="72.73098"
|
||||
width="82.832512"
|
||||
id="rect2987-8"
|
||||
style="fill:none;stroke:#999999;stroke-width:0.69999999;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="177.86595"
|
||||
x="534.49329"
|
||||
height="72.73098"
|
||||
width="82.832512"
|
||||
id="rect2987-4"
|
||||
style="fill:none;stroke:#999999;stroke-width:0.69999999;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#999999;stroke-width:0.69999999;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
d="M 550.71875 258.84375 L 550.71875 286 L 513.59375 286 L 513.59375 358.71875 L 596.40625 358.71875 L 596.40625 331.59375 L 633.5625 331.59375 L 633.5625 258.84375 L 550.71875 258.84375 z "
|
||||
id="rect2987-5" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 276.42857,98.076465 430.71429,83.076464"
|
||||
id="path3037"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 164.28571,391.64789 c 12.85715,-54.28571 55.00001,21.42858 84.28572,22.85715 29.28571,1.42857 30.71429,-14.28572 30.71429,-14.28572"
|
||||
id="path3039"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
id="g3018-3"
|
||||
transform="matrix(0.54511991,0,0,0.54511991,308.96645,74.66094)">
|
||||
<rect
|
||||
y="222.01678"
|
||||
x="508.10672"
|
||||
height="72.73098"
|
||||
width="82.832512"
|
||||
id="rect2987-8-5"
|
||||
style="fill:none;stroke:#999999;stroke-width:1.28412116;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<rect
|
||||
y="177.86595"
|
||||
x="534.49329"
|
||||
height="72.73098"
|
||||
width="82.832512"
|
||||
id="rect2987-4-6"
|
||||
style="fill:none;stroke:#999999;stroke-width:1.28412116;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.9 KiB |
@@ -1,77 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1 Basic//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd'><svg baseProfile="basic" height="0.59in" id="svg" version="1.1" viewBox="0 0 67.502 42.52" width="0.94in" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px">
|
||||
<g id="breadboard">
|
||||
<rect fill="none" height="5.372" id="connector0pin" width="2.16" x="60.644" y="32.178"/>
|
||||
<rect fill="none" height="5.309" id="connector1pin" width="2.16" x="53.496" y="5.002"/>
|
||||
<rect fill="none" height="5.309" id="connector2pin" width="2.16" x="60.644" y="5.002"/>
|
||||
<rect fill="none" height="5.372" id="connector3pin" width="2.159" x="53.506" y="32.178"/>
|
||||
<rect fill="none" height="5.372" id="connector5pin" width="2.159" x="53.506" y="32.178"/>
|
||||
<rect fill="none" height="5.372" id="connector4pin" width="2.159" x="53.506" y="32.178"/>
|
||||
<rect fill="none" height="3.714" id="connector0terminal" width="2.16" x="60.644" y="33.836"/>
|
||||
<rect fill="none" height="3.669" id="connector1terminal" width="2.16" x="53.496" y="5.002"/>
|
||||
<rect fill="none" height="3.669" id="connector2terminal" width="2.16" x="60.644" y="5.002"/>
|
||||
<rect fill="none" height="3.714" id="connector3terminal" width="2.159" x="53.506" y="33.836"/>
|
||||
<rect fill="none" height="3.714" id="connector5terminal" width="2.159" x="53.506" y="33.836"/>
|
||||
<rect fill="none" height="3.714" id="connector4terminal" width="2.159" x="53.506" y="33.836"/>
|
||||
<g>
|
||||
<polygon fill="#1F7A34" points="49.528,34.417 67.502,34.417 67.502,8.102 49.528,8.102 49.528,0 20.776,0 20.776,42.52 49.528,42.52 "/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M30.783,4.96c0-1.988-1.609-3.598-3.598-3.598c-1.985,0-3.598,1.609-3.598,3.598 c0,1.985,1.612,3.598,3.598,3.598C29.173,8.558,30.783,6.945,30.783,4.96z" fill="#9A916C"/>
|
||||
</g>
|
||||
<g>
|
||||
<circle cx="27.182" cy="4.96" fill="#3A3A3A" r="2.708"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M30.783,37.56c0-1.988-1.609-3.598-3.598-3.598c-1.985,0-3.598,1.609-3.598,3.598 c0,1.985,1.612,3.598,3.598,3.598C29.173,41.157,30.783,39.545,30.783,37.56z" fill="#9A916C"/>
|
||||
</g>
|
||||
<g>
|
||||
<circle cx="27.182" cy="37.56" fill="#3A3A3A" r="2.708"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<rect fill="#898989" height="34.016" width="45.355" x="0.001" y="4.252"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect fill="#DDDDDD" height="0.743" width="45.355" x="0.001" y="4.252"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect fill="#C6C6C6" height="0.889" width="45.355" x="0.001" y="4.991"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect fill="#ADADAD" height="31.342" width="45.356" y="5.88"/>
|
||||
</g>
|
||||
<g>
|
||||
<line fill="#919191" stroke="#4D4D4D" stroke-width="0.1" x1="34.173" x2="34.173" y1="4.252" y2="38.268"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect fill="#8C8C8C" height="5.349" width="4.667" x="52.252" y="4.961"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect fill="#8C8C8C" height="5.349" width="4.668" x="59.418" y="4.961"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect fill="#8C8C8C" height="5.349" width="4.667" x="52.252" y="32.177"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect fill="#8C8C8C" height="5.349" width="4.668" x="59.418" y="32.177"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M30.074,21.386l-2.64-1.524v1.134H13.468c0.515-0.416,1.008-0.965,1.493-1.505 c0.802-0.894,1.631-1.819,2.338-1.819h2.277c0.141,0.521,0.597,0.913,1.163,0.913c0.677,0,1.226-0.548,1.226-1.225 s-0.549-1.226-1.226-1.226c-0.566,0-1.022,0.392-1.163,0.914h-2.277c-0.985,0-1.868,0.984-2.803,2.026 c-0.744,0.83-1.509,1.675-2.255,1.922h-1.82c-0.185-1.02-1.073-1.794-2.145-1.794c-1.206,0-2.184,0.978-2.184,2.184 c0,1.207,0.978,2.184,2.184,2.184c1.072,0,1.96-0.774,2.145-1.794h5.196c0.746,0.247,1.511,1.093,2.254,1.922 c0.934,1.043,1.817,2.026,2.802,2.026h2.142v0.985h2.595v-2.595h-2.595v0.985h-2.142c-0.707,0-1.536-0.925-2.337-1.818 c-0.485-0.541-0.978-1.09-1.493-1.506h10.592v1.134L30.074,21.386z" fill="#4D4D4D"/>
|
||||
</g>
|
||||
<g>
|
||||
<polyline fill="none" points="54.586,10.31 54.586,17.006 45.357,17.006 " stroke="#8C8C8C" stroke-width="1"/>
|
||||
</g>
|
||||
<g>
|
||||
<polyline fill="none" points="61.732,10.31 61.732,19.841 45.357,19.841 " stroke="#8C8C8C" stroke-width="1"/>
|
||||
</g>
|
||||
<g>
|
||||
<polyline fill="none" points="54.586,32.177 54.586,25.479 45.357,25.479 " stroke="#8C8C8C" stroke-width="1"/>
|
||||
</g>
|
||||
<g>
|
||||
<polyline fill="none" points="61.732,32.177 61.732,22.646 45.357,22.646 " stroke="#8C8C8C" stroke-width="1"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,101 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<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:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="50mm"
|
||||
height="50mm"
|
||||
viewBox="0 0 50 50"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 5da689c313, 2019-01-14"
|
||||
sodipodi:docname="use.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.4679048"
|
||||
inkscape:cx="113.26276"
|
||||
inkscape:cy="109.86475"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="3834"
|
||||
inkscape:window-height="2095"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<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>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-247)">
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 6.2421073,283.98351 c -2.4960796,-5.97466 14.6658087,-0.0283 2.7443869,-28.40936 -2.6185936,-6.23403 13.3146118,1.40862 15.4980508,1.40862"
|
||||
id="path815"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csc" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#path815"
|
||||
id="use817"
|
||||
transform="matrix(-1,0,0,1,48.96909,0)"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<rect
|
||||
style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
id="rect942"
|
||||
width="4.3065705"
|
||||
height="4.7904549"
|
||||
x="13.742314"
|
||||
y="288.14493" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#rect942"
|
||||
id="use944"
|
||||
transform="matrix(2.4752181,0,0,1.0534789,-4.8199296,-20.27984)"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<circle
|
||||
style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
id="path948"
|
||||
cx="18.823099"
|
||||
cy="275.70914"
|
||||
r="4.5485125" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#path948"
|
||||
id="use950"
|
||||
transform="translate(10.50029,-10.984174)"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.2 KiB |
@@ -1,331 +0,0 @@
|
||||
import unittest
|
||||
from flatcamParsers.ParseExcellon import Excellon
|
||||
from flatcamParsers.ParseGerber import Gerber
|
||||
|
||||
|
||||
class ExcellonNumberParseTestInch(unittest.TestCase):
|
||||
# Inch base format: 00.0000
|
||||
|
||||
# LEADING ZEROS
|
||||
# With leading zeros, when you type in a coordinate,
|
||||
# the leading zeros must always be included. Trailing zeros
|
||||
# are unneeded and may be left off. The CNC-7 will automatically add them.
|
||||
|
||||
# TRAILING ZEROS
|
||||
# You must show all zeros to the right of the number and can omit
|
||||
# all zeros to the left of the number. The CNC-7 will count the number
|
||||
# of digits you typed and automatically fill in the missing zeros.
|
||||
|
||||
def test_inch_leading_6digit(self):
|
||||
excellon = Excellon()
|
||||
self.assertEqual(excellon.zeros, "L")
|
||||
self.assertEqual(excellon.parse_number("123456"), 12.3456)
|
||||
|
||||
def test_inch_leading_5digit(self):
|
||||
excellon = Excellon()
|
||||
self.assertEqual(excellon.parse_number("12345"), 12.345)
|
||||
|
||||
def test_inch_leading_15digit(self):
|
||||
excellon = Excellon()
|
||||
self.assertEqual(excellon.parse_number("012345"), 1.2345)
|
||||
|
||||
def test_inch_leading_51digit(self):
|
||||
excellon = Excellon()
|
||||
self.assertEqual(excellon.parse_number("123450"), 12.345)
|
||||
|
||||
def test_inch_trailing_6digit(self):
|
||||
excellon = Excellon()
|
||||
excellon.zeros = "T"
|
||||
self.assertEqual(excellon.parse_number("123456"), 12.3456)
|
||||
|
||||
def test_inch_trailing_5digit(self):
|
||||
excellon = Excellon()
|
||||
excellon.zeros = "T"
|
||||
self.assertEqual(excellon.parse_number("12345"), 1.2345)
|
||||
|
||||
def test_inch_trailing_15digit(self):
|
||||
excellon = Excellon()
|
||||
excellon.zeros = "T"
|
||||
self.assertEqual(excellon.parse_number("012345"), 1.2345)
|
||||
|
||||
def test_inch_trailing_51digit(self):
|
||||
excellon = Excellon()
|
||||
excellon.zeros = "T"
|
||||
self.assertEqual(excellon.parse_number("123450"), 12.345)
|
||||
|
||||
|
||||
class ExcellonNumberParseTestMetric(unittest.TestCase):
|
||||
# Metric base format: 000.000
|
||||
|
||||
# LEADING ZEROS
|
||||
# With leading zeros, when you type in a coordinate,
|
||||
# the leading zeros must always be included. Trailing zeros
|
||||
# are unneeded and may be left off. The CNC-7 will automatically add them.
|
||||
|
||||
# TRAILING ZEROS
|
||||
# You must show all zeros to the right of the number and can omit
|
||||
# all zeros to the left of the number. The CNC-7 will count the number
|
||||
# of digits you typed and automatically fill in the missing zeros.
|
||||
|
||||
def test_inch_leading_6digit(self):
|
||||
excellon = Excellon()
|
||||
excellon.units = "mm"
|
||||
self.assertEqual(excellon.parse_number("123456"), 123.456)
|
||||
|
||||
def test_inch_leading_5digit(self):
|
||||
excellon = Excellon()
|
||||
excellon.units = "mm"
|
||||
self.assertEqual(excellon.parse_number("12345"), 123.45)
|
||||
|
||||
def test_inch_leading_15digit(self):
|
||||
excellon = Excellon()
|
||||
excellon.units = "mm"
|
||||
self.assertEqual(excellon.parse_number("012345"), 12.345)
|
||||
|
||||
def test_inch_leading_51digit(self):
|
||||
excellon = Excellon()
|
||||
excellon.units = "mm"
|
||||
self.assertEqual(excellon.parse_number("123450"), 123.45)
|
||||
|
||||
def test_inch_trailing_6digit(self):
|
||||
excellon = Excellon()
|
||||
excellon.units = "mm"
|
||||
excellon.zeros = "T"
|
||||
self.assertEqual(excellon.parse_number("123456"), 123.456)
|
||||
|
||||
def test_inch_trailing_5digit(self):
|
||||
excellon = Excellon()
|
||||
excellon.units = "mm"
|
||||
excellon.zeros = "T"
|
||||
self.assertEqual(excellon.parse_number("12345"), 12.345)
|
||||
|
||||
def test_inch_trailing_15digit(self):
|
||||
excellon = Excellon()
|
||||
excellon.units = "mm"
|
||||
excellon.zeros = "T"
|
||||
self.assertEqual(excellon.parse_number("012345"), 12.345)
|
||||
|
||||
def test_inch_trailing_51digit(self):
|
||||
excellon = Excellon()
|
||||
excellon.units = "mm"
|
||||
excellon.zeros = "T"
|
||||
self.assertEqual(excellon.parse_number("123450"), 123.45)
|
||||
|
||||
|
||||
class ExcellonFormatM72Test(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.excellon = Excellon()
|
||||
code = """
|
||||
M48
|
||||
M72
|
||||
T1C.02362F197S550
|
||||
T2C.03543F197S550
|
||||
M95
|
||||
T1
|
||||
X9000Y11750
|
||||
X30250Y10500
|
||||
"""
|
||||
code = code.split('\n')
|
||||
self.excellon.parse_lines(code)
|
||||
|
||||
def test_format(self):
|
||||
self.assertEqual(self.excellon.units.lower(), "in")
|
||||
self.assertEqual(self.excellon.zeros, "L")
|
||||
|
||||
def test_coords(self):
|
||||
# For X9000 add the missing 00 on the right. Then divide by 10000.
|
||||
self.assertEqual(self.excellon.drills[0]["point"].coords[0], (90.0, 11.75))
|
||||
self.assertEqual(self.excellon.drills[1]["point"].coords[0], (30.25, 10.5))
|
||||
|
||||
|
||||
class ExcellonFormatM71Test(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.excellon = Excellon()
|
||||
code = """
|
||||
M48
|
||||
M71
|
||||
T1C.02362F197S550
|
||||
T2C.03543F197S550
|
||||
M95
|
||||
T1
|
||||
X9000Y11750
|
||||
X30250Y10500
|
||||
"""
|
||||
code = code.split('\n')
|
||||
self.excellon.parse_lines(code)
|
||||
|
||||
def test_format(self):
|
||||
self.assertEqual(self.excellon.units.lower(), "mm")
|
||||
self.assertEqual(self.excellon.zeros, "L")
|
||||
|
||||
def test_coords(self):
|
||||
# For X9000 add the missing 00 on the right. Then divide by 10000.
|
||||
self.assertEqual(self.excellon.drills[0]["point"].coords[0], (900.0, 117.5))
|
||||
self.assertEqual(self.excellon.drills[1]["point"].coords[0], (302.5, 105.0))
|
||||
|
||||
|
||||
class ExcellonFormatINCHLZTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.excellon = Excellon()
|
||||
code = """
|
||||
M48
|
||||
INCH,LZ
|
||||
T1C.02362F197S550
|
||||
T2C.03543F197S550
|
||||
M95
|
||||
T1
|
||||
X9000Y11750
|
||||
X30250Y10500
|
||||
"""
|
||||
code = code.split('\n')
|
||||
self.excellon.parse_lines(code)
|
||||
|
||||
def test_format(self):
|
||||
self.assertEqual(self.excellon.units.lower(), "in")
|
||||
self.assertEqual(self.excellon.zeros, "L")
|
||||
|
||||
def test_coords(self):
|
||||
# For X9000 add the missing 00 on the right. Then divide by 10000.
|
||||
self.assertEqual(self.excellon.drills[0]["point"].coords[0], (90.0, 11.75))
|
||||
self.assertEqual(self.excellon.drills[1]["point"].coords[0], (30.25, 10.5))
|
||||
|
||||
|
||||
class ExcellonFormatINCHTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.excellon = Excellon()
|
||||
code = """
|
||||
M48
|
||||
INCH,LZ
|
||||
T1C.02362F197S550
|
||||
T2C.03543F197S550
|
||||
M95
|
||||
T1
|
||||
X9000Y11750
|
||||
X30250Y10500
|
||||
"""
|
||||
code = code.split('\n')
|
||||
self.excellon.parse_lines(code)
|
||||
|
||||
def test_format(self):
|
||||
self.assertEqual(self.excellon.units.lower(), "in")
|
||||
self.assertEqual(self.excellon.zeros, "L")
|
||||
|
||||
def test_coords(self):
|
||||
# For X9000 add the missing 00 on the right. Then divide by 10000.
|
||||
self.assertEqual(self.excellon.drills[0]["point"].coords[0], (90.0, 11.75))
|
||||
self.assertEqual(self.excellon.drills[1]["point"].coords[0], (30.25, 10.5))
|
||||
|
||||
|
||||
class ExcellonFormatINCHTZTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.excellon = Excellon()
|
||||
code = """
|
||||
M48
|
||||
INCH,TZ
|
||||
T1C.02362F197S550
|
||||
T2C.03543F197S550
|
||||
M95
|
||||
T1
|
||||
X9000Y11750
|
||||
X30250Y10500
|
||||
"""
|
||||
code = code.split('\n')
|
||||
self.excellon.parse_lines(code)
|
||||
|
||||
def test_format(self):
|
||||
self.assertEqual(self.excellon.units.lower(), "in")
|
||||
self.assertEqual(self.excellon.zeros, "T")
|
||||
|
||||
def test_coords(self):
|
||||
# For X9000 add the missing 00 on the right. Then divide by 10000.
|
||||
self.assertEqual(self.excellon.drills[0]["point"].coords[0], (0.9, 1.175))
|
||||
self.assertEqual(self.excellon.drills[1]["point"].coords[0], (3.025, 1.05))
|
||||
|
||||
|
||||
class ExcellonFormatMETRICLZTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.excellon = Excellon()
|
||||
code = """
|
||||
M48
|
||||
METRIC,LZ
|
||||
T1C.02362F197S550
|
||||
T2C.03543F197S550
|
||||
M95
|
||||
T1
|
||||
X9000Y11750
|
||||
X30250Y10500
|
||||
"""
|
||||
code = code.split('\n')
|
||||
self.excellon.parse_lines(code)
|
||||
|
||||
def test_format(self):
|
||||
self.assertEqual(self.excellon.units.lower(), "mm")
|
||||
self.assertEqual(self.excellon.zeros, "L")
|
||||
|
||||
def test_coords(self):
|
||||
# For X9000 add the missing 00 on the right. Then divide by 10000.
|
||||
self.assertEqual(self.excellon.drills[0]["point"].coords[0], (900.0, 117.5))
|
||||
self.assertEqual(self.excellon.drills[1]["point"].coords[0], (302.5, 105.0))
|
||||
|
||||
|
||||
class ExcellonFormatMETRICTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.excellon = Excellon()
|
||||
code = """
|
||||
M48
|
||||
METRIC,LZ
|
||||
T1C.02362F197S550
|
||||
T2C.03543F197S550
|
||||
M95
|
||||
T1
|
||||
X9000Y11750
|
||||
X30250Y10500
|
||||
"""
|
||||
code = code.split('\n')
|
||||
self.excellon.parse_lines(code)
|
||||
|
||||
def test_format(self):
|
||||
self.assertEqual(self.excellon.units.lower(), "mm")
|
||||
self.assertEqual(self.excellon.zeros, "L")
|
||||
|
||||
def test_coords(self):
|
||||
# For X9000 add the missing 00 on the right. Then divide by 10000.
|
||||
self.assertEqual(self.excellon.drills[0]["point"].coords[0], (900.0, 117.5))
|
||||
self.assertEqual(self.excellon.drills[1]["point"].coords[0], (302.5, 105.0))
|
||||
|
||||
|
||||
class ExcellonFormatMETRICTZTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.excellon = Excellon()
|
||||
code = """
|
||||
M48
|
||||
METRIC,TZ
|
||||
T1C.02362F197S550
|
||||
T2C.03543F197S550
|
||||
M95
|
||||
T1
|
||||
X9000Y11750
|
||||
X30250Y10500
|
||||
"""
|
||||
code = code.split('\n')
|
||||
self.excellon.parse_lines(code)
|
||||
|
||||
def test_format(self):
|
||||
self.assertEqual(self.excellon.units.lower(), "mm")
|
||||
self.assertEqual(self.excellon.zeros, "T")
|
||||
|
||||
def test_coords(self):
|
||||
# For X9000 add the missing 00 on the right. Then divide by 10000.
|
||||
self.assertEqual(self.excellon.drills[0]["point"].coords[0], (9.0, 11.75))
|
||||
self.assertEqual(self.excellon.drills[1]["point"].coords[0], (30.25, 10.5))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,163 +0,0 @@
|
||||
import unittest
|
||||
from PyQt5 import QtGui, QtWidgets
|
||||
import sys
|
||||
from FlatCAMApp import App
|
||||
from FlatCAMObj import FlatCAMExcellon, FlatCAMCNCjob
|
||||
from flatcamGUI.ObjectUI import ExcellonObjectUI
|
||||
import tempfile
|
||||
import os
|
||||
from time import sleep
|
||||
|
||||
|
||||
class ExcellonFlowTestCase(unittest.TestCase):
|
||||
"""
|
||||
This is a top-level test covering the Excellon-to-GCode
|
||||
generation workflow.
|
||||
|
||||
THIS IS A REQUIRED TEST FOR ANY UPDATES.
|
||||
|
||||
"""
|
||||
|
||||
filename = 'case1.drl'
|
||||
|
||||
def setUp(self):
|
||||
self.app = QtWidgets.QApplication(sys.argv)
|
||||
|
||||
# Create App, keep app defaults (do not load
|
||||
# user-defined defaults).
|
||||
self.fc = App(user_defaults=False)
|
||||
|
||||
self.fc.open_excellon('tests/excellon_files/' + self.filename)
|
||||
|
||||
def tearDown(self):
|
||||
del self.fc
|
||||
del self.app
|
||||
|
||||
def test_flow(self):
|
||||
# Names of available objects.
|
||||
names = self.fc.collection.get_names()
|
||||
print(names)
|
||||
|
||||
#--------------------------------------
|
||||
# Total of 1 objects.
|
||||
#--------------------------------------
|
||||
self.assertEqual(len(names), 1,
|
||||
"Expected 1 object, found %d" % len(names))
|
||||
|
||||
#--------------------------------------
|
||||
# Object's name matches the file name.
|
||||
#--------------------------------------
|
||||
self.assertEqual(names[0], self.filename,
|
||||
"Expected name == %s, got %s" % (self.filename, names[0]))
|
||||
|
||||
#---------------------------------------
|
||||
# Get object by that name, make sure it's a FlatCAMExcellon.
|
||||
#---------------------------------------
|
||||
excellon_name = names[0]
|
||||
excellon_obj = self.fc.collection.get_by_name(excellon_name)
|
||||
self.assertTrue(isinstance(excellon_obj, FlatCAMExcellon),
|
||||
"Expected FlatCAMExcellon, instead, %s is %s" %
|
||||
(excellon_name, type(excellon_obj)))
|
||||
|
||||
#----------------------------------------
|
||||
# Object's GUI matches Object's options
|
||||
#----------------------------------------
|
||||
# TODO: Open GUI with double-click on object.
|
||||
# Opens the Object's GUI, populates it.
|
||||
excellon_obj.build_ui()
|
||||
for option, value in list(excellon_obj.options.items()):
|
||||
try:
|
||||
form_field = excellon_obj.form_fields[option]
|
||||
except KeyError:
|
||||
print(("**********************************************************\n"
|
||||
"* WARNING: Option '{}' has no form field\n"
|
||||
"**********************************************************"
|
||||
"".format(option)))
|
||||
continue
|
||||
self.assertEqual(value, form_field.get_value(),
|
||||
"Option '{}' == {} but form has {}".format(
|
||||
option, value, form_field.get_value()
|
||||
))
|
||||
|
||||
# --------------------------------------------------
|
||||
# Changes in the GUI should be read in when
|
||||
# running any process. Changing something here.
|
||||
# --------------------------------------------------
|
||||
|
||||
form_field = excellon_obj.form_fields['feedrate']
|
||||
value = form_field.get_value()
|
||||
form_field.set_value(value * 1.1) # Increase by 10%
|
||||
print(("'feedrate' == {}".format(value)))
|
||||
|
||||
# --------------------------------------------------
|
||||
# Create GCode using all tools.
|
||||
# --------------------------------------------------
|
||||
|
||||
assert isinstance(excellon_obj, FlatCAMExcellon) # Just for the IDE
|
||||
ui = excellon_obj.ui
|
||||
assert isinstance(ui, ExcellonObjectUI)
|
||||
ui.tools_table.selectAll() # Select All
|
||||
ui.generate_cnc_button.click() # Click
|
||||
|
||||
# Work is done in a separate thread and results are
|
||||
# passed via events to the main event loop which is
|
||||
# not running. Run only for pending events.
|
||||
#
|
||||
# I'm not sure why, but running it only once does
|
||||
# not catch the new object. Might be a timing issue.
|
||||
# http://pyqt.sourceforge.net/Docs/PyQt4/qeventloop.html#details
|
||||
for _ in range(2):
|
||||
sleep(0.1)
|
||||
self.app.processEvents()
|
||||
|
||||
# ---------------------------------------------
|
||||
# Check that GUI has been read in.
|
||||
# ---------------------------------------------
|
||||
|
||||
value = excellon_obj.options['feedrate']
|
||||
form_value = form_field.get_value()
|
||||
self.assertEqual(value, form_value,
|
||||
"Form value for '{}' == {} was not read into options"
|
||||
"which has {}".format('feedrate', form_value, value))
|
||||
print(("'feedrate' == {}".format(value)))
|
||||
|
||||
# ---------------------------------------------
|
||||
# Check that only 1 object has been created.
|
||||
# ---------------------------------------------
|
||||
|
||||
names = self.fc.collection.get_names()
|
||||
self.assertEqual(len(names), 2,
|
||||
"Expected 2 objects, found %d" % len(names))
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Make sure the CNCJob Object has the correct name
|
||||
# -------------------------------------------------------
|
||||
|
||||
cncjob_name = excellon_name + "_cnc"
|
||||
self.assertTrue(cncjob_name in names,
|
||||
"Object named %s not found." % cncjob_name)
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Get the object make sure it's a cncjob object
|
||||
# -------------------------------------------------------
|
||||
|
||||
cncjob_obj = self.fc.collection.get_by_name(cncjob_name)
|
||||
self.assertTrue(isinstance(cncjob_obj, FlatCAMCNCjob),
|
||||
"Expected a FlatCAMCNCjob, got %s" % type(cncjob_obj))
|
||||
|
||||
# -----------------------------------------
|
||||
# Export G-Code, check output
|
||||
# -----------------------------------------
|
||||
assert isinstance(cncjob_obj, FlatCAMCNCjob) # For IDE
|
||||
|
||||
# get system temporary file(try create it and delete)
|
||||
with tempfile.NamedTemporaryFile(prefix='unittest.',
|
||||
suffix="." + cncjob_name + '.gcode',
|
||||
delete=True) as tmp_file:
|
||||
output_filename = tmp_file.name
|
||||
|
||||
cncjob_obj.export_gcode(output_filename)
|
||||
self.assertTrue(os.path.isfile(output_filename))
|
||||
os.remove(output_filename)
|
||||
|
||||
print(names)
|
||||
@@ -1,35 +0,0 @@
|
||||
import unittest
|
||||
import camlib
|
||||
from flatcamParsers.ParseGerber import Gerber
|
||||
|
||||
|
||||
class GerberBuffer(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.gerber1 = Gerber()
|
||||
self.gerber1.use_buffer_for_union = True
|
||||
self.gerber1.parse_file("tests/gerber_files/STM32F4-spindle.cmp")
|
||||
geometry1 = self.gerber1.solid_geometry
|
||||
self.geometry1_area = self.compute_area(geometry1)
|
||||
self.gerber2 = Gerber()
|
||||
self.gerber2.use_buffer_for_union = False
|
||||
self.gerber2.parse_file("tests/gerber_files/STM32F4-spindle.cmp")
|
||||
geometry2 = self.gerber2.solid_geometry
|
||||
self.geometry2_area = self.compute_area (geometry2)
|
||||
|
||||
def compute_area(self, geometry):
|
||||
area = 0
|
||||
try:
|
||||
for geo in geometry:
|
||||
area += geo.area
|
||||
|
||||
# Not iterable, do the actual indexing and add.
|
||||
except TypeError:
|
||||
area = geometry.area
|
||||
return area
|
||||
|
||||
def test_buffer(self):
|
||||
self.assertLessEqual(abs(self.geometry2_area - self.geometry1_area), 0.000001)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,190 +0,0 @@
|
||||
import sys
|
||||
import unittest
|
||||
from PyQt5 import QtGui, QtWidgets
|
||||
from FlatCAMApp import App, tclCommands
|
||||
from FlatCAMObj import FlatCAMGerber, FlatCAMGeometry, FlatCAMCNCjob
|
||||
from flatcamGUI.ObjectUI import GerberObjectUI, GeometryObjectUI
|
||||
from time import sleep
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
|
||||
class GerberFlowTestCase(unittest.TestCase):
|
||||
"""
|
||||
This is a top-level test covering the Gerber-to-GCode
|
||||
generation workflow.
|
||||
|
||||
THIS IS A REQUIRED TEST FOR ANY UPDATES.
|
||||
|
||||
"""
|
||||
|
||||
filename = 'simple1.gbr'
|
||||
|
||||
def setUp(self):
|
||||
self.app = QtWidgets.QApplication(sys.argv)
|
||||
|
||||
# Create App, keep app defaults (do not load
|
||||
# user-defined defaults).
|
||||
self.fc = App(user_defaults=False)
|
||||
|
||||
self.fc.open_gerber('tests/gerber_files/' + self.filename)
|
||||
|
||||
def tearDown(self):
|
||||
del self.fc
|
||||
del self.app
|
||||
|
||||
def test_flow(self):
|
||||
# Names of available objects.
|
||||
names = self.fc.collection.get_names()
|
||||
print(names)
|
||||
|
||||
# --------------------------------------
|
||||
# Total of 1 objects.
|
||||
# --------------------------------------
|
||||
self.assertEqual(len(names), 1,
|
||||
"Expected 1 object, found %d" % len(names))
|
||||
|
||||
# --------------------------------------
|
||||
# Object's name matches the file name.
|
||||
# --------------------------------------
|
||||
self.assertEqual(names[0], self.filename,
|
||||
"Expected name == %s, got %s" % (self.filename, names[0]))
|
||||
|
||||
# ---------------------------------------
|
||||
# Get object by that name, make sure it's a FlatCAMGerber.
|
||||
# ---------------------------------------
|
||||
gerber_name = names[0]
|
||||
gerber_obj = self.fc.collection.get_by_name(gerber_name)
|
||||
self.assertTrue(isinstance(gerber_obj, FlatCAMGerber),
|
||||
"Expected FlatCAMGerber, instead, %s is %s" %
|
||||
(gerber_name, type(gerber_obj)))
|
||||
|
||||
# ----------------------------------------
|
||||
# Object's GUI matches Object's options
|
||||
# ----------------------------------------
|
||||
# TODO: Open GUI with double-click on object.
|
||||
# Opens the Object's GUI, populates it.
|
||||
gerber_obj.build_ui()
|
||||
for option, value in list(gerber_obj.options.items()):
|
||||
try:
|
||||
form_field = gerber_obj.form_fields[option]
|
||||
except KeyError:
|
||||
print(("**********************************************************\n"
|
||||
"* WARNING: Option '{}' has no form field\n"
|
||||
"**********************************************************"
|
||||
"".format(option)))
|
||||
continue
|
||||
self.assertEqual(value, form_field.get_value(),
|
||||
"Option '{}' == {} but form has {}".format(
|
||||
option, value, form_field.get_value()
|
||||
))
|
||||
|
||||
# --------------------------------------------------
|
||||
# Changes in the GUI should be read in when
|
||||
# running any process. Changing something here.
|
||||
# --------------------------------------------------
|
||||
|
||||
form_field = gerber_obj.form_fields['isotooldia']
|
||||
value = form_field.get_value()
|
||||
form_field.set_value(value * 1.1) # Increase by 10%
|
||||
print(("'isotooldia' == {}".format(value)))
|
||||
|
||||
# --------------------------------------------------
|
||||
# Create isolation routing using default values
|
||||
# and by clicking on the button.
|
||||
# --------------------------------------------------
|
||||
# Get the object's GUI and click on "Generate Geometry" under
|
||||
# "Isolation Routing"
|
||||
assert isinstance(gerber_obj, FlatCAMGerber) # Just for the IDE
|
||||
# Changed: UI has been build already
|
||||
#gerber_obj.build_ui() # Open the object's UI.
|
||||
ui = gerber_obj.ui
|
||||
assert isinstance(ui, GerberObjectUI)
|
||||
ui.generate_iso_button.click() # Click
|
||||
|
||||
# ---------------------------------------------
|
||||
# Check that GUI has been read in.
|
||||
# ---------------------------------------------
|
||||
value = gerber_obj.options['isotooldia']
|
||||
form_value = form_field.get_value()
|
||||
self.assertEqual(value, form_value,
|
||||
"Form value for '{}' == {} was not read into options"
|
||||
"which has {}".format('isotooldia', form_value, value))
|
||||
print(("'isotooldia' == {}".format(value)))
|
||||
|
||||
# ---------------------------------------------
|
||||
# Check that only 1 object has been created.
|
||||
# ---------------------------------------------
|
||||
names = self.fc.collection.get_names()
|
||||
self.assertEqual(len(names), 2,
|
||||
"Expected 2 objects, found %d" % len(names))
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Make sure the Geometry Object has the correct name
|
||||
# -------------------------------------------------------
|
||||
geo_name = gerber_name + "_iso"
|
||||
self.assertTrue(geo_name in names,
|
||||
"Object named %s not found." % geo_name)
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Get the object make sure it's a geometry object
|
||||
# -------------------------------------------------------
|
||||
geo_obj = self.fc.collection.get_by_name(geo_name)
|
||||
self.assertTrue(isinstance(geo_obj, FlatCAMGeometry),
|
||||
"Expected a FlatCAMGeometry, got %s" % type(geo_obj))
|
||||
|
||||
# ------------------------------------
|
||||
# Open the UI, make CNCObject
|
||||
# ------------------------------------
|
||||
geo_obj.build_ui()
|
||||
ui = geo_obj.ui
|
||||
assert isinstance(ui, GeometryObjectUI) # Just for the IDE
|
||||
ui.generate_cnc_button.click() # Click
|
||||
|
||||
# Work is done in a separate thread and results are
|
||||
# passed via events to the main event loop which is
|
||||
# not running. Run only for pending events.
|
||||
#
|
||||
# I'm not sure why, but running it only once does
|
||||
# not catch the new object. Might be a timing issue.
|
||||
# http://pyqt.sourceforge.net/Docs/PyQt4/qeventloop.html#details
|
||||
for _ in range(2):
|
||||
sleep(0.1)
|
||||
self.app.processEvents()
|
||||
|
||||
# ---------------------------------------------
|
||||
# Check that only 1 object has been created.
|
||||
# ---------------------------------------------
|
||||
names = self.fc.collection.get_names()
|
||||
self.assertEqual(len(names), 3,
|
||||
"Expected 3 objects, found %d" % len(names))
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Make sure the CNC Job Object has the correct name
|
||||
# -------------------------------------------------------
|
||||
cnc_name = geo_name + "_cnc"
|
||||
self.assertTrue(cnc_name in names,
|
||||
"Object named %s not found." % geo_name)
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Get the object make sure it's a CNC Job object
|
||||
# -------------------------------------------------------
|
||||
cnc_obj = self.fc.collection.get_by_name(cnc_name)
|
||||
self.assertTrue(isinstance(cnc_obj, FlatCAMCNCjob),
|
||||
"Expected a FlatCAMCNCJob, got %s" % type(geo_obj))
|
||||
|
||||
# -----------------------------------------
|
||||
# Export G-Code, check output
|
||||
# -----------------------------------------
|
||||
assert isinstance(cnc_obj, FlatCAMCNCjob)
|
||||
output_filename = ""
|
||||
# get system temporary file(try create it and delete also)
|
||||
with tempfile.NamedTemporaryFile(prefix='unittest.',
|
||||
suffix="." + cnc_name + '.gcode',
|
||||
delete=True) as tmp_file:
|
||||
output_filename = tmp_file.name
|
||||
cnc_obj.export_gcode(output_filename)
|
||||
self.assertTrue(os.path.isfile(output_filename))
|
||||
os.remove(output_filename)
|
||||
|
||||
print(names)
|
||||
@@ -1,213 +0,0 @@
|
||||
import unittest
|
||||
|
||||
from shapely.geometry import LineString, Polygon
|
||||
from shapely.ops import unary_union
|
||||
from matplotlib.pyplot import plot, subplot, show, cla, clf, xlim, ylim, title
|
||||
from matplotlib.axes import *
|
||||
from camlib import *
|
||||
from copy import deepcopy
|
||||
|
||||
|
||||
def mkstorage(paths):
|
||||
def get_pts(o):
|
||||
return [o.coords[0], o.coords[-1]]
|
||||
storage = FlatCAMRTreeStorage()
|
||||
storage.get_points = get_pts
|
||||
for p in paths:
|
||||
storage.insert(p)
|
||||
return storage
|
||||
|
||||
|
||||
def plotg2(geo, solid_poly=False, color="black", linestyle='solid'):
|
||||
|
||||
try:
|
||||
for sub_geo in geo:
|
||||
plotg2(sub_geo, solid_poly=solid_poly, color=color, linestyle=linestyle)
|
||||
except TypeError:
|
||||
if type(geo) == Polygon:
|
||||
if solid_poly:
|
||||
patch = PolygonPatch(geo,
|
||||
#facecolor="#BBF268",
|
||||
facecolor=color,
|
||||
edgecolor="#006E20",
|
||||
alpha=0.5,
|
||||
zorder=2)
|
||||
ax = subplot(111)
|
||||
ax.add_patch(patch)
|
||||
else:
|
||||
x, y = geo.exterior.coords.xy
|
||||
plot(x, y, color=color, linestyle=linestyle)
|
||||
for ints in geo.interiors:
|
||||
x, y = ints.coords.xy
|
||||
plot(x, y, color=color, linestyle=linestyle)
|
||||
|
||||
if type(geo) == LineString or type(geo) == LinearRing:
|
||||
x, y = geo.coords.xy
|
||||
plot(x, y, color=color, linestyle=linestyle)
|
||||
|
||||
if type(geo) == Point:
|
||||
x, y = geo.coords.xy
|
||||
plot(x, y, 'o')
|
||||
|
||||
|
||||
class PaintTestCase(unittest.TestCase):
|
||||
# def __init__(self):
|
||||
# super(PaintTestCase, self).__init__()
|
||||
# self.boundary = None
|
||||
# self.descr = None
|
||||
|
||||
def plot_summary_A(self, paths, tooldia, result, msg):
|
||||
plotg2(self.boundary, solid_poly=True, color="green")
|
||||
plotg2(paths, color="red")
|
||||
plotg2([r.buffer(tooldia / 2) for r in result], solid_poly=True, color="blue")
|
||||
plotg2(result, color="black", linestyle='dashed')
|
||||
title(msg)
|
||||
xlim(0, 5)
|
||||
ylim(0, 5)
|
||||
show()
|
||||
|
||||
|
||||
class PaintConnectTest(PaintTestCase):
|
||||
"""
|
||||
Simple rectangular boundary and paths inside.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.boundary = Polygon([[0, 0], [0, 5], [5, 5], [5, 0]])
|
||||
|
||||
def test_jump(self):
|
||||
print("Test: WALK Expected")
|
||||
paths = [
|
||||
LineString([[0.5, 2], [2, 4.5]]),
|
||||
LineString([[2, 0.5], [4.5, 2]])
|
||||
]
|
||||
for p in paths:
|
||||
print(p)
|
||||
|
||||
tooldia = 1.0
|
||||
|
||||
print("--")
|
||||
result = Geometry.paint_connect(mkstorage(deepcopy(paths)), self.boundary, tooldia)
|
||||
|
||||
result = list(result.get_objects())
|
||||
for r in result:
|
||||
print(r)
|
||||
|
||||
self.assertEqual(len(result), 1)
|
||||
|
||||
# self.plot_summary_A(paths, tooldia, result, "WALK expected.")
|
||||
|
||||
def test_no_jump1(self):
|
||||
print("Test: FLY Expected")
|
||||
paths = [
|
||||
LineString([[0, 2], [2, 5]]),
|
||||
LineString([[2, 0], [5, 2]])
|
||||
]
|
||||
for p in paths:
|
||||
print(p)
|
||||
|
||||
tooldia = 1.0
|
||||
|
||||
print("--")
|
||||
result = Geometry.paint_connect(mkstorage(deepcopy(paths)), self.boundary, tooldia)
|
||||
|
||||
result = list(result.get_objects())
|
||||
for r in result:
|
||||
print(r)
|
||||
|
||||
self.assertEqual(len(result), len(paths))
|
||||
|
||||
# self.plot_summary_A(paths, tooldia, result, "FLY Expected")
|
||||
|
||||
def test_no_jump2(self):
|
||||
print("Test: FLY Expected")
|
||||
paths = [
|
||||
LineString([[0.5, 2], [2, 4.5]]),
|
||||
LineString([[2, 0.5], [4.5, 2]])
|
||||
]
|
||||
for p in paths:
|
||||
print(p)
|
||||
|
||||
tooldia = 1.1
|
||||
|
||||
print("--")
|
||||
result = Geometry.paint_connect(mkstorage(deepcopy(paths)), self.boundary, tooldia)
|
||||
|
||||
result = list(result.get_objects())
|
||||
for r in result:
|
||||
print(r)
|
||||
|
||||
self.assertEqual(len(result), len(paths))
|
||||
|
||||
# self.plot_summary_A(paths, tooldia, result, "FLY Expected")
|
||||
|
||||
|
||||
class PaintConnectTest2(PaintTestCase):
|
||||
"""
|
||||
Boundary with an internal cutout.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.boundary = Polygon([[0, 0], [0, 5], [5, 5], [5, 0]])
|
||||
self.boundary = self.boundary.difference(
|
||||
Polygon([[2, 1], [3, 1], [3, 4], [2, 4]])
|
||||
)
|
||||
|
||||
def test_no_jump3(self):
|
||||
print("TEST: No jump expected")
|
||||
paths = [
|
||||
LineString([[0.5, 1], [1.5, 3]]),
|
||||
LineString([[4, 1], [4, 4]])
|
||||
]
|
||||
for p in paths:
|
||||
print(p)
|
||||
|
||||
tooldia = 1.0
|
||||
|
||||
print("--")
|
||||
result = Geometry.paint_connect(mkstorage(deepcopy(paths)), self.boundary, tooldia)
|
||||
|
||||
result = list(result.get_objects())
|
||||
for r in result:
|
||||
print(r)
|
||||
|
||||
self.assertEqual(len(result), len(paths))
|
||||
|
||||
# self.plot_summary_A(paths, tooldia, result, "FLY Expected")
|
||||
|
||||
|
||||
class PaintConnectTest3(PaintTestCase):
|
||||
"""
|
||||
Tests with linerings among elements.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.boundary = Polygon([[0, 0], [0, 5], [5, 5], [5, 0]])
|
||||
print("TEST w/ LinearRings")
|
||||
|
||||
def test_jump2(self):
|
||||
print("Test: WALK Expected")
|
||||
paths = [
|
||||
LineString([[0.5, 2], [2, 4.5]]),
|
||||
LineString([[2, 0.5], [4.5, 2]]),
|
||||
self.boundary.buffer(-0.5).exterior
|
||||
]
|
||||
for p in paths:
|
||||
print(p)
|
||||
|
||||
tooldia = 1.0
|
||||
|
||||
print("--")
|
||||
result = Geometry.paint_connect(mkstorage(deepcopy(paths)), self.boundary, tooldia)
|
||||
|
||||
result = list(result.get_objects())
|
||||
for r in result:
|
||||
print(r)
|
||||
|
||||
self.assertEqual(len(result), 1)
|
||||
|
||||
# self.plot_summary_A(paths, tooldia, result, "WALK Expected")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,89 +0,0 @@
|
||||
import unittest
|
||||
|
||||
from shapely.geometry import LineString, Polygon
|
||||
from shapely.ops import unary_union
|
||||
from matplotlib.pyplot import plot, subplot, show, cla, clf, xlim, ylim, title
|
||||
from camlib import *
|
||||
from random import random
|
||||
|
||||
|
||||
def mkstorage(paths):
|
||||
def get_pts(o):
|
||||
return [o.coords[0], o.coords[-1]]
|
||||
storage = FlatCAMRTreeStorage()
|
||||
storage.get_points = get_pts
|
||||
for p in paths:
|
||||
storage.insert(p)
|
||||
return storage
|
||||
|
||||
|
||||
class PathConnectTest1(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
print("PathConnectTest1.setUp()")
|
||||
pass
|
||||
|
||||
def test_simple_connect(self):
|
||||
paths = [
|
||||
LineString([[0, 0], [1, 1]]),
|
||||
LineString([[1, 1], [2, 1]])
|
||||
]
|
||||
|
||||
result = Geometry.path_connect(mkstorage(paths))
|
||||
|
||||
result = list(result.get_objects())
|
||||
self.assertEqual(len(result), 1)
|
||||
self.assertTrue(result[0].equals(LineString([[0, 0], [1, 1], [2, 1]])))
|
||||
|
||||
def test_interfere_connect(self):
|
||||
paths = [
|
||||
LineString([[0, 0], [1, 1]]),
|
||||
LineString([[1, 1], [2, 1]]),
|
||||
LineString([[-0.5, 0.5], [0.5, 0]])
|
||||
]
|
||||
|
||||
result = Geometry.path_connect(mkstorage(paths))
|
||||
|
||||
result = list(result.get_objects())
|
||||
self.assertEqual(len(result), 2)
|
||||
matches = [p for p in result if p.equals(LineString([[0, 0], [1, 1], [2, 1]]))]
|
||||
self.assertEqual(len(matches), 1)
|
||||
|
||||
def test_simple_connect_offset1(self):
|
||||
for i in range(20):
|
||||
offset_x = random()
|
||||
offset_y = random()
|
||||
|
||||
paths = [
|
||||
LineString([[0 + offset_x, 0 + offset_y], [1 + offset_x, 1 + offset_y]]),
|
||||
LineString([[1 + offset_x, 1 + offset_y], [2 + offset_x, 1 + offset_y]])
|
||||
]
|
||||
|
||||
result = Geometry.path_connect(mkstorage(paths))
|
||||
|
||||
result = list(result.get_objects())
|
||||
self.assertEqual(len(result), 1)
|
||||
self.assertTrue(result[0].equals(LineString([[0 + offset_x, 0 + offset_y],
|
||||
[1 + offset_x, 1 + offset_y],
|
||||
[2 + offset_x, 1 + offset_y]])))
|
||||
|
||||
def test_ring_interfere_connect(self):
|
||||
print()
|
||||
print("TEST STARTING ...")
|
||||
|
||||
paths = [
|
||||
LineString([[0, 0], [1, 1]]),
|
||||
LineString([[1, 1], [2, 1]]),
|
||||
LinearRing([[1, 1], [2, 2], [1, 3], [0, 2]])
|
||||
]
|
||||
|
||||
result = Geometry.path_connect(mkstorage(paths))
|
||||
|
||||
result = list(result.get_objects())
|
||||
self.assertEqual(len(result), 2)
|
||||
matches = [p for p in result if p.equals(LineString([[0, 0], [1, 1], [2, 1]]))]
|
||||
self.assertEqual(len(matches), 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,220 +0,0 @@
|
||||
import sys
|
||||
import unittest
|
||||
from PyQt5 import QtGui, QtWidgets
|
||||
from FlatCAMApp import App
|
||||
from FlatCAMObj import FlatCAMGeometry, FlatCAMCNCjob
|
||||
from flatcamGUI.ObjectUI import GerberObjectUI, GeometryObjectUI
|
||||
from time import sleep
|
||||
import os
|
||||
import tempfile
|
||||
from shapely.geometry import LineString, LinearRing, Polygon, MultiPolygon
|
||||
|
||||
|
||||
class PolyPaintTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.app = QtWidgets.QApplication(sys.argv)
|
||||
|
||||
# Create App, keep app defaults (do not load
|
||||
# user-defined defaults).
|
||||
self.fc = App(user_defaults=False)
|
||||
|
||||
def tearDown(self):
|
||||
|
||||
for _ in range(2):
|
||||
self.app.processEvents()
|
||||
|
||||
# NOTE: These are creating problems...
|
||||
# del self.fc
|
||||
# del self.app
|
||||
|
||||
def test_poly_paint_svg_all(self):
|
||||
|
||||
print("*********************************")
|
||||
print("* svg_all *")
|
||||
print("*********************************")
|
||||
|
||||
# Clear workspace
|
||||
self.fc.on_file_new()
|
||||
for _ in range(2):
|
||||
self.app.processEvents()
|
||||
|
||||
# Open SVG with polygons
|
||||
self.fc.import_svg('tests/svg/drawing.svg')
|
||||
|
||||
name = self.fc.collection.get_names()[0]
|
||||
|
||||
self.fc.collection.set_active(name)
|
||||
|
||||
geo_obj = self.fc.collection.get_by_name(name)
|
||||
|
||||
# Paint all polygons
|
||||
geo_obj.paint_poly_all(5, 0.2, 1)
|
||||
sleep(5) # Todo: Do not base it on fixed time.
|
||||
for _ in range(2):
|
||||
self.app.processEvents()
|
||||
|
||||
# New object should be available
|
||||
names = self.fc.collection.get_names()
|
||||
|
||||
self.assertEqual(len(names), 2)
|
||||
|
||||
# Verify new geometry makes sense
|
||||
painted = self.fc.collection.get_by_name(names[-1])
|
||||
for geo in painted.solid_geometry:
|
||||
# Correct Type
|
||||
self.assertTrue(isinstance(geo, LineString))
|
||||
# Lots of points (Should be 1000s)
|
||||
self.assertGreater(len(geo.coords), 2)
|
||||
|
||||
def test_poly_paint_svg_click(self):
|
||||
|
||||
print("*********************************")
|
||||
print("* svg_click *")
|
||||
print("*********************************")
|
||||
|
||||
# Clear workspace
|
||||
self.fc.on_file_new()
|
||||
for _ in range(2):
|
||||
self.app.processEvents()
|
||||
|
||||
# Open SVG with polygons
|
||||
self.fc.import_svg('tests/svg/drawing.svg')
|
||||
|
||||
name = self.fc.collection.get_names()[0]
|
||||
|
||||
self.fc.collection.set_active(name)
|
||||
|
||||
geo_obj = self.fc.collection.get_by_name(name)
|
||||
|
||||
# Paint all polygons
|
||||
geo_obj.paint_poly_single_click([300, 700], 5, 0.2, 1)
|
||||
sleep(5)
|
||||
for _ in range(2):
|
||||
self.app.processEvents()
|
||||
|
||||
# New object should be available
|
||||
names = self.fc.collection.get_names()
|
||||
|
||||
sleep(1)
|
||||
self.assertEqual(len(names), 2)
|
||||
|
||||
# Verify new geometry makes sense
|
||||
painted = self.fc.collection.get_by_name(names[-1])
|
||||
for geo in painted.solid_geometry:
|
||||
# Correct Type
|
||||
self.assertTrue(isinstance(geo, LineString))
|
||||
# Lots of points (Should be 1000s)
|
||||
self.assertGreater(len(geo.coords), 2)
|
||||
|
||||
def test_poly_paint_noncopper_all(self):
|
||||
|
||||
print("*********************************")
|
||||
print("* noncopper_all *")
|
||||
print("*********************************")
|
||||
|
||||
# Clear workspace
|
||||
self.fc.on_file_new()
|
||||
for _ in range(2):
|
||||
self.app.processEvents()
|
||||
|
||||
self.fc.open_gerber('tests/gerber_files/simple1.gbr')
|
||||
sleep(1)
|
||||
for _ in range(2):
|
||||
self.app.processEvents()
|
||||
|
||||
name = self.fc.collection.get_names()[0]
|
||||
|
||||
gerber_obj = self.fc.collection.get_by_name(name)
|
||||
|
||||
self.fc.collection.set_active(name)
|
||||
|
||||
gerber_obj.on_generatenoncopper_button_click()
|
||||
sleep(1)
|
||||
for _ in range(2):
|
||||
self.app.processEvents()
|
||||
|
||||
# New object should be available
|
||||
names = self.fc.collection.get_names()
|
||||
|
||||
sleep(1)
|
||||
self.assertEqual(len(names), 2)
|
||||
|
||||
geoname = "simple1.gbr_noncopper"
|
||||
geo_obj = self.fc.collection.get_by_name(geoname)
|
||||
self.fc.collection.set_active(geoname)
|
||||
|
||||
geo_obj.paint_poly_all(0.02, 0.2, 0)
|
||||
sleep(5)
|
||||
for _ in range(2):
|
||||
self.app.processEvents()
|
||||
|
||||
# New object should be available
|
||||
names = self.fc.collection.get_names()
|
||||
|
||||
sleep(1)
|
||||
self.assertEqual(len(names), 3)
|
||||
|
||||
# Verify new geometry makes sense
|
||||
painted = self.fc.collection.get_by_name(names[-1])
|
||||
for geo in painted.solid_geometry:
|
||||
# Correct Type
|
||||
self.assertTrue(isinstance(geo, LineString))
|
||||
# Lots of points (Should be 1000s)
|
||||
self.assertGreater(len(geo.coords), 2)
|
||||
|
||||
def test_poly_paint_noncopper_click(self):
|
||||
|
||||
print("*********************************")
|
||||
print("* noncopper_click *")
|
||||
print("*********************************")
|
||||
|
||||
# Clear workspace
|
||||
self.fc.on_file_new()
|
||||
for _ in range(2):
|
||||
self.app.processEvents()
|
||||
|
||||
self.fc.open_gerber('tests/gerber_files/simple1.gbr')
|
||||
sleep(1)
|
||||
for _ in range(2):
|
||||
self.app.processEvents()
|
||||
|
||||
name = self.fc.collection.get_names()[0]
|
||||
|
||||
gerber_obj = self.fc.collection.get_by_name(name)
|
||||
|
||||
self.fc.collection.set_active(name)
|
||||
|
||||
gerber_obj.on_generatenoncopper_button_click()
|
||||
sleep(1)
|
||||
for _ in range(2):
|
||||
self.app.processEvents()
|
||||
|
||||
# New object should be available
|
||||
names = self.fc.collection.get_names()
|
||||
|
||||
sleep(1)
|
||||
self.assertEqual(len(names), 2)
|
||||
|
||||
geoname = "simple1.gbr_noncopper"
|
||||
geo_obj = self.fc.collection.get_by_name(geoname)
|
||||
self.fc.collection.set_active(geoname)
|
||||
|
||||
geo_obj.paint_poly_single_click([2.7, 1.0], 0.02, 0.2, 0)
|
||||
sleep(5)
|
||||
for _ in range(2):
|
||||
self.app.processEvents()
|
||||
|
||||
# New object should be available
|
||||
names = self.fc.collection.get_names()
|
||||
|
||||
sleep(1)
|
||||
self.assertEqual(len(names), 3)
|
||||
|
||||
# Verify new geometry makes sense
|
||||
painted = self.fc.collection.get_by_name(names[-1])
|
||||
for geo in painted.solid_geometry:
|
||||
# Correct Type
|
||||
self.assertTrue(isinstance(geo, LineString))
|
||||
# Lots of points (Should be 1000s)
|
||||
self.assertGreater(len(geo.coords), 2)
|
||||
@@ -1,127 +0,0 @@
|
||||
import sys
|
||||
import unittest
|
||||
from PyQt5 import QtWidgets
|
||||
from FlatCAMApp import App
|
||||
from FlatCAMObj import FlatCAMGeometry, FlatCAMCNCjob
|
||||
from flatcamGUI.ObjectUI import GerberObjectUI, GeometryObjectUI
|
||||
from time import sleep
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
|
||||
class SVGFlowTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.app = QtWidgets.QApplication(sys.argv)
|
||||
|
||||
# Create App, keep app defaults (do not load
|
||||
# user-defined defaults).
|
||||
self.fc = App(user_defaults=False)
|
||||
|
||||
self.filename = 'drawing.svg'
|
||||
|
||||
def tearDown(self):
|
||||
del self.fc
|
||||
del self.app
|
||||
|
||||
def test_flow(self):
|
||||
|
||||
self.fc.import_svg('tests/svg/' + self.filename)
|
||||
|
||||
names = self.fc.collection.get_names()
|
||||
print(names)
|
||||
|
||||
# --------------------------------------
|
||||
# Total of 1 objects.
|
||||
# --------------------------------------
|
||||
self.assertEqual(len(names), 1, "Expected 1 object, found %d" % len(names))
|
||||
|
||||
# --------------------------------------
|
||||
# Object's name matches the file name.
|
||||
# --------------------------------------
|
||||
self.assertEqual(names[0], self.filename, "Expected name == %s, got %s" % (self.filename, names[0]))
|
||||
|
||||
# ---------------------------------------
|
||||
# Get object by that name, make sure it's a FlatCAMGerber.
|
||||
# ---------------------------------------
|
||||
geo_name = names[0]
|
||||
geo_obj = self.fc.collection.get_by_name(geo_name)
|
||||
self.assertTrue(isinstance(geo_obj, FlatCAMGeometry),
|
||||
"Expected FlatCAMGeometry, instead, %s is %s" %
|
||||
(geo_name, type(geo_obj)))
|
||||
|
||||
# ----------------------------------------
|
||||
# Object's GUI matches Object's options
|
||||
# ----------------------------------------
|
||||
# TODO: Open GUI with double-click on object.
|
||||
# Opens the Object's GUI, populates it.
|
||||
geo_obj.build_ui()
|
||||
for option, value in list(geo_obj.options.items()):
|
||||
try:
|
||||
form_field = geo_obj.form_fields[option]
|
||||
except KeyError:
|
||||
print(("**********************************************************\n"
|
||||
"* WARNING: Option '{}' has no form field\n"
|
||||
"**********************************************************"
|
||||
"".format(option)))
|
||||
continue
|
||||
self.assertEqual(value, form_field.get_value(),
|
||||
"Option '{}' == {} but form has {}".format(
|
||||
option, value, form_field.get_value()
|
||||
))
|
||||
|
||||
# ------------------------------------
|
||||
# Open the UI, make CNCObject
|
||||
# ------------------------------------
|
||||
geo_obj.build_ui()
|
||||
ui = geo_obj.ui
|
||||
assert isinstance(ui, GeometryObjectUI) # Just for the IDE
|
||||
ui.generate_cnc_button.click() # Click
|
||||
|
||||
# Work is done in a separate thread and results are
|
||||
# passed via events to the main event loop which is
|
||||
# not running. Run only for pending events.
|
||||
#
|
||||
# I'm not sure why, but running it only once does
|
||||
# not catch the new object. Might be a timing issue.
|
||||
# http://pyqt.sourceforge.net/Docs/PyQt4/qeventloop.html#details
|
||||
for _ in range(2):
|
||||
sleep(0.1)
|
||||
self.app.processEvents()
|
||||
|
||||
# ---------------------------------------------
|
||||
# Check that only 1 object has been created.
|
||||
# ---------------------------------------------
|
||||
names = self.fc.collection.get_names()
|
||||
self.assertEqual(len(names), 2,
|
||||
"Expected 2 objects, found %d" % len(names))
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Make sure the CNC Job Object has the correct name
|
||||
# -------------------------------------------------------
|
||||
cnc_name = geo_name + "_cnc"
|
||||
self.assertTrue(cnc_name in names,
|
||||
"Object named %s not found." % geo_name)
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Get the object make sure it's a CNC Job object
|
||||
# -------------------------------------------------------
|
||||
cnc_obj = self.fc.collection.get_by_name(cnc_name)
|
||||
self.assertTrue(isinstance(cnc_obj, FlatCAMCNCjob),
|
||||
"Expected a FlatCAMCNCJob, got %s" % type(geo_obj))
|
||||
|
||||
# -----------------------------------------
|
||||
# Export G-Code, check output
|
||||
# -----------------------------------------
|
||||
assert isinstance(cnc_obj, FlatCAMCNCjob)
|
||||
output_filename = ""
|
||||
# get system temporary file(try create it and delete also)
|
||||
with tempfile.NamedTemporaryFile(prefix='unittest.',
|
||||
suffix="." + cnc_name + '.gcode',
|
||||
delete=True) as tmp_file:
|
||||
output_filename = tmp_file.name
|
||||
cnc_obj.export_gcode(output_filename)
|
||||
self.assertTrue(os.path.isfile(output_filename))
|
||||
os.remove(output_filename)
|
||||
|
||||
print(names)
|
||||
@@ -1,18 +0,0 @@
|
||||
import pkgutil
|
||||
import sys
|
||||
|
||||
# allowed command tests (please append them alphabetically ordered)
|
||||
from .test_TclCommandAddPolygon import *
|
||||
from .test_TclCommandAddPolyline import *
|
||||
from .test_TclCommandCncjob import *
|
||||
from .test_TclCommandDrillcncjob import *
|
||||
from .test_TclCommandExportGcode import *
|
||||
from .test_TclCommandExteriors import *
|
||||
from .test_TclCommandImportSvg import *
|
||||
from .test_TclCommandInteriors import *
|
||||
from .test_TclCommandIsolate import *
|
||||
from .test_TclCommandNew import *
|
||||
from .test_TclCommandNewGeometry import *
|
||||
from .test_TclCommandOpenExcellon import *
|
||||
from .test_TclCommandOpenGerber import *
|
||||
from .test_TclCommandPaintPolygon import *
|
||||
@@ -1,18 +0,0 @@
|
||||
from FlatCAMObj import FlatCAMGeometry
|
||||
|
||||
|
||||
def test_add_polygon(self):
|
||||
"""
|
||||
Test add polygon into geometry
|
||||
:param self:
|
||||
:return:
|
||||
"""
|
||||
|
||||
self.fc.exec_command_test('new_geometry "%s"' % self.geometry_name)
|
||||
geometry_obj = self.fc.collection.get_by_name(self.geometry_name)
|
||||
self.assertTrue(isinstance(geometry_obj, FlatCAMGeometry), "Expected FlatCAMGeometry, instead, %s is %s"
|
||||
% (self.geometry_name, type(geometry_obj)))
|
||||
|
||||
points = '0 0 20 0 10 10 0 10'
|
||||
|
||||
self.fc.exec_command_test('add_polygon "%s" %s' % (self.geometry_name, points))
|
||||
@@ -1,18 +0,0 @@
|
||||
from FlatCAMObj import FlatCAMGeometry
|
||||
|
||||
|
||||
def test_add_polyline(self):
|
||||
"""
|
||||
Test add polyline into geometry
|
||||
:param self:
|
||||
:return:
|
||||
"""
|
||||
|
||||
self.fc.exec_command_test('new_geometry "%s"' % self.geometry_name)
|
||||
geometry_obj = self.fc.collection.get_by_name(self.geometry_name)
|
||||
self.assertTrue(isinstance(geometry_obj, FlatCAMGeometry), "Expected FlatCAMGeometry, instead, %s is %s"
|
||||
% (self.geometry_name, type(geometry_obj)))
|
||||
|
||||
points = '0 0 20 0 10 10 0 10 33 33'
|
||||
|
||||
self.fc.exec_command_test('add_polyline "%s" %s' % (self.geometry_name, points))
|
||||
@@ -1,17 +0,0 @@
|
||||
from FlatCAMObj import FlatCAMGerber, FlatCAMGeometry, FlatCAMObj
|
||||
from .test_TclCommandIsolate import *
|
||||
|
||||
def test_cncjob(self):
|
||||
"""
|
||||
Test cncjob
|
||||
:param self:
|
||||
:return:
|
||||
"""
|
||||
|
||||
# reuse isolate tests
|
||||
test_isolate(self)
|
||||
|
||||
self.fc.exec_command_test('cncjob %s_iso -tooldia 0.5 -z_cut 0.05 -z_move 3 -feedrate 300' % self.gerber_top_name)
|
||||
cam_top_obj = self.fc.collection.get_by_name(self.gerber_top_name + '_iso_cnc')
|
||||
self.assertTrue(isinstance(cam_top_obj, FlatCAMObj), "Expected FlatCAMObj, instead, %s is %s"
|
||||
% (self.gerber_top_name + '_iso_cnc', type(cam_top_obj)))
|
||||
@@ -1,18 +0,0 @@
|
||||
from FlatCAMObj import FlatCAMObj
|
||||
from .test_TclCommandOpenExcellon import *
|
||||
|
||||
|
||||
def test_drillcncjob(self):
|
||||
"""
|
||||
Test cncjob
|
||||
:param self:
|
||||
:return:
|
||||
"""
|
||||
# reuse open excellontests
|
||||
test_open_excellon(self)
|
||||
|
||||
self.fc.exec_command_test('drillcncjob %s -tools all -drillz 0.5 -travelz 3 -feedrate 300'
|
||||
% self.excellon_name)
|
||||
cam_top_obj = self.fc.collection.get_by_name(self.excellon_name + '_cnc')
|
||||
self.assertTrue(isinstance(cam_top_obj, FlatCAMObj), "Expected FlatCAMObj, instead, %s is %s"
|
||||
% (self.excellon_name + '_cnc', type(cam_top_obj)))
|
||||
@@ -1,33 +0,0 @@
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from .test_TclCommandCncjob import *
|
||||
from .test_TclCommandDrillcncjob import *
|
||||
|
||||
|
||||
def test_export_gcodecncjob(self):
|
||||
"""
|
||||
Test cncjob
|
||||
:param self:
|
||||
:return:
|
||||
"""
|
||||
|
||||
# reuse tests
|
||||
test_cncjob(self)
|
||||
test_drillcncjob(self)
|
||||
|
||||
with tempfile.NamedTemporaryFile(prefix='unittest.', suffix="." + self.excellon_name + '.gcode', delete=True)\
|
||||
as tmp_file:
|
||||
output_filename = tmp_file.name
|
||||
self.fc.exec_command_test('write_gcode "%s" "%s"' % (self.excellon_name + '_cnc', output_filename))
|
||||
self.assertTrue(os.path.isfile(output_filename))
|
||||
os.remove(output_filename)
|
||||
|
||||
with tempfile.NamedTemporaryFile(prefix='unittest.', suffix="." + self.gerber_top_name + '.gcode', delete=True)\
|
||||
as tmp_file:
|
||||
output_filename = tmp_file.name
|
||||
self.fc.exec_command_test('write_gcode "%s" "%s"' % (self.gerber_top_name + '_iso_cnc', output_filename))
|
||||
self.assertTrue(os.path.isfile(output_filename))
|
||||
os.remove(output_filename)
|
||||
|
||||
# TODO check what is inside files , it should be same every time
|
||||
@@ -1,24 +0,0 @@
|
||||
from FlatCAMObj import FlatCAMGerber, FlatCAMGeometry
|
||||
|
||||
|
||||
def test_exteriors(self):
|
||||
"""
|
||||
Test exteriors
|
||||
:param self:
|
||||
:return:
|
||||
"""
|
||||
|
||||
self.fc.exec_command_test('open_gerber %s/%s -outname %s'
|
||||
% (self.gerber_files, self.cutout_filename, self.gerber_cutout_name))
|
||||
gerber_cutout_obj = self.fc.collection.get_by_name(self.gerber_cutout_name)
|
||||
self.assertTrue(isinstance(gerber_cutout_obj, FlatCAMGerber), "Expected FlatCAMGerber, instead, %s is %s"
|
||||
% (self.gerber_cutout_name, type(gerber_cutout_obj)))
|
||||
|
||||
# exteriors interiors and delete isolated traces
|
||||
self.fc.exec_command_test('isolate %s -dia %f' % (self.gerber_cutout_name, self.engraver_diameter))
|
||||
self.fc.exec_command_test('exteriors %s -outname %s'
|
||||
% (self.gerber_cutout_name + '_iso', self.gerber_cutout_name + '_iso_exterior'))
|
||||
self.fc.exec_command_test('delete %s' % (self.gerber_cutout_name + '_iso'))
|
||||
obj = self.fc.collection.get_by_name(self.gerber_cutout_name + '_iso_exterior')
|
||||
self.assertTrue(isinstance(obj, FlatCAMGeometry), "Expected FlatCAMGeometry, instead, %s is %s"
|
||||
% (self.gerber_cutout_name + '_iso_exterior', type(obj)))
|
||||
@@ -1,60 +0,0 @@
|
||||
from os import listdir
|
||||
|
||||
from FlatCAMObj import FlatCAMGerber, FlatCAMGeometry
|
||||
|
||||
|
||||
def test_import_svg(self):
|
||||
"""
|
||||
Test all SVG files inside svg directory.
|
||||
Problematic SVG files shold be put there as test reference.
|
||||
:param self:
|
||||
:return:
|
||||
"""
|
||||
|
||||
file_list = listdir(self.svg_files)
|
||||
|
||||
for svg_file in file_list:
|
||||
|
||||
# import without outname
|
||||
self.fc.exec_command_test('import_svg "%s/%s"' % (self.svg_files, svg_file))
|
||||
|
||||
obj = self.fc.collection.get_by_name(svg_file)
|
||||
self.assertTrue(isinstance(obj, FlatCAMGeometry), "Expected FlatCAMGeometry, instead, %s is %s"
|
||||
% (svg_file, type(obj)))
|
||||
|
||||
# import with outname
|
||||
outname = '%s-%s' % (self.geometry_name, svg_file)
|
||||
self.fc.exec_command_test('import_svg "%s/%s" -outname "%s"' % (self.svg_files, svg_file, outname))
|
||||
|
||||
obj = self.fc.collection.get_by_name(outname)
|
||||
self.assertTrue(isinstance(obj, FlatCAMGeometry), "Expected FlatCAMGeometry, instead, %s is %s"
|
||||
% (outname, type(obj)))
|
||||
|
||||
names = self.fc.collection.get_names()
|
||||
self.assertEqual(len(names), len(file_list)*2,
|
||||
"Expected %d objects, found %d" % (len(file_list)*2, len(file_list)))
|
||||
|
||||
|
||||
def test_import_svg_as_geometry(self):
|
||||
|
||||
self.fc.exec_command_test('import_svg "%s/%s" -type geometry -outname "%s"'
|
||||
% (self.svg_files, self.svg_filename, self.geometry_name))
|
||||
|
||||
obj = self.fc.collection.get_by_name(self.geometry_name)
|
||||
self.assertTrue(isinstance(obj, FlatCAMGeometry) and not isinstance(obj, FlatCAMGerber),
|
||||
"Expected FlatCAMGeometry, instead, %s is %s" % (self.geometry_name, type(obj)))
|
||||
|
||||
|
||||
def test_import_svg_as_gerber(self):
|
||||
|
||||
self.fc.exec_command_test('import_svg "%s/%s" -type gerber -outname "%s"'
|
||||
% (self.svg_files, self.svg_filename, self.gerber_name))
|
||||
|
||||
obj = self.fc.collection.get_by_name(self.gerber_name)
|
||||
self.assertTrue(isinstance(obj, FlatCAMGerber),
|
||||
"Expected FlatCAMGerber, instead, %s is %s" % (self.gerber_name, type(obj)))
|
||||
|
||||
self.fc.exec_command_test('isolate "%s"' % self.gerber_name)
|
||||
obj = self.fc.collection.get_by_name(self.gerber_name+'_iso')
|
||||
self.assertTrue(isinstance(obj, FlatCAMGeometry),
|
||||
"Expected FlatCAMGeometry, instead, %s is %s" % (self.gerber_name+'_iso', type(obj)))
|
||||
@@ -1,24 +0,0 @@
|
||||
from FlatCAMObj import FlatCAMGerber, FlatCAMGeometry
|
||||
|
||||
|
||||
def test_interiors(self):
|
||||
"""
|
||||
Test interiors
|
||||
:param self:
|
||||
:return:
|
||||
"""
|
||||
|
||||
self.fc.exec_command_test('open_gerber %s/%s -outname %s'
|
||||
% (self.gerber_files, self.cutout_filename, self.gerber_cutout_name))
|
||||
gerber_cutout_obj = self.fc.collection.get_by_name(self.gerber_cutout_name)
|
||||
self.assertTrue(isinstance(gerber_cutout_obj, FlatCAMGerber), "Expected FlatCAMGerber, instead, %s is %s"
|
||||
% (self.gerber_cutout_name, type(gerber_cutout_obj)))
|
||||
|
||||
# interiors and delete isolated traces
|
||||
self.fc.exec_command_test('isolate %s -dia %f' % (self.gerber_cutout_name, self.engraver_diameter))
|
||||
self.fc.exec_command_test('interiors %s -outname %s'
|
||||
% (self.gerber_cutout_name + '_iso', self.gerber_cutout_name + '_iso_interior'))
|
||||
self.fc.exec_command_test('delete %s' % (self.gerber_cutout_name + '_iso'))
|
||||
obj = self.fc.collection.get_by_name(self.gerber_cutout_name + '_iso_interior')
|
||||
self.assertTrue(isinstance(obj, FlatCAMGeometry), "Expected FlatCAMGeometry, instead, %s is %s"
|
||||
% (self.gerber_cutout_name + '_iso_interior', type(obj)))
|
||||
@@ -1,21 +0,0 @@
|
||||
from FlatCAMObj import FlatCAMGerber, FlatCAMGeometry
|
||||
|
||||
|
||||
def test_isolate(self):
|
||||
"""
|
||||
Test isolate gerber
|
||||
:param self:
|
||||
:return:
|
||||
"""
|
||||
|
||||
self.fc.exec_command_test('open_gerber %s/%s -outname %s'
|
||||
% (self.gerber_files, self.copper_top_filename, self.gerber_top_name))
|
||||
gerber_top_obj = self.fc.collection.get_by_name(self.gerber_top_name)
|
||||
self.assertTrue(isinstance(gerber_top_obj, FlatCAMGerber), "Expected FlatCAMGerber, instead, %s is %s"
|
||||
% (self.gerber_top_name, type(gerber_top_obj)))
|
||||
|
||||
# isolate traces
|
||||
self.fc.exec_command_test('isolate %s -dia %f' % (self.gerber_top_name, self.engraver_diameter))
|
||||
geometry_top_obj = self.fc.collection.get_by_name(self.gerber_top_name+'_iso')
|
||||
self.assertTrue(isinstance(geometry_top_obj, FlatCAMGeometry), "Expected FlatCAMGeometry, instead, %s is %s"
|
||||
% (self.gerber_top_name+'_iso', type(geometry_top_obj)))
|
||||
@@ -1,48 +0,0 @@
|
||||
from FlatCAMObj import FlatCAMGeometry
|
||||
|
||||
|
||||
def test_new(self):
|
||||
"""
|
||||
Test new project
|
||||
:param self:
|
||||
:return:
|
||||
"""
|
||||
|
||||
self.fc.exec_command_test('new_geometry "%s"' % self.geometry_name)
|
||||
geometry_obj = self.fc.collection.get_by_name(self.geometry_name)
|
||||
self.assertTrue(isinstance(geometry_obj, FlatCAMGeometry), "Expected FlatCAMGeometry, instead, %s is %s"
|
||||
% (self.geometry_name, type(geometry_obj)))
|
||||
|
||||
self.fc.exec_command_test('proc testproc {} { puts "testresult" }')
|
||||
|
||||
result = self.fc.exec_command_test('testproc')
|
||||
|
||||
self.assertEqual(result, "testresult",'testproc should return "testresult"')
|
||||
|
||||
self.fc.exec_command_test('set_sys units MM')
|
||||
self.fc.exec_command_test('new')
|
||||
|
||||
# object should not exists anymore
|
||||
geometry_obj = self.fc.collection.get_by_name(self.geometry_name)
|
||||
self.assertIsNone(geometry_obj, "Expected object to be None, instead, %s is %s"
|
||||
% (self.geometry_name, type(geometry_obj)))
|
||||
|
||||
# TODO after new it should delete all procedures and variables, we need to make sure "testproc" does not exists
|
||||
|
||||
# Test it again with same names
|
||||
|
||||
self.fc.exec_command_test('set_sys units MM')
|
||||
self.fc.exec_command_test('new')
|
||||
|
||||
self.fc.exec_command_test('new_geometry "%s"' % self.geometry_name)
|
||||
geometry_obj = self.fc.collection.get_by_name(self.geometry_name)
|
||||
self.assertTrue(isinstance(geometry_obj, FlatCAMGeometry), "Expected FlatCAMGeometry, instead, %s is %s"
|
||||
% (self.geometry_name, type(geometry_obj)))
|
||||
|
||||
self.fc.exec_command_test('set_sys units MM')
|
||||
self.fc.exec_command_test('new')
|
||||
|
||||
# object should not exists anymore
|
||||
geometry_obj = self.fc.collection.get_by_name(self.geometry_name)
|
||||
self.assertIsNone(geometry_obj, "Expected object to be None, instead, %s is %s"
|
||||
% (self.geometry_name, type(geometry_obj)))
|
||||
@@ -1,14 +0,0 @@
|
||||
from FlatCAMObj import FlatCAMGeometry
|
||||
|
||||
|
||||
def test_new_geometry(self):
|
||||
"""
|
||||
Test create new geometry
|
||||
:param self:
|
||||
:return:
|
||||
"""
|
||||
|
||||
self.fc.exec_command_test('new_geometry "%s"' % self.geometry_name)
|
||||
geometry_obj = self.fc.collection.get_by_name(self.geometry_name)
|
||||
self.assertTrue(isinstance(geometry_obj, FlatCAMGeometry), "Expected FlatCAMGeometry, instead, %s is %s"
|
||||
% (self.geometry_name, type(geometry_obj)))
|
||||
@@ -1,15 +0,0 @@
|
||||
from FlatCAMObj import FlatCAMExcellon
|
||||
|
||||
|
||||
def test_open_excellon(self):
|
||||
"""
|
||||
Test open excellon file
|
||||
:param self:
|
||||
:return:
|
||||
"""
|
||||
|
||||
self.fc.exec_command_test('open_excellon %s/%s -outname %s'
|
||||
% (self.gerber_files, self.excellon_filename, self.excellon_name))
|
||||
excellon_obj = self.fc.collection.get_by_name(self.excellon_name)
|
||||
self.assertTrue(isinstance(excellon_obj, FlatCAMExcellon), "Expected FlatCAMExcellon, instead, %s is %s"
|
||||
% (self.excellon_name, type(excellon_obj)))
|
||||
@@ -1,25 +0,0 @@
|
||||
from FlatCAMObj import FlatCAMGerber
|
||||
|
||||
|
||||
def test_open_gerber(self):
|
||||
"""
|
||||
Test open gerber file
|
||||
:param self:
|
||||
:return:
|
||||
"""
|
||||
|
||||
self.fc.exec_command_test('open_gerber %s/%s -outname %s'
|
||||
% (self.gerber_files, self.copper_top_filename, self.gerber_top_name))
|
||||
gerber_top_obj = self.fc.collection.get_by_name(self.gerber_top_name)
|
||||
self.assertTrue(isinstance(gerber_top_obj, FlatCAMGerber), "Expected FlatCAMGerber, instead, %s is %s"
|
||||
% (self.gerber_top_name, type(gerber_top_obj)))
|
||||
|
||||
self.fc.exec_command_test('open_gerber %s/%s -outname %s'
|
||||
% (self.gerber_files, self.copper_bottom_filename, self.gerber_bottom_name))
|
||||
gerber_bottom_obj = self.fc.collection.get_by_name(self.gerber_bottom_name)
|
||||
self.assertTrue(isinstance(gerber_bottom_obj, FlatCAMGerber), "Expected FlatCAMGerber, instead, %s is %s"
|
||||
% (self.gerber_bottom_name, type(gerber_bottom_obj)))
|
||||
|
||||
#just read with original name
|
||||
self.fc.exec_command_test('open_gerber %s/%s'
|
||||
% (self.gerber_files, self.copper_top_filename))
|
||||
@@ -1,25 +0,0 @@
|
||||
from FlatCAMObj import FlatCAMGeometry
|
||||
|
||||
|
||||
def test_paint_polygon(self):
|
||||
"""
|
||||
Test create paint polygon geometry
|
||||
:param self:
|
||||
:return:
|
||||
"""
|
||||
|
||||
self.fc.exec_command_test('new_geometry "%s"' % self.geometry_name)
|
||||
geometry_obj = self.fc.collection.get_by_name(self.geometry_name)
|
||||
self.assertTrue(isinstance(geometry_obj, FlatCAMGeometry), "Expected FlatCAMGeometry, instead, %s is %s"
|
||||
% (self.geometry_name, type(geometry_obj)))
|
||||
|
||||
points = '0 0 20 0 10 10 0 10'
|
||||
|
||||
self.fc.exec_command_test('add_polygon "%s" %s' % (self.geometry_name, points))
|
||||
|
||||
# TODO rename to paint_polygon in future oop command implementation
|
||||
self.fc.exec_command_test('paint_poly "%s" 5 5 2 0.5' % (self.geometry_name))
|
||||
geometry_obj = self.fc.collection.get_by_name(self.geometry_name+'_paint')
|
||||
# TODO uncoment check after oop implementation, because of threading inside paint poly
|
||||
#self.assertTrue(isinstance(geometry_obj, FlatCAMGeometry), "Expected FlatCAMGeometry, instead, %s is %s"
|
||||
# % (self.geometry_name+'_paint', type(geometry_obj)))
|
||||
@@ -1,272 +0,0 @@
|
||||
import sys
|
||||
import unittest
|
||||
from PyQt5 import QtWidgets, QtGui
|
||||
from PyQt5.QtCore import QThread
|
||||
|
||||
from FlatCAMApp import App
|
||||
from os import listdir
|
||||
from os.path import isfile
|
||||
from FlatCAMObj import FlatCAMGerber, FlatCAMGeometry, FlatCAMCNCjob, FlatCAMExcellon
|
||||
from flatcamGUI.ObjectUI import GerberObjectUI, GeometryObjectUI
|
||||
from time import sleep
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
|
||||
class TclShellTest(unittest.TestCase):
|
||||
|
||||
svg_files = 'tests/svg'
|
||||
svg_filename = 'Arduino Nano3_pcb.svg'
|
||||
gerber_files = 'tests/gerber_files'
|
||||
copper_bottom_filename = 'detector_copper_bottom.gbr'
|
||||
copper_top_filename = 'detector_copper_top.gbr'
|
||||
cutout_filename = 'detector_contour.gbr'
|
||||
excellon_filename = 'detector_drill.txt'
|
||||
gerber_name = "gerber"
|
||||
geometry_name = "geometry"
|
||||
excellon_name = "excellon"
|
||||
gerber_top_name = "top"
|
||||
gerber_bottom_name = "bottom"
|
||||
gerber_cutout_name = "cutout"
|
||||
engraver_diameter = 0.3
|
||||
cutout_diameter = 3
|
||||
drill_diameter = 0.8
|
||||
|
||||
# load test methods to split huge test file into smaller pieces
|
||||
# reason for this is reuse one test window only,
|
||||
|
||||
# CANNOT DO THIS HERE!!!
|
||||
# from tests.test_tclCommands import *
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
||||
cls.setup = True
|
||||
cls.app = QtWidgets.QApplication(sys.argv)
|
||||
|
||||
# Create App, keep app defaults (do not load
|
||||
# user-defined defaults).
|
||||
cls.fc = App(user_defaults=False)
|
||||
cls.fc.ui.shell_dock.show()
|
||||
|
||||
def setUp(self):
|
||||
self.fc.exec_command_test('set_sys units MM')
|
||||
self.fc.exec_command_test('new')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
|
||||
cls.fc.tcl = None
|
||||
cls.app.closeAllWindows()
|
||||
del cls.fc
|
||||
del cls.app
|
||||
pass
|
||||
|
||||
def test_set_get_units(self):
|
||||
"""
|
||||
Tests setting and getting units via the ``set_sys`` command,
|
||||
and persistance after ``new`` command.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
# MM
|
||||
self.fc.exec_command_test('set_sys units MM')
|
||||
self.fc.exec_command_test('new')
|
||||
|
||||
# IN
|
||||
self.fc.exec_command_test('set_sys units IN')
|
||||
self.fc.exec_command_test('new')
|
||||
|
||||
# ----------------------------------------
|
||||
# Units must be IN
|
||||
# ----------------------------------------
|
||||
units = self.fc.exec_command_test('get_sys units')
|
||||
self.assertEqual(units, "IN")
|
||||
|
||||
# MM
|
||||
self.fc.exec_command_test('set_sys units MM')
|
||||
self.fc.exec_command_test('new')
|
||||
|
||||
# ----------------------------------------
|
||||
# Units must be MM
|
||||
# ----------------------------------------
|
||||
units = self.fc.exec_command_test('get_sys units')
|
||||
self.assertEqual(units, "MM")
|
||||
|
||||
def test_gerber_flow(self):
|
||||
"""
|
||||
Typical workflow from Gerber to GCode.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
gbr_cmd = 'open_gerber {path}/{filename} -outname {outname}'
|
||||
|
||||
# -----------------------------------------
|
||||
# Open top layer and check for object type
|
||||
# -----------------------------------------
|
||||
cmd = gbr_cmd.format(
|
||||
path=self.gerber_files,
|
||||
filename=self.copper_top_filename,
|
||||
outname=self.gerber_top_name)
|
||||
self.fc.exec_command_test(cmd)
|
||||
gerber_top_obj = self.fc.collection.get_by_name(self.gerber_top_name)
|
||||
self.assertTrue(isinstance(gerber_top_obj, FlatCAMGerber),
|
||||
"Expected FlatCAMGerber, instead, %s is %s" %
|
||||
(self.gerber_top_name, type(gerber_top_obj)))
|
||||
|
||||
# --------------------------------------------
|
||||
# Open bottom layer and check for object type
|
||||
# --------------------------------------------
|
||||
cmd = gbr_cmd.format(
|
||||
path=self.gerber_files,
|
||||
filename=self.copper_bottom_filename,
|
||||
outname=self.gerber_bottom_name)
|
||||
self.fc.exec_command_test(cmd)
|
||||
gerber_bottom_obj = self.fc.collection.get_by_name(self.gerber_bottom_name)
|
||||
self.assertTrue(isinstance(gerber_bottom_obj, FlatCAMGerber),
|
||||
"Expected FlatCAMGerber, instead, %s is %s" %
|
||||
(self.gerber_bottom_name, type(gerber_bottom_obj)))
|
||||
|
||||
# --------------------------------------------
|
||||
# Open cutout layer and check for object type
|
||||
# --------------------------------------------
|
||||
cmd = gbr_cmd.format(
|
||||
path=self.gerber_files,
|
||||
filename=self.cutout_filename,
|
||||
outname=self.gerber_cutout_name
|
||||
)
|
||||
self.fc.exec_command_test(cmd)
|
||||
gerber_cutout_obj = self.fc.collection.get_by_name(self.gerber_cutout_name)
|
||||
self.assertTrue(isinstance(gerber_cutout_obj, FlatCAMGerber),
|
||||
"Expected FlatCAMGerber, instead, %s is %s" %
|
||||
(self.gerber_cutout_name, type(gerber_cutout_obj)))
|
||||
|
||||
# exteriors delete and join geometries for top layer
|
||||
cmd = 'isolate {objname} -dia {dia}'.format(
|
||||
objname=self.gerber_cutout_name,
|
||||
dia=self.engraver_diameter)
|
||||
self.fc.exec_command_test(cmd)
|
||||
|
||||
cmd = 'exteriors {objname} -outname {outname}'.format(
|
||||
objname=self.gerber_cutout_name + '_iso',
|
||||
outname=self.gerber_cutout_name + '_iso_exterior')
|
||||
self.fc.exec_command_test(cmd)
|
||||
|
||||
cmd = 'delete {objname}'.format(
|
||||
objname=self.gerber_cutout_name + '_iso')
|
||||
self.fc.exec_command_test(cmd)
|
||||
|
||||
# TODO: Check deleteb object is gone.
|
||||
|
||||
# --------------------------------------------
|
||||
# Exteriors of cutout layer, check type
|
||||
# --------------------------------------------
|
||||
obj = self.fc.collection.get_by_name(self.gerber_cutout_name + '_iso_exterior')
|
||||
self.assertTrue(isinstance(obj, FlatCAMGeometry),
|
||||
"Expected FlatCAMGeometry, instead, %s is %s" %
|
||||
(self.gerber_cutout_name + '_iso_exterior', type(obj)))
|
||||
|
||||
# mirror bottom gerbers
|
||||
self.fc.exec_command_test('mirror %s -box %s -axis X' % (self.gerber_bottom_name, self.gerber_cutout_name))
|
||||
self.fc.exec_command_test('mirror %s -box %s -axis X' % (self.gerber_cutout_name, self.gerber_cutout_name))
|
||||
|
||||
# exteriors delete and join geometries for bottom layer
|
||||
self.fc.exec_command_test(
|
||||
'isolate %s -dia %f -outname %s' %
|
||||
(self.gerber_cutout_name, self.engraver_diameter, self.gerber_cutout_name + '_bottom_iso')
|
||||
)
|
||||
self.fc.exec_command_test(
|
||||
'exteriors %s -outname %s' %
|
||||
(self.gerber_cutout_name + '_bottom_iso', self.gerber_cutout_name + '_bottom_iso_exterior')
|
||||
)
|
||||
self.fc.exec_command_test('delete %s' % (self.gerber_cutout_name + '_bottom_iso'))
|
||||
obj = self.fc.collection.get_by_name(self.gerber_cutout_name + '_bottom_iso_exterior')
|
||||
self.assertTrue(isinstance(obj, FlatCAMGeometry),
|
||||
"Expected FlatCAMGeometry, instead, %s is %s" %
|
||||
(self.gerber_cutout_name + '_bottom_iso_exterior', type(obj)))
|
||||
|
||||
# at this stage we should have 5 objects
|
||||
names = self.fc.collection.get_names()
|
||||
self.assertEqual(len(names), 5,
|
||||
"Expected 5 objects, found %d" % len(names))
|
||||
|
||||
# isolate traces
|
||||
self.fc.exec_command_test('isolate %s -dia %f' % (self.gerber_top_name, self.engraver_diameter))
|
||||
self.fc.exec_command_test('isolate %s -dia %f' % (self.gerber_bottom_name, self.engraver_diameter))
|
||||
|
||||
# join isolated geometries for top and bottom
|
||||
self.fc.exec_command_test(
|
||||
'join_geometries %s %s %s' %
|
||||
(self.gerber_top_name + '_join_iso', self.gerber_top_name + '_iso',
|
||||
self.gerber_cutout_name + '_iso_exterior')
|
||||
)
|
||||
self.fc.exec_command_test(
|
||||
'join_geometries %s %s %s' %
|
||||
(self.gerber_bottom_name + '_join_iso', self.gerber_bottom_name + '_iso',
|
||||
self.gerber_cutout_name + '_bottom_iso_exterior')
|
||||
)
|
||||
|
||||
# at this stage we should have 9 objects
|
||||
names = self.fc.collection.get_names()
|
||||
self.assertEqual(len(names), 9,
|
||||
"Expected 9 objects, found %d" % len(names))
|
||||
|
||||
# clean unused isolations
|
||||
self.fc.exec_command_test('delete %s' % (self.gerber_bottom_name + '_iso'))
|
||||
self.fc.exec_command_test('delete %s' % (self.gerber_top_name + '_iso'))
|
||||
self.fc.exec_command_test('delete %s' % (self.gerber_cutout_name + '_iso_exterior'))
|
||||
self.fc.exec_command_test('delete %s' % (self.gerber_cutout_name + '_bottom_iso_exterior'))
|
||||
|
||||
# at this stage we should have 5 objects again
|
||||
names = self.fc.collection.get_names()
|
||||
self.assertEqual(len(names), 5,
|
||||
"Expected 5 objects, found %d" % len(names))
|
||||
|
||||
# geocutout bottom test (it cuts to same object)
|
||||
self.fc.exec_command_test(
|
||||
'isolate %s -dia %f -outname %s' %
|
||||
(self.gerber_cutout_name, self.cutout_diameter, self.gerber_cutout_name + '_bottom_iso')
|
||||
)
|
||||
self.fc.exec_command_test(
|
||||
'exteriors %s -outname %s' %
|
||||
(self.gerber_cutout_name + '_bottom_iso', self.gerber_cutout_name + '_bottom_iso_exterior')
|
||||
)
|
||||
self.fc.exec_command_test('delete %s' % (self.gerber_cutout_name + '_bottom_iso'))
|
||||
obj = self.fc.collection.get_by_name(self.gerber_cutout_name + '_bottom_iso_exterior')
|
||||
self.assertTrue(isinstance(obj, FlatCAMGeometry),
|
||||
"Expected FlatCAMGeometry, instead, %s is %s" %
|
||||
(self.gerber_cutout_name + '_bottom_iso_exterior', type(obj)))
|
||||
self.fc.exec_command_test('geocutout %s -dia %f -gapsize 0.3 -gaps 4' %
|
||||
(self.gerber_cutout_name + '_bottom_iso_exterior', self.cutout_diameter))
|
||||
|
||||
# at this stage we should have 6 objects
|
||||
names = self.fc.collection.get_names()
|
||||
self.assertEqual(len(names), 6,
|
||||
"Expected 6 objects, found %d" % len(names))
|
||||
|
||||
# TODO: tests for tcl
|
||||
|
||||
def test_open_gerber(self):
|
||||
|
||||
self.fc.exec_command_test('open_gerber %s/%s -outname %s' %
|
||||
(self.gerber_files, self.copper_top_filename, self.gerber_top_name))
|
||||
gerber_top_obj = self.fc.collection.get_by_name(self.gerber_top_name)
|
||||
self.assertTrue(isinstance(gerber_top_obj, FlatCAMGerber),
|
||||
"Expected FlatCAMGerber, instead, %s is %s" %
|
||||
(self.gerber_top_name, type(gerber_top_obj)))
|
||||
|
||||
def test_excellon_flow(self):
|
||||
|
||||
self.fc.exec_command_test('open_excellon %s/%s -outname %s' %
|
||||
(self.gerber_files, self.excellon_filename, self.excellon_name))
|
||||
excellon_obj = self.fc.collection.get_by_name(self.excellon_name)
|
||||
self.assertTrue(isinstance(excellon_obj, FlatCAMExcellon),
|
||||
"Expected FlatCAMExcellon, instead, %s is %s" %
|
||||
(self.excellon_name, type(excellon_obj)))
|
||||
|
||||
# mirror bottom excellon
|
||||
self.fc.exec_command_test('mirror %s -box %s -axis X' % (self.excellon_name, self.gerber_cutout_name))
|
||||
|
||||
# TODO: tests for tcl
|
||||
@@ -1,26 +0,0 @@
|
||||
"""
|
||||
Test cases for Voronoi Diagram creation.
|
||||
Overall, I'm trying less to test the correctness of the result
|
||||
and more to cover input cases and behavior, making sure
|
||||
that we return a sane result without error or raise a useful one.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from shapely.geos import geos_version
|
||||
from shapely.wkt import loads as load_wkt
|
||||
|
||||
from shapely.ops import voronoi_diagram
|
||||
|
||||
requires_geos_35 = pytest.mark.skipif(geos_version < (3, 5, 0), reason='GEOS >= 3.5.0 is required.')
|
||||
|
||||
@requires_geos_35
|
||||
def test_from_multipoint_without_tolerace_with_floating_point_coordinates():
|
||||
"""But it's fine without it."""
|
||||
mp = load_wkt('MULTIPOINT (20.1273 18.7303, 26.5107 18.7303, 20.1273 23.8437, 26.5107 23.8437)')
|
||||
|
||||
regions = voronoi_diagram(mp)
|
||||
print("Len: %d -> Regions: %s" % (len(regions), str(regions)))
|
||||
|
||||
print(geos_version)
|
||||
test_from_multipoint_without_tolerace_with_floating_point_coordinates()
|
||||
@@ -1,197 +0,0 @@
|
||||
# ########################################################
|
||||
# # customize Title bar
|
||||
# # dotpy.ir
|
||||
# # iraj.jelo@gmail.com
|
||||
# ########################################################
|
||||
import sys
|
||||
from PyQt6 import QtWidgets, QtGui
|
||||
from PyQt6 import QtCore
|
||||
from PyQt6.QtCore import Qt
|
||||
|
||||
from datetime import datetime
|
||||
import traceback
|
||||
|
||||
|
||||
class TitleBar(QtWidgets.QDialog):
|
||||
def __init__(self, parent=None):
|
||||
QtWidgets.QWidget.__init__(self, parent)
|
||||
self.setWindowFlags(Qt.WindowType.FramelessWindowHint)
|
||||
css = """
|
||||
QWidget{
|
||||
Background: #0000FF;
|
||||
color:white;
|
||||
font:12px bold;
|
||||
font-weight:bold;
|
||||
border-radius: 1px;
|
||||
height: 11px;
|
||||
}
|
||||
QDialog{
|
||||
Background-image:url('img/titlebar bg.png');
|
||||
font-size:12px;
|
||||
color: black;
|
||||
|
||||
}
|
||||
QToolButton{
|
||||
Background:#AA00AA;
|
||||
font-size:11px;
|
||||
}
|
||||
QToolButton:hover{
|
||||
Background: #FF00FF;
|
||||
font-size:11px;
|
||||
}
|
||||
"""
|
||||
self.setAutoFillBackground(True)
|
||||
self.setBackgroundRole(QtGui.QPalette.ColorRole.Highlight)
|
||||
self.setStyleSheet(css)
|
||||
self.minimize = QtWidgets.QToolButton(self)
|
||||
self.minimize.setIcon(QtGui.QIcon('img/min.png'))
|
||||
self.maximize = QtWidgets.QToolButton(self)
|
||||
self.maximize.setIcon(QtGui.QIcon('img/max.png'))
|
||||
close = QtWidgets.QToolButton(self)
|
||||
close.setIcon(QtGui.QIcon('img/close.png'))
|
||||
self.minimize.setMinimumHeight(10)
|
||||
close.setMinimumHeight(10)
|
||||
self.maximize.setMinimumHeight(10)
|
||||
label = QtWidgets.QLabel(self)
|
||||
label.setText("Window Title")
|
||||
self.setWindowTitle("Window Title")
|
||||
hbox = QtWidgets.QHBoxLayout(self)
|
||||
hbox.addWidget(label)
|
||||
hbox.addWidget(self.minimize)
|
||||
hbox.addWidget(self.maximize)
|
||||
hbox.addWidget(close)
|
||||
hbox.insertStretch(1, 500)
|
||||
hbox.setSpacing(0)
|
||||
self.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Fixed)
|
||||
self.maxNormal = False
|
||||
close.clicked.connect(self.close)
|
||||
self.minimize.clicked.connect(self.showSmall)
|
||||
self.maximize.clicked.connect(self.showMaxRestore)
|
||||
|
||||
@staticmethod
|
||||
def showSmall():
|
||||
box.showMinimized()
|
||||
|
||||
def showMaxRestore(self):
|
||||
if self.maxNormal:
|
||||
box.showNormal()
|
||||
self.maxNormal = False
|
||||
self.maximize.setIcon(QtGui.QIcon('img/max.png'))
|
||||
else:
|
||||
box.showMaximized()
|
||||
self.maxNormal = True
|
||||
self.maximize.setIcon(QtGui.QIcon('img/max2.png'))
|
||||
|
||||
def close(self):
|
||||
box.close()
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
if event.button() == Qt.MouseButton.LeftButton:
|
||||
box.moving = True
|
||||
box.offset = event.position()
|
||||
if event.type() == QtCore.QEvent.Type.MouseButtonDblClick:
|
||||
self.showMaxRestore()
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
if box.isMaximized():
|
||||
self.showMaxRestore()
|
||||
box.move(event.globalPosition().toPoint() - box.offset)
|
||||
else:
|
||||
if box.moving:
|
||||
box.move(event.globalPosition().toPoint() - box.offset)
|
||||
|
||||
|
||||
class Frame(QtWidgets.QFrame):
|
||||
def __init__(self, parent=None):
|
||||
QtWidgets.QFrame.__init__(self, parent)
|
||||
|
||||
self.m_old_pos = None
|
||||
self.m_mouse_down = False
|
||||
self.setFrameShape(QtWidgets.QFrame.Shape.StyledPanel)
|
||||
css = """
|
||||
QFrame{
|
||||
Background: #FFFFF0;
|
||||
color:white;
|
||||
font:13px ;
|
||||
font-weight:bold;
|
||||
}
|
||||
"""
|
||||
self.setStyleSheet(css)
|
||||
self.setWindowFlags(Qt.WindowType.FramelessWindowHint)
|
||||
self.setMouseTracking(True)
|
||||
self.m_titleBar = TitleBar(self)
|
||||
self.m_content = QtWidgets.QWidget(self)
|
||||
vbox = QtWidgets.QVBoxLayout(self)
|
||||
vbox.addWidget(self.m_titleBar)
|
||||
vbox.setContentsMargins(0, 0, 0, 0)
|
||||
vbox.setSpacing(0)
|
||||
layout = QtWidgets.QVBoxLayout()
|
||||
layout.addWidget(self.m_content)
|
||||
layout.setContentsMargins(5, 5, 5, 5)
|
||||
layout.setSpacing(0)
|
||||
vbox.addLayout(layout)
|
||||
# Allows you to access the content area of the frame
|
||||
# where widgets and layouts can be added
|
||||
|
||||
def contentWidget(self):
|
||||
return self.m_content
|
||||
|
||||
def titleBar(self):
|
||||
return self.m_titleBar
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
self.m_old_pos = event.pos()
|
||||
self.m_mouse_down = event.button() == Qt.MouseButton.LeftButton
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
event.position().x()
|
||||
event.position().y()
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
self.m_mouse_down = False
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
def excepthook(exc_type, exc_value, exc_tb):
|
||||
msg = '%s\n' % str(datetime.today())
|
||||
if exc_type != KeyboardInterrupt:
|
||||
msg += "".join(traceback.format_exception(exc_type, exc_value, exc_tb))
|
||||
|
||||
# show the message
|
||||
try:
|
||||
msgbox = QtWidgets.QMessageBox()
|
||||
displayed_msg = "The application encountered a critical error and it will close.\n" \
|
||||
"Please report this error to the developers."
|
||||
|
||||
msgbox.setText(displayed_msg)
|
||||
msgbox.setDetailedText(msg)
|
||||
msgbox.setWindowTitle("Critical Error")
|
||||
# msgbox.setWindowIcon()
|
||||
msgbox.setIcon(QtWidgets.QMessageBox.Icon.Critical)
|
||||
|
||||
bt_yes = msgbox.addButton("Quit", QtWidgets.QMessageBox.ButtonRole.YesRole)
|
||||
|
||||
msgbox.setDefaultButton(bt_yes)
|
||||
# msgbox.setTextFormat(Qt.TextFormat.RichText)
|
||||
msgbox.exec()
|
||||
except Exception:
|
||||
pass
|
||||
QtWidgets.QApplication.quit()
|
||||
# or QtWidgets.QApplication.exit(0)
|
||||
|
||||
|
||||
sys.excepthook = excepthook
|
||||
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
box = Frame()
|
||||
box.move(60, 60)
|
||||
|
||||
le = QtWidgets.QVBoxLayout(box.contentWidget())
|
||||
|
||||
le.setContentsMargins(0, 0, 0, 0)
|
||||
edit = QtWidgets.QLabel("""I would've did anything for you to show you how much I adored you
|
||||
But it's over now, it's too late to save our loveJust promise me you'll think of me
|
||||
Every time you look up in the sky and see a star 'cuz I'm your star.""")
|
||||
le.addWidget(edit)
|
||||
box.show()
|
||||
app.exec()
|
||||
@@ -1,8 +0,0 @@
|
||||
# Run kernprof -l -v gerber_parsing_line_profile_1.py
|
||||
import sys
|
||||
sys.path.append('../../')
|
||||
from camlib import *
|
||||
from shapely.geometry import Polygon
|
||||
|
||||
poly = Polygon([(0.0, 0.0), (1.0, 0.0), (1.0, 0.5), (0.0, 0.5)])
|
||||
result = Geometry.clear_polygon2(poly, 0.01)
|
||||
@@ -1,11 +0,0 @@
|
||||
import cProfile
|
||||
import pstats
|
||||
from camlib import *
|
||||
from shapely.geometry import Polygon
|
||||
|
||||
poly = Polygon([(0.0, 0.0), (1.0, 0.0), (1.0, 0.5), (0.0, 0.5)])
|
||||
|
||||
cProfile.run('result = Geometry.clear_polygon2(poly, 0.01)',
|
||||
'toollist_minimization_profile', sort='cumtime')
|
||||
p = pstats.Stats('toollist_minimization_profile')
|
||||
p.sort_stats('cumulative').print_stats(.1)
|
||||
Reference in New Issue
Block a user