Added feature: Select all polygons for painting and shell support with "paint" command.
This commit is contained in:
@@ -259,6 +259,7 @@ class App(QtCore.QObject):
|
|||||||
"geometry_spindlespeed": self.defaults_form.geometry_group.cncspindlespeed_entry,
|
"geometry_spindlespeed": self.defaults_form.geometry_group.cncspindlespeed_entry,
|
||||||
"geometry_paintoverlap": self.defaults_form.geometry_group.paintoverlap_entry,
|
"geometry_paintoverlap": self.defaults_form.geometry_group.paintoverlap_entry,
|
||||||
"geometry_paintmargin": self.defaults_form.geometry_group.paintmargin_entry,
|
"geometry_paintmargin": self.defaults_form.geometry_group.paintmargin_entry,
|
||||||
|
"geometry_selectmethod": self.defaults_form.geometry_group.selectmethod_combo,
|
||||||
"cncjob_plot": self.defaults_form.cncjob_group.plot_cb,
|
"cncjob_plot": self.defaults_form.cncjob_group.plot_cb,
|
||||||
"cncjob_tooldia": self.defaults_form.cncjob_group.tooldia_entry,
|
"cncjob_tooldia": self.defaults_form.cncjob_group.tooldia_entry,
|
||||||
"cncjob_prepend": self.defaults_form.cncjob_group.prepend_text,
|
"cncjob_prepend": self.defaults_form.cncjob_group.prepend_text,
|
||||||
@@ -304,6 +305,7 @@ class App(QtCore.QObject):
|
|||||||
"geometry_painttooldia": 0.07,
|
"geometry_painttooldia": 0.07,
|
||||||
"geometry_paintoverlap": 0.15,
|
"geometry_paintoverlap": 0.15,
|
||||||
"geometry_paintmargin": 0.0,
|
"geometry_paintmargin": 0.0,
|
||||||
|
"geometry_selectmethod": "single",
|
||||||
"cncjob_plot": True,
|
"cncjob_plot": True,
|
||||||
"cncjob_tooldia": 0.016,
|
"cncjob_tooldia": 0.016,
|
||||||
"cncjob_prepend": "",
|
"cncjob_prepend": "",
|
||||||
@@ -397,6 +399,7 @@ class App(QtCore.QObject):
|
|||||||
"geometry_painttooldia": self.options_form.geometry_group.painttooldia_entry,
|
"geometry_painttooldia": self.options_form.geometry_group.painttooldia_entry,
|
||||||
"geometry_paintoverlap": self.options_form.geometry_group.paintoverlap_entry,
|
"geometry_paintoverlap": self.options_form.geometry_group.paintoverlap_entry,
|
||||||
"geometry_paintmargin": self.options_form.geometry_group.paintmargin_entry,
|
"geometry_paintmargin": self.options_form.geometry_group.paintmargin_entry,
|
||||||
|
"geometry_selectmethod": self.options_form.geometry_group.selectmethod_combo,
|
||||||
"cncjob_plot": self.options_form.cncjob_group.plot_cb,
|
"cncjob_plot": self.options_form.cncjob_group.plot_cb,
|
||||||
"cncjob_tooldia": self.options_form.cncjob_group.tooldia_entry,
|
"cncjob_tooldia": self.options_form.cncjob_group.tooldia_entry,
|
||||||
"cncjob_prepend": self.options_form.cncjob_group.prepend_text,
|
"cncjob_prepend": self.options_form.cncjob_group.prepend_text,
|
||||||
@@ -439,12 +442,15 @@ class App(QtCore.QObject):
|
|||||||
"geometry_painttooldia": 0.07,
|
"geometry_painttooldia": 0.07,
|
||||||
"geometry_paintoverlap": 0.15,
|
"geometry_paintoverlap": 0.15,
|
||||||
"geometry_paintmargin": 0.0,
|
"geometry_paintmargin": 0.0,
|
||||||
|
"geometry_selectmethod": "single",
|
||||||
"cncjob_plot": True,
|
"cncjob_plot": True,
|
||||||
"cncjob_tooldia": 0.016,
|
"cncjob_tooldia": 0.016,
|
||||||
"cncjob_prepend": "",
|
"cncjob_prepend": "",
|
||||||
"cncjob_append": "",
|
"cncjob_append": "",
|
||||||
"background_timeout": 300000, #default value is 5 minutes
|
"background_timeout": 300000, # Default value is 5 minutes
|
||||||
"verbose_error_level": 0, # shell verbosity 0 = default(python trace only for unknown errors), 1 = show trace(show trace allways), 2 = (For the future).
|
"verbose_error_level": 0, # Shell verbosity:
|
||||||
|
# 0 = default(python trace only for unknown errors),
|
||||||
|
# 1 = show trace(show trace allways), 2 = (For the future).
|
||||||
})
|
})
|
||||||
self.options.update(self.defaults) # Copy app defaults to project options
|
self.options.update(self.defaults) # Copy app defaults to project options
|
||||||
#self.options_write_form()
|
#self.options_write_form()
|
||||||
@@ -877,13 +883,13 @@ class App(QtCore.QObject):
|
|||||||
#self.shell.append_error("?\n")
|
#self.shell.append_error("?\n")
|
||||||
self.shell.append_error(str(e) + "\n")
|
self.shell.append_error(str(e) + "\n")
|
||||||
|
|
||||||
def info(self, msg):
|
def info(self, msg, toshell=True):
|
||||||
"""
|
"""
|
||||||
Informs the user. Normally on the status bar, optionally
|
Informs the user. Normally on the status bar, optionally
|
||||||
also on the shell.
|
also on the shell.
|
||||||
|
|
||||||
:param msg: Text to write.
|
:param msg: Text to write.
|
||||||
:param toshell: Forward the
|
:param toshell: Forward the meesage to the shell.
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -894,12 +900,15 @@ class App(QtCore.QObject):
|
|||||||
msg_ = match.group(2)
|
msg_ = match.group(2)
|
||||||
self.ui.fcinfo.set_status(QtCore.QString(msg_), level=level)
|
self.ui.fcinfo.set_status(QtCore.QString(msg_), level=level)
|
||||||
|
|
||||||
error = level == "error" or level == "warning"
|
if toshell:
|
||||||
self.shell_message(msg, error=error, show=True)
|
error = level == "error" or level == "warning"
|
||||||
|
self.shell_message(msg, error=error, show=True)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.ui.fcinfo.set_status(QtCore.QString(msg), level="info")
|
self.ui.fcinfo.set_status(QtCore.QString(msg), level="info")
|
||||||
self.shell_message(msg)
|
|
||||||
|
if toshell:
|
||||||
|
self.shell_message(msg)
|
||||||
|
|
||||||
def load_defaults(self):
|
def load_defaults(self):
|
||||||
"""
|
"""
|
||||||
@@ -981,6 +990,11 @@ class App(QtCore.QObject):
|
|||||||
this is, updates the GUI accordingly, any other records and plots it.
|
this is, updates the GUI accordingly, any other records and plots it.
|
||||||
This method is thread-safe.
|
This method is thread-safe.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
* If the name is in use, the self.collection will modify it
|
||||||
|
when appending it to the collection. There is no need to handle
|
||||||
|
name conflicts here.
|
||||||
|
|
||||||
:param kind: The kind of object to create. One of 'gerber',
|
:param kind: The kind of object to create. One of 'gerber',
|
||||||
'excellon', 'cncjob' and 'geometry'.
|
'excellon', 'cncjob' and 'geometry'.
|
||||||
:type kind: str
|
:type kind: str
|
||||||
@@ -998,19 +1012,6 @@ class App(QtCore.QObject):
|
|||||||
|
|
||||||
t0 = time.time() # Debug
|
t0 = time.time() # Debug
|
||||||
|
|
||||||
### Check for existing name
|
|
||||||
# while name in self.collection.get_names():
|
|
||||||
# ## Create a new name
|
|
||||||
# # Ends with number?
|
|
||||||
# App.log.debug("new_object(): Object name (%s) exists, changing." % name)
|
|
||||||
# match = re.search(r'(.*[^\d])?(\d+)$', name)
|
|
||||||
# if match: # Yes: Increment the number!
|
|
||||||
# base = match.group(1) or ''
|
|
||||||
# num = int(match.group(2))
|
|
||||||
# name = base + str(num + 1)
|
|
||||||
# else: # No: add a number!
|
|
||||||
# name += "_1"
|
|
||||||
|
|
||||||
## Create object
|
## Create object
|
||||||
classdict = {
|
classdict = {
|
||||||
"gerber": FlatCAMGerber,
|
"gerber": FlatCAMGerber,
|
||||||
|
|||||||
@@ -746,7 +746,21 @@ class GeometryOptionsGroupUI(OptionsGroupUI):
|
|||||||
)
|
)
|
||||||
grid2.addWidget(marginlabel, 2, 0)
|
grid2.addWidget(marginlabel, 2, 0)
|
||||||
self.paintmargin_entry = LengthEntry()
|
self.paintmargin_entry = LengthEntry()
|
||||||
grid2.addWidget(self.paintmargin_entry)
|
grid2.addWidget(self.paintmargin_entry, 2, 1)
|
||||||
|
|
||||||
|
# Polygon selection
|
||||||
|
selectlabel = QtGui.QLabel('Selection:')
|
||||||
|
selectlabel.setToolTip(
|
||||||
|
"How to select the polygons to paint."
|
||||||
|
)
|
||||||
|
grid2.addWidget(selectlabel, 3, 0)
|
||||||
|
# grid3 = QtGui.QGridLayout()
|
||||||
|
self.selectmethod_combo = RadioSet([
|
||||||
|
{"label": "Single", "value": "single"},
|
||||||
|
{"label": "All", "value": "all"},
|
||||||
|
# {"label": "Rectangle", "value": "rectangle"}
|
||||||
|
])
|
||||||
|
grid2.addWidget(self.selectmethod_combo, 3, 1)
|
||||||
|
|
||||||
|
|
||||||
class CNCJobOptionsGroupUI(OptionsGroupUI):
|
class CNCJobOptionsGroupUI(OptionsGroupUI):
|
||||||
|
|||||||
111
FlatCAMObj.py
111
FlatCAMObj.py
@@ -1203,7 +1203,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||||||
"paintmargin": 0.01,
|
"paintmargin": 0.01,
|
||||||
"paintmethod": "standard",
|
"paintmethod": "standard",
|
||||||
"multidepth": False,
|
"multidepth": False,
|
||||||
"depthperpass": 0.002
|
"depthperpass": 0.002,
|
||||||
|
"selectmethod": "single"
|
||||||
})
|
})
|
||||||
|
|
||||||
# Attributes to be included in serialization
|
# Attributes to be included in serialization
|
||||||
@@ -1234,7 +1235,8 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||||||
"paintmargin": self.ui.paintmargin_entry,
|
"paintmargin": self.ui.paintmargin_entry,
|
||||||
"paintmethod": self.ui.paintmethod_combo,
|
"paintmethod": self.ui.paintmethod_combo,
|
||||||
"multidepth": self.ui.mpass_cb,
|
"multidepth": self.ui.mpass_cb,
|
||||||
"depthperpass": self.ui.maxdepth_entry
|
"depthperpass": self.ui.maxdepth_entry,
|
||||||
|
"selectmethod": self.ui.selectmethod_combo
|
||||||
})
|
})
|
||||||
|
|
||||||
self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click)
|
self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click)
|
||||||
@@ -1244,24 +1246,38 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||||||
def on_paint_button_click(self, *args):
|
def on_paint_button_click(self, *args):
|
||||||
self.app.report_usage("geometry_on_paint_button")
|
self.app.report_usage("geometry_on_paint_button")
|
||||||
|
|
||||||
self.app.info("Click inside the desired polygon.")
|
|
||||||
self.read_form()
|
self.read_form()
|
||||||
tooldia = self.options["painttooldia"]
|
tooldia = self.options["painttooldia"]
|
||||||
overlap = self.options["paintoverlap"]
|
overlap = self.options["paintoverlap"]
|
||||||
|
|
||||||
# Connection ID for the click event
|
if self.options["selectmethod"] == "all":
|
||||||
subscription = None
|
self.paint_poly_all(tooldia, overlap)
|
||||||
|
return
|
||||||
|
|
||||||
# To be called after clicking on the plot.
|
if self.options["selectmethod"] == "single":
|
||||||
def doit(event):
|
self.app.info("Click inside the desired polygon.")
|
||||||
self.app.info("Painting polygon...")
|
|
||||||
self.app.plotcanvas.mpl_disconnect(subscription)
|
|
||||||
point = [event.xdata, event.ydata]
|
|
||||||
self.paint_poly(point, tooldia, overlap)
|
|
||||||
|
|
||||||
subscription = self.app.plotcanvas.mpl_connect('button_press_event', doit)
|
# To be called after clicking on the plot.
|
||||||
|
def doit(event):
|
||||||
|
self.app.info("Painting polygon...")
|
||||||
|
self.app.plotcanvas.mpl_disconnect(subscription)
|
||||||
|
point = [event.xdata, event.ydata]
|
||||||
|
self.paint_poly_single_click(point, tooldia, overlap)
|
||||||
|
|
||||||
def paint_poly(self, inside_pt, tooldia, overlap):
|
subscription = self.app.plotcanvas.mpl_connect('button_press_event', doit)
|
||||||
|
|
||||||
|
def paint_poly_single_click(self, inside_pt, tooldia, overlap, outname=None):
|
||||||
|
"""
|
||||||
|
Paints a polygon selected by clicking on its interior.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
* The margin is taken directly from the form.
|
||||||
|
|
||||||
|
:param inside_pt: [x, y]
|
||||||
|
:param tooldia: Diameter of the painting tool
|
||||||
|
:param overlap: Overlap of the tool between passes.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
|
||||||
# Which polygon.
|
# Which polygon.
|
||||||
#poly = find_polygon(self.solid_geometry, inside_pt)
|
#poly = find_polygon(self.solid_geometry, inside_pt)
|
||||||
@@ -1275,7 +1291,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||||||
|
|
||||||
proc = self.app.proc_container.new("Painting polygon.")
|
proc = self.app.proc_container.new("Painting polygon.")
|
||||||
|
|
||||||
name = self.options["name"] + "_paint"
|
name = outname or self.options["name"] + "_paint"
|
||||||
|
|
||||||
# Initializes the new geometry object
|
# Initializes the new geometry object
|
||||||
def gen_paintarea(geo_obj, app_obj):
|
def gen_paintarea(geo_obj, app_obj):
|
||||||
@@ -1293,6 +1309,73 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||||||
|
|
||||||
geo_obj.solid_geometry = list(cp.get_objects())
|
geo_obj.solid_geometry = list(cp.get_objects())
|
||||||
geo_obj.options["cnctooldia"] = tooldia
|
geo_obj.options["cnctooldia"] = tooldia
|
||||||
|
|
||||||
|
# Experimental...
|
||||||
|
print "Indexing...",
|
||||||
|
geo_obj.make_index()
|
||||||
|
print "Done"
|
||||||
|
|
||||||
|
self.app.inform.emit("Done.")
|
||||||
|
|
||||||
|
def job_thread(app_obj):
|
||||||
|
try:
|
||||||
|
app_obj.new_object("geometry", name, gen_paintarea)
|
||||||
|
except Exception as e:
|
||||||
|
proc.done()
|
||||||
|
raise e
|
||||||
|
proc.done()
|
||||||
|
|
||||||
|
self.app.inform.emit("Polygon Paint started ...")
|
||||||
|
|
||||||
|
# Promise object with the new name
|
||||||
|
self.app.collection.promise(name)
|
||||||
|
|
||||||
|
# Background
|
||||||
|
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
|
||||||
|
|
||||||
|
def paint_poly_all(self, tooldia, overlap, outname=None):
|
||||||
|
|
||||||
|
proc = self.app.proc_container.new("Painting polygon.")
|
||||||
|
|
||||||
|
name = outname or self.options["name"] + "_paint"
|
||||||
|
|
||||||
|
def recurse(geo):
|
||||||
|
try:
|
||||||
|
for subg in geo:
|
||||||
|
for subsubg in recurse(subg):
|
||||||
|
yield subsubg
|
||||||
|
except TypeError:
|
||||||
|
if isinstance(geo, Polygon):
|
||||||
|
yield geo
|
||||||
|
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
# Initializes the new geometry object
|
||||||
|
def gen_paintarea(geo_obj, app_obj):
|
||||||
|
assert isinstance(geo_obj, FlatCAMGeometry), \
|
||||||
|
"Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj)
|
||||||
|
|
||||||
|
geo_obj.solid_geometry = []
|
||||||
|
|
||||||
|
for poly in recurse(self.solid_geometry):
|
||||||
|
|
||||||
|
if self.options["paintmethod"] == "seed":
|
||||||
|
cp = self.clear_polygon2(poly.buffer(-self.options["paintmargin"]),
|
||||||
|
tooldia, overlap=overlap)
|
||||||
|
|
||||||
|
else:
|
||||||
|
cp = self.clear_polygon(poly.buffer(-self.options["paintmargin"]),
|
||||||
|
tooldia, overlap=overlap)
|
||||||
|
|
||||||
|
geo_obj.solid_geometry += list(cp.get_objects())
|
||||||
|
|
||||||
|
geo_obj.options["cnctooldia"] = tooldia
|
||||||
|
|
||||||
|
# Experimental...
|
||||||
|
print "Indexing...",
|
||||||
|
geo_obj.make_index()
|
||||||
|
print "Done"
|
||||||
|
|
||||||
self.app.inform.emit("Done.")
|
self.app.inform.emit("Done.")
|
||||||
|
|
||||||
def job_thread(app_obj):
|
def job_thread(app_obj):
|
||||||
|
|||||||
14
ObjectUI.py
14
ObjectUI.py
@@ -397,6 +397,20 @@ class GeometryObjectUI(ObjectUI):
|
|||||||
])
|
])
|
||||||
grid2.addWidget(self.paintmethod_combo, 3, 1)
|
grid2.addWidget(self.paintmethod_combo, 3, 1)
|
||||||
|
|
||||||
|
# Polygon selection
|
||||||
|
selectlabel = QtGui.QLabel('Selection:')
|
||||||
|
selectlabel.setToolTip(
|
||||||
|
"How to select the polygons to paint."
|
||||||
|
)
|
||||||
|
grid2.addWidget(selectlabel, 4, 0)
|
||||||
|
#grid3 = QtGui.QGridLayout()
|
||||||
|
self.selectmethod_combo = RadioSet([
|
||||||
|
{"label": "Single", "value": "single"},
|
||||||
|
{"label": "All", "value": "all"},
|
||||||
|
#{"label": "Rectangle", "value": "rectangle"}
|
||||||
|
])
|
||||||
|
grid2.addWidget(self.selectmethod_combo, 4, 1)
|
||||||
|
|
||||||
# GO Button
|
# GO Button
|
||||||
self.generate_paint_button = QtGui.QPushButton('Generate')
|
self.generate_paint_button = QtGui.QPushButton('Generate')
|
||||||
self.generate_paint_button.setToolTip(
|
self.generate_paint_button.setToolTip(
|
||||||
|
|||||||
10
camlib.py
10
camlib.py
@@ -92,6 +92,16 @@ class Geometry(object):
|
|||||||
# Flattened geometry (list of paths only)
|
# Flattened geometry (list of paths only)
|
||||||
self.flat_geometry = []
|
self.flat_geometry = []
|
||||||
|
|
||||||
|
# Index
|
||||||
|
self.index = None
|
||||||
|
|
||||||
|
def make_index(self):
|
||||||
|
self.flatten()
|
||||||
|
self.index = FlatCAMRTree()
|
||||||
|
|
||||||
|
for i, g in enumerate(self.flat_geometry):
|
||||||
|
self.index.insert(i, g)
|
||||||
|
|
||||||
def add_circle(self, origin, radius):
|
def add_circle(self, origin, radius):
|
||||||
"""
|
"""
|
||||||
Adds a circle to the object.
|
Adds a circle to the object.
|
||||||
|
|||||||
84
tclCommands/TclCommandPaint.py
Normal file
84
tclCommands/TclCommandPaint.py
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandPaint(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Paint the interior of polygons
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['paint']
|
||||||
|
|
||||||
|
# dictionary of types from Tcl command, needs to be ordered
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str),
|
||||||
|
('tooldia', float),
|
||||||
|
('overlap', float)
|
||||||
|
])
|
||||||
|
|
||||||
|
# dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
('outname', str),
|
||||||
|
('all', bool),
|
||||||
|
('x', float),
|
||||||
|
('y', float)
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name', 'tooldia', 'overlap']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Paint polygons",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the source Geometry object.'),
|
||||||
|
('tooldia', 'Diameter of the tool to be used.'),
|
||||||
|
('overlap', 'Fraction of the tool diameter to overlap cuts.'),
|
||||||
|
('outname', 'Name of the resulting Geometry object.'),
|
||||||
|
('all', 'Paint all polygons in the object.'),
|
||||||
|
('x', 'X value of coordinate for the selection of a single polygon.'),
|
||||||
|
('y', 'Y value of coordinate for the selection of a single polygon.')
|
||||||
|
]),
|
||||||
|
'examples': []
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
execute current TCL shell command
|
||||||
|
|
||||||
|
:param args: array of known named arguments and options
|
||||||
|
:param unnamed_args: array of other values which were passed into command
|
||||||
|
without -somename and we do not have them in known arg_names
|
||||||
|
:return: None or exception
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = args['name']
|
||||||
|
tooldia = args['tooldia']
|
||||||
|
overlap = args['overlap']
|
||||||
|
|
||||||
|
if 'outname' in args:
|
||||||
|
outname = args['outname']
|
||||||
|
else:
|
||||||
|
outname = name + "_paint"
|
||||||
|
|
||||||
|
obj = self.app.collection.get_by_name(name)
|
||||||
|
if obj is None:
|
||||||
|
self.raise_tcl_error("Object not found: %s" % name)
|
||||||
|
|
||||||
|
if not isinstance(obj, Geometry):
|
||||||
|
self.raise_tcl_error('Expected Geometry, got %s %s.' % (name, type(obj)))
|
||||||
|
|
||||||
|
if 'all' in args and args['all']:
|
||||||
|
obj.paint_poly_all(tooldia, overlap, outname)
|
||||||
|
return
|
||||||
|
|
||||||
|
if 'x' not in args or 'y' not in args:
|
||||||
|
self.raise_tcl_error('Expected -all 1 or -x <value> and -y <value>.')
|
||||||
|
|
||||||
|
x = args['x']
|
||||||
|
y = args['y']
|
||||||
|
|
||||||
|
obj.paint_poly_single_click([x, y], tooldia, overlap, outname)
|
||||||
|
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@ import tclCommands.TclCommandInteriors
|
|||||||
import tclCommands.TclCommandIsolate
|
import tclCommands.TclCommandIsolate
|
||||||
import tclCommands.TclCommandNew
|
import tclCommands.TclCommandNew
|
||||||
import tclCommands.TclCommandOpenGerber
|
import tclCommands.TclCommandOpenGerber
|
||||||
|
import tclCommands.TclCommandPaint
|
||||||
|
|
||||||
|
|
||||||
__all__ = []
|
__all__ = []
|
||||||
|
|||||||
Reference in New Issue
Block a user