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:
parent
89cf6d9e74
commit
0fc1aa2711
@ -17,6 +17,8 @@
|
||||
updating ETAs returned, without changing route selection (for example, in a distance-based profile with traffic data loaded).
|
||||
- Infrastructure:
|
||||
- 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
|
||||
- Changes from 5.10:
|
||||
|
@ -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 |
|
||||
| `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 |
|
||||
| `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
|
||||
|
@ -36,6 +36,15 @@ namespace detail
|
||||
std::string instructionTypeToString(extractor::guidance::TurnType::Enum type);
|
||||
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);
|
||||
|
||||
std::string modeToString(const extractor::TravelMode mode);
|
||||
|
@ -24,6 +24,7 @@ struct TurnData final
|
||||
const int turn_angle;
|
||||
const EdgeWeight weight;
|
||||
const EdgeWeight duration;
|
||||
const extractor::guidance::TurnInstruction turn_instruction;
|
||||
};
|
||||
|
||||
using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf;
|
||||
|
@ -41,15 +41,47 @@ const constexpr char *modifier_names[] = {"uturn",
|
||||
"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
|
||||
const constexpr char *turn_type_names[] = {
|
||||
"invalid", "new name", "continue", "turn", "merge",
|
||||
"on ramp", "off ramp", "fork", "end of road", "notification",
|
||||
"roundabout", "roundabout", "rotary", "rotary", "roundabout turn",
|
||||
"roundabout turn", "use lane", "invalid", "invalid", "invalid",
|
||||
"invalid", "invalid", "invalid", "invalid", "invalid",
|
||||
"invalid", "invalid"};
|
||||
/**
|
||||
* Human readable values for TurnType enum values
|
||||
*/
|
||||
struct TurnTypeName
|
||||
{
|
||||
// String value we return with our API
|
||||
const char *external_name;
|
||||
// Internal only string name for the turn type - useful for debugging
|
||||
// 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"};
|
||||
|
||||
@ -69,7 +101,14 @@ std::string instructionTypeToString(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)];
|
||||
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)
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "util/vector_tile.hpp"
|
||||
#include "util/web_mercator.hpp"
|
||||
|
||||
#include "engine/api/json_factory.hpp"
|
||||
|
||||
#include <boost/geometry.hpp>
|
||||
#include <boost/geometry/geometries/geometries.hpp>
|
||||
#include <boost/geometry/geometries/point_xy.hpp>
|
||||
@ -37,6 +39,41 @@ constexpr const static int MIN_ZOOM_FOR_TURNS = 15;
|
||||
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;
|
||||
// TODO: Port all this encoding logic to https://github.com/mapbox/vector-tile, which wasn't
|
||||
// available when this code was originally written.
|
||||
@ -281,87 +318,17 @@ void encodeVectorTile(const DataFacadeBase &facade,
|
||||
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;
|
||||
|
||||
// This is where we accumulate information on turns
|
||||
|
||||
// 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 found = line_int_offsets.find(value);
|
||||
|
||||
if (found == line_int_offsets.end())
|
||||
{
|
||||
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;
|
||||
};
|
||||
// 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
|
||||
// them during edge explioration, and are then used to generate the lookup
|
||||
// tables for each tile layer.
|
||||
ValueIndexer<int> line_int_index;
|
||||
ValueIndexer<util::StringView> line_string_index;
|
||||
ValueIndexer<int> point_int_index;
|
||||
ValueIndexer<float> point_float_index;
|
||||
ValueIndexer<std::string> point_string_index;
|
||||
|
||||
const auto get_geometry_id = [&facade](auto edge) {
|
||||
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 reverse_weight = reverse_weight_vector[reverse_weight_vector.size() -
|
||||
edge.fwd_segment_position - 1];
|
||||
use_line_value(forward_weight);
|
||||
use_line_value(reverse_weight);
|
||||
line_int_index.add(forward_weight);
|
||||
line_int_index.add(reverse_weight);
|
||||
|
||||
std::uint32_t forward_rate =
|
||||
static_cast<std::uint32_t>(round(length / forward_weight * 10.));
|
||||
std::uint32_t reverse_rate =
|
||||
static_cast<std::uint32_t>(round(length / reverse_weight * 10.));
|
||||
|
||||
use_line_value(forward_rate);
|
||||
use_line_value(reverse_rate);
|
||||
line_int_index.add(forward_rate);
|
||||
line_int_index.add(reverse_rate);
|
||||
|
||||
// Duration values
|
||||
const auto forward_duration_vector =
|
||||
@ -459,8 +426,8 @@ void encodeVectorTile(const DataFacadeBase &facade,
|
||||
const auto reverse_duration =
|
||||
reverse_duration_vector[reverse_duration_vector.size() -
|
||||
edge.fwd_segment_position - 1];
|
||||
use_line_value(forward_duration);
|
||||
use_line_value(reverse_duration);
|
||||
line_int_index.add(forward_duration);
|
||||
line_int_index.add(reverse_duration);
|
||||
}
|
||||
|
||||
// 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);
|
||||
auto name = facade.GetNameForID(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();
|
||||
name_offsets[name] = offset;
|
||||
names.push_back(name);
|
||||
return offset;
|
||||
}
|
||||
return iter->second;
|
||||
}();
|
||||
line_string_index.add(name);
|
||||
|
||||
const auto encode_tile_line = [&line_layer_writer,
|
||||
&edge,
|
||||
&component_id,
|
||||
&id,
|
||||
&max_datasource_id,
|
||||
&used_line_ints](
|
||||
&line_int_index](
|
||||
const FixedLine &tile_line,
|
||||
const std::uint32_t speed_kmh_idx,
|
||||
const std::uint32_t rate_idx,
|
||||
@ -575,12 +532,11 @@ void encodeVectorTile(const DataFacadeBase &facade,
|
||||
duration_idx); // duration value offset
|
||||
field.add_element(5); // "name" tag key offset
|
||||
|
||||
field.add_element(130 + max_datasource_id + 1 + used_line_ints.size() +
|
||||
name_idx); // name value offset
|
||||
field.add_element(130 + max_datasource_id + 1 +
|
||||
line_int_index.values().size() + name_idx);
|
||||
|
||||
field.add_element(6); // rate tag key offset
|
||||
field.add_element(130 + max_datasource_id + 1 +
|
||||
rate_idx); // rate goes in used_line_ints
|
||||
field.add_element(130 + max_datasource_id + 1 + rate_idx);
|
||||
}
|
||||
{
|
||||
|
||||
@ -614,11 +570,11 @@ void encodeVectorTile(const DataFacadeBase &facade,
|
||||
{
|
||||
encode_tile_line(tile_line,
|
||||
speed_kmh_idx,
|
||||
line_int_offsets[forward_rate],
|
||||
line_int_offsets[forward_weight],
|
||||
line_int_offsets[forward_duration],
|
||||
line_int_index.indexOf(forward_rate),
|
||||
line_int_index.indexOf(forward_weight),
|
||||
line_int_index.indexOf(forward_duration),
|
||||
forward_datasource_idx,
|
||||
name_offset,
|
||||
line_string_index.indexOf(name),
|
||||
start_x,
|
||||
start_y);
|
||||
}
|
||||
@ -648,11 +604,11 @@ void encodeVectorTile(const DataFacadeBase &facade,
|
||||
{
|
||||
encode_tile_line(tile_line,
|
||||
speed_kmh_idx,
|
||||
line_int_offsets[reverse_rate],
|
||||
line_int_offsets[reverse_weight],
|
||||
line_int_offsets[reverse_duration],
|
||||
line_int_index.indexOf(reverse_rate),
|
||||
line_int_index.indexOf(reverse_weight),
|
||||
line_int_index.indexOf(reverse_duration),
|
||||
reverse_datasource_idx,
|
||||
name_offset,
|
||||
line_string_index.indexOf(name),
|
||||
start_x,
|
||||
start_y);
|
||||
}
|
||||
@ -703,7 +659,7 @@ void encodeVectorTile(const DataFacadeBase &facade,
|
||||
values_writer.add_string(util::vector_tile::VARIANT_TYPE_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
|
||||
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.);
|
||||
}
|
||||
|
||||
for (const auto &name : names)
|
||||
for (const auto &name : line_string_index.values())
|
||||
{
|
||||
// Writing field type 4 == variant type
|
||||
protozero::pbf_writer values_writer(line_layer_writer,
|
||||
@ -729,22 +685,45 @@ void encodeVectorTile(const DataFacadeBase &facade,
|
||||
// for tiles of z<16, and tiles that don't show any intersections)
|
||||
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
|
||||
// for encoding the actual features.
|
||||
std::vector<std::tuple<util::Coordinate, unsigned, unsigned, unsigned, unsigned>>
|
||||
encoded_turn_data(all_turn_data.size());
|
||||
std::transform(all_turn_data.begin(),
|
||||
std::vector<EncodedTurnData> encoded_turn_data(all_turn_data.size());
|
||||
std::transform(
|
||||
all_turn_data.begin(),
|
||||
all_turn_data.end(),
|
||||
encoded_turn_data.begin(),
|
||||
[&](const routing_algorithms::TurnData &t) {
|
||||
auto angle_idx = use_point_int_value(t.in_angle);
|
||||
auto turn_idx = use_point_int_value(t.turn_angle);
|
||||
auto duration_idx = use_point_float_value(
|
||||
t.duration / 10.0); // Note conversion to float here
|
||||
auto weight_idx = use_point_float_value(
|
||||
t.weight / 10.0); // Note conversion to float here
|
||||
return std::make_tuple(
|
||||
t.coordinate, angle_idx, turn_idx, duration_idx, weight_idx);
|
||||
auto angle_idx = point_int_index.add(t.in_angle);
|
||||
auto turn_idx = point_int_index.add(t.turn_angle);
|
||||
auto duration_idx =
|
||||
point_float_index.add(t.duration / 10.0); // Note conversion to float here
|
||||
auto weight_idx =
|
||||
point_float_index.add(t.weight / 10.0); // Note conversion to float here
|
||||
|
||||
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:
|
||||
@ -778,13 +757,19 @@ void encodeVectorTile(const DataFacadeBase &facade,
|
||||
protozero::packed_field_uint32 field(
|
||||
feature_writer, util::vector_tile::FEATURE_ATTRIBUTES_TAG);
|
||||
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(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(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(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
|
||||
@ -797,8 +782,7 @@ void encodeVectorTile(const DataFacadeBase &facade,
|
||||
// Loop over all the turns we found and add them as features to the layer
|
||||
for (const auto &turndata : encoded_turn_data)
|
||||
{
|
||||
const auto tile_point =
|
||||
coordinatesToTilePoint(std::get<0>(turndata), tile_bbox);
|
||||
const auto tile_point = coordinatesToTilePoint(turndata.coordinate, tile_bbox);
|
||||
if (!boost::geometry::within(point_t(tile_point.x, tile_point.y), clip_box))
|
||||
{
|
||||
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, "cost");
|
||||
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.
|
||||
for (const auto &value : used_point_ints)
|
||||
for (const auto &value : point_int_index.values())
|
||||
{
|
||||
protozero::pbf_writer values_writer(point_layer_writer,
|
||||
util::vector_tile::VARIANT_TAG);
|
||||
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,
|
||||
util::vector_tile::VARIANT_TAG);
|
||||
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
|
||||
|
@ -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.
|
||||
const auto turn_weight = data.weight - sum_node_weight;
|
||||
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)
|
||||
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.
|
||||
// We need the coordinate of the intersection, the angle in, the turn
|
||||
// angle and the turn cost.
|
||||
all_turn_data.push_back(
|
||||
TurnData{coord_via, angle_in, turn_angle, turn_weight, turn_duration});
|
||||
all_turn_data.push_back(TurnData{coord_via,
|
||||
angle_in,
|
||||
turn_angle,
|
||||
turn_weight,
|
||||
turn_duration,
|
||||
turn_instruction});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ exports.three_test_coordinates = [[7.41337, 43.72956],
|
||||
|
||||
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
|
||||
|
@ -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);
|
||||
// properties
|
||||
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();
|
||||
BOOST_CHECK_EQUAL(*iter++, 0); // bearing_in key
|
||||
*iter++;
|
||||
@ -161,6 +161,10 @@ void validate_turn_layer(protozero::pbf_reader &layer_message)
|
||||
*iter++; // skip value check, can be valud uint32
|
||||
BOOST_CHECK_EQUAL(*iter++, 3); // turn weight key
|
||||
*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());
|
||||
// geometry
|
||||
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);
|
||||
}
|
||||
|
||||
@ -337,6 +341,8 @@ void test_tile_turns(const osrm::OSRM &osrm)
|
||||
std::vector<int> found_turn_angles_indexes;
|
||||
std::vector<int> found_time_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) {
|
||||
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);
|
||||
// properties
|
||||
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();
|
||||
BOOST_CHECK_EQUAL(*iter++, 0); // bearing_in key
|
||||
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
|
||||
BOOST_CHECK_EQUAL(*iter++, 3); // "weight" key
|
||||
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());
|
||||
// geometry
|
||||
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, std::int64_t> sint64_vals;
|
||||
std::unordered_map<int, std::string> string_vals;
|
||||
|
||||
int kv_index = 0;
|
||||
|
||||
@ -384,6 +395,9 @@ void test_tile_turns(const osrm::OSRM &osrm)
|
||||
case util::vector_tile::VARIANT_TYPE_SINT64:
|
||||
sint64_vals[kv_index] = value.get_sint64();
|
||||
break;
|
||||
case util::vector_tile::VARIANT_TYPE_STRING:
|
||||
string_vals[kv_index] = value.get_string();
|
||||
break;
|
||||
default:
|
||||
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};
|
||||
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
|
||||
std::vector<std::int64_t> actual_turn_angles;
|
||||
for (const auto &i : found_turn_angles_indexes)
|
||||
|
Loading…
Reference in New Issue
Block a user