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