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