- upgraded/fixed the Panelize Tcl command

This commit is contained in:
Marius Stanciu
2022-01-29 03:11:56 +02:00
committed by Marius
parent eb6ea7e623
commit 965ccca885
3 changed files with 178 additions and 47 deletions

View File

@@ -7,6 +7,10 @@ CHANGELOG for FlatCAM beta
================================================= =================================================
29.01.2022
- upgraded/fixed the Panelize Tcl command
28.01.2022 28.01.2022
- in Tcl command `geocutout` fixed an error due of a no longer used parameter - in Tcl command `geocutout` fixed an error due of a no longer used parameter

View File

@@ -408,6 +408,8 @@ class Panelize(AppTool):
self.app.inform.emit(_("Generating panel ... ")) self.app.inform.emit(_("Generating panel ... "))
def job_init_excellon(obj_fin, app_obj): def job_init_excellon(obj_fin, app_obj):
obj_fin.multitool = True
currenty = 0.0 currenty = 0.0
# init the storage for drills and for slots # init the storage for drills and for slots
for tool in copied_tools: for tool in copied_tools:
@@ -785,7 +787,7 @@ class Panelize(AppTool):
default_data[opt_key] = self.app.options[opt_key] default_data[opt_key] = self.app.options[opt_key]
new_obj.tools = {} new_obj.tools = {}
new_tid = 0 new_tid = 10
for apid in new_obj.tools: for apid in new_obj.tools:
new_tid += 1 new_tid += 1
new_sgeo = [g['solid'] for g in new_obj.tools[apid]['geometry'] if 'solid' in g] new_sgeo = [g['solid'] for g in new_obj.tools[apid]['geometry'] if 'solid' in g]
@@ -809,7 +811,7 @@ class Panelize(AppTool):
'data': deepcopy(default_data), 'data': deepcopy(default_data),
'solid_geometry': deepcopy(new_obj.solid_geometry) 'solid_geometry': deepcopy(new_obj.solid_geometry)
} }
del new_obj.tools del new_obj.tools # TODO what the hack is this? First we create and then immediately delete?
app_obj.inform.emit('%s' % _("Generating panel ... Adding the source code.")) app_obj.inform.emit('%s' % _("Generating panel ... Adding the source code."))
new_obj.source_file = self.app.f_handlers.export_dxf(obj_name=self.outname, filename=None, new_obj.source_file = self.app.f_handlers.export_dxf(obj_name=self.outname, filename=None,

View File

@@ -1,6 +1,7 @@
from tclCommands.TclCommand import TclCommand from tclCommands.TclCommand import TclCommand
import shapely.affinity as affinity import shapely.affinity as affinity
from shapely.geometry import MultiPolygon, MultiLineString
import logging import logging
from copy import deepcopy from copy import deepcopy
@@ -202,20 +203,36 @@ class TclCommandPanelize(TclCommand):
# if ret_value == 'fail': # if ret_value == 'fail':
# return 'fail' # return 'fail'
def panelize_2(): # ############################################################################################################
# make a copy of the panelized Excellon or Geometry tools
# ############################################################################################################
if obj.kind == 'excellon' or obj.kind == 'geometry':
copied_tools = {}
for tt, tt_val in list(obj.tools.items()):
copied_tools[tt] = deepcopy(tt_val)
# ############################################################################################################
# make a copy of the panelized Gerber apertures
# ############################################################################################################
if obj.kind == 'gerber':
copied_apertures = {}
for tt, tt_val in list(obj.tools.items()):
copied_apertures[tt] = deepcopy(tt_val)
def panelize_handler():
if obj is not None: if obj is not None:
self.app.inform.emit("Generating panel ... Please wait.") self.app.inform.emit("Generating panel ... Please wait.")
def job_init_excellon(obj_fin, app_obj): def job_init_excellon(obj_fin, app_obj):
currenty = 0.0 obj_fin.multitool = True
obj_fin.tools = obj.tools.copy() currenty = 0.0
if 'drills' not in obj_fin.tools: # init the storage for drills and for slots
obj_fin.tools['drills'] = [] for tool in copied_tools:
if 'slots' not in obj_fin.tools: copied_tools[tool]['drills'] = []
obj_fin.tools['slots'] = [] copied_tools[tool]['slots'] = []
if 'solid_geometry' not in obj_fin.tools: obj_fin.tools = copied_tools
obj_fin.tools['solid_geometry'] = [] obj_fin.solid_geometry = []
for option in obj.options: for option in obj.options:
if option != 'name': if option != 'name':
@@ -223,28 +240,54 @@ class TclCommandPanelize(TclCommand):
obj_fin.options[option] = obj.options[option] obj_fin.options[option] = obj.options[option]
except Exception as e: except Exception as e:
app_obj.log.error("Failed to copy option: %s" % str(option)) app_obj.log.error("Failed to copy option: %s" % str(option))
app_obj.log.error("TclCommandPanelize.execute().panelize2() --> %s" % str(e)) app_obj.log.error(
"TclCommandPanelize.execute().panelize2.job_init_excellon() Options:--> %s" %
str(e))
# calculate the total number of drills and slots
geo_len_drills = 0
geo_len_slots = 0
for tool in copied_tools:
geo_len_drills += len(copied_tools[tool]['drills'])
geo_len_slots += len(copied_tools[tool]['slots'])
# panelization
for row in range(rows): for row in range(rows):
currentx = 0.0 currentx = 0.0
for col in range(columns): for col in range(columns):
if 'drills' in obj.tools: for tool in obj.tools:
for drill_pt in obj.tools['drills']: if 'drills' in obj.tools[tool]:
point_offseted = affinity.translate(drill_pt, currentx, currenty) if obj.tools[tool]['drills']:
obj_fin.tools['drills'].append(point_offseted) for drill in obj.tools[tool]['drills']:
if 'slots' in obj.tools: # offset / panelization
for slot_tuple in obj.tools['slots']: point_offseted = affinity.translate(drill, currentx, currenty)
start_offseted = affinity.translate(slot_tuple[0], currentx, currenty) obj_fin.tools[tool]['drills'].append(point_offseted)
stop_offseted = affinity.translate(slot_tuple[1], currentx, currenty) else:
obj_fin.tools['slots'].append( obj.tools[tool]['drills'] = []
(start_offseted, stop_offseted)
if 'slots' in obj.tools[tool]:
if obj.tools[tool]['slots']:
for slot in obj.tools[tool]['slots']:
# offset / panelization
start_offseted = affinity.translate(slot[0], currentx, currenty)
stop_offseted = affinity.translate(slot[1], currentx, currenty)
offseted_slot = (
start_offseted,
stop_offseted
) )
obj_fin.tools[tool]['slots'].append(offseted_slot)
else:
obj.tools[tool]['slots'] = []
currentx += lenghtx currentx += lenghtx
currenty += lenghty currenty += lenghty
obj_fin.create_geometry() obj_fin.create_geometry()
obj_fin.zeros = obj.zeros obj_fin.zeros = obj.zeros
obj_fin.units = obj.units obj_fin.units = obj.units
app_obj.inform.emit('%s' % _("Generating panel ... Adding the source code."))
obj_fin.source_file = app_obj.f_handlers.export_excellon(obj_name=outname, filename=None,
local_use=obj_fin, use_thread=False)
def job_init_geometry(obj_fin, app_obj): def job_init_geometry(obj_fin, app_obj):
currentx = 0.0 currentx = 0.0
@@ -261,27 +304,42 @@ class TclCommandPanelize(TclCommand):
obj_fin.solid_geometry = [] obj_fin.solid_geometry = []
if obj.kind == 'geometry': # create the initial structure on which to create the panel
obj_fin.multigeo = obj.multigeo obj_fin.multigeo = obj.multigeo
obj_fin.tools = deepcopy(obj.tools) obj_fin.tools = copied_tools
if obj.multigeo is True: if obj.multigeo is True:
for tool in obj.tools: for tool in obj.tools:
obj_fin.tools[tool]['solid_geometry'][:] = [] obj_fin.tools[tool]['solid_geometry'][:] = []
for row in range(rows): for row in range(rows):
currentx = 0.0 currentx = 0.0
for col in range(columns): for col in range(columns):
if obj.kind == 'geometry':
if obj.multigeo is True: if obj.multigeo is True:
for tool in obj.tools: for tool in obj.tools:
obj_fin.tools[tool]['solid_geometry'].append(translate_recursion( trans_geo = translate_recursion(obj.tools[tool]['solid_geometry'])
obj.tools[tool]['solid_geometry']) try:
) work_geo = trans_geo.geoms if \
else: isinstance(trans_geo, (MultiPolygon, MultiLineString)) else trans_geo
obj_fin.solid_geometry.append( for trans_it in work_geo:
translate_recursion(obj.solid_geometry) if not trans_it.is_empty:
) obj_fin.tools[tool]['solid_geometry'].append(trans_it)
except TypeError:
if not trans_geo.is_empty:
obj_fin.tools[tool]['solid_geometry'].append(trans_geo)
# #############################################################################
# ########## Panelize the solid_geometry - always done #####################
# #############################################################################
try:
sol_geo = obj.solid_geometry
work_geo = sol_geo.geoms if \
isinstance(sol_geo, (MultiPolygon, MultiLineString)) else sol_geo
for geo_el in work_geo:
trans_geo = translate_recursion(geo_el)
obj_fin.solid_geometry.append(trans_geo)
except TypeError:
trans_geo = translate_recursion(obj.solid_geometry)
obj_fin.solid_geometry.append(trans_geo)
else: else:
obj_fin.solid_geometry.append( obj_fin.solid_geometry.append(
translate_recursion(obj.solid_geometry) translate_recursion(obj.solid_geometry)
@@ -289,25 +347,92 @@ class TclCommandPanelize(TclCommand):
currentx += lenghtx currentx += lenghtx
currenty += lenghty currenty += lenghty
obj_fin.source_file = app_obj.f_handlers.export_dxf(obj_name=outname, filename=None,
local_use=obj_fin, use_thread=False)
def job_init_gerber(obj_fin, app_obj):
currentx = 0.0
currenty = 0.0
def translate_recursion(geom):
if type(geom) == list:
geoms = []
for local_geom in geom:
res_geo = translate_recursion(local_geom)
try:
geoms += res_geo
except TypeError:
geoms.append(res_geo)
return geoms
else:
return affinity.translate(geom, xoff=currentx, yoff=currenty)
obj_fin.solid_geometry = []
# create the initial structure on which to create the panel
obj_fin.tools = copied_apertures
for ap in obj_fin.tools:
obj_fin.tools[ap]['geometry'] = []
for row in range(rows):
currentx = 0.0
for col in range(columns):
# Will panelize a Gerber Object
for apid in obj.tools:
if 'geometry' in obj.tools[apid]:
# panelization -> apertures
for el in obj.tools[apid]['geometry']:
new_el = {}
if 'solid' in el:
geo_aper = translate_recursion(el['solid'])
new_el['solid'] = geo_aper
if 'clear' in el:
geo_aper = translate_recursion(el['clear'])
new_el['clear'] = geo_aper
if 'follow' in el:
geo_aper = translate_recursion(el['follow'])
new_el['follow'] = geo_aper
obj_fin.tools[apid]['geometry'].append(deepcopy(new_el))
# #####################################################################################
# ########## Panelize the solid_geometry - always done #############################
# #####################################################################################
try:
for geo_el in obj.solid_geometry:
trans_geo = translate_recursion(geo_el)
obj_fin.solid_geometry.append(trans_geo)
except TypeError:
trans_geo = translate_recursion(obj.solid_geometry)
obj_fin.solid_geometry.append(trans_geo)
currentx += lenghtx
currenty += lenghty
obj_fin.source_file = app_obj.f_handlers.export_gerber(obj_name=outname, filename=None,
local_use=obj_fin, use_thread=False)
if obj.kind == 'excellon': if obj.kind == 'excellon':
self.app.app_obj.new_object("excellon", outname, job_init_excellon, plot=False, autoselected=True) self.app.app_obj.new_object("excellon", outname, job_init_excellon, plot=False, autoselected=True)
else: elif obj.kind == 'geometry':
self.app.app_obj.new_object("geometry", outname, job_init_geometry, plot=False, autoselected=True) self.app.app_obj.new_object("geometry", outname, job_init_geometry, plot=False, autoselected=True)
else:
self.app.app_obj.new_object("gerber", outname, job_init_gerber, plot=False, autoselected=True)
if threaded is True: if threaded is True:
self.app.proc_container.new('%s...' % _("Working")) self.app.proc_container.new('%s...' % _("Working"))
def job_thread(app_obj): def job_thread(app_obj):
try: try:
panelize_2() panelize_handler()
app_obj.inform.emit('[success] %s' % _("Done.")) app_obj.inform.emit('[success] %s' % _("Done."))
except Exception as ee: except Exception as err:
log.error(str(ee)) app_obj.log.error('TclCommandPanelize.execute.job_thread() -> %s' % str(err))
return return
self.app.collection.promise(outname) self.app.collection.promise(outname)
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]}) self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
else: else:
panelize_2() try:
panelize_handler()
self.app.inform.emit('[success] %s' % _("Done.")) self.app.inform.emit('[success] %s' % _("Done."))
except Exception as ee:
self.app.log.error('TclCommandPanelize.execute() non-threaded -> %s' % str(ee))