DblSidedTool.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. from PyQt4 import QtGui
  2. from GUIElements import RadioSet, EvalEntry, LengthEntry
  3. from FlatCAMTool import FlatCAMTool
  4. #from FlatCAMObj import FlatCAMGerber, FlatCAMExcellon
  5. from FlatCAMObj import *
  6. from shapely.geometry import Point
  7. from shapely import affinity
  8. class DblSidedTool(FlatCAMTool):
  9. toolName = "Double-Sided PCB Tool"
  10. def __init__(self, app):
  11. FlatCAMTool.__init__(self, app)
  12. ## Title
  13. title_label = QtGui.QLabel("<font size=4><b>%s</b></font>" % self.toolName)
  14. self.layout.addWidget(title_label)
  15. ## Form Layout
  16. form_layout = QtGui.QFormLayout()
  17. self.layout.addLayout(form_layout)
  18. ## Layer to mirror
  19. self.object_combo = QtGui.QComboBox()
  20. self.object_combo.setModel(self.app.collection)
  21. form_layout.addRow("Bottom Layer:", self.object_combo)
  22. ## Axis
  23. self.mirror_axis = RadioSet([{'label': 'X', 'value': 'X'},
  24. {'label': 'Y', 'value': 'Y'}])
  25. form_layout.addRow("Mirror Axis:", self.mirror_axis)
  26. ## Axis Location
  27. self.axis_location = RadioSet([{'label': 'Point', 'value': 'point'},
  28. {'label': 'Box', 'value': 'box'}])
  29. form_layout.addRow("Axis Location:", self.axis_location)
  30. ## Point/Box
  31. self.point_box_container = QtGui.QVBoxLayout()
  32. form_layout.addRow("Point/Box:", self.point_box_container)
  33. self.point = EvalEntry()
  34. self.point_box_container.addWidget(self.point)
  35. self.box_combo = QtGui.QComboBox()
  36. self.box_combo.setModel(self.app.collection)
  37. self.point_box_container.addWidget(self.box_combo)
  38. self.box_combo.hide()
  39. ## Alignment holes
  40. self.alignment_holes = EvalEntry()
  41. form_layout.addRow("Alignment Holes:", self.alignment_holes)
  42. ## Drill diameter for alignment holes
  43. self.drill_dia = LengthEntry()
  44. form_layout.addRow("Drill diam.:", self.drill_dia)
  45. ## Buttons
  46. hlay = QtGui.QHBoxLayout()
  47. self.layout.addLayout(hlay)
  48. hlay.addStretch()
  49. self.create_alignment_hole_button = QtGui.QPushButton("Create Alignment Drill")
  50. self.mirror_object_button = QtGui.QPushButton("Mirror Object")
  51. hlay.addWidget(self.create_alignment_hole_button)
  52. hlay.addWidget(self.mirror_object_button)
  53. self.layout.addStretch()
  54. ## Signals
  55. self.create_alignment_hole_button.clicked.connect(self.on_create_alignment_holes)
  56. self.mirror_object_button.clicked.connect(self.on_mirror)
  57. self.axis_location.group_toggle_fn = self.on_toggle_pointbox
  58. ## Initialize form
  59. self.mirror_axis.set_value('X')
  60. self.axis_location.set_value('point')
  61. def on_create_alignment_holes(self):
  62. axis = self.mirror_axis.get_value()
  63. mode = self.axis_location.get_value()
  64. if mode == "point":
  65. px, py = self.point.get_value()
  66. else:
  67. selection_index = self.box_combo.currentIndex()
  68. bb_obj = self.app.collection.object_list[selection_index] # TODO: Direct access??
  69. xmin, ymin, xmax, ymax = bb_obj.bounds()
  70. px = 0.5*(xmin+xmax)
  71. py = 0.5*(ymin+ymax)
  72. xscale, yscale = {"X": (1.0, -1.0), "Y": (-1.0, 1.0)}[axis]
  73. dia = self.drill_dia.get_value()
  74. tools = {"1": {"C": dia}}
  75. holes = self.alignment_holes.get_value()
  76. drills = []
  77. for hole in holes:
  78. point = Point(hole)
  79. point_mirror = affinity.scale(point, xscale, yscale, origin=(px, py))
  80. drills.append({"point": point, "tool": "1"})
  81. drills.append({"point": point_mirror, "tool": "1"})
  82. def obj_init(obj_inst, app_inst):
  83. obj_inst.tools = tools
  84. obj_inst.drills = drills
  85. obj_inst.create_geometry()
  86. self.app.new_object("excellon", "Alignment Drills", obj_init)
  87. def on_mirror(self):
  88. selection_index = self.object_combo.currentIndex()
  89. fcobj = self.app.collection.object_list[selection_index]
  90. # For now, lets limit to Gerbers and Excellons.
  91. # assert isinstance(gerb, FlatCAMGerber)
  92. if not isinstance(fcobj, FlatCAMGerber) and not isinstance(fcobj, FlatCAMExcellon):
  93. self.info("ERROR: Only Gerber and Excellon objects can be mirrored.")
  94. return
  95. axis = self.mirror_axis.get_value()
  96. mode = self.axis_location.get_value()
  97. if mode == "point":
  98. px, py = self.point.get_value()
  99. else:
  100. selection_index = self.box_combo.currentIndex()
  101. bb_obj = self.app.collection.object_list[selection_index] # TODO: Direct access??
  102. xmin, ymin, xmax, ymax = bb_obj.bounds()
  103. px = 0.5*(xmin+xmax)
  104. py = 0.5*(ymin+ymax)
  105. fcobj.mirror(axis, [px, py])
  106. fcobj.plot()
  107. def on_toggle_pointbox(self):
  108. if self.axis_location.get_value() == "point":
  109. self.point.show()
  110. self.box_combo.hide()
  111. else:
  112. self.point.hide()
  113. self.box_combo.show()