Bringing up to date with VisPyCanvas. Mostly migration of Tcl commands to new architecture.
This commit is contained in:
2946
FlatCAMApp.py
2946
FlatCAMApp.py
File diff suppressed because it is too large
Load Diff
@@ -77,12 +77,12 @@ class FlatCAMGUI(QtGui.QMainWindow):
|
|||||||
self.menufile.addAction(self.menufilesavedefaults)
|
self.menufile.addAction(self.menufilesavedefaults)
|
||||||
|
|
||||||
# Quit
|
# Quit
|
||||||
exit_action = QtGui.QAction(QtGui.QIcon('share/power16.png'), '&Exit', self)
|
self.exit_action = QtGui.QAction(QtGui.QIcon('share/power16.png'), '&Exit', self)
|
||||||
# exitAction.setShortcut('Ctrl+Q')
|
# exitAction.setShortcut('Ctrl+Q')
|
||||||
# exitAction.setStatusTip('Exit application')
|
# exitAction.setStatusTip('Exit application')
|
||||||
exit_action.triggered.connect(QtGui.qApp.quit)
|
#self.exit_action.triggered.connect(QtGui.qApp.quit)
|
||||||
|
|
||||||
self.menufile.addAction(exit_action)
|
self.menufile.addAction(self.exit_action)
|
||||||
|
|
||||||
### Edit ###
|
### Edit ###
|
||||||
self.menuedit = self.menu.addMenu('&Edit')
|
self.menuedit = self.menu.addMenu('&Edit')
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ class TclCommand(object):
|
|||||||
return "\t[" + option_symbol + help_key + " <" + type_name + ">: " + help_text + "]"
|
return "\t[" + option_symbol + help_key + " <" + type_name + ">: " + help_text + "]"
|
||||||
|
|
||||||
def get_decorated_example(example_item):
|
def get_decorated_example(example_item):
|
||||||
return "> "+example_item
|
return "> " + example_item
|
||||||
|
|
||||||
help_string = [self.help['main']]
|
help_string = [self.help['main']]
|
||||||
for alias in self.aliases:
|
for alias in self.aliases:
|
||||||
@@ -214,7 +214,6 @@ class TclCommand(object):
|
|||||||
|
|
||||||
return named_args, unnamed_args
|
return named_args, unnamed_args
|
||||||
|
|
||||||
|
|
||||||
def raise_tcl_unknown_error(self, unknownException):
|
def raise_tcl_unknown_error(self, unknownException):
|
||||||
"""
|
"""
|
||||||
raise Exception if is different type than TclErrorException
|
raise Exception if is different type than TclErrorException
|
||||||
@@ -253,11 +252,11 @@ class TclCommand(object):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
self.log.debug("TCL command '%s' executed." % str(self.__class__))
|
self.log.debug("TCL command '%s' executed." % str(self.__class__))
|
||||||
self.original_args=args
|
self.original_args = args
|
||||||
args, unnamed_args = self.check_args(args)
|
args, unnamed_args = self.check_args(args)
|
||||||
return self.execute(args, unnamed_args)
|
return self.execute(args, unnamed_args)
|
||||||
except Exception as unknown:
|
except Exception as unknown:
|
||||||
error_info=sys.exc_info()
|
error_info = sys.exc_info()
|
||||||
self.log.error("TCL command '%s' failed." % str(self))
|
self.log.error("TCL command '%s' failed." % str(self))
|
||||||
self.app.display_tcl_error(unknown, error_info)
|
self.app.display_tcl_error(unknown, error_info)
|
||||||
self.raise_tcl_unknown_error(unknown)
|
self.raise_tcl_unknown_error(unknown)
|
||||||
@@ -276,6 +275,7 @@ class TclCommand(object):
|
|||||||
|
|
||||||
raise NotImplementedError("Please Implement this method")
|
raise NotImplementedError("Please Implement this method")
|
||||||
|
|
||||||
|
|
||||||
class TclCommandSignaled(TclCommand):
|
class TclCommandSignaled(TclCommand):
|
||||||
"""
|
"""
|
||||||
!!! I left it here only for demonstration !!!
|
!!! I left it here only for demonstration !!!
|
||||||
@@ -297,12 +297,12 @@ class TclCommandSignaled(TclCommand):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
self.output = None
|
self.output = None
|
||||||
self.error=None
|
self.error = None
|
||||||
self.error_info=None
|
self.error_info = None
|
||||||
self.output = self.execute(args, unnamed_args)
|
self.output = self.execute(args, unnamed_args)
|
||||||
except Exception as unknown:
|
except Exception as unknown:
|
||||||
self.error_info = sys.exc_info()
|
self.error_info = sys.exc_info()
|
||||||
self.error=unknown
|
self.error = unknown
|
||||||
finally:
|
finally:
|
||||||
self.app.shell_command_finished.emit(self)
|
self.app.shell_command_finished.emit(self)
|
||||||
|
|
||||||
@@ -357,17 +357,19 @@ class TclCommandSignaled(TclCommand):
|
|||||||
raise ex[0]
|
raise ex[0]
|
||||||
|
|
||||||
if status['timed_out']:
|
if status['timed_out']:
|
||||||
self.app.raise_tcl_unknown_error("Operation timed outed! Consider increasing option '-timeout <miliseconds>' for command or 'set_sys background_timeout <miliseconds>'.")
|
self.app.raise_tcl_unknown_error("Operation timed outed! Consider increasing option "
|
||||||
|
"'-timeout <miliseconds>' for command or "
|
||||||
|
"'set_sys background_timeout <miliseconds>'.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.log.debug("TCL command '%s' executed." % str(self.__class__))
|
self.log.debug("TCL command '%s' executed." % str(self.__class__))
|
||||||
self.original_args=args
|
self.original_args = args
|
||||||
args, unnamed_args = self.check_args(args)
|
args, unnamed_args = self.check_args(args)
|
||||||
if 'timeout' in args:
|
if 'timeout' in args:
|
||||||
passed_timeout=args['timeout']
|
passed_timeout = args['timeout']
|
||||||
del args['timeout']
|
del args['timeout']
|
||||||
else:
|
else:
|
||||||
passed_timeout= self.app.defaults['background_timeout']
|
passed_timeout = self.app.defaults['background_timeout']
|
||||||
|
|
||||||
# set detail for processing, it will be there until next open or close
|
# set detail for processing, it will be there until next open or close
|
||||||
self.app.shell.open_proccessing(self.get_current_command())
|
self.app.shell.open_proccessing(self.get_current_command())
|
||||||
@@ -392,7 +394,7 @@ class TclCommandSignaled(TclCommand):
|
|||||||
if self.error_info is not None:
|
if self.error_info is not None:
|
||||||
error_info = self.error_info
|
error_info = self.error_info
|
||||||
else:
|
else:
|
||||||
error_info=sys.exc_info()
|
error_info = sys.exc_info()
|
||||||
self.log.error("TCL command '%s' failed." % str(self))
|
self.log.error("TCL command '%s' failed." % str(self))
|
||||||
self.app.display_tcl_error(unknown, error_info)
|
self.app.display_tcl_error(unknown, error_info)
|
||||||
self.raise_tcl_unknown_error(unknown)
|
self.raise_tcl_unknown_error(unknown)
|
||||||
65
tclCommands/TclCommandAddCircle.py
Normal file
65
tclCommands/TclCommandAddCircle.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandAddCircle(TclCommand.TclCommand):
|
||||||
|
"""
|
||||||
|
Tcl shell command to creates a circle in the given Geometry object.
|
||||||
|
|
||||||
|
example:
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['export_svg']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str),
|
||||||
|
('center_x', float),
|
||||||
|
('center_y', float),
|
||||||
|
('radius', float)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name', 'center_x', 'center_y', 'radius']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Creates a circle in the given Geometry object.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the geometry object to which to append the circle.'),
|
||||||
|
('center_x', 'X coordinate of the center of the circle.'),
|
||||||
|
('center_y', 'Y coordinates of the center of the circle.'),
|
||||||
|
('radius', 'Radius of the circle.')
|
||||||
|
]),
|
||||||
|
'examples': []
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param args:
|
||||||
|
:param unnamed_args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = args['name']
|
||||||
|
center_x = args['center_x']
|
||||||
|
center_y = args['center_y']
|
||||||
|
radius = args['radius']
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj = self.collection.get_by_name(name)
|
||||||
|
except:
|
||||||
|
return "Could not retrieve object: %s" % name
|
||||||
|
if obj is None:
|
||||||
|
return "Object not found: %s" % name
|
||||||
|
|
||||||
|
obj.add_circle([float(center_x), float(center_y)], float(radius))
|
||||||
|
|
||||||
66
tclCommands/TclCommandAddRectangle.py
Normal file
66
tclCommands/TclCommandAddRectangle.py
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandAddRectangle(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Tcl shell command to add a rectange to the given Geometry object.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['add_rectangle']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For positional arguments
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str),
|
||||||
|
('x0', float),
|
||||||
|
('y0', float),
|
||||||
|
('x1', float),
|
||||||
|
('y1', float)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name', 'x0', 'y0', 'x1', 'y1']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Add a rectange to the given Geometry object.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the Geometry object in which to add the rectangle.'),
|
||||||
|
('x0 y0', 'Bottom left corner coordinates.'),
|
||||||
|
('x1 y1', 'Top right corner coordinates.')
|
||||||
|
]),
|
||||||
|
'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
|
||||||
|
"""
|
||||||
|
|
||||||
|
obj_name = args['name']
|
||||||
|
x0 = args['x0']
|
||||||
|
y0 = args['y0']
|
||||||
|
x1 = args['x1']
|
||||||
|
y1 = args['y1']
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj = self.app.collection.get_by_name(str(obj_name))
|
||||||
|
except:
|
||||||
|
return "Could not retrieve object: %s" % obj_name
|
||||||
|
if obj is None:
|
||||||
|
return "Object not found: %s" % obj_name
|
||||||
|
|
||||||
|
obj.add_polygon([(x0, y0), (x1, y0), (x1, y1), (x0, y1)])
|
||||||
201
tclCommands/TclCommandAlignDrill.py
Normal file
201
tclCommands/TclCommandAlignDrill.py
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandAlignDrill(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Tcl shell command to create excellon with drills for aligment.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# array of all command aliases, to be able use old names for
|
||||||
|
# backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['aligndrill']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For positional arguments
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
('box', str),
|
||||||
|
('axis', str),
|
||||||
|
('holes', str),
|
||||||
|
('grid', float),
|
||||||
|
('minoffset', float),
|
||||||
|
('gridoffset', float),
|
||||||
|
('axisoffset', float),
|
||||||
|
('dia', float),
|
||||||
|
('dist', float),
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name', 'axis']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Create excellon with drills for aligment.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the object (Gerber or Excellon) to mirror.'),
|
||||||
|
('dia', 'Tool diameter'),
|
||||||
|
('box', 'Name of object which act as box (cutout for example.)'),
|
||||||
|
('grid', 'Aligning to grid, for those, who have aligning pins'
|
||||||
|
'inside table in grid (-5,0),(5,0),(15,0)...'),
|
||||||
|
('gridoffset', 'offset of grid from 0 position.'),
|
||||||
|
('minoffset', 'min and max distance between align hole and pcb.'),
|
||||||
|
('axisoffset', 'Offset on second axis before aligment holes'),
|
||||||
|
('axis', 'Mirror axis parallel to the X or Y axis.'),
|
||||||
|
('dist', 'Distance of the mirror axis to the X or Y axis.')
|
||||||
|
]),
|
||||||
|
'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']
|
||||||
|
|
||||||
|
# Get source object.
|
||||||
|
try:
|
||||||
|
obj = self.app.collection.get_by_name(str(name))
|
||||||
|
except:
|
||||||
|
return "Could not retrieve object: %s" % name
|
||||||
|
|
||||||
|
if obj is None:
|
||||||
|
return "Object not found: %s" % name
|
||||||
|
|
||||||
|
if not isinstance(obj, FlatCAMGeometry) and \
|
||||||
|
not isinstance(obj, FlatCAMGerber) and \
|
||||||
|
not isinstance(obj, FlatCAMExcellon):
|
||||||
|
return "ERROR: Only Gerber, Geometry and Excellon objects can be used."
|
||||||
|
|
||||||
|
# Axis
|
||||||
|
try:
|
||||||
|
axis = args['axis'].upper()
|
||||||
|
except KeyError:
|
||||||
|
return "ERROR: Specify -axis X or -axis Y"
|
||||||
|
|
||||||
|
if not ('holes' in args or ('grid' in args and 'gridoffset' in args)):
|
||||||
|
return "ERROR: Specify -holes or -grid with -gridoffset "
|
||||||
|
|
||||||
|
if 'holes' in args:
|
||||||
|
try:
|
||||||
|
holes = eval("[" + args['holes'] + "]")
|
||||||
|
except KeyError:
|
||||||
|
return "ERROR: Wrong -holes format (X1,Y1),(X2,Y2)"
|
||||||
|
|
||||||
|
xscale, yscale = {"X": (1.0, -1.0), "Y": (-1.0, 1.0)}[axis]
|
||||||
|
|
||||||
|
# Tools
|
||||||
|
tools = {"1": {"C": args['dia']}}
|
||||||
|
|
||||||
|
def alligndrill_init_me(init_obj, app_obj):
|
||||||
|
"""
|
||||||
|
This function is used to initialize the new
|
||||||
|
object once it's created.
|
||||||
|
|
||||||
|
:param init_obj: The new object.
|
||||||
|
:param app_obj: The application (FlatCAMApp)
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
|
||||||
|
drills = []
|
||||||
|
if 'holes' in args:
|
||||||
|
for hole in holes:
|
||||||
|
point = Point(hole)
|
||||||
|
point_mirror = affinity.scale(point, xscale, yscale, origin=(px, py))
|
||||||
|
drills.append({"point": point, "tool": "1"})
|
||||||
|
drills.append({"point": point_mirror, "tool": "1"})
|
||||||
|
else:
|
||||||
|
if 'box' not in args:
|
||||||
|
return "ERROR: -grid can be used only for -box"
|
||||||
|
|
||||||
|
if 'axisoffset' in args:
|
||||||
|
axisoffset = args['axisoffset']
|
||||||
|
else:
|
||||||
|
axisoffset = 0
|
||||||
|
|
||||||
|
# This will align hole to given aligngridoffset and minimal offset from pcb, based on selected axis
|
||||||
|
if axis == "X":
|
||||||
|
firstpoint = args['gridoffset']
|
||||||
|
|
||||||
|
while (xmin - args['minoffset']) < firstpoint:
|
||||||
|
firstpoint = firstpoint - args['grid']
|
||||||
|
|
||||||
|
lastpoint = args['gridoffset']
|
||||||
|
|
||||||
|
while (xmax + args['minoffset']) > lastpoint:
|
||||||
|
lastpoint = lastpoint + args['grid']
|
||||||
|
|
||||||
|
localholes = (firstpoint, axisoffset), (lastpoint, axisoffset)
|
||||||
|
|
||||||
|
else:
|
||||||
|
firstpoint = args['gridoffset']
|
||||||
|
|
||||||
|
while (ymin - args['minoffset']) < firstpoint:
|
||||||
|
firstpoint = firstpoint - args['grid']
|
||||||
|
|
||||||
|
lastpoint = args['gridoffset']
|
||||||
|
|
||||||
|
while (ymax + args['minoffset']) > lastpoint:
|
||||||
|
lastpoint = lastpoint + args['grid']
|
||||||
|
|
||||||
|
localholes = (axisoffset, firstpoint), (axisoffset, lastpoint)
|
||||||
|
|
||||||
|
for hole in localholes:
|
||||||
|
point = Point(hole)
|
||||||
|
point_mirror = affinity.scale(point, xscale, yscale, origin=(px, py))
|
||||||
|
drills.append({"point": point, "tool": "1"})
|
||||||
|
drills.append({"point": point_mirror, "tool": "1"})
|
||||||
|
|
||||||
|
init_obj.tools = tools
|
||||||
|
init_obj.drills = drills
|
||||||
|
init_obj.create_geometry()
|
||||||
|
|
||||||
|
# Box
|
||||||
|
if 'box' in args:
|
||||||
|
try:
|
||||||
|
box = self.app.collection.get_by_name(args['box'])
|
||||||
|
except:
|
||||||
|
return "Could not retrieve object box: %s" % args['box']
|
||||||
|
|
||||||
|
if box is None:
|
||||||
|
return "Object box not found: %s" % args['box']
|
||||||
|
|
||||||
|
try:
|
||||||
|
xmin, ymin, xmax, ymax = box.bounds()
|
||||||
|
px = 0.5 * (xmin + xmax)
|
||||||
|
py = 0.5 * (ymin + ymax)
|
||||||
|
|
||||||
|
obj.app.new_object("excellon",
|
||||||
|
name + "_aligndrill",
|
||||||
|
alligndrill_init_me)
|
||||||
|
|
||||||
|
except Exception, e:
|
||||||
|
return "Operation failed: %s" % str(e)
|
||||||
|
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
dist = float(args['dist'])
|
||||||
|
except KeyError:
|
||||||
|
dist = 0.0
|
||||||
|
except ValueError:
|
||||||
|
return "Invalid distance: %s" % args['dist']
|
||||||
|
|
||||||
|
try:
|
||||||
|
px = dist
|
||||||
|
py = dist
|
||||||
|
obj.app.new_object("excellon", name + "_alligndrill", alligndrill_init_me)
|
||||||
|
except Exception, e:
|
||||||
|
return "Operation failed: %s" % str(e)
|
||||||
|
|
||||||
|
return 'Ok'
|
||||||
105
tclCommands/TclCommandAlignDrillGrid.py
Normal file
105
tclCommands/TclCommandAlignDrillGrid.py
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandAlignDrillGrid(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Tcl shell command to create an Excellon object
|
||||||
|
with drills for aligment grid.
|
||||||
|
|
||||||
|
Todo: What is an alignment grid?
|
||||||
|
"""
|
||||||
|
|
||||||
|
# array of all command aliases, to be able use old names for
|
||||||
|
# backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['aligndrillgrid']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For positional arguments
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('outname', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
('dia', float),
|
||||||
|
('gridx', float),
|
||||||
|
('gridxoffset', float),
|
||||||
|
('gridy', float),
|
||||||
|
('gridyoffset', float),
|
||||||
|
('columns', int),
|
||||||
|
('rows', int)
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['outname', 'gridx', 'gridy', 'columns', 'rows']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Create excellon with drills for aligment grid.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('outname', 'Name of the object to create.'),
|
||||||
|
('dia', 'Tool diameter.'),
|
||||||
|
('gridx', 'Grid size in X axis.'),
|
||||||
|
('gridoffsetx', 'Move grid from origin.'),
|
||||||
|
('gridy', 'Grid size in Y axis.'),
|
||||||
|
('gridoffsety', 'Move grid from origin.'),
|
||||||
|
('colums', 'Number of grid holes on X axis.'),
|
||||||
|
('rows', 'Number of grid holes on Y axis.'),
|
||||||
|
]),
|
||||||
|
'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
|
||||||
|
"""
|
||||||
|
|
||||||
|
if 'gridoffsetx' not in args:
|
||||||
|
gridoffsetx = 0
|
||||||
|
else:
|
||||||
|
gridoffsetx = args['gridoffsetx']
|
||||||
|
|
||||||
|
if 'gridoffsety' not in args:
|
||||||
|
gridoffsety = 0
|
||||||
|
else:
|
||||||
|
gridoffsety = args['gridoffsety']
|
||||||
|
|
||||||
|
# Tools
|
||||||
|
tools = {"1": {"C": args['dia']}}
|
||||||
|
|
||||||
|
def aligndrillgrid_init_me(init_obj, app_obj):
|
||||||
|
"""
|
||||||
|
This function is used to initialize the new
|
||||||
|
object once it's created.
|
||||||
|
|
||||||
|
:param init_obj: The new object.
|
||||||
|
:param app_obj: The application (FlatCAMApp)
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
|
||||||
|
drills = []
|
||||||
|
currenty = 0
|
||||||
|
|
||||||
|
for row in range(args['rows']):
|
||||||
|
currentx = 0
|
||||||
|
|
||||||
|
for col in range(args['columns']):
|
||||||
|
point = Point(currentx + gridoffsetx, currenty + gridoffsety)
|
||||||
|
drills.append({"point": point, "tool": "1"})
|
||||||
|
currentx = currentx + args['gridx']
|
||||||
|
|
||||||
|
currenty = currenty + args['gridy']
|
||||||
|
|
||||||
|
init_obj.tools = tools
|
||||||
|
init_obj.drills = drills
|
||||||
|
init_obj.create_geometry()
|
||||||
|
|
||||||
|
# Create the new object
|
||||||
|
self.new_object("excellon", args['outname'], aligndrillgrid_init_me)
|
||||||
@@ -24,14 +24,14 @@ class TclCommandCncjob(TclCommand.TclCommandSignaled):
|
|||||||
|
|
||||||
# dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
# dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
option_types = collections.OrderedDict([
|
option_types = collections.OrderedDict([
|
||||||
('z_cut',float),
|
('z_cut', float),
|
||||||
('z_move',float),
|
('z_move', float),
|
||||||
('feedrate',float),
|
('feedrate', float),
|
||||||
('tooldia',float),
|
('tooldia', float),
|
||||||
('spindlespeed',int),
|
('spindlespeed', int),
|
||||||
('multidepth',bool),
|
('multidepth', bool),
|
||||||
('depthperpass',float),
|
('depthperpass', float),
|
||||||
('outname',str)
|
('outname', str)
|
||||||
])
|
])
|
||||||
|
|
||||||
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
@@ -77,4 +77,4 @@ class TclCommandCncjob(TclCommand.TclCommandSignaled):
|
|||||||
self.raise_tcl_error('Expected FlatCAMGeometry, got %s %s.' % (name, type(obj)))
|
self.raise_tcl_error('Expected FlatCAMGeometry, got %s %s.' % (name, type(obj)))
|
||||||
|
|
||||||
del args['name']
|
del args['name']
|
||||||
obj.generatecncjob(use_thread = False, **args)
|
obj.generatecncjob(use_thread=False, **args)
|
||||||
|
|||||||
99
tclCommands/TclCommandCutout.py
Normal file
99
tclCommands/TclCommandCutout.py
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandCutout(TclCommand.TclCommand):
|
||||||
|
"""
|
||||||
|
Tcl shell command to create a board cutout geometry.
|
||||||
|
|
||||||
|
example:
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# List of all command aliases, to be able use old
|
||||||
|
# names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['cutout']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str),
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered,
|
||||||
|
# this is for options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
('dia', float),
|
||||||
|
('margin', float),
|
||||||
|
('gapsize', float),
|
||||||
|
('gaps', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': 'Creates board cutout.',
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the object.'),
|
||||||
|
('dia', 'Tool diameter.'),
|
||||||
|
('margin', 'Margin over bounds.'),
|
||||||
|
('gapsize', 'size of gap.'),
|
||||||
|
('gaps', 'type of gaps.'),
|
||||||
|
]),
|
||||||
|
'examples': []
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param args:
|
||||||
|
:param unnamed_args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = args['name']
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj = self.app.collection.get_by_name(str(name))
|
||||||
|
except:
|
||||||
|
return "Could not retrieve object: %s" % name
|
||||||
|
|
||||||
|
def geo_init_me(geo_obj, app_obj):
|
||||||
|
margin = args['margin'] + args['dia'] / 2
|
||||||
|
gap_size = args['dia'] + args['gapsize']
|
||||||
|
minx, miny, maxx, maxy = obj.bounds()
|
||||||
|
minx -= margin
|
||||||
|
maxx += margin
|
||||||
|
miny -= margin
|
||||||
|
maxy += margin
|
||||||
|
midx = 0.5 * (minx + maxx)
|
||||||
|
midy = 0.5 * (miny + maxy)
|
||||||
|
hgap = 0.5 * gap_size
|
||||||
|
pts = [[midx - hgap, maxy],
|
||||||
|
[minx, maxy],
|
||||||
|
[minx, midy + hgap],
|
||||||
|
[minx, midy - hgap],
|
||||||
|
[minx, miny],
|
||||||
|
[midx - hgap, miny],
|
||||||
|
[midx + hgap, miny],
|
||||||
|
[maxx, miny],
|
||||||
|
[maxx, midy - hgap],
|
||||||
|
[maxx, midy + hgap],
|
||||||
|
[maxx, maxy],
|
||||||
|
[midx + hgap, maxy]]
|
||||||
|
cases = {"tb": [[pts[0], pts[1], pts[4], pts[5]],
|
||||||
|
[pts[6], pts[7], pts[10], pts[11]]],
|
||||||
|
"lr": [[pts[9], pts[10], pts[1], pts[2]],
|
||||||
|
[pts[3], pts[4], pts[7], pts[8]]],
|
||||||
|
"4": [[pts[0], pts[1], pts[2]],
|
||||||
|
[pts[3], pts[4], pts[5]],
|
||||||
|
[pts[6], pts[7], pts[8]],
|
||||||
|
[pts[9], pts[10], pts[11]]]}
|
||||||
|
cuts = cases[args['gaps']]
|
||||||
|
geo_obj.solid_geometry = cascaded_union([LineString(segment) for segment in cuts])
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj.app.new_object("geometry", name + "_cutout", geo_init_me)
|
||||||
|
except Exception, e:
|
||||||
|
return "Operation failed: %s" % str(e)
|
||||||
54
tclCommands/TclCommandDelete.py
Normal file
54
tclCommands/TclCommandDelete.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandDelete(TclCommand.TclCommand):
|
||||||
|
"""
|
||||||
|
Tcl shell command to delete an object.
|
||||||
|
|
||||||
|
example:
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['delete']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str),
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': 'Deletes the given object.',
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the Object.'),
|
||||||
|
]),
|
||||||
|
'examples': []
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param args:
|
||||||
|
:param unnamed_args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
obj_name = args['name']
|
||||||
|
|
||||||
|
try:
|
||||||
|
# deselect all to avoid delete selected object when run delete from shell
|
||||||
|
self.app.collection.set_all_inactive()
|
||||||
|
self.app.collection.set_active(str(obj_name))
|
||||||
|
self.app.on_delete() # Todo: This is an event handler for the GUI... bad?
|
||||||
|
except Exception as e:
|
||||||
|
return "Command failed: %s" % str(e)
|
||||||
@@ -17,13 +17,13 @@ class TclCommandDrillcncjob(TclCommand.TclCommandSignaled):
|
|||||||
|
|
||||||
# dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
# dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
option_types = collections.OrderedDict([
|
option_types = collections.OrderedDict([
|
||||||
('tools',str),
|
('tools', str),
|
||||||
('drillz',float),
|
('drillz', float),
|
||||||
('travelz',float),
|
('travelz', float),
|
||||||
('feedrate',float),
|
('feedrate', float),
|
||||||
('spindlespeed',int),
|
('spindlespeed', int),
|
||||||
('toolchange',bool),
|
('toolchange', bool),
|
||||||
('outname',str)
|
('outname', str)
|
||||||
])
|
])
|
||||||
|
|
||||||
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
|||||||
53
tclCommands/TclCommandExportSVG.py
Normal file
53
tclCommands/TclCommandExportSVG.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandExportSVG(TclCommand.TclCommand):
|
||||||
|
"""
|
||||||
|
Tcl shell command to export a Geometry Object as an SVG File.
|
||||||
|
|
||||||
|
example:
|
||||||
|
export_svg my_geometry filename
|
||||||
|
"""
|
||||||
|
|
||||||
|
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['export_svg']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str),
|
||||||
|
('filename', str),
|
||||||
|
('scale_factor', float)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name', 'filename']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Export a Geometry Object as a SVG File.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the object export.'),
|
||||||
|
('filename', 'Path to the file to export.'),
|
||||||
|
('scale_factor', 'Multiplication factor used for scaling line widths during export.')
|
||||||
|
]),
|
||||||
|
'examples': ['export_svg my_geometry my_file.svg']
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param args:
|
||||||
|
:param unnamed_args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = args['name']
|
||||||
|
filename = args['filename']
|
||||||
|
|
||||||
|
self.app.export_svg(name, filename, **args)
|
||||||
118
tclCommands/TclCommandGeoCutout.py
Normal file
118
tclCommands/TclCommandGeoCutout.py
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandGeoCutout(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Tcl shell command to cut holding gaps from geometry.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['geocutout']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For positional arguments
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
('dia', float),
|
||||||
|
('margin', float),
|
||||||
|
('gapsize', float),
|
||||||
|
('gaps', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Cut holding gaps from geometry.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the geometry object.'),
|
||||||
|
('dia', 'Tool diameter.'),
|
||||||
|
('margin', 'Margin over bounds.'),
|
||||||
|
('gapsize', 'Size of gap.'),
|
||||||
|
('gaps', 'Type of gaps.'),
|
||||||
|
]),
|
||||||
|
'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
|
||||||
|
"""
|
||||||
|
|
||||||
|
# How gaps wil be rendered:
|
||||||
|
# lr - left + right
|
||||||
|
# tb - top + bottom
|
||||||
|
# 4 - left + right +top + bottom
|
||||||
|
# 2lr - 2*left + 2*right
|
||||||
|
# 2tb - 2*top + 2*bottom
|
||||||
|
# 8 - 2*left + 2*right +2*top + 2*bottom
|
||||||
|
|
||||||
|
name = args['name']
|
||||||
|
obj = None
|
||||||
|
|
||||||
|
def subtract_rectangle(obj_, x0, y0, x1, y1):
|
||||||
|
pts = [(x0, y0), (x1, y0), (x1, y1), (x0, y1)]
|
||||||
|
obj_.subtract_polygon(pts)
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj = self.app.collection.get_by_name(str(name))
|
||||||
|
except:
|
||||||
|
self.raise_tcl_error("Could not retrieve object: %s" % name)
|
||||||
|
|
||||||
|
# Get min and max data for each object as we just cut rectangles across X or Y
|
||||||
|
xmin, ymin, xmax, ymax = obj.bounds()
|
||||||
|
px = 0.5 * (xmin + xmax)
|
||||||
|
py = 0.5 * (ymin + ymax)
|
||||||
|
lenghtx = (xmax - xmin)
|
||||||
|
lenghty = (ymax - ymin)
|
||||||
|
gapsize = args['gapsize'] + args['dia'] / 2
|
||||||
|
|
||||||
|
if args['gaps'] == '8' or args['gaps'] == '2lr':
|
||||||
|
subtract_rectangle(obj,
|
||||||
|
xmin - gapsize, # botleft_x
|
||||||
|
py - gapsize + lenghty / 4, # botleft_y
|
||||||
|
xmax + gapsize, # topright_x
|
||||||
|
py + gapsize + lenghty / 4) # topright_y
|
||||||
|
subtract_rectangle(obj,
|
||||||
|
xmin - gapsize,
|
||||||
|
py - gapsize - lenghty / 4,
|
||||||
|
xmax + gapsize,
|
||||||
|
py + gapsize - lenghty / 4)
|
||||||
|
|
||||||
|
if args['gaps'] == '8' or args['gaps'] == '2tb':
|
||||||
|
subtract_rectangle(obj,
|
||||||
|
px - gapsize + lenghtx / 4,
|
||||||
|
ymin - gapsize,
|
||||||
|
px + gapsize + lenghtx / 4,
|
||||||
|
ymax + gapsize)
|
||||||
|
subtract_rectangle(obj,
|
||||||
|
px - gapsize - lenghtx / 4,
|
||||||
|
ymin - gapsize,
|
||||||
|
px + gapsize - lenghtx / 4,
|
||||||
|
ymax + gapsize)
|
||||||
|
|
||||||
|
if args['gaps'] == '4' or args['gaps'] == 'lr':
|
||||||
|
subtract_rectangle(obj,
|
||||||
|
xmin - gapsize,
|
||||||
|
py - gapsize,
|
||||||
|
xmax + gapsize,
|
||||||
|
py + gapsize)
|
||||||
|
|
||||||
|
if args['gaps'] == '4' or args['gaps'] == 'tb':
|
||||||
|
subtract_rectangle(obj,
|
||||||
|
px - gapsize,
|
||||||
|
ymin - gapsize,
|
||||||
|
px + gapsize,
|
||||||
|
ymax + gapsize)
|
||||||
59
tclCommands/TclCommandGeoUnion.py
Normal file
59
tclCommands/TclCommandGeoUnion.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandGeoUnion(TclCommand.TclCommand):
|
||||||
|
"""
|
||||||
|
Tcl shell command to run a union (addition) operation on the
|
||||||
|
components of a geometry object.
|
||||||
|
|
||||||
|
example:
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['geo_union']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str),
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': ('Runs a union operation (addition) on the components '
|
||||||
|
'of the geometry object. For example, if it contains '
|
||||||
|
'2 intersecting polygons, this opperation adds them into'
|
||||||
|
'a single larger polygon.'),
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the Geometry Object.'),
|
||||||
|
]),
|
||||||
|
'examples': []
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param args:
|
||||||
|
:param unnamed_args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
obj_name = args['name']
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj = self.collection.get_by_name(str(obj_name))
|
||||||
|
except:
|
||||||
|
return "Could not retrieve object: %s" % obj_name
|
||||||
|
if obj is None:
|
||||||
|
return "Object not found: %s" % obj_name
|
||||||
|
|
||||||
|
obj.union()
|
||||||
46
tclCommands/TclCommandGetNames.py
Normal file
46
tclCommands/TclCommandGetNames.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandGetNames(TclCommand.TclCommand):
|
||||||
|
"""
|
||||||
|
Tcl shell command to set an object as active in the GUI.
|
||||||
|
|
||||||
|
example:
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['get_names']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = []
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': 'Lists the names of objects in the project.',
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
|
||||||
|
]),
|
||||||
|
'examples': []
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param args:
|
||||||
|
:param unnamed_args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
return '\n'.join(self.app.collection.get_names())
|
||||||
@@ -24,11 +24,11 @@ class TclCommandIsolate(TclCommand.TclCommandSignaled):
|
|||||||
|
|
||||||
# dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
# dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
option_types = collections.OrderedDict([
|
option_types = collections.OrderedDict([
|
||||||
('dia',float),
|
('dia', float),
|
||||||
('passes',int),
|
('passes', int),
|
||||||
('overlap',float),
|
('overlap', float),
|
||||||
('combine',int),
|
('combine', int),
|
||||||
('outname',str)
|
('outname', str)
|
||||||
])
|
])
|
||||||
|
|
||||||
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
|||||||
64
tclCommands/TclCommandJoinExcellon.py
Normal file
64
tclCommands/TclCommandJoinExcellon.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandJoinExcellon(TclCommand.TclCommand):
|
||||||
|
"""
|
||||||
|
Tcl shell command to merge Excellon objects.
|
||||||
|
|
||||||
|
example:
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['join_excellon', 'join_excellons']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('outname', str),
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['outname']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Runs a merge operation (join) on the Excellon objects.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the new Excellon Object.'),
|
||||||
|
('obj_name_0', 'Name of the first object'),
|
||||||
|
('obj_name_1', 'Name of the second object.'),
|
||||||
|
('obj_name_2...', 'Additional object names')
|
||||||
|
]),
|
||||||
|
'examples': []
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param args:
|
||||||
|
:param unnamed_args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
outname = args['name']
|
||||||
|
obj_names = unnamed_args
|
||||||
|
|
||||||
|
objs = []
|
||||||
|
for obj_n in obj_names:
|
||||||
|
obj = self.app.collection.get_by_name(str(obj_n))
|
||||||
|
if obj is None:
|
||||||
|
return "Object not found: %s" % obj_n
|
||||||
|
else:
|
||||||
|
objs.append(obj)
|
||||||
|
|
||||||
|
def initialize(obj_, app):
|
||||||
|
FlatCAMExcellon.merge(objs, obj_)
|
||||||
|
|
||||||
|
if objs is not None:
|
||||||
|
self.app.new_object("excellon", outname, initialize)
|
||||||
64
tclCommands/TclCommandJoinGeometry.py
Normal file
64
tclCommands/TclCommandJoinGeometry.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandJoinGeometry(TclCommand.TclCommand):
|
||||||
|
"""
|
||||||
|
Tcl shell command to merge Excellon objects.
|
||||||
|
|
||||||
|
example:
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['join_geometries', 'join_geometry']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('outname', str),
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['outname']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Runs a merge operation (join) on the Excellon objects.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('outname', 'Name of the new Geometry Object.'),
|
||||||
|
('obj_name_0', 'Name of the first object'),
|
||||||
|
('obj_name_1', 'Name of the second object.'),
|
||||||
|
('obj_name_2...', 'Additional object names')
|
||||||
|
]),
|
||||||
|
'examples': []
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param args:
|
||||||
|
:param unnamed_args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
outname = args['name']
|
||||||
|
obj_names = unnamed_args
|
||||||
|
|
||||||
|
objs = []
|
||||||
|
for obj_n in obj_names:
|
||||||
|
obj = self.app.collection.get_by_name(str(obj_n))
|
||||||
|
if obj is None:
|
||||||
|
return "Object not found: %s" % obj_n
|
||||||
|
else:
|
||||||
|
objs.append(obj)
|
||||||
|
|
||||||
|
def initialize(obj_, app):
|
||||||
|
FlatCAMGeometry.merge(objs, obj_)
|
||||||
|
|
||||||
|
if objs is not None:
|
||||||
|
self.app.new_object("geometry", outname, initialize)
|
||||||
77
tclCommands/TclCommandMillHoles.py
Normal file
77
tclCommands/TclCommandMillHoles.py
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandMillHoles(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Tcl shell command to Create Geometry Object for milling holes from Excellon.
|
||||||
|
|
||||||
|
example:
|
||||||
|
millholes my_drill -tools 1,2,3 -tooldia 0.1 -outname mill_holes_geo
|
||||||
|
"""
|
||||||
|
|
||||||
|
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['millholes']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str),
|
||||||
|
('tools', str),
|
||||||
|
('tooldia', float),
|
||||||
|
('outname', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Create Geometry Object for milling holes from Excellon.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the Excellon Object.'),
|
||||||
|
('tools', 'Comma separated indexes of tools (example: 1,3 or 2).'),
|
||||||
|
('tooldia', 'Diameter of the milling tool (example: 0.1).'),
|
||||||
|
('outname', 'Name of object to create.')
|
||||||
|
]),
|
||||||
|
'examples': ['scale my_geometry 4.2']
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param args:
|
||||||
|
:param unnamed_args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = args['name']
|
||||||
|
|
||||||
|
try:
|
||||||
|
if 'tools' in args:
|
||||||
|
# Split and put back. We are passing the whole dictionary later.
|
||||||
|
args['tools'] = [x.strip() for x in args['tools'].split(",")]
|
||||||
|
except Exception as e:
|
||||||
|
self.raise_tcl_error("Bad tools: %s" % str(e))
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj = self.app.collection.get_by_name(str(name))
|
||||||
|
except:
|
||||||
|
self.raise_tcl_error("Could not retrieve object: %s" % name)
|
||||||
|
|
||||||
|
if not isinstance(obj, FlatCAMExcellon):
|
||||||
|
self.raise_tcl_error('Only Excellon objects can be mill-drilled, got %s %s.' % (name, type(obj)))
|
||||||
|
|
||||||
|
try:
|
||||||
|
# This runs in the background... Is blocking handled?
|
||||||
|
success, msg = obj.generate_milling(**args)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.raise_tcl_error("Operation failed: %s" % str(e))
|
||||||
|
|
||||||
|
if not success:
|
||||||
|
self.raise_tcl_error(msg)
|
||||||
108
tclCommands/TclCommandMirror.py
Normal file
108
tclCommands/TclCommandMirror.py
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandMirror(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Tcl shell command to mirror an object.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# array of all command aliases, to be able use
|
||||||
|
# old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['mirror']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For positional arguments
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
('axis', str),
|
||||||
|
('box', str),
|
||||||
|
('dist', float)
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name', 'axis']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Opens an Excellon file.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the object (Gerber or Excellon) to mirror.'),
|
||||||
|
('box', 'Name of object which act as box (cutout for example.)'),
|
||||||
|
('axis', 'Mirror axis parallel to the X or Y axis.'),
|
||||||
|
('dist', 'Distance of the mirror axis to the X or Y axis.')
|
||||||
|
]),
|
||||||
|
'examples': []
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
Execute this 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']
|
||||||
|
|
||||||
|
# Get source object.
|
||||||
|
try:
|
||||||
|
obj = self.app.collection.get_by_name(str(name))
|
||||||
|
except:
|
||||||
|
return "Could not retrieve object: %s" % name
|
||||||
|
|
||||||
|
if obj is None:
|
||||||
|
return "Object not found: %s" % name
|
||||||
|
|
||||||
|
if not isinstance(obj, FlatCAMGerber) and \
|
||||||
|
not isinstance(obj, FlatCAMExcellon) and \
|
||||||
|
not isinstance(obj, FlatCAMGeometry):
|
||||||
|
return "ERROR: Only Gerber, Excellon and Geometry objects can be mirrored."
|
||||||
|
|
||||||
|
# Axis
|
||||||
|
try:
|
||||||
|
axis = args['axis'].upper()
|
||||||
|
except KeyError:
|
||||||
|
return "ERROR: Specify -axis X or -axis Y"
|
||||||
|
|
||||||
|
# Box
|
||||||
|
if 'box' in args:
|
||||||
|
try:
|
||||||
|
box = self.app.collection.get_by_name(args['box'])
|
||||||
|
except:
|
||||||
|
return "Could not retrieve object box: %s" % args['box']
|
||||||
|
|
||||||
|
if box is None:
|
||||||
|
return "Object box not found: %s" % args['box']
|
||||||
|
|
||||||
|
try:
|
||||||
|
xmin, ymin, xmax, ymax = box.bounds()
|
||||||
|
px = 0.5 * (xmin + xmax)
|
||||||
|
py = 0.5 * (ymin + ymax)
|
||||||
|
|
||||||
|
obj.mirror(axis, [px, py])
|
||||||
|
obj.plot()
|
||||||
|
|
||||||
|
except Exception, e:
|
||||||
|
return "Operation failed: %s" % str(e)
|
||||||
|
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
dist = float(args['dist'])
|
||||||
|
except KeyError:
|
||||||
|
dist = 0.0
|
||||||
|
except ValueError:
|
||||||
|
return "Invalid distance: %s" % args['dist']
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj.mirror(axis, [dist, dist])
|
||||||
|
obj.plot()
|
||||||
|
except Exception, e:
|
||||||
|
return "Operation failed: %s" % str(e)
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
from ObjectCollection import *
|
from ObjectCollection import *
|
||||||
from PyQt4 import QtCore
|
|
||||||
import TclCommand
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
@@ -23,7 +22,7 @@ class TclCommandNew(TclCommand.TclCommand):
|
|||||||
# structured help for current command, args needs to be ordered
|
# structured help for current command, args needs to be ordered
|
||||||
help = {
|
help = {
|
||||||
'main': "Starts a new project. Clears objects from memory.",
|
'main': "Starts a new project. Clears objects from memory.",
|
||||||
'args': collections.OrderedDict(),
|
'args': collections.OrderedDict(),
|
||||||
'examples': []
|
'examples': []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
49
tclCommands/TclCommandNewGeometry.py
Normal file
49
tclCommands/TclCommandNewGeometry.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandNewGeometry(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Tcl shell command to subtract polygon from the given Geometry object.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['new_geometry']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For positional arguments
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Creates a new empty geometry object.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'New object name.'),
|
||||||
|
]),
|
||||||
|
'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']
|
||||||
|
|
||||||
|
self.app.new_object('geometry', str(name), lambda x, y: None)
|
||||||
53
tclCommands/TclCommandOffset.py
Normal file
53
tclCommands/TclCommandOffset.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandOffset(TclCommand.TclCommand):
|
||||||
|
"""
|
||||||
|
Tcl shell command to change the position of the object.
|
||||||
|
|
||||||
|
example:
|
||||||
|
offset my_geometry 1.2 -0.3
|
||||||
|
"""
|
||||||
|
|
||||||
|
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['offset']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str),
|
||||||
|
('x', float),
|
||||||
|
('y', float)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name', 'x', 'y']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Changes the position of the object.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the object to offset.'),
|
||||||
|
('x', 'Offset distance in the X axis.'),
|
||||||
|
('y', 'Offset distance in the Y axis')
|
||||||
|
]),
|
||||||
|
'examples': ['offset my_geometry 1.2 -0.3']
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param args:
|
||||||
|
:param unnamed_args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = args['name']
|
||||||
|
x, y = args['x'], args['y']
|
||||||
|
|
||||||
|
self.app.collection.get_by_name(name).offset(x, y)
|
||||||
48
tclCommands/TclCommandOpenExcellon.py
Normal file
48
tclCommands/TclCommandOpenExcellon.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandOpenExcellon(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Tcl shell command to open an Excellon file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['open_gerber']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For positional arguments
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('filename', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
('outname', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['filename']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Opens an Excellon file.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('filename', 'Path to file to open.'),
|
||||||
|
('outname', 'Name of the resulting Excellon object.')
|
||||||
|
]),
|
||||||
|
'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
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.app.open_excellon(args['filename'], **args)
|
||||||
49
tclCommands/TclCommandOpenGCode.py
Normal file
49
tclCommands/TclCommandOpenGCode.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandOpenGCode(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Tcl shell command to open a G-Code file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# array of all command aliases, to be able use old names for
|
||||||
|
# backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['open_gcode']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For positional arguments
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('filename', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
('outname', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['filename']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Opens a G-Code file.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('filename', 'Path to file to open.'),
|
||||||
|
('outname', 'Name of the resulting CNCJob object.')
|
||||||
|
]),
|
||||||
|
'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
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.app.open_gcode(args['filename'], **args)
|
||||||
@@ -27,10 +27,10 @@ class TclCommandOpenGerber(TclCommand.TclCommandSignaled):
|
|||||||
# structured help for current command, args needs to be ordered
|
# structured help for current command, args needs to be ordered
|
||||||
help = {
|
help = {
|
||||||
'main': "Opens a Gerber file.",
|
'main': "Opens a Gerber file.",
|
||||||
'args': collections.OrderedDict([
|
'args': collections.OrderedDict([
|
||||||
('filename', 'Path to file to open.'),
|
('filename', 'Path to file to open.'),
|
||||||
('follow', 'N If 1, does not create polygons, just follows the gerber path.'),
|
('follow', 'N If 1, does not create polygons, just follows the gerber path.'),
|
||||||
('outname', 'Name of the resulting Geometry object.')
|
('outname', 'Name of the resulting Gerber object.')
|
||||||
]),
|
]),
|
||||||
'examples': []
|
'examples': []
|
||||||
}
|
}
|
||||||
|
|||||||
47
tclCommands/TclCommandOpenProject.py
Normal file
47
tclCommands/TclCommandOpenProject.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandOpenProject(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Tcl shell command to open a FlatCAM project.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['open_project']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For positional arguments
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('filename', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['filename']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Opens a FlatCAM project.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('filename', 'Path to file to open.'),
|
||||||
|
]),
|
||||||
|
'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
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.app.open_project(args['filename'])
|
||||||
50
tclCommands/TclCommandOptions.py
Normal file
50
tclCommands/TclCommandOptions.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandOptions(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Tcl shell command to open an Excellon file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['options']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For positional arguments
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Shows the settings for an object.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Object name.'),
|
||||||
|
]),
|
||||||
|
'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']
|
||||||
|
|
||||||
|
ops = self.app.collection.get_by_name(str(name)).options
|
||||||
|
return '\n'.join(["%s: %s" % (o, ops[o]) for o in ops])
|
||||||
145
tclCommands/TclCommandPanelize.py
Normal file
145
tclCommands/TclCommandPanelize.py
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandPanelize(TclCommand.TclCommand):
|
||||||
|
"""
|
||||||
|
Tcl shell command to pannelize an object.
|
||||||
|
|
||||||
|
example:
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['panelize']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str),
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
('rows', int),
|
||||||
|
('columns', int),
|
||||||
|
('spacing_columns', float),
|
||||||
|
('spacing_rows', float),
|
||||||
|
('box', str),
|
||||||
|
('outname', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name', 'rows', 'columns']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': 'Rectangular panelizing.',
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the object to panelize.'),
|
||||||
|
('box', 'Name of object which acts as box (cutout for example.)'
|
||||||
|
'for cutout boundary. Object from name is used if not specified.'),
|
||||||
|
('spacing_columns', 'Spacing between columns.'),
|
||||||
|
('spacing_rows', 'Spacing between rows.'),
|
||||||
|
('columns', 'Number of columns.'),
|
||||||
|
('rows', 'Number of rows;'),
|
||||||
|
('outname', 'Name of the new geometry object.')
|
||||||
|
]),
|
||||||
|
'examples': []
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param args:
|
||||||
|
:param unnamed_args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = args['name']
|
||||||
|
|
||||||
|
# Get source object.
|
||||||
|
try:
|
||||||
|
obj = self.app.collection.get_by_name(str(name))
|
||||||
|
except:
|
||||||
|
return "Could not retrieve object: %s" % name
|
||||||
|
|
||||||
|
if obj is None:
|
||||||
|
return "Object not found: %s" % name
|
||||||
|
|
||||||
|
if 'box' in args:
|
||||||
|
boxname = args['box']
|
||||||
|
try:
|
||||||
|
box = self.app.collection.get_by_name(boxname)
|
||||||
|
except:
|
||||||
|
return "Could not retrieve object: %s" % name
|
||||||
|
else:
|
||||||
|
box = obj
|
||||||
|
|
||||||
|
if 'columns' not in args or 'rows' not in args:
|
||||||
|
return "ERROR: Specify -columns and -rows"
|
||||||
|
|
||||||
|
if 'outname' in args:
|
||||||
|
outname = args['outname']
|
||||||
|
else:
|
||||||
|
outname = name + '_panelized'
|
||||||
|
|
||||||
|
if 'spacing_columns' in args:
|
||||||
|
spacing_columns = args['spacing_columns']
|
||||||
|
else:
|
||||||
|
spacing_columns = 5
|
||||||
|
|
||||||
|
if 'spacing_rows' in args:
|
||||||
|
spacing_rows = args['spacing_rows']
|
||||||
|
else:
|
||||||
|
spacing_rows = 5
|
||||||
|
|
||||||
|
xmin, ymin, xmax, ymax = box.bounds()
|
||||||
|
lenghtx = xmax - xmin + spacing_columns
|
||||||
|
lenghty = ymax - ymin + spacing_rows
|
||||||
|
|
||||||
|
currenty = 0
|
||||||
|
|
||||||
|
def initialize_local(obj_init, app):
|
||||||
|
obj_init.solid_geometry = obj.solid_geometry
|
||||||
|
obj_init.offset([float(currentx), float(currenty)]),
|
||||||
|
|
||||||
|
def initialize_local_excellon(obj_init, app):
|
||||||
|
FlatCAMExcellon.merge(obj, obj_init)
|
||||||
|
obj_init.offset([float(currentx), float(currenty)]),
|
||||||
|
|
||||||
|
def initialize_geometry(obj_init, app):
|
||||||
|
FlatCAMGeometry.merge(objs, obj_init)
|
||||||
|
|
||||||
|
def initialize_excellon(obj_init, app):
|
||||||
|
FlatCAMExcellon.merge(objs, obj_init)
|
||||||
|
|
||||||
|
objs = []
|
||||||
|
if obj is not None:
|
||||||
|
|
||||||
|
for row in range(args['rows']):
|
||||||
|
currentx = 0
|
||||||
|
for col in range(args['columns']):
|
||||||
|
local_outname = outname + ".tmp." + str(col) + "." + str(row)
|
||||||
|
if isinstance(obj, FlatCAMExcellon):
|
||||||
|
self.app.new_object("excellon", local_outname, initialize_local_excellon)
|
||||||
|
else:
|
||||||
|
self.app.new_object("geometry", local_outname, initialize_local)
|
||||||
|
|
||||||
|
currentx += lenghtx
|
||||||
|
currenty += lenghty
|
||||||
|
|
||||||
|
if isinstance(obj, FlatCAMExcellon):
|
||||||
|
self.app.new_object("excellon", outname, initialize_excellon)
|
||||||
|
else:
|
||||||
|
self.app.new_object("geometry", outname, initialize_geometry)
|
||||||
|
|
||||||
|
# deselect all to avoid delete selected object when run delete from shell
|
||||||
|
self.app.collection.set_all_inactive()
|
||||||
|
for delobj in objs:
|
||||||
|
self.app.collection.set_active(delobj.options['name'])
|
||||||
|
self.app.on_delete()
|
||||||
|
|
||||||
|
else:
|
||||||
|
return "ERROR: obj is None"
|
||||||
|
|
||||||
|
return "Ok"
|
||||||
46
tclCommands/TclCommandPlot.py
Normal file
46
tclCommands/TclCommandPlot.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandPlot(TclCommand.TclCommand):
|
||||||
|
"""
|
||||||
|
Tcl shell command to update the plot on the user interface.
|
||||||
|
|
||||||
|
example:
|
||||||
|
plot
|
||||||
|
"""
|
||||||
|
|
||||||
|
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['plot']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = []
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Updates the plot on the user interface.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
|
||||||
|
]),
|
||||||
|
'examples': []
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param args:
|
||||||
|
:param unnamed_args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.app.plot_all()
|
||||||
47
tclCommands/TclCommandSaveProject.py
Normal file
47
tclCommands/TclCommandSaveProject.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandSaveProject(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Tcl shell command to save the FlatCAM project to file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['open_project']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For positional arguments
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('filename', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['filename']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Saves the FlatCAM project to file.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('filename', 'Path to file.'),
|
||||||
|
]),
|
||||||
|
'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
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.app.save_project(args['filename'])
|
||||||
51
tclCommands/TclCommandScale.py
Normal file
51
tclCommands/TclCommandScale.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandScale(TclCommand.TclCommand):
|
||||||
|
"""
|
||||||
|
Tcl shell command to resizes the object by a factor.
|
||||||
|
|
||||||
|
example:
|
||||||
|
scale my_geometry 4.2
|
||||||
|
"""
|
||||||
|
|
||||||
|
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['scale']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str),
|
||||||
|
('factor', float)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name', 'factor']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Resizes the object by a factor.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the object to resize.'),
|
||||||
|
('factor', 'Fraction by which to scale.')
|
||||||
|
]),
|
||||||
|
'examples': ['scale my_geometry 4.2']
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param args:
|
||||||
|
:param unnamed_args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = args['name']
|
||||||
|
factor = args['factor']
|
||||||
|
|
||||||
|
self.app.collection.get_by_name(name).scale(factor)
|
||||||
51
tclCommands/TclCommandSetActive.py
Normal file
51
tclCommands/TclCommandSetActive.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandSetActive(TclCommand.TclCommand):
|
||||||
|
"""
|
||||||
|
Tcl shell command to set an object as active in the GUI.
|
||||||
|
|
||||||
|
example:
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['set_active']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str),
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': 'Sets an object as active.',
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the Object.'),
|
||||||
|
]),
|
||||||
|
'examples': []
|
||||||
|
}
|
||||||
|
|
||||||
|
def execute(self, args, unnamed_args):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param args:
|
||||||
|
:param unnamed_args:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
obj_name = args['name']
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.app.collection.set_active(str(obj_name))
|
||||||
|
except Exception as e:
|
||||||
|
return "Command failed: %s" % str(e)
|
||||||
62
tclCommands/TclCommandSubtractPoly.py
Normal file
62
tclCommands/TclCommandSubtractPoly.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandSubtractPoly(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Tcl shell command to create a new empty Geometry object.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['subtract_poly']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For positional arguments
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Subtract polygon from the given Geometry object.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the Geometry object from which to subtract.'),
|
||||||
|
('x0 y0 x1 y1 x2 y2 ...', 'Points defining the 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
|
||||||
|
"""
|
||||||
|
|
||||||
|
obj_name = args['name']
|
||||||
|
|
||||||
|
if len(unnamed_args) % 2 != 0:
|
||||||
|
return "Incomplete coordinate."
|
||||||
|
|
||||||
|
points = [[float(unnamed_args[2 * i]), float(unnamed_args[2 * i + 1])] for i in range(len(unnamed_args) / 2)]
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj = self.app.collection.get_by_name(str(obj_name))
|
||||||
|
except:
|
||||||
|
return "Could not retrieve object: %s" % obj_name
|
||||||
|
if obj is None:
|
||||||
|
return "Object not found: %s" % obj_name
|
||||||
|
|
||||||
|
obj.subtract_polygon(points)
|
||||||
66
tclCommands/TclCommandSubtractRectangle.py
Normal file
66
tclCommands/TclCommandSubtractRectangle.py
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandSubtractRectangle(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Tcl shell command to subtract a rectange from the given Geometry object.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['subtract_rectangle']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For positional arguments
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str),
|
||||||
|
('x0', float),
|
||||||
|
('y0', float),
|
||||||
|
('x1', float),
|
||||||
|
('y1', float)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name', 'x0', 'y0', 'x1', 'y1']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Subtract rectange from the given Geometry object.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Name of the Geometry object from which to subtract.'),
|
||||||
|
('x0 y0', 'Bottom left corner coordinates.'),
|
||||||
|
('x1 y1', 'Top right corner coordinates.')
|
||||||
|
]),
|
||||||
|
'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
|
||||||
|
"""
|
||||||
|
|
||||||
|
obj_name = args['name']
|
||||||
|
x0 = args['x0']
|
||||||
|
y0 = args['y0']
|
||||||
|
x1 = args['x1']
|
||||||
|
y1 = args['y1']
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj = self.app.collection.get_by_name(str(obj_name))
|
||||||
|
except:
|
||||||
|
return "Could not retrieve object: %s" % obj_name
|
||||||
|
if obj is None:
|
||||||
|
return "Object not found: %s" % obj_name
|
||||||
|
|
||||||
|
obj.subtract_polygon([(x0, y0), (x1, y0), (x1, y1), (x0, y1)])
|
||||||
87
tclCommands/TclCommandWriteGCode.py
Normal file
87
tclCommands/TclCommandWriteGCode.py
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
from ObjectCollection import *
|
||||||
|
import TclCommand
|
||||||
|
|
||||||
|
|
||||||
|
class TclCommandWriteGCode(TclCommand.TclCommandSignaled):
|
||||||
|
"""
|
||||||
|
Tcl shell command to save the G-code of a CNC Job object to file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# array of all command aliases, to be able use
|
||||||
|
# old names for backward compatibility (add_poly, add_polygon)
|
||||||
|
aliases = ['write_gcode']
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For positional arguments
|
||||||
|
arg_names = collections.OrderedDict([
|
||||||
|
('name', str),
|
||||||
|
('filename', str)
|
||||||
|
])
|
||||||
|
|
||||||
|
# Dictionary of types from Tcl command, needs to be ordered.
|
||||||
|
# For options like -optionname value
|
||||||
|
option_types = collections.OrderedDict([
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
||||||
|
required = ['name', 'filename']
|
||||||
|
|
||||||
|
# structured help for current command, args needs to be ordered
|
||||||
|
help = {
|
||||||
|
'main': "Saves G-code of a CNC Job object to file.",
|
||||||
|
'args': collections.OrderedDict([
|
||||||
|
('name', 'Source CNC Job object.'),
|
||||||
|
('filename', 'Output filename'),
|
||||||
|
]),
|
||||||
|
'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
|
||||||
|
"""
|
||||||
|
|
||||||
|
"""
|
||||||
|
Requires obj_name to be available. It might still be in the
|
||||||
|
making at the time this function is called, so check for
|
||||||
|
promises and send to background if there are promises.
|
||||||
|
"""
|
||||||
|
|
||||||
|
obj_name = args['name']
|
||||||
|
filename = args['filename']
|
||||||
|
|
||||||
|
preamble = ''
|
||||||
|
postamble = ''
|
||||||
|
|
||||||
|
# TODO: This is not needed any more? All targets should be present.
|
||||||
|
# If there are promised objects, wait until all promises have been fulfilled.
|
||||||
|
# if self.collection.has_promises():
|
||||||
|
# def write_gcode_on_object(new_object):
|
||||||
|
# self.log.debug("write_gcode_on_object(): Disconnecting %s" % write_gcode_on_object)
|
||||||
|
# self.new_object_available.disconnect(write_gcode_on_object)
|
||||||
|
# write_gcode(obj_name, filename, preamble, postamble)
|
||||||
|
#
|
||||||
|
# # Try again when a new object becomes available.
|
||||||
|
# self.log.debug("write_gcode(): Collection has promises. Queued for %s." % obj_name)
|
||||||
|
# self.log.debug("write_gcode(): Queued function: %s" % write_gcode_on_object)
|
||||||
|
# self.new_object_available.connect(write_gcode_on_object)
|
||||||
|
#
|
||||||
|
# return
|
||||||
|
|
||||||
|
# self.log.debug("write_gcode(): No promises. Continuing for %s." % obj_name)
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj = self.app.collection.get_by_name(str(obj_name))
|
||||||
|
except:
|
||||||
|
return "Could not retrieve object: %s" % obj_name
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj.export_gcode(str(filename), str(preamble), str(postamble))
|
||||||
|
except Exception as e:
|
||||||
|
return "Operation failed: %s" % str(e)
|
||||||
@@ -1,19 +1,48 @@
|
|||||||
import pkgutil
|
import pkgutil
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
# Todo: I think these imports are not needed.
|
||||||
# allowed command modules (please append them alphabetically ordered)
|
# allowed command modules (please append them alphabetically ordered)
|
||||||
|
import tclCommands.TclCommandAddCircle
|
||||||
import tclCommands.TclCommandAddPolygon
|
import tclCommands.TclCommandAddPolygon
|
||||||
import tclCommands.TclCommandAddPolyline
|
import tclCommands.TclCommandAddPolyline
|
||||||
|
import tclCommands.TclCommandAddRectangle
|
||||||
|
import tclCommands.TclCommandAlignDrill
|
||||||
|
import tclCommands.TclCommandAlignDrillGrid
|
||||||
import tclCommands.TclCommandCncjob
|
import tclCommands.TclCommandCncjob
|
||||||
|
import tclCommands.TclCommandCutout
|
||||||
|
import tclCommands.TclCommandDelete
|
||||||
import tclCommands.TclCommandDrillcncjob
|
import tclCommands.TclCommandDrillcncjob
|
||||||
import tclCommands.TclCommandExportGcode
|
import tclCommands.TclCommandExportGcode
|
||||||
|
import tclCommands.TclCommandExportSVG
|
||||||
import tclCommands.TclCommandExteriors
|
import tclCommands.TclCommandExteriors
|
||||||
|
import tclCommands.TclCommandGeoCutout
|
||||||
|
import tclCommands.TclCommandGeoUnion
|
||||||
|
import tclCommands.TclCommandGetNames
|
||||||
import tclCommands.TclCommandImportSvg
|
import tclCommands.TclCommandImportSvg
|
||||||
import tclCommands.TclCommandInteriors
|
import tclCommands.TclCommandInteriors
|
||||||
import tclCommands.TclCommandIsolate
|
import tclCommands.TclCommandIsolate
|
||||||
|
import tclCommands.TclCommandJoinExcellon
|
||||||
|
import tclCommands.TclCommandJoinGeometry
|
||||||
|
import tclCommands.TclCommandMillHoles
|
||||||
|
import tclCommands.TclCommandMirror
|
||||||
import tclCommands.TclCommandNew
|
import tclCommands.TclCommandNew
|
||||||
|
import tclCommands.TclCommandNewGeometry
|
||||||
|
import tclCommands.TclCommandOffset
|
||||||
|
import tclCommands.TclCommandOpenExcellon
|
||||||
|
import tclCommands.TclCommandOpenGCode
|
||||||
import tclCommands.TclCommandOpenGerber
|
import tclCommands.TclCommandOpenGerber
|
||||||
|
import tclCommands.TclCommandOpenProject
|
||||||
|
import tclCommands.TclCommandOptions
|
||||||
import tclCommands.TclCommandPaint
|
import tclCommands.TclCommandPaint
|
||||||
|
import tclCommands.TclCommandPanelize
|
||||||
|
import tclCommands.TclCommandPlot
|
||||||
|
import tclCommands.TclCommandSaveProject
|
||||||
|
import tclCommands.TclCommandScale
|
||||||
|
import tclCommands.TclCommandSetActive
|
||||||
|
import tclCommands.TclCommandSubtractPoly
|
||||||
|
import tclCommands.TclCommandSubtractRectangle
|
||||||
|
import tclCommands.TclCommandWriteGCode
|
||||||
|
|
||||||
|
|
||||||
__all__ = []
|
__all__ = []
|
||||||
@@ -25,7 +54,7 @@ for loader, name, is_pkg in pkgutil.walk_packages(__path__):
|
|||||||
|
|
||||||
def register_all_commands(app, commands):
|
def register_all_commands(app, commands):
|
||||||
"""
|
"""
|
||||||
Static method which register all known commands.
|
Static method which registers all known commands.
|
||||||
|
|
||||||
Command should be for now in directory tclCommands and module should start with TCLCommand
|
Command should be for now in directory tclCommands and module should start with TCLCommand
|
||||||
Class have to follow same name as module.
|
Class have to follow same name as module.
|
||||||
|
|||||||
Reference in New Issue
Block a user