first segment needs to be properly cut
This commit is contained in:
@@ -96,6 +96,11 @@ public:
|
||||
return nodes[node];
|
||||
}
|
||||
|
||||
Key const & operator[]( const NodeID node ) const {
|
||||
UnorderedMapConstIterator iter = nodes.find(node);
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
nodes.clear();
|
||||
}
|
||||
@@ -158,6 +163,11 @@ public:
|
||||
return insertedNodes[index].data;
|
||||
}
|
||||
|
||||
Data const & GetData( NodeID node ) const {
|
||||
const Key index = nodeIndex[node];
|
||||
return insertedNodes[index].data;
|
||||
}
|
||||
|
||||
Weight& GetKey( NodeID node ) {
|
||||
const Key index = nodeIndex[node];
|
||||
return insertedNodes[index].weight;
|
||||
|
||||
@@ -13,67 +13,66 @@
|
||||
struct EdgeBasedNode {
|
||||
|
||||
EdgeBasedNode() :
|
||||
id(INT_MAX),
|
||||
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_edge_based_node_id(SPECIAL_NODEID),
|
||||
reverse_edge_based_node_id(SPECIAL_NODEID),
|
||||
u(SPECIAL_NODEID),
|
||||
v(SPECIAL_NODEID),
|
||||
name_id(0),
|
||||
forward_weight(std::numeric_limits<int>::max() >> 1),
|
||||
reverse_weight(std::numeric_limits<int>::max() >> 1),
|
||||
forward_offset(0),
|
||||
reverse_offset(0)
|
||||
reverse_offset(0),
|
||||
fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
|
||||
rev_segment_position( std::numeric_limits<unsigned short>::max() >> 1 ),
|
||||
belongsToTinyComponent(false)
|
||||
{ }
|
||||
|
||||
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,
|
||||
NodeID u,
|
||||
NodeID v,
|
||||
unsigned name_id,
|
||||
int forward_weight,
|
||||
int reverse_weight,
|
||||
int forward_offset,
|
||||
int reverse_offset
|
||||
int reverse_offset,
|
||||
unsigned short fwd_segment_position,
|
||||
unsigned short rev_segment_position,
|
||||
bool belongsToTinyComponent
|
||||
) :
|
||||
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),
|
||||
u(u),
|
||||
v(v),
|
||||
name_id(name_id),
|
||||
forward_weight(forward_weight),
|
||||
reverse_weight(reverse_weight),
|
||||
forward_offset(forward_offset),
|
||||
reverse_offset(reverse_offset)
|
||||
reverse_offset(reverse_offset),
|
||||
fwd_segment_position(fwd_segment_position),
|
||||
rev_segment_position(rev_segment_position),
|
||||
belongsToTinyComponent(belongsToTinyComponent)
|
||||
{ }
|
||||
|
||||
// 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
|
||||
inline static double ComputePerpendicularDistance(
|
||||
const FixedPointCoordinate & coord_a,
|
||||
const FixedPointCoordinate & coord_b,
|
||||
// the query location on the line defined by p and q.
|
||||
double ComputePerpendicularDistance(
|
||||
const FixedPointCoordinate& query_location,
|
||||
const FixedPointCoordinate & query_location,
|
||||
FixedPointCoordinate & nearest_location,
|
||||
double & ratio,
|
||||
double precision = COORDINATE_PRECISION
|
||||
) const {
|
||||
double & r
|
||||
) {
|
||||
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;
|
||||
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;
|
||||
double p,q/*,mX*/,nY;
|
||||
if( std::abs(a-c) > std::numeric_limits<double>::epsilon() ){
|
||||
const double m = (d-b)/(c-a); // slope
|
||||
@@ -92,18 +91,20 @@ struct EdgeBasedNode {
|
||||
}
|
||||
|
||||
// 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);
|
||||
if( std::isnan(r) ) {
|
||||
r = ((coord_b.lat == query_location.lat) && (coord_b.lon == query_location.lon)) ? 1. : 0.;
|
||||
|
||||
// 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 = 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
|
||||
nearest_location.lat = y2lat(p)*COORDINATE_PRECISION;
|
||||
nearest_location = ComputeNearestPointOnSegment(foot, ratio);
|
||||
|
||||
@@ -120,12 +121,20 @@ struct EdgeBasedNode {
|
||||
return approximated_distance;
|
||||
}
|
||||
|
||||
bool operator<(const EdgeBasedNode & other) const {
|
||||
static inline FixedPointCoordinate Centroid(
|
||||
const FixedPointCoordinate & a,
|
||||
const FixedPointCoordinate & b
|
||||
) {
|
||||
return other.id < id;
|
||||
//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;
|
||||
}
|
||||
|
||||
bool operator==(const EdgeBasedNode & other) const {
|
||||
return id == other.id;
|
||||
bool IsCompressed() {
|
||||
return (fwd_segment_position + rev_segment_position) != 0;
|
||||
}
|
||||
|
||||
// Returns the midpoint of the underlying edge.
|
||||
@@ -134,13 +143,16 @@ struct EdgeBasedNode {
|
||||
}
|
||||
|
||||
NodeID forward_edge_based_node_id;
|
||||
|
||||
// The coordinates of the end-points of the underlying edge.
|
||||
int lat1;
|
||||
int lon1;
|
||||
int lat2;
|
||||
int lon2:31;
|
||||
|
||||
NodeID reverse_edge_based_node_id;
|
||||
NodeID u;
|
||||
NodeID v;
|
||||
unsigned name_id;
|
||||
int forward_weight;
|
||||
int reverse_weight;
|
||||
int forward_offset;
|
||||
int reverse_offset;
|
||||
unsigned short fwd_segment_position;
|
||||
unsigned short rev_segment_position:15;
|
||||
bool belongsToTinyComponent:1;
|
||||
NodeID name_id;
|
||||
|
||||
|
||||
@@ -40,7 +40,9 @@ struct PhantomNode {
|
||||
reverse_weight(INVALID_EDGE_WEIGHT),
|
||||
forward_offset(0),
|
||||
reverse_offset(0),
|
||||
ratio(0.)
|
||||
ratio(0.),
|
||||
fwd_segment_position(0),
|
||||
rev_segment_position(0)
|
||||
{ }
|
||||
|
||||
NodeID forward_node_id;
|
||||
@@ -52,6 +54,9 @@ struct PhantomNode {
|
||||
int reverse_offset;
|
||||
double ratio;
|
||||
FixedPointCoordinate location;
|
||||
unsigned short fwd_segment_position;
|
||||
unsigned short rev_segment_position;
|
||||
|
||||
|
||||
int GetForwardWeightPlusOffset() const {
|
||||
return forward_weight + forward_offset;
|
||||
@@ -108,8 +113,10 @@ struct PhantomNodes {
|
||||
return (startPhantom.forward_node_id == targetPhantom.forward_node_id);
|
||||
}
|
||||
|
||||
|
||||
//TODO: Rename to: BothPhantomNodesAreInvalid
|
||||
bool AtLeastOnePhantomNodeIsUINTMAX() const {
|
||||
return !(startPhantom.forward_node_id == SPECIAL_NODEID || targetPhantom.forward_node_id == SPECIAL_NODEID);
|
||||
return (startPhantom.forward_node_id == SPECIAL_NODEID) && (targetPhantom.forward_node_id == SPECIAL_NODEID);
|
||||
}
|
||||
|
||||
bool PhantomNodesHaveEqualLocation() const {
|
||||
|
||||
@@ -72,13 +72,11 @@ struct NodeInfo {
|
||||
switch(n) {
|
||||
case 1:
|
||||
return lat;
|
||||
break;
|
||||
// break;
|
||||
case 0:
|
||||
return lon;
|
||||
break;
|
||||
// break;
|
||||
default:
|
||||
BOOST_ASSERT_MSG(false, "should not happen");
|
||||
return std::numeric_limits<unsigned>::max();
|
||||
break;
|
||||
}
|
||||
BOOST_ASSERT_MSG(false, "should not happen");
|
||||
|
||||
@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "DeallocatingVector.h"
|
||||
#include "HilbertValue.h"
|
||||
#include "PhantomNodes.h"
|
||||
#include "QueryNode.h"
|
||||
#include "SharedMemoryFactory.h"
|
||||
#include "SharedMemoryVectorWrapper.h"
|
||||
|
||||
@@ -84,21 +85,34 @@ public:
|
||||
|
||||
inline void InitializeMBRectangle(
|
||||
DataT const * objects,
|
||||
const uint32_t element_count
|
||||
const uint32_t element_count,
|
||||
const std::vector<NodeInfo> & coordinate_list
|
||||
) {
|
||||
for(uint32_t i = 0; i < element_count; ++i) {
|
||||
min_lon = std::min(
|
||||
min_lon, std::min(objects[i].lon1, objects[i].lon2)
|
||||
min_lon, std::min(
|
||||
coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon
|
||||
)
|
||||
);
|
||||
max_lon = std::max(
|
||||
max_lon, std::max(objects[i].lon1, objects[i].lon2)
|
||||
max_lon, std::max(
|
||||
coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon
|
||||
)
|
||||
);
|
||||
|
||||
min_lat = std::min(
|
||||
min_lat, std::min(objects[i].lat1, objects[i].lat2)
|
||||
min_lat, std::min(
|
||||
coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lon
|
||||
)
|
||||
);
|
||||
max_lat = std::max(
|
||||
max_lat, std::max(objects[i].lat1, objects[i].lat2)
|
||||
max_lat, std::max(
|
||||
coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lon
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -298,14 +312,15 @@ public:
|
||||
explicit StaticRTree(
|
||||
std::vector<DataT> & input_data_vector,
|
||||
const std::string tree_node_filename,
|
||||
const std::string leaf_node_filename
|
||||
const std::string leaf_node_filename,
|
||||
const std::vector<NodeInfo> & coordinate_list
|
||||
)
|
||||
: m_element_count(input_data_vector.size()),
|
||||
m_leaf_node_filename(leaf_node_filename)
|
||||
{
|
||||
SimpleLogger().Write() <<
|
||||
"constructing r-tree of " << m_element_count <<
|
||||
" elements";
|
||||
" edge elements build on-top of " << coordinate_list.size() << " coordinates";
|
||||
|
||||
double time1 = get_timestamp();
|
||||
std::vector<WrappedInputElement> input_wrapper_vector(m_element_count);
|
||||
@@ -318,7 +333,16 @@ public:
|
||||
input_wrapper_vector[element_counter].m_array_index = element_counter;
|
||||
//Get Hilbert-Value for centroid in mercartor projection
|
||||
DataT const & current_element = input_data_vector[element_counter];
|
||||
FixedPointCoordinate current_centroid = current_element.Centroid();
|
||||
FixedPointCoordinate current_centroid = DataT::Centroid(
|
||||
FixedPointCoordinate(
|
||||
coordinate_list.at(current_element.u).lat,
|
||||
coordinate_list.at(current_element.u).lon
|
||||
),
|
||||
FixedPointCoordinate(
|
||||
coordinate_list.at(current_element.v).lat,
|
||||
coordinate_list.at(current_element.v).lon
|
||||
)
|
||||
);
|
||||
current_centroid.lat = COORDINATE_PRECISION*lat2y(current_centroid.lat/COORDINATE_PRECISION);
|
||||
|
||||
uint64_t current_hilbert_value = get_hilbert_number(current_centroid);
|
||||
@@ -349,7 +373,11 @@ public:
|
||||
}
|
||||
|
||||
//generate tree node that resemble the objects in leaf and store it for next level
|
||||
current_node.minimum_bounding_rectangle.InitializeMBRectangle(current_leaf.objects, current_leaf.object_count);
|
||||
current_node.minimum_bounding_rectangle.InitializeMBRectangle(
|
||||
current_leaf.objects,
|
||||
current_leaf.object_count,
|
||||
coordinate_list
|
||||
);
|
||||
current_node.child_is_on_disk = true;
|
||||
current_node.children[0] = tree_nodes_in_level.size();
|
||||
tree_nodes_in_level.push_back(current_node);
|
||||
@@ -543,29 +571,29 @@ public:
|
||||
double current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
|
||||
input_coordinate.lat,
|
||||
input_coordinate.lon,
|
||||
current_edge.lat1,
|
||||
current_edge.lon1
|
||||
m_coordinate_list->at(current_edge.u).lat,
|
||||
m_coordinate_list->at(current_edge.u).lon
|
||||
);
|
||||
if( current_minimum_distance < min_dist ) {
|
||||
//found a new minimum
|
||||
min_dist = current_minimum_distance;
|
||||
result_coordinate.lat = current_edge.lat1;
|
||||
result_coordinate.lon = current_edge.lon1;
|
||||
result_coordinate.lat = m_coordinate_list->at(current_edge.u).lat;
|
||||
result_coordinate.lon = m_coordinate_list->at(current_edge.u).lon;
|
||||
found_a_nearest_edge = true;
|
||||
}
|
||||
|
||||
current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
|
||||
input_coordinate.lat,
|
||||
input_coordinate.lon,
|
||||
current_edge.lat2,
|
||||
current_edge.lon2
|
||||
m_coordinate_list->at(current_edge.v).lat,
|
||||
m_coordinate_list->at(current_edge.v).lon
|
||||
);
|
||||
|
||||
if( current_minimum_distance < min_dist ) {
|
||||
//found a new minimum
|
||||
min_dist = current_minimum_distance;
|
||||
result_coordinate.lat = current_edge.lat2;
|
||||
result_coordinate.lon = current_edge.lon2;
|
||||
result_coordinate.lat = m_coordinate_list->at(current_edge.v).lat;
|
||||
result_coordinate.lon = m_coordinate_list->at(current_edge.v).lon;
|
||||
found_a_nearest_edge = true;
|
||||
}
|
||||
}
|
||||
@@ -645,6 +673,8 @@ public:
|
||||
|
||||
double current_ratio = 0.;
|
||||
double current_perpendicular_distance = current_edge.ComputePerpendicularDistance(
|
||||
m_coordinate_list->at(current_edge.u),
|
||||
m_coordinate_list->at(current_edge.v),
|
||||
input_coordinate,
|
||||
nearest,
|
||||
current_ratio
|
||||
@@ -653,25 +683,27 @@ public:
|
||||
BOOST_ASSERT( 0. <= current_perpendicular_distance );
|
||||
|
||||
if(
|
||||
( current_perpendicular_distance < min_dist ) &&
|
||||
!DoubleEpsilonCompare(
|
||||
current_perpendicular_distance,
|
||||
min_dist
|
||||
)
|
||||
( current_perpendicular_distance < min_dist ) //&&
|
||||
// !DoubleEpsilonCompare(
|
||||
// current_perpendicular_distance,
|
||||
// min_dist
|
||||
// )
|
||||
) { //found a new minimum
|
||||
min_dist = current_perpendicular_distance;
|
||||
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.forward_offset = current_edge.forward_offset;
|
||||
result_phantom_node.reverse_offset = current_edge.reverse_offset;
|
||||
result_phantom_node.fwd_segment_position = current_edge.fwd_segment_position;
|
||||
result_phantom_node.rev_segment_position = current_edge.rev_segment_position;
|
||||
result_phantom_node.name_id = current_edge.name_id;
|
||||
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;
|
||||
current_start_coordinate.lat = m_coordinate_list->at(current_edge.u).lat;
|
||||
current_start_coordinate.lon = m_coordinate_list->at(current_edge.u).lon;
|
||||
current_end_coordinate.lat = m_coordinate_list->at(current_edge.v).lat;
|
||||
current_end_coordinate.lon = m_coordinate_list->at(current_edge.v).lon;
|
||||
nearest_edge = current_edge;
|
||||
found_a_nearest_edge = true;
|
||||
}
|
||||
@@ -730,10 +762,11 @@ public:
|
||||
}
|
||||
result_phantom_node.ratio = ratio;
|
||||
|
||||
SimpleLogger().Write(logDEBUG) << "result location: " << result_phantom_node.location;
|
||||
SimpleLogger().Write(logDEBUG) << "result location: " << result_phantom_node.location << ", start: " << current_start_coordinate << ", end: " << current_end_coordinate;
|
||||
SimpleLogger().Write(logDEBUG) << "fwd node: " << result_phantom_node.forward_node_id << ", rev node: " << result_phantom_node.reverse_node_id;
|
||||
SimpleLogger().Write(logDEBUG) << "fwd weight: " << result_phantom_node.forward_weight << ", rev weight: " << result_phantom_node.reverse_weight << ", ratio: " << result_phantom_node.ratio;
|
||||
|
||||
SimpleLogger().Write(logDEBUG) << "bidirected: " << (result_phantom_node.isBidirected() ? "y" : "n");
|
||||
SimpleLogger().Write(logDEBUG) << "name id: " << result_phantom_node.name_id;
|
||||
|
||||
return found_a_nearest_edge;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user