BREAKING CHANGE: the routing engine does not use the kd-tree anymore, but an external memory nearest neighbor grid. The memory consumption is less than half. This is a breaking change, please reprocess your .osrm files and take note that the parameter to routed have been changed!

Known Bug: There are some minor rounding errors that affect the position of start and destination node by a few feet.
This commit is contained in:
Dennis Luxen
2010-08-31 14:00:40 +00:00
parent 027c0e46ee
commit 0875c2d557
16 changed files with 1007 additions and 151 deletions
@@ -23,6 +23,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <climits>
#include <cmath>
#include <string>
#include <libxml/xmlreader.h>
/* Default Speed Profile:
motorway 110
@@ -41,7 +43,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
ferry 25
*/
string names[14] = { "motorway", "motorway_link", "trunk", "trunk_link", "primary", "primary_link", "secondary", "secondary_link", "tertiary", "unclassified", "residential", "living_street", "service", "ferry" };
std::string names[14] = { "motorway", "motorway_link", "trunk", "trunk_link", "primary", "primary_link", "secondary", "secondary_link", "tertiary", "unclassified", "residential", "living_street", "service", "ferry" };
double speeds[14] = { 110, 90, 90, 70, 70, 60, 60, 50, 55, 50, 40 , 10, 30, 25};
struct _Node : NodeInfo{
@@ -67,7 +69,8 @@ struct _Node : NodeInfo{
struct _Coordinate {
int lat;
int lon;
_Coordinate () : lat(INT_MIN), lon(INT_MIN) {};
_Coordinate () : lat(INT_MIN), lon(INT_MIN) {}
_Coordinate (int t, int n) : lat(t) , lon(n) {}
};
struct _Way {
@@ -90,6 +93,7 @@ struct _Relation {
struct _Edge {
_Edge() {};
_Edge(NodeID s, NodeID t) : start(s), target(t) { }
_Edge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp) { }
NodeID start;
NodeID target;
short type;
@@ -348,12 +352,12 @@ _Node _ReadXMLNode( xmlTextReaderPtr& inputReader ) {
xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" );
if ( attribute != NULL ) {
node.lat = static_cast<NodeID>(100000*atof(( const char* ) attribute ) );
node.lat = static_cast<NodeID>(100000.*atof(( const char* ) attribute ) );
xmlFree( attribute );
}
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" );
if ( attribute != NULL ) {
node.lon = static_cast<NodeID>(100000*atof(( const char* ) attribute ));
node.lon = static_cast<NodeID>(100000.*atof(( const char* ) attribute ));
xmlFree( attribute );
}
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
+71
View File
@@ -0,0 +1,71 @@
/*
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.
*/
#ifndef GRIDEDGE_H_
#define GRIDEDGE_H_
struct GridEdgeData {
GridEdgeData(_Edge e, unsigned f, unsigned r) : edge(e), fileIndex(f), ramIndex(r) {}
GridEdgeData() {}
_Edge edge;
unsigned ramIndex;
unsigned fileIndex;
bool operator< ( const GridEdgeData& right ) const {
if(right.edge.start != edge.start)
return right.edge.start < edge.start;
if(right.edge.target != edge.target)
return right.edge.target < edge.target;
}
bool operator==( const GridEdgeData& right ) const {
return right.edge.start == edge.start && right.edge.target == edge.target;
}
};
struct CompareGridEdgeDataByFileIndex
{
bool operator () (const GridEdgeData & a, const GridEdgeData & b) const
{
return a.fileIndex < b.fileIndex;
}
};
struct CompareGridEdgeDataByRamIndex
{
typedef GridEdgeData value_type;
bool operator () (const GridEdgeData & a, const GridEdgeData & b) const
{
return a.ramIndex < b.ramIndex;
}
value_type max_value()
{
GridEdgeData e;
e.ramIndex = (1024*1024) - 1;
return e;
}
value_type min_value()
{
GridEdgeData e;
e.ramIndex = 0;
return e;
}
};
#endif /* GRIDEDGE_H_ */
-1
View File
@@ -66,7 +66,6 @@ int readFromBz2Stream( void* pointer, char* buffer, int len )
int closeBz2Stream( void *pointer )
{
BZ2Context* context = (BZ2Context*) pointer;
BZ2_bzclose( context->bz2 );
fclose( context->file );
delete context;
return 0;
+595
View File
@@ -0,0 +1,595 @@
/*
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.
*/
#ifndef NNGRID_H_
#define NNGRID_H_
#include <fstream>
#include <cassert>
#include <limits>
#include <cmath>
#include <vector>
#include <stxxl.h>
#include <google/dense_hash_map>
#include "ExtractorStructs.h"
#include "GridEdge.h"
#include "Percent.h"
#include "PhantomNodes.h"
#include "Util.h"
#include "StaticGraph.h"
namespace NNGrid{
static unsigned getFileIndexForLatLon(const int lt, const int ln)
{
double lat = lt/100000.;
double lon = ln/100000.;
double x = ( lon + 180.0 ) / 360.0;
double y = ( lat + 90.0 ) / 180.0;
assert( x<=1.0 && x >= 0);
assert( y<=1.0 && y >= 0);
unsigned line = 1073741824.0*y;
line = line - (line % 32768);
assert(line % 32768 == 0);
unsigned column = 32768.*x;
unsigned fileIndex = line+column;
return fileIndex;
}
static unsigned getRAMIndexFromFileIndex(const int fileIndex)
{
unsigned fileLine = fileIndex / 32768;
fileLine = fileLine / 32;
fileLine = fileLine * 1024;
unsigned fileColumn = (fileIndex % 32768);
fileColumn = fileColumn / 32;
unsigned ramIndex = fileLine + fileColumn;
assert(ramIndex < 1024*1024);
return ramIndex;
}
static inline int signum(int x){
return (x > 0) ? 1 : (x < 0) ? -1 : 0;
}
static void bresenham(int xstart,int ystart,int xend,int yend, std::vector<std::pair<unsigned, unsigned> > &indexList)
{
int x, y, t, dx, dy, incx, incy, pdx, pdy, ddx, ddy, es, el, err;
dx = xend - xstart;
dy = yend - ystart;
incx = signum(dx);
incy = signum(dy);
if(dx<0) dx = -dx;
if(dy<0) dy = -dy;
if (dx>dy)
{
pdx=incx; pdy=0;
ddx=incx; ddy=incy;
es =dy; el =dx;
} else
{
pdx=0; pdy=incy;
ddx=incx; ddy=incy;
es =dx; el =dy;
}
x = xstart;
y = ystart;
err = el/2;
{
int fileIndex = (y-1)*32768 + x;
int ramIndex = getRAMIndexFromFileIndex(fileIndex);
indexList.push_back(std::make_pair(fileIndex, ramIndex));
}
for(t=0; t<el; ++t)
{
err -= es;
if(err<0)
{
err += el;
x += ddx;
y += ddy;
} else
{
x += pdx;
y += pdy;
}
{
int fileIndex = (y-1)*32768 + x;
int ramIndex = getRAMIndexFromFileIndex(fileIndex);
indexList.push_back(std::make_pair(fileIndex, ramIndex));
}
}
}
static void getListOfIndexesForEdgeAndGridSize(_Coordinate& start, _Coordinate& target, std::vector<std::pair<unsigned, unsigned> > &indexList)
{
double lat1 = start.lat/100000.;
double lon1 = start.lon/100000.;
double x1 = ( lon1 + 180.0 ) / 360.0;
double y1 = ( lat1 + 90.0 ) / 180.0;
double lat2 = target.lat/100000.;
double lon2 = target.lon/100000.;
double x2 = ( lon2 + 180.0 ) / 360.0;
double y2 = ( lat2 + 90.0 ) / 180.0;
bresenham(x1*32768, y1*32768, x2*32768, y2*32768, indexList);
}
class NNGrid {
public:
NNGrid() { ramIndexTable.resize((1024*1024), UINT_MAX); }
NNGrid(const char* rif, const char* iif) {
ramIndexTable.resize((1024*1024), UINT_MAX);
indexInFile.open(iif, std::ios::in | std::ios::binary);
ramInFile.open(rif, std::ios::in | std::ios::binary);
}
~NNGrid() {
if(ramInFile.is_open()) ramInFile.close();
if(indexInFile.is_open()) indexInFile.close();
}
void OpenIndexFiles()
{
assert(ramInFile.is_open());
assert(indexInFile.is_open());
for(int i = 0; i < 1024*1024; i++)
{
unsigned temp;
ramInFile.read((char*)&temp, sizeof(unsigned));
ramIndexTable[i] = temp;
}
ramInFile.close();
}
void AddEdge(_Edge edge, _Coordinate start, _Coordinate target)
{
edge.startCoord = start;
edge.targetCoord = target;
std::vector<std::pair<unsigned, unsigned> > indexList;
getListOfIndexesForEdgeAndGridSize(start, target, indexList);
for(int i = 0; i < indexList.size(); i++)
{
entries.push_back(GridEdgeData(edge, indexList[i].first, indexList[i].second));
}
}
void ConstructGrid(char * ramIndexOut, char * fileIndexOut)
{
double timestamp = get_timestamp();
//create index file on disk, old one is over written
indexOutFile.open(fileIndexOut, std::ios::out | std::ios::binary | std::ios::trunc);
cout << "sorting grid data consisting of " << entries.size() << " edges..." << flush;
//sort entries
stxxl::sort(entries.begin(), entries.end(), CompareGridEdgeDataByRamIndex(), 1024*1024*1024);
cout << "ok in " << (get_timestamp() - timestamp) << "s" << endl;
std::vector<GridEdgeData> entriesInFileWithRAMSameIndex;
unsigned indexInRamTable = entries.begin()->ramIndex;
unsigned lastPositionInIndexFile = 0;
unsigned numberOfUsedCells = 0;
unsigned maxNumberOfRAMCellElements = 0;
cout << "writing data ..." << flush;
Percent p(entries.size());
for(stxxl::vector<GridEdgeData>::iterator vt = entries.begin(); vt != entries.end(); vt++)
{
p.printIncrement();
if(vt->ramIndex != indexInRamTable)
{
unsigned numberOfBytesInCell = FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile);
if(entriesInFileWithRAMSameIndex.size() > maxNumberOfRAMCellElements)
maxNumberOfRAMCellElements = entriesInFileWithRAMSameIndex.size();
ramIndexTable[indexInRamTable] = lastPositionInIndexFile;
lastPositionInIndexFile += numberOfBytesInCell;
entriesInFileWithRAMSameIndex.clear();
indexInRamTable = vt->ramIndex;
numberOfUsedCells++;
}
entriesInFileWithRAMSameIndex.push_back(*vt);
}
unsigned numberOfBytesInCell = FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile);
ramIndexTable[indexInRamTable] = lastPositionInIndexFile;
numberOfUsedCells++;
entriesInFileWithRAMSameIndex.clear();
assert(entriesInFileWithRAMSameIndex.size() == 0);
for(int i = 0; i < 1024*1024; i++)
{
if(ramIndexTable[i] != UINT_MAX){
numberOfUsedCells--;
}
}
assert(numberOfUsedCells == 0);
//close index file
indexOutFile.close();
//Serialize RAM Index
ofstream ramFile(ramIndexOut, std::ios::out | std::ios::binary | std::ios::trunc);
//write 4 MB of index Table in RAM
for(int i = 0; i < 1024*1024; i++)
ramFile.write((char *)&ramIndexTable[i], sizeof(unsigned) );
//close ram index file
ramFile.close();
}
bool FindRoutingStarts(const _Coordinate startCoord, const _Coordinate targetCoord, PhantomNodes * routingStarts) {
unsigned fileIndex = getFileIndexForLatLon(startCoord.lat, startCoord.lon);
std::vector<_Edge> candidates;
double timestamp = get_timestamp();
for(int j = -32768; j < (32768+1); j+=32768){
for(int i = -1; i < 2; i++){
GetContentsOfFileBucket(fileIndex+i+j, candidates);
}
}
_Coordinate tmp;
double dist = numeric_limits<double>::max();
timestamp = get_timestamp();
for(std::vector<_Edge>::iterator it = candidates.begin(); it != candidates.end(); it++)
{
double r = 0.;
double tmpDist = ComputeDistance(startCoord, it->startCoord, it->targetCoord, tmp, &r);
if(tmpDist < dist)
{
routingStarts->startNode1 = it->start;
routingStarts->startNode2 = it->target;
routingStarts->startRatio = r;
dist = tmpDist;
routingStarts->startCoord.lat = tmp.lat;
routingStarts->startCoord.lon = tmp.lon;
}
}
fileIndex = getFileIndexForLatLon(targetCoord.lat, targetCoord.lon);
candidates.clear();
timestamp = get_timestamp();
for(int j = -32768; j < (32768+1); j+=32768){
for(int i = -1; i < 2; i++){
GetContentsOfFileBucket(fileIndex+i+j, candidates);
}
}
dist = numeric_limits<double>::max();
timestamp = get_timestamp();
for(std::vector<_Edge>::iterator it = candidates.begin(); it != candidates.end(); it++)
{
double r = 0.;
double tmpDist = ComputeDistance(targetCoord, it->startCoord, it->targetCoord, tmp, &r);
if(tmpDist < dist)
{
routingStarts->targetNode1 = it->start;
routingStarts->targetNode2 = it->target;
routingStarts->targetRatio = r;
dist = tmpDist;
routingStarts->targetCoord.lat = tmp.lat;
routingStarts->targetCoord.lon = tmp.lon;
}
}
return true;
}
_Coordinate FindNearestPointOnEdge(const _Coordinate& inputCoordinate)
{
unsigned fileIndex = getFileIndexForLatLon(inputCoordinate.lat, inputCoordinate.lon);
std::vector<_Edge> candidates;
double timestamp = get_timestamp();
for(int j = -32768; j < (32768+1); j+=32768){
for(int i = -1; i < 2; i++){
GetContentsOfFileBucket(fileIndex+i+j, candidates);
}
}
_Coordinate nearest, tmp;
double dist = numeric_limits<double>::max();
timestamp = get_timestamp();
for(std::vector<_Edge>::iterator it = candidates.begin(); it != candidates.end(); it++)
{
double r = 0.;
double tmpDist = ComputeDistance(inputCoordinate, it->startCoord, it->targetCoord, tmp, &r);
if(tmpDist < dist)
{
dist = tmpDist;
nearest = tmp;
}
}
return nearest;
}
private:
unsigned FillCell(std::vector<GridEdgeData>& entriesWithSameRAMIndex, unsigned fileOffset )
{
vector<char> tmpBuffer;
tmpBuffer.resize(32*32*4096,0);
unsigned indexIntoTmpBuffer = 0;
unsigned numberOfWrittenBytes = 0;
assert(indexOutFile.is_open());
vector<unsigned> cellIndex;
cellIndex.resize(32*32,UINT_MAX);
google::dense_hash_map< unsigned, unsigned > * cellMap = new google::dense_hash_map< unsigned, unsigned >(1024);
cellMap->set_empty_key(UINT_MAX);
unsigned ramIndex = entriesWithSameRAMIndex.begin()->ramIndex;
unsigned lineBase = ramIndex/1024;
lineBase = lineBase*32*32768;
unsigned columnBase = ramIndex%1024;
columnBase=columnBase*32;
for(int i = 0; i < 32; i++)
{
for(int j = 0; j < 32; j++)
{
unsigned fileIndex = lineBase + i*32768 + columnBase+j;
unsigned cellIndex = i*32+j;
cellMap->insert(std::make_pair(fileIndex, cellIndex));
}
}
for(int i = 0; i < entriesWithSameRAMIndex.size() -1; i++)
{
assert(entriesWithSameRAMIndex[i].ramIndex== entriesWithSameRAMIndex[i+1].ramIndex);
}
//sort & unique
std::sort(entriesWithSameRAMIndex.begin(), entriesWithSameRAMIndex.end(), CompareGridEdgeDataByFileIndex());
std::vector<GridEdgeData>::iterator uniqueEnd = std::unique(entriesWithSameRAMIndex.begin(), entriesWithSameRAMIndex.end());
//traverse each file bucket and write its contents to disk
std::vector<GridEdgeData> entriesWithSameFileIndex;
unsigned fileIndex = entriesWithSameRAMIndex.begin()->fileIndex;
for(std::vector<GridEdgeData>::iterator it = entriesWithSameRAMIndex.begin(); it != uniqueEnd; it++)
{
assert(cellMap->find(it->fileIndex) != cellMap->end() ); //asserting that file index belongs to cell index
if(it->fileIndex != fileIndex)
{
// start in cellIndex vermerken
int localFileIndex = entriesWithSameFileIndex.begin()->fileIndex;
int localCellIndex = cellMap->find(localFileIndex)->second;
int localRamIndex = getRAMIndexFromFileIndex(localFileIndex);
assert(cellMap->find(entriesWithSameFileIndex.begin()->fileIndex) != cellMap->end());
cellIndex[localCellIndex] = indexIntoTmpBuffer + fileOffset;
indexIntoTmpBuffer += FlushEntriesWithSameFileIndexToBuffer(entriesWithSameFileIndex, tmpBuffer, indexIntoTmpBuffer);
entriesWithSameFileIndex.clear(); //todo: in flushEntries erledigen.
}
GridEdgeData data = *it;
entriesWithSameFileIndex.push_back(data);
fileIndex = it->fileIndex;
}
assert(cellMap->find(entriesWithSameFileIndex.begin()->fileIndex) != cellMap->end());
int localFileIndex = entriesWithSameFileIndex.begin()->fileIndex;
int localCellIndex = cellMap->find(localFileIndex)->second;
int localRamIndex = getRAMIndexFromFileIndex(localFileIndex);
cellIndex[localCellIndex] = indexIntoTmpBuffer + fileOffset;
indexIntoTmpBuffer += FlushEntriesWithSameFileIndexToBuffer(entriesWithSameFileIndex, tmpBuffer, indexIntoTmpBuffer);
entriesWithSameFileIndex.clear(); //todo: in flushEntries erledigen.
assert(entriesWithSameFileIndex.size() == 0);
for(int i = 0; i < 32*32; i++)
{
indexOutFile.write((char *)&cellIndex[i], sizeof(unsigned));
numberOfWrittenBytes += sizeof(unsigned);
}
//write contents of tmpbuffer to disk
for(int i = 0; i < indexIntoTmpBuffer; i++)
{
indexOutFile.write(&tmpBuffer[i], sizeof(char));
numberOfWrittenBytes += sizeof(char);
}
delete cellMap;
return numberOfWrittenBytes;
}
unsigned FlushEntriesWithSameFileIndexToBuffer(const std::vector<GridEdgeData> &vectorWithSameFileIndex, vector<char>& tmpBuffer, const unsigned index)
{
unsigned counter = 0;
unsigned max = UINT_MAX;
for(int i = 0; i < vectorWithSameFileIndex.size()-1; i++)
{
assert( vectorWithSameFileIndex[i].fileIndex == vectorWithSameFileIndex[i+1].fileIndex );
assert( vectorWithSameFileIndex[i].ramIndex == vectorWithSameFileIndex[i+1].ramIndex );
}
for(std::vector<GridEdgeData>::const_iterator et = vectorWithSameFileIndex.begin(); et != vectorWithSameFileIndex.end(); et++)
{
char * start = (char *)&et->edge.start;
for(int i = 0; i < sizeof(NodeID); i++)
{
tmpBuffer[index+counter] = start[i];
counter++;
}
char * target = (char *)&et->edge.target;
for(int i = 0; i < sizeof(NodeID); i++)
{
tmpBuffer[index+counter] = target[i];
counter++;
}
char * slat = (char *) &(et->edge.startCoord.lat);
for(int i = 0; i < sizeof(int); i++)
{
tmpBuffer[index+counter] = slat[i];
counter++;
}
char * slon = (char *) &(et->edge.startCoord.lon);
for(int i = 0; i < sizeof(int); i++)
{
tmpBuffer[index+counter] = slon[i];
counter++;
}
char * tlat = (char *) &(et->edge.targetCoord.lat);
for(int i = 0; i < sizeof(int); i++)
{
tmpBuffer[index+counter] = tlat[i];
counter++;
}
char * tlon = (char *) &(et->edge.targetCoord.lon);
for(int i = 0; i < sizeof(int); i++)
{
tmpBuffer[index+counter] = tlon[i];
counter++;
}
}
char * umax = (char *) &max;
for(int i = 0; i < sizeof(unsigned); i++)
{
tmpBuffer[index+counter] = umax[i];
counter++;
}
return counter;
}
void GetContentsOfFileBucket(const unsigned fileIndex, std::vector<_Edge>& result)
{
unsigned ramIndex = getRAMIndexFromFileIndex(fileIndex);
unsigned startIndexInFile = ramIndexTable[ramIndex];
if(startIndexInFile == UINT_MAX){
return;
}
std::vector<unsigned> cellIndex;
cellIndex.resize(32*32);
google::dense_hash_map< unsigned, unsigned > * cellMap = new google::dense_hash_map< unsigned, unsigned >(1024);
cellMap->set_empty_key(UINT_MAX);
indexInFile.seekg(startIndexInFile);
unsigned lineBase = ramIndex/1024;
lineBase = lineBase*32*32768;
unsigned columnBase = ramIndex%1024;
columnBase=columnBase*32;
for(int i = 0; i < 32; i++)
{
for(int j = 0; j < 32; j++)
{
unsigned fileIndex = lineBase + i*32768 + columnBase+j;
unsigned cellIndex = i*32+j;
cellMap->insert(std::make_pair(fileIndex, cellIndex));
}
}
unsigned numOfElementsInCell = 0;
for(int i = 0; i < 32*32; i++)
{
indexInFile.read((char *)&cellIndex[i], sizeof(unsigned));
numOfElementsInCell += cellIndex[i];
}
assert(cellMap->find(fileIndex) != cellMap->end());
if(cellIndex[cellMap->find(fileIndex)->second] == UINT_MAX)
{
return;
}
unsigned position = cellIndex[cellMap->find(fileIndex)->second] + 32*32*sizeof(unsigned) ;
indexInFile.seekg(position);
unsigned numberOfEdgesInFileBucket = 0;
NodeID start, target; int slat, slon, tlat, tlon;
do{
indexInFile.read((char *)&(start), sizeof(NodeID));
if(start == UINT_MAX || indexInFile.eof())
break;
indexInFile.read((char *)&(target), sizeof(NodeID));
indexInFile.read((char *)&(slat), sizeof(int));
indexInFile.read((char *)&(slon), sizeof(int));
indexInFile.read((char *)&(tlat), sizeof(int));
indexInFile.read((char *)&(tlon), sizeof(int));
_Edge e(start, target);
e.startCoord.lat = slat;
e.startCoord.lon = slon;
e.targetCoord.lat = tlat;
e.targetCoord.lon = tlon;
result.push_back(e);
numberOfEdgesInFileBucket++;
} while(true);
delete cellMap;
}
/* More or less from monav project, thanks */
double ComputeDistance(const _Coordinate& inputPoint, const _Coordinate& source, const _Coordinate& target, _Coordinate& nearest, double *r)
{
const double vY = (double)target.lon - (double)source.lon;
const double vX = (double)target.lat - (double)source.lat;
const double wY = (double)inputPoint.lon - (double)source.lon;
const double wX = (double)inputPoint.lat - (double)source.lat;
const double lengthSquared = vX * vX + vY * vY;
if(lengthSquared != 0)
{
*r = (vX * wX + vY * wY) / lengthSquared;
}
double percentage = *r;
if(*r <=0 ){
nearest.lat = source.lat;
nearest.lon = source.lon;
percentage = 0;
return wY * wY + wX * wX;
}
if( *r>= 1){
nearest.lat = target.lat;
nearest.lon = target.lon;
percentage = 1;
const double dY = (double)inputPoint.lon - (double)target.lon;
const double dX = (double)inputPoint.lat - (double)target.lat;
return dY * dY + dX * dX;
}
nearest.lat = (double)source.lat + ( (*r) * vX );
nearest.lon = (double)source.lon + ( (*r) * vY );
const double dX = (double)source.lat + (*r) * vX - (double)inputPoint.lat;
const double dY = (double)source.lon + (*r) * vY - (double)inputPoint.lon;
return dY*dY + dX*dX;
}
ofstream indexOutFile;
ifstream indexInFile;
ifstream ramInFile;
stxxl::vector<GridEdgeData> entries;
std::vector<unsigned> ramIndexTable; //4 MB for first level index in RAM
};
}
#endif /* NNGRID_H_ */
+2
View File
@@ -22,6 +22,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
#define _NODE_COORDS_H
#include <cassert>
#include <cstddef>
#include <limits>
#include "../typedefs.h"
@@ -63,4 +64,5 @@ struct NodeCoords {
}
}
};
#endif //_NODE_COORDS_H
+30 -85
View File
@@ -21,103 +21,48 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef NODEINFORMATIONHELPDESK_H_
#define NODEINFORMATIONHELPDESK_H_
#include <omp.h>
#include <climits>
#include <cstdlib>
#include <algorithm>
#include <deque>
#include <fstream>
#include <iostream>
#include <limits>
#include <list>
#include <stack>
#include <string>
#include <vector>
#include "../typedefs.h"
#include "StaticKDTree.h"
#include "NNGrid.h"
#include "PhantomNodes.h"
typedef KDTree::StaticKDTree<2, int, NodeID> KDTreeType;
typedef NNGrid::NNGrid Grid;
class NodeInformationHelpDesk{
public:
NodeInformationHelpDesk() { int2ExtNodeMap = new vector<KDTreeType::InputPoint>();}
KDTreeType * initKDTree(ifstream& input);
NodeID getExternalNodeID(const NodeID node);
void getExternalNodeInfo(const NodeID node, NodeInfo * info) const;
int getLatitudeOfNode(const NodeID node) const;
int getLongitudeOfNode(const NodeID node) const;
NodeID getNumberOfNodes() const { return int2ExtNodeMap->size(); }
inline NodeID findNearestNodeIDForLatLon(const int lat, const int lon, NodeCoords<NodeID> * data) const
NodeInformationHelpDesk(const char* ramIndexInput, const char* fileIndexInput) { numberOfNodes = 0; int2ExtNodeMap = new vector<_Coordinate>(); g = new Grid(ramIndexInput,fileIndexInput); }
~NodeInformationHelpDesk() { delete int2ExtNodeMap; delete g; }
void initNNGrid(ifstream& in)
{
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;
while(!in.eof())
{
NodeInfo b;
in.read((char *)&b, sizeof(b));
int2ExtNodeMap->push_back(_Coordinate(b.lat, b.lon));
numberOfNodes++;
}
in.close();
g->OpenIndexFiles();
}
int getLatitudeOfNode(const NodeID node) const { return int2ExtNodeMap->at(node).lat; }
int getLongitudeOfNode(const NodeID node) const { return int2ExtNodeMap->at(node).lon; }
NodeID getNumberOfNodes() const { return numberOfNodes; }
inline void findNearestNodeIDForLatLon(const _Coordinate coord, _Coordinate& result) { result = g->FindNearestPointOnEdge(coord); }
inline bool FindRoutingStarts(const _Coordinate start, const _Coordinate target, PhantomNodes * phantomNodes) {
g->FindRoutingStarts(start, target, phantomNodes);
}
private:
vector<KDTreeType::InputPoint> * int2ExtNodeMap;
KDTreeType * kdtree;
vector<_Coordinate> * int2ExtNodeMap;
Grid * g;
unsigned numberOfNodes;
};
//////////////////
//implementation//
//////////////////
/* @brief: initialize kd-tree and internal->external node id map
*
*/
KDTreeType * NodeInformationHelpDesk::initKDTree(ifstream& in)
{
NodeID id = 0;
while(!in.eof())
{
NodeInfo b;
in.read((char *)&b, sizeof(b));
b.id = id;
KDTreeType::InputPoint p;
p.coordinates[0] = b.lat;
p.coordinates[1] = b.lon;
p.data = id;
int2ExtNodeMap->push_back(p);
id++;
}
in.close();
kdtree = new KDTreeType(int2ExtNodeMap);
return kdtree;
}
NodeID NodeInformationHelpDesk::getExternalNodeID(const NodeID node)
{
return int2ExtNodeMap->at(node).data;
}
void NodeInformationHelpDesk::getExternalNodeInfo(const NodeID node, NodeInfo * info) const
{
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).coordinates[0];
}
int NodeInformationHelpDesk::getLongitudeOfNode(const NodeID node) const
{
return int2ExtNodeMap->at(node).coordinates[1];
}
#endif /*NODEINFORMATIONHELPDESK_H_*/
+90
View File
@@ -0,0 +1,90 @@
/*
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.
*/
#ifndef PERCENT_H
#define PERCENT_H
#include <iostream>
#ifdef _OPENMP
#include <omp.h>
#endif
class Percent
{
public:
/**
* Constructor.
* @param maxValue the value that corresponds to 100%
* @param step the progress is shown in steps of 'step' percent
*/
Percent(unsigned maxValue, unsigned step = 5) {
reinit(maxValue, step);
}
/** Reinitializes this object. */
void reinit(unsigned maxValue, unsigned step = 5) {
_maxValue = maxValue;
_current_value = 0;
_intervalPercent = _maxValue / 100;
_nextThreshold = _intervalPercent;
_lastPercent = 0;
_step = step;
}
/** If there has been significant progress, display it. */
void printStatus(unsigned currentValue) {
if (currentValue >= _nextThreshold) {
_nextThreshold += _intervalPercent;
printPercent( currentValue / (double)_maxValue * 100 );
}
if (currentValue + 1 == _maxValue)
std::cout << " 100%" << std::endl;
}
void printIncrement()
{
#pragma omp atomic
_current_value++;
printStatus(_current_value);
}
private:
unsigned _current_value;
unsigned _maxValue;
unsigned _intervalPercent;
unsigned _nextThreshold;
unsigned _lastPercent;
unsigned _step;
/** Displays the new progress. */
void printPercent(double percent) {
while (percent >= _lastPercent+_step) {
_lastPercent+=_step;
if (_lastPercent % 10 == 0) {
std::cout << " " << _lastPercent << "% ";
}
else {
std::cout << ".";
}
std::cout.flush();
}
}
};
#endif // PERCENT_H
+38
View File
@@ -0,0 +1,38 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 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.
*/
#ifndef PHANTOMNODES_H_
#define PHANTOMNODES_H_
#include "ExtractorStructs.h"
struct PhantomNodes {
PhantomNodes() : startNode1(UINT_MAX), startNode2(UINT_MAX), targetNode1(UINT_MAX), targetNode2(UINT_MAX), startRatio(1.), targetRatio(1.) {}
NodeID startNode1;
NodeID startNode2;
NodeID targetNode1;
NodeID targetNode2;
double startRatio;
double targetRatio;
_Coordinate startCoord;
_Coordinate targetCoord;
};
#endif /* PHANTOMNODES_H_ */
+2
View File
@@ -21,6 +21,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef TIMEUTIL_H_
#define TIMEUTIL_H_
#include <climits>
#include <cstdlib>
#include <sys/time.h>
/** Returns a timestamp (now) in seconds (incl. a fractional part). */