Merged in marius_stanciu/flatcam_beta/Beta (pull request #289)

Beta - changes for 8.992
This commit is contained in:
Marius Stanciu 2020-01-01 18:44:01 +00:00
commit 80c252c1a1
4 changed files with 164 additions and 97 deletions

View File

@ -14,7 +14,8 @@ CAD program, and create G-Code for Isolation routing.
- fixed bug in NCC Tool: after trying to add a tool already in the Tool Table when trying to change the Tool Type the GUI does not change
- final fix for app not quiting when running a script as argument, script that has the quit_flatcam Tcl command; fixed issue #360
- fixed issue #363. The Tcl command drillcncjob does not create tool cut, does not allow creation of gcode, it forces the usage of dwell and dwelltime parameters
- in NCC Tool I've added a warning so the user is warned that the NCC margin has to have a value of at least the tool diameter that is doing an iso_op job in the Tool Table
- modified the Drillcncjob and Cncjob Tcl commands to be allowed to work without the 'dwell' and 'toolchange' arguments. If 'dwelltime' argument is present it will be assumed that the 'dwell' is True and the same for 'toolchangez' parameter, if present then 'toolchange' will be assumed to be True, else False
30.12.2019

View File

@ -1626,6 +1626,11 @@ class NonCopperClear(FlatCAMTool, Gerber):
empty = self.get_ncc_empty_area(target=sol_geo, boundary=bounding_box)
if empty == 'fail':
return 'fail'
if empty.is_empty:
app_obj.inform.emit('[ERROR_NOTCL] %s' %
_("Could not get the extent of the area to be non copper cleared."))
return 'fail'
elif isinstance(ncc_obj, FlatCAMGerber) and isotooldia:
isolated_geo = []
@ -1650,6 +1655,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
if isolated_geo == 'fail':
app_obj.inform.emit('[ERROR_NOTCL] %s' % _("Isolation geometry could not be generated."))
else:
if ncc_margin < tool_iso:
app_obj.inform.emit('[WARNING_NOTCL] %s' % _("Isolation geometry is broken. Margin is less "
"than isolation tool diameter."))
try:
for geo_elem in isolated_geo:
# provide the app with a way to process the GUI events when in a blocking loop
@ -1723,26 +1731,28 @@ class NonCopperClear(FlatCAMTool, Gerber):
if empty == 'fail':
return 'fail'
if empty.is_empty:
app_obj.inform.emit('[ERROR_NOTCL] %s' %
_("Isolation geometry is broken. Margin is less than isolation tool diameter."))
return 'fail'
elif isinstance(ncc_obj, FlatCAMGeometry):
sol_geo = cascaded_union(ncc_obj.solid_geometry)
if has_offset is True:
app_obj.inform.emit('[WARNING_NOTCL] %s ...' %
_("Buffering"))
app_obj.inform.emit('[WARNING_NOTCL] %s ...' % _("Buffering"))
sol_geo = sol_geo.buffer(distance=ncc_offset)
app_obj.inform.emit('[success] %s ...' %
_("Buffering finished"))
app_obj.inform.emit('[success] %s ...' % _("Buffering finished"))
empty = self.get_ncc_empty_area(target=sol_geo, boundary=bounding_box)
if empty == 'fail':
return 'fail'
else:
app_obj.inform.emit('[ERROR_NOTCL] %s' %
_('The selected object is not suitable for copper clearing.'))
return
if empty.is_empty:
app_obj.inform.emit('[ERROR_NOTCL] %s' %
_("Could not get the extent of the area to be non copper cleared."))
return 'fail'
if empty.is_empty:
app_obj.inform.emit('[ERROR_NOTCL] %s' %
_("Could not get the extent of the area to be non copper cleared."))
else:
app_obj.inform.emit('[ERROR_NOTCL] %s' % _('The selected object is not suitable for copper clearing.'))
return 'fail'
if type(empty) is Polygon:
@ -1762,11 +1772,8 @@ class NonCopperClear(FlatCAMTool, Gerber):
# provide the app with a way to process the GUI events when in a blocking loop
QtWidgets.QApplication.processEvents()
app_obj.inform.emit(
'[success] %s %s%s %s' % (_('NCC Tool clearing with tool diameter = '),
str(tool),
units.lower(),
_('started.'))
app_obj.inform.emit('[success] %s = %s%s %s' % (
_('NCC Tool clearing with tool diameter'), str(tool), units.lower(), _('started.'))
)
app_obj.proc_container.update_view_text(' %d%%' % 0)
@ -1836,7 +1843,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
poly_processed.append(False)
log.warning("Polygon in MultiPolygon can not be cleared.")
else:
log.warning("Geo in Iterable can not be cleared beacuse it is not Polygon. "
log.warning("Geo in Iterable can not be cleared because it is not Polygon. "
"It is: %s" % str(type(pol)))
except TypeError:
if isinstance(p, Polygon):
@ -1942,32 +1949,59 @@ class NonCopperClear(FlatCAMTool, Gerber):
if geo_obj.tools[tooluid]['solid_geometry']:
has_solid_geo += 1
if has_solid_geo == 0:
app_obj.inform.emit('[ERROR] %s' % _("There is no NCC Geometry in the file.\n"
"Usually it means that the tool diameter is too big "
"for the painted geometry.\n"
"Change the painting parameters and try again."))
return
app_obj.inform.emit('[ERROR] %s' %
_("There is no NCC Geometry in the file.\n"
"Usually it means that the tool diameter is too big for the painted geometry.\n"
"Change the painting parameters and try again."))
return 'fail'
# check to see if geo_obj.tools is empty
# it will be updated only if there is a solid_geometry for tools
if geo_obj.tools:
if warning_flag == 0:
self.app.inform.emit('[success] %s' % _("NCC Tool clear all done."))
else:
self.app.inform.emit('[WARNING] %s: %s %s.' % (
_("NCC Tool clear all done but the copper features isolation is broken for"),
str(warning_flag),
_("tools")))
return
# create the solid_geometry
geo_obj.solid_geometry = list()
for tooluid in geo_obj.tools:
if geo_obj.tools[tooluid]['solid_geometry']:
try:
for geo in geo_obj.tools[tooluid]['solid_geometry']:
geo_obj.solid_geometry.append(geo)
except TypeError:
geo_obj.solid_geometry.append(geo_obj.tools[tooluid]['solid_geometry'])
else:
# I will use this variable for this purpose although it was meant for something else
# signal that we have no geo in the object therefore don't create it
app_obj.poly_not_cleared = False
return "fail"
# create the solid_geometry
geo_obj.solid_geometry = list()
for tooluid in geo_obj.tools:
if geo_obj.tools[tooluid]['solid_geometry']:
try:
for geo in geo_obj.tools[tooluid]['solid_geometry']:
geo_obj.solid_geometry.append(geo)
except TypeError:
geo_obj.solid_geometry.append(geo_obj.tools[tooluid]['solid_geometry'])
# Experimental...
# print("Indexing...", end=' ')
# geo_obj.make_index()
if warning_flag == 0:
self.app.inform.emit('[success] %s' % _("NCC Tool clear all done."))
else:
self.app.inform.emit('[WARNING] %s: %s %s.' % (_("NCC Tool clear all done but the copper features "
"isolation is broken for"),
str(warning_flag),
_("tools")))
# geo_obj.solid_geometry = list()
# for tooluid in geo_obj.tools:
# if geo_obj.tools[tooluid]['solid_geometry']:
# try:
# for geo in geo_obj.tools[tooluid]['solid_geometry']:
# geo_obj.solid_geometry.append(geo)
# except TypeError:
# geo_obj.solid_geometry.append(geo_obj.tools[tooluid]['solid_geometry'])
#
# # Experimental...
# # print("Indexing...", end=' ')
# # geo_obj.make_index()
# if warning_flag == 0:
# self.app.inform.emit('[success] %s' % _("NCC Tool clear all done."))
# else:
# self.app.inform.emit('[WARNING] %s: %s %s.' % (
# _("NCC Tool clear all done but the copper features isolation is broken for"),
# str(warning_flag),
# _("tools")))
# ###########################################################################################
# Initializes the new geometry object for the case of the rest-machining ####################
@ -2009,15 +2043,17 @@ class NonCopperClear(FlatCAMTool, Gerber):
if isinstance(ncc_obj, FlatCAMGerber) and not isotooldia:
sol_geo = ncc_obj.solid_geometry
if has_offset is True:
app_obj.inform.emit('[WARNING_NOTCL] %s ...' %
_("Buffering"))
app_obj.inform.emit('[WARNING_NOTCL] %s ...' % _("Buffering"))
sol_geo = sol_geo.buffer(distance=ncc_offset)
app_obj.inform.emit('[success] %s ...' %
_("Buffering finished"))
app_obj.inform.emit('[success] %s ...' % _("Buffering finished"))
empty = self.get_ncc_empty_area(target=sol_geo, boundary=bounding_box)
if empty == 'fail':
return 'fail'
if empty.is_empty:
app_obj.inform.emit('[ERROR_NOTCL] %s' %
_("Could not get the extent of the area to be non copper cleared."))
return 'fail'
elif isinstance(ncc_obj, FlatCAMGerber) and isotooldia:
isolated_geo = []
self.solid_geometry = ncc_obj.solid_geometry
@ -2036,6 +2072,9 @@ class NonCopperClear(FlatCAMTool, Gerber):
if isolated_geo == 'fail':
app_obj.inform.emit('[ERROR_NOTCL] %s' % _("Isolation geometry could not be generated."))
else:
app_obj.inform.emit('[WARNING_NOTCL] %s' % _("Isolation geometry is broken. Margin is less "
"than isolation tool diameter."))
try:
for geo_elem in isolated_geo:
# provide the app with a way to process the GUI events when in a blocking loop
@ -2105,35 +2144,35 @@ class NonCopperClear(FlatCAMTool, Gerber):
sol_geo = cascaded_union(isolated_geo)
if has_offset is True:
app_obj.inform.emit('[WARNING_NOTCL] %s ...' %
_("Buffering"))
app_obj.inform.emit('[WARNING_NOTCL] %s ...' % _("Buffering"))
sol_geo = sol_geo.buffer(distance=ncc_offset)
app_obj.inform.emit('[success] %s ...' %
_("Buffering finished"))
app_obj.inform.emit('[success] %s ...' % _("Buffering finished"))
empty = self.get_ncc_empty_area(target=sol_geo, boundary=bounding_box)
if empty == 'fail':
return 'fail'
if empty.is_empty:
app_obj.inform.emit('[ERROR_NOTCL] %s' %
_("Isolation geometry is broken. Margin is less than isolation tool diameter."))
return 'fail'
elif isinstance(ncc_obj, FlatCAMGeometry):
sol_geo = cascaded_union(ncc_obj.solid_geometry)
if has_offset is True:
app_obj.inform.emit('[WARNING_NOTCL] %s ...' %
_("Buffering"))
app_obj.inform.emit('[WARNING_NOTCL] %s ...' % _("Buffering"))
sol_geo = sol_geo.buffer(distance=ncc_offset)
app_obj.inform.emit('[success] %s ...' %
_("Buffering finished"))
app_obj.inform.emit('[success] %s ...' % _("Buffering finished"))
empty = self.get_ncc_empty_area(target=sol_geo, boundary=bounding_box)
if empty == 'fail':
return 'fail'
else:
app_obj.inform.emit('[ERROR_NOTCL] %s' %
_('The selected object is not suitable for copper clearing.'))
return
if empty.is_empty:
app_obj.inform.emit('[ERROR_NOTCL] %s' %
_("Could not get the extent of the area to be non copper cleared."))
return 'fail'
if empty.is_empty:
app_obj.inform.emit('[ERROR_NOTCL] %s' %
_("Could not get the extent of the area to be non copper cleared."))
return 'fail'
else:
app_obj.inform.emit('[ERROR_NOTCL] %s' % _('The selected object is not suitable for copper clearing.'))
return
if self.app.abort_flag:
# graceful abort requested by the user
@ -2156,11 +2195,8 @@ class NonCopperClear(FlatCAMTool, Gerber):
tool = sorted_tools.pop(0)
log.debug("Starting geometry processing for tool: %s" % str(tool))
app_obj.inform.emit(
'[success] %s %s%s %s' % (_('NCC Tool clearing with tool diameter = '),
str(tool),
units.lower(),
_('started.'))
app_obj.inform.emit('[success] %s = %s%s %s' % (
_('NCC Tool clearing with tool diameter'), str(tool), units.lower(), _('started.'))
)
app_obj.proc_container.update_view_text(' %d%%' % 0)
@ -2240,7 +2276,8 @@ class NonCopperClear(FlatCAMTool, Gerber):
elif isinstance(p, MultiPolygon):
for poly in p:
if poly is not None:
# provide the app with a way to process the GUI events when in a blocking loop
# provide the app with a way to process the GUI events when
# in a blocking loop
QtWidgets.QApplication.processEvents()
try:
@ -2337,7 +2374,7 @@ class NonCopperClear(FlatCAMTool, Gerber):
self.app.inform.emit(
'[WARNING] %s: %s %s.' % (_("NCC Tool Rest Machining clear all done but the copper features "
"isolation is broken for"), str(warning_flag), _("tools")))
return
return
# create the solid_geometry
geo_obj.solid_geometry = list()

View File

@ -37,13 +37,11 @@ class TclCommandCncjob(TclCommandSignaled):
('extracut', bool),
('extracut_length', float),
('depthperpass', float),
('toolchange', int),
('toolchangez', float),
('toolchangexy', tuple),
('startz', float),
('endz', float),
('spindlespeed', int),
('dwell', bool),
('dwelltime', float),
('pp', str),
('muted', int),
@ -69,13 +67,14 @@ class TclCommandCncjob(TclCommandSignaled):
('extracut', 'The value for extra cnccut over the first point in path,in the job end; float'),
('depthperpass', 'Height of one layer for multidepth.'),
('toolchange', 'Enable tool changes (example: True).'),
('toolchangez', 'Z distance for toolchange (example: 30.0).'),
('toolchangez', 'Z distance for toolchange (example: 30.0).\n'
'If used in the command then a toolchange event will be included in gcode'),
('toolchangexy', 'X, Y coordonates for toolchange in format (x, y) (example: (2.0, 3.1) ).'),
('startz', 'Height before the first move.'),
('endz', 'Height where the last move will park.'),
('spindlespeed', 'Speed of the spindle in rpm (example: 4000).'),
('dwell', 'True or False; use (or not) the dwell'),
('dwelltime', 'Time to pause to allow the spindle to reach the full speed'),
('dwelltime', 'Time to pause to allow the spindle to reach the full speed.\n'
'If it is not used in command then it will not be included'),
('outname', 'Name of the resulting Geometry object.'),
('pp', 'Name of the Geometry preprocessor. No quotes, case sensitive'),
('muted', 'It will not put errors in the Shell.')
@ -138,8 +137,12 @@ class TclCommandCncjob(TclCommandSignaled):
args["multidepth"] = bool(args["multidepth"]) if "multidepth" in args else obj.options["multidepth"]
args["extracut"] = bool(args["extracut"]) if "extracut" in args else obj.options["extracut"]
args["extracut_length"] = float(args["extracut_length"]) if "extracut_length" in args else \
obj.options["extracut_length"]
if "extracut_length" in args:
args["extracut_length"] = float(args["extracut_length"])
else:
args["extracut_length"] = 0.0
args["depthperpass"] = args["depthperpass"] if "depthperpass" in args and args["depthperpass"] else \
obj.options["depthperpass"]
@ -148,14 +151,29 @@ class TclCommandCncjob(TclCommandSignaled):
args["endz"] = args["endz"] if "endz" in args and args["endz"] else obj.options["endz"]
args["spindlespeed"] = args["spindlespeed"] if "spindlespeed" in args and args["spindlespeed"] != 0 else None
args["dwell"] = bool(args["dwell"]) if "dwell" in args else obj.options["dwell"]
args["dwelltime"] = args["dwelltime"] if "dwelltime" in args and args["dwelltime"] else obj.options["dwelltime"]
if 'dwelltime' in args:
args["dwell"] = True
if args['dwelltime'] is not None:
args["dwelltime"] = float(args['dwelltime'])
else:
args["dwelltime"] = float(obj.options["dwelltime"])
else:
args["dwell"] = False
args["dwelltime"] = 0.0
args["pp"] = args["pp"] if "pp" in args and args["pp"] else obj.options["ppname_g"]
args["toolchange"] = True if "toolchange" in args and args["toolchange"] == 1 else False
args["toolchangez"] = args["toolchangez"] if "toolchangez" in args and args["toolchangez"] else \
obj.options["toolchangez"]
if "toolchangez" in args:
args["toolchange"] = True
if args["toolchangez"] is not None:
args["toolchangez"] = args["toolchangez"]
else:
args["toolchangez"] = obj.options["toolchangez"]
else:
args["toolchange"] = False
args["toolchangez"] = 0.0
args["toolchangexy"] = args["toolchangexy"] if "toolchangexy" in args and args["toolchangexy"] else \
self.app.defaults["geometry_toolchangexy"]

View File

@ -48,18 +48,20 @@ class TclCommandDrillcncjob(TclCommandSignaled):
'args': collections.OrderedDict([
('name', 'Name of the source object.'),
('drilled_dias',
'Comma separated tool diameters of the drills to be drilled (example: 0.6,1.0 or 3.125). No space allowed'),
'Comma separated tool diameters of the drills to be drilled (example: 0.6,1.0 or 3.125). '
'No space allowed'),
('drillz', 'Drill depth into material (example: -2.0).'),
('travelz', 'Travel distance above material (example: 2.0).'),
('feedrate', 'Drilling feed rate.'),
('feedrate_rapid', 'Rapid drilling feed rate.'),
('spindlespeed', 'Speed of the spindle in rpm (example: 4000).'),
('toolchange', 'Enable tool changes (example: True).'),
('toolchangez', 'Z distance for toolchange (example: 30.0).'),
('toolchangez', 'Z distance for toolchange (example: 30.0).\n'
'If used in the command then a toolchange event will be included in gcode'),
('toolchangexy', 'X, Y coordonates for toolchange in format (x, y) (example: (2.0, 3.1) ).'),
('endz', 'Z distance at job end (example: 30.0).'),
('dwell', 'True or False; use (or not) the dwell'),
('dwelltime', 'Time to pause to allow the spindle to reach the full speed'),
('dwelltime', 'Time to pause to allow the spindle to reach the full speed.\n'
'If it is not used in command then it will not be included'),
('pp', 'This is the Excellon preprocessor name: case_sensitive, no_quotes'),
('outname', 'Name of the resulting Geometry object.'),
('opt_type', 'Name of move optimization type. B by default for Basic OR-Tools, M for Metaheuristic OR-Tools'
@ -73,7 +75,7 @@ class TclCommandDrillcncjob(TclCommandSignaled):
('muted', 'It will not put errors in the Shell or status bar.')
]),
'examples': ['drillcncjob test.TXT -drillz -1.5 -travelz 14 -feedrate 222 -feedrate_rapid 456 -spindlespeed 777'
' -toolchange True -toolchangez 33 -endz 22 -pp default\n'
' -toolchangez 33 -endz 22 -pp default\n'
'Usage of -feedrate_rapid matter only when the preprocessor is using it, like -marlin-.']
}
@ -118,7 +120,6 @@ class TclCommandDrillcncjob(TclCommandSignaled):
def job_init(job_obj, app_obj):
# tools = args["tools"] if "tools" in args else 'all'
units = self.app.defaults['units'].upper()
try:
if 'drilled_dias' in args and args['drilled_dias'] != 'all':
@ -171,11 +172,19 @@ class TclCommandDrillcncjob(TclCommandSignaled):
else:
return "fail"
drillz = args["drillz"] if "drillz" in args and args["drillz"] else obj.options["drillz"]
toolchangez = args["toolchangez"] if "toolchangez" in args and args["toolchangez"] else \
obj.options["toolchangez"]
endz = args["endz"] if "endz" in args and args["endz"] else obj.options["endz"]
toolchange = True if "toolchange" in args and bool(args["toolchange"]) is True else False
drillz = args["drillz"] if "drillz" in args and args["drillz"] is not None else obj.options["drillz"]
if "toolchangez" in args:
toolchange = True
if args["toolchangez"] is not None:
toolchangez = args["toolchangez"]
else:
toolchangez = obj.options["toolchangez"]
else:
toolchange = False
toolchangez = 0.0
endz = args["endz"] if "endz" in args and args["endz"] is not None else obj.options["endz"]
opt_type = args["opt_type"] if "opt_type" in args and args["opt_type"] else 'B'
job_obj.z_move = args["travelz"] if "travelz" in args and args["travelz"] else obj.options["travelz"]
@ -183,12 +192,15 @@ class TclCommandDrillcncjob(TclCommandSignaled):
job_obj.feedrate_rapid = args["feedrate_rapid"] \
if "feedrate_rapid" in args and args["feedrate_rapid"] else obj.options["feedrate_rapid"]
if bool(args['dwell']) and args['dwelltime']:
if 'dwelltime' in args:
job_obj.dwell = True
job_obj.dwelltime = float(args['dwelltime'])
if args['dwelltime'] is not None:
job_obj.dwelltime = float(args['dwelltime'])
else:
job_obj.dwelltime = float(obj.options["dwelltime"])
else:
job_obj.dwell = obj.options["dwell"]
job_obj.dwelltime = float(obj.options["dwelltime"])
job_obj.dwell = False
job_obj.dwelltime = 0.0
job_obj.spindlespeed = args["spindlespeed"] if "spindlespeed" in args else None
job_obj.pp_excellon_name = args["pp"] if "pp" in args and args["pp"] \
@ -221,7 +233,6 @@ class TclCommandDrillcncjob(TclCommandSignaled):
# for now there is no tool offset support in this Tcl Command so we write the 0.0 value here
job_obj.tool_offset[t_item] = 0.0
print(job_obj.tool_offset)
job_obj.origin_kind = 'excellon'
job_obj.gcode_parse()