diff --git a/src/engine/plugins/tile.cpp b/src/engine/plugins/tile.cpp index f38f2225b..bc3fb2f0b 100644 --- a/src/engine/plugins/tile.cpp +++ b/src/engine/plugins/tile.cpp @@ -621,6 +621,22 @@ Status TilePlugin::HandleRequest(const std::shared_ptrGetUncompressedForwardWeights(edge.packed_geometry_id); + const auto reverse_weight_vector = + 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]; + use_line_value(reverse_weight); + use_line_value(forward_weight); + } + // Begin the layer features block { // Each feature gets a unique id, starting at 1 @@ -652,21 +668,18 @@ Status TilePlugin::HandleRequest(const std::shared_ptrGetNameForID(edge.name_id); const auto name_offset = [&name, &names, &name_offsets]() { auto iter = name_offsets.find(name); if (iter == name_offsets.end()) { - auto offset = names.size() - 1; + auto offset = names.size(); name_offsets[name] = offset; + names.push_back(std::move(name)); return offset; } return iter->second; }(); - names.push_back(std::move(name)); const auto encode_tile_line = [&line_layer_writer, &edge, diff --git a/unit_tests/library/tile.cpp b/unit_tests/library/tile.cpp index 50bc466cb..0f1bcbacf 100644 --- a/unit_tests/library/tile.cpp +++ b/unit_tests/library/tile.cpp @@ -208,4 +208,316 @@ BOOST_AUTO_TEST_CASE(test_tile) BOOST_CHECK_EQUAL(number_of_turns_found, 732); } +BOOST_AUTO_TEST_CASE(test_tile_turns) +{ + const auto args = get_args(); + auto osrm = getOSRM(args.at(0)); + + using namespace osrm; + + // 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 layer + tile_message.skip(); + + tile_message.next(); + auto layer_message = tile_message.get_message(); + + std::vector found_bearing_in_indexes; + std::vector found_turn_angles_indexes; + std::vector found_penalties_indexes; + + const auto check_turn_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 + BOOST_CHECK_EQUAL(feature_message.tag(), util::vector_tile::FEATURE_ATTRIBUTES_TAG); + // properties + auto feature_iter_pair = feature_message.get_packed_uint32(); + BOOST_CHECK_EQUAL(std::distance(feature_iter_pair.begin(), feature_iter_pair.end()), 6); + auto iter = feature_iter_pair.begin(); + BOOST_CHECK_EQUAL(*iter++, 0); // bearing_in key + found_bearing_in_indexes.push_back(*iter++); + BOOST_CHECK_EQUAL(*iter++, 1); // turn_angle key + found_turn_angles_indexes.push_back(*iter++); + BOOST_CHECK_EQUAL(*iter++, 2); // cost key + found_penalties_indexes.push_back(*iter++); // skip value check, can be valud uint32 + BOOST_CHECK(iter == feature_iter_pair.end()); + // geometry + feature_message.next(); + auto geometry_iter_pair = feature_message.get_packed_uint32(); + BOOST_CHECK_GT(std::distance(geometry_iter_pair.begin(), geometry_iter_pair.end()), 1); + }; + + std::unordered_map float_vals; + std::unordered_map sint64_vals; + + int kv_index = 0; + + const auto check_value = [&](protozero::pbf_reader value) { + while (value.next()) + { + switch (value.tag()) + { + case util::vector_tile::VARIANT_TYPE_FLOAT: + float_vals[kv_index] = value.get_float(); + break; + case util::vector_tile::VARIANT_TYPE_SINT64: + sint64_vals[kv_index] = value.get_sint64(); + break; + default: + BOOST_CHECK(false); + } + kv_index++; + } + }; + + auto number_of_turn_keys = 0u; + auto number_of_turns_found = 0u; + + 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(), "turns"); + 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_turn_feature(layer_message.get_message()); + number_of_turns_found++; + break; + case util::vector_tile::KEY_TAG: + layer_message.get_string(); + number_of_turn_keys++; + break; + case util::vector_tile::VARIANT_TAG: + check_value(layer_message.get_message()); + break; + default: + BOOST_CHECK(false); // invalid tag + break; + } + } + + // Verify that we got the expected turn penalties + std::vector actual_turn_penalties; + for (const auto &i : found_penalties_indexes) + { + BOOST_CHECK(float_vals.count(i) == 1); + actual_turn_penalties.push_back(float_vals[i]); + } + std::sort(actual_turn_penalties.begin(), actual_turn_penalties.end()); + const std::vector expected_turn_penalties = { + 0, 0, 0, 0, 0, 0, 0.1, 0.1, 0.3, 0.4, 1.3, 1.8, 5.4, 5.5, 5.8, 7.1, 7.2, 7.2}; + BOOST_CHECK(actual_turn_penalties == expected_turn_penalties); + + // Verify the expected turn angles + std::vector actual_turn_angles; + for (const auto &i : found_turn_angles_indexes) + { + BOOST_CHECK(sint64_vals.count(i) == 1); + actual_turn_angles.push_back(sint64_vals[i]); + } + std::sort(actual_turn_angles.begin(), actual_turn_angles.end()); + const std::vector expected_turn_angles = { + -123, -120, -118, -64, -57, -29, -28, -3, -2, 2, 3, 28, 29, 57, 64, 118, 120, 123}; + BOOST_CHECK(actual_turn_angles == expected_turn_angles); + + // Verify the expected bearings + std::vector actual_turn_bearings; + for (const auto &i : found_bearing_in_indexes) + { + BOOST_CHECK(sint64_vals.count(i) == 1); + actual_turn_bearings.push_back(sint64_vals[i]); + } + std::sort(actual_turn_bearings.begin(), actual_turn_bearings.end()); + const std::vector expected_turn_bearings = { + 49, 49, 106, 106, 169, 169, 171, 171, 229, 229, 258, 258, 287, 287, 349, 349, 352, 352}; + BOOST_CHECK(actual_turn_bearings == expected_turn_bearings); +} + +BOOST_AUTO_TEST_CASE(test_tile_speeds) +{ + const auto args = get_args(); + auto osrm = getOSRM(args.at(0)); + + using namespace osrm; + + // Small tile so we can test all the values + // TileParameters params{272953, 191177, 19}; + TileParameters params{136477, 95580, 18}; + + 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 + protozero::pbf_reader layer_message = tile_message.get_message(); + + std::vector found_speed_indexes; + std::vector found_component_indexes; + std::vector found_datasource_indexes; + std::vector found_duration_indexes; + std::vector found_name_indexes; + + 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_LINE); + + 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 + BOOST_CHECK_EQUAL(feature_message.tag(), util::vector_tile::FEATURE_ATTRIBUTES_TAG); + // properties + auto property_iter_pair = feature_message.get_packed_uint32(); + auto value_begin = property_iter_pair.begin(); + auto value_end = property_iter_pair.end(); + BOOST_CHECK_EQUAL(std::distance(value_begin, value_end), 10); + auto iter = value_begin; + BOOST_CHECK_EQUAL(*iter++, 0); // speed key + found_speed_indexes.push_back(*iter++); + BOOST_CHECK_EQUAL(*iter++, 1); // component key + // component value + found_component_indexes.push_back(*iter++); + BOOST_CHECK_EQUAL(*iter++, 2); // data source key + found_datasource_indexes.push_back(*iter++); + BOOST_CHECK_EQUAL(*iter++, 3); // duration key + found_duration_indexes.push_back(*iter++); + // name + BOOST_CHECK_EQUAL(*iter++, 4); + found_name_indexes.push_back(*iter++); + BOOST_CHECK(iter == value_end); + // geometry + feature_message.next(); + auto geometry_iter_pair = feature_message.get_packed_uint32(); + BOOST_CHECK_GT(std::distance(geometry_iter_pair.begin(), geometry_iter_pair.end()), 1); + }; + + std::unordered_map string_vals; + std::unordered_map bool_vals; + std::unordered_map uint64_vals; + std::unordered_map double_vals; + + int kv_index = 0; + + const auto check_value = [&](protozero::pbf_reader value) { + while (value.next()) + { + switch (value.tag()) + { + case util::vector_tile::VARIANT_TYPE_BOOL: + bool_vals[kv_index] = value.get_bool(); + break; + case util::vector_tile::VARIANT_TYPE_DOUBLE: + double_vals[kv_index] = value.get_double(); + break; + case util::vector_tile::VARIANT_TYPE_FLOAT: + value.get_float(); + break; + case util::vector_tile::VARIANT_TYPE_STRING: + string_vals[kv_index] = value.get_string(); + break; + case util::vector_tile::VARIANT_TYPE_UINT64: + uint64_vals[kv_index] = value.get_uint64(); + break; + case util::vector_tile::VARIANT_TYPE_SINT64: + value.get_sint64(); + break; + } + kv_index++; + } + }; + + auto number_of_speed_keys = 0u; + auto number_of_speed_values = 0u; + + 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(), "speeds"); + 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: + layer_message.get_string(); + number_of_speed_keys++; + break; + case util::vector_tile::VARIANT_TAG: + check_value(layer_message.get_message()); + number_of_speed_values++; + break; + default: + BOOST_CHECK(false); // invalid tag + break; + } + } + + std::vector actual_names; + for (const auto &i : found_name_indexes) + { + BOOST_CHECK(string_vals.count(i) == 1); + actual_names.push_back(string_vals[i]); + } + std::sort(actual_names.begin(), actual_names.end()); + const std::vector expected_names = {"Avenue du Carnier", + "Avenue du Carnier", + "Avenue du Carnier", + "Avenue du Carnier", + "Avenue du Carnier", + "Avenue du Maréchal Foch", + "Avenue du Maréchal Foch", + "Avenue du Maréchal Foch", + "Avenue du Maréchal Foch", + "Avenue du Maréchal Foch", + "Avenue du Maréchal Foch", + "Avenue du Professeur Langevin", + "Avenue du Professeur Langevin", + "Avenue du Professeur Langevin", + "Montée de la Crémaillère", + "Montée de la Crémaillère", + "Rue Jules Ferry", + "Rue Jules Ferry", + "Rue Professeur Calmette", + "Rue Professeur Calmette"}; + BOOST_CHECK(actual_names == expected_names); +} + BOOST_AUTO_TEST_SUITE_END()