removed libkdtree++ dependency.

This commit is contained in:
Dennis Luxen 2010-07-26 08:17:52 +00:00
parent 92963ced1f
commit ec0108553f
8 changed files with 283 additions and 81 deletions

View File

@ -78,7 +78,12 @@ inline NodeID readOSMRGraphFromStream(istream &in, vector<EdgeT>& edgeList, vect
// translate the external NodeIDs to internal IDs // translate the external NodeIDs to internal IDs
ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(source); 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; source = intNodeID->second;
intNodeID = ext2IntNodeMap.find(target); intNodeID = ext2IntNodeMap.find(target);
if(intNodeID == ext2IntNodeMap.end()) { cerr << "unresolved target NodeID : " << target << endl; exit(0); } if(intNodeID == ext2IntNodeMap.end()) { cerr << "unresolved target NodeID : " << target << endl; exit(0); }

View File

@ -39,23 +39,23 @@ class SearchEngine {
private: private:
const GraphT * _graph; const GraphT * _graph;
public: public:
SearchEngine(GraphT * g, KDTST * k) : _graph(g), kdtree(k) {} SearchEngine(GraphT * g, KDTST * k) : _graph(g), nodeHelpDesk(k) {}
~SearchEngine() {} ~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 unsigned int numberOfNodes() const
{ {
return kdtree->getNumberOfNodes(); return nodeHelpDesk->getNumberOfNodes();
} }
unsigned int ComputeRoute(NodeID start, NodeID target, vector<NodeID> * path) unsigned int ComputeRoute(NodeID start, NodeID target, vector<NodeID> * path)
{ {
_Heap * _forwardHeap = new _Heap(kdtree->getNumberOfNodes()); _Heap * _forwardHeap = new _Heap(nodeHelpDesk->getNumberOfNodes());
_Heap * _backwardHeap = new _Heap(kdtree->getNumberOfNodes()); _Heap * _backwardHeap = new _Heap(nodeHelpDesk->getNumberOfNodes());
NodeID middle = ( NodeID ) 0; NodeID middle = ( NodeID ) 0;
unsigned int _upperbound = std::numeric_limits<unsigned int>::max(); unsigned int _upperbound = std::numeric_limits<unsigned int>::max();
_forwardHeap->Insert(start, 0, start); _forwardHeap->Insert(start, 0, start);
@ -93,16 +93,10 @@ public:
packedPath.push_back( pathNode ); packedPath.push_back( pathNode );
} }
// for(deque<NodeID>::size_type i = 0; i < packedPath.size()-1; i++)
// {
// cout << packedPath[i] << endl;
// }
// push start node explicitely // push start node explicitely
path->push_back(packedPath[0]); path->push_back(packedPath[0]);
for(deque<NodeID>::size_type i = 0; i < packedPath.size()-1; i++) for(deque<NodeID>::size_type i = 0; i < packedPath.size()-1; i++)
{ {
// path->push_back(*it);
_UnpackEdge(packedPath[i], packedPath[i+1], path); _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 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: private:
KDTST * kdtree; KDTST * nodeHelpDesk;
void _RoutingStep(_Heap * _forwardHeap, _Heap *_backwardHeap, const bool& forwardDirection, NodeID * middle, unsigned int * _upperbound) void _RoutingStep(_Heap * _forwardHeap, _Heap *_backwardHeap, const bool& forwardDirection, NodeID * middle, unsigned int * _upperbound)
{ {
@ -190,7 +184,6 @@ private:
} }
} }
assert(smallestWeight != SPECIAL_EDGEID); assert(smallestWeight != SPECIAL_EDGEID);
const EdgeData ed = _graph->GetEdgeData(smallestEdge); const EdgeData ed = _graph->GetEdgeData(smallestEdge);

View File

@ -39,21 +39,21 @@ struct NodeCoords {
static NodeCoords<NodeT> min_value() 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() 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 value_type operator[](size_t n) const
{ {
switch(n) switch(n)
{ {
case 0: case 1:
return lat; return lat;
break; break;
case 1: case 0:
return lon; return lon;
break; break;
default: 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 #endif //_NODE_COORDS_H

View File

@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt. or see http://www.gnu.org/licenses/agpl.txt.
*/ */
#ifndef NODEINFORMATIONHELPDESK_H_ #ifndef NODEINFORMATIONHELPDESK_H_
#define NODEINFORMATIONHELPDESK_H_ #define NODEINFORMATIONHELPDESK_H_
@ -37,88 +37,87 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <vector> #include <vector>
#include "../typedefs.h" #include "../typedefs.h"
#include "StaticKDTree.h"
#include <kdtree++/kdtree.hpp> typedef KDTree::StaticKDTree<2, int, NodeID> KDTreeType;
typedef KDTree::KDTree<2, NodeInfo > KDTreeType;
class NodeInformationHelpDesk{ class NodeInformationHelpDesk{
public: public:
~NodeInformationHelpDesk(); NodeInformationHelpDesk() { int2ExtNodeMap = new vector<KDTreeType::InputPoint>();}
NodeInformationHelpDesk() { int2ExtNodeMap = new vector<KDTreeType::iterator>();} KDTreeType * initKDTree(ifstream& input);
KDTreeType * initKDTree(ifstream& input);
NodeID getExternalNodeID(const NodeID node); 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 getLatitudeOfNode(const NodeID node) const;
int getLongitudeOfNode(const NodeID node) const; int getLongitudeOfNode(const NodeID node) const;
NodeID getNumberOfNodes() const { return int2ExtNodeMap->size(); } NodeID getNumberOfNodes() const { return int2ExtNodeMap->size(); }
inline NodeID findNearestNodeIDForLatLon(const int lat, const int lon, NodeCoords<NodeID> * data) const inline NodeID findNearestNodeIDForLatLon(const int lat, const int lon, NodeCoords<NodeID> * data) const
{ {
KDTreeType::InputPoint i;
NodeInfo nearestNeighbor = *(kdtree->find_nearest(NodeInfo(lat, lon, 0)).first); KDTreeType::InputPoint o;
data->id = nearestNeighbor.id; i.coordinates[0] = lat;
data->lat = nearestNeighbor.lat; i.coordinates[1] = lon;
data->lon = nearestNeighbor.lon; kdtree->NearestNeighbor(&o, i);
return data->id; data->id = o.data;
} data->lat = o.coordinates[0];
data->lon = o.coordinates[1];
return data->id;
}
private: private:
vector<KDTreeType::iterator> * int2ExtNodeMap; vector<KDTreeType::InputPoint> * int2ExtNodeMap;
KDTreeType * kdtree; KDTreeType * kdtree;
}; };
////////////////// //////////////////
//implementation// //implementation//
////////////////// //////////////////
NodeInformationHelpDesk::~NodeInformationHelpDesk(){
// delete graph;
// delete calc;
// delete c;
}
/* @brief: initialize kd-tree and internal->external node id map /* @brief: initialize kd-tree and internal->external node id map
* *
*/ */
KDTreeType * NodeInformationHelpDesk::initKDTree(ifstream& in) KDTreeType * NodeInformationHelpDesk::initKDTree(ifstream& in)
{ {
kdtree = new KDTreeType(); NodeID id = 0;
NodeID id = 0; while(!in.eof())
while(!in.eof()) {
{ NodeInfo b;
NodeInfo b; in.read((char *)&b, sizeof(b));
in.read((char *)&b, sizeof(b)); b.id = id;
b.id = id; KDTreeType::InputPoint p;
KDTreeType::iterator kdit = kdtree->insert(b); p.coordinates[0] = b.lat;
int2ExtNodeMap->push_back(kdit); p.coordinates[1] = b.lon;
id++; p.data = id;
} int2ExtNodeMap->push_back(p);
in.close(); id++;
// kdtree->optimise(); }
return kdtree; in.close();
kdtree = new KDTreeType(int2ExtNodeMap);
return kdtree;
} }
NodeID NodeInformationHelpDesk::getExternalNodeID(const NodeID node) 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 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 int NodeInformationHelpDesk::getLongitudeOfNode(const NodeID node) const
{ {
return int2ExtNodeMap->at(node)->lon; return int2ExtNodeMap->at(node).coordinates[1];
} }
#endif /*NODEINFORMATIONHELPDESK_H_*/ #endif /*NODEINFORMATIONHELPDESK_H_*/

View 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

View File

@ -1,6 +1,6 @@
Third Party Libraries: Third Party Libraries:
Scons 1.3+
Boost 1.37+ Boost 1.37+
kdtree++ 0.7+ (0.62 does not work with g++ 4.0+)
sparsehash 1.4+ sparsehash 1.4+
stxxl 1.2.1+ stxxl 1.2.1+

View File

@ -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 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 Use Boost to compress all in-/output streams to the file system

View File

@ -126,14 +126,16 @@ public:
rep.content.append("<coordinates>\n"); rep.content.append("<coordinates>\n");
if(distance != std::numeric_limits<unsigned int>::max()) if(distance != std::numeric_limits<unsigned int>::max())
{ //A route has been found { //A route has been found
NodeInfo * info = new NodeInfo();
for(vector<NodeID>::iterator it = path->begin(); it != path->end(); it++) for(vector<NodeID>::iterator it = path->begin(); it != path->end(); it++)
{ {
NodeInfo info = sEngine-> getNodeInfo(*it); sEngine-> getNodeInfo(*it, info);
stringstream nodeout; stringstream nodeout;
nodeout << std::setprecision(10); 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()); rep.content.append(nodeout.str());
} }
delete info;
} }
rep.content.append("</coordinates>"); rep.content.append("</coordinates>");
rep.content.append("</LineString>"); rep.content.append("</LineString>");
@ -164,7 +166,6 @@ private:
//SearchEngine object that is queried //SearchEngine object that is queried
SearchEngine<EdgeData, GraphT> * sEngine; SearchEngine<EdgeData, GraphT> * sEngine;
}; };
}
} // namespace ROUTER
#endif // HTTP_ROUTER_REQUEST_HANDLER_HPP #endif // HTTP_ROUTER_REQUEST_HANDLER_HPP