- upgraded/fixed the Panelize Tcl command
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
Reference in New Issue
Block a user