| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- from tclCommands.TclCommand import TclCommand
- import shapely.affinity as affinity
- import logging
- from copy import deepcopy
- import collections
- log = logging.getLogger('base')
- class TclCommandPanelize(TclCommand):
- """
- Tcl shell command to panelize an object.
- example:
- """
- # List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
- aliases = ['panelize', 'pan', 'panel']
- description = '%s %s' % ("--", "Create a new object with an array of duplicates of the original geometry, "
- "arranged in a grid.")
- # 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),
- ('use_thread', 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': 'Create a new object with an array of duplicates of the original geometry, arranged in a grid.',
- '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.'),
- ('use_thread', 'False (0) = non-threaded execution or True (1) = threaded execution')
- ]),
- 'examples': [
- 'panelize obj_name',
- 'panel obj_name -rows 2 -columns 2 -spacing_columns 0.4 -spacing_rows 1.3 -box box_obj_name '
- '-outname panelized_name',
- 'panel obj_name -columns 2 -box box_obj_name -outname panelized_name',
- ]
- }
- 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 Exception:
- 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 Exception:
- return "Could not retrieve object: %s" % name
- else:
- box = obj
- if 'columns' in args:
- columns = int(args['columns'])
- else:
- columns = int(0)
- if 'rows' in args:
- rows = int(args['rows'])
- else:
- rows = int(0)
- if 'columns' not in args and 'rows' not in args:
- return "ERROR: Specify either -columns or -rows. The one not specified it will assumed to be 0"
- if 'outname' in args:
- outname = args['outname']
- else:
- outname = name + '_panelized'
- if 'use_thread' in args:
- try:
- par = args['use_thread'].capitalize()
- except AttributeError:
- par = args['use_thread']
- threaded = bool(eval(par))
- else:
- threaded = False
- if 'spacing_columns' in args:
- spacing_columns = int(args['spacing_columns'])
- else:
- spacing_columns = 5
- if 'spacing_rows' in args:
- spacing_rows = int(args['spacing_rows'])
- else:
- spacing_rows = 5
- xmin, ymin, xmax, ymax = box.bounds()
- lenghtx = xmax - xmin + spacing_columns
- lenghty = ymax - ymin + spacing_rows
- # def panelize():
- # currenty = 0
- #
- # def initialize_local(obj_init, app):
- # obj_init.solid_geometry = obj.solid_geometry
- # obj_init.offset([float(currentx), float(currenty)])
- # objs.append(obj_init)
- #
- # def initialize_local_excellon(obj_init, app):
- # obj_init.tools = obj.tools
- # # drills are offset, so they need to be deep copied
- # obj_init.drills = deepcopy(obj.drills)
- # obj_init.offset([float(currentx), float(currenty)])
- # obj_init.create_geometry()
- # objs.append(obj_init)
- #
- # def initialize_geometry(obj_init, app):
- # GeometryObject.merge(objs, obj_init)
- #
- # def initialize_excellon(obj_init, app):
- # # merge expects tools to exist in the target object
- # obj_init.tools = obj.tools.copy()
- # ExcellonObject.merge(objs, obj_init)
- #
- # objs = []
- # if obj is not None:
- #
- # for row in range(rows):
- # currentx = 0
- # for col in range(columns):
- # local_outname = outname + ".tmp." + str(col) + "." + str(row)
- # if isinstance(obj, ExcellonObject):
- # self.app.app_obj.new_object("excellon", local_outname, initialize_local_excellon,
- # plot=False,
- # autoselected=False)
- # else:
- # self.app.app_obj.new_object("geometry", local_outname, initialize_local, plot=False,
- # autoselected=False)
- #
- # currentx += lenghtx
- # currenty += lenghty
- #
- # if isinstance(obj, ExcellonObject):
- # self.app.app_obj.new_object("excellon", outname, initialize_excellon)
- # else:
- # self.app.app_obj.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 "fail"
- #
- # ret_value = panelize()
- # if ret_value == 'fail':
- # return 'fail'
- def panelize_2():
- if obj is not None:
- self.app.inform.emit("Generating panel ... Please wait.")
- def job_init_excellon(obj_fin, app_obj):
- currenty = 0.0
- obj_fin.tools = obj.tools.copy()
- if 'drills' not in obj_fin.tools:
- obj_fin.tools['drills'] = []
- if 'slots' not in obj_fin.tools:
- obj_fin.tools['slots'] = []
- if 'solid_geometry' not in obj_fin.tools:
- obj_fin.tools['solid_geometry'] = []
- for option in obj.options:
- if option != 'name':
- try:
- obj_fin.options[option] = obj.options[option]
- except Exception as e:
- app_obj.log.warning("Failed to copy option: %s" % str(option))
- app_obj.log.debug("TclCommandPanelize.execute().panelize2() --> %s" % str(e))
- for row in range(rows):
- currentx = 0.0
- for col in range(columns):
- if 'drills' in obj.tools:
- for drill_pt in obj.tools['drills']:
- point_offseted = affinity.translate(drill_pt, currentx, currenty)
- obj_fin.tools['drills'].append(point_offseted)
- if 'slots' in obj.tools:
- for slot_tuple in obj.tools['slots']:
- start_offseted = affinity.translate(slot_tuple[0], currentx, currenty)
- stop_offseted = affinity.translate(slot_tuple[1], currentx, currenty)
- obj_fin.tools['slots'].append(
- (start_offseted, stop_offseted)
- )
- currentx += lenghtx
- currenty += lenghty
- obj_fin.create_geometry()
- obj_fin.zeros = obj.zeros
- obj_fin.units = obj.units
- def job_init_geometry(obj_fin, app_obj):
- currentx = 0.0
- currenty = 0.0
- def translate_recursion(geom):
- if type(geom) == list:
- geoms = []
- for local_geom in geom:
- geoms.append(translate_recursion(local_geom))
- return geoms
- else:
- return affinity.translate(geom, xoff=currentx, yoff=currenty)
- obj_fin.solid_geometry = []
- if obj.kind == 'geometry':
- obj_fin.multigeo = obj.multigeo
- obj_fin.tools = deepcopy(obj.tools)
- if obj.multigeo is True:
- for tool in obj.tools:
- obj_fin.tools[tool]['solid_geometry'][:] = []
- for row in range(rows):
- currentx = 0.0
- for col in range(columns):
- if obj.kind == 'geometry':
- if obj.multigeo is True:
- for tool in obj.tools:
- obj_fin.tools[tool]['solid_geometry'].append(translate_recursion(
- obj.tools[tool]['solid_geometry'])
- )
- else:
- obj_fin.solid_geometry.append(
- translate_recursion(obj.solid_geometry)
- )
- else:
- obj_fin.solid_geometry.append(
- translate_recursion(obj.solid_geometry)
- )
- currentx += lenghtx
- currenty += lenghty
- if obj.kind == 'excellon':
- self.app.app_obj.new_object("excellon", outname, job_init_excellon, plot=False, autoselected=True)
- else:
- self.app.app_obj.new_object("geometry", outname, job_init_geometry, plot=False, autoselected=True)
- if threaded is True:
- self.app.proc_container.new(_("Working ..."))
- def job_thread(app_obj):
- try:
- panelize_2()
- app_obj.inform.emit('[success]' % _("Done."))
- except Exception as ee:
- log.debug(str(ee))
- return
- self.app.collection.promise(outname)
- self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
- else:
- panelize_2()
- self.app.inform.emit('[success]' % _("Done."))
|