- added Rtree optimization for Drilling Plugin

This commit is contained in:
Marius Stanciu
2021-11-17 18:59:37 +02:00
committed by Marius Stanciu
parent 9761e8a4d1
commit 370e8f8ec1
3 changed files with 70 additions and 12 deletions

View File

@@ -11,6 +11,7 @@ CHANGELOG for FlatCAM beta
- 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 Rtree optimization for Drilling Plugin
10.11.2021

View File

@@ -231,20 +231,23 @@ class ExcellonGenPrefGroupUI(OptionsGroupUI):
self.excellon_optimization_label = FCLabel(_('Algorithm:'))
self.excellon_optimization_label.setToolTip(
_("This sets the optimization type for the Excellon drill path.\n"
"If <<MetaHeuristic>> is checked then Google OR-Tools algorithm with\n"
_("This sets the path optimization algorithm.\n"
"- Rtre -> Rtree algorithm\n"
"- MetaHeuristic -> Google OR-Tools algorithm with\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"
"If <<TSA>> is checked then Travelling Salesman algorithm is used for\n"
"drill path optimization.\n"
"- Basic -> Using Google OR-Tools Basic algorithm\n"
"- TSA -> Using Travelling Salesman algorithm\n"
"\n"
"Some options are disabled when the application works in 32bit mode.")
)
self.excellon_optimization_radio = RadioSet([{'label': _('MetaHeuristic'), 'value': 'M'},
{'label': _('Basic'), 'value': 'B'},
{'label': _('TSA'), 'value': 'T'}],
orientation='vertical', compact=True)
self.excellon_optimization_radio = RadioSet(
[
{'label': _('Rtree'), 'value': 'R'},
{'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_radio, 0, 1)

View File

@@ -3201,6 +3201,49 @@ class CNCjob(Geometry):
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):
if zcut > 0:
self.app.inform.emit('[WARNING] %s' %
@@ -3251,12 +3294,18 @@ class CNCjob(Geometry):
# ################################## DRILLING !!! #########################################################
# #############################################################################################################
# #############################################################################################################
if not HAS_ORTOOLS:
if opt_type in ['M', 'B']:
opt_type = 'R'
if opt_type == 'M':
log.debug("Using OR-Tools Metaheuristic Guided Local Search drill path optimization.")
elif opt_type == 'B':
log.debug("Using OR-Tools Basic drill path optimization.")
elif opt_type == 'T':
log.debug("Using Travelling Salesman drill path optimization.")
elif opt_type == 'R':
log.debug("Using RTree path optimization.")
else:
log.debug("Using no path optimization.")
@@ -3367,9 +3416,6 @@ class CNCjob(Geometry):
locations = []
optimized_path = []
if not HAS_ORTOOLS:
opt_type = 'T'
if opt_type == 'M':
locations = self.create_tool_data_array(points=points)
# if there are no locations then go to the next tool
@@ -3389,6 +3435,11 @@ class CNCjob(Geometry):
if not locations:
return 'fail'
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:
# it's actually not optimized path but here we build a list of (x,y) coordinates
# out of the tool's drills
@@ -3464,6 +3515,9 @@ class CNCjob(Geometry):
if opt_type == 'T':
locx = point[0]
locy = point[1]
elif opt_type == 'R':
locx = point[0][0]
locy = point[0][1]
else:
locx = locations[point][0]
locy = locations[point][1]