|
@@ -7,10 +7,14 @@
|
|
|
# ########################################################## ##
|
|
# ########################################################## ##
|
|
|
|
|
|
|
|
from FlatCAMTool import FlatCAMTool
|
|
from FlatCAMTool import FlatCAMTool
|
|
|
|
|
+from FlatCAMObj import *
|
|
|
|
|
|
|
|
-from flatcamGUI.GUIElements import RadioSet, FCEntry
|
|
|
|
|
|
|
+from flatcamGUI.GUIElements import RadioSet, FCDoubleSpinner, FCCheckBox, \
|
|
|
|
|
+ OptionalHideInputSection, OptionalInputSection
|
|
|
from PyQt5 import QtGui, QtCore, QtWidgets
|
|
from PyQt5 import QtGui, QtCore, QtWidgets
|
|
|
|
|
|
|
|
|
|
+from copy import deepcopy
|
|
|
|
|
+
|
|
|
import gettext
|
|
import gettext
|
|
|
import FlatCAMTranslation as fcTranslate
|
|
import FlatCAMTranslation as fcTranslate
|
|
|
import builtins
|
|
import builtins
|
|
@@ -39,8 +43,11 @@ class Film(FlatCAMTool):
|
|
|
self.layout.addWidget(title_label)
|
|
self.layout.addWidget(title_label)
|
|
|
|
|
|
|
|
# Form Layout
|
|
# Form Layout
|
|
|
- tf_form_layout = QtWidgets.QFormLayout()
|
|
|
|
|
- self.layout.addLayout(tf_form_layout)
|
|
|
|
|
|
|
+ grid0 = QtWidgets.QGridLayout()
|
|
|
|
|
+ self.layout.addLayout(grid0)
|
|
|
|
|
+
|
|
|
|
|
+ grid0.setColumnStretch(0, 0)
|
|
|
|
|
+ grid0.setColumnStretch(1, 1)
|
|
|
|
|
|
|
|
# Type of object for which to create the film
|
|
# Type of object for which to create the film
|
|
|
self.tf_type_obj_combo = QtWidgets.QComboBox()
|
|
self.tf_type_obj_combo = QtWidgets.QComboBox()
|
|
@@ -60,7 +67,8 @@ class Film(FlatCAMTool):
|
|
|
"The selection here decide the type of objects that will be\n"
|
|
"The selection here decide the type of objects that will be\n"
|
|
|
"in the Film Object combobox.")
|
|
"in the Film Object combobox.")
|
|
|
)
|
|
)
|
|
|
- tf_form_layout.addRow(self.tf_type_obj_combo_label, self.tf_type_obj_combo)
|
|
|
|
|
|
|
+ grid0.addWidget(self.tf_type_obj_combo_label, 0, 0)
|
|
|
|
|
+ grid0.addWidget(self.tf_type_obj_combo, 0, 1)
|
|
|
|
|
|
|
|
# List of objects for which we can create the film
|
|
# List of objects for which we can create the film
|
|
|
self.tf_object_combo = QtWidgets.QComboBox()
|
|
self.tf_object_combo = QtWidgets.QComboBox()
|
|
@@ -72,7 +80,8 @@ class Film(FlatCAMTool):
|
|
|
self.tf_object_label.setToolTip(
|
|
self.tf_object_label.setToolTip(
|
|
|
_("Object for which to create the film.")
|
|
_("Object for which to create the film.")
|
|
|
)
|
|
)
|
|
|
- tf_form_layout.addRow(self.tf_object_label, self.tf_object_combo)
|
|
|
|
|
|
|
+ grid0.addWidget(self.tf_object_label, 1, 0)
|
|
|
|
|
+ grid0.addWidget(self.tf_object_combo, 1, 1)
|
|
|
|
|
|
|
|
# Type of Box Object to be used as an envelope for film creation
|
|
# Type of Box Object to be used as an envelope for film creation
|
|
|
# Within this we can create negative
|
|
# Within this we can create negative
|
|
@@ -93,7 +102,8 @@ class Film(FlatCAMTool):
|
|
|
"The selection here decide the type of objects that will be\n"
|
|
"The selection here decide the type of objects that will be\n"
|
|
|
"in the Box Object combobox.")
|
|
"in the Box Object combobox.")
|
|
|
)
|
|
)
|
|
|
- tf_form_layout.addRow(self.tf_type_box_combo_label, self.tf_type_box_combo)
|
|
|
|
|
|
|
+ grid0.addWidget(self.tf_type_box_combo_label, 2, 0)
|
|
|
|
|
+ grid0.addWidget(self.tf_type_box_combo, 2, 1)
|
|
|
|
|
|
|
|
# Box
|
|
# Box
|
|
|
self.tf_box_combo = QtWidgets.QComboBox()
|
|
self.tf_box_combo = QtWidgets.QComboBox()
|
|
@@ -108,11 +118,28 @@ class Film(FlatCAMTool):
|
|
|
"Usually it is the PCB outline but it can be also the\n"
|
|
"Usually it is the PCB outline but it can be also the\n"
|
|
|
"same object for which the film is created.")
|
|
"same object for which the film is created.")
|
|
|
)
|
|
)
|
|
|
- tf_form_layout.addRow(self.tf_box_combo_label, self.tf_box_combo)
|
|
|
|
|
|
|
+ grid0.addWidget(self.tf_box_combo_label, 3, 0)
|
|
|
|
|
+ grid0.addWidget(self.tf_box_combo, 3, 1)
|
|
|
|
|
+
|
|
|
|
|
+ # Scale Stroke size
|
|
|
|
|
+ self.film_scale_entry = FCDoubleSpinner()
|
|
|
|
|
+ self.film_scale_entry.set_range(-999.9999, 999.9999)
|
|
|
|
|
+
|
|
|
|
|
+ self.film_scale_label = QtWidgets.QLabel('%s:' % _("Scale Stroke"))
|
|
|
|
|
+ self.film_scale_label.setToolTip(
|
|
|
|
|
+ _("Scale the line stroke thickness of each feature in the SVG file.\n"
|
|
|
|
|
+ "It means that the line that envelope each SVG feature will be thicker or thinner,\n"
|
|
|
|
|
+ "therefore the fine features may be more affected by this parameter.")
|
|
|
|
|
+ )
|
|
|
|
|
+ grid0.addWidget(self.film_scale_label, 4, 0)
|
|
|
|
|
+ grid0.addWidget(self.film_scale_entry, 4, 1)
|
|
|
|
|
+
|
|
|
|
|
+ grid0.addWidget(QtWidgets.QLabel(''), 5, 0)
|
|
|
|
|
|
|
|
# Film Type
|
|
# Film Type
|
|
|
self.film_type = RadioSet([{'label': _('Positive'), 'value': 'pos'},
|
|
self.film_type = RadioSet([{'label': _('Positive'), 'value': 'pos'},
|
|
|
- {'label': _('Negative'), 'value': 'neg'}])
|
|
|
|
|
|
|
+ {'label': _('Negative'), 'value': 'neg'}],
|
|
|
|
|
+ stretch=False)
|
|
|
self.film_type_label = QtWidgets.QLabel(_("Film Type:"))
|
|
self.film_type_label = QtWidgets.QLabel(_("Film Type:"))
|
|
|
self.film_type_label.setToolTip(
|
|
self.film_type_label.setToolTip(
|
|
|
_("Generate a Positive black film or a Negative film.\n"
|
|
_("Generate a Positive black film or a Negative film.\n"
|
|
@@ -122,11 +149,12 @@ class Film(FlatCAMTool):
|
|
|
"with white on a black canvas.\n"
|
|
"with white on a black canvas.\n"
|
|
|
"The Film format is SVG.")
|
|
"The Film format is SVG.")
|
|
|
)
|
|
)
|
|
|
- tf_form_layout.addRow(self.film_type_label, self.film_type)
|
|
|
|
|
|
|
+ grid0.addWidget(self.film_type_label, 6, 0)
|
|
|
|
|
+ grid0.addWidget(self.film_type, 6, 1)
|
|
|
|
|
|
|
|
# Boundary for negative film generation
|
|
# Boundary for negative film generation
|
|
|
-
|
|
|
|
|
- self.boundary_entry = FCEntry()
|
|
|
|
|
|
|
+ self.boundary_entry = FCDoubleSpinner()
|
|
|
|
|
+ self.boundary_entry.set_range(-999.9999, 999.9999)
|
|
|
self.boundary_label = QtWidgets.QLabel('%s:' % _("Border"))
|
|
self.boundary_label = QtWidgets.QLabel('%s:' % _("Border"))
|
|
|
self.boundary_label.setToolTip(
|
|
self.boundary_label.setToolTip(
|
|
|
_("Specify a border around the object.\n"
|
|
_("Specify a border around the object.\n"
|
|
@@ -138,21 +166,72 @@ class Film(FlatCAMTool):
|
|
|
"white color like the rest and which may confound with the\n"
|
|
"white color like the rest and which may confound with the\n"
|
|
|
"surroundings if not for this border.")
|
|
"surroundings if not for this border.")
|
|
|
)
|
|
)
|
|
|
- tf_form_layout.addRow(self.boundary_label, self.boundary_entry)
|
|
|
|
|
-
|
|
|
|
|
- self.film_scale_entry = FCEntry()
|
|
|
|
|
- self.film_scale_label = QtWidgets.QLabel('%s:' % _("Scale Stroke"))
|
|
|
|
|
- self.film_scale_label.setToolTip(
|
|
|
|
|
- _("Scale the line stroke thickness of each feature in the SVG file.\n"
|
|
|
|
|
- "It means that the line that envelope each SVG feature will be thicker or thinner,\n"
|
|
|
|
|
- "therefore the fine features may be more affected by this parameter.")
|
|
|
|
|
|
|
+ grid0.addWidget(self.boundary_label, 7, 0)
|
|
|
|
|
+ grid0.addWidget(self.boundary_entry, 7, 1)
|
|
|
|
|
+
|
|
|
|
|
+ self.boundary_label.hide()
|
|
|
|
|
+ self.boundary_entry.hide()
|
|
|
|
|
+
|
|
|
|
|
+ # Punch Drill holes
|
|
|
|
|
+ self.punch_cb = FCCheckBox(_("Punch drill holes"))
|
|
|
|
|
+ self.punch_cb.setToolTip(_("When checked the generated film will have holes in pads when\n"
|
|
|
|
|
+ "the generated film is positive. This is done to help drilling,\n"
|
|
|
|
|
+ "when done manually."))
|
|
|
|
|
+ grid0.addWidget(self.punch_cb, 8, 0, 1, 2)
|
|
|
|
|
+
|
|
|
|
|
+ # this way I can hide/show the frame
|
|
|
|
|
+ self.punch_frame = QtWidgets.QFrame()
|
|
|
|
|
+ self.punch_frame.setContentsMargins(0, 0, 0, 0)
|
|
|
|
|
+ self.layout.addWidget(self.punch_frame)
|
|
|
|
|
+ punch_grid = QtWidgets.QGridLayout()
|
|
|
|
|
+ punch_grid.setContentsMargins(0, 0, 0, 0)
|
|
|
|
|
+ self.punch_frame.setLayout(punch_grid)
|
|
|
|
|
+
|
|
|
|
|
+ punch_grid.setColumnStretch(0, 0)
|
|
|
|
|
+ punch_grid.setColumnStretch(1, 1)
|
|
|
|
|
+
|
|
|
|
|
+ self.ois_p = OptionalHideInputSection(self.punch_cb, [self.punch_frame])
|
|
|
|
|
+
|
|
|
|
|
+ self.source_label = QtWidgets.QLabel('%s:' % _("Source"))
|
|
|
|
|
+ self.source_label.setToolTip(
|
|
|
|
|
+ _("The punch hole source can be:\n"
|
|
|
|
|
+ "- Excellon -> an Excellon holes center will serve as reference.\n"
|
|
|
|
|
+ "- Pad Center -> will try to use the pads center as reference.")
|
|
|
|
|
+ )
|
|
|
|
|
+ self.source_punch = RadioSet([{'label': _('Excellon'), 'value': 'exc'},
|
|
|
|
|
+ {'label': _('Pad center'), 'value': 'pad'}],
|
|
|
|
|
+ stretch=False)
|
|
|
|
|
+ punch_grid.addWidget(self.source_label, 0, 0)
|
|
|
|
|
+ punch_grid.addWidget(self.source_punch, 0, 1)
|
|
|
|
|
+
|
|
|
|
|
+ self.exc_label = QtWidgets.QLabel('%s:' % _("Excellon Obj"))
|
|
|
|
|
+ self.exc_label.setToolTip(
|
|
|
|
|
+ _("Remove the geometry of Excellon from the Film to create tge holes in pads.")
|
|
|
)
|
|
)
|
|
|
- tf_form_layout.addRow(self.film_scale_label, self.film_scale_entry)
|
|
|
|
|
|
|
+ self.exc_combo = QtWidgets.QComboBox()
|
|
|
|
|
+ self.exc_combo.setModel(self.app.collection)
|
|
|
|
|
+ self.exc_combo.setRootModelIndex(self.app.collection.index(1, 0, QtCore.QModelIndex()))
|
|
|
|
|
+ self.exc_combo.setCurrentIndex(1)
|
|
|
|
|
+ punch_grid.addWidget(self.exc_label, 1, 0)
|
|
|
|
|
+ punch_grid.addWidget(self.exc_combo, 1, 1)
|
|
|
|
|
+
|
|
|
|
|
+ self.exc_label.hide()
|
|
|
|
|
+ self.exc_combo.hide()
|
|
|
|
|
+
|
|
|
|
|
+ self.punch_size_label = QtWidgets.QLabel('%s:' % _("Punch Size"))
|
|
|
|
|
+ self.punch_size_label.setToolTip(_("The value here will control how big is the punch hole in the pads."))
|
|
|
|
|
+ self.punch_size_spinner = FCDoubleSpinner()
|
|
|
|
|
+ self.punch_size_spinner.set_range(0, 999.9999)
|
|
|
|
|
+
|
|
|
|
|
+ punch_grid.addWidget(self.punch_size_label, 2, 0)
|
|
|
|
|
+ punch_grid.addWidget(self.punch_size_spinner, 2, 1)
|
|
|
|
|
+
|
|
|
|
|
+ self.punch_size_label.hide()
|
|
|
|
|
+ self.punch_size_spinner.hide()
|
|
|
|
|
|
|
|
# Buttons
|
|
# Buttons
|
|
|
hlay = QtWidgets.QHBoxLayout()
|
|
hlay = QtWidgets.QHBoxLayout()
|
|
|
self.layout.addLayout(hlay)
|
|
self.layout.addLayout(hlay)
|
|
|
- hlay.addStretch()
|
|
|
|
|
|
|
|
|
|
self.film_object_button = QtWidgets.QPushButton(_("Save Film"))
|
|
self.film_object_button = QtWidgets.QPushButton(_("Save Film"))
|
|
|
self.film_object_button.setToolTip(
|
|
self.film_object_button.setToolTip(
|
|
@@ -170,6 +249,9 @@ class Film(FlatCAMTool):
|
|
|
self.tf_type_obj_combo.currentIndexChanged.connect(self.on_type_obj_index_changed)
|
|
self.tf_type_obj_combo.currentIndexChanged.connect(self.on_type_obj_index_changed)
|
|
|
self.tf_type_box_combo.currentIndexChanged.connect(self.on_type_box_index_changed)
|
|
self.tf_type_box_combo.currentIndexChanged.connect(self.on_type_box_index_changed)
|
|
|
|
|
|
|
|
|
|
+ self.film_type.activated_custom.connect(self.on_film_type)
|
|
|
|
|
+ self.source_punch.activated_custom.connect(self.on_punch_source)
|
|
|
|
|
+
|
|
|
def on_type_obj_index_changed(self, index):
|
|
def on_type_obj_index_changed(self, index):
|
|
|
obj_type = self.tf_type_obj_combo.currentIndex()
|
|
obj_type = self.tf_type_obj_combo.currentIndex()
|
|
|
self.tf_object_combo.setRootModelIndex(self.app.collection.index(obj_type, 0, QtCore.QModelIndex()))
|
|
self.tf_object_combo.setRootModelIndex(self.app.collection.index(obj_type, 0, QtCore.QModelIndex()))
|
|
@@ -216,6 +298,7 @@ class Film(FlatCAMTool):
|
|
|
|
|
|
|
|
f_type = self.app.defaults["tools_film_type"] if self.app.defaults["tools_film_type"] else 'neg'
|
|
f_type = self.app.defaults["tools_film_type"] if self.app.defaults["tools_film_type"] else 'neg'
|
|
|
self.film_type.set_value(str(f_type))
|
|
self.film_type.set_value(str(f_type))
|
|
|
|
|
+ self.on_film_type(val=f_type)
|
|
|
|
|
|
|
|
b_entry = self.app.defaults["tools_film_boundary"] if self.app.defaults["tools_film_boundary"] else 0.0
|
|
b_entry = self.app.defaults["tools_film_boundary"] if self.app.defaults["tools_film_boundary"] else 0.0
|
|
|
self.boundary_entry.set_value(float(b_entry))
|
|
self.boundary_entry.set_value(float(b_entry))
|
|
@@ -223,7 +306,41 @@ class Film(FlatCAMTool):
|
|
|
scale_stroke_width = self.app.defaults["tools_film_scale"] if self.app.defaults["tools_film_scale"] else 0.0
|
|
scale_stroke_width = self.app.defaults["tools_film_scale"] if self.app.defaults["tools_film_scale"] else 0.0
|
|
|
self.film_scale_entry.set_value(int(scale_stroke_width))
|
|
self.film_scale_entry.set_value(int(scale_stroke_width))
|
|
|
|
|
|
|
|
|
|
+ self.punch_cb.set_value(False)
|
|
|
|
|
+ self.source_punch.set_value('exc')
|
|
|
|
|
+
|
|
|
|
|
+ def on_film_type(self, val):
|
|
|
|
|
+ type_of_film = val
|
|
|
|
|
+
|
|
|
|
|
+ if type_of_film == 'neg':
|
|
|
|
|
+ self.boundary_label.show()
|
|
|
|
|
+ self.boundary_entry.show()
|
|
|
|
|
+ self.punch_cb.hide()
|
|
|
|
|
+ else:
|
|
|
|
|
+ self.boundary_label.hide()
|
|
|
|
|
+ self.boundary_entry.hide()
|
|
|
|
|
+ self.punch_cb.show()
|
|
|
|
|
+
|
|
|
|
|
+ def on_punch_source(self, val):
|
|
|
|
|
+ if val == 'pad' and self.punch_cb.get_value():
|
|
|
|
|
+ self.punch_size_label.show()
|
|
|
|
|
+ self.punch_size_spinner.show()
|
|
|
|
|
+ self.exc_label.hide()
|
|
|
|
|
+ self.exc_combo.hide()
|
|
|
|
|
+ else:
|
|
|
|
|
+ self.punch_size_label.hide()
|
|
|
|
|
+ self.punch_size_spinner.hide()
|
|
|
|
|
+ self.exc_label.show()
|
|
|
|
|
+ self.exc_combo.show()
|
|
|
|
|
+
|
|
|
|
|
+ if val == 'pad' and self.tf_type_obj_combo.currentText() == 'Geometry':
|
|
|
|
|
+ self.source_punch.set_value('exc')
|
|
|
|
|
+ self.app.inform.emit('[WARNING_NOTCL] %s' % _("Using the Pad center does not work on Geometry objects. "
|
|
|
|
|
+ "Only a Gerber object has pads."))
|
|
|
|
|
+
|
|
|
def on_film_creation(self):
|
|
def on_film_creation(self):
|
|
|
|
|
+ log.debug("ToolFilm.Film.on_film_creation() started ...")
|
|
|
|
|
+
|
|
|
try:
|
|
try:
|
|
|
name = self.tf_object_combo.currentText()
|
|
name = self.tf_object_combo.currentText()
|
|
|
except Exception as e:
|
|
except Exception as e:
|
|
@@ -238,59 +355,133 @@ class Film(FlatCAMTool):
|
|
|
_("No FlatCAM object selected. Load an object for Box and retry."))
|
|
_("No FlatCAM object selected. Load an object for Box and retry."))
|
|
|
return
|
|
return
|
|
|
|
|
|
|
|
- try:
|
|
|
|
|
- border = float(self.boundary_entry.get_value())
|
|
|
|
|
- except ValueError:
|
|
|
|
|
- # try to convert comma to decimal point. if it's still not working error message and return
|
|
|
|
|
- try:
|
|
|
|
|
- border = float(self.boundary_entry.get_value().replace(',', '.'))
|
|
|
|
|
- except ValueError:
|
|
|
|
|
- self.app.inform.emit('[ERROR_NOTCL] %s' % _("Wrong value format entered, use a number."))
|
|
|
|
|
- return
|
|
|
|
|
|
|
+ scale_stroke_width = float(self.film_scale_entry.get_value())
|
|
|
|
|
|
|
|
- try:
|
|
|
|
|
- scale_stroke_width = int(self.film_scale_entry.get_value())
|
|
|
|
|
- except ValueError:
|
|
|
|
|
- self.app.inform.emit('[ERROR_NOTCL] %s' % _("Wrong value format entered, use a number."))
|
|
|
|
|
- return
|
|
|
|
|
|
|
+ source = self.source_punch.get_value()
|
|
|
|
|
|
|
|
- if border is None:
|
|
|
|
|
- border = 0
|
|
|
|
|
|
|
+ # #################################################################
|
|
|
|
|
+ # ################ STARTING THE JOB ###############################
|
|
|
|
|
+ # #################################################################
|
|
|
|
|
|
|
|
self.app.inform.emit(_("Generating Film ..."))
|
|
self.app.inform.emit(_("Generating Film ..."))
|
|
|
|
|
|
|
|
if self.film_type.get_value() == "pos":
|
|
if self.film_type.get_value() == "pos":
|
|
|
- try:
|
|
|
|
|
- filename, _f = QtWidgets.QFileDialog.getSaveFileName(
|
|
|
|
|
- caption=_("Export SVG positive"),
|
|
|
|
|
- directory=self.app.get_last_save_folder() + '/' + name,
|
|
|
|
|
- filter="*.svg")
|
|
|
|
|
- except TypeError:
|
|
|
|
|
- filename, _f = QtWidgets.QFileDialog.getSaveFileName(caption=_("Export SVG positive"))
|
|
|
|
|
-
|
|
|
|
|
- filename = str(filename)
|
|
|
|
|
|
|
|
|
|
- if str(filename) == "":
|
|
|
|
|
- self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export SVG positive cancelled."))
|
|
|
|
|
- return
|
|
|
|
|
|
|
+ if self.punch_cb.get_value() is False:
|
|
|
|
|
+ self.generate_positive_normal_film(name, boxname, factor=scale_stroke_width)
|
|
|
else:
|
|
else:
|
|
|
- self.app.export_svg_positive(name, boxname, filename, scale_factor=scale_stroke_width)
|
|
|
|
|
|
|
+ self.generate_positive_punched_film(name, boxname, source, factor=scale_stroke_width)
|
|
|
else:
|
|
else:
|
|
|
- try:
|
|
|
|
|
- filename, _f = QtWidgets.QFileDialog.getSaveFileName(
|
|
|
|
|
- caption=_("Export SVG negative"),
|
|
|
|
|
- directory=self.app.get_last_save_folder() + '/' + name,
|
|
|
|
|
- filter="*.svg")
|
|
|
|
|
- except TypeError:
|
|
|
|
|
- filename, _f = QtWidgets.QFileDialog.getSaveFileName(caption=_("Export SVG negative"))
|
|
|
|
|
|
|
+ self.generate_negative_film(name, boxname, factor=scale_stroke_width)
|
|
|
|
|
+
|
|
|
|
|
+ def generate_positive_normal_film(self, name, boxname, factor):
|
|
|
|
|
+ log.debug("ToolFilm.Film.generate_positive_normal_film() started ...")
|
|
|
|
|
+ try:
|
|
|
|
|
+ filename, _f = QtWidgets.QFileDialog.getSaveFileName(
|
|
|
|
|
+ caption=_("Export SVG positive"),
|
|
|
|
|
+ directory=self.app.get_last_save_folder() + '/' + name,
|
|
|
|
|
+ filter="*.svg")
|
|
|
|
|
+ except TypeError:
|
|
|
|
|
+ filename, _f = QtWidgets.QFileDialog.getSaveFileName(caption=_("Export SVG positive"))
|
|
|
|
|
+
|
|
|
|
|
+ filename = str(filename)
|
|
|
|
|
+
|
|
|
|
|
+ if str(filename) == "":
|
|
|
|
|
+ self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export SVG positive cancelled."))
|
|
|
|
|
+ return
|
|
|
|
|
+ else:
|
|
|
|
|
+ self.app.export_svg_positive(name, boxname, filename, scale_factor=factor)
|
|
|
|
|
+
|
|
|
|
|
+ def generate_positive_punched_film(self, name, boxname, source, factor):
|
|
|
|
|
+
|
|
|
|
|
+ film_obj = self.app.collection.get_by_name(name)
|
|
|
|
|
|
|
|
- filename = str(filename)
|
|
|
|
|
|
|
+ if source == 'exc':
|
|
|
|
|
+ log.debug("ToolFilm.Film.generate_positive_punched_film() with Excellon source started ...")
|
|
|
|
|
|
|
|
- if str(filename) == "":
|
|
|
|
|
- self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export SVG negative cancelled."))
|
|
|
|
|
|
|
+ try:
|
|
|
|
|
+ exc_name = self.exc_combo.currentText()
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
|
|
|
|
|
+ _("No Excellon object selected. Load an object for punching reference and retry."))
|
|
|
return
|
|
return
|
|
|
- else:
|
|
|
|
|
- self.app.export_svg_negative(name, boxname, filename, border, scale_factor=scale_stroke_width)
|
|
|
|
|
|
|
+
|
|
|
|
|
+ exc_obj = self.app.collection.get_by_name(exc_name)
|
|
|
|
|
+ exc_solid_geometry = MultiPolygon(exc_obj.solid_geometry)
|
|
|
|
|
+ punched_solid_geometry = MultiPolygon(film_obj.solid_geometry).difference(exc_solid_geometry)
|
|
|
|
|
+
|
|
|
|
|
+ def init_func(new_obj, app_obj):
|
|
|
|
|
+ new_obj.solid_geometry = deepcopy(punched_solid_geometry)
|
|
|
|
|
+
|
|
|
|
|
+ outname = name + "_punched"
|
|
|
|
|
+ self.app.new_object('gerber', outname, init_func)
|
|
|
|
|
+
|
|
|
|
|
+ self.generate_positive_normal_film(outname, boxname, factor=factor)
|
|
|
|
|
+ else:
|
|
|
|
|
+ log.debug("ToolFilm.Film.generate_positive_punched_film() with Pad center source started ...")
|
|
|
|
|
+
|
|
|
|
|
+ punch_size = float(self.punch_size_spinner.get_value())
|
|
|
|
|
+
|
|
|
|
|
+ punching_geo = list()
|
|
|
|
|
+ for apid in film_obj.apertures:
|
|
|
|
|
+ if film_obj.apertures[apid]['type'] == 'C':
|
|
|
|
|
+ if punch_size >= float(film_obj.apertures[apid]['size']):
|
|
|
|
|
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
|
|
|
|
|
+ _(" Could not generate punched hole film because the punch hole size"
|
|
|
|
|
+ "is bigger than some of the apertures in the Gerber object."))
|
|
|
|
|
+ return 'fail'
|
|
|
|
|
+ else:
|
|
|
|
|
+ for elem in film_obj.apertures[apid]['geometry']:
|
|
|
|
|
+ if 'follow' in elem:
|
|
|
|
|
+ if isinstance(elem['follow'], Point):
|
|
|
|
|
+ punching_geo.append(elem['follow'].buffer(punch_size / 2))
|
|
|
|
|
+ else:
|
|
|
|
|
+ if punch_size >= float(film_obj.apertures[apid]['width']) or \
|
|
|
|
|
+ punch_size >= float(film_obj.apertures[apid]['height']):
|
|
|
|
|
+ self.app.inform.emit('[ERROR_NOTCL] %s' %
|
|
|
|
|
+ _(" Could not generate punched hole film because the punch hole size"
|
|
|
|
|
+ "is bigger than some of the apertures in the Gerber object."))
|
|
|
|
|
+ return 'fail'
|
|
|
|
|
+ else:
|
|
|
|
|
+ for elem in film_obj.apertures[apid]['geometry']:
|
|
|
|
|
+ if 'follow' in elem:
|
|
|
|
|
+ if isinstance(elem['follow'], Point):
|
|
|
|
|
+ punching_geo.append(elem['follow'].buffer(punch_size / 2))
|
|
|
|
|
+
|
|
|
|
|
+ punching_geo = MultiPolygon(punching_geo)
|
|
|
|
|
+ punched_solid_geometry = MultiPolygon(film_obj.solid_geometry).difference(punching_geo)
|
|
|
|
|
+
|
|
|
|
|
+ def init_func(new_obj, app_obj):
|
|
|
|
|
+ new_obj.solid_geometry = deepcopy(punched_solid_geometry)
|
|
|
|
|
+
|
|
|
|
|
+ outname = name + "_punched"
|
|
|
|
|
+ self.app.new_object('gerber', outname, init_func)
|
|
|
|
|
+
|
|
|
|
|
+ self.generate_positive_normal_film(outname, boxname, factor=factor)
|
|
|
|
|
+
|
|
|
|
|
+ def generate_negative_film(self, name, boxname, factor):
|
|
|
|
|
+ log.debug("ToolFilm.Film.generate_negative_film() started ...")
|
|
|
|
|
+
|
|
|
|
|
+ border = float(self.boundary_entry.get_value())
|
|
|
|
|
+
|
|
|
|
|
+ if border is None:
|
|
|
|
|
+ border = 0
|
|
|
|
|
+
|
|
|
|
|
+ try:
|
|
|
|
|
+ filename, _f = QtWidgets.QFileDialog.getSaveFileName(
|
|
|
|
|
+ caption=_("Export SVG negative"),
|
|
|
|
|
+ directory=self.app.get_last_save_folder() + '/' + name,
|
|
|
|
|
+ filter="*.svg")
|
|
|
|
|
+ except TypeError:
|
|
|
|
|
+ filename, _f = QtWidgets.QFileDialog.getSaveFileName(caption=_("Export SVG negative"))
|
|
|
|
|
+
|
|
|
|
|
+ filename = str(filename)
|
|
|
|
|
+
|
|
|
|
|
+ if str(filename) == "":
|
|
|
|
|
+ self.app.inform.emit('[WARNING_NOTCL] %s' % _("Export SVG negative cancelled."))
|
|
|
|
|
+ return
|
|
|
|
|
+ else:
|
|
|
|
|
+ self.app.export_svg_negative(name, boxname, filename, border, scale_factor=factor)
|
|
|
|
|
|
|
|
def reset_fields(self):
|
|
def reset_fields(self):
|
|
|
self.tf_object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|
|
self.tf_object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
|