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
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); }

View File

@ -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);

View File

@ -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

View File

@ -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_*/

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:
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+

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 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

View File

@ -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