diff --git a/CHANGELOG.md b/CHANGELOG.md index 174717920..148001a6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/include/engine/edge_unpacker.hpp b/include/engine/edge_unpacker.hpp index 8d1f131ba..88291d8c6 100644 --- a/include/engine/edge_unpacker.hpp +++ b/include/engine/edge_unpacker.hpp @@ -8,8 +8,8 @@ #include "util/guidance/turn_lanes.hpp" #include "util/typedefs.hpp" -#include #include +#include namespace osrm { @@ -37,16 +37,19 @@ namespace engine * original edge found. */ -template -inline void UnpackCHEdge(DataFacadeT *facade, - RandomIter packed_path_begin, - RandomIter packed_path_end, - const Callback &callback) +template +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> recursion_stack; + std::stack> 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::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)(edge, data); } } } diff --git a/include/engine/routing_algorithms/routing_base.hpp b/include/engine/routing_algorithms/routing_base.hpp index 615d174c9..f5f1d7a67 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -229,8 +229,8 @@ template 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 BasicRoutingInterface &phantom_node_pair, &start_traversed_in_reverse, &target_traversed_in_reverse](std::pair & /* 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 id_vector; facade->GetUncompressedGeometry(geometry_index, id_vector); BOOST_ASSERT(id_vector.size() > 0); @@ -260,7 +260,7 @@ template class BasicRoutingInterface std::vector 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 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 BasicRoutingInterface void UnpackEdge(const NodeID from, const NodeID to, std::vector &unpacked_path) const { std::array path{{from, to}}; - UnpackCHEdge( - facade, + UnpackCHPath( + *facade, path.begin(), path.end(), [&unpacked_path](const std::pair &edge, const EdgeData & /* data */) { diff --git a/include/util/static_graph.hpp b/include/util/static_graph.hpp index 86ea85b17..547ca2439 100644 --- a/include/util/static_graph.hpp +++ b/include/util/static_graph.hpp @@ -160,17 +160,17 @@ template class StaticGraph * matching edge is found. */ template - 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(filter)(data)) { smallest_edge = edge; smallest_weight = data.distance; diff --git a/include/util/typedefs.hpp b/include/util/typedefs.hpp index 50764727d..36797eea0 100644 --- a/include/util/typedefs.hpp +++ b/include/util/typedefs.hpp @@ -85,8 +85,6 @@ static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits::m using DatasourceID = std::uint8_t; -using DatasourceID = std::uint8_t; - struct SegmentID { SegmentID(const NodeID id_, const bool enabled_) : id{id_}, enabled{enabled_} diff --git a/include/util/vector_tile.hpp b/include/util/vector_tile.hpp index 7fc5d840a..f3c05791e 100644 --- a/include/util/vector_tile.hpp +++ b/include/util/vector_tile.hpp @@ -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; diff --git a/src/engine/plugins/tile.cpp b/src/engine/plugins/tile.cpp index 97c377f0d..4651c7f18 100644 --- a/src/engine/plugins/tile.cpp +++ b/src/engine/plugins/tile.cpp @@ -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; -using FloatPoint = detail::Point; +using FixedPoint = Point; +using FloatPoint = Point; using FixedLine = std::vector; using FloatLine = std::vector; @@ -122,7 +122,7 @@ inline bool encodeLinestring(const FixedLine &line, return false; } - const unsigned LINETO_count = static_cast(line_size) - 1; + const unsigned lineto_count = static_cast(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(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(util::toFloating(point.lon)), static_cast(util::toFloating(point.lat))}; @@ -260,7 +259,7 @@ void UnpackEdgeToEdges(const datafacade::BaseDataFacade &facade, std::vector &unpacked_path) { std::array path{{from, to}}; - UnpackCHEdge(&facade, + UnpackCHPath(facade, path.begin(), path.end(), [&unpacked_path](const std::pair & /* 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 ¶meters, std::string &pbf_buffer) { @@ -311,15 +310,15 @@ Status TilePlugin::HandleRequest(const api::TileParameters ¶meters, std::str std::vector used_point_floats; std::unordered_map 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 all_turn_data; + std::vector 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 ¶meters, 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 ¶meters, 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 ¶meters, 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 ¶meters, 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 ¶meters, 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 ¶meters, 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 first_geometry, second_geometry; + std::vector unpacked_shortcut; + std::vector 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 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 ¶meters, 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 ¶meters, 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 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 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 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 ¶meters, 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 ¶meters, 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 forward_weight_vector, reverse_weight_vector; + std::vector 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 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 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 ¶meters, std::str if (edge.reverse_packed_geometry_id != SPECIAL_EDGEID) { - std::vector 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 ¶meters, std::str reverse_weight = reverse_weight_vector[reverse_weight_vector.size() - edge.fwd_segment_position - 1]; - std::vector 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 ¶meters, 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 ¶meters, std::str { // Each feature gets a unique id, starting at 1 unsigned id = 1; + std::vector forward_weight_vector; + std::vector forward_datasource_vector; + std::vector 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 ¶meters, 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 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 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 ¶meters, std::str if (edge.reverse_packed_geometry_id != SPECIAL_EDGEID) { - std::vector 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 ¶meters, std::str reverse_weight = reverse_weight_vector[reverse_weight_vector.size() - edge.fwd_segment_position - 1]; - std::vector 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 ¶meters, 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 ¶meters, 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 ¶meters, 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 ¶meters, 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; } diff --git a/unit_tests/library/tile.cpp b/unit_tests/library/tile.cpp index becfdb90b..16cbcb06d 100644 --- a/unit_tests/library/tile.cpp +++ b/unit_tests/library/tile.cpp @@ -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();