initial version of intersection classification
This commit is contained in:
parent
6aa97048df
commit
ba074b0116
@ -54,7 +54,7 @@ configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/util/version.hpp.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include/util/version.hpp
|
||||
)
|
||||
file(GLOB UtilGlob src/util/*.cpp)
|
||||
file(GLOB UtilGlob src/util/*.cpp src/util/*/*.cpp)
|
||||
file(GLOB ExtractorGlob src/extractor/*.cpp src/extractor/*/*.cpp)
|
||||
file(GLOB ContractorGlob src/contractor/*.cpp)
|
||||
file(GLOB StorageGlob src/storage/*.cpp)
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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 ×tamp_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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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
include/util/guidance/bearing_class.hpp
Normal file
87
include/util/guidance/bearing_class.hpp
Normal 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
include/util/guidance/entry_class.hpp
Normal file
78
include/util/guidance/entry_class.hpp
Normal 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_ */
|
@ -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_ */
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -4,6 +4,10 @@
|
||||
#include "engine/polyline_compressor.hpp"
|
||||
#include "util/integer_range.hpp"
|
||||
|
||||
#include "util/guidance/bearing_class.hpp"
|
||||
#include "util/guidance/entry_class.hpp"
|
||||
#include "util/guidance/toolkit.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
@ -93,6 +97,47 @@ util::json::Array coordinateToLonLat(const util::Coordinate coordinate)
|
||||
return array;
|
||||
}
|
||||
|
||||
util::json::Object getConnection(const bool entry_allowed, const double bearing)
|
||||
{
|
||||
util::json::Object result;
|
||||
result.values["entry_allowed"] = entry_allowed ? "true" : "false";
|
||||
result.values["bearing"] = bearing;
|
||||
return result;
|
||||
}
|
||||
|
||||
util::json::Array getConnections(const util::guidance::EntryClass entry_class,
|
||||
const util::guidance::BearingClass bearing_class)
|
||||
{
|
||||
util::json::Array result;
|
||||
const auto bearings = bearing_class.getAvailableBearings();
|
||||
for (size_t connection = 0; connection < bearings.size(); ++connection)
|
||||
{
|
||||
result.values.push_back(
|
||||
getConnection(entry_class.allowsEntry(connection), bearings[connection]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
util::json::Object getIntersection(const guidance::StepManeuver maneuver)
|
||||
{
|
||||
util::json::Object result;
|
||||
// bearings are oriented in the direction of driving. For the in-bearing, we actually need to
|
||||
// find the bearing from the view of the intersection. This means we have to rotate the bearing
|
||||
// by 180 degree.
|
||||
const auto rotated_bearing_before = (maneuver.bearing_before >= 180.0)
|
||||
? (maneuver.bearing_before - 180.0)
|
||||
: (maneuver.bearing_before + 180.0);
|
||||
result.values["from_bearing"] =
|
||||
getMatchingDiscreteBearing(false, rotated_bearing_before, maneuver.entry_class,
|
||||
maneuver.bearing_class.getAvailableBearings());
|
||||
result.values["to_bearing"] =
|
||||
getMatchingDiscreteBearing(true, maneuver.bearing_after, maneuver.entry_class,
|
||||
maneuver.bearing_class.getAvailableBearings());
|
||||
|
||||
result.values["connections"] = getConnections(maneuver.entry_class, maneuver.bearing_class);
|
||||
return result;
|
||||
}
|
||||
|
||||
// FIXME this actually needs to be configurable from the profiles
|
||||
std::string modeToString(const extractor::TravelMode mode)
|
||||
{
|
||||
@ -150,6 +195,7 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
|
||||
if (maneuver.waypoint_type == guidance::WaypointType::None)
|
||||
{
|
||||
step_maneuver.values["type"] = detail::instructionTypeToString(maneuver.instruction.type);
|
||||
step_maneuver.values["intersection"] = detail::getIntersection(maneuver);
|
||||
}
|
||||
else
|
||||
step_maneuver.values["type"] = detail::waypointTypeToString(maneuver.waypoint_type);
|
||||
@ -169,6 +215,7 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
|
||||
// actually compute the correct locations of the intersections
|
||||
if (!maneuver.intersections.empty() && maneuver.exit == 0)
|
||||
step_maneuver.values["exit"] = maneuver.intersections.size();
|
||||
|
||||
return step_maneuver;
|
||||
}
|
||||
|
||||
|
@ -37,20 +37,23 @@ StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instr
|
||||
pre_turn_bearing =
|
||||
util::coordinate_calculation::bearing(pre_turn_coordinate, turn_coordinate);
|
||||
}
|
||||
return StepManeuver{
|
||||
std::move(turn_coordinate),
|
||||
pre_turn_bearing,
|
||||
post_turn_bearing,
|
||||
std::move(instruction),
|
||||
waypoint_type,
|
||||
INVALID_EXIT_NR,
|
||||
{} // no intermediate intersections
|
||||
};
|
||||
return StepManeuver{std::move(turn_coordinate),
|
||||
pre_turn_bearing,
|
||||
post_turn_bearing,
|
||||
std::move(instruction),
|
||||
waypoint_type,
|
||||
INVALID_EXIT_NR,
|
||||
// BearingClass,EntryClass, and Intermediate intersections are unknown yet
|
||||
{},
|
||||
{},
|
||||
{}};
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
auto turn_index = leg_geometry.BackIndex(segment_index);
|
||||
BOOST_ASSERT(turn_index > 0);
|
||||
@ -66,15 +69,10 @@ StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instr
|
||||
const double post_turn_bearing =
|
||||
util::coordinate_calculation::bearing(turn_coordinate, post_turn_coordinate);
|
||||
|
||||
return StepManeuver{
|
||||
std::move(turn_coordinate),
|
||||
pre_turn_bearing,
|
||||
post_turn_bearing,
|
||||
std::move(instruction),
|
||||
WaypointType::None,
|
||||
INVALID_EXIT_NR,
|
||||
{} // no intermediate intersections
|
||||
};
|
||||
// add a step without intermediate intersections
|
||||
return StepManeuver{std::move(turn_coordinate), pre_turn_bearing, post_turn_bearing,
|
||||
std::move(instruction), WaypointType::None, INVALID_EXIT_NR,
|
||||
std::move(entry_class), std::move(bearing_class), {}};
|
||||
}
|
||||
} // ns detail
|
||||
} // ns engine
|
||||
|
@ -444,7 +444,8 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
|
||||
auto addIntersection = [](RouteStep into, const RouteStep &last_step,
|
||||
const RouteStep &intersection) {
|
||||
into.maneuver.intersections.push_back(
|
||||
{last_step.duration, last_step.distance, intersection.maneuver.location});
|
||||
{last_step.duration, last_step.distance, intersection.maneuver.location,
|
||||
intersection.maneuver.entry_class, intersection.maneuver.bearing_class});
|
||||
|
||||
return forwardInto(std::move(into), intersection);
|
||||
};
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "extractor/suffix_table.hpp"
|
||||
#include "extractor/guidance/toolkit.hpp"
|
||||
#include "extractor/guidance/turn_analysis.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
@ -22,6 +23,7 @@
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@ -326,6 +328,10 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
guidance::TurnAnalysis turn_analysis(*m_node_based_graph, m_node_info_list, *m_restriction_map,
|
||||
m_barrier_nodes, m_compressed_edge_container, name_table,
|
||||
street_name_suffix_table);
|
||||
|
||||
bearing_class_by_node_based_node.resize(m_node_based_graph->GetNumberOfNodes(),
|
||||
std::numeric_limits<std::uint32_t>::max());
|
||||
|
||||
for (const auto node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||
{
|
||||
progress.PrintStatus(node_u);
|
||||
@ -340,6 +346,40 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
auto possible_turns = turn_analysis.getTurns(node_u, edge_from_u);
|
||||
|
||||
const NodeID node_v = m_node_based_graph->GetTarget(edge_from_u);
|
||||
|
||||
// the entry class depends on the turn, so we have to classify the interesction for
|
||||
// every edge
|
||||
const auto turn_classification = classifyIntersection(
|
||||
node_v, turn_analysis.getIntersection(node_u, edge_from_u), *m_node_based_graph,
|
||||
m_compressed_edge_container, m_node_info_list);
|
||||
|
||||
const auto entry_class_id = [&](const util::guidance::EntryClass entry_class) {
|
||||
if (0 == entry_class_hash.count(entry_class))
|
||||
{
|
||||
const auto id = static_cast<std::uint16_t>(entry_class_hash.size());
|
||||
entry_class_hash[entry_class] = id;
|
||||
return id;
|
||||
}
|
||||
else
|
||||
{
|
||||
return entry_class_hash.find(entry_class)->second;
|
||||
}
|
||||
}(turn_classification.first);
|
||||
|
||||
const auto bearing_class_id = [&](const util::guidance::BearingClass bearing_class) {
|
||||
if (0 == bearing_class_hash.count(bearing_class))
|
||||
{
|
||||
const auto id = static_cast<std::uint32_t>(bearing_class_hash.size());
|
||||
bearing_class_hash[bearing_class] = id;
|
||||
return id;
|
||||
}
|
||||
else
|
||||
{
|
||||
return bearing_class_hash.find(bearing_class)->second;
|
||||
}
|
||||
}(turn_classification.second);
|
||||
bearing_class_by_node_based_node[node_v] = bearing_class_id;
|
||||
|
||||
for (const auto turn : possible_turns)
|
||||
{
|
||||
const double turn_angle = turn.angle;
|
||||
@ -373,7 +413,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
BOOST_ASSERT(m_compressed_edge_container.HasEntryForID(edge_from_u));
|
||||
original_edge_data_vector.emplace_back(
|
||||
m_compressed_edge_container.GetPositionForID(edge_from_u), edge_data1.name_id,
|
||||
turn_instruction, edge_data1.travel_mode);
|
||||
turn_instruction, entry_class_id, edge_data1.travel_mode);
|
||||
|
||||
++original_edges_counter;
|
||||
|
||||
@ -469,6 +509,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
}
|
||||
}
|
||||
|
||||
util::SimpleLogger().Write() << "Created " << entry_class_hash.size() << " entry classes and "
|
||||
<< bearing_class_hash.size() << " Bearing Classes";
|
||||
|
||||
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
||||
|
||||
// Finally jump back to the empty space at the beginning and write length prefix
|
||||
@ -493,6 +536,38 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
<< " turns over barriers";
|
||||
}
|
||||
|
||||
std::vector<util::guidance::BearingClass> EdgeBasedGraphFactory::GetBearingClasses() const
|
||||
{
|
||||
std::vector<util::guidance::BearingClass> result(bearing_class_hash.size());
|
||||
for (const auto &pair : bearing_class_hash)
|
||||
{
|
||||
BOOST_ASSERT(pair.second < result.size());
|
||||
result[pair.second] = pair.first;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const std::vector<BearingClassID> &EdgeBasedGraphFactory::GetBearingClassIds() const
|
||||
{
|
||||
return bearing_class_by_node_based_node;
|
||||
}
|
||||
|
||||
std::vector<BearingClassID> &EdgeBasedGraphFactory::GetBearingClassIds()
|
||||
{
|
||||
return bearing_class_by_node_based_node;
|
||||
}
|
||||
|
||||
std::vector<util::guidance::EntryClass> EdgeBasedGraphFactory::GetEntryClasses() const
|
||||
{
|
||||
std::vector<util::guidance::EntryClass> result(entry_class_hash.size());
|
||||
for (const auto &pair : entry_class_hash)
|
||||
{
|
||||
BOOST_ASSERT(pair.second < result.size());
|
||||
result[pair.second] = pair.first;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) const
|
||||
{
|
||||
BOOST_ASSERT(lua_state != nullptr);
|
||||
|
@ -9,20 +9,18 @@
|
||||
#include "extractor/scripting_environment.hpp"
|
||||
|
||||
#include "extractor/raster_source.hpp"
|
||||
#include "util/graph_loader.hpp"
|
||||
#include "util/io.hpp"
|
||||
#include "util/lua_util.hpp"
|
||||
#include "util/make_unique.hpp"
|
||||
#include "util/name_table.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
#include "util/timing_util.hpp"
|
||||
#include "util/lua_util.hpp"
|
||||
#include "util/graph_loader.hpp"
|
||||
#include "util/name_table.hpp"
|
||||
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/static_rtree.hpp"
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/restriction_map.hpp"
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/static_rtree.hpp"
|
||||
|
||||
#include "extractor/tarjan_scc.hpp"
|
||||
|
||||
@ -41,14 +39,14 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <bitset>
|
||||
#include <chrono>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
#include <chrono>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@ -159,8 +157,7 @@ int Extractor::run()
|
||||
// parse OSM entities in parallel, store in resulting vectors
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<std::size_t>(0, osm_elements.size()),
|
||||
[&](const tbb::blocked_range<std::size_t> &range)
|
||||
{
|
||||
[&](const tbb::blocked_range<std::size_t> &range) {
|
||||
ExtractionNode result_node;
|
||||
ExtractionWay result_way;
|
||||
auto &local_context = scripting_environment.GetContex();
|
||||
@ -269,10 +266,10 @@ int Extractor::run()
|
||||
std::vector<bool> node_is_startpoint;
|
||||
std::vector<EdgeWeight> edge_based_node_weights;
|
||||
std::vector<QueryNode> internal_to_external_node_map;
|
||||
auto graph_size = BuildEdgeExpandedGraph(main_context.state, main_context.properties,
|
||||
internal_to_external_node_map,
|
||||
edge_based_node_list, node_is_startpoint,
|
||||
edge_based_node_weights, edge_based_edge_list);
|
||||
auto graph_size = BuildEdgeExpandedGraph(
|
||||
main_context.state, main_context.properties, internal_to_external_node_map,
|
||||
edge_based_node_list, node_is_startpoint, edge_based_node_weights, edge_based_edge_list,
|
||||
config.intersection_class_data_output_path);
|
||||
|
||||
auto number_of_node_based_nodes = graph_size.first;
|
||||
auto max_edge_id = graph_size.second;
|
||||
@ -474,7 +471,8 @@ Extractor::BuildEdgeExpandedGraph(lua_State *lua_state,
|
||||
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)
|
||||
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
||||
const std::string &intersection_class_output_file)
|
||||
{
|
||||
std::unordered_set<NodeID> barrier_nodes;
|
||||
std::unordered_set<NodeID> traffic_lights;
|
||||
@ -508,6 +506,11 @@ Extractor::BuildEdgeExpandedGraph(lua_State *lua_state,
|
||||
auto max_edge_id = edge_based_graph_factory.GetHighestEdgeID();
|
||||
|
||||
const std::size_t number_of_node_based_nodes = node_based_graph->GetNumberOfNodes();
|
||||
|
||||
WriteIntersectionClassificationData(
|
||||
intersection_class_output_file, edge_based_graph_factory.GetBearingClassIds(),
|
||||
edge_based_graph_factory.GetBearingClasses(), edge_based_graph_factory.GetEntryClasses());
|
||||
|
||||
return std::make_pair(number_of_node_based_nodes, max_edge_id);
|
||||
}
|
||||
|
||||
@ -601,5 +604,40 @@ void Extractor::WriteEdgeBasedGraph(
|
||||
|
||||
util::SimpleLogger().Write() << "Processed " << number_of_used_edges << " edges";
|
||||
}
|
||||
|
||||
void Extractor::WriteIntersectionClassificationData(
|
||||
const std::string &output_file_name,
|
||||
const std::vector<BearingClassID> &node_based_intersection_classes,
|
||||
const std::vector<util::guidance::BearingClass> &bearing_classes,
|
||||
const std::vector<util::guidance::EntryClass> &entry_classes) const
|
||||
{
|
||||
std::ofstream file_out_stream(output_file_name.c_str(), std::ios::binary);
|
||||
if (!file_out_stream)
|
||||
{
|
||||
util::SimpleLogger().Write(logWARNING) << "Failed to open " << output_file_name
|
||||
<< " for writing";
|
||||
return;
|
||||
}
|
||||
|
||||
util::SimpleLogger().Write() << "Writing Intersection Classification Data";
|
||||
TIMER_START(write_edges);
|
||||
util::writeFingerprint(file_out_stream);
|
||||
util::serializeVector(file_out_stream, node_based_intersection_classes);
|
||||
|
||||
static_assert(std::is_trivially_copyable<util::guidance::BearingClass>::value,
|
||||
"BearingClass Serialization requires trivial copyable bearing classes");
|
||||
|
||||
util::serializeVector(file_out_stream, bearing_classes);
|
||||
|
||||
static_assert(std::is_trivially_copyable<util::guidance::EntryClass>::value,
|
||||
"EntryClass Serialization requires trivial copyable entry classes");
|
||||
|
||||
util::serializeVector(file_out_stream, entry_classes);
|
||||
TIMER_STOP(write_edges);
|
||||
util::SimpleLogger().Write() << "ok, after " << TIMER_SEC(write_edges) << "s for "
|
||||
<< node_based_intersection_classes.size() << " Indices into "
|
||||
<< bearing_classes.size() << " bearing classes and "
|
||||
<< entry_classes.size() << " entry classes";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,10 @@
|
||||
#include <cstddef>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
using osrm::util::guidance::getTurnDirection;
|
||||
|
||||
@ -79,6 +81,11 @@ std::vector<TurnOperation> TurnAnalysis::getTurns(const NodeID from_nid, const E
|
||||
return turns;
|
||||
}
|
||||
|
||||
Intersection TurnAnalysis::getIntersection(const NodeID from_nid, const EdgeID via_eid) const
|
||||
{
|
||||
return intersection_generator(from_nid, via_eid);
|
||||
}
|
||||
|
||||
// Sets basic turn types as fallback for otherwise unhandled turns
|
||||
Intersection
|
||||
TurnAnalysis::setTurnTypes(const NodeID from_nid, const EdgeID, Intersection intersection) const
|
||||
|
97
src/extractor/guidance/turn_classification.cpp
Normal file
97
src/extractor/guidance/turn_classification.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
#include "extractor/guidance/turn_classification.hpp"
|
||||
|
||||
#include "util/simple_logger.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace guidance
|
||||
{
|
||||
|
||||
struct TurnPossibility
|
||||
{
|
||||
TurnPossibility(bool entry_allowed, double bearing)
|
||||
: entry_allowed(entry_allowed), bearing(std::move(bearing))
|
||||
{
|
||||
}
|
||||
|
||||
TurnPossibility() : entry_allowed(false), bearing(0) {}
|
||||
|
||||
bool entry_allowed;
|
||||
double bearing;
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
std::vector<TurnPossibility> turns;
|
||||
|
||||
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 auto &road : intersection)
|
||||
{
|
||||
const auto eid = road.turn.eid;
|
||||
const auto edge_coordinate = getRepresentativeCoordinate(
|
||||
nid, node_based_graph.GetTarget(eid), eid, false, compressed_geometries, query_nodes);
|
||||
|
||||
const double bearing =
|
||||
util::coordinate_calculation::bearing(node_coordinate, edge_coordinate);
|
||||
turns.push_back({road.entry_allowed, bearing});
|
||||
}
|
||||
|
||||
if (turns.empty())
|
||||
return {};
|
||||
|
||||
std::sort(turns.begin(), turns.end(),
|
||||
[](const TurnPossibility left, const TurnPossibility right) {
|
||||
return left.bearing < right.bearing;
|
||||
});
|
||||
|
||||
util::guidance::EntryClass entry_class;
|
||||
util::guidance::BearingClass bearing_class;
|
||||
|
||||
std::size_t turn_index = 0;
|
||||
for (std::size_t i = 0; i < turns.size(); ++i)
|
||||
{
|
||||
if (turns[i].entry_allowed)
|
||||
entry_class.activate(turn_index);
|
||||
if (bearing_class.addContinuous(turns[i].bearing))
|
||||
++turn_index;
|
||||
}
|
||||
|
||||
if (turn_index != turns.size())
|
||||
{
|
||||
util::SimpleLogger().Write(logDEBUG)
|
||||
<< "Failed to provide full turn list for intersection: " << turn_index << " roads of "
|
||||
<< turns.size() << " mapped.";
|
||||
for (auto turn : turns)
|
||||
std::cout << " " << (int)turn.bearing << " ("
|
||||
<< (int)util::guidance::BearingClass::discreteBearingID(turn.bearing) << ")";
|
||||
std::cout << std::endl;
|
||||
for (const auto &road : intersection)
|
||||
{
|
||||
const auto eid = road.turn.eid;
|
||||
const auto edge_coordinate =
|
||||
getRepresentativeCoordinate(nid, node_based_graph.GetTarget(eid), eid, false,
|
||||
compressed_geometries, query_nodes);
|
||||
|
||||
const double bearing =
|
||||
util::coordinate_calculation::bearing(node_coordinate, edge_coordinate);
|
||||
std::cout << " " << bearing;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
return std::make_pair(entry_class, bearing_class);
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
@ -1,24 +1,25 @@
|
||||
#include "extractor/original_edge_data.hpp"
|
||||
#include "util/range_table.hpp"
|
||||
#include "contractor/query_edge.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "extractor/profile_properties.hpp"
|
||||
#include "engine/datafacade/datafacade_base.hpp"
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "extractor/original_edge_data.hpp"
|
||||
#include "extractor/profile_properties.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "extractor/travel_mode.hpp"
|
||||
#include "storage/shared_barriers.hpp"
|
||||
#include "storage/shared_datatype.hpp"
|
||||
#include "storage/shared_memory.hpp"
|
||||
#include "storage/storage.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/exception.hpp"
|
||||
#include "util/fingerprint.hpp"
|
||||
#include "util/io.hpp"
|
||||
#include "util/range_table.hpp"
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/static_rtree.hpp"
|
||||
#include "engine/datafacade/datafacade_base.hpp"
|
||||
#include "extractor/travel_mode.hpp"
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "storage/storage.hpp"
|
||||
#include "storage/shared_datatype.hpp"
|
||||
#include "storage/shared_barriers.hpp"
|
||||
#include "storage/shared_memory.hpp"
|
||||
#include "util/fingerprint.hpp"
|
||||
#include "util/exception.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/mman.h>
|
||||
@ -49,8 +50,7 @@ void deleteRegion(const SharedDataType region)
|
||||
{
|
||||
if (SharedMemory::RegionExists(region) && !SharedMemory::Remove(region))
|
||||
{
|
||||
const std::string name = [&]
|
||||
{
|
||||
const std::string name = [&] {
|
||||
switch (region)
|
||||
{
|
||||
case CURRENT_REGIONS:
|
||||
@ -105,20 +105,14 @@ int Storage::Run()
|
||||
|
||||
// determine segment to use
|
||||
bool segment2_in_use = SharedMemory::RegionExists(LAYOUT_2);
|
||||
const storage::SharedDataType layout_region = [&]
|
||||
{
|
||||
const storage::SharedDataType layout_region = [&] {
|
||||
return segment2_in_use ? LAYOUT_1 : LAYOUT_2;
|
||||
}();
|
||||
const storage::SharedDataType data_region = [&]
|
||||
{
|
||||
return segment2_in_use ? DATA_1 : DATA_2;
|
||||
}();
|
||||
const storage::SharedDataType previous_layout_region = [&]
|
||||
{
|
||||
const storage::SharedDataType data_region = [&] { return segment2_in_use ? DATA_1 : DATA_2; }();
|
||||
const storage::SharedDataType previous_layout_region = [&] {
|
||||
return segment2_in_use ? LAYOUT_2 : LAYOUT_1;
|
||||
}();
|
||||
const storage::SharedDataType previous_data_region = [&]
|
||||
{
|
||||
const storage::SharedDataType previous_data_region = [&] {
|
||||
return segment2_in_use ? DATA_2 : DATA_1;
|
||||
}();
|
||||
|
||||
@ -136,7 +130,8 @@ int Storage::Run()
|
||||
boost::filesystem::ifstream name_stream(config.names_data_path, std::ios::binary);
|
||||
if (!name_stream)
|
||||
{
|
||||
throw util::exception("Could not open " + config.names_data_path.string() + " for reading.");
|
||||
throw util::exception("Could not open " + config.names_data_path.string() +
|
||||
" for reading.");
|
||||
}
|
||||
unsigned name_blocks = 0;
|
||||
name_stream.read((char *)&name_blocks, sizeof(unsigned));
|
||||
@ -154,7 +149,8 @@ int Storage::Run()
|
||||
boost::filesystem::ifstream edges_input_stream(config.edges_data_path, std::ios::binary);
|
||||
if (!edges_input_stream)
|
||||
{
|
||||
throw util::exception("Could not open " + config.edges_data_path.string() + " for reading.");
|
||||
throw util::exception("Could not open " + config.edges_data_path.string() +
|
||||
" for reading.");
|
||||
}
|
||||
unsigned number_of_original_edges = 0;
|
||||
edges_input_stream.read((char *)&number_of_original_edges, sizeof(unsigned));
|
||||
@ -168,6 +164,8 @@ int Storage::Run()
|
||||
number_of_original_edges);
|
||||
shared_layout_ptr->SetBlockSize<extractor::guidance::TurnInstruction>(
|
||||
SharedDataLayout::TURN_INSTRUCTION, number_of_original_edges);
|
||||
shared_layout_ptr->SetBlockSize<EntryClassID>(SharedDataLayout::ENTRY_CLASSID,
|
||||
number_of_original_edges);
|
||||
|
||||
boost::filesystem::ifstream hsgr_input_stream(config.hsgr_data_path, std::ios::binary);
|
||||
if (!hsgr_input_stream)
|
||||
@ -250,7 +248,8 @@ int Storage::Run()
|
||||
boost::filesystem::ifstream geometry_input_stream(config.geometries_path, std::ios::binary);
|
||||
if (!geometry_input_stream)
|
||||
{
|
||||
throw util::exception("Could not open " + config.geometries_path.string() + " for reading.");
|
||||
throw util::exception("Could not open " + config.geometries_path.string() +
|
||||
" for reading.");
|
||||
}
|
||||
unsigned number_of_geometries_indices = 0;
|
||||
unsigned number_of_compressed_geometries = 0;
|
||||
@ -270,7 +269,8 @@ int Storage::Run()
|
||||
std::ios::binary);
|
||||
if (!geometry_datasource_input_stream)
|
||||
{
|
||||
throw util::exception("Could not open " + config.datasource_indexes_path.string() + " for reading.");
|
||||
throw util::exception("Could not open " + config.datasource_indexes_path.string() +
|
||||
" for reading.");
|
||||
}
|
||||
std::size_t number_of_compressed_datasources = 0;
|
||||
if (geometry_datasource_input_stream)
|
||||
@ -287,7 +287,8 @@ int Storage::Run()
|
||||
std::ios::binary);
|
||||
if (!datasource_names_input_stream)
|
||||
{
|
||||
throw util::exception("Could not open " + config.datasource_names_path.string() + " for reading.");
|
||||
throw util::exception("Could not open " + config.datasource_names_path.string() +
|
||||
" for reading.");
|
||||
}
|
||||
std::vector<char> m_datasource_name_data;
|
||||
std::vector<std::size_t> m_datasource_name_offsets;
|
||||
@ -331,7 +332,8 @@ int Storage::Run()
|
||||
file_index_path_ptr +
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::FILE_INDEX_PATH),
|
||||
0);
|
||||
std::copy(absolute_file_index_path.string().begin(), absolute_file_index_path.string().end(), file_index_path_ptr);
|
||||
std::copy(absolute_file_index_path.string().begin(), absolute_file_index_path.string().end(),
|
||||
file_index_path_ptr);
|
||||
|
||||
// Loading street names
|
||||
unsigned *name_offsets_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
@ -382,6 +384,9 @@ int Storage::Run()
|
||||
shared_layout_ptr->GetBlockPtr<extractor::guidance::TurnInstruction, true>(
|
||||
shared_memory_ptr, SharedDataLayout::TURN_INSTRUCTION);
|
||||
|
||||
EntryClassID *entry_class_id_ptr = shared_layout_ptr->GetBlockPtr<EntryClassID, true>(
|
||||
shared_memory_ptr, SharedDataLayout::ENTRY_CLASSID);
|
||||
|
||||
extractor::OriginalEdgeData current_edge_data;
|
||||
for (unsigned i = 0; i < number_of_original_edges; ++i)
|
||||
{
|
||||
@ -390,6 +395,7 @@ int Storage::Run()
|
||||
name_id_ptr[i] = current_edge_data.name_id;
|
||||
travel_mode_ptr[i] = current_edge_data.travel_mode;
|
||||
turn_instructions_ptr[i] = current_edge_data.turn_instruction;
|
||||
entry_class_id_ptr[i] = current_edge_data.entry_classid;
|
||||
}
|
||||
edges_input_stream.close();
|
||||
|
||||
@ -503,8 +509,7 @@ int Storage::Run()
|
||||
{
|
||||
const unsigned bucket = i / 32;
|
||||
const unsigned offset = i % 32;
|
||||
const unsigned value = [&]
|
||||
{
|
||||
const unsigned value = [&] {
|
||||
unsigned return_value = 0;
|
||||
if (0 != offset)
|
||||
{
|
||||
@ -539,13 +544,16 @@ int Storage::Run()
|
||||
hsgr_input_stream.close();
|
||||
|
||||
// load profile properties
|
||||
auto profile_properties_ptr = shared_layout_ptr->GetBlockPtr<extractor::ProfileProperties, true>(shared_memory_ptr, SharedDataLayout::PROPERTIES);
|
||||
auto profile_properties_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<extractor::ProfileProperties, true>(
|
||||
shared_memory_ptr, SharedDataLayout::PROPERTIES);
|
||||
boost::filesystem::ifstream profile_properties_stream(config.properties_path);
|
||||
if (!profile_properties_stream)
|
||||
{
|
||||
util::exception("Could not open " + config.properties_path.string() + " for reading!");
|
||||
}
|
||||
profile_properties_stream.read(reinterpret_cast<char*>(profile_properties_ptr), sizeof(extractor::ProfileProperties));
|
||||
profile_properties_stream.read(reinterpret_cast<char *>(profile_properties_ptr),
|
||||
sizeof(extractor::ProfileProperties));
|
||||
|
||||
// acquire lock
|
||||
SharedMemory *data_type_memory =
|
||||
@ -562,6 +570,43 @@ int Storage::Run()
|
||||
barrier.no_running_queries_condition.wait(query_lock);
|
||||
}
|
||||
|
||||
// load intersection classes
|
||||
{
|
||||
boost::filesystem::ifstream intersection_stream(config.intersection_class_path,
|
||||
std::ios::binary);
|
||||
if (!util::readAndCheckFingerprint(intersection_stream))
|
||||
{
|
||||
util::SimpleLogger().Write(logWARNING)
|
||||
<< "Fingerprint does not match or reading failed";
|
||||
}
|
||||
|
||||
std::vector<BearingClassID> bearing_class_id_table;
|
||||
util::deserializeVector(intersection_stream, bearing_class_id_table);
|
||||
shared_layout_ptr->SetBlockSize<BearingClassID>(SharedDataLayout::BEARING_CLASSID,
|
||||
bearing_class_id_table.size());
|
||||
auto bearing_id_ptr = shared_layout_ptr->GetBlockPtr<BearingClassID, true>(
|
||||
shared_memory_ptr, SharedDataLayout::BEARING_CLASSID);
|
||||
std::copy(bearing_class_id_table.begin(), bearing_class_id_table.end(), bearing_id_ptr);
|
||||
|
||||
auto bearing_class_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<util::guidance::BearingClass, true>(
|
||||
shared_memory_ptr, SharedDataLayout::BEARING_CLASS);
|
||||
std::vector<util::guidance::BearingClass> bearing_class_table;
|
||||
util::deserializeVector(intersection_stream, bearing_class_table);
|
||||
shared_layout_ptr->SetBlockSize<util::guidance::BearingClass>(
|
||||
SharedDataLayout::BEARING_CLASS, bearing_class_table.size());
|
||||
std::copy(bearing_class_table.begin(), bearing_class_table.end(), bearing_class_ptr);
|
||||
|
||||
auto entry_class_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<util::guidance::EntryClass, true>(
|
||||
shared_memory_ptr, SharedDataLayout::ENTRY_CLASS);
|
||||
std::vector<util::guidance::EntryClass> entry_class_table;
|
||||
util::deserializeVector(intersection_stream, entry_class_table);
|
||||
shared_layout_ptr->SetBlockSize<util::guidance::EntryClass>(
|
||||
SharedDataLayout::ENTRY_CLASS, entry_class_table.size());
|
||||
std::copy(entry_class_table.begin(), entry_class_table.end(), entry_class_ptr);
|
||||
}
|
||||
|
||||
data_timestamp_ptr->layout = layout_region;
|
||||
data_timestamp_ptr->data = data_region;
|
||||
data_timestamp_ptr->timestamp += 1;
|
||||
|
@ -14,8 +14,8 @@ StorageConfig::StorageConfig(const boost::filesystem::path &base)
|
||||
geometries_path{base.string() + ".geometry"}, timestamp_path{base.string() + ".timestamp"},
|
||||
datasource_names_path{base.string() + ".datasource_names"},
|
||||
datasource_indexes_path{base.string() + ".datasource_indexes"},
|
||||
names_data_path{base.string() + ".names"},
|
||||
properties_path{base.string() + ".properties"}
|
||||
names_data_path{base.string() + ".names"}, properties_path{base.string() + ".properties"},
|
||||
intersection_class_path{base.string() + ".icd"}
|
||||
{
|
||||
}
|
||||
|
||||
@ -32,7 +32,8 @@ bool StorageConfig::IsValid() const
|
||||
boost::filesystem::is_regular_file(datasource_names_path) &&
|
||||
boost::filesystem::is_regular_file(datasource_indexes_path) &&
|
||||
boost::filesystem::is_regular_file(names_data_path) &&
|
||||
boost::filesystem::is_regular_file(properties_path);
|
||||
boost::filesystem::is_regular_file(properties_path) &&
|
||||
boost::filesystem::is_regular_file(intersection_class_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
68
src/util/guidance/bearing_class.cpp
Normal file
68
src/util/guidance/bearing_class.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include "extractor/guidance/discrete_angle.hpp"
|
||||
#include "util/guidance/bearing_class.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
namespace guidance
|
||||
{
|
||||
|
||||
static_assert(
|
||||
360 / BearingClass::discrete_angle_step_size <= 8 * sizeof(BearingClass::FlagBaseType),
|
||||
"The number of expressable bearings does not fit into the datatype used for storage.");
|
||||
|
||||
std::uint8_t BearingClass::discreteBearingID(double angle)
|
||||
{
|
||||
BOOST_ASSERT(angle >= 0. && angle <= 360.);
|
||||
// shift angle by half the step size to have the class be located around the center
|
||||
angle = (angle + 0.5 * BearingClass::discrete_angle_step_size);
|
||||
if (angle > 360)
|
||||
angle -= 360;
|
||||
|
||||
return std::uint8_t(angle / BearingClass::discrete_angle_step_size);
|
||||
}
|
||||
|
||||
BearingClass::BearingClass() : available_bearings_mask(0) {}
|
||||
|
||||
bool BearingClass::operator==(const BearingClass &other) const
|
||||
{
|
||||
return other.available_bearings_mask == available_bearings_mask;
|
||||
}
|
||||
|
||||
bool BearingClass::operator<(const BearingClass &other) const
|
||||
{
|
||||
return available_bearings_mask < other.available_bearings_mask;
|
||||
}
|
||||
|
||||
bool BearingClass::addContinuous(const double angle)
|
||||
{
|
||||
return addDiscreteID(discreteBearingID(angle));
|
||||
}
|
||||
|
||||
bool BearingClass::addDiscreteID(const std::uint8_t discrete_id)
|
||||
{
|
||||
const auto mask = (1 << discrete_id);
|
||||
const auto is_new = (0 == (available_bearings_mask & mask));
|
||||
available_bearings_mask |= mask;
|
||||
return is_new;
|
||||
}
|
||||
|
||||
std::vector<double> BearingClass::getAvailableBearings() const
|
||||
{
|
||||
std::vector<double> result;
|
||||
// account for some basic inaccuracries of double
|
||||
for (std::size_t discrete_id = 0; discrete_id * discrete_angle_step_size <= 361; ++discrete_id)
|
||||
{
|
||||
// ervery set bit indicates a bearing
|
||||
if (available_bearings_mask & (1 << discrete_id))
|
||||
result.push_back(discrete_id * discrete_angle_step_size);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
38
src/util/guidance/entry_class.cpp
Normal file
38
src/util/guidance/entry_class.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "util/guidance/entry_class.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
namespace guidance
|
||||
{
|
||||
|
||||
EntryClass::EntryClass() : enabled_entries_flags(0) {}
|
||||
|
||||
void EntryClass::activate(std::uint32_t index)
|
||||
{
|
||||
BOOST_ASSERT(index < 8 * sizeof(FlagBaseType));
|
||||
enabled_entries_flags |= (1 << index);
|
||||
}
|
||||
|
||||
bool EntryClass::allowsEntry(std::uint32_t index) const
|
||||
{
|
||||
BOOST_ASSERT(index < 8 * sizeof(FlagBaseType));
|
||||
return 0 != (enabled_entries_flags & (1 << index));
|
||||
}
|
||||
|
||||
bool EntryClass::operator==(const EntryClass &other) const
|
||||
{
|
||||
return enabled_entries_flags == other.enabled_entries_flags;
|
||||
}
|
||||
|
||||
bool EntryClass::operator<(const EntryClass &other) const
|
||||
{
|
||||
return enabled_entries_flags < other.enabled_entries_flags;
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
Loading…
Reference in New Issue
Block a user