- added Rtree optimization for Drilling Plugin
This commit is contained in:
committed by
Marius Stanciu
parent
9761e8a4d1
commit
370e8f8ec1
@@ -11,6 +11,7 @@ CHANGELOG for FlatCAM beta
|
|||||||
|
|
||||||
- fixed an issue when using Python 3.10, in GUI elements
|
- fixed an issue when using Python 3.10, in GUI elements
|
||||||
- added fix such that the application will work without having the ortools package installed: TSA and RTree algorithms will be automatically used in that case
|
- added fix such that the application will work without having the ortools package installed: TSA and RTree algorithms will be automatically used in that case
|
||||||
|
- added Rtree optimization for Drilling Plugin
|
||||||
|
|
||||||
10.11.2021
|
10.11.2021
|
||||||
|
|
||||||
|
|||||||
@@ -231,20 +231,23 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
|
|||||||
|
|
||||||
self.excellon_optimization_label = FCLabel(_('Algorithm:'))
|
self.excellon_optimization_label = FCLabel(_('Algorithm:'))
|
||||||
self.excellon_optimization_label.setToolTip(
|
self.excellon_optimization_label.setToolTip(
|
||||||
_("This sets the optimization type for the Excellon drill path.\n"
|
_("This sets the path optimization algorithm.\n"
|
||||||
"If <<MetaHeuristic>> is checked then Google OR-Tools algorithm with\n"
|
"- Rtre -> Rtree algorithm\n"
|
||||||
|
"- MetaHeuristic -> Google OR-Tools algorithm with\n"
|
||||||
"MetaHeuristic Guided Local Path is used. Default search time is 3sec.\n"
|
"MetaHeuristic Guided Local Path is used. Default search time is 3sec.\n"
|
||||||
"If <<Basic>> is checked then Google OR-Tools Basic algorithm is used.\n"
|
"- Basic -> Using Google OR-Tools Basic algorithm\n"
|
||||||
"If <<TSA>> is checked then Travelling Salesman algorithm is used for\n"
|
"- TSA -> Using Travelling Salesman algorithm\n"
|
||||||
"drill path optimization.\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
"Some options are disabled when the application works in 32bit mode.")
|
"Some options are disabled when the application works in 32bit mode.")
|
||||||
)
|
)
|
||||||
|
|
||||||
self.excellon_optimization_radio = RadioSet([{'label': _('MetaHeuristic'), 'value': 'M'},
|
self.excellon_optimization_radio = RadioSet(
|
||||||
{'label': _('Basic'), 'value': 'B'},
|
[
|
||||||
{'label': _('TSA'), 'value': 'T'}],
|
{'label': _('Rtree'), 'value': 'R'},
|
||||||
orientation='vertical', compact=True)
|
{'label': _('MetaHeuristic'), 'value': 'M'},
|
||||||
|
{'label': _('Basic'), 'value': 'B'},
|
||||||
|
{'label': _('TSA'), 'value': 'T'}
|
||||||
|
], orientation='vertical', compact=True)
|
||||||
|
|
||||||
opt_grid.addWidget(self.excellon_optimization_label, 0, 0)
|
opt_grid.addWidget(self.excellon_optimization_label, 0, 0)
|
||||||
opt_grid.addWidget(self.excellon_optimization_radio, 0, 1)
|
opt_grid.addWidget(self.excellon_optimization_radio, 0, 1)
|
||||||
|
|||||||
60
camlib.py
60
camlib.py
@@ -3201,6 +3201,49 @@ class CNCjob(Geometry):
|
|||||||
|
|
||||||
return locations
|
return locations
|
||||||
|
|
||||||
|
def exc_optimized_rtree(self, geometry):
|
||||||
|
locations = []
|
||||||
|
|
||||||
|
# ## Index first and last points in paths. What points to index.
|
||||||
|
def get_pts(o):
|
||||||
|
return [(o.x, o.y)]
|
||||||
|
|
||||||
|
# Create the indexed storage.
|
||||||
|
storage = FlatCAMRTreeStorage()
|
||||||
|
storage.get_points = get_pts
|
||||||
|
|
||||||
|
# Store the geometry
|
||||||
|
log.debug("Indexing geometry before generating G-Code...")
|
||||||
|
self.app.inform.emit(_("Indexing geometry before generating G-Code..."))
|
||||||
|
|
||||||
|
for geo_shape in geometry:
|
||||||
|
if self.app.abort_flag:
|
||||||
|
# graceful abort requested by the user
|
||||||
|
raise grace
|
||||||
|
|
||||||
|
if geo_shape is not None:
|
||||||
|
try:
|
||||||
|
storage.insert(geo_shape)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
current_pt = (0, 0)
|
||||||
|
pt, geo = storage.nearest(current_pt)
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
storage.remove(geo)
|
||||||
|
locations.append((pt, geo))
|
||||||
|
current_pt = (geo.x, geo.y)
|
||||||
|
pt, geo = storage.nearest(current_pt)
|
||||||
|
except StopIteration:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# if there are no locations then go to the next tool
|
||||||
|
if not locations:
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
|
return locations
|
||||||
|
|
||||||
def check_zcut(self, zcut):
|
def check_zcut(self, zcut):
|
||||||
if zcut > 0:
|
if zcut > 0:
|
||||||
self.app.inform.emit('[WARNING] %s' %
|
self.app.inform.emit('[WARNING] %s' %
|
||||||
@@ -3251,12 +3294,18 @@ class CNCjob(Geometry):
|
|||||||
# ################################## DRILLING !!! #########################################################
|
# ################################## DRILLING !!! #########################################################
|
||||||
# #############################################################################################################
|
# #############################################################################################################
|
||||||
# #############################################################################################################
|
# #############################################################################################################
|
||||||
|
if not HAS_ORTOOLS:
|
||||||
|
if opt_type in ['M', 'B']:
|
||||||
|
opt_type = 'R'
|
||||||
|
|
||||||
if opt_type == 'M':
|
if opt_type == 'M':
|
||||||
log.debug("Using OR-Tools Metaheuristic Guided Local Search drill path optimization.")
|
log.debug("Using OR-Tools Metaheuristic Guided Local Search drill path optimization.")
|
||||||
elif opt_type == 'B':
|
elif opt_type == 'B':
|
||||||
log.debug("Using OR-Tools Basic drill path optimization.")
|
log.debug("Using OR-Tools Basic drill path optimization.")
|
||||||
elif opt_type == 'T':
|
elif opt_type == 'T':
|
||||||
log.debug("Using Travelling Salesman drill path optimization.")
|
log.debug("Using Travelling Salesman drill path optimization.")
|
||||||
|
elif opt_type == 'R':
|
||||||
|
log.debug("Using RTree path optimization.")
|
||||||
else:
|
else:
|
||||||
log.debug("Using no path optimization.")
|
log.debug("Using no path optimization.")
|
||||||
|
|
||||||
@@ -3367,9 +3416,6 @@ class CNCjob(Geometry):
|
|||||||
locations = []
|
locations = []
|
||||||
optimized_path = []
|
optimized_path = []
|
||||||
|
|
||||||
if not HAS_ORTOOLS:
|
|
||||||
opt_type = 'T'
|
|
||||||
|
|
||||||
if opt_type == 'M':
|
if opt_type == 'M':
|
||||||
locations = self.create_tool_data_array(points=points)
|
locations = self.create_tool_data_array(points=points)
|
||||||
# if there are no locations then go to the next tool
|
# if there are no locations then go to the next tool
|
||||||
@@ -3389,6 +3435,11 @@ class CNCjob(Geometry):
|
|||||||
if not locations:
|
if not locations:
|
||||||
return 'fail'
|
return 'fail'
|
||||||
optimized_path = self.optimized_travelling_salesman(locations)
|
optimized_path = self.optimized_travelling_salesman(locations)
|
||||||
|
elif opt_type == 'R':
|
||||||
|
temp_solid_geometry = tools[tool]['drills']
|
||||||
|
optimized_path = self.exc_optimized_rtree(temp_solid_geometry)
|
||||||
|
if optimized_path == 'fail':
|
||||||
|
return 'fail'
|
||||||
else:
|
else:
|
||||||
# it's actually not optimized path but here we build a list of (x,y) coordinates
|
# it's actually not optimized path but here we build a list of (x,y) coordinates
|
||||||
# out of the tool's drills
|
# out of the tool's drills
|
||||||
@@ -3464,6 +3515,9 @@ class CNCjob(Geometry):
|
|||||||
if opt_type == 'T':
|
if opt_type == 'T':
|
||||||
locx = point[0]
|
locx = point[0]
|
||||||
locy = point[1]
|
locy = point[1]
|
||||||
|
elif opt_type == 'R':
|
||||||
|
locx = point[0][0]
|
||||||
|
locy = point[0][1]
|
||||||
else:
|
else:
|
||||||
locx = locations[point][0]
|
locx = locations[point][0]
|
||||||
locy = locations[point][1]
|
locy = locations[point][1]
|
||||||
|
|||||||
Reference in New Issue
Block a user