TclCommandCopperClear.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. from tclCommands.TclCommand import TclCommand
  2. import collections
  3. import logging
  4. import gettext
  5. import FlatCAMTranslation as fcTranslate
  6. import builtins
  7. fcTranslate.apply_language('strings')
  8. if '_' not in builtins.__dict__:
  9. _ = gettext.gettext
  10. log = logging.getLogger('base')
  11. class TclCommandCopperClear(TclCommand):
  12. """
  13. Clear the non-copper areas.
  14. """
  15. # Array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
  16. aliases = ['ncc_clear', 'ncc']
  17. description = '%s %s' % ("--", "Clear excess copper.")
  18. # dictionary of types from Tcl command, needs to be ordered
  19. arg_names = collections.OrderedDict([
  20. ('name', str),
  21. ])
  22. # dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value
  23. option_types = collections.OrderedDict([
  24. ('tooldia', str),
  25. ('overlap', float),
  26. ('order', str),
  27. ('margin', float),
  28. ('method', str),
  29. ('connect', str),
  30. ('contour', str),
  31. ('has_offset', str),
  32. ('offset', float),
  33. ('rest', str),
  34. ('all', int),
  35. ('ref', str),
  36. ('box', str),
  37. ('outname', str),
  38. ])
  39. # array of mandatory options for current Tcl command: required = {'name','outname'}
  40. required = ['name']
  41. # structured help for current command, args needs to be ordered
  42. help = {
  43. 'main': "Clear excess copper in polygons. Basically it's a negative Paint.",
  44. 'args': collections.OrderedDict([
  45. ('name', 'Name of the source Geometry object. String.'),
  46. ('tooldia', 'Diameter of the tool to be used. Can be a comma separated list of diameters. No space is '
  47. 'allowed between tool diameters. E.g: correct: 0.5,1 / incorrect: 0.5, 1'),
  48. ('overlap', 'Percentage of tool diameter to overlap current pass over previous pass. Float [0, 99.9999]\n'
  49. 'E.g: for a 25% from tool diameter overlap use -overlap 25'),
  50. ('margin', 'Bounding box margin. Float number.'),
  51. ('order', 'Can have the values: "no", "fwd" and "rev". String.'
  52. 'It is useful when there are multiple tools in tooldia parameter.'
  53. '"no" -> the order used is the one provided.'
  54. '"fwd" -> tools are ordered from smallest to biggest.'
  55. '"rev" -> tools are ordered from biggest to smallest.'),
  56. ('method', 'Algorithm for copper clearing. Can be: "standard", "seed" or "lines".'),
  57. ('connect', 'Draw lines to minimize tool lifts. True (1) or False (0)'),
  58. ('contour', 'Cut around the perimeter of the painting. True (1) or False (0)'),
  59. ('rest', 'Use rest-machining. True (1) or False (0)'),
  60. ('has_offset', 'The offset will used only if this is set True or present in args. True (1) or False (0).'),
  61. ('offset', 'The copper clearing will finish to a distance from copper features. Float number.'),
  62. ('all', 'Will copper clear the whole object. 1 or True = enabled, anything else = disabled'),
  63. ('ref', 'Will clear of extra copper all polygons within a specified object with the name in "box" '
  64. 'parameter. 1 or True = enabled, 0 or False = disabled'),
  65. ('box', 'Name of the object to be used as reference. Required when selecting "ref" = 1 or True. String.'),
  66. ('outname', 'Name of the resulting Geometry object. String.'),
  67. ]),
  68. 'examples': ["ncc obj_name -tooldia 0.3,1 -overlap 10 -margin 1.0 -method 'lines' -all True"]
  69. }
  70. def execute(self, args, unnamed_args):
  71. """
  72. execute current TCL shell command
  73. :param args: array of known named arguments and options
  74. :param unnamed_args: array of other values which were passed into command
  75. without -somename and we do not have them in known arg_names
  76. :return: None or exception
  77. """
  78. name = args['name']
  79. # Get source object.
  80. try:
  81. obj = self.app.collection.get_by_name(str(name))
  82. except Exception as e:
  83. log.debug("TclCommandCopperClear.execute() --> %s" % str(e))
  84. self.raise_tcl_error("%s: %s" % (_("Could not retrieve object"), name))
  85. return "Could not retrieve object: %s" % name
  86. if obj is None:
  87. return "Object not found: %s" % name
  88. if 'tooldia' in args:
  89. tooldia = str(args['tooldia'])
  90. else:
  91. tooldia = self.app.defaults["tools_ncctools"]
  92. if 'overlap' in args:
  93. overlap = float(args['overlap']) / 100.0
  94. else:
  95. overlap = float(self.app.defaults["tools_nccoverlap"]) / 100.0
  96. if 'order' in args:
  97. order = args['order']
  98. else:
  99. order = str(self.app.defaults["tools_nccorder"])
  100. if 'margin' in args:
  101. margin = float(args['margin'])
  102. else:
  103. margin = float(self.app.defaults["tools_nccmargin"])
  104. if 'method' in args:
  105. method = args['method']
  106. else:
  107. method = str(self.app.defaults["tools_nccmethod"])
  108. if 'connect' in args:
  109. connect = bool(eval(args['connect']))
  110. else:
  111. connect = bool(eval(str(self.app.defaults["tools_nccconnect"])))
  112. if 'contour' in args:
  113. contour = bool(eval(args['contour']))
  114. else:
  115. contour = bool(eval(str(self.app.defaults["tools_ncccontour"])))
  116. offset = 0.0
  117. if 'has_offset' in args:
  118. has_offset = bool(eval(args['has_offset']))
  119. if args['has_offset'] is True:
  120. if 'offset' in args:
  121. offset = float(args['margin'])
  122. else:
  123. # 'offset' has to be in args if 'has_offset' is and it is set True
  124. self.raise_tcl_error("%s: %s" % (_("Could not retrieve object"), name))
  125. else:
  126. has_offset = False
  127. try:
  128. tools = [float(eval(dia)) for dia in tooldia.split(",") if dia != '']
  129. except AttributeError:
  130. tools = [float(tooldia)]
  131. # store here the default data for Geometry Data
  132. default_data = {}
  133. default_data.update({
  134. "name": '_paint',
  135. "plot": self.app.defaults["geometry_plot"],
  136. "cutz": self.app.defaults["geometry_cutz"],
  137. "vtipdia": 0.1,
  138. "vtipangle": 30,
  139. "travelz": self.app.defaults["geometry_travelz"],
  140. "feedrate": self.app.defaults["geometry_feedrate"],
  141. "feedrate_z": self.app.defaults["geometry_feedrate_z"],
  142. "feedrate_rapid": self.app.defaults["geometry_feedrate_rapid"],
  143. "dwell": self.app.defaults["geometry_dwell"],
  144. "dwelltime": self.app.defaults["geometry_dwelltime"],
  145. "multidepth": self.app.defaults["geometry_multidepth"],
  146. "ppname_g": self.app.defaults["geometry_ppname_g"],
  147. "depthperpass": self.app.defaults["geometry_depthperpass"],
  148. "extracut": self.app.defaults["geometry_extracut"],
  149. "extracut_length": self.app.defaults["geometry_extracut_length"],
  150. "toolchange": self.app.defaults["geometry_toolchange"],
  151. "toolchangez": self.app.defaults["geometry_toolchangez"],
  152. "endz": self.app.defaults["geometry_endz"],
  153. "endxy": self.app.defaults["geometry_endxy"],
  154. "spindlespeed": self.app.defaults["geometry_spindlespeed"],
  155. "toolchangexy": self.app.defaults["geometry_toolchangexy"],
  156. "startz": self.app.defaults["geometry_startz"],
  157. "tooldia": self.app.defaults["tools_painttooldia"],
  158. "paintmargin": self.app.defaults["tools_paintmargin"],
  159. "paintmethod": self.app.defaults["tools_paintmethod"],
  160. "selectmethod": self.app.defaults["tools_selectmethod"],
  161. "pathconnect": self.app.defaults["tools_pathconnect"],
  162. "paintcontour": self.app.defaults["tools_paintcontour"],
  163. "paintoverlap": self.app.defaults["tools_paintoverlap"]
  164. })
  165. ncc_tools = {}
  166. tooluid = 0
  167. for tool in tools:
  168. tooluid += 1
  169. ncc_tools.update({
  170. int(tooluid): {
  171. 'tooldia': float('%.*f' % (obj.decimals, tool)),
  172. 'offset': 'Path',
  173. 'offset_value': 0.0,
  174. 'type': 'Iso',
  175. 'tool_type': 'C1',
  176. 'data': dict(default_data),
  177. 'solid_geometry': []
  178. }
  179. })
  180. if 'rest' in args:
  181. rest = bool(eval(args['rest']))
  182. else:
  183. rest = bool(eval(str(self.app.defaults["tools_nccrest"])))
  184. if 'outname' in args:
  185. outname = args['outname']
  186. else:
  187. if rest is True:
  188. outname = name + "_ncc"
  189. else:
  190. outname = name + "_ncc_rm"
  191. # Non-Copper clear all polygons in the non-copper clear object
  192. if 'all' in args and bool(args['all']):
  193. self.app.ncclear_tool.clear_copper_tcl(ncc_obj=obj,
  194. select_method='itself',
  195. ncctooldia=tooldia,
  196. overlap=overlap,
  197. order=order,
  198. margin=margin,
  199. has_offset=has_offset,
  200. offset=offset,
  201. method=method,
  202. outname=outname,
  203. connect=connect,
  204. contour=contour,
  205. rest=rest,
  206. tools_storage=ncc_tools,
  207. plot=False,
  208. run_threaded=False)
  209. return
  210. # Non-Copper clear all polygons found within the box object from the the non_copper cleared object
  211. elif 'ref' in args and bool(eval(args['ref'])):
  212. if 'box' not in args:
  213. self.raise_tcl_error('%s' % _("Expected -box <value>."))
  214. else:
  215. box_name = args['box']
  216. # Get box source object.
  217. try:
  218. box_obj = self.app.collection.get_by_name(str(box_name))
  219. except Exception as e:
  220. log.debug("TclCommandCopperClear.execute() --> %s" % str(e))
  221. self.raise_tcl_error("%s: %s" % (_("Could not retrieve box object"), name))
  222. return "Could not retrieve object: %s" % name
  223. self.app.ncclear_tool.clear_copper_tcl(ncc_obj=obj,
  224. sel_obj=box_obj,
  225. select_method='box',
  226. ncctooldia=tooldia,
  227. overlap=overlap,
  228. order=order,
  229. margin=margin,
  230. has_offset=has_offset,
  231. offset=offset,
  232. method=method,
  233. outname=outname,
  234. connect=connect,
  235. contour=contour,
  236. rest=rest,
  237. tools_storage=ncc_tools,
  238. plot=False,
  239. run_threaded=False)
  240. return
  241. else:
  242. self.raise_tcl_error("%s:" % _("None of the following args: 'ref', 'all' were found or none was set to 1.\n"
  243. "Copper clearing failed."))
  244. return "None of the following args: 'ref', 'all' were found or none was set to 1.\n" \
  245. "Copper clearing failed."