Port OSRM, Engine and Datafacades to be algorithm aware

This commit is contained in:
Patrick Niklaus
2017-01-09 20:40:33 +00:00
committed by Patrick Niklaus
parent 71e95c92b6
commit 2fa8d0f534
47 changed files with 1384 additions and 1047 deletions
-110
View File
@@ -1,110 +0,0 @@
#include "engine/engine.hpp"
#include "engine/api/route_parameters.hpp"
#include "engine/engine_config.hpp"
#include "engine/status.hpp"
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
#include "engine/datafacade/process_memory_allocator.hpp"
#include "util/log.hpp"
#include <boost/assert.hpp>
#include <algorithm>
#include <fstream>
#include <memory>
#include <utility>
#include <vector>
namespace
{
// Abstracted away the query locking into a template function
// Works the same for every plugin.
template <typename ParameterT, typename PluginT, typename ResultT>
osrm::engine::Status
RunQuery(const std::unique_ptr<osrm::engine::DataWatchdog> &watchdog,
const std::shared_ptr<const osrm::engine::datafacade::BaseDataFacade> &immutable_facade,
const ParameterT &parameters,
PluginT &plugin,
ResultT &result)
{
if (watchdog)
{
BOOST_ASSERT(!immutable_facade);
auto facade = watchdog->GetDataFacade();
return plugin.HandleRequest(facade, parameters, result);
}
BOOST_ASSERT(immutable_facade);
return plugin.HandleRequest(immutable_facade, parameters, result);
}
} // anon. ns
namespace osrm
{
namespace engine
{
Engine::Engine(const EngineConfig &config)
: route_plugin(config.max_locations_viaroute), //
table_plugin(config.max_locations_distance_table), //
nearest_plugin(config.max_results_nearest), //
trip_plugin(config.max_locations_trip), //
match_plugin(config.max_locations_map_matching), //
tile_plugin() //
{
if (config.use_shared_memory)
{
watchdog = std::make_unique<DataWatchdog>();
BOOST_ASSERT(watchdog);
}
else
{
if (!config.storage_config.IsValid())
{
throw util::exception("Invalid file paths given!" + SOURCE_REF);
}
auto allocator =
std::make_unique<datafacade::ProcessMemoryAllocator>(config.storage_config);
immutable_data_facade =
std::make_shared<const datafacade::ContiguousInternalMemoryDataFacade>(
std::move(allocator));
}
}
Status Engine::Route(const api::RouteParameters &params, util::json::Object &result) const
{
return RunQuery(watchdog, immutable_data_facade, params, route_plugin, result);
}
Status Engine::Table(const api::TableParameters &params, util::json::Object &result) const
{
return RunQuery(watchdog, immutable_data_facade, params, table_plugin, result);
}
Status Engine::Nearest(const api::NearestParameters &params, util::json::Object &result) const
{
return RunQuery(watchdog, immutable_data_facade, params, nearest_plugin, result);
}
Status Engine::Trip(const api::TripParameters &params, util::json::Object &result) const
{
return RunQuery(watchdog, immutable_data_facade, params, trip_plugin, result);
}
Status Engine::Match(const api::MatchParameters &params, util::json::Object &result) const
{
return RunQuery(watchdog, immutable_data_facade, params, match_plugin, result);
}
Status Engine::Tile(const api::TileParameters &params, std::string &result) const
{
return RunQuery(watchdog, immutable_data_facade, params, tile_plugin, result);
}
} // engine ns
} // osrm ns
+4 -2
View File
@@ -19,8 +19,10 @@ bool Hint::IsValid(const util::Coordinate new_input_coordinates,
{
auto is_same_input_coordinate = new_input_coordinates.lon == phantom.input_location.lon &&
new_input_coordinates.lat == phantom.input_location.lat;
return is_same_input_coordinate && phantom.IsValid(facade.GetNumberOfNodes()) &&
facade.GetCheckSum() == data_checksum;
// FIXME this does not use the number of nodes to validate the phantom because
// GetNumberOfNodes()
// depends on the graph which is algorithm dependent
return is_same_input_coordinate && phantom.IsValid() && facade.GetCheckSum() == data_checksum;
}
std::string Hint::ToBase64() const
+10 -12
View File
@@ -108,7 +108,8 @@ void filterCandidates(const std::vector<util::Coordinate> &coordinates,
}
}
Status MatchPlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
Status MatchPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFacadeBase &facade,
const RoutingAlgorithmsInterface &algorithms,
const api::MatchParameters &parameters,
util::json::Object &json_result) const
{
@@ -144,7 +145,7 @@ Status MatchPlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDa
if (parameters.radiuses.empty())
{
search_radiuses.resize(parameters.coordinates.size(),
DEFAULT_GPS_PRECISION * RADIUS_MULTIPLIER);
routing_algorithms::DEFAULT_GPS_PRECISION * RADIUS_MULTIPLIER);
}
else
{
@@ -159,13 +160,13 @@ Status MatchPlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDa
}
else
{
return DEFAULT_GPS_PRECISION * RADIUS_MULTIPLIER;
return routing_algorithms::DEFAULT_GPS_PRECISION * RADIUS_MULTIPLIER;
}
});
}
auto candidates_lists = GetPhantomNodesInRange(*facade, parameters, search_radiuses);
auto candidates_lists = GetPhantomNodesInRange(facade, parameters, search_radiuses);
filterCandidates(parameters.coordinates, candidates_lists);
if (std::all_of(candidates_lists.begin(),
@@ -180,11 +181,8 @@ Status MatchPlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDa
}
// call the actual map matching
SubMatchingList sub_matchings = map_matching(facade,
candidates_lists,
parameters.coordinates,
parameters.timestamps,
parameters.radiuses);
SubMatchingList sub_matchings = algorithms.MapMatching(
candidates_lists, parameters.coordinates, parameters.timestamps, parameters.radiuses);
if (sub_matchings.size() == 0)
{
@@ -210,12 +208,12 @@ Status MatchPlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDa
// force uturns to be on, since we split the phantom nodes anyway and only have
// bi-directional
// phantom nodes for possible uturns
shortest_path(
facade, sub_routes[index].segment_end_coordinates, {false}, sub_routes[index]);
algorithms.ShortestRouting(
sub_routes[index].segment_end_coordinates, {false}, sub_routes[index]);
BOOST_ASSERT(sub_routes[index].shortest_path_length != INVALID_EDGE_WEIGHT);
}
api::MatchAPI match_api{*facade, parameters};
api::MatchAPI match_api{facade, parameters};
match_api.MakeResponse(sub_matchings, sub_routes, json_result);
return Status::Ok;
+7 -5
View File
@@ -19,9 +19,11 @@ namespace plugins
NearestPlugin::NearestPlugin(const int max_results_) : max_results{max_results_} {}
Status NearestPlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
const api::NearestParameters &params,
util::json::Object &json_result) const
Status
NearestPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFacadeBase &facade,
const RoutingAlgorithmsInterface & /*algorithms*/,
const api::NearestParameters &params,
util::json::Object &json_result) const
{
BOOST_ASSERT(params.IsValid());
@@ -42,7 +44,7 @@ Status NearestPlugin::HandleRequest(const std::shared_ptr<const datafacade::Base
return Error("InvalidOptions", "Only one input coordinate is supported", json_result);
}
auto phantom_nodes = GetPhantomNodes(*facade, params, params.number_of_results);
auto phantom_nodes = GetPhantomNodes(facade, params, params.number_of_results);
if (phantom_nodes.front().size() == 0)
{
@@ -50,7 +52,7 @@ Status NearestPlugin::HandleRequest(const std::shared_ptr<const datafacade::Base
}
BOOST_ASSERT(phantom_nodes.front().size() > 0);
api::NearestAPI nearest_api(*facade, params);
api::NearestAPI nearest_api(facade, params);
nearest_api.MakeResponse(phantom_nodes, json_result);
return Status::Ok;
+6 -5
View File
@@ -24,11 +24,12 @@ namespace plugins
{
TablePlugin::TablePlugin(const int max_locations_distance_table)
: distance_table(heaps), max_locations_distance_table(max_locations_distance_table)
: max_locations_distance_table(max_locations_distance_table)
{
}
Status TablePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
Status TablePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFacadeBase &facade,
const RoutingAlgorithmsInterface &algorithms,
const api::TableParameters &params,
util::json::Object &result) const
{
@@ -59,16 +60,16 @@ Status TablePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDa
return Error("TooBig", "Too many table coordinates", result);
}
auto snapped_phantoms = SnapPhantomNodes(GetPhantomNodes(*facade, params));
auto snapped_phantoms = SnapPhantomNodes(GetPhantomNodes(facade, params));
auto result_table =
distance_table(facade, snapped_phantoms, params.sources, params.destinations);
algorithms.ManyToManyRouting(snapped_phantoms, params.sources, params.destinations);
if (result_table.empty())
{
return Error("NoTable", "No table found", result);
}
api::TableAPI table_api{*facade, params};
api::TableAPI table_api{facade, params};
table_api.MakeResponse(result_table, snapped_phantoms, result);
return Status::Ok;
+97 -316
View File
@@ -32,8 +32,13 @@ namespace engine
{
namespace plugins
{
constexpr const static int MIN_ZOOM_FOR_TURNS = 15;
namespace
{
using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf;
// TODO: Port all this encoding logic to https://github.com/mapbox/vector-tile, which wasn't
// available when this code was originally written.
@@ -72,33 +77,12 @@ struct point_type_i final
const std::int64_t y;
};
// Used to accumulate all the information we want in the tile about
// a turn.
struct TurnData final
{
TurnData(const util::Coordinate coordinate_,
const std::size_t _in,
const std::size_t _out,
const std::size_t _weight)
: coordinate(std::move(coordinate_)), in_angle_offset(_in), turn_angle_offset(_out),
weight_offset(_weight)
{
}
const util::Coordinate coordinate;
const std::size_t in_angle_offset;
const std::size_t turn_angle_offset;
const std::size_t weight_offset;
};
using FixedPoint = Point<std::int32_t>;
using FloatPoint = Point<double>;
using FixedLine = std::vector<FixedPoint>;
using FloatLine = std::vector<FloatPoint>;
constexpr const static int MIN_ZOOM_FOR_TURNS = 15;
// We use boost::geometry to clip lines/points that are outside or cross the boundary
// of the tile we're rendering. We need these types defined to use boosts clipping
// logic
@@ -247,33 +231,58 @@ FixedPoint coordinatesToTilePoint(const util::Coordinate point, const BBox &tile
return FixedPoint{px, py};
}
} // namespace
Status TilePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
const api::TileParameters &parameters,
std::string &pbf_buffer) const
std::vector<RTreeLeaf> getEdges(const datafacade::ContiguousInternalMemoryDataFacadeBase &facade,
unsigned x,
unsigned y,
unsigned z)
{
BOOST_ASSERT(parameters.IsValid());
double min_lon, min_lat, max_lon, max_lat;
// Convert the z,x,y mercator tile coordinates into WGS84 lon/lat values
//
util::web_mercator::xyzToWGS84(parameters.x,
parameters.y,
parameters.z,
min_lon,
min_lat,
max_lon,
max_lat,
util::web_mercator::TILE_SIZE * 0.10);
util::web_mercator::xyzToWGS84(
x, y, z, min_lon, min_lat, max_lon, max_lat, util::web_mercator::TILE_SIZE * 0.10);
util::Coordinate southwest{util::FloatLongitude{min_lon}, util::FloatLatitude{min_lat}};
util::Coordinate northeast{util::FloatLongitude{max_lon}, util::FloatLatitude{max_lat}};
// Fetch all the segments that are in our bounding box.
// This hits the OSRM StaticRTree
const auto edges = facade->GetEdgesInBox(southwest, northeast);
return facade.GetEdgesInBox(southwest, northeast);
}
std::vector<std::size_t> getEdgeIndex(const std::vector<RTreeLeaf> &edges)
{
// In order to ensure consistent tile encoding, we need to process
// all edges in the same order. Differences in OSX/Linux/Windows
// sorting methods mean that GetEdgesInBox doesn't return the same
// ordered array on all platforms.
// GetEdgesInBox is marked `const`, so we can't sort the array itself,
// instead we create an array of indexes and sort that instead.
std::vector<std::size_t> sorted_edge_indexes(edges.size(), 0);
std::iota(sorted_edge_indexes.begin(), sorted_edge_indexes.end(), 0); // fill with 1,2,3,...N
// Now, sort that array based on the edges list, using the u/v node IDs
// as the sort condition
std::sort(sorted_edge_indexes.begin(),
sorted_edge_indexes.end(),
[&edges](const std::size_t &left, const std::size_t &right) -> bool {
return (edges[left].u != edges[right].u) ? edges[left].u < edges[right].u
: edges[left].v < edges[right].v;
});
return sorted_edge_indexes;
}
void encodeVectorTile(const datafacade::ContiguousInternalMemoryDataFacadeBase &facade,
unsigned x,
unsigned y,
unsigned z,
const std::vector<RTreeLeaf> &edges,
const std::vector<std::size_t> &sorted_edge_indexes,
const std::vector<routing_algorithms::TurnData> &all_turn_data,
std::string &pbf_buffer)
{
// Vector tiles encode properties as references to a common lookup table.
// When we add a property to a "feature", we actually attach the index of the value
@@ -302,7 +311,6 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
std::uint8_t max_datasource_id = 0;
// This is where we accumulate information on turns
std::vector<TurnData> all_turn_data;
// Helper function for adding a new value to the line_ints lookup table. Returns
// the index of the value in the table, adding the value if it doesn't already
@@ -358,260 +366,6 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
return offset;
};
// In order to ensure consistent tile encoding, we need to process
// all edges in the same order. Differences in OSX/Linux/Windows
// sorting methods mean that GetEdgesInBox doesn't return the same
// ordered array on all platforms.
// GetEdgesInBox is marked `const`, so we can't sort the array itself,
// instead we create an array of indexes and sort that instead.
std::vector<std::size_t> sorted_edge_indexes(edges.size(), 0);
std::iota(sorted_edge_indexes.begin(), sorted_edge_indexes.end(), 0); // fill with 1,2,3,...N
// Now, sort that array based on the edges list, using the u/v node IDs
// as the sort condition
std::sort(sorted_edge_indexes.begin(),
sorted_edge_indexes.end(),
[&edges](const std::size_t &left, const std::size_t &right) -> bool {
return (edges[left].u != edges[right].u) ? edges[left].u < edges[right].u
: edges[left].v < edges[right].v;
});
// From here on, we'll iterate over the sorted_edge_indexes instead of `edges` directly.
// Note, that we do this because `
// If we're zooming into 16 or higher, include turn data. Why? Because turns make the map
// really cramped, so we don't bother including the data for tiles that span a large area.
if (parameters.z >= MIN_ZOOM_FOR_TURNS)
{
// Struct to hold info on all the EdgeBasedNodes that are visible in our tile
// When we create these, we insure that (source, target) and packed_geometry_id
// are all pointed in the same direction.
struct EdgeBasedNodeInfo
{
bool is_geometry_forward; // Is the geometry forward or reverse?
unsigned packed_geometry_id;
};
// Lookup table for edge-based-nodes
std::unordered_map<NodeID, EdgeBasedNodeInfo> edge_based_node_info;
struct SegmentData
{
NodeID target_node;
EdgeID edge_based_node_id;
};
std::unordered_map<NodeID, std::vector<SegmentData>> directed_graph;
// Reserve enough space for unique edge-based-nodes on every edge.
// Only a tile with all unique edges will use this much, but
// it saves us a bunch of re-allocations during iteration.
directed_graph.reserve(edges.size() * 2);
// Build an adjacency list for all the road segments visible in
// the tile
for (const auto &edge_index : sorted_edge_indexes)
{
const auto &edge = edges[edge_index];
if (edge.forward_segment_id.enabled)
{
// operator[] will construct an empty vector at [edge.u] if there is no value.
directed_graph[edge.u].push_back({edge.v, edge.forward_segment_id.id});
if (edge_based_node_info.count(edge.forward_segment_id.id) == 0)
{
edge_based_node_info[edge.forward_segment_id.id] = {true,
edge.packed_geometry_id};
}
else
{
BOOST_ASSERT(
edge_based_node_info[edge.forward_segment_id.id].is_geometry_forward ==
true);
BOOST_ASSERT(
edge_based_node_info[edge.forward_segment_id.id].packed_geometry_id ==
edge.packed_geometry_id);
}
}
if (edge.reverse_segment_id.enabled)
{
directed_graph[edge.v].push_back({edge.u, edge.reverse_segment_id.id});
if (edge_based_node_info.count(edge.reverse_segment_id.id) == 0)
{
edge_based_node_info[edge.reverse_segment_id.id] = {false,
edge.packed_geometry_id};
}
else
{
BOOST_ASSERT(
edge_based_node_info[edge.reverse_segment_id.id].is_geometry_forward ==
false);
BOOST_ASSERT(
edge_based_node_info[edge.reverse_segment_id.id].packed_geometry_id ==
edge.packed_geometry_id);
}
}
}
// Given a turn:
// u---v
// |
// w
// uv is the "approach"
// vw is the "exit"
std::vector<contractor::QueryEdge::EdgeData> unpacked_shortcut;
std::vector<EdgeWeight> approach_weight_vector;
// Make sure we traverse the startnodes in a consistent order
// to ensure identical PBF encoding on all platforms.
std::vector<NodeID> sorted_startnodes;
sorted_startnodes.reserve(directed_graph.size());
for (const auto &startnode : directed_graph)
sorted_startnodes.push_back(startnode.first);
std::sort(sorted_startnodes.begin(), sorted_startnodes.end());
// Look at every node in the directed graph we created
for (const auto &startnode : sorted_startnodes)
{
const auto &nodedata = directed_graph[startnode];
// For all the outgoing edges from the node
for (const auto &approachedge : nodedata)
{
// If the target of this edge doesn't exist in our directed
// graph, it's probably outside the tile, so we can skip it
if (directed_graph.count(approachedge.target_node) == 0)
continue;
// For each of the outgoing edges from our target coordinate
for (const auto &exit_edge : directed_graph[approachedge.target_node])
{
// If the next edge has the same edge_based_node_id, then it's
// not a turn, so skip it
if (approachedge.edge_based_node_id == exit_edge.edge_based_node_id)
continue;
// Skip u-turns
if (startnode == exit_edge.target_node)
continue;
// Find the connection between our source road and the target node
// Since we only want to find direct edges, we cannot check shortcut edges here.
// Otherwise we might find a forward edge even though a shorter backward edge
// exists (due to oneways).
//
// a > - > - > - b
// | |
// |------ c ----|
//
// would offer a backward edge at `b` to `a` (due to the oneway from a to b)
// but could also offer a shortcut (b-c-a) from `b` to `a` which is longer.
EdgeID smaller_edge_id =
facade->FindSmallestEdge(approachedge.edge_based_node_id,
exit_edge.edge_based_node_id,
[](const contractor::QueryEdge::EdgeData &data) {
return data.forward && !data.shortcut;
});
// Depending on how the graph is constructed, we might have to look for
// a backwards edge instead. They're equivalent, just one is available for
// a forward routing search, and one is used for the backwards dijkstra
// steps. Their weight should be the same, we can use either one.
// If we didn't find a forward edge, try for a backward one
if (SPECIAL_EDGEID == smaller_edge_id)
{
smaller_edge_id = facade->FindSmallestEdge(
exit_edge.edge_based_node_id,
approachedge.edge_based_node_id,
[](const contractor::QueryEdge::EdgeData &data) {
return data.backward && !data.shortcut;
});
}
// If no edge was found, it means that there's no connection between these
// nodes, due to oneways or turn restrictions. Given the edge-based-nodes
// that we're examining here, we *should* only find directly-connected
// edges, not shortcuts
if (smaller_edge_id != SPECIAL_EDGEID)
{
const auto &data = facade->GetEdgeData(smaller_edge_id);
BOOST_ASSERT_MSG(!data.shortcut, "Connecting edge must not be a shortcut");
// Now, calculate the sum of the weight of all the segments.
if (edge_based_node_info[approachedge.edge_based_node_id]
.is_geometry_forward)
{
approach_weight_vector = facade->GetUncompressedForwardWeights(
edge_based_node_info[approachedge.edge_based_node_id]
.packed_geometry_id);
}
else
{
approach_weight_vector = facade->GetUncompressedReverseWeights(
edge_based_node_info[approachedge.edge_based_node_id]
.packed_geometry_id);
}
const auto sum_node_weight = std::accumulate(approach_weight_vector.begin(),
approach_weight_vector.end(),
EdgeWeight{0});
// The edge.weight is the whole edge weight, which includes the turn
// cost.
// The turn cost is the edge.weight minus the sum of the individual road
// segment weights. This might not be 100% accurate, because some
// intersections include stop signs, traffic signals and other
// penalties, but at this stage, we can't divide those out, so we just
// treat the whole lot as the "turn cost" that we'll stick on the map.
const auto turn_cost = data.weight - sum_node_weight;
// Find the three nodes that make up the turn movement)
const auto node_from = startnode;
const auto node_via = approachedge.target_node;
const auto node_to = exit_edge.target_node;
const auto coord_from = facade->GetCoordinateOfNode(node_from);
const auto coord_via = facade->GetCoordinateOfNode(node_via);
const auto coord_to = facade->GetCoordinateOfNode(node_to);
// Calculate the bearing that we approach the intersection at
const auto angle_in = static_cast<int>(
util::coordinate_calculation::bearing(coord_from, coord_via));
// Add the angle to the values table for the vector tile, and get the
// index
// of that value in the table
const auto angle_in_index = use_point_int_value(angle_in);
// Calculate the bearing leading away from the intersection
const auto exit_bearing = static_cast<int>(
util::coordinate_calculation::bearing(coord_via, coord_to));
// Figure out the angle of the turn
auto turn_angle = exit_bearing - angle_in;
while (turn_angle > 180)
{
turn_angle -= 360;
}
while (turn_angle < -180)
{
turn_angle += 360;
}
// Add the turn angle value to the value lookup table for the vector
// tile.
const auto turn_angle_index = use_point_int_value(turn_angle);
// And, same for the actual turn cost value - it goes in the lookup
// table,
// not directly on the feature itself.
const auto turn_cost_index = use_point_float_value(
turn_cost / 10.0); // Note conversion to float here
// Save everything we need to later add all the points to the tile.
// We need the coordinate of the intersection, the angle in, the turn
// angle and the turn cost.
all_turn_data.emplace_back(
coord_via, angle_in_index, turn_angle_index, turn_cost_index);
}
}
}
}
}
// Vector tiles encode feature properties as indexes into a lookup table. So, we need
// to "pre-loop" over all the edges to create the lookup tables. Once we have those, we
// can then encode the features, and we'll know the indexes that feature properties
@@ -621,9 +375,9 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
const auto &edge = edges[edge_index];
const auto forward_datasource_vector =
facade->GetUncompressedForwardDatasources(edge.packed_geometry_id);
facade.GetUncompressedForwardDatasources(edge.packed_geometry_id);
const auto reverse_datasource_vector =
facade->GetUncompressedReverseDatasources(edge.packed_geometry_id);
facade.GetUncompressedReverseDatasources(edge.packed_geometry_id);
BOOST_ASSERT(edge.fwd_segment_position < forward_datasource_vector.size());
const auto forward_datasource = forward_datasource_vector[edge.fwd_segment_position];
@@ -639,13 +393,8 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
// Convert tile coordinates into mercator coordinates
double min_mercator_lon, min_mercator_lat, max_mercator_lon, max_mercator_lat;
util::web_mercator::xyzToMercator(parameters.x,
parameters.y,
parameters.z,
min_mercator_lon,
min_mercator_lat,
max_mercator_lon,
max_mercator_lat);
util::web_mercator::xyzToMercator(
x, y, z, min_mercator_lon, min_mercator_lat, max_mercator_lon, max_mercator_lat);
const BBox tile_bbox{min_mercator_lon, min_mercator_lat, max_mercator_lon, max_mercator_lat};
// Protobuf serializes blocks when objects go out of scope, hence
@@ -673,9 +422,9 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
{
const auto &edge = edges[edge_index];
const auto forward_weight_vector =
facade->GetUncompressedForwardWeights(edge.packed_geometry_id);
facade.GetUncompressedForwardWeights(edge.packed_geometry_id);
const auto reverse_weight_vector =
facade->GetUncompressedReverseWeights(edge.packed_geometry_id);
facade.GetUncompressedReverseWeights(edge.packed_geometry_id);
const auto forward_weight = forward_weight_vector[edge.fwd_segment_position];
const auto reverse_weight = reverse_weight_vector[reverse_weight_vector.size() -
edge.fwd_segment_position - 1];
@@ -691,20 +440,20 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
{
const auto &edge = edges[edge_index];
// Get coordinates for start/end nodes of segment (NodeIDs u and v)
const auto a = facade->GetCoordinateOfNode(edge.u);
const auto b = facade->GetCoordinateOfNode(edge.v);
const auto a = facade.GetCoordinateOfNode(edge.u);
const auto b = facade.GetCoordinateOfNode(edge.v);
// Calculate the length in meters
const double length =
osrm::util::coordinate_calculation::haversineDistance(a, b);
const auto forward_weight_vector =
facade->GetUncompressedForwardWeights(edge.packed_geometry_id);
facade.GetUncompressedForwardWeights(edge.packed_geometry_id);
const auto reverse_weight_vector =
facade->GetUncompressedReverseWeights(edge.packed_geometry_id);
facade.GetUncompressedReverseWeights(edge.packed_geometry_id);
const auto forward_datasource_vector =
facade->GetUncompressedForwardDatasources(edge.packed_geometry_id);
facade.GetUncompressedForwardDatasources(edge.packed_geometry_id);
const auto reverse_datasource_vector =
facade->GetUncompressedReverseDatasources(edge.packed_geometry_id);
facade.GetUncompressedReverseDatasources(edge.packed_geometry_id);
const auto forward_weight = forward_weight_vector[edge.fwd_segment_position];
const auto reverse_weight =
reverse_weight_vector[reverse_weight_vector.size() -
@@ -715,7 +464,7 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
reverse_datasource_vector[reverse_datasource_vector.size() -
edge.fwd_segment_position - 1];
auto name = facade->GetNameForID(edge.name_id);
auto name = facade.GetNameForID(edge.name_id);
const auto name_offset = [&name, &names, &name_offsets]() {
auto iter = name_offsets.find(name);
@@ -875,7 +624,7 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
util::vector_tile::VARIANT_TAG);
// Attribute value 1 == string type
values_writer.add_string(util::vector_tile::VARIANT_TYPE_STRING,
facade->GetDatasourceName(i).to_string());
facade.GetDatasourceName(i).to_string());
}
for (auto value : used_line_ints)
{
@@ -918,8 +667,9 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
int id = 1;
// Helper function to encode a new point feature on a vector tile.
const auto encode_tile_point = [&point_layer_writer, &used_point_ints, &id](
const FixedPoint &tile_point, const TurnData &point_turn_data) {
const auto encode_tile_point = [&](
const FixedPoint &tile_point,
const routing_algorithms::TurnData &point_turn_data) {
protozero::pbf_writer feature_writer(point_layer_writer,
util::vector_tile::FEATURE_TAG);
// Field 3 is the "geometry type" field. Value 1 is "point"
@@ -928,17 +678,23 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
util::vector_tile::GEOMETRY_TYPE_POINT); // geometry type
feature_writer.add_uint64(util::vector_tile::ID_TAG, id++); // id
{
const auto in_angle_offset = use_point_int_value(point_turn_data.in_angle);
const auto turn_angle_offset =
use_point_int_value(point_turn_data.turn_angle);
const auto weight_offset = use_point_float_value(
point_turn_data.weight / 10.0); // Note conversion to float here
// Write out the 3 properties we want on the feature. These
// refer to indexes in the properties lookup table, which we
// add to the tile after we add all features.
protozero::packed_field_uint32 field(
feature_writer, util::vector_tile::FEATURE_ATTRIBUTES_TAG);
field.add_element(0); // "bearing_in" tag key offset
field.add_element(point_turn_data.in_angle_offset);
field.add_element(in_angle_offset);
field.add_element(1); // "turn_angle" tag key offset
field.add_element(point_turn_data.turn_angle_offset);
field.add_element(turn_angle_offset);
field.add_element(2); // "cost" tag key offset
field.add_element(used_point_ints.size() + point_turn_data.weight_offset);
field.add_element(used_point_ints.size() + weight_offset);
}
{
// Add the geometry as the last field in this feature
@@ -983,6 +739,31 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
}
// protozero serializes data during object destructors, so once the scope closes,
// our result buffer will have all the tile data encoded into it.
}
}
Status TilePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFacadeBase &facade,
const RoutingAlgorithmsInterface &algorithms,
const api::TileParameters &parameters,
std::string &pbf_buffer) const
{
BOOST_ASSERT(parameters.IsValid());
auto edges = getEdges(facade, parameters.x, parameters.y, parameters.y);
auto edge_index = getEdgeIndex(edges);
std::vector<routing_algorithms::TurnData> turns;
// If we're zooming into 16 or higher, include turn data. Why? Because turns make the map
// really cramped, so we don't bother including the data for tiles that span a large area.
if (parameters.z >= MIN_ZOOM_FOR_TURNS)
{
turns = algorithms.TileTurns(edges, edge_index);
}
encodeVectorTile(
facade, parameters.x, parameters.y, parameters.y, edges, edge_index, turns, pbf_buffer);
return Status::Ok;
}
+12 -11
View File
@@ -52,11 +52,10 @@ bool IsSupportedParameterCombination(const bool fixed_start,
// given the node order in which to visit, compute the actual route (with geometry, travel time and
// so on) and return the result
InternalRouteResult
TripPlugin::ComputeRoute(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
const std::vector<PhantomNode> &snapped_phantoms,
const std::vector<NodeID> &trip,
const bool roundtrip) const
InternalRouteResult TripPlugin::ComputeRoute(const RoutingAlgorithmsInterface &algorithms,
const std::vector<PhantomNode> &snapped_phantoms,
const std::vector<NodeID> &trip,
const bool roundtrip) const
{
InternalRouteResult min_route;
// given the final trip, compute total duration and return the route and location permutation
@@ -86,7 +85,7 @@ TripPlugin::ComputeRoute(const std::shared_ptr<const datafacade::BaseDataFacade>
BOOST_ASSERT(min_route.segment_end_coordinates.size() == trip.size() - 1);
}
shortest_path(facade, min_route.segment_end_coordinates, {false}, min_route);
algorithms.ShortestRouting(min_route.segment_end_coordinates, {false}, min_route);
BOOST_ASSERT_MSG(min_route.shortest_path_length < INVALID_EDGE_WEIGHT, "unroutable route");
return min_route;
}
@@ -143,7 +142,8 @@ void ManipulateTableForFSE(const std::size_t source_id,
//********* End of changes to table *************************************
}
Status TripPlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
Status TripPlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFacadeBase &facade,
const RoutingAlgorithmsInterface &algorithms,
const api::TripParameters &parameters,
util::json::Object &json_result) const
{
@@ -179,7 +179,7 @@ Status TripPlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
return Error("InvalidValue", "Invalid coordinate value.", json_result);
}
auto phantom_node_pairs = GetPhantomNodes(*facade, parameters);
auto phantom_node_pairs = GetPhantomNodes(facade, parameters);
if (phantom_node_pairs.size() != number_of_locations)
{
return Error("NoSegment",
@@ -201,7 +201,7 @@ Status TripPlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
// compute the duration table of all phantom nodes
auto result_table = util::DistTableWrapper<EdgeWeight>(
duration_table(facade, snapped_phantoms, {}, {}), number_of_locations);
algorithms.ManyToManyRouting(snapped_phantoms, {}, {}), number_of_locations);
if (result_table.size() == 0)
{
@@ -250,12 +250,13 @@ Status TripPlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDat
}
// get the route when visiting all destinations in optimized order
InternalRouteResult route = ComputeRoute(facade, snapped_phantoms, trip, parameters.roundtrip);
InternalRouteResult route =
ComputeRoute(algorithms, snapped_phantoms, trip, parameters.roundtrip);
// get api response
const std::vector<std::vector<NodeID>> trips = {trip};
const std::vector<InternalRouteResult> routes = {route};
api::TripAPI trip_api{*facade, parameters};
api::TripAPI trip_api{facade, parameters};
trip_api.MakeResponse(trips, routes, snapped_phantoms, json_result);
return Status::Ok;
+15 -16
View File
@@ -1,6 +1,6 @@
#include "engine/plugins/viaroute.hpp"
#include "engine/api/route_api.hpp"
#include "engine/datafacade/datafacade_base.hpp"
#include "engine/routing_algorithms.hpp"
#include "engine/status.hpp"
#include "util/for_each_pair.hpp"
@@ -22,14 +22,15 @@ namespace plugins
{
ViaRoutePlugin::ViaRoutePlugin(int max_locations_viaroute)
: shortest_path(heaps), alternative_path(heaps), direct_shortest_path(heaps),
max_locations_viaroute(max_locations_viaroute)
: max_locations_viaroute(max_locations_viaroute)
{
}
Status ViaRoutePlugin::HandleRequest(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
const api::RouteParameters &route_parameters,
util::json::Object &json_result) const
Status
ViaRoutePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFacadeBase &facade,
const RoutingAlgorithmsInterface &algorithms,
const api::RouteParameters &route_parameters,
util::json::Object &json_result) const
{
BOOST_ASSERT(route_parameters.IsValid());
@@ -48,7 +49,7 @@ Status ViaRoutePlugin::HandleRequest(const std::shared_ptr<const datafacade::Bas
return Error("InvalidValue", "Invalid coordinate value.", json_result);
}
auto phantom_node_pairs = GetPhantomNodes(*facade, route_parameters);
auto phantom_node_pairs = GetPhantomNodes(facade, route_parameters);
if (phantom_node_pairs.size() != route_parameters.coordinates.size())
{
return Error("NoSegment",
@@ -62,7 +63,7 @@ Status ViaRoutePlugin::HandleRequest(const std::shared_ptr<const datafacade::Bas
const bool continue_straight_at_waypoint = route_parameters.continue_straight
? *route_parameters.continue_straight
: facade->GetContinueStraightDefault();
: facade.GetContinueStraightDefault();
InternalRouteResult raw_route;
auto build_phantom_pairs = [&raw_route, continue_straight_at_waypoint](
@@ -86,28 +87,26 @@ Status ViaRoutePlugin::HandleRequest(const std::shared_ptr<const datafacade::Bas
if (1 == raw_route.segment_end_coordinates.size())
{
if (route_parameters.alternatives && facade->GetCoreSize() == 0)
if (route_parameters.alternatives && algorithms.HasAlternativeRouting())
{
alternative_path(facade, raw_route.segment_end_coordinates.front(), raw_route);
algorithms.AlternativeRouting(raw_route.segment_end_coordinates.front(), raw_route);
}
else
{
direct_shortest_path(facade, raw_route.segment_end_coordinates, raw_route);
algorithms.DirectShortestPathRouting(raw_route.segment_end_coordinates, raw_route);
}
}
else
{
shortest_path(facade,
raw_route.segment_end_coordinates,
route_parameters.continue_straight,
raw_route);
algorithms.ShortestRouting(
raw_route.segment_end_coordinates, route_parameters.continue_straight, raw_route);
}
// we can only know this after the fact, different SCC ids still
// allow for connection in one direction.
if (raw_route.is_valid())
{
api::RouteAPI route_api{*facade, route_parameters};
api::RouteAPI route_api{facade, route_parameters};
route_api.MakeResponse(raw_route, json_result);
}
else
@@ -7,9 +7,9 @@ namespace engine
namespace routing_algorithms
{
void AlternativeRouting::operator()(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
const PhantomNodes &phantom_node_pair,
InternalRouteResult &raw_route_data)
void AlternativeRouting<algorithm::CH>::operator()(const FacadeT &facade,
const PhantomNodes &phantom_node_pair,
InternalRouteResult &raw_route_data)
{
std::vector<NodeID> alternative_path;
std::vector<NodeID> via_node_candidate_list;
@@ -17,9 +17,9 @@ void AlternativeRouting::operator()(const std::shared_ptr<const datafacade::Base
std::vector<SearchSpaceEdge> reverse_search_space;
// Init queues, semi-expensive because access to TSS invokes a sys-call
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade->GetNumberOfNodes());
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade->GetNumberOfNodes());
engine_working_data.InitializeOrClearThirdThreadLocalStorage(facade->GetNumberOfNodes());
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
engine_working_data.InitializeOrClearThirdThreadLocalStorage(facade.GetNumberOfNodes());
QueryHeap &forward_heap1 = *(engine_working_data.forward_heap_1);
QueryHeap &reverse_heap1 = *(engine_working_data.reverse_heap_1);
@@ -320,13 +320,14 @@ void AlternativeRouting::operator()(const std::shared_ptr<const datafacade::Base
}
}
void AlternativeRouting::RetrievePackedAlternatePath(const QueryHeap &forward_heap1,
const QueryHeap &reverse_heap1,
const QueryHeap &forward_heap2,
const QueryHeap &reverse_heap2,
const NodeID s_v_middle,
const NodeID v_t_middle,
std::vector<NodeID> &packed_path) const
void AlternativeRouting<algorithm::CH>::RetrievePackedAlternatePath(
const QueryHeap &forward_heap1,
const QueryHeap &reverse_heap1,
const QueryHeap &forward_heap2,
const QueryHeap &reverse_heap2,
const NodeID s_v_middle,
const NodeID v_t_middle,
std::vector<NodeID> &packed_path) const
{
// fetch packed path [s,v)
std::vector<NodeID> packed_v_t_path;
@@ -343,15 +344,15 @@ void AlternativeRouting::RetrievePackedAlternatePath(const QueryHeap &forward_he
// compute and unpack <s,..,v> and <v,..,t> by exploring search spaces
// from v and intersecting against queues. only half-searches have to be
// done at this stage
void AlternativeRouting::ComputeLengthAndSharingOfViaPath(
const std::shared_ptr<const datafacade::BaseDataFacade> facade,
void AlternativeRouting<algorithm::CH>::ComputeLengthAndSharingOfViaPath(
const FacadeT &facade,
const NodeID via_node,
int *real_length_of_via_path,
int *sharing_of_via_path,
const std::vector<NodeID> &packed_shortest_path,
const EdgeWeight min_edge_offset)
{
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade->GetNumberOfNodes());
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
QueryHeap &existing_forward_heap = *engine_working_data.forward_heap_1;
QueryHeap &existing_reverse_heap = *engine_working_data.reverse_heap_1;
@@ -422,9 +423,9 @@ void AlternativeRouting::ComputeLengthAndSharingOfViaPath(
if (packed_s_v_path[current_node] == packed_shortest_path[current_node] &&
packed_s_v_path[current_node + 1] == packed_shortest_path[current_node + 1])
{
EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_s_v_path[current_node],
packed_s_v_path[current_node + 1]);
*sharing_of_via_path += facade->GetEdgeData(edgeID).weight;
EdgeID edgeID = facade.FindEdgeInEitherDirection(packed_s_v_path[current_node],
packed_s_v_path[current_node + 1]);
*sharing_of_via_path += facade.GetEdgeData(edgeID).weight;
}
else
{
@@ -455,9 +456,9 @@ void AlternativeRouting::ComputeLengthAndSharingOfViaPath(
++current_node)
{
EdgeID selected_edge =
facade->FindEdgeInEitherDirection(partially_unpacked_via_path[current_node],
partially_unpacked_via_path[current_node + 1]);
*sharing_of_via_path += facade->GetEdgeData(selected_edge).weight;
facade.FindEdgeInEitherDirection(partially_unpacked_via_path[current_node],
partially_unpacked_via_path[current_node + 1]);
*sharing_of_via_path += facade.GetEdgeData(selected_edge).weight;
}
// Second, partially unpack v-->t in reverse order until paths deviate and note lengths
@@ -468,9 +469,9 @@ void AlternativeRouting::ComputeLengthAndSharingOfViaPath(
if (packed_v_t_path[via_path_index - 1] == packed_shortest_path[shortest_path_index - 1] &&
packed_v_t_path[via_path_index] == packed_shortest_path[shortest_path_index])
{
EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_v_t_path[via_path_index - 1],
packed_v_t_path[via_path_index]);
*sharing_of_via_path += facade->GetEdgeData(edgeID).weight;
EdgeID edgeID = facade.FindEdgeInEitherDirection(packed_v_t_path[via_path_index - 1],
packed_v_t_path[via_path_index]);
*sharing_of_via_path += facade.GetEdgeData(edgeID).weight;
}
else
{
@@ -499,9 +500,9 @@ void AlternativeRouting::ComputeLengthAndSharingOfViaPath(
partially_unpacked_shortest_path[shortest_path_index])
{
EdgeID edgeID =
facade->FindEdgeInEitherDirection(partially_unpacked_via_path[via_path_index - 1],
partially_unpacked_via_path[via_path_index]);
*sharing_of_via_path += facade->GetEdgeData(edgeID).weight;
facade.FindEdgeInEitherDirection(partially_unpacked_via_path[via_path_index - 1],
partially_unpacked_via_path[via_path_index]);
*sharing_of_via_path += facade.GetEdgeData(edgeID).weight;
}
else
{
@@ -513,8 +514,8 @@ void AlternativeRouting::ComputeLengthAndSharingOfViaPath(
}
// conduct T-Test
bool AlternativeRouting::ViaNodeCandidatePassesTTest(
const std::shared_ptr<const datafacade::BaseDataFacade> facade,
bool AlternativeRouting<algorithm::CH>::ViaNodeCandidatePassesTTest(
const FacadeT &facade,
QueryHeap &existing_forward_heap,
QueryHeap &existing_reverse_heap,
QueryHeap &new_forward_heap,
@@ -606,8 +607,8 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest(
for (std::size_t i = packed_s_v_path.size() - 1; (i > 0) && unpack_stack.empty(); --i)
{
const EdgeID current_edge_id =
facade->FindEdgeInEitherDirection(packed_s_v_path[i - 1], packed_s_v_path[i]);
const EdgeWeight length_of_current_edge = facade->GetEdgeData(current_edge_id).weight;
facade.FindEdgeInEitherDirection(packed_s_v_path[i - 1], packed_s_v_path[i]);
const EdgeWeight length_of_current_edge = facade.GetEdgeData(current_edge_id).weight;
if ((length_of_current_edge + unpacked_until_weight) >= T_threshold)
{
unpack_stack.emplace(packed_s_v_path[i - 1], packed_s_v_path[i]);
@@ -624,21 +625,21 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest(
const SearchSpaceEdge via_path_edge = unpack_stack.top();
unpack_stack.pop();
EdgeID edge_in_via_path_id =
facade->FindEdgeInEitherDirection(via_path_edge.first, via_path_edge.second);
facade.FindEdgeInEitherDirection(via_path_edge.first, via_path_edge.second);
if (SPECIAL_EDGEID == edge_in_via_path_id)
{
return false;
}
const EdgeData &current_edge_data = facade->GetEdgeData(edge_in_via_path_id);
const EdgeData &current_edge_data = facade.GetEdgeData(edge_in_via_path_id);
const bool current_edge_is_shortcut = current_edge_data.shortcut;
if (current_edge_is_shortcut)
{
const NodeID via_path_middle_node_id = current_edge_data.id;
const EdgeID second_segment_edge_id =
facade->FindEdgeInEitherDirection(via_path_middle_node_id, via_path_edge.second);
const int second_segment_length = facade->GetEdgeData(second_segment_edge_id).weight;
facade.FindEdgeInEitherDirection(via_path_middle_node_id, via_path_edge.second);
const int second_segment_length = facade.GetEdgeData(second_segment_edge_id).weight;
// attention: !unpacking in reverse!
// Check if second segment is the one to go over treshold? if yes add second segment
// to stack, else push first segment to stack and add weight of second one.
@@ -669,8 +670,8 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest(
++i)
{
const EdgeID edgeID =
facade->FindEdgeInEitherDirection(packed_v_t_path[i], packed_v_t_path[i + 1]);
int length_of_current_edge = facade->GetEdgeData(edgeID).weight;
facade.FindEdgeInEitherDirection(packed_v_t_path[i], packed_v_t_path[i + 1]);
int length_of_current_edge = facade.GetEdgeData(edgeID).weight;
if (length_of_current_edge + unpacked_until_weight >= T_threshold)
{
unpack_stack.emplace(packed_v_t_path[i], packed_v_t_path[i + 1]);
@@ -687,20 +688,20 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest(
const SearchSpaceEdge via_path_edge = unpack_stack.top();
unpack_stack.pop();
EdgeID edge_in_via_path_id =
facade->FindEdgeInEitherDirection(via_path_edge.first, via_path_edge.second);
facade.FindEdgeInEitherDirection(via_path_edge.first, via_path_edge.second);
if (SPECIAL_EDGEID == edge_in_via_path_id)
{
return false;
}
const EdgeData &current_edge_data = facade->GetEdgeData(edge_in_via_path_id);
const EdgeData &current_edge_data = facade.GetEdgeData(edge_in_via_path_id);
const bool IsViaEdgeShortCut = current_edge_data.shortcut;
if (IsViaEdgeShortCut)
{
const NodeID middleOfViaPath = current_edge_data.id;
EdgeID edgeIDOfFirstSegment =
facade->FindEdgeInEitherDirection(via_path_edge.first, middleOfViaPath);
int lengthOfFirstSegment = facade->GetEdgeData(edgeIDOfFirstSegment).weight;
facade.FindEdgeInEitherDirection(via_path_edge.first, middleOfViaPath);
int lengthOfFirstSegment = facade.GetEdgeData(edgeIDOfFirstSegment).weight;
// Check if first segment is the one to go over treshold? if yes first segment to
// stack, else push second segment to stack and add weight of first one.
if (unpacked_until_weight + lengthOfFirstSegment >= T_threshold)
@@ -723,7 +724,7 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest(
t_test_path_length += unpacked_until_weight;
// Run actual T-Test query and compare if weight equal.
engine_working_data.InitializeOrClearThirdThreadLocalStorage(facade->GetNumberOfNodes());
engine_working_data.InitializeOrClearThirdThreadLocalStorage(facade.GetNumberOfNodes());
QueryHeap &forward_heap3 = *engine_working_data.forward_heap_3;
QueryHeap &reverse_heap3 = *engine_working_data.reverse_heap_3;
@@ -13,8 +13,8 @@ namespace routing_algorithms
/// by the previous route.
/// This variation is only an optimazation for graphs with slow queries, for example
/// not fully contracted graphs.
void DirectShortestPathRouting::
operator()(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
void DirectShortestPathRouting<algorithm::CH>::
operator()(const FacadeT &facade,
const std::vector<PhantomNodes> &phantom_nodes_vector,
InternalRouteResult &raw_route_data) const
{
@@ -26,7 +26,7 @@ operator()(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
const auto &source_phantom = phantom_node_pair.source_phantom;
const auto &target_phantom = phantom_node_pair.target_phantom;
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade->GetNumberOfNodes());
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
QueryHeap &forward_heap = *(engine_working_data.forward_heap_1);
QueryHeap &reverse_heap = *(engine_working_data.reverse_heap_1);
forward_heap.Clear();
@@ -68,9 +68,9 @@ operator()(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
const bool constexpr DO_NOT_FORCE_LOOPS =
false; // prevents forcing of loops, since offsets are set correctly
if (facade->GetCoreSize() > 0)
if (facade.GetCoreSize() > 0)
{
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade->GetNumberOfNodes());
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
QueryHeap &forward_core_heap = *(engine_working_data.forward_heap_2);
QueryHeap &reverse_core_heap = *(engine_working_data.reverse_heap_2);
forward_core_heap.Clear();
@@ -7,8 +7,8 @@ namespace engine
namespace routing_algorithms
{
std::vector<EdgeWeight> ManyToManyRouting::
operator()(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
std::vector<EdgeWeight> ManyToManyRouting<algorithm::CH>::
operator()(const FacadeT &facade,
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const
@@ -22,7 +22,7 @@ operator()(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
std::vector<EdgeWeight> weights_table(number_of_entries, INVALID_EDGE_WEIGHT);
std::vector<EdgeWeight> durations_table(number_of_entries, MAXIMAL_EDGE_DURATION);
engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(facade->GetNumberOfNodes());
engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(facade.GetNumberOfNodes());
QueryHeap &query_heap = *(engine_working_data.many_to_many_heap);
@@ -122,8 +122,8 @@ operator()(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
return durations_table;
}
void ManyToManyRouting::ForwardRoutingStep(
const std::shared_ptr<const datafacade::BaseDataFacade> facade,
void ManyToManyRouting<algorithm::CH>::ForwardRoutingStep(
const FacadeT &facade,
const unsigned row_idx,
const unsigned number_of_targets,
QueryHeap &query_heap,
@@ -179,8 +179,8 @@ void ManyToManyRouting::ForwardRoutingStep(
RelaxOutgoingEdges<true>(facade, node, source_weight, source_duration, query_heap);
}
void ManyToManyRouting::BackwardRoutingStep(
const std::shared_ptr<const datafacade::BaseDataFacade> facade,
void ManyToManyRouting<algorithm::CH>::BackwardRoutingStep(
const FacadeT &facade,
const unsigned column_idx,
QueryHeap &query_heap,
SearchSpaceWithBuckets &search_space_with_buckets) const
@@ -7,7 +7,8 @@ namespace engine
namespace routing_algorithms
{
unsigned MapMatching::GetMedianSampleTime(const std::vector<unsigned> &timestamps) const
unsigned
MapMatching<algorithm::CH>::GetMedianSampleTime(const std::vector<unsigned> &timestamps) const
{
BOOST_ASSERT(timestamps.size() > 1);
@@ -22,8 +23,8 @@ unsigned MapMatching::GetMedianSampleTime(const std::vector<unsigned> &timestamp
return *median;
}
SubMatchingList MapMatching::
operator()(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
SubMatchingList MapMatching<algorithm::CH>::
operator()(const FacadeT &facade,
const CandidateLists &candidates_list,
const std::vector<util::Coordinate> &trace_coordinates,
const std::vector<unsigned> &trace_timestamps,
@@ -50,7 +51,7 @@ operator()(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
const auto max_distance_delta = [&] {
if (use_timestamps)
{
return median_sample_time * facade->GetMapMatchingMaxSpeed();
return median_sample_time * facade.GetMapMatchingMaxSpeed();
}
else
{
@@ -109,8 +110,8 @@ operator()(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
return sub_matchings;
}
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade->GetNumberOfNodes());
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade->GetNumberOfNodes());
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
QueryHeap &forward_heap = *(engine_working_data.forward_heap_1);
QueryHeap &reverse_heap = *(engine_working_data.reverse_heap_1);
@@ -182,7 +183,7 @@ operator()(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
reverse_heap.Clear();
double network_distance;
if (facade->GetCoreSize() > 0)
if (facade.GetCoreSize() > 0)
{
forward_core_heap.Clear();
reverse_core_heap.Clear();
+64 -69
View File
@@ -7,17 +7,16 @@ namespace engine
namespace routing_algorithms
{
void BasicRoutingInterface::RoutingStep(
const std::shared_ptr<const datafacade::BaseDataFacade> facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
NodeID &middle_node_id,
EdgeWeight &upper_bound,
EdgeWeight min_edge_offset,
const bool forward_direction,
const bool stalling,
const bool force_loop_forward,
const bool force_loop_reverse) const
void BasicRouting<algorithm::CH>::RoutingStep(const FacadeT &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
NodeID &middle_node_id,
EdgeWeight &upper_bound,
EdgeWeight min_edge_offset,
const bool forward_direction,
const bool stalling,
const bool force_loop_forward,
const bool force_loop_reverse) const
{
const NodeID node = forward_heap.DeleteMin();
const EdgeWeight weight = forward_heap.GetKey(node);
@@ -35,13 +34,13 @@ void BasicRoutingInterface::RoutingStep(
new_weight < 0)
{
// check whether there is a loop present at the node
for (const auto edge : facade->GetAdjacentEdgeRange(node))
for (const auto edge : facade.GetAdjacentEdgeRange(node))
{
const EdgeData &data = facade->GetEdgeData(edge);
const EdgeData &data = facade.GetEdgeData(edge);
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
if (forward_directionFlag)
{
const NodeID to = facade->GetTarget(edge);
const NodeID to = facade.GetTarget(edge);
if (to == node)
{
const EdgeWeight edge_weight = data.weight;
@@ -77,13 +76,13 @@ void BasicRoutingInterface::RoutingStep(
// Stalling
if (stalling)
{
for (const auto edge : facade->GetAdjacentEdgeRange(node))
for (const auto edge : facade.GetAdjacentEdgeRange(node))
{
const EdgeData &data = facade->GetEdgeData(edge);
const EdgeData &data = facade.GetEdgeData(edge);
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
if (reverse_flag)
{
const NodeID to = facade->GetTarget(edge);
const NodeID to = facade.GetTarget(edge);
const EdgeWeight edge_weight = data.weight;
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
@@ -99,13 +98,13 @@ void BasicRoutingInterface::RoutingStep(
}
}
for (const auto edge : facade->GetAdjacentEdgeRange(node))
for (const auto edge : facade.GetAdjacentEdgeRange(node))
{
const EdgeData &data = facade->GetEdgeData(edge);
const EdgeData &data = facade.GetEdgeData(edge);
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
if (forward_directionFlag)
{
const NodeID to = facade->GetTarget(edge);
const NodeID to = facade.GetTarget(edge);
const EdgeWeight edge_weight = data.weight;
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
@@ -134,15 +133,14 @@ void BasicRoutingInterface::RoutingStep(
* @param to the node the CH edge finishes at
* @param unpacked_path the sequence of original NodeIDs that make up the expanded CH edge
*/
void BasicRoutingInterface::UnpackEdge(
const std::shared_ptr<const datafacade::BaseDataFacade> facade,
const NodeID from,
const NodeID to,
std::vector<NodeID> &unpacked_path) const
void BasicRouting<algorithm::CH>::UnpackEdge(const FacadeT &facade,
const NodeID from,
const NodeID to,
std::vector<NodeID> &unpacked_path) const
{
std::array<NodeID, 2> path{{from, to}};
UnpackCHPath(
*facade,
facade,
path.begin(),
path.end(),
[&unpacked_path](const std::pair<NodeID, NodeID> &edge, const EdgeData & /* data */) {
@@ -151,7 +149,7 @@ void BasicRoutingInterface::UnpackEdge(
unpacked_path.emplace_back(to);
}
void BasicRoutingInterface::RetrievePackedPathFromHeap(
void BasicRouting<algorithm::CH>::RetrievePackedPathFromHeap(
const SearchEngineData::QueryHeap &forward_heap,
const SearchEngineData::QueryHeap &reverse_heap,
const NodeID middle_node_id,
@@ -163,7 +161,7 @@ void BasicRoutingInterface::RetrievePackedPathFromHeap(
RetrievePackedPathFromSingleHeap(reverse_heap, middle_node_id, packed_path);
}
void BasicRoutingInterface::RetrievePackedPathFromSingleHeap(
void BasicRouting<algorithm::CH>::RetrievePackedPathFromSingleHeap(
const SearchEngineData::QueryHeap &search_heap,
const NodeID middle_node_id,
std::vector<NodeID> &packed_path) const
@@ -193,14 +191,14 @@ void BasicRoutingInterface::RetrievePackedPathFromSingleHeap(
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
// requires
// a force loop, if the heaps have been initialized with positive offsets.
void BasicRoutingInterface::Search(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
EdgeWeight &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
const EdgeWeight weight_upper_bound) const
void BasicRouting<algorithm::CH>::Search(const FacadeT &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
EdgeWeight &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
const EdgeWeight weight_upper_bound) const
{
NodeID middle = SPECIAL_NODEID;
weight = weight_upper_bound;
@@ -275,17 +273,16 @@ void BasicRoutingInterface::Search(const std::shared_ptr<const datafacade::BaseD
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
// requires
// a force loop, if the heaps have been initialized with positive offsets.
void BasicRoutingInterface::SearchWithCore(
const std::shared_ptr<const datafacade::BaseDataFacade> facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &forward_core_heap,
SearchEngineData::QueryHeap &reverse_core_heap,
EdgeWeight &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
EdgeWeight weight_upper_bound) const
void BasicRouting<algorithm::CH>::SearchWithCore(const FacadeT &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &forward_core_heap,
SearchEngineData::QueryHeap &reverse_core_heap,
EdgeWeight &weight,
std::vector<NodeID> &packed_leg,
const bool force_loop_forward,
const bool force_loop_reverse,
EdgeWeight weight_upper_bound) const
{
NodeID middle = SPECIAL_NODEID;
weight = weight_upper_bound;
@@ -305,7 +302,7 @@ void BasicRoutingInterface::SearchWithCore(
{
if (!forward_heap.Empty())
{
if (facade->IsCoreNode(forward_heap.Min()))
if (facade.IsCoreNode(forward_heap.Min()))
{
const NodeID node = forward_heap.DeleteMin();
const EdgeWeight key = forward_heap.GetKey(node);
@@ -327,7 +324,7 @@ void BasicRoutingInterface::SearchWithCore(
}
if (!reverse_heap.Empty())
{
if (facade->IsCoreNode(reverse_heap.Min()))
if (facade.IsCoreNode(reverse_heap.Min()))
{
const NodeID node = reverse_heap.DeleteMin();
const EdgeWeight key = reverse_heap.GetKey(node);
@@ -422,7 +419,7 @@ void BasicRoutingInterface::SearchWithCore(
BOOST_ASSERT_MSG((SPECIAL_NODEID != middle && INVALID_EDGE_WEIGHT != weight), "no path found");
// we need to unpack sub path from core heaps
if (facade->IsCoreNode(middle))
if (facade.IsCoreNode(middle))
{
if (weight != forward_core_heap.GetKey(middle) + reverse_core_heap.GetKey(middle))
{
@@ -461,8 +458,8 @@ void BasicRoutingInterface::SearchWithCore(
}
}
bool BasicRoutingInterface::NeedsLoopForward(const PhantomNode &source_phantom,
const PhantomNode &target_phantom) const
bool BasicRouting<algorithm::CH>::NeedsLoopForward(const PhantomNode &source_phantom,
const PhantomNode &target_phantom) const
{
return source_phantom.forward_segment_id.enabled && target_phantom.forward_segment_id.enabled &&
source_phantom.forward_segment_id.id == target_phantom.forward_segment_id.id &&
@@ -470,8 +467,8 @@ bool BasicRoutingInterface::NeedsLoopForward(const PhantomNode &source_phantom,
target_phantom.GetForwardWeightPlusOffset();
}
bool BasicRoutingInterface::NeedsLoopBackwards(const PhantomNode &source_phantom,
const PhantomNode &target_phantom) const
bool BasicRouting<algorithm::CH>::NeedsLoopBackwards(const PhantomNode &source_phantom,
const PhantomNode &target_phantom) const
{
return source_phantom.reverse_segment_id.enabled && target_phantom.reverse_segment_id.enabled &&
source_phantom.reverse_segment_id.id == target_phantom.reverse_segment_id.id &&
@@ -479,11 +476,10 @@ bool BasicRoutingInterface::NeedsLoopBackwards(const PhantomNode &source_phantom
target_phantom.GetReverseWeightPlusOffset();
}
double BasicRoutingInterface::GetPathDistance(
const std::shared_ptr<const datafacade::BaseDataFacade> facade,
const std::vector<NodeID> &packed_path,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom) const
double BasicRouting<algorithm::CH>::GetPathDistance(const FacadeT &facade,
const std::vector<NodeID> &packed_path,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom) const
{
std::vector<PathData> unpacked_path;
PhantomNodes nodes;
@@ -500,7 +496,7 @@ double BasicRoutingInterface::GetPathDistance(
double prev_cos = std::cos(prev_lat);
for (const auto &p : unpacked_path)
{
const auto current_coordinate = facade->GetCoordinateOfNode(p.turn_via_node);
const auto current_coordinate = facade.GetCoordinateOfNode(p.turn_via_node);
const double current_lat =
static_cast<double>(toFloating(current_coordinate.lat)) * DEGREE_TO_RAD;
@@ -539,8 +535,8 @@ double BasicRoutingInterface::GetPathDistance(
// Requires the heaps for be empty
// If heaps should be adjusted to be initialized outside of this function,
// the addition of force_loop parameters might be required
double BasicRoutingInterface::GetNetworkDistanceWithCore(
const std::shared_ptr<const datafacade::BaseDataFacade> facade,
double BasicRouting<algorithm::CH>::GetNetworkDistanceWithCore(
const FacadeT &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
SearchEngineData::QueryHeap &forward_core_heap,
@@ -605,13 +601,12 @@ double BasicRoutingInterface::GetNetworkDistanceWithCore(
// Requires the heaps for be empty
// If heaps should be adjusted to be initialized outside of this function,
// the addition of force_loop parameters might be required
double BasicRoutingInterface::GetNetworkDistance(
const std::shared_ptr<const datafacade::BaseDataFacade> facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
EdgeWeight weight_upper_bound) const
double BasicRouting<algorithm::CH>::GetNetworkDistance(const FacadeT &facade,
SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
EdgeWeight weight_upper_bound) const
{
BOOST_ASSERT(forward_heap.Empty());
BOOST_ASSERT(reverse_heap.Empty());
+50 -49
View File
@@ -9,22 +9,21 @@ namespace routing_algorithms
// allows a uturn at the target_phantom
// searches source forward/reverse -> target forward/reverse
void ShortestPathRouting::SearchWithUTurn(
const std::shared_ptr<const datafacade::BaseDataFacade> facade,
QueryHeap &forward_heap,
QueryHeap &reverse_heap,
QueryHeap &forward_core_heap,
QueryHeap &reverse_core_heap,
const bool search_from_forward_node,
const bool search_from_reverse_node,
const bool search_to_forward_node,
const bool search_to_reverse_node,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
const int total_weight_to_forward,
const int total_weight_to_reverse,
int &new_total_weight,
std::vector<NodeID> &leg_packed_path) const
void ShortestPathRouting<algorithm::CH>::SearchWithUTurn(const FacadeT &facade,
QueryHeap &forward_heap,
QueryHeap &reverse_heap,
QueryHeap &forward_core_heap,
QueryHeap &reverse_core_heap,
const bool search_from_forward_node,
const bool search_from_reverse_node,
const bool search_to_forward_node,
const bool search_to_reverse_node,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
const int total_weight_to_forward,
const int total_weight_to_reverse,
int &new_total_weight,
std::vector<NodeID> &leg_packed_path) const
{
forward_heap.Clear();
reverse_heap.Clear();
@@ -64,7 +63,7 @@ void ShortestPathRouting::SearchWithUTurn(
is_oneway_source && super::NeedsLoopForward(source_phantom, target_phantom);
auto needs_loop_backwards =
is_oneway_target && super::NeedsLoopBackwards(source_phantom, target_phantom);
if (facade->GetCoreSize() > 0)
if (facade.GetCoreSize() > 0)
{
forward_core_heap.Clear();
reverse_core_heap.Clear();
@@ -100,23 +99,23 @@ void ShortestPathRouting::SearchWithUTurn(
// searches shortest path between:
// source forward/reverse -> target forward
// source forward/reverse -> target reverse
void ShortestPathRouting::Search(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
QueryHeap &forward_heap,
QueryHeap &reverse_heap,
QueryHeap &forward_core_heap,
QueryHeap &reverse_core_heap,
const bool search_from_forward_node,
const bool search_from_reverse_node,
const bool search_to_forward_node,
const bool search_to_reverse_node,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
const int total_weight_to_forward,
const int total_weight_to_reverse,
int &new_total_weight_to_forward,
int &new_total_weight_to_reverse,
std::vector<NodeID> &leg_packed_path_forward,
std::vector<NodeID> &leg_packed_path_reverse) const
void ShortestPathRouting<algorithm::CH>::Search(const FacadeT &facade,
QueryHeap &forward_heap,
QueryHeap &reverse_heap,
QueryHeap &forward_core_heap,
QueryHeap &reverse_core_heap,
const bool search_from_forward_node,
const bool search_from_reverse_node,
const bool search_to_forward_node,
const bool search_to_reverse_node,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
const int total_weight_to_forward,
const int total_weight_to_reverse,
int &new_total_weight_to_forward,
int &new_total_weight_to_reverse,
std::vector<NodeID> &leg_packed_path_forward,
std::vector<NodeID> &leg_packed_path_reverse) const
{
if (search_to_forward_node)
{
@@ -143,7 +142,7 @@ void ShortestPathRouting::Search(const std::shared_ptr<const datafacade::BaseDat
BOOST_ASSERT(forward_heap.Size() > 0);
BOOST_ASSERT(reverse_heap.Size() > 0);
if (facade->GetCoreSize() > 0)
if (facade.GetCoreSize() > 0)
{
forward_core_heap.Clear();
reverse_core_heap.Clear();
@@ -194,7 +193,7 @@ void ShortestPathRouting::Search(const std::shared_ptr<const datafacade::BaseDat
}
BOOST_ASSERT(forward_heap.Size() > 0);
BOOST_ASSERT(reverse_heap.Size() > 0);
if (facade->GetCoreSize() > 0)
if (facade.GetCoreSize() > 0)
{
forward_core_heap.Clear();
reverse_core_heap.Clear();
@@ -223,12 +222,13 @@ void ShortestPathRouting::Search(const std::shared_ptr<const datafacade::BaseDat
}
}
void ShortestPathRouting::UnpackLegs(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
const std::vector<PhantomNodes> &phantom_nodes_vector,
const std::vector<NodeID> &total_packed_path,
const std::vector<std::size_t> &packed_leg_begin,
const int shortest_path_length,
InternalRouteResult &raw_route_data) const
void ShortestPathRouting<algorithm::CH>::UnpackLegs(
const FacadeT &facade,
const std::vector<PhantomNodes> &phantom_nodes_vector,
const std::vector<NodeID> &total_packed_path,
const std::vector<std::size_t> &packed_leg_begin,
const int shortest_path_length,
InternalRouteResult &raw_route_data) const
{
raw_route_data.unpacked_path_segments.resize(packed_leg_begin.size() - 1);
@@ -253,17 +253,18 @@ void ShortestPathRouting::UnpackLegs(const std::shared_ptr<const datafacade::Bas
}
}
void ShortestPathRouting::operator()(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
const std::vector<PhantomNodes> &phantom_nodes_vector,
const boost::optional<bool> continue_straight_at_waypoint,
InternalRouteResult &raw_route_data) const
void ShortestPathRouting<algorithm::CH>::
operator()(const FacadeT &facade,
const std::vector<PhantomNodes> &phantom_nodes_vector,
const boost::optional<bool> continue_straight_at_waypoint,
InternalRouteResult &raw_route_data) const
{
const bool allow_uturn_at_waypoint =
!(continue_straight_at_waypoint ? *continue_straight_at_waypoint
: facade->GetContinueStraightDefault());
: facade.GetContinueStraightDefault());
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade->GetNumberOfNodes());
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade->GetNumberOfNodes());
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
QueryHeap &forward_heap = *(engine_working_data.forward_heap_1);
QueryHeap &reverse_heap = *(engine_working_data.reverse_heap_1);
@@ -0,0 +1,228 @@
#include "engine/routing_algorithms/tile_turns.hpp"
namespace osrm
{
namespace engine
{
namespace routing_algorithms
{
std::vector<TurnData> TileTurns<algorithm::CH>::
operator()(const FacadeT &facade,
const std::vector<RTreeLeaf> &edges,
const std::vector<std::size_t> &sorted_edge_indexes) const
{
std::vector<TurnData> all_turn_data;
// Struct to hold info on all the EdgeBasedNodes that are visible in our tile
// When we create these, we insure that (source, target) and packed_geometry_id
// are all pointed in the same direction.
struct EdgeBasedNodeInfo
{
bool is_geometry_forward; // Is the geometry forward or reverse?
unsigned packed_geometry_id;
};
// Lookup table for edge-based-nodes
std::unordered_map<NodeID, EdgeBasedNodeInfo> edge_based_node_info;
struct SegmentData
{
NodeID target_node;
EdgeID edge_based_node_id;
};
std::unordered_map<NodeID, std::vector<SegmentData>> directed_graph;
// Reserve enough space for unique edge-based-nodes on every edge.
// Only a tile with all unique edges will use this much, but
// it saves us a bunch of re-allocations during iteration.
directed_graph.reserve(edges.size() * 2);
// Build an adjacency list for all the road segments visible in
// the tile
for (const auto &edge_index : sorted_edge_indexes)
{
const auto &edge = edges[edge_index];
if (edge.forward_segment_id.enabled)
{
// operator[] will construct an empty vector at [edge.u] if there is no value.
directed_graph[edge.u].push_back({edge.v, edge.forward_segment_id.id});
if (edge_based_node_info.count(edge.forward_segment_id.id) == 0)
{
edge_based_node_info[edge.forward_segment_id.id] = {true, edge.packed_geometry_id};
}
else
{
BOOST_ASSERT(edge_based_node_info[edge.forward_segment_id.id].is_geometry_forward ==
true);
BOOST_ASSERT(edge_based_node_info[edge.forward_segment_id.id].packed_geometry_id ==
edge.packed_geometry_id);
}
}
if (edge.reverse_segment_id.enabled)
{
directed_graph[edge.v].push_back({edge.u, edge.reverse_segment_id.id});
if (edge_based_node_info.count(edge.reverse_segment_id.id) == 0)
{
edge_based_node_info[edge.reverse_segment_id.id] = {false, edge.packed_geometry_id};
}
else
{
BOOST_ASSERT(edge_based_node_info[edge.reverse_segment_id.id].is_geometry_forward ==
false);
BOOST_ASSERT(edge_based_node_info[edge.reverse_segment_id.id].packed_geometry_id ==
edge.packed_geometry_id);
}
}
}
// Given a turn:
// u---v
// |
// w
// uv is the "approach"
// vw is the "exit"
std::vector<contractor::QueryEdge::EdgeData> unpacked_shortcut;
std::vector<EdgeWeight> approach_weight_vector;
// Make sure we traverse the startnodes in a consistent order
// to ensure identical PBF encoding on all platforms.
std::vector<NodeID> sorted_startnodes;
sorted_startnodes.reserve(directed_graph.size());
for (const auto &startnode : directed_graph)
sorted_startnodes.push_back(startnode.first);
std::sort(sorted_startnodes.begin(), sorted_startnodes.end());
// Look at every node in the directed graph we created
for (const auto &startnode : sorted_startnodes)
{
const auto &nodedata = directed_graph[startnode];
// For all the outgoing edges from the node
for (const auto &approachedge : nodedata)
{
// If the target of this edge doesn't exist in our directed
// graph, it's probably outside the tile, so we can skip it
if (directed_graph.count(approachedge.target_node) == 0)
continue;
// For each of the outgoing edges from our target coordinate
for (const auto &exit_edge : directed_graph[approachedge.target_node])
{
// If the next edge has the same edge_based_node_id, then it's
// not a turn, so skip it
if (approachedge.edge_based_node_id == exit_edge.edge_based_node_id)
continue;
// Skip u-turns
if (startnode == exit_edge.target_node)
continue;
// Find the connection between our source road and the target node
// Since we only want to find direct edges, we cannot check shortcut edges here.
// Otherwise we might find a forward edge even though a shorter backward edge
// exists (due to oneways).
//
// a > - > - > - b
// | |
// |------ c ----|
//
// would offer a backward edge at `b` to `a` (due to the oneway from a to b)
// but could also offer a shortcut (b-c-a) from `b` to `a` which is longer.
EdgeID smaller_edge_id =
facade.FindSmallestEdge(approachedge.edge_based_node_id,
exit_edge.edge_based_node_id,
[](const contractor::QueryEdge::EdgeData &data) {
return data.forward && !data.shortcut;
});
// Depending on how the graph is constructed, we might have to look for
// a backwards edge instead. They're equivalent, just one is available for
// a forward routing search, and one is used for the backwards dijkstra
// steps. Their weight should be the same, we can use either one.
// If we didn't find a forward edge, try for a backward one
if (SPECIAL_EDGEID == smaller_edge_id)
{
smaller_edge_id =
facade.FindSmallestEdge(exit_edge.edge_based_node_id,
approachedge.edge_based_node_id,
[](const contractor::QueryEdge::EdgeData &data) {
return data.backward && !data.shortcut;
});
}
// If no edge was found, it means that there's no connection between these
// nodes, due to oneways or turn restrictions. Given the edge-based-nodes
// that we're examining here, we *should* only find directly-connected
// edges, not shortcuts
if (smaller_edge_id != SPECIAL_EDGEID)
{
const auto &data = facade.GetEdgeData(smaller_edge_id);
BOOST_ASSERT_MSG(!data.shortcut, "Connecting edge must not be a shortcut");
// Now, calculate the sum of the weight of all the segments.
if (edge_based_node_info[approachedge.edge_based_node_id].is_geometry_forward)
{
approach_weight_vector = facade.GetUncompressedForwardWeights(
edge_based_node_info[approachedge.edge_based_node_id]
.packed_geometry_id);
}
else
{
approach_weight_vector = facade.GetUncompressedReverseWeights(
edge_based_node_info[approachedge.edge_based_node_id]
.packed_geometry_id);
}
const auto sum_node_weight = std::accumulate(approach_weight_vector.begin(),
approach_weight_vector.end(),
EdgeWeight{0});
// The edge.weight is the whole edge weight, which includes the turn
// cost.
// The turn cost is the edge.weight minus the sum of the individual road
// segment weights. This might not be 100% accurate, because some
// intersections include stop signs, traffic signals and other
// penalties, but at this stage, we can't divide those out, so we just
// treat the whole lot as the "turn cost" that we'll stick on the map.
const auto turn_cost = data.weight - sum_node_weight;
// Find the three nodes that make up the turn movement)
const auto node_from = startnode;
const auto node_via = approachedge.target_node;
const auto node_to = exit_edge.target_node;
const auto coord_from = facade.GetCoordinateOfNode(node_from);
const auto coord_via = facade.GetCoordinateOfNode(node_via);
const auto coord_to = facade.GetCoordinateOfNode(node_to);
// Calculate the bearing that we approach the intersection at
const auto angle_in = static_cast<int>(
util::coordinate_calculation::bearing(coord_from, coord_via));
const auto exit_bearing = static_cast<int>(
util::coordinate_calculation::bearing(coord_via, coord_to));
// Figure out the angle of the turn
auto turn_angle = exit_bearing - angle_in;
while (turn_angle > 180)
{
turn_angle -= 360;
}
while (turn_angle < -180)
{
turn_angle += 360;
}
// Save everything we need to later add all the points to the tile.
// We need the coordinate of the intersection, the angle in, the turn
// angle and the turn cost.
all_turn_data.push_back(TurnData{coord_via, angle_in, turn_angle, turn_cost});
}
}
}
}
return all_turn_data;
}
} // namespace routing_algorithms
} // namespace engine
} // namespace osrm