Turn Angles in OSRM were computed using a lookahead of 10 meters.

This PR adds more advanced coordinate extraction, analysing the road
to detect offsets due to OSM way modelling.

In addition it improves the handling of bearings. Right now OSM reports
bearings simply based on the very first coordinate along a way.
With this PR, we store the bearings for a turn correctly, making the
bearings for turns correct.
This commit is contained in:
Moritz Kobitzsch
2016-08-17 09:49:19 +02:00
parent 1f8ca2879f
commit 5e167b8745
62 changed files with 3451 additions and 679 deletions
@@ -13,6 +13,8 @@
#include "util/exception.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/guidance/turn_bearing.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/integer_range.hpp"
#include "util/string_util.hpp"
#include "util/typedefs.hpp"
@@ -173,6 +175,9 @@ class BaseDataFacade
virtual BearingClassID GetBearingClassID(const NodeID id) const = 0;
virtual util::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const = 0;
virtual util::guidance::TurnBearing PostTurnBearing(const EdgeID eid) const = 0;
virtual util::guidance::BearingClass
GetBearingClass(const BearingClassID bearing_class_id) const = 0;
@@ -18,6 +18,7 @@
#include "storage/io.hpp"
#include "engine/geospatial_query.hpp"
#include "util/graph_loader.hpp"
#include "util/guidance/turn_bearing.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/io.hpp"
#include "util/packed_vector.hpp"
@@ -104,6 +105,9 @@ class InternalDataFacade final : public BaseDataFacade
util::ShM<BearingClassID, false>::vector m_bearing_class_id_table;
// entry class IDs by edge based egde
util::ShM<EntryClassID, false>::vector m_entry_class_id_list;
// bearings pre/post turn
util::ShM<util::guidance::TurnBearing, false>::vector m_pre_turn_bearing;
util::ShM<util::guidance::TurnBearing, false>::vector m_post_turn_bearing;
// the look-up table for entry classes. An entry class lists the possibility of entry for all
// available turns. For every turn, there is an associated entry class.
util::ShM<util::guidance::EntryClass, false>::vector m_entry_class_table;
@@ -205,6 +209,8 @@ class InternalDataFacade final : public BaseDataFacade
m_lane_data_id.resize(number_of_edges);
m_travel_mode_list.resize(number_of_edges);
m_entry_class_id_list.resize(number_of_edges);
m_pre_turn_bearing.resize(number_of_edges);
m_post_turn_bearing.resize(number_of_edges);
extractor::OriginalEdgeData current_edge_data;
for (unsigned i = 0; i < number_of_edges; ++i)
@@ -217,6 +223,8 @@ class InternalDataFacade final : public BaseDataFacade
m_lane_data_id[i] = current_edge_data.lane_data_id;
m_travel_mode_list[i] = current_edge_data.travel_mode;
m_entry_class_id_list[i] = current_edge_data.entry_classid;
m_pre_turn_bearing[i] = current_edge_data.pre_turn_bearing;
m_post_turn_bearing[i] = current_edge_data.post_turn_bearing;
}
}
@@ -921,6 +929,15 @@ class InternalDataFacade final : public BaseDataFacade
return m_entry_class_id_list.at(eid);
}
util::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const override final
{
return m_pre_turn_bearing.at(eid);
}
util::guidance::TurnBearing PostTurnBearing(const EdgeID eid) const override final
{
return m_post_turn_bearing.at(eid);
}
util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const override final
{
return m_entry_class_table.at(entry_class_id);
+37 -10
View File
@@ -18,6 +18,7 @@
#include "engine/geospatial_query.hpp"
#include "util/packed_vector.hpp"
#include "util/guidance/turn_bearing.hpp"
#include "util/range_table.hpp"
#include "util/rectangle.hpp"
#include "util/simple_logger.hpp"
@@ -85,6 +86,8 @@ class SharedDataFacade final : public BaseDataFacade
util::ShM<LaneDataID, true>::vector m_lane_data_id;
util::ShM<extractor::guidance::TurnInstruction, true>::vector m_turn_instruction_list;
util::ShM<extractor::TravelMode, true>::vector m_travel_mode_list;
util::ShM<util::guidance::TurnBearing, true>::vector m_pre_turn_bearing;
util::ShM<util::guidance::TurnBearing, true>::vector m_post_turn_bearing;
util::ShM<char, true>::vector m_names_char_list;
util::ShM<unsigned, true>::vector m_name_begin_indices;
util::ShM<unsigned, true>::vector m_geometry_indices;
@@ -104,11 +107,11 @@ class SharedDataFacade final : public BaseDataFacade
boost::filesystem::path file_index_path;
std::shared_ptr<util::RangeTable<16, true>> m_name_table;
// bearing classes by node based node
util::ShM<BearingClassID, true>::vector m_bearing_class_id_table;
// entry class IDs
util::ShM<EntryClassID, true>::vector m_entry_class_id_list;
// the look-up table for entry classes. An entry class lists the possibility of entry for all
// available turns. Such a class id is stored with every edge.
util::ShM<util::guidance::EntryClass, true>::vector m_entry_class_table;
@@ -182,7 +185,7 @@ class SharedDataFacade final : public BaseDataFacade
void LoadNodeAndEdgeInformation()
{
auto coordinate_list_ptr = data_layout->GetBlockPtr<util::Coordinate>(
const auto coordinate_list_ptr = data_layout->GetBlockPtr<util::Coordinate>(
shared_memory, storage::SharedDataLayout::COORDINATE_LIST);
m_coordinate_list.reset(
coordinate_list_ptr,
@@ -193,7 +196,7 @@ class SharedDataFacade final : public BaseDataFacade
BOOST_ASSERT(GetCoordinateOfNode(i).IsValid());
}
auto osmnodeid_list_ptr = data_layout->GetBlockPtr<std::uint64_t>(
const auto osmnodeid_list_ptr = data_layout->GetBlockPtr<std::uint64_t>(
shared_memory, storage::SharedDataLayout::OSM_NODE_ID_LIST);
m_osmnodeid_list.reset(
osmnodeid_list_ptr,
@@ -202,26 +205,27 @@ class SharedDataFacade final : public BaseDataFacade
m_osmnodeid_list.set_number_of_entries(
data_layout->num_entries[storage::SharedDataLayout::COORDINATE_LIST]);
auto travel_mode_list_ptr = data_layout->GetBlockPtr<extractor::TravelMode>(
const auto travel_mode_list_ptr = data_layout->GetBlockPtr<extractor::TravelMode>(
shared_memory, storage::SharedDataLayout::TRAVEL_MODE);
util::ShM<extractor::TravelMode, true>::vector travel_mode_list(
travel_mode_list_ptr, data_layout->num_entries[storage::SharedDataLayout::TRAVEL_MODE]);
m_travel_mode_list = std::move(travel_mode_list);
auto lane_data_id_ptr = data_layout->GetBlockPtr<LaneDataID>(
const auto lane_data_id_ptr = data_layout->GetBlockPtr<LaneDataID>(
shared_memory, storage::SharedDataLayout::LANE_DATA_ID);
util::ShM<LaneDataID, true>::vector lane_data_id(
lane_data_id_ptr, data_layout->num_entries[storage::SharedDataLayout::LANE_DATA_ID]);
m_lane_data_id = std::move(lane_data_id);
auto lane_tupel_id_pair_ptr = data_layout->GetBlockPtr<util::guidance::LaneTupleIdPair>(
shared_memory, storage::SharedDataLayout::TURN_LANE_DATA);
const auto lane_tupel_id_pair_ptr =
data_layout->GetBlockPtr<util::guidance::LaneTupleIdPair>(
shared_memory, storage::SharedDataLayout::TURN_LANE_DATA);
util::ShM<util::guidance::LaneTupleIdPair, true>::vector lane_tupel_id_pair(
lane_tupel_id_pair_ptr,
data_layout->num_entries[storage::SharedDataLayout::TURN_LANE_DATA]);
m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair);
auto turn_instruction_list_ptr =
const auto turn_instruction_list_ptr =
data_layout->GetBlockPtr<extractor::guidance::TurnInstruction>(
shared_memory, storage::SharedDataLayout::TURN_INSTRUCTION);
util::ShM<extractor::guidance::TurnInstruction, true>::vector turn_instruction_list(
@@ -229,18 +233,32 @@ class SharedDataFacade final : public BaseDataFacade
data_layout->num_entries[storage::SharedDataLayout::TURN_INSTRUCTION]);
m_turn_instruction_list = std::move(turn_instruction_list);
auto name_id_list_ptr = data_layout->GetBlockPtr<unsigned>(
const auto name_id_list_ptr = data_layout->GetBlockPtr<unsigned>(
shared_memory, storage::SharedDataLayout::NAME_ID_LIST);
util::ShM<unsigned, true>::vector name_id_list(
name_id_list_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_ID_LIST]);
m_name_ID_list = std::move(name_id_list);
auto entry_class_id_list_ptr = data_layout->GetBlockPtr<EntryClassID>(
const auto entry_class_id_list_ptr = data_layout->GetBlockPtr<EntryClassID>(
shared_memory, storage::SharedDataLayout::ENTRY_CLASSID);
typename util::ShM<EntryClassID, true>::vector entry_class_id_list(
entry_class_id_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::ENTRY_CLASSID]);
m_entry_class_id_list = std::move(entry_class_id_list);
const auto pre_turn_bearing_ptr = data_layout->GetBlockPtr<util::guidance::TurnBearing>(
shared_memory, storage::SharedDataLayout::PRE_TURN_BEARING);
typename util::ShM<util::guidance::TurnBearing, true>::vector pre_turn_bearing(
pre_turn_bearing_ptr,
data_layout->num_entries[storage::SharedDataLayout::PRE_TURN_BEARING]);
m_pre_turn_bearing = std::move(pre_turn_bearing);
const auto post_turn_bearing_ptr = data_layout->GetBlockPtr<util::guidance::TurnBearing>(
shared_memory, storage::SharedDataLayout::POST_TURN_BEARING);
typename util::ShM<util::guidance::TurnBearing, true>::vector post_turn_bearing(
post_turn_bearing_ptr,
data_layout->num_entries[storage::SharedDataLayout::POST_TURN_BEARING]);
m_post_turn_bearing = std::move(post_turn_bearing);
}
void LoadViaNodeList()
@@ -931,6 +949,15 @@ class SharedDataFacade final : public BaseDataFacade
return m_entry_class_id_list.at(eid);
}
util::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const override final
{
return m_pre_turn_bearing.at(eid);
}
util::guidance::TurnBearing PostTurnBearing(const EdgeID eid) const override final
{
return m_post_turn_bearing.at(eid);
}
util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const override final
{
return m_entry_class_table.at(entry_class_id);
+11 -8
View File
@@ -372,8 +372,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
int forward_offset = 0, forward_weight = 0;
int reverse_offset = 0, reverse_weight = 0;
const std::vector<EdgeWeight> forward_weight_vector = datafacade.GetUncompressedForwardWeights(data.packed_geometry_id);
const std::vector<EdgeWeight> reverse_weight_vector = datafacade.GetUncompressedReverseWeights(data.packed_geometry_id);
const std::vector<EdgeWeight> forward_weight_vector =
datafacade.GetUncompressedForwardWeights(data.packed_geometry_id);
const std::vector<EdgeWeight> reverse_weight_vector =
datafacade.GetUncompressedReverseWeights(data.packed_geometry_id);
for (std::size_t i = 0; i < data.fwd_segment_position; i++)
{
@@ -383,8 +385,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
BOOST_ASSERT(data.fwd_segment_position < reverse_weight_vector.size());
for (std::size_t i = 0;
i < reverse_weight_vector.size() - data.fwd_segment_position - 1;
for (std::size_t i = 0; i < reverse_weight_vector.size() - data.fwd_segment_position - 1;
i++)
{
reverse_offset += reverse_weight_vector[i];
@@ -469,16 +470,18 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
bool forward_edge_valid = false;
bool reverse_edge_valid = false;
const std::vector<EdgeWeight> forward_weight_vector = datafacade.GetUncompressedForwardWeights(segment.data.packed_geometry_id);
const std::vector<EdgeWeight> forward_weight_vector =
datafacade.GetUncompressedForwardWeights(segment.data.packed_geometry_id);
if (forward_weight_vector[segment.data.fwd_segment_position] != INVALID_EDGE_WEIGHT)
{
forward_edge_valid = segment.data.forward_segment_id.enabled;
}
const std::vector<EdgeWeight> reverse_weight_vector = datafacade.GetUncompressedReverseWeights(segment.data.packed_geometry_id);
if (reverse_weight_vector[reverse_weight_vector.size() -
segment.data.fwd_segment_position - 1] != INVALID_EDGE_WEIGHT)
const std::vector<EdgeWeight> reverse_weight_vector =
datafacade.GetUncompressedReverseWeights(segment.data.packed_geometry_id);
if (reverse_weight_vector[reverse_weight_vector.size() - segment.data.fwd_segment_position -
1] != INVALID_EDGE_WEIGHT)
{
reverse_edge_valid = segment.data.reverse_segment_id.enabled;
}
@@ -47,8 +47,8 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
// TODO: check if this was traversed in reverse?
const std::vector<NodeID> source_geometry =
facade.GetUncompressedForwardGeometry(source_node.packed_geometry_id);
geometry.osm_node_ids.push_back(facade.GetOSMNodeIDOfNode(
source_geometry[source_node.fwd_segment_position]));
geometry.osm_node_ids.push_back(
facade.GetOSMNodeIDOfNode(source_geometry[source_node.fwd_segment_position]));
auto cumulative_distance = 0.;
auto current_distance = 0.;
+8 -6
View File
@@ -33,8 +33,6 @@ namespace detail
{
std::pair<short, short> getDepartBearings(const LegGeometry &leg_geometry);
std::pair<short, short> getArriveBearings(const LegGeometry &leg_geometry);
std::pair<short, short> getIntermediateBearings(const LegGeometry &leg_geometry,
const std::size_t segment_index);
} // ns detail
inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &facade,
@@ -132,12 +130,14 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
step_name_id = target_node.name_id;
}
bearings = detail::getIntermediateBearings(leg_geometry, segment_index);
// extract bearings
bearings = std::make_pair<std::uint16_t, std::uint16_t>(
path_point.pre_turn_bearing.Get(), path_point.post_turn_bearing.Get());
const auto entry_class = facade.GetEntryClass(path_point.entry_classid);
const auto bearing_class =
facade.GetBearingClass(facade.GetBearingClassID(path_point.turn_via_node));
intersection.in = bearing_class.findMatchingBearing(
util::bearing::reverseBearing(bearings.first));
auto bearing_data = bearing_class.getAvailableBearings();
intersection.in = bearing_class.findMatchingBearing(bearings.first);
intersection.out = bearing_class.findMatchingBearing(bearings.second);
intersection.location = facade.GetCoordinateOfNode(path_point.turn_via_node);
intersection.bearings.clear();
@@ -155,8 +155,10 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
{
intersection.entry.push_back(entry_class.allowsEntry(idx));
}
std::int16_t bearing_in_driving_direction =
util::bearing::reverseBearing(std::round(bearings.first));
maneuver = {intersection.location,
bearings.first,
bearing_in_driving_direction,
bearings.second,
path_point.turn_instruction,
WaypointType::None,
+6
View File
@@ -5,6 +5,7 @@
#include "extractor/travel_mode.hpp"
#include "engine/phantom_node.hpp"
#include "osrm/coordinate.hpp"
#include "util/guidance/turn_bearing.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp"
@@ -36,6 +37,11 @@ struct PathData
// Source of the speed value on this road segment
DatasourceID datasource_id;
// bearing (as seen from the intersection) pre-turn
util::guidance::TurnBearing pre_turn_bearing;
// bearing (as seen from the intersection) post-turn
util::guidance::TurnBearing post_turn_bearing;
};
struct InternalRouteResult
+6 -7
View File
@@ -64,10 +64,10 @@ struct PhantomNode
: forward_segment_id(forward_segment_id), reverse_segment_id(reverse_segment_id),
name_id(name_id), forward_weight(forward_weight), reverse_weight(reverse_weight),
forward_offset(forward_offset), reverse_offset(reverse_offset),
packed_geometry_id(packed_geometry_id_),
component{component_id, is_tiny_component}, location(std::move(location)),
input_location(std::move(input_location)), fwd_segment_position(fwd_segment_position),
forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode)
packed_geometry_id(packed_geometry_id_), component{component_id, is_tiny_component},
location(std::move(location)), input_location(std::move(input_location)),
fwd_segment_position(fwd_segment_position), forward_travel_mode(forward_travel_mode),
backward_travel_mode(backward_travel_mode)
{
}
@@ -76,9 +76,8 @@ struct PhantomNode
reverse_segment_id{SPECIAL_SEGMENTID, false},
name_id(std::numeric_limits<unsigned>::max()), forward_weight(INVALID_EDGE_WEIGHT),
reverse_weight(INVALID_EDGE_WEIGHT), forward_offset(0), reverse_offset(0),
packed_geometry_id(SPECIAL_GEOMETRYID),
component{INVALID_COMPONENTID, false}, fwd_segment_position(0),
forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
packed_geometry_id(SPECIAL_GEOMETRYID), component{INVALID_COMPONENTID, false},
fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
{
}
@@ -6,6 +6,7 @@
#include "engine/internal_route_result.hpp"
#include "engine/search_engine_data.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/guidance/turn_bearing.hpp"
#include "util/typedefs.hpp"
#include <boost/assert.hpp>
@@ -250,81 +251,83 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
{
id_vector = facade.GetUncompressedForwardGeometry(geometry_index.id);
weight_vector = facade.GetUncompressedForwardWeights(geometry_index.id);
datasource_vector =
facade.GetUncompressedForwardDatasources(geometry_index.id);
datasource_vector = facade.GetUncompressedForwardDatasources(geometry_index.id);
}
else
{
id_vector = facade.GetUncompressedReverseGeometry(geometry_index.id);
weight_vector = facade.GetUncompressedReverseWeights(geometry_index.id);
datasource_vector =
facade.GetUncompressedReverseDatasources(geometry_index.id);
datasource_vector = facade.GetUncompressedReverseDatasources(geometry_index.id);
}
BOOST_ASSERT(id_vector.size() > 0);
BOOST_ASSERT(weight_vector.size() > 0);
BOOST_ASSERT(datasource_vector.size() > 0);
const 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() - 1);
const bool is_first_segment = unpacked_path.empty();
BOOST_ASSERT(weight_vector.size() == id_vector.size() - 1);
const bool is_first_segment = unpacked_path.empty();
const std::size_t start_index =
(is_first_segment
? ((start_traversed_in_reverse)
? weight_vector.size() -
phantom_node_pair.source_phantom.fwd_segment_position - 1
: phantom_node_pair.source_phantom.fwd_segment_position)
: 0);
const std::size_t end_index = weight_vector.size();
const std::size_t start_index =
(is_first_segment
? ((start_traversed_in_reverse)
? weight_vector.size() -
phantom_node_pair.source_phantom.fwd_segment_position - 1
: phantom_node_pair.source_phantom.fwd_segment_position)
: 0);
const std::size_t end_index = weight_vector.size();
BOOST_ASSERT(start_index >= 0);
BOOST_ASSERT(start_index < end_index);
for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx)
{
unpacked_path.push_back(
PathData{id_vector[segment_idx + 1],
name_index,
weight_vector[segment_idx],
extractor::guidance::TurnInstruction::NO_TURN(),
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
travel_mode,
INVALID_ENTRY_CLASSID,
datasource_vector[segment_idx]});
}
BOOST_ASSERT(unpacked_path.size() > 0);
if (facade.hasLaneData(edge_data.id))
unpacked_path.back().lane_data = facade.GetLaneData(edge_data.id);
BOOST_ASSERT(start_index >= 0);
BOOST_ASSERT(start_index < end_index);
for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx)
{
unpacked_path.push_back(
PathData{id_vector[segment_idx + 1],
name_index,
weight_vector[segment_idx],
extractor::guidance::TurnInstruction::NO_TURN(),
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
travel_mode,
INVALID_ENTRY_CLASSID,
datasource_vector[segment_idx],
util::guidance::TurnBearing(0),
util::guidance::TurnBearing(0)});
}
BOOST_ASSERT(unpacked_path.size() > 0);
if (facade.hasLaneData(edge_data.id))
unpacked_path.back().lane_data = facade.GetLaneData(edge_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 += (edge_data.distance - total_weight);
});
unpacked_path.back().entry_classid = facade.GetEntryClassID(edge_data.id);
unpacked_path.back().turn_instruction = turn_instruction;
unpacked_path.back().duration_until_turn += (edge_data.distance - total_weight);
unpacked_path.back().pre_turn_bearing = facade.PreTurnBearing(edge_data.id);
unpacked_path.back().post_turn_bearing = facade.PostTurnBearing(edge_data.id);
});
std::size_t start_index = 0, end_index = 0;
std::vector<unsigned> id_vector;
std::vector<EdgeWeight> weight_vector;
std::vector<DatasourceID> datasource_vector;
const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id ==
phantom_node_pair.target_phantom.packed_geometry_id) &&
unpacked_path.empty();
std::size_t start_index = 0, end_index = 0;
std::vector<unsigned> id_vector;
std::vector<EdgeWeight> weight_vector;
std::vector<DatasourceID> datasource_vector;
const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id ==
phantom_node_pair.target_phantom.packed_geometry_id) &&
unpacked_path.empty();
if (target_traversed_in_reverse)
{
id_vector = facade.GetUncompressedReverseGeometry(
phantom_node_pair.target_phantom.packed_geometry_id);
if (target_traversed_in_reverse)
{
id_vector = facade.GetUncompressedReverseGeometry(
phantom_node_pair.target_phantom.packed_geometry_id);
weight_vector = facade.GetUncompressedReverseWeights(
phantom_node_pair.target_phantom.packed_geometry_id);
weight_vector = facade.GetUncompressedReverseWeights(
phantom_node_pair.target_phantom.packed_geometry_id);
datasource_vector = facade.GetUncompressedReverseDatasources(
phantom_node_pair.target_phantom.packed_geometry_id);
datasource_vector = facade.GetUncompressedReverseDatasources(
phantom_node_pair.target_phantom.packed_geometry_id);
if (is_local_path)
{
start_index =
weight_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position - 1;
start_index = weight_vector.size() -
phantom_node_pair.source_phantom.fwd_segment_position - 1;
}
end_index =
weight_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position - 1;
@@ -354,7 +357,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
// t: fwd_segment 3
// -> (U, v), (v, w), (w, x)
// note that (x, t) is _not_ included but needs to be added later.
for (std::size_t segment_idx = start_index; segment_idx != end_index; (start_index < end_index ? ++segment_idx : --segment_idx))
for (std::size_t segment_idx = start_index; segment_idx != end_index;
(start_index < end_index ? ++segment_idx : --segment_idx))
{
BOOST_ASSERT(segment_idx < id_vector.size() - 1);
BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode > 0);
@@ -367,7 +371,9 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
: phantom_node_pair.target_phantom.forward_travel_mode,
INVALID_ENTRY_CLASSID,
datasource_vector[segment_idx]});
datasource_vector[segment_idx],
util::guidance::TurnBearing(0),
util::guidance::TurnBearing(0)});
}
if (unpacked_path.size() > 0)
+1 -2
View File
@@ -22,8 +22,7 @@ struct EdgeBasedNode
EdgeBasedNode()
: forward_segment_id{SPECIAL_SEGMENTID, false},
reverse_segment_id{SPECIAL_SEGMENTID, false}, u(SPECIAL_NODEID), v(SPECIAL_NODEID),
name_id(0), packed_geometry_id(SPECIAL_GEOMETRYID),
component{INVALID_COMPONENTID, false},
name_id(0), packed_geometry_id(SPECIAL_GEOMETRYID), component{INVALID_COMPONENTID, false},
fwd_segment_position(std::numeric_limits<unsigned short>::max()),
forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
+1 -1
View File
@@ -34,7 +34,7 @@ const int constexpr MAX_SLIPROAD_THRESHOLD = 250;
// Road priorities give an idea of how obvious a turn is. If two priorities differ greatly (e.g.
// service road over a primary road, the better priority can be seen as obvious due to its road
// category).
const double constexpr PRIORITY_DISTINCTION_FACTOR = 2.0;
const double constexpr PRIORITY_DISTINCTION_FACTOR = 1.75;
} // namespace guidance
} // namespace extractor
@@ -0,0 +1,203 @@
#ifndef OSRM_EXTRACTOR_COORDINATE_EXTRACTOR_HPP_
#define OSRM_EXTRACTOR_COORDINATE_EXTRACTOR_HPP_
#include <vector>
#include "extractor/query_node.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "util/node_based_graph.hpp"
namespace osrm
{
namespace extractor
{
namespace guidance
{
class CoordinateExtractor
{
public:
CoordinateExtractor(const util::NodeBasedDynamicGraph &node_based_graph,
const extractor::CompressedEdgeContainer &compressed_geometries,
const std::vector<extractor::QueryNode> &node_coordinates);
/* Find a interpolated coordinate a long the compressed geometries. The desired coordinate
* should be in a certain distance. This method is dedicated to find representative coordinates
* at turns.
*/
util::Coordinate GetCoordinateAlongRoad(const NodeID intersection_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
const NodeID to_node,
const std::uint8_t number_of_in_lanes) const;
// instead of finding only a single coordinate, we can also list all coordinates along a road.
std::vector<util::Coordinate> GetCoordinatesAlongRoad(const NodeID intersection_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
const NodeID to_node) const;
/* When extracting the coordinates, we first extract all coordinates. We don't care about most
* of them, though.
*
* Our very first step trims the coordinates to a saller set, close to the intersection.. The
* idea here is to filter all coordinates at the end of the road and consider only the formi
* close to the intersection:
*
* a -------------- v ----------.
* .
* .
* .
* b
*
* For calculating the turn angle for the intersection at `a`, we do not care about the turn
* between `v` and `b`. This calculation trims the coordinates to the ones immediately at the
* intersection.
*/
std::vector<util::Coordinate> TrimCoordinatesToLength(std::vector<util::Coordinate> coordinates,
const double desired_length) const;
/* when looking at a set of coordinates, this function allows trimming the vector to a smaller,
* only containing coordinates up to a given distance along the path. The last coordinate might
* be interpolated
*/
std::vector<util::Coordinate>
TrimCoordinatesByLengthFront(std::vector<util::Coordinate> coordinates,
const double desired_length) const;
/*
* to correct for the initial offset, we move the lookahead coordinate close
* to the original road. We do so by subtracting the difference between the
* turn coordinate and the offset coordinate from the lookahead coordinge:
*
* a ------ b ------ c
* |
* d
* \
* \
* e
*
* is converted to:
*
* a ------ b ------ c
* \
* \
* e
*
* for fixpoint `b`, vector_base `d` and vector_head `e`
*/
util::Coordinate GetCorrectedCoordinate(const util::Coordinate fixpoint,
const util::Coordinate vector_base,
const util::Coordinate vector_head) const;
/* generate a uniform vector of coordinates in same range distances
*
* Turns:
* x ------------ x -- x - x
*
* Into:
* x -- x -- x -- x -- x - x
*/
std::vector<util::Coordinate>
SampleCoordinates(const std::vector<util::Coordinate> &coordinates,
const double length,
const double rate) const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;
const extractor::CompressedEdgeContainer &compressed_geometries;
const std::vector<extractor::QueryNode> &node_coordinates;
double ComputeInterpolationFactor(const double desired_distance,
const double distance_to_first,
const double distance_to_second) const;
std::pair<util::Coordinate, util::Coordinate>
RegressionLine(const std::vector<util::Coordinate> &coordinates) const;
/* In an ideal world, the road would only have two coordinates if it goes mainly straigt. Since
* OSM is operating on noisy data, we have some variations going straight.
*
* b d
* a ---------------------------------------------- e
* c
*
* The road from a-e offers a lot of variation, even though it is mostly straight. Here we
* calculate the distances of all nodes in between to the straight line between a and e. If the
* distances inbetween are small, we assume a straight road. To calculate these distances, we
* don't use the coordinates of the road itself but our just calculated regression vector
*/
double GetMaxDeviation(std::vector<util::Coordinate>::const_iterator range_begin,
const std::vector<util::Coordinate>::const_iterator &range_end,
const util::Coordinate straight_begin,
const util::Coordinate straight_end) const;
/*
* the curve is still best described as looking at the very first vector for the turn angle.
* Consider:
*
* |
* a - 1
* | o
* | 2
* | o
* | 3
* | o
* | 4
*
* The turn itself from a-1 would be considered as a 90 degree turn, even though the road is
* taking a turn later.
* In this situaiton we return the very first coordinate, describing the road just at the
* turn.
* As an added benefit, we get a straight turn at a curved road:
*
* o b o
* o o
* o o
* o o
* o o
* a c
*
* The turn from a-b to b-c is straight. With every vector we go further down the road, the
* turn
* angle would get stronger. Therefore we consider the very first coordinate as our best
* choice
*/
bool IsCurve(const std::vector<util::Coordinate> &coordinates,
const std::vector<double> &segment_distances,
const double segment_length,
const double considered_lane_width,
const util::NodeBasedEdgeData &edge_data) const;
/*
* If the very first coordinate is within lane offsets and the rest offers a near straight line,
* we use an offset coordinate.
*
* ----------------------------------------
*
* ----------------------------------------
* a -
* ----------------------------------------
* \
* ----------------------------------------
* \
* b --------------------c
*
* Will be considered a very slight turn, instead of the near 90 degree turn we see right here.
*/
bool IsDirectOffset(const std::vector<util::Coordinate> &coordinates,
const std::size_t straight_index,
const double straight_distance,
const double segment_length,
const std::vector<double> &segment_distances,
const std::uint8_t considered_lanes) const;
};
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif // OSRM_EXTRACTOR_COORDINATE_EXTRACTOR_HPP_
@@ -21,6 +21,7 @@ struct TurnOperation final
{
EdgeID eid;
double angle;
double bearing;
TurnInstruction instruction;
LaneDataID lane_data_id;
};
@@ -2,6 +2,7 @@
#define OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_GENERATOR_HPP_
#include "extractor/compressed_edge_container.hpp"
#include "extractor/guidance/coordinate_extractor.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/query_node.hpp"
#include "extractor/restriction_map.hpp"
@@ -51,7 +52,7 @@ class IntersectionGenerator
const RestrictionMap &restriction_map;
const std::unordered_set<NodeID> &barrier_nodes;
const std::vector<QueryNode> &node_info_list;
const CompressedEdgeContainer &compressed_edge_container;
const CoordinateExtractor coordinate_extractor;
// Check for restrictions/barriers and generate a list of valid and invalid turns present at
// the
@@ -59,21 +59,24 @@ class RoadClassification
// (difference <=1), we can see the road as a fork. Else one of the road classes is seen as
// obvious choice
RoadPriorityClass::Enum road_priority_class : 5;
// the number of lanes in the road
std::uint8_t number_of_lanes;
public:
// default construction
RoadClassification()
: motorway_class(0), link_class(0), may_be_ignored(1),
road_priority_class(RoadPriorityClass::CONNECTIVITY)
road_priority_class(RoadPriorityClass::CONNECTIVITY), number_of_lanes(0)
{
}
RoadClassification(bool motorway_class,
bool link_class,
bool may_be_ignored,
RoadPriorityClass::Enum road_priority_class)
RoadPriorityClass::Enum road_priority_class,
std::uint8_t number_of_lanes)
: motorway_class(motorway_class), link_class(link_class), may_be_ignored(may_be_ignored),
road_priority_class(road_priority_class)
road_priority_class(road_priority_class), number_of_lanes(number_of_lanes)
{
}
@@ -88,6 +91,9 @@ class RoadClassification
bool IsLowPriorityRoadClass() const { return (0 != may_be_ignored); }
void SetLowPriorityFlag(const bool new_value) { may_be_ignored = new_value; }
std::uint8_t GetNumberOfLanes() const { return number_of_lanes; }
void SetNumberOfLanes(const std::uint8_t new_value) { number_of_lanes = new_value; }
std::uint32_t GetPriority() const { return static_cast<std::uint32_t>(road_priority_class); }
RoadPriorityClass::Enum GetClass() const { return road_priority_class; }
@@ -112,8 +118,8 @@ class RoadClassification
#pragma pack(pop)
static_assert(
sizeof(RoadClassification) == 1,
"Road Classification should fit a byte. Increasing this has a severe impact on memory.");
sizeof(RoadClassification) == 2,
"Road Classification should fit two bytes. Increasing this has a severe impact on memory.");
inline bool canBeSeenAsFork(const RoadClassification first, const RoadClassification second)
{
@@ -2,6 +2,7 @@
#define OSRM_EXTRACTOR_GUIDANCE_ROUNDABOUT_HANDLER_HPP_
#include "extractor/compressed_edge_container.hpp"
#include "extractor/guidance/coordinate_extractor.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/guidance/intersection_handler.hpp"
@@ -87,6 +88,8 @@ class RoundaboutHandler : public IntersectionHandler
const CompressedEdgeContainer &compressed_edge_container;
const ProfileProperties &profile_properties;
const CoordinateExtractor coordinate_extractor;
};
} // namespace guidance
+76 -107
View File
@@ -7,12 +7,15 @@
#include "util/coordinate_calculation.hpp"
#include "util/guidance/toolkit.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/query_node.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/road_classification.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "engine/guidance/route_step.hpp"
@@ -24,6 +27,7 @@
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/functional/hash.hpp>
@@ -44,113 +48,6 @@ using util::guidance::angularDeviation;
using util::guidance::entersRoundabout;
using util::guidance::leavesRoundabout;
namespace detail
{
const constexpr double DESIRED_SEGMENT_LENGTH = 10.0;
template <typename IteratorType>
util::Coordinate
getCoordinateFromCompressedRange(util::Coordinate current_coordinate,
const IteratorType compressed_geometry_begin,
const IteratorType compressed_geometry_end,
const util::Coordinate final_coordinate,
const std::vector<extractor::QueryNode> &query_nodes)
{
const auto extractCoordinateFromNode =
[](const extractor::QueryNode &node) -> util::Coordinate {
return {node.lon, node.lat};
};
double distance_to_current_coordinate = 0;
double distance_to_next_coordinate = 0;
// get the length that is missing from the current segment to reach DESIRED_SEGMENT_LENGTH
const auto getFactor = [](const double first_distance, const double second_distance) {
BOOST_ASSERT(first_distance < detail::DESIRED_SEGMENT_LENGTH);
double segment_length = second_distance - first_distance;
BOOST_ASSERT(segment_length > 0);
BOOST_ASSERT(second_distance >= detail::DESIRED_SEGMENT_LENGTH);
double missing_distance = detail::DESIRED_SEGMENT_LENGTH - first_distance;
return std::max(0., std::min(missing_distance / segment_length, 1.0));
};
for (auto compressed_geometry_itr = compressed_geometry_begin;
compressed_geometry_itr != compressed_geometry_end;
++compressed_geometry_itr)
{
const auto next_coordinate =
extractCoordinateFromNode(query_nodes[compressed_geometry_itr->node_id]);
distance_to_next_coordinate =
distance_to_current_coordinate +
util::coordinate_calculation::haversineDistance(current_coordinate, next_coordinate);
// reached point where coordinates switch between
if (distance_to_next_coordinate >= detail::DESIRED_SEGMENT_LENGTH)
return util::coordinate_calculation::interpolateLinear(
getFactor(distance_to_current_coordinate, distance_to_next_coordinate),
current_coordinate,
next_coordinate);
// prepare for next iteration
current_coordinate = next_coordinate;
distance_to_current_coordinate = distance_to_next_coordinate;
}
distance_to_next_coordinate =
distance_to_current_coordinate +
util::coordinate_calculation::haversineDistance(current_coordinate, final_coordinate);
// reached point where coordinates switch between
if (distance_to_current_coordinate < detail::DESIRED_SEGMENT_LENGTH &&
distance_to_next_coordinate >= detail::DESIRED_SEGMENT_LENGTH)
return util::coordinate_calculation::interpolateLinear(
getFactor(distance_to_current_coordinate, distance_to_next_coordinate),
current_coordinate,
final_coordinate);
else
return final_coordinate;
}
} // namespace detail
// Finds a (potentially interpolated) coordinate that is DESIRED_SEGMENT_LENGTH away
// from the start of an edge
inline util::Coordinate
getRepresentativeCoordinate(const NodeID from_node,
const NodeID to_node,
const EdgeID via_edge_id,
const bool traverse_in_reverse,
const extractor::CompressedEdgeContainer &compressed_geometries,
const std::vector<extractor::QueryNode> &query_nodes)
{
const auto extractCoordinateFromNode =
[](const extractor::QueryNode &node) -> util::Coordinate {
return {node.lon, node.lat};
};
// Uncompressed roads are simple, return the coordinate at the end
if (!compressed_geometries.HasZippedEntryForForwardID(via_edge_id) && !compressed_geometries.HasZippedEntryForReverseID(via_edge_id))
{
return extractCoordinateFromNode(traverse_in_reverse ? query_nodes[from_node]
: query_nodes[to_node]);
}
else
{
const auto &geometry = compressed_geometries.GetBucketReference(via_edge_id);
const auto base_node_id = (traverse_in_reverse) ? to_node : from_node;
const auto base_coordinate = extractCoordinateFromNode(query_nodes[base_node_id]);
const auto final_node = (traverse_in_reverse) ? from_node : to_node;
const auto final_coordinate = extractCoordinateFromNode(query_nodes[final_node]);
if (traverse_in_reverse)
return detail::getCoordinateFromCompressedRange(
base_coordinate, geometry.rbegin(), geometry.rend(), final_coordinate, query_nodes);
else
return detail::getCoordinateFromCompressedRange(
base_coordinate, geometry.begin(), geometry.end(), final_coordinate, query_nodes);
}
}
// To simplify handling of Left/Right hand turns, we can mirror turns and write an intersection
// handler only for one side. The mirror function turns a left-hand turn in a equivalent right-hand
// turn and vice versa.
@@ -313,6 +210,78 @@ auto inline lanesToTheRight(const engine::guidance::RouteStep &step)
return boost::make_iterator_range(description.end() - num_lanes_right, description.end());
}
inline std::uint8_t getLaneCountAtIntersection(const NodeID intersection_node,
const util::NodeBasedDynamicGraph &node_based_graph)
{
std::uint8_t lanes = 0;
for (const EdgeID onto_edge : node_based_graph.GetAdjacentEdgeRange(intersection_node))
lanes = std::max(
lanes, node_based_graph.GetEdgeData(onto_edge).road_classification.GetNumberOfLanes());
return lanes;
}
inline bool obviousByRoadClass(const RoadClassification in_classification,
const RoadClassification obvious_candidate,
const RoadClassification compare_candidate)
{
const bool has_high_priority = PRIORITY_DISTINCTION_FACTOR * obvious_candidate.GetPriority() <
compare_candidate.GetPriority();
const bool continues_on_same_class = in_classification == obvious_candidate;
return (has_high_priority && continues_on_same_class) ||
(!obvious_candidate.IsLowPriorityRoadClass() &&
!in_classification.IsLowPriorityRoadClass() &&
compare_candidate.IsLowPriorityRoadClass());
}
/* We use the sum of least squares to calculate a linear regression through our
* coordinates.
* This regression gives a good idea of how the road can be perceived and corrects for
* initial and final corrections
*/
inline std::pair<util::Coordinate, util::Coordinate>
leastSquareRegression(const std::vector<util::Coordinate> &coordinates)
{
BOOST_ASSERT(coordinates.size() >= 2);
double sum_lon = 0, sum_lat = 0, sum_lon_lat = 0, sum_lon_lon = 0;
double min_lon = static_cast<double>(toFloating(coordinates.front().lon));
double max_lon = static_cast<double>(toFloating(coordinates.front().lon));
for (const auto coord : coordinates)
{
min_lon = std::min(min_lon, static_cast<double>(toFloating(coord.lon)));
max_lon = std::max(max_lon, static_cast<double>(toFloating(coord.lon)));
sum_lon += static_cast<double>(toFloating(coord.lon));
sum_lon_lon +=
static_cast<double>(toFloating(coord.lon)) * static_cast<double>(toFloating(coord.lon));
sum_lat += static_cast<double>(toFloating(coord.lat));
sum_lon_lat +=
static_cast<double>(toFloating(coord.lon)) * static_cast<double>(toFloating(coord.lat));
}
const auto dividend = coordinates.size() * sum_lon_lat - sum_lon * sum_lat;
const auto divisor = coordinates.size() * sum_lon_lon - sum_lon * sum_lon;
if (std::abs(divisor) < std::numeric_limits<double>::epsilon())
return std::make_pair(coordinates.front(), coordinates.back());
// slope of the regression line
const auto slope = dividend / divisor;
const auto intercept = (sum_lat - slope * sum_lon) / coordinates.size();
const auto GetLatAtLon = [intercept,
slope](const util::FloatLongitude longitude) -> util::FloatLatitude {
return {intercept + slope * static_cast<double>((longitude))};
};
const util::Coordinate regression_first = {
toFixed(util::FloatLongitude{min_lon - 1}),
toFixed(util::FloatLatitude(GetLatAtLon(util::FloatLongitude{min_lon - 1})))};
const util::Coordinate regression_end = {
toFixed(util::FloatLongitude{max_lon + 1}),
toFixed(util::FloatLatitude(GetLatAtLon(util::FloatLongitude{max_lon + 1})))};
return {regression_first, regression_end};
}
} // namespace guidance
} // namespace extractor
} // namespace osrm
@@ -25,11 +25,7 @@ namespace guidance
{
std::pair<util::guidance::EntryClass, util::guidance::BearingClass>
classifyIntersection(NodeID nid,
const Intersection &intersection,
const util::NodeBasedDynamicGraph &node_based_graph,
const extractor::CompressedEdgeContainer &compressed_geometries,
const std::vector<extractor::QueryNode> &query_nodes);
classifyIntersection(Intersection intersection);
} // namespace guidance
} // namespace extractor
@@ -6,7 +6,6 @@
#include <boost/assert.hpp>
#include "extractor/guidance/roundabout_type.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp"
namespace osrm
@@ -68,10 +67,8 @@ const constexpr Enum Sliproad =
const constexpr Enum MaxTurnType = 27; // Special value for static asserts
}
// turn angle in 1.40625 degree -> 128 == 180 degree
struct TurnInstruction
{
using LaneTuple = util::guidance::LaneTuple;
TurnInstruction(const TurnType::Enum type = TurnType::Invalid,
const DirectionModifier::Enum direction_modifier = DirectionModifier::UTurn)
: type(type), direction_modifier(direction_modifier)
+10 -4
View File
@@ -3,6 +3,7 @@
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/travel_mode.hpp"
#include "util/guidance/turn_bearing.hpp"
#include "util/typedefs.hpp"
#include <cstddef>
@@ -20,9 +21,12 @@ struct OriginalEdgeData
LaneDataID lane_data_id,
guidance::TurnInstruction turn_instruction,
EntryClassID entry_classid,
TravelMode travel_mode)
TravelMode travel_mode,
util::guidance::TurnBearing pre_turn_bearing,
util::guidance::TurnBearing post_turn_bearing)
: via_geometry(via_geometry), name_id(name_id), entry_classid(entry_classid),
lane_data_id(lane_data_id), turn_instruction(turn_instruction), travel_mode(travel_mode)
lane_data_id(lane_data_id), turn_instruction(turn_instruction), travel_mode(travel_mode),
pre_turn_bearing(pre_turn_bearing), post_turn_bearing(post_turn_bearing)
{
}
@@ -30,16 +34,18 @@ struct OriginalEdgeData
: via_geometry{std::numeric_limits<unsigned>::max() >> 1, false},
name_id(std::numeric_limits<unsigned>::max()), entry_classid(INVALID_ENTRY_CLASSID),
lane_data_id(INVALID_LANE_DATAID), turn_instruction(guidance::TurnInstruction::INVALID()),
travel_mode(TRAVEL_MODE_INACCESSIBLE)
travel_mode(TRAVEL_MODE_INACCESSIBLE), pre_turn_bearing(0.0), post_turn_bearing(0.0)
{
}
GeometryID via_geometry;
unsigned name_id;
NameID name_id;
EntryClassID entry_classid;
LaneDataID lane_data_id;
guidance::TurnInstruction turn_instruction;
TravelMode travel_mode;
util::guidance::TurnBearing pre_turn_bearing;
util::guidance::TurnBearing post_turn_bearing;
};
static_assert(sizeof(OriginalEdgeData) == 16,
+4
View File
@@ -46,6 +46,8 @@ const constexpr char *block_id_to_name[] = {"NAME_OFFSETS",
"BEARING_VALUES",
"ENTRY_CLASS",
"LANE_DATA_ID",
"PRE_TURN_BEARING",
"POST_TURN_BEARING",
"TURN_LANE_DATA",
"LANE_DESCRIPTION_OFFSETS",
"LANE_DESCRIPTION_MASKS"};
@@ -84,6 +86,8 @@ struct SharedDataLayout
BEARING_VALUES,
ENTRY_CLASS,
LANE_DATA_ID,
PRE_TURN_BEARING,
POST_TURN_BEARING,
TURN_LANE_DATA,
LANE_DESCRIPTION_OFFSETS,
LANE_DESCRIPTION_MASKS,
+17
View File
@@ -30,6 +30,13 @@ double haversineDistance(const Coordinate first_coordinate, const Coordinate sec
double greatCircleDistance(const Coordinate first_coordinate, const Coordinate second_coordinate);
// Find the closest distance and location between coordinate and the line connecting source and
// target:
// coordinate
// |
// |
// source -------- x -------- target.
// returns x as well as the distance between source and x as ratio ([0,1])
inline std::pair<double, FloatCoordinate> projectPointOnSegment(const FloatCoordinate &source,
const FloatCoordinate &target,
const FloatCoordinate &coordinate)
@@ -99,6 +106,16 @@ double circleRadius(const Coordinate first_coordinate,
// returns to
Coordinate interpolateLinear(double factor, const Coordinate from, const Coordinate to);
// compute the signed area of a triangle
double signedArea(const Coordinate first_coordinate,
const Coordinate second_coordinate,
const Coordinate third_coordinate);
// check if a set of three coordinates is given in CCW order
bool isCCW(const Coordinate first_coordinate,
const Coordinate second_coordinate,
const Coordinate third_coordinate);
} // ns coordinate_calculation
} // ns util
} // ns osrm
+6 -1
View File
@@ -10,12 +10,15 @@
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
namespace osrm
{
namespace util
{
namespace guidance
{
inline void print(const engine::guidance::RouteStep &step)
@@ -30,7 +33,9 @@ inline void print(const engine::guidance::RouteStep &step)
for (const auto &intersection : step.intersections)
{
std::cout << "(Lanes: " << static_cast<int>(intersection.lanes.lanes_in_turn) << " "
<< static_cast<int>(intersection.lanes.first_lane_from_the_right) << " bearings:";
<< static_cast<int>(intersection.lanes.first_lane_from_the_right) << " ["
<< intersection.in << "," << intersection.out << "]"
<< " bearings:";
for (auto bearing : intersection.bearings)
std::cout << " " << bearing;
std::cout << ", entry: ";
+6
View File
@@ -32,6 +32,12 @@ inline double angularDeviation(const double angle, const double from)
return std::min(360 - deviation, deviation);
}
inline bool hasRampType(const extractor::guidance::TurnInstruction instruction)
{
return instruction.type == extractor::guidance::TurnType::OffRamp ||
instruction.type == extractor::guidance::TurnType::OnRamp;
}
inline extractor::guidance::DirectionModifier::Enum getTurnDirection(const double angle)
{
// An angle of zero is a u-turn
+30
View File
@@ -0,0 +1,30 @@
#ifndef OSRM_INCLUDE_UTIL_TURN_BEARING_HPP_
#define OSRM_INCLUDE_UTIL_TURN_BEARING_HPP_
#include <cstdint>
namespace osrm
{
namespace util
{
namespace guidance
{
#pragma pack(push, 1)
class TurnBearing
{
public:
TurnBearing(const double value = 0);
double Get() const;
private:
std::uint8_t bearing;
};
#pragma pack(pop)
} // namespace guidance
} // namespace util
} // namespace osrm
#endif /* OSRM_INCLUDE_UTIL_TURN_BEARING_HPP_ */
@@ -46,7 +46,8 @@ template <typename DataT> class ShMemIterator : public std::iterator<std::input_
DataT &operator*() { return *p; }
};
template <typename DataT> class ShMemReverseIterator : public std::iterator<std::input_iterator_tag, DataT>
template <typename DataT>
class ShMemReverseIterator : public std::iterator<std::input_iterator_tag, DataT>
{
DataT *p;
@@ -99,7 +100,10 @@ template <typename DataT> class SharedMemoryWrapper
ShMemIterator<DataT> end() const { return ShMemIterator<DataT>(m_ptr + m_size); }
ShMemReverseIterator<DataT> rbegin() const { return ShMemReverseIterator<DataT>(m_ptr + m_size - 1); }
ShMemReverseIterator<DataT> rbegin() const
{
return ShMemReverseIterator<DataT>(m_ptr + m_size - 1);
}
ShMemReverseIterator<DataT> rend() const { return ShMemReverseIterator<DataT>(m_ptr - 1); }
-1
View File
@@ -112,7 +112,6 @@ struct GeometryID
std::uint32_t forward : 1;
};
static_assert(sizeof(SegmentID) == 4, "SegmentID needs to be 4 bytes big");
#endif /* TYPEDEFS_H */