Adds turn instructions to the turns layer in debug tiles. (#4460)

Add turn types and modifiers to turn points in debug tiles.  Also refactor some of the tile code to reduce some repetition.
This commit is contained in:
Daniel Patterson 2017-09-01 15:08:22 -07:00 committed by GitHub
parent 89cf6d9e74
commit 0fc1aa2711
9 changed files with 270 additions and 150 deletions

View File

@ -17,6 +17,8 @@
updating ETAs returned, without changing route selection (for example, in a distance-based profile with traffic data loaded). updating ETAs returned, without changing route selection (for example, in a distance-based profile with traffic data loaded).
- Infrastructure: - Infrastructure:
- New file `.osrm.cell_metrics` created by `osrm-customize`. - New file `.osrm.cell_metrics` created by `osrm-customize`.
- Debug tiles:
- Added new properties `type` and `modifier` to `turns` layer, useful for viewing guidance calculated turn types on the map
# 5.11.0 # 5.11.0
- Changes from 5.10: - Changes from 5.10:

View File

@ -437,6 +437,8 @@ Vector tiles contain two layers:
| `turn_angle` | `integer` | the angle of the turn, relative to the `bearing_in`. -180 to +180, 0 = straight ahead, 90 = 90-degrees to the right | | `turn_angle` | `integer` | the angle of the turn, relative to the `bearing_in`. -180 to +180, 0 = straight ahead, 90 = 90-degrees to the right |
| `cost` | `float` | the time we think it takes to make that turn, in seconds. May be negative, depending on how the data model is constructed (some turns get a "bonus"). | | `cost` | `float` | the time we think it takes to make that turn, in seconds. May be negative, depending on how the data model is constructed (some turns get a "bonus"). |
| `weight` | `float` | the weight we think it takes to make that turn. May be negative, depending on how the data model is constructed (some turns get a "bonus"). ACTUAL ROUTING USES THIS VALUE | | `weight` | `float` | the weight we think it takes to make that turn. May be negative, depending on how the data model is constructed (some turns get a "bonus"). ACTUAL ROUTING USES THIS VALUE |
| `type` | `string` | the type of this turn - values like `turn`, `continue`, etc. See the `StepManeuver` for a partial list, this field also exposes internal turn types that are never returned with an API response |
| `modifier` | `string` | the direction modifier of the turn (`left`, `sharp left`, etc) |
## Result objects ## Result objects

View File

@ -36,6 +36,15 @@ namespace detail
std::string instructionTypeToString(extractor::guidance::TurnType::Enum type); std::string instructionTypeToString(extractor::guidance::TurnType::Enum type);
std::string instructionModifierToString(extractor::guidance::DirectionModifier::Enum modifier); std::string instructionModifierToString(extractor::guidance::DirectionModifier::Enum modifier);
/**
* Returns a string representing all instruction types (including internal types that
* are normally not exposed in route responses)
*
* @param type the TurnType value to convert into a string
* @return a string representing the turn type (e.g. `turn` or `continue`)
*/
std::string internalInstructionTypeToString(extractor::guidance::TurnType::Enum type);
util::json::Array coordinateToLonLat(const util::Coordinate coordinate); util::json::Array coordinateToLonLat(const util::Coordinate coordinate);
std::string modeToString(const extractor::TravelMode mode); std::string modeToString(const extractor::TravelMode mode);

View File

@ -24,6 +24,7 @@ struct TurnData final
const int turn_angle; const int turn_angle;
const EdgeWeight weight; const EdgeWeight weight;
const EdgeWeight duration; const EdgeWeight duration;
const extractor::guidance::TurnInstruction turn_instruction;
}; };
using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf; using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf;

View File

@ -41,15 +41,47 @@ const constexpr char *modifier_names[] = {"uturn",
"left", "left",
"sharp left"}; "sharp left"};
// translations of TurnTypes. Not all types are exposed to the outside world. /**
// invalid types should never be returned as part of the API * Human readable values for TurnType enum values
const constexpr char *turn_type_names[] = { */
"invalid", "new name", "continue", "turn", "merge", struct TurnTypeName
"on ramp", "off ramp", "fork", "end of road", "notification", {
"roundabout", "roundabout", "rotary", "rotary", "roundabout turn", // String value we return with our API
"roundabout turn", "use lane", "invalid", "invalid", "invalid", const char *external_name;
"invalid", "invalid", "invalid", "invalid", "invalid", // Internal only string name for the turn type - useful for debugging
"invalid", "invalid"}; // and used by debug tiles for visualizing hidden turn types
const char *internal_name;
};
// Indexes in this list correspond to the Enum values of osrm::extractor::guidance::TurnType
const constexpr TurnTypeName turn_type_names[] = {
{"invalid", "(not set)"},
{"new name", "new name"},
{"continue", "continue"},
{"turn", "turn"},
{"merge", "merge"},
{"on ramp", "on ramp"},
{"off ramp", "off ramp"},
{"fork", "fork"},
{"end of road", "end of road"},
{"notification", "notification"},
{"roundabout", "enter roundabout"},
{"roundabout", "enter and exit roundabout"},
{"rotary", "enter rotary"},
{"rotary", "enter and exit rotary"},
{"roundabout turn", "enter roundabout turn"},
{"roundabout turn", "enter and exit roundabout turn"},
{"use lane", "use lane"},
{"invalid", "(noturn)"},
{"invalid", "(suppressed)"},
{"invalid", "(enter roundabout at exit)"},
{"invalid", "(exit roundabout)"},
{"invalid", "(enter rotary at exit)"},
{"invalid", "(exit rotary)"},
{"invalid", "(enter roundabout intersection at exit)"},
{"invalid", "(exit roundabout intersection)"},
{"invalid", "(stay on roundabout)"},
{"invalid", "(sliproad)"}};
const constexpr char *waypoint_type_names[] = {"invalid", "arrive", "depart"}; const constexpr char *waypoint_type_names[] = {"invalid", "arrive", "depart"};
@ -69,7 +101,14 @@ std::string instructionTypeToString(const TurnType::Enum type)
{ {
static_assert(sizeof(turn_type_names) / sizeof(turn_type_names[0]) >= TurnType::MaxTurnType, static_assert(sizeof(turn_type_names) / sizeof(turn_type_names[0]) >= TurnType::MaxTurnType,
"Some turn types has not string representation."); "Some turn types has not string representation.");
return turn_type_names[static_cast<std::size_t>(type)]; return turn_type_names[static_cast<std::size_t>(type)].external_name;
}
std::string internalInstructionTypeToString(const TurnType::Enum type)
{
static_assert(sizeof(turn_type_names) / sizeof(turn_type_names[0]) >= TurnType::MaxTurnType,
"Some turn types has not string representation.");
return turn_type_names[static_cast<std::size_t>(type)].internal_name;
} }
util::json::Array lanesFromIntersection(const guidance::IntermediateIntersection &intersection) util::json::Array lanesFromIntersection(const guidance::IntermediateIntersection &intersection)

View File

@ -6,6 +6,8 @@
#include "util/vector_tile.hpp" #include "util/vector_tile.hpp"
#include "util/web_mercator.hpp" #include "util/web_mercator.hpp"
#include "engine/api/json_factory.hpp"
#include <boost/geometry.hpp> #include <boost/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp> #include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/geometries/point_xy.hpp> #include <boost/geometry/geometries/point_xy.hpp>
@ -37,6 +39,41 @@ constexpr const static int MIN_ZOOM_FOR_TURNS = 15;
namespace namespace
{ {
// Creates an indexed lookup table for values - used to encoded the vector tile
// which uses a lookup table and index pointers for encoding
template <typename T> struct ValueIndexer
{
private:
std::vector<T> used_values;
std::unordered_map<T, std::size_t> value_offsets;
public:
std::size_t add(const T &value)
{
const auto found = value_offsets.find(value);
std::size_t offset;
if (found == value_offsets.end())
{
used_values.push_back(value);
offset = used_values.size() - 1;
value_offsets[value] = offset;
}
else
{
offset = found->second;
}
return offset;
}
std::size_t indexOf(const T &value) { return value_offsets[value]; };
const std::vector<T> &values() { return used_values; }
std::size_t size() const { return used_values.size(); }
};
using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf; using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf;
// TODO: Port all this encoding logic to https://github.com/mapbox/vector-tile, which wasn't // TODO: Port all this encoding logic to https://github.com/mapbox/vector-tile, which wasn't
// available when this code was originally written. // available when this code was originally written.
@ -281,87 +318,17 @@ void encodeVectorTile(const DataFacadeBase &facade,
std::string &pbf_buffer) std::string &pbf_buffer)
{ {
// Vector tiles encode properties as references to a common lookup table.
// When we add a property to a "feature", we actually attach the index of the value
// rather than the value itself. Thus, we need to keep a list of the unique
// values we need, and we add this list to the tile as a lookup table. This
// vector holds all the actual used values, the feature refernce offsets in
// this vector.
// for integer values
std::vector<int> used_line_ints;
// While constructing the tile, we keep track of which integers we have in our table
// and their offsets, so multiple features can re-use the same values
std::unordered_map<int, std::size_t> line_int_offsets;
// Same idea for street names - one lookup table for names for all features
std::vector<util::StringView> names;
std::unordered_map<util::StringView, std::size_t> name_offsets;
// And again for integer values used by points.
std::vector<int> used_point_ints;
std::unordered_map<int, std::size_t> point_int_offsets;
// And again for float values used by points
std::vector<float> used_point_floats;
std::unordered_map<float, std::size_t> point_float_offsets;
std::uint8_t max_datasource_id = 0; std::uint8_t max_datasource_id = 0;
// This is where we accumulate information on turns // Vector tiles encode properties on features as indexes into a layer-specific
// lookup table. These ValueIndexer's act as memoizers for values as we discover
// Helper function for adding a new value to the line_ints lookup table. Returns // them during edge explioration, and are then used to generate the lookup
// the index of the value in the table, adding the value if it doesn't already // tables for each tile layer.
// exist ValueIndexer<int> line_int_index;
const auto use_line_value = [&used_line_ints, &line_int_offsets](const int value) { ValueIndexer<util::StringView> line_string_index;
const auto found = line_int_offsets.find(value); ValueIndexer<int> point_int_index;
ValueIndexer<float> point_float_index;
if (found == line_int_offsets.end()) ValueIndexer<std::string> point_string_index;
{
used_line_ints.push_back(value);
line_int_offsets[value] = used_line_ints.size() - 1;
}
return;
};
// Same again
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;
if (found == point_int_offsets.end())
{
used_point_ints.push_back(value);
offset = used_point_ints.size() - 1;
point_int_offsets[value] = offset;
}
else
{
offset = found->second;
}
return offset;
};
// And a third time, should probably template this....
const auto use_point_float_value = [&used_point_floats,
&point_float_offsets](const float value) {
const auto found = point_float_offsets.find(value);
std::size_t offset;
if (found == point_float_offsets.end())
{
used_point_floats.push_back(value);
offset = used_point_floats.size() - 1;
point_float_offsets[value] = offset;
}
else
{
offset = found->second;
}
return offset;
};
const auto get_geometry_id = [&facade](auto edge) { const auto get_geometry_id = [&facade](auto edge) {
return facade.GetGeometryIndex(edge.forward_segment_id.id).id; return facade.GetGeometryIndex(edge.forward_segment_id.id).id;
@ -439,16 +406,16 @@ void encodeVectorTile(const DataFacadeBase &facade,
const auto forward_weight = forward_weight_vector[edge.fwd_segment_position]; const auto forward_weight = forward_weight_vector[edge.fwd_segment_position];
const auto reverse_weight = reverse_weight_vector[reverse_weight_vector.size() - const auto reverse_weight = reverse_weight_vector[reverse_weight_vector.size() -
edge.fwd_segment_position - 1]; edge.fwd_segment_position - 1];
use_line_value(forward_weight); line_int_index.add(forward_weight);
use_line_value(reverse_weight); line_int_index.add(reverse_weight);
std::uint32_t forward_rate = std::uint32_t forward_rate =
static_cast<std::uint32_t>(round(length / forward_weight * 10.)); static_cast<std::uint32_t>(round(length / forward_weight * 10.));
std::uint32_t reverse_rate = std::uint32_t reverse_rate =
static_cast<std::uint32_t>(round(length / reverse_weight * 10.)); static_cast<std::uint32_t>(round(length / reverse_weight * 10.));
use_line_value(forward_rate); line_int_index.add(forward_rate);
use_line_value(reverse_rate); line_int_index.add(reverse_rate);
// Duration values // Duration values
const auto forward_duration_vector = const auto forward_duration_vector =
@ -459,8 +426,8 @@ void encodeVectorTile(const DataFacadeBase &facade,
const auto reverse_duration = const auto reverse_duration =
reverse_duration_vector[reverse_duration_vector.size() - reverse_duration_vector[reverse_duration_vector.size() -
edge.fwd_segment_position - 1]; edge.fwd_segment_position - 1];
use_line_value(forward_duration); line_int_index.add(forward_duration);
use_line_value(reverse_duration); line_int_index.add(reverse_duration);
} }
// Begin the layer features block // Begin the layer features block
@ -510,24 +477,14 @@ void encodeVectorTile(const DataFacadeBase &facade,
const auto name_id = facade.GetNameIndex(edge.forward_segment_id.id); const auto name_id = facade.GetNameIndex(edge.forward_segment_id.id);
auto name = facade.GetNameForID(name_id); auto name = facade.GetNameForID(name_id);
const auto name_offset = [&name, &names, &name_offsets]() { line_string_index.add(name);
auto iter = name_offsets.find(name);
if (iter == name_offsets.end())
{
auto offset = names.size();
name_offsets[name] = offset;
names.push_back(name);
return offset;
}
return iter->second;
}();
const auto encode_tile_line = [&line_layer_writer, const auto encode_tile_line = [&line_layer_writer,
&edge, &edge,
&component_id, &component_id,
&id, &id,
&max_datasource_id, &max_datasource_id,
&used_line_ints]( &line_int_index](
const FixedLine &tile_line, const FixedLine &tile_line,
const std::uint32_t speed_kmh_idx, const std::uint32_t speed_kmh_idx,
const std::uint32_t rate_idx, const std::uint32_t rate_idx,
@ -575,12 +532,11 @@ void encodeVectorTile(const DataFacadeBase &facade,
duration_idx); // duration value offset duration_idx); // duration value offset
field.add_element(5); // "name" tag key offset field.add_element(5); // "name" tag key offset
field.add_element(130 + max_datasource_id + 1 + used_line_ints.size() + field.add_element(130 + max_datasource_id + 1 +
name_idx); // name value offset line_int_index.values().size() + name_idx);
field.add_element(6); // rate tag key offset field.add_element(6); // rate tag key offset
field.add_element(130 + max_datasource_id + 1 + field.add_element(130 + max_datasource_id + 1 + rate_idx);
rate_idx); // rate goes in used_line_ints
} }
{ {
@ -614,11 +570,11 @@ void encodeVectorTile(const DataFacadeBase &facade,
{ {
encode_tile_line(tile_line, encode_tile_line(tile_line,
speed_kmh_idx, speed_kmh_idx,
line_int_offsets[forward_rate], line_int_index.indexOf(forward_rate),
line_int_offsets[forward_weight], line_int_index.indexOf(forward_weight),
line_int_offsets[forward_duration], line_int_index.indexOf(forward_duration),
forward_datasource_idx, forward_datasource_idx,
name_offset, line_string_index.indexOf(name),
start_x, start_x,
start_y); start_y);
} }
@ -648,11 +604,11 @@ void encodeVectorTile(const DataFacadeBase &facade,
{ {
encode_tile_line(tile_line, encode_tile_line(tile_line,
speed_kmh_idx, speed_kmh_idx,
line_int_offsets[reverse_rate], line_int_index.indexOf(reverse_rate),
line_int_offsets[reverse_weight], line_int_index.indexOf(reverse_weight),
line_int_offsets[reverse_duration], line_int_index.indexOf(reverse_duration),
reverse_datasource_idx, reverse_datasource_idx,
name_offset, line_string_index.indexOf(name),
start_x, start_x,
start_y); start_y);
} }
@ -703,7 +659,7 @@ void encodeVectorTile(const DataFacadeBase &facade,
values_writer.add_string(util::vector_tile::VARIANT_TYPE_STRING, values_writer.add_string(util::vector_tile::VARIANT_TYPE_STRING,
facade.GetDatasourceName(i).to_string()); facade.GetDatasourceName(i).to_string());
} }
for (auto value : used_line_ints) for (auto value : line_int_index.values())
{ {
// Writing field type 4 == variant type // Writing field type 4 == variant type
protozero::pbf_writer values_writer(line_layer_writer, protozero::pbf_writer values_writer(line_layer_writer,
@ -714,7 +670,7 @@ void encodeVectorTile(const DataFacadeBase &facade,
values_writer.add_double(util::vector_tile::VARIANT_TYPE_DOUBLE, value / 10.); values_writer.add_double(util::vector_tile::VARIANT_TYPE_DOUBLE, value / 10.);
} }
for (const auto &name : names) for (const auto &name : line_string_index.values())
{ {
// Writing field type 4 == variant type // Writing field type 4 == variant type
protozero::pbf_writer values_writer(line_layer_writer, protozero::pbf_writer values_writer(line_layer_writer,
@ -729,23 +685,46 @@ void encodeVectorTile(const DataFacadeBase &facade,
// for tiles of z<16, and tiles that don't show any intersections) // for tiles of z<16, and tiles that don't show any intersections)
if (!all_turn_data.empty()) if (!all_turn_data.empty())
{ {
struct EncodedTurnData
{
util::Coordinate coordinate;
std::size_t angle_index;
std::size_t turn_index;
std::size_t duration_index;
std::size_t weight_index;
std::size_t turntype_index;
std::size_t turnmodifier_index;
};
// we need to pre-encode all values here because we need the full offsets later // we need to pre-encode all values here because we need the full offsets later
// for encoding the actual features. // for encoding the actual features.
std::vector<std::tuple<util::Coordinate, unsigned, unsigned, unsigned, unsigned>> std::vector<EncodedTurnData> encoded_turn_data(all_turn_data.size());
encoded_turn_data(all_turn_data.size()); std::transform(
std::transform(all_turn_data.begin(), all_turn_data.begin(),
all_turn_data.end(), all_turn_data.end(),
encoded_turn_data.begin(), encoded_turn_data.begin(),
[&](const routing_algorithms::TurnData &t) { [&](const routing_algorithms::TurnData &t) {
auto angle_idx = use_point_int_value(t.in_angle); auto angle_idx = point_int_index.add(t.in_angle);
auto turn_idx = use_point_int_value(t.turn_angle); auto turn_idx = point_int_index.add(t.turn_angle);
auto duration_idx = use_point_float_value( auto duration_idx =
t.duration / 10.0); // Note conversion to float here point_float_index.add(t.duration / 10.0); // Note conversion to float here
auto weight_idx = use_point_float_value( auto weight_idx =
t.weight / 10.0); // Note conversion to float here point_float_index.add(t.weight / 10.0); // Note conversion to float here
return std::make_tuple(
t.coordinate, angle_idx, turn_idx, duration_idx, weight_idx); auto turntype_idx =
}); point_string_index.add(api::json::detail::internalInstructionTypeToString(
t.turn_instruction.type));
auto turnmodifier_idx =
point_string_index.add(api::json::detail::instructionModifierToString(
t.turn_instruction.direction_modifier));
return EncodedTurnData{t.coordinate,
angle_idx,
turn_idx,
duration_idx,
weight_idx,
turntype_idx,
turnmodifier_idx};
});
// Now write the points layer for turn penalty data: // Now write the points layer for turn penalty data:
// Add a layer object to the PBF stream. 3=='layer' from the vector tile spec // Add a layer object to the PBF stream. 3=='layer' from the vector tile spec
@ -778,13 +757,19 @@ void encodeVectorTile(const DataFacadeBase &facade,
protozero::packed_field_uint32 field( protozero::packed_field_uint32 field(
feature_writer, util::vector_tile::FEATURE_ATTRIBUTES_TAG); feature_writer, util::vector_tile::FEATURE_ATTRIBUTES_TAG);
field.add_element(0); // "bearing_in" tag key offset field.add_element(0); // "bearing_in" tag key offset
field.add_element(std::get<1>(point_turn_data)); field.add_element(point_turn_data.angle_index);
field.add_element(1); // "turn_angle" tag key offset field.add_element(1); // "turn_angle" tag key offset
field.add_element(std::get<2>(point_turn_data)); field.add_element(point_turn_data.turn_index);
field.add_element(2); // "cost" tag key offset field.add_element(2); // "cost" tag key offset
field.add_element(used_point_ints.size() + std::get<3>(point_turn_data)); field.add_element(point_int_index.size() + point_turn_data.duration_index);
field.add_element(3); // "weight" tag key offset field.add_element(3); // "weight" tag key offset
field.add_element(used_point_ints.size() + std::get<4>(point_turn_data)); field.add_element(point_int_index.size() + point_turn_data.weight_index);
field.add_element(4); // "type" tag key offset
field.add_element(point_int_index.size() + point_float_index.size() +
point_turn_data.turntype_index);
field.add_element(5); // "modifier" tag key offset
field.add_element(point_int_index.size() + point_float_index.size() +
point_turn_data.turnmodifier_index);
} }
{ {
// Add the geometry as the last field in this feature // Add the geometry as the last field in this feature
@ -797,8 +782,7 @@ void encodeVectorTile(const DataFacadeBase &facade,
// Loop over all the turns we found and add them as features to the layer // Loop over all the turns we found and add them as features to the layer
for (const auto &turndata : encoded_turn_data) for (const auto &turndata : encoded_turn_data)
{ {
const auto tile_point = const auto tile_point = coordinatesToTilePoint(turndata.coordinate, tile_bbox);
coordinatesToTilePoint(std::get<0>(turndata), tile_bbox);
if (!boost::geometry::within(point_t(tile_point.x, tile_point.y), clip_box)) if (!boost::geometry::within(point_t(tile_point.x, tile_point.y), clip_box))
{ {
continue; continue;
@ -813,20 +797,28 @@ void encodeVectorTile(const DataFacadeBase &facade,
point_layer_writer.add_string(util::vector_tile::KEY_TAG, "turn_angle"); point_layer_writer.add_string(util::vector_tile::KEY_TAG, "turn_angle");
point_layer_writer.add_string(util::vector_tile::KEY_TAG, "cost"); point_layer_writer.add_string(util::vector_tile::KEY_TAG, "cost");
point_layer_writer.add_string(util::vector_tile::KEY_TAG, "weight"); point_layer_writer.add_string(util::vector_tile::KEY_TAG, "weight");
point_layer_writer.add_string(util::vector_tile::KEY_TAG, "type");
point_layer_writer.add_string(util::vector_tile::KEY_TAG, "modifier");
// Now, save the lists of integers and floats that our features refer to. // Now, save the lists of integers and floats that our features refer to.
for (const auto &value : used_point_ints) for (const auto &value : point_int_index.values())
{ {
protozero::pbf_writer values_writer(point_layer_writer, protozero::pbf_writer values_writer(point_layer_writer,
util::vector_tile::VARIANT_TAG); util::vector_tile::VARIANT_TAG);
values_writer.add_sint64(util::vector_tile::VARIANT_TYPE_SINT64, value); values_writer.add_sint64(util::vector_tile::VARIANT_TYPE_SINT64, value);
} }
for (const auto &value : used_point_floats) for (const auto &value : point_float_index.values())
{ {
protozero::pbf_writer values_writer(point_layer_writer, protozero::pbf_writer values_writer(point_layer_writer,
util::vector_tile::VARIANT_TAG); util::vector_tile::VARIANT_TAG);
values_writer.add_float(util::vector_tile::VARIANT_TYPE_FLOAT, value); values_writer.add_float(util::vector_tile::VARIANT_TYPE_FLOAT, value);
} }
for (const auto &value : point_string_index.values())
{
protozero::pbf_writer values_writer(point_layer_writer,
util::vector_tile::VARIANT_TAG);
values_writer.add_string(util::vector_tile::VARIANT_TYPE_STRING, value);
}
} }
// OSM Node tile layer // OSM Node tile layer

View File

@ -183,6 +183,7 @@ std::vector<TurnData> generateTurns(const datafacade &facade,
// treat the whole lot as the "turn cost" that we'll stick on the map. // treat the whole lot as the "turn cost" that we'll stick on the map.
const auto turn_weight = data.weight - sum_node_weight; const auto turn_weight = data.weight - sum_node_weight;
const auto turn_duration = data.duration - sum_node_duration; const auto turn_duration = data.duration - sum_node_duration;
const auto turn_instruction = facade.GetTurnInstructionForEdgeID(data.turn_id);
// Find the three nodes that make up the turn movement) // Find the three nodes that make up the turn movement)
const auto node_from = startnode; const auto node_from = startnode;
@ -214,8 +215,12 @@ std::vector<TurnData> generateTurns(const datafacade &facade,
// 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.push_back( all_turn_data.push_back(TurnData{coord_via,
TurnData{coord_via, angle_in, turn_angle, turn_weight, turn_duration}); angle_in,
turn_angle,
turn_weight,
turn_duration,
turn_instruction});
} }
} }
} }

View File

@ -10,7 +10,7 @@ exports.three_test_coordinates = [[7.41337, 43.72956],
exports.two_test_coordinates = exports.three_test_coordinates.slice(0, 2) exports.two_test_coordinates = exports.three_test_coordinates.slice(0, 2)
exports.test_tile = {'at': [17059, 11948, 15], 'size': 162429}; exports.test_tile = {'at': [17059, 11948, 15], 'size': 167178};
// Test files generated by the routing engine; check test/data // Test files generated by the routing engine; check test/data

View File

@ -151,7 +151,7 @@ void validate_turn_layer(protozero::pbf_reader &layer_message)
BOOST_CHECK_EQUAL(feature_message.tag(), util::vector_tile::FEATURE_ATTRIBUTES_TAG); BOOST_CHECK_EQUAL(feature_message.tag(), util::vector_tile::FEATURE_ATTRIBUTES_TAG);
// properties // properties
auto feature_iter_pair = feature_message.get_packed_uint32(); auto feature_iter_pair = feature_message.get_packed_uint32();
BOOST_CHECK_EQUAL(std::distance(feature_iter_pair.begin(), feature_iter_pair.end()), 8); BOOST_CHECK_EQUAL(std::distance(feature_iter_pair.begin(), feature_iter_pair.end()), 12);
auto iter = feature_iter_pair.begin(); auto iter = feature_iter_pair.begin();
BOOST_CHECK_EQUAL(*iter++, 0); // bearing_in key BOOST_CHECK_EQUAL(*iter++, 0); // bearing_in key
*iter++; *iter++;
@ -161,6 +161,10 @@ void validate_turn_layer(protozero::pbf_reader &layer_message)
*iter++; // skip value check, can be valud uint32 *iter++; // skip value check, can be valud uint32
BOOST_CHECK_EQUAL(*iter++, 3); // turn weight key BOOST_CHECK_EQUAL(*iter++, 3); // turn weight key
*iter++; // skip value check, can be valud uint32 *iter++; // skip value check, can be valud uint32
BOOST_CHECK_EQUAL(*iter++, 4); // turn type key
*iter++; // skip value check, can be valud uint32
BOOST_CHECK_EQUAL(*iter++, 5); // turn modifier
*iter++; // skip value check, can be valud uint32
BOOST_CHECK(iter == feature_iter_pair.end()); BOOST_CHECK(iter == feature_iter_pair.end());
// geometry // geometry
feature_message.next(); feature_message.next();
@ -201,7 +205,7 @@ void validate_turn_layer(protozero::pbf_reader &layer_message)
} }
} }
BOOST_CHECK_EQUAL(number_of_turn_keys, 4); BOOST_CHECK_EQUAL(number_of_turn_keys, 6);
BOOST_CHECK(number_of_turns_found > 700); BOOST_CHECK(number_of_turns_found > 700);
} }
@ -337,6 +341,8 @@ void test_tile_turns(const osrm::OSRM &osrm)
std::vector<int> found_turn_angles_indexes; std::vector<int> found_turn_angles_indexes;
std::vector<int> found_time_penalties_indexes; std::vector<int> found_time_penalties_indexes;
std::vector<int> found_weight_penalties_indexes; std::vector<int> found_weight_penalties_indexes;
std::vector<int> found_turn_type_indexes;
std::vector<int> found_turn_modifier_indexes;
const auto check_turn_feature = [&](protozero::pbf_reader feature_message) { const auto check_turn_feature = [&](protozero::pbf_reader feature_message) {
feature_message.next(); // advance parser to first entry feature_message.next(); // advance parser to first entry
@ -351,7 +357,7 @@ void test_tile_turns(const osrm::OSRM &osrm)
BOOST_CHECK_EQUAL(feature_message.tag(), util::vector_tile::FEATURE_ATTRIBUTES_TAG); BOOST_CHECK_EQUAL(feature_message.tag(), util::vector_tile::FEATURE_ATTRIBUTES_TAG);
// properties // properties
auto feature_iter_pair = feature_message.get_packed_uint32(); auto feature_iter_pair = feature_message.get_packed_uint32();
BOOST_CHECK_EQUAL(std::distance(feature_iter_pair.begin(), feature_iter_pair.end()), 8); BOOST_CHECK_EQUAL(std::distance(feature_iter_pair.begin(), feature_iter_pair.end()), 12);
auto iter = feature_iter_pair.begin(); auto iter = feature_iter_pair.begin();
BOOST_CHECK_EQUAL(*iter++, 0); // bearing_in key BOOST_CHECK_EQUAL(*iter++, 0); // bearing_in key
found_bearing_in_indexes.push_back(*iter++); found_bearing_in_indexes.push_back(*iter++);
@ -361,6 +367,10 @@ void test_tile_turns(const osrm::OSRM &osrm)
found_time_penalties_indexes.push_back(*iter++); // skip value check, can be valud uint32 found_time_penalties_indexes.push_back(*iter++); // skip value check, can be valud uint32
BOOST_CHECK_EQUAL(*iter++, 3); // "weight" key BOOST_CHECK_EQUAL(*iter++, 3); // "weight" key
found_weight_penalties_indexes.push_back(*iter++); // skip value check, can be valud uint32 found_weight_penalties_indexes.push_back(*iter++); // skip value check, can be valud uint32
BOOST_CHECK_EQUAL(*iter++, 4); // "weight" key
found_turn_type_indexes.push_back(*iter++); // skip value check, can be valud uint32
BOOST_CHECK_EQUAL(*iter++, 5); // "weight" key
found_turn_modifier_indexes.push_back(*iter++); // skip value check, can be valud uint32
BOOST_CHECK(iter == feature_iter_pair.end()); BOOST_CHECK(iter == feature_iter_pair.end());
// geometry // geometry
feature_message.next(); feature_message.next();
@ -370,6 +380,7 @@ void test_tile_turns(const osrm::OSRM &osrm)
std::unordered_map<int, float> float_vals; std::unordered_map<int, float> float_vals;
std::unordered_map<int, std::int64_t> sint64_vals; std::unordered_map<int, std::int64_t> sint64_vals;
std::unordered_map<int, std::string> string_vals;
int kv_index = 0; int kv_index = 0;
@ -384,6 +395,9 @@ void test_tile_turns(const osrm::OSRM &osrm)
case util::vector_tile::VARIANT_TYPE_SINT64: case util::vector_tile::VARIANT_TYPE_SINT64:
sint64_vals[kv_index] = value.get_sint64(); sint64_vals[kv_index] = value.get_sint64();
break; break;
case util::vector_tile::VARIANT_TYPE_STRING:
string_vals[kv_index] = value.get_string();
break;
default: default:
BOOST_CHECK(false); BOOST_CHECK(false);
} }
@ -448,6 +462,62 @@ void test_tile_turns(const osrm::OSRM &osrm)
0, 0, 0, 0, 0, 0, .1f, .1f, .3f, .4f, 1.2f, 1.9f, 5.3f, 5.5f, 5.8f, 7.1f, 7.2f, 7.2f}; 0, 0, 0, 0, 0, 0, .1f, .1f, .3f, .4f, 1.2f, 1.9f, 5.3f, 5.5f, 5.8f, 7.1f, 7.2f, 7.2f};
CHECK_EQUAL_RANGE(actual_weight_turn_penalties, expected_weight_turn_penalties); CHECK_EQUAL_RANGE(actual_weight_turn_penalties, expected_weight_turn_penalties);
// Verify that we got the expected turn types
std::vector<std::string> actual_turn_types;
for (const auto &i : found_turn_type_indexes)
{
BOOST_CHECK(string_vals.count(i) == 1);
actual_turn_types.push_back(string_vals[i]);
}
std::sort(actual_turn_types.begin(), actual_turn_types.end());
const std::vector<std::string> expected_turn_types = {"(noturn)",
"(noturn)",
"(noturn)",
"(noturn)",
"(suppressed)",
"(suppressed)",
"end of road",
"end of road",
"fork",
"fork",
"turn",
"turn",
"turn",
"turn",
"turn",
"turn",
"turn",
"turn"};
CHECK_EQUAL_RANGE(actual_turn_types, expected_turn_types);
// Verify that we got the expected turn modifiers
std::vector<std::string> actual_turn_modifiers;
for (const auto &i : found_turn_modifier_indexes)
{
BOOST_CHECK(string_vals.count(i) == 1);
actual_turn_modifiers.push_back(string_vals[i]);
}
std::sort(actual_turn_modifiers.begin(), actual_turn_modifiers.end());
const std::vector<std::string> expected_turn_modifiers = {"left",
"left",
"left",
"left",
"right",
"right",
"right",
"right",
"sharp left",
"sharp right",
"slight left",
"slight left",
"slight right",
"slight right",
"straight",
"straight",
"straight",
"straight"};
CHECK_EQUAL_RANGE(actual_turn_modifiers, expected_turn_modifiers);
// Verify the expected turn angles // Verify the expected turn angles
std::vector<std::int64_t> actual_turn_angles; std::vector<std::int64_t> actual_turn_angles;
for (const auto &i : found_turn_angles_indexes) for (const auto &i : found_turn_angles_indexes)