DblSidedTool.py 5.0 KB

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