ToolRulesCheck.py 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. # ########################################################## ##
  2. # FlatCAM: 2D Post-processing for Manufacturing #
  3. # http://flatcam.org #
  4. # File Author: Marius Adrian Stanciu (c) #
  5. # Date: 09/27/2019 #
  6. # MIT Licence #
  7. # ########################################################## ##
  8. from FlatCAMTool import FlatCAMTool
  9. from copy import copy, deepcopy
  10. from ObjectCollection import *
  11. import time
  12. import gettext
  13. import FlatCAMTranslation as fcTranslate
  14. import builtins
  15. fcTranslate.apply_language('strings')
  16. if '_' not in builtins.__dict__:
  17. _ = gettext.gettext
  18. class RulesCheck(FlatCAMTool):
  19. toolName = _("Check Rules")
  20. def __init__(self, app):
  21. super(RulesCheck, self).__init__(self)
  22. self.app = app
  23. # ## Title
  24. title_label = QtWidgets.QLabel("%s" % self.toolName)
  25. title_label.setStyleSheet("""
  26. QLabel
  27. {
  28. font-size: 16px;
  29. font-weight: bold;
  30. }
  31. """)
  32. self.layout.addWidget(title_label)
  33. # Form Layout
  34. form_layout = QtWidgets.QFormLayout()
  35. self.layout.addLayout(form_layout)
  36. self.gerber_title_lbl = QtWidgets.QLabel('<b>%s</b>:' % _("Gerber Files"))
  37. self.gerber_title_lbl.setToolTip(
  38. _("Gerber files for which to check rules.")
  39. )
  40. # Copper object
  41. self.copper_object = QtWidgets.QComboBox()
  42. self.copper_object.setModel(self.app.collection)
  43. self.copper_object.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
  44. self.copper_object.setCurrentIndex(1)
  45. self.copper_object_lbl = QtWidgets.QLabel('%s:' % _("Copper"))
  46. self.copper_object_lbl.setToolTip(
  47. _("Object to be panelized. This means that it will\n"
  48. "be duplicated in an array of rows and columns.")
  49. )
  50. # SolderMask object
  51. self.sm_object = QtWidgets.QComboBox()
  52. self.sm_object.setModel(self.app.collection)
  53. self.sm_object.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
  54. self.sm_object.setCurrentIndex(1)
  55. self.sm_object_lbl = QtWidgets.QLabel('%s:' % _("SolderMask"))
  56. self.sm_object_lbl.setToolTip(
  57. _("Object to be panelized. This means that it will\n"
  58. "be duplicated in an array of rows and columns.")
  59. )
  60. # SilkScreen object
  61. self.ss_object = QtWidgets.QComboBox()
  62. self.ss_object.setModel(self.app.collection)
  63. self.ss_object.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
  64. self.ss_object.setCurrentIndex(1)
  65. self.ss_object_lbl = QtWidgets.QLabel('%s:' % _("Silkscreen"))
  66. self.ss_object_lbl.setToolTip(
  67. _("Object to be panelized. This means that it will\n"
  68. "be duplicated in an array of rows and columns.")
  69. )
  70. # Outline object
  71. self.outline_object = QtWidgets.QComboBox()
  72. self.outline_object.setModel(self.app.collection)
  73. self.outline_object.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
  74. self.outline_object.setCurrentIndex(1)
  75. self.outline_object_lbl = QtWidgets.QLabel('%s:' % _("Outline"))
  76. self.outline_object_lbl.setToolTip(
  77. _("Object to be panelized. This means that it will\n"
  78. "be duplicated in an array of rows and columns.")
  79. )
  80. form_layout.addRow(self.gerber_title_lbl)
  81. form_layout.addRow(self.copper_object_lbl, self.copper_object)
  82. form_layout.addRow(self.sm_object_lbl, self.sm_object)
  83. form_layout.addRow(self.ss_object_lbl, self.ss_object)
  84. form_layout.addRow(self.outline_object_lbl, self.outline_object)
  85. form_layout.addRow(QtWidgets.QLabel(""))
  86. self.excellon_title_lbl = QtWidgets.QLabel('<b>%s</b>:' % _("Excellon Files"))
  87. self.excellon_title_lbl.setToolTip(
  88. _("Excellon files for which to check rules.")
  89. )
  90. # Excellon 1 object
  91. self.e1_object = QtWidgets.QComboBox()
  92. self.e1_object.setModel(self.app.collection)
  93. self.e1_object.setRootModelIndex(self.app.collection.index(1, 0, QtCore.QModelIndex()))
  94. self.e1_object.setCurrentIndex(1)
  95. self.e1_object_lbl = QtWidgets.QLabel('%s:' % _("Excellon 1"))
  96. self.e1_object_lbl.setToolTip(
  97. _("Object to be panelized. This means that it will\n"
  98. "be duplicated in an array of rows and columns.")
  99. )
  100. # Excellon 2 object
  101. self.e2_object = QtWidgets.QComboBox()
  102. self.e2_object.setModel(self.app.collection)
  103. self.e2_object.setRootModelIndex(self.app.collection.index(1, 0, QtCore.QModelIndex()))
  104. self.e2_object.setCurrentIndex(1)
  105. self.e2_object_lbl = QtWidgets.QLabel('%s:' % _("Excellon 2"))
  106. self.e2_object_lbl.setToolTip(
  107. _("Object to be panelized. This means that it will\n"
  108. "be duplicated in an array of rows and columns.")
  109. )
  110. form_layout.addRow(self.excellon_title_lbl)
  111. form_layout.addRow(self.e1_object_lbl, self.e1_object)
  112. form_layout.addRow(self.e2_object_lbl, self.e2_object)
  113. form_layout.addRow(QtWidgets.QLabel(""))
  114. # Form Layout
  115. form_layout_1 = QtWidgets.QFormLayout()
  116. self.layout.addLayout(form_layout_1)
  117. # Copper2copper clearance
  118. self.clearance_copper2copper_cb = FCCheckBox('%s:' % _("Copper to copper clearance"))
  119. self.clearance_copper2copper_cb.setToolTip(
  120. _("This checks if the minimum clearance between copper\n"
  121. "features is met.")
  122. )
  123. form_layout_1.addRow(self.clearance_copper2copper_cb)
  124. # Copper2copper clearance value
  125. self.clearance_copper2copper_entry = FCEntry()
  126. self.clearance_copper2copper_lbl = QtWidgets.QLabel('%s:' % _("Min value"))
  127. self.clearance_copper2copper_lbl.setToolTip(
  128. _("Minimum acceptable clearance value.")
  129. )
  130. form_layout_1.addRow(self.clearance_copper2copper_lbl, self.clearance_copper2copper_entry)
  131. self.c2c = OptionalInputSection(
  132. self.clearance_copper2copper_cb, [self.clearance_copper2copper_lbl, self.clearance_copper2copper_entry])
  133. # Copper2soldermask clearance
  134. self.clearance_copper2sm_cb = FCCheckBox('%s:' % _("Copper to soldermask clearance"))
  135. self.clearance_copper2sm_cb.setToolTip(
  136. _("This checks if the minimum clearance between copper\n"
  137. "features and soldermask features is met.")
  138. )
  139. form_layout_1.addRow(self.clearance_copper2sm_cb)
  140. # Copper2soldermask clearance value
  141. self.clearance_copper2sm_entry = FCEntry()
  142. self.clearance_copper2sm_lbl = QtWidgets.QLabel('%s:' % _("Min value"))
  143. self.clearance_copper2sm_lbl.setToolTip(
  144. _("Minimum acceptable clearance value.")
  145. )
  146. form_layout_1.addRow(self.clearance_copper2sm_lbl, self.clearance_copper2sm_entry)
  147. self.c2sm = OptionalInputSection(
  148. self.clearance_copper2sm_cb, [self.clearance_copper2sm_lbl, self.clearance_copper2sm_entry])
  149. # Copper2silkscreen clearance
  150. self.clearance_copper2sk_cb = FCCheckBox('%s:' % _("Copper to silkscreen clearance"))
  151. self.clearance_copper2sk_cb.setToolTip(
  152. _("This checks if the minimum clearance between copper\n"
  153. "features and silkscreen features is met.")
  154. )
  155. form_layout_1.addRow(self.clearance_copper2sk_cb)
  156. # Copper2silkscreen clearance value
  157. self.clearance_copper2sk_entry = FCEntry()
  158. self.clearance_copper2sk_lbl = QtWidgets.QLabel('%s:' % _("Min value"))
  159. self.clearance_copper2sk_lbl.setToolTip(
  160. _("Minimum acceptable clearance value.")
  161. )
  162. form_layout_1.addRow(self.clearance_copper2sk_lbl, self.clearance_copper2sk_entry)
  163. self.c2sk = OptionalInputSection(
  164. self.clearance_copper2sk_cb, [self.clearance_copper2sk_lbl, self.clearance_copper2sk_entry])
  165. # Copper2outline clearance
  166. self.clearance_copper2ol_cb = FCCheckBox('%s:' % _("Copper to outline clearance"))
  167. self.clearance_copper2ol_cb.setToolTip(
  168. _("This checks if the minimum clearance between copper\n"
  169. "features and the outline is met.")
  170. )
  171. form_layout_1.addRow(self.clearance_copper2ol_cb)
  172. # Copper2outline clearance value
  173. self.clearance_copper2ol_entry = FCEntry()
  174. self.clearance_copper2ol_lbl = QtWidgets.QLabel('%s:' % _("Min value"))
  175. self.clearance_copper2ol_lbl.setToolTip(
  176. _("Minimum acceptable clearance value.")
  177. )
  178. form_layout_1.addRow(self.clearance_copper2ol_lbl, self.clearance_copper2ol_entry)
  179. self.c2ol = OptionalInputSection(
  180. self.clearance_copper2ol_cb, [self.clearance_copper2ol_lbl, self.clearance_copper2ol_entry])
  181. # Silkscreen2silkscreen clearance
  182. self.clearance_silk2silk_cb = FCCheckBox('%s:' % _("Silkscreen to silkscreen clearance"))
  183. self.clearance_silk2silk_cb.setToolTip(
  184. _("This checks if the minimum clearance between silkscreen\n"
  185. "features and silkscreen features is met.")
  186. )
  187. form_layout_1.addRow(self.clearance_silk2silk_cb)
  188. # Copper2silkscreen clearance value
  189. self.clearance_silk2silk_entry = FCEntry()
  190. self.clearance_silk2silk_lbl = QtWidgets.QLabel('%s:' % _("Min value"))
  191. self.clearance_silk2silk_lbl.setToolTip(
  192. _("Minimum acceptable clearance value.")
  193. )
  194. form_layout_1.addRow(self.clearance_silk2silk_lbl, self.clearance_silk2silk_entry)
  195. self.s2s = OptionalInputSection(
  196. self.clearance_silk2silk_cb, [self.clearance_silk2silk_lbl, self.clearance_silk2silk_entry])
  197. # Silkscreen2soldermask clearance
  198. self.clearance_silk2sm_cb = FCCheckBox('%s:' % _("Silkscreen to soldermask clearance"))
  199. self.clearance_silk2sm_cb.setToolTip(
  200. _("This checks if the minimum clearance between silkscreen\n"
  201. "features and soldermask features is met.")
  202. )
  203. form_layout_1.addRow(self.clearance_silk2sm_cb)
  204. # Silkscreen2soldermask clearance value
  205. self.clearance_silk2sm_entry = FCEntry()
  206. self.clearance_silk2sm_lbl = QtWidgets.QLabel('%s:' % _("Min value"))
  207. self.clearance_silk2sm_lbl.setToolTip(
  208. _("Minimum acceptable clearance value.")
  209. )
  210. form_layout_1.addRow(self.clearance_silk2sm_lbl, self.clearance_silk2sm_entry)
  211. self.s2sm = OptionalInputSection(
  212. self.clearance_silk2sm_cb, [self.clearance_silk2sm_lbl, self.clearance_silk2sm_entry])
  213. # Soldermask2soldermask clearance
  214. self.clearance_sm2sm_cb = FCCheckBox('%s:' % _("Soldermask to soldermask clearance"))
  215. self.clearance_sm2sm_cb.setToolTip(
  216. _("This checks if the minimum clearance between soldermask\n"
  217. "features and soldermask features is met.")
  218. )
  219. form_layout_1.addRow(self.clearance_sm2sm_cb)
  220. # Soldermask2soldermask clearance value
  221. self.clearance_sm2sm_entry = FCEntry()
  222. self.clearance_sm2sm_lbl = QtWidgets.QLabel('%s:' % _("Min value"))
  223. self.clearance_sm2sm_lbl.setToolTip(
  224. _("Minimum acceptable clearance value.")
  225. )
  226. form_layout_1.addRow(self.clearance_sm2sm_lbl, self.clearance_sm2sm_entry)
  227. self.sm2sm = OptionalInputSection(
  228. self.clearance_sm2sm_cb, [self.clearance_sm2sm_lbl, self.clearance_sm2sm_entry])
  229. form_layout_1.addRow(QtWidgets.QLabel(""))
  230. # Drill2Drill clearance
  231. self.clearance_d2d_cb = FCCheckBox('%s:' % _("Drill hole to drill hole clearance"))
  232. self.clearance_d2d_cb.setToolTip(
  233. _("This checks if the minimum clearance between a drill hole\n"
  234. "and another drill hole is met.")
  235. )
  236. form_layout_1.addRow(self.clearance_d2d_cb)
  237. # Drill2Drill clearance value
  238. self.clearance_d2d_entry = FCEntry()
  239. self.clearance_d2d_lbl = QtWidgets.QLabel('%s:' % _("Min value"))
  240. self.clearance_d2d_lbl.setToolTip(
  241. _("Minimum acceptable clearance value.")
  242. )
  243. form_layout_1.addRow(self.clearance_d2d_lbl, self.clearance_d2d_entry)
  244. self.d2d = OptionalInputSection(
  245. self.clearance_d2d_cb, [self.clearance_d2d_lbl, self.clearance_d2d_entry])
  246. # Ring integrity check
  247. self.ring_integrity_cb = FCCheckBox('%s:' % _("Ring integrity check"))
  248. self.ring_integrity_cb.setToolTip(
  249. _("This checks if the minimum copper ring left by drilling\n"
  250. "a hole into a pad is met.")
  251. )
  252. form_layout_1.addRow(self.ring_integrity_cb)
  253. # Ring integrity value
  254. self.ring_integrity_entry = FCEntry()
  255. self.ring_integrity_lbl = QtWidgets.QLabel('%s:' % _("Min value"))
  256. self.ring_integrity_lbl.setToolTip(
  257. _("Minimum acceptable ring value.")
  258. )
  259. form_layout_1.addRow(self.ring_integrity_lbl, self.ring_integrity_entry)
  260. self.d2d = OptionalInputSection(
  261. self.ring_integrity_cb, [self.ring_integrity_lbl, self.ring_integrity_entry])
  262. # Drill holes overlap check
  263. self.drill_overlap_cb = FCCheckBox('%s:' % _("Drill hole overlap check"))
  264. self.drill_overlap_cb.setToolTip(
  265. _("This checks if drill holes are overlapping\n"
  266. "one over another.")
  267. )
  268. form_layout_1.addRow(self.drill_overlap_cb)
  269. # Buttons
  270. hlay_2 = QtWidgets.QHBoxLayout()
  271. self.layout.addLayout(hlay_2)
  272. # hlay_2.addStretch()
  273. self.run_button = QtWidgets.QPushButton(_("Run Rules Check"))
  274. self.run_button.setToolTip(
  275. _("Panelize the specified object around the specified box.\n"
  276. "In other words it creates multiple copies of the source object,\n"
  277. "arranged in a 2D array of rows and columns.")
  278. )
  279. hlay_2.addWidget(self.run_button)
  280. self.layout.addStretch()
  281. # #######################################################
  282. # ################ SIGNALS ##############################
  283. # #######################################################
  284. # self.app.collection.rowsInserted.connect(self.on_object_loaded)
  285. # list to hold the temporary objects
  286. self.objs = []
  287. # final name for the panel object
  288. self.outname = ""
  289. # flag to signal the constrain was activated
  290. self.constrain_flag = False
  291. # def on_object_loaded(self, index, row):
  292. # print(index.internalPointer().child_items[row].obj.options['name'], index.data())
  293. def run(self, toggle=True):
  294. self.app.report_usage("ToolRulesCheck()")
  295. if toggle:
  296. # if the splitter is hidden, display it, else hide it but only if the current widget is the same
  297. if self.app.ui.splitter.sizes()[0] == 0:
  298. self.app.ui.splitter.setSizes([1, 1])
  299. else:
  300. try:
  301. if self.app.ui.tool_scroll_area.widget().objectName() == self.toolName:
  302. # if tab is populated with the tool but it does not have the focus, focus on it
  303. if not self.app.ui.notebook.currentWidget() is self.app.ui.tool_tab:
  304. # focus on Tool Tab
  305. self.app.ui.notebook.setCurrentWidget(self.app.ui.tool_tab)
  306. else:
  307. self.app.ui.splitter.setSizes([0, 1])
  308. except AttributeError:
  309. pass
  310. else:
  311. if self.app.ui.splitter.sizes()[0] == 0:
  312. self.app.ui.splitter.setSizes([1, 1])
  313. FlatCAMTool.run(self)
  314. self.set_tool_ui()
  315. self.app.ui.notebook.setTabText(2, _("Rules Tool"))
  316. def install(self, icon=None, separator=None, **kwargs):
  317. FlatCAMTool.install(self, icon, separator, shortcut='ALT+R', **kwargs)
  318. def set_tool_ui(self):
  319. self.reset_fields()
  320. # def on_panelize(self):
  321. # name = self.object_combo.currentText()
  322. #
  323. # # Get source object.
  324. # try:
  325. # obj = self.app.collection.get_by_name(str(name))
  326. # except Exception as e:
  327. # log.debug("Panelize.on_panelize() --> %s" % str(e))
  328. # self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
  329. # (_("Could not retrieve object"), name))
  330. # return "Could not retrieve object: %s" % name
  331. #
  332. # panel_obj = obj
  333. #
  334. # if panel_obj is None:
  335. # self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
  336. # (_("Object not found"), panel_obj))
  337. # return "Object not found: %s" % panel_obj
  338. #
  339. # boxname = self.box_combo.currentText()
  340. #
  341. # try:
  342. # box = self.app.collection.get_by_name(boxname)
  343. # except Exception as e:
  344. # log.debug("Panelize.on_panelize() --> %s" % str(e))
  345. # self.app.inform.emit('[ERROR_NOTCL] %s: %s' %
  346. # (_("Could not retrieve object"), boxname))
  347. # return "Could not retrieve object: %s" % boxname
  348. #
  349. # if box is None:
  350. # self.app.inform.emit('[WARNING_NOTCL]%s: %s' %
  351. # (_("No object Box. Using instead"), panel_obj))
  352. # self.reference_radio.set_value('bbox')
  353. #
  354. # if self.reference_radio.get_value() == 'bbox':
  355. # box = panel_obj
  356. #
  357. # self.outname = name + '_panelized'
  358. #
  359. # try:
  360. # spacing_columns = float(self.spacing_columns.get_value())
  361. # except ValueError:
  362. # # try to convert comma to decimal point. if it's still not working error message and return
  363. # try:
  364. # spacing_columns = float(self.spacing_columns.get_value().replace(',', '.'))
  365. # except ValueError:
  366. # self.app.inform.emit('[ERROR_NOTCL] %s' %
  367. # _("Wrong value format entered, use a number."))
  368. # return
  369. # spacing_columns = spacing_columns if spacing_columns is not None else 0
  370. #
  371. # try:
  372. # spacing_rows = float(self.spacing_rows.get_value())
  373. # except ValueError:
  374. # # try to convert comma to decimal point. if it's still not working error message and return
  375. # try:
  376. # spacing_rows = float(self.spacing_rows.get_value().replace(',', '.'))
  377. # except ValueError:
  378. # self.app.inform.emit('[ERROR_NOTCL] %s' %
  379. # _("Wrong value format entered, use a number."))
  380. # return
  381. # spacing_rows = spacing_rows if spacing_rows is not None else 0
  382. #
  383. # try:
  384. # rows = int(self.rows.get_value())
  385. # except ValueError:
  386. # # try to convert comma to decimal point. if it's still not working error message and return
  387. # try:
  388. # rows = float(self.rows.get_value().replace(',', '.'))
  389. # rows = int(rows)
  390. # except ValueError:
  391. # self.app.inform.emit('[ERROR_NOTCL] %s' %
  392. # _("Wrong value format entered, use a number."))
  393. # return
  394. # rows = rows if rows is not None else 1
  395. #
  396. # try:
  397. # columns = int(self.columns.get_value())
  398. # except ValueError:
  399. # # try to convert comma to decimal point. if it's still not working error message and return
  400. # try:
  401. # columns = float(self.columns.get_value().replace(',', '.'))
  402. # columns = int(columns)
  403. # except ValueError:
  404. # self.app.inform.emit('[ERROR_NOTCL] %s' %
  405. # _("Wrong value format entered, use a number."))
  406. # return
  407. # columns = columns if columns is not None else 1
  408. #
  409. # try:
  410. # constrain_dx = float(self.x_width_entry.get_value())
  411. # except ValueError:
  412. # # try to convert comma to decimal point. if it's still not working error message and return
  413. # try:
  414. # constrain_dx = float(self.x_width_entry.get_value().replace(',', '.'))
  415. # except ValueError:
  416. # self.app.inform.emit('[ERROR_NOTCL] %s' %
  417. # _("Wrong value format entered, use a number."))
  418. # return
  419. #
  420. # try:
  421. # constrain_dy = float(self.y_height_entry.get_value())
  422. # except ValueError:
  423. # # try to convert comma to decimal point. if it's still not working error message and return
  424. # try:
  425. # constrain_dy = float(self.y_height_entry.get_value().replace(',', '.'))
  426. # except ValueError:
  427. # self.app.inform.emit('[ERROR_NOTCL] %s' %
  428. # _("Wrong value format entered, use a number."))
  429. # return
  430. #
  431. # panel_type = str(self.panel_type_radio.get_value())
  432. #
  433. # if 0 in {columns, rows}:
  434. # self.app.inform.emit('[ERROR_NOTCL] %s' %
  435. # _("Columns or Rows are zero value. Change them to a positive integer."))
  436. # return "Columns or Rows are zero value. Change them to a positive integer."
  437. #
  438. # xmin, ymin, xmax, ymax = box.bounds()
  439. # lenghtx = xmax - xmin + spacing_columns
  440. # lenghty = ymax - ymin + spacing_rows
  441. #
  442. # # check if constrain within an area is desired
  443. # if self.constrain_cb.isChecked():
  444. # panel_lengthx = ((xmax - xmin) * columns) + (spacing_columns * (columns - 1))
  445. # panel_lengthy = ((ymax - ymin) * rows) + (spacing_rows * (rows - 1))
  446. #
  447. # # adjust the number of columns and/or rows so the panel will fit within the panel constraint area
  448. # if (panel_lengthx > constrain_dx) or (panel_lengthy > constrain_dy):
  449. # self.constrain_flag = True
  450. #
  451. # while panel_lengthx > constrain_dx:
  452. # columns -= 1
  453. # panel_lengthx = ((xmax - xmin) * columns) + (spacing_columns * (columns - 1))
  454. # while panel_lengthy > constrain_dy:
  455. # rows -= 1
  456. # panel_lengthy = ((ymax - ymin) * rows) + (spacing_rows * (rows - 1))
  457. #
  458. # def panelize_2():
  459. # if panel_obj is not None:
  460. # self.app.inform.emit(_("Generating panel ... "))
  461. #
  462. # self.app.progress.emit(0)
  463. #
  464. # def job_init_excellon(obj_fin, app_obj):
  465. # currenty = 0.0
  466. # self.app.progress.emit(10)
  467. # obj_fin.tools = panel_obj.tools.copy()
  468. # obj_fin.drills = []
  469. # obj_fin.slots = []
  470. # obj_fin.solid_geometry = []
  471. #
  472. # for option in panel_obj.options:
  473. # if option is not 'name':
  474. # try:
  475. # obj_fin.options[option] = panel_obj.options[option]
  476. # except KeyError:
  477. # log.warning("Failed to copy option. %s" % str(option))
  478. #
  479. # geo_len_drills = len(panel_obj.drills) if panel_obj.drills else 0
  480. # geo_len_slots = len(panel_obj.slots) if panel_obj.slots else 0
  481. #
  482. # element = 0
  483. # for row in range(rows):
  484. # currentx = 0.0
  485. # for col in range(columns):
  486. # element += 1
  487. # disp_number = 0
  488. # old_disp_number = 0
  489. #
  490. # if panel_obj.drills:
  491. # drill_nr = 0
  492. # for tool_dict in panel_obj.drills:
  493. # if self.app.abort_flag:
  494. # # graceful abort requested by the user
  495. # raise FlatCAMApp.GracefulException
  496. #
  497. # point_offseted = affinity.translate(tool_dict['point'], currentx, currenty)
  498. # obj_fin.drills.append(
  499. # {
  500. # "point": point_offseted,
  501. # "tool": tool_dict['tool']
  502. # }
  503. # )
  504. #
  505. # drill_nr += 1
  506. # disp_number = int(np.interp(drill_nr, [0, geo_len_drills], [0, 100]))
  507. #
  508. # if disp_number > old_disp_number and disp_number <= 100:
  509. # self.app.proc_container.update_view_text(' %s: %d D:%d%%' %
  510. # (_("Copy"),
  511. # int(element),
  512. # disp_number))
  513. # old_disp_number = disp_number
  514. #
  515. # if panel_obj.slots:
  516. # slot_nr = 0
  517. # for tool_dict in panel_obj.slots:
  518. # if self.app.abort_flag:
  519. # # graceful abort requested by the user
  520. # raise FlatCAMApp.GracefulException
  521. #
  522. # start_offseted = affinity.translate(tool_dict['start'], currentx, currenty)
  523. # stop_offseted = affinity.translate(tool_dict['stop'], currentx, currenty)
  524. # obj_fin.slots.append(
  525. # {
  526. # "start": start_offseted,
  527. # "stop": stop_offseted,
  528. # "tool": tool_dict['tool']
  529. # }
  530. # )
  531. #
  532. # slot_nr += 1
  533. # disp_number = int(np.interp(slot_nr, [0, geo_len_slots], [0, 100]))
  534. #
  535. # if disp_number > old_disp_number and disp_number <= 100:
  536. # self.app.proc_container.update_view_text(' %s: %d S:%d%%' %
  537. # (_("Copy"),
  538. # int(element),
  539. # disp_number))
  540. # old_disp_number = disp_number
  541. #
  542. # currentx += lenghtx
  543. # currenty += lenghty
  544. #
  545. # obj_fin.create_geometry()
  546. # obj_fin.zeros = panel_obj.zeros
  547. # obj_fin.units = panel_obj.units
  548. # self.app.proc_container.update_view_text('')
  549. #
  550. # def job_init_geometry(obj_fin, app_obj):
  551. # currentx = 0.0
  552. # currenty = 0.0
  553. #
  554. # def translate_recursion(geom):
  555. # if type(geom) == list:
  556. # geoms = list()
  557. # for local_geom in geom:
  558. # res_geo = translate_recursion(local_geom)
  559. # try:
  560. # geoms += res_geo
  561. # except TypeError:
  562. # geoms.append(res_geo)
  563. # return geoms
  564. # else:
  565. # return affinity.translate(geom, xoff=currentx, yoff=currenty)
  566. #
  567. # obj_fin.solid_geometry = []
  568. #
  569. # # create the initial structure on which to create the panel
  570. # if isinstance(panel_obj, FlatCAMGeometry):
  571. # obj_fin.multigeo = panel_obj.multigeo
  572. # obj_fin.tools = deepcopy(panel_obj.tools)
  573. # if panel_obj.multigeo is True:
  574. # for tool in panel_obj.tools:
  575. # obj_fin.tools[tool]['solid_geometry'][:] = []
  576. # elif isinstance(panel_obj, FlatCAMGerber):
  577. # obj_fin.apertures = deepcopy(panel_obj.apertures)
  578. # for ap in obj_fin.apertures:
  579. # obj_fin.apertures[ap]['geometry'] = list()
  580. #
  581. # # find the number of polygons in the source solid_geometry
  582. # geo_len = 0
  583. # if isinstance(panel_obj, FlatCAMGeometry):
  584. # if panel_obj.multigeo is True:
  585. # for tool in panel_obj.tools:
  586. # try:
  587. # for pol in panel_obj.tools[tool]['solid_geometry']:
  588. # geo_len += 1
  589. # except TypeError:
  590. # geo_len = 1
  591. # else:
  592. # try:
  593. # for pol in panel_obj.solid_geometry:
  594. # geo_len += 1
  595. # except TypeError:
  596. # geo_len = 1
  597. # elif isinstance(panel_obj, FlatCAMGerber):
  598. # for ap in panel_obj.apertures:
  599. # for elem in panel_obj.apertures[ap]['geometry']:
  600. # geo_len += 1
  601. #
  602. # self.app.progress.emit(0)
  603. # element = 0
  604. # for row in range(rows):
  605. # currentx = 0.0
  606. #
  607. # for col in range(columns):
  608. # element += 1
  609. # disp_number = 0
  610. # old_disp_number = 0
  611. #
  612. # if isinstance(panel_obj, FlatCAMGeometry):
  613. # if panel_obj.multigeo is True:
  614. # for tool in panel_obj.tools:
  615. # if self.app.abort_flag:
  616. # # graceful abort requested by the user
  617. # raise FlatCAMApp.GracefulException
  618. #
  619. # # geo = translate_recursion(panel_obj.tools[tool]['solid_geometry'])
  620. # # if isinstance(geo, list):
  621. # # obj_fin.tools[tool]['solid_geometry'] += geo
  622. # # else:
  623. # # obj_fin.tools[tool]['solid_geometry'].append(geo)
  624. #
  625. # # calculate the number of polygons
  626. # geo_len = len(panel_obj.tools[tool]['solid_geometry'])
  627. # pol_nr = 0
  628. # for geo_el in panel_obj.tools[tool]['solid_geometry']:
  629. # trans_geo = translate_recursion(geo_el)
  630. # obj_fin.tools[tool]['solid_geometry'].append(trans_geo)
  631. #
  632. # pol_nr += 1
  633. # disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
  634. #
  635. # if old_disp_number < disp_number <= 100:
  636. # self.app.proc_container.update_view_text(' %s: %d %d%%' %
  637. # (_("Copy"),
  638. # int(element),
  639. # disp_number))
  640. # old_disp_number = disp_number
  641. # else:
  642. # # geo = translate_recursion(panel_obj.solid_geometry)
  643. # # if isinstance(geo, list):
  644. # # obj_fin.solid_geometry += geo
  645. # # else:
  646. # # obj_fin.solid_geometry.append(geo)
  647. # if self.app.abort_flag:
  648. # # graceful abort requested by the user
  649. # raise FlatCAMApp.GracefulException
  650. #
  651. # try:
  652. # # calculate the number of polygons
  653. # geo_len = len(panel_obj.solid_geometry)
  654. # except TypeError:
  655. # geo_len = 1
  656. # pol_nr = 0
  657. # try:
  658. # for geo_el in panel_obj.solid_geometry:
  659. # if self.app.abort_flag:
  660. # # graceful abort requested by the user
  661. # raise FlatCAMApp.GracefulException
  662. #
  663. # trans_geo = translate_recursion(geo_el)
  664. # obj_fin.solid_geometry.append(trans_geo)
  665. #
  666. # pol_nr += 1
  667. # disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
  668. #
  669. # if old_disp_number < disp_number <= 100:
  670. # self.app.proc_container.update_view_text(' %s: %d %d%%' %
  671. # (_("Copy"),
  672. # int(element),
  673. # disp_number))
  674. # old_disp_number = disp_number
  675. # except TypeError:
  676. # trans_geo = translate_recursion(panel_obj.solid_geometry)
  677. # obj_fin.solid_geometry.append(trans_geo)
  678. # else:
  679. # # geo = translate_recursion(panel_obj.solid_geometry)
  680. # # if isinstance(geo, list):
  681. # # obj_fin.solid_geometry += geo
  682. # # else:
  683. # # obj_fin.solid_geometry.append(geo)
  684. # if self.app.abort_flag:
  685. # # graceful abort requested by the user
  686. # raise FlatCAMApp.GracefulException
  687. #
  688. # try:
  689. # for geo_el in panel_obj.solid_geometry:
  690. # if self.app.abort_flag:
  691. # # graceful abort requested by the user
  692. # raise FlatCAMApp.GracefulException
  693. #
  694. # trans_geo = translate_recursion(geo_el)
  695. # obj_fin.solid_geometry.append(trans_geo)
  696. # except TypeError:
  697. # trans_geo = translate_recursion(panel_obj.solid_geometry)
  698. # obj_fin.solid_geometry.append(trans_geo)
  699. #
  700. # for apid in panel_obj.apertures:
  701. # if self.app.abort_flag:
  702. # # graceful abort requested by the user
  703. # raise FlatCAMApp.GracefulException
  704. #
  705. # try:
  706. # # calculate the number of polygons
  707. # geo_len = len(panel_obj.apertures[apid]['geometry'])
  708. # except TypeError:
  709. # geo_len = 1
  710. # pol_nr = 0
  711. # for el in panel_obj.apertures[apid]['geometry']:
  712. # if self.app.abort_flag:
  713. # # graceful abort requested by the user
  714. # raise FlatCAMApp.GracefulException
  715. #
  716. # new_el = dict()
  717. # if 'solid' in el:
  718. # geo_aper = translate_recursion(el['solid'])
  719. # new_el['solid'] = geo_aper
  720. #
  721. # if 'clear' in el:
  722. # geo_aper = translate_recursion(el['clear'])
  723. # new_el['clear'] = geo_aper
  724. #
  725. # if 'follow' in el:
  726. # geo_aper = translate_recursion(el['follow'])
  727. # new_el['follow'] = geo_aper
  728. #
  729. # obj_fin.apertures[apid]['geometry'].append(deepcopy(new_el))
  730. #
  731. # pol_nr += 1
  732. # disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100]))
  733. #
  734. # if old_disp_number < disp_number <= 100:
  735. # self.app.proc_container.update_view_text(' %s: %d %d%%' %
  736. # (_("Copy"),
  737. # int(element),
  738. # disp_number))
  739. # old_disp_number = disp_number
  740. #
  741. # currentx += lenghtx
  742. # currenty += lenghty
  743. #
  744. # if panel_type == 'gerber':
  745. # self.app.inform.emit('%s' %
  746. # _("Generating panel ... Adding the Gerber code."))
  747. # obj_fin.source_file = self.app.export_gerber(obj_name=self.outname, filename=None,
  748. # local_use=obj_fin, use_thread=False)
  749. #
  750. # # app_obj.log.debug("Found %s geometries. Creating a panel geometry cascaded union ..." %
  751. # # len(obj_fin.solid_geometry))
  752. #
  753. # # obj_fin.solid_geometry = cascaded_union(obj_fin.solid_geometry)
  754. # # app_obj.log.debug("Finished creating a cascaded union for the panel.")
  755. # self.app.proc_container.update_view_text('')
  756. #
  757. # self.app.inform.emit('%s: %d' %
  758. # (_("Generating panel... Spawning copies"), (int(rows * columns))))
  759. # if isinstance(panel_obj, FlatCAMExcellon):
  760. # self.app.progress.emit(50)
  761. # self.app.new_object("excellon", self.outname, job_init_excellon, plot=True, autoselected=True)
  762. # else:
  763. # self.app.progress.emit(50)
  764. # self.app.new_object(panel_type, self.outname, job_init_geometry,
  765. # plot=True, autoselected=True)
  766. #
  767. # if self.constrain_flag is False:
  768. # self.app.inform.emit('[success] %s' % _("Panel done..."))
  769. # else:
  770. # self.constrain_flag = False
  771. # self.app.inform.emit(_("{text} Too big for the constrain area. "
  772. # "Final panel has {col} columns and {row} rows").format(
  773. # text='[WARNING] ', col=columns, row=rows))
  774. #
  775. # proc = self.app.proc_container.new(_("Working..."))
  776. #
  777. # def job_thread(app_obj):
  778. # try:
  779. # panelize_2()
  780. # self.app.inform.emit('[success] %s' % _("Panel created successfully."))
  781. # except Exception as ee:
  782. # proc.done()
  783. # log.debug(str(ee))
  784. # return
  785. # proc.done()
  786. #
  787. # self.app.collection.promise(self.outname)
  788. # self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
  789. def reset_fields(self):
  790. # self.object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
  791. # self.box_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
  792. pass