From 4136bf2808ad9e0d68f96ce974b48c44cd1b7587 Mon Sep 17 00:00:00 2001 From: Daniel Patterson Date: Sat, 17 Jun 2017 17:10:08 +0200 Subject: [PATCH] Add layer to debug tiles to expose all OSM nodes in that area. --- src/engine/plugins/tile.cpp | 45 ++++++++++ unit_tests/library/tile.cpp | 158 ++++++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+) diff --git a/src/engine/plugins/tile.cpp b/src/engine/plugins/tile.cpp index 74f5b100e..80e027971 100644 --- a/src/engine/plugins/tile.cpp +++ b/src/engine/plugins/tile.cpp @@ -831,6 +831,51 @@ void encodeVectorTile(const datafacade::ContiguousInternalMemoryDataFacadeBase & values_writer.add_float(util::vector_tile::VARIANT_TYPE_FLOAT, value); } } + + // OSM Node tile layer + { + 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_string(util::vector_tile::NAME_TAG, "osmnodes"); // name + point_layer_writer.add_uint32(util::vector_tile::EXTENT_TAG, + util::vector_tile::EXTENT); // extent + + std::vector internal_nodes; + internal_nodes.reserve(edges.size() * 2); + for (const auto &edge : edges) + { + internal_nodes.push_back(edge.u); + internal_nodes.push_back(edge.v); + } + std::sort(internal_nodes.begin(), internal_nodes.end()); + auto new_end = std::unique(internal_nodes.begin(), internal_nodes.end()); + internal_nodes.resize(new_end - internal_nodes.begin()); + + for (const auto &internal_node : internal_nodes) + { + const auto coord = facade.GetCoordinateOfNode(internal_node); + const auto tile_point = coordinatesToTilePoint(coord, tile_bbox); + if (!boost::geometry::within(point_t(tile_point.x, tile_point.y), clip_box)) + { + continue; + } + 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 + const auto osmid = + static_cast(facade.GetOSMNodeIDOfNode(internal_node)); + feature_writer.add_uint64(util::vector_tile::ID_TAG, osmid); // id + // There are no additional properties, just the ID and the geometry + { + // Add the geometry as the last field in this feature + protozero::packed_field_uint32 geometry( + feature_writer, util::vector_tile::FEATURE_GEOMETRIES_TAG); + encodePoint(tile_point, geometry); + } + } + } } // protozero serializes data during object destructors, so once the scope closes, // our result buffer will have all the tile data encoded into it. diff --git a/unit_tests/library/tile.cpp b/unit_tests/library/tile.cpp index 85af1ca30..36fefb543 100644 --- a/unit_tests/library/tile.cpp +++ b/unit_tests/library/tile.cpp @@ -11,6 +11,7 @@ #include "osrm/osrm.hpp" #include "osrm/status.hpp" +#include "util/typedefs.hpp" #include "util/vector_tile.hpp" #include @@ -212,6 +213,58 @@ template void test_tile(algorithm &osrm) BOOST_CHECK_EQUAL(number_of_turn_keys, 4); BOOST_CHECK(number_of_turns_found > 700); + + tile_message.next(); + layer_message = tile_message.get_message(); + + auto number_of_nodes_found = 0u; + + const auto check_osmnode_feature = [](protozero::pbf_reader feature_message) { + feature_message.next(); // advance parser to first entry + BOOST_CHECK_EQUAL(feature_message.tag(), util::vector_tile::GEOMETRY_TAG); + BOOST_CHECK_EQUAL(feature_message.get_enum(), util::vector_tile::GEOMETRY_TYPE_POINT); + + feature_message.next(); // advance to next entry + BOOST_CHECK_EQUAL(feature_message.tag(), util::vector_tile::ID_TAG); + feature_message.get_uint64(); // id + + feature_message.next(); // advance to next entry + // Note - on this layer, there should be no feature attributes, the next thing + // we get should be the geometry + BOOST_CHECK_EQUAL(feature_message.tag(), util::vector_tile::FEATURE_GEOMETRIES_TAG); + auto geometry_iter_pair = feature_message.get_packed_uint32(); + BOOST_CHECK_GT(std::distance(geometry_iter_pair.begin(), geometry_iter_pair.end()), 1); + }; + + while (layer_message.next()) + { + switch (layer_message.tag()) + { + case util::vector_tile::VERSION_TAG: + BOOST_CHECK_EQUAL(layer_message.get_uint32(), 2); + break; + case util::vector_tile::NAME_TAG: + BOOST_CHECK_EQUAL(layer_message.get_string(), "osmnodes"); + break; + case util::vector_tile::EXTENT_TAG: + BOOST_CHECK_EQUAL(layer_message.get_uint32(), util::vector_tile::EXTENT); + break; + case util::vector_tile::FEATURE_TAG: + check_osmnode_feature(layer_message.get_message()); + number_of_nodes_found++; + break; + case util::vector_tile::KEY_TAG: + BOOST_CHECK(false); // There should be no properties on node features + break; + case util::vector_tile::VARIANT_TAG: + BOOST_CHECK(false); // There should be no properties on node features + break; + default: + BOOST_CHECK(false); // invalid tag + break; + } + } + BOOST_CHECK_EQUAL(number_of_nodes_found, 1791); } BOOST_AUTO_TEST_CASE(test_tile_ch) @@ -613,4 +666,109 @@ BOOST_AUTO_TEST_CASE(test_tile_speeds_mld) test_tile_speeds(osrm); } +template void test_tile_nodes(algorithm &osrm) +{ + using namespace osrm; + + // Small tile so we can test all the values + // TileParameters params{272953, 191177, 19}; + // TileParameters params{136477, 95580, 18}; + // Small tile where we can test all the values + TileParameters params{272953, 191177, 19}; + + std::string result; + const auto rc = osrm.Tile(params, result); + BOOST_CHECK(rc == Status::Ok); + + BOOST_CHECK_GT(result.size(), 128); + + protozero::pbf_reader tile_message(result); + tile_message.next(); + BOOST_CHECK_EQUAL(tile_message.tag(), util::vector_tile::LAYER_TAG); // must be a layer + + // Skip the segments and turns layers + tile_message.skip(); + tile_message.next(); + tile_message.skip(); + + // Get the osmnodes layer + tile_message.next(); + protozero::pbf_reader layer_message = tile_message.get_message(); + + std::vector found_node_ids; + + const auto check_feature = [&](protozero::pbf_reader feature_message) { + feature_message.next(); // advance parser to first entry + BOOST_CHECK_EQUAL(feature_message.tag(), util::vector_tile::GEOMETRY_TAG); + BOOST_CHECK_EQUAL(feature_message.get_enum(), util::vector_tile::GEOMETRY_TYPE_POINT); + + feature_message.next(); // advance to next entry + BOOST_CHECK_EQUAL(feature_message.tag(), util::vector_tile::ID_TAG); + found_node_ids.push_back(feature_message.get_uint64()); // id + + feature_message.next(); // advance to next entry + BOOST_CHECK_EQUAL(feature_message.tag(), util::vector_tile::FEATURE_GEOMETRIES_TAG); + auto geometry_iter_pair = feature_message.get_packed_uint32(); + BOOST_CHECK_GT(std::distance(geometry_iter_pair.begin(), geometry_iter_pair.end()), 1); + }; + + while (layer_message.next()) + { + switch (layer_message.tag()) + { + case util::vector_tile::VERSION_TAG: + BOOST_CHECK_EQUAL(layer_message.get_uint32(), 2); + break; + case util::vector_tile::NAME_TAG: + BOOST_CHECK_EQUAL(layer_message.get_string(), "osmnodes"); + break; + case util::vector_tile::EXTENT_TAG: + BOOST_CHECK_EQUAL(layer_message.get_uint32(), util::vector_tile::EXTENT); + break; + case util::vector_tile::FEATURE_TAG: + check_feature(layer_message.get_message()); + break; + case util::vector_tile::KEY_TAG: + BOOST_CHECK(false); // There should be no keys + break; + case util::vector_tile::VARIANT_TAG: + BOOST_CHECK(false); // There should be no values + break; + default: + BOOST_CHECK(false); // invalid tag + break; + } + } + + std::sort(found_node_ids.begin(), found_node_ids.end()); + const std::vector expected_node_ids = { + 25191722, 25191725, 357300400, 1737389138, 1737389140, 2241375220}; + BOOST_CHECK(found_node_ids == expected_node_ids); +} + +BOOST_AUTO_TEST_CASE(test_tile_nodes_ch) +{ + using namespace osrm; + + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm", osrm::EngineConfig::Algorithm::CH); + test_tile_nodes(osrm); +} + +BOOST_AUTO_TEST_CASE(test_tile_nodes_corech) +{ + using namespace osrm; + + auto osrm = + getOSRM(OSRM_TEST_DATA_DIR "/corech/monaco.osrm", osrm::EngineConfig::Algorithm::CoreCH); + test_tile_nodes(osrm); +} + +BOOST_AUTO_TEST_CASE(test_tile_nodes_mld) +{ + using namespace osrm; + + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/mld/monaco.osrm", osrm::EngineConfig::Algorithm::MLD); + test_tile_nodes(osrm); +} + BOOST_AUTO_TEST_SUITE_END()