Compare commits

..

20 Commits

Author SHA1 Message Date
DennisSchiefer 5ebe8080f9 small bug class/id mixed up 2012-03-14 11:24:40 +01:00
DennisSchiefer d92b28d2c3 restructured for release 2012-03-14 10:39:37 +01:00
DennisSchiefer ec27881f39 test fencing 2012-03-13 22:39:28 +01:00
DennisSchiefer c5a8ec7c31 added better lat/lng display when dragging,
added experimental faster route redraw (commented out),
changed default website url and routing url,
removed drag after dragend event workaround
2012-03-13 22:25:40 +01:00
DennisSchiefer afbd3347da added clear debug log button,
removed showing of links in gpx, route requests,
checked html with validator
2012-03-13 20:51:44 +01:00
DennisSchiefer 41bcafc3a1 added lat/lng processing 2012-03-13 17:57:48 +01:00
DennisSchiefer 27d24885a9 debug window stays at botoom when adding data 2012-03-13 17:36:40 +01:00
DennisSchiefer 805402b230 starting to reverse geocoding 2012-03-13 17:32:18 +01:00
DennisSchiefer 4918549bac fixed bug when selecting city options in geocoder,
added clicking on map to create markers,
reset also clears input boxes now
2012-03-13 15:26:53 +01:00
DennisSchiefer 784f417857 changed geocoder to official OSM geocoder,
switched default map style to osm.org
2012-03-13 14:31:23 +01:00
DennisSchiefer 0bc3e098ac added GUI support for IE9 and IE10,
changed GUI legal text,
changed via-node deletion to click only,
moved default entries for input boxes to config file,
made input boxes selectable again
2012-03-13 14:15:07 +01:00
DennisSchiefer dfd3a5d554 changed round-about symbol, corrected bug with ENTER not working on
location input
2012-03-13 10:26:31 +01:00
DennisSchiefer 9dcc472c60 Merge branch 'feature/prefetching' into develop 2012-03-12 13:33:14 +01:00
DennisSchiefer c972e2cf41 Merge branch 'gui/buttons' into develop 2012-03-12 13:26:38 +01:00
DennisSchiefer de9ab83cea ignore eclipse files 2012-03-12 13:16:32 +01:00
schiefer 174e388e2d debug window added,
when including OSRM.debug, a debug window is shown
2012-03-12 11:33:39 +01:00
DennisSchiefer ee41fb45b7 added more turn instructions, changed clickability of gui 2012-03-10 17:08:25 +01:00
schiefer 93892b9806 changed buttons look 2012-03-09 17:33:06 +01:00
schiefer 749d83a69f - store prefetched images permanently
(otherwise they are not prefetched before the function terminated)
- store each type of marker icon once
2012-03-09 15:26:32 +01:00
schiefer 8b109904c8 initial import 2012-03-09 09:24:51 +01:00
221 changed files with 8144 additions and 19832 deletions
+2 -72
View File
@@ -1,72 +1,2 @@
# Compiled source #
###################
*.com
*.class
*.dll
*.exe
*.o
*.so
# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
# Logs and databases #
######################
*.log
*.sql
*.sqlite
# OS generated files #
######################
.DS_Store?
ehthumbs.db
Icon?
Thumbs.db
# SCons related files #
#######################
SconsBuilder*
.scon*
.build
# Eclipse related files #
#########################
.setting*
.scb
.cproject
.project
# stxxl related files #
#######################
.stxxl
stxxl.log
stxxl.errlog
# compiled protobuffers #
#########################
DataStructures/pbf-proto/*.pb.h
DataStructures/pbf-proto/*.pb.cc
# External Libs #
#################
lib/
# Visual Studio Temp + build Files #
####################################
vcprojects/*.user
vcprojects/*.ncb
vcprojects/*.suo
vcprojects/Debug/
vcprojects/Release/
bin/
bin-debug/
/.settings
/.project
-10
View File
@@ -1,10 +0,0 @@
The following people contributed code to the Open Source Routing Machine:
Christian Vetter
Dennis Luxen
Ruslan Krenzler
Frederik Ramm
Bharath Vissapragada
Pascal Neis
Sasa Ivetic
Emil Tin
-126
View File
@@ -1,126 +0,0 @@
/*
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 DOUGLASPEUCKER_H_
#define DOUGLASPEUCKER_H_
#include <cfloat>
#include <stack>
/*This class object computes the bitvector of indicating generalized input points
* according to the (Ramer-)Douglas-Peucker algorithm.
*
* Input is vector of pairs. Each pair consists of the point information and a bit
* indicating if the points is present in the generalization.
* Note: points may also be pre-selected*/
//These thresholds are more or less heuristically chosen.
static double DouglasPeuckerThresholds[19] = { 10240000., 512., 2560000., 1280000., 640000., 320000., 160000., 80000., 40000., 20000., 10000., 5000., 2400., 1200., 200, 16, 6, 3., 1. };
template<class PointT>
class DouglasPeucker {
private:
typedef std::pair<std::size_t, std::size_t> PairOfPoints;
//Stack to simulate the recursion
std::stack<PairOfPoints > recursionStack;
double ComputeDistance(const _Coordinate& inputPoint, const _Coordinate& source, const _Coordinate& target) {
double r;
const double x = (double)inputPoint.lat;
const double y = (double)inputPoint.lon;
const double a = (double)source.lat;
const double b = (double)source.lon;
const double c = (double)target.lat;
const double d = (double)target.lon;
double p,q,mX,nY;
if(c != a) {
const double m = (d-b)/(c-a); // slope
// Projection of (x,y) on line joining (a,b) and (c,d)
p = ((x + (m*y)) + (m*m*a - m*b))/(1 + m*m);
q = b + m*(p - a);
} else {
p = c;
q = y;
}
nY = (d*p - c*q)/(a*d - b*c);
mX = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we neednot calculate the values of m an n as we are just interested in the ratio
r = mX;
if(r<=0){
return ((b - y)*(b - y) + (a - x)*(a - x));
}
else if(r >= 1){
return ((d - y)*(d - y) + (c - x)*(c - x));
}
// point lies in between
return (p-x)*(p-x) + (q-y)*(q-y);
}
public:
void Run(std::vector<PointT> & inputVector, const unsigned zoomLevel) {
{
assert(zoomLevel < 19);
assert(1 < inputVector.size());
std::size_t leftBorderOfRange = 0;
std::size_t rightBorderOfRange = 1;
//Sweep linerarily over array and identify those ranges that need to be checked
do {
assert(inputVector[leftBorderOfRange].necessary);
assert(inputVector[inputVector.size()-1].necessary);
if(inputVector[rightBorderOfRange].necessary) {
recursionStack.push(std::make_pair(leftBorderOfRange, rightBorderOfRange));
leftBorderOfRange = rightBorderOfRange;
}
++rightBorderOfRange;
} while( rightBorderOfRange < inputVector.size());
}
while(!recursionStack.empty()) {
//pop next element
const PairOfPoints pair = recursionStack.top();
recursionStack.pop();
assert(inputVector[pair.first].necessary);
assert(inputVector[pair.second].necessary);
assert(pair.second < inputVector.size());
assert(pair.first < pair.second);
double maxDistance = -DBL_MAX;
std::size_t indexOfFarthestElement = pair.second;
//find index idx of element with maxDistance
for(std::size_t i = pair.first+1; i < pair.second; ++i){
double distance = std::fabs(ComputeDistance(inputVector[i].location, inputVector[pair.first].location, inputVector[pair.second].location));
if(distance > DouglasPeuckerThresholds[zoomLevel] && distance > maxDistance) {
indexOfFarthestElement = i;
maxDistance = distance;
}
}
if (maxDistance > DouglasPeuckerThresholds[zoomLevel]) {
// mark idx as necessary
inputVector[indexOfFarthestElement].necessary = true;
if (1 < indexOfFarthestElement - pair.first) {
recursionStack.push(std::make_pair(pair.first, indexOfFarthestElement) );
}
if (1 < pair.second - indexOfFarthestElement)
recursionStack.push(std::make_pair(indexOfFarthestElement, pair.second) );
}
}
}
};
#endif /* DOUGLASPEUCKER_H_ */
-134
View File
@@ -1,134 +0,0 @@
/*
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 POLYLINECOMPRESSOR_H_
#define POLYLINECOMPRESSOR_H_
#include <string>
#include "../DataStructures/ExtractorStructs.h"
#include "../DataStructures/SegmentInformation.h"
#include "../Util/StringUtil.h"
class PolylineCompressor {
private:
inline void encodeVectorSignedNumber(vector<int> & numbers, string & output) {
for(unsigned i = 0; i < numbers.size(); ++i) {
numbers[i] <<= 1;
if (numbers[i] < 0) {
numbers[i] = ~(numbers[i]);
}
}
for(unsigned i = 0; i < numbers.size(); ++i) {
encodeNumber(numbers[i], output);
}
}
inline void encodeNumber(int numberToEncode, string & output) {
while (numberToEncode >= 0x20) {
int nextValue = (0x20 | (numberToEncode & 0x1f)) + 63;
output += (static_cast<char> (nextValue));
if(92 == nextValue)
output += (static_cast<char> (nextValue));
numberToEncode >>= 5;
}
numberToEncode += 63;
output += (static_cast<char> (numberToEncode));
if(92 == numberToEncode)
output += (static_cast<char> (numberToEncode));
}
public:
inline void printEncodedString(const vector<SegmentInformation>& polyline, string &output) {
vector<int> deltaNumbers;
output += "\"";
if(!polyline.empty()) {
_Coordinate lastCoordinate = polyline[0].location;
deltaNumbers.push_back( lastCoordinate.lat );
deltaNumbers.push_back( lastCoordinate.lon );
for(unsigned i = 1; i < polyline.size(); ++i) {
if(!polyline[i].necessary)
continue;
deltaNumbers.push_back(polyline[i].location.lat - lastCoordinate.lat);
deltaNumbers.push_back(polyline[i].location.lon - lastCoordinate.lon);
lastCoordinate = polyline[i].location;
}
encodeVectorSignedNumber(deltaNumbers, output);
}
output += "\"";
}
inline void printEncodedString(const vector<_Coordinate>& polyline, string &output) {
vector<int> deltaNumbers(2*polyline.size());
output += "\"";
if(!polyline.empty()) {
deltaNumbers[0] = polyline[0].lat;
deltaNumbers[1] = polyline[0].lon;
for(unsigned i = 1; i < polyline.size(); ++i) {
deltaNumbers[(2*i)] = (polyline[i].lat - polyline[i-1].lat);
deltaNumbers[(2*i)+1] = (polyline[i].lon - polyline[i-1].lon);
}
encodeVectorSignedNumber(deltaNumbers, output);
}
output += "\"";
}
inline void printUnencodedString(vector<_Coordinate> & polyline, string & output) {
output += "[";
string tmp;
for(unsigned i = 0; i < polyline.size(); i++) {
convertInternalLatLonToString(polyline[i].lat, tmp);
output += "[";
output += tmp;
convertInternalLatLonToString(polyline[i].lon, tmp);
output += ", ";
output += tmp;
output += "]";
if( i < polyline.size()-1 ) {
output += ",";
}
}
output += "]";
}
inline void printUnencodedString(vector<SegmentInformation> & polyline, string & output) {
output += "[";
string tmp;
for(unsigned i = 0; i < polyline.size(); i++) {
if(!polyline[i].necessary)
continue;
convertInternalLatLonToString(polyline[i].location.lat, tmp);
output += "[";
output += tmp;
convertInternalLatLonToString(polyline[i].location.lon, tmp);
output += ", ";
output += tmp;
output += "]";
if( i < polyline.size()-1 ) {
output += ",";
}
}
output += "]";
}
};
#endif /* POLYLINECOMPRESSOR_H_ */
-290
View File
@@ -1,290 +0,0 @@
/*
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 CONTRACTIONCLEANUP_H_INCLUDED
#define CONTRACTIONCLEANUP_H_INCLUDED
#ifdef _GLIBCXX_PARALLEL
#include <parallel/algorithm>
#else
#include <algorithm>
#endif
#ifndef _WIN32
#include <sys/time.h>
#endif
#include "Contractor.h"
#ifdef _OPENMP
#include <omp.h>
#endif
class ContractionCleanup {
private:
struct _CleanupHeapData {
NodeID parent;
_CleanupHeapData( NodeID p ) {
parent = p;
}
};
#ifdef _MANYCORES
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, DenseStorage<NodeID, NodeID> > _Heap;
#else
typedef BinaryHeap< NodeID, NodeID, int, _CleanupHeapData > _Heap;
#endif
struct _ThreadData {
_Heap* _heapForward;
_Heap* _heapBackward;
_ThreadData( NodeID nodes ) {
_heapBackward = new _Heap(nodes);
_heapForward = new _Heap(nodes);
}
~_ThreadData()
{
delete _heapBackward;
delete _heapForward;
}
};
public:
struct Edge {
NodeID source;
NodeID target;
struct EdgeData {
NodeID via;
unsigned nameID1;
unsigned nameID2;
int distance;
bool shortcut;
bool forward;
bool backward;
short turnInstruction;
} data;
//sorts by source and other attributes
static bool CompareBySource( const Edge& left, const Edge& right ) {
if ( left.source != right.source )
return left.source < right.source;
int l = ( left.data.forward ? -1 : 0 ) + ( left.data.backward ? -1 : 0 );
int r = ( right.data.forward ? -1 : 0 ) + ( right.data.backward ? -1 : 0 );
if ( l != r )
return l < r;
if ( left.target != right.target )
return left.target < right.target;
return left.data.distance < right.data.distance;
}
bool operator== ( const Edge& right ) const {
return ( source == right.source && target == right.target && data.distance == right.data.distance &&
data.shortcut == right.data.shortcut && data.forward == right.data.forward && data.backward == right.data.backward
&& data.via == right.data.via && data.nameID1 == right.data.nameID1 && data.nameID2 == right.data.nameID2
);
}
};
ContractionCleanup( int numNodes, const std::vector< Edge >& edges ) {
_graph = edges;
_numNodes = numNodes;
}
~ContractionCleanup() {
}
void Run() {
RemoveUselessShortcuts();
}
template< class EdgeT >
void GetData( std::vector< EdgeT >& edges ) {
for ( int edge = 0, endEdges = ( int ) _graph.size(); edge != endEdges; ++edge ) {
if(_graph[edge].data.forward || _graph[edge].data.backward) {
EdgeT newEdge;
newEdge.source = _graph[edge].source;
newEdge.target = _graph[edge].target;
newEdge.data = _graph[edge].data;
edges.push_back( newEdge );
}
}
#ifdef _GLIBCXX_PARALLEL
__gnu_parallel::sort( edges.begin(), edges.end() );
#else
sort( edges.begin(), edges.end() );
#endif
}
private:
double _Timestamp() {
struct timeval tp;
gettimeofday(&tp, NULL);
return double(tp.tv_sec) + tp.tv_usec / 1000000.;
}
void BuildOutgoingGraph() {
//sort edges by source
#ifdef _GLIBCXX_PARALLEL
__gnu_parallel::sort( _graph.begin(), _graph.end(), Edge::CompareBySource );
#else
sort( _graph.begin(), _graph.end(), Edge::CompareBySource );
#endif
try {
_firstEdge.resize( _numNodes + 1 );
} catch(...) {
cerr << "Not enough RAM on machine" << endl;
return;
}
_firstEdge[0] = 0;
for ( NodeID i = 0, node = 0; i < ( NodeID ) _graph.size(); i++ ) {
while ( _graph[i].source != node )
_firstEdge[++node] = i;
if ( i == ( NodeID ) _graph.size() - 1 )
while ( node < _numNodes )
_firstEdge[++node] = ( int ) _graph.size();
}
}
void RemoveUselessShortcuts() {
int maxThreads = omp_get_max_threads();
std::vector < _ThreadData* > threadData;
for ( int threadNum = 0; threadNum < maxThreads; ++threadNum ) {
threadData.push_back( new _ThreadData( _numNodes ) );
}
cout << "Scanning for useless shortcuts" << endl;
BuildOutgoingGraph();
#pragma omp parallel for
for ( int i = 0; i < ( int ) _graph.size(); i++ ) {
for ( unsigned edge = _firstEdge[_graph[i].source]; edge < _firstEdge[_graph[i].source + 1]; ++edge ) {
if ( edge == (unsigned)i )
continue;
if ( _graph[edge].target != _graph[i].target )
continue;
if ( _graph[edge].data.distance < _graph[i].data.distance )
continue;
_graph[edge].data.forward &= !_graph[i].data.forward;
_graph[edge].data.backward &= !_graph[i].data.backward;
}
if ( !_graph[i].data.forward && !_graph[i].data.backward )
continue;
//only remove shortcuts
if ( !_graph[i].data.shortcut )
continue;
if ( _graph[i].data.forward ) {
int result = _ComputeDistance( _graph[i].source, _graph[i].target, threadData[omp_get_thread_num()] );
if ( result < _graph[i].data.distance ) {
_graph[i].data.forward = false;
}
}
if ( _graph[i].data.backward ) {
int result = _ComputeDistance( _graph[i].target, _graph[i].source, threadData[omp_get_thread_num()] );
if ( result < _graph[i].data.distance ) {
_graph[i].data.backward = false;
}
}
}
cout << "Removing edges" << endl;
int useful = 0;
for ( int i = 0; i < ( int ) _graph.size(); i++ ) {
if ( !_graph[i].data.forward && !_graph[i].data.backward && _graph[i].data.shortcut )
continue;
_graph[useful] = _graph[i];
useful++;
}
cout << "Removed " << _graph.size() - useful << " useless shortcuts" << endl;
_graph.resize( useful );
for ( int threadNum = 0; threadNum < maxThreads; ++threadNum ) {
delete threadData[threadNum];
}
}
void _ComputeStep( _Heap* heapForward, _Heap* heapBackward, bool forwardDirection, NodeID* middle, int* targetDistance ) {
const NodeID node = heapForward->DeleteMin();
const int distance = heapForward->GetKey( node );
if ( heapBackward->WasInserted( node ) ) {
const int newDistance = heapBackward->GetKey( node ) + distance;
if ( newDistance < *targetDistance ) {
*middle = node;
*targetDistance = newDistance;
}
}
if ( distance > *targetDistance ) {
heapForward->DeleteAll();
return;
}
for ( int edge = _firstEdge[node], endEdges = _firstEdge[node + 1]; edge != endEdges; ++edge ) {
const NodeID to = _graph[edge].target;
const int edgeWeight = _graph[edge].data.distance;
assert( edgeWeight > 0 );
const int toDistance = distance + edgeWeight;
if ( (forwardDirection ? _graph[edge].data.forward : _graph[edge].data.backward ) ) {
//New Node discovered -> Add to Heap + Node Info Storage
if ( !heapForward->WasInserted( to ) )
heapForward->Insert( to, toDistance, node );
//Found a shorter Path -> Update distance
else if ( toDistance < heapForward->GetKey( to ) ) {
heapForward->DecreaseKey( to, toDistance );
//new parent
heapForward->GetData( to ) = node;
}
}
}
}
int _ComputeDistance( NodeID source, NodeID target, _ThreadData * data, std::vector< NodeID >* path = NULL ) {
data->_heapForward->Clear();
data->_heapBackward->Clear();
//insert source into heap
data->_heapForward->Insert( source, 0, source );
data->_heapBackward->Insert( target, 0, target );
int targetDistance = (std::numeric_limits< int >::max)();
NodeID middle = (std::numeric_limits<NodeID>::max)();
while ( data->_heapForward->Size() + data->_heapBackward->Size() > 0 ) {
if ( data->_heapForward->Size() > 0 ) {
_ComputeStep( data->_heapForward, data->_heapBackward, true, &middle, &targetDistance );
}
if ( data->_heapBackward->Size() > 0 ) {
_ComputeStep( data->_heapBackward, data->_heapForward, false, &middle, &targetDistance );
}
}
return targetDistance;
}
NodeID _numNodes;
std::vector< Edge > _graph;
std::vector< unsigned > _firstEdge;
};
#endif // CONTRACTIONCLEANUP_H_INCLUDED
-570
View File
@@ -1,570 +0,0 @@
/*
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 CONTRACTOR_H_INCLUDED
#define CONTRACTOR_H_INCLUDED
#ifdef _GLIBCXX_PARALLEL
#include <parallel/algorithm>
#else
#include <algorithm>
#endif
#include <boost/shared_ptr.hpp>
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/BinaryHeap.h"
#include <ctime>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <limits>
#ifdef _OPEMP
#include <omp.h>
#endif
class Contractor {
private:
struct _EdgeBasedContractorEdgeData {
unsigned distance;
unsigned originalEdges;
unsigned via;
unsigned nameID;
bool shortcut;
bool forward;
bool backward;
short turnInstruction;
} data;
struct _HeapData {
bool target;
_HeapData() : target(false) {}
_HeapData( bool t ) : target(t) {}
};
typedef DynamicGraph< _EdgeBasedContractorEdgeData > _DynamicGraph;
typedef BinaryHeap< NodeID, NodeID, int, _HeapData> _Heap;
typedef _DynamicGraph::InputEdge _ImportEdge;
struct _ThreadData {
_Heap heap;
std::vector< _ImportEdge > insertedEdges;
std::vector< NodeID > neighbours;
_ThreadData( NodeID nodes ): heap( nodes ) {
}
};
struct _PriorityData {
int depth;
NodeID bias;
_PriorityData() : depth(0), bias(0) { }
};
struct _ContractionInformation {
int edgesDeleted;
int edgesAdded;
int originalEdgesDeleted;
int originalEdgesAdded;
_ContractionInformation() {
edgesAdded = edgesDeleted = originalEdgesAdded = originalEdgesDeleted = 0;
}
};
struct _NodePartitionor {
bool operator()( std::pair< NodeID, bool > nodeData ) {
return !nodeData.second;
}
};
public:
template< class InputEdge >
Contractor( int nodes, std::vector< InputEdge >& inputEdges, unsigned eqf = 2, unsigned oqf = 1, unsigned df = 1) : edgeQuotionFactor(eqf), originalQuotientFactor(oqf), depthFactor(df) {
std::vector< _ImportEdge > edges;
edges.reserve( 2 * inputEdges.size() );
for ( typename std::vector< InputEdge >::const_iterator i = inputEdges.begin(), e = inputEdges.end(); i != e; ++i ) {
_ImportEdge edge;
edge.source = i->source();
edge.target = i->target();
edge.data.distance = (std::max)((int)i->weight(), 1 );
assert( edge.data.distance > 0 );
#ifndef NDEBUG
if ( edge.data.distance > 24 * 60 * 60 * 10 ) {
std::cout << "Edge Weight too large -> May lead to invalid CH" << std::endl;
continue;
}
#endif
edge.data.shortcut = false;
edge.data.nameID = i->getNameIDOfTurnTarget();
edge.data.via = i->via();
edge.data.turnInstruction = i->turnInstruction();
edge.data.forward = i->isForward();
edge.data.backward = i->isBackward();
edge.data.originalEdges = 1;
edges.push_back( edge );
std::swap( edge.source, edge.target );
edge.data.forward = i->isBackward();
edge.data.backward = i->isForward();
edges.push_back( edge );
}
//remove data from memory
inputEdges.clear();
std::vector< InputEdge >().swap( inputEdges );
#ifdef _GLIBCXX_PARALLEL
__gnu_parallel::sort( edges.begin(), edges.end() );
#else
sort( edges.begin(), edges.end() );
#endif
NodeID edge = 0;
for ( NodeID i = 0; i < edges.size(); ) {
const NodeID source = edges[i].source;
const NodeID target = edges[i].target;
const NodeID via = edges[i].data.via;
const short turnType = edges[i].data.turnInstruction;
//remove eigenloops
if ( source == target ) {
i++;
continue;
}
_ImportEdge forwardEdge;
_ImportEdge backwardEdge;
forwardEdge.source = backwardEdge.source = source;
forwardEdge.target = backwardEdge.target = target;
forwardEdge.data.forward = backwardEdge.data.backward = true;
forwardEdge.data.backward = backwardEdge.data.forward = false;
forwardEdge.data.turnInstruction = backwardEdge.data.turnInstruction = turnType;
forwardEdge.data.nameID = backwardEdge.data.nameID = edges[i].data.nameID;
forwardEdge.data.shortcut = backwardEdge.data.shortcut = false;
forwardEdge.data.via = backwardEdge.data.via = via;
forwardEdge.data.originalEdges = backwardEdge.data.originalEdges = 1;
forwardEdge.data.distance = backwardEdge.data.distance = std::numeric_limits< int >::max();
//remove parallel edges
while ( i < edges.size() && edges[i].source == source && edges[i].target == target ) {
if ( edges[i].data.forward )
forwardEdge.data.distance = std::min( edges[i].data.distance, forwardEdge.data.distance );
if ( edges[i].data.backward )
backwardEdge.data.distance = std::min( edges[i].data.distance, backwardEdge.data.distance );
i++;
}
//merge edges (s,t) and (t,s) into bidirectional edge
if ( forwardEdge.data.distance == backwardEdge.data.distance ) {
if ( (int)forwardEdge.data.distance != std::numeric_limits< int >::max() ) {
forwardEdge.data.backward = true;
edges[edge++] = forwardEdge;
}
} else { //insert seperate edges
if ( ((int)forwardEdge.data.distance) != std::numeric_limits< int >::max() ) {
edges[edge++] = forwardEdge;
}
if ( (int)backwardEdge.data.distance != std::numeric_limits< int >::max() ) {
edges[edge++] = backwardEdge;
}
}
}
std::cout << "ok" << std::endl << "merged " << edges.size() - edge << " edges out of " << edges.size() << std::endl;
edges.resize( edge );
_graph.reset( new _DynamicGraph( nodes, edges ) );
std::vector< _ImportEdge >().swap( edges );
}
~Contractor() { }
void Run() {
const NodeID numberOfNodes = _graph->GetNumberOfNodes();
Percent p (numberOfNodes);
unsigned maxThreads = omp_get_max_threads();
std::vector < _ThreadData* > threadData;
for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
threadData.push_back( new _ThreadData( numberOfNodes ) );
}
std::cout << "Contractor is using " << maxThreads << " threads" << std::endl;
NodeID levelID = 0;
std::vector< std::pair< NodeID, bool > > remainingNodes( numberOfNodes );
std::vector< double > nodePriority( numberOfNodes );
std::vector< _PriorityData > nodeData( numberOfNodes );
//initialize the variables
#pragma omp parallel for schedule ( guided )
for ( int x = 0; x < ( int ) numberOfNodes; ++x )
remainingNodes[x].first = x;
std::random_shuffle( remainingNodes.begin(), remainingNodes.end() );
for ( int x = 0; x < ( int ) numberOfNodes; ++x )
nodeData[remainingNodes[x].first].bias = x;
std::cout << "initializing elimination PQ ..." << std::flush;
#pragma omp parallel
{
_ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp parallel for schedule ( guided )
for ( int x = 0; x < ( int ) numberOfNodes; ++x ) {
nodePriority[x] = _Evaluate( data, &nodeData[x], x );
}
}
std::cout << "ok" << std::endl << "preprocessing ..." << std::flush;
while ( levelID < numberOfNodes ) {
const int last = ( int ) remainingNodes.size();
#pragma omp parallel
{
//determine independent node set
_ThreadData* const data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided )
for ( int i = 0; i < last; ++i ) {
const NodeID node = remainingNodes[i].first;
remainingNodes[i].second = _IsIndependent( nodePriority, nodeData, data, node );
}
}
_NodePartitionor functor;
const std::vector < std::pair < NodeID, bool > >::const_iterator first = stable_partition( remainingNodes.begin(), remainingNodes.end(), functor );
const int firstIndependent = first - remainingNodes.begin();
//contract independent nodes
#pragma omp parallel
{
_ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) nowait
for ( int position = firstIndependent ; position < last; ++position ) {
NodeID x = remainingNodes[position].first;
_Contract< false > ( data, x );
nodePriority[x] = -1;
}
std::sort( data->insertedEdges.begin(), data->insertedEdges.end() );
}
#pragma omp parallel
{
_ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) nowait
for ( int position = firstIndependent ; position < last; ++position ) {
NodeID x = remainingNodes[position].first;
_DeleteIncomingEdges( data, x );
}
}
//insert new edges
for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
_ThreadData& data = *threadData[threadNum];
for ( int i = 0; i < ( int ) data.insertedEdges.size(); ++i ) {
const _ImportEdge& edge = data.insertedEdges[i];
_graph->InsertEdge( edge.source, edge.target, edge.data );
}
std::vector< _ImportEdge >().swap( data.insertedEdges );
}
//update priorities
#pragma omp parallel
{
_ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) nowait
for ( int position = firstIndependent ; position < last; ++position ) {
NodeID x = remainingNodes[position].first;
_UpdateNeighbours( &nodePriority, &nodeData, data, x );
}
}
//remove contracted nodes from the pool
levelID += last - firstIndependent;
remainingNodes.resize( firstIndependent );
std::vector< std::pair< NodeID, bool > >( remainingNodes ).swap( remainingNodes );
p.printStatus(levelID);
}
for ( unsigned threadNum = 0; threadNum < maxThreads; threadNum++ ) {
delete threadData[threadNum];
}
}
template< class Edge >
void GetEdges( std::vector< Edge >& edges ) {
NodeID numberOfNodes = _graph->GetNumberOfNodes();
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; edge++ ) {
const NodeID target = _graph->GetTarget( edge );
const _EdgeBasedContractorEdgeData& data = _graph->GetEdgeData( edge );
Edge newEdge;
newEdge.source = node;
newEdge.target = target;
newEdge.data.distance = data.distance;
newEdge.data.shortcut = data.shortcut;
newEdge.data.via = data.via;
newEdge.data.nameID1 = data.nameID;
newEdge.data.turnInstruction = data.turnInstruction;
newEdge.data.forward = data.forward;
newEdge.data.backward = data.backward;
edges.push_back( newEdge );
}
}
}
private:
void _Dijkstra( const int maxDistance, const unsigned numTargets, const int maxNodes, _ThreadData* data ){
_Heap& heap = data->heap;
int nodes = 0;
unsigned targetsFound = 0;
while ( heap.Size() > 0 ) {
const NodeID node = heap.DeleteMin();
const int distance = heap.GetKey( node );
if ( nodes++ > maxNodes )
return;
//Destination settled?
if ( distance > maxDistance )
return;
if ( heap.GetData( node ).target ) {
targetsFound++;
if ( targetsFound >= numTargets )
return;
}
//iterate over all edges of node
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) {
const _EdgeBasedContractorEdgeData& data = _graph->GetEdgeData( edge );
if ( !data.forward )
continue;
const NodeID to = _graph->GetTarget( edge );
const int toDistance = distance + data.distance;
//New Node discovered -> Add to Heap + Node Info Storage
if ( !heap.WasInserted( to ) )
heap.Insert( to, toDistance, _HeapData() );
//Found a shorter Path -> Update distance
else if ( toDistance < heap.GetKey( to ) ) {
heap.DecreaseKey( to, toDistance );
//heap.GetData( to ).hops = hops + 1;
}
}
}
}
double _Evaluate( _ThreadData* const data, _PriorityData* const nodeData, NodeID node ){
_ContractionInformation stats;
//perform simulated contraction
_Contract< true > ( data, node, &stats );
// Result will contain the priority
if ( stats.edgesDeleted == 0 || stats.originalEdgesDeleted == 0 )
return depthFactor * nodeData->depth;
return edgeQuotionFactor * ((( double ) stats.edgesAdded ) / stats.edgesDeleted ) + originalQuotientFactor * ((( double ) stats.originalEdgesAdded ) / stats.originalEdgesDeleted ) + depthFactor * nodeData->depth;
}
template< bool Simulate > bool _Contract( _ThreadData* data, NodeID node, _ContractionInformation* stats = NULL ) {
_Heap& heap = data->heap;
int insertedEdgesSize = data->insertedEdges.size();
std::vector< _ImportEdge >& insertedEdges = data->insertedEdges;
for ( _DynamicGraph::EdgeIterator inEdge = _graph->BeginEdges( node ), endInEdges = _graph->EndEdges( node ); inEdge != endInEdges; ++inEdge ) {
const _EdgeBasedContractorEdgeData& inData = _graph->GetEdgeData( inEdge );
const NodeID source = _graph->GetTarget( inEdge );
if ( Simulate ) {
assert( stats != NULL );
stats->edgesDeleted++;
stats->originalEdgesDeleted += inData.originalEdges;
}
if ( !inData.backward )
continue;
heap.Clear();
heap.Insert( source, 0, _HeapData() );
if ( node != source )
heap.Insert( node, inData.distance, _HeapData() );
int maxDistance = 0;
unsigned numTargets = 0;
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
const _EdgeBasedContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
if ( !outData.forward )
continue;
const NodeID target = _graph->GetTarget( outEdge );
const int pathDistance = inData.distance + outData.distance;
maxDistance = std::max( maxDistance, pathDistance );
if ( !heap.WasInserted( target ) ) {
heap.Insert( target, pathDistance, _HeapData( true ) );
numTargets++;
} else if ( pathDistance < heap.GetKey( target ) ) {
heap.DecreaseKey( target, pathDistance );
}
}
if( Simulate )
_Dijkstra( maxDistance, numTargets, 500, data );
else
_Dijkstra( maxDistance, numTargets, 1000, data );
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
const _EdgeBasedContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
if ( !outData.forward )
continue;
const NodeID target = _graph->GetTarget( outEdge );
const int pathDistance = inData.distance + outData.distance;
const int distance = heap.GetKey( target );
if ( pathDistance <= distance ) {
if ( Simulate ) {
assert( stats != NULL );
stats->edgesAdded+=2;
stats->originalEdgesAdded += 2* ( outData.originalEdges + inData.originalEdges );
} else {
_ImportEdge newEdge;
newEdge.source = source;
newEdge.target = target;
newEdge.data.distance = pathDistance;
newEdge.data.forward = true;
newEdge.data.backward = false;
newEdge.data.via = node;
newEdge.data.shortcut = true;
newEdge.data.turnInstruction = inData.turnInstruction;
newEdge.data.originalEdges = outData.originalEdges + inData.originalEdges;
insertedEdges.push_back( newEdge );
std::swap( newEdge.source, newEdge.target );
newEdge.data.forward = false;
newEdge.data.backward = true;
insertedEdges.push_back( newEdge );
}
}
}
}
if ( !Simulate ) {
for ( int i = insertedEdgesSize, iend = insertedEdges.size(); i < iend; i++ ) {
bool found = false;
for ( int other = i + 1 ; other < iend ; ++other ) {
if ( insertedEdges[other].source != insertedEdges[i].source )
continue;
if ( insertedEdges[other].target != insertedEdges[i].target )
continue;
if ( insertedEdges[other].data.distance != insertedEdges[i].data.distance )
continue;
if ( insertedEdges[other].data.shortcut != insertedEdges[i].data.shortcut )
continue;
insertedEdges[other].data.forward |= insertedEdges[i].data.forward;
insertedEdges[other].data.backward |= insertedEdges[i].data.backward;
found = true;
break;
}
if ( !found )
insertedEdges[insertedEdgesSize++] = insertedEdges[i];
}
insertedEdges.resize( insertedEdgesSize );
}
return true;
}
bool _DeleteIncomingEdges( _ThreadData* data, NodeID node ) {
std::vector< NodeID >& neighbours = data->neighbours;
neighbours.clear();
//find all neighbours
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ) ; e < _graph->EndEdges( node ) ; ++e ) {
const NodeID u = _graph->GetTarget( e );
if ( u == node )
continue;
neighbours.push_back( u );
}
//eliminate duplicate entries ( forward + backward edges )
std::sort( neighbours.begin(), neighbours.end() );
neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
for ( int i = 0, e = ( int ) neighbours.size(); i < e; ++i ) {
const NodeID u = neighbours[i];
_graph->DeleteEdgesTo( u, node );
}
return true;
}
bool _UpdateNeighbours( std::vector< double >* priorities, std::vector< _PriorityData >* const nodeData, _ThreadData* const data, NodeID node ) {
std::vector< NodeID >& neighbours = data->neighbours;
neighbours.clear();
//find all neighbours
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ) ; e < _graph->EndEdges( node ) ; ++e ) {
const NodeID u = _graph->GetTarget( e );
if ( u == node )
continue;
neighbours.push_back( u );
( *nodeData )[u].depth = (std::max)(( *nodeData )[node].depth + 1, ( *nodeData )[u].depth );
}
//eliminate duplicate entries ( forward + backward edges )
std::sort( neighbours.begin(), neighbours.end() );
neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
for ( int i = 0, e = ( int ) neighbours.size(); i < e; ++i ) {
const NodeID u = neighbours[i];
( *priorities )[u] = _Evaluate( data, &( *nodeData )[u], u );
}
return true;
}
bool _IsIndependent( const std::vector< double >& priorities, const std::vector< _PriorityData >& nodeData, _ThreadData* const data, NodeID node ) {
const double priority = priorities[node];
std::vector< NodeID >& neighbours = data->neighbours;
neighbours.clear();
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ) ; e < _graph->EndEdges( node ) ; ++e ) {
const NodeID target = _graph->GetTarget( e );
const double targetPriority = priorities[target];
assert( targetPriority >= 0 );
//found a neighbour with lower priority?
if ( priority > targetPriority )
return false;
//tie breaking
if ( priority == targetPriority && nodeData[node].bias < nodeData[target].bias )
return false;
neighbours.push_back( target );
}
std::sort( neighbours.begin(), neighbours.end() );
neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
//examine all neighbours that are at most 2 hops away
for ( std::vector< NodeID >::const_iterator i = neighbours.begin(), lastNode = neighbours.end(); i != lastNode; ++i ) {
const NodeID u = *i;
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( u ) ; e < _graph->EndEdges( u ) ; ++e ) {
const NodeID target = _graph->GetTarget( e );
const double targetPriority = priorities[target];
assert( targetPriority >= 0 );
//found a neighbour with lower priority?
if ( priority > targetPriority )
return false;
//tie breaking
if ( priority == targetPriority && nodeData[node].bias < nodeData[target].bias )
return false;
}
}
return true;
}
boost::shared_ptr<_DynamicGraph> _graph;
unsigned edgeQuotionFactor;
unsigned originalQuotientFactor;
unsigned depthFactor;
};
#endif // CONTRACTOR_H_INCLUDED
-234
View File
@@ -1,234 +0,0 @@
/*
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.
*/
#ifdef _GLIBCXX_PARALLEL
#include <parallel/algorithm>
#else
#include <algorithm>
#endif
#include <boost/foreach.hpp>
#include "EdgeBasedGraphFactory.h"
template<>
EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector<NodeBasedEdge> & inputEdges, std::vector<_Restriction> & irs, std::vector<NodeInfo> & nI)
: inputRestrictions(irs), inputNodeInfoList(nI) {
#ifdef _GLIBCXX_PARALLEL
__gnu_parallel::sort(inputRestrictions.begin(), inputRestrictions.end(), CmpRestrictionByFrom);
#else
std::sort(inputRestrictions.begin(), inputRestrictions.end(), CmpRestrictionByFrom);
#endif
std::vector< _NodeBasedEdge > edges;
edges.reserve( 2 * inputEdges.size() );
for ( typename std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(), e = inputEdges.end(); i != e; ++i ) {
_NodeBasedEdge edge;
edge.source = i->source();
edge.target = i->target();
if(edge.source == edge.target)
continue;
edge.data.distance = (std::max)((int)i->weight(), 1 );
assert( edge.data.distance > 0 );
edge.data.shortcut = false;
edge.data.roundabout = i->isRoundabout();
edge.data.nameID = i->name();
edge.data.type = i->type();
edge.data.forward = i->isForward();
edge.data.backward = i->isBackward();
edge.data.edgeBasedNodeID = edges.size();
edges.push_back( edge );
std::swap( edge.source, edge.target );
if( edge.data.backward ) {
edge.data.forward = i->isBackward();
edge.data.backward = i->isForward();
edge.data.edgeBasedNodeID = edges.size();
edges.push_back( edge );
}
}
#ifdef _GLIBCXX_PARALLEL
__gnu_parallel::sort( edges.begin(), edges.end() );
#else
sort( edges.begin(), edges.end() );
#endif
_nodeBasedGraph.reset(new _NodeBasedDynamicGraph( nodes, edges ));
INFO("Converted " << inputEdges.size() << " node-based edges into " << _nodeBasedGraph->GetNumberOfEdges() << " edge-based nodes.");
}
template<>
void EdgeBasedGraphFactory::GetEdgeBasedEdges( std::vector< EdgeBasedEdge >& outputEdgeList ) {
GUARANTEE(0 == outputEdgeList.size(), "Vector passed to EdgeBasedGraphFactory::GetEdgeBasedEdges(..) is not empty");
GUARANTEE(0 != edgeBasedEdges.size(), "No edges in edge based graph");
edgeBasedEdges.swap(outputEdgeList);
}
void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes) {
for(unsigned i = 0; i < edgeBasedNodes.size(); ++i)
nodes.push_back(edgeBasedNodes[i]);
}
void EdgeBasedGraphFactory::Run() {
INFO("Generating Edge based representation of input data");
std::vector<_Restriction>::iterator restrictionIterator = inputRestrictions.begin();
Percent p(_nodeBasedGraph->GetNumberOfNodes());
int numberOfResolvedRestrictions(0);
int nodeBasedEdgeCounter(0);
//Loop over all nodes u. Three nested loop look super-linear, but we are dealing with a number linear in the turns only.
for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
//loop over all adjacent edge (u,v)
while(restrictionIterator->fromNode < u && inputRestrictions.end() != restrictionIterator) {
++restrictionIterator;
}
for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
++nodeBasedEdgeCounter;
_NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
//loop over all reachable edges (v,w)
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
_NodeBasedDynamicGraph::NodeIterator w = _nodeBasedGraph->GetTarget(e2);
//if (u,v,w) is a forbidden turn, continue
bool isTurnProhibited = false;
if( u != w ) { //only add an edge if turn is not a U-turn
if(u == restrictionIterator->fromNode) {
std::vector<_Restriction>::iterator secondRestrictionIterator = restrictionIterator;
do {
if( v == secondRestrictionIterator->viaNode && w == secondRestrictionIterator->toNode) {
isTurnProhibited = true;
}
++secondRestrictionIterator;
} while(u == secondRestrictionIterator->fromNode);
}
if( !isTurnProhibited ) { //only add an edge if turn is not prohibited
//new costs for edge based edge (e1, e2) = cost (e1) + tc(e1,e2)
const _NodeBasedDynamicGraph::NodeIterator edgeBasedSource = _nodeBasedGraph->GetEdgeData(e1).edgeBasedNodeID;
// INFO("edgeBasedSource: " << edgeBasedSource);
if(edgeBasedSource > _nodeBasedGraph->GetNumberOfEdges()) {
ERR("edgeBasedTarget" << edgeBasedSource << ">" << _nodeBasedGraph->GetNumberOfEdges());
}
const _NodeBasedDynamicGraph::NodeIterator edgeBasedTarget = _nodeBasedGraph->GetEdgeData(e2).edgeBasedNodeID;
// INFO("edgeBasedTarget: " << edgeBasedTarget);
if(edgeBasedTarget > _nodeBasedGraph->GetNumberOfEdges()) {
ERR("edgeBasedTarget" << edgeBasedTarget << ">" << _nodeBasedGraph->GetNumberOfEdges());
}
//incorporate turn costs, this is just a simple model and can (read: must) be extended
double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]);
unsigned distance = (int)( _nodeBasedGraph->GetEdgeData(e1).distance *(1+std::abs((angle-180.)/180.)));
unsigned nameID = _nodeBasedGraph->GetEdgeData(e2).nameID;
short turnInstruction = AnalyzeTurn(u, v, w);
//create edge-based graph edge
//EdgeBasedEdge(NodeID s, NodeID t, NodeID v, unsigned n1, EdgeWeight w, bool f, bool b, short ty)
EdgeBasedEdge newEdge(edgeBasedSource, edgeBasedTarget, v, nameID, distance, true, false, turnInstruction);
edgeBasedEdges.push_back(newEdge);
EdgeBasedNode currentNode;
if(_nodeBasedGraph->GetEdgeData(e1).type != 14) {
currentNode.nameID = _nodeBasedGraph->GetEdgeData(e1).nameID;
currentNode.lat1 = inputNodeInfoList[u].lat;
currentNode.lon1 = inputNodeInfoList[u].lon;
currentNode.lat2 = inputNodeInfoList[v].lat;
currentNode.lon2 = inputNodeInfoList[v].lon;
currentNode.id = edgeBasedSource;
currentNode.weight = _nodeBasedGraph->GetEdgeData(e1).distance;
edgeBasedNodes.push_back(currentNode);
}
} else {
++numberOfResolvedRestrictions;
}
}
}
}
p.printIncrement();
}
std::sort(edgeBasedNodes.begin(), edgeBasedNodes.end());
edgeBasedNodes.erase( std::unique(edgeBasedNodes.begin(), edgeBasedNodes.end()), edgeBasedNodes.end() );
INFO("Node-based graph contains " << nodeBasedEdgeCounter << " edges");
INFO("Edge-based graph contains " << edgeBasedEdges.size() << " edges, blowup is " << (double)edgeBasedEdges.size()/(double)nodeBasedEdgeCounter);
INFO("Edge-based graph obeys " << numberOfResolvedRestrictions << " turn restrictions, " << (inputRestrictions.size() - numberOfResolvedRestrictions )<< " skipped.");
INFO("Generated " << edgeBasedNodes.size() << " edge based nodes");
}
short EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const {
_NodeBasedDynamicGraph::EdgeIterator edge1 = _nodeBasedGraph->FindEdge(u, v);
_NodeBasedDynamicGraph::EdgeIterator edge2 = _nodeBasedGraph->FindEdge(v, w);
_NodeBasedDynamicGraph::EdgeData & data1 = _nodeBasedGraph->GetEdgeData(edge1);
_NodeBasedDynamicGraph::EdgeData & data2 = _nodeBasedGraph->GetEdgeData(edge2);
double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]);
//roundabouts need to be handled explicitely
if(data1.roundabout && data2.roundabout) {
//Is a turn possible? If yes, we stay on the roundabout!
if( 1 == (_nodeBasedGraph->EndEdges(v) - _nodeBasedGraph->BeginEdges(v)) ) {
//No turn possible.
return TurnInstructions.NoTurn;
} else {
return TurnInstructions.StayOnRoundAbout;
}
}
//Does turn start or end on roundabout?
if(data1.roundabout || data2.roundabout) {
//We are entering the roundabout
if( (!data1.roundabout) && data2.roundabout)
return TurnInstructions.EnterRoundAbout;
//We are leaving the roundabout
if(data1.roundabout && (!data2.roundabout) )
return TurnInstructions.LeaveRoundAbout;
}
//If street names stay the same and if we are certain that it is not a roundabout, we skip it.
if(data1.nameID == data2.nameID)
return TurnInstructions.NoTurn;
return TurnInstructions.GetTurnDirectionOfInstruction(angle);
}
unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
return edgeBasedEdges.size();
}
EdgeBasedGraphFactory::~EdgeBasedGraphFactory() {
}
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
template<class CoordinateT>
double EdgeBasedGraphFactory::GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const {
const int v1x = A.lon - C.lon;
const int v1y = A.lat - C.lat;
const int v2x = B.lon - C.lon;
const int v2y = B.lat - C.lat;
double angle = (atan2((double)v2y,v2x) - atan2((double)v1y,v1x) )*180/M_PI;
while(angle < 0)
angle += 360;
return angle;
}
-104
View File
@@ -1,104 +0,0 @@
/*
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.
*/
/*
* This class constructs the edge base representation of a graph from a given node based edge list
*/
#ifndef EDGEBASEDGRAPHFACTORY_H_
#define EDGEBASEDGRAPHFACTORY_H_
#include <boost/shared_ptr.hpp>
#include <vector>
#include "../typedefs.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/ExtractorStructs.h"
#include "../DataStructures/ImportEdge.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/TurnInstructions.h"
class EdgeBasedGraphFactory {
private:
struct _NodeBasedEdgeData {
int distance;
unsigned edgeBasedNodeID;
unsigned nameID;
bool shortcut:1;
bool forward:1;
bool backward:1;
bool roundabout:1;
short type;
} data;
struct _EdgeBasedEdgeData {
int distance;
unsigned via;
unsigned nameID;
bool forward;
bool backward;
short turnInstruction;
};
typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph;
typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge;
public:
struct EdgeBasedNode {
bool operator<(const EdgeBasedNode & other) const {
return other.id < id;
}
bool operator==(const EdgeBasedNode & other) const {
return id == other.id;
}
int lat1;
int lat2;
int lon1;
int lon2;
NodeID id;
NodeID nameID;
unsigned weight;
};
private:
boost::shared_ptr<_NodeBasedDynamicGraph> _nodeBasedGraph;
std::vector<_Restriction> & inputRestrictions;
std::vector<NodeInfo> & inputNodeInfoList;
std::vector<EdgeBasedEdge> edgeBasedEdges;
std::vector<EdgeBasedNode> edgeBasedNodes;
template<class CoordinateT>
double GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const;
public:
template< class InputEdgeT >
explicit EdgeBasedGraphFactory(int nodes, std::vector<InputEdgeT> & inputEdges, std::vector<_Restriction> & inputRestrictions, std::vector<NodeInfo> & nI);
virtual ~EdgeBasedGraphFactory();
void Run();
template< class ImportEdgeT >
void GetEdgeBasedEdges( std::vector< ImportEdgeT >& edges );
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
short AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const;
unsigned GetNumberOfNodes() const;
};
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
-33
View File
@@ -1,33 +0,0 @@
/*
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 BASEPARSER_H_
#define BASEPARSER_H_
template<typename NodeT, typename RestrictionT, typename WayT>
class BaseParser {
public:
virtual ~BaseParser() {}
virtual bool Init() = 0;
virtual bool RegisterCallbacks(bool (*nodeCallbackPointer)(NodeT), bool (*restrictionCallbackPointer)(RestrictionT), bool (*wayCallbackPointer)(WayT), bool (*addressCallbackPointer)(NodeT, HashTable<std::string, std::string>)) = 0;
virtual bool Parse() = 0;
};
#endif /* BASEPARSER_H_ */
-293
View File
@@ -1,293 +0,0 @@
/*
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 BINARYHEAP_H_INCLUDED
#define BINARYHEAP_H_INCLUDED
//Not compatible with non contiguous node ids
#include <cassert>
#include <limits>
#include <vector>
#include <algorithm>
#include <map>
#include <google/dense_hash_map>
#include <google/sparse_hash_map>
#include <google/sparsetable>
template< typename NodeID, typename Key >
class ArrayStorage {
public:
ArrayStorage( size_t size ) : positions( new Key[size] ) {
memset(positions, 0, size*sizeof(Key));
}
~ArrayStorage() {
delete[] positions;
}
Key &operator[]( NodeID node ) {
return positions[node];
}
void Clear() {}
private:
Key* positions;
};
template< typename NodeID, typename Key >
class MapStorage {
public:
MapStorage( size_t size = 0 ) {}
Key &operator[]( NodeID node ) {
return nodes[node];
}
void Clear() {
nodes.clear();
}
private:
std::map< NodeID, Key > nodes;
};
template< typename NodeID, typename Key >
class DenseStorage {
public:
DenseStorage( size_t size = 0 ) { nodes.set_empty_key(UINT_MAX); }
Key &operator[]( NodeID node ) {
return nodes[node];
}
void Clear() {
nodes.clear();
}
private:
google::dense_hash_map< NodeID, Key > nodes;
};
template< typename NodeID, typename Key >
class SparseStorage {
public:
SparseStorage( size_t size = 0 ) { }
Key &operator[]( NodeID node ) {
return nodes[node];
}
void Clear() {
nodes.clear();
}
private:
google::sparse_hash_map< NodeID, Key > nodes;
};
template< typename NodeID, typename Key >
class SparseTableStorage : public google::sparsetable<NodeID> {
public:
SparseTableStorage(size_t n) : google::sparsetable<NodeID>(n){ }
void Clear() {
google::sparsetable<NodeID>::clear();
}
};
template<typename NodeID = unsigned>
struct _SimpleHeapData {
NodeID parent;
_SimpleHeapData( NodeID p ) : parent(p) { }
};
template < typename NodeID, typename Key, typename Weight, typename Data, typename IndexStorage = ArrayStorage<NodeID, NodeID> >
class BinaryHeap {
private:
BinaryHeap( const BinaryHeap& right );
void operator=( const BinaryHeap& right );
public:
typedef Weight WeightType;
typedef Data DataType;
BinaryHeap( size_t maxID )
: nodeIndex( maxID ) {
Clear();
}
void Clear() {
heap.resize( 1 );
insertedNodes.clear();
heap[0].weight = std::numeric_limits< Weight >::min();
nodeIndex.Clear();
}
Key Size() const {
return ( Key )( heap.size() - 1 );
}
void Insert( NodeID node, Weight weight, const Data &data ) {
HeapElement element;
element.index = ( NodeID ) insertedNodes.size();
element.weight = weight;
const Key key = ( Key ) heap.size();
heap.push_back( element );
insertedNodes.push_back( HeapNode( node, key, weight, data ) );
nodeIndex[node] = element.index;
Upheap( key );
CheckHeap();
}
Data& GetData( NodeID node ) {
const Key index = nodeIndex[node];
return insertedNodes[index].data;
}
Weight& GetKey( NodeID node ) {
const Key index = nodeIndex[node];
return insertedNodes[index].weight;
}
bool WasRemoved( NodeID node ) {
assert( WasInserted( node ) );
const Key index = nodeIndex[node];
return insertedNodes[index].key == 0;
}
bool WasInserted( NodeID node ) {
const Key index = nodeIndex[node];
if ( index >= ( Key ) insertedNodes.size() )
return false;
return insertedNodes[index].node == node;
}
NodeID Min() const {
assert( heap.size() > 1 );
return insertedNodes[heap[1].index].node;
}
NodeID DeleteMin() {
assert( heap.size() > 1 );
const Key removedIndex = heap[1].index;
heap[1] = heap[heap.size()-1];
heap.pop_back();
if ( heap.size() > 1 )
Downheap( 1 );
insertedNodes[removedIndex].key = 0;
CheckHeap();
return insertedNodes[removedIndex].node;
}
void DeleteAll() {
for ( typename std::vector< HeapElement >::iterator i = heap.begin() + 1, iend = heap.end(); i != iend; ++i )
insertedNodes[i->index].key = 0;
heap.resize( 1 );
heap[0].weight = (std::numeric_limits< Weight >::min)();
}
void DecreaseKey( NodeID node, Weight weight ) {
assert( UINT_MAX != node );
const Key index = nodeIndex[node];
Key key = insertedNodes[index].key;
assert ( key >= 0 );
insertedNodes[index].weight = weight;
heap[key].weight = weight;
Upheap( key );
CheckHeap();
}
private:
class HeapNode {
public:
HeapNode() {
}
HeapNode( NodeID n, Key k, Weight w, Data d )
: node( n ), key( k ), weight( w ), data( d ) {
}
NodeID node;
Key key;
Weight weight;
Data data;
};
struct HeapElement {
Key index;
Weight weight;
};
std::vector< HeapNode > insertedNodes;
std::vector< HeapElement > heap;
IndexStorage nodeIndex;
void Downheap( Key key ) {
const Key droppingIndex = heap[key].index;
const Weight weight = heap[key].weight;
Key nextKey = key << 1;
while ( nextKey < ( Key ) heap.size() ) {
const Key nextKeyOther = nextKey + 1;
if ( ( nextKeyOther < ( Key ) heap.size() )&& ( heap[nextKey].weight > heap[nextKeyOther].weight) )
nextKey = nextKeyOther;
if ( weight <= heap[nextKey].weight )
break;
heap[key] = heap[nextKey];
insertedNodes[heap[key].index].key = key;
key = nextKey;
nextKey <<= 1;
}
heap[key].index = droppingIndex;
heap[key].weight = weight;
insertedNodes[droppingIndex].key = key;
}
void Upheap( Key key ) {
const Key risingIndex = heap[key].index;
const Weight weight = heap[key].weight;
Key nextKey = key >> 1;
while ( heap[nextKey].weight > weight ) {
assert( nextKey != 0 );
heap[key] = heap[nextKey];
insertedNodes[heap[key].index].key = key;
key = nextKey;
nextKey >>= 1;
}
heap[key].index = risingIndex;
heap[key].weight = weight;
insertedNodes[risingIndex].key = key;
}
void CheckHeap() {
#ifndef NDEBUG
for ( Key i = 2; i < (Key) heap.size(); ++i ) {
assert( heap[i].weight >= heap[i >> 1].weight );
}
#endif
}
};
#endif //#ifndef BINARYHEAP_H_INCLUDED
-98
View File
@@ -1,98 +0,0 @@
/*
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 CONCURRENTQUEUE_H_INCLUDED
#define CONCURRENTQUEUE_H_INCLUDED
#include <queue>
#include <boost/signals2/mutex.hpp>
#include "../typedefs.h"
/*
Concurrent Queue written by Anthony Williams:
http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html
*/
template<typename Data>
class ConcurrentQueue {
public:
ConcurrentQueue(const size_t max_size)
: max_queue_size(max_size) {
}
void push(Data const& data) {
if (size_exceeded()) {
boost::mutex::scoped_lock qf_lock(queue_full_mutex);
queue_full_cv.wait(qf_lock);
}
boost::mutex::scoped_lock lock(queue_mutex);
internal_queue.push(data);
lock.unlock();
queue_cv.notify_one();
}
bool empty() const {
return internal_queue.empty();
}
bool try_pop(Data& popped_value) {
boost::mutex::scoped_lock lock(queue_mutex);
if(internal_queue.empty()) {
return false;
}
popped_value=internal_queue.front();
internal_queue.pop();
queue_full_cv.notify_one();
return true;
}
void wait_and_pop(Data& popped_value) {
boost::mutex::scoped_lock lock(queue_mutex);
while(internal_queue.empty()) {
queue_cv.wait(lock);
}
popped_value=internal_queue.front();
internal_queue.pop();
queue_full_cv.notify_one();
}
int size() const {
return static_cast<int>(internal_queue.size());
}
private:
std::queue<Data> internal_queue;
mutable boost::mutex queue_mutex;
mutable boost::mutex queue_full_mutex;
boost::condition_variable queue_cv;
boost::condition_variable queue_full_cv;
const size_t max_queue_size;
bool size_exceeded() const {
return internal_queue.size() >= max_queue_size;
}
};
#endif //#ifndef CONCURRENTQUEUE_H_INCLUDED
-237
View File
@@ -1,237 +0,0 @@
/*
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 DYNAMICGRAPH_H_INCLUDED
#define DYNAMICGRAPH_H_INCLUDED
#include <vector>
#include <algorithm>
#include <limits>
template< typename EdgeDataT>
class DynamicGraph {
public:
typedef EdgeDataT EdgeData;
typedef unsigned NodeIterator;
typedef unsigned EdgeIterator;
class InputEdge {
public:
NodeIterator source;
NodeIterator target;
EdgeDataT data;
bool operator<( const InputEdge& right ) const {
if ( source != right.source )
return source < right.source;
return target < right.target;
}
};
//Constructs an empty graph with a given number of nodes.
DynamicGraph( int nodes ) : m_numNodes(nodes), m_numEdges(0) {
m_nodes.reserve( m_numNodes );
m_nodes.resize( m_numNodes );
m_edges.reserve( m_numNodes * 1.2 );
m_edges.resize( m_numNodes );
}
DynamicGraph( int nodes, const std::vector< InputEdge > &graph )
{
m_numNodes = nodes;
m_numEdges = ( EdgeIterator ) graph.size();
m_nodes.reserve( m_numNodes );
m_nodes.resize( m_numNodes );
EdgeIterator edge = 0;
EdgeIterator position = 0;
for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
EdgeIterator lastEdge = edge;
while ( edge < m_numEdges && graph[edge].source == node ) {
++edge;
}
m_nodes[node].firstEdge = position;
m_nodes[node].edges = edge - lastEdge;
position += m_nodes[node].edges;
}
m_edges.reserve( position * 1.2 );
m_edges.resize( position );
edge = 0;
for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
for ( EdgeIterator i = m_nodes[node].firstEdge, e = m_nodes[node].firstEdge + m_nodes[node].edges; i != e; ++i ) {
m_edges[i].target = graph[edge].target;
m_edges[i].data = graph[edge].data;
GUARANTEE(graph[edge].data.distance > 0, "edge: " << edge << "(" << graph[edge].source << "," << graph[edge].target << ")=" << graph[edge].data.distance);
edge++;
}
}
}
~DynamicGraph(){ }
unsigned GetNumberOfNodes() const
{
return m_numNodes;
}
unsigned GetNumberOfEdges() const
{
return m_numEdges;
}
unsigned GetOutDegree( const NodeIterator &n ) const
{
return m_nodes[n].edges;
}
NodeIterator GetTarget( const EdgeIterator &e ) const
{
return NodeIterator( m_edges[e].target );
}
EdgeDataT &GetEdgeData( const EdgeIterator &e )
{
return m_edges[e].data;
}
const EdgeDataT &GetEdgeData( const EdgeIterator &e ) const
{
return m_edges[e].data;
}
EdgeIterator BeginEdges( const NodeIterator &n ) const
{
//assert( EndEdges( n ) - EdgeIterator( _nodes[n].firstEdge ) <= 100 );
return EdgeIterator( m_nodes[n].firstEdge );
}
EdgeIterator EndEdges( const NodeIterator &n ) const
{
return EdgeIterator( m_nodes[n].firstEdge + m_nodes[n].edges );
}
//adds an edge. Invalidates edge iterators for the source node
EdgeIterator InsertEdge( const NodeIterator &from, const NodeIterator &to, const EdgeDataT &data )
{
Node &node = m_nodes[from];
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
if ( newFirstEdge >= m_edges.size() || !isDummy( newFirstEdge ) ) {
if ( node.firstEdge != 0 && isDummy( node.firstEdge - 1 ) ) {
node.firstEdge--;
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
} else {
EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size();
unsigned newSize = node.edges * 1.2 + 2;
EdgeIterator requiredCapacity = newSize + m_edges.size();
EdgeIterator oldCapacity = m_edges.capacity();
if ( requiredCapacity >= oldCapacity ) {
m_edges.reserve( requiredCapacity * 1.1 );
}
m_edges.resize( m_edges.size() + newSize );
for ( EdgeIterator i = 0; i < node.edges; ++i ) {
m_edges[newFirstEdge + i ] = m_edges[node.firstEdge + i];
makeDummy( node.firstEdge + i );
}
for ( EdgeIterator i = node.edges + 1; i < newSize; i++ )
makeDummy( newFirstEdge + i );
node.firstEdge = newFirstEdge;
}
}
Edge &edge = m_edges[node.firstEdge + node.edges];
edge.target = to;
edge.data = data;
m_numEdges++;
node.edges++;
return EdgeIterator( node.firstEdge + node.edges );
}
//removes an edge. Invalidates edge iterators for the source node
void DeleteEdge( const NodeIterator source, const EdgeIterator &e ) {
Node &node = m_nodes[source];
--m_numEdges;
--node.edges;
const unsigned last = node.firstEdge + node.edges;
//swap with last edge
m_edges[e] = m_edges[last];
makeDummy( last );
}
//removes all edges (source,target)
int DeleteEdgesTo( const NodeIterator source, const NodeIterator target )
{
int deleted = 0;
for ( EdgeIterator i = BeginEdges( source ), iend = EndEdges( source ); i < iend - deleted; ++i ) {
if ( m_edges[i].target == target ) {
do {
deleted++;
m_edges[i] = m_edges[iend - deleted];
makeDummy( iend - deleted );
} while ( i < iend - deleted && m_edges[i].target == target );
}
}
#pragma omp atomic
m_numEdges -= deleted;
m_nodes[source].edges -= deleted;
return deleted;
}
//searches for a specific edge
EdgeIterator FindEdge( const NodeIterator &from, const NodeIterator &to ) const
{
for ( EdgeIterator i = BeginEdges( from ), iend = EndEdges( from ); i != iend; ++i ) {
if ( m_edges[i].target == to ) {
return i;
}
}
return EndEdges( from );
}
protected:
bool isDummy( EdgeIterator edge ) const
{
return m_edges[edge].target == (std::numeric_limits< NodeIterator >::max)();
}
void makeDummy( EdgeIterator edge )
{
m_edges[edge].target = (std::numeric_limits< NodeIterator >::max)();
}
struct Node {
//index of the first edge
EdgeIterator firstEdge;
//amount of edges
unsigned edges;
};
struct Edge {
NodeIterator target;
EdgeDataT data;
};
NodeIterator m_numNodes;
EdgeIterator m_numEdges;
std::vector< Node > m_nodes;
std::vector< Edge > m_edges;
};
#endif // DYNAMICGRAPH_H_INCLUDED
-196
View File
@@ -1,196 +0,0 @@
/*
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 EXTRACTORCALLBACKS_H_
#define EXTRACTORCALLBACKS_H_
#include <stxxl.h>
#include <vector>
#include "ExtractorStructs.h"
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
typedef stxxl::vector<_Node> STXXLNodeVector;
typedef stxxl::vector<_Edge> STXXLEdgeVector;
typedef stxxl::vector<_Address> STXXLAddressVector;
typedef stxxl::vector<string> STXXLStringVector;
typedef stxxl::vector<_RawRestrictionContainer> STXXLRestrictionsVector;
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
struct STXXLContainers {
STXXLNodeIDVector usedNodeIDs;
STXXLNodeVector allNodes;
STXXLEdgeVector allEdges;
STXXLAddressVector adressVector;
STXXLStringVector nameVector;
STXXLRestrictionsVector restrictionsVector;
STXXLWayIDStartEndVector wayStartEndVector;
};
class ExtractorCallbacks{
private:
Settings settings;
StringMap * stringMap;
STXXLContainers * externalMemory;
public:
ExtractorCallbacks(STXXLContainers * ext, Settings set, StringMap * strMap){
externalMemory = ext;
settings = set;
stringMap = strMap;
}
~ExtractorCallbacks() {
}
/** warning: caller needs to take care of synchronization! */
inline bool adressFunction(_Node n, HashTable<std::string, std::string> &keyVals) {
/*
std::string housenumber(keyVals.Find("addr:housenumber"));
std::string housename(keyVals.Find("addr:housename"));
std::string street(keyVals.Find("addr:street"));
std::string state(keyVals.Find("addr:state"));
std::string country(keyVals.Find("addr:country"));
std::string postcode(keyVals.Find("addr:postcode"));
std::string city(keyVals.Find("addr:city"));
if(housenumber != "" || housename != "" || street != "") {
if(housenumber == "")
housenumber = housename;
addressVector->push_back(_Address(n, housenumber, street, state, country, postcode, city));
}
*/
return true;
}
/** warning: caller needs to take care of synchronization! */
inline bool nodeFunction(_Node &n) {
externalMemory->allNodes.push_back(n);
return true;
}
inline bool restrictionFunction(_RawRestrictionContainer &r) {
externalMemory->restrictionsVector.push_back(r);
return true;
}
/** warning: caller needs to take care of synchronization! */
inline bool wayFunction(_Way &w) {
//Get the properties of the way.
std::string highway( w.keyVals.Find("highway") );
std::string name( w.keyVals.Find("name") );
std::string ref( w.keyVals.Find("ref"));
std::string oneway( w.keyVals.Find("oneway"));
std::string junction( w.keyVals.Find("junction") );
std::string route( w.keyVals.Find("route") );
double maxspeed( atoi(w.keyVals.Find("maxspeed").c_str()) );
std::string access( w.keyVals.Find("access") );
std::string accessClass( w.keyVals.Find(settings.accessTag) );
std::string man_made( w.keyVals.Find("man_made") );
std::string barrier( w.keyVals.Find("barrier") );
//Save the name of the way if it has one, ref has precedence over name tag.
if ( 0 < ref.length() )
w.name = ref;
else
if ( 0 < name.length() )
w.name = name;
if(junction == "roundabout") {
w.roundabout = true;
}
//Is the highway tag listed as usable way?
if(0 < settings[highway]) {
if(0 != maxspeed)
w.speed = maxspeed;
else
w.speed = settings[highway];
w.useful = true;
//Okay, do we have access to that way?
if(0 < access.size()) { //fastest way to check for non-empty string
//If access is forbidden, we don't want to route there.
if(access == "private" || access == "no" || access == "agricultural" || access == "forestry" || access == "delivery") { //Todo: this is still hard coded
w.access = false;
}
}
if("yes" == accessClass)
w.access = true;
else if("no" == accessClass)
w.access = false;
//Let's process oneway property, if speed profile obeys to it
if(oneway != "no" && oneway != "false" && oneway != "0" && settings.obeyOneways) {
//if oneway tag is in forward direction or if actually roundabout
if(junction == "roundabout" || oneway == "yes" || oneway == "true" || oneway == "1") {
w.direction = _Way::oneway;
} else {
if( oneway == "-1")
w.direction = _Way::opposite;
}
}
} else {
//Is the route tag listed as usable way in the profile?
if(settings[route] > 0 || settings[man_made] > 0) {
w.useful = true;
w.direction = _Way::oneway;
w.speed = settings[route];
w.direction = _Way::bidirectional;
}
}
if ( w.useful && w.access && (1 < w.path.size()) ) { //Only true if the way is specified by the speed profile
//TODO: type is not set, perhaps use a bimap'ed speed profile to do set the type correctly?
w.type = 1;
//Get the unique identifier for the street name
StringMap::const_iterator strit = stringMap->find(w.name);
if(strit == stringMap->end()) {
w.nameID = externalMemory->nameVector.size();
externalMemory->nameVector.push_back(w.name);
stringMap->insert(StringMap::value_type(w.name, w.nameID));
} else {
w.nameID = strit->second;
}
GUARANTEE(w.id != UINT_MAX, "found way with unknown type");
GUARANTEE(-1 != w.speed, "found way with unknown speed");
if ( w.direction == _Way::opposite ){
std::reverse( w.path.begin(), w.path.end() );
}
for(vector< NodeID >::size_type n = 0; n < w.path.size()-1; ++n) {
externalMemory->allEdges.push_back(_Edge(w.path[n], w.path[n+1], w.type, w.direction, w.speed, w.nameID, w.roundabout));
externalMemory->usedNodeIDs.push_back(w.path[n]);
}
externalMemory->usedNodeIDs.push_back(w.path[w.path.size()-1]);
//The following information is needed to identify start and end segments of restrictions
externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(w.id, w.path[0], w.path[1], w.path[w.path.size()-2], w.path[w.path.size()-1]));
}
return true;
}
};
#endif /* EXTRACTORCALLBACKS_H_ */
-359
View File
@@ -1,359 +0,0 @@
/*
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 EXTRACTORSTRUCTS_H_
#define EXTRACTORSTRUCTS_H_
#include <climits>
#include <string>
#include <boost/unordered_map.hpp>
#include "../typedefs.h"
#include "Util.h"
struct _PathData {
_PathData(NodeID no, unsigned na, unsigned tu, unsigned dur) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu) { }
NodeID node;
unsigned nameID;
unsigned durationOfSegment;
short turnInstruction;
};
typedef boost::unordered_map<std::string, NodeID> StringMap;
struct _Node : NodeInfo{
_Node(int _lat, int _lon, unsigned int _id) : NodeInfo(_lat, _lon, _id) {}
_Node() {}
static _Node min_value() {
return _Node(0,0,0);
}
static _Node max_value() {
return _Node((numeric_limits<int>::max)(), (numeric_limits<int>::max)(), (numeric_limits<unsigned int>::max)());
}
NodeID key() const {
return id;
}
};
struct _Coordinate {
int lat;
int lon;
_Coordinate () : lat(INT_MIN), lon(INT_MIN) {}
_Coordinate (int t, int n) : lat(t) , lon(n) {}
void Reset() {
lat = INT_MIN;
lon = INT_MIN;
}
bool isSet() const {
return (INT_MIN != lat) && (INT_MIN != lon);
}
};
inline ostream & operator<<(ostream & out, const _Coordinate & c){
out << "(" << c.lat << "," << c.lon << ")";
return out;
}
struct _Way {
_Way() : id(UINT_MAX), nameID(UINT_MAX) {
direction = _Way::notSure;
speed = -1;
type = -1;
useful = false;
access = true;
roundabout = false;
}
enum {
notSure = 0, oneway, bidirectional, opposite
} direction;
unsigned id;
unsigned nameID;
std::string name;
double speed;
short type;
bool useful;
bool access;
bool roundabout;
std::vector< NodeID > path;
HashTable<std::string, std::string> keyVals;
};
struct _Address {
_Address() {}
_Address(_Node n, std::string h, std::string str, std::string sta, std::string p, std::string ci, std::string co) {
node = n;
housenumber = h;
street = str;
state = sta;
postcode = p;
city = ci;
country = co;
}
_Node node;
std::string housenumber;
std::string street;
std::string state;
std::string postcode;
std::string city;
std::string country;
};
struct _Relation {
_Relation() : type(unknown){}
enum {
unknown = 0, ferry, turnRestriction
} type;
HashTable<std::string, std::string> keyVals;
};
struct _Edge {
_Edge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false) {};
_Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false) { }
_Edge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false) { }
_Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra) { }
NodeID start;
NodeID target;
short type;
short direction;
double speed;
unsigned nameID;
bool isRoundabout;
_Coordinate startCoord;
_Coordinate targetCoord;
static _Edge min_value() {
return _Edge(0,0);
}
static _Edge max_value() {
return _Edge((numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)());
}
};
struct _Restriction {
NodeID viaNode;
NodeID fromNode;
NodeID toNode;
struct bits { //mostly unused
char isOnly:1;
char unused1:1;
char unused2:1;
char unused3:1;
char unused4:1;
char unused5:1;
char unused6:1;
char unused7:1;
} flags;
_Restriction(NodeID vn) : viaNode(vn), fromNode(UINT_MAX), toNode(UINT_MAX) { }
_Restriction(bool isOnly = false) : viaNode(UINT_MAX), fromNode(UINT_MAX), toNode(UINT_MAX) {
flags.isOnly = isOnly;
}
};
inline bool CmpRestrictionByFrom ( _Restriction a, _Restriction b) { return (a.fromNode < b.fromNode); }
struct _RawRestrictionContainer {
_Restriction restriction;
EdgeID fromWay;
EdgeID toWay;
unsigned viaWay;
_RawRestrictionContainer(EdgeID f, EdgeID t, NodeID vn, unsigned vw) : fromWay(f), toWay(t), viaWay(vw) { restriction.viaNode = vn;}
_RawRestrictionContainer(bool isOnly = false) : fromWay(UINT_MAX), toWay(UINT_MAX), viaWay(UINT_MAX) { restriction.flags.isOnly = isOnly;}
static _RawRestrictionContainer min_value() {
return _RawRestrictionContainer((numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)());
}
static _RawRestrictionContainer max_value() {
return _RawRestrictionContainer((numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)());
}
};
struct CmpRestrictionContainerByFrom: public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
typedef _RawRestrictionContainer value_type;
bool operator () (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
return a.fromWay < b.fromWay;
}
value_type max_value() {
return _RawRestrictionContainer::max_value();
}
value_type min_value() {
return _RawRestrictionContainer::min_value();
}
};
struct CmpRestrictionContainerByTo: public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
typedef _RawRestrictionContainer value_type;
bool operator () (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
return a.toWay < b.toWay;
}
value_type max_value() {
return _RawRestrictionContainer::max_value();
}
value_type min_value() {
return _RawRestrictionContainer::min_value();
}
};
struct _WayIDStartAndEndEdge {
unsigned wayID;
NodeID firstStart;
NodeID firstTarget;
NodeID lastStart;
NodeID lastTarget;
_WayIDStartAndEndEdge() : wayID(UINT_MAX), firstStart(UINT_MAX), firstTarget(UINT_MAX), lastStart(UINT_MAX), lastTarget(UINT_MAX) {}
_WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt) : wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt) {}
static _WayIDStartAndEndEdge min_value() {
return _WayIDStartAndEndEdge((numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)());
}
static _WayIDStartAndEndEdge max_value() {
return _WayIDStartAndEndEdge((numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)());
}
};
struct CmpWayStartAndEnd : public std::binary_function<_WayIDStartAndEndEdge, _WayIDStartAndEndEdge, bool> {
typedef _WayIDStartAndEndEdge value_type;
bool operator () (const _WayIDStartAndEndEdge & a, const _WayIDStartAndEndEdge & b) const {
return a.wayID < b.wayID;
}
value_type max_value() {
return _WayIDStartAndEndEdge::max_value();
}
value_type min_value() {
return _WayIDStartAndEndEdge::min_value();
}
};
struct Settings {
Settings() : obeyPollards(true), obeyOneways(true), useRestrictions(true), accessTag("motorcar") {}
StringMap speedProfile;
int operator[](const string & param) const {
if(speedProfile.find(param) == speedProfile.end())
return 0;
else
return speedProfile.at(param);
}
bool obeyPollards;
bool obeyOneways;
bool useRestrictions;
string accessTag;
};
struct Cmp : public std::binary_function<NodeID, NodeID, bool> {
typedef NodeID value_type;
bool operator () (const NodeID & a, const NodeID & b) const {
return a < b;
}
value_type max_value() {
return 0xffffffff;
}
value_type min_value() {
return 0x0;
}
};
struct CmpNodeByID : public std::binary_function<_Node, _Node, bool> {
typedef _Node value_type;
bool operator () (const _Node & a, const _Node & b) const {
return a.id < b.id;
}
value_type max_value() {
return _Node::max_value();
}
value_type min_value() {
return _Node::min_value();
}
};
struct CmpEdgeByStartID : public std::binary_function<_Edge, _Edge, bool>
{
typedef _Edge value_type;
bool operator () (const _Edge & a, const _Edge & b) const {
return a.start < b.start;
}
value_type max_value() {
return _Edge::max_value();
}
value_type min_value() {
return _Edge::min_value();
}
};
struct CmpEdgeByTargetID : public std::binary_function<_Edge, _Edge, bool>
{
typedef _Edge value_type;
bool operator () (const _Edge & a, const _Edge & b) const
{
return a.target < b.target;
}
value_type max_value()
{
return _Edge::max_value();
}
value_type min_value()
{
return _Edge::min_value();
}
};
inline double ApproximateDistance( const int lat1, const int lon1, const int lat2, const int lon2 ) {
assert(lat1 != INT_MIN);
assert(lon1 != INT_MIN);
assert(lat2 != INT_MIN);
assert(lon2 != INT_MIN);
static const double DEG_TO_RAD = 0.017453292519943295769236907684886;
///Earth's quatratic mean radius for WGS-84
static const double EARTH_RADIUS_IN_METERS = 6372797.560856;
double latitudeArc = ( lat1/100000. - lat2/100000. ) * DEG_TO_RAD;
double longitudeArc = ( lon1/100000. - lon2/100000. ) * DEG_TO_RAD;
double latitudeH = sin( latitudeArc * 0.5 );
latitudeH *= latitudeH;
double lontitudeH = sin( longitudeArc * 0.5 );
lontitudeH *= lontitudeH;
double tmp = cos( lat1/100000. * DEG_TO_RAD ) * cos( lat2/100000. * DEG_TO_RAD );
double distanceArc = 2.0 * asin( sqrt( latitudeH + tmp * lontitudeH ) );
return EARTH_RADIUS_IN_METERS * distanceArc;
}
inline double ApproximateDistance(const _Coordinate &c1, const _Coordinate &c2) {
return ApproximateDistance( c1.lat, c1.lon, c2.lat, c2.lon );
}
inline string GetRandomString() {
char s[128];
static const char alphanum[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < 127; ++i) {
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
}
s[127] = 0;
return string(s);
}
#endif /* EXTRACTORSTRUCTS_H_ */
-78
View File
@@ -1,78 +0,0 @@
/*
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 _GridEdge {
_GridEdge(NodeID n, NodeID na, int w, _Coordinate sc, _Coordinate tc) : edgeBasedNode(n), nameID(na), weight(w), startCoord(sc), targetCoord(tc) {}
_GridEdge() : edgeBasedNode(UINT_MAX), nameID(UINT_MAX), weight(INT_MAX) {}
NodeID edgeBasedNode;
NodeID nameID;
int weight;
_Coordinate startCoord;
_Coordinate targetCoord;
};
struct GridEntry {
GridEntry() : fileIndex(UINT_MAX), ramIndex(UINT_MAX){}
GridEntry(_GridEdge e, unsigned f, unsigned r) : edge(e), fileIndex(f), ramIndex(r) {}
_GridEdge edge;
unsigned fileIndex;
unsigned ramIndex;
bool operator< ( const GridEntry& right ) const {
return (edge.edgeBasedNode < right.edge.edgeBasedNode);
}
bool operator==( const GridEntry& right ) const {
return right.edge.edgeBasedNode == edge.edgeBasedNode;
}
};
struct CompareGridEdgeDataByFileIndex
{
bool operator () (const GridEntry & a, const GridEntry & b) const
{
return a.fileIndex < b.fileIndex;
}
};
struct CompareGridEdgeDataByRamIndex
{
typedef GridEntry value_type;
bool operator () (const GridEntry & a, const GridEntry & b) const
{
return a.ramIndex < b.ramIndex;
}
value_type max_value()
{
GridEntry e;
e.ramIndex = (1024*1024) - 1;
return e;
}
value_type min_value()
{
GridEntry e;
e.ramIndex = 0;
return e;
}
};
#endif /* GRIDEDGE_H_ */
-78
View File
@@ -1,78 +0,0 @@
/*
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.
Created on: 18.11.2010
Author: dennis
*/
#ifndef HASHTABLE_H_
#define HASHTABLE_H_
#include <boost/unordered_map.hpp>
template<typename keyT, typename valueT>
class HashTable {
typedef boost::unordered_map<keyT, valueT> MyHashTable;
public:
typedef typename boost::unordered_map<keyT, valueT>::const_iterator MyIterator;
typedef MyIterator iterator;
HashTable() { }
HashTable(const unsigned size) {
table.resize(size);
}
void Add(const keyT& key, const valueT& value){
table[key] = value;
}
void Set(const keyT& key, const valueT& value){
table[key] = value;
}
valueT Find(const keyT& key) {
if(table.find(key) == table.end())
return valueT();
return table.find(key)->second;
}
bool Holds(const keyT& key) {
if(table.find(key) == table.end())
return false;
return true;
}
void EraseAll() {
if(table.size() > 0)
table.clear();
}
inline
valueT & operator[] (keyT key) {
return table[key];
}
unsigned Size() const {
return table.size();
}
MyIterator begin() const {
return table.begin();
}
MyIterator end() const {
return table.end();
}
private:
MyHashTable table;
};
#endif /* HASHTABLE_H_ */
-136
View File
@@ -1,136 +0,0 @@
/*
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 EDGE_H
#define EDGE_H
#include <cassert>
class NodeBasedEdge {
public:
bool operator< (const NodeBasedEdge& e) const {
if (source() == e.source()) {
if (target() == e.target()) {
if (weight() == e.weight()) {
return (isForward() && isBackward() &&
((! e.isForward()) || (! e.isBackward())));
}
return (weight() < e.weight());
}
return (target() < e.target());
}
return (source() < e.source());
}
/** Default constructor. target and weight are set to 0.*/
NodeBasedEdge() :
_source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _type(0), _roundabout(false) { assert(false); } //shall not be used.
explicit NodeBasedEdge(NodeID s, NodeID t, NodeID n, EdgeWeight w, bool f, bool b, short ty, bool ra) :
_source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra) { assert(ty >= 0); }
NodeID target() const {return _target; }
NodeID source() const {return _source; }
NodeID name() const { return _name; }
EdgeWeight weight() const {return _weight; }
short type() const { assert(_type >= 0); return _type; }
bool isBackward() const { return backward; }
bool isForward() const { return forward; }
bool isLocatable() const { return _type != 14; }
bool isRoundabout() const { return _roundabout; }
NodeID _source;
NodeID _target;
NodeID _name;
EdgeWeight _weight;
bool forward;
bool backward;
short _type;
bool _roundabout;
};
class EdgeBasedEdge {
public:
bool operator< (const EdgeBasedEdge& e) const {
if (source() == e.source()) {
if (target() == e.target()) {
if (weight() == e.weight()) {
return (isForward() && isBackward() &&
((! e.isForward()) || (! e.isBackward())));
}
return (weight() < e.weight());
}
return (target() < e.target());
}
return (source() < e.source());
}
template<class EdgeT>
EdgeBasedEdge(const EdgeT & myEdge ) :
_source(myEdge.source),
_target(myEdge.target),
_via(myEdge.data.via),
_nameID1(myEdge.data.nameID),
_weight(myEdge.data.distance),
_forward(myEdge.data.forward),
_backward(myEdge.data.backward),
_turnInstruction(myEdge.data.turnInstruction) { }
/** Default constructor. target and weight are set to 0.*/
EdgeBasedEdge() :
_source(0), _target(0), _via(0), _nameID1(0), _weight(0), _forward(0), _backward(0), _turnInstruction(0) { assert(false); } //shall not be used.
explicit EdgeBasedEdge(NodeID s, NodeID t, NodeID v, unsigned n1, EdgeWeight w, bool f, bool b, short ty) :
_source(s), _target(t), _via(v), _nameID1(n1), _weight(w), _forward(f), _backward(b), _turnInstruction(ty) { assert(ty >= 0); }
NodeID target() const {return _target; }
NodeID source() const {return _source; }
EdgeWeight weight() const {return _weight; }
NodeID via() const { return _via; }
short turnInstruction() const { assert(_turnInstruction >= 0); return _turnInstruction; }
bool isBackward() const { return _backward; }
bool isForward() const { return _forward; }
unsigned getNameIDOfTurnTarget() const { return _nameID1; }
NodeID _source;
NodeID _target;
NodeID _via;
unsigned _nameID1;
EdgeWeight _weight;
bool _forward;
bool _backward;
short _turnInstruction;
};
struct MinimalEdgeData {
public:
EdgeWeight distance;
bool forward;
bool backward;
};
typedef NodeBasedEdge ImportEdge;
#endif // EDGE_H
-94
View File
@@ -1,94 +0,0 @@
/*
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 INPUTREADERFACTORY_H
#define INPUTREADERFACTORY_H
#include <bzlib.h>
#include <libxml/xmlreader.h>
struct BZ2Context {
FILE* file;
BZFILE* bz2;
int error;
int nUnused;
char unused[BZ_MAX_UNUSED];
};
int readFromBz2Stream( void* pointer, char* buffer, int len ) {
void *unusedTmpVoid=NULL;
char *unusedTmp=NULL;
BZ2Context* context = (BZ2Context*) pointer;
int read = 0;
while(0 == read && !(BZ_STREAM_END == context->error && 0 == context->nUnused && feof(context->file))) {
read = BZ2_bzRead(&context->error, context->bz2, buffer, len);
if(BZ_OK == context->error) {
return read;
} else if(BZ_STREAM_END == context->error) {
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
if(BZ_OK != context->error) { cerr << "Could not BZ2_bzReadGetUnused" << endl; exit(-1);};
unusedTmp = (char*)unusedTmpVoid;
for(int i=0;i<context->nUnused;i++) {
context->unused[i] = unusedTmp[i];
}
BZ2_bzReadClose(&context->error, context->bz2);
if(BZ_OK != context->error) { cerr << "Could not BZ2_bzReadClose" << endl; exit(-1);};
context->error = BZ_STREAM_END; // set to the stream end for next call to this function
if(0 == context->nUnused && feof(context->file)) {
return read;
} else {
context->bz2 = BZ2_bzReadOpen(&context->error, context->file, 0, 0, context->unused, context->nUnused);
if(NULL == context->bz2){ cerr << "Could not open file" << endl; exit(-1);};
}
} else { cerr << "Could not read bz2 file" << endl; exit(-1); }
}
return read;
}
int closeBz2Stream( void *pointer )
{
BZ2Context* context = (BZ2Context*) pointer;
fclose( context->file );
delete context;
return 0;
}
xmlTextReaderPtr inputReaderFactory( const char* name )
{
std::string inputName(name);
if(inputName.find(".osm.bz2")!=string::npos)
{
BZ2Context* context = new BZ2Context();
context->error = false;
context->file = fopen( name, "r" );
int error;
context->bz2 = BZ2_bzReadOpen( &error, context->file, 0, 0, context->unused, context->nUnused );
if ( context->bz2 == NULL || context->file == NULL ) {
delete context;
return NULL;
}
return xmlReaderForIO( readFromBz2Stream, closeBz2Stream, (void*) context, NULL, NULL, 0 );
} else {
return xmlNewTextReaderFilename(name);
}
}
#endif // INPUTREADERFACTORY_H
-128
View File
@@ -1,128 +0,0 @@
#include <climits>
#include <google/sparse_hash_map>
#include <iostream>
#include <list>
#include <vector>
template < class T >
struct Countfn {
unsigned long operator()( const T &x ) { return 1; }
};
template< class Key, class Data, class Sizefn = Countfn< Data > > class LRUCache {
public:
typedef std::list< std::pair< Key, Data > > List; ///< Main cache storage typedef
typedef typename List::iterator List_Iter; ///< Main cache iterator
typedef typename List::const_iterator List_cIter; ///< Main cache iterator (const)
typedef std::vector< Key > Key_List; ///< List of keys
typedef typename Key_List::iterator Key_List_Iter; ///< Main cache iterator
typedef typename Key_List::const_iterator Key_List_cIter; ///< Main cache iterator (const)
typedef google::sparse_hash_map< Key, List_Iter > Map; ///< Index typedef
typedef std::pair< Key, List_Iter > Pair; ///< Pair of Map elements
typedef typename Map::iterator Map_Iter; ///< Index iterator
typedef typename Map::const_iterator Map_cIter; ///< Index iterator (const)
private:
List _list; ///< Main cache storage
Map _index; ///< Cache storage index
unsigned long _max_size; ///< Maximum abstract size of the cache
unsigned long _curr_size; ///< Current abstract size of the cache
public:
LRUCache( const unsigned long Size ) : _max_size( Size ), _curr_size( 0 ) {
_index.set_deleted_key(UINT_MAX);
}
~LRUCache() { clear(); }
inline const unsigned long size( void ) const { return _curr_size; }
inline const unsigned long max_size( void ) const { return _max_size; }
/// Clears all storage and indices.
void clear( void ) {
_list.clear();
_index.clear();
};
inline bool exists( const Key &key ) const {
return _index.find( key ) != _index.end();
}
inline void remove( const Key &key ) {
Map_Iter miter = _index.find( key );
if( miter == _index.end() ) return;
_remove( miter );
}
inline void touch( const Key &key ) {
_touch( key );
}
inline Data *fetch_ptr( const Key &key, bool touch = true ) {
Map_Iter miter = _index.find( key );
if( miter == _index.end() ) return NULL;
_touch( key );
return &(miter->second->second);
}
inline bool fetch( const Key &key, Data &data, bool touch_data = true ) {
Map_Iter miter = _index.find( key );
if( miter == _index.end() ) return false;
if( touch_data )
_touch( key );
data = miter->second->second;
return true;
}
inline void insert( const Key &key, const Data data ) {
// Touch the key, if it exists, then replace the content.
Map_Iter miter = _touch( key );
if( miter != _index.end() )
_remove( miter );
// Ok, do the actual insert at the head of the list
_list.push_front( std::make_pair( key, data ) );
List_Iter liter = _list.begin();
// Store the index
_index.insert( std::make_pair( key, liter ) );
_curr_size += Sizefn()( data );
// Check to see if we need to remove an element due to exceeding max_size
while( _curr_size > _max_size ) {
std::cout << "removing element " << std::endl;
// Remove the last element.
liter = _list.end();
--liter;
_remove( liter->first );
}
}
inline const Key_List get_all_keys( void ) {
Key_List ret;
for( List_cIter liter = _list.begin(); liter != _list.end(); liter++ )
ret.push_back( liter->first );
return ret;
}
private:
inline Map_Iter _touch( const Key &key ) {
Map_Iter miter = _index.find( key );
if( miter == _index.end() ) return miter;
// Move the found node to the head of the list.
_list.splice( _list.begin(), _list, miter->second );
return miter;
}
inline void _remove( const Map_Iter &miter ) {
_curr_size -= Sizefn()( miter->second->second );
_list.erase( miter->second );
_index.erase( miter );
}
inline void _remove( const Key &key ) {
Map_Iter miter = _index.find( key );
_remove( miter );
}
};
-635
View File
@@ -1,635 +0,0 @@
/*
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 <algorithm>
#include <cassert>
#include <cmath>
#include <fstream>
#include <limits>
#include <vector>
#include <stxxl.h>
#ifdef _OPENMP
#include <omp.h>
#endif
#ifdef _WIN32
#include <math.h>
#endif
#include <boost/thread.hpp>
#include <boost/foreach.hpp>
#include <google/dense_hash_map>
#include "ExtractorStructs.h"
#include "GridEdge.h"
#include "LRUCache.h"
#include "Percent.h"
#include "PhantomNodes.h"
#include "Util.h"
#include "StaticGraph.h"
static const unsigned MAX_CACHE_ELEMENTS = 1000;
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 + 180.0 ) / 360.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 GetIndicesByBresenhamsAlgorithm(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 + 180.0 ) / 360.0;
double lat2 = target.lat/100000.;
double lon2 = target.lon/100000.;
double x2 = ( lon2 + 180.0 ) / 360.0;
double y2 = ( lat2 + 180.0 ) / 360.0;
GetIndicesByBresenhamsAlgorithm(x1*32768, y1*32768, x2*32768, y2*32768, indexList);
}
static boost::thread_specific_ptr<std::ifstream> localStream;
template<bool WriteAccess = false>
class NNGrid {
public:
NNGrid() /*: cellCache(500), fileCache(500)*/ {
ramIndexTable.resize((1024*1024), UINT_MAX);
if( WriteAccess) {
entries = new stxxl::vector<GridEntry>();
}
}
NNGrid(const char* rif, const char* _i, unsigned numberOfThreads = omp_get_num_procs()) /*: cellCache(500), fileCache(500) */{
if(WriteAccess) {
ERR("Not available in Write mode");
}
iif = std::string(_i);
ramIndexTable.resize((1024*1024), UINT_MAX);
ramInFile.open(rif, std::ios::in | std::ios::binary);
entries = NULL;
}
~NNGrid() {
if(ramInFile.is_open()) ramInFile.close();
if (WriteAccess) {
delete entries;
}
if(localStream.get() && localStream->is_open()) {
localStream->close();
}
}
void OpenIndexFiles() {
assert(ramInFile.is_open());
for(int i = 0; i < 1024*1024; ++i) {
unsigned temp;
ramInFile.read((char*)&temp, sizeof(unsigned));
ramIndexTable[i] = temp;
}
ramInFile.close();
}
template<typename EdgeT, typename NodeInfoT>
void ConstructGrid(std::vector<EdgeT> & edgeList, vector<NodeInfoT> * int2ExtNodeMap, char * ramIndexOut, char * fileIndexOut) {
Percent p(edgeList.size());
for(NodeID i = 0; i < edgeList.size(); ++i) {
p.printIncrement();
EdgeT & edge = edgeList[i];
int slat = 100000*lat2y(edge.lat1/100000.);
int slon = edge.lon1;
int tlat = 100000*lat2y(edge.lat2/100000.);
int tlon = edge.lon2;
AddEdge( _GridEdge(
edge.id, edge.nameID, edge.weight,
_Coordinate(slat, slon),
_Coordinate(tlat, tlon) )
);
}
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<GridEntry> entriesInFileWithRAMSameIndex;
unsigned indexInRamTable = entries->begin()->ramIndex;
unsigned lastPositionInIndexFile = 0;
unsigned numberOfUsedCells = 0;
unsigned maxNumberOfRAMCellElements = 0;
cout << "writing data ..." << flush;
p.reinit(entries->size());
for(stxxl::vector<GridEntry>::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 GetEdgeBasedStartNode(const _Coordinate& coord, NodesOfEdge& nodesOfEdge) {
_Coordinate startCoord(100000*(lat2y(static_cast<double>(coord.lat)/100000.)), coord.lon);
/** search for point on edge next to source */
unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
std::vector<_GridEdge> candidates;
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();
BOOST_FOREACH(_GridEdge candidate, candidates) {
double r = 0.;
double tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
if(tmpDist < dist) {
nodesOfEdge.edgeBasedNode = candidate.edgeBasedNode;
nodesOfEdge.ratio = r;
dist = tmpDist;
nodesOfEdge.projectedPoint.lat = round(100000*(y2lat(static_cast<double>(tmp.lat)/100000.)));
nodesOfEdge.projectedPoint.lon = tmp.lon;
}
}
if(dist != (numeric_limits<double>::max)()) {
return true;
}
return false;
}
bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode) {
bool foundNode = false;
_Coordinate startCoord(100000*(lat2y(static_cast<double>(location.lat)/100000.)), location.lon);
/** search for point on edge close to source */
unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
std::vector<_GridEdge> candidates;
for(int j = -32768; j < (32768+1); j+=32768) {
for(int i = -1; i < 2; i++){
GetContentsOfFileBucket(fileIndex+i+j, candidates);
}
}
_GridEdge smallestEdge;
_Coordinate tmp, newEndpoint;
double dist = (numeric_limits<double>::max)();
BOOST_FOREACH(_GridEdge candidate, candidates) {
double r = 0.;
double tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
if(DoubleEpsilonCompare(dist, tmpDist) && 1 == std::abs((int)candidate.edgeBasedNode-(int)resultNode.edgeBasedNode)) {
resultNode.weight2 = candidate.weight;
/* if(resultNode.weight1 != resultNode.weight2) {
ERR("w1: " << resultNode.weight1 << ", w2: " << resultNode.weight2);
assert(false);
}*/
if(candidate.edgeBasedNode < resultNode.edgeBasedNode) {
resultNode.edgeBasedNode = candidate.edgeBasedNode;
std::swap(resultNode.weight1, resultNode.weight2);
}
}
if(tmpDist < dist) {
resultNode.Reset();
resultNode.edgeBasedNode = candidate.edgeBasedNode;
resultNode.nodeBasedEdgeNameID = candidate.nameID;
resultNode.weight1 = candidate.weight;
dist = tmpDist;
resultNode.location.lat = round(100000*(y2lat(static_cast<double>(tmp.lat)/100000.)));
resultNode.location.lon = tmp.lon;
foundNode = true;
smallestEdge = candidate;
newEndpoint = tmp;
}
}
// INFO("startcoord: " << smallestEdge.startCoord << ", tgtcoord" << smallestEdge.targetCoord << "result: " << newEndpoint);
// INFO("length of old edge: " << LengthOfVector(smallestEdge.startCoord, smallestEdge.targetCoord));
// INFO("Length of new edge: " << LengthOfVector(smallestEdge.startCoord, newEndpoint));
// assert(!resultNode.isBidirected || (resultNode.weight1 == resultNode.weight2));
// if(resultNode.weight1 != resultNode.weight2) {
// INFO("-> Weight1: " << resultNode.weight1 << ", weight2: " << resultNode.weight2);
// INFO("-> node: " << resultNode.edgeBasedNode << ", bidir: " << (resultNode.isBidirected ? "yes" : "no"));
// }
double ratio = std::min(1., LengthOfVector(smallestEdge.startCoord, newEndpoint)/LengthOfVector(smallestEdge.startCoord, smallestEdge.targetCoord) );
assert(ratio >= 0 && ratio <=1);
// INFO("Old weight1: " << resultNode.weight1 << ", old weight2: " << resultNode.weight2);
resultNode.weight1 *= ratio;
if(INT_MAX != resultNode.weight2) {
resultNode.weight2 *= (1-ratio);
// INFO("New weight1: " << resultNode.weight1 << ", new weight2: " << resultNode.weight2);
}
return foundNode;
}
bool FindRoutingStarts(const _Coordinate& start, const _Coordinate& target, PhantomNodes & routingStarts) {
routingStarts.Reset();
return (FindPhantomNodeForCoordinate( start, routingStarts.startPhantom) &&
FindPhantomNodeForCoordinate( target, routingStarts.targetPhantom) );
}
void FindNearestCoordinateOnEdgeInNodeBasedGraph(const _Coordinate& inputCoordinate, _Coordinate& outputCoordinate) {
unsigned fileIndex = GetFileIndexForLatLon(100000*(lat2y(static_cast<double>(inputCoordinate.lat)/100000.)), inputCoordinate.lon);
std::vector<_GridEdge> candidates;
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)();
BOOST_FOREACH(_GridEdge candidate, candidates) {
double r = 0.;
double tmpDist = ComputeDistance(inputCoordinate, candidate.startCoord, candidate.targetCoord, tmp, &r);
if(tmpDist < dist) {
dist = tmpDist;
outputCoordinate = tmp;
}
}
outputCoordinate.lat = 100000*(y2lat(static_cast<double>(outputCoordinate.lat)/100000.));
}
void FindNearestPointOnEdge(const _Coordinate& inputCoordinate, _Coordinate& outputCoordinate) {
_Coordinate startCoord(100000*(lat2y(static_cast<double>(inputCoordinate.lat)/100000.)), inputCoordinate.lon);
unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
std::vector<_GridEdge> candidates;
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)();
BOOST_FOREACH(_GridEdge candidate, candidates) {
double r = 0.;
double tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
if(tmpDist < dist) {
dist = tmpDist;
outputCoordinate.lat = round(100000*(y2lat(static_cast<double>(tmp.lat)/100000.)));
outputCoordinate.lon = tmp.lon;
}
}
}
private:
inline double LengthOfVector(const _Coordinate & c1, const _Coordinate & c2) {
double length1 = std::sqrt(c1.lat/100000.*c1.lat/100000. + c1.lon/100000.*c1.lon/100000.);
double length2 = std::sqrt(c2.lat/100000.*c2.lat/100000. + c2.lon/100000.*c2.lon/100000.);
return std::fabs(length1-length2);
}
inline bool DoubleEpsilonCompare(const double d1, const double d2) {
return (std::fabs(d1 - d2) < 0.000000001);
}
unsigned FillCell(std::vector<GridEntry>& entriesWithSameRAMIndex, unsigned fileOffset ) {
vector<char> * tmpBuffer = new vector<char>();
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(unsigned 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<GridEntry>::iterator uniqueEnd = std::unique(entriesWithSameRAMIndex.begin(), entriesWithSameRAMIndex.end());
//traverse each file bucket and write its contents to disk
std::vector<GridEntry> entriesWithSameFileIndex;
unsigned fileIndex = entriesWithSameRAMIndex.begin()->fileIndex;
for(std::vector<GridEntry>::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);
}
GridEntry 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);
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(unsigned i = 0; i < indexIntoTmpBuffer; i++) {
indexOutFile.write(&(tmpBuffer->at(i)), sizeof(char));
numberOfWrittenBytes += sizeof(char);
}
delete tmpBuffer;
delete cellMap;
return numberOfWrittenBytes;
}
unsigned FlushEntriesWithSameFileIndexToBuffer( std::vector<GridEntry> &vectorWithSameFileIndex, vector<char> * tmpBuffer, const unsigned index) {
tmpBuffer->resize(tmpBuffer->size()+(sizeof(_GridEdge)*vectorWithSameFileIndex.size()) );
unsigned counter = 0;
unsigned max = UINT_MAX;
for(unsigned i = 0; i < vectorWithSameFileIndex.size()-1; i++) {
assert( vectorWithSameFileIndex[i].fileIndex == vectorWithSameFileIndex[i+1].fileIndex );
assert( vectorWithSameFileIndex[i].ramIndex == vectorWithSameFileIndex[i+1].ramIndex );
}
sort( vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end() );
vectorWithSameFileIndex.erase(unique(vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end()), vectorWithSameFileIndex.end());
BOOST_FOREACH(GridEntry entry, vectorWithSameFileIndex) {
char * data = (char *)&(entry.edge);
for(unsigned i = 0; i < sizeof(_GridEdge); ++i) {
tmpBuffer->at(index+counter) = data[i];
++counter;
}
}
char * umax = (char *) &max;
for(unsigned i = 0; i < sizeof(unsigned); i++) {
tmpBuffer->at(index+counter) = umax[i];
counter++;
}
vectorWithSameFileIndex.clear();
std::vector<GridEntry>().swap(vectorWithSameFileIndex);
return counter;
}
void GetContentsOfFileBucket(const unsigned fileIndex, std::vector<_GridEdge>& 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(1024);
cellMap.set_empty_key(UINT_MAX);
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));
}
}
if(!localStream.get() || !localStream->is_open()) {
localStream.reset(new std::ifstream(iif.c_str(), std::ios::in | std::ios::binary));
}
localStream->seekg(startIndexInFile);
localStream->read((char*) &cellIndex[0], 32*32*sizeof(unsigned));
assert(cellMap.find(fileIndex) != cellMap.end());
if(cellIndex[cellMap.find(fileIndex)->second] == UINT_MAX) {
return;
}
const unsigned position = cellIndex[cellMap.find(fileIndex)->second] + 32*32*sizeof(unsigned) ;
localStream->seekg(position);
_GridEdge gridEdge;
do {
localStream->read((char *)&(gridEdge), sizeof(_GridEdge));
if(localStream->eof() || gridEdge.edgeBasedNode == UINT_MAX)
break;
result.push_back(gridEdge);
} while(true);
}
void AddEdge(_GridEdge edge) {
std::vector<std::pair<unsigned, unsigned> > indexList;
GetListOfIndexesForEdgeAndGridSize(edge.startCoord, edge.targetCoord, indexList);
for(unsigned i = 0; i < indexList.size(); ++i) {
entries->push_back(GridEntry(edge, indexList[i].first, indexList[i].second));
}
}
double ComputeDistance(const _Coordinate& inputPoint, const _Coordinate& source, const _Coordinate& target, _Coordinate& nearest, double *r) {
const double x = (double)inputPoint.lat;
const double y = (double)inputPoint.lon;
const double a = (double)source.lat;
const double b = (double)source.lon;
const double c = (double)target.lat;
const double d = (double)target.lon;
double p,q,mX,nY;
if(c != a){
const double m = (d-b)/(c-a); // slope
// Projection of (x,y) on line joining (a,b) and (c,d)
p = ((x + (m*y)) + (m*m*a - m*b))/(1 + m*m);
q = b + m*(p - a);
}
else{
p = c;
q = y;
}
nY = (d*p - c*q)/(a*d - b*c);
mX = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we neednot calculate the values of m an n as we are just interested in the ratio
*r = mX;
if(*r<=0){
nearest.lat = source.lat;
nearest.lon = source.lon;
return ((b - y)*(b - y) + (a - x)*(a - x));
}
else if(*r >= 1){
nearest.lat = target.lat;
nearest.lon = target.lon;
return ((d - y)*(d - y) + (c - x)*(c - x));
}
// point lies in between
nearest.lat = p;
nearest.lon = q;
return (p-x)*(p-x) + (q-y)*(q-y);
}
ofstream indexOutFile;
ifstream ramInFile;
stxxl::vector<GridEntry> * entries;
std::vector<unsigned> ramIndexTable; //4 MB for first level index in RAM
std::string iif;
// LRUCache<int,std::vector<unsigned> > cellCache;
// LRUCache<int,std::vector<_Edge> > fileCache;
};
}
typedef NNGrid::NNGrid<false> ReadOnlyGrid;
typedef NNGrid::NNGrid<true > WritableGrid;
#endif /* NNGRID_H_ */
-68
View File
@@ -1,68 +0,0 @@
/*
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 _NODE_COORDS_H
#define _NODE_COORDS_H
#include <cassert>
#include <cstddef>
#include <climits>
#include "../typedefs.h"
template<typename NodeT>
struct NodeCoords {
typedef unsigned key_type; //type of NodeID
typedef int value_type; //type of lat,lons
NodeCoords(int _lat, int _lon, NodeT _id) : lat(_lat), lon(_lon), id(_id) {}
NodeCoords() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {}
int lat;
int lon;
NodeT id;
static NodeCoords<NodeT> min_value()
{
return NodeCoords<NodeT>(-90*100000,-180*100000,numeric_limits<NodeT>::min());
}
static NodeCoords<NodeT> max_value()
{
return NodeCoords<NodeT>(90*100000, 180*100000, numeric_limits<NodeT>::max());
}
value_type operator[](size_t n) const {
switch(n) {
case 1:
return lat;
break;
case 0:
return lon;
break;
default:
assert(false);
return UINT_MAX;
break;
}
assert(false);
return UINT_MAX;
}
};
#endif //_NODE_COORDS_H
-90
View File
@@ -1,90 +0,0 @@
/*
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 NODEINFORMATIONHELPDESK_H_
#define NODEINFORMATIONHELPDESK_H_
#include <fstream>
#include <iostream>
#include <vector>
#include "../typedefs.h"
#include "NNGrid.h"
#include "PhantomNodes.h"
class NodeInformationHelpDesk{
public:
NodeInformationHelpDesk(const char* ramIndexInput, const char* fileIndexInput, unsigned _numberOfNodes) : numberOfNodes(_numberOfNodes) {
readOnlyGrid = new ReadOnlyGrid(ramIndexInput,fileIndexInput);
int2ExtNodeMap = new vector<_Coordinate>();
int2ExtNodeMap->reserve(numberOfNodes);
assert(0 == int2ExtNodeMap->size());
}
~NodeInformationHelpDesk() {
delete int2ExtNodeMap;
delete readOnlyGrid;
}
void initNNGrid(ifstream& in) {
while(!in.eof()) {
NodeInfo b;
in.read((char *)&b, sizeof(b));
int2ExtNodeMap->push_back(_Coordinate(b.lat, b.lon));
}
in.close();
readOnlyGrid->OpenIndexFiles();
}
inline int getLatitudeOfNode(const NodeID node) const {
return int2ExtNodeMap->at(node).lat;
}
inline int getLongitudeOfNode(const NodeID node) const { return int2ExtNodeMap->at(node).lon; }
NodeID getNumberOfNodes() const { return numberOfNodes; }
NodeID getNumberOfNodes2() const { return int2ExtNodeMap->size(); }
inline void FindNearestNodeCoordForLatLon(const _Coordinate& coord, _Coordinate& result) {
readOnlyGrid->FindNearestCoordinateOnEdgeInNodeBasedGraph(coord, result);
}
bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode) {
return readOnlyGrid->FindPhantomNodeForCoordinate(location, resultNode);
}
inline bool FindRoutingStarts(const _Coordinate &start, const _Coordinate &target, PhantomNodes & phantomNodes) {
readOnlyGrid->FindRoutingStarts(start, target, phantomNodes);
return true;
}
inline bool GetStartAndDestNodesOfEdge(const _Coordinate& coord, NodesOfEdge& nodesOfEdge) {
return readOnlyGrid->GetEdgeBasedStartNode(coord, nodesOfEdge);
}
inline void FindNearestPointOnEdge(const _Coordinate & input, _Coordinate& output){
readOnlyGrid->FindNearestPointOnEdge(input, output);
}
private:
vector<_Coordinate> * int2ExtNodeMap;
ReadOnlyGrid * readOnlyGrid;
unsigned numberOfNodes;
};
#endif /*NODEINFORMATIONHELPDESK_H_*/
-535
View File
@@ -1,535 +0,0 @@
/*
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 PBFPARSER_H_
#define PBFPARSER_H_
#include <zlib.h>
#include "BaseParser.h"
#include "pbf-proto/fileformat.pb.h"
#include "pbf-proto/osmformat.pb.h"
#include "../typedefs.h"
#include "HashTable.h"
#include "ExtractorStructs.h"
#include "ConcurrentQueue.h"
class PBFParser : public BaseParser<_Node, _RawRestrictionContainer, _Way> {
enum EntityType {
TypeNode = 1,
TypeWay = 2,
TypeRelation = 4,
TypeDenseNode = 8
} ;
enum Endianness {
LittleEndian = 1,
BigEndian = 2
};
struct _ThreadData {
int currentGroupID;
int currentEntityID;
short entityTypeIndicator;
OSMPBF::BlobHeader PBFBlobHeader;
OSMPBF::Blob PBFBlob;
OSMPBF::HeaderBlock PBFHeaderBlock;
OSMPBF::PrimitiveBlock PBFprimitiveBlock;
std::vector<char> charBuffer;
};
public:
PBFParser(const char * fileName)
: threadDataQueue( new ConcurrentQueue<_ThreadData*>(25) ) { /* Max 25 items in queue */
GOOGLE_PROTOBUF_VERIFY_VERSION;
input.open(fileName, std::ios::in | std::ios::binary);
if (!input) {
std::cerr << fileName << ": File not found." << std::endl;
}
blockCount = 0;
groupCount = 0;
//Dummy initialization
wayCallback = NULL; nodeCallback = NULL;
addressCallback = NULL; restrictionCallback = NULL;
}
bool RegisterCallbacks(bool (*nodeCallbackPointer)(_Node), bool (*restrictionCallbackPointer)(_RawRestrictionContainer), bool (*wayCallbackPointer)(_Way),bool (*addressCallbackPointer)(_Node, HashTable<std::string, std::string>) ) {
nodeCallback = *nodeCallbackPointer;
wayCallback = *wayCallbackPointer;
restrictionCallback = *restrictionCallbackPointer;
addressCallback = *addressCallbackPointer;
return true;
}
~PBFParser() {
if(input.is_open())
input.close();
// Clean up any leftover ThreadData objects in the queue
_ThreadData* td;
while (threadDataQueue->try_pop(td)) {
delete td;
}
delete threadDataQueue;
google::protobuf::ShutdownProtobufLibrary();
#ifndef NDEBUG
std::cout << "[info] blocks: " << blockCount << std::endl;
std::cout << "[info] groups: " << groupCount << std::endl;
#endif
}
bool Init() {
_ThreadData initData;
/** read Header */
if(!readPBFBlobHeader(input, &initData)) {
return false;
}
if(readBlob(input, &initData)) {
if(!initData.PBFHeaderBlock.ParseFromArray(&(initData.charBuffer[0]), initData.charBuffer.size() ) ) {
std::cerr << "[error] Header not parseable!" << std::endl;
return false;
}
for(int i = 0; i < initData.PBFHeaderBlock.required_features_size(); i++) {
const std::string& feature = initData.PBFHeaderBlock.required_features( i );
bool supported = false;
if ( feature == "OsmSchema-V0.6" )
supported = true;
else if ( feature == "DenseNodes" )
supported = true;
if ( !supported ) {
std::cerr << "[error] required feature not supported: " << feature.data() << std::endl;
return false;
}
}
} else {
std::cerr << "[error] blob not loaded!" << std::endl;
}
return true;
}
void ReadData() {
bool keepRunning = true;
do {
_ThreadData *threadData = new _ThreadData();
keepRunning = readNextBlock(input, threadData);
if (keepRunning)
threadDataQueue->push(threadData);
else
threadDataQueue->push(NULL); // No more data to read, parse stops when NULL encountered
} while(keepRunning);
}
void ParseData() {
while (1) {
_ThreadData *threadData;
threadDataQueue->wait_and_pop(threadData);
if (threadData == NULL) {
cout << "Parse Data Thread Finished" << endl;
threadDataQueue->push(NULL); // Signal end of data for other threads
break;
}
loadBlock(threadData);
for(int i = 0; i < threadData->PBFprimitiveBlock.primitivegroup_size(); i++) {
threadData->currentGroupID = i;
loadGroup(threadData);
if(threadData->entityTypeIndicator == TypeNode)
parseNode(threadData);
if(threadData->entityTypeIndicator == TypeWay)
parseWay(threadData);
if(threadData->entityTypeIndicator == TypeRelation)
parseRelation(threadData);
if(threadData->entityTypeIndicator == TypeDenseNode)
parseDenseNode(threadData);
}
delete threadData;
threadData = NULL;
}
}
bool Parse() {
// Start the read and parse threads
boost::thread readThread(boost::bind(&PBFParser::ReadData, this));
boost::thread parseThread(boost::bind(&PBFParser::ParseData, this));
// Wait for the threads to finish
readThread.join();
parseThread.join();
return true;
}
private:
void parseDenseNode(_ThreadData * threadData) {
const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense();
int denseTagIndex = 0;
int m_lastDenseID = 0;
int m_lastDenseLatitude = 0;
int m_lastDenseLongitude = 0;
for(int i = 0; i < dense.id_size(); i++) {
HashTable<std::string, std::string> keyVals;
m_lastDenseID += dense.id( i );
m_lastDenseLatitude += dense.lat( i );
m_lastDenseLongitude += dense.lon( i );
_Node n;
n.id = m_lastDenseID;
n.lat = 100000*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() +threadData-> PBFprimitiveBlock.lat_offset() ) / NANO;
n.lon = 100000*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO;
while (denseTagIndex < dense.keys_vals_size()) {
int tagValue = dense.keys_vals( denseTagIndex );
if(tagValue == 0) {
denseTagIndex++;
break;
}
int keyValue = dense.keys_vals ( denseTagIndex+1 );
std::string key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data();
std::string value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data();
keyVals.Add(key, value);
denseTagIndex += 2;
}
if(!(*addressCallback)(n, keyVals))
std::cerr << "[PBFParser] adress not parsed" << std::endl;
if(!(*nodeCallback)(n))
std::cerr << "[PBFParser] dense node not parsed" << std::endl;
}
}
void parseNode(_ThreadData * threadData) {
_Node n;
if(!(*nodeCallback)(n))
std::cerr << "[PBFParser] simple node not parsed" << std::endl;
}
void parseRelation(_ThreadData * threadData) {
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
for(int i = 0; i < group.relations_size(); i++ ) {
const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i);
bool isRestriction = false;
bool isOnlyRestriction = false;
for(int k = 0; k < inputRelation.keys_size(); k++) {
const std::string key = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k));
const std::string val = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k));
if ("type" == key && "restriction" == val) {
isRestriction = true;
}
if ("restriction" == key) {
if(val.find("only_") == 0)
isOnlyRestriction = true;
}
}
if(isRestriction) {
long long lastRef = 0;
_RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
for(int rolesIndex = 0; rolesIndex < inputRelation.roles_sid_size(); rolesIndex++) {
string role(threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) ).data());
lastRef += inputRelation.memids(rolesIndex);
if(false == ("from" == role || "to" == role || "via" == role)) {
continue;
}
switch(inputRelation.types(rolesIndex)) {
case 0: //node
if("from" == role || "to" == role) //Only via should be a node
continue;
assert("via" == role);
if(UINT_MAX != currentRestrictionContainer.viaWay)
currentRestrictionContainer.viaWay = UINT_MAX;
assert(UINT_MAX == currentRestrictionContainer.viaWay);
currentRestrictionContainer.restriction.viaNode = lastRef;
break;
case 1: //way
assert("from" == role || "to" == role || "via" == role);
if("from" == role) {
currentRestrictionContainer.fromWay = lastRef;
}
if ("to" == role) {
currentRestrictionContainer.toWay = lastRef;
}
if ("via" == role) {
assert(currentRestrictionContainer.restriction.toNode == UINT_MAX);
currentRestrictionContainer.viaWay = lastRef;
}
break;
case 2: //relation, not used. relations relating to relations are evil.
continue;
assert(false);
break;
default: //should not happen
cout << "unknown";
assert(false);
break;
}
}
// if(UINT_MAX != currentRestriction.viaNode) {
// cout << "restr from " << currentRestriction.from << " via ";
// cout << "node " << currentRestriction.viaNode;
// cout << " to " << currentRestriction.to << endl;
// }
if(!(*restrictionCallback)(currentRestrictionContainer))
std::cerr << "[PBFParser] relation not parsed" << std::endl;
}
}
}
void parseWay(_ThreadData * threadData) {
if( threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size() > 0) {
for(int i = 0; i < threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); i++) {
const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i );
_Way w;
w.id = inputWay.id();
unsigned pathNode(0);
for(int i = 0; i < inputWay.refs_size(); i++) {
pathNode += inputWay.refs(i);
w.path.push_back(pathNode);
}
assert(inputWay.keys_size() == inputWay.vals_size());
for(int i = 0; i < inputWay.keys_size(); i++) {
const std::string key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(i));
const std::string val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(i));
w.keyVals.Add(key, val);
}
if(!(*wayCallback)(w)) {
std::cerr << "[PBFParser] way not parsed" << std::endl;
}
}
}
}
void loadGroup(_ThreadData * threadData) {
groupCount++;
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
threadData->entityTypeIndicator = 0;
if ( group.nodes_size() != 0 ) {
threadData->entityTypeIndicator = TypeNode;
}
if ( group.ways_size() != 0 ) {
threadData->entityTypeIndicator = TypeWay;
}
if ( group.relations_size() != 0 ) {
threadData->entityTypeIndicator = TypeRelation;
}
if ( group.has_dense() ) {
threadData->entityTypeIndicator = TypeDenseNode;
assert( group.dense().id_size() != 0 );
}
assert( threadData->entityTypeIndicator != 0 );
}
void loadBlock(_ThreadData * threadData) {
blockCount++;
threadData->currentGroupID = 0;
threadData->currentEntityID = 0;
}
/* Reverses Network Byte Order into something usable */
inline unsigned swapEndian(unsigned x) {
if(getMachineEndianness() == LittleEndian)
return ( (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24) );
return x;
}
bool readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData) {
int size(0);
stream.read((char *)&size, sizeof(int));
size = swapEndian(size);
if(stream.eof()) {
return false;
}
if ( size > MAX_BLOB_HEADER_SIZE || size < 0 ) {
return false;
}
char *data = (char*)malloc(size);
stream.read(data, size*sizeof(data[0]));
if ( !(threadData->PBFBlobHeader).ParseFromArray( data, size ) ){
free(data);
return false;
}
free(data);
return true;
}
bool unpackZLIB(std::fstream & stream, _ThreadData * threadData) {
unsigned rawSize = threadData->PBFBlob.raw_size();
char* unpackedDataArray = (char*)malloc(rawSize);
z_stream compressedDataStream;
compressedDataStream.next_in = ( unsigned char* ) threadData->PBFBlob.zlib_data().data();
compressedDataStream.avail_in = threadData->PBFBlob.zlib_data().size();
compressedDataStream.next_out = ( unsigned char* ) unpackedDataArray;
compressedDataStream.avail_out = rawSize;
compressedDataStream.zalloc = Z_NULL;
compressedDataStream.zfree = Z_NULL;
compressedDataStream.opaque = Z_NULL;
int ret = inflateInit( &compressedDataStream );
if ( ret != Z_OK ) {
std::cerr << "[error] failed to init zlib stream" << std::endl;
free(unpackedDataArray);
return false;
}
ret = inflate( &compressedDataStream, Z_FINISH );
if ( ret != Z_STREAM_END ) {
std::cerr << "[error] failed to inflate zlib stream" << std::endl;
std::cerr << "[error] Error type: " << ret << std::endl;
free(unpackedDataArray);
return false;
}
ret = inflateEnd( &compressedDataStream );
if ( ret != Z_OK ) {
std::cerr << "[error] failed to deinit zlib stream" << std::endl;
free(unpackedDataArray);
return false;
}
threadData->charBuffer.clear(); threadData->charBuffer.resize(rawSize);
for(unsigned i = 0; i < rawSize; i++) {
threadData->charBuffer[i] = unpackedDataArray[i];
}
free(unpackedDataArray);
return true;
}
bool unpackLZMA(std::fstream & stream, _ThreadData * threadData) {
return false;
}
bool readBlob(std::fstream& stream, _ThreadData * threadData) {
if(stream.eof())
return false;
int size = threadData->PBFBlobHeader.datasize();
if ( size < 0 || size > MAX_BLOB_SIZE ) {
std::cerr << "[error] invalid Blob size:" << size << std::endl;
return false;
}
char* data = (char*)malloc(size);
stream.read(data, sizeof(data[0])*size);
if ( !threadData->PBFBlob.ParseFromArray( data, size ) ) {
std::cerr << "[error] failed to parse blob" << std::endl;
free(data);
return false;
}
if ( threadData->PBFBlob.has_raw() ) {
const std::string& data = threadData->PBFBlob.raw();
threadData->charBuffer.clear();
threadData->charBuffer.resize( data.size() );
for ( unsigned i = 0; i < data.size(); i++ ) {
threadData->charBuffer[i] = data[i];
}
} else if ( threadData->PBFBlob.has_zlib_data() ) {
if ( !unpackZLIB(stream, threadData) ) {
std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
free(data);
return false;
}
} else if ( threadData->PBFBlob.has_lzma_data() ) {
if ( !unpackLZMA(stream, threadData) )
std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
free(data);
return false;
} else {
std::cerr << "[error] Blob contains no data" << std::endl;
free(data);
return false;
}
free(data);
return true;
}
bool readNextBlock(std::fstream& stream, _ThreadData * threadData) {
if(stream.eof()) {
return false;
}
if ( !readPBFBlobHeader(stream, threadData) )
return false;
if ( threadData->PBFBlobHeader.type() != "OSMData" ) {
std::cerr << "[error] invalid block type, found" << threadData->PBFBlobHeader.type().data() << "instead of OSMData" << std::endl;
return false;
}
if ( !readBlob(stream, threadData) )
return false;
if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) {
std::cerr << "[error] failed to parse PrimitiveBlock" << std::endl;
return false;
}
return true;
}
static Endianness getMachineEndianness() {
int i(1);
char *p = (char *) &i;
if (p[0] == 1)
return LittleEndian;
return BigEndian;
}
static const int NANO = 1000 * 1000 * 1000;
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
/* counting the number of read blocks and groups */
unsigned groupCount;
unsigned blockCount;
/* Function pointer for nodes */
bool (*nodeCallback)(_Node);
bool (*wayCallback)(_Way);
bool (*restrictionCallback)(_RawRestrictionContainer);
bool (*addressCallback)(_Node, HashTable<std::string, std::string>);
/* the input stream to parse */
std::fstream input;
/* ThreadData Queue */
ConcurrentQueue < _ThreadData* >* threadDataQueue;
};
#endif /* PBFPARSER_H_ */
-90
View File
@@ -1,90 +0,0 @@
/*
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
-76
View File
@@ -1,76 +0,0 @@
/*
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 PhantomNode {
PhantomNode() : edgeBasedNode(UINT_MAX), nodeBasedEdgeNameID(UINT_MAX), weight1(INT_MAX), weight2(INT_MAX) {}
NodeID edgeBasedNode;
unsigned nodeBasedEdgeNameID;
int weight1;
int weight2;
_Coordinate location;
void Reset() {
edgeBasedNode = UINT_MAX;
nodeBasedEdgeNameID = UINT_MAX;
weight1 = INT_MAX;
weight2 = INT_MAX;
location.Reset();
}
bool isBidirected() const {
return weight2 != INT_MAX;
}
};
struct PhantomNodes {
PhantomNode startPhantom;
PhantomNode targetPhantom;
void Reset() {
startPhantom.Reset();
targetPhantom.Reset();
}
bool PhantomsAreOnSameNodeBasedEdge() const {
return (startPhantom.edgeBasedNode == targetPhantom.edgeBasedNode);
}
bool AtLeastOnePhantomNodeIsUINTMAX() const {
return !(startPhantom.edgeBasedNode == UINT_MAX || targetPhantom.edgeBasedNode == UINT_MAX);
}
};
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn){
out << "Node1: " << pn.startPhantom.edgeBasedNode << std::endl;
out << "Node2: " << pn.targetPhantom.edgeBasedNode << std::endl;
out << "startCoord: " << pn.startPhantom.location << std::endl;
out << "targetCoord: " << pn.targetPhantom.location << std::endl;
return out;
}
struct NodesOfEdge {
NodeID edgeBasedNode;
double ratio;
_Coordinate projectedPoint;
};
#endif /* PHANTOMNODES_H_ */
-267
View File
@@ -1,267 +0,0 @@
/*
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 SEARCHENGINE_H_
#define SEARCHENGINE_H_
#include <climits>
#include <deque>
#include <boost/thread.hpp>
#include "BinaryHeap.h"
#include "PhantomNodes.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
struct _HeapData {
NodeID parent;
_HeapData( NodeID p ) : parent(p) { }
};
typedef boost::thread_specific_ptr<BinaryHeap< NodeID, NodeID, int, _HeapData > > HeapPtr;
template<class EdgeData, class GraphT>
class SearchEngine {
private:
const GraphT * _graph;
NodeInformationHelpDesk * nodeHelpDesk;
std::vector<string> * _names;
static HeapPtr _forwardHeap;
static HeapPtr _backwardHeap;
inline double absDouble(double input) { if(input < 0) return input*(-1); else return input;}
public:
SearchEngine(GraphT * g, NodeInformationHelpDesk * nh, std::vector<string> * n = new std::vector<string>()) : _graph(g), nodeHelpDesk(nh), _names(n) {}
~SearchEngine() {}
inline const void GetCoordinatesForNodeID(NodeID id, _Coordinate& result) const {
result.lat = nodeHelpDesk->getLatitudeOfNode(id);
result.lon = nodeHelpDesk->getLongitudeOfNode(id);
}
inline void InitializeThreadLocalStorageIfNecessary() {
if(!_forwardHeap.get())
_forwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData >(nodeHelpDesk->getNumberOfNodes()));
else
_forwardHeap->Clear();
if(!_backwardHeap.get())
_backwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData >(nodeHelpDesk->getNumberOfNodes()));
else
_backwardHeap->Clear();
}
int ComputeRoute(PhantomNodes & phantomNodes, std::vector<_PathData> & path) {
int _upperbound = INT_MAX;
if(!phantomNodes.AtLeastOnePhantomNodeIsUINTMAX())
return _upperbound;
InitializeThreadLocalStorageIfNecessary();
NodeID middle = ( NodeID ) UINT_MAX;
bool stOnSameEdge = false;
//Handling the special case that origin and destination are on same edge and that the order is correct.
if(phantomNodes.PhantomsAreOnSameNodeBasedEdge()){
if(phantomNodes.startPhantom.isBidirected() && phantomNodes.targetPhantom.isBidirected()) {
int weight = std::abs(phantomNodes.startPhantom.weight1 - phantomNodes.targetPhantom.weight1);
return weight;
} else if(phantomNodes.startPhantom.weight1 <= phantomNodes.targetPhantom.weight1){
int weight = std::abs(phantomNodes.startPhantom.weight1 - phantomNodes.targetPhantom.weight1);
return weight;
} else {
stOnSameEdge = true;
}
}
//insert start and/or target node of start edge
_forwardHeap->Insert(phantomNodes.startPhantom.edgeBasedNode, -phantomNodes.startPhantom.weight1, phantomNodes.startPhantom.edgeBasedNode);
if(phantomNodes.startPhantom.isBidirected() ) {
_forwardHeap->Insert(phantomNodes.startPhantom.edgeBasedNode+1, -phantomNodes.startPhantom.weight2, phantomNodes.startPhantom.edgeBasedNode+1);
}
//insert start and/or target node of target edge id
_backwardHeap->Insert(phantomNodes.targetPhantom.edgeBasedNode, -phantomNodes.targetPhantom.weight1, phantomNodes.targetPhantom.edgeBasedNode);
if(phantomNodes.targetPhantom.isBidirected() ) {
_backwardHeap->Insert(phantomNodes.targetPhantom.edgeBasedNode+1, -phantomNodes.targetPhantom.weight2, phantomNodes.targetPhantom.edgeBasedNode+1);
}
while(_forwardHeap->Size() + _backwardHeap->Size() > 0){
if(_forwardHeap->Size() > 0){
_RoutingStep(_forwardHeap, _backwardHeap, true, &middle, &_upperbound, stOnSameEdge);
}
if(_backwardHeap->Size() > 0){
_RoutingStep(_backwardHeap, _forwardHeap, false, &middle, &_upperbound, stOnSameEdge);
}
}
if ( _upperbound == INT_MAX ) {
return _upperbound;
}
NodeID pathNode = middle;
deque<NodeID> packedPath;
while(phantomNodes.startPhantom.edgeBasedNode != pathNode && (!phantomNodes.startPhantom.isBidirected() || phantomNodes.startPhantom.edgeBasedNode+1 != pathNode) ) {
pathNode = _forwardHeap->GetData(pathNode).parent;
packedPath.push_front(pathNode);
}
packedPath.push_back(middle);
pathNode = middle;
while(phantomNodes.targetPhantom.edgeBasedNode != pathNode && (!phantomNodes.targetPhantom.isBidirected() || phantomNodes.targetPhantom.edgeBasedNode+1 != pathNode)) {
pathNode = _backwardHeap->GetData(pathNode).parent;
packedPath.push_back(pathNode);
}
for(deque<NodeID>::size_type i = 0;i < packedPath.size() - 1;i++){
_UnpackEdge(packedPath[i], packedPath[i + 1], path);
}
return _upperbound;
}
inline bool FindRoutingStarts(const _Coordinate & start, const _Coordinate & target, PhantomNodes & routingStarts) const {
nodeHelpDesk->FindRoutingStarts(start, target, routingStarts);
return true;
}
inline bool FindPhantomNodeForCoordinate(const _Coordinate & location, PhantomNode & result) const {
return nodeHelpDesk->FindPhantomNodeForCoordinate(location, result);
}
inline NodeID GetNameIDForOriginDestinationNodeID(NodeID s, NodeID t) const {
if(s == t)
return 0;
EdgeID e = _graph->FindEdge(s, t);
if(e == UINT_MAX)
e = _graph->FindEdge( t, s );
if(UINT_MAX == e) {
return 0;
}
assert(e != UINT_MAX);
const EdgeData ed = _graph->GetEdgeData(e);
return ed.via;
}
inline std::string GetEscapedNameForNameID(const NodeID nameID) const {
return ((nameID >= _names->size() || nameID == 0) ? std::string("") : HTMLEntitize(_names->at(nameID)));
}
inline std::string GetEscapedNameForEdgeBasedEdgeID(const unsigned edgeID) const {
const unsigned nameID = _graph->GetEdgeData(edgeID).nameID1;
return GetEscapedNameForNameID(nameID);
}
private:
inline void _RoutingStep(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const bool & forwardDirection, NodeID *middle, int *_upperbound, const bool stOnSameEdge) const {
const NodeID node = _forwardHeap->DeleteMin();
const int distance = _forwardHeap->GetKey(node);
if(_backwardHeap->WasInserted(node) && (!stOnSameEdge || distance > 0) ){
const int newDistance = _backwardHeap->GetKey(node) + distance;
if(newDistance < *_upperbound){
*middle = node;
*_upperbound = newDistance;
}
}
if(distance > *_upperbound){
_forwardHeap->DeleteAll();
return;
}
for ( typename GraphT::EdgeIterator edge = _graph->BeginEdges( node ); edge < _graph->EndEdges(node); edge++ ) {
const EdgeData & data = _graph->GetEdgeData(edge);
bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward;
if(backwardDirectionFlag) {
const NodeID to = _graph->GetTarget(edge);
const int edgeWeight = data.distance;
assert( edgeWeight > 0 );
//Stalling
if(_forwardHeap->WasInserted( to )) {
if(_forwardHeap->GetKey( to ) + edgeWeight < distance) {
return;
}
}
}
}
for ( typename GraphT::EdgeIterator edge = _graph->BeginEdges( node ); edge < _graph->EndEdges(node); edge++ ) {
const EdgeData & data = _graph->GetEdgeData(edge);
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
if(forwardDirectionFlag) {
const NodeID to = _graph->GetTarget(edge);
const int edgeWeight = data.distance;
assert( edgeWeight > 0 );
const int toDistance = distance + edgeWeight;
//New Node discovered -> Add to Heap + Node Info Storage
if ( !_forwardHeap->WasInserted( to ) ) {
_forwardHeap->Insert( to, toDistance, node );
}
//Found a shorter Path -> Update distance
else if ( toDistance < _forwardHeap->GetKey( to ) ) {
_forwardHeap->GetData( to ).parent = node;
_forwardHeap->DecreaseKey( to, toDistance );
//new parent
}
}
}
}
inline bool _UnpackEdge(const NodeID source, const NodeID target, std::vector<_PathData> & path) const {
assert(source != target);
//find edge first.
typename GraphT::EdgeIterator smallestEdge = SPECIAL_EDGEID;
int smallestWeight = INT_MAX;
for(typename GraphT::EdgeIterator eit = _graph->BeginEdges(source);eit < _graph->EndEdges(source);eit++){
const int weight = _graph->GetEdgeData(eit).distance;
if(_graph->GetTarget(eit) == target && weight < smallestWeight && _graph->GetEdgeData(eit).forward){
smallestEdge = eit;
smallestWeight = weight;
}
}
if(smallestEdge == SPECIAL_EDGEID){
for(typename GraphT::EdgeIterator eit = _graph->BeginEdges(target);eit < _graph->EndEdges(target);eit++){
const int weight = _graph->GetEdgeData(eit).distance;
if(_graph->GetTarget(eit) == source && weight < smallestWeight && _graph->GetEdgeData(eit).backward){
smallestEdge = eit;
smallestWeight = weight;
}
}
}
assert(smallestWeight != INT_MAX);
const EdgeData& ed = _graph->GetEdgeData(smallestEdge);
if(ed.shortcut) {//unpack
const NodeID middle = ed.via;
_UnpackEdge(source, middle, path);
_UnpackEdge(middle, target, path);
return false;
} else {
assert(!ed.shortcut);
path.push_back(_PathData(ed.via, ed.nameID1, ed.turnInstruction, ed.distance) );
return true;
}
}
};
template<class EdgeData, class GraphT> HeapPtr SearchEngine<EdgeData, GraphT>::_forwardHeap;
template<class EdgeData, class GraphT> HeapPtr SearchEngine<EdgeData, GraphT>::_backwardHeap;
#endif /* SEARCHENGINE_H_ */
-39
View File
@@ -1,39 +0,0 @@
/*
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 SEGMENTINFORMATION_H_
#define SEGMENTINFORMATION_H_
#include <climits>
struct SegmentInformation {
_Coordinate location;
NodeID nameID;
unsigned length;
unsigned duration;
short turnInstruction;
bool necessary;
SegmentInformation(const _Coordinate & loc, const NodeID nam, const unsigned len, const unsigned dur, const short tInstr, const bool nec) :
location(loc), nameID(nam), length(len), duration(dur), turnInstruction(tInstr), necessary(nec) {}
SegmentInformation(const _Coordinate & loc, const NodeID nam, const unsigned len, const unsigned dur, const short tInstr) :
location(loc), nameID(nam), length(len), duration(dur), turnInstruction(tInstr), necessary(tInstr != 0) {}
};
#endif /* SEGMENTINFORMATION_H_ */
-162
View File
@@ -1,162 +0,0 @@
/*
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 STATICGRAPH_H_INCLUDED
#define STATICGRAPH_H_INCLUDED
#include <vector>
#ifdef _GLIBCXX_PARALLEL
#include <parallel/algorithm>
#else
#include <algorithm>
#endif
#include "../typedefs.h"
#include "ImportEdge.h"
template< typename EdgeDataT>
class StaticGraph {
public:
typedef NodeID NodeIterator;
typedef NodeID EdgeIterator;
typedef EdgeDataT EdgeData;
class InputEdge {
public:
EdgeDataT data;
NodeIterator source;
NodeIterator target;
bool operator<( const InputEdge& right ) const {
if ( source != right.source )
return source < right.source;
return target < right.target;
}
};
StaticGraph( const int nodes, std::vector< InputEdge > &graph ) {
#ifdef _GLIBCXX_PARALLEL
__gnu_parallel::sort( graph.begin(), graph.end() );
#else
std::sort( graph.begin(), graph.end() );
#endif
_numNodes = nodes;
_numEdges = ( EdgeIterator ) graph.size();
_nodes.resize( _numNodes + 1);
EdgeIterator edge = 0;
EdgeIterator position = 0;
for ( NodeIterator node = 0; node <= _numNodes; ++node ) {
EdgeIterator lastEdge = edge;
while ( edge < _numEdges && graph[edge].source == node )
++edge;
_nodes[node].firstEdge = position; //=edge
position += edge - lastEdge; //remove
}
_edges.resize( position ); //(edge)
edge = 0;
for ( NodeIterator node = 0; node < _numNodes; ++node ) {
for ( EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) {
_edges[i].target = graph[edge].target;
_edges[i].data = graph[edge].data;
assert(_edges[i].data.distance > 0);
edge++;
}
}
}
unsigned GetNumberOfNodes() const {
return _numNodes;
}
unsigned GetNumberOfEdges() const {
return _numEdges;
}
unsigned GetOutDegree( const NodeIterator &n ) const {
return BeginEdges(n)-EndEdges(n) - 1;
}
inline NodeIterator GetTarget( const EdgeIterator &e ) const {
return NodeIterator( _edges[e].target );
}
inline EdgeDataT &GetEdgeData( const EdgeIterator &e ) {
return _edges[e].data;
}
const EdgeDataT &GetEdgeData( const EdgeIterator &e ) const {
return _edges[e].data;
}
EdgeIterator BeginEdges( const NodeIterator &n ) const {
return EdgeIterator( _nodes[n].firstEdge );
}
EdgeIterator EndEdges( const NodeIterator &n ) const {
return EdgeIterator( _nodes[n+1].firstEdge );
}
//searches for a specific edge
EdgeIterator FindEdge( const NodeIterator &from, const NodeIterator &to ) const {
EdgeIterator smallestEdge = SPECIAL_EDGEID;
EdgeWeight smallestWeight = UINT_MAX;
for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
const NodeID target = GetTarget(edge);
const EdgeWeight weight = GetEdgeData(edge).distance;
if(target == to && weight < smallestWeight) {
smallestEdge = edge; smallestWeight = weight;
}
}
return smallestEdge;
}
EdgeIterator FindEdgeInEitherDirection( const NodeIterator &from, const NodeIterator &to ) const {
EdgeIterator tmp = FindEdge( from, to );
return (UINT_MAX != tmp ? tmp : FindEdge( to, from ));
}
EdgeIterator FindEdgeIndicateIfReverse( const NodeIterator &from, const NodeIterator &to, bool & result ) const {
EdgeIterator tmp = FindEdge( from, to );
if(UINT_MAX == tmp) {
tmp = FindEdge( to, from );
if(UINT_MAX != tmp)
result = true;
}
return tmp;
}
private:
struct _StrNode {
//index of the first edge
EdgeIterator firstEdge;
};
struct _StrEdge {
NodeID target;
EdgeDataT data;
};
NodeIterator _numNodes;
EdgeIterator _numEdges;
std::vector< _StrNode > _nodes;
std::vector< _StrEdge > _edges;
};
#endif // STATICGRAPH_H_INCLUDED
-230
View File
@@ -1,230 +0,0 @@
/*
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 {
#define KDTREE_BASESIZE (8)
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;
bool operator==( const InputPoint& right )
{
for ( int i = 0; i < k; i++ ) {
if ( coordinates[i] != right.coordinates[i] )
return false;
}
return true;
}
};
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.right - tree.left < KDTREE_BASESIZE )
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 ) {
Metric distance;
bool found = false;
double nearestDistance = std::numeric_limits< T >::max();
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.right - tree.left < KDTREE_BASESIZE ) {
for ( unsigned i = tree.left; i < tree.right; i++ ) {
double newDistance = distance( kdtree[i].coordinates, point.coordinates );
if ( newDistance < nearestDistance ) {
nearestDistance = newDistance;
*result = kdtree[i];
found = true;
}
}
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
-154
View File
@@ -1,154 +0,0 @@
/*
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 TURNINSTRUCTIONS_H_
#define TURNINSTRUCTIONS_H_
#include <string>
//This is a hack until c++0x is available enough to use scoped enums
struct TurnInstructionsClass {
const static short NoTurn = 0; //Give no instruction at all
const static short GoStraight = 1; //Tell user to go straight!
const static short TurnSlightRight = 2;
const static short TurnRight = 3;
const static short TurnSharpRight = 4;
const static short UTurn = 5;
const static short TurnSharpLeft = 6;
const static short TurnLeft = 7;
const static short TurnSlightLeft = 8;
const static short ReachViaPoint = 9;
const static short HeadOn = 10;
const static short EnterRoundAbout = 11;
const static short LeaveRoundAbout = 12;
const static short StayOnRoundAbout = 13;
std::string TurnStrings[14];
std::string Ordinals[11];
//This is a hack until c++0x is available enough to use initializer lists.
TurnInstructionsClass(){
TurnStrings [0] = "";
TurnStrings [1] = "Continue";
TurnStrings [2] = "Turn slight right";
TurnStrings [3] = "Turn right";
TurnStrings [4] = "Turn sharp right";
TurnStrings [5] = "U-Turn";
TurnStrings [6] = "Turn sharp left";
TurnStrings [7] = "Turn left";
TurnStrings [8] = "Turn slight left";
TurnStrings [9] = "Reach via point";
TurnStrings[10] = "Head";
TurnStrings[11] = "Enter round-about";
TurnStrings[12] = "Leave round-about";
TurnStrings[13] = "Stay on round-about";
Ordinals[0] = "zeroth";
Ordinals[1] = "first";
Ordinals[2] = "second";
Ordinals[3] = "third";
Ordinals[4] = "fourth";
Ordinals[5] = "fifth";
Ordinals[6] = "sixth";
Ordinals[7] = "seventh";
Ordinals[8] = "eighth";
Ordinals[9] = "nineth";
Ordinals[10] = "tenth";
};
static inline double GetTurnDirectionOfInstruction( const double angle ) {
if(angle >= 23 && angle < 67) {
return TurnSharpRight;
}
if (angle >= 67 && angle < 113) {
return TurnRight;
}
if (angle >= 113 && angle < 158) {
return TurnSlightRight;
}
if (angle >= 158 && angle < 202) {
return GoStraight;
}
if (angle >= 202 && angle < 248) {
return TurnSlightLeft;
}
if (angle >= 248 && angle < 292) {
return TurnLeft;
}
if (angle >= 292 && angle < 336) {
return TurnSharpLeft;
}
return 5;
}
static inline bool TurnIsNecessary ( const short turnInstruction ) {
if(NoTurn == turnInstruction || StayOnRoundAbout == turnInstruction)
return false;
return true;
}
// static inline void getDirectionOfInstruction(double angle, DirectionOfInstruction & dirInst) {
// if(angle >= 23 && angle < 67) {
// dirInst.direction = "southeast";
// dirInst.shortDirection = "SE";
// return;
// }
// if(angle >= 67 && angle < 113) {
// dirInst.direction = "south";
// dirInst.shortDirection = "S";
// return;
// }
// if(angle >= 113 && angle < 158) {
// dirInst.direction = "southwest";
// dirInst.shortDirection = "SW";
// return;
// }
// if(angle >= 158 && angle < 202) {
// dirInst.direction = "west";
// dirInst.shortDirection = "W";
// return;
// }
// if(angle >= 202 && angle < 248) {
// dirInst.direction = "northwest";
// dirInst.shortDirection = "NW";
// return;
// }
// if(angle >= 248 && angle < 292) {
// dirInst.direction = "north";
// dirInst.shortDirection = "N";
// return;
// }
// if(angle >= 292 && angle < 336) {
// dirInst.direction = "northeast";
// dirInst.shortDirection = "NE";
// return;
// }
// dirInst.direction = "East";
// dirInst.shortDirection = "E";
// return;
// }
//
};
static TurnInstructionsClass TurnInstructions;
#endif /* TURNINSTRUCTIONS_H_ */
-70
View File
@@ -1,70 +0,0 @@
/*
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 TIMEUTIL_H_
#define TIMEUTIL_H_
#include <climits>
#include <cmath>
#include <cstdlib>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifdef _WIN32
#include <sys/timeb.h>
#include <sys/types.h>
#include <winsock.h>
void gettimeofday(struct timeval* t,void* timezone)
{ struct _timeb timebuffer;
_ftime( &timebuffer );
t->tv_sec=timebuffer.time;
t->tv_usec=1000*timebuffer.millitm;
}
#else
#include <sys/time.h>
#endif
#ifdef _WIN32
#include <boost/functional/hash.hpp>
#else
#include <tr1/functional_hash.h>
#endif
#include <boost/thread.hpp>
/** Returns a timestamp (now) in seconds (incl. a fractional part). */
static inline double get_timestamp() {
struct timeval tp;
gettimeofday(&tp, NULL);
return double(tp.tv_sec) + tp.tv_usec / 1000000.;
}
static inline double y2lat(double a) { return 180/M_PI * (2 * atan(exp(a*M_PI/180)) - M_PI/2); }
static inline double lat2y(double a) { return 180/M_PI * log(tan(M_PI/4+a*(M_PI/180)/2)); }
static inline unsigned boost_thread_id_hash(boost::thread::id const& id) {
std::stringstream ostr;
ostr << id;
std::tr1::hash<std::string> h;
return h(ostr.str());
}
#endif /* TIMEUTIL_H_ */
-217
View File
@@ -1,217 +0,0 @@
/*
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 XMLPARSER_H_
#define XMLPARSER_H_
#include <libxml/xmlreader.h>
#include "../typedefs.h"
#include "BaseParser.h"
#include "HashTable.h"
#include "ExtractorStructs.h"
#include "InputReaderFactory.h"
class XMLParser : public BaseParser<_Node, _RawRestrictionContainer, _Way> {
public:
XMLParser(const char * filename) {
WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf");
inputReader = inputReaderFactory(filename);
}
virtual ~XMLParser() {}
bool RegisterCallbacks(bool (*nodeCallbackPointer)(_Node), bool (*restrictionCallbackPointer)(_RawRestrictionContainer), bool (*wayCallbackPointer)(_Way), bool (*addressCallbackPointer)(_Node, HashTable<std::string, std::string>) ) {
nodeCallback = *nodeCallbackPointer;
wayCallback = *wayCallbackPointer;
restrictionCallback = *restrictionCallbackPointer;
return true;
}
bool Init() {
return (xmlTextReaderRead( inputReader ) == 1);
}
bool Parse() {
while ( xmlTextReaderRead( inputReader ) == 1 ) {
const int type = xmlTextReaderNodeType( inputReader );
//1 is Element
if ( type != 1 )
continue;
xmlChar* currentName = xmlTextReaderName( inputReader );
if ( currentName == NULL )
continue;
if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) {
_Node n = _ReadXMLNode( );
if(!(*nodeCallback)(n))
std::cerr << "[XMLParser] node not parsed" << std::endl;
}
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
string name;
_Way way = _ReadXMLWay( );
if(!(*wayCallback)(way)) {
std::cerr << "[XMLParser] way not parsed" << std::endl;
}
}
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
_Relation r;
r.type = _Relation::unknown;
//todo: parse relation
}
xmlFree( currentName );
}
return true;
}
private:
_Relation _ReadXMLRelation ( ) {
_Relation relation;
relation.type = _Relation::unknown;
return relation;
}
_Way _ReadXMLWay( ) {
_Way way;
way.direction = _Way::notSure;
way.speed = -1;
way.type = -1;
way.useful = false;
way.access = true;
// cout << "new way" << endl;
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
const int depth = xmlTextReaderDepth( inputReader );
while ( xmlTextReaderRead( inputReader ) == 1 ) {
const int childType = xmlTextReaderNodeType( inputReader );
if ( childType != 1 && childType != 15 )
continue;
const int childDepth = xmlTextReaderDepth( inputReader );
xmlChar* childName = xmlTextReaderName( inputReader );
if ( childName == NULL )
continue;
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) {
xmlFree( childName );
break;
}
if ( childType != 1 ) {
xmlFree( childName );
continue;
}
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
// cout << "->k=" << k << ", v=" << value << endl;
if ( k != NULL && value != NULL ) {
way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value));
}
if ( k != NULL )
xmlFree( k );
if ( value != NULL )
xmlFree( value );
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) {
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
if ( ref != NULL ) {
way.path.push_back( atoi(( const char* ) ref ) );
xmlFree( ref );
}
}
xmlFree( childName );
}
}
return way;
}
_Node _ReadXMLNode( ) {
_Node node;
xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" );
if ( attribute != NULL ) {
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 ));
xmlFree( attribute );
}
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
if ( attribute != NULL ) {
node.id = atoi(( const char* ) attribute );
xmlFree( attribute );
}
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
const int depth = xmlTextReaderDepth( inputReader );
while ( xmlTextReaderRead( inputReader ) == 1 ) {
const int childType = xmlTextReaderNodeType( inputReader );
// 1 = Element, 15 = EndElement
if ( childType != 1 && childType != 15 )
continue;
const int childDepth = xmlTextReaderDepth( inputReader );
xmlChar* childName = xmlTextReaderName( inputReader );
if ( childName == NULL )
continue;
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) {
xmlFree( childName );
break;
}
if ( childType != 1 ) {
xmlFree( childName );
continue;
}
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
if ( k != NULL && value != NULL ) {
if ( xmlStrEqual( k, ( const xmlChar* ) "highway" ) == 1 ) {
if ( xmlStrEqual( value, ( const xmlChar* ) "traffic_signals" ) == 1 ){
//node.trafficSignal = true;
}
}
}
if ( k != NULL )
xmlFree( k );
if ( value != NULL )
xmlFree( value );
}
xmlFree( childName );
}
}
return node;
}
/* Input Reader */
xmlTextReaderPtr inputReader;
/* Function pointer for nodes */
bool (*nodeCallback)(_Node);
bool (*wayCallback)(_Way);
bool (*restrictionCallback)(_RawRestrictionContainer);
};
#endif /* XMLPARSER_H_ */
-53
View File
@@ -1,53 +0,0 @@
/** Copyright (c) 2010 Scott A. Crosby. <scott@sacrosby.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) 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 General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
option java_package = "crosby.binary";
package OSMPBF;
//protoc --java_out=../.. fileformat.proto
//
// STORAGE LAYER: Storing primitives.
//
message Blob {
optional bytes raw = 1; // No compression
optional int32 raw_size = 2; // When compressed, the uncompressed size
// Possible compressed versions of the data.
optional bytes zlib_data = 3;
// PROPOSED feature for LZMA compressed data. SUPPORT IS NOT REQUIRED.
optional bytes lzma_data = 4;
// Formerly used for bzip2 compressed data. Depreciated in 2010.
optional bytes OBSOLETE_bzip2_data = 5 [deprecated=true]; // Don't reuse this tag number.
}
/* A file contains an sequence of fileblock headers, each prefixed by
their length in network byte order, followed by a data block
containing the actual data. types staring with a "_" are reserved.
*/
message BlobHeader {
required string type = 1;
optional bytes indexdata = 2;
required int32 datasize = 3;
}
-226
View File
@@ -1,226 +0,0 @@
/** Copyright (c) 2010 Scott A. Crosby. <scott@sacrosby.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) 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 General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
option java_package = "crosby.binary";
package OSMPBF;
/* OSM Binary file format
This is the master schema file of the OSM binary file format. This
file is designed to support limited random-access and future
extendability.
A binary OSM file consists of a sequence of FileBlocks (please see
fileformat.proto). The first fileblock contains a serialized instance
of HeaderBlock, followed by a sequence of PrimitiveBlock blocks that
contain the primitives.
Each primitiveblock is designed to be independently parsable. It
contains a string table storing all strings in that block (keys and
values in tags, roles in relations, usernames, etc.) as well as
metadata containing the precision of coordinates or timestamps in that
block.
A primitiveblock contains a sequence of primitive groups, each
containing primitives of the same type (nodes, densenodes, ways,
relations). Coordinates are stored in signed 64-bit integers. Lat&lon
are measured in units <granularity> nanodegrees. The default of
granularity of 100 nanodegrees corresponds to about 1cm on the ground,
and a full lat or lon fits into 32 bits.
Converting an integer to a lattitude or longitude uses the formula:
$OUT = IN * granularity / 10**9$. Many encoding schemes use delta
coding when representing nodes and relations.
*/
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
/* Contains the file header. */
message HeaderBlock {
optional HeaderBBox bbox = 1;
/* Additional tags to aid in parsing this dataset */
repeated string required_features = 4;
repeated string optional_features = 5;
optional string writingprogram = 16;
optional string source = 17; // From the bbox field.
}
/** The bounding box field in the OSM header. BBOX, as used in the OSM
header. Units are always in nanodegrees -- they do not obey
granularity rules. */
message HeaderBBox {
required sint64 left = 1;
required sint64 right = 2;
required sint64 top = 3;
required sint64 bottom = 4;
}
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
message PrimitiveBlock {
required StringTable stringtable = 1;
repeated PrimitiveGroup primitivegroup = 2;
// Granularity, units of nanodegrees, used to store coordinates in this block
optional int32 granularity = 17 [default=100];
// Offset value between the output coordinates coordinates and the granularity grid in unites of nanodegrees.
optional int64 lat_offset = 19 [default=0];
optional int64 lon_offset = 20 [default=0];
// Granularity of dates, normally represented in units of milliseconds since the 1970 epoch.
optional int32 date_granularity = 18 [default=1000];
// Proposed extension:
//optional BBox bbox = XX;
}
// Group of OSMPrimitives. All primitives in a group must be the same type.
message PrimitiveGroup {
repeated Node nodes = 1;
optional DenseNodes dense = 2;
repeated Way ways = 3;
repeated Relation relations = 4;
repeated ChangeSet changesets = 5;
}
/** String table, contains the common strings in each block.
Note that we reserve index '0' as a delimiter, so the entry at that
index in the table is ALWAYS blank and unused.
*/
message StringTable {
repeated bytes s = 1;
}
/* Optional metadata that may be included into each primitive. */
message Info {
optional int32 version = 1 [default = -1];
optional int64 timestamp = 2;
optional int64 changeset = 3;
optional int32 uid = 4;
optional uint32 user_sid = 5; // String IDs
}
/** Optional metadata that may be included into each primitive. Special dense format used in DenseNodes. */
message DenseInfo {
repeated int32 version = 1 [packed = true];
repeated sint64 timestamp = 2 [packed = true]; // DELTA coded
repeated sint64 changeset = 3 [packed = true]; // DELTA coded
repeated sint32 uid = 4 [packed = true]; // DELTA coded
repeated sint32 user_sid = 5 [packed = true]; // String IDs for usernames. DELTA coded
}
// THIS IS STUB DESIGN FOR CHANGESETS. NOT USED RIGHT NOW.
// TODO: REMOVE THIS?
message ChangeSet {
required int64 id = 1;
//
// // Parallel arrays.
// repeated uint32 keys = 2 [packed = true]; // String IDs.
// repeated uint32 vals = 3 [packed = true]; // String IDs.
//
// optional Info info = 4;
// optional int64 created_at = 8;
// optional int64 closetime_delta = 9;
// optional bool open = 10;
// optional HeaderBBox bbox = 11;
}
message Node {
required sint64 id = 1;
// Parallel arrays.
repeated uint32 keys = 2 [packed = true]; // String IDs.
repeated uint32 vals = 3 [packed = true]; // String IDs.
optional Info info = 4; // May be omitted in omitmeta
required sint64 lat = 8;
required sint64 lon = 9;
}
/* Used to densly represent a sequence of nodes that do not have any tags.
We represent these nodes columnwise as five columns: ID's, lats, and
lons, all delta coded. When metadata is not omitted,
We encode keys & vals for all nodes as a single array of integers
containing key-stringid and val-stringid, using a stringid of 0 as a
delimiter between nodes.
( (<keyid> <valid>)* '0' )*
*/
message DenseNodes {
repeated sint64 id = 1 [packed = true]; // DELTA coded
//repeated Info info = 4;
optional DenseInfo denseinfo = 5;
repeated sint64 lat = 8 [packed = true]; // DELTA coded
repeated sint64 lon = 9 [packed = true]; // DELTA coded
// Special packing of keys and vals into one array. May be empty if all nodes in this block are tagless.
repeated int32 keys_vals = 10 [packed = true];
}
message Way {
required int64 id = 1;
// Parallel arrays.
repeated uint32 keys = 2 [packed = true];
repeated uint32 vals = 3 [packed = true];
optional Info info = 4;
repeated sint64 refs = 8 [packed = true]; // DELTA coded
}
message Relation {
enum MemberType {
NODE = 0;
WAY = 1;
RELATION = 2;
}
required int64 id = 1;
// Parallel arrays.
repeated uint32 keys = 2 [packed = true];
repeated uint32 vals = 3 [packed = true];
optional Info info = 4;
// Parallel arrays
repeated int32 roles_sid = 8 [packed = true];
repeated sint64 memids = 9 [packed = true]; // DELTA encoded
repeated MemberType types = 10 [packed = true];
}
-73
View File
@@ -1,73 +0,0 @@
/*
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 BASE_DESCRIPTOR_H_
#define BASE_DESCRIPTOR_H_
#include <cassert>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include "../typedefs.h"
#include "../DataStructures/ExtractorStructs.h"
#include "../DataStructures/HashTable.h"
#include "../Util/StringUtil.h"
#include "../Plugins/RawRouteData.h"
struct _RouteSummary {
std::string lengthString;
std::string durationString;
std::string startName;
std::string destName;
_RouteSummary() : lengthString("0"), durationString("0"), startName("unknown street"), destName("unknown street") {}
void BuildDurationAndLengthStrings(unsigned distance, unsigned time) {
//compute distance/duration for route summary
std::ostringstream s;
s << 10*(round(distance/10.));
lengthString = s.str();
int travelTime = time/10 + 1;
s.str("");
s << travelTime;
durationString = s.str();
}
};
struct _DescriptorConfig {
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(false), z(18) {}
bool instructions;
bool geometry;
bool encodeGeometry;
unsigned short z;
};
template<class SearchEngineT>
class BaseDescriptor {
public:
BaseDescriptor() { }
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
virtual ~BaseDescriptor() { }
virtual void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned distance) = 0;
virtual void SetConfig(const _DescriptorConfig & config) = 0;
};
#endif /* BASE_DESCRIPTOR_H_ */
-95
View File
@@ -1,95 +0,0 @@
/*
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.
*/
#include "DescriptionFactory.h"
DescriptionFactory::DescriptionFactory() { }
DescriptionFactory::~DescriptionFactory() { }
double DescriptionFactory::GetAngleBetweenCoordinates() const {
return 0.;//GetAngleBetweenTwoEdges(previousCoordinate, currentCoordinate, nextCoordinate);
}
void DescriptionFactory::SetStartSegment(const PhantomNode & _startPhantom) {
startPhantom = _startPhantom;
AppendSegment(_startPhantom.location, _PathData(0, _startPhantom.nodeBasedEdgeNameID, 10, _startPhantom.weight1));
}
void DescriptionFactory::SetEndSegment(const PhantomNode & _targetPhantom) {
targetPhantom = _targetPhantom;
pathDescription.push_back(SegmentInformation(_targetPhantom.location, _targetPhantom.nodeBasedEdgeNameID, 0, _targetPhantom.weight1, 0, true) );
}
void DescriptionFactory::AppendSegment(const _Coordinate & coordinate, const _PathData & data ) {
pathDescription.push_back(SegmentInformation(coordinate, data.nameID, 0, data.durationOfSegment, data.turnInstruction) );
}
void DescriptionFactory::AppendEncodedPolylineString(std::string & output, bool isEncoded) {
if(isEncoded)
pc.printEncodedString(pathDescription, output);
else
pc.printUnencodedString(pathDescription, output);
}
void DescriptionFactory::AppendEncodedPolylineString(std::string &output) {
pc.printEncodedString(pathDescription, output);
}
void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) {
pc.printUnencodedString(pathDescription, output);
}
unsigned DescriptionFactory::Run(const unsigned zoomLevel) {
if(0 == pathDescription.size())
return 0;
unsigned entireLength = 0;
/** starts at index 1 */
pathDescription[0].length = 0;
for(unsigned i = 1; i < pathDescription.size(); ++i) {
pathDescription[i].length = ApproximateDistance(pathDescription[i-1].location, pathDescription[i].location);
}
unsigned lengthOfSegment = 0;
unsigned durationOfSegment = 0;
unsigned indexOfSegmentBegin = 0;
for(unsigned i = 1; i < pathDescription.size(); ++i) {
entireLength += pathDescription[i].length;
lengthOfSegment += pathDescription[i].length;
durationOfSegment += pathDescription[i].duration;
pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
if(pathDescription[i].turnInstruction != 0) {
//INFO("Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID);
assert(pathDescription[i].necessary);
lengthOfSegment = 0;
durationOfSegment = 0;
indexOfSegmentBegin = i;
}
}
//Generalize poly line
dp.Run(pathDescription, zoomLevel);
//fix what needs to be fixed else
return entireLength;
}
-98
View File
@@ -1,98 +0,0 @@
/*
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 DESCRIPTIONFACTORY_H_
#define DESCRIPTIONFACTORY_H_
#include <vector>
#include "../typedefs.h"
#include "../Algorithms/DouglasPeucker.h"
#include "../Algorithms/PolylineCompressor.h"
#include "../DataStructures/ExtractorStructs.h"
#include "../DataStructures/SegmentInformation.h"
/* This class is fed with all way segments in consecutive order
* and produces the description plus the encoded polyline */
class DescriptionFactory {
DouglasPeucker<SegmentInformation> dp;
PolylineCompressor pc;
PhantomNode startPhantom, targetPhantom;
public:
//I know, declaring this public is considered bad. I'm lazy
std::vector <SegmentInformation> pathDescription;
DescriptionFactory();
virtual ~DescriptionFactory();
double GetAngleBetweenCoordinates() const;
void AppendEncodedPolylineString(std::string &output);
void AppendUnencodedPolylineString(std::string &output);
void AppendSegment(const _Coordinate & coordinate, const _PathData & data);
void SetStartSegment(const PhantomNode & startPhantom);
void SetEndSegment(const PhantomNode & startPhantom);
void AppendEncodedPolylineString(std::string & output, bool isEncoded);
unsigned Run(const unsigned zoomLevel);
};
#endif /* DESCRIPTIONFACTORY_H_ */
//private:
// void appendInstructionNameToString(const std::string & nameOfStreet, const std::string & instructionOrDirection, std::string &output, bool firstAdvice = false) {
// output += "[";
// if(config.instructions) {
// output += "\"";
// if(firstAdvice) {
// output += "Head ";
// }
// output += instructionOrDirection;
// output += "\",\"";
// output += nameOfStreet;
// output += "\",";
// }
// }
//
// void appendInstructionLengthToString(unsigned length, std::string &output) {
// if(config.instructions){
// std::string tmpDistance;
// intToString(10*(round(length/10.)), tmpDistance);
// output += tmpDistance;
// output += ",";
// intToString(descriptionFactory.startIndexOfGeometry, tmp);
// output += tmp;
// output += ",";
// intToString(descriptionFactory.durationOfInstruction, tmp);
// output += tmp;
// output += ",";
// output += "\"";
// output += tmpDistance;
// output += "\",";
// double angle = descriptionFactory.GetAngleBetweenCoordinates();
// DirectionOfInstruction direction;
// getDirectionOfInstruction(angle, direction);
// output += "\"";
// output += direction.shortDirection;
// output += "\",";
// std::stringstream numberString;
// numberString << fixed << setprecision(2) << angle;
// output += numberString.str();
// }
// output += "]";
// }
-67
View File
@@ -1,67 +0,0 @@
/*
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 GPX_DESCRIPTOR_H_
#define GPX_DESCRIPTOR_H_
#include <boost/foreach.hpp>
#include "BaseDescriptor.h"
template<class SearchEngineT>
class GPXDescriptor : public BaseDescriptor<SearchEngineT>{
private:
_DescriptorConfig config;
_Coordinate current;
std::string tmp;
public:
void SetConfig(const _DescriptorConfig& c) { config = c; }
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned distance) {
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
reply.content += "<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" "
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
"\">";
reply.content += "<rte>";
if(distance != UINT_MAX && rawRoute.routeSegments.size()) {
convertInternalLatLonToString(phantomNodes.startPhantom.location.lat, tmp);
reply.content += "<rtept lat=\"" + tmp + "\" ";
convertInternalLatLonToString(phantomNodes.startPhantom.location.lon, tmp);
reply.content += "lon=\"" + tmp + "\"></rtept>";
for(unsigned segmentIdx = 0; segmentIdx < rawRoute.routeSegments.size(); segmentIdx++) {
BOOST_FOREACH(_PathData pathData, rawRoute.routeSegments[segmentIdx]) {
sEngine.GetCoordinatesForNodeID(pathData.node, current);
convertInternalLatLonToString(current.lat, tmp);
reply.content += "<rtept lat=\"" + tmp + "\" ";
convertInternalLatLonToString(current.lon, tmp);
reply.content += "lon=\"" + tmp + "\"></rtept>";
}
}
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lat, tmp);
reply.content += "<rtept lat=\"" + tmp + "\" ";
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lon, tmp);
reply.content += "lon=\"" + tmp + "\"></rtept>";
}
reply.content += "</rte></gpx>";
}
};
#endif /* GPX_DESCRIPTOR_H_ */
-176
View File
@@ -1,176 +0,0 @@
/*
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 JSON_DESCRIPTOR_H_
#define JSON_DESCRIPTOR_H_
#include <boost/foreach.hpp>
#include "BaseDescriptor.h"
#include "DescriptionFactory.h"
#include "../DataStructures/SegmentInformation.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/StringUtil.h"
template<class SearchEngineT>
class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
private:
_DescriptorConfig config;
_RouteSummary summary;
DescriptionFactory descriptionFactory;
std::string tmp;
_Coordinate current;
struct {
int startIndex;
int nameID;
int leaveAtExit;
} roundAbout;
public:
JSONDescriptor() {}
void SetConfig(const _DescriptorConfig & c) { config = c; }
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned durationOfTrip) {
WriteHeaderToOutput(reply.content);
if(durationOfTrip != INT_MAX && rawRoute.routeSegments.size() > 0) {
summary.startName = sEngine.GetEscapedNameForNameID(phantomNodes.startPhantom.nodeBasedEdgeNameID);
descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
summary.destName = sEngine.GetEscapedNameForNameID(phantomNodes.targetPhantom.nodeBasedEdgeNameID);
reply.content += "0,"
"\"status_message\": \"Found route between points\",";
for(unsigned segmentIdx = 0; segmentIdx < rawRoute.routeSegments.size(); segmentIdx++) {
const std::vector< _PathData > & path = rawRoute.routeSegments[segmentIdx];
BOOST_FOREACH(_PathData pathData, path) {
sEngine.GetCoordinatesForNodeID(pathData.node, current);
descriptionFactory.AppendSegment(current, pathData );
}
//TODO: Add via points
}
descriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
} else {
//We do not need to do much, if there is no route ;-)
reply.content += "207,"
"\"status_message\": \"Cannot find route between points\",";
}
summary.BuildDurationAndLengthStrings(descriptionFactory.Run(config.z), durationOfTrip);
reply.content += "\"route_summary\": {"
"\"total_distance\":";
reply.content += summary.lengthString;
reply.content += ","
"\"total_time\":";
reply.content += summary.durationString;
reply.content += ","
"\"start_point\":\"";
reply.content += summary.startName;
reply.content += "\","
"\"end_point\":\"";
reply.content += summary.destName;
reply.content += "\"";
reply.content += "},";
reply.content += "\"route_geometry\": ";
if(config.geometry) {
if(config.encodeGeometry)
descriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
} else {
reply.content += "[]";
}
reply.content += ","
"\"route_instructions\": [";
if(config.instructions) {
//Segment information has following format:
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
unsigned prefixSumOfNecessarySegments = 0;
roundAbout.leaveAtExit = 0;
roundAbout.nameID = 0;
std::string tmpDist, tmpLength, tmp;
//Fetch data from Factory and generate a string from it.
BOOST_FOREACH(SegmentInformation segment, descriptionFactory.pathDescription) {
if(TurnInstructions.TurnIsNecessary( segment.turnInstruction) ) {
if(TurnInstructions.EnterRoundAbout == segment.turnInstruction) {
roundAbout.nameID = segment.nameID;
roundAbout.startIndex = prefixSumOfNecessarySegments;
} else {
if(0 != prefixSumOfNecessarySegments)
reply.content += ",";
reply.content += "[\"";
if(TurnInstructions.LeaveRoundAbout == segment.turnInstruction) {
reply.content += TurnInstructions.TurnStrings[TurnInstructions.EnterRoundAbout];
reply.content += " and leave at ";
reply.content += TurnInstructions.Ordinals[roundAbout.leaveAtExit+1];
reply.content += " exit";
roundAbout.leaveAtExit = 0;
} else {
reply.content += TurnInstructions.TurnStrings[segment.turnInstruction];
}
reply.content += "\",\"";
reply.content += sEngine.GetEscapedNameForNameID(segment.nameID);
reply.content += "\",";
intToString(segment.length, tmpDist);
reply.content += tmpDist;
reply.content += ",";
intToString(prefixSumOfNecessarySegments, tmpLength);
reply.content += tmpLength;
reply.content += ",";
intToString(segment.duration, tmp);
reply.content += ",\"";
reply.content += tmpLength;
//TODO: fix heading
reply.content += "\",\"NE\",22.5";
reply.content += "]";
}
} else if(TurnInstructions.StayOnRoundAbout == segment.turnInstruction) {
++roundAbout.leaveAtExit;
}
if(segment.necessary)
++prefixSumOfNecessarySegments;
}
}
reply.content += "],";
//list all viapoints so that the client may display it
reply.content += "\"via_points\":[";
for(unsigned segmentIdx = 1; (true == config.geometry) && (segmentIdx < rawRoute.segmentEndCoordinates.size()); segmentIdx++) {
if(segmentIdx > 1)
reply.content += ",";
reply.content += "[";
if(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location.isSet())
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location, tmp);
else
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates[segmentIdx], tmp);
reply.content += tmp;
reply.content += "]";
}
reply.content += "],"
"\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.2)\"";
reply.content += "}";
}
void WriteHeaderToOutput(std::string & output) {
output += "{"
"\"version\": 0.3,"
"\"status\":";
}
};
#endif /* JSON_DESCRIPTOR_H_ */
-9
View File
@@ -1,9 +0,0 @@
Third Party Libraries:
Scons 1.3+
Boost 1.37+
sparsehash 1.4+
stxxl 1.3.1+
libz2-dev 1.0.5+
protobuffer 2.3.0+
zlib 1.2.3.4+
-44
View File
@@ -1,44 +0,0 @@
FAQ
---
Q: What platforms does OSMR run on?
A: Virtually any Unix-like platform with g++ installed. It has been developed
under Linux and tested on MacOS X 10.6. It should run under Windows as well
though the code will need some adjustments.
Q: What is the workflow to get the engine up and running
A: Road network extraction->Preprocessing->Startup
Q: What does OSRM stand for?
A: It is an abbreviation for Open Source Routing Machine.
Q: What does HSGR stand for?
A: It is an abbreviation for Hierarchy Search GRaph.
Q: What is the .nodes file?
A: It is a map that translates between internal and external Node IDs. Remember
that external NodeIDs can be arbitrary and non-contigous. Internally the
nodes are numbered from 0 to n-1.
Q: The routing engine crashes with a seg-fault
A: Check the startup parameters.
Q: Something about the route is odd. I know that there is a better path
A: Most probably it is missing data in the OSM file.
Q: I work for this company that would like to use the code, but we are hesistant
because of the license.
A: Contact me. Probably, we can work something out.
Q: How fast is this thing?
A: Good question. Here is a number. The engine was able to handle more than
2800 requests per Minute on the German road network with the travel time
metric on a Core 2 Duo. This also includes transfer of data across a
switched 100MBit/s LAN. So, I guess it's fair to say it's fast.
Q: What is the difference between extractNetwork and extractLargeNetwork?
A: extractNetwork does all of its magic in RAM, while extractLargeNetwork uses the
stxxl library to store the data in external memory. Use the first one for small
networks, but beware of running out of RAM. Swapping is the kiss of death. For
larger networks use extractLargeNetwork. It will be somewhat slower on the
smaller files, but way faster with large ones like the planet file.
-6
View File
@@ -1,6 +0,0 @@
- extractorLargeNetwork finishes with:
terminate called after throwing an instance of 'stxxl::resource_error'
what(): Error in function void stxxl::mutex::lock() pthread_mutex_lock(&_mutex) Invalid argument
This ist a known, albeit odd behavior that is caused by a bug in stxxl. It can be ignored. Upgrade
to version 1.3.1 of stxxl.
-159
View File
@@ -1,159 +0,0 @@
/*
* Open Source Routing Machine (OSRM) - Web (GUI) Interface
* Copyright (C) Pascal Neis, 2011
*
* 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.
*/
/**
* Title: Geocode.js
* Description: JS file for geocoding
*
* @author Pascal Neis, pascal@neis-one.org
* @version 0.1 2011-05-15
*/
//======================
// OBJECTS
var HOST_GEOCODE_URL = 'http://open.mapquestapi.com';
var GEOCODE_POST = HOST_GEOCODE_URL + '/nominatim/v1/search?format=json&json_callback=showResultsGeocode';
var searchType = 'search';
var isStartPointSet = false;
var isEndPointSet = false;
//======================
// FUNCTIONS
/*
* geocodeAddress()-Function to read out textfield and send request to a OSM nominatim geocoder
*/
function geocodeAddress(tf){
var freeform;
if(tf == 'start'){
freeform = document.getElementById('tfStartSearch').value;
}
if(tf == 'end'){
freeform = document.getElementById('tfEndSearch').value;
}
document.getElementById('information').style.visibility = 'visible';
document.getElementById('information').innerHTML = '<p class="infoHL">One moment please ...</p>';
var newURL = GEOCODE_POST + "&q="+freeform;
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = newURL;
document.body.appendChild(script);
}
/*
* showResultsGeocode()-Function to show the geocode result in a div
*/
function showResultsGeocode(response) {
var html = '';
var lonlat = '';
if(response){
html += '<p class="infoHL">Search Results:</p>';
html += '<table>'
var markername;
if(getStatus()=='start'){
markername = 'start'; isStartPointSet = true;
}
else if(getStatus()=='end'){
markername = 'end'; isEndPointSet = true;
}
for(var i=0; i < response.length; i++){
var result = response[i]; var resultNum = i+1;
        //odd or even ?
        var rowstyle='geocodeResultOdd';
        if(i%2==0){ rowstyle='geocodeResultEven'; }
       
html += '<tr class="'+rowstyle+'">';
html += '<td align="right" valign="top"><span class="routeSummarybold">'+resultNum+'</span></td>';
html += '<td class="'+rowstyle+'">';
if(result.display_name){
var new_display_name = result.display_name;//.replace(/,/g, ",<br />")
html += '<a href="#" onclick="javascript:setMarkerAndZoom(\''+markername+'\', new OpenLayers.LonLat('+result.lon+','+result.lat+'));">'+new_display_name.trim()+'</a>';
}
html += "</td></tr>";
//alert(result.lat + ", " + result.lon);
if(lonlat == ''){
lonlat = new OpenLayers.LonLat(result.lon,result.lat);
}
}
html += '</table>';
setMarkerAndZoom(markername, lonlat);
}
switch (searchType) {
case "search":
document.getElementById('information').style.display = "";
document.getElementById('information').innerHTML = html;
break;
}
}
/*
* setMarkerAndZoom()-Function to set a marker on the map and zoom
*/
function setMarkerAndZoom(markername,lonlat){
setMarker(markername,lonlat);
//Hack - FIXME !
lonlat.lon -= 500;
//Set Center
map.setCenter(lonlat, 15);
}
/*
* setMarker()-Function to set a marker on the map
*/
function setMarker(markername,lonlat){
lonlat.transform(EPSG_4326, EPSG_900913);
for(var i= 0; i<dragLayer.features.length; i++){
if(dragLayer.features[i].name == markername){ dragLayer.removeFeatures([dragLayer.features[i]]); }
}
var point = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat));
point.attributes = { icon: "img/start.png" };
if(markername == 'start'){
point.attributes = { icon: "img/start.png" };
}
else if(markername == 'end'){
point.attributes = { icon: "img/end.png" };
}
point.name = markername;
dragLayer.addFeatures([point]);
}
/*
* getMarkerByName()-Function to return the marker-object by a name
*/
function getMarkerByName(markerName){
for(var i= 0; i<dragLayer.features.length; i++){
if(dragLayer.features[i].name == markerName){
return dragLayer.features[i];
}
}
}
-354
View File
@@ -1,354 +0,0 @@
/*
* Open Source Routing Machine (OSRM) - Web (GUI) Interface
* Copyright (C) Pascal Neis, 2011
*
* 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.
*/
/**
* Title: Map.js
* Description: JS file to show a map, for markers, left slide div, ...
*
* @author Pascal Neis, pascal@neis-one.org
* @version 0.1.1 2011-06-09
*/
//======================
// OBJECTS
//Map
var map;
//Status object for what position actually a coordinate is searched
var status = ''; //possible values [start,end]
function getStatus(){ return status; }
function setStatus(stat){ status = stat; }
//Indicator
var ISDRAGGING = false;
//Layer
var dragLayer;
var vectorLayerRoute;
var vectorLayerViaRoute;
var markersLayer;
var selectFeature;
//======================
// FUNCTIONS
/*
* init()-Function to create the map div
*/
function init(){
//Create Map
map = new OpenLayers.Map ("map", {
controls:[
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.Permalink(),
new OpenLayers.Control.LayerSwitcher()],
maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
maxResolution: 156543.0399,
numZoomLevels: 19,
units: 'm',
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326")
} );
//Add the base layers.
var coverageLayer = new OpenLayers.Layer.Vector("Coverage", {
style: {
strokeColor: "#000000",
strokeTransparency: 0.5,
strokeWidth: 4
}
});
if("map.project-osrm.org" == location.host) {
var coveragePointList = [
new OpenLayers.Geometry.Point(-11.99, 58.80),
new OpenLayers.Geometry.Point(-11.99, 35.30),
new OpenLayers.Geometry.Point(-7.57, 35.30),
new OpenLayers.Geometry.Point(9.22, 38.24),
new OpenLayers.Geometry.Point(15.38, 35.39),
new OpenLayers.Geometry.Point(18.92, 40.02),
new OpenLayers.Geometry.Point(15.70, 42.25),
new OpenLayers.Geometry.Point(15.70, 55.40),
new OpenLayers.Geometry.Point(30.31, 60.29),
new OpenLayers.Geometry.Point(30.31, 71.27),
new OpenLayers.Geometry.Point(21.01, 71.27),
new OpenLayers.Geometry.Point(-11.99, 58.80)
];
var line_string = new OpenLayers.Geometry.LineString(coveragePointList).transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));
coverageLayer.addFeatures([new OpenLayers.Feature.Vector(line_string)]);
map.addLayer(coverageLayer);
}
map.addLayer(new OpenLayers.Layer.OSM.Mapnik("Mapnik"));
map.addLayer(new OpenLayers.Layer.OSM.MapQuest("MapQuest"));
map.addLayer(new OpenLayers.Layer.OSM.Osmarender("Osmarender"));
//Add layer for the route
vectorLayerRoute = new OpenLayers.Layer.Vector("Route",{maxResolution: 156543.0339});
map.addLayer(vectorLayerRoute);
//Add layer for temporary via route
vectorLayerViaRoute = new OpenLayers.Layer.Vector("ViaRoute",{maxResolution: 156543.0339});
map.addLayer(vectorLayerViaRoute);
//Add Layerswitcher
map.addControl(new OpenLayers.Control.LayerSwitcher());
//Add Panzoombar
var panZoomBar = new OpenLayers.Control.PanZoomBar({id:'panzoombar',displayClass:'olControlPanZoomBar'})
map.addControl(panZoomBar);
//Customize the position of the panzoombar
document.getElementById('panzoombar').style.left="400px";
document.getElementById('panzoombar').style.top="25px";
//Create drag vector layer
dragLayer = new OpenLayers.Layer.Vector(
"Start/End Marker",{
styleMap: new OpenLayers.StyleMap({
// Set the external graphic and background graphic images.
externalGraphic: '${icon}',
// Makes sure the background graphic is placed correctly relative
// to the external graphic.
backgroundXOffset: -11,
backgroundYOffset: -40,
graphicXOffset: -11,
graphicYOffset: -40,
// Set the z-indexes of both graphics to make sure the background
// graphics stay in the background (shadows on top of markers looks
// odd; let's not do that).
graphicZIndex: 10,
backgroundGraphicZIndex: 11,
pointRadius: 10,
graphicWidth: 22,
graphicHeight: 40
}),
rendererOptions: {zIndexing: true}
}
);
// Add a drag feature control to move features around.
var dragFeatures = new OpenLayers.Control.DragFeature(dragLayer,
{ onDrag: function(feature, pixel){
ISDRAGGING = true;
if(feature.name == "start" || feature.name == "end") {
feature.move(map.getLonLatFromPixel(pixel));
if(!ISCALCULATING){ routing(true); }
}
if(feature.name == "via") {
computeViaRoute(pixel, true);
}
if(feature.name == "viapoint" && feature.popup) {
map.removePopup(feature.popup);
computeViaRoute(pixel, true, feature.viaIndex);
}
},
onComplete: function(feature, pixel){
ISDRAGGING = false;
if(feature.name == "start" || feature.name == "end") {
feature.move(map.getLonLatFromPixel(pixel));
routing(false);
} else if(feature.name == "via") {
console.log('finished via');
//Erase temporary point from draglayer
dragLayer.renderer.eraseFeatures([feature]);
//delete temporary route from via route Layer
vectorLayerViaRoute.removeFeatures(vectorLayerViaRoute.features);
//compute via route
computeViaRoute(pixel, false);
feature.destroy();
} else if(feature.name == "viapoint") {
//Erase temporary point from draglayer
dragLayer.renderer.eraseFeatures([feature]);
//delete via point from vector
viaPointsVector.splice(feature.viaIndex,1);
//delete temporary route from via route Layer
vectorLayerViaRoute.removeFeatures(vectorLayerViaRoute.features);
//compute via route
computeViaRoute(pixel, false);
feature.destroy();
}
},
onLeave: function(f){
if(!ISCALCULATING){ routing(false); }}
});
map.addControl(dragFeatures);
dragFeatures.activate();
map.addLayers([dragLayer]);
//Add a marker layer
markersLayer = new OpenLayers.Layer.Markers("Markers");
map.addLayer(markersLayer);
//Add zoom event for rerouting
map.events.on({zoomend: function(e) {reroute();distanceToRoute(null);}});
// Register Callback to evaluate distance to from mouse location to route on Mousemove
map.events.on({mousemove: function(e) {distanceToRoute(e.xy);}});
// Set center of the map
if (!map.getCenter()){
map.setCenter(new OpenLayers.LonLat(600000, 6600000),6);
}
//Check if the URL contains some GET parameter, e.g. for the route
checkURL();
for(var i = 0; i < map.layers.length; i++) {
map.layers[i].transitionEffect = 'resize';
}
document.getElementById('map').oncontextmenu = function(e){
e = e?e:window.event;
if (e.preventDefault) e.preventDefault(); // For non-IE browsers.
else return false; // For IE browsers.
};
// A control class for capturing click events...
OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, {
defaultHandlerOptions: {
'single': true,
'double': true,
'pixelTolerance': 0,
'stopSingle': false,
'stopDouble': false
},
handleRightClicks:true,
initialize: function(options) {
this.handlerOptions = OpenLayers.Util.extend(
{}, this.defaultHandlerOptions
);
OpenLayers.Control.prototype.initialize.apply(
this, arguments
);
this.handler = new OpenLayers.Handler.Click(
this, this.eventMethods, this.handlerOptions
);
},
CLASS_NAME: "OpenLayers.Control.Click"
});
// Add an instance of the Click control that listens to various click events:
var oClick = new OpenLayers.Control.Click({eventMethods:{
'rightclick': function(e) {
rightClick(e);
},
'click': function(e) {
leftClick(e);
},
'dblclick': function(e) {
dblClick(e);
},
'dblrightclick': function(e) {
dblRightClick(e);
}
}});
map.addControl(oClick);
oClick.activate();
selectFeature = new OpenLayers.Control.SelectFeature(
[dragLayer],
{
clickout: true, toggle: false,
multiple: false, hover: true,
toggleKey: "ctrlKey", // ctrl key removes from selection
multipleKey: "shiftKey", // shift key adds to selection
onSelect: createPopup,
onUnselect: destroyPopup
}
);
map.addControl(selectFeature);
dragLayer.events.on({
"featureselected": function(e) {
featureSelected(e);
},
"featureunselected": function(e) {
featureUnselected(e);
}
});
selectFeature.activate();
}
//Helper Functions
function checkReturn(textfieldname,e){
var evt = e || window.event;
if(!evt){ return; }
var key = 0;
if (evt.keyCode) { key = evt.keyCode; }
else if (typeof(evt.which)!= 'undefined') { key = evt.which; }
if( key == 13 && textfieldname=='start'){ setStatus('start'); geocodeAddress('start'); return; }
if( key == 13 && textfieldname=='end'){ setStatus('end'); geocodeAddress('end'); return; }
}
function closeOpenDiv(name){
if(document.getElementById(name).style.display == 'none'){ document.getElementById(name).style.display = ''; }
else{ document.getElementById(name).style.display = 'none'; }
}
//URL Functions
function checkURL(){
var getObjs = new Array();
var getString = document.location.search.substr(1,document.location.search.length);
if(getString != ''){
var getArray=getString.split('&');
console.log(getArray);
for(i=0 ; i<getArray.length ; ++i){
var v='';
var vArr = getArray[i].split('=');
if(vArr.length>1){ v = vArr[1]; }
if("via" == vArr[0]) {
var via_loc = unescape(v).split(',');
for(var j=0; j<via_loc.length; j++) { via_loc[j] = parseFloat(via_loc[j]); }
viaPointsVector.push(via_loc);
} else {
getObjs[unescape(vArr[0])]=unescape(v);
}
}
}
var fr = getObjectOfArray(getObjs, "fr");
var to = getObjectOfArray(getObjs, "to");
if(fr != 'undefined' && to != 'undefined'){
//From
var fr_pos = fr.split(',');
var fr_lonlat = new OpenLayers.LonLat(fr_pos[1],fr_pos[0]);
setMarkerAndZoom('start', fr_lonlat);
isStartPointSet = true;
//To
var to_pos = to.split(',');
var to_lonlat = new OpenLayers.LonLat(to_pos[1],to_pos[0]);
setMarker('end', to_lonlat);
isEndPointSet = true;
//Calculate the route
routing(false);
}
}
function getObjectOfArray(objects, elementName){
if(!objects[elementName]){ return 'undefined'; }
return objects[elementName];
}
-115
View File
@@ -1,115 +0,0 @@
var selectedFeature = null;
var popupCloseTimer = null;
var popupToRemove = null;
function rightClick(e) {
console.log("right click1");
if(null == selectedFeature)
return;
//alert('rightclick at '+e.xy.x+','+e.xy.y);
console.log("right click2");
}
function dblClick(e) {
//alert('dblclick at '+e.xy.x+','+e.xy.y);
}
function dblRightClick(e) {
//alert('dblrightclick at '+e.xy.x+','+e.xy.y);
}
function leftClick(e) {
//set start and target via clicks
var lonlat = map.getLonLatFromViewPortPx(e.xy);
var markername = "";
/* //routing shall not be done by left clicks
* if (e.ctrlKey || e.altKey) {
markername = "end";
isEndPointSet = true;
} else if(e.shiftKey) {
markername = "start";
isStartPointSet = true;
}
for(var i= 0; i<dragLayer.features.length; i++){
if(dragLayer.features[i].name == markername){ dragLayer.removeFeatures([dragLayer.features[i]]); }
}
var point = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat));
point.attributes = { icon: "img/start.png" };
if(markername == 'start'){
point.attributes = { icon: "img/start.png" };
}
else if(markername == 'end'){
point.attributes = { icon: "img/end.png" };
}
point.name = markername;
dragLayer.addFeatures([point]);
reroute();
*/
}
function featureSelected(f) {
if("viapoint" == f.feature.name) {
// console.log('selected ' + f.feature.name);
selectedFeature = f.feature;
}
}
function featureUnselected(f) {
if("viapoint" == f.feature.name) {
// console.log('unselected ' + f.feature.name);
selectedFeature = null;
}
}
function createPopup(feature) {
if("viapoint" != feature.name || ISDRAGGING)
return;
if(popupCloseTimer != null) {
clearInterval(popupCloseTimer);
popupCloseTimer = null;
map.removePopup(popupToRemove);
popupToRemove = null;
}
var location = feature.geometry.getBounds().getCenterLonLat().clone();
location.lon; location.lat;
feature.popup = new OpenLayers.Popup.Anchored("ViaPointInfo",
location,
new OpenLayers.Size(16,16),
'<div><a href="javascript:removeViaPoint('+ feature.viaIndex +')"><img src="img/cancel_small.png"/></a></div>',
null,
false,
destroyPopup );
feature.popup.backgroundColor = 'transparent';
feature.popup.fixedRelativePosition = true;
feature.popup.relativePosition = "tr";
map.addPopup(feature.popup, true);
}
function destroyPopup(feature) {
if(feature.popup) {
popupToRemove = feature.popup;
popupCloseTimer = setTimeout("removePopup()",2000);
}
}
function removePopup() {
if(null == popupToRemove)
return;
map.removePopup(popupToRemove);
popupToRemove = null;
popupCloseTimer = null;
}
function removeViaPoint(index) {
for(var i = 0; i < map.popups.length; i++) {
map.removePopup(map.popups[i]);
}
viaPointsVector.splice(index, 1);
reroute();
}
-366
View File
@@ -1,366 +0,0 @@
/*
* Open Source Routing Machine (OSRM) - Web (GUI) Interface
* Copyright (C) Pascal Neis, 2011
*
* 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.
*/
/**
* Title: Route.js
* Description: JS file for routing
*
* @author Pascal Neis, pascal@neis-one.org
* @version 0.2 2011-06-23
*/
//======================
// OBJECTS
//Map
//var HOST_ROUTING_URL = 'http://localhost:5000/viaroute';
var HOST_ROUTING_URL = 'http://routingdemo.geofabrik.de/route-via/';
var HOST_WEBSITE = 'http://map.project-osrm.org/';//location.host
var ISCALCULATING = false;
var EPSG_4326 = new OpenLayers.Projection("EPSG:4326");
var EPSG_900913 = new OpenLayers.Projection("EPSG:900913");
var allRoutePoints = [];
//======================
// FUNCTIONS
/*
* routing()-Function to create and send route request
*/
function routing(isDragRoute){
//Check if startpoint is set
if(!isStartPointSet){
//alert("Please set your Start location first!");
document.getElementById('information').innerHTML = '<p class="infoHLRed">Please set your Start location first!</p>';
return;
}
//Check if endpoint is set
if(!isEndPointSet){
//alert("Please set your Destination first!");
document.getElementById('information').innerHTML = '<p class="infoHLRed">Please set your Destination first!</p>';
return;
}
//Check if already a route is planning
if(!isDragRoute){ ISCALCULATING = false; }
if(ISCALCULATING){ return; }
else{ ISCALCULATING = true; }
//Get Coordinates of the Start and Endpoint
var startFeat = getMarkerByName('start');
var endFeat = getMarkerByName('end');
var from = new OpenLayers.LonLat(startFeat.geometry.x,startFeat.geometry.y).transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
var to = new OpenLayers.LonLat(endFeat.geometry.x,endFeat.geometry.y).transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
//Send Request
var script = document.createElement('script');
script.type = 'text/javascript';
var callBackFunction = 'showResultsRoute';
var instructions = '&geomformat=cmp&instructions=true';
if(isDragRoute){
callBackFunction = 'showResultsDragRoute';
instructions = '&geomformat=cmp&instructions=false';
document.getElementById('information').innerHTML = '<p class="infoHL">Release mouse button to get Route Information!</p>(If no Route Summary is diplayed, press the Route!-button)';
}
script.src = HOST_ROUTING_URL + "&start="+from.lat + ',' + from.lon + '&dest=' + to.lat + ',' + to.lon;
for(var i = 0; i < viaPointsVector.length; i++) {
script.src += ('&via=' + viaPointsVector[i][0] + ',' + viaPointsVector[i][1]);
}
script.src +='&z='+this.map.getZoom()+'&output=json&jsonp='+callBackFunction+instructions;
document.body.appendChild(script);
}
/*
* reroute()-Function
*/
function reroute() {
if(!isStartPointSet || !isEndPointSet){ return; }
routing(false);
}
/*
* showResultsDragRoute()-Function to show route result for drag-route
*/
function showResultsDragRoute(response) {
   if (response) {
    //Display Route
    showRouteGeometry(response);
   }
  markersLayer.clearMarkers();
   ISCALCULATING = false;
}
/*
* showResultsRoute()-Function to show route result
*/
function showResultsRoute(response) {
   if (response) {
//Display Route
if(document.getElementById("cbNoNames").checked == true){
showNoNameStreets(response);
}
else{
showRouteGeometry(response);
}
//Save Via Points that come with route
var lengthOfArray = response.via_points.length;
var i = 0;
viaPointsVector.length = 0;
viaPointsVector = response.via_points.slice(0);
paintViaPoints();
  //Create Link of the route
var startFeat = getMarkerByName('start');
var endFeat = getMarkerByName('end');
var from = new OpenLayers.LonLat(startFeat.geometry.x,startFeat.geometry.y).transform(EPSG_900913,EPSG_4326);
var to = new OpenLayers.LonLat(endFeat.geometry.x,endFeat.geometry.y).transform(EPSG_900913,EPSG_4326);
var routelink = '<div id="routelink"><input name="routelink" type="submit" title="Get Link" onClick="createShortLink(\''+HOST_WEBSITE+'?fr='+from.lat.toFixed(6)+','+from.lon.toFixed(6)+'&to='+to.lat.toFixed(6)+','+to.lon.toFixed(6);
for(i = 0; i < viaPointsVector.length; i++) {
routelink += "&via=" + viaPointsVector[i][0] + "," + viaPointsVector[i][1];
}
routelink += '\');" value="Get Link"></div>';
//Link for the GPX Download
var gpxLink = '(<a href="'+HOST_ROUTING_URL+'&start='+from.lat.toFixed(6)+','+from.lon.toFixed(6)+'&dest='+to.lat.toFixed(6)+','+to.lon.toFixed(6)+'&z='+this.map.getZoom();
for(i = 0; i < viaPointsVector.length; i++) {
gpxLink += "&via=" + viaPointsVector[i][0] + "," + viaPointsVector[i][1];
}
gpxLink += '&output=gpx">Get GPX File</a>)';;
       //Show Route Summary
       var output = '<p class="routeSummaryHL">Some information about your Way <br> from \'<span class="routeSummaryHLlight">'+response.route_summary.start_point+'</span>\' to \'<span class="routeSummaryHLlight">'+response.route_summary.end_point+'</span>\'</p>';
       output += '<p class="routeSummary">Distance: <span class="routeSummarybold">'+response.route_summary.total_distance/1000+' km</span> - Duration: <span class="routeSummarybold">'+secondsToTime(response.route_summary.total_time)+'</span></p><p>'+routelink+'</p><p><span class="routeInstructionsHL">The Route-Instructions:</span> '+gpxLink+'</p>';
       //Show Route Instructions
        output += '<table>';
       lengthOfArray = response.route_instructions.length;
for (i = 0; i < lengthOfArray; i++) {
//console.log(response.route_instructions[i]);
        //odd or even ?
        var rowstyle='routeInstructionsOdd';
        if(i%2==0){ rowstyle='routeInstructionsEven'; }
           var indexPos = response.route_instructions[i][3];
//console.log('setting : ' + response.route_instructions[i] + ' at ' + allRoutePoints[indexPos]);
var point = allRoutePoints[indexPos];
       
           output += '<tr class="'+rowstyle+'"><td align="right" valign="top"><span class="routeSummarybold">'+(i+1)+'.</span></td><td class="'+rowstyle+'"><a href="#" class="nolinkStyle" onclick="setMapCenter(new OpenLayers.LonLat('+point.x+','+point.y+'));">'+response.route_instructions[i][0]+' on '+response.route_instructions[i][1]+' for '+getDistanceWithUnit(response.route_instructions[i][2])+'</a></td></tr>';
       }
var rowstyle='routeInstructionsOdd';
      if(i%2==0){ rowstyle='routeInstructionsEven'; }
if( lengthOfArray > 0) {
       var point = allRoutePoints[allRoutePoints.length-1];
       output += '<tr class="'+rowstyle+'"><td align="right" valign="top"><span class="routeSummarybold">'+(i+1)+'.</span></td><td class="'+rowstyle+'"><a href="#" class="nolinkStyle" onclick="setMapCenter(new OpenLayers.LonLat('+point.x+','+point.y+'));">You have reached your destination</a></td></tr>';
       }
output += '</table>';
       //alert(vectorLayerRoute.features[0].geometry.getVertices());
       
       document.getElementById('information').innerHTML = output;
   ISCALCULATING = false;
ISCALCULATINGVIA = false;
   }
}
/*
* showRouteGeometry()-Function to show route result
*/
function showRouteGeometry(response) {
if (response) {
allRoutePoints.length = 0;
    // now with compression of the route geometry
       var geometry = decodeRouteGeometry(response.route_geometry, 5);
      var lengthOfArray = geometry.length;
       var points = [];
       points.length = lengthOfArray;
       var points = [];
//delete any previously displayed via route
vectorLayerViaRoute.removeFeatures(vectorLayerViaRoute.features);
vectorLayerRoute.removeAllFeatures();
       //Create Route Layer for Display
       for (var i = 0; i < lengthOfArray; i++) {
           var point = new OpenLayers.Geometry.Point(geometry[i][1], geometry[i][0]).transform(EPSG_4326, EPSG_900913);
           allRoutePoints.push(point);
points.push(point);
           
if(i % 1024 == 0 && i>0 || i==lengthOfArray-1){
/* var feature2 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(points), null, {
strokeColor: "#000066",
strokeOpacity: 1,
strokeWidth: 9
});
var feature1 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(points), null, {
strokeColor: "#ffffff",
strokeOpacity: 0.75,
strokeWidth: 7
});
*/
var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(points), null, {
strokeColor: "#0033ff",
strokeOpacity: 0.7,
strokeWidth: 5
});
// vectorLayerRoute.addFeatures([feature2]);
// vectorLayerRoute.addFeatures([feature1]);
vectorLayerRoute.addFeatures([feature]);
points = [];
points.push(point);
}
       }
  }
}
/*
* showNoNameStreets()-Function to show route result
*/
function showNoNameStreets(response) {
   if (response) {
    allRoutePoints.length = 0;
    vectorLayerRoute.removeFeatures(vectorLayerRoute.features);
      // now with compression of the route geometry
       var geometry = decodeRouteGeometry(response.route_geometry, 5);
      var lengthOfArray = geometry.length;
       var points = [];
       points.length = lengthOfArray;
       
       //Check if a instruction has no name !
       var colors = [];
       if(true){
        var instrucLength = response.route_instructions.length;
        for (var i = 0; i < instrucLength; i++) {
        var indexPos = response.route_instructions[i][3];
        var streetName = response.route_instructions[i][1];
if(streetName == ''){ colors[indexPos] = "#FF00FF"; }
else{ colors[indexPos] = "#0033ff"; }
        }
       }
//delete any previously displayed via route
vectorLayerViaRoute.removeFeatures(vectorLayerViaRoute.features);
vectorLayerRoute.removeAllFeatures();
       
       //Create Route Layer for Display
       var color = "#0033ff";
       var changeColor = false;
       for (var i = 0; i < lengthOfArray; i++) {
           var point = new OpenLayers.Geometry.Point(geometry[i][1], geometry[i][0]).transform(EPSG_4326, EPSG_900913);
           points.push(point);
           allRoutePoints.push(point);
           if(colors[i] != undefined){ changeColor=true;}
           
if(i % 1024 == 0 && i>0 || i==lengthOfArray-1 || changeColor){
var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(points), null, {
strokeColor: color,
strokeOpacity: 0.7,
strokeWidth: 5
});
vectorLayerRoute.addFeatures([feature]);
points = [];
points.push(point);
if(colors[i] != undefined){ color = colors[i]; }
changeColor=false;
}
       }
  }
}
/*
* secondsToTime()-Function to transform seconds to a time string
*/
function secondsToTime(seconds){
seconds = parseInt(seconds);
minutes = parseInt(seconds/60);
seconds = seconds%60;
hours = parseInt(minutes/60);
minutes = minutes%60;
//return stunden+':'+minuten+':'+seconds;
if(hours==0){
return minutes+' min(s)';
}
else{
return hours+' h '+minutes+' min(s)';
}
}
/*
* getDistanceWithUnit()-Function to return a distance with units
*/
function getDistanceWithUnit(distance){
distance = parseInt(distance);
if(distance >= 1000){ return (parseInt(distance/1000))+' km'; }
else{ return distance+' m'; }
}
/*
* setMapCenter()-Function to add a marker and center the map
*/
function setMapCenter(lonlat){
//lonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));
//console.log('zooming to :' + lonlat);
//Add Marker
markersLayer.clearMarkers();
var size = new OpenLayers.Size(21,25);
var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
var icon = new OpenLayers.Icon('img/marker.png',size,offset);
markersLayer.addMarker(new OpenLayers.Marker(lonlat,icon));
//Hack - FIXME !
map.setCenter(new OpenLayers.LonLat(lonlat.lon-200, lonlat.lat), 17);
}
/*
* decodeRouteGeometry()-Function to decode encoded Route Geometry
*/
function decodeRouteGeometry(encoded, precision) {
precision = Math.pow(10, -precision);
var len = encoded.length, index=0, lat=0, lng = 0, array = [];
while (index < len) {
var b, shift = 0, result = 0;
do {
b = encoded.charCodeAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charCodeAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
array.push([lat * precision, lng * precision]);
}
return array;
}
/*
* createShortLink()-Function to "create" shortlink of a route
*/
function createShortLink(str){
var script = document.createElement('script');
-114
View File
@@ -1,114 +0,0 @@
/*
* Open Source Routing Machine (OSRM) - Web (GUI) Interface
* Copyright (C) Pascal Neis, 2011
*
* 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.
*/
/**
* Title: Slide.js
* Description: Fixme
*
* @author Pascal Neis, pascal@neis-one.org
* @version 0.1 2011-05-15
*/
var timerlen = 5;
var slideAniLen = 250;
var timerID = new Array();
var startTime = new Array();
var obj = new Array();
var endWidth = new Array();
var moving = new Array();
var dir = new Array();
function toggleSlide(objname){
document.getElementById('panzoombar').style.top="25px";
document.getElementById('panzoombar').style.display = "none";
document.getElementById('slide').style.display = "none";
if(document.getElementById(objname).style.display == "none"){
// div is hidden, so let's slide right
slide_right(objname);
}else{
// div is not hidden, so slide left
slide_left(objname);
}
}
function slide_right(objname){
if(moving[objname]){ return; }
if(document.getElementById(objname).style.display != "none"){
return; // cannot slide right something that is already visible
}
moving[objname] = true; dir[objname] = "right"; startslide(objname);
}
function slide_left(objname){
if(moving[objname]){ return; }
if(document.getElementById(objname).style.display == "none"){
return; // cannot slide left something that is already hidden
}
moving[objname] = true; dir[objname] = "left"; startslide(objname);
}
function startslide(objname){
obj[objname] = document.getElementById(objname);
endWidth[objname] = parseInt(obj[objname].style.width);
startTime[objname] = (new Date()).getTime();
if(dir[objname] == "right"){ obj[objname].style.width = "1px"; }
obj[objname].style.display = "block";
timerID[objname] = setInterval('slidetick(\'' + objname + '\');',timerlen);
}
function slidetick(objname){
var elapsed = (new Date()).getTime() - startTime[objname];
if (elapsed > slideAniLen){ endSlide(objname); }
else {
var d = Math.round(elapsed / slideAniLen * endWidth[objname]);
if(dir[objname] == "left"){ d = endWidth[objname] - d; }
obj[objname].style.width = d + "px";
}
return;
}
function endSlide(objname){
clearInterval(timerID[objname]);
if(dir[objname] == "left"){
obj[objname].style.display = "none";
document.getElementById('panzoombar').style.left="25px";
document.getElementById('panzoombar').style.display = "";
document.getElementById('slide').style.left="5px";
document.getElementById('slide').innerHTML = "<a class=\"btn-slide\" href=\"javascript:;\" onmousedown=\"toggleSlide('data');\">>></a>";
document.getElementById('slide').style.display = "";
}
else{
document.getElementById('panzoombar').style.left="400px";
document.getElementById('panzoombar').style.display = "";document.getElementById('slide').style.left="365px";
document.getElementById('slide').innerHTML = "<a class=\"btn-slide\" href=\"javascript:;\" onmousedown=\"toggleSlide('data');\"><<</a>";
document.getElementById('slide').style.display = "";
}
obj[objname].style.width = endWidth[objname] + "px";
delete(moving[objname]);
delete(timerID[objname]);
delete(startTime[objname]);
delete(endWidth[objname]);
delete(obj[objname]);
delete(dir[objname]);
return;
}
-340
View File
@@ -1,340 +0,0 @@
/*
* Open Source Routing Machine (OSRM) - Web (GUI) Interface
* Copyright (C) Dennis Luxen, 2011
*
* 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.
*/
/**
* Title: ViaRoute.js
* Description: JS file for routing with via points
*
* @author Dennis Luxen, luxen@kit.edu
* @version 0.1 June 2011
*
*/
//======================
// OBJECTS
//global timestamp to control frequency of mouse->route distance computations
var timestamp = (new Date()).getTime();
var ISCOMPUTINGDISTANCE = false;
var ISCALCULATINGVIA = false;
//var HASDELETEDTEMPORARYVIAROUTE = false;
var nearestPoint = new OpenLayers.Geometry.Point(1,1);
var nearestSegmentIndex = null;
var viaPointsVector = [];
var p0;
var temporaryViaStyle = {
fillColor: "#ffffff",
strokeColor: "#33ff33",
strokeOpacity: 0.6,
strokeWidth: 2,
pointRadius: 4,
pointerEvents: "visiblePainted"
};
var permanentViaStyle = {
fillColor: "#ffffff",
strokeColor: "#0033ff",
strokeOpacity: 0.6,
strokeWidth: 2,
pointRadius: 4,
pointerEvents: "visiblePainted"
};
//======================
//FUNCTIONS
function distanceBetweenPoint(x1, y1, x2, y2) {
var a = x1 - x2;
var b = y1 - y2;
return Math.sqrt(a*a + b*b);
}
/* Distance from a point to a line or segment.
x point's x coord
y point's y coord
x0 x coord of the line's A point
y0 y coord of the line's A point
x1 x coord of the line's B point
y1 y coord of the line's B point
o specifies if the distance should respect the limits of the segment
(overLine = true) or if it should consider the segment as an infinite
line (overLine = false), if false returns the distance from the point
to the line, otherwise the distance from the point to the segment
*/
function dotLineLength(x, y, x0, y0, x1, y1, o){
function lineLength(x, y, x0, y0){
return Math.sqrt((x -= x0) * x + (y -= y0) * y);
}
if(o && !(o = function(x, y, x0, y0, x1, y1){
if(!(x1 - x0)) return {x: x0, y: y};
else if(!(y1 - y0)) return {x: x, y: y0};
var left, tg = -1 / ((y1 - y0) / (x1 - x0));
return {x: left = (x1 * (x * tg - y + y0) + x0 * (x * - tg + y - y1)) / (tg * (x1 - x0) + y0 - y1), y: tg * left - tg * x + y};
}(x, y, x0, y0, x1, y1), o.x >= Math.min(x0, x1) && o.x <= Math.max(x0, x1) && o.y >= Math.min(y0, y1) && o.y <= Math.max(y0, y1))){
var l1 = lineLength(x, y, x0, y0), l2 = lineLength(x, y, x1, y1);
return l1 > l2 ? l2 : l1;
}
else {
var a = y0 - y1, b = x1 - x0, c = x0 * y1 - y0 * x1;
return Math.abs(a * x + b * y + c) / Math.sqrt(a * a + b * b);
}
};
function distanceToRoute(pixel) {
if(!isStartPointSet || !isEndPointSet){
return;
}
if(ISDRAGGING) {
return;
}
if(ISCOMPUTINGDISTANCE) {
return;
}
var tempTime = (new Date()).getTime()
if( tempTime - timestamp < 25) {
return;
}
timestamp = tempTime;
if(ISCALCULATING) {
var viaPointFeature = dragLayer.getFeatureBy("name", 'via');
if(viaPointFeature != null) {
dragLayer.removeFeatures(viaPointFeature);
viaPointFeature.destroy;
}
return;
}
if(pixel == null) {
pixel.x = window.event.clientX;
pixel.y = window.event.clientY;
}
var newLonLat = map.getLonLatFromPixel(pixel);
var minimumDist = 20*Math.pow(2,(19- this.map.getZoom()));
var minimumDistToVia = 20*Math.pow(2,(19- this.map.getZoom()));
var indexToInsertViaPoint = 0;
var startFeat = getMarkerByName('start');
var endFeat = getMarkerByName('end');
var from = new OpenLayers.LonLat(startFeat.geometry.x,startFeat.geometry.y).transform(EPSG_900913, EPSG_4326);
var to = new OpenLayers.LonLat(endFeat.geometry.x,endFeat.geometry.y).transform(EPSG_900913, EPSG_4326);
var mapExtent = map.getExtent();
for(var i = 0; i < allRoutePoints.length-1; i++) {
var p1 = allRoutePoints[i];
var p2 = allRoutePoints[i+1];
if(p1.x < mapExtent.left || p1.x > mapExtent.right || p1.y < mapExtent.bottom || p1.y > mapExtent.top) {
if(p2.x < mapExtent.left || p2.x > mapExtent.right || p2.y < mapExtent.bottom || p2.y > mapExtent.top) {
continue;
}
}
//check if previous segment is closest to via point
//if yes, then we have passed a via point.
if(viaPointsVector.length > indexToInsertViaPoint && p0) {
var viaPoint = new OpenLayers.LonLat(viaPointsVector[indexToInsertViaPoint][1],viaPointsVector[indexToInsertViaPoint][0]).transform(EPSG_4326, EPSG_900913);
var dist2 = dotLineLength(viaPoint.lon, viaPoint.lat, p1.x, p1.y, p0.x, p0.y, true)
if( 0 == dist2 ) {
indexToInsertViaPoint++;
}
var tmpDist = distanceBetweenPoint(viaPoint.lat, viaPoint.lon, newLonLat.lat, newLonLat.lon);
if(tmpDist < minimumDistToVia) {
minimumDistToVia = tmpDist;
}
}
//continue if point out of view
dist = dotLineLength(newLonLat.lon, newLonLat.lat, p1.x, p1.y, p2.x, p2.y, true);
if(dist <= minimumDist) {
nearestSegmentIndex = indexToInsertViaPoint;
minimumDist = dist;
var lonDiff = (p2.x - p1.x)
var m = (p2.y - p1.y) / lonDiff;
var b = p1.y - (m * p1.x);
var m2 = m*m;
var x = (m * newLonLat.lat + newLonLat.lon - m * b) / (m2 + 1);
var y = (m2 * newLonLat.lat + m * newLonLat.lon + b) / (m2 + 1);
var r = (x - p1.x) / lonDiff;
if ( r <= 1 && r >= 0 ) {
nearestPoint.x = x;
nearestPoint.y = y;
} else {
if( r < 0 ) {
nearestPoint.x = p1.x;
nearestPoint.y = p1.y;
} if ( r > 1 ) {
nearestPoint.x = p2.x;
nearestPoint.y = p2.y;
}
}
if(p2.x == p1.x) {
nearestPoint.x = p1.x;
nearestPoint.y = newLonLat.lat;
}
}
}
var zoomFactor = Math.pow(2,(19- this.map.getZoom()));
var viaPointFeature = dragLayer.getFeatureBy("name", 'via');
if(viaPointFeature != null) {
dragLayer.removeFeatures(viaPointFeature);
viaPointFeature.destroy;
}
//too close to start or destination?
if(Math.min(distanceBetweenPoint(startFeat.geometry.x, startFeat.geometry.y, newLonLat.lon, newLonLat.lat),
distanceBetweenPoint(endFeat.geometry.x, endFeat.geometry.y, newLonLat.lon, newLonLat.lat)) < 10*zoomFactor) {
ISCOMPUTINGDISTANCE = false;
return;
}
//Are we close to the route but sufficiently far away from any existing via point?
if(minimumDist < 10*zoomFactor && minimumDistToVia > 5*zoomFactor) {
viaPointFeature = new OpenLayers.Feature.Vector( OpenLayers.Geometry.Polygon.createRegularPolygon( nearestPoint, (1.5*zoomFactor), 15, 0 ), null, temporaryViaStyle );
viaPointFeature.name = "via";
dragLayer.addFeatures( viaPointFeature );
//console.log('nearestSegmentIndex: ' + nearestSegmentIndex);
}
ISCOMPUTINGDISTANCE = false;
p0 = p1;
}
function computeViaRoute(pixel, isTemporary, skipViaPointsIndex) {
if(ISCALCULATINGVIA && isTemporary)
return;
if( nearestSegmentIndex == null ) {
//console.log('nearestSegmentIndex: ' + nearestSegmentIndex);
return;
}
if(isTemporary == null) {
isTemporary = false;
}
//So, we jumped all fences
ISCALCULATINGVIA = true;
var startFeat = getMarkerByName('start');
var endFeat = getMarkerByName('end');
var from = new OpenLayers.LonLat(startFeat.geometry.x,startFeat.geometry.y).transform(EPSG_900913, EPSG_4326);
var to = new OpenLayers.LonLat(endFeat.geometry.x,endFeat.geometry.y).transform(EPSG_900913, EPSG_4326);
var coordinate = map.getLonLatFromPixel(pixel);
var via = coordinate.transform(EPSG_900913, EPSG_4326);
var viaNodeInserted = false;
var newURL = HOST_ROUTING_URL + "&start="+from.lat + ',' + from.lon + '&dest=' + to.lat + ',' + to.lon;
newURL += '&geomformat=cmp';
for(var i = 0; i < viaPointsVector.length; i++) {
if(i == nearestSegmentIndex) { //insert new via node here
newURL += '&via=' + via.lat + ',' + via.lon;
viaNodeInserted = true;
}
if(skipViaPointsIndex == i)
continue;
newURL += '&via=' + viaPointsVector[i][0] + ',' + viaPointsVector[i][1];
}
if(false == viaNodeInserted) {
newURL += '&via=' + via.lat + ',' + via.lon;
}
newURL += '&output=json' + '&z=' + this.map.getZoom();
if(!isTemporary) {
newURL += '&instructions=true&jsonp=showResultsRoute';
} else {
newURL += '&instructions=false&jsonp=showResultsViaRoute';
}
//console.log(newURL);
var script = document.createElement('script');
script.id = 'JSONP';
script.type = 'application/javascript';
script.src = newURL;
document.body.appendChild(script);
}
function showResultsViaRoute(response) {
if (response) {
var viaRouteVector = [];
    // now with compression of the route geometry
       var geometry = decodeRouteGeometry(response.route_geometry, 5);
      var lengthOfArray = geometry.length;
       var points = [];
       points.length = lengthOfArray;
       //Create Route Layer for Display
       for (var i = 0; i < lengthOfArray; i++) {
           var point = new OpenLayers.Geometry.Point(geometry[i][1], geometry[i][0]).transform(EPSG_4326, EPSG_900913);
           allRoutePoints.push(point);
points.push(point);
           
if(i % 1024 == 0 && i>0 || i==lengthOfArray-1){
/* var feature1 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(points), null, {
strokeColor: "#006600",
strokeOpacity: 1,
strokeWidth: 9
});
*/
var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(points), null, {
strokeColor: "#aaffaa",
strokeOpacity: 0.8,
strokeWidth: 7
});
// viaRouteVector.push(feature1);
viaRouteVector.push(feature);
points = [];
points.push(point);
}
       }
vectorLayerViaRoute.removeFeatures(vectorLayerViaRoute.features);
for(var i = 0; i< viaRouteVector.length; i++) {
vectorLayerViaRoute.addFeatures(viaRouteVector[i]);
}
viaRouteVector.length = 0;
ISCALCULATINGVIA = false;
}
}
function paintViaPoints() {
//remove all previous via points
var featuresToRemove = [];
for(var i = 0; i < dragLayer.features.length; i++) {
if(dragLayer.features[i].name == "viapoint" || "via" == dragLayer.features[i].name ) {
featuresToRemove.push(dragLayer.features[i]);
}
}
dragLayer.removeFeatures(featuresToRemove);
featuresToRemove.length = 0;
//paint all via points
var zoomFactor = Math.pow(2,(19- this.map.getZoom()));
//console.log('painting ' + viaPointsVector.length + ' via points');
for(var i = 0; i < viaPointsVector.length; i++) {
//console.log(viaPointsVector[i]);
var viapoint = new OpenLayers.Geometry.Point(
viaPointsVector[i][1],
viaPointsVector[i][0]);
viapoint.transform(EPSG_4326, EPSG_900913);
var viaPointFeature = new OpenLayers.Feature.Vector( OpenLayers.Geometry.Polygon.createRegularPolygon( viapoint, (1.5*zoomFactor), 20, 0 ), null, permanentViaStyle );
viaPointFeature.name = "viapoint";
viaPointFeature.viaIndex = i;
dragLayer.addFeatures( viaPointFeature )
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 934 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 831 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

-70
View File
@@ -1,70 +0,0 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>OSRM Web(GUI)Interface</title>
<meta name="description" content="OSRM Web(GUI)Interface"/>
<meta name="language" content="en" />
<meta name="robots" content="index,follow" />
<meta name="author" content="Pascal Neis" />
<meta name="revisit-After" content="7 days" />
<meta name="distribution" content="global" />
<script src="ol/OpenLayers.js"></script>
<script src="ol/OpenStreetMap.js"></script>
<script src="Slides.js"></script>
<script src="Map.js"></script>
<script src="Route.js"></script>
<script src="ViaRoute.js"></script>
<script src="Geocode.js"></script>
<script src="MouseClick.js"></script>
<!-- <script src="osrm.js"></script> -->
<link rel="stylesheet" href="style.css" type="text/css" media="all" />
</head>
<body onload="init();">
<div id="slide" class="slide"><a class="btn-slide" href="javascript:;" onmousedown="toggleSlide('data');"><<</a></div>
<div id="data" style="width:350px;overflow:hidden;" class="data">
<div id="inner" style="width:350px;overflow:hidden;">
<div id="routing">
<!-- http://map.project-osrm.org/osrm3_small.png - http://project-osrm.org/osrm3.png -->
<img src="http://map.project-osrm.org/osrm3_small.png" style="margin-left:auto; margin-right:auto; width:200px; display:block; padding: 5px;" alt="">
<table width="100%">
<tr id="StartPoint">
<td><div class="textLabel"><img src="img/arrow-start.png" class="radioIcons" width="12" height="16" alt=""><span class="text"></span></div></td>
<td><input name="tfStartSearch" style="width:220px" type="text" id="tfStartSearch" class="tfPoints" value="Berlin" title="Search your start point!" onKeyPress="checkReturn('start',event);" >
<button name="enterStart" onclick="setStatus('start'); geocodeAddress('start');">Search</button></td>
<td rowspan="2" valign="middle">
<!-- <button name="switchStartEnd" disabled="true" id="switchStartEnd" type="button"
value="Change Start and Endpoint"onClick="changeStartEnd();"><img src="img/changePos.gif" width="9" height="22" alt="Tausche Start- und Endpunkt"><br> --></button></td>
</tr>
<tr id="EndPoint">
<td nowrap>
<div class="textLabel"><img src="img/arrow-finish.png" class="radioIcons" width="12" height="16" alt=""><span class="text"></span></div>
</td>
<td id="tdEnd">
<input name="tfEndSearch" style="width:220px" type="text" id="tfEndSearch" class="tfPoints" value="München, Altstadt" title="Search your end point!" onKeyPress="checkReturn('end',event);">
<button name="enterEnd" onclick="setStatus('end'); geocodeAddress('end');">Search</button>
</td>
</tr>
</table>
</div>
<div id="calc_route" class="calc_route"><span class="options"><a href="#" onclick="closeOpenDiv('options');">Options</a></span>
<select name="selectRoutePref" id="selectRoutePref" title="Select the route preference ..."><option value="Fastest" selected>Car (travel time)</option></select>
<input name="Submit5" type="submit" class="calculate_button" id="Calculate" title="Route!" onClick="markersLayer.clearMarkers(); routing(false);" value="Route!"></div>
<div id="options" class="options_div" style="display:none"><input class="checkbox" type="checkbox" name="cbNoNames" id="cbNoNames" value="checkbox">Highlight No Name Streets in my Route</div>
<div id="information" class="information"> <p class="infoHL">Demo Website for the <br><a target="_blank" href="http://project-osrm.org/">Open Source Routing Machine Project</a></p> </div>
<div id="thx" class="thx">GUI v0.3 110722 - OSRM hosting by <a target="_blank" href="http://www.geofabrik.de/">Geofabrik</a> - Geocoder by <a target="_blank" href="http://developer.mapquest.com/web/products/open/nominatim/">MapQuest</a></div>
</div>
</div>
<div id="map" class="map"></div>
<div class="copyright">&copy; 2011 <a target="_blank" href="http://project-osrm.org/">Project OSRM</a> - Map data <a target="_blank" href="http://creativecommons.org/licenses/by-sa/2.0/">CC-By-SA</a> <a target="_blank" href="http://www.openstreetmap.org">by OpenStreetMap</a></div>
</body>
</html>
File diff suppressed because one or more lines are too long
-141
View File
@@ -1,141 +0,0 @@
/**
* Namespace: Util.OSM
*/
OpenLayers.Util.OSM = {};
/**
* Constant: MISSING_TILE_URL
* {String} URL of image to display for missing tiles
*/
OpenLayers.Util.OSM.MISSING_TILE_URL = "http://www.openstreetmap.org/openlayers/img/404.png";
/**
* Property: originalOnImageLoadError
* {Function} Original onImageLoadError function.
*/
OpenLayers.Util.OSM.originalOnImageLoadError = OpenLayers.Util.onImageLoadError;
/**
* Function: onImageLoadError
*/
OpenLayers.Util.onImageLoadError = function() {
if (this.src.match(/^http:\/\/[abc]\.[a-z]+\.openstreetmap\.org\//)) {
this.src = OpenLayers.Util.OSM.MISSING_TILE_URL;
} else if (this.src.match(/^http:\/\/[def]\.tah\.openstreetmap\.org\//)) {
// do nothing - this layer is transparent
} else {
OpenLayers.Util.OSM.originalOnImageLoadError;
}
};
/**
* Class: OpenLayers.Layer.OSM.Mapnik
*
* Inherits from:
* - <OpenLayers.Layer.OSM>
*/
OpenLayers.Layer.OSM.Mapnik = OpenLayers.Class(OpenLayers.Layer.OSM, {
/**
* Constructor: OpenLayers.Layer.OSM.Mapnik
*
* Parameters:
* name - {String}
* options - {Object} Hashtable of extra options to tag onto the layer
*/
initialize: function(name, options) {
var url = [
"http://a.tile.openstreetmap.org/${z}/${x}/${y}.png",
"http://b.tile.openstreetmap.org/${z}/${x}/${y}.png",
"http://c.tile.openstreetmap.org/${z}/${x}/${y}.png"
];
options = OpenLayers.Util.extend({ numZoomLevels: 19, buffer: 0 }, options);
var newArguments = [name, url, options];
OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
},
CLASS_NAME: "OpenLayers.Layer.OSM.Mapnik"
});
/**
* Class: OpenLayers.Layer.OSM.Osmarender
*
* Inherits from:
* - <OpenLayers.Layer.OSM>
*/
OpenLayers.Layer.OSM.Osmarender = OpenLayers.Class(OpenLayers.Layer.OSM, {
/**
* Constructor: OpenLayers.Layer.OSM.Osmarender
*
* Parameters:
* name - {String}
* options - {Object} Hashtable of extra options to tag onto the layer
*/
initialize: function(name, options) {
var url = [
"http://a.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png",
"http://b.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png",
"http://c.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"
];
options = OpenLayers.Util.extend({ numZoomLevels: 18, buffer: 0 }, options);
var newArguments = [name, url, options];
OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
},
CLASS_NAME: "OpenLayers.Layer.OSM.Osmarender"
});
/**
* Class: OpenLayers.Layer.OSM.CycleMap
*
* Inherits from:
* - <OpenLayers.Layer.OSM>
*/
OpenLayers.Layer.OSM.CycleMap = OpenLayers.Class(OpenLayers.Layer.OSM, {
/**
* Constructor: OpenLayers.Layer.OSM.CycleMap
*
* Parameters:
* name - {String}
* options - {Object} Hashtable of extra options to tag onto the layer
*/
initialize: function(name, options) {
var url = [
"http://a.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png",
"http://b.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png",
"http://c.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png"
];
options = OpenLayers.Util.extend({ numZoomLevels: 19, buffer: 0 }, options);
var newArguments = [name, url, options];
OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
},
CLASS_NAME: "OpenLayers.Layer.OSM.CycleMap"
});
/**
* Class: OpenLayers.Layer.OSM.MapQuest
*
* Inherits from:
* - <OpenLayers.Layer.OSM>
*/
OpenLayers.Layer.OSM.MapQuest = OpenLayers.Class(OpenLayers.Layer.OSM, {
/**
* Constructor: OpenLayers.Layer.OSM.MapQuest
*
* Parameters:
* name - {String}
* options - {Object} Hashtable of extra options to tag onto the layer
*/
initialize: function(name, options) {
var url = [
"http://otile1.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
"http://otile2.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
"http://otile3.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png"
];
options = OpenLayers.Util.extend({ numZoomLevels: 19, buffer: 0 }, options);
var newArguments = [name, url, options];
OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
},
CLASS_NAME: "OpenLayers.Layer.OSM.MapQuest"
});
-1
View File
@@ -1 +0,0 @@
This is the OpenLayers Version 2.10
Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 992 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 831 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 967 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 463 B

@@ -1,10 +0,0 @@
.olLayerGoogleCopyright {
right: 3px;
bottom: 2px;
left: auto;
}
.olLayerGooglePoweredBy {
left: 2px;
bottom: 2px;
}
@@ -1,7 +0,0 @@
.olControlZoomPanel div {
background-image: url(img/zoom-panel-NOALPHA.png);
}
.olControlPanPanel div {
background-image: url(img/pan-panel-NOALPHA.png);
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Some files were not shown because too many files have changed in this diff Show More