Review changes.
This commit is contained in:
parent
f96e61ee06
commit
481b03baeb
@ -246,27 +246,6 @@ FixedPoint coordinatesToTilePoint(const util::Coordinate point, const BBox &tile
|
|||||||
return FixedPoint{px, py};
|
return FixedPoint{px, py};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Unpacks a single CH edge (NodeID->NodeID) down to the original edges, and returns a list of the
|
|
||||||
* edge data
|
|
||||||
* @param from the node the CH edge starts at
|
|
||||||
* @param to the node the CH edge finishes at
|
|
||||||
* @param unpacked_path the sequence of EdgeData objects along the unpacked path
|
|
||||||
*/
|
|
||||||
void UnpackEdgeToEdges(const datafacade::BaseDataFacade &facade,
|
|
||||||
const NodeID from,
|
|
||||||
const NodeID to,
|
|
||||||
std::vector<datafacade::BaseDataFacade::EdgeData> &unpacked_path)
|
|
||||||
{
|
|
||||||
std::array<NodeID, 2> path{{from, to}};
|
|
||||||
UnpackCHPath(facade,
|
|
||||||
path.begin(),
|
|
||||||
path.end(),
|
|
||||||
[&unpacked_path](const std::pair<NodeID, NodeID> & /* edge */,
|
|
||||||
const datafacade::BaseDataFacade::EdgeData &data) {
|
|
||||||
unpacked_path.emplace_back(data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Status TilePlugin::HandleRequest(const std::shared_ptr<datafacade::BaseDataFacade> facade,
|
Status TilePlugin::HandleRequest(const std::shared_ptr<datafacade::BaseDataFacade> facade,
|
||||||
@ -400,6 +379,10 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<datafacade::BaseDataFacad
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::unordered_map<NodeID, std::vector<SegmentData>> directed_graph;
|
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
|
// Build an adjacency list for all the road segments visible in
|
||||||
// the tile
|
// the tile
|
||||||
@ -407,66 +390,79 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<datafacade::BaseDataFacad
|
|||||||
{
|
{
|
||||||
if (edge.forward_segment_id.enabled)
|
if (edge.forward_segment_id.enabled)
|
||||||
{
|
{
|
||||||
if (directed_graph.count(edge.u) == 0)
|
// 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)
|
||||||
{
|
{
|
||||||
directed_graph[edge.u] = {{edge.v, edge.forward_segment_id.id}};
|
edge_based_node_info[edge.forward_segment_id.id] = {true,
|
||||||
|
edge.packed_geometry_id};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
directed_graph[edge.u].push_back({edge.v, edge.forward_segment_id.id});
|
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);
|
||||||
}
|
}
|
||||||
edge_based_node_info[edge.forward_segment_id.id] = {true, edge.packed_geometry_id};
|
|
||||||
}
|
}
|
||||||
if (edge.reverse_segment_id.enabled)
|
if (edge.reverse_segment_id.enabled)
|
||||||
{
|
{
|
||||||
if (directed_graph.count(edge.v) == 0)
|
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)
|
||||||
{
|
{
|
||||||
directed_graph[edge.v] = {{edge.u, edge.reverse_segment_id.id}};
|
edge_based_node_info[edge.reverse_segment_id.id] = {false,
|
||||||
|
edge.packed_geometry_id};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
directed_graph[edge.v].push_back({edge.u, edge.reverse_segment_id.id});
|
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);
|
||||||
}
|
}
|
||||||
edge_based_node_info[edge.reverse_segment_id.id] = {false, edge.packed_geometry_id};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, scan over our adjacency list
|
// Given a turn:
|
||||||
// For every edge A:
|
// u---v
|
||||||
// Look at the outgoing edges from A
|
// |
|
||||||
// If the outgoing edge has a different edge_based_node_id
|
// w
|
||||||
// This is a turn. Find it in the CH
|
// uv is the "approach"
|
||||||
// Get the edge data
|
// vw is the "exit"
|
||||||
// Subtract the road weights from the edge weight
|
|
||||||
// Calculate angles, add to tile.
|
|
||||||
std::vector<contractor::QueryEdge::EdgeData> unpacked_shortcut;
|
std::vector<contractor::QueryEdge::EdgeData> unpacked_shortcut;
|
||||||
std::vector<EdgeWeight> first_weight_vector;
|
std::vector<EdgeWeight> approach_weight_vector;
|
||||||
for (const auto &firstnode : directed_graph)
|
// Look at every node in the directed graph we created
|
||||||
|
for (const auto &startnode : directed_graph)
|
||||||
{
|
{
|
||||||
for (const auto &firstedge : firstnode.second)
|
// For all the outgoing edges from the node
|
||||||
{
|
for (const auto &approachedge : startnode.second)
|
||||||
// If this edge points to something else (i.e. degree > 1)
|
|
||||||
if (directed_graph.count(firstedge.target_node) > 0)
|
|
||||||
{
|
{
|
||||||
|
// 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 each of the outgoing edges from our target coordinate
|
||||||
for (const auto &secondedge : directed_graph[firstedge.target_node])
|
for (const auto &exit_edge : directed_graph[approachedge.target_node])
|
||||||
{
|
{
|
||||||
// If the next edge has the same edge_based_node_id, then it's
|
// If the next edge has the same edge_based_node_id, then it's
|
||||||
// not a turn, so skip it
|
// not a turn, so skip it
|
||||||
if (firstedge.edge_based_node_id == secondedge.edge_based_node_id)
|
if (approachedge.edge_based_node_id == exit_edge.edge_based_node_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Skip u-turns
|
// Skip u-turns
|
||||||
if (firstnode.first == secondedge.target_node)
|
if (startnode.first == exit_edge.target_node)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Find the connection between our source road and the target node
|
// Find the connection between our source road and the target node
|
||||||
EdgeID smaller_edge_id = facade->FindSmallestEdge(
|
EdgeID smaller_edge_id = facade->FindSmallestEdge(
|
||||||
firstedge.edge_based_node_id,
|
approachedge.edge_based_node_id,
|
||||||
secondedge.edge_based_node_id,
|
exit_edge.edge_based_node_id,
|
||||||
[](const contractor::QueryEdge::EdgeData &data) {
|
[](const contractor::QueryEdge::EdgeData &data) { return data.forward; });
|
||||||
return data.forward;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Depending on how the graph is constructed, we might have to look for
|
// 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 backwards edge instead. They're equivalent, just one is available for
|
||||||
@ -476,8 +472,8 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<datafacade::BaseDataFacad
|
|||||||
if (SPECIAL_EDGEID == smaller_edge_id)
|
if (SPECIAL_EDGEID == smaller_edge_id)
|
||||||
{
|
{
|
||||||
smaller_edge_id = facade->FindSmallestEdge(
|
smaller_edge_id = facade->FindSmallestEdge(
|
||||||
secondedge.edge_based_node_id,
|
exit_edge.edge_based_node_id,
|
||||||
firstedge.edge_based_node_id,
|
approachedge.edge_based_node_id,
|
||||||
[](const contractor::QueryEdge::EdgeData &data) {
|
[](const contractor::QueryEdge::EdgeData &data) {
|
||||||
return data.backward;
|
return data.backward;
|
||||||
});
|
});
|
||||||
@ -489,49 +485,25 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<datafacade::BaseDataFacad
|
|||||||
// edges, not shortcuts
|
// edges, not shortcuts
|
||||||
if (smaller_edge_id != SPECIAL_EDGEID)
|
if (smaller_edge_id != SPECIAL_EDGEID)
|
||||||
{
|
{
|
||||||
// Check to see if it was a shortcut edge we found. This can happen
|
const auto &data = facade->GetEdgeData(smaller_edge_id);
|
||||||
// when exactly? Anyway, unpack it and get the first "real" edgedata
|
BOOST_ASSERT_MSG(!data.shortcut, "Connecting edge must not be a shortcut");
|
||||||
// out of it, which should represent the first hop, which is the one
|
|
||||||
// we want to find the turn.
|
|
||||||
const auto &data = [this,
|
|
||||||
&facade,
|
|
||||||
smaller_edge_id,
|
|
||||||
firstedge,
|
|
||||||
secondedge,
|
|
||||||
&unpacked_shortcut]() {
|
|
||||||
const auto inner_data = facade->GetEdgeData(smaller_edge_id);
|
|
||||||
if (inner_data.shortcut)
|
|
||||||
{
|
|
||||||
unpacked_shortcut.clear();
|
|
||||||
UnpackEdgeToEdges(*facade,
|
|
||||||
firstedge.edge_based_node_id,
|
|
||||||
secondedge.edge_based_node_id,
|
|
||||||
unpacked_shortcut);
|
|
||||||
return unpacked_shortcut.front();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return inner_data;
|
|
||||||
}();
|
|
||||||
BOOST_ASSERT_MSG(!data.shortcut,
|
|
||||||
"Connecting edge must not be a shortcut");
|
|
||||||
|
|
||||||
// Now, calculate the sum of the weight of all the segments.
|
// Now, calculate the sum of the weight of all the segments.
|
||||||
if (edge_based_node_info[firstedge.edge_based_node_id]
|
if (edge_based_node_info[approachedge.edge_based_node_id]
|
||||||
.is_geometry_forward)
|
.is_geometry_forward)
|
||||||
{
|
{
|
||||||
first_weight_vector = facade->GetUncompressedForwardWeights(
|
approach_weight_vector = facade->GetUncompressedForwardWeights(
|
||||||
edge_based_node_info[firstedge.edge_based_node_id]
|
edge_based_node_info[approachedge.edge_based_node_id]
|
||||||
.packed_geometry_id);
|
.packed_geometry_id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
first_weight_vector = facade->GetUncompressedReverseWeights(
|
approach_weight_vector = facade->GetUncompressedReverseWeights(
|
||||||
edge_based_node_info[firstedge.edge_based_node_id]
|
edge_based_node_info[approachedge.edge_based_node_id]
|
||||||
.packed_geometry_id);
|
.packed_geometry_id);
|
||||||
}
|
}
|
||||||
const auto sum_node_weight =
|
const auto sum_node_weight = std::accumulate(approach_weight_vector.begin(),
|
||||||
std::accumulate(first_weight_vector.begin(),
|
approach_weight_vector.end(),
|
||||||
first_weight_vector.end(),
|
|
||||||
EdgeWeight{0});
|
EdgeWeight{0});
|
||||||
|
|
||||||
// The edge.weight is the whole edge weight, which includes the turn
|
// The edge.weight is the whole edge weight, which includes the turn
|
||||||
@ -544,9 +516,9 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<datafacade::BaseDataFacad
|
|||||||
const auto turn_cost = data.weight - sum_node_weight;
|
const auto turn_cost = data.weight - sum_node_weight;
|
||||||
|
|
||||||
// Find the three nodes that make up the turn movement)
|
// Find the three nodes that make up the turn movement)
|
||||||
const auto node_from = firstnode.first;
|
const auto node_from = startnode.first;
|
||||||
const auto node_via = firstedge.target_node;
|
const auto node_via = approachedge.target_node;
|
||||||
const auto node_to = secondedge.target_node;
|
const auto node_to = exit_edge.target_node;
|
||||||
|
|
||||||
const auto coord_from = facade->GetCoordinateOfNode(node_from);
|
const auto coord_from = facade->GetCoordinateOfNode(node_from);
|
||||||
const auto coord_via = facade->GetCoordinateOfNode(node_via);
|
const auto coord_via = facade->GetCoordinateOfNode(node_via);
|
||||||
@ -588,9 +560,8 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<datafacade::BaseDataFacad
|
|||||||
// Save everything we need to later add all the points to the tile.
|
// 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
|
// We need the coordinate of the intersection, the angle in, the turn
|
||||||
// angle and the turn cost.
|
// angle and the turn cost.
|
||||||
all_turn_data.emplace_back(TurnData{
|
all_turn_data.emplace_back(
|
||||||
coord_via, angle_in_index, turn_angle_index, turn_cost_index});
|
coord_via, angle_in_index, turn_angle_index, turn_cost_index);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -598,8 +569,7 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<datafacade::BaseDataFacad
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Vector tiles encode feature properties as indexes into a lookup table. So, we need
|
// Vector tiles encode feature properties as indexes into a lookup table. So, we need
|
||||||
// to
|
// to "pre-loop" over all the edges to create the lookup tables. Once we have those, we
|
||||||
// "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
|
// can then encode the features, and we'll know the indexes that feature properties
|
||||||
// need to refer to.
|
// need to refer to.
|
||||||
for (const auto &edge : edges)
|
for (const auto &edge : edges)
|
||||||
@ -710,10 +680,8 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<datafacade::BaseDataFacad
|
|||||||
std::int32_t &start_x,
|
std::int32_t &start_x,
|
||||||
std::int32_t &start_y) {
|
std::int32_t &start_y) {
|
||||||
// Here, we save the two attributes for our feature: the speed and
|
// Here, we save the two attributes for our feature: the speed and
|
||||||
// the
|
// the is_small boolean. We only serve up speeds from 0-139, so all we
|
||||||
// is_small boolean. We only serve up speeds from 0-139, so all we
|
// do is save the first
|
||||||
// do is
|
|
||||||
// save the first
|
|
||||||
protozero::pbf_writer feature_writer(line_layer_writer,
|
protozero::pbf_writer feature_writer(line_layer_writer,
|
||||||
util::vector_tile::FEATURE_TAG);
|
util::vector_tile::FEATURE_TAG);
|
||||||
// Field 3 is the "geometry type" field. Value 2 is "line"
|
// Field 3 is the "geometry type" field. Value 2 is "line"
|
||||||
@ -809,8 +777,7 @@ Status TilePlugin::HandleRequest(const std::shared_ptr<datafacade::BaseDataFacad
|
|||||||
|
|
||||||
// Field id 3 is the "keys" attribute
|
// Field id 3 is the "keys" attribute
|
||||||
// We need two "key" fields, these are referred to with 0 and 1 (their array
|
// We need two "key" fields, these are referred to with 0 and 1 (their array
|
||||||
// indexes)
|
// indexes) earlier
|
||||||
// earlier
|
|
||||||
line_layer_writer.add_string(util::vector_tile::KEY_TAG, "speed");
|
line_layer_writer.add_string(util::vector_tile::KEY_TAG, "speed");
|
||||||
line_layer_writer.add_string(util::vector_tile::KEY_TAG, "is_small");
|
line_layer_writer.add_string(util::vector_tile::KEY_TAG, "is_small");
|
||||||
line_layer_writer.add_string(util::vector_tile::KEY_TAG, "datasource");
|
line_layer_writer.add_string(util::vector_tile::KEY_TAG, "datasource");
|
||||||
|
Loading…
Reference in New Issue
Block a user