Bringing up to date with VisPyCanvas. Mostly migration of Tcl commands to new architecture.

This commit is contained in:
Juan Pablo Caram
2016-10-08 11:49:22 -04:00
parent 2abc9a8faf
commit f77403b0f2
37 changed files with 3619 additions and 1471 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -77,12 +77,12 @@ class FlatCAMGUI(QtGui.QMainWindow):
self.menufile.addAction(self.menufilesavedefaults)
# 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.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 ###
self.menuedit = self.menu.addMenu('&Edit')

View File

@@ -116,7 +116,7 @@ class TclCommand(object):
return "\t[" + option_symbol + help_key + " <" + type_name + ">: " + help_text + "]"
def get_decorated_example(example_item):
return "> "+example_item
return "> " + example_item
help_string = [self.help['main']]
for alias in self.aliases:
@@ -214,7 +214,6 @@ class TclCommand(object):
return named_args, unnamed_args
def raise_tcl_unknown_error(self, unknownException):
"""
raise Exception if is different type than TclErrorException
@@ -253,11 +252,11 @@ class TclCommand(object):
try:
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)
return self.execute(args, unnamed_args)
except Exception as unknown:
error_info=sys.exc_info()
error_info = sys.exc_info()
self.log.error("TCL command '%s' failed." % str(self))
self.app.display_tcl_error(unknown, error_info)
self.raise_tcl_unknown_error(unknown)
@@ -276,6 +275,7 @@ class TclCommand(object):
raise NotImplementedError("Please Implement this method")
class TclCommandSignaled(TclCommand):
"""
!!! I left it here only for demonstration !!!
@@ -297,12 +297,12 @@ class TclCommandSignaled(TclCommand):
try:
self.output = None
self.error=None
self.error_info=None
self.error = None
self.error_info = None
self.output = self.execute(args, unnamed_args)
except Exception as unknown:
self.error_info = sys.exc_info()
self.error=unknown
self.error = unknown
finally:
self.app.shell_command_finished.emit(self)
@@ -357,17 +357,19 @@ class TclCommandSignaled(TclCommand):
raise ex[0]
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:
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)
if 'timeout' in args:
passed_timeout=args['timeout']
passed_timeout = args['timeout']
del args['timeout']
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
self.app.shell.open_proccessing(self.get_current_command())
@@ -392,7 +394,7 @@ class TclCommandSignaled(TclCommand):
if self.error_info is not None:
error_info = self.error_info
else:
error_info=sys.exc_info()
error_info = sys.exc_info()
self.log.error("TCL command '%s' failed." % str(self))
self.app.display_tcl_error(unknown, error_info)
self.raise_tcl_unknown_error(unknown)
self.raise_tcl_unknown_error(unknown)

View 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))

View 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)])

View 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'

View 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)

View File

@@ -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
option_types = collections.OrderedDict([
('z_cut',float),
('z_move',float),
('feedrate',float),
('tooldia',float),
('spindlespeed',int),
('multidepth',bool),
('depthperpass',float),
('outname',str)
('z_cut', float),
('z_move', float),
('feedrate', float),
('tooldia', float),
('spindlespeed', int),
('multidepth', bool),
('depthperpass', float),
('outname', str)
])
# 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)))
del args['name']
obj.generatecncjob(use_thread = False, **args)
obj.generatecncjob(use_thread=False, **args)

View 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)

View 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)

View File

@@ -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
option_types = collections.OrderedDict([
('tools',str),
('drillz',float),
('travelz',float),
('feedrate',float),
('spindlespeed',int),
('toolchange',bool),
('outname',str)
('tools', str),
('drillz', float),
('travelz', float),
('feedrate', float),
('spindlespeed', int),
('toolchange', bool),
('outname', str)
])
# array of mandatory options for current Tcl command: required = {'name','outname'}

View 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)

View 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)

View 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()

View 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())

View File

@@ -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
option_types = collections.OrderedDict([
('dia',float),
('passes',int),
('overlap',float),
('combine',int),
('outname',str)
('dia', float),
('passes', int),
('overlap', float),
('combine', int),
('outname', str)
])
# array of mandatory options for current Tcl command: required = {'name','outname'}

View 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)

View 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)

View 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)

View 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)

View File

@@ -1,5 +1,4 @@
from ObjectCollection import *
from PyQt4 import QtCore
import TclCommand
@@ -23,7 +22,7 @@ class TclCommandNew(TclCommand.TclCommand):
# structured help for current command, args needs to be ordered
help = {
'main': "Starts a new project. Clears objects from memory.",
'args': collections.OrderedDict(),
'args': collections.OrderedDict(),
'examples': []
}

View 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)

View 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)

View 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)

View 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)

View File

@@ -27,10 +27,10 @@ class TclCommandOpenGerber(TclCommand.TclCommandSignaled):
# structured help for current command, args needs to be ordered
help = {
'main': "Opens a Gerber file.",
'args': collections.OrderedDict([
'args': collections.OrderedDict([
('filename', 'Path to file to open.'),
('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': []
}

View 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'])

View 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])

View 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"

View 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()

View 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'])

View 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)

View 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)

View 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)

View 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)])

View 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)

View File

@@ -1,19 +1,48 @@
import pkgutil
import sys
# Todo: I think these imports are not needed.
# allowed command modules (please append them alphabetically ordered)
import tclCommands.TclCommandAddCircle
import tclCommands.TclCommandAddPolygon
import tclCommands.TclCommandAddPolyline
import tclCommands.TclCommandAddRectangle
import tclCommands.TclCommandAlignDrill
import tclCommands.TclCommandAlignDrillGrid
import tclCommands.TclCommandCncjob
import tclCommands.TclCommandCutout
import tclCommands.TclCommandDelete
import tclCommands.TclCommandDrillcncjob
import tclCommands.TclCommandExportGcode
import tclCommands.TclCommandExportSVG
import tclCommands.TclCommandExteriors
import tclCommands.TclCommandGeoCutout
import tclCommands.TclCommandGeoUnion
import tclCommands.TclCommandGetNames
import tclCommands.TclCommandImportSvg
import tclCommands.TclCommandInteriors
import tclCommands.TclCommandIsolate
import tclCommands.TclCommandJoinExcellon
import tclCommands.TclCommandJoinGeometry
import tclCommands.TclCommandMillHoles
import tclCommands.TclCommandMirror
import tclCommands.TclCommandNew
import tclCommands.TclCommandNewGeometry
import tclCommands.TclCommandOffset
import tclCommands.TclCommandOpenExcellon
import tclCommands.TclCommandOpenGCode
import tclCommands.TclCommandOpenGerber
import tclCommands.TclCommandOpenProject
import tclCommands.TclCommandOptions
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__ = []
@@ -25,7 +54,7 @@ for loader, name, is_pkg in pkgutil.walk_packages(__path__):
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
Class have to follow same name as module.