ToolTransform.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. from PyQt4 import QtGui, QtCore
  2. from PyQt4 import Qt
  3. from GUIElements import FCEntry, FCButton
  4. from FlatCAMTool import FlatCAMTool
  5. from FlatCAMObj import FlatCAMGerber, FlatCAMExcellon, FlatCAMGeometry
  6. class ToolTransform(FlatCAMTool):
  7. toolName = "Object Transformation"
  8. rotateName = "Rotate Transformation"
  9. skewName = "Skew/Shear Transformation"
  10. flipName = "Flip Transformation"
  11. def __init__(self, app):
  12. FlatCAMTool.__init__(self, app)
  13. self.transform_lay = QtGui.QVBoxLayout()
  14. self.layout.addLayout(self.transform_lay)
  15. ## Title
  16. title_label = QtGui.QLabel("<font size=4><b>%s</b></font><br>" % self.toolName)
  17. self.transform_lay.addWidget(title_label)
  18. self.empty_label = QtGui.QLabel("")
  19. self.empty_label.setFixedWidth(80)
  20. self.empty_label1 = QtGui.QLabel("")
  21. self.empty_label1.setFixedWidth(80)
  22. self.empty_label2 = QtGui.QLabel("")
  23. self.empty_label2.setFixedWidth(80)
  24. self.transform_lay.addWidget(self.empty_label)
  25. ## Rotate Title
  26. rotate_title_label = QtGui.QLabel("<font size=3><b>%s</b></font>" % self.rotateName)
  27. self.transform_lay.addWidget(rotate_title_label)
  28. ## Form Layout
  29. form_layout = QtGui.QFormLayout()
  30. self.transform_lay.addLayout(form_layout)
  31. self.rotate_entry = FCEntry()
  32. self.rotate_entry.setFixedWidth(70)
  33. self.rotate_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
  34. self.rotate_label = QtGui.QLabel("Angle:")
  35. self.rotate_label.setToolTip(
  36. "Angle for Rotation action, in degrees.\n"
  37. "Float number between -360 and 359.\n"
  38. "Positive numbers for CW motion.\n"
  39. "Negative numbers for CCW motion."
  40. )
  41. self.rotate_label.setFixedWidth(80)
  42. self.rotate_button = FCButton()
  43. self.rotate_button.set_value("Rotate")
  44. self.rotate_button.setToolTip(
  45. "Rotate the selected object(s).\n"
  46. "The point of reference is the middle of\n"
  47. "the bounding box for all selected objects.\n"
  48. )
  49. self.rotate_button.setFixedWidth(70)
  50. form_layout.addRow(self.rotate_label, self.rotate_entry)
  51. form_layout.addRow(self.empty_label, self.rotate_button)
  52. self.transform_lay.addWidget(self.empty_label1)
  53. ## Skew Title
  54. skew_title_label = QtGui.QLabel("<font size=3><b>%s</b></font>" % self.skewName)
  55. self.transform_lay.addWidget(skew_title_label)
  56. ## Form Layout
  57. form1_layout = QtGui.QFormLayout()
  58. self.transform_lay.addLayout(form1_layout)
  59. self.skewx_entry = FCEntry()
  60. self.skewx_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
  61. self.skewx_entry.setFixedWidth(70)
  62. self.skewx_label = QtGui.QLabel("Angle:")
  63. self.skewx_label.setToolTip(
  64. "Angle for Skew action, in degrees.\n"
  65. "Float number between -360 and 359."
  66. )
  67. self.skewx_label.setFixedWidth(80)
  68. self.skewx_button = FCButton()
  69. self.skewx_button.set_value("Skew_X")
  70. self.skewx_button.setToolTip(
  71. "Skew/shear the selected object(s).\n"
  72. "The point of reference is the middle of\n"
  73. "the bounding box for all selected objects.\n")
  74. self.skewx_button.setFixedWidth(70)
  75. self.skewy_entry = FCEntry()
  76. self.skewy_entry.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
  77. self.skewy_entry.setFixedWidth(70)
  78. self.skewy_label = QtGui.QLabel("Angle:")
  79. self.skewy_label.setToolTip(
  80. "Angle for Skew action, in degrees.\n"
  81. "Float number between -360 and 359."
  82. )
  83. self.skewy_label.setFixedWidth(80)
  84. self.skewy_button = FCButton()
  85. self.skewy_button.set_value("Skew_Y")
  86. self.skewy_button.setToolTip(
  87. "Skew/shear the selected object(s).\n"
  88. "The point of reference is the middle of\n"
  89. "the bounding box for all selected objects.\n")
  90. self.skewy_button.setFixedWidth(70)
  91. form1_layout.addRow(self.skewx_label, self.skewx_entry)
  92. form1_layout.addRow(self.empty_label, self.skewx_button)
  93. form1_layout.addRow(self.skewy_label, self.skewy_entry)
  94. form1_layout.addRow(self.empty_label, self.skewy_button)
  95. self.transform_lay.addWidget(self.empty_label2)
  96. ## Flip Title
  97. flip_title_label = QtGui.QLabel("<font size=3><b>%s</b></font>" % self.flipName)
  98. self.transform_lay.addWidget(flip_title_label)
  99. ## Form Layout
  100. form2_layout = QtGui.QFormLayout()
  101. self.transform_lay.addLayout(form2_layout)
  102. self.flipx_button = FCButton()
  103. self.flipx_button.set_value("Flip_X")
  104. self.flipx_button.setToolTip(
  105. "Flip the selected object(s) over the X axis.\n"
  106. "Does not create a new object.\n "
  107. )
  108. self.flipx_button.setFixedWidth(70)
  109. self.flipy_button = FCButton()
  110. self.flipy_button.set_value("Flip_Y")
  111. self.flipy_button.setToolTip(
  112. "Flip the selected object(s) over the X axis.\n"
  113. "Does not create a new object.\n "
  114. )
  115. self.flipy_button.setFixedWidth(70)
  116. form2_layout.setSpacing(16)
  117. form2_layout.addRow(self.flipx_button, self.flipy_button)
  118. self.transform_lay.addStretch()
  119. ## Signals
  120. self.rotate_button.clicked.connect(self.on_rotate)
  121. self.skewx_button.clicked.connect(self.on_skewx)
  122. self.skewy_button.clicked.connect(self.on_skewy)
  123. self.flipx_button.clicked.connect(self.on_flipx)
  124. self.flipy_button.clicked.connect(self.on_flipy)
  125. self.rotate_entry.returnPressed.connect(self.on_rotate)
  126. self.skewx_entry.returnPressed.connect(self.on_skewx)
  127. self.skewy_entry.returnPressed.connect(self.on_skewy)
  128. ## Initialize form
  129. self.rotate_entry.set_value('0')
  130. self.skewx_entry.set_value('0')
  131. self.skewy_entry.set_value('0')
  132. def on_rotate(self):
  133. value = float(self.rotate_entry.get_value())
  134. self.on_rotate_action(value)
  135. return
  136. def on_flipx(self):
  137. self.on_flip("Y")
  138. return
  139. def on_flipy(self):
  140. self.on_flip("X")
  141. return
  142. def on_skewx(self):
  143. value = float(self.skewx_entry.get_value())
  144. self.on_skew("X", value)
  145. return
  146. def on_skewy(self):
  147. value = float(self.skewy_entry.get_value())
  148. self.on_skew("Y", value)
  149. return
  150. def on_rotate_action(self, num):
  151. obj_list = self.app.collection.get_selected()
  152. xminlist = []
  153. yminlist = []
  154. xmaxlist = []
  155. ymaxlist = []
  156. if not obj_list:
  157. self.app.inform.emit("WARNING: No object selected.")
  158. msg = "Please Select an object to rotate!"
  159. warningbox = QtGui.QMessageBox()
  160. warningbox.setText(msg)
  161. warningbox.setWindowTitle("Warning ...")
  162. warningbox.setWindowIcon(QtGui.QIcon('share/warning.png'))
  163. warningbox.setStandardButtons(QtGui.QMessageBox.Ok)
  164. warningbox.setDefaultButton(QtGui.QMessageBox.Ok)
  165. warningbox.exec_()
  166. else:
  167. try:
  168. # first get a bounding box to fit all
  169. for obj in obj_list:
  170. xmin, ymin, xmax, ymax = obj.bounds()
  171. xminlist.append(xmin)
  172. yminlist.append(ymin)
  173. xmaxlist.append(xmax)
  174. ymaxlist.append(ymax)
  175. # get the minimum x,y and maximum x,y for all objects selected
  176. xminimal = min(xminlist)
  177. yminimal = min(yminlist)
  178. xmaximal = max(xmaxlist)
  179. ymaximal = max(ymaxlist)
  180. for sel_obj in obj_list:
  181. px = 0.5 * (xminimal + xmaximal)
  182. py = 0.5 * (yminimal + ymaximal)
  183. sel_obj.rotate(-num, point=(px, py))
  184. sel_obj.plot()
  185. self.app.inform.emit('Object was rotated ...')
  186. except Exception as e:
  187. self.app.inform.emit("[ERROR] Due of %s, rotation movement was not executed." % str(e))
  188. return
  189. def on_flip(self, axis):
  190. obj_list = self.app.collection.get_selected()
  191. xminlist = []
  192. yminlist = []
  193. xmaxlist = []
  194. ymaxlist = []
  195. if not obj_list:
  196. self.app.inform.emit("WARNING: No object selected.")
  197. msg = "Please Select an object to flip!"
  198. warningbox = QtGui.QMessageBox()
  199. warningbox.setText(msg)
  200. warningbox.setWindowTitle("Warning ...")
  201. warningbox.setWindowIcon(QtGui.QIcon('share/warning.png'))
  202. warningbox.setStandardButtons(QtGui.QMessageBox.Ok)
  203. warningbox.setDefaultButton(QtGui.QMessageBox.Ok)
  204. warningbox.exec_()
  205. return
  206. else:
  207. try:
  208. # first get a bounding box to fit all
  209. for obj in obj_list:
  210. xmin, ymin, xmax, ymax = obj.bounds()
  211. xminlist.append(xmin)
  212. yminlist.append(ymin)
  213. xmaxlist.append(xmax)
  214. ymaxlist.append(ymax)
  215. # get the minimum x,y and maximum x,y for all objects selected
  216. xminimal = min(xminlist)
  217. yminimal = min(yminlist)
  218. xmaximal = max(xmaxlist)
  219. ymaximal = max(ymaxlist)
  220. px = 0.5 * (xminimal + xmaximal)
  221. py = 0.5 * (yminimal + ymaximal)
  222. # execute mirroring
  223. for obj in obj_list:
  224. if axis is 'X':
  225. obj.mirror('X', [px, py])
  226. obj.plot()
  227. self.app.inform.emit('Flipped on the Y axis ...')
  228. elif axis is 'Y':
  229. obj.mirror('Y', [px, py])
  230. obj.plot()
  231. self.app.inform.emit('Flipped on the X axis ...')
  232. except Exception as e:
  233. self.app.inform.emit("[ERROR] Due of %s, Flip action was not executed.")
  234. return
  235. def on_skew(self, axis, num):
  236. obj_list = self.app.collection.get_selected()
  237. xminlist = []
  238. yminlist = []
  239. if not obj_list:
  240. self.app.inform.emit("WARNING: No object selected.")
  241. msg = "Please Select an object to skew/shear!"
  242. warningbox = QtGui.QMessageBox()
  243. warningbox.setText(msg)
  244. warningbox.setWindowTitle("Warning ...")
  245. warningbox.setWindowIcon(QtGui.QIcon('share/warning.png'))
  246. warningbox.setStandardButtons(QtGui.QMessageBox.Ok)
  247. warningbox.setDefaultButton(QtGui.QMessageBox.Ok)
  248. warningbox.exec_()
  249. else:
  250. try:
  251. # first get a bounding box to fit all
  252. for obj in obj_list:
  253. xmin, ymin, xmax, ymax = obj.bounds()
  254. xminlist.append(xmin)
  255. yminlist.append(ymin)
  256. # get the minimum x,y and maximum x,y for all objects selected
  257. xminimal = min(xminlist)
  258. yminimal = min(yminlist)
  259. for obj in obj_list:
  260. if axis is 'X':
  261. obj.skew(num, 0, point=(xminimal, yminimal))
  262. elif axis is 'Y':
  263. obj.skew(0, num, point=(xminimal, yminimal))
  264. obj.plot()
  265. self.app.inform.emit('Object was skewed on %s axis ...' % str(axis))
  266. except Exception as e:
  267. self.app.inform.emit("[ERROR] Due of %s, Skew action was not executed." % str(e))
  268. return
  269. # end of file