initial version of intersection classification
This commit is contained in:
committed by
Patrick Niklaus
parent
6aa97048df
commit
ba074b0116
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user