2019-08-24 16:55:03 +00:00
|
|
|
from tclCommands.TclCommand import TclCommand
|
2019-01-03 19:25:08 +00:00
|
|
|
|
2019-10-24 23:10:52 +00:00
|
|
|
import collections
|
|
|
|
import logging
|
|
|
|
|
2019-08-24 16:55:03 +00:00
|
|
|
import gettext
|
|
|
|
import FlatCAMTranslation as fcTranslate
|
|
|
|
import builtins
|
2019-01-03 19:25:08 +00:00
|
|
|
|
2019-08-24 16:55:03 +00:00
|
|
|
fcTranslate.apply_language('strings')
|
|
|
|
if '_' not in builtins.__dict__:
|
|
|
|
_ = gettext.gettext
|
|
|
|
|
2019-10-24 23:10:52 +00:00
|
|
|
log = logging.getLogger('base')
|
|
|
|
|
2019-08-24 16:55:03 +00:00
|
|
|
|
|
|
|
class TclCommandPaint(TclCommand):
|
2019-01-03 19:25:08 +00:00
|
|
|
"""
|
|
|
|
Paint the interior of polygons
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
|
|
|
|
aliases = ['paint']
|
|
|
|
|
2020-04-13 16:15:20 +00:00
|
|
|
description = '%s %s' % ("--", "Paint polygons in the specified object by covering them with toolpaths.")
|
|
|
|
|
2019-01-03 19:25:08 +00:00
|
|
|
# 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([
|
2019-08-24 16:55:03 +00:00
|
|
|
('tooldia', str),
|
|
|
|
('overlap', float),
|
|
|
|
('order', str),
|
|
|
|
('margin', float),
|
|
|
|
('method', str),
|
2020-04-13 16:15:20 +00:00
|
|
|
('connect', str),
|
|
|
|
('contour', str),
|
2019-08-24 16:55:03 +00:00
|
|
|
|
2020-04-13 16:15:20 +00:00
|
|
|
('all', str),
|
|
|
|
('single', str),
|
|
|
|
('ref', str),
|
2019-08-24 16:55:03 +00:00
|
|
|
('box', str),
|
2019-01-03 19:25:08 +00:00
|
|
|
('x', float),
|
2019-08-24 16:55:03 +00:00
|
|
|
('y', float),
|
|
|
|
('outname', str),
|
2019-01-03 19:25:08 +00:00
|
|
|
])
|
|
|
|
|
|
|
|
# array of mandatory options for current Tcl command: required = {'name','outname'}
|
2019-08-24 16:55:03 +00:00
|
|
|
required = ['name']
|
2019-01-03 19:25:08 +00:00
|
|
|
|
|
|
|
# structured help for current command, args needs to be ordered
|
|
|
|
help = {
|
2020-04-13 16:15:20 +00:00
|
|
|
'main': "Paint polygons in the specified object by covering them with toolpaths.",
|
2019-01-03 19:25:08 +00:00
|
|
|
'args': collections.OrderedDict([
|
2019-08-24 16:55:03 +00:00
|
|
|
('name', 'Name of the source Geometry object. String.'),
|
|
|
|
('tooldia', 'Diameter of the tool to be used. Can be a comma separated list of diameters. No space is '
|
|
|
|
'allowed between tool diameters. E.g: correct: 0.5,1 / incorrect: 0.5, 1'),
|
2019-12-30 21:33:22 +00:00
|
|
|
('overlap', 'Percentage of tool diameter to overlap current pass over previous pass. Float [0, 99.9999]\n'
|
|
|
|
'E.g: for a 25% from tool diameter overlap use -overlap 25'),
|
2019-08-25 01:45:16 +00:00
|
|
|
('margin', 'Bounding box margin. Float number.'),
|
2019-08-24 16:55:03 +00:00
|
|
|
('order', 'Can have the values: "no", "fwd" and "rev". String.'
|
|
|
|
'It is useful when there are multiple tools in tooldia parameter.'
|
|
|
|
'"no" -> the order used is the one provided.'
|
|
|
|
'"fwd" -> tools are ordered from smallest to biggest.'
|
|
|
|
'"rev" -> tools are ordered from biggest to smallest.'),
|
2020-04-24 18:08:27 +00:00
|
|
|
('method', 'Algorithm for painting. Can be: "standard", "seed", "lines", "laser_lines", "combo".'),
|
2020-04-13 16:15:20 +00:00
|
|
|
('connect', 'Draw lines to minimize tool lifts. True (1) or False (0)'),
|
|
|
|
('contour', 'Cut around the perimeter of the painting. True (1) or False (0)'),
|
2020-04-22 11:37:03 +00:00
|
|
|
('all', 'If used, paint all polygons in the object.'),
|
|
|
|
('box', 'name of the object to be used as paint reference. String.'),
|
2020-04-13 16:15:20 +00:00
|
|
|
('single', 'Paint a single polygon specified by "x" and "y" parameters. True (1) or False (0)'),
|
2019-08-24 16:55:03 +00:00
|
|
|
('x', 'X value of coordinate for the selection of a single polygon. Float number.'),
|
|
|
|
('y', 'Y value of coordinate for the selection of a single polygon. Float number.'),
|
|
|
|
('outname', 'Name of the resulting Geometry object. String.'),
|
2019-01-03 19:25:08 +00:00
|
|
|
]),
|
2020-04-22 11:37:03 +00:00
|
|
|
'examples': ["paint obj_name -tooldia 0.3 -margin 0.1 -method 'seed' -all"]
|
2019-01-03 19:25:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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']
|
2019-08-24 16:55:03 +00:00
|
|
|
|
2019-12-05 13:18:54 +00:00
|
|
|
# Get source object.
|
|
|
|
try:
|
|
|
|
obj = self.app.collection.get_by_name(str(name))
|
|
|
|
except Exception as e:
|
|
|
|
log.debug("TclCommandPaint.execute() --> %s" % str(e))
|
|
|
|
self.raise_tcl_error("%s: %s" % (_("Could not retrieve object"), name))
|
|
|
|
return "Could not retrieve object: %s" % name
|
|
|
|
|
2019-08-24 16:55:03 +00:00
|
|
|
if 'tooldia' in args:
|
|
|
|
tooldia = str(args['tooldia'])
|
|
|
|
else:
|
|
|
|
tooldia = float(self.app.defaults["tools_paintoverlap"])
|
|
|
|
|
|
|
|
if 'overlap' in args:
|
2019-12-30 20:04:39 +00:00
|
|
|
overlap = float(args['overlap']) / 100.0
|
2019-08-24 16:55:03 +00:00
|
|
|
else:
|
2019-12-30 20:04:39 +00:00
|
|
|
overlap = float(self.app.defaults["tools_paintoverlap"]) / 100.0
|
2019-08-24 16:55:03 +00:00
|
|
|
|
|
|
|
if 'order' in args:
|
|
|
|
order = args['order']
|
|
|
|
else:
|
|
|
|
order = str(self.app.defaults["tools_paintorder"])
|
|
|
|
|
|
|
|
if 'margin' in args:
|
|
|
|
margin = float(args['margin'])
|
|
|
|
else:
|
|
|
|
margin = float(self.app.defaults["tools_paintmargin"])
|
|
|
|
|
|
|
|
if 'method' in args:
|
|
|
|
method = args['method']
|
2020-04-24 18:08:27 +00:00
|
|
|
if method == "standard":
|
|
|
|
method = _("Standard")
|
|
|
|
elif method == "seed":
|
|
|
|
method = _("Seed")
|
|
|
|
elif method == "lines":
|
|
|
|
method = _("Lines")
|
|
|
|
elif method == "laser_lines":
|
|
|
|
method = _("Laser_lines")
|
|
|
|
else:
|
|
|
|
method = _("Combo")
|
2019-08-24 16:55:03 +00:00
|
|
|
else:
|
|
|
|
method = str(self.app.defaults["tools_paintmethod"])
|
|
|
|
|
|
|
|
if 'connect' in args:
|
2020-04-22 11:37:03 +00:00
|
|
|
try:
|
|
|
|
par = args['connect'].capitalize()
|
|
|
|
except AttributeError:
|
|
|
|
par = args['connect']
|
|
|
|
connect = bool(eval(par))
|
2019-08-24 16:55:03 +00:00
|
|
|
else:
|
2020-04-22 11:37:03 +00:00
|
|
|
connect = bool(eval(str(self.app.defaults["tools_pathconnect"])))
|
2019-08-24 16:55:03 +00:00
|
|
|
|
|
|
|
if 'contour' in args:
|
2020-04-22 11:37:03 +00:00
|
|
|
try:
|
|
|
|
par = args['contour'].capitalize()
|
|
|
|
except AttributeError:
|
|
|
|
par = args['contour']
|
|
|
|
contour = bool(eval(par))
|
2019-08-24 16:55:03 +00:00
|
|
|
else:
|
2020-04-22 11:37:03 +00:00
|
|
|
contour = bool(eval(str(self.app.defaults["tools_paintcontour"])))
|
2019-01-03 19:25:08 +00:00
|
|
|
|
|
|
|
if 'outname' in args:
|
|
|
|
outname = args['outname']
|
|
|
|
else:
|
|
|
|
outname = name + "_paint"
|
|
|
|
|
2020-04-24 18:08:27 +00:00
|
|
|
# used only to have correct information's in the obj.tools[tool]['data'] dict
|
|
|
|
if "all" in args:
|
|
|
|
select = _("All Polygons")
|
|
|
|
elif "single" in args:
|
|
|
|
select = _("Polygon Selection")
|
|
|
|
else:
|
|
|
|
select = _("Reference Object")
|
|
|
|
|
2019-08-24 16:55:03 +00:00
|
|
|
try:
|
|
|
|
tools = [float(eval(dia)) for dia in tooldia.split(",") if dia != '']
|
|
|
|
except AttributeError:
|
|
|
|
tools = [float(tooldia)]
|
|
|
|
# store here the default data for Geometry Data
|
|
|
|
default_data = {}
|
|
|
|
default_data.update({
|
2020-04-24 18:08:27 +00:00
|
|
|
"name": outname,
|
|
|
|
"plot": False,
|
2019-08-24 16:55:03 +00:00
|
|
|
"cutz": self.app.defaults["geometry_cutz"],
|
|
|
|
"vtipdia": 0.1,
|
|
|
|
"vtipangle": 30,
|
|
|
|
"travelz": self.app.defaults["geometry_travelz"],
|
|
|
|
"feedrate": self.app.defaults["geometry_feedrate"],
|
|
|
|
"feedrate_z": self.app.defaults["geometry_feedrate_z"],
|
|
|
|
"feedrate_rapid": self.app.defaults["geometry_feedrate_rapid"],
|
|
|
|
"dwell": self.app.defaults["geometry_dwell"],
|
|
|
|
"dwelltime": self.app.defaults["geometry_dwelltime"],
|
|
|
|
"multidepth": self.app.defaults["geometry_multidepth"],
|
|
|
|
"ppname_g": self.app.defaults["geometry_ppname_g"],
|
|
|
|
"depthperpass": self.app.defaults["geometry_depthperpass"],
|
|
|
|
"extracut": self.app.defaults["geometry_extracut"],
|
2019-12-10 03:28:02 +00:00
|
|
|
"extracut_length": self.app.defaults["geometry_extracut_length"],
|
2019-08-24 16:55:03 +00:00
|
|
|
"toolchange": self.app.defaults["geometry_toolchange"],
|
|
|
|
"toolchangez": self.app.defaults["geometry_toolchangez"],
|
|
|
|
"endz": self.app.defaults["geometry_endz"],
|
2020-02-26 02:43:54 +00:00
|
|
|
"endxy": self.app.defaults["geometry_endxy"],
|
|
|
|
|
2019-08-24 16:55:03 +00:00
|
|
|
"spindlespeed": self.app.defaults["geometry_spindlespeed"],
|
|
|
|
"toolchangexy": self.app.defaults["geometry_toolchangexy"],
|
|
|
|
"startz": self.app.defaults["geometry_startz"],
|
2019-01-03 19:25:08 +00:00
|
|
|
|
2019-08-24 16:55:03 +00:00
|
|
|
"tooldia": self.app.defaults["tools_painttooldia"],
|
2020-04-24 18:08:27 +00:00
|
|
|
"paintmargin": margin,
|
|
|
|
"paintmethod": method,
|
|
|
|
"selectmethod": select,
|
|
|
|
"pathconnect": connect,
|
|
|
|
"paintcontour": contour,
|
|
|
|
"paintoverlap": overlap
|
2019-08-24 16:55:03 +00:00
|
|
|
})
|
2020-02-29 22:52:24 +00:00
|
|
|
paint_tools = {}
|
2019-01-03 19:25:08 +00:00
|
|
|
|
2019-08-24 16:55:03 +00:00
|
|
|
tooluid = 0
|
|
|
|
for tool in tools:
|
|
|
|
tooluid += 1
|
|
|
|
paint_tools.update({
|
|
|
|
int(tooluid): {
|
2019-12-05 13:18:54 +00:00
|
|
|
'tooldia': float('%.*f' % (obj.decimals, tool)),
|
2019-08-24 16:55:03 +00:00
|
|
|
'offset': 'Path',
|
|
|
|
'offset_value': 0.0,
|
|
|
|
'type': 'Iso',
|
|
|
|
'tool_type': 'C1',
|
|
|
|
'data': dict(default_data),
|
|
|
|
'solid_geometry': []
|
|
|
|
}
|
|
|
|
})
|
2020-04-24 18:08:27 +00:00
|
|
|
paint_tools[int(tooluid)]['data']['tooldia'] = float('%.*f' % (obj.decimals, tool))
|
2019-08-24 16:55:03 +00:00
|
|
|
|
|
|
|
if obj is None:
|
|
|
|
return "Object not found: %s" % name
|
|
|
|
|
|
|
|
# Paint all polygons in the painted object
|
2020-04-22 11:37:03 +00:00
|
|
|
if 'all' in args:
|
2019-08-24 16:55:03 +00:00
|
|
|
self.app.paint_tool.paint_poly_all(obj=obj,
|
|
|
|
tooldia=tooldia,
|
|
|
|
order=order,
|
|
|
|
method=method,
|
|
|
|
outname=outname,
|
2019-09-15 22:39:11 +00:00
|
|
|
tools_storage=paint_tools,
|
|
|
|
plot=False,
|
|
|
|
run_threaded=False)
|
2019-01-03 19:25:08 +00:00
|
|
|
return
|
|
|
|
|
2019-08-24 16:55:03 +00:00
|
|
|
# Paint single polygon in the painted object
|
2020-04-22 11:37:03 +00:00
|
|
|
if 'single' in args:
|
|
|
|
if 'x' not in args and 'y' not in args:
|
2019-08-24 16:55:03 +00:00
|
|
|
self.raise_tcl_error('%s' % _("Expected -x <value> and -y <value>."))
|
|
|
|
else:
|
|
|
|
x = args['x']
|
|
|
|
y = args['y']
|
2019-01-03 19:25:08 +00:00
|
|
|
|
2019-08-24 16:55:03 +00:00
|
|
|
self.app.paint_tool.paint_poly(obj=obj,
|
|
|
|
inside_pt=[x, y],
|
|
|
|
tooldia=tooldia,
|
|
|
|
order=order,
|
|
|
|
method=method,
|
|
|
|
outname=outname,
|
2019-09-15 22:39:11 +00:00
|
|
|
tools_storage=paint_tools,
|
|
|
|
plot=False,
|
|
|
|
run_threaded=False)
|
2019-08-24 16:55:03 +00:00
|
|
|
return
|
2019-01-03 19:25:08 +00:00
|
|
|
|
2019-08-24 16:55:03 +00:00
|
|
|
# Paint all polygons found within the box object from the the painted object
|
2020-04-22 11:37:03 +00:00
|
|
|
if 'box' in args:
|
|
|
|
box_name = args['box']
|
|
|
|
|
|
|
|
if box_name is None:
|
2019-08-24 16:55:03 +00:00
|
|
|
self.raise_tcl_error('%s' % _("Expected -box <value>."))
|
2020-04-22 11:37:03 +00:00
|
|
|
|
|
|
|
# Get box source object.
|
|
|
|
try:
|
|
|
|
box_obj = self.app.collection.get_by_name(str(box_name))
|
|
|
|
except Exception as e:
|
|
|
|
log.debug("TclCommandPaint.execute() --> %s" % str(e))
|
|
|
|
self.raise_tcl_error("%s: %s" % (_("Could not retrieve box object"), name))
|
|
|
|
return "Could not retrieve object: %s" % name
|
|
|
|
|
|
|
|
self.app.paint_tool.paint_poly_ref(obj=obj,
|
|
|
|
sel_obj=box_obj,
|
|
|
|
tooldia=tooldia,
|
|
|
|
order=order,
|
|
|
|
method=method,
|
|
|
|
outname=outname,
|
|
|
|
tools_storage=paint_tools,
|
|
|
|
plot=False,
|
|
|
|
run_threaded=False)
|
2019-08-24 16:55:03 +00:00
|
|
|
return
|
|
|
|
|
2020-04-22 11:37:03 +00:00
|
|
|
self.raise_tcl_error("%s:" % _("None of the following args: 'box', 'single', 'all' were used.\n"
|
|
|
|
"Paint failed."))
|
|
|
|
return "None of the following args: 'box', 'single', 'all' were used. Paint failed."
|