removed libkdtree++ dependency.
This commit is contained in:
parent
92963ced1f
commit
ec0108553f
@ -78,7 +78,12 @@ inline NodeID readOSMRGraphFromStream(istream &in, vector<EdgeT>& edgeList, vect
|
||||
|
||||
// translate the external NodeIDs to internal IDs
|
||||
ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(source);
|
||||
if( intNodeID == ext2IntNodeMap.end()) { cerr << "unresolved source NodeID: " << source << endl; exit(0); }
|
||||
if( intNodeID == ext2IntNodeMap.end())
|
||||
{
|
||||
cerr << "after " << edgeList.size() << " edges" << endl;
|
||||
cerr << "->" << source << "," << target << "," << length << "," << dir << "," << weight << endl;
|
||||
cerr << "unresolved source NodeID: " << source << endl; exit(0);
|
||||
}
|
||||
source = intNodeID->second;
|
||||
intNodeID = ext2IntNodeMap.find(target);
|
||||
if(intNodeID == ext2IntNodeMap.end()) { cerr << "unresolved target NodeID : " << target << endl; exit(0); }
|
||||
|
@ -39,23 +39,23 @@ class SearchEngine {
|
||||
private:
|
||||
const GraphT * _graph;
|
||||
public:
|
||||
SearchEngine(GraphT * g, KDTST * k) : _graph(g), kdtree(k) {}
|
||||
SearchEngine(GraphT * g, KDTST * k) : _graph(g), nodeHelpDesk(k) {}
|
||||
~SearchEngine() {}
|
||||
|
||||
const NodeInfo& getNodeInfo(NodeID id) const
|
||||
const void getNodeInfo(NodeID id, NodeInfo * info) const
|
||||
{
|
||||
return kdtree->getExternalNodeInfo(id);
|
||||
nodeHelpDesk->getExternalNodeInfo(id, info);
|
||||
}
|
||||
|
||||
unsigned int numberOfNodes() const
|
||||
{
|
||||
return kdtree->getNumberOfNodes();
|
||||
return nodeHelpDesk->getNumberOfNodes();
|
||||
}
|
||||
|
||||
unsigned int ComputeRoute(NodeID start, NodeID target, vector<NodeID> * path)
|
||||
{
|
||||
_Heap * _forwardHeap = new _Heap(kdtree->getNumberOfNodes());
|
||||
_Heap * _backwardHeap = new _Heap(kdtree->getNumberOfNodes());
|
||||
_Heap * _forwardHeap = new _Heap(nodeHelpDesk->getNumberOfNodes());
|
||||
_Heap * _backwardHeap = new _Heap(nodeHelpDesk->getNumberOfNodes());
|
||||
NodeID middle = ( NodeID ) 0;
|
||||
unsigned int _upperbound = std::numeric_limits<unsigned int>::max();
|
||||
_forwardHeap->Insert(start, 0, start);
|
||||
@ -93,16 +93,10 @@ public:
|
||||
packedPath.push_back( pathNode );
|
||||
}
|
||||
|
||||
// for(deque<NodeID>::size_type i = 0; i < packedPath.size()-1; i++)
|
||||
// {
|
||||
// cout << packedPath[i] << endl;
|
||||
// }
|
||||
|
||||
// push start node explicitely
|
||||
path->push_back(packedPath[0]);
|
||||
for(deque<NodeID>::size_type i = 0; i < packedPath.size()-1; i++)
|
||||
{
|
||||
// path->push_back(*it);
|
||||
_UnpackEdge(packedPath[i], packedPath[i+1], path);
|
||||
}
|
||||
|
||||
@ -115,10 +109,10 @@ public:
|
||||
|
||||
unsigned int findNearestNodeForLatLon(const int lat, const int lon, NodeCoords<NodeID> * data) const
|
||||
{
|
||||
return kdtree->findNearestNodeIDForLatLon( lat, lon, data);
|
||||
return nodeHelpDesk->findNearestNodeIDForLatLon( lat, lon, data);
|
||||
}
|
||||
private:
|
||||
KDTST * kdtree;
|
||||
KDTST * nodeHelpDesk;
|
||||
|
||||
void _RoutingStep(_Heap * _forwardHeap, _Heap *_backwardHeap, const bool& forwardDirection, NodeID * middle, unsigned int * _upperbound)
|
||||
{
|
||||
@ -190,7 +184,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
assert(smallestWeight != SPECIAL_EDGEID);
|
||||
|
||||
const EdgeData ed = _graph->GetEdgeData(smallestEdge);
|
||||
|
@ -39,21 +39,21 @@ struct NodeCoords {
|
||||
|
||||
static NodeCoords<NodeT> min_value()
|
||||
{
|
||||
return NodeCoords<NodeT>(0,0,numeric_limits<NodeT>::min());
|
||||
return NodeCoords<NodeT>(-90*100000,-180*100000,numeric_limits<NodeT>::min());
|
||||
}
|
||||
static NodeCoords<NodeT> max_value()
|
||||
{
|
||||
return NodeCoords<NodeT>(numeric_limits<int>::max(), numeric_limits<int>::max(), numeric_limits<NodeT>::max());
|
||||
return NodeCoords<NodeT>(90*100000, 180*100000, numeric_limits<NodeT>::max());
|
||||
}
|
||||
|
||||
value_type operator[](size_t n) const
|
||||
{
|
||||
switch(n)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
return lat;
|
||||
break;
|
||||
case 1:
|
||||
case 0:
|
||||
return lon;
|
||||
break;
|
||||
default:
|
||||
@ -63,10 +63,4 @@ struct NodeCoords {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename NodeT>
|
||||
bool operator < (const NodeCoords<NodeT> & a, const NodeCoords<NodeT> & b)
|
||||
{
|
||||
return a.id < b.id;
|
||||
}
|
||||
#endif //_NODE_COORDS_H
|
||||
|
@ -37,19 +37,17 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
#include <vector>
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include "StaticKDTree.h"
|
||||
|
||||
#include <kdtree++/kdtree.hpp>
|
||||
|
||||
typedef KDTree::KDTree<2, NodeInfo > KDTreeType;
|
||||
typedef KDTree::StaticKDTree<2, int, NodeID> KDTreeType;
|
||||
|
||||
class NodeInformationHelpDesk{
|
||||
public:
|
||||
~NodeInformationHelpDesk();
|
||||
NodeInformationHelpDesk() { int2ExtNodeMap = new vector<KDTreeType::iterator>();}
|
||||
NodeInformationHelpDesk() { int2ExtNodeMap = new vector<KDTreeType::InputPoint>();}
|
||||
KDTreeType * initKDTree(ifstream& input);
|
||||
|
||||
NodeID getExternalNodeID(const NodeID node);
|
||||
const NodeInfo& getExternalNodeInfo(const NodeID node) const;
|
||||
void getExternalNodeInfo(const NodeID node, NodeInfo * info) const;
|
||||
int getLatitudeOfNode(const NodeID node) const;
|
||||
int getLongitudeOfNode(const NodeID node) const;
|
||||
|
||||
@ -57,15 +55,18 @@ public:
|
||||
|
||||
inline NodeID findNearestNodeIDForLatLon(const int lat, const int lon, NodeCoords<NodeID> * data) const
|
||||
{
|
||||
|
||||
NodeInfo nearestNeighbor = *(kdtree->find_nearest(NodeInfo(lat, lon, 0)).first);
|
||||
data->id = nearestNeighbor.id;
|
||||
data->lat = nearestNeighbor.lat;
|
||||
data->lon = nearestNeighbor.lon;
|
||||
KDTreeType::InputPoint i;
|
||||
KDTreeType::InputPoint o;
|
||||
i.coordinates[0] = lat;
|
||||
i.coordinates[1] = lon;
|
||||
kdtree->NearestNeighbor(&o, i);
|
||||
data->id = o.data;
|
||||
data->lat = o.coordinates[0];
|
||||
data->lon = o.coordinates[1];
|
||||
return data->id;
|
||||
}
|
||||
private:
|
||||
vector<KDTreeType::iterator> * int2ExtNodeMap;
|
||||
vector<KDTreeType::InputPoint> * int2ExtNodeMap;
|
||||
KDTreeType * kdtree;
|
||||
};
|
||||
|
||||
@ -73,52 +74,50 @@ private:
|
||||
//implementation//
|
||||
//////////////////
|
||||
|
||||
NodeInformationHelpDesk::~NodeInformationHelpDesk(){
|
||||
// delete graph;
|
||||
// delete calc;
|
||||
// delete c;
|
||||
}
|
||||
|
||||
/* @brief: initialize kd-tree and internal->external node id map
|
||||
*
|
||||
*/
|
||||
KDTreeType * NodeInformationHelpDesk::initKDTree(ifstream& in)
|
||||
{
|
||||
kdtree = new KDTreeType();
|
||||
NodeID id = 0;
|
||||
while(!in.eof())
|
||||
{
|
||||
NodeInfo b;
|
||||
in.read((char *)&b, sizeof(b));
|
||||
b.id = id;
|
||||
KDTreeType::iterator kdit = kdtree->insert(b);
|
||||
int2ExtNodeMap->push_back(kdit);
|
||||
KDTreeType::InputPoint p;
|
||||
p.coordinates[0] = b.lat;
|
||||
p.coordinates[1] = b.lon;
|
||||
p.data = id;
|
||||
int2ExtNodeMap->push_back(p);
|
||||
id++;
|
||||
}
|
||||
in.close();
|
||||
// kdtree->optimise();
|
||||
kdtree = new KDTreeType(int2ExtNodeMap);
|
||||
return kdtree;
|
||||
}
|
||||
|
||||
NodeID NodeInformationHelpDesk::getExternalNodeID(const NodeID node)
|
||||
{
|
||||
|
||||
return int2ExtNodeMap->at(node)->id;
|
||||
return int2ExtNodeMap->at(node).data;
|
||||
}
|
||||
|
||||
const NodeInfo& NodeInformationHelpDesk::getExternalNodeInfo(const NodeID node) const
|
||||
void NodeInformationHelpDesk::getExternalNodeInfo(const NodeID node, NodeInfo * info) const
|
||||
{
|
||||
return *(int2ExtNodeMap->at(node) );
|
||||
info->id = int2ExtNodeMap->at(node).data;
|
||||
info->lat = int2ExtNodeMap->at(node).coordinates[0];
|
||||
info->lon = int2ExtNodeMap->at(node).coordinates[1];
|
||||
}
|
||||
|
||||
int NodeInformationHelpDesk::getLatitudeOfNode(const NodeID node) const
|
||||
{
|
||||
return int2ExtNodeMap->at(node)->lat;
|
||||
return int2ExtNodeMap->at(node).coordinates[0];
|
||||
}
|
||||
|
||||
int NodeInformationHelpDesk::getLongitudeOfNode(const NodeID node) const
|
||||
{
|
||||
return int2ExtNodeMap->at(node)->lon;
|
||||
return int2ExtNodeMap->at(node).coordinates[1];
|
||||
}
|
||||
|
||||
#endif /*NODEINFORMATIONHELPDESK_H_*/
|
||||
|
212
DataStructures/StaticKDTree.h
Normal file
212
DataStructures/StaticKDTree.h
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
open source routing machine
|
||||
Copyright (C) Dennis Luxen, others 2010
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU AFFERO General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
or see http://www.gnu.org/licenses/agpl.txt.
|
||||
|
||||
KD Tree coded by Christian Vetter, Monav Project
|
||||
|
||||
*/
|
||||
#ifndef STATICKDTREE_H_INCLUDED
|
||||
#define STATICKDTREE_H_INCLUDED
|
||||
|
||||
#include <vector>
|
||||
#ifdef _GLIBCXX_PARALLEL
|
||||
#include <parallel/algorithm>
|
||||
#else
|
||||
#include <algorithm>
|
||||
#endif
|
||||
#include <stack>
|
||||
#include <limits>
|
||||
|
||||
namespace KDTree {
|
||||
|
||||
template< unsigned k, typename T >
|
||||
class BoundingBox {
|
||||
public:
|
||||
BoundingBox() {
|
||||
for ( unsigned dim = 0; dim < k; ++dim ) {
|
||||
min[dim] = std::numeric_limits< T >::min();
|
||||
max[dim] = std::numeric_limits< T >::max();
|
||||
}
|
||||
}
|
||||
|
||||
T min[k];
|
||||
T max[k];
|
||||
};
|
||||
|
||||
struct NoData {};
|
||||
|
||||
template< unsigned k, typename T >
|
||||
class EuclidianMetric {
|
||||
public:
|
||||
double operator() ( const T left[k], const T right[k] ) {
|
||||
double result = 0;
|
||||
for ( unsigned i = 0; i < k; ++i ) {
|
||||
double temp = (double)left[i] - (double)right[i];
|
||||
result += temp * temp;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
double operator() ( const BoundingBox< k, T > &box, const T point[k] ) {
|
||||
T nearest[k];
|
||||
for ( unsigned dim = 0; dim < k; ++dim ) {
|
||||
if ( point[dim] < box.min[dim] )
|
||||
nearest[dim] = box.min[dim];
|
||||
else if ( point[dim] > box.max[dim] )
|
||||
nearest[dim] = box.max[dim];
|
||||
else
|
||||
nearest[dim] = point[dim];
|
||||
}
|
||||
return operator() ( point, nearest );
|
||||
}
|
||||
};
|
||||
|
||||
template < unsigned k, typename T, typename Data = NoData, typename Metric = EuclidianMetric< k, T > >
|
||||
class StaticKDTree {
|
||||
public:
|
||||
|
||||
struct InputPoint {
|
||||
T coordinates[k];
|
||||
Data data;
|
||||
};
|
||||
|
||||
StaticKDTree( std::vector< InputPoint > * points ){
|
||||
assert( k > 0 );
|
||||
assert ( points->size() > 0 );
|
||||
size = points->size();
|
||||
kdtree = new InputPoint[size];
|
||||
for ( Iterator i = 0; i != size; ++i ) {
|
||||
kdtree[i] = points->at(i);
|
||||
for ( unsigned dim = 0; dim < k; ++dim ) {
|
||||
if ( kdtree[i].coordinates[dim] < boundingBox.min[dim] )
|
||||
boundingBox.min[dim] = kdtree[i].coordinates[dim];
|
||||
if ( kdtree[i].coordinates[dim] > boundingBox.max[dim] )
|
||||
boundingBox.max[dim] = kdtree[i].coordinates[dim];
|
||||
}
|
||||
}
|
||||
std::stack< Tree > s;
|
||||
s.push ( Tree ( 0, size, 0 ) );
|
||||
while ( !s.empty() ) {
|
||||
Tree tree = s.top();
|
||||
s.pop();
|
||||
|
||||
if ( tree.left == tree.right )
|
||||
continue;
|
||||
|
||||
Iterator middle = tree.left + ( tree.right - tree.left ) / 2;
|
||||
#ifdef _GLIBCXX_PARALLEL
|
||||
__gnu_parallel::nth_element( kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less( tree.dimension ) );
|
||||
#else
|
||||
std::nth_element( kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less( tree.dimension ) );
|
||||
#endif
|
||||
s.push( Tree( tree.left, middle, ( tree.dimension + 1 ) % k ) );
|
||||
s.push( Tree( middle + 1, tree.right, ( tree.dimension + 1 ) % k ) );
|
||||
}
|
||||
}
|
||||
|
||||
~StaticKDTree(){
|
||||
delete[] kdtree;
|
||||
}
|
||||
|
||||
bool NearestNeighbor( InputPoint* result, const InputPoint& point, double radius = std::numeric_limits< T >::max() ) {
|
||||
Metric distance;
|
||||
bool found = false;
|
||||
double nearestDistance = radius;
|
||||
std::stack< NNTree > s;
|
||||
s.push ( NNTree ( 0, size, 0, boundingBox ) );
|
||||
while ( !s.empty() ) {
|
||||
NNTree tree = s.top();
|
||||
s.pop();
|
||||
|
||||
if ( distance( tree.box, point.coordinates ) >= nearestDistance )
|
||||
continue;
|
||||
|
||||
if ( tree.left == tree.right )
|
||||
continue;
|
||||
|
||||
Iterator middle = tree.left + ( tree.right - tree.left ) / 2;
|
||||
|
||||
double newDistance = distance( kdtree[middle].coordinates, point.coordinates );
|
||||
if ( newDistance < nearestDistance ) {
|
||||
nearestDistance = newDistance;
|
||||
*result = kdtree[middle];
|
||||
found = true;
|
||||
}
|
||||
|
||||
Less comperator( tree.dimension );
|
||||
if ( !comperator( point, kdtree[middle] ) ) {
|
||||
NNTree first( middle + 1, tree.right, ( tree.dimension + 1 ) % k, tree.box );
|
||||
NNTree second( tree.left, middle, ( tree.dimension + 1 ) % k, tree.box );
|
||||
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||
s.push( second );
|
||||
s.push( first );
|
||||
}
|
||||
else {
|
||||
NNTree first( middle + 1, tree.right, ( tree.dimension + 1 ) % k, tree.box );
|
||||
NNTree second( tree.left, middle, ( tree.dimension + 1 ) % k, tree.box );
|
||||
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||
s.push( first );
|
||||
s.push( second );
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef unsigned Iterator;
|
||||
struct Tree {
|
||||
Iterator left;
|
||||
Iterator right;
|
||||
unsigned dimension;
|
||||
Tree() {}
|
||||
Tree( Iterator l, Iterator r, unsigned d ): left( l ), right( r ), dimension( d ) {}
|
||||
};
|
||||
struct NNTree {
|
||||
Iterator left;
|
||||
Iterator right;
|
||||
unsigned dimension;
|
||||
BoundingBox< k, T > box;
|
||||
NNTree() {}
|
||||
NNTree( Iterator l, Iterator r, unsigned d, const BoundingBox< k, T >& b ): left( l ), right( r ), dimension( d ), box ( b ) {}
|
||||
};
|
||||
class Less {
|
||||
public:
|
||||
Less( unsigned d ) {
|
||||
dimension = d;
|
||||
assert( dimension < k );
|
||||
}
|
||||
|
||||
bool operator() ( const InputPoint& left, const InputPoint& right ) {
|
||||
assert( dimension < k );
|
||||
return left.coordinates[dimension] < right.coordinates[dimension];
|
||||
}
|
||||
private:
|
||||
unsigned dimension;
|
||||
};
|
||||
|
||||
BoundingBox< k, T > boundingBox;
|
||||
InputPoint* kdtree;
|
||||
Iterator size;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // STATICKDTREE_H_INCLUDED
|
@ -1,6 +1,6 @@
|
||||
Third Party Libraries:
|
||||
|
||||
Scons 1.3+
|
||||
Boost 1.37+
|
||||
kdtree++ 0.7+ (0.62 does not work with g++ 4.0+)
|
||||
sparsehash 1.4+
|
||||
stxxl 1.2.1+
|
@ -5,6 +5,4 @@ Start/Endpoints of queries can only start on nodes only. Instead of selecting th
|
||||
|
||||
The server part is mostly adapted from the boost http examples. It should be replaced with a self-written front-end
|
||||
|
||||
The KD-Tree uses a lot of RAM. An own implementation might be better.
|
||||
|
||||
Use Boost to compress all in-/output streams to the file system
|
||||
|
@ -126,14 +126,16 @@ public:
|
||||
rep.content.append("<coordinates>\n");
|
||||
if(distance != std::numeric_limits<unsigned int>::max())
|
||||
{ //A route has been found
|
||||
NodeInfo * info = new NodeInfo();
|
||||
for(vector<NodeID>::iterator it = path->begin(); it != path->end(); it++)
|
||||
{
|
||||
NodeInfo info = sEngine-> getNodeInfo(*it);
|
||||
sEngine-> getNodeInfo(*it, info);
|
||||
stringstream nodeout;
|
||||
nodeout << std::setprecision(10);
|
||||
nodeout << info.lon/100000. << "," << info.lat/100000. << " " << endl;
|
||||
nodeout << info->lon/100000. << "," << info->lat/100000. << " " << endl;
|
||||
rep.content.append(nodeout.str());
|
||||
}
|
||||
delete info;
|
||||
}
|
||||
rep.content.append("</coordinates>");
|
||||
rep.content.append("</LineString>");
|
||||
@ -164,7 +166,6 @@ private:
|
||||
//SearchEngine object that is queried
|
||||
SearchEngine<EdgeData, GraphT> * sEngine;
|
||||
};
|
||||
|
||||
} // namespace ROUTER
|
||||
}
|
||||
|
||||
#endif // HTTP_ROUTER_REQUEST_HANDLER_HPP
|
||||
|
Loading…
Reference in New Issue
Block a user