@@ -56,7 +56,8 @@ namespace thor {
56
56
PathAlgorithm::PathAlgorithm ()
57
57
: edgelabel_index_(0 ),
58
58
adjacencylist_ (nullptr ),
59
- edgestatus_(nullptr ) {
59
+ edgestatus_(nullptr ),
60
+ best_destination_{kInvalidLabel , std::numeric_limits<float >::max ()}{
60
61
edgelabels_.reserve (kInitialEdgeLabelCount );
61
62
}
62
63
@@ -70,6 +71,7 @@ void PathAlgorithm::Clear() {
70
71
// Set the edge label index back to 0
71
72
edgelabel_index_ = 0 ;
72
73
edgelabels_.clear ();
74
+ best_destination_ = std::make_pair (kInvalidLabel , std::numeric_limits<float >::max ());
73
75
74
76
// Clear elements from the adjacency list
75
77
if (adjacencylist_ != nullptr ) {
@@ -123,7 +125,7 @@ std::vector<GraphId> PathAlgorithm::GetBestPath(const PathLocation& origin,
123
125
124
126
// Initialize the origin and destination locations
125
127
SetOrigin (graphreader, origin, costing, loop_edge);
126
- SetDestination (dest);
128
+ SetDestination (graphreader, dest, costing );
127
129
128
130
// Counts of transitions to upper levels (TEST - TODO better design!)
129
131
uint32_t upto1count = 0 ;
@@ -146,6 +148,10 @@ std::vector<GraphId> PathAlgorithm::GetBestPath(const PathLocation& origin,
146
148
// error codes and return the appropriate one here
147
149
next_label_index = adjacencylist_->Remove (edgelabels_);
148
150
if (next_label_index == kInvalidLabel ) {
151
+ // If we had a destination but we were waiting on other possible ones
152
+ if (best_destination_.first != kInvalidLabel )
153
+ return FormPath (best_destination_.first , graphreader, loop_edge);
154
+ // We didn't find any destination edge
149
155
LOG_ERROR (" Route failed after iterations = " + std::to_string (edgelabel_index_));
150
156
throw std::runtime_error (" No path could be found for input" );
151
157
}
@@ -156,8 +162,8 @@ std::vector<GraphId> PathAlgorithm::GetBestPath(const PathLocation& origin,
156
162
edgestatus_->Set (nextlabel.edgeid (), kPermanent );
157
163
158
164
// Check for completion. Form path and return if complete.
159
- if (IsComplete (nextlabel )) {
160
- return FormPath (next_label_index , graphreader, loop_edge);
165
+ if (IsComplete (next_label_index )) {
166
+ return FormPath (best_destination_. first , graphreader, loop_edge);
161
167
}
162
168
163
169
// TODO - do we need to terminate fruitless searches?
@@ -283,7 +289,7 @@ std::vector<GraphId> PathAlgorithm::GetBestPath(const PathLocation& origin,
283
289
}
284
290
285
291
// Add an edge at the origin to the adjacency list
286
- void PathAlgorithm::SetOrigin (baldr:: GraphReader& graphreader,
292
+ void PathAlgorithm::SetOrigin (GraphReader& graphreader,
287
293
const PathLocation& origin, const std::shared_ptr<DynamicCost>& costing, const GraphId& loop_edge_id) {
288
294
// Get sort heuristic based on distance from origin to destination
289
295
float dist = astarheuristic_.GetDistance (origin.vertex ());
@@ -328,21 +334,37 @@ void PathAlgorithm::SetOrigin(baldr::GraphReader& graphreader,
328
334
}
329
335
330
336
// Add a destination edge
331
- void PathAlgorithm::SetDestination (const PathLocation& dest) {
332
- // TODO - add partial distances
337
+ void PathAlgorithm::SetDestination (GraphReader& graphreader, const PathLocation& dest, const std::shared_ptr<DynamicCost>& costing ) {
338
+ // For each edge
333
339
for (const auto & edge : dest.edges ()) {
334
- destinations_[edge.id ] = edge.dist ;
340
+ // Keep the id and the cost to traverse the partial distance
341
+ const GraphTile* tile = graphreader.GetGraphTile (edge.id );
342
+ destinations_[edge.id ] = costing->Get (tile->directededge (edge.id )) * edge.dist ;
335
343
}
336
344
}
337
345
338
346
// Test is the shortest path has been found.
339
- bool PathAlgorithm::IsComplete (const EdgeLabel& edge_label) {
340
- // TODO - if destination is along an edge and the edge allows
341
- // travel in both directions we need to make sure both directions
342
- // are found or some further cost is encountered to rule out the
343
- // other direction
344
- const auto & p = destinations_.find (edge_label.edgeid ());
345
- return p != destinations_.end ();
347
+ bool PathAlgorithm::IsComplete (const uint32_t edge_label_index) {
348
+ // grab the label
349
+ const EdgeLabel& edge_label = edgelabels_[edge_label_index];
350
+ // if we've already found a destination and the search's current edge is more costly to get to, we are done
351
+ if (best_destination_.first != kInvalidLabel && edge_label.truecost () > best_destination_.second )
352
+ return true ;
353
+ // check if its a destination
354
+ auto p = destinations_.find (edge_label.edgeid ());
355
+ // it is indeed one of the possible destination edges
356
+ if (p != destinations_.end ()) {
357
+ // if we didnt have another destination yet or this one is better
358
+ auto cost = edge_label.truecost () + p->second ;
359
+ if (best_destination_.first == kInvalidLabel || cost < best_destination_.second ){
360
+ best_destination_.first = edge_label_index;
361
+ best_destination_.second = cost;
362
+ }
363
+ destinations_.erase (p);
364
+ // if we've found all of the destinations we are done looking
365
+ return destinations_.size () == 0 ;
366
+ }
367
+ return false ;
346
368
}
347
369
348
370
// Form the path from the adjacency list.
0 commit comments