osrm-backend/DataStructures/EdgeBasedNode.h

161 lines
5.9 KiB
C
Raw Normal View History

#ifndef EDGE_BASED_NODE_H
#define EDGE_BASED_NODE_H
#include "../Util/MercatorUtil.h"
2014-04-24 12:13:50 -04:00
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
2013-12-20 07:12:56 -05:00
#include <osrm/Coordinate.h>
2014-04-24 12:13:50 -04:00
#include <boost/assert.hpp>
2014-02-11 05:42:24 -05:00
#include <limits>
struct EdgeBasedNode {
EdgeBasedNode() :
2014-02-26 09:55:04 -05:00
forward_edge_based_node_id(SPECIAL_NODEID),
reverse_edge_based_node_id(SPECIAL_NODEID),
u(SPECIAL_NODEID),
v(SPECIAL_NODEID),
name_id(0),
2014-02-28 11:14:38 -05:00
forward_weight(INVALID_EDGE_WEIGHT >> 1),
reverse_weight(INVALID_EDGE_WEIGHT >> 1),
forward_offset(0),
2014-02-26 09:55:04 -05:00
reverse_offset(0),
2014-02-28 11:14:38 -05:00
packed_geometry_id(SPECIAL_EDGEID),
2014-02-26 09:55:04 -05:00
fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
2014-02-28 11:14:38 -05:00
belongsToTinyComponent(false)
2014-02-11 05:42:24 -05:00
{ }
2014-02-27 13:49:53 -05:00
explicit EdgeBasedNode(
2014-02-11 05:42:24 -05:00
NodeID forward_edge_based_node_id,
NodeID reverse_edge_based_node_id,
2014-02-26 09:55:04 -05:00
NodeID u,
NodeID v,
unsigned name_id,
2014-02-11 05:42:24 -05:00
int forward_weight,
int reverse_weight,
int forward_offset,
2014-02-26 09:55:04 -05:00
int reverse_offset,
2014-02-28 11:14:38 -05:00
unsigned packed_geometry_id,
2014-02-26 09:55:04 -05:00
unsigned short fwd_segment_position,
2014-02-28 11:14:38 -05:00
bool belongs_to_tiny_component
2014-02-11 05:42:24 -05:00
) :
forward_edge_based_node_id(forward_edge_based_node_id),
reverse_edge_based_node_id(reverse_edge_based_node_id),
2014-02-26 09:55:04 -05:00
u(u),
v(v),
2014-02-11 05:42:24 -05:00
name_id(name_id),
forward_weight(forward_weight),
reverse_weight(reverse_weight),
forward_offset(forward_offset),
2014-02-26 09:55:04 -05:00
reverse_offset(reverse_offset),
2014-02-28 11:14:38 -05:00
packed_geometry_id(packed_geometry_id),
2014-02-26 09:55:04 -05:00
fwd_segment_position(fwd_segment_position),
2014-02-28 11:14:38 -05:00
belongsToTinyComponent(belongs_to_tiny_component)
2014-02-27 13:49:53 -05:00
{
BOOST_ASSERT(
( forward_edge_based_node_id != SPECIAL_NODEID ) ||
( reverse_edge_based_node_id != SPECIAL_NODEID )
);
}
2014-02-26 09:55:04 -05:00
inline static double ComputePerpendicularDistance(
const FixedPointCoordinate & coord_a,
const FixedPointCoordinate & coord_b,
const FixedPointCoordinate & query_location,
FixedPointCoordinate & nearest_location,
2014-02-26 09:55:04 -05:00
double & r
) {
2014-01-08 11:18:59 -05:00
BOOST_ASSERT( query_location.isValid() );
2014-04-24 12:13:50 -04:00
const double x = lat2y(query_location.lat/COORDINATE_PRECISION);
2014-02-11 05:42:24 -05:00
const double y = query_location.lon/COORDINATE_PRECISION;
2014-02-26 09:55:04 -05:00
const double a = lat2y(coord_a.lat/COORDINATE_PRECISION);
const double b = coord_a.lon/COORDINATE_PRECISION;
const double c = lat2y(coord_b.lat/COORDINATE_PRECISION);
const double d = coord_b.lon/COORDINATE_PRECISION;
2014-02-11 05:42:24 -05:00
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);
2014-02-11 05:42:24 -05:00
//discretize the result to coordinate precision. it's a hack!
if( std::abs(nY) < (1./COORDINATE_PRECISION) ) {
nY = 0.;
}
2014-04-24 12:13:50 -04:00
r = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we need
// not calculate the explicit values of m an n as we
// are just interested in the ratio
2014-02-26 09:55:04 -05:00
if( std::isnan(r) ) {
r = ((coord_b.lat == query_location.lat) && (coord_b.lon == query_location.lon)) ? 1. : 0.;
2014-04-24 12:13:50 -04:00
} else if( std::abs(r) <= std::numeric_limits<double>::epsilon() ) {
r = 0.;
2014-02-11 05:42:24 -05:00
} else if( std::abs(r-1.) <= std::numeric_limits<double>::epsilon() ) {
2014-04-24 12:13:50 -04:00
r = 1.;
}
BOOST_ASSERT( !std::isnan(r) );
if( r <= 0. ){
2014-02-26 09:55:04 -05:00
nearest_location.lat = coord_a.lat;
nearest_location.lon = coord_a.lon;
} else if( r >= 1. ){
nearest_location.lat = coord_b.lat;
nearest_location.lon = coord_b.lon;
} else {
// point lies in between
2014-02-11 05:42:24 -05:00
nearest_location.lat = y2lat(p)*COORDINATE_PRECISION;
2014-04-24 12:13:50 -04:00
nearest_location.lon = q*COORDINATE_PRECISION;
}
BOOST_ASSERT( nearest_location.isValid() );
// TODO: Replace with euclidean approximation when k-NN search is done
// const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
2014-04-24 12:13:50 -04:00
const double approximated_distance = FixedPointCoordinate::ApproximateDistance(
2014-02-11 05:42:24 -05:00
query_location,
nearest_location
);
2014-04-24 12:13:50 -04:00
BOOST_ASSERT( 0. <= approximated_distance );
return approximated_distance;
}
2014-02-26 09:55:04 -05:00
static inline FixedPointCoordinate Centroid(
const FixedPointCoordinate & a,
const FixedPointCoordinate & b
) {
2014-04-24 12:13:50 -04:00
FixedPointCoordinate centroid;
2014-02-26 09:55:04 -05:00
//The coordinates of the midpoint are given by:
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
centroid.lon = (std::min(a.lon, b.lon) + std::max(a.lon, b.lon))/2;
centroid.lat = (std::min(a.lat, b.lat) + std::max(a.lat, b.lat))/2;
return centroid;
}
2014-02-26 09:55:04 -05:00
bool IsCompressed() {
2014-02-28 11:14:38 -05:00
return packed_geometry_id != SPECIAL_EDGEID;
}
2014-04-24 12:13:50 -04:00
NodeID forward_edge_based_node_id; // needed for edge-expanded graph
2014-02-28 11:14:38 -05:00
NodeID reverse_edge_based_node_id; // needed for edge-expanded graph
2014-04-24 12:13:50 -04:00
NodeID u; // indices into the coordinates array
NodeID v; // indices into the coordinates array
unsigned name_id; // id of the edge name
int forward_weight; // weight of the edge
int reverse_weight; // weight in the other direction (may be different)
int forward_offset; // prefix sum of the weight up the edge TODO: short must suffice
int reverse_offset; // prefix sum of the weight from the edge TODO: short must suffice
unsigned packed_geometry_id; // if set, then the edge represents a packed geometry
unsigned short fwd_segment_position; // segment id in a compressed geometry
bool belongsToTinyComponent;
};
#endif //EDGE_BASED_NODE_H