initial version of intersection classification

This commit is contained in:
Moritz Kobitzsch
2016-04-26 13:27:40 +02:00
committed by Patrick Niklaus
parent 6aa97048df
commit ba074b0116
33 changed files with 1065 additions and 262 deletions
+16 -5
View File
@@ -3,13 +3,15 @@
// Exposes all data access interfaces to the algorithms via base class ptr
#include "extractor/edge_based_node.hpp"
#include "extractor/external_memory_node.hpp"
#include "contractor/query_edge.hpp"
#include "engine/phantom_node.hpp"
#include "extractor/edge_based_node.hpp"
#include "extractor/external_memory_node.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "util/integer_range.hpp"
#include "util/exception.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/integer_range.hpp"
#include "util/string_util.hpp"
#include "util/typedefs.hpp"
@@ -17,9 +19,9 @@
#include <cstddef>
#include <vector>
#include <utility>
#include <string>
#include <utility>
#include <vector>
namespace osrm
{
@@ -145,6 +147,15 @@ class BaseDataFacade
virtual std::string GetTimestamp() const = 0;
virtual bool GetContinueStraightDefault() const = 0;
virtual BearingClassID GetBearingClassID(const NodeID id) const = 0;
virtual util::guidance::BearingClass
GetBearingClass(const BearingClassID bearing_class_id) const = 0;
virtual EntryClassID GetEntryClassID(const EdgeID eid) const = 0;
virtual util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const = 0;
};
}
}
+101 -22
View File
@@ -6,21 +6,23 @@
#include "engine/datafacade/datafacade_base.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "storage/storage_config.hpp"
#include "engine/geospatial_query.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/original_edge_data.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/query_node.hpp"
#include "contractor/query_edge.hpp"
#include "util/graph_loader.hpp"
#include "util/io.hpp"
#include "util/range_table.hpp"
#include "util/rectangle.hpp"
#include "util/shared_memory_vector_wrapper.hpp"
#include "util/simple_logger.hpp"
#include "util/static_graph.hpp"
#include "util/static_rtree.hpp"
#include "util/range_table.hpp"
#include "util/graph_loader.hpp"
#include "util/simple_logger.hpp"
#include "util/rectangle.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "osrm/coordinate.hpp"
@@ -89,6 +91,17 @@ class InternalDataFacade final : public BaseDataFacade
boost::filesystem::path file_index_path;
util::RangeTable<16, false> m_name_table;
// bearing classes by node based node
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;
// 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;
// the look-up table for distinct bearing classes. A bearing class lists the available bearings
// at an intersection
util::ShM<util::guidance::BearingClass, false>::vector m_bearing_class_table;
void LoadProfileProperties(const boost::filesystem::path &properties_path)
{
boost::filesystem::ifstream in_stream(properties_path);
@@ -97,7 +110,8 @@ class InternalDataFacade final : public BaseDataFacade
throw util::exception("Could not open " + properties_path.string() + " for reading.");
}
in_stream.read(reinterpret_cast<char*>(&m_profile_properties), sizeof(m_profile_properties));
in_stream.read(reinterpret_cast<char *>(&m_profile_properties),
sizeof(m_profile_properties));
}
void LoadTimestamp(const boost::filesystem::path &timestamp_path)
@@ -154,6 +168,7 @@ class InternalDataFacade final : public BaseDataFacade
m_name_ID_list.resize(number_of_edges);
m_turn_instruction_list.resize(number_of_edges);
m_travel_mode_list.resize(number_of_edges);
m_entry_class_id_list.resize(number_of_edges);
extractor::OriginalEdgeData current_edge_data;
for (unsigned i = 0; i < number_of_edges; ++i)
@@ -164,6 +179,7 @@ class InternalDataFacade final : public BaseDataFacade
m_name_ID_list[i] = current_edge_data.name_id;
m_turn_instruction_list[i] = current_edge_data.turn_instruction;
m_travel_mode_list[i] = current_edge_data.travel_mode;
m_entry_class_id_list[i] = current_edge_data.entry_classid;
}
}
@@ -224,7 +240,8 @@ class InternalDataFacade final : public BaseDataFacade
boost::filesystem::ifstream datasources_stream(datasource_indexes_file, std::ios::binary);
if (!datasources_stream)
{
throw util::exception("Could not open " + datasource_indexes_file.string() + " for reading!");
throw util::exception("Could not open " + datasource_indexes_file.string() +
" for reading!");
}
BOOST_ASSERT(datasources_stream);
@@ -241,7 +258,8 @@ class InternalDataFacade final : public BaseDataFacade
boost::filesystem::ifstream datasourcenames_stream(datasource_names_file, std::ios::binary);
if (!datasourcenames_stream)
{
throw util::exception("Could not open " + datasource_names_file.string() + " for reading!");
throw util::exception("Could not open " + datasource_names_file.string() +
" for reading!");
}
BOOST_ASSERT(datasourcenames_stream);
std::string name;
@@ -277,6 +295,43 @@ class InternalDataFacade final : public BaseDataFacade
}
}
void LoadIntersectionClasses(const boost::filesystem::path &intersection_class_file)
{
std::ifstream intersection_stream(intersection_class_file.string(), std::ios::binary);
if (!intersection_stream)
util::SimpleLogger().Write(logWARNING) << "Failed to open " << intersection_class_file
<< " for reading.";
if (!util::readAndCheckFingerprint(intersection_stream))
{
util::SimpleLogger().Write(logWARNING)
<< "Fingerprint does not match or reading failed";
exit(-1);
}
{
util::SimpleLogger().Write(logINFO) << "Loading Bearing Class IDs";
std::vector<BearingClassID> bearing_class_id;
util::deserializeVector(intersection_stream, bearing_class_id);
m_bearing_class_id_table.resize(bearing_class_id.size());
std::copy(bearing_class_id.begin(), bearing_class_id.end(),
&m_bearing_class_id_table[0]);
}
{
util::SimpleLogger().Write(logINFO) << "Loading Bearing Classes";
std::vector<util::guidance::BearingClass> bearing_classes;
util::deserializeVector(intersection_stream, bearing_classes);
m_bearing_class_table.resize(bearing_classes.size());
std::copy(bearing_classes.begin(), bearing_classes.end(), &m_bearing_class_table[0]);
}
{
util::SimpleLogger().Write(logINFO) << "Loading Entry Classes";
std::vector<util::guidance::EntryClass> entry_classes;
util::deserializeVector(intersection_stream, entry_classes);
m_entry_class_table.resize(entry_classes.size());
std::copy(entry_classes.begin(), entry_classes.end(), &m_entry_class_table[0]);
}
}
public:
virtual ~InternalDataFacade()
{
@@ -284,7 +339,7 @@ class InternalDataFacade final : public BaseDataFacade
m_geospatial_query.reset();
}
explicit InternalDataFacade(const storage::StorageConfig& config)
explicit InternalDataFacade(const storage::StorageConfig &config)
{
ram_index_path = config.ram_index_path;
file_index_path = config.file_index_path;
@@ -302,8 +357,7 @@ class InternalDataFacade final : public BaseDataFacade
LoadGeometries(config.geometries_path);
util::SimpleLogger().Write() << "loading datasource info";
LoadDatasourceInfo(config.datasource_names_path,
config.datasource_indexes_path);
LoadDatasourceInfo(config.datasource_names_path, config.datasource_indexes_path);
util::SimpleLogger().Write() << "loading timestamp";
LoadTimestamp(config.timestamp_path);
@@ -316,6 +370,9 @@ class InternalDataFacade final : public BaseDataFacade
util::SimpleLogger().Write() << "loading rtree";
LoadRTree();
util::SimpleLogger().Write() << "loading intersection class data";
LoadIntersectionClasses(config.intersection_class_path);
}
// search graph access
@@ -548,8 +605,7 @@ class InternalDataFacade final : public BaseDataFacade
result_nodes.clear();
result_nodes.reserve(end - begin);
std::for_each(m_geometry_list.begin() + begin, m_geometry_list.begin() + end,
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge)
{
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge) {
result_nodes.emplace_back(edge.node_id);
});
}
@@ -564,8 +620,7 @@ class InternalDataFacade final : public BaseDataFacade
result_weights.clear();
result_weights.reserve(end - begin);
std::for_each(m_geometry_list.begin() + begin, m_geometry_list.begin() + end,
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge)
{
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge) {
result_weights.emplace_back(edge.weight);
});
}
@@ -592,11 +647,9 @@ class InternalDataFacade final : public BaseDataFacade
}
else
{
std::for_each(m_datasource_list.begin() + begin, m_datasource_list.begin() + end,
[&](const uint8_t &datasource_id)
{
result_datasources.push_back(datasource_id);
});
std::for_each(
m_datasource_list.begin() + begin, m_datasource_list.begin() + end,
[&](const uint8_t &datasource_id) { result_datasources.push_back(datasource_id); });
}
}
@@ -609,7 +662,33 @@ class InternalDataFacade final : public BaseDataFacade
std::string GetTimestamp() const override final { return m_timestamp; }
bool GetContinueStraightDefault() const override final { return m_profile_properties.continue_straight_at_waypoint; }
bool GetContinueStraightDefault() const override final
{
return m_profile_properties.continue_straight_at_waypoint;
}
BearingClassID GetBearingClassID(const NodeID nid) const override final
{
return m_bearing_class_id_table.at(nid);
}
util::guidance::BearingClass
GetBearingClass(const BearingClassID bearing_class_id) const override final
{
BOOST_ASSERT(bearing_class_id != INVALID_BEARING_CLASSID);
return m_bearing_class_table.at(bearing_class_id);
}
EntryClassID GetEntryClassID(const EdgeID eid) const override final
{
return m_entry_class_id_list.at(eid);
}
util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const override final
{
BOOST_ASSERT(entry_class_id != INVALID_ENTRY_CLASSID);
return m_entry_class_table.at(entry_class_id);
}
};
}
}
+79 -14
View File
@@ -10,14 +10,16 @@
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "engine/geospatial_query.hpp"
#include "util/make_unique.hpp"
#include "util/range_table.hpp"
#include "util/rectangle.hpp"
#include "util/simple_logger.hpp"
#include "util/static_graph.hpp"
#include "util/static_rtree.hpp"
#include "util/make_unique.hpp"
#include "util/simple_logger.hpp"
#include "util/rectangle.hpp"
#include <cstddef>
@@ -30,9 +32,9 @@
#include <vector>
#include <boost/assert.hpp>
#include <boost/thread/tss.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/tss.hpp>
namespace osrm
{
@@ -94,6 +96,17 @@ class SharedDataFacade final : public BaseDataFacade
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;
// the look-up table for distinct bearing classes. A bearing class lists the available bearings
// at an intersection
util::ShM<util::guidance::BearingClass, true>::vector m_bearing_class_table;
void LoadChecksum()
{
m_check_sum = *data_layout->GetBlockPtr<unsigned>(shared_memory,
@@ -171,6 +184,13 @@ class SharedDataFacade final : public BaseDataFacade
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>(
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);
}
void LoadViaNodeList()
@@ -263,6 +283,28 @@ class SharedDataFacade final : public BaseDataFacade
m_datasource_name_lengths = std::move(datasource_name_lengths);
}
void LoadIntersecionClasses()
{
auto bearing_class_id_ptr = data_layout->GetBlockPtr<BearingClassID>(
shared_memory, storage::SharedDataLayout::BEARING_CLASSID);
typename util::ShM<BearingClassID, true>::vector bearing_class_id_table(
bearing_class_id_ptr,
data_layout->num_entries[storage::SharedDataLayout::BEARING_CLASSID]);
m_bearing_class_id_table = std::move(bearing_class_id_table);
auto bearing_class_ptr = data_layout->GetBlockPtr<util::guidance::BearingClass>(
shared_memory, storage::SharedDataLayout::BEARING_CLASS);
typename util::ShM<util::guidance::BearingClass, true>::vector bearing_class_table(
bearing_class_ptr, data_layout->num_entries[storage::SharedDataLayout::BEARING_CLASS]);
m_bearing_class_table = std::move(bearing_class_table);
auto entry_class_ptr = data_layout->GetBlockPtr<util::guidance::EntryClass>(
shared_memory, storage::SharedDataLayout::ENTRY_CLASS);
typename util::ShM<util::guidance::EntryClass, true>::vector entry_class_table(
entry_class_ptr, data_layout->num_entries[storage::SharedDataLayout::ENTRY_CLASS]);
m_entry_class_table = std::move(entry_class_table);
}
public:
virtual ~SharedDataFacade() {}
@@ -350,6 +392,7 @@ class SharedDataFacade final : public BaseDataFacade
LoadCoreInformation();
LoadProfileProperties();
LoadRTree();
LoadIntersecionClasses();
util::SimpleLogger().Write() << "number of geometries: "
<< m_coordinate_list.size();
@@ -420,8 +463,7 @@ class SharedDataFacade final : public BaseDataFacade
result_nodes.clear();
result_nodes.reserve(end - begin);
std::for_each(m_geometry_list.begin() + begin, m_geometry_list.begin() + end,
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge)
{
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge) {
result_nodes.emplace_back(edge.node_id);
});
}
@@ -436,8 +478,7 @@ class SharedDataFacade final : public BaseDataFacade
result_weights.clear();
result_weights.reserve(end - begin);
std::for_each(m_geometry_list.begin() + begin, m_geometry_list.begin() + end,
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge)
{
[&](const osrm::extractor::CompressedEdgeContainer::CompressedEdge &edge) {
result_weights.emplace_back(edge.weight);
});
}
@@ -634,11 +675,9 @@ class SharedDataFacade final : public BaseDataFacade
}
else
{
std::for_each(m_datasource_list.begin() + begin, m_datasource_list.begin() + end,
[&](const uint8_t &datasource_id)
{
result_datasources.push_back(datasource_id);
});
std::for_each(
m_datasource_list.begin() + begin, m_datasource_list.begin() + end,
[&](const uint8_t &datasource_id) { result_datasources.push_back(datasource_id); });
}
}
@@ -663,6 +702,32 @@ class SharedDataFacade final : public BaseDataFacade
{
return m_profile_properties->continue_straight_at_waypoint;
}
<<<<<<< HEAD
=======
BearingClassID GetBearingClassID(const NodeID id) const override final
{
return m_bearing_class_id_table.at(id);
}
util::guidance::BearingClass
GetBearingClass(const BearingClassID bearing_class_id) const override final
{
BOOST_ASSERT(bearing_class_id != INVALID_BEARING_CLASSID);
return m_bearing_class_table.at(bearing_class_id);
}
EntryClassID GetEntryClassID(const EdgeID eid) const override final
{
return m_entry_class_id_list.at(eid);
}
util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const override final
{
BOOST_ASSERT(entry_class_id != INVALID_ENTRY_CLASSID);
return m_entry_class_table.at(entry_class_id);
}
>>>>>>> a5cb6a1... initial version of intersection classification
};
}
}
+10 -4
View File
@@ -12,6 +12,9 @@
#include "util/bearing.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/typedefs.hpp"
#include <boost/optional.hpp>
#include <cstddef>
@@ -27,12 +30,13 @@ namespace detail
{
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
const LegGeometry &leg_geometry,
const std::size_t segment_index);
const std::size_t segment_index,
util::guidance::EntryClass entry_class,
util::guidance::BearingClass bearing_class);
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
const WaypointType waypoint_type,
const LegGeometry &leg_geometry);
} // ns detail
template <typename DataFacadeT>
@@ -100,8 +104,10 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
} else {
step_name_id = target_node.name_id;
}
maneuver = detail::stepManeuverFromGeometry(path_point.turn_instruction,
leg_geometry, segment_index);
maneuver = detail::stepManeuverFromGeometry(
path_point.turn_instruction, leg_geometry, segment_index,
facade.GetEntryClass(path_point.entry_classid),
facade.GetBearingClass(facade.GetBearingClassID(path_point.turn_via_node)));
segment_index++;
segment_duration = 0;
}
@@ -3,6 +3,8 @@
#include "extractor/guidance/turn_instruction.hpp"
#include "util/coordinate.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include <cstdint>
#include <vector>
@@ -27,6 +29,8 @@ struct IntermediateIntersection
double duration;
double distance;
util::Coordinate location;
util::guidance::EntryClass entry_class;
util::guidance::BearingClass bearing_class;
};
struct StepManeuver
@@ -37,6 +41,8 @@ struct StepManeuver
extractor::guidance::TurnInstruction instruction;
WaypointType waypoint_type;
unsigned exit;
util::guidance::EntryClass entry_class;
util::guidance::BearingClass bearing_class;
std::vector<IntermediateIntersection> intersections;
};
+3 -1
View File
@@ -2,8 +2,8 @@
#define RAW_ROUTE_DATA_H
#include "engine/phantom_node.hpp"
#include "extractor/travel_mode.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/travel_mode.hpp"
#include "util/typedefs.hpp"
#include "osrm/coordinate.hpp"
@@ -29,6 +29,8 @@ struct PathData
extractor::guidance::TurnInstruction turn_instruction;
// travel mode of the street that leads to the turn
extractor::TravelMode travel_mode : 4;
// entry class of the turn, indicating possibility of turns
EntryClassID entry_classid;
};
struct InternalRouteResult
@@ -1,10 +1,10 @@
#ifndef ROUTING_BASE_HPP
#define ROUTING_BASE_HPP
#include "util/coordinate_calculation.hpp"
#include "engine/internal_route_result.hpp"
#include "engine/search_engine_data.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/typedefs.hpp"
#include <boost/assert.hpp>
@@ -14,10 +14,10 @@
#include <algorithm>
#include <iterator>
#include <numeric>
#include <stack>
#include <utility>
#include <vector>
#include <stack>
#include <numeric>
namespace osrm
{
@@ -317,13 +317,12 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
for (std::size_t i = start_index; i < end_index; ++i)
{
unpacked_path.push_back(
PathData{id_vector[i],
name_index,
weight_vector[i],
extractor::guidance::TurnInstruction::NO_TURN(),
travel_mode});
PathData{id_vector[i], name_index, weight_vector[i],
extractor::guidance::TurnInstruction::NO_TURN(), travel_mode,
INVALID_ENTRY_CLASSID});
}
BOOST_ASSERT(unpacked_path.size() > 0);
unpacked_path.back().entry_classid = facade->GetEntryClassID(ed.id);
unpacked_path.back().turn_instruction = turn_instruction;
unpacked_path.back().duration_until_turn += (ed.distance - total_weight);
}
@@ -376,14 +375,12 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
{
BOOST_ASSERT(i < id_vector.size());
BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode > 0);
unpacked_path.push_back(
PathData{id_vector[i],
phantom_node_pair.target_phantom.name_id,
weight_vector[i],
extractor::guidance::TurnInstruction::NO_TURN(),
target_traversed_in_reverse
? phantom_node_pair.target_phantom.backward_travel_mode
: phantom_node_pair.target_phantom.forward_travel_mode});
unpacked_path.push_back(PathData{
id_vector[i], phantom_node_pair.target_phantom.name_id, weight_vector[i],
extractor::guidance::TurnInstruction::NO_TURN(),
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
: phantom_node_pair.target_phantom.forward_travel_mode,
INVALID_ENTRY_CLASSID});
}
if (unpacked_path.size() > 0)
@@ -641,9 +638,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
}
// TODO check if unordered_set might be faster
// sort by id and increasing by distance
auto entry_point_comparator =
[](const std::pair<NodeID, EdgeWeight> &lhs, const std::pair<NodeID, EdgeWeight> &rhs)
{
auto entry_point_comparator = [](const std::pair<NodeID, EdgeWeight> &lhs,
const std::pair<NodeID, EdgeWeight> &rhs) {
return lhs.first < rhs.first || (lhs.first == rhs.first && lhs.second < rhs.second);
};
std::sort(forward_entry_points.begin(), forward_entry_points.end(), entry_point_comparator);
+20 -8
View File
@@ -3,33 +3,35 @@
#ifndef EDGE_BASED_GRAPH_FACTORY_HPP_
#define EDGE_BASED_GRAPH_FACTORY_HPP_
#include "extractor/edge_based_edge.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/restriction_map.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/edge_based_edge.hpp"
#include "extractor/edge_based_node.hpp"
#include "extractor/original_edge_data.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/query_node.hpp"
#include "extractor/guidance/turn_analysis.hpp"
#include "extractor/restriction_map.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "extractor/guidance/turn_analysis.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include "util/deallocating_vector.hpp"
#include "util/name_table.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include <algorithm>
#include <cstdint>
#include <cstddef>
#include <cstdint>
#include <iosfwd>
#include <memory>
#include <queue>
#include <string>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <string>
#include <boost/filesystem/fstream.hpp>
@@ -67,6 +69,12 @@ class EdgeBasedGraphFactory
void GetStartPointMarkers(std::vector<bool> &node_is_startpoint);
void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights);
// These access functions don't destroy the content
const std::vector<BearingClassID> &GetBearingClassIds() const;
std::vector<BearingClassID> &GetBearingClassIds();
std::vector<util::guidance::BearingClass> GetBearingClasses() const;
std::vector<util::guidance::EntryClass> GetEntryClasses() const;
unsigned GetHighestEdgeID();
// Basic analysis of a turn (u --(e1)-- v --(e2)-- w)
@@ -127,6 +135,10 @@ class EdgeBasedGraphFactory
std::size_t restricted_turns_counter;
std::size_t skipped_uturns_counter;
std::size_t skipped_barrier_turns_counter;
std::unordered_map<util::guidance::BearingClass, BearingClassID> bearing_class_hash;
std::vector<BearingClassID> bearing_class_by_node_based_node;
std::unordered_map<util::guidance::EntryClass, EntryClassID> entry_class_hash;
};
} // namespace extractor
} // namespace osrm
+16 -5
View File
@@ -29,10 +29,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define EXTRACTOR_HPP
#include "extractor/edge_based_edge.hpp"
#include "extractor/extractor_config.hpp"
#include "extractor/edge_based_graph_factory.hpp"
#include "extractor/extractor_config.hpp"
#include "extractor/graph_compressor.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/typedefs.hpp"
namespace osrm
@@ -52,14 +55,16 @@ class Extractor
ExtractorConfig config;
std::pair<std::size_t, std::size_t>
BuildEdgeExpandedGraph(lua_State* lua_state,
const ProfileProperties& profile_properties,
BuildEdgeExpandedGraph(lua_State *lua_state,
const ProfileProperties &profile_properties,
std::vector<QueryNode> &internal_to_external_node_map,
std::vector<EdgeBasedNode> &node_based_edge_list,
std::vector<bool> &node_is_startpoint,
std::vector<EdgeWeight> &edge_based_node_weights,
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list);
void WriteProfileProperties(const std::string& output_path, const ProfileProperties& properties) const;
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
const std::string &intersection_class_output_file);
void WriteProfileProperties(const std::string &output_path,
const ProfileProperties &properties) const;
void WriteNodeMapping(const std::vector<QueryNode> &internal_to_external_node_map);
void FindComponents(unsigned max_edge_id,
const util::DeallocatingVector<EdgeBasedEdge> &edges,
@@ -76,6 +81,12 @@ class Extractor
void WriteEdgeBasedGraph(const std::string &output_file_filename,
const size_t max_edge_id,
util::DeallocatingVector<EdgeBasedEdge> const &edge_based_edge_list);
void WriteIntersectionClassificationData(
const std::string &output_file_name,
const std::vector<std::uint32_t> &node_based_intersection_classes,
const std::vector<util::guidance::BearingClass> &bearing_classes,
const std::vector<util::guidance::EntryClass> &entry_classes) const;
};
}
}
+2
View File
@@ -72,6 +72,7 @@ struct ExtractorConfig
edge_penalty_path = basepath + ".osrm.edge_penalties";
edge_based_node_weights_output_path = basepath + ".osrm.enw";
profile_properties_output_path = basepath + ".osrm.properties";
intersection_class_data_output_path = basepath + ".osrm.icd";
}
boost::filesystem::path config_file_path;
@@ -90,6 +91,7 @@ struct ExtractorConfig
std::string rtree_nodes_output_path;
std::string rtree_leafs_output_path;
std::string profile_properties_output_path;
std::string intersection_class_data_output_path;
unsigned requested_num_threads;
unsigned small_component_size;
+4 -3
View File
@@ -41,7 +41,8 @@ const constexpr bool shiftable_ccw[] = {false, true, true, false, false, true, t
const constexpr bool shiftable_cw[] = {false, false, true, true, false, false, true, true};
const constexpr std::uint8_t modifier_bounds[detail::num_direction_modifiers] = {
0, 36, 93, 121, 136, 163, 220, 255};
const constexpr double discrete_angle_step_size = 360. / 256.;
const constexpr double discrete_angle_step_size = 360. / 24;
template <typename IteratorType>
util::Coordinate
@@ -246,12 +247,12 @@ inline bool isConflict(const TurnInstruction first, const TurnInstruction second
inline DiscreteAngle discretizeAngle(const double angle)
{
BOOST_ASSERT(angle >= 0. && angle <= 360.);
return DiscreteAngle(static_cast<std::uint8_t>(angle / detail::discrete_angle_step_size));
return DiscreteAngle(static_cast<std::uint8_t>((angle + 0.5 *detail::discrete_angle_step_size) / detail::discrete_angle_step_size));
}
inline double angleFromDiscreteAngle(const DiscreteAngle angle)
{
return static_cast<double>(angle) * detail::discrete_angle_step_size;
return static_cast<double>(angle) * detail::discrete_angle_step_size + 0.5 * detail::discrete_angle_step_size;
}
inline double getAngularPenalty(const double angle, DirectionModifier modifier)
@@ -46,6 +46,9 @@ class TurnAnalysis
// the entry into the turn analysis
std::vector<TurnOperation> getTurns(const NodeID from_node, const EdgeID via_eid) const;
// access to the intersection representation for classification purposes
Intersection getIntersection(const NodeID from_node, const EdgeID via_eid) const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;
const IntersectionGenerator intersection_generator;
@@ -1,18 +1,23 @@
#ifndef OSRM_GUIDANCE_TURN_CLASSIFICATION_HPP_
#define OSRM_GUIDANCE_TURN_CLASSIFICATION_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/query_node.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/coordinate.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/query_node.hpp"
#include <algorithm>
#include <cstddef>
#include <vector>
#include <utility>
namespace osrm
{
@@ -21,99 +26,12 @@ namespace extractor
namespace guidance
{
struct TurnPossibility
{
TurnPossibility(DiscreteAngle angle, EdgeID edge_id)
: angle(std::move(angle)), edge_id(std::move(edge_id))
{
}
TurnPossibility() : angle(0), edge_id(SPECIAL_EDGEID) {}
DiscreteAngle angle;
EdgeID edge_id;
};
struct CompareTurnPossibilities
{
bool operator()(const std::vector<TurnPossibility> &left,
const std::vector<TurnPossibility> &right) const
{
if (left.size() < right.size())
return true;
if (left.size() > right.size())
return false;
for (std::size_t i = 0; i < left.size(); ++i)
{
if ((((int)left[i].angle + 16) % 256) / 32 < (((int)right[i].angle + 16) % 256) / 32)
return true;
if ((((int)left[i].angle + 16) % 256) / 32 > (((int)right[i].angle + 16) % 256) / 32)
return false;
}
return false;
}
};
inline std::vector<TurnPossibility>
std::pair<util::guidance::EntryClass,util::guidance::BearingClass>
classifyIntersection(NodeID nid,
const util::NodeBasedDynamicGraph &graph,
const Intersection &intersection,
const util::NodeBasedDynamicGraph &node_based_graph,
const extractor::CompressedEdgeContainer &compressed_geometries,
const std::vector<extractor::QueryNode> &query_nodes)
{
std::vector<TurnPossibility> turns;
if (graph.BeginEdges(nid) == graph.EndEdges(nid))
return std::vector<TurnPossibility>();
const EdgeID base_id = graph.BeginEdges(nid);
const auto base_coordinate = getRepresentativeCoordinate(nid, graph.GetTarget(base_id), base_id,
graph.GetEdgeData(base_id).reversed,
compressed_geometries, query_nodes);
const auto node_coordinate = util::Coordinate(query_nodes[nid].lon, query_nodes[nid].lat);
// generate a list of all turn angles between a base edge, the node and a current edge
for (const EdgeID eid : graph.GetAdjacentEdgeRange(nid))
{
const auto edge_coordinate = getRepresentativeCoordinate(
nid, graph.GetTarget(eid), eid, false, compressed_geometries, query_nodes);
double angle = util::coordinate_calculation::computeAngle(base_coordinate, node_coordinate,
edge_coordinate);
turns.emplace_back(discretizeAngle(angle), eid);
}
std::sort(turns.begin(), turns.end(),
[](const TurnPossibility left, const TurnPossibility right) {
return left.angle < right.angle;
});
turns.push_back(turns.front()); // sentinel
for (std::size_t turn_nr = 0; turn_nr + 1 < turns.size(); ++turn_nr)
{
turns[turn_nr].angle = (256 + static_cast<uint32_t>(turns[turn_nr + 1].angle) -
static_cast<uint32_t>(turns[turn_nr].angle)) %
256; // calculate the difference to the right
}
turns.pop_back(); // remove sentinel again
// find largest:
std::size_t best_id = 0;
DiscreteAngle largest_turn_angle = turns.front().angle;
for (std::size_t current_turn_id = 1; current_turn_id < turns.size(); ++current_turn_id)
{
if (turns[current_turn_id].angle > largest_turn_angle)
{
largest_turn_angle = turns[current_turn_id].angle;
best_id = current_turn_id;
}
}
// rotate all angles so the largest angle comes first
std::rotate(turns.begin(), turns.begin() + best_id, turns.end());
return turns;
}
const std::vector<extractor::QueryNode> &query_nodes);
} // namespace guidance
} // namespace extractor
+6 -2
View File
@@ -1,10 +1,11 @@
#ifndef ORIGINAL_EDGE_DATA_HPP
#define ORIGINAL_EDGE_DATA_HPP
#include "extractor/travel_mode.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/travel_mode.hpp"
#include "util/typedefs.hpp"
#include <cstddef>
#include <limits>
namespace osrm
@@ -17,9 +18,10 @@ struct OriginalEdgeData
explicit OriginalEdgeData(NodeID via_node,
unsigned name_id,
guidance::TurnInstruction turn_instruction,
EntryClassID entry_classid,
TravelMode travel_mode)
: via_node(via_node), name_id(name_id), turn_instruction(turn_instruction),
travel_mode(travel_mode)
entry_classid(entry_classid), travel_mode(travel_mode)
{
}
@@ -27,6 +29,7 @@ struct OriginalEdgeData
: via_node(std::numeric_limits<unsigned>::max()),
name_id(std::numeric_limits<unsigned>::max()),
turn_instruction(guidance::TurnInstruction::INVALID()),
entry_classid(INVALID_ENTRY_CLASSID),
travel_mode(TRAVEL_MODE_INACCESSIBLE)
{
}
@@ -34,6 +37,7 @@ struct OriginalEdgeData
NodeID via_node;
unsigned name_id;
guidance::TurnInstruction turn_instruction;
EntryClassID entry_classid;
TravelMode travel_mode;
};
}
+4
View File
@@ -29,6 +29,7 @@ struct SharedDataLayout
GRAPH_EDGE_LIST,
COORDINATE_LIST,
TURN_INSTRUCTION,
ENTRY_CLASSID,
TRAVEL_MODE,
R_SEARCH_TREE,
GEOMETRIES_INDEX,
@@ -42,6 +43,9 @@ struct SharedDataLayout
DATASOURCE_NAME_OFFSETS,
DATASOURCE_NAME_LENGTHS,
PROPERTIES,
BEARING_CLASSID,
ENTRY_CLASS,
BEARING_CLASS,
NUM_BLOCKS
};
+1
View File
@@ -64,6 +64,7 @@ struct StorageConfig final
boost::filesystem::path datasource_indexes_path;
boost::filesystem::path names_data_path;
boost::filesystem::path properties_path;
boost::filesystem::path intersection_class_path;
};
}
}
+87
View File
@@ -0,0 +1,87 @@
#ifndef OSRM_UTIL_GUIDANCE_BEARING_CLASS_HPP_
#define OSRM_UTIL_GUIDANCE_BEARING_CLASS_HPP_
#include <cstddef>
#include <cstdint>
#include <functional>
#include <vector>
namespace osrm
{
namespace util
{
namespace guidance
{
class BearingClass;
} // namespace guidance
} // namespace util
} // namespace osrm
namespace std
{
template <> struct hash<::osrm::util::guidance::BearingClass>
{
inline std::size_t operator()(const ::osrm::util::guidance::BearingClass &bearing_class) const;
};
} // namespace std
namespace osrm
{
namespace util
{
namespace guidance
{
class BearingClass
{
public:
using FlagBaseType = std::uint32_t;
const static constexpr double discrete_angle_step_size = 360. / 24;
BearingClass();
// add a continuous angle to the, returns true if no item existed that uses the same discrete
// angle
bool addContinuous(const double bearing);
// add a discrete ID, returns true if no item existed that uses the same discrete angle
bool addDiscreteID(const std::uint8_t id);
// hashing
bool operator==(const BearingClass &other) const;
// sorting
bool operator<(const BearingClass &other) const;
std::vector<double> getAvailableBearings() const;
// get a discrete representation of an angle. Required to map a bearing/angle to the discrete
// ones stored within the class
static std::uint8_t discreteBearingID(double angle);
// we are hiding the access to the flags behind a protection wall, to make sure the bit logic
// isn't tempered with
private:
// given a list of possible discrete angles, the available angles flag indicates the presence of
// a given turn at the intersection
FlagBaseType available_bearings_mask;
// allow hash access to internal representation
friend std::size_t std::hash<BearingClass>::operator()(const BearingClass &) const;
};
} // namespace guidance
} // namespace util
} // namespace osrm
// make Bearing Class hasbable
namespace std
{
inline size_t hash<::osrm::util::guidance::BearingClass>::
operator()(const ::osrm::util::guidance::BearingClass &bearing_class) const
{
return hash<::osrm::util::guidance::BearingClass::FlagBaseType>()(
bearing_class.available_bearings_mask);
}
} // namespace std
#endif /* OSRM_UTIL_GUIDANCE_BEARING_CLASS_HPP_ */
+78
View File
@@ -0,0 +1,78 @@
#ifndef OSRM_UTIL_GUIDANCE_ENTRY_CLASS_HPP_
#define OSRM_UTIL_GUIDANCE_ENTRY_CLASS_HPP_
#include <cstddef>
#include <cstdint>
#include <functional>
namespace osrm
{
namespace util
{
namespace guidance
{
class EntryClass;
} // namespace guidance
} // namespace util
} // namespace osrm
namespace std
{
template <> struct hash<::osrm::util::guidance::EntryClass>
{
inline std::size_t operator()(const ::osrm::util::guidance::EntryClass &entry_class) const;
};
} // namespace std
namespace osrm
{
namespace util
{
namespace guidance
{
class EntryClass
{
using FlagBaseType = std::uint32_t;
public:
EntryClass();
// we are hiding the access to the flags behind a protection wall, to make sure the bit logic
// isn't tempered with. zero based indexing
void activate(std::uint32_t index);
// check whether a certain turn allows entry
bool allowsEntry(std::uint32_t index) const;
// required for hashing
bool operator==(const EntryClass &) const;
// sorting
bool operator<(const EntryClass &) const;
private:
// given a list of possible discrete angles, the available angles flag indicates the presence of
// a given turn at the intersection
FlagBaseType enabled_entries_flags;
// allow hash access to internal representation
friend std::size_t std::hash<EntryClass>::operator()(const EntryClass &) const;
};
} // namespace guidance
} // namespace utilr
} // namespace osrm
// make Entry Class hasbable
namespace std
{
inline size_t hash<::osrm::util::guidance::EntryClass>::
operator()(const ::osrm::util::guidance::EntryClass &entry_class) const
{
return hash<::osrm::util::guidance::EntryClass::FlagBaseType>()(
entry_class.enabled_entries_flags);
}
} // namespace std
#endif /* OSRM_UTIL_GUIDANCE_ENTRY_CLASS_HPP_ */
+77 -3
View File
@@ -4,6 +4,12 @@
/* A set of tools required for guidance in both pre and post-processing */
#include "extractor/guidance/turn_instruction.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/simple_logger.hpp"
#include <algorithm>
#include <vector>
namespace osrm
{
@@ -41,8 +47,76 @@ inline extractor::guidance::DirectionModifier getTurnDirection(const double angl
return extractor::guidance::DirectionModifier::UTurn;
}
} /* namespace guidance */
} /* namespace util */
} /* namespace osrm */
inline double getMatchingDiscreteBearing(const bool requires_entry,
const double bearing,
const EntryClass entry_class,
const std::vector<double> existing_bearings)
{
if (existing_bearings.empty())
return 0;
const double discrete_bearing =
BearingClass::discreteBearingID(bearing) * BearingClass::discrete_angle_step_size;
// it they are very close to the turn, the discrete bearing should be fine
if (std::abs(bearing - discrete_bearing) < 0.25 * BearingClass::discrete_angle_step_size)
{
const auto isValidEntry = [&]() {
const auto bound = std::upper_bound(existing_bearings.begin(), existing_bearings.end(),
(discrete_bearing - 0.001));
const auto index = bound == existing_bearings.end()
? 0
: std::distance(existing_bearings.begin(), bound);
return entry_class.allowsEntry(index);
};
BOOST_ASSERT(!requires_entry || isValidEntry());
return discrete_bearing;
}
else
{
// the next larger bearing or first if we are wrapping around at zero
const auto next_index =
std::distance(existing_bearings.begin(),
std::lower_bound(existing_bearings.begin(), existing_bearings.end(),
discrete_bearing)) %
existing_bearings.size();
// next smaller bearing or last if we are wrapping around at zero
const auto previous_index =
(next_index + existing_bearings.size() - 1) % existing_bearings.size();
const auto difference = [](const double first, const double second) {
return std::min(std::abs(first - second), 360.0 - std::abs(first - second));
};
const auto next_bearing = existing_bearings[next_index];
const auto previous_bearing = existing_bearings[previous_index];
const auto decideOnBearing = [&](
const std::size_t preferred_index, const double preferred_bearing,
const std::size_t alternative_index, const double alternative_bearing) {
if (!requires_entry || entry_class.allowsEntry(preferred_index))
return preferred_bearing;
else if (entry_class.allowsEntry(alternative_index))
return alternative_bearing;
else
{
SimpleLogger().Write(logDEBUG)
<< "Cannot find a valid entry for a discrete Bearing in Turn Classificiation";
return 0.;
}
};
if (difference(bearing, next_bearing) < difference(bearing, previous_index))
return decideOnBearing(next_index, next_bearing, previous_index, previous_bearing);
else
return decideOnBearing(previous_index, previous_bearing, next_index, next_bearing);
}
return 0;
}
} // namespace guidance
} // namespace util
} // namespace osrm
#endif /* OSRM_UTIL_GUIDANCE_TOOLKIT_HPP_ */
+22 -1
View File
@@ -8,8 +8,8 @@
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <bitset>
#include <fstream>
#include <vector>
#include "util/fingerprint.hpp"
@@ -51,6 +51,16 @@ bool serializeVector(const std::string &filename, const std::vector<simple_type>
return static_cast<bool>(stream);
}
template <typename simple_type>
bool serializeVector(std::ostream &stream, const std::vector<simple_type> &data)
{
std::uint64_t count = data.size();
stream.write(reinterpret_cast<const char *>(&count), sizeof(count));
if (!data.empty())
stream.write(reinterpret_cast<const char *>(&data[0]), sizeof(simple_type) * count);
return static_cast<bool>(stream);
}
template <typename simple_type>
bool deserializeVector(const std::string &filename, std::vector<simple_type> &data)
{
@@ -67,6 +77,17 @@ bool deserializeVector(const std::string &filename, std::vector<simple_type> &da
return static_cast<bool>(stream);
}
template <typename simple_type>
bool deserializeVector(std::istream &stream, std::vector<simple_type> &data)
{
std::uint64_t count = 0;
stream.read(reinterpret_cast<char *>(&count), sizeof(count));
data.resize(count);
if (count)
stream.read(reinterpret_cast<char *>(&data[0]), sizeof(simple_type) * count);
return static_cast<bool>(stream);
}
inline bool serializeFlags(const boost::filesystem::path &path, const std::vector<bool> &flags)
{
// TODO this should be replaced with a FILE-based write using error checking
+11 -4
View File
@@ -34,13 +34,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <limits>
#include <cstddef>
#include <cstdint>
// OpenStreetMap node ids are higher than 2^32
OSRM_STRONG_TYPEDEF(uint64_t, OSMNodeID)
OSRM_STRONG_TYPEDEF_HASHABLE(uint64_t, OSMNodeID)
OSRM_STRONG_TYPEDEF(std::uint64_t, OSMNodeID)
OSRM_STRONG_TYPEDEF_HASHABLE(std::uint64_t, OSMNodeID)
OSRM_STRONG_TYPEDEF(uint32_t, OSMWayID)
OSRM_STRONG_TYPEDEF_HASHABLE(uint32_t, OSMWayID)
OSRM_STRONG_TYPEDEF(std::uint32_t, OSMWayID)
OSRM_STRONG_TYPEDEF_HASHABLE(std::uint32_t, OSMWayID)
static const OSMNodeID SPECIAL_OSM_NODEID = OSMNodeID(std::numeric_limits<std::uint64_t>::max());
static const OSMWayID SPECIAL_OSM_WAYID = OSMWayID(std::numeric_limits<std::uint32_t>::max());
@@ -57,6 +58,12 @@ using NodeID = unsigned int;
using EdgeID = unsigned int;
using EdgeWeight = int;
using BearingClassID = std::uint32_t;
static const BearingClassID INVALID_BEARING_CLASSID = std::numeric_limits<std::uint32_t>::max();
using EntryClassID = std::uint16_t;
static const EntryClassID INVALID_ENTRY_CLASSID = std::numeric_limits<std::uint16_t>::max();
static const NodeID SPECIAL_NODEID = std::numeric_limits<unsigned>::max();
static const NodeID SPECIAL_SEGMENTID = std::numeric_limits<int>::max();
static const EdgeID SPECIAL_EDGEID = std::numeric_limits<unsigned>::max();