Unpacking of intermediate paths
This commit is contained in:
@@ -1,28 +1,58 @@
|
||||
#ifndef EDGE_BASED_NODE_H
|
||||
#define EDGE_BASED_NODE_H
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
// An EdgeBasedNode represents a node in the edge-expanded graph.
|
||||
|
||||
#include <limits>
|
||||
|
||||
struct EdgeBasedNode {
|
||||
|
||||
EdgeBasedNode() :
|
||||
id(INT_MAX),
|
||||
lat1(INT_MAX),
|
||||
lat2(INT_MAX),
|
||||
lon1(INT_MAX),
|
||||
lon2(INT_MAX >> 1),
|
||||
belongsToTinyComponent(false),
|
||||
nameID(UINT_MAX),
|
||||
weight(UINT_MAX >> 1),
|
||||
ignoreInGrid(false)
|
||||
reverse_edge_based_node_id(std::numeric_limits<int>::max()),
|
||||
lat1(std::numeric_limits<int>::max()),
|
||||
lon1(std::numeric_limits<int>::max()),
|
||||
lat2(std::numeric_limits<int>::max()),
|
||||
lon2(std::numeric_limits<int>::max() >> 1),
|
||||
belongsToTinyComponent(false),
|
||||
name_id(std::numeric_limits<unsigned>::max()),
|
||||
forward_weight(std::numeric_limits<int>::max() >> 1),
|
||||
reverse_weight(std::numeric_limits<int>::max() >> 1),
|
||||
forward_offset_to_edge_based_node(0),
|
||||
reverse_offset_to_edge_based_node(0)
|
||||
{ }
|
||||
|
||||
EdgeBasedNode(
|
||||
NodeID forward_edge_based_node_id,
|
||||
NodeID reverse_edge_based_node_id,
|
||||
int lat1,
|
||||
int lon1,
|
||||
int lat2,
|
||||
int lon2,
|
||||
bool belongsToTinyComponent,
|
||||
NodeID name_id,
|
||||
int forward_weight,
|
||||
int reverse_weight,
|
||||
int forward_offset_to_edge_based_node,
|
||||
int reverse_offset_to_edge_based_node
|
||||
) :
|
||||
forward_edge_based_node_id(forward_edge_based_node_id),
|
||||
reverse_edge_based_node_id(reverse_edge_based_node_id),
|
||||
lat1(lat1),
|
||||
lon1(lon1),
|
||||
lat2(lat2),
|
||||
lon2(lon2),
|
||||
belongsToTinyComponent(belongsToTinyComponent),
|
||||
name_id(name_id),
|
||||
forward_weight(forward_weight),
|
||||
reverse_weight(reverse_weight),
|
||||
forward_offset_to_edge_based_node(forward_offset_to_edge_based_node),
|
||||
reverse_offset_to_edge_based_node(reverse_offset_to_edge_based_node)
|
||||
{ }
|
||||
|
||||
// Computes:
|
||||
@@ -39,9 +69,26 @@ struct EdgeBasedNode {
|
||||
BOOST_ASSERT( query_location.isValid() );
|
||||
|
||||
const double epsilon = 1.0/precision;
|
||||
const double y = query_location.lon/COORDINATE_PRECISION;
|
||||
const double a = lat2y(lat1/COORDINATE_PRECISION);
|
||||
const double b = lon1/COORDINATE_PRECISION;
|
||||
const double c = lat2y(lat2/COORDINATE_PRECISION);
|
||||
const double d = lon2/COORDINATE_PRECISION;
|
||||
double p,q/*,mX*/,nY;
|
||||
if( std::abs(a-c) > std::numeric_limits<double>::epsilon() ){
|
||||
const double m = (d-b)/(c-a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
|
||||
q = b + m*(p - a);
|
||||
} else {
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d*p - c*q)/(a*d - b*c);
|
||||
|
||||
if( ignoreInGrid ) {
|
||||
return std::numeric_limits<double>::max();
|
||||
//discretize the result to coordinate precision. it's a hack!
|
||||
if( std::abs(nY) < (1./COORDINATE_PRECISION) ) {
|
||||
nY = 0.;
|
||||
}
|
||||
|
||||
// p, q : the end points of the underlying edge
|
||||
@@ -50,13 +97,14 @@ struct EdgeBasedNode {
|
||||
|
||||
// r : query location
|
||||
const Point r(lat2y(query_location.lat/COORDINATE_PRECISION),
|
||||
} else if( std::abs(r-1.) <= std::numeric_limits<double>::epsilon() ) {
|
||||
query_location.lon/COORDINATE_PRECISION);
|
||||
|
||||
const Point foot = ComputePerpendicularFoot(p, q, r, epsilon);
|
||||
ratio = ComputeRatio(p, q, foot, epsilon);
|
||||
|
||||
BOOST_ASSERT( !std::isnan(ratio) );
|
||||
|
||||
nearest_location.lat = y2lat(p)*COORDINATE_PRECISION;
|
||||
nearest_location = ComputeNearestPointOnSegment(foot, ratio);
|
||||
|
||||
BOOST_ASSERT( nearest_location.isValid() );
|
||||
@@ -65,6 +113,9 @@ struct EdgeBasedNode {
|
||||
// const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const double approximated_distance = FixedPointCoordinate::ApproximateDistance(query_location, nearest_location);
|
||||
|
||||
query_location,
|
||||
nearest_location
|
||||
);
|
||||
BOOST_ASSERT( 0.0 <= approximated_distance );
|
||||
return approximated_distance;
|
||||
}
|
||||
@@ -82,21 +133,21 @@ struct EdgeBasedNode {
|
||||
return FixedPointCoordinate((lat1+lat2)/2, (lon1+lon2)/2);
|
||||
}
|
||||
|
||||
NodeID id;
|
||||
NodeID forward_edge_based_node_id;
|
||||
|
||||
// The coordinates of the end-points of the underlying edge.
|
||||
int lat1;
|
||||
int lat2;
|
||||
int lon1;
|
||||
int lat2;
|
||||
int lon2:31;
|
||||
|
||||
bool belongsToTinyComponent:1;
|
||||
NodeID nameID;
|
||||
NodeID name_id;
|
||||
|
||||
// The weight of the underlying edge.
|
||||
unsigned weight:31;
|
||||
|
||||
bool ignoreInGrid:1;
|
||||
int reverse_weight;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ public:
|
||||
m_weight(w),
|
||||
m_forward(f),
|
||||
m_backward(b)
|
||||
{}
|
||||
{ }
|
||||
|
||||
NodeID target() const { return m_target; }
|
||||
NodeID source() const { return m_source; }
|
||||
|
||||
@@ -29,37 +29,45 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define PHANTOMNODES_H_
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
struct PhantomNode {
|
||||
PhantomNode() :
|
||||
edgeBasedNode(UINT_MAX),
|
||||
nodeBasedEdgeNameID(UINT_MAX),
|
||||
weight1(INT_MAX),
|
||||
weight2(INT_MAX),
|
||||
forward_node_id(UINT_MAX),
|
||||
reverse_node_id(UINT_MAX),
|
||||
name_id(UINT_MAX),
|
||||
forward_weight(INT_MAX),
|
||||
reverse_weight(INT_MAX),
|
||||
ratio(0.)
|
||||
{ }
|
||||
|
||||
NodeID edgeBasedNode;
|
||||
unsigned nodeBasedEdgeNameID;
|
||||
int weight1;
|
||||
int weight2;
|
||||
NodeID forward_node_id;
|
||||
NodeID reverse_node_id;
|
||||
unsigned name_id;
|
||||
int forward_weight;
|
||||
int reverse_weight;
|
||||
double ratio;
|
||||
FixedPointCoordinate location;
|
||||
|
||||
void Reset() {
|
||||
edgeBasedNode = UINT_MAX;
|
||||
nodeBasedEdgeNameID = UINT_MAX;
|
||||
weight1 = INT_MAX;
|
||||
weight2 = INT_MAX;
|
||||
forward_node_id = UINT_MAX;
|
||||
name_id = UINT_MAX;
|
||||
forward_weight = INT_MAX;
|
||||
reverse_weight = INT_MAX;
|
||||
ratio = 0.;
|
||||
location.Reset();
|
||||
}
|
||||
bool isBidirected() const {
|
||||
return weight2 != INT_MAX;
|
||||
return forward_weight != INT_MAX && reverse_weight != INT_MAX;
|
||||
}
|
||||
bool isValid(const unsigned numberOfNodes) const {
|
||||
return location.isValid() && (edgeBasedNode < numberOfNodes) && (weight1 != INT_MAX) && (ratio >= 0.) && (ratio <= 1.) && (nodeBasedEdgeNameID != UINT_MAX);
|
||||
return
|
||||
location.isValid() &&
|
||||
( (forward_node_id < numberOfNodes) || (reverse_node_id < numberOfNodes) ) &&
|
||||
( (forward_weight != INT_MAX) || (reverse_weight != INT_MAX) ) &&
|
||||
(ratio >= 0.) &&
|
||||
(ratio <= 1.) &&
|
||||
(name_id != UINT_MAX);
|
||||
}
|
||||
|
||||
bool operator==(const PhantomNode & other) const {
|
||||
@@ -76,11 +84,11 @@ struct PhantomNodes {
|
||||
}
|
||||
|
||||
bool PhantomsAreOnSameNodeBasedEdge() const {
|
||||
return (startPhantom.edgeBasedNode == targetPhantom.edgeBasedNode);
|
||||
return (startPhantom.forward_node_id == targetPhantom.forward_node_id);
|
||||
}
|
||||
|
||||
bool AtLeastOnePhantomNodeIsUINTMAX() const {
|
||||
return !(startPhantom.edgeBasedNode == UINT_MAX || targetPhantom.edgeBasedNode == UINT_MAX);
|
||||
return !(startPhantom.forward_node_id == UINT_MAX || targetPhantom.forward_node_id == UINT_MAX);
|
||||
}
|
||||
|
||||
bool PhantomNodesHaveEqualLocation() const {
|
||||
@@ -89,15 +97,15 @@ struct PhantomNodes {
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn){
|
||||
out << "Node1: " << pn.startPhantom.edgeBasedNode << std::endl;
|
||||
out << "Node2: " << pn.targetPhantom.edgeBasedNode << std::endl;
|
||||
out << "startCoord: " << pn.startPhantom.location << std::endl;
|
||||
out << "Node1: " << pn.startPhantom.forward_node_id << std::endl;
|
||||
out << "Node2: " << pn.targetPhantom.reverse_node_id << std::endl;
|
||||
out << "startCoord: " << pn.startPhantom.location << std::endl;
|
||||
out << "targetCoord: " << pn.targetPhantom.location << std::endl;
|
||||
return out;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn){
|
||||
out << "node: " << pn.edgeBasedNode << ", name: " << pn.nodeBasedEdgeNameID << ", w1: " << pn.weight1 << ", w2: " << pn.weight2 << ", ratio: " << pn.ratio << ", loc: " << pn.location;
|
||||
out << "node1: " << pn.forward_node_id << ", node2: " << pn.reverse_node_id << ", name: " << pn.name_id << ", w1: " << pn.forward_weight << ", w2: " << pn.reverse_weight << ", ratio: " << pn.ratio << ", loc: " << pn.location;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,17 +34,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <climits>
|
||||
|
||||
#include <limits>
|
||||
|
||||
struct NodeInfo {
|
||||
typedef NodeID key_type; //type of NodeID
|
||||
typedef int value_type; //type of lat,lons
|
||||
|
||||
NodeInfo(int _lat, int _lon, NodeID _id) : lat(_lat), lon(_lon), id(_id) {}
|
||||
NodeInfo() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {}
|
||||
NodeInfo(int lat, int lon, NodeID id) : lat(lat), lon(lon), id(id) { }
|
||||
NodeInfo()
|
||||
:
|
||||
lat(std::numeric_limits<int>::max()),
|
||||
lon(std::numeric_limits<int>::max()),
|
||||
id(std::numeric_limits<unsigned>::max())
|
||||
{ }
|
||||
|
||||
int lat;
|
||||
int lon;
|
||||
NodeID id;
|
||||
@@ -75,11 +78,11 @@ struct NodeInfo {
|
||||
break;
|
||||
default:
|
||||
BOOST_ASSERT_MSG(false, "should not happen");
|
||||
return UINT_MAX;
|
||||
return std::numeric_limits<unsigned>::max();
|
||||
break;
|
||||
}
|
||||
BOOST_ASSERT_MSG(false, "should not happen");
|
||||
return UINT_MAX;
|
||||
return std::numeric_limits<unsigned>::max();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -487,152 +487,7 @@ public:
|
||||
//SimpleLogger().Write() << m_element_count << " elements in leafs";
|
||||
}
|
||||
//Read-only operation for queries
|
||||
/*
|
||||
inline void FindKNearestPhantomNodesForCoordinate(
|
||||
const FixedPointCoordinate & location,
|
||||
const unsigned zoom_level,
|
||||
const unsigned candidate_count,
|
||||
std::vector<std::pair<PhantomNode, double> > & result_vector
|
||||
) const {
|
||||
|
||||
bool ignore_tiny_components = (zoom_level <= 14);
|
||||
DataT nearest_edge;
|
||||
|
||||
uint32_t io_count = 0;
|
||||
uint32_t explored_tree_nodes_count = 0;
|
||||
SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
double min_max_dist = std::numeric_limits<double>::max();
|
||||
bool found_a_nearest_edge = false;
|
||||
|
||||
FixedPointCoordinate nearest, current_start_coordinate, current_end_coordinate;
|
||||
|
||||
//initialize queue with root element
|
||||
std::priority_queue<QueryCandidate> traversal_queue;
|
||||
traversal_queue.push(QueryCandidate(0, m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate)));
|
||||
BOOST_ASSERT_MSG(std::numberic_limits<double>::epsilon() > (0. - traversal_queue.top().min_dist), "Root element in NN Search has min dist != 0.");
|
||||
|
||||
while(!traversal_queue.empty()) {
|
||||
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
|
||||
|
||||
++explored_tree_nodes_count;
|
||||
bool prune_downward = (current_query_node.min_dist >= min_max_dist);
|
||||
bool prune_upward = (current_query_node.min_dist >= min_dist);
|
||||
if( !prune_downward && !prune_upward ) { //downward pruning
|
||||
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
|
||||
if (current_tree_node.child_is_on_disk) {
|
||||
LeafNode current_leaf_node;
|
||||
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
|
||||
++io_count;
|
||||
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
||||
DataT & current_edge = current_leaf_node.objects[i];
|
||||
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double current_ratio = 0.;
|
||||
double current_perpendicular_distance = current_edge.ComputePerpendicularDistance(
|
||||
input_coordinate,
|
||||
nearest,
|
||||
current_ratio
|
||||
);
|
||||
|
||||
if(
|
||||
current_perpendicular_distance < min_dist
|
||||
&& !DoubleEpsilonCompare(
|
||||
current_perpendicular_distance,
|
||||
min_dist
|
||||
)
|
||||
) { //found a new minimum
|
||||
min_dist = current_perpendicular_distance;
|
||||
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
|
||||
result_phantom_node.weight1 = current_edge.weight;
|
||||
result_phantom_node.weight2 = INT_MAX;
|
||||
result_phantom_node.location = nearest;
|
||||
current_start_coordinate.lat = current_edge.lat1;
|
||||
current_start_coordinate.lon = current_edge.lon1;
|
||||
current_end_coordinate.lat = current_edge.lat2;
|
||||
current_end_coordinate.lon = current_edge.lon2;
|
||||
nearest_edge = current_edge;
|
||||
found_a_nearest_edge = true;
|
||||
} else if(
|
||||
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
|
||||
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
|
||||
&& EdgesAreEquivalent(
|
||||
current_start_coordinate,
|
||||
FixedPointCoordinate(
|
||||
current_edge.lat1,
|
||||
current_edge.lon1
|
||||
),
|
||||
FixedPointCoordinate(
|
||||
current_edge.lat2,
|
||||
current_edge.lon2
|
||||
),
|
||||
current_end_coordinate
|
||||
)
|
||||
) {
|
||||
result_phantom_node.edgeBasedNode = std::min(current_edge.id, result_phantom_node.edgeBasedNode);
|
||||
result_phantom_node.weight2 = current_edge.weight;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//traverse children, prune if global mindist is smaller than local one
|
||||
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
|
||||
const int32_t child_id = current_tree_node.children[i];
|
||||
TreeNode & child_tree_node = m_search_tree[child_id];
|
||||
RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
|
||||
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
|
||||
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
|
||||
if( current_min_max_dist < min_max_dist ) {
|
||||
min_max_dist = current_min_max_dist;
|
||||
}
|
||||
if (current_min_dist > min_max_dist) {
|
||||
continue;
|
||||
}
|
||||
if (current_min_dist > min_dist) { //upward pruning
|
||||
continue;
|
||||
}
|
||||
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const double distance_to_edge =
|
||||
ApproximateDistance (
|
||||
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
|
||||
result_phantom_node.location
|
||||
);
|
||||
|
||||
const double length_of_edge =
|
||||
ApproximateDistance(
|
||||
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
|
||||
FixedPointCoordinate(nearest_edge.lat2, nearest_edge.lon2)
|
||||
);
|
||||
|
||||
const double ratio = (found_a_nearest_edge ?
|
||||
std::min(1., distance_to_edge/ length_of_edge ) : 0 );
|
||||
result_phantom_node.weight1 *= ratio;
|
||||
if(INT_MAX != result_phantom_node.weight2) {
|
||||
result_phantom_node.weight2 *= (1.-ratio);
|
||||
}
|
||||
result_phantom_node.ratio = ratio;
|
||||
|
||||
//Hack to fix rounding errors and wandering via nodes.
|
||||
if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
|
||||
result_phantom_node.location.lon = input_coordinate.lon;
|
||||
}
|
||||
if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) {
|
||||
result_phantom_node.location.lat = input_coordinate.lat;
|
||||
}
|
||||
|
||||
SimpleLogger().Write() << "mindist: " << min_distphantom_node.isBidirected() ? "yes" : "no");
|
||||
return found_a_nearest_edge;
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
bool LocateClosestEndPointForCoordinate(
|
||||
const FixedPointCoordinate & input_coordinate,
|
||||
FixedPointCoordinate & result_coordinate,
|
||||
@@ -799,10 +654,11 @@ public:
|
||||
)
|
||||
) { //found a new minimum
|
||||
min_dist = current_perpendicular_distance;
|
||||
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
|
||||
result_phantom_node.weight1 = current_edge.weight;
|
||||
result_phantom_node.weight2 = INT_MAX;
|
||||
result_phantom_node.forward_node_id = current_edge.forward_edge_based_node_id;
|
||||
result_phantom_node.reverse_node_id = current_edge.reverse_edge_based_node_id;
|
||||
result_phantom_node.name_id = current_edge.name_id;
|
||||
result_phantom_node.forward_weight = current_edge.forward_weight;
|
||||
result_phantom_node.reverse_weight = current_edge.reverse_weight;
|
||||
result_phantom_node.location = nearest;
|
||||
current_start_coordinate.lat = current_edge.lat1;
|
||||
current_start_coordinate.lon = current_edge.lon1;
|
||||
@@ -810,30 +666,6 @@ public:
|
||||
current_end_coordinate.lon = current_edge.lon2;
|
||||
nearest_edge = current_edge;
|
||||
found_a_nearest_edge = true;
|
||||
} else
|
||||
if( DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
|
||||
( 1 == abs(current_edge.id - result_phantom_node.edgeBasedNode ) ) &&
|
||||
EdgesAreEquivalent(
|
||||
current_start_coordinate,
|
||||
FixedPointCoordinate(
|
||||
current_edge.lat1,
|
||||
current_edge.lon1
|
||||
),
|
||||
FixedPointCoordinate(
|
||||
current_edge.lat2,
|
||||
current_edge.lon2
|
||||
),
|
||||
current_end_coordinate
|
||||
)
|
||||
) {
|
||||
|
||||
BOOST_ASSERT_MSG(current_edge.id != result_phantom_node.edgeBasedNode, "IDs not different");
|
||||
result_phantom_node.weight2 = current_edge.weight;
|
||||
if(current_edge.id < result_phantom_node.edgeBasedNode) {
|
||||
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||
std::swap(result_phantom_node.weight1, result_phantom_node.weight2);
|
||||
std::swap(current_end_coordinate, current_start_coordinate);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -884,9 +716,9 @@ public:
|
||||
ratio = std::min(1., ratio);
|
||||
}
|
||||
|
||||
result_phantom_node.weight1 *= ratio;
|
||||
if(INT_MAX != result_phantom_node.weight2) {
|
||||
result_phantom_node.weight2 *= (1.-ratio);
|
||||
result_phantom_node.forward_weight *= ratio;
|
||||
if( INT_MAX != result_phantom_node.reverse_weight ) {
|
||||
result_phantom_node.reverse_weight *= (1.-ratio);
|
||||
}
|
||||
result_phantom_node.ratio = ratio;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user