- refactored the imports in the Plugins, moved almost all imports in the AppTool file
- fixed a number of issues, mostly leftovers from moving the UI of a Plugin in its own class - fixed some bugs in the Punch Gerber plugin - fixed some bugs where the 'pool' parameter was not passed when creating shapes collections (in 3D graphic mode); I wonder how it worked until now - added a new feature in the Isolation Plugin: now for all the isolation Geometry objects this plugin can do a supplementary simplification of the geometry using the tolerance parameter defined in the General Parameters. This should lead to a reduced number of tool lifts when doing corners
This commit is contained in:
committed by
Marius Stanciu
parent
e1824a09f7
commit
ada48269a9
@@ -5,36 +5,10 @@
|
||||
# License: MIT Licence #
|
||||
# ##########################################################
|
||||
|
||||
from PyQt6 import QtWidgets, QtCore, QtGui
|
||||
|
||||
from appTool import AppTool
|
||||
from appGUI.GUIElements import FCCheckBox, FCDoubleSpinner, RadioSet, FCTable, FCButton, FCComboBox2, \
|
||||
FCComboBox, OptionalInputSection, FCSpinner, NumericalEvalTupleEntry, OptionalHideInputSection, FCLabel, \
|
||||
VerticalScrollArea, FCGridLayout, FCFrame
|
||||
from appTool import *
|
||||
from appParsers.ParseExcellon import Excellon
|
||||
|
||||
from camlib import grace
|
||||
import numpy as np
|
||||
|
||||
from copy import deepcopy
|
||||
import math
|
||||
import simplejson as json
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
# from appObjects.FlatCAMObj import FlatCAMObj
|
||||
# import numpy as np
|
||||
# import math
|
||||
|
||||
# from shapely.ops import unary_union
|
||||
from shapely.geometry import Point, LineString, box
|
||||
|
||||
from matplotlib.backend_bases import KeyEvent as mpl_key_event
|
||||
|
||||
import logging
|
||||
import gettext
|
||||
import appTranslation as fcTranslate
|
||||
import builtins
|
||||
from camlib import grace
|
||||
|
||||
fcTranslate.apply_language('strings')
|
||||
if '_' not in builtins.__dict__:
|
||||
@@ -251,8 +225,8 @@ class ToolMilling(AppTool, Excellon):
|
||||
self.ui.level.toggled.connect(self.on_level_changed)
|
||||
|
||||
# add Tool
|
||||
self.ui.search_and_add_btn.clicked.connect(self.on_tool_add)
|
||||
self.ui.deltool_btn.clicked.connect(self.on_tool_delete)
|
||||
self.ui.search_and_add_btn.clicked.connect(lambda: self.on_tool_add())
|
||||
self.ui.deltool_btn.clicked.connect(lambda: self.on_tool_delete())
|
||||
self.ui.addtool_from_db_btn.clicked.connect(self.on_tool_add_from_db_clicked)
|
||||
|
||||
self.ui.target_radio.activated_custom.connect(self.on_target_changed)
|
||||
@@ -585,7 +559,7 @@ class ToolMilling(AppTool, Excellon):
|
||||
"mill_spindlespeed": "tools_mill_spindlespeed",
|
||||
"mill_dwell": "tools_mill_dwell",
|
||||
"mill_dwelltime": "tools_mill_dwelltime",
|
||||
"mill_minpower":"tools_mill_min_power",
|
||||
"mill_minpower": "tools_mill_min_power",
|
||||
|
||||
# General Parameters
|
||||
"mill_toolchange": "tools_mill_toolchange",
|
||||
@@ -1154,9 +1128,8 @@ class ToolMilling(AppTool, Excellon):
|
||||
self.tool_row = 0
|
||||
|
||||
for tool_no in tools:
|
||||
|
||||
drill_cnt = 0 # variable to store the nr of drills per tool
|
||||
slot_cnt = 0 # variable to store the nr of slots per tool
|
||||
# drill_cnt = 0 # variable to store the nr of drills per tool
|
||||
# slot_cnt = 0 # variable to store the nr of slots per tool
|
||||
|
||||
# Find no of drills for the current tool
|
||||
try:
|
||||
@@ -1946,6 +1919,7 @@ class ToolMilling(AppTool, Excellon):
|
||||
|
||||
def on_tt_change(self):
|
||||
cw = self.sender()
|
||||
assert isinstance(cw, FCComboBox2)
|
||||
|
||||
tool_type = cw.currentText()
|
||||
self.ui_update_v_shape(tool_type)
|
||||
@@ -2043,14 +2017,14 @@ class ToolMilling(AppTool, Excellon):
|
||||
tooluid_item = int(self.ui.tools_table.item(row, 3).text())
|
||||
temp_tool_data = {}
|
||||
|
||||
for tooluid_key, tooluid_val in self.iso_tools.items():
|
||||
for tooluid_key, tooluid_val in self.target_obj.tools.items():
|
||||
if int(tooluid_key) == tooluid_item:
|
||||
# this will hold the 'data' key of the self.tools[tool] dictionary that corresponds to
|
||||
# the current row in the tool table
|
||||
temp_tool_data = tooluid_val['data']
|
||||
break
|
||||
|
||||
for tooluid_key, tooluid_val in self.iso_tools.items():
|
||||
for tooluid_key, tooluid_val in self.target_obj.tools.items():
|
||||
tooluid_val['data'] = deepcopy(temp_tool_data)
|
||||
|
||||
self.app.inform.emit('[success] %s' % _("Current Tool parameters were applied to all tools."))
|
||||
@@ -2060,7 +2034,7 @@ class ToolMilling(AppTool, Excellon):
|
||||
if order != 0: # "default"
|
||||
self.build_ui()
|
||||
|
||||
def on_tool_add(self, clicked_state, dia=None, new_geo=None):
|
||||
def on_tool_add(self, dia=None, new_geo=None):
|
||||
self.app.log.debug("GeometryObject.on_add_tool()")
|
||||
|
||||
if self.target_obj is None:
|
||||
@@ -2428,11 +2402,7 @@ class ToolMilling(AppTool, Excellon):
|
||||
self.builduiSig.emit()
|
||||
self.app.inform.emit('[success] %s' % _("Tool was copied in Tool Table."))
|
||||
|
||||
def on_tool_delete(self, clicked_signal, all_tools=None):
|
||||
"""
|
||||
It's important to keep the not clicked_signal parameter otherwise the signal will go to the all_tools
|
||||
parameter and I might get all the tool deleted
|
||||
"""
|
||||
def on_tool_delete(self, all_tools=None):
|
||||
self.ui_disconnect()
|
||||
|
||||
if all_tools is None:
|
||||
@@ -2549,34 +2519,30 @@ class ToolMilling(AppTool, Excellon):
|
||||
outname = self.target_obj.obj_options["name"] + "_mill"
|
||||
|
||||
if tooldia is None:
|
||||
tooldia = float(self.target_obj.obj_options["tooldia"])
|
||||
tooldia = self.ui.tooldia_entry.get_value()
|
||||
|
||||
# Sort tools by diameter. items() -> [('name', diameter), ...]
|
||||
sorted_tools = sorted(list(self.tools.items()), key=lambda tl: tl[1]['tooldia'])
|
||||
# sorted_tools = sorted(list(self.tools.items()), key=lambda tl: tl[1]) # no longer works in Python3
|
||||
|
||||
# sort = []
|
||||
# for k, v in self.tools.items():
|
||||
# sort.append((k, v.get('tooldia')))
|
||||
# sorted_tools = sorted(sort, key=lambda t1: t1[1])
|
||||
sort = []
|
||||
for k, v in self.target_obj.tools.items():
|
||||
sort.append((k, v['tooldia']))
|
||||
sorted_tools = sorted(sort, key=lambda t1: t1[1])
|
||||
|
||||
if tools == "all":
|
||||
tools = [i[0] for i in sorted_tools] # List if ordered tool names.
|
||||
self.app.log.debug("Tools 'all' and sorted are: %s" % str(tools))
|
||||
|
||||
if len(tools) == 0:
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||
_("Please select one or more tools from the list and try again."))
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Please select one or more tools from the list and try again."))
|
||||
return False, "Error: No tools."
|
||||
|
||||
for tool in tools:
|
||||
if tooldia > self.tools[tool]['data']['tools_mill_tooldia']:
|
||||
self.app.inform.emit(
|
||||
'[ERROR_NOTCL] %s %s: %s' % (
|
||||
_("Milling tool for DRILLS is larger than hole size. Cancelled."),
|
||||
_("Tool"),
|
||||
str(tool)
|
||||
)
|
||||
)
|
||||
if tooldia > self.target_obj.tools[tool]["tooldia"]:
|
||||
mseg = '[ERROR_NOTCL] %s %s: %s' % (_("Milling tool for DRILLS is larger than hole size. Cancelled."),
|
||||
_("Tool"),
|
||||
str(tool))
|
||||
self.app.inform.emit(mseg)
|
||||
return False, "Error: Milling tool is larger than hole."
|
||||
|
||||
def geo_init(geo_obj, app_obj):
|
||||
@@ -2591,27 +2557,26 @@ class ToolMilling(AppTool, Excellon):
|
||||
"""
|
||||
assert geo_obj.kind == 'geometry', "Initializer expected a GeometryObject, got %s" % type(geo_obj)
|
||||
|
||||
app_obj.inform.emit(_("Generating drills milling geometry..."))
|
||||
|
||||
# ## Add properties to the object
|
||||
|
||||
geo_obj.obj_options['type'] = 'Excellon Geometry'
|
||||
geo_obj.obj_options["tools_mill_tooldia"] = str(tooldia)
|
||||
geo_obj.obj_options["tools_mill_multidepth"] = self.target_obj.obj_options["tools_mill_multidepth"]
|
||||
geo_obj.obj_options["multidepth"] = app_obj.options["tools_mill_multidepth"]
|
||||
geo_obj.solid_geometry = []
|
||||
|
||||
# in case that the tool used has the same diameter with the hole, and since the maximum resolution
|
||||
# for FlatCAM is 6 decimals,
|
||||
# we add a tenth of the minimum value, meaning 0.0000001, which from our point of view is "almost zero"
|
||||
for hole in self.drills:
|
||||
if hole['tool'] in tools:
|
||||
buffer_value = self.tools[hole['tool']]["C"] / 2 - tooldia / 2
|
||||
for etool in tools:
|
||||
for drill in self.target_obj.tools[etool]['drills']:
|
||||
buffer_value = self.target_obj.tools[etool]['tooldia'] / 2 - tooldia / 2
|
||||
if buffer_value == 0:
|
||||
geo_obj.solid_geometry.append(
|
||||
Point(hole['point']).buffer(0.0000001).exterior)
|
||||
geo_obj.solid_geometry.append(drill.buffer(0.0000001).exterior)
|
||||
else:
|
||||
geo_obj.solid_geometry.append(
|
||||
Point(hole['point']).buffer(buffer_value).exterior)
|
||||
geo_obj.solid_geometry.append(drill.buffer(buffer_value).exterior)
|
||||
|
||||
if not geo_obj.solid_geometry:
|
||||
return "fail"
|
||||
|
||||
if use_thread:
|
||||
def geo_thread(a_obj):
|
||||
@@ -2656,32 +2621,31 @@ class ToolMilling(AppTool, Excellon):
|
||||
tools = self.get_selected_tools_list()
|
||||
|
||||
if outname is None:
|
||||
outname = self.target_obj.obj_options["name"] + "_slots"
|
||||
outname = self.target_obj.obj_options["name"] + "_mill"
|
||||
|
||||
if tooldia is None:
|
||||
tooldia = float(self.target_obj.obj_options["slot_tooldia"])
|
||||
|
||||
# Sort tools by diameter. items() -> [('name', diameter), ...]
|
||||
sorted_tools = sorted(list(self.tools.items()), key=lambda tl: tl[1]['tooldia'])
|
||||
#
|
||||
# sort = []
|
||||
# for k, v in self.tools.items():
|
||||
# sort.append((k, v.get('tooldia')))
|
||||
# sorted_tools = sorted(sort, key=lambda t1: t1[1])
|
||||
# sorted_tools = sorted(list(self.tools.items()), key=lambda tl: tl[1]) # no longer works in Python3
|
||||
|
||||
sort = []
|
||||
for k, v in self.target_obj.tools.items():
|
||||
sort.append((k, v['tooldia']))
|
||||
sorted_tools = sorted(sort, key=lambda t1: t1[1])
|
||||
|
||||
if tools == "all":
|
||||
tools = [i[0] for i in sorted_tools] # List if ordered tool names.
|
||||
self.app.log.debug("Tools 'all' and sorted are: %s" % str(tools))
|
||||
|
||||
if len(tools) == 0:
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||
_("Please select one or more tools from the list and try again."))
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Please select one or more tools from the list and try again."))
|
||||
return False, "Error: No tools."
|
||||
|
||||
for tool in tools:
|
||||
# I add the 0.0001 value to account for the rounding error in converting from IN to MM and reverse
|
||||
adj_toolstable_tooldia = float('%.*f' % (self.decimals, float(tooldia)))
|
||||
adj_file_tooldia = float('%.*f' % (self.decimals, float(self.tools[tool]['data']['tools_mill_tooldia'])))
|
||||
adj_file_tooldia = float('%.*f' % (self.decimals, float(self.target_obj.tools[tool]["tooldia"])))
|
||||
if adj_toolstable_tooldia > adj_file_tooldia + 0.0001:
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' %
|
||||
_("Milling tool for SLOTS is larger than hole size. Cancelled."))
|
||||
@@ -2690,40 +2654,40 @@ class ToolMilling(AppTool, Excellon):
|
||||
def geo_init(geo_obj, app_obj):
|
||||
assert geo_obj.kind == 'geometry', "Initializer expected a GeometryObject, got %s" % type(geo_obj)
|
||||
|
||||
app_obj.inform.emit(_("Generating slot milling geometry..."))
|
||||
|
||||
# ## Add properties to the object
|
||||
|
||||
geo_obj.obj_options['type'] = 'Excellon Geometry'
|
||||
geo_obj.obj_options["tools_mill_tooldia"] = str(tooldia)
|
||||
geo_obj.obj_options["tools_mill_multidepth"] = self.target_obj.obj_options["tools_mill_multidepth"]
|
||||
geo_obj.obj_options["tools_mill_multidepth"] = app_obj.options["tools_mill_multidepth"]
|
||||
geo_obj.solid_geometry = []
|
||||
|
||||
# in case that the tool used has the same diameter with the hole, and since the maximum resolution
|
||||
# for FlatCAM is 6 decimals,
|
||||
# we add a tenth of the minimum value, meaning 0.0000001, which from our point of view is "almost zero"
|
||||
for slot in self.slots:
|
||||
if slot['tool'] in tools:
|
||||
for m_tool in tools:
|
||||
for slot in self.target_obj.tools[m_tool]['slots']:
|
||||
toolstable_tool = float('%.*f' % (self.decimals, float(tooldia)))
|
||||
file_tool = float('%.*f' % (self.decimals, float(self.tools[tool]["C"])))
|
||||
file_tool = float('%.*f' % (self.decimals, float(self.target_obj.tools[m_tool]["tooldia"])))
|
||||
|
||||
# I add the 0.0001 value to account for the rounding error in converting from IN to MM and reverse
|
||||
# for the file_tool (tooldia actually)
|
||||
buffer_value = float(file_tool / 2) - float(toolstable_tool / 2) + 0.0001
|
||||
if buffer_value == 0:
|
||||
start = slot['start']
|
||||
stop = slot['stop']
|
||||
start = slot[0]
|
||||
stop = slot[1]
|
||||
|
||||
lines_string = LineString([start, stop])
|
||||
poly = lines_string.buffer(0.0000001, int(self.geo_steps_per_circle)).exterior
|
||||
geo_obj.solid_geometry.append(poly)
|
||||
else:
|
||||
start = slot['start']
|
||||
stop = slot['stop']
|
||||
start = slot[0]
|
||||
stop = slot[1]
|
||||
|
||||
lines_string = LineString([start, stop])
|
||||
poly = lines_string.buffer(buffer_value, int(self.geo_steps_per_circle)).exterior
|
||||
geo_obj.solid_geometry.append(poly)
|
||||
if not geo_obj.solid_geometry:
|
||||
return "fail"
|
||||
|
||||
if use_thread:
|
||||
def geo_thread(a_obj):
|
||||
|
||||
Reference in New Issue
Block a user