first segment needs to be properly cut

This commit is contained in:
Dennis Luxen
2014-02-26 15:55:04 +01:00
parent 5bde545ce3
commit b679a94930
14 changed files with 435 additions and 256 deletions
+10
View File
@@ -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;
+62 -50
View File
@@ -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;
+9 -2
View File
@@ -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 {
+2 -4
View File
@@ -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");
+62 -29
View File
@@ -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;
}