Unpacking of intermediate paths

This commit is contained in:
Dennis Luxen
2014-02-11 11:42:24 +01:00
parent 3be644265b
commit c71c8b0047
20 changed files with 639 additions and 443 deletions
+70 -19
View File
@@ -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:
+1 -1
View File
@@ -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 -21
View File
@@ -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;
}
+10 -7
View File
@@ -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();
}
};
+8 -176
View File
@@ -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;