|
@@ -15,8 +15,7 @@ import shapely.affinity as affinity
|
|
|
|
|
|
|
|
from camlib import Geometry
|
|
from camlib import Geometry
|
|
|
|
|
|
|
|
-from flatcamObjects.FlatCAMObj import *
|
|
|
|
|
-import FlatCAMTool
|
|
|
|
|
|
|
+from AppObjects.FlatCAMObj import *
|
|
|
|
|
|
|
|
import ezdxf
|
|
import ezdxf
|
|
|
import math
|
|
import math
|
|
@@ -25,7 +24,7 @@ from copy import deepcopy
|
|
|
import traceback
|
|
import traceback
|
|
|
|
|
|
|
|
import gettext
|
|
import gettext
|
|
|
-import FlatCAMTranslation as fcTranslate
|
|
|
|
|
|
|
+import AppTranslation as fcTranslate
|
|
|
import builtins
|
|
import builtins
|
|
|
|
|
|
|
|
fcTranslate.apply_language('strings')
|
|
fcTranslate.apply_language('strings')
|
|
@@ -53,6 +52,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
|
|
|
|
|
self.options.update({
|
|
self.options.update({
|
|
|
"plot": True,
|
|
"plot": True,
|
|
|
|
|
+ "multicolored": False,
|
|
|
"cutz": -0.002,
|
|
"cutz": -0.002,
|
|
|
"vtipdia": 0.1,
|
|
"vtipdia": 0.1,
|
|
|
"vtipangle": 30,
|
|
"vtipangle": 30,
|
|
@@ -151,17 +151,9 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
|
|
|
|
|
self.param_fields = {}
|
|
self.param_fields = {}
|
|
|
|
|
|
|
|
- # Event signals disconnect id holders
|
|
|
|
|
- self.mr = None
|
|
|
|
|
- self.mm = None
|
|
|
|
|
- self.kp = None
|
|
|
|
|
-
|
|
|
|
|
- # variables to be used in area exclusion
|
|
|
|
|
- self.cursor_pos = (0, 0)
|
|
|
|
|
- self.exclusion_areas_list = []
|
|
|
|
|
- self.first_click = False
|
|
|
|
|
- self.points = []
|
|
|
|
|
- self.poly_drawn = False
|
|
|
|
|
|
|
+ # store here the state of the exclusion checkbox state to be restored after building the UI
|
|
|
|
|
+ # TODO add this in the sel.app.defaults dict and in Preferences
|
|
|
|
|
+ self.exclusion_area_cb_is_checked = False
|
|
|
|
|
|
|
|
# Attributes to be included in serialization
|
|
# Attributes to be included in serialization
|
|
|
# Always append to it because it carries contents
|
|
# Always append to it because it carries contents
|
|
@@ -172,6 +164,15 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
self.ui_disconnect()
|
|
self.ui_disconnect()
|
|
|
FlatCAMObj.build_ui(self)
|
|
FlatCAMObj.build_ui(self)
|
|
|
|
|
|
|
|
|
|
+ # Area Exception - exclusion shape added signal
|
|
|
|
|
+ # first disconnect it from any other object
|
|
|
|
|
+ try:
|
|
|
|
|
+ self.app.exc_areas.e_shape_modified.disconnect()
|
|
|
|
|
+ except (TypeError, AttributeError):
|
|
|
|
|
+ pass
|
|
|
|
|
+ # then connect it to the current build_ui() method
|
|
|
|
|
+ self.app.exc_areas.e_shape_modified.connect(self.update_exclusion_table)
|
|
|
|
|
+
|
|
|
self.units = self.app.defaults['units']
|
|
self.units = self.app.defaults['units']
|
|
|
|
|
|
|
|
tool_idx = 0
|
|
tool_idx = 0
|
|
@@ -192,7 +193,6 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
# For INCH the decimals should be no more than 3. There are no tools under 10mils.
|
|
# For INCH the decimals should be no more than 3. There are no tools under 10mils.
|
|
|
|
|
|
|
|
dia_item = QtWidgets.QTableWidgetItem('%.*f' % (self.decimals, float(tooluid_value['tooldia'])))
|
|
dia_item = QtWidgets.QTableWidgetItem('%.*f' % (self.decimals, float(tooluid_value['tooldia'])))
|
|
|
-
|
|
|
|
|
dia_item.setFlags(QtCore.Qt.ItemIsEnabled)
|
|
dia_item.setFlags(QtCore.Qt.ItemIsEnabled)
|
|
|
|
|
|
|
|
offset_item = FCComboBox()
|
|
offset_item = FCComboBox()
|
|
@@ -305,6 +305,63 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
|
|
|
|
|
self.set_tool_offset_visibility(selected_row)
|
|
self.set_tool_offset_visibility(selected_row)
|
|
|
|
|
|
|
|
|
|
+ # -----------------------------
|
|
|
|
|
+ # Build Exclusion Areas section
|
|
|
|
|
+ # -----------------------------
|
|
|
|
|
+ e_len = len(self.app.exc_areas.exclusion_areas_storage)
|
|
|
|
|
+ self.ui.exclusion_table.setRowCount(e_len)
|
|
|
|
|
+
|
|
|
|
|
+ area_id = 0
|
|
|
|
|
+
|
|
|
|
|
+ for area in range(e_len):
|
|
|
|
|
+ area_id += 1
|
|
|
|
|
+
|
|
|
|
|
+ area_dict = self.app.exc_areas.exclusion_areas_storage[area]
|
|
|
|
|
+
|
|
|
|
|
+ area_id_item = QtWidgets.QTableWidgetItem('%d' % int(area_id))
|
|
|
|
|
+ area_id_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
|
|
|
|
|
+ self.ui.exclusion_table.setItem(area, 0, area_id_item) # Area id
|
|
|
|
|
+
|
|
|
|
|
+ object_item = QtWidgets.QTableWidgetItem('%s' % area_dict["obj_type"])
|
|
|
|
|
+ object_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
|
|
|
|
|
+ self.ui.exclusion_table.setItem(area, 1, object_item) # Origin Object
|
|
|
|
|
+
|
|
|
|
|
+ strategy_item = QtWidgets.QTableWidgetItem('%s' % area_dict["strategy"])
|
|
|
|
|
+ strategy_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
|
|
|
|
|
+ self.ui.exclusion_table.setItem(area, 2, strategy_item) # Strategy
|
|
|
|
|
+
|
|
|
|
|
+ overz_item = QtWidgets.QTableWidgetItem('%s' % area_dict["overz"])
|
|
|
|
|
+ overz_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
|
|
|
|
|
+ self.ui.exclusion_table.setItem(area, 3, overz_item) # Over Z
|
|
|
|
|
+
|
|
|
|
|
+ self.ui.exclusion_table.resizeColumnsToContents()
|
|
|
|
|
+ self.ui.exclusion_table.resizeRowsToContents()
|
|
|
|
|
+
|
|
|
|
|
+ area_vheader = self.ui.exclusion_table.verticalHeader()
|
|
|
|
|
+ area_vheader.hide()
|
|
|
|
|
+ self.ui.exclusion_table.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
|
|
|
|
+
|
|
|
|
|
+ area_hheader = self.ui.exclusion_table.horizontalHeader()
|
|
|
|
|
+ area_hheader.setMinimumSectionSize(10)
|
|
|
|
|
+ area_hheader.setDefaultSectionSize(70)
|
|
|
|
|
+
|
|
|
|
|
+ area_hheader.setSectionResizeMode(0, QtWidgets.QHeaderView.Fixed)
|
|
|
|
|
+ area_hheader.resizeSection(0, 20)
|
|
|
|
|
+ area_hheader.setSectionResizeMode(1, QtWidgets.QHeaderView.Stretch)
|
|
|
|
|
+ area_hheader.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents)
|
|
|
|
|
+ area_hheader.setSectionResizeMode(3, QtWidgets.QHeaderView.ResizeToContents)
|
|
|
|
|
+
|
|
|
|
|
+ # area_hheader.setStretchLastSection(True)
|
|
|
|
|
+ self.ui.exclusion_table.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
|
|
|
|
+
|
|
|
|
|
+ self.ui.exclusion_table.setColumnWidth(0, 20)
|
|
|
|
|
+
|
|
|
|
|
+ self.ui.exclusion_table.setMinimumHeight(self.ui.exclusion_table.getHeight())
|
|
|
|
|
+ self.ui.exclusion_table.setMaximumHeight(self.ui.exclusion_table.getHeight())
|
|
|
|
|
+
|
|
|
|
|
+ # End Build Exclusion Areas
|
|
|
|
|
+ # -----------------------------
|
|
|
|
|
+
|
|
|
# HACK: for whatever reasons the name in Selected tab is reverted to the original one after a successful rename
|
|
# HACK: for whatever reasons the name in Selected tab is reverted to the original one after a successful rename
|
|
|
# done in the collection view but only for Geometry objects. Perhaps some references remains. Should be fixed.
|
|
# done in the collection view but only for Geometry objects. Perhaps some references remains. Should be fixed.
|
|
|
self.ui.name_entry.set_value(self.options['name'])
|
|
self.ui.name_entry.set_value(self.options['name'])
|
|
@@ -340,6 +397,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
|
|
|
|
|
self.form_fields.update({
|
|
self.form_fields.update({
|
|
|
"plot": self.ui.plot_cb,
|
|
"plot": self.ui.plot_cb,
|
|
|
|
|
+ "multicolored": self.ui.multicolored_cb,
|
|
|
"cutz": self.ui.cutz_entry,
|
|
"cutz": self.ui.cutz_entry,
|
|
|
"vtipdia": self.ui.tipdia_entry,
|
|
"vtipdia": self.ui.tipdia_entry,
|
|
|
"vtipangle": self.ui.tipangle_entry,
|
|
"vtipangle": self.ui.tipangle_entry,
|
|
@@ -363,7 +421,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
"endxy": self.ui.endxy_entry,
|
|
"endxy": self.ui.endxy_entry,
|
|
|
"cnctooldia": self.ui.addtool_entry,
|
|
"cnctooldia": self.ui.addtool_entry,
|
|
|
"area_exclusion": self.ui.exclusion_cb,
|
|
"area_exclusion": self.ui.exclusion_cb,
|
|
|
- "area_shape":self.ui.area_shape_radio,
|
|
|
|
|
|
|
+ "area_shape": self.ui.area_shape_radio,
|
|
|
"area_strategy": self.ui.strategy_radio,
|
|
"area_strategy": self.ui.strategy_radio,
|
|
|
"area_overz": self.ui.over_z_entry,
|
|
"area_overz": self.ui.over_z_entry,
|
|
|
})
|
|
})
|
|
@@ -535,6 +593,8 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
self.ui.extracut_cb.toggled.connect(lambda state: self.ui.e_cut_entry.setDisabled(not state))
|
|
self.ui.extracut_cb.toggled.connect(lambda state: self.ui.e_cut_entry.setDisabled(not state))
|
|
|
|
|
|
|
|
self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click)
|
|
self.ui.plot_cb.stateChanged.connect(self.on_plot_cb_click)
|
|
|
|
|
+ self.ui.multicolored_cb.stateChanged.connect(self.on_multicolored_cb_click)
|
|
|
|
|
+
|
|
|
self.ui.generate_cnc_button.clicked.connect(self.on_generatecnc_button_click)
|
|
self.ui.generate_cnc_button.clicked.connect(self.on_generatecnc_button_click)
|
|
|
self.ui.paint_tool_button.clicked.connect(lambda: self.app.paint_tool.run(toggle=False))
|
|
self.ui.paint_tool_button.clicked.connect(lambda: self.app.paint_tool.run(toggle=False))
|
|
|
self.ui.generate_ncc_button.clicked.connect(lambda: self.app.ncclear_tool.run(toggle=False))
|
|
self.ui.generate_ncc_button.clicked.connect(lambda: self.app.ncclear_tool.run(toggle=False))
|
|
@@ -547,8 +607,14 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
self.ui.apply_param_to_all.clicked.connect(self.on_apply_param_to_all_clicked)
|
|
self.ui.apply_param_to_all.clicked.connect(self.on_apply_param_to_all_clicked)
|
|
|
self.ui.cutz_entry.returnPressed.connect(self.on_cut_z_changed)
|
|
self.ui.cutz_entry.returnPressed.connect(self.on_cut_z_changed)
|
|
|
|
|
|
|
|
|
|
+ # Exclusion areas signals
|
|
|
|
|
+ self.ui.exclusion_table.horizontalHeader().sectionClicked.connect(self.exclusion_table_toggle_all)
|
|
|
|
|
+ self.ui.exclusion_table.lost_focus.connect(self.clear_selection)
|
|
|
|
|
+ self.ui.exclusion_table.itemClicked.connect(self.draw_sel_shape)
|
|
|
self.ui.add_area_button.clicked.connect(self.on_add_area_click)
|
|
self.ui.add_area_button.clicked.connect(self.on_add_area_click)
|
|
|
self.ui.delete_area_button.clicked.connect(self.on_clear_area_click)
|
|
self.ui.delete_area_button.clicked.connect(self.on_clear_area_click)
|
|
|
|
|
+ self.ui.delete_sel_area_button.clicked.connect(self.on_delete_sel_areas)
|
|
|
|
|
+ self.ui.strategy_radio.activated_custom.connect(self.on_strategy)
|
|
|
|
|
|
|
|
def on_cut_z_changed(self):
|
|
def on_cut_z_changed(self):
|
|
|
self.old_cutz = self.ui.cutz_entry.get_value()
|
|
self.old_cutz = self.ui.cutz_entry.get_value()
|
|
@@ -595,8 +661,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
self.ui.tool_offset_entry.get_value().replace(',', '.')
|
|
self.ui.tool_offset_entry.get_value().replace(',', '.')
|
|
|
)
|
|
)
|
|
|
except ValueError:
|
|
except ValueError:
|
|
|
- self.app.inform.emit('[ERROR_NOTCL] %s' %
|
|
|
|
|
- _("Wrong value format entered, use a number."))
|
|
|
|
|
|
|
+ self.app.inform.emit('[ERROR_NOTCL] %s' % _("Wrong value format entered, use a number."))
|
|
|
return
|
|
return
|
|
|
|
|
|
|
|
def ui_connect(self):
|
|
def ui_connect(self):
|
|
@@ -604,6 +669,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
# changes in geometry UI
|
|
# changes in geometry UI
|
|
|
for i in self.param_fields:
|
|
for i in self.param_fields:
|
|
|
current_widget = self.param_fields[i]
|
|
current_widget = self.param_fields[i]
|
|
|
|
|
+
|
|
|
if isinstance(current_widget, FCCheckBox):
|
|
if isinstance(current_widget, FCCheckBox):
|
|
|
current_widget.stateChanged.connect(self.gui_form_to_storage)
|
|
current_widget.stateChanged.connect(self.gui_form_to_storage)
|
|
|
elif isinstance(current_widget, FCComboBox):
|
|
elif isinstance(current_widget, FCComboBox):
|
|
@@ -874,7 +940,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
self.ui_connect()
|
|
self.ui_connect()
|
|
|
self.build_ui()
|
|
self.build_ui()
|
|
|
|
|
|
|
|
- # if there is no tool left in the Tools Table, enable the parameters GUI
|
|
|
|
|
|
|
+ # if there is no tool left in the Tools Table, enable the parameters AppGUI
|
|
|
if self.ui.geo_tools_table.rowCount() != 0:
|
|
if self.ui.geo_tools_table.rowCount() != 0:
|
|
|
self.ui.geo_param_frame.setDisabled(False)
|
|
self.ui.geo_param_frame.setDisabled(False)
|
|
|
|
|
|
|
@@ -950,7 +1016,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
self.ui_connect()
|
|
self.ui_connect()
|
|
|
self.build_ui()
|
|
self.build_ui()
|
|
|
|
|
|
|
|
- # if there is no tool left in the Tools Table, enable the parameters GUI
|
|
|
|
|
|
|
+ # if there is no tool left in the Tools Table, enable the parameters AppGUI
|
|
|
if self.ui.geo_tools_table.rowCount() != 0:
|
|
if self.ui.geo_tools_table.rowCount() != 0:
|
|
|
self.ui.geo_param_frame.setDisabled(False)
|
|
self.ui.geo_param_frame.setDisabled(False)
|
|
|
|
|
|
|
@@ -1131,7 +1197,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
obj_active.options['xmax'] = 0
|
|
obj_active.options['xmax'] = 0
|
|
|
obj_active.options['ymax'] = 0
|
|
obj_active.options['ymax'] = 0
|
|
|
|
|
|
|
|
- # if there is no tool left in the Tools Table, disable the parameters GUI
|
|
|
|
|
|
|
+ # if there is no tool left in the Tools Table, disable the parameters AppGUI
|
|
|
if self.ui.geo_tools_table.rowCount() == 0:
|
|
if self.ui.geo_tools_table.rowCount() == 0:
|
|
|
self.ui.geo_param_frame.setDisabled(True)
|
|
self.ui.geo_param_frame.setDisabled(True)
|
|
|
|
|
|
|
@@ -1149,8 +1215,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
"- 'V-tip Angle' -> angle at the tip of the tool\n"
|
|
"- 'V-tip Angle' -> angle at the tip of the tool\n"
|
|
|
"- 'V-tip Dia' -> diameter at the tip of the tool \n"
|
|
"- 'V-tip Dia' -> diameter at the tip of the tool \n"
|
|
|
"- Tool Dia -> 'Dia' column found in the Tool Table\n"
|
|
"- Tool Dia -> 'Dia' column found in the Tool Table\n"
|
|
|
- "NB: a value of zero means that Tool Dia = 'V-tip Dia'"
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ "NB: a value of zero means that Tool Dia = 'V-tip Dia'")
|
|
|
)
|
|
)
|
|
|
self.ui.cutz_entry.setToolTip(
|
|
self.ui.cutz_entry.setToolTip(
|
|
|
_("Disabled because the tool is V-shape.\n"
|
|
_("Disabled because the tool is V-shape.\n"
|
|
@@ -1159,8 +1224,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
"- 'V-tip Angle' -> angle at the tip of the tool\n"
|
|
"- 'V-tip Angle' -> angle at the tip of the tool\n"
|
|
|
"- 'V-tip Dia' -> diameter at the tip of the tool \n"
|
|
"- 'V-tip Dia' -> diameter at the tip of the tool \n"
|
|
|
"- Tool Dia -> 'Dia' column found in the Tool Table\n"
|
|
"- Tool Dia -> 'Dia' column found in the Tool Table\n"
|
|
|
- "NB: a value of zero means that Tool Dia = 'V-tip Dia'"
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ "NB: a value of zero means that Tool Dia = 'V-tip Dia'")
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
self.update_cutz()
|
|
self.update_cutz()
|
|
@@ -1172,8 +1236,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
self.ui.cutz_entry.setDisabled(False)
|
|
self.ui.cutz_entry.setDisabled(False)
|
|
|
self.ui.cutzlabel.setToolTip(
|
|
self.ui.cutzlabel.setToolTip(
|
|
|
_("Cutting depth (negative)\n"
|
|
_("Cutting depth (negative)\n"
|
|
|
- "below the copper surface."
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ "below the copper surface.")
|
|
|
)
|
|
)
|
|
|
self.ui.cutz_entry.setToolTip('')
|
|
self.ui.cutz_entry.setToolTip('')
|
|
|
|
|
|
|
@@ -1328,16 +1391,18 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
self.ui_connect()
|
|
self.ui_connect()
|
|
|
|
|
|
|
|
def gui_form_to_storage(self):
|
|
def gui_form_to_storage(self):
|
|
|
|
|
+ self.ui_disconnect()
|
|
|
|
|
+
|
|
|
if self.ui.geo_tools_table.rowCount() == 0:
|
|
if self.ui.geo_tools_table.rowCount() == 0:
|
|
|
# there is no tool in tool table so we can't save the GUI elements values to storage
|
|
# there is no tool in tool table so we can't save the GUI elements values to storage
|
|
|
log.debug("GeometryObject.gui_form_to_storage() --> no tool in Tools Table, aborting.")
|
|
log.debug("GeometryObject.gui_form_to_storage() --> no tool in Tools Table, aborting.")
|
|
|
return
|
|
return
|
|
|
|
|
|
|
|
- self.ui_disconnect()
|
|
|
|
|
widget_changed = self.sender()
|
|
widget_changed = self.sender()
|
|
|
try:
|
|
try:
|
|
|
widget_idx = self.ui.grid3.indexOf(widget_changed)
|
|
widget_idx = self.ui.grid3.indexOf(widget_changed)
|
|
|
- except Exception:
|
|
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ log.debug("GeometryObject.gui_form_to_storage() -- wdg index -> %s" % str(e))
|
|
|
return
|
|
return
|
|
|
|
|
|
|
|
# those are the indexes for the V-Tip Dia and V-Tip Angle, if edited calculate the new Cut Z
|
|
# those are the indexes for the V-Tip Dia and V-Tip Angle, if edited calculate the new Cut Z
|
|
@@ -1690,15 +1755,11 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
The actual work is done by the target CNCJobObject object's
|
|
The actual work is done by the target CNCJobObject object's
|
|
|
`generate_from_geometry_2()` method.
|
|
`generate_from_geometry_2()` method.
|
|
|
|
|
|
|
|
- :param tools_dict: a dictionary that holds the whole data needed to create the Gcode
|
|
|
|
|
- (including the solid_geometry)
|
|
|
|
|
-
|
|
|
|
|
- :param tools_in_use: the tools that are used, needed by some preprocessors
|
|
|
|
|
- :type list of lists, each list in the list is made out of row elements of tools table from GUI
|
|
|
|
|
-
|
|
|
|
|
:param outname:
|
|
:param outname:
|
|
|
- :param tools_dict:
|
|
|
|
|
- :param tools_in_use:
|
|
|
|
|
|
|
+ :param tools_dict: a dictionary that holds the whole data needed to create the Gcode
|
|
|
|
|
+ (including the solid_geometry)
|
|
|
|
|
+ :param tools_in_use: the tools that are used, needed by some preprocessors
|
|
|
|
|
+ :type tools_in_use list of lists, each list in the list is made out of row elements of tools table from AppGUI
|
|
|
:param segx: number of segments on the X axis, for auto-levelling
|
|
:param segx: number of segments on the X axis, for auto-levelling
|
|
|
:param segy: number of segments on the Y axis, for auto-levelling
|
|
:param segy: number of segments on the Y axis, for auto-levelling
|
|
|
:param plot: if True the generated object will be plotted; if False will not be plotted
|
|
:param plot: if True the generated object will be plotted; if False will not be plotted
|
|
@@ -1728,7 +1789,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
self.app.inform.emit(msg)
|
|
self.app.inform.emit(msg)
|
|
|
return
|
|
return
|
|
|
|
|
|
|
|
- # Object initialization function for app.new_object()
|
|
|
|
|
|
|
+ # Object initialization function for app.app_obj.new_object()
|
|
|
# RUNNING ON SEPARATE THREAD!
|
|
# RUNNING ON SEPARATE THREAD!
|
|
|
def job_init_single_geometry(job_obj, app_obj):
|
|
def job_init_single_geometry(job_obj, app_obj):
|
|
|
log.debug("Creating a CNCJob out of a single-geometry")
|
|
log.debug("Creating a CNCJob out of a single-geometry")
|
|
@@ -1742,7 +1803,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
# count the tools
|
|
# count the tools
|
|
|
tool_cnt = 0
|
|
tool_cnt = 0
|
|
|
|
|
|
|
|
- dia_cnc_dict = {}
|
|
|
|
|
|
|
+ # dia_cnc_dict = {}
|
|
|
|
|
|
|
|
# this turn on the FlatCAMCNCJob plot for multiple tools
|
|
# this turn on the FlatCAMCNCJob plot for multiple tools
|
|
|
job_obj.multitool = True
|
|
job_obj.multitool = True
|
|
@@ -1868,7 +1929,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
})
|
|
})
|
|
|
dia_cnc_dict.clear()
|
|
dia_cnc_dict.clear()
|
|
|
|
|
|
|
|
- # Object initialization function for app.new_object()
|
|
|
|
|
|
|
+ # Object initialization function for app.app_obj.new_object()
|
|
|
# RUNNING ON SEPARATE THREAD!
|
|
# RUNNING ON SEPARATE THREAD!
|
|
|
def job_init_multi_geometry(job_obj, app_obj):
|
|
def job_init_multi_geometry(job_obj, app_obj):
|
|
|
log.debug("Creating a CNCJob out of a multi-geometry")
|
|
log.debug("Creating a CNCJob out of a multi-geometry")
|
|
@@ -1882,7 +1943,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
# count the tools
|
|
# count the tools
|
|
|
tool_cnt = 0
|
|
tool_cnt = 0
|
|
|
|
|
|
|
|
- dia_cnc_dict = {}
|
|
|
|
|
|
|
+ # dia_cnc_dict = {}
|
|
|
|
|
|
|
|
# this turn on the FlatCAMCNCJob plot for multiple tools
|
|
# this turn on the FlatCAMCNCJob plot for multiple tools
|
|
|
job_obj.multitool = True
|
|
job_obj.multitool = True
|
|
@@ -2022,15 +2083,15 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
|
|
|
|
|
if use_thread:
|
|
if use_thread:
|
|
|
# To be run in separate thread
|
|
# To be run in separate thread
|
|
|
- def job_thread(app_obj):
|
|
|
|
|
|
|
+ def job_thread(a_obj):
|
|
|
if self.multigeo is False:
|
|
if self.multigeo is False:
|
|
|
with self.app.proc_container.new(_("Generating CNC Code")):
|
|
with self.app.proc_container.new(_("Generating CNC Code")):
|
|
|
- if app_obj.new_object("cncjob", outname, job_init_single_geometry, plot=plot) != 'fail':
|
|
|
|
|
- app_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
|
|
|
|
|
|
|
+ if a_obj.app_obj.new_object("cncjob", outname, job_init_single_geometry, plot=plot) != 'fail':
|
|
|
|
|
+ a_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
|
|
|
else:
|
|
else:
|
|
|
with self.app.proc_container.new(_("Generating CNC Code")):
|
|
with self.app.proc_container.new(_("Generating CNC Code")):
|
|
|
- if app_obj.new_object("cncjob", outname, job_init_multi_geometry) != 'fail':
|
|
|
|
|
- app_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
|
|
|
|
|
|
|
+ if a_obj.app_obj.new_object("cncjob", outname, job_init_multi_geometry) != 'fail':
|
|
|
|
|
+ a_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
|
|
|
|
|
|
|
|
# Create a promise with the name
|
|
# Create a promise with the name
|
|
|
self.app.collection.promise(outname)
|
|
self.app.collection.promise(outname)
|
|
@@ -2038,25 +2099,17 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
|
|
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
|
|
|
else:
|
|
else:
|
|
|
if self.solid_geometry:
|
|
if self.solid_geometry:
|
|
|
- self.app.new_object("cncjob", outname, job_init_single_geometry, plot=plot)
|
|
|
|
|
|
|
+ self.app.app_obj.new_object("cncjob", outname, job_init_single_geometry, plot=plot)
|
|
|
else:
|
|
else:
|
|
|
- self.app.new_object("cncjob", outname, job_init_multi_geometry, plot=plot)
|
|
|
|
|
-
|
|
|
|
|
- def generatecncjob(
|
|
|
|
|
- self, outname=None,
|
|
|
|
|
- dia=None, offset=None,
|
|
|
|
|
- z_cut=None, z_move=None,
|
|
|
|
|
- feedrate=None, feedrate_z=None, feedrate_rapid=None,
|
|
|
|
|
- spindlespeed=None, dwell=None, dwelltime=None,
|
|
|
|
|
- multidepth=None, depthperpass=None,
|
|
|
|
|
- toolchange=None, toolchangez=None, toolchangexy=None,
|
|
|
|
|
- extracut=None, extracut_length=None, startz=None, endz=None,
|
|
|
|
|
- pp=None,
|
|
|
|
|
- segx=None, segy=None,
|
|
|
|
|
- use_thread=True,
|
|
|
|
|
- plot=True):
|
|
|
|
|
|
|
+ self.app.app_obj.new_object("cncjob", outname, job_init_multi_geometry, plot=plot)
|
|
|
|
|
+
|
|
|
|
|
+ def generatecncjob(self, outname=None, dia=None, offset=None, z_cut=None, z_move=None,
|
|
|
|
|
+ feedrate=None, feedrate_z=None, feedrate_rapid=None, spindlespeed=None, dwell=None, dwelltime=None,
|
|
|
|
|
+ multidepth=None, dpp=None, toolchange=None, toolchangez=None, toolchangexy=None,
|
|
|
|
|
+ extracut=None, extracut_length=None, startz=None, endz=None, endxy=None, pp=None, segx=None, segy=None,
|
|
|
|
|
+ use_thread=True, plot=True):
|
|
|
"""
|
|
"""
|
|
|
- Only used for TCL Command.
|
|
|
|
|
|
|
+ Only used by the TCL Command Cncjob.
|
|
|
Creates a CNCJob out of this Geometry object. The actual
|
|
Creates a CNCJob out of this Geometry object. The actual
|
|
|
work is done by the target camlib.CNCjob
|
|
work is done by the target camlib.CNCjob
|
|
|
`generate_from_geometry_2()` method.
|
|
`generate_from_geometry_2()` method.
|
|
@@ -2073,14 +2126,17 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
:param dwell:
|
|
:param dwell:
|
|
|
:param dwelltime:
|
|
:param dwelltime:
|
|
|
:param multidepth:
|
|
:param multidepth:
|
|
|
- :param depthperpass:
|
|
|
|
|
|
|
+ :param dpp: Depth for each pass when multidepth parameter is True
|
|
|
:param toolchange:
|
|
:param toolchange:
|
|
|
:param toolchangez:
|
|
:param toolchangez:
|
|
|
- :param toolchangexy:
|
|
|
|
|
|
|
+ :param toolchangexy: A sequence ox X,Y coordinates: a 2-length tuple or a string.
|
|
|
|
|
+ Coordinates in X,Y plane for the Toolchange event
|
|
|
:param extracut:
|
|
:param extracut:
|
|
|
:param extracut_length:
|
|
:param extracut_length:
|
|
|
:param startz:
|
|
:param startz:
|
|
|
:param endz:
|
|
:param endz:
|
|
|
|
|
+ :param endxy: A sequence ox X,Y coordinates: a 2-length tuple or a string.
|
|
|
|
|
+ Coordinates in X, Y plane for the last move after ending the job.
|
|
|
:param pp: Name of the preprocessor
|
|
:param pp: Name of the preprocessor
|
|
|
:param segx:
|
|
:param segx:
|
|
|
:param segy:
|
|
:param segy:
|
|
@@ -2100,7 +2156,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
feedrate_rapid = feedrate_rapid if feedrate_rapid is not None else float(self.options["feedrate_rapid"])
|
|
feedrate_rapid = feedrate_rapid if feedrate_rapid is not None else float(self.options["feedrate_rapid"])
|
|
|
|
|
|
|
|
multidepth = multidepth if multidepth is not None else self.options["multidepth"]
|
|
multidepth = multidepth if multidepth is not None else self.options["multidepth"]
|
|
|
- depthperpass = depthperpass if depthperpass is not None else float(self.options["depthperpass"])
|
|
|
|
|
|
|
+ depthperpass = dpp if dpp is not None else float(self.options["depthperpass"])
|
|
|
|
|
|
|
|
segx = segx if segx is not None else float(self.app.defaults['geometry_segx'])
|
|
segx = segx if segx is not None else float(self.app.defaults['geometry_segx'])
|
|
|
segy = segy if segy is not None else float(self.app.defaults['geometry_segy'])
|
|
segy = segy if segy is not None else float(self.app.defaults['geometry_segy'])
|
|
@@ -2110,10 +2166,21 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
|
|
|
|
|
startz = startz if startz is not None else self.options["startz"]
|
|
startz = startz if startz is not None else self.options["startz"]
|
|
|
endz = endz if endz is not None else float(self.options["endz"])
|
|
endz = endz if endz is not None else float(self.options["endz"])
|
|
|
- endxy = self.options["endxy"]
|
|
|
|
|
|
|
+
|
|
|
|
|
+ endxy = endxy if endxy else self.options["endxy"]
|
|
|
|
|
+ if isinstance(endxy, str):
|
|
|
|
|
+ endxy = re.sub('[()\[\]]', '', endxy)
|
|
|
|
|
+ if endxy and endxy != '':
|
|
|
|
|
+ endxy = [float(eval(a)) for a in endxy.split(",")]
|
|
|
|
|
|
|
|
toolchangez = toolchangez if toolchangez else float(self.options["toolchangez"])
|
|
toolchangez = toolchangez if toolchangez else float(self.options["toolchangez"])
|
|
|
|
|
+
|
|
|
toolchangexy = toolchangexy if toolchangexy else self.options["toolchangexy"]
|
|
toolchangexy = toolchangexy if toolchangexy else self.options["toolchangexy"]
|
|
|
|
|
+ if isinstance(toolchangexy, str):
|
|
|
|
|
+ toolchangexy = re.sub('[()\[\]]', '', toolchangexy)
|
|
|
|
|
+ if toolchangexy and toolchangexy != '':
|
|
|
|
|
+ toolchangexy = [float(eval(a)) for a in toolchangexy.split(",")]
|
|
|
|
|
+
|
|
|
toolchange = toolchange if toolchange else self.options["toolchange"]
|
|
toolchange = toolchange if toolchange else self.options["toolchange"]
|
|
|
|
|
|
|
|
offset = offset if offset else 0.0
|
|
offset = offset if offset else 0.0
|
|
@@ -2125,7 +2192,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
|
|
|
|
|
ppname_g = pp if pp else self.options["ppname_g"]
|
|
ppname_g = pp if pp else self.options["ppname_g"]
|
|
|
|
|
|
|
|
- # Object initialization function for app.new_object()
|
|
|
|
|
|
|
+ # Object initialization function for app.app_obj.new_object()
|
|
|
# RUNNING ON SEPARATE THREAD!
|
|
# RUNNING ON SEPARATE THREAD!
|
|
|
def job_init(job_obj, app_obj):
|
|
def job_init(job_obj, app_obj):
|
|
|
assert job_obj.kind == 'cncjob', "Initializer expected a CNCJobObject, got %s" % type(job_obj)
|
|
assert job_obj.kind == 'cncjob', "Initializer expected a CNCJobObject, got %s" % type(job_obj)
|
|
@@ -2174,7 +2241,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
# To be run in separate thread
|
|
# To be run in separate thread
|
|
|
def job_thread(app_obj):
|
|
def job_thread(app_obj):
|
|
|
with self.app.proc_container.new(_("Generating CNC Code")):
|
|
with self.app.proc_container.new(_("Generating CNC Code")):
|
|
|
- app_obj.new_object("cncjob", outname, job_init, plot=plot)
|
|
|
|
|
|
|
+ app_obj.app_obj.new_object("cncjob", outname, job_init, plot=plot)
|
|
|
app_obj.inform.emit('[success] %s: %s' % (_("CNCjob created")), outname)
|
|
app_obj.inform.emit('[success] %s: %s' % (_("CNCjob created")), outname)
|
|
|
|
|
|
|
|
# Create a promise with the name
|
|
# Create a promise with the name
|
|
@@ -2182,7 +2249,7 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
# Send to worker
|
|
# Send to worker
|
|
|
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
|
|
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
|
|
|
else:
|
|
else:
|
|
|
- self.app.new_object("cncjob", outname, job_init, plot=plot)
|
|
|
|
|
|
|
+ self.app.app_obj.new_object("cncjob", outname, job_init, plot=plot)
|
|
|
|
|
|
|
|
# def on_plot_cb_click(self, *args):
|
|
# def on_plot_cb_click(self, *args):
|
|
|
# if self.muted_ui:
|
|
# if self.muted_ui:
|
|
@@ -2469,6 +2536,110 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
|
|
|
|
|
return factor
|
|
return factor
|
|
|
|
|
|
|
|
|
|
+ def on_add_area_click(self):
|
|
|
|
|
+ shape_button = self.ui.area_shape_radio
|
|
|
|
|
+ overz_button = self.ui.over_z_entry
|
|
|
|
|
+ strategy_radio = self.ui.strategy_radio
|
|
|
|
|
+ cnc_button = self.ui.generate_cnc_button
|
|
|
|
|
+ solid_geo = self.solid_geometry
|
|
|
|
|
+ obj_type = self.kind
|
|
|
|
|
+
|
|
|
|
|
+ self.app.exc_areas.on_add_area_click(
|
|
|
|
|
+ shape_button=shape_button, overz_button=overz_button, cnc_button=cnc_button, strategy_radio=strategy_radio,
|
|
|
|
|
+ solid_geo=solid_geo, obj_type=obj_type)
|
|
|
|
|
+
|
|
|
|
|
+ def on_clear_area_click(self):
|
|
|
|
|
+ if not self.app.exc_areas.exclusion_areas_storage:
|
|
|
|
|
+ self.app.inform.emit("[WARNING_NOTCL] %s" % _("Delete failed. There are no exclusion areas to delete."))
|
|
|
|
|
+ return
|
|
|
|
|
+
|
|
|
|
|
+ self.app.exc_areas.on_clear_area_click()
|
|
|
|
|
+ self.app.exc_areas.e_shape_modified.emit()
|
|
|
|
|
+
|
|
|
|
|
+ def on_delete_sel_areas(self):
|
|
|
|
|
+ sel_model = self.ui.exclusion_table.selectionModel()
|
|
|
|
|
+ sel_indexes = sel_model.selectedIndexes()
|
|
|
|
|
+
|
|
|
|
|
+ # it will iterate over all indexes which means all items in all columns too but I'm interested only on rows
|
|
|
|
|
+ # so the duplicate rows will not be added
|
|
|
|
|
+ sel_rows = set()
|
|
|
|
|
+ for idx in sel_indexes:
|
|
|
|
|
+ sel_rows.add(idx.row())
|
|
|
|
|
+
|
|
|
|
|
+ if not sel_rows:
|
|
|
|
|
+ self.app.inform.emit("[WARNING_NOTCL] %s" % _("Delete failed. Nothing is selected."))
|
|
|
|
|
+ return
|
|
|
|
|
+
|
|
|
|
|
+ self.app.exc_areas.delete_sel_shapes(idxs=list(sel_rows))
|
|
|
|
|
+ self.app.exc_areas.e_shape_modified.emit()
|
|
|
|
|
+
|
|
|
|
|
+ def draw_sel_shape(self):
|
|
|
|
|
+ sel_model = self.ui.exclusion_table.selectionModel()
|
|
|
|
|
+ sel_indexes = sel_model.selectedIndexes()
|
|
|
|
|
+
|
|
|
|
|
+ # it will iterate over all indexes which means all items in all columns too but I'm interested only on rows
|
|
|
|
|
+ sel_rows = set()
|
|
|
|
|
+ for idx in sel_indexes:
|
|
|
|
|
+ sel_rows.add(idx.row())
|
|
|
|
|
+
|
|
|
|
|
+ self.delete_sel_shape()
|
|
|
|
|
+
|
|
|
|
|
+ if self.app.is_legacy is False:
|
|
|
|
|
+ face = self.app.defaults['global_sel_fill'][:-2] + str(hex(int(0.2 * 255)))[2:]
|
|
|
|
|
+ outline = self.app.defaults['global_sel_line'][:-2] + str(hex(int(0.8 * 255)))[2:]
|
|
|
|
|
+ else:
|
|
|
|
|
+ face = self.app.defaults['global_sel_fill'][:-2] + str(hex(int(0.4 * 255)))[2:]
|
|
|
|
|
+ outline = self.app.defaults['global_sel_line'][:-2] + str(hex(int(1.0 * 255)))[2:]
|
|
|
|
|
+
|
|
|
|
|
+ for row in sel_rows:
|
|
|
|
|
+ sel_rect = self.app.exc_areas.exclusion_areas_storage[row]['shape']
|
|
|
|
|
+ self.app.move_tool.sel_shapes.add(sel_rect, color=outline, face_color=face, update=True, layer=0,
|
|
|
|
|
+ tolerance=None)
|
|
|
|
|
+ if self.app.is_legacy is True:
|
|
|
|
|
+ self.app.move_tool.sel_shapes.redraw()
|
|
|
|
|
+
|
|
|
|
|
+ def clear_selection(self):
|
|
|
|
|
+ self.app.delete_selection_shape()
|
|
|
|
|
+ # self.ui.exclusion_table.clearSelection()
|
|
|
|
|
+
|
|
|
|
|
+ def delete_sel_shape(self):
|
|
|
|
|
+ self.app.delete_selection_shape()
|
|
|
|
|
+
|
|
|
|
|
+ def update_exclusion_table(self):
|
|
|
|
|
+ self.exclusion_area_cb_is_checked = True if self.ui.exclusion_cb.isChecked() else False
|
|
|
|
|
+
|
|
|
|
|
+ self.build_ui()
|
|
|
|
|
+ self.ui.exclusion_cb.set_value(self.exclusion_area_cb_is_checked)
|
|
|
|
|
+
|
|
|
|
|
+ def on_strategy(self, val):
|
|
|
|
|
+ if val == 'around':
|
|
|
|
|
+ self.ui.over_z_label.setDisabled(True)
|
|
|
|
|
+ self.ui.over_z_entry.setDisabled(True)
|
|
|
|
|
+ else:
|
|
|
|
|
+ self.ui.over_z_label.setDisabled(False)
|
|
|
|
|
+ self.ui.over_z_entry.setDisabled(False)
|
|
|
|
|
+
|
|
|
|
|
+ def exclusion_table_toggle_all(self):
|
|
|
|
|
+ """
|
|
|
|
|
+ will toggle the selection of all rows in Exclusion Areas table
|
|
|
|
|
+
|
|
|
|
|
+ :return:
|
|
|
|
|
+ """
|
|
|
|
|
+ sel_model = self.ui.exclusion_table.selectionModel()
|
|
|
|
|
+ sel_indexes = sel_model.selectedIndexes()
|
|
|
|
|
+
|
|
|
|
|
+ # it will iterate over all indexes which means all items in all columns too but I'm interested only on rows
|
|
|
|
|
+ sel_rows = set()
|
|
|
|
|
+ for idx in sel_indexes:
|
|
|
|
|
+ sel_rows.add(idx.row())
|
|
|
|
|
+
|
|
|
|
|
+ if sel_rows:
|
|
|
|
|
+ self.ui.exclusion_table.clearSelection()
|
|
|
|
|
+ self.delete_sel_shape()
|
|
|
|
|
+ else:
|
|
|
|
|
+ self.ui.exclusion_table.selectAll()
|
|
|
|
|
+ self.draw_sel_shape()
|
|
|
|
|
+
|
|
|
def plot_element(self, element, color=None, visible=None):
|
|
def plot_element(self, element, color=None, visible=None):
|
|
|
|
|
|
|
|
if color is None:
|
|
if color is None:
|
|
@@ -2498,6 +2669,27 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
if not FlatCAMObj.plot(self):
|
|
if not FlatCAMObj.plot(self):
|
|
|
return
|
|
return
|
|
|
|
|
|
|
|
|
|
+ if self.app.is_legacy is False:
|
|
|
|
|
+ def random_color():
|
|
|
|
|
+ r_color = np.random.rand(4)
|
|
|
|
|
+ r_color[3] = 1
|
|
|
|
|
+ return r_color
|
|
|
|
|
+ else:
|
|
|
|
|
+ def random_color():
|
|
|
|
|
+ while True:
|
|
|
|
|
+ r_color = np.random.rand(4)
|
|
|
|
|
+ r_color[3] = 1
|
|
|
|
|
+
|
|
|
|
|
+ new_color = '#'
|
|
|
|
|
+ for idx in range(len(r_color)):
|
|
|
|
|
+ new_color += '%x' % int(r_color[idx] * 255)
|
|
|
|
|
+ # do it until a valid color is generated
|
|
|
|
|
+ # a valid color has the # symbol, another 6 chars for the color and the last 2 chars for alpha
|
|
|
|
|
+ # for a total of 9 chars
|
|
|
|
|
+ if len(new_color) == 9:
|
|
|
|
|
+ break
|
|
|
|
|
+ return new_color
|
|
|
|
|
+
|
|
|
try:
|
|
try:
|
|
|
# plot solid geometries found as members of self.tools attribute dict
|
|
# plot solid geometries found as members of self.tools attribute dict
|
|
|
# for MultiGeo
|
|
# for MultiGeo
|
|
@@ -2505,7 +2697,8 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
for tooluid_key in self.tools:
|
|
for tooluid_key in self.tools:
|
|
|
solid_geometry = self.tools[tooluid_key]['solid_geometry']
|
|
solid_geometry = self.tools[tooluid_key]['solid_geometry']
|
|
|
self.plot_element(solid_geometry, visible=visible,
|
|
self.plot_element(solid_geometry, visible=visible,
|
|
|
- color=self.app.defaults["geometry_plot_line"])
|
|
|
|
|
|
|
+ color=random_color() if self.options['multicolored']
|
|
|
|
|
+ else self.app.defaults["geometry_plot_line"])
|
|
|
else:
|
|
else:
|
|
|
# plot solid geometry that may be an direct attribute of the geometry object
|
|
# plot solid geometry that may be an direct attribute of the geometry object
|
|
|
# for SingleGeo
|
|
# for SingleGeo
|
|
@@ -2573,218 +2766,11 @@ class GeometryObject(FlatCAMObj, Geometry):
|
|
|
self.ui.plot_cb.setChecked(True)
|
|
self.ui.plot_cb.setChecked(True)
|
|
|
self.ui_connect()
|
|
self.ui_connect()
|
|
|
|
|
|
|
|
- def on_add_area_click(self):
|
|
|
|
|
- self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click the start point of the area."))
|
|
|
|
|
- self.app.call_source = 'geometry'
|
|
|
|
|
-
|
|
|
|
|
- if self.app.is_legacy is False:
|
|
|
|
|
- self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
|
|
|
|
|
- self.app.plotcanvas.graph_event_disconnect('mouse_move', self.app.on_mouse_move_over_plot)
|
|
|
|
|
- self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
|
|
|
|
|
- else:
|
|
|
|
|
- self.app.plotcanvas.graph_event_disconnect(self.app.mp)
|
|
|
|
|
- self.app.plotcanvas.graph_event_disconnect(self.app.mm)
|
|
|
|
|
- self.app.plotcanvas.graph_event_disconnect(self.app.mr)
|
|
|
|
|
-
|
|
|
|
|
- self.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.on_mouse_release)
|
|
|
|
|
- self.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.on_mouse_move)
|
|
|
|
|
- # self.kp = self.app.plotcanvas.graph_event_connect('key_press', self.on_key_press)
|
|
|
|
|
-
|
|
|
|
|
- # To be called after clicking on the plot.
|
|
|
|
|
- def on_mouse_release(self, event):
|
|
|
|
|
- if self.app.is_legacy is False:
|
|
|
|
|
- event_pos = event.pos
|
|
|
|
|
- # event_is_dragging = event.is_dragging
|
|
|
|
|
- right_button = 2
|
|
|
|
|
- else:
|
|
|
|
|
- event_pos = (event.xdata, event.ydata)
|
|
|
|
|
- # event_is_dragging = self.app.plotcanvas.is_dragging
|
|
|
|
|
- right_button = 3
|
|
|
|
|
-
|
|
|
|
|
- event_pos = self.app.plotcanvas.translate_coords(event_pos)
|
|
|
|
|
- if self.app.grid_status():
|
|
|
|
|
- curr_pos = self.app.geo_editor.snap(event_pos[0], event_pos[1])
|
|
|
|
|
- else:
|
|
|
|
|
- curr_pos = (event_pos[0], event_pos[1])
|
|
|
|
|
-
|
|
|
|
|
- x1, y1 = curr_pos[0], curr_pos[1]
|
|
|
|
|
-
|
|
|
|
|
- shape_type = self.ui.area_shape_radio.get_value()
|
|
|
|
|
-
|
|
|
|
|
- # do clear area only for left mouse clicks
|
|
|
|
|
- if event.button == 1:
|
|
|
|
|
- if shape_type == "square":
|
|
|
|
|
- if self.first_click is False:
|
|
|
|
|
- self.first_click = True
|
|
|
|
|
- self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click the end point of the area."))
|
|
|
|
|
-
|
|
|
|
|
- self.cursor_pos = self.app.plotcanvas.translate_coords(event_pos)
|
|
|
|
|
- if self.app.grid_status():
|
|
|
|
|
- self.cursor_pos = self.app.geo_editor.snap(event_pos[0], event_pos[1])
|
|
|
|
|
- else:
|
|
|
|
|
- self.app.inform.emit(_("Zone added. Click to start adding next zone or right click to finish."))
|
|
|
|
|
- self.app.delete_selection_shape()
|
|
|
|
|
-
|
|
|
|
|
- x0, y0 = self.cursor_pos[0], self.cursor_pos[1]
|
|
|
|
|
-
|
|
|
|
|
- pt1 = (x0, y0)
|
|
|
|
|
- pt2 = (x1, y0)
|
|
|
|
|
- pt3 = (x1, y1)
|
|
|
|
|
- pt4 = (x0, y1)
|
|
|
|
|
-
|
|
|
|
|
- new_rectangle = Polygon([pt1, pt2, pt3, pt4])
|
|
|
|
|
- self.exclusion_areas_list.append(new_rectangle)
|
|
|
|
|
-
|
|
|
|
|
- # add a temporary shape on canvas
|
|
|
|
|
- FlatCAMTool.FlatCAMTool.draw_tool_selection_shape(self, old_coords=(x0, y0), coords=(x1, y1))
|
|
|
|
|
-
|
|
|
|
|
- self.first_click = False
|
|
|
|
|
- return
|
|
|
|
|
- else:
|
|
|
|
|
- self.points.append((x1, y1))
|
|
|
|
|
-
|
|
|
|
|
- if len(self.points) > 1:
|
|
|
|
|
- self.poly_drawn = True
|
|
|
|
|
- self.app.inform.emit(_("Click on next Point or click right mouse button to complete ..."))
|
|
|
|
|
-
|
|
|
|
|
- return ""
|
|
|
|
|
- elif event.button == right_button and self.mouse_is_dragging is False:
|
|
|
|
|
-
|
|
|
|
|
- shape_type = self.ui.area_shape_radio.get_value()
|
|
|
|
|
-
|
|
|
|
|
- if shape_type == "square":
|
|
|
|
|
- self.first_click = False
|
|
|
|
|
- else:
|
|
|
|
|
- # if we finish to add a polygon
|
|
|
|
|
- if self.poly_drawn is True:
|
|
|
|
|
- try:
|
|
|
|
|
- # try to add the point where we last clicked if it is not already in the self.points
|
|
|
|
|
- last_pt = (x1, y1)
|
|
|
|
|
- if last_pt != self.points[-1]:
|
|
|
|
|
- self.points.append(last_pt)
|
|
|
|
|
- except IndexError:
|
|
|
|
|
- pass
|
|
|
|
|
-
|
|
|
|
|
- # we need to add a Polygon and a Polygon can be made only from at least 3 points
|
|
|
|
|
- if len(self.points) > 2:
|
|
|
|
|
- FlatCAMTool.FlatCAMTool.delete_moving_selection_shape(self)
|
|
|
|
|
- pol = Polygon(self.points)
|
|
|
|
|
- # do not add invalid polygons even if they are drawn by utility geometry
|
|
|
|
|
- if pol.is_valid:
|
|
|
|
|
- self.exclusion_areas_list.append(pol)
|
|
|
|
|
- FlatCAMTool.FlatCAMTool.draw_selection_shape_polygon(self, points=self.points)
|
|
|
|
|
- self.app.inform.emit(
|
|
|
|
|
- _("Zone added. Click to start adding next zone or right click to finish."))
|
|
|
|
|
-
|
|
|
|
|
- self.points = []
|
|
|
|
|
- self.poly_drawn = False
|
|
|
|
|
- return
|
|
|
|
|
-
|
|
|
|
|
- FlatCAMTool.FlatCAMTool.delete_tool_selection_shape(self)
|
|
|
|
|
-
|
|
|
|
|
- if self.app.is_legacy is False:
|
|
|
|
|
- self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_release)
|
|
|
|
|
- self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_mouse_move)
|
|
|
|
|
- # self.app.plotcanvas.graph_event_disconnect('key_press', self.on_key_press)
|
|
|
|
|
- else:
|
|
|
|
|
- self.app.plotcanvas.graph_event_disconnect(self.mr)
|
|
|
|
|
- self.app.plotcanvas.graph_event_disconnect(self.mm)
|
|
|
|
|
- # self.app.plotcanvas.graph_event_disconnect(self.kp)
|
|
|
|
|
-
|
|
|
|
|
- self.app.mp = self.app.plotcanvas.graph_event_connect('mouse_press',
|
|
|
|
|
- self.app.on_mouse_click_over_plot)
|
|
|
|
|
- self.app.mm = self.app.plotcanvas.graph_event_connect('mouse_move',
|
|
|
|
|
- self.app.on_mouse_move_over_plot)
|
|
|
|
|
- self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
|
|
|
|
|
- self.app.on_mouse_click_release_over_plot)
|
|
|
|
|
-
|
|
|
|
|
- self.app.call_source = 'app'
|
|
|
|
|
-
|
|
|
|
|
- if len(self.exclusion_areas_list) == 0:
|
|
|
|
|
- return
|
|
|
|
|
-
|
|
|
|
|
- def area_disconnect(self):
|
|
|
|
|
- if self.app.is_legacy is False:
|
|
|
|
|
- self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_mouse_release)
|
|
|
|
|
- self.app.plotcanvas.graph_event_disconnect('mouse_move', self.on_mouse_move)
|
|
|
|
|
- else:
|
|
|
|
|
- self.app.plotcanvas.graph_event_disconnect(self.mr)
|
|
|
|
|
- self.app.plotcanvas.graph_event_disconnect(self.mm)
|
|
|
|
|
- self.app.plotcanvas.graph_event_disconnect(self.kp)
|
|
|
|
|
-
|
|
|
|
|
- self.app.mp = self.app.plotcanvas.graph_event_connect('mouse_press',
|
|
|
|
|
- self.app.on_mouse_click_over_plot)
|
|
|
|
|
- self.app.mm = self.app.plotcanvas.graph_event_connect('mouse_move',
|
|
|
|
|
- self.app.on_mouse_move_over_plot)
|
|
|
|
|
- self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
|
|
|
|
|
- self.app.on_mouse_click_release_over_plot)
|
|
|
|
|
- self.points = []
|
|
|
|
|
- self.poly_drawn = False
|
|
|
|
|
- self.exclusion_areas_list = []
|
|
|
|
|
-
|
|
|
|
|
- FlatCAMTool.FlatCAMTool.delete_moving_selection_shape(self)
|
|
|
|
|
- FlatCAMTool.FlatCAMTool.delete_tool_selection_shape(self)
|
|
|
|
|
-
|
|
|
|
|
- self.app.call_source = "app"
|
|
|
|
|
- self.app.inform.emit("[WARNING_NOTCL] %s" % _("Cancelled. Area exclusion drawing was interrupted."))
|
|
|
|
|
-
|
|
|
|
|
- # called on mouse move
|
|
|
|
|
- def on_mouse_move(self, event):
|
|
|
|
|
- shape_type = self.ui.area_shape_radio.get_value()
|
|
|
|
|
-
|
|
|
|
|
- if self.app.is_legacy is False:
|
|
|
|
|
- event_pos = event.pos
|
|
|
|
|
- event_is_dragging = event.is_dragging
|
|
|
|
|
- # right_button = 2
|
|
|
|
|
- else:
|
|
|
|
|
- event_pos = (event.xdata, event.ydata)
|
|
|
|
|
- event_is_dragging = self.app.plotcanvas.is_dragging
|
|
|
|
|
- # right_button = 3
|
|
|
|
|
-
|
|
|
|
|
- curr_pos = self.app.plotcanvas.translate_coords(event_pos)
|
|
|
|
|
-
|
|
|
|
|
- # detect mouse dragging motion
|
|
|
|
|
- if event_is_dragging is True:
|
|
|
|
|
- self.mouse_is_dragging = True
|
|
|
|
|
- else:
|
|
|
|
|
- self.mouse_is_dragging = False
|
|
|
|
|
-
|
|
|
|
|
- # update the cursor position
|
|
|
|
|
- if self.app.grid_status():
|
|
|
|
|
- # Update cursor
|
|
|
|
|
- curr_pos = self.app.geo_editor.snap(curr_pos[0], curr_pos[1])
|
|
|
|
|
-
|
|
|
|
|
- self.app.app_cursor.set_data(np.asarray([(curr_pos[0], curr_pos[1])]),
|
|
|
|
|
- symbol='++', edge_color=self.app.cursor_color_3D,
|
|
|
|
|
- edge_width=self.app.defaults["global_cursor_width"],
|
|
|
|
|
- size=self.app.defaults["global_cursor_size"])
|
|
|
|
|
-
|
|
|
|
|
- # update the positions on status bar
|
|
|
|
|
- self.app.ui.position_label.setText(" <b>X</b>: %.4f "
|
|
|
|
|
- "<b>Y</b>: %.4f" % (curr_pos[0], curr_pos[1]))
|
|
|
|
|
- if self.cursor_pos is None:
|
|
|
|
|
- self.cursor_pos = (0, 0)
|
|
|
|
|
-
|
|
|
|
|
- self.app.dx = curr_pos[0] - float(self.cursor_pos[0])
|
|
|
|
|
- self.app.dy = curr_pos[1] - float(self.cursor_pos[1])
|
|
|
|
|
- self.app.ui.rel_position_label.setText("<b>Dx</b>: %.4f <b>Dy</b>: "
|
|
|
|
|
- "%.4f " % (self.app.dx, self.app.dy))
|
|
|
|
|
-
|
|
|
|
|
- # draw the utility geometry
|
|
|
|
|
- if shape_type == "square":
|
|
|
|
|
- if self.first_click:
|
|
|
|
|
- self.app.delete_selection_shape()
|
|
|
|
|
- self.app.draw_moving_selection_shape(old_coords=(self.cursor_pos[0], self.cursor_pos[1]),
|
|
|
|
|
- coords=(curr_pos[0], curr_pos[1]))
|
|
|
|
|
- else:
|
|
|
|
|
- FlatCAMTool.FlatCAMTool.delete_moving_selection_shape(self)
|
|
|
|
|
- FlatCAMTool.FlatCAMTool.draw_moving_selection_shape_poly(
|
|
|
|
|
- self, points=self.points, data=(curr_pos[0], curr_pos[1]))
|
|
|
|
|
-
|
|
|
|
|
- def on_clear_area_click(self):
|
|
|
|
|
- self.exclusion_areas_list = []
|
|
|
|
|
- FlatCAMTool.FlatCAMTool.delete_moving_selection_shape(self)
|
|
|
|
|
- self.app.delete_selection_shape()
|
|
|
|
|
|
|
+ def on_multicolored_cb_click(self, *args):
|
|
|
|
|
+ if self.muted_ui:
|
|
|
|
|
+ return
|
|
|
|
|
+ self.read_form_item('multicolored')
|
|
|
|
|
+ self.plot()
|
|
|
|
|
|
|
|
@staticmethod
|
|
@staticmethod
|
|
|
def merge(geo_list, geo_final, multigeo=None):
|
|
def merge(geo_list, geo_final, multigeo=None):
|