adjust for comments by daniel-j-h

This commit is contained in:
Moritz Kobitzsch 2016-09-30 14:33:43 +02:00
parent 805d93912d
commit d1f1358e48
8 changed files with 180 additions and 162 deletions

View File

@ -10,6 +10,8 @@
- Bugfixes
- fixed a bug where polyline decoding on a defective polyline could end up in out-of-bound access on a vector
- fixed compile errors in tile unit-test framework
- Debug Tiles
- Added support for turn penalties
# 5.4.0
- Changes from 5.3.0

View File

@ -8,8 +8,8 @@
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp"
#include <vector>
#include <stack>
#include <vector>
namespace osrm
{
@ -37,16 +37,19 @@ namespace engine
* original edge found.
*/
template <typename DataFacadeT, typename RandomIter, typename Callback>
inline void UnpackCHEdge(DataFacadeT *facade,
RandomIter packed_path_begin,
RandomIter packed_path_end,
const Callback &callback)
template <typename DataFacadeT, typename BidirectionalIterator, typename Callback>
inline void UnpackCHPath(const DataFacadeT &facade,
BidirectionalIterator packed_path_begin,
BidirectionalIterator packed_path_end,
Callback &&callback)
{
// make sure we have at least something to unpack
if( packed_path_begin == packed_path_end )
return;
using EdgeData = typename DataFacadeT::EdgeData;
std::stack<std::pair<NodeID, NodeID>> recursion_stack;
std::stack<std::pair<NodeID,NodeID>> recursion_stack;
// We have to push the path in reverse order onto the stack because it's LIFO.
for (auto current = std::prev(packed_path_end); current != packed_path_begin;
@ -62,7 +65,7 @@ inline void UnpackCHEdge(DataFacadeT *facade,
recursion_stack.pop();
// Look for an edge on the forward CH graph (.forward)
EdgeID smaller_edge_id = facade->FindSmallestEdge(
EdgeID smaller_edge_id = facade.FindSmallestEdge(
edge.first, edge.second, [](const EdgeData &data) { return data.forward; });
// If we didn't find one there, the we might be looking at a part of the path that
@ -70,7 +73,7 @@ inline void UnpackCHEdge(DataFacadeT *facade,
// and only consider edges with the `.backward` flag.
if (SPECIAL_EDGEID == smaller_edge_id)
{
smaller_edge_id = facade->FindSmallestEdge(
smaller_edge_id = facade.FindSmallestEdge(
edge.second, edge.first, [](const EdgeData &data) { return data.backward; });
}
@ -78,7 +81,7 @@ inline void UnpackCHEdge(DataFacadeT *facade,
// called this function with bad values.
BOOST_ASSERT_MSG(smaller_edge_id != SPECIAL_EDGEID, "Invalid smaller edge ID");
const auto &data = facade->GetEdgeData(smaller_edge_id);
const auto &data = facade.GetEdgeData(smaller_edge_id);
BOOST_ASSERT_MSG(data.distance != std::numeric_limits<EdgeWeight>::max(),
"edge weight invalid");
@ -94,7 +97,7 @@ inline void UnpackCHEdge(DataFacadeT *facade,
else
{
// We found an original edge, call our callback.
callback(edge, data);
std::forward<Callback>(callback)(edge, data);
}
}
}

View File

@ -229,8 +229,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
*std::prev(packed_path_end) == phantom_node_pair.target_phantom.forward_segment_id.id ||
*std::prev(packed_path_end) == phantom_node_pair.target_phantom.reverse_segment_id.id);
UnpackCHEdge(
facade,
UnpackCHPath(
*facade,
packed_path_begin,
packed_path_end,
[this,
@ -238,17 +238,17 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
&phantom_node_pair,
&start_traversed_in_reverse,
&target_traversed_in_reverse](std::pair<NodeID, NodeID> & /* edge */,
const EdgeData &data) {
const EdgeData &edge_data) {
BOOST_ASSERT_MSG(!data.shortcut, "original edge flagged as shortcut");
unsigned name_index = facade->GetNameIndexFromEdgeID(data.id);
const auto turn_instruction = facade->GetTurnInstructionForEdgeID(data.id);
BOOST_ASSERT_MSG(!edge_data.shortcut, "original edge flagged as shortcut");
const auto name_index = facade->GetNameIndexFromEdgeID(edge_data.id);
const auto turn_instruction = facade->GetTurnInstructionForEdgeID(edge_data.id);
const extractor::TravelMode travel_mode =
(unpacked_path.empty() && start_traversed_in_reverse)
? phantom_node_pair.source_phantom.backward_travel_mode
: facade->GetTravelModeForEdgeID(data.id);
: facade->GetTravelModeForEdgeID(edge_data.id);
const auto geometry_index = facade->GetGeometryIndexForEdgeID(data.id);
const auto geometry_index = facade->GetGeometryIndexForEdgeID(edge_data.id);
std::vector<NodeID> id_vector;
facade->GetUncompressedGeometry(geometry_index, id_vector);
BOOST_ASSERT(id_vector.size() > 0);
@ -260,7 +260,7 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
std::vector<DatasourceID> datasource_vector;
facade->GetUncompressedDatasources(geometry_index, datasource_vector);
auto total_weight = std::accumulate(weight_vector.begin(), weight_vector.end(), 0);
const auto total_weight = std::accumulate(weight_vector.begin(), weight_vector.end(), 0);
BOOST_ASSERT(weight_vector.size() == id_vector.size());
const bool is_first_segment = unpacked_path.empty();
@ -289,12 +289,12 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
datasource_vector[i]});
}
BOOST_ASSERT(unpacked_path.size() > 0);
if (facade->hasLaneData(data.id))
unpacked_path.back().lane_data = facade->GetLaneData(data.id);
if (facade->hasLaneData(edge_data.id))
unpacked_path.back().lane_data = facade->GetLaneData(edge_data.id);
unpacked_path.back().entry_classid = facade->GetEntryClassID(data.id);
unpacked_path.back().entry_classid = facade->GetEntryClassID(edge_data.id);
unpacked_path.back().turn_instruction = turn_instruction;
unpacked_path.back().duration_until_turn += (data.distance - total_weight);
unpacked_path.back().duration_until_turn += (edge_data.distance - total_weight);
});
std::size_t start_index = 0, end_index = 0;
@ -415,8 +415,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
void UnpackEdge(const NodeID from, const NodeID to, std::vector<NodeID> &unpacked_path) const
{
std::array<NodeID, 2> path{{from, to}};
UnpackCHEdge(
facade,
UnpackCHPath(
*facade,
path.begin(),
path.end(),
[&unpacked_path](const std::pair<NodeID, NodeID> &edge, const EdgeData & /* data */) {

View File

@ -160,17 +160,17 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
* matching edge is found.
*/
template <typename FilterFunction>
EdgeIterator FindSmallestEdge(const NodeIterator from,
const NodeIterator to,
const FilterFunction filter) const
EdgeIterator
FindSmallestEdge(const NodeIterator from, const NodeIterator to, FilterFunction &&filter) const
{
EdgeIterator smallest_edge = SPECIAL_EDGEID;
EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT;
for (auto edge : GetAdjacentEdgeRange(from))
{
const NodeID target = GetTarget(edge);
const auto data = GetEdgeData(edge);
if (target == to && data.distance < smallest_weight && filter(data))
const auto &data = GetEdgeData(edge);
if (target == to && data.distance < smallest_weight &&
std::forward<FilterFunction>(filter)(data))
{
smallest_edge = edge;
smallest_weight = data.distance;

View File

@ -85,8 +85,6 @@ static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<EdgeWeight>::m
using DatasourceID = std::uint8_t;
using DatasourceID = std::uint8_t;
struct SegmentID
{
SegmentID(const NodeID id_, const bool enabled_) : id{id_}, enabled{enabled_}

View File

@ -10,25 +10,29 @@ namespace util
namespace vector_tile
{
const constexpr std::uint32_t LAYER_TAG = 3;
const constexpr std::uint32_t NAME_TAG = 1;
const constexpr std::uint32_t VERSION_TAG = 15;
const constexpr std::uint32_t EXTENT_TAG = 5;
const constexpr std::uint32_t FEATURE_TAG = 2;
const constexpr std::uint32_t GEOMETRY_TAG = 3;
const constexpr std::uint32_t VARIANT_TAG = 4;
const constexpr std::uint32_t KEY_TAG = 3;
const constexpr std::uint32_t ID_TAG = 1;
const constexpr std::uint32_t GEOMETRY_TYPE_POINT = 1;
const constexpr std::uint32_t GEOMETRY_TYPE_LINE = 2;
const constexpr std::uint32_t NAME_TAG = 1;
const constexpr std::uint32_t FEATURE_TAG = 2;
const constexpr std::uint32_t LAYER_TAG = 3;
const constexpr std::uint32_t GEOMETRY_TAG = 3;
const constexpr std::uint32_t KEY_TAG = 3;
const constexpr std::uint32_t VARIANT_TAG = 4;
const constexpr std::uint32_t EXTENT_TAG = 5;
const constexpr std::uint32_t VERSION_TAG = 15;
const constexpr std::uint32_t FEATURE_ATTRIBUTES_TAG = 2;
const constexpr std::uint32_t FEATURE_GEOMETRIES_TAG = 4;
const constexpr std::uint32_t GEOMETRY_TYPE_POINT = 1;
const constexpr std::uint32_t GEOMETRY_TYPE_LINE = 2;
const constexpr std::uint32_t VARIANT_TYPE_STRING = 1;
const constexpr std::uint32_t VARIANT_TYPE_FLOAT = 2;
const constexpr std::uint32_t VARIANT_TYPE_DOUBLE = 3;
const constexpr std::uint32_t VARIANT_TYPE_UINT64 = 5;
const constexpr std::uint32_t VARIANT_TYPE_SINT64 = 6;
const constexpr std::uint32_t VARIANT_TYPE_BOOL = 7;
const constexpr std::uint32_t VARIANT_TYPE_STRING = 1;
const constexpr std::uint32_t VARIANT_TYPE_DOUBLE = 3;
const constexpr std::uint32_t VARIANT_TYPE_FLOAT = 2;
// Vector tiles are 4096 virtual pixels on each side
const constexpr double EXTENT = 4096.0;

View File

@ -1,6 +1,6 @@
#include "engine/plugins/tile.hpp"
#include "engine/plugins/plugin_base.hpp"
#include "engine/edge_unpacker.hpp"
#include "engine/plugins/plugin_base.hpp"
#include "engine/plugins/tile.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/vector_tile.hpp"
@ -31,7 +31,7 @@ namespace engine
{
namespace plugins
{
namespace detail
namespace
{
// TODO: Port all this encoding logic to https://github.com/mapbox/vector-tile, which wasn't
// available when this code was originally written.
@ -79,7 +79,7 @@ struct TurnData final
const std::size_t _in,
const std::size_t _out,
const std::size_t _weight)
: coordinate(coordinate_), in_angle_offset(_in), turn_angle_offset(_out),
: coordinate(std::move(coordinate_)), in_angle_offset(_in), turn_angle_offset(_out),
weight_offset(_weight)
{
}
@ -90,8 +90,8 @@ struct TurnData final
const std::size_t weight_offset;
};
using FixedPoint = detail::Point<std::int32_t>;
using FloatPoint = detail::Point<double>;
using FixedPoint = Point<std::int32_t>;
using FloatPoint = Point<double>;
using FixedLine = std::vector<FixedPoint>;
using FloatLine = std::vector<FloatPoint>;
@ -122,7 +122,7 @@ inline bool encodeLinestring(const FixedLine &line,
return false;
}
const unsigned LINETO_count = static_cast<const unsigned>(line_size) - 1;
const unsigned lineto_count = static_cast<const unsigned>(line_size) - 1;
auto pt = line.begin();
const constexpr int MOVETO_COMMAND = 9;
@ -133,7 +133,7 @@ inline bool encodeLinestring(const FixedLine &line,
start_y = pt->y;
// This means LINETO repeated N times
// See: https://github.com/mapbox/vector-tile-spec/tree/master/2.1#example-command-integers
geometry.add_element((LINETO_count << 3u) | 2u);
geometry.add_element((lineto_count << 3u) | 2u);
// Now that we've issued the LINETO REPEAT N command, we append
// N coordinate pairs immediately after the command.
for (++pt; pt != line.end(); ++pt)
@ -150,7 +150,7 @@ inline bool encodeLinestring(const FixedLine &line,
// from mapnik-vctor-tile
// Encodes a point
inline bool encodePoint(const FixedPoint &pt, protozero::packed_field_uint32 &geometry)
inline void encodePoint(const FixedPoint &pt, protozero::packed_field_uint32 &geometry)
{
const constexpr int MOVETO_COMMAND = 9;
geometry.add_element(MOVETO_COMMAND);
@ -159,7 +159,6 @@ inline bool encodePoint(const FixedPoint &pt, protozero::packed_field_uint32 &ge
// Manual zigzag encoding.
geometry.add_element(protozero::encode_zigzag32(dx));
geometry.add_element(protozero::encode_zigzag32(dy));
return true;
}
/**
@ -173,7 +172,7 @@ inline bool encodePoint(const FixedPoint &pt, protozero::packed_field_uint32 &ge
*/
FixedLine coordinatesToTileLine(const util::Coordinate start,
const util::Coordinate target,
const detail::BBox &tile_bbox)
const BBox &tile_bbox)
{
FloatLine geo_line;
geo_line.emplace_back(static_cast<double>(util::toFloating(start.lon)),
@ -228,7 +227,7 @@ FixedLine coordinatesToTileLine(const util::Coordinate start,
* @param tile_bbox the mercator boundaries of the tile
* @return a point (x,y) on the tile defined by tile_bbox
*/
FixedPoint coordinatesToTilePoint(const util::Coordinate point, const detail::BBox &tile_bbox)
FixedPoint coordinatesToTilePoint(const util::Coordinate point, const BBox &tile_bbox)
{
const FloatPoint geo_point{static_cast<double>(util::toFloating(point.lon)),
static_cast<double>(util::toFloating(point.lat))};
@ -260,7 +259,7 @@ void UnpackEdgeToEdges(const datafacade::BaseDataFacade &facade,
std::vector<datafacade::BaseDataFacade::EdgeData> &unpacked_path)
{
std::array<NodeID, 2> path{{from, to}};
UnpackCHEdge(&facade,
UnpackCHPath(facade,
path.begin(),
path.end(),
[&unpacked_path](const std::pair<NodeID, NodeID> & /* edge */,
@ -268,7 +267,7 @@ void UnpackEdgeToEdges(const datafacade::BaseDataFacade &facade,
unpacked_path.emplace_back(data);
});
}
} // ::detail namespace
} // namespace
Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::string &pbf_buffer)
{
@ -311,15 +310,15 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
std::vector<float> used_point_floats;
std::unordered_map<float, std::size_t> point_float_offsets;
uint8_t max_datasource_id = 0;
std::uint8_t max_datasource_id = 0;
// This is where we accumulate information on turns
std::vector<detail::TurnData> all_turn_data;
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
// exist
const auto use_line_value = [&used_line_ints, &line_int_offsets](const int &value) {
const auto use_line_value = [&used_line_ints, &line_int_offsets](const int value) {
const auto found = line_int_offsets.find(value);
if (found == line_int_offsets.end())
@ -332,7 +331,7 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
};
// Same again
const auto use_point_int_value = [&used_point_ints, &point_int_offsets](const int &value) {
const auto use_point_int_value = [&used_point_ints, &point_int_offsets](const int value) {
const auto found = point_int_offsets.find(value);
std::size_t offset;
@ -352,7 +351,7 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
// And a third time, should probably template this....
const auto use_point_float_value = [&used_point_floats,
&point_float_offsets](const float &value) {
&point_float_offsets](const float value) {
const auto found = point_float_offsets.find(value);
std::size_t offset;
@ -373,7 +372,7 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
// 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 >= detail::MIN_ZOOM_FOR_TURNS)
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
@ -404,10 +403,10 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
edge_based_node_info.count(edge.forward_segment_id.id) == 0)
{
// Add this edge-based-nodeid as an outgoing from the source intersection
auto f = outgoing_edges.find(edge.u);
if (f != outgoing_edges.end())
const auto outgoing_itr_u = outgoing_edges.find(edge.u);
if (outgoing_itr_u != outgoing_edges.end())
{
f->second.push_back(edge.forward_segment_id.id);
outgoing_itr_u->second.push_back(edge.forward_segment_id.id);
}
else
{
@ -415,10 +414,10 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
}
// Add this edge-based-nodeid as an incoming to the target intersection
f = incoming_edges.find(edge.v);
if (f != incoming_edges.end())
const auto incoming_itr_v = incoming_edges.find(edge.v);
if (incoming_itr_v != incoming_edges.end())
{
f->second.push_back(edge.forward_segment_id.id);
incoming_itr_v->second.push_back(edge.forward_segment_id.id);
}
else
{
@ -461,10 +460,13 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
// Now, for every edge-based-node that we discovered (edge-based-nodes are sources
// and targets of turns). EBN is short for edge-based-node
std::vector<NodeID> first_geometry, second_geometry;
std::vector<contractor::QueryEdge::EdgeData> unpacked_shortcut;
std::vector<EdgeWeight> forward_weight_vector;
for (const auto &source_ebn : edge_based_node_info)
{
// Grab a copy of the geometry leading up to the intersection.
std::vector<NodeID> first_geometry;
first_geometry.clear();
facade.GetUncompressedGeometry(source_ebn.second.packed_geometry_id, first_geometry);
// We earlier saved the source and target intersection nodes for every road section.
@ -492,9 +494,9 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
if (SPECIAL_EDGEID == smaller_edge_id)
{
smaller_edge_id = facade.FindSmallestEdge(
target_ebn, source_ebn.first, [](const contractor::QueryEdge::EdgeData &data) {
return data.backward;
});
target_ebn,
source_ebn.first,
[](const contractor::QueryEdge::EdgeData &data) { return data.backward; });
}
// If no edge was found, it means that there's no connection between these nodes,
@ -507,27 +509,33 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
// when exactly? Anyway, unpack it and get the first "real" edgedata
// out of it, which should represent the first hop, which is the one
// we want to find the turn.
auto data = facade.GetEdgeData(smaller_edge_id);
if (data.shortcut)
{
std::vector<contractor::QueryEdge::EdgeData> unpacked_shortcut;
detail::UnpackEdgeToEdges(facade, source_ebn.first, target_ebn, unpacked_shortcut);
data = unpacked_shortcut.front();
}
const auto &data =
[this, smaller_edge_id, source_ebn, target_ebn, &unpacked_shortcut]() {
const auto inner_data = facade.GetEdgeData(smaller_edge_id);
if (inner_data.shortcut)
{
unpacked_shortcut.clear();
UnpackEdgeToEdges(
facade, source_ebn.first, target_ebn, unpacked_shortcut);
return unpacked_shortcut.front();
}
else
return inner_data;
}();
BOOST_ASSERT_MSG(!data.shortcut, "Connecting edge must not be a shortcut");
// This is the geometry leading away from the intersection
// (i.e. the geometry of the target edge-based-node)
std::vector<NodeID> second_geometry;
second_geometry.clear();
facade.GetUncompressedGeometry(
edge_based_node_info.at(target_ebn).packed_geometry_id, second_geometry);
// Now, calculate the sum of the weight of all the segments.
std::vector<EdgeWeight> forward_weight_vector;
forward_weight_vector.clear();
facade.GetUncompressedWeights(source_ebn.second.packed_geometry_id,
forward_weight_vector);
const auto sum_node_weight = std::accumulate(
forward_weight_vector.begin(), forward_weight_vector.end(), 0);
forward_weight_vector.begin(), forward_weight_vector.end(), EdgeWeight{0});
// The edge.distance is the whole edge weight, which includes the turn cost.
// The turn cost is the edge.distance minus the sum of the individual road
@ -581,8 +589,8 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
// 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(detail::TurnData{
coord_via, angle_in_index, turn_angle_index, turn_cost_index});
all_turn_data.emplace_back(
TurnData{coord_via, angle_in_index, turn_angle_index, turn_cost_index});
}
}
}
@ -592,21 +600,23 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
// "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
// need to refer to.
std::vector<EdgeWeight> forward_weight_vector, reverse_weight_vector;
std::vector<std::uint8_t> forward_datasource_vector, reverse_datasource_vector;
for (const auto &edge : edges)
{
int forward_weight = 0, reverse_weight = 0;
uint8_t forward_datasource = 0;
uint8_t reverse_datasource = 0;
std::uint8_t forward_datasource = 0;
std::uint8_t reverse_datasource = 0;
// TODO this approach of writing at least an empty vector for any segment is probably stupid
// (inefficient)
if (edge.forward_packed_geometry_id != SPECIAL_EDGEID)
{
std::vector<EdgeWeight> forward_weight_vector;
forward_weight_vector.clear();
facade.GetUncompressedWeights(edge.forward_packed_geometry_id, forward_weight_vector);
forward_weight = forward_weight_vector[edge.fwd_segment_position];
std::vector<uint8_t> forward_datasource_vector;
forward_datasource_vector.clear();
facade.GetUncompressedDatasources(edge.forward_packed_geometry_id,
forward_datasource_vector);
forward_datasource = forward_datasource_vector[edge.fwd_segment_position];
@ -616,7 +626,7 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
if (edge.reverse_packed_geometry_id != SPECIAL_EDGEID)
{
std::vector<EdgeWeight> reverse_weight_vector;
reverse_weight_vector.clear();
facade.GetUncompressedWeights(edge.reverse_packed_geometry_id, reverse_weight_vector);
BOOST_ASSERT(edge.fwd_segment_position < reverse_weight_vector.size());
@ -624,7 +634,7 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
reverse_weight =
reverse_weight_vector[reverse_weight_vector.size() - edge.fwd_segment_position - 1];
std::vector<uint8_t> reverse_datasource_vector;
reverse_datasource_vector.clear();
facade.GetUncompressedDatasources(edge.reverse_packed_geometry_id,
reverse_datasource_vector);
reverse_datasource = reverse_datasource_vector[reverse_datasource_vector.size() -
@ -648,7 +658,7 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
// Convert tile coordinates into mercator coordinates
util::web_mercator::xyzToMercator(
parameters.x, parameters.y, parameters.z, min_lon, min_lat, max_lon, max_lat);
const detail::BBox tile_bbox{min_lon, min_lat, max_lon, max_lat};
const BBox tile_bbox{min_lon, min_lat, max_lon, max_lat};
// Protobuf serializes blocks when objects go out of scope, hence
// the extra scoping below.
@ -671,6 +681,9 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
{
// Each feature gets a unique id, starting at 1
unsigned id = 1;
std::vector<EdgeWeight> forward_weight_vector;
std::vector<std::uint8_t> forward_datasource_vector;
std::vector<std::uint8_t> reverse_datasource_vector;
for (const auto &edge : edges)
{
// Get coordinates for start/end nodes of segment (NodeIDs u and v)
@ -683,19 +696,19 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
int forward_weight = 0;
int reverse_weight = 0;
uint8_t forward_datasource = 0;
uint8_t reverse_datasource = 0;
std::uint8_t forward_datasource = 0;
std::uint8_t reverse_datasource = 0;
std::string name = facade.GetNameForID(edge.name_id);
if (edge.forward_packed_geometry_id != SPECIAL_EDGEID)
{
std::vector<EdgeWeight> forward_weight_vector;
forward_weight_vector.clear();
facade.GetUncompressedWeights(edge.forward_packed_geometry_id,
forward_weight_vector);
forward_weight = forward_weight_vector[edge.fwd_segment_position];
std::vector<uint8_t> forward_datasource_vector;
forward_datasource_vector.clear();
facade.GetUncompressedDatasources(edge.forward_packed_geometry_id,
forward_datasource_vector);
forward_datasource = forward_datasource_vector[edge.fwd_segment_position];
@ -703,7 +716,7 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
if (edge.reverse_packed_geometry_id != SPECIAL_EDGEID)
{
std::vector<EdgeWeight> reverse_weight_vector;
reverse_weight_vector.clear();
facade.GetUncompressedWeights(edge.reverse_packed_geometry_id,
reverse_weight_vector);
@ -712,7 +725,7 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
reverse_weight = reverse_weight_vector[reverse_weight_vector.size() -
edge.fwd_segment_position - 1];
std::vector<uint8_t> reverse_datasource_vector;
reverse_datasource_vector.clear();
facade.GetUncompressedDatasources(edge.reverse_packed_geometry_id,
reverse_datasource_vector);
reverse_datasource =
@ -725,64 +738,63 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
max_datasource_id = std::max(max_datasource_id, forward_datasource);
max_datasource_id = std::max(max_datasource_id, reverse_datasource);
const auto encode_tile_line =
[&line_layer_writer, &edge, &id, &max_datasource_id, &used_line_ints](
const detail::FixedLine &tile_line,
const std::uint32_t speed_kmh,
const std::size_t duration,
const DatasourceID datasource,
const std::size_t name,
std::int32_t &start_x,
std::int32_t &start_y) {
// Here, we save the two attributes for our feature: the speed and the
// is_small
// boolean. We only serve up speeds from 0-139, so all we do is save
// the
// first
protozero::pbf_writer feature_writer(line_layer_writer,
util::vector_tile::FEATURE_TAG);
// Field 3 is the "geometry type" field. Value 2 is "line"
feature_writer.add_enum(
util::vector_tile::GEOMETRY_TAG,
util::vector_tile::GEOMETRY_TYPE_LINE); // geometry type
// Field 1 for the feature is the "id" field.
feature_writer.add_uint64(util::vector_tile::ID_TAG, id++); // id
{
// When adding attributes to a feature, we have to write
// pairs of numbers. The first value is the index in the
// keys array (written later), and the second value is the
// index into the "values" array (also written later). We're
// not writing the actual speed or bool value here, we're saving
// an index into the "values" array. This means many features
// can share the same value data, leading to smaller tiles.
protozero::packed_field_uint32 field(
feature_writer, util::vector_tile::FEATURE_ATTRIBUTES_TAG);
const auto encode_tile_line = [&line_layer_writer,
&edge,
&id,
&max_datasource_id,
&used_line_ints](const FixedLine &tile_line,
const std::uint32_t speed_kmh,
const std::size_t duration,
const DatasourceID datasource,
const std::size_t name,
std::int32_t &start_x,
std::int32_t &start_y) {
// Here, we save the two attributes for our feature: the speed and the
// is_small boolean. We only serve up speeds from 0-139, so all we do is
// save the first
protozero::pbf_writer feature_writer(line_layer_writer,
util::vector_tile::FEATURE_TAG);
// Field 3 is the "geometry type" field. Value 2 is "line"
feature_writer.add_enum(
util::vector_tile::GEOMETRY_TAG,
util::vector_tile::GEOMETRY_TYPE_LINE); // geometry type
// Field 1 for the feature is the "id" field.
feature_writer.add_uint64(util::vector_tile::ID_TAG, id++); // id
{
// When adding attributes to a feature, we have to write
// pairs of numbers. The first value is the index in the
// keys array (written later), and the second value is the
// index into the "values" array (also written later). We're
// not writing the actual speed or bool value here, we're saving
// an index into the "values" array. This means many features
// can share the same value data, leading to smaller tiles.
protozero::packed_field_uint32 field(
feature_writer, util::vector_tile::FEATURE_ATTRIBUTES_TAG);
field.add_element(0); // "speed" tag key offset
field.add_element(std::min(
speed_kmh, 127u)); // save the speed value, capped at 127
field.add_element(1); // "is_small" tag key offset
field.add_element(
128 + (edge.component.is_tiny ? 0 : 1)); // is_small feature
field.add_element(2); // "datasource" tag key offset
field.add_element(130 + datasource); // datasource value offset
field.add_element(3); // "duration" tag key offset
field.add_element(130 + max_datasource_id + 1 +
duration); // duration value offset
field.add_element(4); // "name" tag key offset
field.add_element(0); // "speed" tag key offset
field.add_element(
std::min(speed_kmh, 127u)); // save the speed value, capped at 127
field.add_element(1); // "is_small" tag key offset
field.add_element(128 +
(edge.component.is_tiny ? 0 : 1)); // is_small feature
field.add_element(2); // "datasource" tag key offset
field.add_element(130 + datasource); // datasource value offset
field.add_element(3); // "duration" tag key offset
field.add_element(130 + max_datasource_id + 1 +
duration); // duration value offset
field.add_element(4); // "name" tag key offset
field.add_element(130 + max_datasource_id + 1 +
used_line_ints.size() +
name); // name value offset
}
{
field.add_element(130 + max_datasource_id + 1 + used_line_ints.size() +
name); // name value offset
}
{
// Encode the geometry for the feature
protozero::packed_field_uint32 geometry(
feature_writer, util::vector_tile::FEATURE_GEOMETRIES_TAG);
encodeLinestring(tile_line, geometry, start_x, start_y);
}
};
// Encode the geometry for the feature
protozero::packed_field_uint32 geometry(
feature_writer, util::vector_tile::FEATURE_GEOMETRIES_TAG);
encodeLinestring(tile_line, geometry, start_x, start_y);
}
};
// If this is a valid forward edge, go ahead and add it to the tile
if (forward_weight != 0 && edge.forward_segment_id.enabled)
@ -902,7 +914,7 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
// Now write the points layer for turn penalty data:
// Add a layer object to the PBF stream. 3=='layer' from the vector tile spec (2.1)
protozero::pbf_writer point_layer_writer(tile_writer, util::vector_tile::LAYER_TAG);
point_layer_writer.add_uint32(util::vector_tile::VERSION_TAG, 2); // version
point_layer_writer.add_uint32(util::vector_tile::VERSION_TAG, 2); // version
point_layer_writer.add_string(util::vector_tile::NAME_TAG, "turns"); // name
point_layer_writer.add_uint32(util::vector_tile::EXTENT_TAG,
util::vector_tile::EXTENT); // extent
@ -914,13 +926,13 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
// 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 detail::FixedPoint &tile_point, const detail::TurnData &point_turn_data) {
const FixedPoint &tile_point, const 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"
feature_writer.add_enum(
util::vector_tile::GEOMETRY_TAG,
util::vector_tile::GEOMETRY_TYPE_POINT); // geometry type
util::vector_tile::GEOMETRY_TYPE_POINT); // geometry type
feature_writer.add_uint64(util::vector_tile::ID_TAG, id++); // id
{
// Write out the 3 properties we want on the feature. These
@ -947,8 +959,7 @@ Status TilePlugin::HandleRequest(const api::TileParameters &parameters, std::str
for (const auto &turndata : all_turn_data)
{
const auto tile_point = coordinatesToTilePoint(turndata.coordinate, tile_bbox);
if (!boost::geometry::within(detail::point_t(tile_point.x, tile_point.y),
detail::clip_box))
if (!boost::geometry::within(point_t(tile_point.x, tile_point.y), clip_box))
{
continue;
}

View File

@ -122,7 +122,7 @@ BOOST_AUTO_TEST_CASE(test_tile)
BOOST_CHECK_EQUAL(layer_message.get_uint32(), util::vector_tile::EXTENT);
break;
case util::vector_tile::FEATURE_TAG:
check_speed_feature(layer_message.get_message());
check_feature(layer_message.get_message());
break;
case util::vector_tile::KEY_TAG:
layer_message.get_string();