Compare commits

..

4 Commits

Author SHA1 Message Date
Daniel Patterson 8250cd0f10 Prep alpha release for testing. 2018-09-07 04:06:32 -07:00
Daniel Patterson 631c9f2360 Remove logging. 2018-09-07 04:05:37 -07:00
Daniel Patterson d8741a39e3 Store edge distances to improve matrix distance calculation. 2018-09-07 03:23:17 -07:00
Daniel Patterson d33ff6a897 Add command-line parameter for enabling distance cache. 2018-09-05 15:25:56 -07:00
49 changed files with 702 additions and 735 deletions
-1
View File
@@ -13,7 +13,6 @@ notifications:
branches: branches:
only: only:
- master - master
- "5.19"
# enable building tags # enable building tags
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/ - /^v\d+\.\d+(\.\d+)?(-\S*)?$/
+3 -8
View File
@@ -1,16 +1,11 @@
# 5.19.0 # UNRELEASED
- Changes from 5.18.0: - Changes from 5.18.0:
- Optimizations: - Optimizations:
- CHANGED: Map matching is now almost twice as fast. [#5060](https://github.com/Project-OSRM/osrm-backend/pull/5060)
- CHANGED: Use Grisu2 for serializing floating point numbers. [#5188](https://github.com/Project-OSRM/osrm-backend/pull/5188) - CHANGED: Use Grisu2 for serializing floating point numbers. [#5188](https://github.com/Project-OSRM/osrm-backend/pull/5188)
- ADDED: Node bindings can return pre-rendered JSON buffer. [#5189](https://github.com/Project-OSRM/osrm-backend/pull/5189)
- Profiles:
- CHANGED: Bicycle profile now blacklists barriers instead of whitelisting them [#5076
](https://github.com/Project-OSRM/osrm-backend/pull/5076/)
- CHANGED: Foot profile now blacklists barriers instead of whitelisting them [#5077
](https://github.com/Project-OSRM/osrm-backend/pull/5077/)
- CHANGED: Support maxlength and maxweight in car profile [#5101](https://github.com/Project-OSRM/osrm-backend/pull/5101]
- Bugfixes: - Bugfixes:
- FIXED: collapsing of ExitRoundabout instructions [#5114](https://github.com/Project-OSRM/osrm-backend/issues/5114) - FIXED: collapsing of ExitRoundabout instructions [#5114](https://github.com/Project-OSRM/osrm-backend/issues/5114)
- FIXED: negative distances in table plugin annotation [#5106](https://github.com/Project-OSRM/osrm-backend/issues/5106)
- Misc: - Misc:
- CHANGED: Support up to 512 named shared memory regions [#5185](https://github.com/Project-OSRM/osrm-backend/pull/5185) - CHANGED: Support up to 512 named shared memory regions [#5185](https://github.com/Project-OSRM/osrm-backend/pull/5185)
-23
View File
@@ -297,29 +297,6 @@ Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer
2) `waypoint_index`: index of the point in the trip. 2) `waypoint_index`: index of the point in the trip.
**`trips`**: an array of [`Route`](#route) objects that assemble the trace. **`trips`**: an array of [`Route`](#route) objects that assemble the trace.
## Plugin behaviour
All plugins support a second additional object that is available to configure some NodeJS specific behaviours.
- `plugin_config` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
- `plugin_config.format` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The format of the result object to various API calls. Valid options are `object` (default), which returns a standard Javascript object, as described above, and `json_buffer`, which will return a NodeJS **[Buffer](https://nodejs.org/api/buffer.html)** object, containing a JSON string. The latter has the advantage that it can be immediately serialized to disk/sent over the network, and the generation of the string is performed outside the main NodeJS event loop. This option is ignored by the `tile` plugin.
**Examples**
```javascript
var osrm = new OSRM('network.osrm');
var options = {
coordinates: [
[13.36761474609375, 52.51663871100423],
[13.374481201171875, 52.506191342034576]
]
};
osrm.route(options, { format: "json_buffer" }, function(err, response) {
if (err) throw err;
console.log(response.toString("utf-8"));
});
```
## Responses ## Responses
Responses Responses
+1 -1
View File
@@ -792,4 +792,4 @@ Feature: Basic Map Matching
When I match I should get When I match I should get
| trace | geometry | a:distance | a:duration | a:weight | duration | | trace | geometry | a:distance | a:duration | a:weight | duration |
| 2345 | 1.00018,1,1.000315,1 | 15.013264 | 1.5 | 1.5 | 1.5 | | 2345 | 1.00018,1,1.000315,1 | 15.013264 | 1.5 | 1.5 | 1.5 |
| 4321 | 1.00027,1,1.000135,1 | 15.013264 | 1.5 | 1.5 | 1.5 | | 4321 | 1.00027,1,1.000135,1 | 15.013264 | 1.5 | 1.5 | 1.5 |
+8 -2
View File
@@ -72,8 +72,14 @@ struct ContractorConfig final : storage::IOConfig
// The remaining vertices form the core of the hierarchy // The remaining vertices form the core of the hierarchy
//(e.g. 0.8 contracts 80 percent of the hierarchy, leaving a core of 20%) //(e.g. 0.8 contracts 80 percent of the hierarchy, leaving a core of 20%)
double core_factor; double core_factor;
// Whether to store distances for CH edges in addition to duration/weight
// Defaults to false. Setting to true will require more storage/memory,
// but avoids the need for path unpacking to learn the distance of a CH
// route (useful for faster distance results in table queries)
bool cache_distances;
}; };
} } // namespace contractor
} } // namespace osrm
#endif // EXTRACTOR_OPTIONS_HPP #endif // EXTRACTOR_OPTIONS_HPP
+5 -2
View File
@@ -12,23 +12,26 @@ namespace contractor
struct ContractorEdgeData struct ContractorEdgeData
{ {
ContractorEdgeData() ContractorEdgeData()
: weight(0), duration(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0) : weight(0), duration(0), distance(0), id(0), originalEdges(0), shortcut(0), forward(0),
backward(0)
{ {
} }
ContractorEdgeData(EdgeWeight weight, ContractorEdgeData(EdgeWeight weight,
EdgeWeight duration, EdgeWeight duration,
EdgeDistance distance,
unsigned original_edges, unsigned original_edges,
unsigned id, unsigned id,
bool shortcut, bool shortcut,
bool forward, bool forward,
bool backward) bool backward)
: weight(weight), duration(duration), id(id), : weight(weight), duration(duration), distance(distance), id(id),
originalEdges(std::min((1u << 29) - 1u, original_edges)), shortcut(shortcut), originalEdges(std::min((1u << 29) - 1u, original_edges)), shortcut(shortcut),
forward(forward), backward(backward) forward(forward), backward(backward)
{ {
} }
EdgeWeight weight; EdgeWeight weight;
EdgeWeight duration; EdgeWeight duration;
EdgeDistance distance;
unsigned id; unsigned id;
unsigned originalEdges : 29; unsigned originalEdges : 29;
bool shortcut : 1; bool shortcut : 1;
@@ -41,6 +41,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
input_edge.target, input_edge.target,
std::max(input_edge.data.weight, 1), std::max(input_edge.data.weight, 1),
input_edge.data.duration, input_edge.data.duration,
input_edge.data.distance,
1, 1,
input_edge.data.turn_id, input_edge.data.turn_id,
false, false,
@@ -51,6 +52,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
input_edge.source, input_edge.source,
std::max(input_edge.data.weight, 1), std::max(input_edge.data.weight, 1),
input_edge.data.duration, input_edge.data.duration,
input_edge.data.distance,
1, 1,
input_edge.data.turn_id, input_edge.data.turn_id,
false, false,
@@ -82,6 +84,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1; forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT; forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION; forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION;
forward_edge.data.distance = reverse_edge.data.distance = MAXIMAL_EDGE_DISTANCE;
// remove parallel edges // remove parallel edges
while (i < edges.size() && edges[i].source == source && edges[i].target == target) while (i < edges.size() && edges[i].source == source && edges[i].target == target)
{ {
@@ -90,12 +93,16 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight); forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight);
forward_edge.data.duration = forward_edge.data.duration =
std::min(edges[i].data.duration, forward_edge.data.duration); std::min(edges[i].data.duration, forward_edge.data.duration);
forward_edge.data.distance =
std::min(edges[i].data.distance, forward_edge.data.distance);
} }
if (edges[i].data.backward) if (edges[i].data.backward)
{ {
reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight); reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight);
reverse_edge.data.duration = reverse_edge.data.duration =
std::min(edges[i].data.duration, reverse_edge.data.duration); std::min(edges[i].data.duration, reverse_edge.data.duration);
reverse_edge.data.distance =
std::min(edges[i].data.distance, reverse_edge.data.distance);
} }
++i; ++i;
} }
@@ -151,6 +158,7 @@ template <class Edge, typename GraphT> inline std::vector<Edge> toEdges(GraphT g
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid"); BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
new_edge.data.weight = data.weight; new_edge.data.weight = data.weight;
new_edge.data.duration = data.duration; new_edge.data.duration = data.duration;
new_edge.data.distance = data.distance;
new_edge.data.shortcut = data.shortcut; new_edge.data.shortcut = data.shortcut;
new_edge.data.turn_id = data.id; new_edge.data.turn_id = data.id;
BOOST_ASSERT_MSG(new_edge.data.turn_id != INT_MAX, // 2^31 BOOST_ASSERT_MSG(new_edge.data.turn_id != INT_MAX, // 2^31
+10 -5
View File
@@ -17,7 +17,8 @@ struct QueryEdge
struct EdgeData struct EdgeData
{ {
explicit EdgeData() explicit EdgeData()
: turn_id(0), shortcut(false), weight(0), duration(0), forward(false), backward(false) : turn_id(0), shortcut(false), weight(0), duration(0), forward(false), backward(false),
distance(0)
{ {
} }
@@ -25,10 +26,11 @@ struct QueryEdge
const bool shortcut, const bool shortcut,
const EdgeWeight weight, const EdgeWeight weight,
const EdgeWeight duration, const EdgeWeight duration,
const EdgeDistance distance,
const bool forward, const bool forward,
const bool backward) const bool backward)
: turn_id(turn_id), shortcut(shortcut), weight(weight), duration(duration), : turn_id(turn_id), shortcut(shortcut), weight(weight), duration(duration),
forward(forward), backward(backward) forward(forward), backward(backward), distance(distance)
{ {
} }
@@ -40,6 +42,7 @@ struct QueryEdge
turn_id = other.id; turn_id = other.id;
forward = other.forward; forward = other.forward;
backward = other.backward; backward = other.backward;
distance = other.distance;
} }
// this ID is either the middle node of the shortcut, or the ID of the edge based node (node // this ID is either the middle node of the shortcut, or the ID of the edge based node (node
// based edge) storing the appropriate data. If `shortcut` is set to true, we get the middle // based edge) storing the appropriate data. If `shortcut` is set to true, we get the middle
@@ -50,6 +53,7 @@ struct QueryEdge
EdgeWeight duration : 30; EdgeWeight duration : 30;
std::uint32_t forward : 1; std::uint32_t forward : 1;
std::uint32_t backward : 1; std::uint32_t backward : 1;
EdgeDistance distance;
} data; } data;
QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {} QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {}
@@ -69,10 +73,11 @@ struct QueryEdge
return (source == right.source && target == right.target && return (source == right.source && target == right.target &&
data.weight == right.data.weight && data.duration == right.data.duration && data.weight == right.data.weight && data.duration == right.data.duration &&
data.shortcut == right.data.shortcut && data.forward == right.data.forward && data.shortcut == right.data.shortcut && data.forward == right.data.forward &&
data.backward == right.data.backward && data.turn_id == right.data.turn_id); data.backward == right.data.backward && data.turn_id == right.data.turn_id &&
data.distance == right.data.distance);
} }
}; };
} } // namespace contractor
} } // namespace osrm
#endif // QUERYEDGE_HPP #endif // QUERYEDGE_HPP
+13 -14
View File
@@ -449,6 +449,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
const auto reverse_durations = datafacade.GetUncompressedReverseDurations(geometry_id); const auto reverse_durations = datafacade.GetUncompressedReverseDurations(geometry_id);
const auto forward_geometry = datafacade.GetUncompressedForwardGeometry(geometry_id); const auto forward_geometry = datafacade.GetUncompressedForwardGeometry(geometry_id);
const auto reverse_geometry = datafacade.GetUncompressedReverseGeometry(geometry_id);
const auto forward_weight_offset = const auto forward_weight_offset =
std::accumulate(forward_weights.begin(), std::accumulate(forward_weights.begin(),
@@ -479,19 +480,19 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position)), datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position)),
point_on_segment); point_on_segment);
const auto reverse_weight_offset = const auto rev_segment_position = reverse_weights.size() - data.fwd_segment_position - 1;
std::accumulate(reverse_weights.begin(),
reverse_weights.end() - data.fwd_segment_position - 1, const auto reverse_weight_offset = std::accumulate(
EdgeWeight{0}); reverse_weights.begin(), reverse_weights.begin() + rev_segment_position, EdgeWeight{0});
const auto reverse_duration_offset = const auto reverse_duration_offset =
std::accumulate(reverse_durations.begin(), std::accumulate(reverse_durations.begin(),
reverse_durations.end() - data.fwd_segment_position - 1, reverse_durations.begin() + rev_segment_position,
EdgeDuration{0}); EdgeDuration{0});
EdgeDistance reverse_distance_offset = 0; EdgeDistance reverse_distance_offset = 0;
for (auto current = forward_geometry.begin(); for (auto current = reverse_geometry.begin();
current < forward_geometry.end() - data.fwd_segment_position - 2; current < reverse_geometry.begin() + rev_segment_position;
++current) ++current)
{ {
reverse_distance_offset += util::coordinate_calculation::fccApproximateDistance( reverse_distance_offset += util::coordinate_calculation::fccApproximateDistance(
@@ -499,13 +500,11 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
datafacade.GetCoordinateOfNode(*std::next(current))); datafacade.GetCoordinateOfNode(*std::next(current)));
} }
EdgeWeight reverse_weight = EdgeWeight reverse_weight = reverse_weights[rev_segment_position];
reverse_weights[reverse_weights.size() - data.fwd_segment_position - 1]; EdgeDuration reverse_duration = reverse_durations[rev_segment_position];
EdgeDuration reverse_duration =
reverse_durations[reverse_durations.size() - data.fwd_segment_position - 1];
EdgeDistance reverse_distance = util::coordinate_calculation::fccApproximateDistance( EdgeDistance reverse_distance = util::coordinate_calculation::fccApproximateDistance(
point_on_segment, point_on_segment,
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position + 1))); datafacade.GetCoordinateOfNode(reverse_geometry(rev_segment_position)));
ratio = std::min(1.0, std::max(0.0, ratio)); ratio = std::min(1.0, std::max(0.0, ratio));
if (data.forward_segment_id.id != SPECIAL_SEGMENTID) if (data.forward_segment_id.id != SPECIAL_SEGMENTID)
@@ -693,7 +692,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
const CoordinateList &coordinates; const CoordinateList &coordinates;
DataFacadeT &datafacade; DataFacadeT &datafacade;
}; };
} } // namespace engine
} } // namespace osrm
#endif #endif
+13 -9
View File
@@ -34,6 +34,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "util/coordinate.hpp" #include "util/coordinate.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <iostream>
#include <boost/assert.hpp> #include <boost/assert.hpp>
namespace osrm namespace osrm
@@ -44,14 +46,15 @@ namespace engine
struct PhantomNode struct PhantomNode
{ {
PhantomNode() PhantomNode()
: forward_segment_id{SPECIAL_SEGMENTID, false}, : forward_segment_id{SPECIAL_SEGMENTID, false}, reverse_segment_id{SPECIAL_SEGMENTID,
reverse_segment_id{SPECIAL_SEGMENTID, false}, forward_weight(INVALID_EDGE_WEIGHT), false},
reverse_weight(INVALID_EDGE_WEIGHT), forward_weight_offset(0), reverse_weight_offset(0), forward_weight(INVALID_EDGE_WEIGHT), reverse_weight(INVALID_EDGE_WEIGHT),
forward_weight_offset(0), reverse_weight_offset(0),
forward_distance(INVALID_EDGE_DISTANCE), reverse_distance(INVALID_EDGE_DISTANCE), forward_distance(INVALID_EDGE_DISTANCE), reverse_distance(INVALID_EDGE_DISTANCE),
forward_distance_offset(0), reverse_distance_offset(0), forward_distance_offset(0), reverse_distance_offset(0),
forward_duration(MAXIMAL_EDGE_DURATION), reverse_duration(MAXIMAL_EDGE_DURATION), forward_duration(MAXIMAL_EDGE_DURATION), reverse_duration(MAXIMAL_EDGE_DURATION),
forward_duration_offset(0), reverse_duration_offset(0), fwd_segment_position(0), forward_duration_offset(0), reverse_duration_offset(0),
is_valid_forward_source{false}, is_valid_forward_target{false}, fwd_segment_position(0), is_valid_forward_source{false}, is_valid_forward_target{false},
is_valid_reverse_source{false}, is_valid_reverse_target{false}, bearing(0) is_valid_reverse_source{false}, is_valid_reverse_target{false}, bearing(0)
{ {
@@ -109,8 +112,9 @@ struct PhantomNode
bool IsValid(const unsigned number_of_nodes) const bool IsValid(const unsigned number_of_nodes) const
{ {
return location.IsValid() && ((forward_segment_id.id < number_of_nodes) || return location.IsValid() &&
(reverse_segment_id.id < number_of_nodes)) && ((forward_segment_id.id < number_of_nodes) ||
(reverse_segment_id.id < number_of_nodes)) &&
((forward_weight != INVALID_EDGE_WEIGHT) || ((forward_weight != INVALID_EDGE_WEIGHT) ||
(reverse_weight != INVALID_EDGE_WEIGHT)) && (reverse_weight != INVALID_EDGE_WEIGHT)) &&
((forward_duration != MAXIMAL_EDGE_DURATION) || ((forward_duration != MAXIMAL_EDGE_DURATION) ||
@@ -234,7 +238,7 @@ struct PhantomNodes
PhantomNode source_phantom; PhantomNode source_phantom;
PhantomNode target_phantom; PhantomNode target_phantom;
}; };
} } // namespace engine
} } // namespace osrm
#endif // PHANTOM_NODES_H #endif // PHANTOM_NODES_H
@@ -25,15 +25,17 @@ struct NodeBucket
unsigned from_clique_arc : 1; unsigned from_clique_arc : 1;
EdgeWeight weight; EdgeWeight weight;
EdgeDuration duration; EdgeDuration duration;
EdgeDistance distance;
NodeBucket(NodeID middle_node, NodeBucket(NodeID middle_node,
NodeID parent_node, NodeID parent_node,
bool from_clique_arc, bool from_clique_arc,
unsigned column_index, unsigned column_index,
EdgeWeight weight, EdgeWeight weight,
EdgeDuration duration) EdgeDuration duration,
EdgeDistance distance)
: middle_node(middle_node), parent_node(parent_node), column_index(column_index), : middle_node(middle_node), parent_node(parent_node), column_index(column_index),
from_clique_arc(from_clique_arc), weight(weight), duration(duration) from_clique_arc(from_clique_arc), weight(weight), duration(duration), distance(distance)
{ {
} }
@@ -41,9 +43,10 @@ struct NodeBucket
NodeID parent_node, NodeID parent_node,
unsigned column_index, unsigned column_index,
EdgeWeight weight, EdgeWeight weight,
EdgeDuration duration) EdgeDuration duration,
EdgeDistance distance)
: middle_node(middle_node), parent_node(parent_node), column_index(column_index), : middle_node(middle_node), parent_node(parent_node), column_index(column_index),
from_clique_arc(false), weight(weight), duration(duration) from_clique_arc(false), weight(weight), duration(duration), distance(distance)
{ {
} }
@@ -44,42 +44,140 @@ bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &ta
bool needsLoopForward(const PhantomNodes &phantoms); bool needsLoopForward(const PhantomNodes &phantoms);
bool needsLoopBackwards(const PhantomNodes &phantoms); bool needsLoopBackwards(const PhantomNodes &phantoms);
template <typename Heap> namespace detail
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
{ {
const auto &source = nodes.source_phantom; template <typename Algorithm>
if (source.IsValidForwardSource()) void insertSourceInHeap(typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &heap,
const PhantomNode &phantom_node)
{
if (phantom_node.IsValidForwardTarget())
{ {
forward_heap.Insert(source.forward_segment_id.id, heap.Insert(phantom_node.forward_segment_id.id,
-source.GetForwardWeightPlusOffset(), -phantom_node.GetForwardWeightPlusOffset(),
source.forward_segment_id.id); {phantom_node.forward_segment_id.id,
-phantom_node.GetForwardDuration(),
-phantom_node.GetForwardDistance()});
} }
if (phantom_node.IsValidReverseTarget())
if (source.IsValidReverseSource())
{ {
forward_heap.Insert(source.reverse_segment_id.id, heap.Insert(phantom_node.reverse_segment_id.id,
-source.GetReverseWeightPlusOffset(), -phantom_node.GetReverseWeightPlusOffset(),
source.reverse_segment_id.id); {phantom_node.reverse_segment_id.id,
} -phantom_node.GetReverseDuration(),
-phantom_node.GetReverseDistance()});
const auto &target = nodes.target_phantom;
if (target.IsValidForwardTarget())
{
reverse_heap.Insert(target.forward_segment_id.id,
target.GetForwardWeightPlusOffset(),
target.forward_segment_id.id);
}
if (target.IsValidReverseTarget())
{
reverse_heap.Insert(target.reverse_segment_id.id,
target.GetReverseWeightPlusOffset(),
target.reverse_segment_id.id);
} }
} }
template <typename ManyToManyQueryHeap> template <typename Algorithm>
void insertSourceInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_node) void insertTargetInHeap(typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &heap,
const PhantomNode &phantom_node)
{
if (phantom_node.IsValidForwardTarget())
{
heap.Insert(phantom_node.forward_segment_id.id,
phantom_node.GetForwardWeightPlusOffset(),
{phantom_node.forward_segment_id.id,
phantom_node.GetForwardDuration(),
phantom_node.GetForwardDistance()});
}
if (phantom_node.IsValidReverseTarget())
{
heap.Insert(phantom_node.reverse_segment_id.id,
phantom_node.GetReverseWeightPlusOffset(),
{phantom_node.reverse_segment_id.id,
phantom_node.GetReverseDuration(),
phantom_node.GetReverseDistance()});
}
}
template <typename Algorithm>
void insertSourceInHeap(typename SearchEngineData<Algorithm>::QueryHeap &heap,
const PhantomNode &phantom_node)
{
if (phantom_node.IsValidForwardSource())
{
heap.Insert(phantom_node.forward_segment_id.id,
-phantom_node.GetForwardWeightPlusOffset(),
phantom_node.forward_segment_id.id);
}
if (phantom_node.IsValidReverseSource())
{
heap.Insert(phantom_node.reverse_segment_id.id,
-phantom_node.GetReverseWeightPlusOffset(),
phantom_node.reverse_segment_id.id);
}
}
template <typename Algorithm>
void insertTargetInHeap(typename SearchEngineData<Algorithm>::QueryHeap &heap,
const PhantomNode &phantom_node)
{
if (phantom_node.IsValidForwardTarget())
{
heap.Insert(phantom_node.forward_segment_id.id,
phantom_node.GetForwardWeightPlusOffset(),
phantom_node.forward_segment_id.id);
}
if (phantom_node.IsValidReverseTarget())
{
heap.Insert(phantom_node.reverse_segment_id.id,
phantom_node.GetReverseWeightPlusOffset(),
phantom_node.reverse_segment_id.id);
}
}
} // namespace detail
inline void insertTargetInHeap(typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &heap,
const PhantomNode &phantom_node)
{
detail::insertTargetInHeap<mld::Algorithm>(heap, phantom_node);
}
inline void insertTargetInHeap(typename SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
const PhantomNode &phantom_node)
{
detail::insertTargetInHeap<ch::Algorithm>(heap, phantom_node);
}
inline void insertTargetInHeap(typename SearchEngineData<mld::Algorithm>::QueryHeap &heap,
const PhantomNode &phantom_node)
{
detail::insertTargetInHeap<mld::Algorithm>(heap, phantom_node);
}
inline void insertTargetInHeap(typename SearchEngineData<ch::Algorithm>::QueryHeap &heap,
const PhantomNode &phantom_node)
{
detail::insertTargetInHeap<ch::Algorithm>(heap, phantom_node);
}
inline void insertSourceInHeap(typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &heap,
const PhantomNode &phantom_node)
{
detail::insertSourceInHeap<mld::Algorithm>(heap, phantom_node);
}
inline void insertSourceInHeap(typename SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
const PhantomNode &phantom_node)
{
detail::insertSourceInHeap<ch::Algorithm>(heap, phantom_node);
}
inline void insertSourceInHeap(typename SearchEngineData<mld::Algorithm>::QueryHeap &heap,
const PhantomNode &phantom_node)
{
detail::insertSourceInHeap<mld::Algorithm>(heap, phantom_node);
}
inline void insertSourceInHeap(typename SearchEngineData<ch::Algorithm>::QueryHeap &heap,
const PhantomNode &phantom_node)
{
detail::insertSourceInHeap<ch::Algorithm>(heap, phantom_node);
}
template <typename Heap>
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
{
insertSourceInHeap(forward_heap, nodes.source_phantom);
insertTargetInHeap(reverse_heap, nodes.target_phantom);
}
template <typename Algorithm>
void insertSourceInHeap(typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &heap,
const PhantomNode &phantom_node)
{ {
if (phantom_node.IsValidForwardSource()) if (phantom_node.IsValidForwardSource())
{ {
@@ -95,23 +193,6 @@ void insertSourceInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_no
} }
} }
template <typename ManyToManyQueryHeap>
void insertTargetInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_node)
{
if (phantom_node.IsValidForwardTarget())
{
heap.Insert(phantom_node.forward_segment_id.id,
phantom_node.GetForwardWeightPlusOffset(),
{phantom_node.forward_segment_id.id, phantom_node.GetForwardDuration()});
}
if (phantom_node.IsValidReverseTarget())
{
heap.Insert(phantom_node.reverse_segment_id.id,
phantom_node.GetReverseWeightPlusOffset(),
{phantom_node.reverse_segment_id.id, phantom_node.GetReverseDuration()});
}
}
template <typename FacadeT> template <typename FacadeT>
void annotatePath(const FacadeT &facade, void annotatePath(const FacadeT &facade,
const PhantomNodes &phantom_node_pair, const PhantomNodes &phantom_node_pair,
@@ -321,58 +402,10 @@ void annotatePath(const FacadeT &facade,
} }
} }
template <typename Algorithm> EdgeDistance adjustPathDistanceToPhantomNodes(const std::vector<NodeID> &path,
double getPathDistance(const DataFacade<Algorithm> &facade, const PhantomNode &source_phantom,
const std::vector<PathData> unpacked_path, const PhantomNode &target_phantom,
const PhantomNode &source_phantom, const EdgeDistance distance);
const PhantomNode &target_phantom)
{
using util::coordinate_calculation::detail::DEGREE_TO_RAD;
using util::coordinate_calculation::detail::EARTH_RADIUS;
double distance = 0;
double prev_lat =
static_cast<double>(util::toFloating(source_phantom.location.lat)) * DEGREE_TO_RAD;
double prev_lon =
static_cast<double>(util::toFloating(source_phantom.location.lon)) * DEGREE_TO_RAD;
double prev_cos = std::cos(prev_lat);
for (const auto &p : unpacked_path)
{
const auto current_coordinate = facade.GetCoordinateOfNode(p.turn_via_node);
const double current_lat =
static_cast<double>(util::toFloating(current_coordinate.lat)) * DEGREE_TO_RAD;
const double current_lon =
static_cast<double>(util::toFloating(current_coordinate.lon)) * DEGREE_TO_RAD;
const double current_cos = std::cos(current_lat);
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
distance += EARTH_RADIUS * charv;
prev_lat = current_lat;
prev_lon = current_lon;
prev_cos = current_cos;
}
const double current_lat =
static_cast<double>(util::toFloating(target_phantom.location.lat)) * DEGREE_TO_RAD;
const double current_lon =
static_cast<double>(util::toFloating(target_phantom.location.lon)) * DEGREE_TO_RAD;
const double current_cos = std::cos(current_lat);
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
distance += EARTH_RADIUS * charv;
return distance;
}
template <typename AlgorithmT> template <typename AlgorithmT>
InternalRouteResult extractRoute(const DataFacade<AlgorithmT> &facade, InternalRouteResult extractRoute(const DataFacade<AlgorithmT> &facade,
@@ -186,9 +186,10 @@ void routingStep(const DataFacade<Algorithm> &facade,
} }
template <bool UseDuration> template <bool UseDuration>
EdgeWeight getLoopWeight(const DataFacade<Algorithm> &facade, NodeID node) std::tuple<EdgeWeight,EdgeDistance> getLoopWeight(const DataFacade<Algorithm> &facade, NodeID node)
{ {
EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT; EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT;
EdgeDistance loop_distance = MAXIMAL_EDGE_DISTANCE;
for (auto edge : facade.GetAdjacentEdgeRange(node)) for (auto edge : facade.GetAdjacentEdgeRange(node))
{ {
const auto &data = facade.GetEdgeData(edge); const auto &data = facade.GetEdgeData(edge);
@@ -198,11 +199,15 @@ EdgeWeight getLoopWeight(const DataFacade<Algorithm> &facade, NodeID node)
if (to == node) if (to == node)
{ {
const auto value = UseDuration ? data.duration : data.weight; const auto value = UseDuration ? data.duration : data.weight;
loop_weight = std::min(loop_weight, value); if (value < loop_weight)
{
loop_weight = value;
loop_distance = data.distance;
}
} }
} }
} }
return loop_weight; return std::make_tuple(loop_weight, loop_distance);
} }
/** /**
@@ -97,7 +97,6 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
const std::vector<std::size_t> &phantom_indices) const std::vector<std::size_t> &phantom_indices)
{ {
auto min_level = [&partition, node](const PhantomNode &phantom_node) { auto min_level = [&partition, node](const PhantomNode &phantom_node) {
const auto &forward_segment = phantom_node.forward_segment_id; const auto &forward_segment = phantom_node.forward_segment_id;
const auto forward_level = const auto forward_level =
forward_segment.enabled ? partition.GetHighestDifferentLevel(node, forward_segment.id) forward_segment.enabled ? partition.GetHighestDifferentLevel(node, forward_segment.id)
@@ -120,7 +119,7 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
} }
return result; return result;
} }
} } // namespace
// Heaps only record for each node its predecessor ("parent") on the shortest path. // Heaps only record for each node its predecessor ("parent") on the shortest path.
// For re-constructing the actual path we need to trace back all parent "pointers". // For re-constructing the actual path we need to trace back all parent "pointers".
@@ -391,21 +390,27 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
EdgeWeight weight_upper_bound, EdgeWeight weight_upper_bound,
Args... args) Args... args)
{ {
if (forward_heap.Empty() || reverse_heap.Empty()) if (forward_heap.Empty() && reverse_heap.Empty())
{ {
return std::make_tuple(INVALID_EDGE_WEIGHT, std::vector<NodeID>(), std::vector<EdgeID>()); return std::make_tuple(INVALID_EDGE_WEIGHT, std::vector<NodeID>(), std::vector<EdgeID>());
} }
const auto &partition = facade.GetMultiLevelPartition(); const auto &partition = facade.GetMultiLevelPartition();
BOOST_ASSERT(!forward_heap.Empty() && forward_heap.MinKey() < INVALID_EDGE_WEIGHT); BOOST_ASSERT(forward_heap.Empty() || forward_heap.MinKey() < INVALID_EDGE_WEIGHT);
BOOST_ASSERT(!reverse_heap.Empty() && reverse_heap.MinKey() < INVALID_EDGE_WEIGHT); BOOST_ASSERT(reverse_heap.Empty() || reverse_heap.MinKey() < INVALID_EDGE_WEIGHT);
// run two-Target Dijkstra routing step. // run two-Target Dijkstra routing step.
NodeID middle = SPECIAL_NODEID; NodeID middle = SPECIAL_NODEID;
EdgeWeight weight = weight_upper_bound; EdgeWeight weight = weight_upper_bound;
EdgeWeight forward_heap_min = forward_heap.MinKey();
EdgeWeight reverse_heap_min = reverse_heap.MinKey(); EdgeWeight forward_heap_min = 0;
if (!forward_heap.Empty())
forward_heap_min = forward_heap.MinKey();
EdgeWeight reverse_heap_min = 0;
if (!reverse_heap.Empty())
reverse_heap_min = reverse_heap.MinKey();
while (forward_heap.Size() + reverse_heap.Size() > 0 && while (forward_heap.Size() + reverse_heap.Size() > 0 &&
forward_heap_min + reverse_heap_min < weight) forward_heap_min + reverse_heap_min < weight)
{ {
@@ -657,11 +662,7 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
const PhantomNode &target_phantom, const PhantomNode &target_phantom,
EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT) EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
{ {
forward_heap.Clear();
reverse_heap.Clear();
const PhantomNodes phantom_nodes{source_phantom, target_phantom}; const PhantomNodes phantom_nodes{source_phantom, target_phantom};
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
EdgeWeight weight = INVALID_EDGE_WEIGHT; EdgeWeight weight = INVALID_EDGE_WEIGHT;
std::vector<NodeID> unpacked_nodes; std::vector<NodeID> unpacked_nodes;
@@ -680,11 +681,22 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
return std::numeric_limits<double>::max(); return std::numeric_limits<double>::max();
} }
std::vector<PathData> unpacked_path; EdgeDistance distance = 0;
annotatePath(facade, phantom_nodes, unpacked_nodes, unpacked_edges, unpacked_path); if (!unpacked_nodes.empty())
{
distance = std::accumulate(unpacked_nodes.begin(),
std::prev(unpacked_nodes.end()),
EdgeDistance{0},
[&](const EdgeDistance distance, const auto node_id) {
return distance + computeEdgeDistance(facade, node_id);
});
}
return getPathDistance(facade, unpacked_path, source_phantom, target_phantom); distance = adjustPathDistanceToPhantomNodes(
unpacked_nodes, phantom_nodes.source_phantom, phantom_nodes.target_phantom, distance);
return distance;
} }
} // namespace mld } // namespace mld
+15 -7
View File
@@ -30,7 +30,11 @@ struct HeapData
struct ManyToManyHeapData : HeapData struct ManyToManyHeapData : HeapData
{ {
EdgeWeight duration; EdgeWeight duration;
ManyToManyHeapData(NodeID p, EdgeWeight duration) : HeapData(p), duration(duration) {} EdgeDistance distance;
ManyToManyHeapData(NodeID p, EdgeWeight duration, EdgeDistance distance)
: HeapData(p), duration(duration), distance(distance)
{
}
}; };
template <> struct SearchEngineData<routing_algorithms::ch::Algorithm> template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
@@ -75,12 +79,16 @@ struct MultiLayerDijkstraHeapData
struct ManyToManyMultiLayerDijkstraHeapData : MultiLayerDijkstraHeapData struct ManyToManyMultiLayerDijkstraHeapData : MultiLayerDijkstraHeapData
{ {
EdgeWeight duration; EdgeWeight duration;
ManyToManyMultiLayerDijkstraHeapData(NodeID p, EdgeWeight duration) EdgeDistance distance;
: MultiLayerDijkstraHeapData(p), duration(duration) ManyToManyMultiLayerDijkstraHeapData(NodeID p, EdgeWeight duration, EdgeDistance distance)
: MultiLayerDijkstraHeapData(p), duration(duration), distance(distance)
{ {
} }
ManyToManyMultiLayerDijkstraHeapData(NodeID p, bool from, EdgeWeight duration) ManyToManyMultiLayerDijkstraHeapData(NodeID p,
: MultiLayerDijkstraHeapData(p, from), duration(duration) bool from,
EdgeWeight duration,
EdgeDistance distance)
: MultiLayerDijkstraHeapData(p, from), duration(duration), distance(distance)
{ {
} }
}; };
@@ -112,7 +120,7 @@ template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes, void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes,
unsigned number_of_boundary_nodes); unsigned number_of_boundary_nodes);
}; };
} } // namespace engine
} } // namespace osrm
#endif // SEARCH_ENGINE_DATA_HPP #endif // SEARCH_ENGINE_DATA_HPP
@@ -82,7 +82,7 @@ class CompressedEdgeContainer
std::unordered_map<EdgeID, unsigned> m_reverse_edge_id_to_zipped_index_map; std::unordered_map<EdgeID, unsigned> m_reverse_edge_id_to_zipped_index_map;
std::unique_ptr<SegmentDataContainer> segment_data; std::unique_ptr<SegmentDataContainer> segment_data;
}; };
} } // namespace extractor
} } // namespace osrm
#endif // GEOMETRY_COMPRESSOR_HPP_ #endif // GEOMETRY_COMPRESSOR_HPP_
+14 -7
View File
@@ -15,20 +15,25 @@ struct EdgeBasedEdge
public: public:
struct EdgeData struct EdgeData
{ {
EdgeData() : turn_id(0), weight(0), duration(0), forward(false), backward(false) {} EdgeData()
: turn_id(0), weight(0), distance(0), duration(0), forward(false), backward(false)
{
}
EdgeData(const NodeID turn_id, EdgeData(const NodeID turn_id,
const EdgeWeight weight, const EdgeWeight weight,
const EdgeDistance distance,
const EdgeWeight duration, const EdgeWeight duration,
const bool forward, const bool forward,
const bool backward) const bool backward)
: turn_id(turn_id), weight(weight), duration(duration), forward(forward), : turn_id(turn_id), weight(weight), distance(distance), duration(duration),
backward(backward) forward(forward), backward(backward)
{ {
} }
NodeID turn_id; // ID of the edge based node (node based edge) NodeID turn_id; // ID of the edge based node (node based edge)
EdgeWeight weight; EdgeWeight weight;
EdgeDistance distance;
EdgeWeight duration : 30; EdgeWeight duration : 30;
std::uint32_t forward : 1; std::uint32_t forward : 1;
std::uint32_t backward : 1; std::uint32_t backward : 1;
@@ -43,6 +48,7 @@ struct EdgeBasedEdge
const NodeID edge_id, const NodeID edge_id,
const EdgeWeight weight, const EdgeWeight weight,
const EdgeWeight duration, const EdgeWeight duration,
const EdgeDistance distance,
const bool forward, const bool forward,
const bool backward); const bool backward);
EdgeBasedEdge(const NodeID source, const NodeID target, const EdgeBasedEdge::EdgeData &data); EdgeBasedEdge(const NodeID source, const NodeID target, const EdgeBasedEdge::EdgeData &data);
@@ -53,7 +59,7 @@ struct EdgeBasedEdge
NodeID target; NodeID target;
EdgeData data; EdgeData data;
}; };
static_assert(sizeof(extractor::EdgeBasedEdge) == 20, static_assert(sizeof(extractor::EdgeBasedEdge) == 24,
"Size of extractor::EdgeBasedEdge type is " "Size of extractor::EdgeBasedEdge type is "
"bigger than expected. This will influence " "bigger than expected. This will influence "
"memory consumption."); "memory consumption.");
@@ -67,9 +73,10 @@ inline EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
const NodeID turn_id, const NodeID turn_id,
const EdgeWeight weight, const EdgeWeight weight,
const EdgeWeight duration, const EdgeWeight duration,
const EdgeDistance distance,
const bool forward, const bool forward,
const bool backward) const bool backward)
: source(source), target(target), data{turn_id, weight, duration, forward, backward} : source(source), target(target), data{turn_id, weight, distance, duration, forward, backward}
{ {
} }
@@ -89,7 +96,7 @@ inline bool EdgeBasedEdge::operator<(const EdgeBasedEdge &other) const
return std::tie(source, target, data.weight, unidirectional) < return std::tie(source, target, data.weight, unidirectional) <
std::tie(other.source, other.target, other.data.weight, other_is_unidirectional); std::tie(other.source, other.target, other.data.weight, other_is_unidirectional);
} }
} // ns extractor } // namespace extractor
} // ns osrm } // namespace osrm
#endif /* EDGE_BASED_EDGE_HPP */ #endif /* EDGE_BASED_EDGE_HPP */
@@ -49,7 +49,7 @@ struct ByEdgeOrByMeterValue
using value_type = float; using value_type = float;
value_type value; value_type value;
}; };
} } // namespace detail
struct InternalExtractorEdge struct InternalExtractorEdge
{ {
@@ -63,7 +63,7 @@ struct InternalExtractorEdge
WeightData weight_data, WeightData weight_data,
DurationData duration_data, DurationData duration_data,
util::Coordinate source_coordinate) util::Coordinate source_coordinate)
: result(source, target, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)), : result(source, target, 0, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)),
duration_data(std::move(duration_data)), source_coordinate(std::move(source_coordinate)) duration_data(std::move(duration_data)), source_coordinate(std::move(source_coordinate))
{ {
} }
@@ -113,7 +113,7 @@ struct InternalExtractorEdge
return v; return v;
} }
}; };
} } // namespace extractor
} } // namespace osrm
#endif // INTERNAL_EXTRACTOR_EDGE_HPP #endif // INTERNAL_EXTRACTOR_EDGE_HPP
+20 -8
View File
@@ -97,6 +97,7 @@ struct NodeBasedEdge
NodeID target, NodeID target,
EdgeWeight weight, EdgeWeight weight,
EdgeDuration duration, EdgeDuration duration,
EdgeDistance distance,
GeometryID geometry_id, GeometryID geometry_id,
AnnotationID annotation_data, AnnotationID annotation_data,
NodeBasedEdgeClassification flags); NodeBasedEdgeClassification flags);
@@ -107,6 +108,7 @@ struct NodeBasedEdge
NodeID target; // 32 4 NodeID target; // 32 4
EdgeWeight weight; // 32 4 EdgeWeight weight; // 32 4
EdgeDuration duration; // 32 4 EdgeDuration duration; // 32 4
EdgeDistance distance; // 32 4
GeometryID geometry_id; // 32 4 GeometryID geometry_id; // 32 4
AnnotationID annotation_data; // 32 4 AnnotationID annotation_data; // 32 4
NodeBasedEdgeClassification flags; // 32 4 NodeBasedEdgeClassification flags; // 32 4
@@ -120,6 +122,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
OSMNodeID target, OSMNodeID target,
EdgeWeight weight, EdgeWeight weight,
EdgeDuration duration, EdgeDuration duration,
EdgeDistance distance,
GeometryID geometry_id, GeometryID geometry_id,
AnnotationID annotation_data, AnnotationID annotation_data,
NodeBasedEdgeClassification flags); NodeBasedEdgeClassification flags);
@@ -137,7 +140,8 @@ inline NodeBasedEdgeClassification::NodeBasedEdgeClassification()
} }
inline NodeBasedEdge::NodeBasedEdge() inline NodeBasedEdge::NodeBasedEdge()
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), weight(0), duration(0), annotation_data(-1) : source(SPECIAL_NODEID), target(SPECIAL_NODEID), weight(0), duration(0), distance(0),
annotation_data(-1)
{ {
} }
@@ -145,11 +149,12 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
NodeID target, NodeID target,
EdgeWeight weight, EdgeWeight weight,
EdgeDuration duration, EdgeDuration duration,
EdgeDistance distance,
GeometryID geometry_id, GeometryID geometry_id,
AnnotationID annotation_data, AnnotationID annotation_data,
NodeBasedEdgeClassification flags) NodeBasedEdgeClassification flags)
: source(source), target(target), weight(weight), duration(duration), geometry_id(geometry_id), : source(source), target(target), weight(weight), duration(duration), distance(distance),
annotation_data(annotation_data), flags(flags) geometry_id(geometry_id), annotation_data(annotation_data), flags(flags)
{ {
} }
@@ -175,11 +180,18 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
OSMNodeID target, OSMNodeID target,
EdgeWeight weight, EdgeWeight weight,
EdgeDuration duration, EdgeDuration duration,
EdgeDistance distance,
GeometryID geometry_id, GeometryID geometry_id,
AnnotationID annotation_data, AnnotationID annotation_data,
NodeBasedEdgeClassification flags) NodeBasedEdgeClassification flags)
: NodeBasedEdge( : NodeBasedEdge(SPECIAL_NODEID,
SPECIAL_NODEID, SPECIAL_NODEID, weight, duration, geometry_id, annotation_data, flags), SPECIAL_NODEID,
weight,
duration,
distance,
geometry_id,
annotation_data,
flags),
osm_source_id(std::move(source)), osm_target_id(std::move(target)) osm_source_id(std::move(source)), osm_target_id(std::move(target))
{ {
} }
@@ -189,12 +201,12 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM()
{ {
} }
static_assert(sizeof(extractor::NodeBasedEdge) == 28, static_assert(sizeof(extractor::NodeBasedEdge) == 32,
"Size of extractor::NodeBasedEdge type is " "Size of extractor::NodeBasedEdge type is "
"bigger than expected. This will influence " "bigger than expected. This will influence "
"memory consumption."); "memory consumption.");
} // ns extractor } // namespace extractor
} // ns osrm } // namespace osrm
#endif /* NODE_BASED_EDGE_HPP */ #endif /* NODE_BASED_EDGE_HPP */
+5 -68
View File
@@ -2,7 +2,6 @@
#define OSRM_BINDINGS_NODE_SUPPORT_HPP #define OSRM_BINDINGS_NODE_SUPPORT_HPP
#include "nodejs/json_v8_renderer.hpp" #include "nodejs/json_v8_renderer.hpp"
#include "util/json_renderer.hpp"
#include "osrm/approach.hpp" #include "osrm/approach.hpp"
#include "osrm/bearing.hpp" #include "osrm/bearing.hpp"
@@ -25,7 +24,6 @@
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <iterator> #include <iterator>
#include <sstream>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -44,13 +42,6 @@ using match_parameters_ptr = std::unique_ptr<osrm::MatchParameters>;
using nearest_parameters_ptr = std::unique_ptr<osrm::NearestParameters>; using nearest_parameters_ptr = std::unique_ptr<osrm::NearestParameters>;
using table_parameters_ptr = std::unique_ptr<osrm::TableParameters>; using table_parameters_ptr = std::unique_ptr<osrm::TableParameters>;
struct PluginParameters
{
bool renderJSONToBuffer = false;
};
using ObjectOrString = typename mapbox::util::variant<osrm::json::Object, std::string>;
template <typename ResultT> inline v8::Local<v8::Value> render(const ResultT &result); template <typename ResultT> inline v8::Local<v8::Value> render(const ResultT &result);
template <> v8::Local<v8::Value> inline render(const std::string &result) template <> v8::Local<v8::Value> inline render(const std::string &result)
@@ -58,21 +49,11 @@ template <> v8::Local<v8::Value> inline render(const std::string &result)
return Nan::CopyBuffer(result.data(), result.size()).ToLocalChecked(); return Nan::CopyBuffer(result.data(), result.size()).ToLocalChecked();
} }
template <> v8::Local<v8::Value> inline render(const ObjectOrString &result) template <> v8::Local<v8::Value> inline render(const osrm::json::Object &result)
{ {
if (result.is<osrm::json::Object>()) v8::Local<v8::Value> value;
{ renderToV8(value, result);
// Convert osrm::json object tree into matching v8 object tree return value;
v8::Local<v8::Value> value;
renderToV8(value, result.get<osrm::json::Object>());
return value;
}
else
{
// Return the string object as a node Buffer
return Nan::CopyBuffer(result.get<std::string>().data(), result.get<std::string>().size())
.ToLocalChecked();
}
} }
inline void ParseResult(const osrm::Status &result_status, osrm::json::Object &result) inline void ParseResult(const osrm::Status &result_status, osrm::json::Object &result)
@@ -833,50 +814,6 @@ inline bool parseCommonParameters(const v8::Local<v8::Object> &obj, ParamType &p
return true; return true;
} }
inline PluginParameters
argumentsToPluginParameters(const Nan::FunctionCallbackInfo<v8::Value> &args)
{
if (args.Length() < 3 || !args[1]->IsObject())
{
return {};
}
v8::Local<v8::Object> obj = Nan::To<v8::Object>(args[1]).ToLocalChecked();
if (obj->Has(Nan::New("format").ToLocalChecked()))
{
v8::Local<v8::Value> format = obj->Get(Nan::New("format").ToLocalChecked());
if (format.IsEmpty())
{
return {};
}
if (!format->IsString())
{
Nan::ThrowError("format must be a string: \"object\" or \"json_buffer\"");
return {};
}
const Nan::Utf8String format_utf8str(format);
std::string format_str{*format_utf8str, *format_utf8str + format_utf8str.length()};
if (format_str == "object")
{
return {false};
}
else if (format_str == "json_buffer")
{
return {true};
}
else
{
Nan::ThrowError("format must be a string: \"object\" or \"json_buffer\"");
return {};
}
}
return {};
}
inline route_parameters_ptr inline route_parameters_ptr
argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args, argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates) bool requires_multiple_coordinates)
@@ -1420,6 +1357,6 @@ argumentsToMatchParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
return params; return params;
} }
} // namespace node_osrm } // ns node_osrm
#endif #endif
@@ -14,6 +14,8 @@
#include <tbb/parallel_for.h> #include <tbb/parallel_for.h>
#include <tbb/parallel_reduce.h> #include <tbb/parallel_reduce.h>
#include <iostream>
#include <cstdint> #include <cstdint>
#include <algorithm> #include <algorithm>
@@ -43,6 +45,7 @@ splitBidirectionalEdges(const std::vector<extractor::EdgeBasedEdge> &edges)
edge.data.turn_id, edge.data.turn_id,
std::max(edge.data.weight, 1), std::max(edge.data.weight, 1),
edge.data.duration, edge.data.duration,
edge.data.distance,
edge.data.forward, edge.data.forward,
edge.data.backward); edge.data.backward);
@@ -51,6 +54,7 @@ splitBidirectionalEdges(const std::vector<extractor::EdgeBasedEdge> &edges)
edge.data.turn_id, edge.data.turn_id,
std::max(edge.data.weight, 1), std::max(edge.data.weight, 1),
edge.data.duration, edge.data.duration,
edge.data.distance,
edge.data.backward, edge.data.backward,
edge.data.forward); edge.data.forward);
} }
@@ -196,7 +200,7 @@ inline DynamicEdgeBasedGraph LoadEdgeBasedGraph(const boost::filesystem::path &p
return DynamicEdgeBasedGraph(number_of_edge_based_nodes, std::move(tidied), checksum); return DynamicEdgeBasedGraph(number_of_edge_based_nodes, std::move(tidied), checksum);
} }
} // ns partition } // namespace partitioner
} // ns osrm } // namespace osrm
#endif #endif
-3
View File
@@ -23,9 +23,6 @@ namespace detail
{ {
const constexpr double DEGREE_TO_RAD = 0.017453292519943295769236907684886; const constexpr double DEGREE_TO_RAD = 0.017453292519943295769236907684886;
const constexpr double RAD_TO_DEGREE = 1. / DEGREE_TO_RAD; const constexpr double RAD_TO_DEGREE = 1. / DEGREE_TO_RAD;
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
const constexpr long double EARTH_RADIUS = 6372797.560856;
inline double degToRad(const double degree) inline double degToRad(const double degree)
{ {
+31 -11
View File
@@ -1,9 +1,11 @@
#ifndef OSRM_UTIL_DEBUG_HPP_ #ifndef OSRM_UTIL_DEBUG_HPP_
#define OSRM_UTIL_DEBUG_HPP_ #define OSRM_UTIL_DEBUG_HPP_
#include "extractor/edge_based_edge.hpp"
#include "extractor/node_data_container.hpp" #include "extractor/node_data_container.hpp"
#include "extractor/query_node.hpp" #include "extractor/query_node.hpp"
#include "guidance/intersection.hpp" #include "guidance/intersection.hpp"
#include "guidance/turn_instruction.hpp"
#include "guidance/turn_lane_data.hpp" #include "guidance/turn_lane_data.hpp"
#include "engine/guidance/route_step.hpp" #include "engine/guidance/route_step.hpp"
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
@@ -25,7 +27,7 @@ inline std::ostream &operator<<(std::ostream &out, const Coordinate &coordinate)
<< toFloating(coordinate.lat) << "}"; << toFloating(coordinate.lat) << "}";
return out; return out;
} }
} } // namespace util
namespace engine namespace engine
{ {
@@ -60,8 +62,8 @@ inline std::ostream &operator<<(std::ostream &out, const RouteStep &step)
return out; return out;
} }
} } // namespace guidance
} } // namespace engine
namespace guidance namespace guidance
{ {
@@ -74,7 +76,7 @@ inline std::ostream &operator<<(std::ostream &out, const ConnectedRoad &road)
<< static_cast<std::int32_t>(road.lane_data_id) << "}"; << static_cast<std::int32_t>(road.lane_data_id) << "}";
return out; return out;
} }
} } // namespace guidance
namespace extractor namespace extractor
{ {
@@ -93,7 +95,7 @@ inline std::ostream &operator<<(std::ostream &out, const IntersectionViewData &v
<< " angle: " << view.angle << " bearing: " << view.perceived_bearing << "}"; << " angle: " << view.angle << " bearing: " << view.perceived_bearing << "}";
return out; return out;
} }
} } // namespace intersection
namespace TurnLaneType namespace TurnLaneType
{ {
@@ -123,9 +125,9 @@ inline std::ostream &operator<<(std::ostream &out, const Mask lane_type)
return out; return out;
} }
} } // namespace TurnLaneType
} } // namespace extractor
} } // namespace osrm
namespace std namespace std
{ {
@@ -145,7 +147,7 @@ inline std::ostream &operator<<(std::ostream &out,
return out; return out;
} }
} } // namespace std
namespace osrm namespace osrm
{ {
@@ -184,8 +186,26 @@ inline std::ostream &operator<<(std::ostream &out, const LaneDataVector &turn_la
return out; return out;
} }
} } // namespace lanes
} } // namespace guidance
namespace extractor
{
inline std::ostream &operator<<(std::ostream &out, const EdgeBasedEdge &edge)
{
out << " EdgeBasedEdge {";
out << " source " << edge.source << ", target: " << edge.target;
out << " EdgeBasedEdgeData data {";
out << " turn_id: " << edge.data.turn_id << ", weight: " << edge.data.weight;
out << " distance: " << edge.data.distance << ", duration: " << edge.data.duration;
out << " forward: " << (edge.data.forward == 0 ? "false" : "true")
<< ", backward: " << (edge.data.backward == 0 ? "false" : "true");
out << " }";
out << "}";
return out;
} }
} // namespace extractor
} // namespace osrm
#endif /*OSRM_ENGINE_GUIDANCE_DEBUG_HPP_*/ #endif /*OSRM_ENGINE_GUIDANCE_DEBUG_HPP_*/
+11 -6
View File
@@ -20,24 +20,27 @@ namespace util
struct NodeBasedEdgeData struct NodeBasedEdgeData
{ {
NodeBasedEdgeData() NodeBasedEdgeData()
: weight(INVALID_EDGE_WEIGHT), duration(INVALID_EDGE_WEIGHT), geometry_id({0, false}), : weight(INVALID_EDGE_WEIGHT), duration(INVALID_EDGE_WEIGHT),
reversed(false), annotation_data(-1) distance(INVALID_EDGE_DISTANCE), geometry_id({0, false}), reversed(false),
annotation_data(-1)
{ {
} }
NodeBasedEdgeData(EdgeWeight weight, NodeBasedEdgeData(EdgeWeight weight,
EdgeWeight duration, EdgeWeight duration,
EdgeDistance distance,
GeometryID geometry_id, GeometryID geometry_id,
bool reversed, bool reversed,
extractor::NodeBasedEdgeClassification flags, extractor::NodeBasedEdgeClassification flags,
AnnotationID annotation_data) AnnotationID annotation_data)
: weight(weight), duration(duration), geometry_id(geometry_id), reversed(reversed), : weight(weight), duration(duration), distance(distance), geometry_id(geometry_id),
flags(flags), annotation_data(annotation_data) reversed(reversed), flags(flags), annotation_data(annotation_data)
{ {
} }
EdgeWeight weight; EdgeWeight weight;
EdgeWeight duration; EdgeWeight duration;
EdgeDistance distance;
GeometryID geometry_id; GeometryID geometry_id;
bool reversed : 1; bool reversed : 1;
extractor::NodeBasedEdgeClassification flags; extractor::NodeBasedEdgeClassification flags;
@@ -80,18 +83,20 @@ NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
const extractor::NodeBasedEdge &input_edge) { const extractor::NodeBasedEdge &input_edge) {
output_edge.data.weight = input_edge.weight; output_edge.data.weight = input_edge.weight;
output_edge.data.duration = input_edge.duration; output_edge.data.duration = input_edge.duration;
output_edge.data.distance = input_edge.distance;
output_edge.data.flags = input_edge.flags; output_edge.data.flags = input_edge.flags;
output_edge.data.annotation_data = input_edge.annotation_data; output_edge.data.annotation_data = input_edge.annotation_data;
BOOST_ASSERT(output_edge.data.weight > 0); BOOST_ASSERT(output_edge.data.weight > 0);
BOOST_ASSERT(output_edge.data.duration > 0); BOOST_ASSERT(output_edge.data.duration > 0);
BOOST_ASSERT(output_edge.data.distance > 0);
}); });
tbb::parallel_sort(edges_list.begin(), edges_list.end()); tbb::parallel_sort(edges_list.begin(), edges_list.end());
return NodeBasedDynamicGraph(number_of_nodes, edges_list); return NodeBasedDynamicGraph(number_of_nodes, edges_list);
} }
} } // namespace util
} } // namespace osrm
#endif // NODE_BASED_GRAPH_HPP #endif // NODE_BASED_GRAPH_HPP
+2 -1
View File
@@ -48,7 +48,7 @@ struct osm_way_id
struct duplicated_node struct duplicated_node
{ {
}; };
} } // namespace tag
using OSMNodeID = osrm::Alias<std::uint64_t, tag::osm_node_id>; using OSMNodeID = osrm::Alias<std::uint64_t, tag::osm_node_id>;
static_assert(std::is_pod<OSMNodeID>(), "OSMNodeID is not a valid alias"); static_assert(std::is_pod<OSMNodeID>(), "OSMNodeID is not a valid alias");
using OSMWayID = osrm::Alias<std::uint64_t, tag::osm_way_id>; using OSMWayID = osrm::Alias<std::uint64_t, tag::osm_way_id>;
@@ -113,6 +113,7 @@ static const SegmentWeight MAX_SEGMENT_WEIGHT = INVALID_SEGMENT_WEIGHT - 1;
static const SegmentDuration MAX_SEGMENT_DURATION = INVALID_SEGMENT_DURATION - 1; static const SegmentDuration MAX_SEGMENT_DURATION = INVALID_SEGMENT_DURATION - 1;
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<EdgeWeight>::max(); static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<EdgeWeight>::max();
static const EdgeDuration MAXIMAL_EDGE_DURATION = std::numeric_limits<EdgeDuration>::max(); static const EdgeDuration MAXIMAL_EDGE_DURATION = std::numeric_limits<EdgeDuration>::max();
static const EdgeDistance MAXIMAL_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>::max(); static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>::max();
static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max(); static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "osrm", "name": "osrm",
"version": "5.19.0", "version": "5.20.0-alpha.1",
"private": false, "private": false,
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.", "description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
"dependencies": { "dependencies": {
-3
View File
@@ -120,9 +120,6 @@ function setup()
-- classes to support for exclude flags -- classes to support for exclude flags
excludable = Sequence { excludable = Sequence {
Set {'toll'},
Set {'motorway'},
Set {'ferry'}
}, },
avoid = Set { avoid = Set {
+1
View File
@@ -102,6 +102,7 @@ int Contractor::Run()
QueryGraph query_graph; QueryGraph query_graph;
std::vector<std::vector<bool>> edge_filters; std::vector<std::vector<bool>> edge_filters;
std::vector<std::vector<bool>> cores; std::vector<std::vector<bool>> cores;
std::tie(query_graph, edge_filters) = contractExcludableGraph( std::tie(query_graph, edge_filters) = contractExcludableGraph(
toContractorGraph(number_of_edge_based_nodes, std::move(edge_based_edge_list)), toContractorGraph(number_of_edge_based_nodes, std::move(edge_based_edge_list)),
std::move(node_weights), std::move(node_weights),
+5 -1
View File
@@ -215,6 +215,7 @@ void ContractNode(ContractorThreadData *data,
target, target,
path_weight, path_weight,
in_data.duration + out_data.duration, in_data.duration + out_data.duration,
in_data.distance + out_data.distance,
out_data.originalEdges + in_data.originalEdges, out_data.originalEdges + in_data.originalEdges,
node, node,
SHORTCUT_ARC, SHORTCUT_ARC,
@@ -225,6 +226,7 @@ void ContractNode(ContractorThreadData *data,
source, source,
path_weight, path_weight,
in_data.duration + out_data.duration, in_data.duration + out_data.duration,
in_data.distance + out_data.distance,
out_data.originalEdges + in_data.originalEdges, out_data.originalEdges + in_data.originalEdges,
node, node,
SHORTCUT_ARC, SHORTCUT_ARC,
@@ -280,6 +282,7 @@ void ContractNode(ContractorThreadData *data,
target, target,
path_weight, path_weight,
in_data.duration + out_data.duration, in_data.duration + out_data.duration,
in_data.distance + out_data.distance,
out_data.originalEdges + in_data.originalEdges, out_data.originalEdges + in_data.originalEdges,
node, node,
SHORTCUT_ARC, SHORTCUT_ARC,
@@ -290,6 +293,7 @@ void ContractNode(ContractorThreadData *data,
source, source,
path_weight, path_weight,
in_data.duration + out_data.duration, in_data.duration + out_data.duration,
in_data.distance + out_data.distance,
out_data.originalEdges + in_data.originalEdges, out_data.originalEdges + in_data.originalEdges,
node, node,
SHORTCUT_ARC, SHORTCUT_ARC,
@@ -556,7 +560,7 @@ bool IsNodeIndependent(const util::XORFastHash<> &hash,
} }
return true; return true;
} }
} } // namespace
std::vector<bool> contractGraph(ContractorGraph &graph, std::vector<bool> contractGraph(ContractorGraph &graph,
std::vector<bool> node_is_uncontracted_, std::vector<bool> node_is_uncontracted_,
@@ -90,7 +90,7 @@ void alternativeRoutingStep(const DataFacade<Algorithm> &facade,
else else
{ {
// check whether there is a loop present at the node // check whether there is a loop present at the node
const auto loop_weight = getLoopWeight<false>(facade, node); const auto loop_weight = std::get<0>(getLoopWeight<false>(facade, node));
const EdgeWeight new_weight_with_loop = new_weight + loop_weight; const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
if (loop_weight != INVALID_EDGE_WEIGHT && if (loop_weight != INVALID_EDGE_WEIGHT &&
new_weight_with_loop <= *upper_bound_to_shortest_path_weight) new_weight_with_loop <= *upper_bound_to_shortest_path_weight)
@@ -558,7 +558,7 @@ bool viaNodeCandidatePassesTTest(SearchEngineData<Algorithm> &engine_working_dat
} }
return (upper_bound <= t_test_path_weight); return (upper_bound <= t_test_path_weight);
} }
} // anon. namespace } // namespace
InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data, InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade, const DataFacade<Algorithm> &facade,
@@ -853,4 +853,4 @@ InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &engi
} // namespace routing_algorithms } // namespace routing_algorithms
} // namespace engine } // namespace engine
} // namespace osrm} } // namespace osrm
@@ -21,18 +21,21 @@ namespace ch
inline bool addLoopWeight(const DataFacade<ch::Algorithm> &facade, inline bool addLoopWeight(const DataFacade<ch::Algorithm> &facade,
const NodeID node, const NodeID node,
EdgeWeight &weight, EdgeWeight &weight,
EdgeDuration &duration) EdgeDuration &duration,
EdgeDistance &distance)
{ // Special case for CH when contractor creates a loop edge node->node { // Special case for CH when contractor creates a loop edge node->node
BOOST_ASSERT(weight < 0); BOOST_ASSERT(weight < 0);
const auto loop_weight = ch::getLoopWeight<false>(facade, node); const auto loop_weight = ch::getLoopWeight<false>(facade, node);
if (loop_weight != INVALID_EDGE_WEIGHT) if (std::get<0>(loop_weight) != INVALID_EDGE_WEIGHT)
{ {
const auto new_weight_with_loop = weight + loop_weight; const auto new_weight_with_loop = weight + std::get<0>(loop_weight);
if (new_weight_with_loop >= 0) if (new_weight_with_loop >= 0)
{ {
weight = new_weight_with_loop; weight = new_weight_with_loop;
duration += ch::getLoopWeight<true>(facade, node); auto result = ch::getLoopWeight<true>(facade, node);
duration += std::get<0>(result);
distance += std::get<1>(result);
return true; return true;
} }
} }
@@ -46,6 +49,7 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
const NodeID node, const NodeID node,
const EdgeWeight weight, const EdgeWeight weight,
const EdgeDuration duration, const EdgeDuration duration,
const EdgeDistance distance,
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap, typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
const PhantomNode &) const PhantomNode &)
{ {
@@ -63,21 +67,23 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
const auto edge_weight = data.weight; const auto edge_weight = data.weight;
const auto edge_duration = data.duration; const auto edge_duration = data.duration;
const auto edge_distance = data.distance;
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid"); BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
const auto to_weight = weight + edge_weight; const auto to_weight = weight + edge_weight;
const auto to_duration = duration + edge_duration; const auto to_duration = duration + edge_duration;
const auto to_distance = distance + edge_distance;
// New Node discovered -> Add to Heap + Node Info Storage // New Node discovered -> Add to Heap + Node Info Storage
if (!query_heap.WasInserted(to)) if (!query_heap.WasInserted(to))
{ {
query_heap.Insert(to, to_weight, {node, to_duration}); query_heap.Insert(to, to_weight, {node, to_duration, to_distance});
} }
// Found a shorter Path -> Update weight and set new parent // Found a shorter Path -> Update weight and set new parent
else if (std::tie(to_weight, to_duration) < else if (std::tie(to_weight, to_duration) <
std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration)) std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration))
{ {
query_heap.GetData(to) = {node, to_duration}; query_heap.GetData(to) = {node, to_duration, to_distance};
query_heap.DecreaseKey(to, to_weight); query_heap.DecreaseKey(to, to_weight);
} }
} }
@@ -91,12 +97,14 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
const std::vector<NodeBucket> &search_space_with_buckets, const std::vector<NodeBucket> &search_space_with_buckets,
std::vector<EdgeWeight> &weights_table, std::vector<EdgeWeight> &weights_table,
std::vector<EdgeDuration> &durations_table, std::vector<EdgeDuration> &durations_table,
std::vector<EdgeDistance> &distances_table,
std::vector<NodeID> &middle_nodes_table, std::vector<NodeID> &middle_nodes_table,
const PhantomNode &phantom_node) const PhantomNode &phantom_node)
{ {
const auto node = query_heap.DeleteMin(); const auto node = query_heap.DeleteMin();
const auto source_weight = query_heap.GetKey(node); const auto source_weight = query_heap.GetKey(node);
const auto source_duration = query_heap.GetData(node).duration; const auto source_duration = query_heap.GetData(node).duration;
const auto source_distance = query_heap.GetData(node).distance;
// Check if each encountered node has an entry // Check if each encountered node has an entry
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(), const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
@@ -109,20 +117,24 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
const auto column_index = current_bucket.column_index; const auto column_index = current_bucket.column_index;
const auto target_weight = current_bucket.weight; const auto target_weight = current_bucket.weight;
const auto target_duration = current_bucket.duration; const auto target_duration = current_bucket.duration;
const auto target_distance = current_bucket.distance;
auto &current_weight = weights_table[row_index * number_of_targets + column_index]; auto &current_weight = weights_table[row_index * number_of_targets + column_index];
auto &current_duration = durations_table[row_index * number_of_targets + column_index]; auto &current_duration = durations_table[row_index * number_of_targets + column_index];
auto &current_distance = distances_table[row_index * number_of_targets + column_index];
// Check if new weight is better // Check if new weight is better
auto new_weight = source_weight + target_weight; auto new_weight = source_weight + target_weight;
auto new_duration = source_duration + target_duration; auto new_duration = source_duration + target_duration;
auto new_distance = source_distance + target_distance;
if (new_weight < 0) if (new_weight < 0)
{ {
if (addLoopWeight(facade, node, new_weight, new_duration)) if (addLoopWeight(facade, node, new_weight, new_duration, new_distance))
{ {
current_weight = std::min(current_weight, new_weight); current_weight = std::min(current_weight, new_weight);
current_duration = std::min(current_duration, new_duration); current_duration = std::min(current_duration, new_duration);
current_distance = std::min(current_distance, new_distance);
middle_nodes_table[row_index * number_of_targets + column_index] = node; middle_nodes_table[row_index * number_of_targets + column_index] = node;
} }
} }
@@ -130,12 +142,13 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
{ {
current_weight = new_weight; current_weight = new_weight;
current_duration = new_duration; current_duration = new_duration;
current_distance = new_distance;
middle_nodes_table[row_index * number_of_targets + column_index] = node; middle_nodes_table[row_index * number_of_targets + column_index] = node;
} }
} }
relaxOutgoingEdges<FORWARD_DIRECTION>( relaxOutgoingEdges<FORWARD_DIRECTION>(
facade, node, source_weight, source_duration, query_heap, phantom_node); facade, node, source_weight, source_duration, source_distance, query_heap, phantom_node);
} }
void backwardRoutingStep(const DataFacade<Algorithm> &facade, void backwardRoutingStep(const DataFacade<Algorithm> &facade,
@@ -147,14 +160,15 @@ void backwardRoutingStep(const DataFacade<Algorithm> &facade,
const auto node = query_heap.DeleteMin(); const auto node = query_heap.DeleteMin();
const auto target_weight = query_heap.GetKey(node); const auto target_weight = query_heap.GetKey(node);
const auto target_duration = query_heap.GetData(node).duration; const auto target_duration = query_heap.GetData(node).duration;
const auto target_distance = query_heap.GetData(node).distance;
const auto parent = query_heap.GetData(node).parent; const auto parent = query_heap.GetData(node).parent;
// Store settled nodes in search space bucket // Store settled nodes in search space bucket
search_space_with_buckets.emplace_back( search_space_with_buckets.emplace_back(
node, parent, column_index, target_weight, target_duration); node, parent, column_index, target_weight, target_duration, target_distance);
relaxOutgoingEdges<REVERSE_DIRECTION>( relaxOutgoingEdges<REVERSE_DIRECTION>(
facade, node, target_weight, target_duration, query_heap, phantom_node); facade, node, target_weight, target_duration, target_distance, query_heap, phantom_node);
} }
} // namespace ch } // namespace ch
@@ -235,79 +249,17 @@ void calculateDistances(typename SearchEngineData<ch::Algorithm>::ManyToManyQuer
needsLoopBackwards(source_phantom, target_phantom))) needsLoopBackwards(source_phantom, target_phantom)))
{ {
auto weight = ch::getLoopWeight<false>(facade, packed_leg.front()); auto weight = ch::getLoopWeight<false>(facade, packed_leg.front());
if (weight != INVALID_EDGE_WEIGHT) if (std::get<0>(weight) != INVALID_EDGE_WEIGHT)
packed_leg.push_back(packed_leg.front()); packed_leg.push_back(packed_leg.front());
} }
if (!packed_leg.empty()) if (!packed_leg.empty())
{ {
auto annotation = EdgeDistance annotation =
ch::calculateEBGNodeAnnotations(facade, packed_leg.begin(), packed_leg.end()); ch::calculateEBGNodeAnnotations(facade, packed_leg.begin(), packed_leg.end());
annotation = adjustPathDistanceToPhantomNodes(
packed_leg, source_phantom, target_phantom, annotation);
distances_table[row_index * number_of_targets + column_index] = annotation; distances_table[row_index * number_of_targets + column_index] = annotation;
// check the direction of travel to figure out how to calculate the offset to/from
// the source/target
if (source_phantom.forward_segment_id.id == packed_leg.front())
{
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
// -->s <-- subtract offset to start at source
// ......... <-- want this distance as result
// entry 0---1---2---3--- <-- 3 is exit node
EdgeDistance offset = source_phantom.GetForwardDistance();
distances_table[row_index * number_of_targets + column_index] -= offset;
}
else if (source_phantom.reverse_segment_id.id == packed_leg.front())
{
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
// s<------- <-- subtract offset to start at source
// ... <-- want this distance
// entry 0---1---2---3 <-- 3 is exit node
EdgeDistance offset = source_phantom.GetReverseDistance();
distances_table[row_index * number_of_targets + column_index] -= offset;
}
if (target_phantom.forward_segment_id.id == packed_leg.back())
{
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
// ++>t <-- add offset to get to target
// ................ <-- want this distance as result
// entry 0---1---2---3--- <-- 3 is exit node
EdgeDistance offset = target_phantom.GetForwardDistance();
distances_table[row_index * number_of_targets + column_index] += offset;
}
else if (target_phantom.reverse_segment_id.id == packed_leg.back())
{
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
// <++t <-- add offset to get from target
// ................ <-- want this distance as result
// entry 0---1---2---3--- <-- 3 is exit node
EdgeDistance offset = target_phantom.GetReverseDistance();
distances_table[row_index * number_of_targets + column_index] += offset;
}
}
else
{
// there is no shortcut to unpack. source and target are on the same EBG Node.
// if the offset of the target is greater than the offset of the source, subtract it
if (target_phantom.GetForwardDistance() > source_phantom.GetForwardDistance())
{
// --------->t <-- offsets
// ->s <-- subtract source offset from target offset
// ......... <-- want this distance as result
// entry 0---1---2---3--- <-- 3 is exit node
EdgeDistance offset =
target_phantom.GetForwardDistance() - source_phantom.GetForwardDistance();
distances_table[row_index * number_of_targets + column_index] = offset;
}
else
{
// s<--- <-- offsets
// t<--------- <-- subtract source offset from target offset
// ...... <-- want this distance as result
// entry 0---1---2---3--- <-- 3 is exit node
EdgeDistance offset =
target_phantom.GetReverseDistance() - source_phantom.GetReverseDistance();
distances_table[row_index * number_of_targets + column_index] = offset;
}
} }
packed_leg.clear(); packed_leg.clear();
} }
@@ -331,7 +283,7 @@ manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
std::vector<EdgeWeight> weights_table(number_of_entries, INVALID_EDGE_WEIGHT); std::vector<EdgeWeight> weights_table(number_of_entries, INVALID_EDGE_WEIGHT);
std::vector<EdgeDuration> durations_table(number_of_entries, MAXIMAL_EDGE_DURATION); std::vector<EdgeDuration> durations_table(number_of_entries, MAXIMAL_EDGE_DURATION);
std::vector<EdgeDistance> distances_table; std::vector<EdgeDistance> distances_table(number_of_entries, MAXIMAL_EDGE_DISTANCE);
std::vector<NodeID> middle_nodes_table(number_of_entries, SPECIAL_NODEID); std::vector<NodeID> middle_nodes_table(number_of_entries, SPECIAL_NODEID);
std::vector<NodeBucket> search_space_with_buckets; std::vector<NodeBucket> search_space_with_buckets;
@@ -380,6 +332,7 @@ manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
search_space_with_buckets, search_space_with_buckets,
weights_table, weights_table,
durations_table, durations_table,
distances_table,
middle_nodes_table, middle_nodes_table,
source_phantom); source_phantom);
} }
@@ -387,17 +340,21 @@ manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
if (calculate_distance) if (calculate_distance)
{ {
distances_table.resize(number_of_entries, INVALID_EDGE_DISTANCE); distances_table.resize(number_of_entries, INVALID_EDGE_DISTANCE);
calculateDistances(query_heap, // TODO: this is a hack to work around stuff
facade, if (number_of_entries == 0)
phantom_nodes, {
target_indices, calculateDistances(query_heap,
row_index, facade,
source_index, phantom_nodes,
source_phantom, target_indices,
number_of_targets, row_index,
search_space_with_buckets, source_index,
distances_table, source_phantom,
middle_nodes_table); number_of_targets,
search_space_with_buckets,
distances_table,
middle_nodes_table);
}
} }
} }
@@ -41,6 +41,7 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
const NodeID node, const NodeID node,
const EdgeWeight weight, const EdgeWeight weight,
const EdgeDuration duration, const EdgeDuration duration,
const EdgeDistance /* distance TODO use this */,
typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &query_heap, typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &query_heap,
Args... args) Args... args)
{ {
@@ -77,14 +78,14 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
const auto to_duration = duration + shortcut_durations.front(); const auto to_duration = duration + shortcut_durations.front();
if (!query_heap.WasInserted(to)) if (!query_heap.WasInserted(to))
{ {
query_heap.Insert(to, to_weight, {node, true, to_duration}); query_heap.Insert(to, to_weight, {node, true, to_duration, 0});
} }
else if (std::tie(to_weight, to_duration, node) < else if (std::tie(to_weight, to_duration, node) <
std::tie(query_heap.GetKey(to), std::tie(query_heap.GetKey(to),
query_heap.GetData(to).duration, query_heap.GetData(to).duration,
query_heap.GetData(to).parent)) query_heap.GetData(to).parent))
{ {
query_heap.GetData(to) = {node, true, to_duration}; query_heap.GetData(to) = {node, true, to_duration, 0};
query_heap.DecreaseKey(to, to_weight); query_heap.DecreaseKey(to, to_weight);
} }
} }
@@ -109,14 +110,14 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
const auto to_duration = duration + shortcut_durations.front(); const auto to_duration = duration + shortcut_durations.front();
if (!query_heap.WasInserted(to)) if (!query_heap.WasInserted(to))
{ {
query_heap.Insert(to, to_weight, {node, true, to_duration}); query_heap.Insert(to, to_weight, {node, true, to_duration, 0});
} }
else if (std::tie(to_weight, to_duration, node) < else if (std::tie(to_weight, to_duration, node) <
std::tie(query_heap.GetKey(to), std::tie(query_heap.GetKey(to),
query_heap.GetData(to).duration, query_heap.GetData(to).duration,
query_heap.GetData(to).parent)) query_heap.GetData(to).parent))
{ {
query_heap.GetData(to) = {node, true, to_duration}; query_heap.GetData(to) = {node, true, to_duration, 0};
query_heap.DecreaseKey(to, to_weight); query_heap.DecreaseKey(to, to_weight);
} }
} }
@@ -153,7 +154,7 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
// New Node discovered -> Add to Heap + Node Info Storage // New Node discovered -> Add to Heap + Node Info Storage
if (!query_heap.WasInserted(to)) if (!query_heap.WasInserted(to))
{ {
query_heap.Insert(to, to_weight, {node, false, to_duration}); query_heap.Insert(to, to_weight, {node, false, to_duration, 0});
} }
// Found a shorter Path -> Update weight and set new parent // Found a shorter Path -> Update weight and set new parent
else if (std::tie(to_weight, to_duration, node) < else if (std::tie(to_weight, to_duration, node) <
@@ -161,7 +162,7 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
query_heap.GetData(to).duration, query_heap.GetData(to).duration,
query_heap.GetData(to).parent)) query_heap.GetData(to).parent))
{ {
query_heap.GetData(to) = {node, false, to_duration}; query_heap.GetData(to) = {node, false, to_duration, 0};
query_heap.DecreaseKey(to, to_weight); query_heap.DecreaseKey(to, to_weight);
} }
} }
@@ -178,15 +179,15 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const std::vector<PhantomNode> &phantom_nodes, const std::vector<PhantomNode> &phantom_nodes,
std::size_t phantom_index, std::size_t phantom_index,
const std::vector<std::size_t> &phantom_indices, const std::vector<std::size_t> &phantom_indices,
const bool calculate_distance) const bool /* calculate_distance */)
{ {
std::vector<EdgeWeight> weights(phantom_indices.size(), INVALID_EDGE_WEIGHT); std::vector<EdgeWeight> weights(phantom_indices.size(), INVALID_EDGE_WEIGHT);
std::vector<EdgeDuration> durations(phantom_indices.size(), MAXIMAL_EDGE_DURATION); std::vector<EdgeDuration> durations(phantom_indices.size(), MAXIMAL_EDGE_DURATION);
std::vector<EdgeDistance> distances_table; std::vector<EdgeDistance> distances_table(phantom_indices.size(), MAXIMAL_EDGE_DISTANCE);
std::vector<NodeID> middle_nodes_table(phantom_indices.size(), SPECIAL_NODEID); std::vector<NodeID> middle_nodes_table(phantom_indices.size(), SPECIAL_NODEID);
// Collect destination (source) nodes into a map // Collect destination (source) nodes into a map
std::unordered_multimap<NodeID, std::tuple<std::size_t, EdgeWeight, EdgeDuration>> std::unordered_multimap<NodeID, std::tuple<std::size_t, EdgeWeight, EdgeDuration, EdgeDistance>>
target_nodes_index; target_nodes_index;
target_nodes_index.reserve(phantom_indices.size()); target_nodes_index.reserve(phantom_indices.size());
for (std::size_t index = 0; index < phantom_indices.size(); ++index) for (std::size_t index = 0; index < phantom_indices.size(); ++index)
@@ -201,13 +202,15 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
{phantom_node.forward_segment_id.id, {phantom_node.forward_segment_id.id,
std::make_tuple(index, std::make_tuple(index,
phantom_node.GetForwardWeightPlusOffset(), phantom_node.GetForwardWeightPlusOffset(),
phantom_node.GetForwardDuration())}); phantom_node.GetForwardDuration(),
phantom_node.GetForwardDistance())});
if (phantom_node.IsValidReverseTarget()) if (phantom_node.IsValidReverseTarget())
target_nodes_index.insert( target_nodes_index.insert(
{phantom_node.reverse_segment_id.id, {phantom_node.reverse_segment_id.id,
std::make_tuple(index, std::make_tuple(index,
phantom_node.GetReverseWeightPlusOffset(), phantom_node.GetReverseWeightPlusOffset(),
phantom_node.GetReverseDuration())}); phantom_node.GetReverseDuration(),
phantom_node.GetReverseDistance())});
} }
else if (DIRECTION == REVERSE_DIRECTION) else if (DIRECTION == REVERSE_DIRECTION)
{ {
@@ -216,13 +219,15 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
{phantom_node.forward_segment_id.id, {phantom_node.forward_segment_id.id,
std::make_tuple(index, std::make_tuple(index,
-phantom_node.GetForwardWeightPlusOffset(), -phantom_node.GetForwardWeightPlusOffset(),
-phantom_node.GetForwardDuration())}); -phantom_node.GetForwardDuration(),
-phantom_node.GetForwardDistance())});
if (phantom_node.IsValidReverseSource()) if (phantom_node.IsValidReverseSource())
target_nodes_index.insert( target_nodes_index.insert(
{phantom_node.reverse_segment_id.id, {phantom_node.reverse_segment_id.id,
std::make_tuple(index, std::make_tuple(index,
-phantom_node.GetReverseWeightPlusOffset(), -phantom_node.GetReverseWeightPlusOffset(),
-phantom_node.GetReverseDuration())}); -phantom_node.GetReverseDuration(),
-phantom_node.GetReverseDistance())});
} }
} }
@@ -232,44 +237,50 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
auto &query_heap = *(engine_working_data.many_to_many_heap); auto &query_heap = *(engine_working_data.many_to_many_heap);
// Check if node is in the destinations list and update weights/durations // Check if node is in the destinations list and update weights/durations
auto update_values = [&](NodeID node, EdgeWeight weight, EdgeDuration duration) { auto update_values =
auto candidates = target_nodes_index.equal_range(node); [&](NodeID node, EdgeWeight weight, EdgeDuration duration, EdgeDistance distance) {
for (auto it = candidates.first; it != candidates.second;) auto candidates = target_nodes_index.equal_range(node);
{ for (auto it = candidates.first; it != candidates.second;)
std::size_t index;
EdgeWeight target_weight;
EdgeDuration target_duration;
std::tie(index, target_weight, target_duration) = it->second;
const auto path_weight = weight + target_weight;
if (path_weight >= 0)
{ {
const auto path_duration = duration + target_duration; std::size_t index;
EdgeWeight target_weight;
EdgeDuration target_duration;
EdgeDuration target_distance;
std::tie(index, target_weight, target_duration, target_distance) = it->second;
if (std::tie(path_weight, path_duration) < const auto path_weight = weight + target_weight;
std::tie(weights[index], durations[index])) if (path_weight >= 0)
{ {
weights[index] = path_weight; const auto path_duration = duration + target_duration;
durations[index] = path_duration; const auto path_distance = distance + target_distance;
middle_nodes_table[index] = node;
if (std::tie(path_weight, path_duration) <
std::tie(weights[index], durations[index]))
{
weights[index] = path_weight;
durations[index] = path_duration;
distances_table[index] = path_distance;
middle_nodes_table[index] = node;
}
// Remove node from destinations list
it = target_nodes_index.erase(it);
}
else
{
++it;
} }
// Remove node from destinations list
it = target_nodes_index.erase(it);
} }
else };
{
++it;
}
}
};
auto insert_node = [&](NodeID node, EdgeWeight initial_weight, EdgeDuration initial_duration) {
auto insert_node = [&](NodeID node,
EdgeWeight initial_weight,
EdgeDuration initial_duration,
EdgeDistance initial_distance) {
// Update single node paths // Update single node paths
update_values(node, initial_weight, initial_duration); update_values(node, initial_weight, initial_duration, initial_distance);
query_heap.Insert(node, initial_weight, {node, initial_duration}); query_heap.Insert(node, initial_weight, {node, initial_duration, initial_distance});
// Place adjacent nodes into heap // Place adjacent nodes into heap
for (auto edge : facade.GetAdjacentEdgeRange(node)) for (auto edge : facade.GetAdjacentEdgeRange(node))
@@ -292,8 +303,9 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
facade.GetWeightPenaltyForEdgeID(turn_id); facade.GetWeightPenaltyForEdgeID(turn_id);
const auto edge_duration = initial_duration + facade.GetNodeDuration(node_id) + const auto edge_duration = initial_duration + facade.GetNodeDuration(node_id) +
facade.GetDurationPenaltyForEdgeID(turn_id); facade.GetDurationPenaltyForEdgeID(turn_id);
const auto edge_distance = initial_distance;
query_heap.Insert(to, edge_weight, {node, edge_duration}); query_heap.Insert(to, edge_weight, {node, edge_duration, edge_distance});
} }
} }
}; };
@@ -307,14 +319,16 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
{ {
insert_node(phantom_node.forward_segment_id.id, insert_node(phantom_node.forward_segment_id.id,
-phantom_node.GetForwardWeightPlusOffset(), -phantom_node.GetForwardWeightPlusOffset(),
-phantom_node.GetForwardDuration()); -phantom_node.GetForwardDuration(),
-phantom_node.GetForwardDistance());
} }
if (phantom_node.IsValidReverseSource()) if (phantom_node.IsValidReverseSource())
{ {
insert_node(phantom_node.reverse_segment_id.id, insert_node(phantom_node.reverse_segment_id.id,
-phantom_node.GetReverseWeightPlusOffset(), -phantom_node.GetReverseWeightPlusOffset(),
-phantom_node.GetReverseDuration()); -phantom_node.GetReverseDuration(),
-phantom_node.GetReverseDistance());
} }
} }
else if (DIRECTION == REVERSE_DIRECTION) else if (DIRECTION == REVERSE_DIRECTION)
@@ -323,14 +337,16 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
{ {
insert_node(phantom_node.forward_segment_id.id, insert_node(phantom_node.forward_segment_id.id,
phantom_node.GetForwardWeightPlusOffset(), phantom_node.GetForwardWeightPlusOffset(),
phantom_node.GetForwardDuration()); phantom_node.GetForwardDuration(),
phantom_node.GetForwardDistance());
} }
if (phantom_node.IsValidReverseTarget()) if (phantom_node.IsValidReverseTarget())
{ {
insert_node(phantom_node.reverse_segment_id.id, insert_node(phantom_node.reverse_segment_id.id,
phantom_node.GetReverseWeightPlusOffset(), phantom_node.GetReverseWeightPlusOffset(),
phantom_node.GetReverseDuration()); phantom_node.GetReverseDuration(),
phantom_node.GetReverseDistance());
} }
} }
} }
@@ -341,22 +357,26 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const auto node = query_heap.DeleteMin(); const auto node = query_heap.DeleteMin();
const auto weight = query_heap.GetKey(node); const auto weight = query_heap.GetKey(node);
const auto duration = query_heap.GetData(node).duration; const auto duration = query_heap.GetData(node).duration;
const auto distance = query_heap.GetData(node).distance;
// Update values // Update values
update_values(node, weight, duration); update_values(node, weight, duration, distance);
// Relax outgoing edges // Relax outgoing edges
relaxOutgoingEdges<DIRECTION>(facade, relaxOutgoingEdges<DIRECTION>(facade,
node, node,
weight, weight,
duration, duration,
distance,
query_heap, query_heap,
phantom_nodes, phantom_nodes,
phantom_index, phantom_index,
phantom_indices); phantom_indices);
} }
if (calculate_distance) // TODO: re-enable this if we need to fallback
// if (calculate_distance)
if (false)
{ {
// Initialize unpacking heaps // Initialize unpacking heaps
engine_working_data.InitializeOrClearFirstThreadLocalStorage( engine_working_data.InitializeOrClearFirstThreadLocalStorage(
@@ -497,6 +517,7 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
const auto node = query_heap.DeleteMin(); const auto node = query_heap.DeleteMin();
const auto source_weight = query_heap.GetKey(node); const auto source_weight = query_heap.GetKey(node);
const auto source_duration = query_heap.GetData(node).duration; const auto source_duration = query_heap.GetData(node).duration;
const auto source_distance = query_heap.GetData(node).distance;
// Check if each encountered node has an entry // Check if each encountered node has an entry
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(), const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
@@ -533,7 +554,7 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
} }
relaxOutgoingEdges<DIRECTION>( relaxOutgoingEdges<DIRECTION>(
facade, node, source_weight, source_duration, query_heap, phantom_node); facade, node, source_weight, source_duration, source_distance, query_heap, phantom_node);
} }
template <bool DIRECTION> template <bool DIRECTION>
@@ -546,6 +567,7 @@ void backwardRoutingStep(const DataFacade<Algorithm> &facade,
const auto node = query_heap.DeleteMin(); const auto node = query_heap.DeleteMin();
const auto target_weight = query_heap.GetKey(node); const auto target_weight = query_heap.GetKey(node);
const auto target_duration = query_heap.GetData(node).duration; const auto target_duration = query_heap.GetData(node).duration;
const auto target_distance = query_heap.GetData(node).distance;
const auto parent = query_heap.GetData(node).parent; const auto parent = query_heap.GetData(node).parent;
const auto from_clique_arc = query_heap.GetData(node).from_clique_arc; const auto from_clique_arc = query_heap.GetData(node).from_clique_arc;
@@ -556,8 +578,14 @@ void backwardRoutingStep(const DataFacade<Algorithm> &facade,
const auto &partition = facade.GetMultiLevelPartition(); const auto &partition = facade.GetMultiLevelPartition();
const auto maximal_level = partition.GetNumberOfLevels() - 1; const auto maximal_level = partition.GetNumberOfLevels() - 1;
relaxOutgoingEdges<!DIRECTION>( relaxOutgoingEdges<!DIRECTION>(facade,
facade, node, target_weight, target_duration, query_heap, phantom_node, maximal_level); node,
target_weight,
target_duration,
target_distance,
query_heap,
phantom_node,
maximal_level);
} }
template <bool DIRECTION> template <bool DIRECTION>
+16 -8
View File
@@ -227,6 +227,9 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
{ {
continue; continue;
} }
forward_heap.Clear();
const auto &source_phantom = prev_unbroken_timestamps_list[s].phantom_node;
insertSourceInHeap(forward_heap, source_phantom);
for (const auto s_prime : util::irange<std::size_t>(0UL, current_viterbi.size())) for (const auto s_prime : util::irange<std::size_t>(0UL, current_viterbi.size()))
{ {
@@ -237,14 +240,19 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
continue; continue;
} }
double network_distance = reverse_heap.Clear();
getNetworkDistance(engine_working_data, const auto &target_phantom = current_timestamps_list[s_prime].phantom_node;
facade, insertTargetInHeap(reverse_heap, target_phantom);
forward_heap,
reverse_heap, double network_distance = getNetworkDistance(engine_working_data,
prev_unbroken_timestamps_list[s].phantom_node, facade,
current_timestamps_list[s_prime].phantom_node, forward_heap,
weight_upper_bound); reverse_heap,
source_phantom,
target_phantom,
weight_upper_bound);
network_distance = std::round(network_distance * 10) / 10;
// get distance diff between loc1/2 and locs/s_prime // get distance diff between loc1/2 and locs/s_prime
const auto d_t = std::abs(network_distance - haversine_distance); const auto d_t = std::abs(network_distance - haversine_distance);
@@ -33,6 +33,79 @@ bool needsLoopBackwards(const PhantomNodes &phantoms)
return needsLoopBackwards(phantoms.source_phantom, phantoms.target_phantom); return needsLoopBackwards(phantoms.source_phantom, phantoms.target_phantom);
} }
EdgeDistance adjustPathDistanceToPhantomNodes(const std::vector<NodeID> &path,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
const EdgeDistance uncorrected_distance)
{
EdgeDistance distance = uncorrected_distance;
if (!path.empty())
{
// check the direction of travel to figure out how to calculate the offset to/from
// the source/target
if (source_phantom.forward_segment_id.id == path.front())
{
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
// -->s <-- subtract offset to start at source
// ......... <-- want this distance as result
// entry 0---1---2---3--- <-- 3 is exit node
distance -= source_phantom.GetForwardDistance();
}
else if (source_phantom.reverse_segment_id.id == path.front())
{
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
// s<------- <-- subtract offset to start at source
// ... <-- want this distance
// entry 0---1---2---3 <-- 3 is exit node
distance -= source_phantom.GetReverseDistance();
}
if (target_phantom.forward_segment_id.id == path.back())
{
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
// ++>t <-- add offset to get to target
// ................ <-- want this distance as result
// entry 0---1---2---3--- <-- 3 is exit node
distance += target_phantom.GetForwardDistance();
}
else if (target_phantom.reverse_segment_id.id == path.back())
{
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
// <++t <-- add offset to get from target
// ................ <-- want this distance as result
// entry 0---1---2---3--- <-- 3 is exit node
distance += target_phantom.GetReverseDistance();
}
}
else
{
// there is no shortcut to unpack. source and target are on the same EBG Node.
// if the offset of the target is greater than the offset of the source, subtract it
if (target_phantom.GetForwardDistance() > source_phantom.GetForwardDistance())
{
// --------->t <-- offsets
// ->s <-- subtract source offset from target offset
// ......... <-- want this distance as result
// entry 0---1---2---3--- <-- 3 is exit node
distance = target_phantom.GetForwardDistance() - source_phantom.GetForwardDistance();
}
else
{
// s<--- <-- offsets
// t<--------- <-- subtract source offset from target offset
// ...... <-- want this distance as result
// entry 0---1---2---3--- <-- 3 is exit node
distance = target_phantom.GetReverseDistance() - source_phantom.GetReverseDistance();
}
}
BOOST_ASSERT_MSG(distance >= 0 || distance > -1.0f,
"Distance correction generated negative number");
// guard against underflow errors caused by rounding
distance = std::max(EdgeDistance{0}, distance);
return distance;
}
} // namespace routing_algorithms } // namespace routing_algorithms
} // namespace engine } // namespace engine
} // namespace osrm } // namespace osrm
@@ -100,7 +100,7 @@ void search(SearchEngineData<Algorithm> & /*engine_working_data*/,
const PhantomNodes & /*phantom_nodes*/, const PhantomNodes & /*phantom_nodes*/,
const EdgeWeight weight_upper_bound) const EdgeWeight weight_upper_bound)
{ {
if (forward_heap.Empty() || reverse_heap.Empty()) if (forward_heap.Empty() && reverse_heap.Empty())
{ {
weight = INVALID_EDGE_WEIGHT; weight = INVALID_EDGE_WEIGHT;
return; return;
@@ -110,10 +110,14 @@ void search(SearchEngineData<Algorithm> & /*engine_working_data*/,
weight = weight_upper_bound; weight = weight_upper_bound;
// get offset to account for offsets on phantom nodes on compressed edges // get offset to account for offsets on phantom nodes on compressed edges
const auto min_edge_offset = std::min(0, forward_heap.MinKey()); EdgeWeight min_edge_offset = 0;
BOOST_ASSERT(min_edge_offset <= 0); if (forward_heap.Size() > 0)
{
min_edge_offset = std::min(min_edge_offset, forward_heap.MinKey());
BOOST_ASSERT(min_edge_offset <= 0);
}
// we only every insert negative offsets for nodes in the forward heap // we only every insert negative offsets for nodes in the forward heap
BOOST_ASSERT(reverse_heap.MinKey() >= 0); BOOST_ASSERT(reverse_heap.Empty() || reverse_heap.MinKey() >= 0);
// run two-Target Dijkstra routing step. // run two-Target Dijkstra routing step.
while (0 < (forward_heap.Size() + reverse_heap.Size())) while (0 < (forward_heap.Size() + reverse_heap.Size()))
@@ -176,11 +180,6 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
const PhantomNode &target_phantom, const PhantomNode &target_phantom,
EdgeWeight weight_upper_bound) EdgeWeight weight_upper_bound)
{ {
forward_heap.Clear();
reverse_heap.Clear();
insertNodesInHeaps(forward_heap, reverse_heap, {source_phantom, target_phantom});
EdgeWeight weight = INVALID_EDGE_WEIGHT; EdgeWeight weight = INVALID_EDGE_WEIGHT;
std::vector<NodeID> packed_path; std::vector<NodeID> packed_path;
search(engine_working_data, search(engine_working_data,
@@ -199,14 +198,31 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
return std::numeric_limits<double>::max(); return std::numeric_limits<double>::max();
} }
std::vector<PathData> unpacked_path; EdgeDistance distance = 0;
unpackPath(facade,
packed_path.begin(),
packed_path.end(),
{source_phantom, target_phantom},
unpacked_path);
return getPathDistance(facade, unpacked_path, source_phantom, target_phantom); std::vector<NodeID> unpacked_nodes;
unpacked_nodes.reserve(packed_path.size());
if (!packed_path.empty())
{
unpacked_nodes.push_back(packed_path.front());
unpackPath(
facade, packed_path.begin(), packed_path.end(), [&](const auto &edge, const auto &) {
BOOST_ASSERT(edge.first == unpacked_nodes.back());
unpacked_nodes.push_back(edge.second);
});
distance = std::accumulate(unpacked_nodes.begin(),
std::prev(unpacked_nodes.end()),
EdgeDistance{0},
[&](const EdgeDistance distance, const auto node_id) {
return distance + computeEdgeDistance(facade, node_id);
});
}
distance =
adjustPathDistanceToPhantomNodes(unpacked_nodes, source_phantom, target_phantom, distance);
return distance;
} }
} // namespace ch } // namespace ch
+2 -2
View File
@@ -396,5 +396,5 @@ std::unique_ptr<SegmentDataContainer> CompressedEdgeContainer::ToSegmentData()
return std::move(segment_data); return std::move(segment_data);
} }
} } // namespace extractor
} } // namespace osrm
+27 -29
View File
@@ -51,7 +51,7 @@ template <> struct hash<std::pair<NodeID, NodeID>>
return seed; return seed;
} }
}; };
} } // namespace std
// Buffer size of turn_indexes_write_buffer to reduce number of write(v) syscals // Buffer size of turn_indexes_write_buffer to reduce number of write(v) syscals
const constexpr int TURN_INDEX_WRITE_BUFFER_SIZE = 1000; const constexpr int TURN_INDEX_WRITE_BUFFER_SIZE = 1000;
@@ -555,22 +555,21 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
&scripting_environment, &scripting_environment,
weight_multiplier, weight_multiplier,
&conditional_restriction_map]( &conditional_restriction_map](
// what nodes will be used? In most cases this will be the id // what nodes will be used? In most cases this will be the id
// stored in the edge_data. In case of duplicated nodes (e.g. // stored in the edge_data. In case of duplicated nodes (e.g.
// due to via-way restrictions), one/both of these might // due to via-way restrictions), one/both of these might
// refer to a newly added edge based node // refer to a newly added edge based node
const auto edge_based_node_from, const auto edge_based_node_from,
const auto edge_based_node_to, const auto edge_based_node_to,
// the situation of the turn // the situation of the turn
const auto node_along_road_entering, const auto node_along_road_entering,
const auto node_based_edge_from, const auto node_based_edge_from,
const auto intersection_node, const auto intersection_node,
const auto node_based_edge_to, const auto node_based_edge_to,
const auto &turn_angle, const auto &turn_angle,
const auto &road_legs_on_the_right, const auto &road_legs_on_the_right,
const auto &road_legs_on_the_left, const auto &road_legs_on_the_left,
const auto &edge_geometries) { const auto &edge_geometries) {
const auto node_restricted = const auto node_restricted =
isRestricted(node_along_road_entering, isRestricted(node_along_road_entering,
intersection_node, intersection_node,
@@ -652,16 +651,17 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// auto turn_id = m_edge_based_edge_list.size(); // auto turn_id = m_edge_based_edge_list.size();
auto weight = boost::numeric_cast<EdgeWeight>(edge_data1.weight + weight_penalty); auto weight = boost::numeric_cast<EdgeWeight>(edge_data1.weight + weight_penalty);
auto duration = boost::numeric_cast<EdgeWeight>(edge_data1.duration + duration_penalty); auto duration = boost::numeric_cast<EdgeWeight>(edge_data1.duration + duration_penalty);
auto distance = boost::numeric_cast<EdgeDistance>(edge_data1.distance);
EdgeBasedEdge edge_based_edge = { EdgeBasedEdge edge_based_edge = {edge_based_node_from,
edge_based_node_from, edge_based_node_to,
edge_based_node_to, SPECIAL_NODEID, // This will be updated once the main
SPECIAL_NODEID, // This will be updated once the main loop // loop completes!
// completes! weight,
weight, duration,
duration, distance,
true, true,
false}; false};
// We write out the mapping between the edge-expanded edges and the original nodes. // We write out the mapping between the edge-expanded edges and the original nodes.
// Since each edge represents a possible maneuver, external programs can use this to // Since each edge represents a possible maneuver, external programs can use this to
@@ -693,7 +693,6 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// //
tbb::filter_t<tbb::blocked_range<NodeID>, EdgesPipelineBufferPtr> processor_stage( tbb::filter_t<tbb::blocked_range<NodeID>, EdgesPipelineBufferPtr> processor_stage(
tbb::filter::parallel, [&](const tbb::blocked_range<NodeID> &intersection_node_range) { tbb::filter::parallel, [&](const tbb::blocked_range<NodeID> &intersection_node_range) {
auto buffer = std::make_shared<EdgesPipelineBuffer>(); auto buffer = std::make_shared<EdgesPipelineBuffer>();
buffer->nodes_processed = intersection_node_range.size(); buffer->nodes_processed = intersection_node_range.size();
@@ -891,7 +890,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// TODO: this loop is not optimized - once we have a few // TODO: this loop is not optimized - once we have a few
// overrides available, we should index this for faster // overrides available, we should index this for faster
// lookups // lookups
for (auto & override : unresolved_maneuver_overrides) for (auto &override : unresolved_maneuver_overrides)
{ {
for (auto &turn : override.turn_sequence) for (auto &turn : override.turn_sequence)
{ {
@@ -1032,7 +1031,6 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
std::vector<EdgeWithData> delayed_data; std::vector<EdgeWithData> delayed_data;
tbb::filter_t<EdgesPipelineBufferPtr, void> output_stage( tbb::filter_t<EdgesPipelineBufferPtr, void> output_stage(
tbb::filter::serial_in_order, [&](auto buffer) { tbb::filter::serial_in_order, [&](auto buffer) {
routing_progress.PrintAddition(buffer->nodes_processed); routing_progress.PrintAddition(buffer->nodes_processed);
m_connectivity_checksum = buffer->checksum.update_checksum(m_connectivity_checksum); m_connectivity_checksum = buffer->checksum.update_checksum(m_connectivity_checksum);
+10 -7
View File
@@ -99,7 +99,7 @@ inline NodeID mapExternalToInternalNodeID(Iter first, Iter last, const OSMNodeID
return (it == last || value < *it) ? SPECIAL_NODEID return (it == last || value < *it) ? SPECIAL_NODEID
: static_cast<NodeID>(std::distance(first, it)); : static_cast<NodeID>(std::distance(first, it));
} }
} } // namespace
namespace osrm namespace osrm
{ {
@@ -277,8 +277,8 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
{ {
if (edge_iterator->result.osm_source_id < node_iterator->node_id) if (edge_iterator->result.osm_source_id < node_iterator->node_id)
{ {
util::Log(logDEBUG) << "Found invalid node reference " util::Log(logDEBUG)
<< edge_iterator->result.source; << "Found invalid node reference " << edge_iterator->result.source;
edge_iterator->result.source = SPECIAL_NODEID; edge_iterator->result.source = SPECIAL_NODEID;
++edge_iterator; ++edge_iterator;
continue; continue;
@@ -387,12 +387,16 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
const auto weight = edge_iterator->weight_data(distance); const auto weight = edge_iterator->weight_data(distance);
const auto duration = edge_iterator->duration_data(distance); const auto duration = edge_iterator->duration_data(distance);
const auto accurate_distance =
util::coordinate_calculation::fccApproximateDistance(source_coord, target_coord);
ExtractionSegment segment(source_coord, target_coord, distance, weight, duration); ExtractionSegment segment(source_coord, target_coord, distance, weight, duration);
scripting_environment.ProcessSegment(segment); scripting_environment.ProcessSegment(segment);
auto &edge = edge_iterator->result; auto &edge = edge_iterator->result;
edge.weight = std::max<EdgeWeight>(1, std::round(segment.weight * weight_multiplier)); edge.weight = std::max<EdgeWeight>(1, std::round(segment.weight * weight_multiplier));
edge.duration = std::max<EdgeWeight>(1, std::round(segment.duration * 10.)); edge.duration = std::max<EdgeWeight>(1, std::round(segment.duration * 10.));
edge.distance = accurate_distance;
// assign new node id // assign new node id
const auto node_id = mapExternalToInternalNodeID( const auto node_id = mapExternalToInternalNodeID(
@@ -740,7 +744,6 @@ void ExtractionContainers::PrepareManeuverOverrides()
**/ **/
auto const find_turn_from_way_tofrom_nodes = [&](auto const &from_segment, auto const find_turn_from_way_tofrom_nodes = [&](auto const &from_segment,
auto const &to_segment) { auto const &to_segment) {
if (from_segment.first_segment_source_id == to_segment.first_segment_source_id) if (from_segment.first_segment_source_id == to_segment.first_segment_source_id)
{ {
return NodeBasedTurn{osm_node_to_internal_nbn(from_segment.first_segment_target_id), return NodeBasedTurn{osm_node_to_internal_nbn(from_segment.first_segment_target_id),
@@ -857,7 +860,6 @@ void ExtractionContainers::PrepareManeuverOverrides()
// Later, the UnresolvedManeuverOverride will be converted into a final ManeuverOverride // Later, the UnresolvedManeuverOverride will be converted into a final ManeuverOverride
// once the edge-based-node IDs are generated by the edge-based-graph-factory // once the edge-based-node IDs are generated by the edge-based-graph-factory
const auto transform = [&](const auto &external, auto &internal) { const auto transform = [&](const auto &external, auto &internal) {
// Create a stub override // Create a stub override
auto maneuver_override = auto maneuver_override =
UnresolvedManeuverOverride{{}, UnresolvedManeuverOverride{{},
@@ -1036,8 +1038,9 @@ void ExtractionContainers::PrepareRestrictions()
// translate the turn from one segment onto another into a node restriction (the ways can // translate the turn from one segment onto another into a node restriction (the ways can
// only // only
// be connected at a single location) // be connected at a single location)
auto const get_node_restriction_from_OSM_ids = [&]( auto const get_node_restriction_from_OSM_ids = [&](auto const from_id,
auto const from_id, auto const to_id, const OSMNodeID via_node) { auto const to_id,
const OSMNodeID via_node) {
auto const from_segment_itr = referenced_ways.find(from_id); auto const from_segment_itr = referenced_ways.find(from_id);
if (from_segment_itr->second.way_id != from_id) if (from_segment_itr->second.way_id != from_id)
{ {
+3 -1
View File
@@ -75,7 +75,7 @@ void ExtractorCallbacks::ProcessRestriction(const InputConditionalTurnRestrictio
// util::Log() << restriction.toString(); // util::Log() << restriction.toString();
} }
void ExtractorCallbacks::ProcessManeuverOverride(const InputManeuverOverride & override) void ExtractorCallbacks::ProcessManeuverOverride(const InputManeuverOverride &override)
{ {
external_memory.external_maneuver_overrides_list.push_back(override); external_memory.external_maneuver_overrides_list.push_back(override);
} }
@@ -415,6 +415,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())}, OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
0, // weight 0, // weight
0, // duration 0, // duration
0, // distance
{}, // geometry id {}, // geometry id
static_cast<AnnotationID>(annotation_data_id), static_cast<AnnotationID>(annotation_data_id),
{true, {true,
@@ -450,6 +451,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())}, OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
0, // weight 0, // weight
0, // duration 0, // duration
0, // distance
{}, // geometry id {}, // geometry id
static_cast<AnnotationID>(annotation_data_id), static_cast<AnnotationID>(annotation_data_id),
{false, {false,
+23 -13
View File
@@ -185,17 +185,18 @@ void GraphCompressor::Compress(
* just * just
* like a barrier. * like a barrier.
*/ */
const auto selectAnnotation = [&node_data_container]( const auto selectAnnotation =
const AnnotationID front_annotation, const AnnotationID back_annotation) { [&node_data_container](const AnnotationID front_annotation,
// A lane has tags: u - (front) - v - (back) - w const AnnotationID back_annotation) {
// During contraction, we keep only one of the tags. Usually the one closer // A lane has tags: u - (front) - v - (back) - w
// to the intersection is preferred. If its empty, however, we keep the // During contraction, we keep only one of the tags. Usually the one closer
// non-empty one // to the intersection is preferred. If its empty, however, we keep the
if (node_data_container[back_annotation].lane_description_id == // non-empty one
INVALID_LANE_DESCRIPTIONID) if (node_data_container[back_annotation].lane_description_id ==
return front_annotation; INVALID_LANE_DESCRIPTIONID)
return back_annotation; return front_annotation;
}; return back_annotation;
};
graph.GetEdgeData(forward_e1).annotation_data = selectAnnotation( graph.GetEdgeData(forward_e1).annotation_data = selectAnnotation(
fwd_edge_data1.annotation_data, fwd_edge_data2.annotation_data); fwd_edge_data1.annotation_data, fwd_edge_data2.annotation_data);
@@ -259,6 +260,8 @@ void GraphCompressor::Compress(
const auto forward_weight2 = fwd_edge_data2.weight; const auto forward_weight2 = fwd_edge_data2.weight;
const auto forward_duration1 = fwd_edge_data1.duration; const auto forward_duration1 = fwd_edge_data1.duration;
const auto forward_duration2 = fwd_edge_data2.duration; const auto forward_duration2 = fwd_edge_data2.duration;
// const auto forward_distance1 = fwd_edge_data1.distance;
const auto forward_distance2 = fwd_edge_data2.distance;
BOOST_ASSERT(0 != forward_weight1); BOOST_ASSERT(0 != forward_weight1);
BOOST_ASSERT(0 != forward_weight2); BOOST_ASSERT(0 != forward_weight2);
@@ -267,6 +270,8 @@ void GraphCompressor::Compress(
const auto reverse_weight2 = rev_edge_data2.weight; const auto reverse_weight2 = rev_edge_data2.weight;
const auto reverse_duration1 = rev_edge_data1.duration; const auto reverse_duration1 = rev_edge_data1.duration;
const auto reverse_duration2 = rev_edge_data2.duration; const auto reverse_duration2 = rev_edge_data2.duration;
// const auto reverse_distance1 = rev_edge_data1.distance;
const auto reverse_distance2 = rev_edge_data2.distance;
BOOST_ASSERT(0 != reverse_weight1); BOOST_ASSERT(0 != reverse_weight1);
BOOST_ASSERT(0 != reverse_weight2); BOOST_ASSERT(0 != reverse_weight2);
@@ -279,6 +284,10 @@ void GraphCompressor::Compress(
graph.GetEdgeData(forward_e1).duration += forward_duration2; graph.GetEdgeData(forward_e1).duration += forward_duration2;
graph.GetEdgeData(reverse_e1).duration += reverse_duration2; graph.GetEdgeData(reverse_e1).duration += reverse_duration2;
// add duration of e2's to e1
graph.GetEdgeData(forward_e1).distance += forward_distance2;
graph.GetEdgeData(reverse_e1).distance += reverse_distance2;
if (node_weight_penalty != INVALID_EDGE_WEIGHT && if (node_weight_penalty != INVALID_EDGE_WEIGHT &&
node_duration_penalty != MAXIMAL_EDGE_DURATION) node_duration_penalty != MAXIMAL_EDGE_DURATION)
{ {
@@ -286,6 +295,7 @@ void GraphCompressor::Compress(
graph.GetEdgeData(reverse_e1).weight += node_weight_penalty; graph.GetEdgeData(reverse_e1).weight += node_weight_penalty;
graph.GetEdgeData(forward_e1).duration += node_duration_penalty; graph.GetEdgeData(forward_e1).duration += node_duration_penalty;
graph.GetEdgeData(reverse_e1).duration += node_duration_penalty; graph.GetEdgeData(reverse_e1).duration += node_duration_penalty;
// Note: no penalties for distances
} }
// extend e1's to targets of e2's // extend e1's to targets of e2's
@@ -359,5 +369,5 @@ void GraphCompressor::PrintStatistics(unsigned original_number_of_nodes,
util::Log() << "Node compression ratio: " << new_node_count / (double)original_number_of_nodes; util::Log() << "Node compression ratio: " << new_node_count / (double)original_number_of_nodes;
util::Log() << "Edge compression ratio: " << new_edge_count / (double)original_number_of_edges; util::Log() << "Edge compression ratio: " << new_edge_count / (double)original_number_of_edges;
} }
} } // namespace extractor
} } // namespace osrm
+11 -92
View File
@@ -9,15 +9,12 @@
#include "osrm/trip_parameters.hpp" #include "osrm/trip_parameters.hpp"
#include <exception> #include <exception>
#include <sstream>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include "nodejs/node_osrm.hpp" #include "nodejs/node_osrm.hpp"
#include "nodejs/node_osrm_support.hpp" #include "nodejs/node_osrm_support.hpp"
#include "util/json_renderer.hpp"
namespace node_osrm namespace node_osrm
{ {
@@ -125,8 +122,6 @@ inline void async(const Nan::FunctionCallbackInfo<v8::Value> &info,
if (!params) if (!params)
return; return;
auto pluginParams = argumentsToPluginParameters(info);
BOOST_ASSERT(params->IsValid()); BOOST_ASSERT(params->IsValid());
if (!info[info.Length() - 1]->IsFunction()) if (!info[info.Length() - 1]->IsFunction())
@@ -142,89 +137,9 @@ inline void async(const Nan::FunctionCallbackInfo<v8::Value> &info,
Worker(std::shared_ptr<osrm::OSRM> osrm_, Worker(std::shared_ptr<osrm::OSRM> osrm_,
ParamPtr params_, ParamPtr params_,
ServiceMemFn service, ServiceMemFn service,
Nan::Callback *callback, Nan::Callback *callback)
PluginParameters pluginParams_)
: Base(callback), osrm{std::move(osrm_)}, service{std::move(service)}, : Base(callback), osrm{std::move(osrm_)}, service{std::move(service)},
params{std::move(params_)}, pluginParams{std::move(pluginParams_)} params{std::move(params_)}
{
}
void Execute() override try
{
osrm::json::Object r;
const auto status = ((*osrm).*(service))(*params, r);
ParseResult(status, r);
if (pluginParams.renderJSONToBuffer)
{
std::ostringstream buf;
osrm::util::json::render(buf, r);
result = buf.str();
}
else
{
result = r;
}
}
catch (const std::exception &e)
{
SetErrorMessage(e.what());
}
void HandleOKCallback() override
{
Nan::HandleScope scope;
const constexpr auto argc = 2u;
v8::Local<v8::Value> argv[argc] = {Nan::Null(), render(result)};
callback->Call(argc, argv);
}
// Keeps the OSRM object alive even after shutdown until we're done with callback
std::shared_ptr<osrm::OSRM> osrm;
ServiceMemFn service;
const ParamPtr params;
const PluginParameters pluginParams;
ObjectOrString result;
};
auto *callback = new Nan::Callback{info[info.Length() - 1].As<v8::Function>()};
Nan::AsyncQueueWorker(
new Worker{self->this_, std::move(params), service, callback, std::move(pluginParams)});
}
template <typename ParameterParser, typename ServiceMemFn>
inline void asyncForTiles(const Nan::FunctionCallbackInfo<v8::Value> &info,
ParameterParser argsToParams,
ServiceMemFn service,
bool requires_multiple_coordinates)
{
auto params = argsToParams(info, requires_multiple_coordinates);
if (!params)
return;
auto pluginParams = argumentsToPluginParameters(info);
BOOST_ASSERT(params->IsValid());
if (!info[info.Length() - 1]->IsFunction())
return Nan::ThrowTypeError("last argument must be a callback function");
auto *const self = Nan::ObjectWrap::Unwrap<Engine>(info.Holder());
using ParamPtr = decltype(params);
struct Worker final : Nan::AsyncWorker
{
using Base = Nan::AsyncWorker;
Worker(std::shared_ptr<osrm::OSRM> osrm_,
ParamPtr params_,
ServiceMemFn service,
Nan::Callback *callback,
PluginParameters pluginParams_)
: Base(callback), osrm{std::move(osrm_)}, service{std::move(service)},
params{std::move(params_)}, pluginParams{std::move(pluginParams_)}
{ {
} }
@@ -252,14 +167,18 @@ inline void asyncForTiles(const Nan::FunctionCallbackInfo<v8::Value> &info,
std::shared_ptr<osrm::OSRM> osrm; std::shared_ptr<osrm::OSRM> osrm;
ServiceMemFn service; ServiceMemFn service;
const ParamPtr params; const ParamPtr params;
const PluginParameters pluginParams;
std::string result; // All services return json::Object .. except for Tile!
using ObjectOrString =
typename std::conditional<std::is_same<ParamPtr, tile_parameters_ptr>::value,
std::string,
osrm::json::Object>::type;
ObjectOrString result;
}; };
auto *callback = new Nan::Callback{info[info.Length() - 1].As<v8::Function>()}; auto *callback = new Nan::Callback{info[info.Length() - 1].As<v8::Function>()};
Nan::AsyncQueueWorker( Nan::AsyncQueueWorker(new Worker{self->this_, std::move(params), service, callback});
new Worker{self->this_, std::move(params), service, callback, std::move(pluginParams)});
} }
// clang-format off // clang-format off
@@ -422,7 +341,7 @@ NAN_METHOD(Engine::table) //
// clang-format on // clang-format on
NAN_METHOD(Engine::tile) NAN_METHOD(Engine::tile)
{ {
asyncForTiles(info, &argumentsToTileParameters, &osrm::OSRM::Tile, {/*unused*/}); async(info, &argumentsToTileParameters, &osrm::OSRM::Tile, {/*unused*/});
} }
// clang-format off // clang-format off
+2 -1
View File
@@ -81,7 +81,8 @@ return_code parseArguments(int argc,
"time-zone-file", "time-zone-file",
boost::program_options::value<std::string>(&contractor_config.updater_config.tz_file_path), boost::program_options::value<std::string>(&contractor_config.updater_config.tz_file_path),
"Required for conditional turn restriction parsing, provide a geojson file containing " "Required for conditional turn restriction parsing, provide a geojson file containing "
"time zone boundaries"); "time zone boundaries")("cache-distances",boost::program_options::bool_switch(&contractor_config.cache_distances)->default_value(false),
"Store distances for CH edges, avoiding the need for query-time re-calculation.");
// hidden options, will be allowed on command line, but will not be shown to the user // hidden options, will be allowed on command line, but will not be shown to the user
boost::program_options::options_description hidden_options("Hidden options"); boost::program_options::options_description hidden_options("Hidden options");
+13 -9
View File
@@ -70,8 +70,8 @@ std::istream &operator>>(std::istream &in, EngineConfig::Algorithm &algorithm)
throw util::RuntimeError(token, ErrorCode::UnknownAlgorithm, SOURCE_REF); throw util::RuntimeError(token, ErrorCode::UnknownAlgorithm, SOURCE_REF);
return in; return in;
} }
} // namespace engine }
} // namespace osrm }
// generate boost::program_options object for the routing part // generate boost::program_options object for the routing part
inline unsigned generateServerProgramOptions(const int argc, inline unsigned generateServerProgramOptions(const int argc,
@@ -273,12 +273,10 @@ int main(int argc, const char *argv[]) try
#ifndef _WIN32 #ifndef _WIN32
int sig = 0; int sig = 0;
sigset_t wait_mask; sigset_t new_mask;
sigemptyset(&wait_mask); sigset_t old_mask;
sigaddset(&wait_mask, SIGINT); sigfillset(&new_mask);
sigaddset(&wait_mask, SIGQUIT); pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);
sigaddset(&wait_mask, SIGTERM);
pthread_sigmask(SIG_BLOCK, &wait_mask, nullptr); // only block necessary signals
#endif #endif
auto service_handler = std::make_unique<server::ServiceHandler>(config); auto service_handler = std::make_unique<server::ServiceHandler>(config);
@@ -300,13 +298,19 @@ int main(int argc, const char *argv[]) try
std::thread server_thread(std::move(server_task)); std::thread server_thread(std::move(server_task));
#ifndef _WIN32 #ifndef _WIN32
sigset_t wait_mask;
pthread_sigmask(SIG_SETMASK, &old_mask, nullptr);
sigemptyset(&wait_mask);
sigaddset(&wait_mask, SIGINT);
sigaddset(&wait_mask, SIGQUIT);
sigaddset(&wait_mask, SIGTERM);
pthread_sigmask(SIG_BLOCK, &wait_mask, nullptr);
util::Log() << "running and waiting for requests"; util::Log() << "running and waiting for requests";
if (std::getenv("SIGNAL_PARENT_WHEN_READY")) if (std::getenv("SIGNAL_PARENT_WHEN_READY"))
{ {
kill(getppid(), SIGUSR1); kill(getppid(), SIGUSR1);
} }
sigwait(&wait_mask, &sig); sigwait(&wait_mask, &sig);
util::Log() << "received signal " << sig;
#else #else
// Set console control handler to allow server to be stopped. // Set console control handler to allow server to be stopped.
console_ctrl_function = std::bind(&server::Server::Stop, routing_server); console_ctrl_function = std::bind(&server::Server::Stop, routing_server);
+7 -2
View File
@@ -22,6 +22,11 @@ namespace coordinate_calculation
namespace namespace
{ {
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
const constexpr double EARTH_RADIUS = 6372797.560856;
class CheapRulerContainer class CheapRulerContainer
{ {
public: public:
@@ -112,7 +117,7 @@ double haversineDistance(const Coordinate coordinate_1, const Coordinate coordin
const double aharv = std::pow(std::sin(dlat / 2.0), 2.0) + const double aharv = std::pow(std::sin(dlat / 2.0), 2.0) +
std::cos(dlat1) * std::cos(dlat2) * std::pow(std::sin(dlong / 2.), 2); std::cos(dlat1) * std::cos(dlat2) * std::pow(std::sin(dlong / 2.), 2);
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv)); const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
return detail::EARTH_RADIUS * charv; return EARTH_RADIUS * charv;
} }
double greatCircleDistance(const Coordinate coordinate_1, const Coordinate coordinate_2) double greatCircleDistance(const Coordinate coordinate_1, const Coordinate coordinate_2)
@@ -133,7 +138,7 @@ double greatCircleDistance(const Coordinate coordinate_1, const Coordinate coord
const double x_value = (float_lon2 - float_lon1) * std::cos((float_lat1 + float_lat2) / 2.0); const double x_value = (float_lon2 - float_lon1) * std::cos((float_lat1 + float_lat2) / 2.0);
const double y_value = float_lat2 - float_lat1; const double y_value = float_lat2 - float_lat1;
return std::hypot(x_value, y_value) * detail::EARTH_RADIUS; return std::hypot(x_value, y_value) * EARTH_RADIUS;
} }
double perpendicularDistance(const Coordinate segment_source, double perpendicularDistance(const Coordinate segment_source,
-32
View File
@@ -25,28 +25,6 @@ test('match: match in Monaco', function(assert) {
}); });
}); });
test('match: match in Monaco returning a buffer', function(assert) {
assert.plan(6);
var osrm = new OSRM(data_path);
var options = {
coordinates: three_test_coordinates,
timestamps: [1424684612, 1424684616, 1424684620]
};
osrm.match(options, { format: 'json_buffer' }, function(err, response) {
assert.ifError(err);
assert.ok(response instanceof Buffer);
response = JSON.parse(response);
assert.equal(response.matchings.length, 1);
assert.ok(response.matchings.every(function(m) {
return !!m.distance && !!m.duration && Array.isArray(m.legs) && !!m.geometry && m.confidence > 0;
}))
assert.equal(response.tracepoints.length, 3);
assert.ok(response.tracepoints.every(function(t) {
return !!t.hint && !isNaN(t.matchings_index) && !isNaN(t.waypoint_index) && !!t.name;
}));
});
});
test('match: match in Monaco without timestamps', function(assert) { test('match: match in Monaco without timestamps', function(assert) {
assert.plan(3); assert.plan(3);
var osrm = new OSRM(data_path); var osrm = new OSRM(data_path);
@@ -247,16 +225,6 @@ test('match: throws on invalid tidy param', function(assert) {
/tidy must be of type Boolean/); /tidy must be of type Boolean/);
}); });
test('match: throws on invalid config param', function(assert) {
assert.plan(1);
var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'});
var options = {
coordinates: three_test_coordinates,
};
assert.throws(function() { osrm.match(options, { format: 'invalid' }, function(err, response) {}) },
/format must be a string:/);
});
test('match: match in Monaco without motorways', function(assert) { test('match: match in Monaco without motorways', function(assert) {
assert.plan(3); assert.plan(3);
var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'}); var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'});
+1 -20
View File
@@ -19,21 +19,6 @@ test('nearest', function(assert) {
}); });
}); });
test('nearest', function(assert) {
assert.plan(5);
var osrm = new OSRM(data_path);
osrm.nearest({
coordinates: [three_test_coordinates[0]]
}, { format: 'json_buffer' }, function(err, result) {
assert.ifError(err);
assert.ok(result instanceof Buffer);
result = JSON.parse(result);
assert.equal(result.waypoints.length, 1);
assert.equal(result.waypoints[0].location.length, 2);
assert.ok(result.waypoints[0].hasOwnProperty('name'));
});
});
test('nearest: can ask for multiple nearest pts', function(assert) { test('nearest: can ask for multiple nearest pts', function(assert) {
assert.plan(2); assert.plan(2);
var osrm = new OSRM(data_path); var osrm = new OSRM(data_path);
@@ -47,7 +32,7 @@ test('nearest: can ask for multiple nearest pts', function(assert) {
}); });
test('nearest: throws on invalid args', function(assert) { test('nearest: throws on invalid args', function(assert) {
assert.plan(7); assert.plan(6);
var osrm = new OSRM(data_path); var osrm = new OSRM(data_path);
var options = {}; var options = {};
assert.throws(function() { osrm.nearest(options); }, assert.throws(function() { osrm.nearest(options); },
@@ -67,10 +52,6 @@ test('nearest: throws on invalid args', function(assert) {
options.number = 0; options.number = 0;
assert.throws(function() { osrm.nearest(options, function(err, res) {}); }, assert.throws(function() { osrm.nearest(options, function(err, res) {}); },
/Number must be an integer greater than or equal to 1/); /Number must be an integer greater than or equal to 1/);
options.number = 1;
assert.throws(function() { osrm.nearest(options, { format: 'invalid' }, function(err, res) {}); },
/format must be a string:/);
}); });
test('nearest: nearest in Monaco without motorways', function(assert) { test('nearest: nearest in Monaco without motorways', function(assert) {
+1 -17
View File
@@ -43,22 +43,8 @@ test('route: routes Monaco on CoreCH', function(assert) {
}); });
}); });
test('route: routes Monaco and returns a JSON buffer', function(assert) {
assert.plan(6);
var osrm = new OSRM({path: monaco_corech_path, algorithm: 'CoreCH'});
osrm.route({coordinates: [[13.43864,52.51993],[13.415852,52.513191]]}, { format: 'json_buffer'}, function(err, result) {
assert.ifError(err);
assert.ok(result instanceof Buffer);
const route = JSON.parse(result);
assert.ok(route.waypoints);
assert.ok(route.routes);
assert.ok(route.routes.length);
assert.ok(route.routes[0].geometry);
});
});
test('route: throws with too few or invalid args', function(assert) { test('route: throws with too few or invalid args', function(assert) {
assert.plan(4); assert.plan(3);
var osrm = new OSRM(monaco_path); var osrm = new OSRM(monaco_path);
assert.throws(function() { osrm.route({coordinates: two_test_coordinates}) }, assert.throws(function() { osrm.route({coordinates: two_test_coordinates}) },
/Two arguments required/); /Two arguments required/);
@@ -66,8 +52,6 @@ test('route: throws with too few or invalid args', function(assert) {
/First arg must be an object/); /First arg must be an object/);
assert.throws(function() { osrm.route({coordinates: two_test_coordinates}, true)}, assert.throws(function() { osrm.route({coordinates: two_test_coordinates}, true)},
/last argument must be a callback function/); /last argument must be a callback function/);
assert.throws(function() { osrm.route({coordinates: two_test_coordinates}, { format: 'invalid' }, function(err, route) {})},
/format must be a string:/);
}); });
test('route: provides no alternatives by default, but when requested it may (not guaranteed)', function(assert) { test('route: provides no alternatives by default, but when requested it may (not guaranteed)', function(assert) {
+1 -18
View File
@@ -48,20 +48,6 @@ test('table: test annotations paramater combination', function(assert) {
}); });
}); });
test('table: returns buffer', function(assert) {
assert.plan(3);
var osrm = new OSRM(data_path);
var options = {
coordinates: [three_test_coordinates[0], three_test_coordinates[1]],
};
osrm.table(options, { format: 'json_buffer' }, function(err, table) {
assert.ifError(err);
assert.ok(table instanceof Buffer);
table = JSON.parse(table);
assert.ok(table['durations'], 'distances table result should exist');
});
});
var tables = ['distances', 'durations']; var tables = ['distances', 'durations'];
tables.forEach(function(annotation) { tables.forEach(function(annotation) {
@@ -130,7 +116,7 @@ tables.forEach(function(annotation) {
}); });
test('table: ' + annotation + ' throws on invalid arguments', function(assert) { test('table: ' + annotation + ' throws on invalid arguments', function(assert) {
assert.plan(15); assert.plan(14);
var osrm = new OSRM(data_path); var osrm = new OSRM(data_path);
var options = {annotations: [annotation.slice(0,-1)]}; var options = {annotations: [annotation.slice(0,-1)]};
assert.throws(function() { osrm.table(options); }, assert.throws(function() { osrm.table(options); },
@@ -149,9 +135,6 @@ tables.forEach(function(annotation) {
/Coordinates must be an array of \(lon\/lat\) pairs/); /Coordinates must be an array of \(lon\/lat\) pairs/);
options.coordinates = two_test_coordinates; options.coordinates = two_test_coordinates;
assert.throws(function() { osrm.table(options, { format: 'invalid' }, function(err, response) {}) },
/format must be a string:/);
options.sources = true; options.sources = true;
assert.throws(function() { osrm.table(options, function(err, response) {}) }, assert.throws(function() { osrm.table(options, function(err, response) {}) },
/Sources must be an array of indices \(or undefined\)/); /Sources must be an array of indices \(or undefined\)/);
+1 -16
View File
@@ -17,19 +17,6 @@ test('trip: trip in Monaco', function(assert) {
}); });
}); });
test('trip: trip in Monaco as a buffer', function(assert) {
assert.plan(3);
var osrm = new OSRM(data_path);
osrm.trip({coordinates: two_test_coordinates}, { format: 'json_buffer' }, function(err, trip) {
assert.ifError(err);
assert.ok(trip instanceof Buffer);
trip = JSON.parse(trip);
for (t = 0; t < trip.trips.length; t++) {
assert.ok(trip.trips[t].geometry);
}
});
});
test('trip: trip with many locations in Monaco', function(assert) { test('trip: trip with many locations in Monaco', function(assert) {
assert.plan(2); assert.plan(2);
@@ -46,14 +33,12 @@ test('trip: trip with many locations in Monaco', function(assert) {
}); });
test('trip: throws with too few or invalid args', function(assert) { test('trip: throws with too few or invalid args', function(assert) {
assert.plan(3); assert.plan(2);
var osrm = new OSRM(data_path); var osrm = new OSRM(data_path);
assert.throws(function() { osrm.trip({coordinates: two_test_coordinates}) }, assert.throws(function() { osrm.trip({coordinates: two_test_coordinates}) },
/Two arguments required/); /Two arguments required/);
assert.throws(function() { osrm.trip(null, function(err, trip) {}) }, assert.throws(function() { osrm.trip(null, function(err, trip) {}) },
/First arg must be an object/); /First arg must be an object/);
assert.throws(function() { osrm.trip({coordinates: two_test_coordinates}, { format: 'invalid' }, function(err, trip) {}) },
/format must be a string:/);
}); });
test('trip: throws with bad params', function(assert) { test('trip: throws with bad params', function(assert) {