applied requested changes to EdgeBasedNode.h

This commit is contained in:
Daniel Karch 2014-03-12 10:24:35 +01:00
parent b465dabe77
commit f923f508f5

View File

@ -9,176 +9,166 @@
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <iostream>
#include <osrm/Coordinate.h> #include <osrm/Coordinate.h>
// An EdgeBasedNode represents a node in the edge-expanded graph. // An EdgeBasedNode represents a node in the edge-expanded graph.
struct EdgeBasedNode { struct EdgeBasedNode {
EdgeBasedNode() : EdgeBasedNode() :
id(INT_MAX), id(INT_MAX),
lat1(INT_MAX), lat1(INT_MAX),
lat2(INT_MAX), lat2(INT_MAX),
lon1(INT_MAX), lon1(INT_MAX),
lon2(INT_MAX >> 1), lon2(INT_MAX >> 1),
belongsToTinyComponent(false), belongsToTinyComponent(false),
nameID(UINT_MAX), nameID(UINT_MAX),
weight(UINT_MAX >> 1), weight(UINT_MAX >> 1),
ignoreInGrid(false) ignoreInGrid(false)
{ } { }
// Computes: // Computes:
// - the distance from the given query location to nearest point on this edge (and returns it) // - the distance from the given query location to nearest point on this edge (and returns it)
// - the location on this edge which is nearest to the query location // - the location on this edge which is nearest to the query location
// - the ratio ps:pq, where p and q are the end points of this edge, and s is the perpendicular foot of // - the ratio ps:pq, where p and q are the end points of this edge, and s is the perpendicular foot of
// the query location on the line defined by p and q. // the query location on the line defined by p and q.
double ComputePerpendicularDistance( double ComputePerpendicularDistance(
const FixedPointCoordinate& query_location, const FixedPointCoordinate& query_location,
FixedPointCoordinate & nearest_location, FixedPointCoordinate & nearest_location,
double & ratio, double & ratio,
double precision = COORDINATE_PRECISION double precision = COORDINATE_PRECISION
) const { ) const {
BOOST_ASSERT( query_location.isValid() ); BOOST_ASSERT( query_location.isValid() );
double epsilon = 1.0/COORDINATE_PRECISION; const double epsilon = 1.0/COORDINATE_PRECISION;
if( ignoreInGrid ) { if( ignoreInGrid ) {
return std::numeric_limits<double>::max(); return std::numeric_limits<double>::max();
} }
// p, q : the end points of the underlying edge // p, q : the end points of the underlying edge
const Point p(lat2y(lat1/COORDINATE_PRECISION), lon1/COORDINATE_PRECISION); const Point p(lat2y(lat1/COORDINATE_PRECISION), lon1/COORDINATE_PRECISION);
const Point q(lat2y(lat2/COORDINATE_PRECISION), lon2/COORDINATE_PRECISION); const Point q(lat2y(lat2/COORDINATE_PRECISION), lon2/COORDINATE_PRECISION);
// r : query location // r : query location
const Point r(lat2y(query_location.lat/COORDINATE_PRECISION), const Point r(lat2y(query_location.lat/COORDINATE_PRECISION),
query_location.lon/COORDINATE_PRECISION); query_location.lon/COORDINATE_PRECISION);
const Point foot = ComputePerpendicularFoot(p, q, r, epsilon); const Point foot = ComputePerpendicularFoot(p, q, r, epsilon);
ratio = ComputeRatio(p, q, foot, epsilon); ratio = ComputeRatio(p, q, foot, epsilon);
BOOST_ASSERT( !std::isnan(ratio) ); BOOST_ASSERT( !std::isnan(ratio) );
nearest_location = ComputeNearestPointOnSegment(foot, ratio); nearest_location = ComputeNearestPointOnSegment(foot, ratio);
BOOST_ASSERT( nearest_location.isValid() ); BOOST_ASSERT( nearest_location.isValid() );
// TODO: Replace with euclidean approximation when k-NN search is done // TODO: Replace with euclidean approximation when k-NN search is done
// const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance( // const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
const double approximated_distance = const double approximated_distance = FixedPointCoordinate::ApproximateDistance(query_location, nearest_location);
FixedPointCoordinate::ApproximateDistance(query_location, nearest_location);
BOOST_ASSERT( 0. <= approximated_distance ); BOOST_ASSERT( 0.0 <= approximated_distance );
return approximated_distance; return approximated_distance;
} }
bool operator<(const EdgeBasedNode & other) const { bool operator<(const EdgeBasedNode & other) const {
return other.id < id; return other.id < id;
} }
bool operator==(const EdgeBasedNode & other) const { bool operator==(const EdgeBasedNode & other) const {
return id == other.id; return id == other.id;
} }
// Returns the midpoint of the underlying edge. // Returns the midpoint of the underlying edge.
inline FixedPointCoordinate Centroid() const { inline FixedPointCoordinate Centroid() const {
return FixedPointCoordinate((lat1+lat2)/2, (lon1+lon2)/2); return FixedPointCoordinate((lat1+lat2)/2, (lon1+lon2)/2);
} }
NodeID id; NodeID id;
// The coordinates of the end-points of the underlying edge. // The coordinates of the end-points of the underlying edge.
int lat1; int lat1;
int lat2; int lat2;
int lon1; int lon1;
int lon2:31; int lon2:31;
bool belongsToTinyComponent:1; bool belongsToTinyComponent:1;
NodeID nameID; NodeID nameID;
// The weight of the underlying edge. // The weight of the underlying edge.
unsigned weight:31; unsigned weight:31;
bool ignoreInGrid:1; bool ignoreInGrid:1;
private: private:
struct Point typedef std::pair<double,double> Point;
{
const double x;
const double y;
Point(double x, double y)
: x(x), y(y) {}
};
// Compute the perpendicular foot of point r on the line defined by p and q. // Compute the perpendicular foot of point r on the line defined by p and q.
Point ComputePerpendicularFoot(const Point &p, const Point &q, const Point &r, double epsilon) const { Point ComputePerpendicularFoot(const Point &p, const Point &q, const Point &r, double epsilon) const {
// the projection of r onto the line pq // the projection of r onto the line pq
double foot_x; double foot_x, foot_y;
double foot_y;
const bool parallel_to_y_axis = std::abs(q.x - p.x) < epsilon; const bool is_parallel_to_y_axis = std::abs(q.first - p.first) < epsilon;
if( parallel_to_y_axis ) { if( is_parallel_to_y_axis ) {
foot_x = q.x; foot_x = q.first;
foot_y = r.y; foot_y = r.second;
} else { } else {
// the slope of the line through (a|b) and (c|d) // the slope of the line through (a|b) and (c|d)
const double m = (q.y - p.y) / (q.x - p.x); const double m = (q.second - p.second) / (q.first - p.first);
// Projection of (x|y) onto the line joining (a|b) and (c|d). // Projection of (x|y) onto the line joining (a|b) and (c|d).
foot_x = ((r.x + (m*r.y)) + (m*m*p.x - m*p.y))/(1.0 + m*m); foot_x = ((r.first + (m*r.second)) + (m*m*p.first - m*p.second))/(1.0 + m*m);
foot_y = p.y + m*(foot_x - p.x); foot_y = p.second + m*(foot_x - p.first);
} }
return Point(foot_x, foot_y); return Point(foot_x, foot_y);
} }
// Compute the ratio of the line segment pr to line segment pq. // Compute the ratio of the line segment pr to line segment pq.
double ComputeRatio(const Point & p, const Point & q, const Point & r, double epsilon) const { double ComputeRatio(const Point & p, const Point & q, const Point & r, double epsilon) const {
const bool parallel_to_x_axis = std::abs(q.y-p.y) < epsilon; const bool is_parallel_to_x_axis = std::abs(q.second-p.second) < epsilon;
const bool parallel_to_y_axis = std::abs(q.x-p.x) < epsilon; const bool is_parallel_to_y_axis = std::abs(q.first-p.first) < epsilon;
double ratio; double ratio;
if( !parallel_to_y_axis ) { if( !is_parallel_to_y_axis ) {
ratio = (r.x - p.x)/(q.x - p.x); ratio = (r.first - p.first)/(q.first - p.first);
} else if( !parallel_to_x_axis ) { } else if( !is_parallel_to_x_axis ) {
ratio = (r.y - p.y)/(q.y - p.y); ratio = (r.second - p.second)/(q.second - p.second);
} else { } else {
// (a|b) and (c|d) are essentially the same point // (a|b) and (c|d) are essentially the same point
// by convention, we set the ratio to 0 in this case // by convention, we set the ratio to 0 in this case
//ratio = ((lat2 == query_location.lat) && (lon2 == query_location.lon)) ? 1. : 0.; //ratio = ((lat2 == query_location.lat) && (lon2 == query_location.lon)) ? 1. : 0.;
ratio = 0.0; ratio = 0.0;
} }
// Round to integer if the ratio is close to 0 or 1. // Round to integer if the ratio is close to 0 or 1.
if( std::abs(ratio) <= epsilon ) { if( std::abs(ratio) <= epsilon ) {
ratio = 0.0; ratio = 0.0;
} else if( std::abs(ratio-1.0) <= epsilon ) { } else if( std::abs(ratio-1.0) <= epsilon ) {
ratio = 1.0; ratio = 1.0;
} }
return ratio; return ratio;
} }
// Computes the point on the segment pq which is nearest to a point r = p + lambda * (q-p). // Computes the point on the segment pq which is nearest to a point r = p + lambda * (q-p).
// p and q are the end points of the underlying edge. // p and q are the end points of the underlying edge.
FixedPointCoordinate ComputeNearestPointOnSegment(const Point & r, double lambda) const { FixedPointCoordinate ComputeNearestPointOnSegment(const Point & r, double lambda) const {
if( lambda <= 0.0 ) { if( lambda <= 0.0 ) {
return FixedPointCoordinate(lat1, lon1); return FixedPointCoordinate(lat1, lon1);
} else if( lambda >= 1.0 ) { } else if( lambda >= 1.0 ) {
return FixedPointCoordinate(lat2, lon2); return FixedPointCoordinate(lat2, lon2);
} else { } else {
// r lies between p and q // r lies between p and q
return FixedPointCoordinate(y2lat(r.x)*COORDINATE_PRECISION, return FixedPointCoordinate(y2lat(r.first)*COORDINATE_PRECISION,
r.y*COORDINATE_PRECISION); r.second*COORDINATE_PRECISION);
} }
} }