Compare commits

..

6 Commits

Author SHA1 Message Date
Dennis Luxen 6574436c33 Merge branch 'develop' 2012-12-24 10:35:51 +01:00
Dennis Luxen 824724630f Reomving the Travis CI experiment 2012-12-08 23:19:59 +01:00
Dennis Luxen 85c5da8512 removing --with-tools flag for travic CI 2012-12-08 21:10:24 +01:00
Dennis Luxen d79ebabe03 cuke dependencies for travic CI 2012-12-08 20:42:24 +01:00
Dennis Luxen f9cab44bc1 Adding irc config for Travis CI build server 2012-12-08 16:28:30 +01:00
Dennis Luxen 636f69b29f Adding config for Travis CI build server 2012-12-08 16:25:45 +01:00
191 changed files with 6036 additions and 9360 deletions
+17 -17
View File
@@ -33,10 +33,11 @@ ehthumbs.db
Icon?
Thumbs.db
# build related files #
# SCons related files #
#######################
/build/
/Util/UUID.cpp
SconsBuilder*
.scon*
.build
# Eclipse related files #
#########################
@@ -53,31 +54,30 @@ stxxl.errlog
# compiled protobuffers #
#########################
/DataStructures/pbf-proto/*.pb.h
/DataStructures/pbf-proto/*.pb.cc
DataStructures/pbf-proto/*.pb.h
DataStructures/pbf-proto/*.pb.cc
# External Libs #
#################
/lib/
/win/lib
lib/
win/lib
# Visual Studio Temp + build Files #
####################################
/win/*.user
/win/*.ncb
/win/*.suo
/win/Debug/
/win/Release/
/win/bin/
/win/bin-debug/
win/*.user
win/*.ncb
win/*.suo
win/Debug/
win/Release/
win/bin/
win/bin-debug/
/osrm-extract
/osrm-routed
/osrm-prepare
/osrm-cli
/nohup.out
# Sandbox folder #
###################
/sandbox/
sandbox/
/test/profile.lua
test/profile.lua
+3
View File
@@ -0,0 +1,3 @@
[submodule "Docs"]
path = Docs
url = https://github.com/DennisSchiefer/Project-OSRM-Web.git
-39
View File
@@ -1,39 +0,0 @@
language: cpp
compiler:
- gcc
# - clang
# Make sure CMake is installed
install:
- sudo apt-get update >/dev/null
- sudo apt-get -q install build-essential git cmake pkg-config libprotoc-dev libprotobuf7 protobuf-compiler libprotobuf-dev libosmpbf-dev libpng12-dev libbz2-dev libstxxl-dev libstxxl-doc libstxxl1 libxml2-dev libzip-dev libboost-thread-dev libboost-system-dev libboost-regex-dev libboost-filesystem-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems osmosis
before_script:
- sudo gem install bundler
- bundle install
- mkdir build
- cd build
- cmake .. $CMAKEOPTIONS
script: make
after_script:
- cd ..
- cucumber -p verify
branches:
only:
- master
- develop
env:
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release"
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug"
notifications:
irc:
channels:
- irc.oftc.net#osrm
on_success: change
on_failure: always
use_notice: true
skip_join: false
recipients:
- dennis@mapbox.com
email:
on_success: change
on_failure: always
+1 -2
View File
@@ -23,10 +23,9 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <cmath>
#include <vector>
typedef std::pair<unsigned, unsigned> BresenhamPixel;
inline void Bresenham (int x0, int y0, const int x1, int const y1, std::vector<BresenhamPixel> &resultList) {
inline void Bresenham (int x0, int y0, int x1, int y1, std::vector<BresenhamPixel> &resultList) {
int dx = std::abs(x1-x0);
int dy = std::abs(y1-y0);
int sx = (x0 < x1 ? 1 : -1);
+2 -2
View File
@@ -62,10 +62,10 @@ CRC32::CRC32CFunctionPtr CRC32::detectBestCRC32C() {
unsigned ecx = cpuid(1);
bool hasSSE42 = ecx & (1 << SSE42_BIT);
if (hasSSE42) {
SimpleLogger().Write() << "using hardware base sse computation";
std::cout << "using hardware base sse computation" << std::endl;
return &CRC32::SSEBasedCRC32; //crc32 hardware accelarated;
} else {
SimpleLogger().Write() << "using software base sse computation";
std::cout << "using software base sse computation" << std::endl;
return &CRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
}
}
+1 -2
View File
@@ -21,14 +21,13 @@
#ifndef CRC32_H_
#define CRC32_H_
#include "../Util/SimpleLogger.h"
#include <boost/crc.hpp> // for boost::crc_32_type
#include <iostream>
class CRC32 {
private:
unsigned crc;
unsigned slowcrc_table[1<<8];
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
typedef unsigned (CRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
+2 -3
View File
@@ -21,13 +21,12 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef DOUGLASPEUCKER_H_
#define DOUGLASPEUCKER_H_
#include "../DataStructures/Coordinate.h"
#include <cassert>
#include <cmath>
#include <cfloat>
#include <stack>
#include <vector>
#include "../DataStructures/Coordinate.h"
/*This class object computes the bitvector of indicating generalized input points
* according to the (Ramer-)Douglas-Peucker algorithm.
+4 -5
View File
@@ -22,8 +22,6 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef ITERATORBASEDCRC32_H_
#define ITERATORBASEDCRC32_H_
#include "../Util/SimpleLogger.h"
#include <boost/crc.hpp> // for boost::crc_32_type
#include <iostream>
@@ -32,6 +30,7 @@ class IteratorbasedCRC32 {
private:
typedef typename ContainerT::iterator ContainerT_iterator;
unsigned crc;
unsigned slowcrc_table[1<<8];
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
typedef unsigned (IteratorbasedCRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
@@ -82,10 +81,10 @@ private:
unsigned ecx = cpuid(1);
bool hasSSE42 = ecx & (1 << SSE42_BIT);
if (hasSSE42) {
SimpleLogger().Write() << "using hardware based CRC32 computation";
std::cout << "using hardware base sse computation" << std::endl;
return &IteratorbasedCRC32::SSEBasedCRC32; //crc32 hardware accelarated;
} else {
SimpleLogger().Write() << "using software based CRC32 computation";
std::cout << "using software base sse computation" << std::endl;
return &IteratorbasedCRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
}
}
@@ -95,7 +94,7 @@ public:
crcFunction = detectBestCRC32C();
}
virtual ~IteratorbasedCRC32() { }
virtual ~IteratorbasedCRC32() {};
unsigned operator()( ContainerT_iterator iter, const ContainerT_iterator end) {
unsigned crc = 0;
+18 -44
View File
@@ -21,9 +21,6 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef OBJECTTOBASE64_H_
#define OBJECTTOBASE64_H_
#include "../Util/StringUtil.h"
#include <boost/assert.hpp>
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp>
@@ -31,63 +28,40 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <algorithm>
#include <string>
#include <vector>
#include "../Util/StringUtil.h"
typedef
boost::archive::iterators::base64_from_binary<
boost::archive::iterators::transform_width<const char *, 6, 8>
> base64_t;
boost::archive::iterators::transform_width<string::const_iterator, 6, 8>
> base64_t;
typedef
boost::archive::iterators::transform_width<
boost::archive::iterators::binary_from_base64<
std::string::const_iterator>, 8, 6
boost::archive::iterators::binary_from_base64<string::const_iterator>, 8, 6
> binary_t;
template<class ObjectT>
static void EncodeObjectToBase64(const ObjectT & object, std::string& encoded) {
const char * char_ptr_to_object = (const char *)&object;
std::vector<unsigned char> data(sizeof(object));
std::copy(
char_ptr_to_object,
char_ptr_to_object + sizeof(ObjectT),
data.begin()
);
unsigned char number_of_padded_chars = 0; // is in {0,1,2};
while(data.size() % 3 != 0) {
++number_of_padded_chars;
data.push_back(0x00);
}
BOOST_ASSERT_MSG(
0 == data.size() % 3,
"base64 input data size is not a multiple of 3!"
);
encoded.resize(sizeof(ObjectT));
encoded.assign(
base64_t( &data[0] ),
base64_t( &data[0] + (data.size() - number_of_padded_chars) )
);
template<class ToEncodeT>
static void EncodeObjectToBase64(const ToEncodeT & object, std::string& encoded) {
encoded.clear();
char * pointerToOriginalObject = (char *)&object;
encoded = std::string(base64_t(pointerToOriginalObject), base64_t(pointerToOriginalObject+sizeof(ToEncodeT)));
//replace "+" with "-" and "/" with "_"
replaceAll(encoded, "+", "-");
replaceAll(encoded, "/", "_");
}
template<class ObjectT>
static void DecodeObjectFromBase64(const std::string& input, ObjectT & object) {
template<class ToEncodeT>
static void DecodeObjectFromBase64(ToEncodeT & object, const std::string& _encoded) {
try {
std::string encoded(input);
string encoded(_encoded);
//replace "-" with "+" and "_" with "/"
replaceAll(encoded, "-", "+");
replaceAll(encoded, "_", "/");
std::copy (
binary_t( encoded.begin() ),
binary_t( encoded.begin() + encoded.length() - 1),
(char *)&object
);
} catch(...) { }
char * pointerToDecodedObject = (char *)&object;
std::string dec(binary_t(encoded.begin()), binary_t(encoded.begin() + encoded.length() - 1));
std::copy ( dec.begin(), dec.end(), pointerToDecodedObject );
} catch(...) {}
}
#endif /* OBJECTTOBASE64_H_ */
+7 -9
View File
@@ -21,11 +21,12 @@ 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"
#include <string>
class PolylineCompressor {
private:
inline void encodeVectorSignedNumber(std::vector<int> & numbers, std::string & output) const {
@@ -56,14 +57,11 @@ private:
}
public:
inline void printEncodedString(
const std::vector<SegmentInformation> & polyline,
std::string & output
) const {
inline void printEncodedString(const std::vector<SegmentInformation>& polyline, std::string &output) const {
std::vector<int> deltaNumbers;
output += "\"";
if(!polyline.empty()) {
FixedPointCoordinate lastCoordinate = polyline[0].location;
_Coordinate lastCoordinate = polyline[0].location;
deltaNumbers.push_back( lastCoordinate.lat );
deltaNumbers.push_back( lastCoordinate.lon );
for(unsigned i = 1; i < polyline.size(); ++i) {
@@ -79,7 +77,7 @@ public:
}
inline void printEncodedString(const std::vector<FixedPointCoordinate>& polyline, std::string &output) const {
inline void printEncodedString(const std::vector<_Coordinate>& polyline, std::string &output) const {
std::vector<int> deltaNumbers(2*polyline.size());
output += "\"";
if(!polyline.empty()) {
@@ -94,7 +92,7 @@ public:
output += "\"";
}
inline void printUnencodedString(std::vector<FixedPointCoordinate> & polyline, std::string & output) const {
inline void printUnencodedString(std::vector<_Coordinate> & polyline, std::string & output) const {
output += "[";
std::string tmp;
for(unsigned i = 0; i < polyline.size(); i++) {
+86 -123
View File
@@ -16,88 +16,76 @@ 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.
Strongly connected components using Tarjan's Algorithm
*/
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_
#define STRONGLYCONNECTEDCOMPONENTS_H_
#include "../DataStructures/Coordinate.h"
#include <cassert>
#include <stack>
#include <vector>
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>
#include <boost/unordered_map.hpp>
#include <gdal/gdal.h>
#include <gdal/ogrsf_frmts.h>
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/ImportEdge.h"
#include "../DataStructures/QueryNode.h"
#include "../DataStructures/NodeCoords.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/Restriction.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/SimpleLogger.h"
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/integer.hpp>
#include <boost/make_shared.hpp>
#include <boost/unordered_map.hpp>
#ifdef __APPLE__
#include <gdal.h>
#include <ogrsf_frmts.h>
#else
#include <gdal/gdal.h>
#include <gdal/ogrsf_frmts.h>
#endif
#include <cassert>
#include <stack>
#include <vector>
// Strongly connected components using Tarjan's Algorithm
class TarjanSCC {
private:
struct TarjanNode {
TarjanNode() : index(UINT_MAX), lowlink(UINT_MAX), onStack(false) {}
unsigned index;
unsigned lowlink;
bool onStack;
};
struct TarjanEdgeData {
struct _NodeBasedEdgeData {
int distance;
unsigned edgeBasedNodeID;
unsigned nameID:31;
bool shortcut:1;
short type;
bool isAccessRestricted:1;
bool forward:1;
bool backward:1;
bool roundabout:1;
bool ignoreInGrid:1;
bool reversedEdge:1;
short type;
bool isAccessRestricted;
};
struct TarjanStackFrame {
explicit TarjanStackFrame(NodeID _v, NodeID p) : v(_v), parent(p) {}
NodeID v;
NodeID parent;
struct _EdgeBasedEdgeData {
int distance;
unsigned via;
unsigned nameID;
bool forward;
bool backward;
TurnInstruction turnInstruction;
};
typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph;
typedef TarjanDynamicGraph::InputEdge TarjanEdge;
typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph;
typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge;
std::vector<NodeInfo> inputNodeInfoList;
unsigned numberOfTurnRestrictions;
boost::shared_ptr<_NodeBasedDynamicGraph> _nodeBasedGraph;
boost::unordered_map<NodeID, bool> _barrierNodes;
boost::unordered_map<NodeID, bool> _trafficLights;
typedef std::pair<NodeID, NodeID> RestrictionSource;
typedef std::pair<NodeID, bool> RestrictionTarget;
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
std::vector<NodeInfo> inputNodeInfoList;
unsigned numberOfTurnRestrictions;
boost::shared_ptr<TarjanDynamicGraph> _nodeBasedGraph;
boost::unordered_map<NodeID, bool> _barrierNodes;
boost::unordered_map<NodeID, bool> _trafficLights;
std::vector<EmanatingRestrictionsVector> _restrictionBucketVector;
RestrictionMap _restrictionMap;
public:
struct EdgeBasedNode {
bool operator<(const EdgeBasedNode & other) const {
return other.id < id;
@@ -116,23 +104,25 @@ private:
bool ignoreInGrid:1;
};
private:
DeallocatingVector<EdgeBasedNode> edgeBasedNodes;
struct TarjanNode {
TarjanNode() : index(UINT_MAX), lowlink(UINT_MAX), onStack(false) {}
unsigned index;
unsigned lowlink;
bool onStack;
};
struct TarjanStackFrame {
explicit TarjanStackFrame(NodeID _v, NodeID p) : v(_v), parent(p) {}
NodeID v;
NodeID parent;
};
public:
TarjanSCC(
int nodes,
std::vector<NodeBasedEdge> & inputEdges,
std::vector<NodeID> & bn,
std::vector<NodeID> & tl,
std::vector<TurnRestriction> & irs,
std::vector<NodeInfo> & nI
) :
inputNodeInfoList(nI),
numberOfTurnRestrictions(irs.size())
{
BOOST_FOREACH(const TurnRestriction & restriction, irs) {
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(
restriction.fromNode, restriction.viaNode
);
TarjanSCC(int nodes, std::vector<NodeBasedEdge> & inputEdges, std::vector<NodeID> & bn, std::vector<NodeID> & tl, std::vector<_Restriction> & irs, std::vector<NodeInfo> & nI) : inputNodeInfoList(nI), numberOfTurnRestrictions(irs.size()) {
BOOST_FOREACH(_Restriction & restriction, irs) {
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(restriction.fromNode, restriction.viaNode);
unsigned index;
RestrictionMap::iterator restrIter = _restrictionMap.find(restrictionSource);
if(restrIter == _restrictionMap.end()) {
@@ -150,9 +140,7 @@ public:
}
}
_restrictionBucketVector.at(index).push_back(
std::make_pair(restriction.toNode, restriction.flags.isOnly)
);
_restrictionBucketVector.at(index).push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly));
}
BOOST_FOREACH(NodeID id, bn) {
@@ -162,10 +150,10 @@ public:
_trafficLights[id] = true;
}
DeallocatingVector< TarjanEdge > edges;
DeallocatingVector< _NodeBasedEdge > edges;
for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
TarjanEdge edge;
_NodeBasedEdge edge;
if(!i->isForward()) {
edge.source = i->target();
edge.target = i->source();
@@ -189,28 +177,21 @@ public:
edge.data.type = i->type();
edge.data.isAccessRestricted = i->isAccessRestricted();
edge.data.edgeBasedNodeID = edges.size();
edge.data.reversedEdge = false;
edges.push_back( edge );
if( edge.data.backward ) {
std::swap( edge.source, edge.target );
edge.data.forward = i->isBackward();
edge.data.backward = i->isForward();
edge.data.edgeBasedNodeID = edges.size();
edge.data.reversedEdge = true;
edges.push_back( edge );
}
}
std::vector<NodeBasedEdge>().swap(inputEdges);
std::sort( edges.begin(), edges.end() );
_nodeBasedGraph = boost::make_shared<TarjanDynamicGraph>( nodes, edges );
_nodeBasedGraph = boost::make_shared<_NodeBasedDynamicGraph>( nodes, edges );
}
void Run() {
//remove files from previous run if exist
DeleteFileIfExists("component.dbf");
DeleteFileIfExists("component.shx");
DeleteFileIfExists("component.shp");
Percent p(_nodeBasedGraph->GetNumberOfNodes());
const char *pszDriverName = "ESRI Shapefile";
@@ -259,7 +240,7 @@ public:
bool beforeRecursion = recursionStack.top().first;
TarjanStackFrame currentFrame = recursionStack.top().second;
NodeID v = currentFrame.v;
// SimpleLogger().Write() << "popping node " << v << (beforeRecursion ? " before " : " after ") << "recursion";
// INFO("popping node " << v << (beforeRecursion ? " before " : " after ") << "recursion");
recursionStack.pop();
if(beforeRecursion) {
@@ -272,45 +253,45 @@ public:
tarjanStack.push(v);
tarjanNodes[v].onStack = true;
++index;
// SimpleLogger().Write() << "pushing " << v << " onto tarjan stack, idx[" << v << "]=" << tarjanNodes[v].index << ", lowlink["<< v << "]=" << tarjanNodes[v].lowlink;
// INFO("pushing " << v << " onto tarjan stack, idx[" << v << "]=" << tarjanNodes[v].index << ", lowlink["<< v << "]=" << tarjanNodes[v].lowlink);
//Traverse outgoing edges
for(TarjanDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
TarjanDynamicGraph::NodeIterator vprime = _nodeBasedGraph->GetTarget(e2);
// SimpleLogger().Write() << "traversing edge (" << v << "," << vprime << ")";
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
_NodeBasedDynamicGraph::NodeIterator vprime = _nodeBasedGraph->GetTarget(e2);
// INFO("traversing edge (" << v << "," << vprime << ")");
if(UINT_MAX == tarjanNodes[vprime].index) {
recursionStack.push(std::make_pair(true,TarjanStackFrame(vprime, v)));
} else {
// SimpleLogger().Write() << "Node " << vprime << " is already explored";
// INFO("Node " << vprime << " is already explored");
if(tarjanNodes[vprime].onStack) {
unsigned newLowlink = std::min(tarjanNodes[v].lowlink, tarjanNodes[vprime].index);
// SimpleLogger().Write() << "Setting lowlink[" << v << "] from " << tarjanNodes[v].lowlink << " to " << newLowlink;
// INFO("Setting lowlink[" << v << "] from " << tarjanNodes[v].lowlink << " to " << newLowlink);
tarjanNodes[v].lowlink = newLowlink;
// } else {
// SimpleLogger().Write() << "But node " << vprime << " is not on stack";
// INFO("But node " << vprime << " is not on stack");
}
}
}
} else {
// SimpleLogger().Write() << "we are at the end of recursion and checking node " << v;
// INFO("we are at the end of recursion and checking node " << v);
{ // setting lowlink in its own scope so it does not pollute namespace
// NodeID parent = (UINT_MAX == tarjanNodes[v].parent ? v : tarjanNodes[v].parent );
// SimpleLogger().Write() << "parent=" << currentFrame.parent;
// SimpleLogger().Write() << "tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << currentFrame.parent << "].lowlink=" << tarjanNodes[currentFrame.parent].lowlink;
// INFO("parent=" << currentFrame.parent);
// INFO("tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << currentFrame.parent << "].lowlink=" << tarjanNodes[currentFrame.parent].lowlink);
//Note the index shift by 1 compared to the recursive version
tarjanNodes[currentFrame.parent].lowlink = std::min(tarjanNodes[currentFrame.parent].lowlink, tarjanNodes[v].lowlink);
// SimpleLogger().Write() << "Setting tarjanNodes[" << currentFrame.parent <<"].lowlink=" << tarjanNodes[currentFrame.parent].lowlink;
// INFO("Setting tarjanNodes[" << currentFrame.parent <<"].lowlink=" << tarjanNodes[currentFrame.parent].lowlink);
}
// SimpleLogger().Write() << "tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << v << "].index=" << tarjanNodes[v].index;
// INFO("tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << v << "].index=" << tarjanNodes[v].index);
//after recursion, lets do cycle checking
//Check if we found a cycle. This is the bottom part of the recursion
if(tarjanNodes[v].lowlink == tarjanNodes[v].index) {
NodeID vprime;
do {
// SimpleLogger().Write() << "identified component " << currentComponent << ": " << tarjanStack.top();
// INFO("identified component " << currentComponent << ": " << tarjanStack.top());
vprime = tarjanStack.top(); tarjanStack.pop();
tarjanNodes[vprime].onStack = false;
componentsIndex[vprime] = currentComponent;
@@ -318,7 +299,7 @@ public:
} while( v != vprime);
vectorOfComponentSizes.push_back(sizeOfCurrentComponent);
if(sizeOfCurrentComponent > 1000)
SimpleLogger().Write() << "large component [" << currentComponent << "]=" << sizeOfCurrentComponent;
INFO("large component [" << currentComponent << "]=" << sizeOfCurrentComponent);
++currentComponent;
sizeOfCurrentComponent = 0;
}
@@ -326,50 +307,38 @@ public:
}
}
SimpleLogger().Write() << "identified: " << vectorOfComponentSizes.size() << " many components, marking small components";
INFO("identified: " << vectorOfComponentSizes.size() << " many components, marking small components");
int singleCounter = 0;
for(unsigned i = 0; i < vectorOfComponentSizes.size(); ++i){
if(1 == vectorOfComponentSizes[i])
++singleCounter;
}
SimpleLogger().Write() << "identified " << singleCounter << " SCCs of size 1";
uint64_t total_network_distance = 0;
p.reinit(_nodeBasedGraph->GetNumberOfNodes());
for(TarjanDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
p.printIncrement();
for(TarjanDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
if(_nodeBasedGraph->GetEdgeData(e1).reversedEdge) {
continue;
}
TarjanDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
INFO("identified " << singleCounter << " SCCs of size 1");
total_network_distance += 100*ApproximateDistance(
inputNodeInfoList[u].lat,
inputNodeInfoList[u].lon,
inputNodeInfoList[v].lat,
inputNodeInfoList[v].lon
);
p.reinit(_nodeBasedGraph->GetNumberOfNodes());
for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
_NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) {
assert(e1 != UINT_MAX);
assert(u != UINT_MAX);
assert(v != UINT_MAX);
//edges that end on bollard nodes may actually be in two distinct components
if(std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 10) {
//INFO("(" << inputNodeInfoList[u].lat/COORDINATE_PRECISION << ";" << inputNodeInfoList[u].lon/COORDINATE_PRECISION << ") -> (" << inputNodeInfoList[v].lat/COORDINATE_PRECISION << ";" << inputNodeInfoList[v].lon/COORDINATE_PRECISION << ")");
//INFO("(" << inputNodeInfoList[u].lat/100000. << ";" << inputNodeInfoList[u].lon/100000. << ") -> (" << inputNodeInfoList[v].lat/100000. << ";" << inputNodeInfoList[v].lon/100000. << ")");
OGRLineString lineString;
lineString.addPoint(inputNodeInfoList[u].lon/COORDINATE_PRECISION, inputNodeInfoList[u].lat/COORDINATE_PRECISION);
lineString.addPoint(inputNodeInfoList[v].lon/COORDINATE_PRECISION, inputNodeInfoList[v].lat/COORDINATE_PRECISION);
lineString.addPoint(inputNodeInfoList[u].lon/100000., inputNodeInfoList[u].lat/100000.);
lineString.addPoint(inputNodeInfoList[v].lon/100000., inputNodeInfoList[v].lat/100000.);
OGRFeature *poFeature;
poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() );
poFeature->SetGeometry( &lineString );
if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE ) {
throw OSRMException(
"Failed to create feature in shapefile."
);
if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE )
{
ERR( "Failed to create feature in shapefile.\n" );
}
OGRFeature::DestroyFeature( poFeature );
}
@@ -379,7 +348,7 @@ public:
OGRDataSource::DestroyDataSource( poDS );
std::vector<NodeID>().swap(vectorOfComponentSizes);
std::vector<NodeID>().swap(componentsIndex);
SimpleLogger().Write() << "total network distance: " << (uint64_t)total_network_distance/100/1000. << " km";
}
private:
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
@@ -408,12 +377,6 @@ private:
}
return false;
}
void DeleteFileIfExists(const std::string file_name) const {
if (boost::filesystem::exists(file_name) ) {
boost::filesystem::remove(file_name);
}
}
};
#endif /* STRONGLYCONNECTEDCOMPONENTS_H_ */
-160
View File
@@ -1,160 +0,0 @@
cmake_minimum_required(VERSION 2.6)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(OSRM)
include(FindPackageHandleStandardArgs)
TRY_RUN(SHARED_LIBRARY_PATH_TYPE SHARED_LIBRARY_PATH_INFO_COMPILED ${PROJECT_BINARY_DIR}/CMakeTmp ${PROJECT_SOURCE_DIR}/cmake/size.cpp OUTPUT_VARIABLE IS_64_SYSTEM)
if(IS_64_SYSTEM)
message(STATUS "System supports 64 bits.")
set( HAS64BITS 1 )
else(IS_64_SYSTEM)
MESSAGE(WARNING "Compiling on a 32 bit system is unsupported!")
set( HAS64BITS 0 )
endif(IS_64_SYSTEM)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/UUID.cpp UUID.cpp.alwaysbuild
COMMAND ${CMAKE_COMMAND} -P
${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake
DEPENDS
${CMAKE_SOURCE_DIR}/Util/UUID.cpp.in
${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake
COMMENT "Configuring UUID.cpp"
VERBATIM)
add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp )
set(BOOST_COMPONENTS filesystem regex system thread)
file(GLOB ExtractorGlob Extractor/*.cpp)
set(ExtractorSources extractor.cpp ${ExtractorGlob})
add_executable(osrm-extract ${ExtractorSources} )
file(GLOB PrepareGlob Contractor/*.cpp)
set(PrepareSources createHierarchy.cpp ${PrepareGlob})
add_executable(osrm-prepare ${PrepareSources} )
add_executable(osrm-routed routed.cpp )
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
file(GLOB DescriptorGlob Descriptors/*.cpp)
file(GLOB LibOSRMGlob Library/*.cpp)
file(GLOB SearchEngineSource DataStructures/SearchEngine*.cpp)
file(GLOB ServerStructureGlob Server/DataStructures/*.cpp)
set(OSRMSources ${LibOSRMGlob} ${DescriptorGlob} ${SearchEngineSource} ${ServerStructureGlob})
add_library(OSRM SHARED ${OSRMSources})
add_library(UUID STATIC Util/UUID.cpp)
add_dependencies( UUID UUIDConfigure )
# Check the release mode
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_BUILD_TYPE Release)
endif(NOT CMAKE_BUILD_TYPE MATCHES Debug)
if(CMAKE_BUILD_TYPE MATCHES Debug)
message(STATUS "Configuring OSRM in debug mode")
endif(CMAKE_BUILD_TYPE MATCHES Debug)
if(CMAKE_BUILD_TYPE MATCHES Release)
message(STATUS "Configuring OSRM in release mode")
endif(CMAKE_BUILD_TYPE MATCHES Release)
#Configuring compilers
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# using Clang
set(CMAKE_CXX_FLAGS "-Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration")
message(STATUS "OpenMP parallelization not available using clang++")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# using GCC
set(CMAKE_CXX_FLAGS "-Wall -fopenmp -pedantic")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
# using Intel C++
set(CMAKE_CXX_FLAGS "-static-intel -wd10237 -Wall -openmp -ipo")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++
endif()
if(APPLE)
SET(CMAKE_OSX_ARCHITECTURES "x86_64")
message("Set Architecture to x64 on OS X")
endif()
#Check Boost
set(BOOST_MIN_VERSION "1.44.0")
find_package( Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED )
if (NOT Boost_FOUND)
message(FATAL_ERROR "Fatal error: Boost (version >= 1.44.0) required.\n")
endif (NOT Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
IF( APPLE )
target_link_libraries( OSRM ${Boost_LIBRARIES} UUID )
ELSE( APPLE )
target_link_libraries( OSRM ${Boost_LIBRARIES} )
ENDIF( APPLE )
target_link_libraries( osrm-extract ${Boost_LIBRARIES} UUID )
target_link_libraries( osrm-prepare ${Boost_LIBRARIES} UUID )
target_link_libraries( osrm-routed ${Boost_LIBRARIES} OSRM UUID )
find_package ( BZip2 REQUIRED )
include_directories(${BZIP_INCLUDE_DIRS})
target_link_libraries (osrm-extract ${BZIP2_LIBRARIES})
find_package( ZLIB REQUIRED )
include_directories(${ZLIB_INCLUDE_DIRS})
target_link_libraries (osrm-extract ${ZLIB_LIBRARY})
target_link_libraries (osrm-routed ${ZLIB_LIBRARY})
find_package( Threads REQUIRED )
target_link_libraries (osrm-extract ${Threads_LIBRARY})
find_package( LuaJIT )
IF( NOT APPLE AND LUAJIT_INCLUDE_DIR AND LUAJIT_LIBRARIES)
include_directories(${LUAJIT_INCLUDE_DIR})
target_link_libraries( osrm-extract ${LUAJIT_LIBRARIES} )
target_link_libraries( osrm-prepare ${LUAJIT_LIBRARIES} )
ELSE( LUAJIT_INCLUDE_DIR )
find_package( Lua51 REQUIRED AND LUAJIT_LIBRARIES )
include_directories(${LUA_INCLUDE_DIR})
target_link_libraries( osrm-extract ${LUA_LIBRARY} )
target_link_libraries( osrm-prepare ${LUA_LIBRARY} )
ENDIF( NOT APPLE AND LUAJIT_INCLUDE_DIR AND LUAJIT_LIBRARIES )
find_package( LibXml2 REQUIRED )
include_directories(${LIBXML2_INCLUDE_DIR})
target_link_libraries (osrm-extract ${LIBXML2_LIBRARIES})
find_package( Luabind REQUIRED )
include_directories(${LUABIND_INCLUDE_DIR})
target_link_libraries (osrm-extract ${LUABIND_LIBRARY})
target_link_libraries (osrm-prepare ${LUABIND_LIBRARY})
find_package( Protobuf REQUIRED )
include_directories(${PROTOBUF_INCLUDE_DIRS})
target_link_libraries (osrm-extract ${PROTOBUF_LIBRARY})
target_link_libraries (osrm-prepare ${PROTOBUF_LIBRARY})
find_package( STXXL REQUIRED )
include_directories(${STXXL_INCLUDE_DIR})
target_link_libraries (OSRM ${STXXL_LIBRARY})
target_link_libraries (osrm-extract ${STXXL_LIBRARY})
target_link_libraries (osrm-prepare ${STXXL_LIBRARY})
find_package( OSMPBF REQUIRED )
include_directories(${OSMPBF_INCLUDE_DIR})
target_link_libraries (osrm-extract ${OSMPBF_LIBRARY})
target_link_libraries (osrm-prepare ${OSMPBF_LIBRARY})
if(WITH_TOOLS)
message("-- Activating OSRM internal tools")
find_package( GDAL )
if(GDAL_FOUND)
add_executable(osrm-components Tools/componentAnalysis.cpp)
include_directories(${GDAL_INCLUDE_DIR})
target_link_libraries(
osrm-components ${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID
)
endif(GDAL_FOUND)
add_executable ( osrm-cli Tools/simpleclient.cpp )
target_link_libraries( osrm-cli ${Boost_LIBRARIES} OSRM UUID )
endif(WITH_TOOLS)
+261
View File
@@ -0,0 +1,261 @@
/*
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
#include <algorithm>
#ifndef _WIN32
#include <sys/time.h>
#endif
#include "Contractor.h"
class ContractionCleanup {
private:
struct _CleanupHeapData {
NodeID parent;
_CleanupHeapData( NodeID p ) {
parent = p;
}
};
typedef BinaryHeap< NodeID, NodeID, int, _CleanupHeapData > _Heap;
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 nameID;
int distance;
TurnInstruction turnInstruction;
bool shortcut:1;
bool forward:1;
bool backward:1;
} data;
bool operator<( const Edge& right ) const {
if ( source != right.source )
return source < right.source;
return target < right.target;
}
//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.nameID == right.data.nameID
);
}
};
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 );
}
}
sort( edges.begin(), edges.end() );
}
private:
double _Timestamp() {
struct timeval tp;
gettimeofday(&tp, NULL);
return double(tp.tv_sec) + tp.tv_usec / 1000000.;
}
void BuildOutgoingGraph() {
//sort edges by source
sort( _graph.begin(), _graph.end(), Edge::CompareBySource );
try {
_firstEdge.resize( _numNodes + 1 );
} catch(...) {
ERR("Not enough RAM on machine");
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 ) );
}
INFO("Scanning for useless shortcuts");
BuildOutgoingGraph();
/*
#pragma omp parallel for
for ( int i = 0; i < ( int ) _graph.size(); i++ ) {
//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;
}
}
}
*/
INFO("Removing edges");
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++;
}
INFO("Removed " << _graph.size() - useful << " useless shortcuts");
_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 ( distance > *targetDistance ) {
heapForward->DeleteAll();
return;
}
if ( heapBackward->WasInserted( node ) ) {
const int newDistance = heapBackward->GetKey( node ) + distance;
if ( newDistance < *targetDistance ) {
*middle = node;
*targetDistance = newDistance;
}
}
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 ) {
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
+55 -81
View File
@@ -20,6 +20,17 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef CONTRACTOR_H_INCLUDED
#define CONTRACTOR_H_INCLUDED
#include <algorithm>
#include <limits>
#include <vector>
#include <cfloat>
#include <ctime>
#include <boost/foreach.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include "TemporaryStorage.h"
#include "../DataStructures/BinaryHeap.h"
@@ -29,22 +40,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include "../DataStructures/XORFastHash.h"
#include "../DataStructures/XORFastHashStorage.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <cfloat>
#include <ctime>
#include <algorithm>
#include <limits>
#include <vector>
class Contractor {
private:
@@ -122,11 +119,10 @@ public:
newEdge.target = diter->target();
newEdge.data = _ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward());
BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" );
assert( newEdge.data.distance > 0 );
#ifndef NDEBUG
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
SimpleLogger().Write(logWARNING) <<
"Edge weight large -> " << newEdge.data.distance;
WARN("Edge weight large -> " << newEdge.data.distance);
}
#endif
edges.push_back( newEdge );
@@ -161,13 +157,11 @@ public:
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) {
if ( edges[i].data.forward )
forwardEdge.data.distance = std::min( edges[i].data.distance, forwardEdge.data.distance );
}
if ( edges[i].data.backward) {
if ( edges[i].data.backward )
backwardEdge.data.distance = std::min( edges[i].data.distance, backwardEdge.data.distance );
}
++i;
i++;
}
//merge edges (s,t) and (t,s) into bidirectional edge
if ( forwardEdge.data.distance == backwardEdge.data.distance ) {
@@ -200,9 +194,9 @@ public:
// }
// }
//
// SimpleLogger().Write() << "edges at node with id " << highestNode << " has degree " << maxdegree;
// INFO("edges at node with id " << highestNode << " has degree " << maxdegree);
// for(unsigned i = _graph->BeginEdges(highestNode); i < _graph->EndEdges(highestNode); ++i) {
// SimpleLogger().Write() << " ->(" << highestNode << "," << _graph->GetTarget(i) << "); via: " << _graph->GetEdgeData(i).via;
// INFO(" ->(" << highestNode << "," << _graph->GetTarget(i) << "); via: " << _graph->GetEdgeData(i).via);
// }
//Create temporary file
@@ -236,9 +230,8 @@ public:
//initialize the variables
#pragma omp parallel for schedule ( guided )
for ( int x = 0; x < ( int ) numberOfNodes; ++x ) {
for ( int x = 0; x < ( int ) numberOfNodes; ++x )
remainingNodes[x].id = x;
}
std::cout << "initializing elimination PQ ..." << std::flush;
#pragma omp parallel
@@ -249,10 +242,10 @@ public:
nodePriority[x] = _Evaluate( data, &nodeData[x], x );
}
}
std::cout << "ok" << std::endl << "preprocessing " << numberOfNodes << " nodes ..." << std::flush;
std::cout << "ok" << std::endl << "preprocessing ..." << std::flush;
bool flushedContractor = false;
while ( numberOfNodes > 2 && numberOfContractedNodes < numberOfNodes ) {
while ( numberOfContractedNodes < numberOfNodes ) {
if(!flushedContractor && (numberOfContractedNodes > (numberOfNodes*0.65) ) ){
DeallocatingVector<_ContractorEdge> newSetOfEdges; //this one is not explicitely cleared since it goes out of scope anywa
std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush;
@@ -281,12 +274,13 @@ public:
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
//Write dummy number of edges to temporary file
// std::ofstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary);
uint64_t initialFilePosition = tempStorage.tell(temporaryStorageSlotID);
long initialFilePosition = tempStorage.tell(temporaryStorageSlotID);
unsigned numberOfTemporaryEdges = 0;
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
//walk over all nodes
for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
//INFO("Restructuring node " << i << "|" << _graph->GetNumberOfNodes());
const NodeID start = i;
for(_DynamicGraph::EdgeIterator currentEdge = _graph->BeginEdges(start); currentEdge < _graph->EndEdges(start); ++currentEdge) {
_DynamicGraph::EdgeData & data = _graph->GetEdgeData(currentEdge);
@@ -305,14 +299,8 @@ public:
newEdge.target = newNodeIDFromOldNodeIDMap[target];
newEdge.data = data;
newEdge.data.originalViaNodeID = true;
BOOST_ASSERT_MSG(
UINT_MAX != newNodeIDFromOldNodeIDMap[start],
"new start id not resolveable"
);
BOOST_ASSERT_MSG(
UINT_MAX != newNodeIDFromOldNodeIDMap[target],
"new target id not resolveable"
);
assert(UINT_MAX != newNodeIDFromOldNodeIDMap[start] );
assert(UINT_MAX != newNodeIDFromOldNodeIDMap[target]);
newSetOfEdges.push_back(newEdge);
}
}
@@ -321,6 +309,8 @@ public:
tempStorage.seek(temporaryStorageSlotID, initialFilePosition);
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
// INFO("Flushed " << numberOfTemporaryEdges << " edges to disk");
//Delete map from old NodeIDs to new ones.
std::vector<NodeID>().swap(newNodeIDFromOldNodeIDMap);
@@ -432,63 +422,52 @@ public:
// avgdegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
// quaddegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
//
// SimpleLogger().Write() << "rest: " << remainingNodes.size() << ", max: " << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", quad: " << quaddegree;
// INFO("rest: " << remainingNodes.size() << ", max: " << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", quad: " << quaddegree);
p.printStatus(numberOfContractedNodes);
}
BOOST_FOREACH(_ThreadData * data, threadData) {
BOOST_FOREACH(_ThreadData * data, threadData)
delete data;
}
threadData.clear();
}
template< class Edge >
inline void GetEdges( DeallocatingVector< Edge >& edges ) {
Percent p (_graph->GetNumberOfNodes());
SimpleLogger().Write() << "Getting edges of minimized graph";
INFO("Getting edges of minimized graph");
NodeID numberOfNodes = _graph->GetNumberOfNodes();
if(_graph->GetNumberOfNodes()) {
if(oldNodeIDFromNewNodeIDMap.size()) {
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
p.printStatus(node);
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) {
const NodeID target = _graph->GetTarget( edge );
const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge );
Edge newEdge;
if(0 != oldNodeIDFromNewNodeIDMap.size()) {
newEdge.source = oldNodeIDFromNewNodeIDMap[node];
newEdge.target = oldNodeIDFromNewNodeIDMap[target];
} else {
newEdge.source = node;
newEdge.target = target;
}
BOOST_ASSERT_MSG(
UINT_MAX != newEdge.source,
"Source id invalid"
);
BOOST_ASSERT_MSG(
UINT_MAX != newEdge.target,
"Target id invalid"
);
newEdge.source = oldNodeIDFromNewNodeIDMap[node];
newEdge.target = oldNodeIDFromNewNodeIDMap[target];
assert(UINT_MAX != newEdge.source);
assert(UINT_MAX != newEdge.target);
newEdge.data.distance = data.distance;
newEdge.data.shortcut = data.shortcut;
if(!data.originalViaNodeID && oldNodeIDFromNewNodeIDMap.size()) {
if(!data.originalViaNodeID)
newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id];
} else {
else
newEdge.data.id = data.id;
}
BOOST_ASSERT_MSG(
newEdge.data.id != INT_MAX, //2^31
"edge id invalid"
);
assert(newEdge.data.id != UINT_MAX);
newEdge.data.forward = data.forward;
newEdge.data.backward = data.backward;
edges.push_back( newEdge );
}
}
}
INFO("Renumbered edges of minimized graph, freeing space");
_graph.reset();
std::vector<NodeID>().swap(oldNodeIDFromNewNodeIDMap);
INFO("Loading temporary edges");
// std::ifstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary);
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
//Also get the edges from temporary storage
unsigned numberOfTemporaryEdges = 0;
@@ -513,6 +492,7 @@ public:
edges.push_back( newEdge );
}
tempStorage.deallocateSlot(temporaryStorageSlotID);
INFO("Hierarchy has " << edges.size() << " edges");
}
private:
@@ -535,27 +515,24 @@ private:
if ( heap.GetData( node ).target ) {
++targetsFound;
if ( targetsFound >= numTargets ) {
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 _ContractorEdgeData& data = _graph->GetEdgeData( edge );
if ( !data.forward ){
if ( !data.forward )
continue;
}
const NodeID to = _graph->GetTarget( edge );
if(middleNode == to) {
if(middleNode == to)
continue;
}
const int toDistance = distance + data.distance;
//New Node discovered -> Add to Heap + Node Info Storage
if ( !heap.WasInserted( to ) ) {
if ( !heap.WasInserted( to ) )
heap.Insert( to, toDistance, _HeapData(currentHop, false) );
}
//Found a shorter Path -> Update distance
else if ( toDistance < heap.GetKey( to ) ) {
heap.DecreaseKey( to, toDistance );
@@ -605,9 +582,8 @@ private:
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
if ( !outData.forward ) {
if ( !outData.forward )
continue;
}
const NodeID target = _graph->GetTarget( outEdge );
const int pathDistance = inData.distance + outData.distance;
maxDistance = std::max( maxDistance, pathDistance );
@@ -617,16 +593,15 @@ private:
}
}
if( Simulate ) {
if( Simulate )
_Dijkstra( maxDistance, numTargets, 1000, data, node );
} else {
else
_Dijkstra( maxDistance, numTargets, 2000, data, node );
}
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
if ( !outData.forward ) {
if ( !outData.forward )
continue;
}
const NodeID target = _graph->GetTarget( outEdge );
const int pathDistance = inData.distance + outData.distance;
const int distance = heap.GetKey( target );
@@ -666,9 +641,8 @@ private:
found = true;
break;
}
if ( !found ) {
if ( !found )
insertedEdges[insertedEdgesSize++] = insertedEdges[i];
}
}
insertedEdges.resize( insertedEdgesSize );
}
+234 -404
View File
@@ -20,262 +20,194 @@
#include "EdgeBasedGraphFactory.h"
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
int number_of_nodes,
std::vector<ImportEdge> & input_edge_list,
std::vector<NodeID> & barrier_node_list,
std::vector<NodeID> & traffic_light_node_list,
std::vector<TurnRestriction> & input_restrictions_list,
std::vector<NodeInfo> & m_node_info_list,
SpeedProfileProperties speed_profile
) : speed_profile(speed_profile),
m_turn_restrictions_count(0),
m_node_info_list(m_node_info_list)
{
BOOST_FOREACH(const TurnRestriction & restriction, input_restrictions_list) {
std::pair<NodeID, NodeID> restriction_source =
std::make_pair(restriction.fromNode, restriction.viaNode);
template<>
EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector<NodeBasedEdge> & inputEdges, std::vector<NodeID> & bn, std::vector<NodeID> & tl, std::vector<_Restriction> & irs, std::vector<NodeInfo> & nI, SpeedProfileProperties sp) : inputNodeInfoList(nI), numberOfTurnRestrictions(irs.size()), speedProfile(sp) {
BOOST_FOREACH(_Restriction & restriction, irs) {
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(restriction.fromNode, restriction.viaNode);
unsigned index;
RestrictionMap::iterator restriction_iter = m_restriction_map.find(restriction_source);
if(restriction_iter == m_restriction_map.end()) {
index = m_restriction_bucket_list.size();
m_restriction_bucket_list.resize(index+1);
m_restriction_map[restriction_source] = index;
RestrictionMap::iterator restrIter = _restrictionMap.find(restrictionSource);
if(restrIter == _restrictionMap.end()) {
index = _restrictionBucketVector.size();
_restrictionBucketVector.resize(index+1);
_restrictionMap[restrictionSource] = index;
} else {
index = restriction_iter->second;
index = restrIter->second;
//Map already contains an is_only_*-restriction
if(m_restriction_bucket_list.at(index).begin()->second) {
if(_restrictionBucketVector.at(index).begin()->second)
continue;
} else if(restriction.flags.isOnly) {
else if(restriction.flags.isOnly){
//We are going to insert an is_only_*-restriction. There can be only one.
m_turn_restrictions_count -= m_restriction_bucket_list.at(index).size();
m_restriction_bucket_list.at(index).clear();
_restrictionBucketVector.at(index).clear();
}
}
++m_turn_restrictions_count;
m_restriction_bucket_list.at(index).push_back(
std::make_pair( restriction.toNode, restriction.flags.isOnly)
);
_restrictionBucketVector.at(index).push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly));
}
m_barrier_nodes.insert(
barrier_node_list.begin(),
barrier_node_list.end()
);
BOOST_FOREACH(NodeID id, bn) {
_barrierNodes[id] = true;
}
BOOST_FOREACH(NodeID id, tl) {
_trafficLights[id] = true;
}
m_traffic_lights.insert(
traffic_light_node_list.begin(),
traffic_light_node_list.end()
);
DeallocatingVector< _NodeBasedEdge > edges;
// edges.reserve( 2 * inputEdges.size() );
for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
DeallocatingVector< NodeBasedEdge > edges_list;
NodeBasedEdge edge;
BOOST_FOREACH(const ImportEdge & import_edge, input_edge_list) {
if(!import_edge.isForward()) {
edge.source = import_edge.target();
edge.target = import_edge.source();
edge.data.backward = import_edge.isForward();
edge.data.forward = import_edge.isBackward();
_NodeBasedEdge edge;
if(!i->isForward()) {
edge.source = i->target();
edge.target = i->source();
edge.data.backward = i->isForward();
edge.data.forward = i->isBackward();
} else {
edge.source = import_edge.source();
edge.target = import_edge.target();
edge.data.forward = import_edge.isForward();
edge.data.backward = import_edge.isBackward();
edge.source = i->source();
edge.target = i->target();
edge.data.forward = i->isForward();
edge.data.backward = i->isBackward();
}
if(edge.source == edge.target) {
continue;
}
edge.data.distance = (std::max)((int)import_edge.weight(), 1 );
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 = import_edge.isRoundabout();
edge.data.ignoreInGrid = import_edge.ignoreInGrid();
edge.data.nameID = import_edge.name();
edge.data.type = import_edge.type();
edge.data.isAccessRestricted = import_edge.isAccessRestricted();
edge.data.edgeBasedNodeID = edges_list.size();
edge.data.contraFlow = import_edge.isContraFlow();
edges_list.push_back( edge );
edge.data.roundabout = i->isRoundabout();
edge.data.ignoreInGrid = i->ignoreInGrid();
edge.data.nameID = i->name();
edge.data.type = i->type();
edge.data.isAccessRestricted = i->isAccessRestricted();
edge.data.edgeBasedNodeID = edges.size();
edges.push_back( edge );
if( edge.data.backward ) {
std::swap( edge.source, edge.target );
edge.data.forward = import_edge.isBackward();
edge.data.backward = import_edge.isForward();
edge.data.edgeBasedNodeID = edges_list.size();
edges_list.push_back( edge );
edge.data.forward = i->isBackward();
edge.data.backward = i->isForward();
edge.data.edgeBasedNodeID = edges.size();
edges.push_back( edge );
}
}
std::vector<ImportEdge>().swap(input_edge_list);
std::sort( edges_list.begin(), edges_list.end() );
m_node_based_graph = boost::make_shared<NodeBasedDynamicGraph>(
number_of_nodes, edges_list
);
std::vector<NodeBasedEdge>().swap(inputEdges);
std::sort( edges.begin(), edges.end() );
_nodeBasedGraph = boost::make_shared<_NodeBasedDynamicGraph>( nodes, edges );
}
void EdgeBasedGraphFactory::GetEdgeBasedEdges(
DeallocatingVector< EdgeBasedEdge >& output_edge_list
) {
BOOST_ASSERT_MSG(
0 == output_edge_list.size(),
"Vector is not empty"
);
m_edge_based_edge_list.swap(output_edge_list);
void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector< EdgeBasedEdge >& outputEdgeList ) {
GUARANTEE(0 == outputEdgeList.size(), "Vector passed to EdgeBasedGraphFactory::GetEdgeBasedEdges(..) is not empty");
edgeBasedEdges.swap(outputEdgeList);
}
void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector<EdgeBasedNode> & nodes) {
void EdgeBasedGraphFactory::GetEdgeBasedNodes( DeallocatingVector< EdgeBasedNode> & nodes) {
#ifndef NDEBUG
BOOST_FOREACH(const EdgeBasedNode & node, m_edge_based_node_list){
BOOST_FOREACH(EdgeBasedNode & node, edgeBasedNodes){
assert(node.lat1 != INT_MAX); assert(node.lon1 != INT_MAX);
assert(node.lat2 != INT_MAX); assert(node.lon2 != INT_MAX);
}
#endif
nodes.swap(m_edge_based_node_list);
nodes.swap(edgeBasedNodes);
}
NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(
const NodeID u,
const NodeID v
) const {
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
RestrictionMap::const_iterator restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter != m_restriction_map.end()) {
const unsigned index = restriction_iter->second;
BOOST_FOREACH(
const RestrictionSource & restriction_target,
m_restriction_bucket_list.at(index)
) {
if(restriction_target.second) {
return restriction_target.first;
void EdgeBasedGraphFactory::GetOriginalEdgeData( std::vector< OriginalEdgeData> & oed) {
oed.swap(originalEdgeData);
}
NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
if (restrIter != _restrictionMap.end()) {
unsigned index = restrIter->second;
BOOST_FOREACH(RestrictionSource restrictionTarget, _restrictionBucketVector.at(index)) {
if(restrictionTarget.second) {
return restrictionTarget.first;
}
}
}
return UINT_MAX;
}
bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
const NodeID u,
const NodeID v,
const NodeID w
) const {
bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const {
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
RestrictionMap::const_iterator restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter != m_restriction_map.end()) {
const unsigned index = restriction_iter->second;
BOOST_FOREACH(
const RestrictionTarget & restriction_target,
m_restriction_bucket_list.at(index)
) {
if(w == restriction_target.first) {
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
if (restrIter != _restrictionMap.end()) {
unsigned index = restrIter->second;
BOOST_FOREACH(RestrictionTarget restrictionTarget, _restrictionBucketVector.at(index)) {
if(w == restrictionTarget.first)
return true;
}
}
}
return false;
}
void EdgeBasedGraphFactory::InsertEdgeBasedNode(
EdgeIterator e1,
NodeIterator u,
NodeIterator v,
_NodeBasedDynamicGraph::EdgeIterator e1,
_NodeBasedDynamicGraph::NodeIterator u,
_NodeBasedDynamicGraph::NodeIterator v,
bool belongsToTinyComponent) {
EdgeData & data = m_node_based_graph->GetEdgeData(e1);
_NodeBasedDynamicGraph::EdgeData & data = _nodeBasedGraph->GetEdgeData(e1);
EdgeBasedNode currentNode;
currentNode.nameID = data.nameID;
currentNode.lat1 = m_node_info_list[u].lat;
currentNode.lon1 = m_node_info_list[u].lon;
currentNode.lat2 = m_node_info_list[v].lat;
currentNode.lon2 = m_node_info_list[v].lon;
currentNode.lat1 = inputNodeInfoList[u].lat;
currentNode.lon1 = inputNodeInfoList[u].lon;
currentNode.lat2 = inputNodeInfoList[v].lat;
currentNode.lon2 = inputNodeInfoList[v].lon;
currentNode.belongsToTinyComponent = belongsToTinyComponent;
currentNode.id = data.edgeBasedNodeID;
currentNode.ignoreInGrid = data.ignoreInGrid;
currentNode.weight = data.distance;
m_edge_based_node_list.push_back(currentNode);
edgeBasedNodes.push_back(currentNode);
}
void EdgeBasedGraphFactory::Run(
const char * original_edge_data_filename,
lua_State *lua_state
) {
SimpleLogger().Write() << "Identifying components of the road network";
void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) {
Percent p(_nodeBasedGraph->GetNumberOfNodes());
int numberOfSkippedTurns(0);
int nodeBasedEdgeCounter(0);
unsigned numberOfOriginalEdges(0);
std::ofstream originalEdgeDataOutFile(originalEdgeDataFilename, std::ios::binary);
originalEdgeDataOutFile.write((char*)&numberOfOriginalEdges, sizeof(unsigned));
Percent p(m_node_based_graph->GetNumberOfNodes());
unsigned skipped_turns_counter = 0;
unsigned node_based_edge_counter = 0;
unsigned original_edges_counter = 0;
std::ofstream edge_data_file(
original_edge_data_filename,
std::ios::binary
);
//writes a dummy value that is updated later
edge_data_file.write(
(char*)&original_edges_counter,
sizeof(unsigned)
);
unsigned current_component = 0, current_component_size = 0;
INFO("Identifying small components");
//Run a BFS on the undirected graph and identify small components
std::queue<std::pair<NodeID, NodeID> > bfs_queue;
std::vector<unsigned> component_index_list(
m_node_based_graph->GetNumberOfNodes(),
UINT_MAX
);
std::vector<NodeID> component_size_list;
std::queue<std::pair<NodeID, NodeID> > bfsQueue;
std::vector<unsigned> componentsIndex(_nodeBasedGraph->GetNumberOfNodes(), UINT_MAX);
std::vector<NodeID> vectorOfComponentSizes;
unsigned currentComponent = 0, sizeOfCurrentComponent = 0;
//put unexplorered node with parent pointer into queue
for(
NodeID node = 0,
last_node = m_node_based_graph->GetNumberOfNodes();
node < last_node;
++node
) {
if(UINT_MAX == component_index_list[node]) {
bfs_queue.push(std::make_pair(node, node));
for(NodeID node = 0, endNodes = _nodeBasedGraph->GetNumberOfNodes(); node < endNodes; ++node) {
if(UINT_MAX == componentsIndex[node]) {
bfsQueue.push(std::make_pair(node, node));
//mark node as read
component_index_list[node] = current_component;
componentsIndex[node] = currentComponent;
p.printIncrement();
while(!bfs_queue.empty()) {
while(!bfsQueue.empty()) {
//fetch element from BFS queue
std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
bfs_queue.pop();
// SimpleLogger().Write() << "sizeof queue: " << bfs_queue.size() <<
// ", current_component_sizes: " << current_component_size <<
//", settled nodes: " << settledNodes++ << ", max: " << endNodes;
const NodeID v = current_queue_item.first; //current node
const NodeID u = current_queue_item.second; //parent
std::pair<NodeID, NodeID> currentQueueItem = bfsQueue.front();
bfsQueue.pop();
// INFO("sizeof queue: " << bfsQueue.size() << ", sizeOfCurrentComponents: " << sizeOfCurrentComponent << ", settled nodes: " << settledNodes++ << ", max: " << endNodes);
const NodeID v = currentQueueItem.first; //current node
const NodeID u = currentQueueItem.second; //parent
//increment size counter of current component
++current_component_size;
const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
if(!is_barrier_node) {
const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
++sizeOfCurrentComponent;
const bool isBollardNode = (_barrierNodes.find(v) != _barrierNodes.end());
if(!isBollardNode) {
const NodeID onlyToNode = CheckForEmanatingIsOnlyTurn(u, v);
//relaxieren edge outgoing edge like below where edge-expanded graph
for(
EdgeIterator e2 = m_node_based_graph->BeginEdges(v);
e2 < m_node_based_graph->EndEdges(v);
++e2
) {
NodeIterator w = m_node_based_graph->GetTarget(e2);
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
_NodeBasedDynamicGraph::NodeIterator w = _nodeBasedGraph->GetTarget(e2);
if(
to_node_of_only_restriction != UINT_MAX &&
w != to_node_of_only_restriction
) {
//We are at an only_-restriction but not at the right turn.
if(onlyToNode != UINT_MAX && w != onlyToNode) { //We are at an only_-restriction but not at the right turn.
continue;
}
if( u != w ) {
//only add an edge if turn is not a U-turn except
//when it is at the end of a dead-end street.
if (!CheckIfTurnIsRestricted(u, v, w) ) {
//only add an edge if turn is not prohibited
if(UINT_MAX == component_index_list[w]) {
//insert next (node, parent) only if w has
//not yet been explored
if( u != w ) { //only add an edge if turn is not a U-turn except it is the end of dead-end street.
if (!CheckIfTurnIsRestricted(u, v, w) ) { //only add an edge if turn is not prohibited
//insert next (node, parent) only if w has not yet been explored
if(UINT_MAX == componentsIndex[w]) {
//mark node as read
component_index_list[w] = current_component;
bfs_queue.push(std::make_pair(w,v));
componentsIndex[w] = currentComponent;
bfsQueue.push(std::make_pair(w,v));
p.printIncrement();
}
}
@@ -284,278 +216,176 @@ void EdgeBasedGraphFactory::Run(
}
}
//push size into vector
component_size_list.push_back(current_component_size);
vectorOfComponentSizes.push_back(sizeOfCurrentComponent);
//reset counters;
current_component_size = 0;
++current_component;
sizeOfCurrentComponent = 0;
++currentComponent;
}
}
SimpleLogger().Write() <<
"identified: " << component_size_list.size() << " many components";
INFO("identified: " << vectorOfComponentSizes.size() << " many components");
p.reinit(m_node_based_graph->GetNumberOfNodes());
p.reinit(_nodeBasedGraph->GetNumberOfNodes());
//loop over all edges and generate new set of nodes.
for(
NodeIterator u = 0,
number_of_nodes = m_node_based_graph->GetNumberOfNodes();
u < number_of_nodes;
++u
) {
for(
EdgeIterator e1 = m_node_based_graph->BeginEdges(u),
last_edge = m_node_based_graph->EndEdges(u);
e1 < last_edge;
++e1
) {
NodeIterator v = m_node_based_graph->GetTarget(e1);
for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
_NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
if(m_node_based_graph->GetEdgeData(e1).type != SHRT_MAX) {
BOOST_ASSERT_MSG(e1 != UINT_MAX, "edge id invalid");
BOOST_ASSERT_MSG(u != UINT_MAX, "souce node invalid");
BOOST_ASSERT_MSG(v != UINT_MAX, "target node invalid");
//Note: edges that end on barrier nodes or on a turn restriction
//may actually be in two distinct components. We choose the smallest
const unsigned size_of_component = std::min(
component_size_list[component_index_list[u]],
component_size_list[component_index_list[v]]
);
InsertEdgeBasedNode( e1, u, v, size_of_component < 1000 );
if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) {
assert(e1 != UINT_MAX);
assert(u != UINT_MAX);
assert(v != UINT_MAX);
//edges that end on bollard nodes may actually be in two distinct components
InsertEdgeBasedNode(e1, u, v, (std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 1000) );
}
}
}
std::vector<NodeID>().swap(component_size_list);
BOOST_ASSERT_MSG(
0 == component_size_list.capacity(),
"component size vector not deallocated"
);
std::vector<NodeID>().swap(component_index_list);
BOOST_ASSERT_MSG(
0 == component_index_list.capacity(),
"component index vector not deallocated"
);
std::vector<OriginalEdgeData> original_edge_data_vector;
original_edge_data_vector.reserve(10000);
std::vector<NodeID>().swap(vectorOfComponentSizes);
std::vector<NodeID>().swap(componentsIndex);
//Loop over all turns and generate new set of edges.
//Three nested loop look super-linear, but we are dealing with a (kind of)
//linear number of turns only.
for(
NodeIterator u = 0,
last_node = m_node_based_graph->GetNumberOfNodes();
u < last_node;
++u
) {
for(
EdgeIterator e1 = m_node_based_graph->BeginEdges(u),
last_edge_u = m_node_based_graph->EndEdges(u);
e1 < last_edge_u;
++e1
) {
++node_based_edge_counter;
NodeIterator v = m_node_based_graph->GetTarget(e1);
bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
for(
EdgeIterator e2 = m_node_based_graph->BeginEdges(v),
last_edge_v = m_node_based_graph->EndEdges(v);
e2 < last_edge_v;
++e2
) {
const NodeIterator w = m_node_based_graph->GetTarget(e2);
if(
to_node_of_only_restriction != UINT_MAX &&
w != to_node_of_only_restriction
) {
//We are at an only_-restriction but not at the right turn.
++skipped_turns_counter;
//Three nested loop look super-linear, but we are dealing with a linear number of turns only.
for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
++nodeBasedEdgeCounter;
_NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
//EdgeWeight heightPenalty = ComputeHeightPenalty(u, v);
NodeID onlyToNode = CheckForEmanatingIsOnlyTurn(u, v);
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
const _NodeBasedDynamicGraph::NodeIterator w = _nodeBasedGraph->GetTarget(e2);
if(onlyToNode != UINT_MAX && w != onlyToNode) { //We are at an only_-restriction but not at the right turn.
++numberOfSkippedTurns;
continue;
}
bool isBollardNode = (_barrierNodes.find(v) != _barrierNodes.end());
if(u == w && 1 != _nodeBasedGraph->GetOutDegree(v) ) {
continue;
}
if(u == w && 1 != m_node_based_graph->GetOutDegree(v) ) {
continue;
}
if( !isBollardNode ) { //only add an edge if turn is not a U-turn except it is the end of dead-end street.
if (!CheckIfTurnIsRestricted(u, v, w) || (onlyToNode != UINT_MAX && w == onlyToNode)) { //only add an edge if turn is not prohibited
const _NodeBasedDynamicGraph::EdgeData edgeData1 = _nodeBasedGraph->GetEdgeData(e1);
const _NodeBasedDynamicGraph::EdgeData edgeData2 = _nodeBasedGraph->GetEdgeData(e2);
assert(edgeData1.edgeBasedNodeID < _nodeBasedGraph->GetNumberOfEdges());
assert(edgeData2.edgeBasedNodeID < _nodeBasedGraph->GetNumberOfEdges());
if( !is_barrier_node ) {
//only add an edge if turn is not a U-turn except when it is
//at the end of a dead-end street
if (
!CheckIfTurnIsRestricted(u, v, w) ||
(to_node_of_only_restriction != UINT_MAX && w == to_node_of_only_restriction)
) { //only add an edge if turn is not prohibited
const EdgeData edge_data1 = m_node_based_graph->GetEdgeData(e1);
const EdgeData edge_data2 = m_node_based_graph->GetEdgeData(e2);
assert(edge_data1.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges());
assert(edge_data2.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges());
if(!edge_data1.forward || !edge_data2.forward) {
if(!edgeData1.forward || !edgeData2.forward) {
continue;
}
unsigned distance = edge_data1.distance;
if(m_traffic_lights.find(v) != m_traffic_lights.end()) {
distance += speed_profile.trafficSignalPenalty;
unsigned distance = edgeData1.distance;
if(_trafficLights.find(v) != _trafficLights.end()) {
distance += speedProfile.trafficSignalPenalty;
}
const unsigned penalty =
GetTurnPenalty(u, v, w, lua_state);
TurnInstruction turnInstruction = AnalyzeTurn(u, v, w);
if(turnInstruction == TurnInstructions.UTurn){
distance += speed_profile.uTurnPenalty;
if(turnInstruction == TurnInstructions.UTurn)
distance += speedProfile.uTurnPenalty;
// if(!edgeData1.isAccessRestricted && edgeData2.isAccessRestricted) {
// distance += TurnInstructions.AccessRestrictionPenalty;
// turnInstruction |= TurnInstructions.AccessRestrictionFlag;
// }
//distance += heightPenalty;
//distance += ComputeTurnPenalty(u, v, w);
assert(edgeData1.edgeBasedNodeID != edgeData2.edgeBasedNodeID);
if(originalEdgeData.size() == originalEdgeData.capacity()-3) {
originalEdgeData.reserve(originalEdgeData.size()*1.2);
}
distance += penalty;
assert(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID);
original_edge_data_vector.push_back(
OriginalEdgeData(
v,
edge_data2.nameID,
turnInstruction
)
);
++original_edges_counter;
if(original_edge_data_vector.size() > 100000) {
edge_data_file.write(
(char*)&(original_edge_data_vector[0]),
original_edge_data_vector.size()*sizeof(OriginalEdgeData)
);
original_edge_data_vector.clear();
OriginalEdgeData oed(v,edgeData2.nameID, turnInstruction);
EdgeBasedEdge newEdge(edgeData1.edgeBasedNodeID, edgeData2.edgeBasedNodeID, edgeBasedEdges.size(), distance, true, false );
originalEdgeData.push_back(oed);
if(originalEdgeData.size() > 100000) {
originalEdgeDataOutFile.write((char*)&(originalEdgeData[0]), originalEdgeData.size()*sizeof(OriginalEdgeData));
originalEdgeData.clear();
}
m_edge_based_edge_list.push_back(
EdgeBasedEdge(
edge_data1.edgeBasedNodeID,
edge_data2.edgeBasedNodeID,
m_edge_based_edge_list.size(),
distance,
true,
false
)
);
++numberOfOriginalEdges;
++nodeBasedEdgeCounter;
edgeBasedEdges.push_back(newEdge);
} else {
++skipped_turns_counter;
++numberOfSkippedTurns;
}
}
}
}
p.printIncrement();
}
edge_data_file.write(
(char*)&(original_edge_data_vector[0]),
original_edge_data_vector.size()*sizeof(OriginalEdgeData)
);
edge_data_file.seekp(std::ios::beg);
edge_data_file.write(
(char*)&original_edges_counter,
sizeof(unsigned)
);
edge_data_file.close();
numberOfOriginalEdges += originalEdgeData.size();
originalEdgeDataOutFile.write((char*)&(originalEdgeData[0]), originalEdgeData.size()*sizeof(OriginalEdgeData));
originalEdgeDataOutFile.seekp(std::ios::beg);
originalEdgeDataOutFile.write((char*)&numberOfOriginalEdges, sizeof(unsigned));
originalEdgeDataOutFile.close();
SimpleLogger().Write() <<
"Generated " << m_edge_based_node_list.size() << " edge based nodes";
SimpleLogger().Write() <<
"Node-based graph contains " << node_based_edge_counter << " edges";
SimpleLogger().Write() <<
"Edge-expanded graph ...";
SimpleLogger().Write() <<
" contains " << m_edge_based_edge_list.size() << " edges";
SimpleLogger().Write() <<
" skips " << skipped_turns_counter << " turns, "
"defined by " << m_turn_restrictions_count << " restrictions";
// INFO("Sorting edge-based Nodes");
// std::sort(edgeBasedNodes.begin(), edgeBasedNodes.end());
// INFO("Removing duplicate nodes (if any)");
// edgeBasedNodes.erase( std::unique(edgeBasedNodes.begin(), edgeBasedNodes.end()), edgeBasedNodes.end() );
// INFO("Applying vector self-swap trick to free up memory");
// INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity());
// std::vector<EdgeBasedNode>(edgeBasedNodes).swap(edgeBasedNodes);
// INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity());
INFO("Node-based graph contains " << nodeBasedEdgeCounter << " edges");
// INFO("Edge-based graph contains " << edgeBasedEdges.size() << " edges, blowup is " << 2*((double)edgeBasedEdges.size()/(double)nodeBasedEdgeCounter));
INFO("Edge-based graph skipped " << numberOfSkippedTurns << " turns, defined by " << numberOfTurnRestrictions << " restrictions.");
INFO("Generated " << edgeBasedNodes.size() << " edge based nodes");
}
int EdgeBasedGraphFactory::GetTurnPenalty(
const NodeID u,
const NodeID v,
const NodeID w,
lua_State *lua_state
) const {
const double angle = GetAngleBetweenThreeFixedPointCoordinates (
m_node_info_list[u],
m_node_info_list[v],
m_node_info_list[w]
);
if( speed_profile.has_turn_penalty_function ) {
try {
//call lua profile to compute turn penalty
return luabind::call_function<int>(
lua_state,
"turn_function",
180.-angle
);
} catch (const luabind::error &er) {
SimpleLogger().Write(logWARNING) << er.what();
}
}
return 0;
}
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
const NodeID u,
const NodeID v,
const NodeID w
) const {
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const {
if(u == w) {
return TurnInstructions.UTurn;
}
EdgeIterator edge1 = m_node_based_graph->FindEdge(u, v);
EdgeIterator edge2 = m_node_based_graph->FindEdge(v, w);
_NodeBasedDynamicGraph::EdgeIterator edge1 = _nodeBasedGraph->FindEdge(u, v);
_NodeBasedDynamicGraph::EdgeIterator edge2 = _nodeBasedGraph->FindEdge(v, w);
EdgeData & data1 = m_node_based_graph->GetEdgeData(edge1);
EdgeData & data2 = m_node_based_graph->GetEdgeData(edge2);
if(!data1.contraFlow && data2.contraFlow) {
return TurnInstructions.EnterAgainstAllowedDirection;
}
if(data1.contraFlow && !data2.contraFlow) {
return TurnInstructions.LeaveAgainstAllowedDirection;
}
_NodeBasedDynamicGraph::EdgeData & data1 = _nodeBasedGraph->GetEdgeData(edge1);
_NodeBasedDynamicGraph::EdgeData & data2 = _nodeBasedGraph->GetEdgeData(edge2);
//roundabouts need to be handled explicitely
if(data1.roundabout && data2.roundabout) {
//Is a turn possible? If yes, we stay on the roundabout!
if( 1 == m_node_based_graph->GetOutDegree(v) ) {
if( 1 == (_nodeBasedGraph->EndEdges(v) - _nodeBasedGraph->BeginEdges(v)) ) {
//No turn possible.
return TurnInstructions.NoTurn;
} else {
return TurnInstructions.StayOnRoundAbout;
}
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) {
if( (!data1.roundabout) && data2.roundabout)
return TurnInstructions.EnterRoundAbout;
}
//We are leaving the roundabout
if(data1.roundabout && (!data2.roundabout) ) {
else if(data1.roundabout && (!data2.roundabout) )
return TurnInstructions.LeaveRoundAbout;
}
}
//If street names stay the same and if we are certain that it is not a
//a segment of a roundabout, we skip it.
if( data1.nameID == data2.nameID ) {
//TODO: Here we should also do a small graph exploration to check for
// more complex situations
if( 0 != data1.nameID ) {
return TurnInstructions.NoTurn;
} else if (m_node_based_graph->GetOutDegree(v) <= 2) {
return TurnInstructions.NoTurn;
}
}
const double angle = GetAngleBetweenThreeFixedPointCoordinates (
m_node_info_list[u],
m_node_info_list[v],
m_node_info_list[w]
);
//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) && (0 != data1.nameID))
return TurnInstructions.NoTurn;
if( (data1.nameID == data2.nameID) && (0 == data1.nameID) && (_nodeBasedGraph->GetOutDegree(v) <= 2) )
return TurnInstructions.NoTurn;
double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]);
return TurnInstructions.GetTurnDirectionOfInstruction(angle);
}
unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
return m_node_based_graph->GetNumberOfEdges();
return _nodeBasedGraph->GetNumberOfEdges();
}
/* 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;
}
+82 -140
View File
@@ -18,11 +18,25 @@
or see http://www.gnu.org/licenses/agpl.txt.
*/
// This class constructs the edge-expanded routing graph
/*
* This class constructs the edge base representation of a graph from a given node based edge list
*/
#ifndef EDGEBASEDGRAPHFACTORY_H_
#define EDGEBASEDGRAPHFACTORY_H_
#include <algorithm>
#include <queue>
#include <vector>
#include <stxxl.h>
#include <cstdlib>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include "../typedefs.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
@@ -32,121 +46,21 @@
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/LuaUtil.h"
#include "../Util/SimpleLogger.h"
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <algorithm>
#include <fstream>
#include <queue>
#include <vector>
class EdgeBasedGraphFactory : boost::noncopyable {
public:
struct EdgeBasedNode {
EdgeBasedNode() :
id(INT_MAX),
lat1(INT_MAX),
lat2(INT_MAX),
lon1(INT_MAX),
lon2(INT_MAX >> 1),
belongsToTinyComponent(false),
nameID(UINT_MAX),
weight(UINT_MAX >> 1),
ignoreInGrid(false)
{ }
bool operator<(const EdgeBasedNode & other) const {
return other.id < id;
}
bool operator==(const EdgeBasedNode & other) const {
return id == other.id;
}
inline FixedPointCoordinate Centroid() const {
FixedPointCoordinate centroid;
//The coordinates of the midpoint are given by:
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
centroid.lon = (std::min(lon1, lon2) + std::max(lon1, lon2))/2;
centroid.lat = (std::min(lat1, lat2) + std::max(lat1, lat2))/2;
return centroid;
}
inline bool isIgnored() const {
return ignoreInGrid;
}
NodeID id;
int lat1;
int lat2;
int lon1;
int lon2:31;
bool belongsToTinyComponent:1;
NodeID nameID;
unsigned weight:31;
bool ignoreInGrid:1;
};
struct SpeedProfileProperties{
SpeedProfileProperties() :
trafficSignalPenalty(0),
uTurnPenalty(0),
has_turn_penalty_function(false)
{ }
int trafficSignalPenalty;
int uTurnPenalty;
bool has_turn_penalty_function;
} speed_profile;
explicit EdgeBasedGraphFactory(
int number_of_nodes,
std::vector<ImportEdge> & input_edge_list,
std::vector<NodeID> & barrier_node_list,
std::vector<NodeID> & traffic_light_node_list,
std::vector<TurnRestriction> & input_restrictions_list,
std::vector<NodeInfo> & m_node_info_list,
SpeedProfileProperties speed_profile
);
void Run(const char * originalEdgeDataFilename, lua_State *myLuaState);
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
void GetOriginalEdgeData( std::vector<OriginalEdgeData> & originalEdgeData);
TurnInstruction AnalyzeTurn(
const NodeID u,
const NodeID v,
const NodeID w
) const;
int GetTurnPenalty(
const NodeID u,
const NodeID v,
const NodeID w,
lua_State *myLuaState
) const;
unsigned GetNumberOfNodes() const;
#include "../Util/BaseConfiguration.h"
class EdgeBasedGraphFactory {
private:
struct NodeBasedEdgeData {
struct _NodeBasedEdgeData {
int distance;
unsigned edgeBasedNodeID;
unsigned nameID;
short type;
bool isAccessRestricted:1;
unsigned nameID:31;
bool shortcut:1;
bool forward:1;
bool backward:1;
bool roundabout:1;
bool ignoreInGrid:1;
bool contraFlow:1;
short type;
bool isAccessRestricted;
};
struct _EdgeBasedEdgeData {
@@ -158,46 +72,74 @@ private:
TurnInstruction turnInstruction;
};
unsigned m_turn_restrictions_count;
typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph;
typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge;
std::vector<NodeInfo> inputNodeInfoList;
unsigned numberOfTurnRestrictions;
public:
struct EdgeBasedNode {
bool operator<(const EdgeBasedNode & other) const {
return other.id < id;
}
bool operator==(const EdgeBasedNode & other) const {
return id == other.id;
}
NodeID id;
int lat1;
int lat2;
int lon1;
int lon2:31;
bool belongsToTinyComponent:1;
NodeID nameID;
unsigned weight:31;
bool ignoreInGrid:1;
};
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge;
typedef NodeBasedDynamicGraph::NodeIterator NodeIterator;
typedef NodeBasedDynamicGraph::EdgeIterator EdgeIterator;
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
typedef std::pair<NodeID, NodeID> RestrictionSource;
typedef std::pair<NodeID, bool> RestrictionTarget;
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
struct SpeedProfileProperties{
SpeedProfileProperties() : trafficSignalPenalty(0), uTurnPenalty(0) {}
int trafficSignalPenalty;
int uTurnPenalty;
} speedProfile;
private:
boost::shared_ptr<_NodeBasedDynamicGraph> _nodeBasedGraph;
boost::unordered_map<NodeID, bool> _barrierNodes;
boost::unordered_map<NodeID, bool> _trafficLights;
typedef std::pair<NodeID, NodeID> RestrictionSource;
typedef std::pair<NodeID, bool> RestrictionTarget;
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
std::vector<NodeInfo> m_node_info_list;
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
std::vector<EdgeBasedNode> m_edge_based_node_list;
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
boost::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
boost::unordered_set<NodeID> m_barrier_nodes;
boost::unordered_set<NodeID> m_traffic_lights;
RestrictionMap m_restriction_map;
std::vector<EmanatingRestrictionsVector> _restrictionBucketVector;
RestrictionMap _restrictionMap;
NodeID CheckForEmanatingIsOnlyTurn(
const NodeID u,
const NodeID v
) const;
bool CheckIfTurnIsRestricted(
const NodeID u,
const NodeID v,
const NodeID w
) const;
DeallocatingVector<EdgeBasedEdge> edgeBasedEdges;
DeallocatingVector<EdgeBasedNode> edgeBasedNodes;
std::vector<OriginalEdgeData> originalEdgeData;
NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
void InsertEdgeBasedNode(
NodeBasedDynamicGraph::EdgeIterator e1,
NodeBasedDynamicGraph::NodeIterator u,
NodeBasedDynamicGraph::NodeIterator v,
_NodeBasedDynamicGraph::EdgeIterator e1,
_NodeBasedDynamicGraph::NodeIterator u,
_NodeBasedDynamicGraph::NodeIterator v,
bool belongsToTinyComponent);
template<class CoordinateT>
double GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const;
// SRTMLookup srtmLookup;
public:
template< class InputEdgeT >
explicit EdgeBasedGraphFactory(int nodes, std::vector<InputEdgeT> & inputEdges, std::vector<NodeID> & _bollardNodes, std::vector<NodeID> & trafficLights, std::vector<_Restriction> & inputRestrictions, std::vector<NodeInfo> & nI, SpeedProfileProperties speedProfile);
void Run(const char * originalEdgeDataFilename);
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
void GetEdgeBasedNodes( DeallocatingVector< EdgeBasedNode> & nodes);
void GetOriginalEdgeData( std::vector< OriginalEdgeData> & originalEdgeData);
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const;
unsigned GetNumberOfNodes() const;
};
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
+22 -11
View File
@@ -18,10 +18,16 @@
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include <boost/foreach.hpp>
#include "TemporaryStorage.h"
TemporaryStorage::TemporaryStorage() {
tempDirectory = boost::filesystem::temp_directory_path();
try {
tempDirectory = boost::filesystem::temp_directory_path();
} catch(boost::filesystem::filesystem_error & e) {
ERR("could not retrieve location of temporary path: " << e.what());
}
}
TemporaryStorage & TemporaryStorage::GetInstance(){
@@ -35,8 +41,12 @@ TemporaryStorage::~TemporaryStorage() {
void TemporaryStorage::removeAll() {
boost::mutex::scoped_lock lock(mutex);
for(unsigned slot_id = 0; slot_id < vectorOfStreamDatas.size(); ++slot_id) {
deallocateSlot(slot_id);
try {
for(unsigned slotID = 0; slotID < vectorOfStreamDatas.size(); ++slotID)
deallocateSlot(slotID);
} catch(boost::filesystem::filesystem_error & e) {
ERR("could not retrieve location of temporary path: " << e.what());
}
vectorOfStreamDatas.clear();
}
@@ -45,7 +55,7 @@ int TemporaryStorage::allocateSlot() {
boost::mutex::scoped_lock lock(mutex);
try {
vectorOfStreamDatas.push_back(StreamData());
//SimpleLogger().Write() << "created new temporary file: " << vectorOfStreamDatas.back().pathToTemporaryFile;
//INFO("created new temporary file: " << vectorOfStreamDatas.back().pathToTemporaryFile);
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
@@ -56,13 +66,13 @@ void TemporaryStorage::deallocateSlot(int slotID) {
try {
StreamData & data = vectorOfStreamDatas[slotID];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
if(!boost::filesystem::exists(data.pathToTemporaryFile)) {
if(!boost::filesystem::exists(data.pathToTemporaryFile)) {
return;
}
if(data.streamToTemporaryFile->is_open()) {
if(data.streamToTemporaryFile->is_open())
data.streamToTemporaryFile->close();
}
//INFO("deallocating slot " << slotID << " and its file: " << data.pathToTemporaryFile);
boost::filesystem::remove(data.pathToTemporaryFile);
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
@@ -73,10 +83,8 @@ void TemporaryStorage::writeToSlot(int slotID, char * pointer, std::streamsize s
try {
StreamData & data = vectorOfStreamDatas[slotID];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
BOOST_ASSERT_MSG(
data.writeMode,
"Writing after first read is not allowed"
);
if(!data.writeMode)
ERR("Writing after first read is not allowed");
data.streamToTemporaryFile->write(pointer, size);
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
@@ -115,11 +123,13 @@ boost::filesystem::fstream::pos_type TemporaryStorage::tell(int slotID) {
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
// INFO("telling position: " << position);
return position;
}
void TemporaryStorage::abort(boost::filesystem::filesystem_error& ) {
removeAll();
// ERR("I/O Error occured: " << e.what());
}
void TemporaryStorage::seek(int slotID, boost::filesystem::fstream::pos_type position) {
@@ -127,6 +137,7 @@ void TemporaryStorage::seek(int slotID, boost::filesystem::fstream::pos_type pos
StreamData & data = vectorOfStreamDatas[slotID];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
data.streamToTemporaryFile->seekg(position);
// INFO("seeking to position: " << position);
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
+7 -11
View File
@@ -24,21 +24,17 @@
#include <vector>
#include <fstream>
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
//This is one big workaround for latest boost renaming woes.
#if BOOST_FILESYSTEM_VERSION < 3
#warning Boost Installation with Filesystem3 missing, activating workaround
#ifndef BOOST_FILESYSTEM_VERSION
#warning Boost Installation with Filesystem3 (>=1.44) is required, activating workaround
#include <cstdio>
namespace boost {
namespace filesystem {
@@ -58,9 +54,8 @@ inline path unique_path(const path&) {
#endif
#ifndef BOOST_FILESYSTEM_VERSION
#define BOOST_FILESYSTEM_VERSION 3
#endif
/**
* This class implements a singleton file storage for temporary data.
* temporary slots can be accessed by other objects through an int
@@ -94,6 +89,8 @@ private:
}
void abort(boost::filesystem::filesystem_error& e);
;
struct StreamData {
bool writeMode;
boost::filesystem::path pathToTemporaryFile;
@@ -105,9 +102,8 @@ private:
streamToTemporaryFile(new boost::filesystem::fstream(pathToTemporaryFile, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
readWriteMutex(new boost::mutex)
{
if(streamToTemporaryFile->fail()) {
throw OSRMException("temporary file could not be created");
}
if(streamToTemporaryFile->fail())
ERR("Aborting, because temporary file at " << pathToTemporaryFile << " could not be created");
}
};
//vector of file streams that is used to store temporary data
+10 -15
View File
@@ -23,14 +23,12 @@ or see http://www.gnu.org/licenses/agpl.txt.
//Not compatible with non contiguous node ids
#include <boost/unordered_map.hpp>
#include <cassert>
#include <algorithm>
#include <limits>
#include <map>
#include <vector>
#include <algorithm>
#include <map>
#include <boost/unordered_map.hpp>
template< typename NodeID, typename Key >
class ArrayStorage {
@@ -77,13 +75,10 @@ template< typename NodeID, typename Key >
class UnorderedMapStorage {
public:
UnorderedMapStorage( size_t ) {
//hash table gets 1000 Buckets
nodes.rehash(1000);
}
UnorderedMapStorage( size_t ) { }
Key &operator[]( const NodeID node ) {
return nodes[node];
Key &operator[]( NodeID node ) {
return nodes[node];
}
void Clear() {
@@ -147,13 +142,13 @@ public:
return insertedNodes[index].weight;
}
bool WasRemoved( const NodeID node ) {
bool WasRemoved( NodeID node ) {
assert( WasInserted( node ) );
const Key index = nodeIndex[node];
return insertedNodes[index].key == 0;
}
bool WasInserted( const NodeID node ) {
bool WasInserted( NodeID node ) {
const Key index = nodeIndex[node];
if ( index >= static_cast<Key> (insertedNodes.size()) )
return false;
@@ -186,8 +181,8 @@ public:
void DecreaseKey( NodeID node, Weight weight ) {
assert( UINT_MAX != node );
const Key & index = nodeIndex[node];
Key & key = insertedNodes[index].key;
const Key index = nodeIndex[node];
Key key = insertedNodes[index].key;
assert ( key >= 0 );
insertedNodes[index].weight = weight;
+19 -76
View File
@@ -18,26 +18,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef FIXED_POINT_COORDINATE_H_
#define FIXED_POINT_COORDINATE_H_
#ifndef COORDINATE_H_
#define COORDINATE_H_
#include "../DataStructures/MercatorUtil.h"
#include "../Util/StringUtil.h"
#include <cassert>
#include <cmath>
#include <climits>
#include <iostream>
static const double COORDINATE_PRECISION = 1000000.;
struct FixedPointCoordinate {
struct _Coordinate {
int lat;
int lon;
FixedPointCoordinate () : lat(INT_MIN), lon(INT_MIN) {}
explicit FixedPointCoordinate (int lat, int lon) : lat(lat) , lon(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;
@@ -46,22 +37,17 @@ struct FixedPointCoordinate {
return (INT_MIN != lat) && (INT_MIN != lon);
}
inline bool isValid() const {
if(
lat > 90*COORDINATE_PRECISION ||
lat < -90*COORDINATE_PRECISION ||
lon > 180*COORDINATE_PRECISION ||
lon < -180*COORDINATE_PRECISION
) {
if(lat > 90*100000 || lat < -90*100000 || lon > 180*100000 || lon <-180*100000) {
return false;
}
return true;
}
bool operator==(const FixedPointCoordinate & other) const {
bool operator==(const _Coordinate & other) const {
return lat == other.lat && lon == other.lon;
}
};
inline std::ostream & operator<<(std::ostream & out, const FixedPointCoordinate & c){
inline std::ostream & operator<<(std::ostream & out, const _Coordinate & c){
out << "(" << c.lat << "," << c.lon << ")";
return out;
}
@@ -72,10 +58,10 @@ inline double ApproximateDistance( const int lat1, const int lon1, const int lat
assert(lat2 != INT_MIN);
assert(lon2 != INT_MIN);
double RAD = 0.017453292519943295769236907684886;
double lt1 = lat1/COORDINATE_PRECISION;
double ln1 = lon1/COORDINATE_PRECISION;
double lt2 = lat2/COORDINATE_PRECISION;
double ln2 = lon2/COORDINATE_PRECISION;
double lt1 = lat1/100000.;
double ln1 = lon1/100000.;
double lt2 = lat2/100000.;
double ln2 = lon2/100000.;
double dlat1=lt1*(RAD);
double dlong1=ln1*(RAD);
@@ -94,20 +80,20 @@ inline double ApproximateDistance( const int lat1, const int lon1, const int lat
return distance;
}
inline double ApproximateDistance(const FixedPointCoordinate &c1, const FixedPointCoordinate &c2) {
inline double ApproximateDistance(const _Coordinate &c1, const _Coordinate &c2) {
return ApproximateDistance( c1.lat, c1.lon, c2.lat, c2.lon );
}
inline double ApproximateEuclideanDistance(const FixedPointCoordinate &c1, const FixedPointCoordinate &c2) {
inline double ApproximateDistanceByEuclid(const _Coordinate &c1, const _Coordinate &c2) {
assert(c1.lat != INT_MIN);
assert(c1.lon != INT_MIN);
assert(c2.lat != INT_MIN);
assert(c2.lon != INT_MIN);
const double RAD = 0.017453292519943295769236907684886;
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD;
const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD;
const double lat2 = (c2.lat/COORDINATE_PRECISION)*RAD;
const double lon2 = (c2.lon/COORDINATE_PRECISION)*RAD;
const double lat1 = (c1.lat/100000.)*RAD;
const double lon1 = (c1.lon/100000.)*RAD;
const double lat2 = (c2.lat/100000.)*RAD;
const double lon2 = (c2.lon/100000.)*RAD;
const double x = (lon2-lon1) * cos((lat1+lat2)/2.);
const double y = (lat2-lat1);
@@ -116,48 +102,5 @@ inline double ApproximateEuclideanDistance(const FixedPointCoordinate &c1, const
return d;
}
static inline void convertInternalLatLonToString(const int value, std::string & output) {
char buffer[100];
buffer[10] = 0; // Nullterminierung
char* string = printInt< 10, 6 >( buffer, value );
output = string;
}
static inline void convertInternalCoordinateToString(const FixedPointCoordinate & coord, std::string & output) {
std::string tmp;
convertInternalLatLonToString(coord.lon, tmp);
output = tmp;
output += ",";
convertInternalLatLonToString(coord.lat, tmp);
output += tmp;
output += " ";
}
static inline void convertInternalReversedCoordinateToString(const FixedPointCoordinate & coord, std::string & output) {
std::string tmp;
convertInternalLatLonToString(coord.lat, tmp);
output = tmp;
output += ",";
convertInternalLatLonToString(coord.lon, tmp);
output += tmp;
output += " ";
}
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
template<class CoordinateT>
static inline double GetAngleBetweenThreeFixedPointCoordinates (
const CoordinateT & A,
const CoordinateT & C,
const CoordinateT & B
) {
const double v1x = (A.lon - C.lon)/COORDINATE_PRECISION;
const double v1y = lat2y(A.lat/COORDINATE_PRECISION) - lat2y(C.lat/COORDINATE_PRECISION);
const double v2x = (B.lon - C.lon)/COORDINATE_PRECISION;
const double v2y = lat2y(B.lat/COORDINATE_PRECISION) - lat2y(C.lat/COORDINATE_PRECISION);
double angle = (atan2(v2y,v2x) - atan2(v1y,v1x) )*180/M_PI;
while(angle < 0)
angle += 360;
return angle;
}
#endif /* FIXED_POINT_COORDINATE_H_ */
#endif /* COORDINATE_H_ */
+27 -38
View File
@@ -22,6 +22,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
#define DEALLOCATINGVECTOR_H_
#include <cassert>
#include <cstdlib>
#include <vector>
#if __cplusplus > 199711L
@@ -31,7 +32,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
#endif
template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT), bool DeallocateC = false>
template<typename ElementT, size_t bucketSizeC = 10485760/sizeof(ElementT), bool DeallocateC = false>
class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT> {
protected:
@@ -41,12 +42,12 @@ protected:
DeallocatingVectorIteratorState();
public:
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : mData(r.mData), mIndex(r.mIndex), mBucketList(r.mBucketList) {}
//explicit DeallocatingVectorIteratorState(const ElementT * ptr, const std::size_t idx, const std::vector<ElementT *> & input_list) : mData(ptr), mIndex(idx), mBucketList(input_list) {}
explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector<ElementT *> & input_list) : mData(DEALLOCATION_VECTOR_NULL_PTR), mIndex(idx), mBucketList(input_list) {
//explicit DeallocatingVectorIteratorState(const ElementT * ptr, const size_t idx, const std::vector<ElementT *> & input_list) : mData(ptr), mIndex(idx), mBucketList(input_list) {}
explicit DeallocatingVectorIteratorState(const size_t idx, std::vector<ElementT *> & input_list) : mData(DEALLOCATION_VECTOR_NULL_PTR), mIndex(idx), mBucketList(input_list) {
setPointerForIndex();
}
ElementT * mData;
std::size_t mIndex;
size_t mIndex;
std::vector<ElementT *> & mBucketList;
inline void setPointerForIndex() {
@@ -54,8 +55,8 @@ protected:
mData = DEALLOCATION_VECTOR_NULL_PTR;
return;
}
std::size_t _bucket = mIndex/bucketSizeC;
std::size_t _index = mIndex%bucketSizeC;
size_t _bucket = mIndex/bucketSizeC;
size_t _index = mIndex%bucketSizeC;
mData = &(mBucketList[_bucket][_index]);
if(DeallocateC) {
@@ -103,8 +104,8 @@ public:
template<typename T2>
DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
//DeallocatingVectorIterator(std::size_t idx, const std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
DeallocatingVectorIterator(size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
//DeallocatingVectorIterator(size_t idx, const std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
template<typename T2>
@@ -184,10 +185,10 @@ public:
}
};
template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT) >
template<typename ElementT, size_t bucketSizeC = 10485760/sizeof(ElementT) >
class DeallocatingVector {
private:
std::size_t mCurrentSize;
size_t mCurrentSize;
std::vector<ElementT *> mBucketList;
public:
@@ -226,21 +227,21 @@ public:
}
inline void push_back(const ElementT & element) {
std::size_t _capacity = capacity();
size_t _capacity = capacity();
if(mCurrentSize == _capacity) {
mBucketList.push_back(new ElementT[bucketSizeC]);
}
std::size_t _index = size()%bucketSizeC;
size_t _index = size()%bucketSizeC;
mBucketList.back()[_index] = element;
++mCurrentSize;
}
inline void reserve(const std::size_t) const {
inline void reserve(const size_t) const {
//don't do anything
}
inline void resize(const std::size_t new_size) {
inline void resize(const size_t new_size) {
if(new_size > mCurrentSize) {
while(capacity() < new_size) {
mBucketList.push_back(new ElementT[bucketSizeC]);
@@ -248,7 +249,7 @@ public:
mCurrentSize = new_size;
}
if(new_size < mCurrentSize) {
std::size_t number_of_necessary_buckets = 1+(new_size / bucketSizeC);
size_t number_of_necessary_buckets = 1+(new_size / bucketSizeC);
for(unsigned i = number_of_necessary_buckets; i < mBucketList.size(); ++i) {
delete[] mBucketList[i];
@@ -258,16 +259,16 @@ public:
}
}
inline std::size_t size() const {
inline size_t size() const {
return mCurrentSize;
}
inline std::size_t capacity() const {
inline size_t capacity() const {
return mBucketList.size() * bucketSizeC;
}
inline iterator begin() {
return iterator(static_cast<std::size_t>(0), mBucketList);
return iterator(static_cast<size_t>(0), mBucketList);
}
inline iterator end() {
@@ -275,7 +276,7 @@ public:
}
inline deallocation_iterator dbegin() {
return deallocation_iterator(static_cast<std::size_t>(0), mBucketList);
return deallocation_iterator(static_cast<size_t>(0), mBucketList);
}
inline deallocation_iterator dend() {
@@ -283,36 +284,24 @@ public:
}
inline const_iterator begin() const {
return const_iterator(static_cast<std::size_t>(0), mBucketList);
return const_iterator(static_cast<size_t>(0), mBucketList);
}
inline const_iterator end() const {
return const_iterator(size(), mBucketList);
}
inline ElementT & operator[](const std::size_t index) {
std::size_t _bucket = index / bucketSizeC;
std::size_t _index = index % bucketSizeC;
inline ElementT & operator[](const size_t index) {
size_t _bucket = index / bucketSizeC;
size_t _index = index % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
const inline ElementT & operator[](const std::size_t index) const {
std::size_t _bucket = index / bucketSizeC;
std::size_t _index = index % bucketSizeC;
const inline ElementT & operator[](const size_t index) const {
size_t _bucket = index / bucketSizeC;
size_t _index = index % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
inline ElementT & back() {
std::size_t _bucket = mCurrentSize / bucketSizeC;
std::size_t _index = mCurrentSize % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
const inline ElementT & back() const {
std::size_t _bucket = mCurrentSize / bucketSizeC;
std::size_t _index = mCurrentSize % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
};
#endif /* DEALLOCATINGVECTOR_H_ */
+47 -39
View File
@@ -21,21 +21,18 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef DYNAMICGRAPH_H_INCLUDED
#define DYNAMICGRAPH_H_INCLUDED
#include "../DataStructures/DeallocatingVector.h"
#include <boost/assert.hpp>
#include <boost/integer.hpp>
#include <vector>
#include <algorithm>
#include <limits>
#include <vector>
#include "../DataStructures/DeallocatingVector.h"
template< typename EdgeDataT>
class DynamicGraph {
public:
typedef EdgeDataT EdgeData;
typedef uint32_t NodeIterator;
typedef uint32_t EdgeIterator;
typedef unsigned NodeIterator;
typedef unsigned EdgeIterator;
class InputEdge {
public:
@@ -50,20 +47,20 @@ class DynamicGraph {
};
//Constructs an empty graph with a given number of nodes.
DynamicGraph( int32_t nodes ) : m_numNodes(nodes), m_numEdges(0) {
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.1 );
m_edges.resize( m_numNodes );
}
template<class ContainerT>
DynamicGraph( const int32_t nodes, const ContainerT &graph ) {
DynamicGraph( const int nodes, const ContainerT &graph )
{
m_numNodes = nodes;
m_numEdges = ( EdgeIterator ) graph.size();
m_nodes.reserve( m_numNodes +1);
m_nodes.resize( m_numNodes +1);
m_nodes.reserve( m_numNodes );
m_nodes.resize( m_numNodes );
EdgeIterator edge = 0;
EdgeIterator position = 0;
for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
@@ -75,7 +72,6 @@ class DynamicGraph {
m_nodes[node].edges = edge - lastEdge;
position += m_nodes[node].edges;
}
m_nodes.back().firstEdge = position;
m_edges.reserve( position * 1.1 );
m_edges.resize( position );
edge = 0;
@@ -83,10 +79,7 @@ class DynamicGraph {
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;
BOOST_ASSERT_MSG(
graph[edge].data.distance > 0,
"edge distance invalid"
);
GUARANTEE(graph[edge].data.distance > 0, "edge: " << edge << "(" << graph[edge].source << "," << graph[edge].target << ")=" << graph[edge].data.distance);
++edge;
}
}
@@ -94,40 +87,50 @@ class DynamicGraph {
~DynamicGraph(){ }
uint32_t GetNumberOfNodes() const {
unsigned GetNumberOfNodes() const
{
return m_numNodes;
}
uint32_t GetNumberOfEdges() const {
unsigned GetNumberOfEdges() const
{
return m_numEdges;
}
uint32_t GetOutDegree( const NodeIterator n ) const {
unsigned GetOutDegree( const NodeIterator &n ) const
{
return m_nodes[n].edges;
}
NodeIterator GetTarget( const EdgeIterator e ) const {
NodeIterator GetTarget( const EdgeIterator &e ) const
{
return NodeIterator( m_edges[e].target );
}
EdgeDataT &GetEdgeData( const EdgeIterator e ) {
EdgeDataT &GetEdgeData( const EdgeIterator &e )
{
return m_edges[e].data;
}
const EdgeDataT &GetEdgeData( const EdgeIterator e ) const {
const EdgeDataT &GetEdgeData( const EdgeIterator &e ) const
{
return m_edges[e].data;
}
EdgeIterator BeginEdges( const NodeIterator n ) const {
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 {
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 ) {
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 ) ) {
@@ -136,7 +139,7 @@ class DynamicGraph {
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
} else {
EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size();
uint32_t newSize = node.edges * 1.1 + 2;
unsigned newSize = node.edges * 1.1 + 2;
EdgeIterator requiredCapacity = newSize + m_edges.size();
EdgeIterator oldCapacity = m_edges.capacity();
if ( requiredCapacity >= oldCapacity ) {
@@ -161,19 +164,20 @@ class DynamicGraph {
}
//removes an edge. Invalidates edge iterators for the source node
void DeleteEdge( const NodeIterator source, const EdgeIterator e ) {
void DeleteEdge( const NodeIterator source, const EdgeIterator &e ) {
Node &node = m_nodes[source];
--m_numEdges;
--node.edges;
const uint32_t last = node.firstEdge + 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)
int32_t DeleteEdgesTo( const NodeIterator source, const NodeIterator target ) {
int32_t deleted = 0;
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 {
@@ -192,9 +196,10 @@ class DynamicGraph {
}
//searches for a specific edge
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
EdgeIterator FindEdge( const NodeIterator &from, const NodeIterator &to ) const
{
for ( EdgeIterator i = BeginEdges( from ), iend = EndEdges( from ); i != iend; ++i ) {
if ( to == m_edges[i].target ) {
if ( m_edges[i].target == to ) {
return i;
}
}
@@ -203,11 +208,13 @@ class DynamicGraph {
protected:
bool isDummy( const EdgeIterator edge ) const {
bool isDummy( EdgeIterator edge ) const
{
return m_edges[edge].target == (std::numeric_limits< NodeIterator >::max)();
}
void makeDummy( const EdgeIterator edge ) {
void makeDummy( EdgeIterator edge )
{
m_edges[edge].target = (std::numeric_limits< NodeIterator >::max)();
}
@@ -215,7 +222,7 @@ class DynamicGraph {
//index of the first edge
EdgeIterator firstEdge;
//amount of edges
uint32_t edges;
unsigned edges;
};
struct Edge {
@@ -226,8 +233,9 @@ class DynamicGraph {
NodeIterator m_numNodes;
EdgeIterator m_numEdges;
std::vector< Node > m_nodes;
DeallocatingVector< Edge > m_edges;
DeallocatingVector< Node > m_nodes;
DeallocatingVector< Edge > m_edges;
};
#endif // DYNAMICGRAPH_H_INCLUDED
+82
View File
@@ -0,0 +1,82 @@
/*
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_
#include "Coordinate.h"
struct _GridEdge {
_GridEdge(NodeID n, NodeID na, int w, _Coordinate sc, _Coordinate tc, bool bttc) : edgeBasedNode(n), nameID(na), weight(w), startCoord(sc), targetCoord(tc), belongsToTinyComponent(bttc) {}
_GridEdge() : edgeBasedNode(UINT_MAX), nameID(UINT_MAX), weight(INT_MAX), belongsToTinyComponent(false) {}
NodeID edgeBasedNode;
NodeID nameID;
int weight;
_Coordinate startCoord;
_Coordinate targetCoord;
bool belongsToTinyComponent;
bool operator< ( const _GridEdge& right) const {
return edgeBasedNode < right.edgeBasedNode;
}
bool operator== ( const _GridEdge& right) const {
return edgeBasedNode == right.edgeBasedNode;
}
};
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_ */
+37 -16
View File
@@ -24,35 +24,56 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef HASHTABLE_H_
#define HASHTABLE_H_
#include <boost/ref.hpp>
#include <boost/unordered_map.hpp>
template<typename keyT, typename valueT>
class HashTable : public boost::unordered_map<keyT, valueT> {
private:
typedef boost::unordered_map<keyT, valueT> super;
class HashTable {
typedef boost::unordered_map<keyT, valueT> MyHashTable;
public:
HashTable() : super() { }
HashTable(const unsigned size) : super(size) { }
inline void Add(const keyT& key, const valueT& value){
super::insert(std::make_pair(key, value));
typedef typename boost::unordered_map<keyT, valueT>::const_iterator MyIterator;
typedef MyIterator iterator;
HashTable() { }
HashTable(const unsigned size) {
table.resize(size);
}
inline void Add(const keyT& key, const valueT& value){
table[key] = value;
}
inline void Set(const keyT& key, const valueT& value){
table[key] = value;
}
inline valueT Find(const keyT& key) const {
if(super::find(key) == super::end()) {
if(table.find(key) == table.end())
return valueT();
}
return boost::ref(super::find(key)->second);
return table.find(key)->second;
}
inline bool Holds(const keyT& key) const {
if(super::find(key) == super::end()) {
if(table.find(key) == table.end())
return false;
}
return true;
}
void EraseAll() {
if(table.size() > 0)
table.clear();
}
inline valueT operator[] (keyT key) const {
if(table.find(key) == table.end())
return valueT();
return table.find(key)->second;
}
inline unsigned Size() const {
return table.size();
}
MyIterator begin() const {
return table.begin();
}
MyIterator end() const {
return table.end();
}
private:
MyHashTable table;
};
#endif /* HASHTABLE_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 HILBERTVALUE_H_
#define HILBERTVALUE_H_
#include "Coordinate.h"
#include <boost/integer.hpp>
#include <boost/noncopyable.hpp>
// computes a 64 bit value that corresponds to the hilbert space filling curve
class HilbertCode : boost::noncopyable {
public:
static uint64_t GetHilbertNumberForCoordinate(
const FixedPointCoordinate & current_coordinate
) {
unsigned location[2];
location[0] = current_coordinate.lat+( 90*COORDINATE_PRECISION);
location[1] = current_coordinate.lon+(180*COORDINATE_PRECISION);
TransposeCoordinate(location);
const uint64_t result = BitInterleaving(location[0], location[1]);
return result;
}
private:
static inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) {
uint64_t result = 0;
for(int8_t index = 31; index >= 0; --index){
result |= (a >> index) & 1;
result <<= 1;
result |= (b >> index) & 1;
if(0 != index){
result <<= 1;
}
}
return result;
}
static inline void TransposeCoordinate( uint32_t * X) {
uint32_t M = 1 << (32-1), P, Q, t;
int i;
// Inverse undo
for( Q = M; Q > 1; Q >>= 1 ) {
P=Q-1;
for( i = 0; i < 2; ++i ) {
if( X[i] & Q ) {
X[0] ^= P; // invert
} else {
t = (X[0]^X[i]) & P;
X[0] ^= t;
X[i] ^= t;
}
} // exchange
}
// Gray encode
for( i = 1; i < 2; ++i ) {
X[i] ^= X[i-1];
}
t=0;
for( Q = M; Q > 1; Q >>= 1 ) {
if( X[2-1] & Q ) {
t ^= Q-1;
}
} //check if this for loop is wrong
for( i = 0; i < 2; ++i ) {
X[i] ^= t;
}
}
};
#endif /* HILBERTVALUE_H_ */
+39 -74
View File
@@ -16,13 +16,11 @@ 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 "../Util/OSRMException.h"
#include <cassert>
class NodeBasedEdge {
@@ -42,34 +40,12 @@ public:
return (source() < e.source());
}
explicit NodeBasedEdge(
NodeID s,
NodeID t,
NodeID n,
EdgeWeight w,
bool f,
bool b,
short ty,
bool ra,
bool ig,
bool ar,
bool cf
) : _source(s),
_target(t),
_name(n),
_weight(w),
forward(f),
backward(b),
_type(ty),
_roundabout(ra),
_ignoreInGrid(ig),
_accessRestricted(ar),
_contraFlow(cf)
{
if(ty < 0) {
throw OSRMException("negative edge type");
}
}
/** 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), _ignoreInGrid(false), _accessRestricted(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, bool ig, bool ar) :
_source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar) { if(ty < 0) {ERR("Type: " << ty);}; }
NodeID target() const {return _target; }
NodeID source() const {return _source; }
@@ -83,7 +59,6 @@ public:
bool isRoundabout() const { return _roundabout; }
bool ignoreInGrid() const { return _ignoreInGrid; }
bool isAccessRestricted() const { return _accessRestricted; }
bool isContraFlow() const { return _contraFlow; }
NodeID _source;
NodeID _target;
@@ -95,13 +70,6 @@ public:
bool _roundabout;
bool _ignoreInGrid;
bool _accessRestricted;
bool _contraFlow;
private:
/** 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), _ignoreInGrid(false), _accessRestricted(false), _contraFlow(false) { assert(false); } //shall not be used.
};
class EdgeBasedEdge {
@@ -123,46 +91,43 @@ public:
template<class EdgeT>
EdgeBasedEdge(const EdgeT & myEdge ) :
m_source(myEdge.source),
m_target(myEdge.target),
m_edgeID(myEdge.data.via),
m_weight(myEdge.data.distance),
m_forward(myEdge.data.forward),
m_backward(myEdge.data.backward)
{ }
_source(myEdge.source),
_target(myEdge.target),
_edgeID(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() :
m_source(0),
m_target(0),
m_edgeID(0),
m_weight(0),
m_forward(false),
m_backward(false)
{ }
_source(0), _target(0), _edgeID(0), _weight(0), _forward(false), _backward(false) { }
explicit EdgeBasedEdge(const NodeID s, const NodeID t, const NodeID v, const EdgeWeight w, const bool f, const bool b) :
m_source(s),
m_target(t),
m_edgeID(v),
m_weight(w),
m_forward(f),
m_backward(b)
{}
explicit EdgeBasedEdge(NodeID s, NodeID t, NodeID v, EdgeWeight w, bool f, bool b) :
_source(s), _target(t), _edgeID(v), _weight(w), _forward(f), _backward(b){}
NodeID target() const {return m_target; }
NodeID source() const {return m_source; }
EdgeWeight weight() const {return m_weight; }
NodeID id() const { return m_edgeID; }
bool isBackward() const { return m_backward; }
bool isForward() const { return m_forward; }
private:
NodeID m_source;
NodeID m_target;
NodeID m_edgeID;
EdgeWeight m_weight:30;
bool m_forward:1;
bool m_backward:1;
NodeID target() const {return _target; }
NodeID source() const {return _source; }
EdgeWeight weight() const {return _weight; }
NodeID id() const { return _edgeID; }
bool isBackward() const { return _backward; }
bool isForward() const { return _forward; }
NodeID _source;
NodeID _target;
NodeID _edgeID;
EdgeWeight _weight:30;
bool _forward:1;
bool _backward:1;
};
struct MinimalEdgeData {
public:
EdgeWeight distance;
bool forward;
bool backward;
};
typedef NodeBasedEdge ImportEdge;
+3 -3
View File
@@ -21,7 +21,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef IMPORTNODE_H_
#define IMPORTNODE_H_
#include "QueryNode.h"
#include "NodeCoords.h"
#include "../DataStructures/HashTable.h"
@@ -44,9 +44,9 @@ struct _Node : NodeInfo{
struct ImportNode : public _Node {
HashTable<std::string, std::string> keyVals;
inline void Clear() {
keyVals.clear();
keyVals.EraseAll();
lat = 0; lon = 0; id = 0; bollard = false; trafficLight = false;
}
};
+5 -5
View File
@@ -43,21 +43,21 @@ int readFromBz2Stream( void* pointer, char* buffer, int len ) {
return read;
} else if(BZ_STREAM_END == context->error) {
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadGetUnused" <<std::endl; exit(-1);};
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) {std::cerr << "Could not BZ2_bzReadClose" <<std::endl; exit(-1);};
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){std::cerr << "Could not open file" <<std::endl; exit(-1);};
if(NULL == context->bz2){ cerr << "Could not open file" << endl; exit(-1);};
}
} else { std::cerr << "Could not read bz2 file" << std::endl; exit(-1); }
} else { cerr << "Could not read bz2 file" << endl; exit(-1); }
}
return read;
}
@@ -74,7 +74,7 @@ xmlTextReaderPtr inputReaderFactory( const char* name )
{
std::string inputName(name);
if(inputName.find(".osm.bz2")!=std::string::npos)
if(inputName.find(".osm.bz2")!=string::npos)
{
BZ2Context* context = new BZ2Context();
context->error = false;
+594
View File
@@ -0,0 +1,594 @@
/*
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 <cfloat>
#include <cmath>
#include <fstream>
#include <limits>
#include <vector>
#ifndef ROUTED
#include <stxxl.h>
#endif
#ifdef _WIN32
#include <math.h>
#endif
#include <boost/thread.hpp>
#include <boost/foreach.hpp>
#include <boost/unordered_map.hpp>
#include "DeallocatingVector.h"
//#include "ExtractorStructs.h"
#include "GridEdge.h"
#include "Percent.h"
#include "PhantomNodes.h"
#include "Util.h"
#include "StaticGraph.h"
#include "../Algorithms/Bresenham.h"
namespace NNGrid{
static boost::thread_specific_ptr<std::ifstream> localStream;
template<bool WriteAccess = false>
class NNGrid {
public:
NNGrid() /*: cellCache(500), fileCache(500)*/ {
ramIndexTable.resize((1024*1024), ULONG_MAX);
}
NNGrid(const char* rif, const char* _i) {
if(WriteAccess) {
ERR("Not available in Write mode");
}
iif = std::string(_i);
ramIndexTable.resize((1024*1024), ULONG_MAX);
ramInFile.open(rif, std::ios::in | std::ios::binary);
if(!ramInFile) { ERR(rif << " not found"); }
}
~NNGrid() {
if(ramInFile.is_open()) ramInFile.close();
#ifndef ROUTED
if (WriteAccess) {
entries.clear();
}
#endif
if(localStream.get() && localStream->is_open()) {
localStream->close();
}
}
void OpenIndexFiles() {
assert(ramInFile.is_open());
ramInFile.read(static_cast<char*>(static_cast<void*>(&ramIndexTable[0]) ), sizeof(unsigned long)*1024*1024);
ramInFile.close();
}
#ifndef ROUTED
template<typename EdgeT>
inline void ConstructGrid(DeallocatingVector<EdgeT> & edgeList, char * ramIndexOut, char * fileIndexOut) {
//TODO: Implement this using STXXL-Streams
Percent p(edgeList.size());
BOOST_FOREACH(EdgeT & edge, edgeList) {
p.printIncrement();
if(edge.ignoreInGrid)
continue;
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), edge.belongsToTinyComponent ) );
}
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);
//sort entries
stxxl::sort(entries.begin(), entries.end(), CompareGridEdgeDataByRamIndex(), 1024*1024*1024);
INFO("finished sorting after " << (get_timestamp() - timestamp) << "s");
std::vector<GridEntry> entriesInFileWithRAMSameIndex;
unsigned indexInRamTable = entries.begin()->ramIndex;
unsigned long lastPositionInIndexFile = 0;
cout << "writing data ..." << flush;
p.reinit(entries.size());
boost::unordered_map< unsigned, unsigned > cellMap(1024);
BOOST_FOREACH(GridEntry & gridEntry, entries) {
p.printIncrement();
if(gridEntry.ramIndex != indexInRamTable) {
cellMap.clear();
BuildCellIndexToFileIndexMap(indexInRamTable, cellMap);
unsigned numberOfBytesInCell = FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile, cellMap);
ramIndexTable[indexInRamTable] = lastPositionInIndexFile;
lastPositionInIndexFile += numberOfBytesInCell;
entriesInFileWithRAMSameIndex.clear();
indexInRamTable = gridEntry.ramIndex;
}
entriesInFileWithRAMSameIndex.push_back(gridEntry);
}
cellMap.clear();
BuildCellIndexToFileIndexMap(indexInRamTable, cellMap);
/*unsigned numberOfBytesInCell = */FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile, cellMap);
ramIndexTable[indexInRamTable] = lastPositionInIndexFile;
entriesInFileWithRAMSameIndex.clear();
std::vector<GridEntry>().swap(entriesInFileWithRAMSameIndex);
assert(entriesInFileWithRAMSameIndex.size() == 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
ramFile.write((char *)&ramIndexTable[0], sizeof(unsigned long)*1024*1024 );
//close ram index file
ramFile.close();
}
#endif
inline bool CoordinatesAreEquivalent(const _Coordinate & a, const _Coordinate & b, const _Coordinate & c, const _Coordinate & d) const {
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
}
bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode, const unsigned zoomLevel) {
bool ignoreTinyComponents = (zoomLevel <= 14);
// INFO("Coordinate: " << location << ", zoomLevel: " << zoomLevel << ", ignoring tinyComponentents: " << (ignoreTinyComponents ? "yes" : "no"));
// double time1 = get_timestamp();
bool foundNode = false;
const _Coordinate startCoord(100000*(lat2y(static_cast<double>(location.lat)/100000.)), location.lon);
/** search for point on edge close to source */
const unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
std::vector<_GridEdge> candidates;
const int lowerBoundForLoop = (fileIndex < 32768 ? 0 : -32768);
for(int j = lowerBoundForLoop; (j < (32768+1)) && (fileIndex != UINT_MAX); j+=32768) {
for(int i = -1; i < 2; ++i){
// unsigned oldSize = candidates.size();
GetContentsOfFileBucketEnumerated(fileIndex+i+j, candidates);
// INFO("Getting fileIndex=" << fileIndex+i+j << " with " << candidates.size() - oldSize << " candidates");
}
}
// INFO("looked up " << candidates.size());
_GridEdge smallestEdge;
_Coordinate tmp, edgeStartCoord, edgeEndCoord;
double dist = numeric_limits<double>::max();
double r, tmpDist;
BOOST_FOREACH(_GridEdge candidate, candidates) {
if(candidate.belongsToTinyComponent && ignoreTinyComponents)
continue;
r = 0.;
tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
// INFO("dist " << startCoord << "->[" << candidate.startCoord << "-" << candidate.targetCoord << "]=" << tmpDist );
// INFO("Looking at edge " << candidate.edgeBasedNode << " at distance " << tmpDist);
if(tmpDist < dist && !DoubleEpsilonCompare(dist, tmpDist)) {
// INFO("a) " << candidate.edgeBasedNode << ", dist: " << tmpDist << ", tinyCC: " << (candidate.belongsToTinyComponent ? "yes" : "no"));
dist = tmpDist;
resultNode.edgeBasedNode = candidate.edgeBasedNode;
resultNode.nodeBasedEdgeNameID = candidate.nameID;
resultNode.weight1 = candidate.weight;
resultNode.weight2 = INT_MAX;
resultNode.location.lat = tmp.lat;
resultNode.location.lon = tmp.lon;
edgeStartCoord = candidate.startCoord;
edgeEndCoord = candidate.targetCoord;
foundNode = true;
smallestEdge = candidate;
//} else if(tmpDist < dist) {
//INFO("a) ignored " << candidate.edgeBasedNode << " at distance " << std::fabs(dist - tmpDist));
} else if(DoubleEpsilonCompare(dist, tmpDist) && 1 == std::abs(static_cast<int>(candidate.edgeBasedNode)-static_cast<int>(resultNode.edgeBasedNode) ) && CoordinatesAreEquivalent(edgeStartCoord, candidate.startCoord, edgeEndCoord, candidate.targetCoord)) {
resultNode.edgeBasedNode = std::min(candidate.edgeBasedNode, resultNode.edgeBasedNode);
resultNode.weight2 = candidate.weight;
//INFO("b) " << candidate.edgeBasedNode << ", dist: " << tmpDist);
}
}
// INFO("startcoord: " << smallestEdge.startCoord << ", tgtcoord" << smallestEdge.targetCoord << "result: " << newEndpoint);
// INFO("length of old edge: " << ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord));
// INFO("Length of new edge: " << ApproximateDistance(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"));
// }
// INFO("startCoord: " << smallestEdge.startCoord << "; targetCoord: " << smallestEdge.targetCoord << "; newEndpoint: " << resultNode.location);
double ratio = (foundNode ? std::min(1., ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord)) : 0);
resultNode.location.lat = round(100000.*(y2lat(static_cast<double>(resultNode.location.lat)/100000.)));
// INFO("Length of vector: " << ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord));
//Hack to fix rounding errors and wandering via nodes.
if(std::abs(location.lon - resultNode.location.lon) == 1)
resultNode.location.lon = location.lon;
if(std::abs(location.lat - resultNode.location.lat) == 1)
resultNode.location.lat = location.lat;
resultNode.weight1 *= ratio;
if(INT_MAX != resultNode.weight2) {
resultNode.weight2 -= resultNode.weight1;
}
resultNode.ratio = ratio;
// INFO("New weight1: " << resultNode.weight1 << ", new weight2: " << resultNode.weight2 << ", ratio: " << ratio);
// INFO("start: " << edgeStartCoord << ", end: " << edgeEndCoord);
// INFO("selected node: " << resultNode.edgeBasedNode << ", bidirected: " << (resultNode.isBidirected() ? "yes" : "no") << "\n--");
// double time2 = get_timestamp();
// INFO("NN-Lookup in " << 1000*(time2-time1) << "ms");
return foundNode;
}
bool FindRoutingStarts(const _Coordinate& start, const _Coordinate& target, PhantomNodes & routingStarts, unsigned zoomLevel) {
routingStarts.Reset();
return (FindPhantomNodeForCoordinate( start, routingStarts.startPhantom, zoomLevel) &&
FindPhantomNodeForCoordinate( target, routingStarts.targetPhantom, zoomLevel) );
}
bool FindNearestCoordinateOnEdgeInNodeBasedGraph(const _Coordinate& inputCoordinate, _Coordinate& outputCoordinate, unsigned zoomLevel = 18) {
PhantomNode resultNode;
bool foundNode = FindPhantomNodeForCoordinate(inputCoordinate, resultNode, zoomLevel);
outputCoordinate = resultNode.location;
return foundNode;
}
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;
boost::unordered_map< unsigned, unsigned > cellMap;
for(int j = -32768; j < (32768+1); j+=32768) {
for(int i = -1; i < 2; ++i) {
GetContentsOfFileBucket(fileIndex+i+j, candidates, cellMap);
}
}
_Coordinate tmp;
double dist = (std::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 unsigned GetCellIndexFromRAMAndFileIndex(const unsigned ramIndex, const unsigned fileIndex) const {
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) {
const unsigned localFileIndex = lineBase + i * 32768 + columnBase + j;
if(localFileIndex == fileIndex) {
unsigned cellIndex = i * 32 + j;
return cellIndex;
}
}
}
return UINT_MAX;
}
inline void BuildCellIndexToFileIndexMap(const unsigned ramIndex, boost::unordered_map<unsigned, unsigned >& cellMap){
unsigned lineBase = ramIndex/1024;
lineBase = lineBase*32*32768;
unsigned columnBase = ramIndex%1024;
columnBase=columnBase*32;
std::vector<std::pair<unsigned, unsigned> >insertionVector(1024);
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;
insertionVector[i * 32 + j] = std::make_pair(fileIndex, cellIndex);
}
}
cellMap.insert(insertionVector.begin(), insertionVector.end());
}
inline bool DoubleEpsilonCompare(const double d1, const double d2) {
return (std::fabs(d1 - d2) < FLT_EPSILON);
}
inline unsigned FillCell(std::vector<GridEntry>& entriesWithSameRAMIndex, const unsigned long fileOffset, boost::unordered_map< unsigned, unsigned > & cellMap ) {
std::vector<char> tmpBuffer(32*32*4096,0);
unsigned long indexIntoTmpBuffer = 0;
unsigned numberOfWrittenBytes = 0;
assert(indexOutFile.is_open());
std::vector<unsigned long> cellIndex(32*32,ULONG_MAX);
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());
// entriesWithSameRAMIndex.erase(std::unique(entriesWithSameRAMIndex.begin(), entriesWithSameRAMIndex.end()), entriesWithSameRAMIndex.end());
//traverse each file bucket and write its contents to disk
std::vector<GridEntry> entriesWithSameFileIndex;
unsigned fileIndex = entriesWithSameRAMIndex.begin()->fileIndex;
BOOST_FOREACH(GridEntry & gridEntry, entriesWithSameRAMIndex) {
assert(cellMap.find(gridEntry.fileIndex) != cellMap.end() ); //asserting that file index belongs to cell index
if(gridEntry.fileIndex != fileIndex) {
// start in cellIndex vermerken
int localFileIndex = entriesWithSameFileIndex.begin()->fileIndex;
int localCellIndex = cellMap.find(localFileIndex)->second;
assert(cellMap.find(entriesWithSameFileIndex.begin()->fileIndex) != cellMap.end());
cellIndex[localCellIndex] = indexIntoTmpBuffer + fileOffset;
indexIntoTmpBuffer += FlushEntriesWithSameFileIndexToBuffer(entriesWithSameFileIndex, tmpBuffer, indexIntoTmpBuffer);
fileIndex = gridEntry.fileIndex;
}
entriesWithSameFileIndex.push_back(gridEntry);
}
assert(cellMap.find(entriesWithSameFileIndex.begin()->fileIndex) != cellMap.end());
int localFileIndex = entriesWithSameFileIndex.begin()->fileIndex;
int localCellIndex = cellMap.find(localFileIndex)->second;
cellIndex[localCellIndex] = indexIntoTmpBuffer + fileOffset;
indexIntoTmpBuffer += FlushEntriesWithSameFileIndexToBuffer(entriesWithSameFileIndex, tmpBuffer, indexIntoTmpBuffer);
assert(entriesWithSameFileIndex.size() == 0);
indexOutFile.write(static_cast<char*>(static_cast<void*>(&cellIndex[0])),32*32*sizeof(unsigned long));
numberOfWrittenBytes += 32*32*sizeof(unsigned long);
//write contents of tmpbuffer to disk
indexOutFile.write(&tmpBuffer[0], indexIntoTmpBuffer*sizeof(char));
numberOfWrittenBytes += indexIntoTmpBuffer*sizeof(char);
return numberOfWrittenBytes;
}
inline unsigned FlushEntriesWithSameFileIndexToBuffer( std::vector<GridEntry> &vectorWithSameFileIndex, std::vector<char> & tmpBuffer, const unsigned long index) const {
sort( vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end() );
vectorWithSameFileIndex.erase(unique(vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end()), vectorWithSameFileIndex.end());
const unsigned lengthOfBucket = vectorWithSameFileIndex.size();
tmpBuffer.resize(tmpBuffer.size()+(sizeof(_GridEdge)*lengthOfBucket) + sizeof(unsigned) );
unsigned counter = 0;
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 );
}
//write length of bucket
memcpy((char*)&(tmpBuffer[index+counter]), (char*)&lengthOfBucket, sizeof(lengthOfBucket));
counter += sizeof(lengthOfBucket);
BOOST_FOREACH(const GridEntry & entry, vectorWithSameFileIndex) {
char * data = (char*)&(entry.edge);
memcpy(static_cast<char*>(static_cast<void*>(&(tmpBuffer[index+counter]) )), data, sizeof(entry.edge));
counter += sizeof(entry.edge);
}
//Freeing data
vectorWithSameFileIndex.clear();
return counter;
}
inline void GetContentsOfFileBucketEnumerated(const unsigned fileIndex, std::vector<_GridEdge>& result) const {
unsigned ramIndex = GetRAMIndexFromFileIndex(fileIndex);
unsigned long startIndexInFile = ramIndexTable[ramIndex];
if(startIndexInFile == ULONG_MAX) {
return;
}
unsigned enumeratedIndex = GetCellIndexFromRAMAndFileIndex(ramIndex, fileIndex);
if(!localStream.get() || !localStream->is_open()) {
localStream.reset(new std::ifstream(iif.c_str(), std::ios::in | std::ios::binary));
}
if(!localStream->good()) {
localStream->clear(std::ios::goodbit);
DEBUG("Resetting stale filestream");
}
//only read the single necessary cell index
localStream->seekg(startIndexInFile+(enumeratedIndex*sizeof(unsigned long)));
unsigned long fetchedIndex = 0;
localStream->read(static_cast<char*>( static_cast<void*>(&fetchedIndex)), sizeof(unsigned long));
if(fetchedIndex == ULONG_MAX) {
return;
}
const unsigned long position = fetchedIndex + 32*32*sizeof(unsigned long) ;
unsigned lengthOfBucket;
unsigned currentSizeOfResult = result.size();
localStream->seekg(position);
localStream->read(static_cast<char*>( static_cast<void*>(&(lengthOfBucket))), sizeof(unsigned));
result.resize(currentSizeOfResult+lengthOfBucket);
localStream->read(static_cast<char*>( static_cast<void*>(&result[currentSizeOfResult])), lengthOfBucket*sizeof(_GridEdge));
}
inline void GetContentsOfFileBucket(const unsigned fileIndex, std::vector<_GridEdge>& result, boost::unordered_map< unsigned, unsigned> & cellMap) {
unsigned ramIndex = GetRAMIndexFromFileIndex(fileIndex);
unsigned long startIndexInFile = ramIndexTable[ramIndex];
if(startIndexInFile == ULONG_MAX) {
return;
}
unsigned long cellIndex[32*32];
cellMap.clear();
BuildCellIndexToFileIndexMap(ramIndex, cellMap);
if(!localStream.get() || !localStream->is_open()) {
localStream.reset(new std::ifstream(iif.c_str(), std::ios::in | std::ios::binary));
}
if(!localStream->good()) {
localStream->clear(std::ios::goodbit);
DEBUG("Resetting stale filestream");
}
localStream->seekg(startIndexInFile);
localStream->read(static_cast<char*>(static_cast<void*>( cellIndex)), 32*32*sizeof(unsigned long));
assert(cellMap.find(fileIndex) != cellMap.end());
if(cellIndex[cellMap[fileIndex]] == ULONG_MAX) {
return;
}
const unsigned long position = cellIndex[cellMap[fileIndex]] + 32*32*sizeof(unsigned long) ;
unsigned lengthOfBucket;
unsigned currentSizeOfResult = result.size();
localStream->seekg(position);
localStream->read(static_cast<char*>(static_cast<void*>(&(lengthOfBucket))), sizeof(unsigned));
result.resize(currentSizeOfResult+lengthOfBucket);
localStream->read(static_cast<char*>(static_cast<void*>(&result[currentSizeOfResult])), lengthOfBucket*sizeof(_GridEdge));
}
#ifndef ROUTED
inline void AddEdge(const _GridEdge & edge) {
std::vector<BresenhamPixel> 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));
}
}
#endif
inline double ComputeDistance(const _Coordinate& inputPoint, const _Coordinate& source, const _Coordinate& target, _Coordinate& nearest, double *r) {
// INFO("comparing point " << inputPoint << " to edge [" << source << "-" << target << "]");
const double x = static_cast<double>(inputPoint.lat);
const double y = static_cast<double>(inputPoint.lon);
const double a = static_cast<double>(source.lat);
const double b = static_cast<double>(source.lon);
const double c = static_cast<double>(target.lat);
const double d = static_cast<double>(target.lon);
double p,q,mX,nY;
// INFO("x=" << x << ", y=" << y << ", a=" << a << ", b=" << b << ", c=" << c << ", d=" << d);
if(fabs(a-c) > FLT_EPSILON){
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
// INFO("p=" << p << ", q=" << q << ", nY=" << nY << ", mX=" << mX);
if(std::isnan(mX)) {
*r = (target == inputPoint) ? 1. : 0.;
} else {
*r = mX;
}
// INFO("r=" << *r);
if(*r<=0.){
nearest.lat = source.lat;
nearest.lon = source.lon;
// INFO("a returning distance " << ((b - y)*(b - y) + (a - x)*(a - x)))
return ((b - y)*(b - y) + (a - x)*(a - x));
}
else if(*r >= 1.){
nearest.lat = target.lat;
nearest.lon = target.lon;
// INFO("b returning distance " << ((d - y)*(d - y) + (c - x)*(c - x)))
return ((d - y)*(d - y) + (c - x)*(c - x));
}
// point lies in between
nearest.lat = p;
nearest.lon = q;
// INFO("c returning distance " << (p-x)*(p-x) + (q-y)*(q-y))
return (p-x)*(p-x) + (q-y)*(q-y);
}
inline void GetListOfIndexesForEdgeAndGridSize(const _Coordinate& start, const _Coordinate& target, std::vector<BresenhamPixel> &indexList) const {
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;
Bresenham(x1*32768, y1*32768, x2*32768, y2*32768, indexList);
BOOST_FOREACH(BresenhamPixel & pixel, indexList) {
int fileIndex = (pixel.second-1)*32768 + pixel.first;
int ramIndex = GetRAMIndexFromFileIndex(fileIndex);
pixel.first = fileIndex;
pixel.second = ramIndex;
}
}
inline 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;
if( x>1.0 || x < 0.)
return UINT_MAX;
if( y>1.0 || y < 0.)
return UINT_MAX;
unsigned line = (32768 * (32768-1))*y;
line = line - (line % 32768);
assert(line % 32768 == 0);
unsigned column = 32768.*x;
unsigned fileIndex = line+column;
return fileIndex;
}
inline unsigned GetRAMIndexFromFileIndex(const int fileIndex) const {
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;
}
const static unsigned long END_OF_BUCKET_DELIMITER = UINT_MAX;
std::ofstream indexOutFile;
std::ifstream ramInFile;
#ifndef ROUTED
stxxl::vector<GridEntry> entries;
#endif
std::vector<unsigned long> ramIndexTable; //8 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_ */
@@ -21,43 +21,32 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef _NODE_COORDS_H
#define _NODE_COORDS_H
#include "Coordinate.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <cassert>
#include <cstddef>
#include <climits>
#include <limits>
struct NodeInfo {
typedef NodeID key_type; //type of NodeID
#include "../typedefs.h"
template<typename NodeT>
struct NodeCoords {
typedef unsigned key_type; //type of NodeID
typedef int value_type; //type of lat,lons
NodeInfo(int _lat, int _lon, NodeID _id) : lat(_lat), lon(_lon), id(_id) {}
NodeInfo() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {}
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;
NodeID id;
NodeT id;
static NodeInfo min_value() {
return NodeInfo(
-90*COORDINATE_PRECISION,
-180*COORDINATE_PRECISION,
std::numeric_limits<NodeID>::min()
);
static NodeCoords<NodeT> min_value() {
return NodeCoords<NodeT>(-90*100000,-180*100000,std::numeric_limits<NodeT>::min());
}
static NodeCoords<NodeT> max_value() {
return NodeCoords<NodeT>(90*100000, 180*100000, std::numeric_limits<NodeT>::max());
}
static NodeInfo max_value() {
return NodeInfo(
90*COORDINATE_PRECISION,
180*COORDINATE_PRECISION,
std::numeric_limits<NodeID>::max()
);
}
value_type operator[](const std::size_t n) const {
value_type operator[](std::size_t n) const {
switch(n) {
case 1:
return lat;
@@ -66,13 +55,15 @@ struct NodeInfo {
return lon;
break;
default:
BOOST_ASSERT_MSG(false, "should not happen");
assert(false);
return UINT_MAX;
break;
}
BOOST_ASSERT_MSG(false, "should not happen");
assert(false);
return UINT_MAX;
}
};
typedef NodeCoords<NodeID> NodeInfo;
#endif //_NODE_COORDS_H
+64 -144
View File
@@ -21,184 +21,104 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef NODEINFORMATIONHELPDESK_H_
#define NODEINFORMATIONHELPDESK_H_
#include "QueryNode.h"
#include "PhantomNodes.h"
#include "StaticRTree.h"
#include "../Contractor/EdgeBasedGraphFactory.h"
#include "../Util/OSRMException.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/noncopyable.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
typedef EdgeBasedGraphFactory::EdgeBasedNode RTreeLeaf;
#include "../typedefs.h"
#include "../DataStructures/QueryEdge.h"
#include "NNGrid.h"
#include "PhantomNodes.h"
#include "NodeCoords.h"
class NodeInformationHelpDesk : boost::noncopyable {
class NodeInformationHelpDesk{
public:
NodeInformationHelpDesk(
const std::string & ramIndexInput,
const std::string & fileIndexInput,
const std::string & nodes_filename,
const std::string & edges_filename,
const unsigned number_of_nodes,
const unsigned check_sum
) : number_of_nodes(number_of_nodes), check_sum(check_sum)
{
if ( ramIndexInput.empty() ) {
throw OSRMException("no ram index file name in server ini");
}
if ( fileIndexInput.empty() ) {
throw OSRMException("no mem index file name in server ini");
}
if ( nodes_filename.empty() ) {
throw OSRMException("no nodes file name in server ini");
}
if ( edges_filename.empty() ) {
throw OSRMException("no edges file name in server ini");
}
read_only_rtree = new StaticRTree<RTreeLeaf>(
ramIndexInput,
fileIndexInput
);
BOOST_ASSERT_MSG(
0 == coordinateVector.size(),
"Coordinate vector not empty"
);
LoadNodesAndEdges(nodes_filename, edges_filename);
NodeInformationHelpDesk(const char* ramIndexInput, const char* fileIndexInput, const unsigned _numberOfNodes, const unsigned crc) : numberOfNodes(_numberOfNodes), checkSum(crc) {
readOnlyGrid = new ReadOnlyGrid(ramIndexInput,fileIndexInput);
assert(0 == coordinateVector.size());
}
//Todo: Shared memory mechanism
// NodeInformationHelpDesk(const char* ramIndexInput, const char* fileIndexInput, const unsigned crc) : checkSum(crc) {
// readOnlyGrid = new ReadOnlyGrid(ramIndexInput,fileIndexInput);
// }
~NodeInformationHelpDesk() {
delete read_only_rtree;
delete readOnlyGrid;
}
void initNNGrid(std::ifstream& nodesInstream, std::ifstream& edgesInStream) {
DEBUG("Loading node data");
NodeInfo b;
while(!nodesInstream.eof()) {
nodesInstream.read((char *)&b, sizeof(NodeInfo));
coordinateVector.push_back(_Coordinate(b.lat, b.lon));
}
std::vector<_Coordinate>(coordinateVector).swap(coordinateVector);
nodesInstream.close();
DEBUG("Loading edge data");
unsigned numberOfOrigEdges(0);
edgesInStream.read((char*)&numberOfOrigEdges, sizeof(unsigned));
origEdgeData.resize(numberOfOrigEdges);
edgesInStream.read((char*)&(origEdgeData[0]), numberOfOrigEdges*sizeof(OriginalEdgeData));
edgesInStream.close();
DEBUG("Loaded " << numberOfOrigEdges << " orig edges");
DEBUG("Opening NN indices");
readOnlyGrid->OpenIndexFiles();
}
void initNNGrid() {
readOnlyGrid->OpenIndexFiles();
}
inline int getLatitudeOfNode(const unsigned id) const {
const NodeID node = origEdgeData_viaNode.at(id);
const NodeID node = origEdgeData.at(id).viaNode;
return coordinateVector.at(node).lat;
}
inline int getLongitudeOfNode(const unsigned id) const {
const NodeID node = origEdgeData_viaNode.at(id);
const NodeID node = origEdgeData.at(id).viaNode;
return coordinateVector.at(node).lon;
}
inline unsigned getNameIndexFromEdgeID(const unsigned id) const {
return origEdgeData_nameID.at(id);
return origEdgeData.at(id).nameID;
}
inline TurnInstruction getTurnInstructionFromEdgeID(const unsigned id) const {
return origEdgeData_turnInstruction.at(id);
return origEdgeData.at(id).turnInstruction;
}
inline NodeID getNumberOfNodes() const {
return number_of_nodes;
}
inline NodeID getNumberOfNodes() const { return numberOfNodes; }
inline NodeID getNumberOfNodes2() const { return coordinateVector.size(); }
inline NodeID getNumberOfNodes2() const {
return coordinateVector.size();
}
inline bool FindNearestNodeCoordForLatLon(const _Coordinate& coord, _Coordinate& result) const {
return readOnlyGrid->FindNearestCoordinateOnEdgeInNodeBasedGraph(coord, result);
}
inline bool FindNearestNodeCoordForLatLon(
const FixedPointCoordinate& input_coordinate,
FixedPointCoordinate& result,
const unsigned zoom_level = 18
) const {
PhantomNode resulting_phantom_node;
bool foundNode = FindPhantomNodeForCoordinate(
input_coordinate,
resulting_phantom_node, zoom_level
);
result = resulting_phantom_node.location;
return foundNode;
}
inline bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode, const unsigned zoomLevel) const {
return readOnlyGrid->FindPhantomNodeForCoordinate(location, resultNode, zoomLevel);
}
inline bool FindPhantomNodeForCoordinate(
const FixedPointCoordinate & input_coordinate,
PhantomNode & resulting_phantom_node,
const unsigned zoom_level
) const {
return read_only_rtree->FindPhantomNodeForCoordinate(
input_coordinate,
resulting_phantom_node,
zoom_level
);
}
inline void FindRoutingStarts(const _Coordinate &start, const _Coordinate &target, PhantomNodes & phantomNodes, const unsigned zoomLevel) const {
readOnlyGrid->FindRoutingStarts(start, target, phantomNodes, zoomLevel);
}
inline void FindNearestPointOnEdge(const _Coordinate & input, _Coordinate& output){
readOnlyGrid->FindNearestPointOnEdge(input, output);
}
inline unsigned GetCheckSum() const {
return check_sum;
return checkSum;
}
private:
void LoadNodesAndEdges(
const std::string & nodes_filename,
const std::string & edges_filename
) {
boost::filesystem::path nodes_file(nodes_filename);
if ( !boost::filesystem::exists( nodes_file ) ) {
throw OSRMException("nodes file does not exist");
}
if ( 0 == boost::filesystem::file_size( nodes_file ) ) {
throw OSRMException("nodes file is empty");
}
std::vector<_Coordinate> coordinateVector;
std::vector<OriginalEdgeData> origEdgeData;
boost::filesystem::path edges_file(edges_filename);
if ( !boost::filesystem::exists( edges_file ) ) {
throw OSRMException("edges file does not exist");
}
if ( 0 == boost::filesystem::file_size( edges_file ) ) {
throw OSRMException("edges file is empty");
}
boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary);
boost::filesystem::ifstream edges_input_stream(edges_file, std::ios::binary);
SimpleLogger().Write(logDEBUG) << "Loading node data";
NodeInfo b;
while(!nodes_input_stream.eof()) {
nodes_input_stream.read((char *)&b, sizeof(NodeInfo));
coordinateVector.push_back(FixedPointCoordinate(b.lat, b.lon));
}
std::vector<FixedPointCoordinate>(coordinateVector).swap(coordinateVector);
nodes_input_stream.close();
SimpleLogger().Write(logDEBUG) << "Loading edge data";
unsigned numberOfOrigEdges(0);
edges_input_stream.read((char*)&numberOfOrigEdges, sizeof(unsigned));
origEdgeData_viaNode.resize(numberOfOrigEdges);
origEdgeData_nameID.resize(numberOfOrigEdges);
origEdgeData_turnInstruction.resize(numberOfOrigEdges);
OriginalEdgeData deserialized_originalEdgeData;
for(unsigned i = 0; i < numberOfOrigEdges; ++i) {
edges_input_stream.read(
(char*)&(deserialized_originalEdgeData),
sizeof(OriginalEdgeData)
);
origEdgeData_viaNode[i] = deserialized_originalEdgeData.viaNode;
origEdgeData_nameID[i] = deserialized_originalEdgeData.nameID;
origEdgeData_turnInstruction[i] = deserialized_originalEdgeData.turnInstruction;
}
edges_input_stream.close();
SimpleLogger().Write(logDEBUG) << "Loaded " << numberOfOrigEdges << " orig edges";
SimpleLogger().Write(logDEBUG) << "Opening NN indices";
}
std::vector<FixedPointCoordinate> coordinateVector;
std::vector<NodeID> origEdgeData_viaNode;
std::vector<unsigned> origEdgeData_nameID;
std::vector<TurnInstruction> origEdgeData_turnInstruction;
StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode> * read_only_rtree;
const unsigned number_of_nodes;
const unsigned check_sum;
ReadOnlyGrid * readOnlyGrid;
const unsigned numberOfNodes;
const unsigned checkSum;
};
#endif /*NODEINFORMATIONHELPDESK_H_*/
+1 -1
View File
@@ -21,9 +21,9 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef PERCENT_H
#define PERCENT_H
#include "../Util/OpenMPWrapper.h"
#include <iostream>
class Percent
{
public:
+3 -10
View File
@@ -24,20 +24,13 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include "Coordinate.h"
struct PhantomNode {
PhantomNode() :
edgeBasedNode(UINT_MAX),
nodeBasedEdgeNameID(UINT_MAX),
weight1(INT_MAX),
weight2(INT_MAX),
ratio(0.)
{ }
PhantomNode() : edgeBasedNode(UINT_MAX), nodeBasedEdgeNameID(UINT_MAX), weight1(INT_MAX), weight2(INT_MAX), ratio(0.) {}
NodeID edgeBasedNode;
unsigned nodeBasedEdgeNameID;
int weight1;
int weight2;
double ratio;
FixedPointCoordinate location;
_Coordinate location;
void Reset() {
edgeBasedNode = UINT_MAX;
nodeBasedEdgeNameID = UINT_MAX;
@@ -95,7 +88,7 @@ inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn){
struct NodesOfEdge {
NodeID edgeBasedNode;
double ratio;
FixedPointCoordinate projectedPoint;
_Coordinate projectedPoint;
};
#endif /* PHANTOMNODES_H_ */
+18 -9
View File
@@ -18,6 +18,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef QUERYEDGE_H_
#define QUERYEDGE_H_
@@ -27,11 +29,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <climits>
struct OriginalEdgeData{
explicit OriginalEdgeData(
NodeID viaNode,
unsigned nameID,
TurnInstruction turnInstruction
) : viaNode(viaNode), nameID(nameID), turnInstruction(turnInstruction) {}
explicit OriginalEdgeData(NodeID v, unsigned n, TurnInstruction t) : viaNode(v), nameID(n), turnInstruction(t) {}
OriginalEdgeData() : viaNode(UINT_MAX), nameID(UINT_MAX), turnInstruction(UCHAR_MAX) {}
NodeID viaNode;
unsigned nameID;
@@ -43,19 +41,30 @@ struct QueryEdge {
NodeID target;
struct EdgeData {
NodeID id:31;
bool shortcut:1;
int distance:30;
bool shortcut:1;
bool forward:1;
bool backward:1;
} data;
bool operator<( const QueryEdge& right ) const {
if ( source != right.source ) {
if ( source != right.source )
return source < right.source;
}
return target < right.target;
}
//sorts by source and other attributes
static bool CompareBySource( const QueryEdge& left, const QueryEdge& 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 QueryEdge& 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
+20 -56
View File
@@ -23,78 +23,40 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef RESTRICTION_H_
#define RESTRICTION_H_
#include "../typedefs.h"
#include <climits>
struct TurnRestriction {
struct _Restriction {
NodeID viaNode;
NodeID fromNode;
NodeID toNode;
struct Bits { //mostly unused
Bits()
:
isOnly(false),
unused1(false),
unused2(false),
unused3(false),
unused4(false),
unused5(false),
unused6(false),
unused7(false)
{ }
bool isOnly:1;
bool unused1:1;
bool unused2:1;
bool unused3:1;
bool unused4:1;
bool unused5:1;
bool unused6:1;
bool unused7:1;
Bits() : isOnly(false), unused1(false), unused2(false), unused3(false), unused4(false), unused5(false), unused6(false), unused7(false) {}
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;
TurnRestriction(NodeID viaNode) :
viaNode(viaNode),
fromNode(UINT_MAX),
toNode(UINT_MAX) {
}
TurnRestriction(const bool isOnly = false) :
viaNode(UINT_MAX),
fromNode(UINT_MAX),
toNode(UINT_MAX) {
_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 {
TurnRestriction restriction;
_Restriction restriction;
EdgeID fromWay;
EdgeID toWay;
unsigned viaNode;
_RawRestrictionContainer(
EdgeID fromWay,
EdgeID toWay,
NodeID vn,
unsigned vw
) :
fromWay(fromWay),
toWay(toWay),
viaNode(vw)
{
restriction.viaNode = vn;
}
_RawRestrictionContainer(
bool isOnly = false
) :
fromWay(UINT_MAX),
toWay(UINT_MAX),
viaNode(UINT_MAX)
{
restriction.flags.isOnly = isOnly;
}
_RawRestrictionContainer(EdgeID f, EdgeID t, NodeID vn, unsigned vw) : fromWay(f), toWay(t), viaNode(vw) { restriction.viaNode = vn;}
_RawRestrictionContainer(bool isOnly = false) : fromWay(UINT_MAX), toWay(UINT_MAX), viaNode(UINT_MAX) { restriction.flags.isOnly = isOnly;}
static _RawRestrictionContainer min_value() {
return _RawRestrictionContainer(0, 0, 0, 0);
@@ -104,7 +66,7 @@ struct _RawRestrictionContainer {
}
};
struct CmpRestrictionContainerByFrom : public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
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;
@@ -130,4 +92,6 @@ struct CmpRestrictionContainerByTo: public std::binary_function<_RawRestrictionC
}
};
#endif /* RESTRICTION_H_ */
-89
View File
@@ -1,89 +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 "SearchEngine.h"
SearchEngine::SearchEngine(
QueryGraph * g,
NodeInformationHelpDesk * nh,
std::vector<std::string> & n
) :
_queryData(g, nh, n),
shortestPath(_queryData),
alternativePaths(_queryData)
{}
SearchEngine::~SearchEngine() {}
void SearchEngine::GetCoordinatesForNodeID(
NodeID id,
FixedPointCoordinate& result
) const {
result.lat = _queryData.nodeHelpDesk->getLatitudeOfNode(id);
result.lon = _queryData.nodeHelpDesk->getLongitudeOfNode(id);
}
void SearchEngine::FindPhantomNodeForCoordinate(
const FixedPointCoordinate & location,
PhantomNode & result,
const unsigned zoomLevel
) const {
_queryData.nodeHelpDesk->FindPhantomNodeForCoordinate(
location,
result, zoomLevel
);
}
NodeID SearchEngine::GetNameIDForOriginDestinationNodeID(
const NodeID s,
const NodeID t
) const {
if(s == t){
return 0;
}
EdgeID e = _queryData.graph->FindEdge(s, t);
if(e == UINT_MAX) {
e = _queryData.graph->FindEdge( t, s );
}
if(UINT_MAX == e) {
return 0;
}
assert(e != UINT_MAX);
const QueryEdge::EdgeData ed = _queryData.graph->GetEdgeData(e);
return ed.id;
}
std::string SearchEngine::GetEscapedNameForNameID(const unsigned nameID) const {
bool is_name_invalid = (nameID >= _queryData.names.size() || nameID == 0);
if (is_name_invalid) {
return std::string("");
}
return HTMLEntitize(_queryData.names.at(nameID));
}
SearchEngineHeapPtr SearchEngineData::forwardHeap;
SearchEngineHeapPtr SearchEngineData::backwardHeap;
SearchEngineHeapPtr SearchEngineData::forwardHeap2;
SearchEngineHeapPtr SearchEngineData::backwardHeap2;
SearchEngineHeapPtr SearchEngineData::forwardHeap3;
SearchEngineHeapPtr SearchEngineData::backwardHeap3;
+137 -34
View File
@@ -21,48 +21,151 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef SEARCHENGINE_H_
#define SEARCHENGINE_H_
#include "Coordinate.h"
#include <climits>
#include <deque>
#include "SimpleStack.h"
#include <boost/thread.hpp>
#include "BinaryHeap.h"
#include "NodeInformationHelpDesk.h"
#include "PhantomNodes.h"
#include "QueryEdge.h"
#include "SearchEngineData.h"
#include "../RoutingAlgorithms/AlternativePathRouting.h"
#include "../RoutingAlgorithms/BasicRoutingInterface.h"
#include "../RoutingAlgorithms/ShortestPathRouting.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
#include <climits>
#include <string>
#include <vector>
class SearchEngine {
private:
SearchEngineData _queryData;
public:
ShortestPathRouting<SearchEngineData> shortestPath;
AlternativeRouting<SearchEngineData> alternativePaths;
SearchEngine(
QueryGraph * g,
NodeInformationHelpDesk * nh,
std::vector<std::string> & n
);
~SearchEngine();
void GetCoordinatesForNodeID(NodeID id, FixedPointCoordinate& result) const;
void FindPhantomNodeForCoordinate(
const FixedPointCoordinate & location,
PhantomNode & result,
unsigned zoomLevel
) const;
NodeID GetNameIDForOriginDestinationNodeID(
const NodeID s, const NodeID t) const;
std::string GetEscapedNameForNameID(const unsigned nameID) const;
struct _HeapData {
NodeID parent;
_HeapData( NodeID p ) : parent(p) { }
};
typedef boost::thread_specific_ptr<BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > > SearchEngineHeapPtr;
template<class EdgeData, class GraphT>
struct SearchEngineData {
typedef SearchEngineHeapPtr HeapPtr;
typedef GraphT Graph;
SearchEngineData(GraphT * g, NodeInformationHelpDesk * nh, std::vector<string> & n) :graph(g), nodeHelpDesk(nh), names(n) {}
const GraphT * graph;
NodeInformationHelpDesk * nodeHelpDesk;
std::vector<string> & names;
static HeapPtr forwardHeap;
static HeapPtr backwardHeap;
static HeapPtr forwardHeap2;
static HeapPtr backwardHeap2;
static HeapPtr forwardHeap3;
static HeapPtr backwardHeap3;
inline void InitializeOrClearFirstThreadLocalStorage() {
if(!forwardHeap.get()) {
forwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
}
else
forwardHeap->Clear();
if(!backwardHeap.get()) {
backwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
}
else
backwardHeap->Clear();
}
inline void InitializeOrClearSecondThreadLocalStorage() {
if(!forwardHeap2.get()) {
forwardHeap2.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
}
else
forwardHeap2->Clear();
if(!backwardHeap2.get()) {
backwardHeap2.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
}
else
backwardHeap2->Clear();
}
inline void InitializeOrClearThirdThreadLocalStorage() {
if(!forwardHeap3.get()) {
forwardHeap3.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
}
else
forwardHeap3->Clear();
if(!backwardHeap3.get()) {
backwardHeap3.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
}
else
backwardHeap3->Clear();
}
};
template<class EdgeData, class GraphT>
class SearchEngine {
private:
typedef SearchEngineData<EdgeData, GraphT> SearchEngineDataT;
SearchEngineDataT _queryData;
inline double absDouble(double input) { if(input < 0) return input*(-1); else return input;}
public:
ShortestPathRouting<SearchEngineDataT> shortestPath;
AlternativeRouting<SearchEngineDataT> alternativePaths;
SearchEngine(GraphT * g, NodeInformationHelpDesk * nh, std::vector<string> & n) :
_queryData(g, nh, n),
shortestPath(_queryData),
alternativePaths(_queryData)
{}
~SearchEngine() {}
inline void GetCoordinatesForNodeID(NodeID id, _Coordinate& result) const {
result.lat = _queryData.nodeHelpDesk->getLatitudeOfNode(id);
result.lon = _queryData.nodeHelpDesk->getLongitudeOfNode(id);
}
inline void FindRoutingStarts(const _Coordinate & start, const _Coordinate & target, PhantomNodes & routingStarts) const {
_queryData.nodeHelpDesk->FindRoutingStarts(start, target, routingStarts);
}
inline void FindPhantomNodeForCoordinate(const _Coordinate & location, PhantomNode & result, unsigned zoomLevel) const {
_queryData.nodeHelpDesk->FindPhantomNodeForCoordinate(location, result, zoomLevel);
}
inline NodeID GetNameIDForOriginDestinationNodeID(const NodeID s, const NodeID t) const {
if(s == t)
return 0;
EdgeID e = _queryData.graph->FindEdge(s, t);
if(e == UINT_MAX)
e = _queryData.graph->FindEdge( t, s );
if(UINT_MAX == e) {
return 0;
}
assert(e != UINT_MAX);
const EdgeData ed = _queryData.graph->GetEdgeData(e);
return ed.via;
}
inline std::string GetEscapedNameForNameID(const unsigned nameID) const {
return ((nameID >= _queryData.names.size() || nameID == 0) ? std::string("") : HTMLEntitize(_queryData.names.at(nameID)));
}
inline std::string GetEscapedNameForEdgeBasedEdgeID(const unsigned edgeID) const {
const unsigned nameID = _queryData.graph->GetEdgeData(edgeID).nameID1;
return GetEscapedNameForNameID(nameID);
}
};
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::forwardHeap;
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::backwardHeap;
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::forwardHeap2;
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::backwardHeap2;
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::forwardHeap3;
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::backwardHeap3;
#endif /* SEARCHENGINE_H_ */
-60
View File
@@ -1,60 +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 "SearchEngineData.h"
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage() {
if(!forwardHeap.get()) {
forwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
} else {
forwardHeap->Clear();
}
if(!backwardHeap.get()) {
backwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
} else {
backwardHeap->Clear();
}
}
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage() {
if(!forwardHeap2.get()) {
forwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
} else {
forwardHeap2->Clear();
}
if(!backwardHeap2.get()) {
backwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
} else {
backwardHeap2->Clear();
}
}
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage() {
if(!forwardHeap3.get()) {
forwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
} else {
forwardHeap3->Clear();
}
if(!backwardHeap3.get()) {
backwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
} else {
backwardHeap3->Clear();
}
}
-60
View File
@@ -1,60 +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 "BinaryHeap.h"
#include "QueryEdge.h"
#include "NodeInformationHelpDesk.h"
#include "StaticGraph.h"
#include "../typedefs.h"
#include <boost/thread.hpp>
#include <string>
#include <vector>
struct _HeapData {
NodeID parent;
_HeapData( NodeID p ) : parent(p) { }
};
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeapType;
typedef boost::thread_specific_ptr<QueryHeapType> SearchEngineHeapPtr;
struct SearchEngineData {
typedef QueryGraph Graph;
typedef QueryHeapType QueryHeap;
SearchEngineData(QueryGraph * g, NodeInformationHelpDesk * nh, std::vector<std::string> & n) :graph(g), nodeHelpDesk(nh), names(n) {}
const QueryGraph * graph;
NodeInformationHelpDesk * nodeHelpDesk;
std::vector<std::string> & names;
static SearchEngineHeapPtr forwardHeap;
static SearchEngineHeapPtr backwardHeap;
static SearchEngineHeapPtr forwardHeap2;
static SearchEngineHeapPtr backwardHeap2;
static SearchEngineHeapPtr forwardHeap3;
static SearchEngineHeapPtr backwardHeap3;
void InitializeOrClearFirstThreadLocalStorage();
void InitializeOrClearSecondThreadLocalStorage();
void InitializeOrClearThirdThreadLocalStorage();
};
+5 -6
View File
@@ -21,22 +21,21 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef SEGMENTINFORMATION_H_
#define SEGMENTINFORMATION_H_
#include "TurnInstructions.h"
#include "../typedefs.h"
#include <climits>
#include "TurnInstructions.h"
struct SegmentInformation {
FixedPointCoordinate location;
_Coordinate location;
NodeID nameID;
double length;
unsigned duration;
double bearing;
TurnInstruction turnInstruction;
bool necessary;
SegmentInformation(const FixedPointCoordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr, const bool nec) :
SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr, const bool nec) :
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(nec) {}
SegmentInformation(const FixedPointCoordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr) :
SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr) :
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(tInstr != 0) {}
};
+6 -11
View File
@@ -21,11 +21,11 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef STATICGRAPH_H_INCLUDED
#define STATICGRAPH_H_INCLUDED
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <algorithm>
#include <vector>
#include <algorithm>
#include "../typedefs.h"
#include "ImportEdge.h"
template< typename EdgeDataT>
class StaticGraph {
@@ -100,17 +100,12 @@ public:
if(data.shortcut) {
unsigned eid2 = FindEdgeInEitherDirection(u, data.id);
if(eid2 == UINT_MAX) {
SimpleLogger().Write(logWARNING) <<
"cannot find first segment of edge (" <<
u << "," << data.id << "," << v << ")";
DEBUG("cannot find first segment of edge (" << u << "," << data.id << "," << v << ")");
data.shortcut = false;
}
eid2 = FindEdgeInEitherDirection(data.id, v);
if(eid2 == UINT_MAX) {
SimpleLogger().Write(logWARNING) <<
"cannot find second segment of edge (" <<
u << "," << data.id << "," << v << ")";
DEBUG("cannot find second segment of edge (" << u << "," << data.id << "," << v << ")");
data.shortcut = false;
}
}
-832
View File
@@ -1,832 +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 STATICRTREE_H_
#define STATICRTREE_H_
#include "MercatorUtil.h"
#include "Coordinate.h"
#include "PhantomNodes.h"
#include "DeallocatingVector.h"
#include "HilbertValue.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../Util/TimingUtil.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/algorithm/minmax.hpp>
#include <boost/algorithm/minmax_element.hpp>
#include <boost/range/algorithm_ext/erase.hpp>
#include <boost/noncopyable.hpp>
#include <boost/thread.hpp>
#include <cassert>
#include <cfloat>
#include <climits>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
//tuning parameters
const static uint32_t RTREE_BRANCHING_FACTOR = 50;
const static uint32_t RTREE_LEAF_NODE_SIZE = 1170;
// Implements a static, i.e. packed, R-tree
static boost::thread_specific_ptr<boost::filesystem::ifstream> thread_local_rtree_stream;
template<class DataT>
class StaticRTree : boost::noncopyable {
private:
struct RectangleInt2D {
RectangleInt2D() :
min_lon(INT_MAX),
max_lon(INT_MIN),
min_lat(INT_MAX),
max_lat(INT_MIN) {}
int32_t min_lon, max_lon;
int32_t min_lat, max_lat;
inline void InitializeMBRectangle(
const DataT * objects,
const uint32_t element_count
) {
for(uint32_t i = 0; i < element_count; ++i) {
min_lon = std::min(
min_lon, std::min(objects[i].lon1, objects[i].lon2)
);
max_lon = std::max(
max_lon, std::max(objects[i].lon1, objects[i].lon2)
);
min_lat = std::min(
min_lat, std::min(objects[i].lat1, objects[i].lat2)
);
max_lat = std::max(
max_lat, std::max(objects[i].lat1, objects[i].lat2)
);
}
}
inline void AugmentMBRectangle(const RectangleInt2D & other) {
min_lon = std::min(min_lon, other.min_lon);
max_lon = std::max(max_lon, other.max_lon);
min_lat = std::min(min_lat, other.min_lat);
max_lat = std::max(max_lat, other.max_lat);
}
inline FixedPointCoordinate Centroid() const {
FixedPointCoordinate centroid;
//The coordinates of the midpoints are given by:
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
centroid.lon = (min_lon + max_lon)/2;
centroid.lat = (min_lat + max_lat)/2;
return centroid;
}
inline bool Intersects(const RectangleInt2D & other) const {
FixedPointCoordinate upper_left (other.max_lat, other.min_lon);
FixedPointCoordinate upper_right(other.max_lat, other.max_lon);
FixedPointCoordinate lower_right(other.min_lat, other.max_lon);
FixedPointCoordinate lower_left (other.min_lat, other.min_lon);
return (
Contains(upper_left)
|| Contains(upper_right)
|| Contains(lower_right)
|| Contains(lower_left)
);
}
inline double GetMinDist(const FixedPointCoordinate & location) const {
bool is_contained = Contains(location);
if (is_contained) {
return 0.0;
}
double min_dist = DBL_MAX;
min_dist = std::min(
min_dist,
ApproximateDistance(
location.lat,
location.lon,
max_lat,
min_lon
)
);
min_dist = std::min(
min_dist,
ApproximateDistance(
location.lat,
location.lon,
max_lat,
max_lon
)
);
min_dist = std::min(
min_dist,
ApproximateDistance(
location.lat,
location.lon,
min_lat,
max_lon
)
);
min_dist = std::min(
min_dist,
ApproximateDistance(
location.lat,
location.lon,
min_lat,
min_lon
)
);
return min_dist;
}
inline double GetMinMaxDist(const FixedPointCoordinate & location) const {
double min_max_dist = DBL_MAX;
//Get minmax distance to each of the four sides
FixedPointCoordinate upper_left (max_lat, min_lon);
FixedPointCoordinate upper_right(max_lat, max_lon);
FixedPointCoordinate lower_right(min_lat, max_lon);
FixedPointCoordinate lower_left (min_lat, min_lon);
min_max_dist = std::min(
min_max_dist,
std::max(
ApproximateDistance(location, upper_left ),
ApproximateDistance(location, upper_right)
)
);
min_max_dist = std::min(
min_max_dist,
std::max(
ApproximateDistance(location, upper_right),
ApproximateDistance(location, lower_right)
)
);
min_max_dist = std::min(
min_max_dist,
std::max(
ApproximateDistance(location, lower_right),
ApproximateDistance(location, lower_left )
)
);
min_max_dist = std::min(
min_max_dist,
std::max(
ApproximateDistance(location, lower_left ),
ApproximateDistance(location, upper_left )
)
);
return min_max_dist;
}
inline bool Contains(const FixedPointCoordinate & location) const {
bool lats_contained =
(location.lat > min_lat) && (location.lat < max_lat);
bool lons_contained =
(location.lon > min_lon) && (location.lon < max_lon);
return lats_contained && lons_contained;
}
inline friend std::ostream & operator<< (
std::ostream & out,
const RectangleInt2D & rect
) {
out << rect.min_lat/COORDINATE_PRECISION << ","
<< rect.min_lon/COORDINATE_PRECISION << " "
<< rect.max_lat/COORDINATE_PRECISION << ","
<< rect.max_lon/COORDINATE_PRECISION;
return out;
}
};
typedef RectangleInt2D RectangleT;
struct WrappedInputElement {
explicit WrappedInputElement(
const uint32_t _array_index,
const uint64_t _hilbert_value
) : m_array_index(_array_index), m_hilbert_value(_hilbert_value) {}
WrappedInputElement() : m_array_index(UINT_MAX), m_hilbert_value(0) {}
uint32_t m_array_index;
uint64_t m_hilbert_value;
inline bool operator<(const WrappedInputElement & other) const {
return m_hilbert_value < other.m_hilbert_value;
}
};
struct LeafNode {
LeafNode() : object_count(0) {}
uint32_t object_count;
DataT objects[RTREE_LEAF_NODE_SIZE];
};
struct TreeNode {
TreeNode() : child_count(0), child_is_on_disk(false) {}
RectangleT minimum_bounding_rectangle;
uint32_t child_count:31;
bool child_is_on_disk:1;
uint32_t children[RTREE_BRANCHING_FACTOR];
};
struct QueryCandidate {
explicit QueryCandidate(
const uint32_t n_id,
const double dist
) : node_id(n_id), min_dist(dist) {}
QueryCandidate() : node_id(UINT_MAX), min_dist(DBL_MAX) {}
uint32_t node_id;
double min_dist;
inline bool operator<(const QueryCandidate & other) const {
return min_dist < other.min_dist;
}
};
std::vector<TreeNode> m_search_tree;
uint64_t m_element_count;
const std::string m_leaf_node_filename;
public:
//Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1]
explicit StaticRTree(
std::vector<DataT> & input_data_vector,
const std::string tree_node_filename,
const std::string leaf_node_filename
)
: m_element_count(input_data_vector.size()),
m_leaf_node_filename(leaf_node_filename)
{
SimpleLogger().Write() <<
"constructing r-tree of " << m_element_count <<
" elements";
double time1 = get_timestamp();
std::vector<WrappedInputElement> input_wrapper_vector(m_element_count);
//generate auxiliary vector of hilbert-values
#pragma omp parallel for schedule(guided)
for(uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) {
input_wrapper_vector[element_counter].m_array_index = element_counter;
//Get Hilbert-Value for centroid in mercartor projection
DataT & current_element = input_data_vector[element_counter];
FixedPointCoordinate current_centroid = current_element.Centroid();
current_centroid.lat = COORDINATE_PRECISION*lat2y(current_centroid.lat/COORDINATE_PRECISION);
uint64_t current_hilbert_value = HilbertCode::GetHilbertNumberForCoordinate(current_centroid);
input_wrapper_vector[element_counter].m_hilbert_value = current_hilbert_value;
}
//open leaf file
boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
leaf_node_file.write((char*) &m_element_count, sizeof(uint64_t));
//sort the hilbert-value representatives
std::sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
std::vector<TreeNode> tree_nodes_in_level;
//pack M elements into leaf node and write to leaf file
uint64_t processed_objects_count = 0;
while(processed_objects_count < m_element_count) {
LeafNode current_leaf;
TreeNode current_node;
for(uint32_t current_element_index = 0; RTREE_LEAF_NODE_SIZE > current_element_index; ++current_element_index) {
if(m_element_count > (processed_objects_count + current_element_index)) {
uint32_t index_of_next_object = input_wrapper_vector[processed_objects_count + current_element_index].m_array_index;
current_leaf.objects[current_element_index] = input_data_vector[index_of_next_object];
++current_leaf.object_count;
}
}
//generate tree node that resemble the objects in leaf and store it for next level
current_node.minimum_bounding_rectangle.InitializeMBRectangle(current_leaf.objects, current_leaf.object_count);
current_node.child_is_on_disk = true;
current_node.children[0] = tree_nodes_in_level.size();
tree_nodes_in_level.push_back(current_node);
//write leaf_node to leaf node file
leaf_node_file.write((char*)&current_leaf, sizeof(current_leaf));
processed_objects_count += current_leaf.object_count;
}
//close leaf file
leaf_node_file.close();
uint32_t processing_level = 0;
while(1 < tree_nodes_in_level.size()) {
std::vector<TreeNode> tree_nodes_in_next_level;
uint32_t processed_tree_nodes_in_level = 0;
while(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
TreeNode parent_node;
//pack RTREE_BRANCHING_FACTOR elements into tree_nodes each
for(
uint32_t current_child_node_index = 0;
RTREE_BRANCHING_FACTOR > current_child_node_index;
++current_child_node_index
) {
if(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
TreeNode & current_child_node = tree_nodes_in_level[processed_tree_nodes_in_level];
//add tree node to parent entry
parent_node.children[current_child_node_index] = m_search_tree.size();
m_search_tree.push_back(current_child_node);
//augment MBR of parent
parent_node.minimum_bounding_rectangle.AugmentMBRectangle(current_child_node.minimum_bounding_rectangle);
//increase counters
++parent_node.child_count;
++processed_tree_nodes_in_level;
}
}
tree_nodes_in_next_level.push_back(parent_node);
}
tree_nodes_in_level.swap(tree_nodes_in_next_level);
++processing_level;
}
BOOST_ASSERT_MSG(1 == tree_nodes_in_level.size(), "tree broken, more than one root node");
//last remaining entry is the root node, store it
m_search_tree.push_back(tree_nodes_in_level[0]);
//reverse and renumber tree to have root at index 0
std::reverse(m_search_tree.begin(), m_search_tree.end());
#pragma omp parallel for schedule(guided)
for(uint32_t i = 0; i < m_search_tree.size(); ++i) {
TreeNode & current_tree_node = m_search_tree[i];
for(uint32_t j = 0; j < current_tree_node.child_count; ++j) {
const uint32_t old_id = current_tree_node.children[j];
const uint32_t new_id = m_search_tree.size() - old_id - 1;
current_tree_node.children[j] = new_id;
}
}
//open tree file
boost::filesystem::ofstream tree_node_file(
tree_node_filename,
std::ios::binary
);
uint32_t size_of_tree = m_search_tree.size();
BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
tree_node_file.write((char *)&size_of_tree, sizeof(uint32_t));
tree_node_file.write((char *)&m_search_tree[0], sizeof(TreeNode)*size_of_tree);
//close tree node file.
tree_node_file.close();
double time2 = get_timestamp();
SimpleLogger().Write() <<
"finished r-tree construction in " << (time2-time1) << " seconds";
}
//Read-only operation for queries
explicit StaticRTree(
const std::string & node_filename,
const std::string & leaf_filename
) : m_leaf_node_filename(leaf_filename) {
//open tree node file and load into RAM.
boost::filesystem::path node_file(node_filename);
if ( !boost::filesystem::exists( node_file ) ) {
throw OSRMException("ram index file does not exist");
}
if ( 0 == boost::filesystem::file_size( node_file ) ) {
throw OSRMException("ram index file is empty");
}
boost::filesystem::ifstream tree_node_file( node_file, std::ios::binary );
uint32_t tree_size = 0;
tree_node_file.read((char*)&tree_size, sizeof(uint32_t));
//SimpleLogger().Write() << "reading " << tree_size << " tree nodes in " << (sizeof(TreeNode)*tree_size) << " bytes";
m_search_tree.resize(tree_size);
tree_node_file.read((char*)&m_search_tree[0], sizeof(TreeNode)*tree_size);
tree_node_file.close();
//open leaf node file and store thread specific pointer
boost::filesystem::path leaf_file(leaf_filename);
if ( !boost::filesystem::exists( leaf_file ) ) {
throw OSRMException("mem index file does not exist");
}
if ( 0 == boost::filesystem::file_size( leaf_file ) ) {
throw OSRMException("mem index file is empty");
}
boost::filesystem::ifstream leaf_node_file( leaf_file, std::ios::binary );
leaf_node_file.read((char*)&m_element_count, sizeof(uint64_t));
leaf_node_file.close();
//SimpleLogger().Write() << tree_size << " nodes in search tree";
//SimpleLogger().Write() << m_element_count << " elements in leafs";
}
/*
inline void FindKNearestPhantomNodesForCoordinate(
const FixedPointCoordinate & location,
const unsigned zoom_level,
const unsigned candidate_count,
std::vector<std::pair<PhantomNode, double> > & result_vector
) const {
bool ignore_tiny_components = (zoom_level <= 14);
DataT nearest_edge;
uint32_t io_count = 0;
uint32_t explored_tree_nodes_count = 0;
SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
double min_dist = DBL_MAX;
double min_max_dist = DBL_MAX;
bool found_a_nearest_edge = false;
FixedPointCoordinate nearest, current_start_coordinate, current_end_coordinate;
//initialize queue with root element
std::priority_queue<QueryCandidate> traversal_queue;
traversal_queue.push(QueryCandidate(0, m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate)));
BOOST_ASSERT_MSG(FLT_EPSILON > (0. - traversal_queue.top().min_dist), "Root element in NN Search has min dist != 0.");
while(!traversal_queue.empty()) {
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
++explored_tree_nodes_count;
bool prune_downward = (current_query_node.min_dist >= min_max_dist);
bool prune_upward = (current_query_node.min_dist >= min_dist);
if( !prune_downward && !prune_upward ) { //downward pruning
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
if (current_tree_node.child_is_on_disk) {
LeafNode current_leaf_node;
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
++io_count;
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
DataT & current_edge = current_leaf_node.objects[i];
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
continue;
}
double current_ratio = 0.;
double current_perpendicular_distance = ComputePerpendicularDistance(
input_coordinate,
FixedPointCoordinate(current_edge.lat1, current_edge.lon1),
FixedPointCoordinate(current_edge.lat2, current_edge.lon2),
nearest,
&current_ratio
);
if(
current_perpendicular_distance < min_dist
&& !DoubleEpsilonCompare(
current_perpendicular_distance,
min_dist
)
) { //found a new minimum
min_dist = current_perpendicular_distance;
result_phantom_node.edgeBasedNode = current_edge.id;
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
result_phantom_node.weight1 = current_edge.weight;
result_phantom_node.weight2 = INT_MAX;
result_phantom_node.location = nearest;
current_start_coordinate.lat = current_edge.lat1;
current_start_coordinate.lon = current_edge.lon1;
current_end_coordinate.lat = current_edge.lat2;
current_end_coordinate.lon = current_edge.lon2;
nearest_edge = current_edge;
found_a_nearest_edge = true;
} else if(
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
&& CoordinatesAreEquivalent(
current_start_coordinate,
FixedPointCoordinate(
current_edge.lat1,
current_edge.lon1
),
FixedPointCoordinate(
current_edge.lat2,
current_edge.lon2
),
current_end_coordinate
)
) {
result_phantom_node.edgeBasedNode = std::min(current_edge.id, result_phantom_node.edgeBasedNode);
result_phantom_node.weight2 = current_edge.weight;
}
}
} else {
//traverse children, prune if global mindist is smaller than local one
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
const int32_t child_id = current_tree_node.children[i];
TreeNode & child_tree_node = m_search_tree[child_id];
RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
if( current_min_max_dist < min_max_dist ) {
min_max_dist = current_min_max_dist;
}
if (current_min_dist > min_max_dist) {
continue;
}
if (current_min_dist > min_dist) { //upward pruning
continue;
}
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
}
}
}
}
const double distance_to_edge =
ApproximateDistance (
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
result_phantom_node.location
);
const double length_of_edge =
ApproximateDistance(
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
FixedPointCoordinate(nearest_edge.lat2, nearest_edge.lon2)
);
const double ratio = (found_a_nearest_edge ?
std::min(1., distance_to_edge/ length_of_edge ) : 0 );
result_phantom_node.weight1 *= ratio;
if(INT_MAX != result_phantom_node.weight2) {
result_phantom_node.weight2 *= (1.-ratio);
}
result_phantom_node.ratio = ratio;
//Hack to fix rounding errors and wandering via nodes.
if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
result_phantom_node.location.lon = input_coordinate.lon;
}
if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) {
result_phantom_node.location.lat = input_coordinate.lat;
}
SimpleLogger().Write() << "mindist: " << min_distphantom_node.isBidirected() ? "yes" : "no");
return found_a_nearest_edge;
}
*/
bool FindPhantomNodeForCoordinate(
const FixedPointCoordinate & input_coordinate,
PhantomNode & result_phantom_node,
const unsigned zoom_level
) {
bool ignore_tiny_components = (zoom_level <= 14);
DataT nearest_edge;
uint32_t io_count = 0;
uint32_t explored_tree_nodes_count = 0;
//SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
double min_dist = DBL_MAX;
double min_max_dist = DBL_MAX;
bool found_a_nearest_edge = false;
FixedPointCoordinate nearest, current_start_coordinate, current_end_coordinate;
//initialize queue with root element
std::priority_queue<QueryCandidate> traversal_queue;
double current_min_dist = m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate);
traversal_queue.push(
QueryCandidate(0, current_min_dist)
);
BOOST_ASSERT_MSG(
FLT_EPSILON > (0. - traversal_queue.top().min_dist),
"Root element in NN Search has min dist != 0."
);
while(!traversal_queue.empty()) {
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
++explored_tree_nodes_count;
bool prune_downward = (current_query_node.min_dist >= min_max_dist);
bool prune_upward = (current_query_node.min_dist >= min_dist);
if( !prune_downward && !prune_upward ) { //downward pruning
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
if (current_tree_node.child_is_on_disk) {
LeafNode current_leaf_node;
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
++io_count;
//SimpleLogger().Write() << "checking " << current_leaf_node.object_count << " elements";
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
DataT & current_edge = current_leaf_node.objects[i];
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
continue;
}
if(current_edge.isIgnored()) {
continue;
}
double current_ratio = 0.;
double current_perpendicular_distance = ComputePerpendicularDistance(
input_coordinate,
FixedPointCoordinate(current_edge.lat1, current_edge.lon1),
FixedPointCoordinate(current_edge.lat2, current_edge.lon2),
nearest,
&current_ratio
);
if(
current_perpendicular_distance < min_dist
&& !DoubleEpsilonCompare(
current_perpendicular_distance,
min_dist
)
) { //found a new minimum
min_dist = current_perpendicular_distance;
result_phantom_node.edgeBasedNode = current_edge.id;
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
result_phantom_node.weight1 = current_edge.weight;
result_phantom_node.weight2 = INT_MAX;
result_phantom_node.location = nearest;
current_start_coordinate.lat = current_edge.lat1;
current_start_coordinate.lon = current_edge.lon1;
current_end_coordinate.lat = current_edge.lat2;
current_end_coordinate.lon = current_edge.lon2;
nearest_edge = current_edge;
found_a_nearest_edge = true;
} else if(
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
&& CoordinatesAreEquivalent(
current_start_coordinate,
FixedPointCoordinate(
current_edge.lat1,
current_edge.lon1
),
FixedPointCoordinate(
current_edge.lat2,
current_edge.lon2
),
current_end_coordinate
)
) {
BOOST_ASSERT_MSG(current_edge.id != result_phantom_node.edgeBasedNode, "IDs not different");
//SimpleLogger().Write() << "found bidirected edge on nodes " << current_edge.id << " and " << result_phantom_node.edgeBasedNode;
result_phantom_node.weight2 = current_edge.weight;
if(current_edge.id < result_phantom_node.edgeBasedNode) {
result_phantom_node.edgeBasedNode = current_edge.id;
std::swap(result_phantom_node.weight1, result_phantom_node.weight2);
std::swap(current_end_coordinate, current_start_coordinate);
// SimpleLogger().Write() <<"case 2";
}
//SimpleLogger().Write() << "w1: " << result_phantom_node.weight1 << ", w2: " << result_phantom_node.weight2;
}
}
} else {
//traverse children, prune if global mindist is smaller than local one
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
const int32_t child_id = current_tree_node.children[i];
TreeNode & child_tree_node = m_search_tree[child_id];
RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
if( current_min_max_dist < min_max_dist ) {
min_max_dist = current_min_max_dist;
}
if (current_min_dist > min_max_dist) {
continue;
}
if (current_min_dist > min_dist) { //upward pruning
continue;
}
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
}
}
}
}
const double ratio = (found_a_nearest_edge ?
std::min(1., ApproximateDistance(current_start_coordinate,
result_phantom_node.location)/ApproximateDistance(current_start_coordinate, current_end_coordinate)
) : 0
);
result_phantom_node.weight1 *= ratio;
if(INT_MAX != result_phantom_node.weight2) {
result_phantom_node.weight2 *= (1.-ratio);
}
result_phantom_node.ratio = ratio;
//Hack to fix rounding errors and wandering via nodes.
if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
result_phantom_node.location.lon = input_coordinate.lon;
}
if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) {
result_phantom_node.location.lat = input_coordinate.lat;
}
return found_a_nearest_edge;
}
private:
inline void LoadLeafFromDisk(const uint32_t leaf_id, LeafNode& result_node) {
if(!thread_local_rtree_stream.get() || !thread_local_rtree_stream->is_open()) {
thread_local_rtree_stream.reset(
new boost::filesystem::ifstream(
m_leaf_node_filename,
std::ios::in | std::ios::binary
)
);
}
if(!thread_local_rtree_stream->good()) {
thread_local_rtree_stream->clear(std::ios::goodbit);
SimpleLogger().Write(logDEBUG) << "Resetting stale filestream";
}
uint64_t seek_pos = sizeof(uint64_t) + leaf_id*sizeof(LeafNode);
thread_local_rtree_stream->seekg(seek_pos);
thread_local_rtree_stream->read((char *)&result_node, sizeof(LeafNode));
}
inline double ComputePerpendicularDistance(
const FixedPointCoordinate& inputPoint,
const FixedPointCoordinate& source,
const FixedPointCoordinate& target,
FixedPointCoordinate& nearest, double *r) const {
const double x = static_cast<double>(inputPoint.lat);
const double y = static_cast<double>(inputPoint.lon);
const double a = static_cast<double>(source.lat);
const double b = static_cast<double>(source.lon);
const double c = static_cast<double>(target.lat);
const double d = static_cast<double>(target.lon);
double p,q,mX,nY;
if(fabs(a-c) > FLT_EPSILON){
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 need
// not calculate the explicit values of m an n as we
// are just interested in the ratio
if(std::isnan(mX)) {
*r = (target == inputPoint) ? 1. : 0.;
} else {
*r = mX;
}
if(*r<=0.){
nearest.lat = source.lat;
nearest.lon = source.lon;
return ((b - y)*(b - y) + (a - x)*(a - x));
// return std::sqrt(((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));
// return std::sqrt(((d - y)*(d - y) + (c - x)*(c - x)));
}
// point lies in between
nearest.lat = p;
nearest.lon = q;
// return std::sqrt((p-x)*(p-x) + (q-y)*(q-y));
return (p-x)*(p-x) + (q-y)*(q-y);
}
inline bool CoordinatesAreEquivalent(const FixedPointCoordinate & a, const FixedPointCoordinate & b, const FixedPointCoordinate & c, const FixedPointCoordinate & d) const {
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
}
inline bool DoubleEpsilonCompare(const double d1, const double d2) const {
return (std::fabs(d1 - d2) < FLT_EPSILON);
}
};
//[1] "On Packing R-Trees"; I. Kamel, C. Faloutsos; 1993; DOI: 10.1145/170088.170403
//[2] "Nearest Neighbor Queries", N. Roussopulos et al; 1995; DOI: 10.1145/223784.223794
#endif /* STATICRTREE_H_ */
+38 -4
View File
@@ -21,12 +21,12 @@
#ifndef TURNINSTRUCTIONS_H_
#define TURNINSTRUCTIONS_H_
#include <boost/noncopyable.hpp>
#include <string>
typedef unsigned char TurnInstruction;
//This is a hack until c++0x is available enough to use scoped enums
struct TurnInstructionsClass : boost::noncopyable {
struct TurnInstructionsClass {
const static TurnInstruction NoTurn = 0; //Give no instruction at all
const static TurnInstruction GoStraight = 1; //Tell user to go straight!
@@ -44,14 +44,48 @@ struct TurnInstructionsClass : boost::noncopyable {
const static TurnInstruction StayOnRoundAbout = 13;
const static TurnInstruction StartAtEndOfStreet = 14;
const static TurnInstruction ReachedYourDestination = 15;
const static TurnInstruction EnterAgainstAllowedDirection = 16;
const static TurnInstruction LeaveAgainstAllowedDirection = 17;
const static TurnInstruction AccessRestrictionFlag = 128;
const static TurnInstruction InverseAccessRestrictionFlag = 0x7f; // ~128 does not work without a warning.
const static int AccessRestrictionPenalty = 1 << 15; //unrelated to the bit set in the restriction flag
// std::string TurnStrings[16];
// std::string Ordinals[12];
//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 roundabout";
// TurnStrings[12] = "Leave roundabout";
// TurnStrings[13] = "Stay on roundabout";
// TurnStrings[14] = "Start";
// TurnStrings[15] = "You have reached your destination";
//
// 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";
// Ordinals[11] = "one of the too many";
// };
static inline TurnInstruction GetTurnDirectionOfInstruction( const double angle ) {
if(angle >= 23 && angle < 67) {
return TurnSharpRight;
+70
View File
@@ -0,0 +1,70 @@
/*
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_ */
+3 -3
View File
@@ -49,7 +49,7 @@ public:
table1.resize(2 << 16);
table2.resize(2 << 16);
for(unsigned i = 0; i < (2 << 16); ++i) {
table1[i] = i; table2[i] = i;
table1[i] = i; table2[i];
}
std::random_shuffle(table1.begin(), table1.end());
std::random_shuffle(table2.begin(), table2.end());
@@ -75,8 +75,8 @@ public:
table3.resize(1 << 8);
table4.resize(1 << 8);
for(unsigned i = 0; i < (1 << 8); ++i) {
table1[i] = i; table2[i] = i;
table3[i] = i; table4[i] = i;
table1[i] = i; table2[i];
table3[i] = i; table4[i];
}
std::random_shuffle(table1.begin(), table1.end());
std::random_shuffle(table2.begin(), table2.end());
+2 -2
View File
@@ -21,12 +21,12 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef XORFASTHASHSTORAGE_H_
#define XORFASTHASHSTORAGE_H_
#include "XORFastHash.h"
#include <climits>
#include <vector>
#include <bitset>
#include "XORFastHash.h"
template< typename NodeID, typename Key >
class XORFastHashStorage {
public:
+9 -10
View File
@@ -21,21 +21,19 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef BASE_DESCRIPTOR_H_
#define BASE_DESCRIPTOR_H_
#include "../DataStructures/HashTable.h"
#include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/RawRouteData.h"
#include "../DataStructures/SearchEngine.h"
#include "../Server/BasicDatastructures.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
#include <cassert>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include "../typedefs.h"
#include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/HashTable.h"
#include "../Util/StringUtil.h"
#include "../Plugins/RawRouteData.h"
struct _DescriptorConfig {
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(true), z(18) {}
bool instructions;
@@ -44,12 +42,13 @@ struct _DescriptorConfig {
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, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) = 0;
virtual void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) = 0;
virtual void SetConfig(const _DescriptorConfig & config) = 0;
};
+14 -17
View File
@@ -32,14 +32,11 @@ inline double DescriptionFactory::RadianToDegree(const double radian) const {
return radian * (180/M_PI);
}
double DescriptionFactory::GetBearing(
const FixedPointCoordinate & A,
const FixedPointCoordinate & B
) const {
double deltaLong = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
double DescriptionFactory::GetBearing(const _Coordinate& A, const _Coordinate& B) const {
double deltaLong = DegreeToRadian(B.lon/100000. - A.lon/100000.);
double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION);
double lat2 = DegreeToRadian(B.lat/COORDINATE_PRECISION);
double lat1 = DegreeToRadian(A.lat/100000.);
double lat2 = DegreeToRadian(B.lat/100000.);
double y = sin(deltaLong) * cos(lat2);
double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLong);
@@ -62,7 +59,7 @@ void DescriptionFactory::SetEndSegment(const PhantomNode & _targetPhantom) {
pathDescription.push_back(SegmentInformation(_targetPhantom.location, _targetPhantom.nodeBasedEdgeNameID, 0, _targetPhantom.weight1, 0, true) );
}
void DescriptionFactory::AppendSegment(const FixedPointCoordinate & coordinate, const _PathData & data ) {
void DescriptionFactory::AppendSegment(const _Coordinate & coordinate, const _PathData & data ) {
if(1 == pathDescription.size() && pathDescription.back().location == coordinate) {
pathDescription.back().nameID = data.nameID;
} else {
@@ -85,7 +82,7 @@ void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) {
pc.printUnencodedString(pathDescription, output);
}
void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) {
void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLevel) {
if(0 == pathDescription.size())
return;
@@ -94,7 +91,7 @@ void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLev
/** starts at index 1 */
pathDescription[0].length = 0;
for(unsigned i = 1; i < pathDescription.size(); ++i) {
pathDescription[i].length = ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
pathDescription[i].length = ApproximateDistanceByEuclid(pathDescription[i-1].location, pathDescription[i].location);
}
double lengthOfSegment = 0;
@@ -126,7 +123,7 @@ void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLev
// || std::string::npos != string0.find(string1+" ;")
// || std::string::npos != string0.find("; "+string1)
// ){
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
// INFO("->next correct: " << string0 << " contains " << string1);
// for(; lastTurn != i; ++lastTurn)
// pathDescription[lastTurn].nameID = pathDescription[i].nameID;
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
@@ -135,7 +132,7 @@ void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLev
// || std::string::npos != string1.find(string0+" ;")
// || std::string::npos != string1.find("; "+string0)
// ){
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
// INFO("->prev correct: " << string1 << " contains " << string0);
// pathDescription[i].nameID = pathDescription[i-1].nameID;
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
// }
@@ -156,24 +153,24 @@ void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLev
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
//SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID;
//INFO("Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID);
assert(pathDescription[i].necessary);
lengthOfSegment = 0;
durationOfSegment = 0;
indexOfSegmentBegin = i;
}
}
// SimpleLogger().Write() << "#segs: " << pathDescription.size();
// INFO("#segs: " << pathDescription.size());
//Post-processing to remove empty or nearly empty path segments
if(FLT_EPSILON > pathDescription.back().length) {
// SimpleLogger().Write() << "#segs: " << pathDescription.size() << ", last ratio: " << targetPhantom.ratio << ", length: " << pathDescription.back().length;
// INFO("#segs: " << pathDescription.size() << ", last ratio: " << targetPhantom.ratio << ", length: " << pathDescription.back().length);
if(pathDescription.size() > 2){
pathDescription.pop_back();
pathDescription.back().necessary = true;
pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
targetPhantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
// SimpleLogger().Write() << "Deleting last turn instruction";
// INFO("Deleting last turn instruction");
}
} else {
pathDescription[indexOfSegmentBegin].duration *= (1.-targetPhantom.ratio);
@@ -185,7 +182,7 @@ void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLev
pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
pathDescription[0].necessary = true;
startPhantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
// SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << startPhantom.ratio << ", length: " << pathDescription[0].length;
// INFO("Deleting first turn instruction, ratio: " << startPhantom.ratio << ", length: " << pathDescription[0].length);
}
} else {
pathDescription[0].duration *= startPhantom.ratio;
+15 -9
View File
@@ -21,16 +21,16 @@
#ifndef DESCRIPTIONFACTORY_H_
#define DESCRIPTIONFACTORY_H_
#include <vector>
#include "../typedefs.h"
#include "../Algorithms/DouglasPeucker.h"
#include "../Algorithms/PolylineCompressor.h"
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/SearchEngine.h"
#include "../DataStructures/SegmentInformation.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <vector>
/* This class is fed with all way segments in consecutive order
* and produces the description plus the encoded polyline */
@@ -40,6 +40,8 @@ class DescriptionFactory {
PolylineCompressor pc;
PhantomNode startPhantom, targetPhantom;
typedef SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > SearchEngineT;
double DegreeToRadian(const double degree) const;
double RadianToDegree(const double degree) const;
public:
@@ -51,9 +53,13 @@ public:
_RouteSummary() : lengthString("0"), durationString("0"), startName(0), destName(0) {}
void BuildDurationAndLengthStrings(const double distance, const unsigned time) {
//compute distance/duration for route summary
intToString(round(distance), lengthString);
std::ostringstream s;
s << round(distance);
lengthString = s.str();
int travelTime = time/10 + 1;
intToString(travelTime, durationString);
s.str("");
s << travelTime;
durationString = s.str();
}
} summary;
@@ -63,15 +69,15 @@ public:
std::vector <SegmentInformation> pathDescription;
DescriptionFactory();
virtual ~DescriptionFactory();
double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const;
double GetBearing(const _Coordinate& C, const _Coordinate& B) const;
void AppendEncodedPolylineString(std::string &output);
void AppendUnencodedPolylineString(std::string &output);
void AppendSegment(const FixedPointCoordinate & coordinate, const _PathData & data);
void AppendSegment(const _Coordinate & coordinate, const _PathData & data);
void BuildRouteSummary(const double distance, const unsigned time);
void SetStartSegment(const PhantomNode & startPhantom);
void SetEndSegment(const PhantomNode & startPhantom);
void AppendEncodedPolylineString(std::string & output, bool isEncoded);
void Run(const SearchEngine &sEngine, const unsigned zoomLevel);
void Run(const SearchEngineT &sEngine, const unsigned zoomLevel);
};
#endif /* DESCRIPTIONFACTORY_H_ */
+6 -7
View File
@@ -21,25 +21,24 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef GPX_DESCRIPTOR_H_
#define GPX_DESCRIPTOR_H_
#include <boost/foreach.hpp>
#include "BaseDescriptor.h"
#include <boost/foreach.hpp>
class GPXDescriptor : public BaseDescriptor{
template<class SearchEngineT>
class GPXDescriptor : public BaseDescriptor<SearchEngineT>{
private:
_DescriptorConfig config;
FixedPointCoordinate current;
_Coordinate current;
std::string tmp;
public:
void SetConfig(const _DescriptorConfig& c) { config = c; }
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) {
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
reply.content += "<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" 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 += "<metadata><copyright author=\"Project OSRM\"><license>Data (c) OpenStreetMap contributors (ODbL)</license></copyright></metadata>";
reply.content += "<rte>";
if(rawRoute.lengthOfShortestPath != INT_MAX && rawRoute.computedShortestPath.size()) {
convertInternalLatLonToString(phantomNodes.startPhantom.location.lat, tmp);
@@ -47,7 +46,7 @@ public:
convertInternalLatLonToString(phantomNodes.startPhantom.location.lon, tmp);
reply.content += "lon=\"" + tmp + "\"></rtept>";
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) {
BOOST_FOREACH(_PathData pathData, rawRoute.computedShortestPath) {
sEngine.GetCoordinatesForNodeID(pathData.node, current);
convertInternalLatLonToString(current.lat, tmp);
+21 -27
View File
@@ -21,6 +21,11 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef JSON_DESCRIPTOR_H_
#define JSON_DESCRIPTOR_H_
#include <algorithm>
#include <boost/lambda/lambda.hpp>
#include <boost/bind.hpp>
#include "BaseDescriptor.h"
#include "DescriptionFactory.h"
#include "../Algorithms/ObjectToBase64.h"
@@ -29,24 +34,15 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include "../Util/Azimuth.h"
#include "../Util/StringUtil.h"
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <algorithm>
class JSONDescriptor : public BaseDescriptor{
template<class SearchEngineT>
class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
private:
_DescriptorConfig config;
DescriptionFactory descriptionFactory;
DescriptionFactory alternateDescriptionFactory;
FixedPointCoordinate current;
_Coordinate current;
unsigned numberOfEnteredRestrictedAreas;
struct RoundAbout{
RoundAbout() :
startIndex(INT_MAX),
nameID(INT_MAX),
leaveAtExit(INT_MAX)
{}
struct {
int startIndex;
int nameID;
int leaveAtExit;
@@ -72,7 +68,7 @@ public:
JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {}
void SetConfig(const _DescriptorConfig & c) { config = c; }
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) {
WriteHeaderToOutput(reply.content);
@@ -250,7 +246,7 @@ public:
reply.content += "}";
}
void GetRouteNames(std::vector<Segment> & shortestSegments, std::vector<Segment> & alternativeSegments, const SearchEngine &sEngine, RouteNames & routeNames) {
void GetRouteNames(std::vector<Segment> & shortestSegments, std::vector<Segment> & alternativeSegments, SearchEngineT &sEngine, RouteNames & routeNames) {
/*** extract names for both alternatives ***/
Segment shortestSegment1, shortestSegment2;
@@ -266,25 +262,23 @@ public:
std::vector<Segment> shortestDifference(shortestSegments.size());
std::vector<Segment> alternativeDifference(alternativeSegments.size());
std::set_difference(shortestSegments.begin(), shortestSegments.end(), alternativeSegments.begin(), alternativeSegments.end(), shortestDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
int size_of_difference = shortestDifference.size();
if(0 < size_of_difference ) {
int i = 0;
while( i < size_of_difference && shortestDifference[i].nameID == shortestSegments[0].nameID) {
if(0 < shortestDifference.size() ) {
unsigned i = 0;
while( i < shortestDifference.size() && shortestDifference[i].nameID == shortestSegments[0].nameID) {
++i;
}
if(i < size_of_difference ) {
if(i < shortestDifference.size()) {
shortestSegment2 = shortestDifference[i];
}
}
std::set_difference(alternativeSegments.begin(), alternativeSegments.end(), shortestSegments.begin(), shortestSegments.end(), alternativeDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
size_of_difference = alternativeDifference.size();
if(0 < size_of_difference ) {
int i = 0;
while( i < size_of_difference && alternativeDifference[i].nameID == alternativeSegments[0].nameID) {
if(0 < alternativeDifference.size() ) {
unsigned i = 0;
while( i < alternativeDifference.size() && alternativeDifference[i].nameID == alternativeSegments[0].nameID) {
++i;
}
if(i < size_of_difference ) {
if(i < alternativeDifference.size()) {
alternativeSegment2 = alternativeDifference[i];
}
}
@@ -298,7 +292,7 @@ public:
routeNames.shortestPathName2 = sEngine.GetEscapedNameForNameID(shortestSegment2.nameID);
routeNames.alternativePathName1 = sEngine.GetEscapedNameForNameID(alternativeSegment1.nameID);
routeNames.alternativePathName2 = sEngine.GetEscapedNameForNameID(alternativeSegment2.nameID);
routeNames.alternativePathName2 += sEngine.GetEscapedNameForNameID(alternativeSegment2.nameID);
}
}
@@ -308,7 +302,7 @@ public:
"\"status\":";
}
inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngine &sEngine, std::vector<Segment> & segmentVector) {
inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngineT &sEngine, std::vector<Segment> & segmentVector) {
//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]
Submodule
+1
Submodule Docs added at f7150057d5
-3
View File
@@ -1,3 +0,0 @@
The javascript based web client is a seperate project available at
https://github.com/DennisSchiefer/Project-OSRM-Web
-100
View File
@@ -1,100 +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 "BaseParser.h"
BaseParser::BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se) :
extractor_callbacks(ec), scriptingEnvironment(se), luaState(NULL), use_turn_restrictions(true) {
luaState = se.getLuaStateForThreadID(0);
ReadUseRestrictionsSetting();
ReadRestrictionExceptions();
}
void BaseParser::ReadUseRestrictionsSetting() {
if( 0 != luaL_dostring( luaState, "return use_turn_restrictions\n") ) {
throw OSRMException(
/*lua_tostring( luaState, -1 ) + */"ERROR occured in scripting block"
);
}
if( lua_isboolean( luaState, -1) ) {
use_turn_restrictions = lua_toboolean(luaState, -1);
}
if( use_turn_restrictions ) {
SimpleLogger().Write() << "Using turn restrictions";
} else {
SimpleLogger().Write() << "Ignoring turn restrictions";
}
}
void BaseParser::ReadRestrictionExceptions() {
if(lua_function_exists(luaState, "get_exceptions" )) {
//get list of turn restriction exceptions
luabind::call_function<void>(
luaState,
"get_exceptions",
boost::ref(restriction_exceptions)
);
SimpleLogger().Write() << "Found " << restriction_exceptions.size() << " exceptions to turn restriction";
BOOST_FOREACH(const std::string & str, restriction_exceptions) {
SimpleLogger().Write() << " " << str;
}
} else {
SimpleLogger().Write() << "Found no exceptions to turn restrictions";
}
}
void BaseParser::report_errors(lua_State *L, const int status) const {
if( 0!=status ) {
std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
lua_pop(L, 1); // remove error message
}
}
void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) {
luabind::call_function<void>( localLuaState, "node_function", boost::ref(n) );
}
void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState) {
if(2 > w.path.size()) {
return;
}
luabind::call_function<void>( localLuaState, "way_function", boost::ref(w) );
}
bool BaseParser::ShouldIgnoreRestriction(const std::string& except_tag_string) const {
//should this restriction be ignored? yes if there's an overlap between:
//a) the list of modes in the except tag of the restriction (except_tag_string), ex: except=bus;bicycle
//b) the lua profile defines a hierachy of modes, ex: [access, vehicle, bicycle]
if( "" == except_tag_string ) {
return false;
}
//Be warned, this is quadratic work here, but we assume that
//only a few exceptions are actually defined.
std::vector<std::string> exceptions;
boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
BOOST_FOREACH(std::string& str, exceptions) {
if( restriction_exceptions.end() != std::find(restriction_exceptions.begin(), restriction_exceptions.end(), str) ) {
return true;
}
}
return false;
}
+15 -26
View File
@@ -21,40 +21,29 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef BASEPARSER_H_
#define BASEPARSER_H_
#include "ExtractorCallbacks.h"
#include "ScriptingEnvironment.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <boost/noncopyable.hpp>
#include "ScriptingEnvironment.h"
class BaseParser : boost::noncopyable {
template<class ExternalMemoryT, typename NodeT, typename RestrictionT, typename WayT>
class BaseParser {
public:
BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se);
virtual ~BaseParser() {}
virtual bool ReadHeader() = 0;
virtual bool Init() = 0;
virtual void RegisterCallbacks(ExternalMemoryT * externalMemory) = 0;
virtual void RegisterScriptingEnvironment(ScriptingEnvironment & _se) = 0;
virtual bool Parse() = 0;
virtual void ParseNodeInLua(ImportNode& n, lua_State* luaStateForThread);
virtual void ParseWayInLua(ExtractionWay& n, lua_State* luaStateForThread);
virtual void report_errors(lua_State *L, const int status) const;
protected:
virtual void ReadUseRestrictionsSetting();
virtual void ReadRestrictionExceptions();
virtual bool ShouldIgnoreRestriction(const std::string& except_tag_string) const;
ExtractorCallbacks* extractor_callbacks;
ScriptingEnvironment& scriptingEnvironment;
lua_State* luaState;
std::vector<std::string> restriction_exceptions;
bool use_turn_restrictions;
void report_errors(lua_State *L, int status) {
if ( status!=0 ) {
std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
lua_pop(L, 1); // remove error message
}
}
};
+55 -58
View File
@@ -20,38 +20,38 @@
#include "ExtractionContainers.h"
void ExtractionContainers::PrepareData(const std::string & output_file_name, const std::string restrictionsFileName, const unsigned amountOfRAM) {
void ExtractionContainers::PrepareData(const std::string & outputFileName, const std::string restrictionsFileName, const unsigned amountOfRAM) {
try {
unsigned usedNodeCounter = 0;
unsigned usedEdgeCounter = 0;
double time = get_timestamp();
boost::uint64_t memory_to_use = static_cast<boost::uint64_t>(amountOfRAM) * 1024 * 1024 * 1024;
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
cout << "[extractor] Sorting used nodes ... " << flush;
stxxl::sort(usedNodeIDs.begin(), usedNodeIDs.end(), Cmp(), memory_to_use);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
stxxl::vector<NodeID>::iterator NewEnd = std::unique ( usedNodeIDs.begin(),usedNodeIDs.end() ) ;
cout << "[extractor] Erasing duplicate nodes ... " << flush;
stxxl::vector<NodeID>::iterator NewEnd = unique ( usedNodeIDs.begin(),usedNodeIDs.end() ) ;
usedNodeIDs.resize ( NewEnd - usedNodeIDs.begin() );
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
cout << "[extractor] Sorting all nodes ... " << flush;
stxxl::sort(allNodes.begin(), allNodes.end(), CmpNodeByID(), memory_to_use);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
std::cout << "[extractor] Sorting used ways ... " << std::flush;
cout << "[extractor] Sorting used ways ... " << flush;
stxxl::sort(wayStartEndVector.begin(), wayStartEndVector.end(), CmpWayByID(), memory_to_use);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
cout << "ok, after " << get_timestamp() - time << "s" << endl;
std::cout << "[extractor] Sorting restrctns. by from... " << std::flush;
cout << "[extractor] Sorting restrctns. by from... " << flush;
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByFrom(), memory_to_use);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
cout << "ok, after " << get_timestamp() - time << "s" << endl;
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
cout << "[extractor] Fixing restriction starts ... " << flush;
STXXLRestrictionsVector::iterator restrictionsIT = restrictionsVector.begin();
STXXLWayIDStartEndVector::iterator wayStartAndEndEdgeIT = wayStartEndVector.begin();
@@ -79,16 +79,16 @@ void ExtractionContainers::PrepareData(const std::string & output_file_name, con
++restrictionsIT;
}
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
std::cout << "[extractor] Sorting restrctns. by to ... " << std::flush;
cout << "[extractor] Sorting restrctns. by to ... " << flush;
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByTo(), memory_to_use);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
unsigned usableRestrictionsCounter(0);
std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
cout << "[extractor] Fixing restriction ends ... " << flush;
restrictionsIT = restrictionsVector.begin();
wayStartAndEndEdgeIT = wayStartEndVector.begin();
while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) {
@@ -116,26 +116,24 @@ void ExtractionContainers::PrepareData(const std::string & output_file_name, con
}
++restrictionsIT;
}
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
SimpleLogger().Write() << "usable restrictions: " << usableRestrictionsCounter;
cout << "ok, after " << get_timestamp() - time << "s" << endl;
INFO("usable restrictions: " << usableRestrictionsCounter );
//serialize restrictions
std::ofstream restrictionsOutstream;
restrictionsOutstream.open(restrictionsFileName.c_str(), std::ios::binary);
restrictionsOutstream.write((char*)&uuid, sizeof(UUID));
ofstream restrictionsOutstream;
restrictionsOutstream.open(restrictionsFileName.c_str(), ios::binary);
restrictionsOutstream.write((char*)&usableRestrictionsCounter, sizeof(unsigned));
for(restrictionsIT = restrictionsVector.begin(); restrictionsIT != restrictionsVector.end(); ++restrictionsIT) {
if(UINT_MAX != restrictionsIT->restriction.fromNode && UINT_MAX != restrictionsIT->restriction.toNode) {
restrictionsOutstream.write((char *)&(restrictionsIT->restriction), sizeof(TurnRestriction));
restrictionsOutstream.write((char *)&(restrictionsIT->restriction), sizeof(_Restriction));
}
}
restrictionsOutstream.close();
std::ofstream fout;
fout.open(output_file_name.c_str(), std::ios::binary);
fout.write((char*)&uuid, sizeof(UUID));
ofstream fout;
fout.open(outputFileName.c_str(), ios::binary);
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
time = get_timestamp();
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
cout << "[extractor] Confirming/Writing used nodes ... " << flush;
STXXLNodeVector::iterator nodesIT = allNodes.begin();
STXXLNodeIDVector::iterator usedNodeIDsIT = usedNodeIDs.begin();
@@ -156,24 +154,24 @@ void ExtractionContainers::PrepareData(const std::string & output_file_name, con
}
}
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
cout << "ok, after " << get_timestamp() - time << "s" << endl;
std::cout << "[extractor] setting number of nodes ... " << std::flush;
std::ios::pos_type positionInFile = fout.tellp();
fout.seekp(std::ios::beg+sizeof(UUID));
cout << "[extractor] setting number of nodes ... " << flush;
ios::pos_type positionInFile = fout.tellp();
fout.seekp(ios::beg);
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
fout.seekp(positionInFile);
std::cout << "ok" << std::endl;
cout << "ok" << endl;
time = get_timestamp();
// Sort edges by start.
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
cout << "[extractor] Sorting edges by start ... " << flush;
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByStartID(), memory_to_use);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
std::cout << "[extractor] Setting start coords ... " << std::flush;
cout << "[extractor] Setting start coords ... " << flush;
fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
// Traverse list of edges and nodes in parallel and set start coord
nodesIT = allNodes.begin();
@@ -193,16 +191,16 @@ void ExtractionContainers::PrepareData(const std::string & output_file_name, con
++edgeIT;
}
}
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
// Sort Edges by target
std::cout << "[extractor] Sorting edges by target ... " << std::flush;
cout << "[extractor] Sorting edges by target ... " << flush;
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByTargetID(), memory_to_use);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
std::cout << "[extractor] Setting target coords ... " << std::flush;
cout << "[extractor] Setting target coords ... " << flush;
// Traverse list of edges and nodes in parallel and set target coord
nodesIT = allNodes.begin();
edgeIT = allEdges.begin();
@@ -233,22 +231,22 @@ void ExtractionContainers::PrepareData(const std::string & output_file_name, con
fout.write((char*)&edgeIT->target, sizeof(unsigned));
fout.write((char*)&intDist, sizeof(int));
switch(edgeIT->direction) {
case ExtractionWay::notSure:
case _Way::notSure:
fout.write((char*)&zero, sizeof(short));
break;
case ExtractionWay::oneway:
case _Way::oneway:
fout.write((char*)&one, sizeof(short));
break;
case ExtractionWay::bidirectional:
case _Way::bidirectional:
fout.write((char*)&zero, sizeof(short));
break;
case ExtractionWay::opposite:
case _Way::opposite:
fout.write((char*)&one, sizeof(short));
break;
default:
std::cerr << "[error] edge with no direction: " << edgeIT->direction << std::endl;
assert(false);
cerr << "[error] edge with no direction: " << edgeIT->direction << endl;
assert(false);
break;
}
fout.write((char*)&intWeight, sizeof(int));
@@ -258,34 +256,33 @@ void ExtractionContainers::PrepareData(const std::string & output_file_name, con
fout.write((char*)&edgeIT->isRoundabout, sizeof(bool));
fout.write((char*)&edgeIT->ignoreInGrid, sizeof(bool));
fout.write((char*)&edgeIT->isAccessRestricted, sizeof(bool));
fout.write((char*)&edgeIT->isContraFlow, sizeof(bool));
++usedEdgeCounter;
}
++usedEdgeCounter;
++edgeIT;
}
}
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
std::cout << "[extractor] setting number of edges ... " << std::flush;
cout << "ok, after " << get_timestamp() - time << "s" << endl;
cout << "[extractor] setting number of edges ... " << flush;
fout.seekp(positionInFile);
fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
fout.close();
std::cout << "ok" << std::endl;
cout << "ok" << endl;
time = get_timestamp();
std::cout << "[extractor] writing street name index ... " << std::flush;
std::string nameOutFileName = (output_file_name + ".names");
std::ofstream nameOutFile(nameOutFileName.c_str(), std::ios::binary);
cout << "[extractor] writing street name index ... " << flush;
std::string nameOutFileName = (outputFileName + ".names");
ofstream nameOutFile(nameOutFileName.c_str(), ios::binary);
unsigned sizeOfNameIndex = nameVector.size();
nameOutFile.write((char *)&(sizeOfNameIndex), sizeof(unsigned));
BOOST_FOREACH(const std::string & str, nameVector) {
BOOST_FOREACH(string str, nameVector) {
unsigned lengthOfRawString = strlen(str.c_str());
nameOutFile.write((char *)&(lengthOfRawString), sizeof(unsigned));
nameOutFile.write(str.c_str(), lengthOfRawString);
}
nameOutFile.close();
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
cout << "ok, after " << get_timestamp() - time << "s" << endl;
// time = get_timestamp();
// cout << "[extractor] writing address list ... " << flush;
@@ -298,11 +295,11 @@ void ExtractionContainers::PrepareData(const std::string & output_file_name, con
// addressOutFile.close();
// cout << "ok, after " << get_timestamp() - time << "s" << endl;
SimpleLogger().Write() << "Processed " << usedNodeCounter << " nodes and " << usedEdgeCounter << " edges";
INFO("Processed " << usedNodeCounter << " nodes and " << usedEdgeCounter << " edges");
} catch ( const std::exception& e ) {
std::cerr << "Caught Execption:" << e.what() << std::endl;
} catch ( const exception& e ) {
cerr << "Caught Execption:" << e.what() << endl;
}
}
+12 -10
View File
@@ -21,29 +21,31 @@
#ifndef EXTRACTIONCONTAINERS_H_
#define EXTRACTIONCONTAINERS_H_
#include "ExtractorStructs.h"
#include "../Util/SimpleLogger.h"
#include "../Util/TimingUtil.h"
#include "../Util/UUID.h"
#include <boost/foreach.hpp>
#include <stxxl.h>
#include "ExtractorStructs.h"
#include "../DataStructures/Util.h"
class ExtractionContainers {
public:
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
typedef stxxl::vector<_Node> STXXLNodeVector;
typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector;
typedef stxxl::vector<_Edge> STXXLEdgeVector;
typedef stxxl::vector<std::string> STXXLStringVector;
typedef stxxl::vector<_RawRestrictionContainer> STXXLRestrictionsVector;
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
ExtractionContainers() {
//Check if another instance of stxxl is already running or if there is a general problem
stxxl::vector<unsigned> testForRunningInstance;
try {
stxxl::vector<unsigned> testForRunningInstance;
} catch(std::exception & e) {
ERR("Could not instantiate STXXL layer." << std::endl << e.what());
}
nameVector.push_back("");
}
virtual ~ExtractionContainers() {
usedNodeIDs.clear();
allNodes.clear();
@@ -53,7 +55,7 @@ public:
wayStartEndVector.clear();
}
void PrepareData( const std::string & output_file_name, const std::string restrictionsFileName, const unsigned amountOfRAM);
void PrepareData( const std::string & outputFileName, const std::string restrictionsFileName, const unsigned amountOfRAM);
STXXLNodeIDVector usedNodeIDs;
STXXLNodeVector allNodes;
@@ -61,7 +63,7 @@ public:
STXXLStringVector nameVector;
STXXLRestrictionsVector restrictionsVector;
STXXLWayIDStartEndVector wayStartEndVector;
const UUID uuid;
};
#endif /* EXTRACTIONCONTAINERS_H_ */
+11 -21
View File
@@ -18,22 +18,22 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef EXTRACTIONHELPERFUNCTIONS_H_
#define EXTRACTIONHELPERFUNCTIONS_H_
#include "../Util/StringUtil.h"
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string_regex.hpp>
#include <boost/regex.hpp>
#include <climits>
namespace qi = boost::spirit::qi;
#include "../Util/StringUtil.h"
//TODO: Move into LUA
inline bool durationIsValid(const std::string &s) {
boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
boost::regex e ("((\\d|\\d\\d):)*(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
std::vector< std::string > result;
boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ;
@@ -42,28 +42,17 @@ inline bool durationIsValid(const std::string &s) {
}
inline unsigned parseDuration(const std::string &s) {
unsigned hours = 0;
unsigned minutes = 0;
unsigned seconds = 0;
boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
int hours = 0;
int minutes = 0;
boost::regex e ("((\\d|\\d\\d):)*(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
std::vector< std::string > result;
boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ;
bool matched = regex_match(s, e);
if(matched) {
if(1 == result.size()) {
minutes = stringToInt(result[0]);
}
if(2 == result.size()) {
minutes = stringToInt(result[1]);
hours = stringToInt(result[0]);
}
if(3 == result.size()) {
seconds = stringToInt(result[2]);
minutes = stringToInt(result[1]);
hours = stringToInt(result[0]);
}
return 10*(3600*hours+60*minutes+seconds);
hours = (result.size()== 2) ? stringToInt(result[0]) : 0;
minutes = (result.size()== 2) ? stringToInt(result[1]) : stringToInt(result[0]);
return 600*(hours*60+minutes);
}
return UINT_MAX;
}
@@ -77,4 +66,5 @@ inline int parseMaxspeed(std::string input) { //call-by-value on purpose.
return n;
}
#endif /* EXTRACTIONHELPERFUNCTIONS_H_ */
+56 -75
View File
@@ -12,6 +12,26 @@ 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.
*/
/*
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
@@ -20,6 +40,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include "ExtractorCallbacks.h"
#include "ExtractionHelperFunctions.h"
ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; }
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) {
@@ -27,98 +48,58 @@ ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * s
stringMap = strMap;
}
ExtractorCallbacks::~ExtractorCallbacks() { }
/** warning: caller needs to take care of synchronization! */
void ExtractorCallbacks::nodeFunction(const _Node &n) {
if(n.lat <= 85*COORDINATE_PRECISION && n.lat >= -85*COORDINATE_PRECISION) {
externalMemory->allNodes.push_back(n);
}
ExtractorCallbacks::~ExtractorCallbacks() {
}
bool ExtractorCallbacks::restrictionFunction(const _RawRestrictionContainer &r) {
/** warning: caller needs to take care of synchronization! */
bool ExtractorCallbacks::nodeFunction(_Node &n) {
if(n.lat <= 85*100000 && n.lat >= -85*100000)
externalMemory->allNodes.push_back(n);
return true;
}
bool ExtractorCallbacks::restrictionFunction(_RawRestrictionContainer &r) {
externalMemory->restrictionsVector.push_back(r);
return true;
}
/** warning: caller needs to take care of synchronization! */
void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
if((0 < parsed_way.speed) || (0 < parsed_way.duration)) { //Only true if the way is specified by the speed profile
if(UINT_MAX == parsed_way.id){
SimpleLogger().Write(logDEBUG) <<
"found bogus way with id: " << parsed_way.id <<
" of size " << parsed_way.path.size();
return;
}
bool ExtractorCallbacks::wayFunction(_Way &w) {
/*** Store name of way and split it into edge segments ***/
if(0 < parsed_way.duration) {
//TODO: iterate all way segments and set duration corresponding to the length of each segment
parsed_way.speed = parsed_way.duration/(parsed_way.path.size()-1);
}
if(FLT_EPSILON >= fabs(-1. - parsed_way.speed)){
SimpleLogger().Write(logDEBUG) <<
"found way with bogus speed, id: " << parsed_way.id;
return;
}
if ( w.speed > 0 ) { //Only true if the way is specified by the speed profile
//Get the unique identifier for the street name
const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name);
if(stringMap->end() == string_map_iterator) {
parsed_way.nameID = externalMemory->nameVector.size();
externalMemory->nameVector.push_back(parsed_way.name);
stringMap->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
const 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 {
parsed_way.nameID = string_map_iterator->second;
w.nameID = strit->second;
}
if(ExtractionWay::opposite == parsed_way.direction) {
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
parsed_way.direction = ExtractionWay::oneway;
if(fabs(-1. - w.speed) < FLT_EPSILON){
WARN("found way with bogus speed, id: " << w.id);
return true;
}
if(w.id == UINT_MAX) {
WARN("found way with unknown type: " << w.id);
return true;
}
const bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
externalMemory->allEdges.push_back(
InternalExtractorEdge(parsed_way.path[n],
parsed_way.path[n+1],
parsed_way.type,
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
parsed_way.speed,
parsed_way.nameID,
parsed_way.roundabout,
parsed_way.ignoreInGrid,
(0 < parsed_way.duration),
parsed_way.isAccessRestricted
)
);
externalMemory->usedNodeIDs.push_back(parsed_way.path[n]);
if ( w.direction == _Way::opposite ){
std::reverse( w.path.begin(), w.path.end() );
}
externalMemory->usedNodeIDs.push_back(parsed_way.path.back());
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, w.ignoreInGrid, w.isDurationSet, w.isAccessRestricted));
externalMemory->usedNodeIDs.push_back(w.path[n]);
}
externalMemory->usedNodeIDs.push_back(w.path.back());
//The following information is needed to identify start and end segments of restrictions
externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
if(split_bidirectional_edge) { //Only true if the way should be split
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
externalMemory->allEdges.push_back(
InternalExtractorEdge(parsed_way.path[n],
parsed_way.path[n+1],
parsed_way.type,
ExtractionWay::oneway,
parsed_way.backward_speed,
parsed_way.nameID,
parsed_way.roundabout,
parsed_way.ignoreInGrid,
(0 < parsed_way.duration),
parsed_way.isAccessRestricted,
(ExtractionWay::oneway == parsed_way.direction)
)
);
}
externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
}
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;
}
+7 -10
View File
@@ -21,11 +21,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef EXTRACTORCALLBACKS_H_
#define EXTRACTORCALLBACKS_H_
#include "ExtractionContainers.h"
#include "ExtractionHelperFunctions.h"
#include "ExtractorStructs.h"
#include "../DataStructures/Coordinate.h"
#include <string>
#include <vector>
#include <cfloat>
@@ -33,8 +30,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <boost/algorithm/string/regex.hpp>
#include <boost/regex.hpp>
#include <string>
#include <vector>
#include "ExtractionContainers.h"
#include "ExtractorStructs.h"
class ExtractorCallbacks{
private:
@@ -48,12 +45,12 @@ public:
~ExtractorCallbacks();
/** warning: caller needs to take care of synchronization! */
void nodeFunction(const _Node &n);
bool nodeFunction(_Node &n);
bool restrictionFunction(const _RawRestrictionContainer &r);
bool restrictionFunction(_RawRestrictionContainer &r);
/** warning: caller needs to take care of synchronization! */
void wayFunction(ExtractionWay &w);
bool wayFunction(_Way &w);
};
+53 -55
View File
@@ -21,80 +21,75 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef EXTRACTORSTRUCTS_H_
#define EXTRACTORSTRUCTS_H_
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportNode.h"
#include "../DataStructures/QueryNode.h"
#include "../DataStructures/Restriction.h"
#include "../typedefs.h"
#include <climits>
#include <string>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <boost/regex.hpp>
#include <boost/unordered_map.hpp>
#include <climits>
#include <string>
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportNode.h"
#include "../DataStructures/NodeCoords.h"
#include "../DataStructures/Restriction.h"
#include "../DataStructures/Util.h"
#include "../typedefs.h"
typedef boost::unordered_map<std::string, NodeID > StringMap;
typedef boost::unordered_map<std::string, std::pair<int, short> > StringToIntPairMap;
struct ExtractionWay {
ExtractionWay() {
struct _Way {
_Way() {
Clear();
}
inline void Clear(){
id = UINT_MAX;
nameID = UINT_MAX;
path.clear();
keyVals.clear();
direction = ExtractionWay::notSure;
keyVals.EraseAll();
direction = _Way::notSure;
speed = -1;
backward_speed = -1;
duration = -1;
type = -1;
access = true;
roundabout = false;
isDurationSet = false;
isAccessRestricted = false;
ignoreInGrid = false;
}
enum Directions {
enum {
notSure = 0, oneway, bidirectional, opposite
};
Directions direction;
} direction;
unsigned id;
unsigned nameID;
std::string name;
double speed;
double backward_speed;
double duration;
short type;
bool access;
bool roundabout;
bool isDurationSet;
bool isAccessRestricted;
bool ignoreInGrid;
std::vector< NodeID > path;
HashTable<std::string, std::string> keyVals;
};
struct ExtractorRelation {
ExtractorRelation() : type(unknown){}
struct _Relation {
_Relation() : type(unknown){}
enum {
unknown = 0, ferry, turnRestriction
} type;
HashTable<std::string, std::string> keyVals;
};
struct InternalExtractorEdge {
InternalExtractorEdge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) {};
InternalExtractorEdge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { }
InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { }
InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(false) {
assert(0 <= type);
}
InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, bool icf): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(icf) {
struct _Edge {
_Edge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) {};
_Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(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), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) { }
_Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar) {
assert(0 <= type);
}
NodeID start;
@@ -107,21 +102,19 @@ struct InternalExtractorEdge {
bool ignoreInGrid;
bool isDurationSet;
bool isAccessRestricted;
bool isContraFlow;
FixedPointCoordinate startCoord;
FixedPointCoordinate targetCoord;
_Coordinate startCoord;
_Coordinate targetCoord;
static InternalExtractorEdge min_value() {
return InternalExtractorEdge(0,0);
static _Edge min_value() {
return _Edge(0,0);
}
static InternalExtractorEdge max_value() {
return InternalExtractorEdge((std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)());
static _Edge max_value() {
return _Edge((numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)());
}
};
struct _WayIDStartAndEndEdge {
unsigned wayID;
NodeID firstStart;
@@ -132,10 +125,10 @@ struct _WayIDStartAndEndEdge {
_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((std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)());
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((std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)());
return _WayIDStartAndEndEdge((numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)());
}
};
@@ -178,33 +171,38 @@ struct CmpNodeByID : public std::binary_function<_Node, _Node, bool> {
}
};
struct CmpEdgeByStartID : public std::binary_function<InternalExtractorEdge, InternalExtractorEdge, bool> {
typedef InternalExtractorEdge value_type;
bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const {
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 InternalExtractorEdge::max_value();
return _Edge::max_value();
}
value_type min_value() {
return InternalExtractorEdge::min_value();
return _Edge::min_value();
}
};
struct CmpEdgeByTargetID : public std::binary_function<InternalExtractorEdge, InternalExtractorEdge, bool> {
typedef InternalExtractorEdge value_type;
bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const {
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 InternalExtractorEdge::max_value();
value_type max_value()
{
return _Edge::max_value();
}
value_type min_value() {
return InternalExtractorEdge::min_value();
value_type min_value()
{
return _Edge::min_value();
}
};
inline std::string GetRandomString() {
inline string GetRandomString() {
char s[128];
static const char alphanum[] =
"0123456789"
@@ -215,7 +213,7 @@ inline std::string GetRandomString() {
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
}
s[127] = 0;
return std::string(s);
return string(s);
}
#endif /* EXTRACTORSTRUCTS_H_ */
+11 -9
View File
@@ -16,18 +16,20 @@ 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 TIMINGUTIL_H_
#define TIMINGUTIL_H_
#include <boost/timer.hpp>
static boost::timer my_timer;
#ifndef LUAUTIL_H_
#define LUAUTIL_H_
/** Returns a timestamp (now) in seconds (incl. a fractional part). */
static inline double get_timestamp() {
return my_timer.elapsed();
#include <iostream>
template<typename T>
void LUA_print(T number) {
std::cout << "[LUA] " << number << std::endl;
}
#endif /* TIMINGUTIL_H_ */
#endif /* LUAUTIL_H_ */
-487
View File
@@ -1,487 +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 "PBFParser.h"
PBFParser::PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser( ec, se ) {
GOOGLE_PROTOBUF_VERIFY_VERSION;
//TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
//NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
threadDataQueue = boost::make_shared<ConcurrentQueue<_ThreadData*> >( 2500 ); /* Max 2500 items in queue, hardcoded. */
input.open(fileName, std::ios::in | std::ios::binary);
if (!input) {
throw OSRMException("pbf file not found.");
}
#ifndef NDEBUG
blockCount = 0;
groupCount = 0;
#endif
}
PBFParser::~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;
}
google::protobuf::ShutdownProtobufLibrary();
#ifndef NDEBUG
SimpleLogger().Write(logDEBUG) <<
"parsed " << blockCount <<
" blocks from pbf with " << groupCount <<
" groups";
#endif
}
inline bool PBFParser::ReadHeader() {
_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, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) {
const std::string& feature = initData.PBFHeaderBlock.required_features( i );
bool supported = false;
if ( "OsmSchema-V0.6" == feature ) {
supported = true;
}
else if ( "DenseNodes" == feature ) {
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;
}
inline void PBFParser::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
delete threadData;
}
} while(keepRunning);
}
inline void PBFParser::ParseData() {
while (true) {
_ThreadData *threadData;
threadDataQueue->wait_and_pop(threadData);
if( NULL==threadData ) {
SimpleLogger().Write() << "Parse Data Thread Finished";
threadDataQueue->push(NULL); // Signal end of data for other threads
break;
}
loadBlock(threadData);
for(int i = 0, groupSize = threadData->PBFprimitiveBlock.primitivegroup_size(); i < groupSize; ++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;
}
}
inline bool PBFParser::Parse() {
// Start the read and parse threads
boost::thread readThread(boost::bind(&PBFParser::ReadData, this));
//Open several parse threads that are synchronized before call to
boost::thread parseThread(boost::bind(&PBFParser::ParseData, this));
// Wait for the threads to finish
readThread.join();
parseThread.join();
return true;
}
inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense();
int denseTagIndex = 0;
int64_t m_lastDenseID = 0;
int64_t m_lastDenseLatitude = 0;
int64_t m_lastDenseLongitude = 0;
const int number_of_nodes = dense.id_size();
std::vector<ImportNode> extracted_nodes_vector(number_of_nodes);
for(int i = 0; i < number_of_nodes; ++i) {
m_lastDenseID += dense.id( i );
m_lastDenseLatitude += dense.lat( i );
m_lastDenseLongitude += dense.lon( i );
extracted_nodes_vector[i].id = m_lastDenseID;
extracted_nodes_vector[i].lat = COORDINATE_PRECISION*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lat_offset() ) / NANO;
extracted_nodes_vector[i].lon = COORDINATE_PRECISION*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO;
while (denseTagIndex < dense.keys_vals_size()) {
const int tagValue = dense.keys_vals( denseTagIndex );
if( 0==tagValue ) {
++denseTagIndex;
break;
}
const int keyValue = dense.keys_vals ( denseTagIndex+1 );
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data();
const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data();
extracted_nodes_vector[i].keyVals.insert(std::make_pair(key, value));
denseTagIndex += 2;
}
}
#pragma omp parallel for schedule ( guided )
for(int i = 0; i < number_of_nodes; ++i) {
ImportNode &n = extracted_nodes_vector[i];
ParseNodeInLua( n, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) );
}
BOOST_FOREACH(ImportNode &n, extracted_nodes_vector) {
extractor_callbacks->nodeFunction(n);
}
}
inline void PBFParser::parseNode(_ThreadData * ) {
throw OSRMException(
"Parsing of simple nodes not supported. PBF should use dense nodes"
);
}
inline void PBFParser::parseRelation(_ThreadData * threadData) {
//TODO: leave early, if relation is not a restriction
//TODO: reuse rawRestriction container
if( !use_turn_restrictions ) {
return;
}
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
for(int i = 0; i < group.relations_size(); ++i ) {
std::string except_tag_string;
const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i);
bool isRestriction = false;
bool isOnlyRestriction = false;
for(int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++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) {
if( "restriction" == val) {
isRestriction = true;
} else {
break;
}
}
if ("restriction" == key) {
if(val.find("only_") == 0) {
isOnlyRestriction = true;
}
}
if ("except" == key) {
except_tag_string = val;
}
}
if( isRestriction && ShouldIgnoreRestriction(except_tag_string) ) {
continue;
}
if(isRestriction) {
int64_t lastRef = 0;
_RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
for(int rolesIndex = 0; rolesIndex < inputRelation.roles_sid_size(); ++rolesIndex) {
std::string role(threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) ).data());
lastRef += inputRelation.memids(rolesIndex);
if(!("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.viaNode) {
currentRestrictionContainer.viaNode = UINT_MAX;
}
assert(UINT_MAX == currentRestrictionContainer.viaNode);
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.viaNode = 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(!extractor_callbacks->restrictionFunction(currentRestrictionContainer)) {
std::cerr << "[PBFParser] relation not parsed" << std::endl;
}
}
}
}
inline void PBFParser::parseWay(_ThreadData * threadData) {
const int number_of_ways = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size();
std::vector<ExtractionWay> parsed_way_vector(number_of_ways);
for(int i = 0; i < number_of_ways; ++i) {
const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i );
parsed_way_vector[i].id = inputWay.id();
unsigned pathNode(0);
const int number_of_referenced_nodes = inputWay.refs_size();
for(int j = 0; j < number_of_referenced_nodes; ++j) {
pathNode += inputWay.refs(j);
parsed_way_vector[i].path.push_back(pathNode);
}
assert(inputWay.keys_size() == inputWay.vals_size());
const int number_of_keys = inputWay.keys_size();
for(int j = 0; j < number_of_keys; ++j) {
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(j));
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(j));
parsed_way_vector[i].keyVals.insert(std::make_pair(key, val));
}
}
#pragma omp parallel for schedule ( guided )
for(int i = 0; i < number_of_ways; ++i) {
ExtractionWay & w = parsed_way_vector[i];
ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) );
}
BOOST_FOREACH(ExtractionWay & w, parsed_way_vector) {
extractor_callbacks->wayFunction(w);
}
}
inline void PBFParser::loadGroup(_ThreadData * threadData) {
#ifndef NDEBUG
++groupCount;
#endif
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 );
}
inline void PBFParser::loadBlock(_ThreadData * threadData) {
#ifndef NDEBUG
++blockCount;
#endif
threadData->currentGroupID = 0;
threadData->currentEntityID = 0;
}
inline bool PBFParser::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 = new char[size];
stream.read(data, size*sizeof(data[0]));
bool dataSuccessfullyParsed = (threadData->PBFBlobHeader).ParseFromArray( data, size);
delete[] data;
return dataSuccessfullyParsed;
}
inline bool PBFParser::unpackZLIB(std::fstream &, _ThreadData * threadData) {
unsigned rawSize = threadData->PBFBlob.raw_size();
char* unpackedDataArray = new char[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;
delete[] 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;
delete[] unpackedDataArray;
return false;
}
ret = inflateEnd( &compressedDataStream );
if ( ret != Z_OK ) {
std::cerr << "[error] failed to deinit zlib stream" << std::endl;
delete[] unpackedDataArray;
return false;
}
threadData->charBuffer.clear(); threadData->charBuffer.resize(rawSize);
std::copy(unpackedDataArray, unpackedDataArray + rawSize, threadData->charBuffer.begin());
delete[] unpackedDataArray;
return true;
}
inline bool PBFParser::unpackLZMA(std::fstream &, _ThreadData * ) {
return false;
}
inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData) {
if(stream.eof()) {
return false;
}
const 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 = new char[size];
stream.read(data, sizeof(data[0])*size);
if ( !threadData->PBFBlob.ParseFromArray( data, size ) ) {
std::cerr << "[error] failed to parse blob" << std::endl;
delete[] data;
return false;
}
if ( threadData->PBFBlob.has_raw() ) {
const std::string& data = threadData->PBFBlob.raw();
threadData->charBuffer.clear();
threadData->charBuffer.resize( data.size() );
std::copy(data.begin(), data.end(), threadData->charBuffer.begin());
} else if ( threadData->PBFBlob.has_zlib_data() ) {
if ( !unpackZLIB(stream, threadData) ) {
std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
delete[] 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;
}
delete[] data;
return false;
} else {
std::cerr << "[error] Blob contains no data" << std::endl;
delete[] data;
return false;
}
delete[] data;
return true;
}
bool PBFParser::readNextBlock(std::fstream& stream, _ThreadData * threadData) {
if(stream.eof()) {
return false;
}
if ( !readPBFBlobHeader(stream, threadData) ){
return false;
}
if ( threadData->PBFBlobHeader.type() != "OSMData" ) {
return false;
}
if ( !readBlob(stream, threadData) ) {
return false;
}
if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) {
std::cerr << "failed to parse PrimitiveBlock" << std::endl;
return false;
}
return true;
}
+542 -46
View File
@@ -1,47 +1,47 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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 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.
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.
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 "BaseParser.h"
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ConcurrentQueue.h"
#include "../Util/MachineInfo.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <boost/shared_ptr.hpp>
#include <zlib.h>
#include <boost/make_shared.hpp>
#include <boost/ref.hpp>
#include <boost/shared_ptr.hpp>
#include <osmpbf/fileformat.pb.h>
#include <osmpbf/osmformat.pb.h>
#include <zlib.h>
#include "../typedefs.h"
class PBFParser : public BaseParser {
#include "BaseParser.h"
#include "ExtractorCallbacks.h"
#include "ExtractorStructs.h"
#include "ScriptingEnvironment.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ConcurrentQueue.h"
#include "../Util/OpenMPWrapper.h"
class PBFParser : public BaseParser<ExtractorCallbacks, _Node, _RawRestrictionContainer, _Way> {
// typedef BaseParser<ExtractorCallbacks, _Node, _RawRestrictionContainer, _Way> super;
enum EntityType {
TypeNode = 1,
@@ -50,6 +50,11 @@ class PBFParser : public BaseParser {
TypeDenseNode = 8
} ;
enum Endianness {
LittleEndian = 1,
BigEndian = 2
};
struct _ThreadData {
int currentGroupID;
int currentEntityID;
@@ -65,27 +70,512 @@ class PBFParser : public BaseParser {
};
public:
PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se);
virtual ~PBFParser();
PBFParser(const char * fileName) : externalMemory(NULL){
GOOGLE_PROTOBUF_VERIFY_VERSION;
//TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
//NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
threadDataQueue = boost::make_shared<ConcurrentQueue<_ThreadData*> >( 2500 ); /* Max 2500 items in queue, hardcoded. */
input.open(fileName, std::ios::in | std::ios::binary);
inline bool ReadHeader();
inline bool Parse();
if (!input) {
std::cerr << fileName << ": File not found." << std::endl;
}
#ifndef NDEBUG
blockCount = 0;
groupCount = 0;
#endif
}
void RegisterCallbacks(ExtractorCallbacks * em) {
externalMemory = em;
}
//call by value, but who cares. It is done once.
void RegisterScriptingEnvironment(ScriptingEnvironment & _se) {
scriptingEnvironment = _se;
}
~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;
}
google::protobuf::ShutdownProtobufLibrary();
#ifndef NDEBUG
DEBUG("parsed " << blockCount << " blocks from pbf with " << groupCount << " groups");
#endif
}
inline 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, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) {
const std::string& feature = initData.PBFHeaderBlock.required_features( i );
bool supported = false;
if ( "OsmSchema-V0.6" == feature )
supported = true;
else if ( "DenseNodes" == feature )
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;
}
inline 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
delete threadData;
}
} while(keepRunning);
}
inline void ParseData() {
while (1) {
_ThreadData *threadData;
threadDataQueue->wait_and_pop(threadData);
if (threadData == NULL) {
INFO("Parse Data Thread Finished");
threadDataQueue->push(NULL); // Signal end of data for other threads
break;
}
loadBlock(threadData);
for(int i = 0, groupSize = threadData->PBFprimitiveBlock.primitivegroup_size(); i < groupSize; ++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;
}
}
inline bool Parse() {
// Start the read and parse threads
boost::thread readThread(boost::bind(&PBFParser::ReadData, this));
//Open several parse threads that are synchronized before call to
boost::thread parseThread(boost::bind(&PBFParser::ParseData, this));
// Wait for the threads to finish
readThread.join();
parseThread.join();
return true;
}
private:
inline void ReadData();
inline void ParseData();
inline void parseDenseNode(_ThreadData * threadData);
inline void parseNode(_ThreadData * );
inline void parseRelation(_ThreadData * threadData);
inline void parseWay(_ThreadData * threadData);
inline void loadGroup(_ThreadData * threadData);
inline void loadBlock(_ThreadData * threadData);
inline bool readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData);
inline bool unpackZLIB(std::fstream &, _ThreadData * threadData);
inline bool unpackLZMA(std::fstream &, _ThreadData * );
inline bool readBlob(std::fstream& stream, _ThreadData * threadData) ;
inline bool readNextBlock(std::fstream& stream, _ThreadData * threadData);
inline 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;
ImportNode n;
std::vector<ImportNode> nodesToParse;
for(int i = 0, idSize = dense.id_size(); i < idSize; ++i) {
n.Clear();
m_lastDenseID += dense.id( i );
m_lastDenseLatitude += dense.lat( i );
m_lastDenseLongitude += dense.lon( i );
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()) {
const int tagValue = dense.keys_vals( denseTagIndex );
if(tagValue == 0) {
++denseTagIndex;
break;
}
const int keyValue = dense.keys_vals ( denseTagIndex+1 );
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data();
const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data();
n.keyVals.Add(key, value);
denseTagIndex += 2;
}
nodesToParse.push_back(n);
}
unsigned endi_nodes = nodesToParse.size();
#pragma omp parallel for schedule ( guided )
for(unsigned i = 0; i < endi_nodes; ++i) {
ImportNode &n = nodesToParse[i];
/** Pass the unpacked node to the LUA call back **/
try {
luabind::call_function<int>(
scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()),
"node_function",
boost::ref(n)
);
} catch (const luabind::error &er) {
lua_State* Ler=er.state();
report_errors(Ler, -1);
ERR(er.what());
}
// catch (...) {
// ERR("Unknown error occurred during PBF dense node parsing!");
// }
}
BOOST_FOREACH(ImportNode &n, nodesToParse) {
if(!externalMemory->nodeFunction(n))
std::cerr << "[PBFParser] dense node not parsed" << std::endl;
}
}
inline void parseNode(_ThreadData * ) {
ERR("Parsing of simple nodes not supported. PBF should use dense nodes");
}
inline void parseRelation(_ThreadData * threadData) {
//TODO: leave early, if relatio is not a restriction
//TODO: reuse rawRestriction container
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, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++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) {
if( "restriction" == val)
isRestriction = true;
else
break;
}
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) {
std::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.viaNode)
currentRestrictionContainer.viaNode = UINT_MAX;
assert(UINT_MAX == currentRestrictionContainer.viaNode);
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.viaNode = 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(!externalMemory->restrictionFunction(currentRestrictionContainer))
std::cerr << "[PBFParser] relation not parsed" << std::endl;
}
}
}
inline void parseWay(_ThreadData * threadData) {
_Way w;
std::vector<_Way> waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size());
for(int i = 0, ways_size = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); i < ways_size; ++i) {
w.Clear();
const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i );
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);
}
waysToParse.push_back(w);
}
unsigned endi_ways = waysToParse.size();
#pragma omp parallel for schedule ( guided )
for(unsigned i = 0; i < endi_ways; ++i) {
_Way & w = waysToParse[i];
/** Pass the unpacked way to the LUA call back **/
try {
luabind::call_function<int>(
scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()),
"way_function",
boost::ref(w),
w.path.size()
);
} catch (const luabind::error &er) {
lua_State* Ler=er.state();
report_errors(Ler, -1);
ERR(er.what());
}
// catch (...) {
// ERR("Unknown error!");
// }
}
BOOST_FOREACH(_Way & w, waysToParse) {
if(!externalMemory->wayFunction(w)) {
std::cerr << "[PBFParser] way not parsed" << std::endl;
}
}
}
inline void loadGroup(_ThreadData * threadData) {
#ifndef NDEBUG
++groupCount;
#endif
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 );
}
inline void loadBlock(_ThreadData * threadData) {
#ifndef NDEBUG
++blockCount;
#endif
threadData->currentGroupID = 0;
threadData->currentEntityID = 0;
}
/* Reverses Network Byte Order into something usable, compiles down to a bswap-mov combination */
inline unsigned swapEndian(unsigned x) const {
if(getMachineEndianness() == LittleEndian)
return ( (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24) );
return x;
}
inline 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 = new char[size];
stream.read(data, size*sizeof(data[0]));
bool dataSuccessfullyParsed = (threadData->PBFBlobHeader).ParseFromArray( data, size);
delete[] data;
return dataSuccessfullyParsed;
}
inline bool unpackZLIB(std::fstream &, _ThreadData * threadData) {
unsigned rawSize = threadData->PBFBlob.raw_size();
char* unpackedDataArray = new char[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;
delete[] 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;
delete[] unpackedDataArray;
return false;
}
ret = inflateEnd( &compressedDataStream );
if ( ret != Z_OK ) {
std::cerr << "[error] failed to deinit zlib stream" << std::endl;
delete[] unpackedDataArray;
return false;
}
threadData->charBuffer.clear(); threadData->charBuffer.resize(rawSize);
std::copy(unpackedDataArray, unpackedDataArray + rawSize, threadData->charBuffer.begin());
delete[] unpackedDataArray;
return true;
}
inline bool unpackLZMA(std::fstream &, _ThreadData * ) const {
return false;
}
inline bool readBlob(std::fstream& stream, _ThreadData * threadData) {
if(stream.eof())
return false;
const 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 = new char[size];
stream.read(data, sizeof(data[0])*size);
if ( !threadData->PBFBlob.ParseFromArray( data, size ) ) {
std::cerr << "[error] failed to parse blob" << std::endl;
delete[] data;
return false;
}
if ( threadData->PBFBlob.has_raw() ) {
const std::string& data = threadData->PBFBlob.raw();
threadData->charBuffer.clear();
threadData->charBuffer.resize( data.size() );
std::copy(data.begin(), data.end(), threadData->charBuffer.begin());
} else if ( threadData->PBFBlob.has_zlib_data() ) {
if ( !unpackZLIB(stream, threadData) ) {
std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
delete[] 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;
delete[] data;
return false;
} else {
std::cerr << "[error] Blob contains no data" << std::endl;
delete[] data;
return false;
}
delete[] data;
return true;
}
inline bool readNextBlock(std::fstream& stream, _ThreadData * threadData) {
if(stream.eof()) {
return false;
}
if ( !readPBFBlobHeader(stream, threadData) ){
return false;
}
if ( threadData->PBFBlobHeader.type() != "OSMData" ) {
return false;
}
if ( !readBlob(stream, threadData) ) {
return false;
}
if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) {
ERR("failed to parse PrimitiveBlock");
return false;
}
return true;
}
//Is optimized to a single 'mov eax,1' on GCC, clang and icc using -O3
inline Endianness getMachineEndianness() const {
int i(1);
char *p = (char *) &i;
if (1 == p[0])
return LittleEndian;
return BigEndian;
}
static const int NANO = 1000 * 1000 * 1000;
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
@@ -96,9 +586,15 @@ private:
unsigned groupCount;
unsigned blockCount;
#endif
ExtractorCallbacks * externalMemory;
/* the input stream to parse */
std::fstream input;
std::fstream input; // the input stream to parse
/* ThreadData Queue */
boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue;
ScriptingEnvironment scriptingEnvironment;
};
#endif /* PBFPARSER_H_ */
+63 -50
View File
@@ -18,16 +18,23 @@
or see http://www.gnu.org/licenses/agpl.txt.
*/
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include "ScriptingEnvironment.h"
#include "../typedefs.h"
#include "../Util/OpenMPWrapper.h"
ScriptingEnvironment::ScriptingEnvironment() {}
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
SimpleLogger().Write() << "Using script " << fileName;
INFO("Using script " << fileName);
// Create a new lua state
for(int i = 0; i < omp_get_max_threads(); ++i) {
for(int i = 0; i < omp_get_max_threads(); ++i)
luaStateVector.push_back(luaL_newstate());
}
// Connect LuaBind to this lua state for all threads
#pragma omp parallel
@@ -37,63 +44,69 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
//open utility libraries string library;
luaL_openlibs(myLuaState);
luaAddScriptFolderToLoadPath( myLuaState, fileName );
// Add our function to the state's global scope
luabind::module(myLuaState) [
luabind::def("print", LUA_print<std::string>),
luabind::def("parseMaxspeed", parseMaxspeed),
luabind::def("durationIsValid", durationIsValid),
luabind::def("parseDuration", parseDuration)
luabind::def("print", LUA_print<std::string>),
luabind::def("parseMaxspeed", parseMaxspeed),
luabind::def("durationIsValid", durationIsValid),
luabind::def("parseDuration", parseDuration)
];
//#pragma omp critical
// {
// if(0 != luaL_dostring(
// myLuaState,
// "print('Initializing LUA engine')\n"
// )) {
// ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
// }
// }
luabind::module(myLuaState) [
luabind::class_<HashTable<std::string, std::string> >("keyVals")
.def("Add", &HashTable<std::string, std::string>::Add)
.def("Find", &HashTable<std::string, std::string>::Find)
.def("Holds", &HashTable<std::string, std::string>::Holds)
];
luabind::module(myLuaState) [
luabind::class_<HashTable<std::string, std::string> >("keyVals")
.def("Add", &HashTable<std::string, std::string>::Add)
.def("Find", &HashTable<std::string, std::string>::Find)
.def("Holds", &HashTable<std::string, std::string>::Holds)
];
luabind::class_<ImportNode>("Node")
.def(luabind::constructor<>())
.def_readwrite("lat", &ImportNode::lat)
.def_readwrite("lon", &ImportNode::lon)
.def_readwrite("id", &ImportNode::id)
.def_readwrite("bollard", &ImportNode::bollard)
.def_readwrite("traffic_light", &ImportNode::trafficLight)
.def_readwrite("tags", &ImportNode::keyVals)
];
luabind::module(myLuaState) [
luabind::class_<ImportNode>("Node")
.def(luabind::constructor<>())
.def_readwrite("lat", &ImportNode::lat)
.def_readwrite("lon", &ImportNode::lon)
.def_readwrite("id", &ImportNode::id)
.def_readwrite("bollard", &ImportNode::bollard)
.def_readwrite("traffic_light", &ImportNode::trafficLight)
.def_readwrite("tags", &ImportNode::keyVals)
];
luabind::module(myLuaState) [
luabind::class_<ExtractionWay>("Way")
.def(luabind::constructor<>())
.def_readwrite("name", &ExtractionWay::name)
.def_readwrite("speed", &ExtractionWay::speed)
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
.def_readwrite("duration", &ExtractionWay::duration)
.def_readwrite("type", &ExtractionWay::type)
.def_readwrite("access", &ExtractionWay::access)
.def_readwrite("roundabout", &ExtractionWay::roundabout)
.def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
.def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
.def_readwrite("tags", &ExtractionWay::keyVals)
.def_readwrite("direction", &ExtractionWay::direction)
.enum_("constants") [
luabind::value("notSure", 0),
luabind::value("oneway", 1),
luabind::value("bidirectional", 2),
luabind::value("opposite", 3)
]
];
luabind::module(myLuaState) [
luabind::class_<std::vector<std::string> >("vector")
.def("Add", &std::vector<std::string>::push_back)
luabind::class_<_Way>("Way")
.def(luabind::constructor<>())
.def_readwrite("name", &_Way::name)
.def_readwrite("speed", &_Way::speed)
.def_readwrite("type", &_Way::type)
.def_readwrite("access", &_Way::access)
.def_readwrite("roundabout", &_Way::roundabout)
.def_readwrite("is_duration_set", &_Way::isDurationSet)
.def_readwrite("is_access_restricted", &_Way::isAccessRestricted)
.def_readwrite("ignore_in_grid", &_Way::ignoreInGrid)
.def_readwrite("tags", &_Way::keyVals)
.def_readwrite("direction", &_Way::direction)
.enum_("constants")
[
luabind::value("notSure", 0),
luabind::value("oneway", 1),
luabind::value("bidirectional", 2),
luabind::value("opposite", 3)
]
];
// Now call our function in a lua script
//#pragma omp critical
// {
// INFO("Parsing speedprofile from " << fileName );
// }
if(0 != luaL_dofile(myLuaState, fileName) ) {
throw OSRMException("ERROR occured in scripting block");
ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
}
}
}
+9 -7
View File
@@ -21,16 +21,18 @@
#ifndef SCRIPTINGENVIRONMENT_H_
#define SCRIPTINGENVIRONMENT_H_
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <luabind/luabind.hpp>
#include "ExtractionHelperFunctions.h"
#include "ExtractorStructs.h"
#include "../DataStructures/ImportNode.h"
#include "../Util/LuaUtil.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include "LuaUtil.h"
#include <vector>
#include "../DataStructures/ImportNode.h"
class ScriptingEnvironment {
public:
-277
View File
@@ -1,277 +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 "XMLParser.h"
#include "ExtractorStructs.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/InputReaderFactory.h"
#include <boost/ref.hpp>
XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) {
SimpleLogger().Write(logWARNING) <<
"Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf";
inputReader = inputReaderFactory(filename);
}
bool XMLParser::ReadHeader() {
return (xmlTextReaderRead( inputReader ) == 1);
}
bool XMLParser::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 ) {
ImportNode n = _ReadXMLNode();
ParseNodeInLua( n, luaState );
extractor_callbacks->nodeFunction(n);
// if(!extractor_callbacks->nodeFunction(n))
// std::cerr << "[XMLParser] dense node not parsed" << std::endl;
}
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
ExtractionWay way = _ReadXMLWay( );
ParseWayInLua( way, luaState );
extractor_callbacks->wayFunction(way);
// if(!extractor_callbacks->wayFunction(way))
// std::cerr << "[PBFParser] way not parsed" << std::endl;
}
if( use_turn_restrictions ) {
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
_RawRestrictionContainer r = _ReadXMLRestriction();
if(r.fromWay != UINT_MAX) {
if(!extractor_callbacks->restrictionFunction(r)) {
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
}
}
}
}
xmlFree( currentName );
}
return true;
}
_RawRestrictionContainer XMLParser::_ReadXMLRestriction() {
_RawRestrictionContainer restriction;
std::string except_tag_string;
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* ) "relation" ) == 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* ) "restriction" )){
if(0 == std::string((const char *) value).find("only_")) {
restriction.restriction.flags.isOnly = true;
}
}
if ( xmlStrEqual(k, (const xmlChar *) "except") ) {
except_tag_string = (const char*) value;
}
}
if ( k != NULL ) {
xmlFree( k );
}
if ( value != NULL ) {
xmlFree( value );
}
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) {
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
if ( ref != NULL ) {
xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" );
xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" );
if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) {
restriction.toWay = stringToUint((const char*) ref);
}
if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) {
restriction.fromWay = stringToUint((const char*) ref);
}
if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) {
restriction.restriction.viaNode = stringToUint((const char*) ref);
}
if(NULL != type) {
xmlFree( type );
}
if(NULL != role) {
xmlFree( role );
}
if(NULL != ref) {
xmlFree( ref );
}
}
}
xmlFree( childName );
}
}
if( ShouldIgnoreRestriction(except_tag_string) ) {
restriction.fromWay = UINT_MAX; //workaround to ignore the restriction
}
return restriction;
}
ExtractionWay XMLParser::_ReadXMLWay() {
ExtractionWay way;
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 ) {
xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
way.id = stringToUint((char*)id);
xmlFree(id);
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( stringToUint(( const char* ) ref ) );
xmlFree( ref );
}
}
xmlFree( childName );
}
}
return way;
}
ImportNode XMLParser::_ReadXMLNode() {
ImportNode node;
xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" );
if ( attribute != NULL ) {
node.lat = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ) );
xmlFree( attribute );
}
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" );
if ( attribute != NULL ) {
node.lon = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ));
xmlFree( attribute );
}
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
if ( attribute != NULL ) {
node.id = stringToUint(( 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 ) {
node.keyVals.Add(std::string( reinterpret_cast<char*>(k) ), std::string( reinterpret_cast<char*>(value)));
}
if ( k != NULL ) {
xmlFree( k );
}
if ( value != NULL ) {
xmlFree( value );
}
}
xmlFree( childName );
}
}
return node;
}
+289 -27
View File
@@ -1,46 +1,308 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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 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.
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.
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 "BaseParser.h"
#include "../DataStructures/Coordinate.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
#include <boost/ref.hpp>
#include <libxml/xmlreader.h>
#include "../typedefs.h"
#include "BaseParser.h"
#include "ExtractorStructs.h"
#include "ExtractorCallbacks.h"
#include "ScriptingEnvironment.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/InputReaderFactory.h"
class XMLParser : public BaseParser {
class XMLParser : public BaseParser<ExtractorCallbacks, _Node, _RawRestrictionContainer, _Way> {
public:
XMLParser(const char* filename, ExtractorCallbacks* ec, ScriptingEnvironment& se);
bool ReadHeader();
bool Parse();
XMLParser(const char * filename) : externalMemory(NULL), myLuaState(NULL){
WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf");
inputReader = inputReaderFactory(filename);
}
virtual ~XMLParser() {}
void RegisterCallbacks(ExtractorCallbacks * em) {
externalMemory = em;
}
void RegisterScriptingEnvironment(ScriptingEnvironment & _se) {
myLuaState = _se.getLuaStateForThreadID(0);
}
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 ) {
ImportNode n = _ReadXMLNode( );
/** Pass the unpacked node to the LUA call back **/
try {
luabind::call_function<int>(
myLuaState,
"node_function",
boost::ref(n)
);
if(!externalMemory->nodeFunction(n))
std::cerr << "[XMLParser] dense node not parsed" << std::endl;
} catch (const luabind::error &er) {
cerr << er.what() << endl;
lua_State* Ler=er.state();
report_errors(Ler, -1);
} catch (std::exception & e) {
ERR(e.what());
} catch (...) {
ERR("Unknown error occurred during XML node parsing!");
}
}
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
string name;
_Way way = _ReadXMLWay( );
/** Pass the unpacked way to the LUA call back **/
try {
luabind::call_function<int>(
myLuaState,
"way_function",
boost::ref(way),
way.path.size()
);
if(!externalMemory->wayFunction(way)) {
std::cerr << "[PBFParser] way not parsed" << std::endl;
}
} catch (const luabind::error &er) {
cerr << er.what() << endl;
lua_State* Ler=er.state();
report_errors(Ler, -1);
} catch (std::exception & e) {
ERR(e.what());
} catch (...) {
ERR("Unknown error occurred during XML way parsing!");
}
}
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
_RawRestrictionContainer r = _ReadXMLRestriction();
if(r.fromWay != UINT_MAX) {
if(!externalMemory->restrictionFunction(r)) {
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
}
}
}
xmlFree( currentName );
}
return true;
}
private:
_RawRestrictionContainer _ReadXMLRestriction();
ExtractionWay _ReadXMLWay();
ImportNode _ReadXMLNode();
_RawRestrictionContainer _ReadXMLRestriction ( ) {
_RawRestrictionContainer restriction;
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* ) "relation" ) == 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* ) "restriction" )){
if(0 == std::string((const char *) value).find("only_"))
restriction.restriction.flags.isOnly = true;
}
}
if ( k != NULL )
xmlFree( k );
if ( value != NULL )
xmlFree( value );
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) {
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
if ( ref != NULL ) {
xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" );
xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" );
if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) {
restriction.toWay = atoi((const char*) ref);
}
if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) {
restriction.fromWay = atoi((const char*) ref);
}
if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) {
restriction.restriction.viaNode = atoi((const char*) ref);
}
if(NULL != type)
xmlFree( type );
if(NULL != role)
xmlFree( role );
if(NULL != ref)
xmlFree( ref );
}
}
xmlFree( childName );
}
}
return restriction;
}
_Way _ReadXMLWay( ) {
_Way way;
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 ) {
xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
way.id = atoi((char*)id);
xmlFree(id);
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;
}
ImportNode _ReadXMLNode( ) {
ImportNode 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 ) {
node.keyVals.Add(std::string( reinterpret_cast<char*>(k) ), std::string( reinterpret_cast<char*>(value)));
}
if ( k != NULL )
xmlFree( k );
if ( value != NULL )
xmlFree( value );
}
xmlFree( childName );
}
}
return node;
}
/* Input Reader */
xmlTextReaderPtr inputReader;
//holds the callback functions and storage for our temporary data
ExtractorCallbacks * externalMemory;
lua_State *myLuaState;
};
#endif /* XMLPARSER_H_ */
-122
View File
@@ -1,122 +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.
*/
#include "OSRM.h"
OSRM::OSRM(const char * server_ini_path) {
if( !testDataFile(server_ini_path) ){
std::string error_message = std::string(server_ini_path) + " not found";
throw OSRMException(error_message.c_str());
}
IniFile serverConfig(server_ini_path);
boost::filesystem::path base_path =
boost::filesystem::absolute(server_ini_path).parent_path();
if ( !serverConfig.Holds("hsgrData")) {
throw OSRMException("no ram index file name in server ini");
}
if ( !serverConfig.Holds("ramIndex") ) {
throw OSRMException("no mem index file name in server ini");
}
if ( !serverConfig.Holds("fileIndex") ) {
throw OSRMException("no nodes file name in server ini");
}
if ( !serverConfig.Holds("nodesData") ) {
throw OSRMException("no nodes file name in server ini");
}
if ( !serverConfig.Holds("edgesData") ) {
throw OSRMException("no edges file name in server ini");
}
boost::filesystem::path hsgr_path = boost::filesystem::absolute(
serverConfig.GetParameter("hsgrData"),
base_path
);
boost::filesystem::path ram_index_path = boost::filesystem::absolute(
serverConfig.GetParameter("ramIndex"),
base_path
);
boost::filesystem::path file_index_path = boost::filesystem::absolute(
serverConfig.GetParameter("fileIndex"),
base_path
);
boost::filesystem::path node_data_path = boost::filesystem::absolute(
serverConfig.GetParameter("nodesData"),
base_path
);
boost::filesystem::path edge_data_path = boost::filesystem::absolute(
serverConfig.GetParameter("edgesData"),
base_path
);
boost::filesystem::path name_data_path = boost::filesystem::absolute(
serverConfig.GetParameter("namesData"),
base_path
);
boost::filesystem::path timestamp_path = boost::filesystem::absolute(
serverConfig.GetParameter("timestamp"),
base_path
);
objects = new QueryObjectsStorage(
hsgr_path.string(),
ram_index_path.string(),
file_index_path.string(),
node_data_path.string(),
edge_data_path.string(),
name_data_path.string(),
timestamp_path.string()
);
RegisterPlugin(new HelloWorldPlugin());
RegisterPlugin(new LocatePlugin(objects));
RegisterPlugin(new NearestPlugin(objects));
RegisterPlugin(new TimestampPlugin(objects));
RegisterPlugin(new ViaRoutePlugin(objects));
}
OSRM::~OSRM() {
BOOST_FOREACH(PluginMap::value_type & plugin_pointer, pluginMap) {
delete plugin_pointer.second;
}
delete objects;
}
void OSRM::RegisterPlugin(BasePlugin * plugin) {
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
if( pluginMap.find(plugin->GetDescriptor()) != pluginMap.end() ) {
delete pluginMap[plugin->GetDescriptor()];
}
pluginMap.insert(std::make_pair(plugin->GetDescriptor(), plugin));
}
void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
const PluginMap::const_iterator & iter = pluginMap.find(route_parameters.service);
if(pluginMap.end() != iter) {
reply.status = http::Reply::ok;
iter->second->HandleRequest(route_parameters, reply );
} else {
reply = http::Reply::stockReply(http::Reply::badRequest);
}
}
-58
View File
@@ -1,58 +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 OSRM_H
#define OSRM_H
#include "OSRM.h"
#include "../Plugins/BasePlugin.h"
#include "../Plugins/HelloWorldPlugin.h"
#include "../Plugins/LocatePlugin.h"
#include "../Plugins/NearestPlugin.h"
#include "../Plugins/TimestampPlugin.h"
#include "../Plugins/ViaRoutePlugin.h"
#include "../Server/DataStructures/RouteParameters.h"
#include "../Util/IniFile.h"
#include "../Util/InputFileUtil.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../Server/BasicDatastructures.h"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/noncopyable.hpp>
#include <boost/thread.hpp>
#include <vector>
class OSRM : boost::noncopyable {
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap;
QueryObjectsStorage * objects;
public:
OSRM(const char * server_ini_path);
~OSRM();
void RunQuery(RouteParameters & route_parameters, http::Reply & reply);
private:
void RegisterPlugin(BasePlugin * plugin);
PluginMap pluginMap;
};
#endif //OSRM_H
+6 -17
View File
@@ -21,32 +21,21 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef BASEPLUGIN_H_
#define BASEPLUGIN_H_
#include "../DataStructures/Coordinate.h"
#include "../Server/BasicDatastructures.h"
#include "../Server/DataStructures/RouteParameters.h"
#include <cassert>
#include <string>
#include <vector>
#include "RouteParameters.h"
#include "../Server/BasicDatastructures.h"
class BasePlugin {
public:
BasePlugin() { }
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
virtual ~BasePlugin() { }
virtual const std::string & GetDescriptor() const = 0;
virtual std::string GetDescriptor() const = 0;
virtual std::string GetVersionString() const = 0 ;
virtual void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) = 0;
inline bool checkCoord(const FixedPointCoordinate & c) {
if(
c.lat > 90*COORDINATE_PRECISION ||
c.lat < -90*COORDINATE_PRECISION ||
c.lon > 180*COORDINATE_PRECISION ||
c.lon < -180*COORDINATE_PRECISION
) {
return false;
}
return true;
}
};
#endif /* BASEPLUGIN_H_ */
+12 -25
View File
@@ -1,35 +1,24 @@
/*
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.
* LocatePlugin.h
*
* Created on: 01.01.2011
* Author: dennis
*/
#ifndef HELLOWORLDPLUGIN_H_
#define HELLOWORLDPLUGIN_H_
#include "BasePlugin.h"
#include <sstream>
#include "BasePlugin.h"
#include "RouteParameters.h"
class HelloWorldPlugin : public BasePlugin {
public:
HelloWorldPlugin() : descriptor_string("hello"){}
virtual ~HelloWorldPlugin() { }
const std::string & GetDescriptor() const { return descriptor_string; }
HelloWorldPlugin() {}
virtual ~HelloWorldPlugin() { /*std::cout << GetDescriptor() << " destructor" << std::endl;*/ }
std::string GetDescriptor() const { return std::string("hello"); }
std::string GetVersionString() const { return std::string("0.1a"); }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
reply.status = http::Reply::ok;
@@ -46,7 +35,7 @@ public:
content << "language: " << routeParameters.language << "<br>";
content << "Number of locations: " << routeParameters.coordinates.size() << "\n";
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
content << " [" << i << "] " << routeParameters.coordinates[i].lat/COORDINATE_PRECISION << "," << routeParameters.coordinates[i].lon/COORDINATE_PRECISION << "\n";
content << " [" << i << "] " << routeParameters.coordinates[i].lat/100000. << "," << routeParameters.coordinates[i].lon/100000. << "\n";
}
content << "Number of hints: " << routeParameters.hints.size() << "\n";
for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
@@ -56,8 +45,6 @@ public:
reply.content.append(content.str());
reply.content.append("</body></html>");
}
private:
std::string descriptor_string;
};
#endif /* HELLOWORLDPLUGIN_H_ */
+19 -10
View File
@@ -21,20 +21,24 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef LOCATEPLUGIN_H_
#define LOCATEPLUGIN_H_
#include "BasePlugin.h"
#include "../DataStructures/NodeInformationHelpDesk.h"
#include <fstream>
#include "../Server/DataStructures/QueryObjectsStorage.h"
#include "BasePlugin.h"
#include "RouteParameters.h"
#include "../Util/StringUtil.h"
#include "../DataStructures/NodeInformationHelpDesk.h"
/*
* This Plugin locates the nearest node in the road network for a given coordinate.
*/
class LocatePlugin : public BasePlugin {
public:
LocatePlugin(QueryObjectsStorage * objects) : descriptor_string("locate") {
LocatePlugin(QueryObjectsStorage * objects) {
nodeHelpDesk = objects->nodeHelpDesk;
}
const std::string & GetDescriptor() const { return descriptor_string; }
std::string GetDescriptor() const { return std::string("locate"); }
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
//check number of parameters
if(!routeParameters.coordinates.size()) {
@@ -47,13 +51,13 @@ public:
}
//query to helpdesk
FixedPointCoordinate result;
std::string tmp;
_Coordinate result;
std::string JSONParameter, tmp;
//json
// JSONParameter = routeParameters.options.Find("jsonp");
if("" != routeParameters.jsonpParameter) {
reply.content += routeParameters.jsonpParameter;
reply.content += JSONParameter;
reply.content += "(";
}
reply.status = http::Reply::ok;
@@ -78,7 +82,7 @@ public:
reply.content += ",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\"";
reply.content += ("}");
reply.headers.resize(3);
if("" != routeParameters.jsonpParameter) {
if("" != JSONParameter) {
reply.content += ")";
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
@@ -95,10 +99,15 @@ public:
reply.headers[0].value = tmp;
return;
}
private:
inline bool checkCoord(const _Coordinate & c) {
if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) {
return false;
}
return true;
}
NodeInformationHelpDesk * nodeHelpDesk;
std::string descriptor_string;
};
#endif /* LOCATEPLUGIN_H_ */
+19 -12
View File
@@ -21,10 +21,14 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef NearestPlugin_H_
#define NearestPlugin_H_
#include <fstream>
#include "BasePlugin.h"
#include "RouteParameters.h"
#include "../Server/DataStructures/QueryObjectsStorage.h"
#include "../DataStructures/NodeInformationHelpDesk.h"
#include "../Server/DataStructures/QueryObjectsStorage.h"
#include "../Util/StringUtil.h"
/*
@@ -32,17 +36,14 @@ or see http://www.gnu.org/licenses/agpl.txt.
*/
class NearestPlugin : public BasePlugin {
public:
NearestPlugin(QueryObjectsStorage * objects )
:
names(objects->names),
descriptor_string("nearest")
{
NearestPlugin(QueryObjectsStorage * objects) : names(objects->names) {
nodeHelpDesk = objects->nodeHelpDesk;
descriptorTable.insert(std::make_pair("" , 0)); //default descriptor
descriptorTable.insert(std::make_pair("json", 1));
descriptorTable.Set("", 0); //default descriptor
descriptorTable.Set("json", 1);
}
const std::string & GetDescriptor() const { return descriptor_string; }
std::string GetDescriptor() const { return std::string("nearest"); }
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
//check number of parameters
if(!routeParameters.coordinates.size()) {
@@ -59,6 +60,7 @@ public:
nodeHelpDesk->FindPhantomNodeForCoordinate(routeParameters.coordinates[0], result, routeParameters.zoomLevel);
std::string tmp;
std::string JSONParameter;
//json
if("" != routeParameters.jsonpParameter) {
@@ -91,7 +93,7 @@ public:
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\"";
reply.content += ("}");
reply.headers.resize(3);
if("" != routeParameters.jsonpParameter) {
if("" != JSONParameter) {
reply.content += ")";
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
@@ -107,12 +109,17 @@ public:
intToString(reply.content.size(), tmp);
reply.headers[0].value = tmp;
}
private:
inline bool checkCoord(const _Coordinate & c) {
if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) {
return false;
}
return true;
}
NodeInformationHelpDesk * nodeHelpDesk;
HashTable<std::string, unsigned> descriptorTable;
std::vector<std::string> & names;
std::string descriptor_string;
};
#endif /* NearestPlugin_H_ */
@@ -18,22 +18,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef OSRM_EXCEPTION_H
#define OSRM_EXCEPTION_H
#ifndef PLUGINMAPFACTORY_H_
#define PLUGINMAPFACTORY_H_
#include <exception>
#include <string>
//#include "../DataStructures/HashTable.h"
//#include "../Plugins/BasePlugin.h"
//
//struct PluginMapFactory {
// static HashTable<std::string, BasePlugin *> * CreatePluginMap() {
// HashTable<std::string, BasePlugin *> * map = new HashTable<std::string, BasePlugin *>();
//
// }
//};
class OSRMException: public std::exception {
public:
OSRMException(const char * message) : message(message) {}
OSRMException(const std::string & message) : message(message) {}
virtual ~OSRMException() throw() {}
private:
virtual const char* what() const throw() {
return message.c_str();
}
const std::string message;
};
#endif /* OSRM_EXCEPTION_H */
#endif /* PLUGINMAPFACTORY_H_ */
@@ -21,12 +21,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef RAWROUTEDATA_H_
#define RAWROUTEDATA_H_
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/PhantomNodes.h"
#include "../typedefs.h"
#include <vector>
struct _PathData {
_PathData(NodeID no, unsigned na, unsigned tu, unsigned dur) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu) { }
NodeID node;
@@ -39,7 +35,7 @@ struct RawRouteData {
std::vector< _PathData > computedShortestPath;
std::vector< _PathData > computedAlternativePath;
std::vector< PhantomNodes > segmentEndCoordinates;
std::vector< FixedPointCoordinate > rawViaNodeCoordinates;
std::vector< _Coordinate > rawViaNodeCoordinates;
unsigned checkSum;
int lengthOfShortestPath;
int lengthOfAlternativePath;
@@ -21,25 +21,15 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef ROUTE_PARAMETERS_H
#define ROUTE_PARAMETERS_H
#include "../../DataStructures/Coordinate.h"
#include "../../DataStructures/HashTable.h"
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/sequence/intrinsic.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <string>
#include <vector>
#include <boost/fusion/sequence/intrinsic.hpp>
#include "../DataStructures/Coordinate.h"
struct RouteParameters {
RouteParameters() :
zoomLevel(18),
printInstructions(false),
alternateRoute(true),
geometry(true),
compression(true),
deprecatedAPI(false),
checkSum(-1) {}
RouteParameters() : zoomLevel(18), printInstructions(false), alternateRoute(true), geometry(true), compression(true), deprecatedAPI(false), checkSum(-1) {}
short zoomLevel;
bool printInstructions;
bool alternateRoute;
@@ -52,13 +42,12 @@ struct RouteParameters {
std::string jsonpParameter;
std::string language;
std::vector<std::string> hints;
std::vector<FixedPointCoordinate> coordinates;
typedef HashTable<std::string, std::string>::const_iterator OptionsIterator;
std::vector<_Coordinate> coordinates;
typedef HashTable<std::string, std::string>::MyIterator OptionsIterator;
void setZoomLevel(const short i) {
if (18 > i && 0 < i) {
if (18 > i && 0 < i)
zoomLevel = i;
}
}
void setAlternateRouteFlag(const bool b) {
@@ -106,11 +95,13 @@ struct RouteParameters {
compression = b;
}
void addCoordinate(const boost::fusion::vector < double, double > & arg_) {
int lat = COORDINATE_PRECISION*boost::fusion::at_c < 0 > (arg_);
int lon = COORDINATE_PRECISION*boost::fusion::at_c < 1 > (arg_);
coordinates.push_back(FixedPointCoordinate(lat, lon));
void addCoordinate(boost::fusion::vector < double, double > arg_) {
int lat = 100000.*boost::fusion::at_c < 0 > (arg_);
int lon = 100000.*boost::fusion::at_c < 1 > (arg_);
_Coordinate myCoordinate(lat, lon);
coordinates.push_back(_Coordinate(lat, lon));
}
};
#endif /*ROUTE_PARAMETERS_H*/
+7 -5
View File
@@ -21,14 +21,17 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef TIMESTAMPPLUGIN_H_
#define TIMESTAMPPLUGIN_H_
#include <cassert>
#include "BasePlugin.h"
#include "RouteParameters.h"
class TimestampPlugin : public BasePlugin {
public:
TimestampPlugin(QueryObjectsStorage * o)
: objects(o), descriptor_string("timestamp")
{ }
const std::string & GetDescriptor() const { return descriptor_string; }
TimestampPlugin(QueryObjectsStorage * o) : objects(o) {
}
std::string GetDescriptor() const { return std::string("timestamp"); }
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
std::string tmp;
@@ -67,7 +70,6 @@ public:
}
private:
QueryObjectsStorage * objects;
std::string descriptor_string;
};
#endif /* TIMESTAMPPLUGIN_H_ */
+48 -40
View File
@@ -21,24 +21,29 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef VIAROUTEPLUGIN_H_
#define VIAROUTEPLUGIN_H_
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include "BasePlugin.h"
#include "RouteParameters.h"
#include "../Algorithms/ObjectToBase64.h"
#include "../Descriptors/BaseDescriptor.h"
#include "../Descriptors/GPXDescriptor.h"
#include "../Descriptors/JSONDescriptor.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/StaticGraph.h"
#include "../DataStructures/SearchEngine.h"
#include "../Descriptors/BaseDescriptor.h"
#include "../Descriptors/GPXDescriptor.h"
#include "../Descriptors/JSONDescriptor.h"
#include "../Server/DataStructures/QueryObjectsStorage.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include <cstdlib>
#include <string>
#include <vector>
#include "../Server/DataStructures/QueryObjectsStorage.h"
class ViaRoutePlugin : public BasePlugin {
private:
@@ -46,30 +51,27 @@ private:
std::vector<std::string> & names;
StaticGraph<QueryEdge::EdgeData> * graph;
HashTable<std::string, unsigned> descriptorTable;
SearchEngine * searchEnginePtr;
std::string pluginDescriptorString;
SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > * searchEngine;
public:
ViaRoutePlugin(QueryObjectsStorage * objects)
:
names(objects->names),
descriptor_string("viaroute")
{
ViaRoutePlugin(QueryObjectsStorage * objects, std::string psd = "viaroute") : names(objects->names), pluginDescriptorString(psd) {
nodeHelpDesk = objects->nodeHelpDesk;
graph = objects->graph;
searchEnginePtr = new SearchEngine(graph, nodeHelpDesk, names);
searchEngine = new SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> >(graph, nodeHelpDesk, names);
descriptorTable.insert(std::make_pair("" , 0));
descriptorTable.insert(std::make_pair("json", 0));
descriptorTable.insert(std::make_pair("gpx" , 1));
descriptorTable.Set("", 0); //default descriptor
descriptorTable.Set("json", 0);
descriptorTable.Set("gpx", 1);
}
virtual ~ViaRoutePlugin() {
delete searchEnginePtr;
delete searchEngine;
}
const std::string & GetDescriptor() const { return descriptor_string; }
std::string GetDescriptor() const { return pluginDescriptorString; }
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
//check number of parameters
if( 2 > routeParameters.coordinates.size() ) {
@@ -91,15 +93,15 @@ public:
std::vector<PhantomNode> phantomNodeVector(rawRoute.rawViaNodeCoordinates.size());
for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) {
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
// SimpleLogger().Write() <<"Decoding hint: " << routeParameters.hints[i] << " for location index " << i;
DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]);
// INFO("Decoding hint: " << routeParameters.hints[i] << " for location index " << i);
DecodeObjectFromBase64(phantomNodeVector[i], routeParameters.hints[i]);
if(phantomNodeVector[i].isValid(nodeHelpDesk->getNumberOfNodes())) {
// SimpleLogger().Write() << "Decoded hint " << i << " successfully";
// INFO("Decoded hint " << i << " successfully");
continue;
}
}
// SimpleLogger().Write() << "Brute force lookup of coordinate " << i;
searchEnginePtr->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], routeParameters.zoomLevel);
// INFO("Brute force lookup of coordinate " << i);
searchEngine->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], routeParameters.zoomLevel);
}
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
@@ -109,21 +111,21 @@ public:
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
}
if( ( routeParameters.alternateRoute ) && (1 == rawRoute.segmentEndCoordinates.size()) ) {
// SimpleLogger().Write() << "Checking for alternative paths";
searchEnginePtr->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute);
// INFO("Checking for alternative paths");
searchEngine->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute);
} else {
searchEnginePtr->shortestPath(rawRoute.segmentEndCoordinates, rawRoute);
searchEngine->shortestPath(rawRoute.segmentEndCoordinates, rawRoute);
}
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
DEBUG( "Error occurred, single path not found" );
}
reply.status = http::Reply::ok;
//TODO: Move to member as smart pointer
BaseDescriptor * desc;
BaseDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > > * desc;
if("" != routeParameters.jsonpParameter) {
reply.content += routeParameters.jsonpParameter;
reply.content += "(";
@@ -138,28 +140,28 @@ public:
switch(descriptorType){
case 0:
desc = new JSONDescriptor();
desc = new JSONDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > >();
break;
case 1:
desc = new GPXDescriptor();
desc = new GPXDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > >();
break;
default:
desc = new JSONDescriptor();
desc = new JSONDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > >();
break;
}
PhantomNodes phantomNodes;
phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom;
// SimpleLogger().Write() << "Start location: " << phantomNodes.startPhantom.location;
// INFO("Start location: " << phantomNodes.startPhantom.location)
phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom;
// SimpleLogger().Write() << "TargetLocation: " << phantomNodes.targetPhantom.location;
// SimpleLogger().Write() << "Number of segments: " << rawRoute.segmentEndCoordinates.size();
// INFO("TargetLocation: " << phantomNodes.targetPhantom.location);
// INFO("Number of segments: " << rawRoute.segmentEndCoordinates.size());
desc->SetConfig(descriptorConfig);
desc->Run(reply, rawRoute, phantomNodes, *searchEnginePtr);
desc->Run(reply, rawRoute, phantomNodes, *searchEngine);
if("" != routeParameters.jsonpParameter) {
reply.content += ")\n";
}
@@ -202,6 +204,7 @@ public:
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.json\"";
}
break;
}
@@ -209,7 +212,12 @@ public:
return;
}
private:
std::string descriptor_string;
inline bool checkCoord(const _Coordinate & c) {
if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) {
return false;
}
return true;
}
};
-40
View File
@@ -1,40 +0,0 @@
# Readme
For instructions on how to compile and run OSRM, please consult the Wiki at
https://github.com/DennisOSRM/Project-OSRM/wiki
or use our free and daily updated online service at
http://map.project-osrm.org
## References in publications
When using the code in a (scientific) publication, please cite
```
@inproceedings{luxen-vetter-2011,
author = {Luxen, Dennis and Vetter, Christian},
title = {Real-time routing with OpenStreetMap data},
booktitle = {Proceedings of the 19th ACM SIGSPATIAL International Conference on Advances in Geographic Information Systems},
series = {GIS '11},
year = {2011},
isbn = {978-1-4503-1031-4},
location = {Chicago, Illinois},
pages = {513--516},
numpages = {4},
url = {http://doi.acm.org/10.1145/2093973.2094062},
doi = {10.1145/2093973.2094062},
acmid = {2094062},
publisher = {ACM},
address = {New York, NY, USA},
}
```
## Current build status
| build config | branch | status |
|:-------------|:--------|:------------|
| Project OSRM | master | [![Build Status](https://travis-ci.org/DennisOSRM/Project-OSRM.png?branch=master)](https://travis-ci.org/DennisOSRM/Project-OSRM) |
| Project OSRM | develop | [![Build Status](https://travis-ci.org/DennisOSRM/Project-OSRM.png?branch=develop)](https://travis-ci.org/DennisOSRM/Project-OSRM) |
| LUAbind fork | master | [![Build Status](https://travis-ci.org/DennisOSRM/luabind.png?branch=master)](https://travis-ci.org/DennisOSRM/luabind) |
+10 -32
View File
@@ -4,11 +4,9 @@ require 'digest/sha1'
require 'cucumber/rake/task'
require 'sys/proctable'
BUILD_FOLDER = 'build'
DATA_FOLDER = 'sandbox'
PROFILE = 'bicycle'
OSRM_PORT = 5000
PROFILES_FOLDER = '../profiles'
Cucumber::Rake::Task.new do |t|
t.cucumber_opts = %w{--format pretty}
@@ -18,7 +16,7 @@ areas = {
:kbh => { :country => 'denmark', :bbox => 'top=55.6972 left=12.5222 right=12.624 bottom=55.6376' },
:frd => { :country => 'denmark', :bbox => 'top=55.7007 left=12.4765 bottom=55.6576 right=12.5698' },
:regh => { :country => 'denmark', :bbox => 'top=56.164 left=11.792 bottom=55.403 right=12.731' },
:denmark => { :country => 'denmark', :bbox => nil },
:dk => { :country => 'denmark', :bbox => nil },
:skaane => { :country => 'sweden', :bbox => 'top=56.55 left=12.4 bottom=55.3 right=14.6' }
}
@@ -78,17 +76,11 @@ end
desc "Rebuild and run tests."
task :default => [:build]
task :default => [:build, :cucumber]
desc "Build using CMake."
desc "Build using SConsstruct."
task :build do
if Dir.exists? BUILD_FOLDER
Dir.chdir BUILD_FOLDER do
system "make"
end
else
system "mkdir build; cd build; cmake ..; make"
end
system "scons"
end
desc "Setup config files."
@@ -106,8 +98,8 @@ desc "Download OSM data."
task :download => :setup do
Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
puts "Downloading..."
puts "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
raise "Error while downloading data." unless system "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
puts "curl http://download.geofabrik.de/openstreetmap/europe/#{osm_data_country}.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
raise "Error while downloading data." unless system "curl http://download.geofabrik.de/openstreetmap/europe/#{osm_data_country}.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
if osm_data_area_bbox
puts "Cropping and converting to protobuffer..."
raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true"
@@ -124,27 +116,13 @@ end
desc "Reprocess OSM data."
task :process => :setup do
Dir.chdir DATA_FOLDER do
raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf #{PROFILES_FOLDER}/#{PROFILE}.lua"
raise "Error while extracting data." unless system "../osrm-extract #{osm_data_area_name}.osm.pbf ../profiles/#{PROFILE}.lua"
puts
raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions #{PROFILES_FOLDER}/#{PROFILE}.lua"
raise "Error while preparing data." unless system "../osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions ../profiles/#{PROFILE}.lua"
puts
end
end
desc "Extract OSM data."
task :extract => :setup do
Dir.chdir DATA_FOLDER do
raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf ../profiles/#{PROFILE}.lua"
end
end
desc "Prepare OSM data."
task :prepare => :setup do
Dir.chdir DATA_FOLDER do
raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions ../profiles/#{PROFILE}.lua"
end
end
desc "Delete preprocessing files."
task :clean do
File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm")
@@ -161,7 +139,7 @@ desc "Run the routing server in the terminal. Press Ctrl-C to stop."
task :run => :setup do
Dir.chdir DATA_FOLDER do
write_server_ini osm_data_area_name
system "../#{BUILD_FOLDER}/osrm-routed"
system "../osrm-routed"
end
end
@@ -170,7 +148,7 @@ task :up => :setup do
Dir.chdir DATA_FOLDER do
abort("Already up.") if up?
write_server_ini osm_data_area_name
pipe = IO.popen("../#{BUILD_FOLDER}/osrm-routed 1>>osrm-routed.log 2>>osrm-routed.log")
pipe = IO.popen('../osrm-routed 1>>osrm-routed.log 2>>osrm-routed.log')
timeout = 5
(timeout*10).times do
begin
+148 -205
View File
@@ -21,24 +21,23 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef ALTERNATIVEROUTES_H_
#define ALTERNATIVEROUTES_H_
#include "BasicRoutingInterface.h"
#include <boost/unordered_map.hpp>
#include <cmath>
#include <vector>
const double VIAPATH_ALPHA = 0.15;
const double VIAPATH_EPSILON = 0.10; //alternative at most 15% longer
const double VIAPATH_GAMMA = 0.75; //alternative shares at most 75% with the shortest.
#include "BasicRoutingInterface.h"
const double VIAPATH_ALPHA = 0.25;
const double VIAPATH_EPSILON = 0.25;
const double VIAPATH_GAMMA = 0.80;
template<class QueryDataT>
class AlternativeRouting : private BasicRoutingInterface<QueryDataT> {
class AlternativeRouting : private BasicRoutingInterface<QueryDataT>{
typedef BasicRoutingInterface<QueryDataT> super;
typedef typename QueryDataT::Graph SearchGraph;
typedef typename QueryDataT::QueryHeap QueryHeap;
typedef std::pair<NodeID, NodeID> SearchSpaceEdge;
typedef std::pair<NodeID, int> PreselectedNode;
typedef typename QueryDataT::HeapPtr HeapPtr;
typedef std::pair<NodeID, NodeID> UnpackEdge;
struct RankedCandidateNode {
RankedCandidateNode(const NodeID n, const int l, const int s) : node(n), length(l), sharing(s) {}
RankedCandidateNode(NodeID n, int l, int s) : node(n), length(l), sharing(s) {}
NodeID node;
int length;
int sharing;
@@ -46,12 +45,9 @@ class AlternativeRouting : private BasicRoutingInterface<QueryDataT> {
return (2*length + sharing) < (2*other.length + other.sharing);
}
};
const SearchGraph * search_graph;
public:
AlternativeRouting(QueryDataT & qd) : super(qd), search_graph(qd.graph) { }
AlternativeRouting(QueryDataT & qd) : super(qd) { }
~AlternativeRouting() {}
@@ -63,115 +59,81 @@ public:
std::vector<NodeID> alternativePath;
std::vector<NodeID> viaNodeCandidates;
std::vector<SearchSpaceEdge> forward_search_space;
std::vector<SearchSpaceEdge> reverse_search_space;
std::vector <NodeID> packedShortestPath;
std::vector<PreselectedNode> nodesThatPassPreselection;
//Initialize Queues, semi-expensive because access to TSS invokes a system call
HeapPtr & forwardHeap = super::_queryData.forwardHeap;
HeapPtr & backwardHeap = super::_queryData.backwardHeap;
HeapPtr & forwardHeap2 = super::_queryData.forwardHeap2;
HeapPtr & backwardHeap2 = super::_queryData.backwardHeap2;
//Initialize Queues
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap);
QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap);
QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2);
QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2);
int upper_bound_to_shortest_path_distance = INT_MAX;
NodeID middle_node = UINT_MAX;
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
int _upperBound = INT_MAX;
NodeID middle = UINT_MAX;
forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
if(phantomNodePair.startPhantom.isBidirected() ) {
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
}
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
if(phantomNodePair.targetPhantom.isBidirected() ) {
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
}
const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
const int offset = (phantomNodePair.startPhantom.isBidirected() ? std::max(phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.weight2) : phantomNodePair.startPhantom.weight1)
+ (phantomNodePair.targetPhantom.isBidirected() ? std::max(phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.weight2) : phantomNodePair.targetPhantom.weight1);
//exploration dijkstra from nodes s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
while(0 < (forward_heap1.Size() + reverse_heap1.Size())){
if(0 < forward_heap1.Size()){
AlternativeRoutingStep<true >(forward_heap1, reverse_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, forward_search_space, forward_offset);
while(forwardHeap->Size() + backwardHeap->Size() > 0){
if(forwardHeap->Size() > 0){
AlternativeRoutingStep(forwardHeap, backwardHeap, &middle, &_upperBound, 2*offset, true, viaNodeCandidates);
}
if(0 < reverse_heap1.Size()){
AlternativeRoutingStep<false>(reverse_heap1, forward_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, reverse_search_space, reverse_offset);
if(backwardHeap->Size() > 0){
AlternativeRoutingStep(backwardHeap, forwardHeap, &middle, &_upperBound, 2*offset, false, viaNodeCandidates);
}
}
sort_unique_resize(viaNodeCandidates);
std::sort(viaNodeCandidates.begin(), viaNodeCandidates.end());
int size = std::unique(viaNodeCandidates.begin(), viaNodeCandidates.end())- viaNodeCandidates.begin();
viaNodeCandidates.resize(size);
std::vector<NodeID> packed_forward_path;
std::vector<NodeID> packed_reverse_path;
//save (packed) shortest path of shortest path and keep it for later use.
//we need it during the checks and dont want to recompute it always
super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle, packedShortestPath);
super::RetrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path);
super::RetrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path);
boost::unordered_map<NodeID, int> approximated_forward_sharing;
boost::unordered_map<NodeID, int> approximated_reverse_sharing;
unsigned index_into_forward_path = 0;
//sweep over search space, compute forward sharing for each current edge (u,v)
BOOST_FOREACH(const SearchSpaceEdge & current_edge, forward_search_space) {
const NodeID u = current_edge.first;
const NodeID v = current_edge.second;
if(packed_forward_path.size() < index_into_forward_path && current_edge == forward_search_space[index_into_forward_path]) {
//current_edge is on shortest path => sharing(u):=queue.GetKey(u);
++index_into_forward_path;
approximated_forward_sharing[v] = forward_heap1.GetKey(u);
} else {
//sharing (s) = sharing (t)
approximated_forward_sharing[v] = approximated_forward_sharing[u];
}
}
unsigned index_into_reverse_path = 0;
//sweep over search space, compute backward sharing
BOOST_FOREACH(const SearchSpaceEdge & current_edge, reverse_search_space) {
const NodeID u = current_edge.first;
const NodeID v = current_edge.second;
if(packed_reverse_path.size() < index_into_reverse_path && current_edge == reverse_search_space[index_into_reverse_path]) {
//current_edge is on shortest path => sharing(u):=queue.GetKey(u);
++index_into_reverse_path;
approximated_reverse_sharing[v] = reverse_heap1.GetKey(u);
} else {
//sharing (s) = sharing (t)
approximated_reverse_sharing[v] = approximated_reverse_sharing[u];
}
}
std::vector<NodeID> nodes_that_passed_preselection;
//ch-pruning of via nodes in both search spaces
BOOST_FOREACH(const NodeID node, viaNodeCandidates) {
int approximated_sharing = approximated_forward_sharing[node] + approximated_reverse_sharing[node];
int approximated_length = forward_heap1.GetKey(node)+reverse_heap1.GetKey(node);
bool lengthPassed = (approximated_length < upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON));
bool sharingPassed = (approximated_sharing <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA);
bool stretchPassed = approximated_length - approximated_sharing < (1.+VIAPATH_EPSILON)*(upper_bound_to_shortest_path_distance-approximated_sharing);
if(node == middle) //subpath optimality tells us that this case is just the shortest path
continue;
if(lengthPassed && sharingPassed && stretchPassed) {
nodes_that_passed_preselection.push_back(node);
}
int sharing = approximateAmountOfSharing(node, forwardHeap, backwardHeap, packedShortestPath);
int length1 = forwardHeap->GetKey(node);
int length2 = backwardHeap->GetKey(node);
bool lengthPassed = (length1+length2 < _upperBound*(1+VIAPATH_EPSILON));
bool sharingPassed = (sharing <= _upperBound*VIAPATH_GAMMA);
bool stretchPassed = length1+length2 - sharing < (1.+VIAPATH_EPSILON)*(_upperBound-sharing);
if(lengthPassed && sharingPassed && stretchPassed)
nodesThatPassPreselection.push_back(std::make_pair(node, length1+length2));
}
std::vector<NodeID> & packedShortestPath = packed_forward_path;
std::reverse(packedShortestPath.begin(), packedShortestPath.end());
packedShortestPath.push_back(middle_node);
packedShortestPath.insert(packedShortestPath.end(),packed_reverse_path.begin(), packed_reverse_path.end());
std::vector<RankedCandidateNode > rankedCandidates;
//prioritizing via nodes for deep inspection
BOOST_FOREACH(const NodeID node, nodes_that_passed_preselection) {
BOOST_FOREACH(const PreselectedNode node, nodesThatPassPreselection) {
int lengthOfViaPath = 0, sharingOfViaPath = 0;
computeLengthAndSharingOfViaPath(node, &lengthOfViaPath, &sharingOfViaPath, forward_offset+reverse_offset, packedShortestPath);
if(sharingOfViaPath <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA) {
rankedCandidates.push_back(RankedCandidateNode(node, lengthOfViaPath, sharingOfViaPath));
}
computeLengthAndSharingOfViaPath(node, &lengthOfViaPath, &sharingOfViaPath, offset, packedShortestPath);
if(sharingOfViaPath <= VIAPATH_GAMMA*_upperBound)
rankedCandidates.push_back(RankedCandidateNode(node.first, lengthOfViaPath, sharingOfViaPath));
}
std::sort(rankedCandidates.begin(), rankedCandidates.end());
NodeID selectedViaNode = UINT_MAX;
int lengthOfViaPath = INT_MAX;
NodeID s_v_middle = UINT_MAX, v_t_middle = UINT_MAX;
BOOST_FOREACH(const RankedCandidateNode & candidate, rankedCandidates){
if(viaNodeCandidatePasses_T_Test(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, candidate, forward_offset+reverse_offset, upper_bound_to_shortest_path_distance, &lengthOfViaPath, &s_v_middle, &v_t_middle)) {
BOOST_FOREACH(const RankedCandidateNode candidate, rankedCandidates){
if(viaNodeCandidatePasses_T_Test(forwardHeap, backwardHeap, forwardHeap2, backwardHeap2, candidate, offset, _upperBound, &lengthOfViaPath, &s_v_middle, &v_t_middle)) {
// select first admissable
selectedViaNode = candidate.node;
break;
@@ -179,15 +141,15 @@ public:
}
//Unpack shortest path and alternative, if they exist
if(INT_MAX != upper_bound_to_shortest_path_distance) {
if(INT_MAX != _upperBound) {
super::UnpackPath(packedShortestPath, rawRouteData.computedShortestPath);
rawRouteData.lengthOfShortestPath = upper_bound_to_shortest_path_distance;
rawRouteData.lengthOfShortestPath = _upperBound;
} else {
rawRouteData.lengthOfShortestPath = INT_MAX;
}
if(selectedViaNode != UINT_MAX) {
retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, rawRouteData.computedAlternativePath);
retrievePackedViaPath(forwardHeap, backwardHeap, forwardHeap2, backwardHeap2, s_v_middle, v_t_middle, rawRouteData.computedAlternativePath);
rawRouteData.lengthOfAlternativePath = lengthOfViaPath;
} else {
rawRouteData.lengthOfAlternativePath = INT_MAX;
@@ -196,7 +158,7 @@ public:
private:
//unpack <s,..,v,..,t> by exploring search spaces from v
inline void retrievePackedViaPath(QueryHeap & _forwardHeap1, QueryHeap & _backwardHeap1, QueryHeap & _forwardHeap2, QueryHeap & _backwardHeap2,
inline void retrievePackedViaPath(const HeapPtr & _forwardHeap1, const HeapPtr & _backwardHeap1, const HeapPtr & _forwardHeap2, const HeapPtr & _backwardHeap2,
const NodeID s_v_middle, const NodeID v_t_middle, std::vector<_PathData> & unpackedPath) {
//unpack [s,v)
std::vector<NodeID> packed_s_v_path, packed_v_t_path;
@@ -208,16 +170,16 @@ private:
super::UnpackPath(packed_s_v_path, unpackedPath);
}
inline void computeLengthAndSharingOfViaPath(const NodeID via_node, int *real_length_of_via_path, int *sharing_of_via_path,
const int offset, const std::vector<NodeID> & packed_shortest_path) {
inline void computeLengthAndSharingOfViaPath(const PreselectedNode& node, int *lengthOfViaPath, int *sharingOfViaPath,
const int offset, const std::vector<NodeID> & packedShortestPath) {
//compute and unpack <s,..,v> and <v,..,t> by exploring search spaces from v and intersecting against queues
//only half-searches have to be done at this stage
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
QueryHeap & existingForwardHeap = *super::_queryData.forwardHeap;
QueryHeap & existingBackwardHeap = *super::_queryData.backwardHeap;
QueryHeap & newForwardHeap = *super::_queryData.forwardHeap2;
QueryHeap & newBackwardHeap = *super::_queryData.backwardHeap2;
HeapPtr & existingForwardHeap = super::_queryData.forwardHeap;
HeapPtr & existingBackwardHeap = super::_queryData.backwardHeap;
HeapPtr & newForwardHeap = super::_queryData.forwardHeap2;
HeapPtr & newBackwardHeap = super::_queryData.backwardHeap2;
std::vector < NodeID > packed_s_v_path;
std::vector < NodeID > packed_v_t_path;
@@ -227,18 +189,18 @@ private:
NodeID s_v_middle = UINT_MAX;
int upperBoundFor_s_v_Path = INT_MAX;//compute path <s,..,v> by reusing forward search from s
newBackwardHeap.Insert(via_node, 0, via_node);
while (0 < newBackwardHeap.Size()) {
newBackwardHeap->Insert(node.first, 0, node.first);
while (newBackwardHeap->Size() > 0) {
super::RoutingStep(newBackwardHeap, existingForwardHeap, &s_v_middle, &upperBoundFor_s_v_Path, 2 * offset, false);
}
//compute path <v,..,t> by reusing backward search from node t
NodeID v_t_middle = UINT_MAX;
int upperBoundFor_v_t_Path = INT_MAX;
newForwardHeap.Insert(via_node, 0, via_node);
while (0 < newForwardHeap.Size() ) {
newForwardHeap->Insert(node.first, 0, node.first);
while (newForwardHeap->Size() > 0) {
super::RoutingStep(newForwardHeap, existingBackwardHeap, &v_t_middle, &upperBoundFor_v_t_Path, 2 * offset, true);
}
*real_length_of_via_path = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path;
*lengthOfViaPath = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path;
if(UINT_MAX == s_v_middle || UINT_MAX == v_t_middle)
return;
@@ -249,35 +211,35 @@ private:
//partial unpacking, compute sharing
//First partially unpack s-->v until paths deviate, note length of common path.
for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packed_shortest_path.size()) - 1; (i < lengthOfPackedPath); ++i) {
if (packed_s_v_path[i] == packed_shortest_path[i] && packed_s_v_path[i + 1] == packed_shortest_path[i + 1]) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packedShortestPath.size()) - 1; (i < lengthOfPackedPath); ++i) {
if (packed_s_v_path[i] == packedShortestPath[i] && packed_s_v_path[i + 1] == packedShortestPath[i + 1]) {
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance;
} else {
if (packed_s_v_path[i] == packed_shortest_path[i]) {
if (packed_s_v_path[i] == packedShortestPath[i]) {
super::UnpackEdge(packed_s_v_path[i], packed_s_v_path[i+1], partiallyUnpackedViaPath);
super::UnpackEdge(packed_shortest_path[i], packed_shortest_path[i+1], partiallyUnpackedShortestPath);
super::UnpackEdge(packedShortestPath[i], packedShortestPath[i+1], partiallyUnpackedShortestPath);
break;
}
}
}
//traverse partially unpacked edge and note common prefix
for (int i = 0, lengthOfPackedPath = std::min( partiallyUnpackedViaPath.size(), partiallyUnpackedShortestPath.size()) - 1; (i < lengthOfPackedPath) && (partiallyUnpackedViaPath[i] == partiallyUnpackedShortestPath[i] && partiallyUnpackedViaPath[i+1] == partiallyUnpackedShortestPath[i+1]); ++i) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]);
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]);
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance;
}
//Second, partially unpack v-->t in reverse order until paths deviate and note lengths
int viaPathIndex = packed_v_t_path.size() - 1;
int shortestPathIndex = packed_shortest_path.size() - 1;
int shortestPathIndex = packedShortestPath.size() - 1;
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex ) {
if (packed_v_t_path[viaPathIndex - 1] == packed_shortest_path[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]);
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
if (packed_v_t_path[viaPathIndex - 1] == packedShortestPath[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packedShortestPath[shortestPathIndex]) {
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]);
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance;
} else {
if (packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
if (packed_v_t_path[viaPathIndex] == packedShortestPath[shortestPathIndex]) {
super::UnpackEdge(packed_v_t_path[viaPathIndex-1], packed_v_t_path[viaPathIndex], partiallyUnpackedViaPath);
super::UnpackEdge(packed_shortest_path[shortestPathIndex-1] , packed_shortest_path[shortestPathIndex], partiallyUnpackedShortestPath);
super::UnpackEdge(packedShortestPath[shortestPathIndex-1] , packedShortestPath[shortestPathIndex], partiallyUnpackedShortestPath);
break;
}
}
@@ -287,16 +249,16 @@ private:
shortestPathIndex = partiallyUnpackedShortestPath.size() - 1;
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex) {
if (partiallyUnpackedViaPath[viaPathIndex - 1] == partiallyUnpackedShortestPath[shortestPathIndex - 1] && partiallyUnpackedViaPath[viaPathIndex] == partiallyUnpackedShortestPath[shortestPathIndex]) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]);
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]);
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance;
} else {
break;
}
}
//finished partial unpacking spree! Amount of sharing is stored to appropriate pointer variable
//finished partial unpacking spree! Amount of sharing is stored to appropriate poiner variable
}
inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, QueryHeap & _forwardHeap, QueryHeap & _backwardHeap, const std::vector<NodeID> & packedShortestPath) {
inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const std::vector<NodeID> & packedShortestPath) {
std::vector<NodeID> packedAlternativePath;
super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfAlternativePath, packedAlternativePath);
@@ -307,9 +269,9 @@ private:
int aindex = 0;
//compute forward sharing
while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) {
// SimpleLogger().Write() << "retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")";
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]);
sharing += search_graph->GetEdgeData(edgeID).distance;
// INFO("retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")");
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]);
sharing += super::_queryData.graph->GetEdgeData(edgeID).distance;
++aindex;
}
@@ -317,65 +279,55 @@ private:
int bindex = packedShortestPath.size()-1;
//compute backward sharing
while( aindex > 0 && bindex > 0 && (packedAlternativePath[aindex] == packedShortestPath[bindex]) && (packedAlternativePath[aindex-1] == packedShortestPath[bindex-1]) ) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]);
sharing += search_graph->GetEdgeData(edgeID).distance;
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]);
sharing += super::_queryData.graph->GetEdgeData(edgeID).distance;
--aindex; --bindex;
}
return sharing;
}
template<bool forwardDirection>
inline void AlternativeRoutingStep(
QueryHeap & _forward_heap,
QueryHeap & _reverse_heap,
NodeID *middle_node,
int *upper_bound_to_shortest_path_distance,
std::vector<NodeID>& searchSpaceIntersection,
std::vector<SearchSpaceEdge> & search_space,
const int edgeBasedOffset
) const {
const NodeID node = _forward_heap.DeleteMin();
const int distance = _forward_heap.GetKey(node);
int scaledDistance = (distance-edgeBasedOffset)/(1.+VIAPATH_EPSILON);
if(scaledDistance > *upper_bound_to_shortest_path_distance){
_forward_heap.DeleteAll();
return;
}
inline void AlternativeRoutingStep(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection, std::vector<NodeID>& searchSpaceIntersection) const {
const NodeID node = _forwardHeap->DeleteMin();
search_space.push_back(std::make_pair(_forward_heap.GetData( node ).parent, node));
if(_reverse_heap.WasInserted(node) ){
const int distance = _forwardHeap->GetKey(node);
if(_backwardHeap->WasInserted(node) ){
searchSpaceIntersection.push_back(node);
const int newDistance = _reverse_heap.GetKey(node) + distance;
if(newDistance < *upper_bound_to_shortest_path_distance ){
const int newDistance = _backwardHeap->GetKey(node) + distance;
if(newDistance < *_upperbound ){
if(newDistance>=0 ) {
*middle_node = node;
*upper_bound_to_shortest_path_distance = newDistance;
*middle = node;
*_upperbound = newDistance;
}
}
}
for ( typename SearchGraph::EdgeIterator edge = search_graph->BeginEdges( node ); edge < search_graph->EndEdges(node); edge++ ) {
const typename SearchGraph::EdgeData & data = search_graph->GetEdgeData(edge);
int scaledDistance = (distance-edgeBasedOffset)/(1.+VIAPATH_EPSILON);
if(scaledDistance > *_upperbound){
_forwardHeap->DeleteAll();
return;
}
for ( typename QueryDataT::Graph::EdgeIterator edge = super::_queryData.graph->BeginEdges( node ); edge < super::_queryData.graph->EndEdges(node); edge++ ) {
const typename QueryDataT::Graph::EdgeData & data = super::_queryData.graph->GetEdgeData(edge);
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
if(forwardDirectionFlag) {
const NodeID to = search_graph->GetTarget(edge);
const NodeID to = super::_queryData.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 ( !_forward_heap.WasInserted( to ) ) {
_forward_heap.Insert( to, toDistance, node );
if ( !_forwardHeap->WasInserted( to ) ) {
_forwardHeap->Insert( to, toDistance, node );
}
//Found a shorter Path -> Update distance
else if ( toDistance < _forward_heap.GetKey( to ) ) {
_forward_heap.GetData( to ).parent = node;
_forward_heap.DecreaseKey( to, toDistance );
else if ( toDistance < _forwardHeap->GetKey( to ) ) {
_forwardHeap->GetData( to ).parent = node;
_forwardHeap->DecreaseKey( to, toDistance );
//new parent
}
}
@@ -383,17 +335,16 @@ private:
}
//conduct T-Test
inline bool viaNodeCandidatePasses_T_Test( QueryHeap& existingForwardHeap, QueryHeap& existingBackwardHeap, QueryHeap& newForwardHeap, QueryHeap& newBackwardHeap, const RankedCandidateNode& candidate, const int offset, const int lengthOfShortestPath, int * lengthOfViaPath, NodeID * s_v_middle, NodeID * v_t_middle) {
newForwardHeap.Clear();
newBackwardHeap.Clear();
inline bool viaNodeCandidatePasses_T_Test( HeapPtr& existingForwardHeap, HeapPtr& existingBackwardHeap, HeapPtr& newForwardHeap, HeapPtr& newBackwardHeap, const RankedCandidateNode& candidate, const int offset, const int lengthOfShortestPath, int * lengthOfViaPath, NodeID * s_v_middle, NodeID * v_t_middle) {
std::vector < NodeID > packed_s_v_path;
std::vector < NodeID > packed_v_t_path;
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
*s_v_middle = UINT_MAX;
int upperBoundFor_s_v_Path = INT_MAX;
//compute path <s,..,v> by reusing forward search from s
newBackwardHeap.Insert(candidate.node, 0, candidate.node);
while (newBackwardHeap.Size() > 0) {
newBackwardHeap->Insert(candidate.node, 0, candidate.node);
while (newBackwardHeap->Size() > 0) {
super::RoutingStep(newBackwardHeap, existingForwardHeap, s_v_middle, &upperBoundFor_s_v_Path, 2*offset, false);
}
@@ -403,8 +354,8 @@ private:
//compute path <v,..,t> by reusing backward search from t
*v_t_middle = UINT_MAX;
int upperBoundFor_v_t_Path = INT_MAX;
newForwardHeap.Insert(candidate.node, 0, candidate.node);
while (newForwardHeap.Size() > 0) {
newForwardHeap->Insert(candidate.node, 0, candidate.node);
while (newForwardHeap->Size() > 0) {
super::RoutingStep(newForwardHeap, existingBackwardHeap, v_t_middle, &upperBoundFor_v_t_Path, 2*offset, true);
}
@@ -418,21 +369,14 @@ private:
super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, *v_t_middle, packed_v_t_path);
NodeID s_P = *s_v_middle, t_P = *v_t_middle;
if(UINT_MAX == s_P) {
return false;
}
if(UINT_MAX == t_P) {
return false;
}
const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath;
int unpackedUntilDistance = 0;
std::stack<SearchSpaceEdge> unpackStack;
std::stack<UnpackEdge> unpackStack;
//Traverse path s-->v
for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpackStack.empty(); --i) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance;
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance;
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
unpackStack.push(std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i]));
} else {
@@ -442,17 +386,17 @@ private:
}
while (!unpackStack.empty()) {
const SearchSpaceEdge viaPathEdge = unpackStack.top();
const UnpackEdge viaPathEdge = unpackStack.top();
unpackStack.pop();
typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
if(UINT_MAX == edgeIDInViaPath)
return false;
typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath);
typename QueryDataT::Graph::EdgeData currentEdgeData = super::_queryData.graph->GetEdgeData(edgeIDInViaPath);
bool IsViaEdgeShortCut = currentEdgeData.shortcut;
if (IsViaEdgeShortCut) {
const NodeID middleOfViaPath = currentEdgeData.id;
typename SearchGraph::EdgeIterator edgeIDOfSecondSegment = search_graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
int lengthOfSecondSegment = search_graph->GetEdgeData(edgeIDOfSecondSegment).distance;
typename QueryDataT::Graph::EdgeIterator edgeIDOfSecondSegment = super::_queryData.graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
int lengthOfSecondSegment = super::_queryData.graph->GetEdgeData(edgeIDOfSecondSegment).distance;
//attention: !unpacking in reverse!
//Check if second segment is the one to go over treshold? if yes add second segment to stack, else push first segment to stack and add distance of second one.
if (unpackedUntilDistance + lengthOfSecondSegment >= T_threshold) {
@@ -472,8 +416,8 @@ private:
unpackedUntilDistance = 0;
//Traverse path s-->v
for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance;
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance;
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
unpackStack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1]));
} else {
@@ -483,17 +427,17 @@ private:
}
while (!unpackStack.empty()) {
const SearchSpaceEdge viaPathEdge = unpackStack.top();
const UnpackEdge viaPathEdge = unpackStack.top();
unpackStack.pop();
typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
if(UINT_MAX == edgeIDInViaPath)
return false;
typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath);
typename QueryDataT::Graph::EdgeData currentEdgeData = super::_queryData.graph->GetEdgeData(edgeIDInViaPath);
const bool IsViaEdgeShortCut = currentEdgeData.shortcut;
if (IsViaEdgeShortCut) {
const NodeID middleOfViaPath = currentEdgeData.id;
typename SearchGraph::EdgeIterator edgeIDOfFirstSegment = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
int lengthOfFirstSegment = search_graph->GetEdgeData( edgeIDOfFirstSegment).distance;
typename QueryDataT::Graph::EdgeIterator edgeIDOfFirstSegment = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
int lengthOfFirstSegment = super::_queryData.graph->GetEdgeData( edgeIDOfFirstSegment).distance;
//Check if first segment is the one to go over treshold? if yes first segment to stack, else push second segment to stack and add distance of first one.
if (unpackedUntilDistance + lengthOfFirstSegment >= T_threshold) {
unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath));
@@ -510,21 +454,20 @@ private:
lengthOfPathT_Test_Path += unpackedUntilDistance;
//Run actual T-Test query and compare if distances equal.
HeapPtr& forwardHeap = super::_queryData.forwardHeap3;
HeapPtr& backwardHeap = super::_queryData.backwardHeap3;
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
QueryHeap& forward_heap3 = *super::_queryData.forwardHeap3;
QueryHeap& backward_heap3 = *super::_queryData.backwardHeap3;
int _upperBound = INT_MAX;
NodeID middle = UINT_MAX;
forward_heap3.Insert(s_P, 0, s_P);
backward_heap3.Insert(t_P, 0, t_P);
forwardHeap->Insert(s_P, 0, s_P);
backwardHeap->Insert(t_P, 0, t_P);
//exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
while (forward_heap3.Size() + backward_heap3.Size() > 0) {
if (forward_heap3.Size() > 0) {
super::RoutingStep(forward_heap3, backward_heap3, &middle, &_upperBound, offset, true);
while (forwardHeap->Size() + backwardHeap->Size() > 0) {
if (forwardHeap->Size() > 0) {
super::RoutingStep(forwardHeap, backwardHeap, &middle, &_upperBound, offset, true);
}
if (backward_heap3.Size() > 0) {
super::RoutingStep(backward_heap3, forward_heap3, &middle, &_upperBound, offset, false);
if (backwardHeap->Size() > 0) {
super::RoutingStep(backwardHeap, forwardHeap, &middle, &_upperBound, offset, false);
}
}
return (_upperBound <= lengthOfPathT_Test_Path);
+39 -39
View File
@@ -23,47 +23,43 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef BASICROUTINGINTERFACE_H_
#define BASICROUTINGINTERFACE_H_
#include "../DataStructures/RawRouteData.h"
#include "../Util/ContainerUtils.h"
#include "../Util/SimpleLogger.h"
#include <boost/noncopyable.hpp>
#include <cassert>
#include <climits>
#include <stack>
#include "../Plugins/RawRouteData.h"
template<class QueryDataT>
class BasicRoutingInterface : boost::noncopyable{
class BasicRoutingInterface {
protected:
QueryDataT & _queryData;
public:
BasicRoutingInterface(QueryDataT & qd) : _queryData(qd) { }
virtual ~BasicRoutingInterface(){ };
inline void RoutingStep(typename QueryDataT::QueryHeap & _forwardHeap, typename QueryDataT::QueryHeap & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const {
const NodeID node = _forwardHeap.DeleteMin();
const int distance = _forwardHeap.GetKey(node);
//SimpleLogger().Write() << "Settled (" << _forwardHeap.GetData( node ).parent << "," << node << ")=" << distance;
if(_backwardHeap.WasInserted(node) ){
const int newDistance = _backwardHeap.GetKey(node) + distance;
inline void RoutingStep(typename QueryDataT::HeapPtr & _forwardHeap, typename QueryDataT::HeapPtr & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const {
const NodeID node = _forwardHeap->DeleteMin();
const int distance = _forwardHeap->GetKey(node);
// INFO((forwardDirection ? "[forw]" : "[back]") << " settled node " << node << " at distance " << distance);
if(_backwardHeap->WasInserted(node) ){
// INFO((forwardDirection ? "[forw]" : "[back]") << " scanned node " << node << " in both directions, upper bound: " << *_upperbound);
const int newDistance = _backwardHeap->GetKey(node) + distance;
if(newDistance < *_upperbound ){
if(newDistance>=0 ) {
// INFO((forwardDirection ? "[forw]" : "[back]") << " -> node " << node << " is new middle at total distance " << newDistance);
*middle = node;
*_upperbound = newDistance;
} else {
// INFO((forwardDirection ? "[forw]" : "[back]") << " -> ignored " << node << " as new middle at total distance " << newDistance);
}
}
}
if(distance-edgeBasedOffset > *_upperbound){
_forwardHeap.DeleteAll();
_forwardHeap->DeleteAll();
return;
}
//Stalling
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); edge++ ) {
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward;
if(backwardDirectionFlag) {
@@ -72,15 +68,16 @@ public:
assert( edgeWeight > 0 );
if(_forwardHeap.WasInserted( to )) {
if(_forwardHeap.GetKey( to ) + edgeWeight < distance) {
//Stalling
if(_forwardHeap->WasInserted( to )) {
if(_forwardHeap->GetKey( to ) + edgeWeight < distance) {
return;
}
}
}
}
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); edge++ ) {
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
if(forwardDirectionFlag) {
@@ -92,20 +89,23 @@ public:
const int toDistance = distance + edgeWeight;
//New Node discovered -> Add to Heap + Node Info Storage
if ( !_forwardHeap.WasInserted( to ) ) {
_forwardHeap.Insert( to, toDistance, node );
if ( !_forwardHeap->WasInserted( to ) ) {
// INFO((forwardDirection ? "[forw]" : "[back]") << " scanning edge (" << node << "," << to << ") with distance " << toDistance << ", edge length: " << data.distance);
_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 );
else if ( toDistance < _forwardHeap->GetKey( to ) ) {
// INFO((forwardDirection ? "[forw]" : "[back]") << " decrease and scanning edge (" << node << "," << to << ") from " << _forwardHeap->GetKey(to) << "to " << toDistance << ", edge length: " << data.distance);
_forwardHeap->GetData( to ).parent = node;
_forwardHeap->DecreaseKey( to, toDistance );
//new parent
}
}
}
}
inline void UnpackPath(const std::vector<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const {
inline void UnpackPath(std::vector<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const {
const unsigned sizeOfPackedPath = packedPath.size();
std::stack<std::pair<NodeID, NodeID> > recursionStack;
@@ -118,12 +118,15 @@ public:
while(!recursionStack.empty()) {
edge = recursionStack.top();
recursionStack.pop();
// INFO("Unpacking edge (" << edge.first << "," << edge.second << ")");
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
int smallestWeight = INT_MAX;
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
const int weight = _queryData.graph->GetEdgeData(eit).distance;
// INFO("Checking edge (" << edge.first << "/" << _queryData.graph->GetTarget(eit) << ")");
if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
// INFO("1smallest " << eit << ", " << weight);
smallestEdge = eit;
smallestWeight = weight;
}
@@ -132,7 +135,9 @@ public:
if(smallestEdge == SPECIAL_EDGEID){
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
const int weight = _queryData.graph->GetEdgeData(eit).distance;
// INFO("Checking edge (" << edge.first << "/" << _queryData.graph->GetTarget(eit) << ")");
if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
// INFO("2smallest " << eit << ", " << weight);
smallestEdge = eit;
smallestWeight = weight;
}
@@ -154,6 +159,7 @@ public:
}
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpackedPath) const {
std::stack<std::pair<NodeID, NodeID> > recursionStack;
recursionStack.push(std::make_pair(s,t));
@@ -187,6 +193,7 @@ public:
if(ed.shortcut) {//unpack
const NodeID middle = ed.id;
//again, we need to this in reversed order
// INFO("unpacking (" << middle << "," << edge.second << ") and (" << edge.first << "," << middle << ")");
recursionStack.push(std::make_pair(middle, edge.second));
recursionStack.push(std::make_pair(edge.first, middle));
} else {
@@ -197,29 +204,22 @@ public:
unpackedPath.push_back(t);
}
inline void RetrievePackedPathFromHeap(typename QueryDataT::QueryHeap & _fHeap, typename QueryDataT::QueryHeap & _bHeap, const NodeID middle, std::vector<NodeID>& packedPath) const {
inline void RetrievePackedPathFromHeap(const typename QueryDataT::HeapPtr & _fHeap, const typename QueryDataT::HeapPtr & _bHeap, const NodeID middle, std::vector<NodeID>& packedPath) {
NodeID pathNode = middle;
while(pathNode != _fHeap.GetData(pathNode).parent) {
pathNode = _fHeap.GetData(pathNode).parent;
while(pathNode != _fHeap->GetData(pathNode).parent) {
pathNode = _fHeap->GetData(pathNode).parent;
packedPath.push_back(pathNode);
}
std::reverse(packedPath.begin(), packedPath.end());
packedPath.push_back(middle);
pathNode = middle;
while (pathNode != _bHeap.GetData(pathNode).parent){
pathNode = _bHeap.GetData(pathNode).parent;
while (pathNode != _bHeap->GetData(pathNode).parent){
pathNode = _bHeap->GetData(pathNode).parent;
packedPath.push_back(pathNode);
}
}
inline void RetrievePackedPathFromSingleHeap(typename QueryDataT::QueryHeap & search_heap, const NodeID middle, std::vector<NodeID>& packed_path) const {
NodeID pathNode = middle;
while(pathNode != search_heap.GetData(pathNode).parent) {
pathNode = search_heap.GetData(pathNode).parent;
packed_path.push_back(pathNode);
}
}
};
+113 -53
View File
@@ -28,14 +28,13 @@ or see http://www.gnu.org/licenses/agpl.txt.
template<class QueryDataT>
class ShortestPathRouting : public BasicRoutingInterface<QueryDataT>{
typedef BasicRoutingInterface<QueryDataT> super;
typedef typename QueryDataT::QueryHeap QueryHeap;
public:
ShortestPathRouting( QueryDataT & qd) : super(qd) {}
ShortestPathRouting(QueryDataT & qd) : super(qd) {}
~ShortestPathRouting() {}
void operator()(std::vector<PhantomNodes> & phantomNodesVector, RawRouteData & rawRouteData) const {
BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
void operator()(std::vector<PhantomNodes> & phantomNodesVector, RawRouteData & rawRouteData) {
BOOST_FOREACH(PhantomNodes & phantomNodePair, phantomNodesVector) {
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) {
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
return;
@@ -44,108 +43,125 @@ public:
int distance1 = 0;
int distance2 = 0;
bool searchFrom1stStartNode = true;
bool searchFrom2ndStartNode = true;
NodeID middle1 = UINT_MAX;
NodeID middle2 = UINT_MAX;
bool searchFrom1stStartNode(true);
bool searchFrom2ndStartNode(true);
NodeID middle1 = ( NodeID ) UINT_MAX;
NodeID middle2 = ( NodeID ) UINT_MAX;
std::vector<NodeID> packedPath1;
std::vector<NodeID> packedPath2;
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
typename QueryDataT::HeapPtr & forwardHeap = super::_queryData.forwardHeap;
typename QueryDataT::HeapPtr & backwardHeap = super::_queryData.backwardHeap;
typename QueryDataT::HeapPtr & forwardHeap2 = super::_queryData.forwardHeap2;
typename QueryDataT::HeapPtr & backwardHeap2 = super::_queryData.backwardHeap2;
QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap);
QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap);
QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2);
QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2);
//Get distance to next pair of target nodes.
BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
forward_heap1.Clear(); forward_heap2.Clear();
reverse_heap1.Clear(); reverse_heap2.Clear();
BOOST_FOREACH(PhantomNodes & phantomNodePair, phantomNodesVector) {
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
int _localUpperbound1 = INT_MAX;
int _localUpperbound2 = INT_MAX;
middle1 = UINT_MAX;
middle2 = UINT_MAX;
//insert new starting nodes into forward heap, adjusted by previous distances.
if(searchFrom1stStartNode) {
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
// INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
// INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
}
forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
forwardHeap2->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
// INFO("a 1,2)forw insert " << phantomNodePair.startPhantom.edgeBasedNode << " with weight " << phantomNodePair.startPhantom.weight1);
// } else {
// INFO("Skipping first start node");
}
if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) {
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
// INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
// INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
forwardHeap2->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
// INFO("b 1,2)forw insert " << phantomNodePair.startPhantom.edgeBasedNode+1 << " with weight " << -phantomNodePair.startPhantom.weight1);
// } else if(!searchFrom2ndStartNode) {
// INFO("Skipping second start node");
}
// backwardHeap->Clear();
// backwardHeap2->Clear();
//insert new backward nodes into backward heap, unadjusted.
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
// INFO("rv1: " << phantomNodePair.targetPhantom.edgeBasedNode << ", w;" << phantomNodePair.targetPhantom.weight1 );
backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
// INFO("1) back insert " << phantomNodePair.targetPhantom.edgeBasedNode << " with weight " << phantomNodePair.targetPhantom.weight1);
if(phantomNodePair.targetPhantom.isBidirected() ) {
reverse_heap2.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
// INFO("rv2: " << phantomNodePair.targetPhantom.edgeBasedNode+1 << ", w;" << phantomNodePair.targetPhantom.weight2 );
}
const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
// INFO("2) back insert " << phantomNodePair.targetPhantom.edgeBasedNode+1 << " with weight " << phantomNodePair.targetPhantom.weight2);
backwardHeap2->Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
}
int offset = (phantomNodePair.startPhantom.isBidirected() ? std::max(phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.weight2) : phantomNodePair.startPhantom.weight1) ;
offset += (phantomNodePair.targetPhantom.isBidirected() ? std::max(phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.weight2) : phantomNodePair.targetPhantom.weight1) ;
//run two-Target Dijkstra routing step.
while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
if(0 < forward_heap1.Size()){
super::RoutingStep(forward_heap1, reverse_heap1, &middle1, &_localUpperbound1, forward_offset, true);
while(forwardHeap->Size() + backwardHeap->Size() > 0){
if(forwardHeap->Size() > 0){
super::RoutingStep(forwardHeap, backwardHeap, &middle1, &_localUpperbound1, 2*offset, true);
}
if(0 < reverse_heap1.Size() ){
super::RoutingStep(reverse_heap1, forward_heap1, &middle1, &_localUpperbound1, reverse_offset, false);
if(backwardHeap->Size() > 0){
super::RoutingStep(backwardHeap, forwardHeap, &middle1, &_localUpperbound1, 2*offset, false);
}
}
if(0 < reverse_heap2.Size()) {
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
if(0 < forward_heap2.Size()){
super::RoutingStep(forward_heap2, reverse_heap2, &middle2, &_localUpperbound2, forward_offset, true);
if(backwardHeap2->Size() > 0) {
while(forwardHeap2->Size() + backwardHeap2->Size() > 0){
if(forwardHeap2->Size() > 0){
super::RoutingStep(forwardHeap2, backwardHeap2, &middle2, &_localUpperbound2, 2*offset, true);
}
if(0 < reverse_heap2.Size()){
super::RoutingStep(reverse_heap2, forward_heap2, &middle2, &_localUpperbound2, reverse_offset, false);
if(backwardHeap2->Size() > 0){
super::RoutingStep(backwardHeap2, forwardHeap2, &middle2, &_localUpperbound2, 2*offset, false);
}
}
}
// INFO("upperbound1: " << _localUpperbound1 << ", distance1: " << distance1);
// INFO("upperbound2: " << _localUpperbound2 << ", distance2: " << distance2);
//No path found for both target nodes?
if((INT_MAX == _localUpperbound1) && (INT_MAX == _localUpperbound2)) {
if(INT_MAX == _localUpperbound1 && INT_MAX == _localUpperbound2) {
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
return;
}
if(UINT_MAX == middle1) {
searchFrom1stStartNode = false;
// INFO("Next Search will not start from 1st");
} else {
// INFO("Next Search will start from 1st");
searchFrom1stStartNode = true;
}
if(UINT_MAX == middle2) {
searchFrom2ndStartNode = false;
// INFO("Next Search will not start from 2nd");
} else {
searchFrom2ndStartNode = true;
// INFO("Next Search will start from 2nd");
}
//Was at most one of the two paths not found?
assert(!(INT_MAX == distance1 && INT_MAX == distance2));
// INFO("middle1: " << middle1);
//Unpack paths if they exist
std::vector<NodeID> temporaryPackedPath1;
std::vector<NodeID> temporaryPackedPath2;
if(INT_MAX != _localUpperbound1) {
super::RetrievePackedPathFromHeap(forward_heap1, reverse_heap1, middle1, temporaryPackedPath1);
super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle1, temporaryPackedPath1);
// INFO("temporaryPackedPath1 ends with " << *(temporaryPackedPath1.end()-1) );
}
// INFO("middle2: " << middle2);
if(INT_MAX != _localUpperbound2) {
super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap2, middle2, temporaryPackedPath2);
super::RetrievePackedPathFromHeap(forwardHeap2, backwardHeap2, middle2, temporaryPackedPath2);
// INFO("temporaryPackedPath2 ends with " << *(temporaryPackedPath2.end()-1) );
}
//if one of the paths was not found, replace it with the other one.
if(0 == temporaryPackedPath1.size()) {
// INFO("Deleting path 1");
temporaryPackedPath1.insert(temporaryPackedPath1.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
_localUpperbound1 = _localUpperbound2;
}
if(0 == temporaryPackedPath2.size()) {
// INFO("Deleting path 2");
temporaryPackedPath2.insert(temporaryPackedPath2.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
_localUpperbound2 = _localUpperbound1;
}
@@ -154,21 +170,28 @@ public:
//Plug paths together, s.t. end of packed path is begin of temporary packed path
if(0 < packedPath1.size() && 0 < packedPath2.size() ) {
// INFO("Both paths are non-empty");
if( *(temporaryPackedPath1.begin()) == *(temporaryPackedPath2.begin())) {
// INFO("both paths start with the same node:" << *(temporaryPackedPath1.begin()));
//both new route segments start with the same node, thus one of the packedPath must go.
assert( (packedPath1.size() == packedPath2.size() ) || (*(packedPath1.end()-1) != *(packedPath2.end()-1)) );
if( *(packedPath1.end()-1) == *(temporaryPackedPath1.begin())) {
// INFO("Deleting packedPath2 that ends with " << *(packedPath2.end()-1) << ", other ends with " << *(packedPath1.end()-1));
packedPath2.clear();
packedPath2.insert(packedPath2.end(), packedPath1.begin(), packedPath1.end());
distance2 = distance1;
// INFO("packedPath2 now ends with " << *(packedPath2.end()-1));
} else {
// INFO("Deleting path1 that ends with " << *(packedPath1.end()-1) << ", other ends with " << *(packedPath2.end()-1));
packedPath1.clear();
packedPath1.insert(packedPath1.end(), packedPath2.begin(), packedPath2.end());
distance1 = distance2;
// INFO("Path1 now ends with " << *(packedPath1.end()-1));
}
} else {
//packed paths 1 and 2 may need to switch.
if(*(packedPath1.end()-1) != *(temporaryPackedPath1.begin())) {
// INFO("Switching");
packedPath1.swap(packedPath2);
std::swap(distance1, distance2);
}
@@ -178,24 +201,61 @@ public:
packedPath2.insert(packedPath2.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
if( (packedPath1.back() == packedPath2.back()) && phantomNodePair.targetPhantom.isBidirected() ) {
// INFO("both paths end in same direction on bidirected edge, make sure start only start with : " << packedPath1.back());
NodeID lastNodeID = packedPath2.back();
searchFrom1stStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode+1);
searchFrom2ndStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode);
// INFO("Next search from node " << phantomNodePair.targetPhantom.edgeBasedNode << ": " << (searchFrom1stStartNode ? "yes" : "no") );
// INFO("Next search from node " << phantomNodePair.targetPhantom.edgeBasedNode+1 << ": " << (searchFrom2ndStartNode ? "yes" : "no") );
}
distance1 += _localUpperbound1;
distance2 += _localUpperbound2;
}
if(distance1 > distance2){
// INFO("length path1: " << distance1);
// INFO("length path2: " << distance2);
if(distance1 <= distance2){
//remove consecutive duplicates
// std::cout << "unclean 1: ";
// for(unsigned i = 0; i < packedPath1.size(); ++i)
// std::cout << packedPath1[i] << " ";
// std::cout << std::endl;
// std::cout << "cleaned 1: ";
// for(unsigned i = 0; i < packedPath1.size(); ++i)
// std::cout << packedPath1[i] << " ";
// std::cout << std::endl;
// super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
} else {
std::swap(packedPath1, packedPath2);
// std::cout << "unclean 2: ";
// for(unsigned i = 0; i < packedPath2.size(); ++i)
// std::cout << packedPath2[i] << " ";
// std::cout << std::endl;
// _RemoveConsecutiveDuplicatesFromContainer(packedPath2);
// std::cout << "cleaned 2: ";
// for(unsigned i = 0; i < packedPath2.size(); ++i)
// std::cout << packedPath2[i] << " ";
// std::cout << std::endl;
// super::UnpackPath(packedPath2, unpackedPath);
}
remove_consecutive_duplicates_from_vector(packedPath1);
_RemoveConsecutiveDuplicatesFromContainer(packedPath1);
super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
rawRouteData.lengthOfShortestPath = std::min(distance1, distance2);
// INFO("Found via route with distance " << std::min(distance1, distance2));
return;
}
private:
template<class ContainerT>
void _RemoveConsecutiveDuplicatesFromContainer(ContainerT & packedPath) {
//remove consecutive duplicates
typename ContainerT::iterator it;
// using default comparison:
it = std::unique(packedPath.begin(), packedPath.end());
packedPath.resize(it - packedPath.begin());
}
};
#endif /* SHORTESTPATHROUTING_H_ */
+299
View File
@@ -0,0 +1,299 @@
#Sconstruct
import os
import os.path
import string
import sys
from subprocess import call
def CheckBoost(context, version):
# Boost versions are in format major.minor.subminor
v_arr = version.split(".")
version_n = 0
if len(v_arr) > 0:
version_n += int(v_arr[0])*100000
if len(v_arr) > 1:
version_n += int(v_arr[1])*100
if len(v_arr) > 2:
version_n += int(v_arr[2])
context.Message('Checking for Boost version >= %s... ' % (version))
ret = context.TryRun("""
#include <boost/version.hpp>
int main()
{
return BOOST_VERSION >= %d ? 0 : 1;
}
""" % version_n, '.cpp')[0]
context.Result(ret)
return ret
def CheckProtobuf(context, version):
# Protobuf versions are in format major.minor.subminor
v_arr = version.split(".")
version_n = 0
if len(v_arr) > 0:
version_n += int(v_arr[0])*1000000
if len(v_arr) > 1:
version_n += int(v_arr[1])*1000
if len(v_arr) > 2:
version_n += int(v_arr[2])
context.Message('Checking for Protobuffer version >= %s... ' % (version))
ret = context.TryRun("""
#include <google/protobuf/stubs/common.h>
int main() {
return (GOOGLE_PROTOBUF_VERSION >= %d) ? 0 : 1;
}
""" % version_n, '.cpp')[0]
context.Result(ret)
return ret
# Adding various options to the SConstruct
AddOption('--cxx', dest='cxx', type='string', nargs=1, action='store', metavar='STRING', help='C++ Compiler')
AddOption('--stxxlroot', dest='stxxlroot', type='string', nargs=1, action='store', metavar='STRING', help='root directory of STXXL')
AddOption('--verbosity', dest='verbosity', type='string', nargs=1, action='store', metavar='STRING', help='make Scons talking')
AddOption('--buildconfiguration', dest='buildconfiguration', type='string', nargs=1, action='store', metavar='STRING', help='debug or release')
AddOption('--all-flags', dest='allflags', type='string', nargs=0, action='store', metavar='STRING', help='turn off -march optimization in release mode')
AddOption('--with-tools', dest='withtools', type='string', nargs=0, action='store', metavar='STRING', help='build tools for data analysis')
AddOption('--no-march', dest='nomarch', type='string', nargs=0, action='store', metavar='STRING', help='turn off native optimizations')
env = Environment( ENV = {'PATH' : os.environ['PATH']} ,COMPILER = GetOption('cxx'))
env["CC"] = os.getenv("CC") or env["CC"]
env["CXX"] = os.getenv("CXX") or env["CXX"]
env["ENV"].update(x for x in os.environ.items() if x[0].startswith("CCC_"))
try:
env['ENV']['TERM'] = os.environ['TERM']
except KeyError:
env['ENV']['TERM'] = 'none'
conf = Configure(env, custom_tests = { 'CheckBoost' : CheckBoost, 'CheckProtobuf' : CheckProtobuf })
if GetOption('cxx') is None:
#default Compiler
if sys.platform == 'darwin': #Mac OS X
env['CXX'] = 'clang++'
print 'Using default C++ Compiler: ', env['CXX'].strip()
else:
env.Replace(CXX = GetOption('cxx'))
print 'Using user supplied C++ Compiler: ', env['CXX']
if GetOption('allflags') is not None:
env.Append(CXXFLAGS = ["-Wextra", "-Wall", "-Wnon-virtual-dtor", "-Wundef", "-Wno-long-long", "-Woverloaded-virtual", "-Wfloat-equal", "-Wredundant-decls"])
if "clang" in env["CXX"]:
print "Warning building with clang removes OpenMP parallelization"
if GetOption('allflags') is not None:
env.Append(CXXFLAGS = ["-W#warnings", "-Wc++0x-compat", "-Waddress-of-temporary", "-Wambiguous-member-template", "-Warray-bounds", "-Watomic-properties", "-Wbind-to-temporary-copy", "-Wbuiltin-macro-redefined", "-Wc++-compat", "-Wc++0x-extensions", "-Wcomments", "-Wconditional-uninitialized", "-Wconstant-logical-operand", "-Wdeclaration-after-statement", "-Wdeprecated", "-Wdeprecated-implementations", "-Wdeprecated-writable-strings", "-Wduplicate-method-arg", "-Wempty-body", "-Wendif-labels", "-Wenum-compare", "-Wformat=2", "-Wfour-char-constants", "-Wgnu", "-Wincomplete-implementation", "-Winvalid-noreturn", "-Winvalid-offsetof", "-Winvalid-token-paste", "-Wlocal-type-template-args", "-Wmethod-signatures", "-Wmicrosoft", "-Wmissing-declarations", "-Wnon-pod-varargs", "-Wnonfragile-abi2", "-Wnull-dereference", "-Wout-of-line-declaration", "-Woverlength-strings", "-Wpacked", "-Wpointer-arith", "-Wpointer-sign", "-Wprotocol", "-Wreadonly-setter-attrs", "-Wselector", "-Wshift-overflow", "-Wshift-sign-overflow", "-Wstrict-selector-match", "-Wsuper-class-method-mismatch", "-Wtautological-compare", "-Wtypedef-redefinition", "-Wundeclared-selector", "-Wunnamed-type-template-args", "-Wunused-exception-parameter", "-Wunused-member-function", "-Wused-but-marked-unused", "-Wvariadic-macros"])
else:
env.Append(CCFLAGS = ['-minline-all-stringops', '-fopenmp'])
env.Append(LINKFLAGS = '-fopenmp')
if GetOption('buildconfiguration') == 'debug':
env.Append(CCFLAGS = ['-Wall', '-g3', '-rdynamic'])
else:
env.Append(CCFLAGS = ['-O3', '-DNDEBUG'])
if sys.platform == 'darwin': #Mac OS X
#os x default installations
env.Append(CPPPATH = ['/usr/include/libxml2'] )
env.Append(CPPPATH = ['/usr/X11/include']) #comes with os x
# env.Append(LIBPATH = ['/usr/X11/lib']) #needed for libpng
#assume stxxl and boost are installed via homebrew. call brew binary to get folder locations
import subprocess
stxxl_prefix = subprocess.check_output(["brew", "--prefix", "libstxxl"]).strip()
env.Append(CPPPATH = [stxxl_prefix+"/include"] )
env.Append(LIBPATH = [stxxl_prefix+"/lib"] )
boost_prefix = subprocess.check_output(["brew", "--prefix", "boost"]).strip()
env.Append(CPPPATH = [boost_prefix+"/include"] )
env.Append(LIBPATH = [boost_prefix+"/lib"] )
if not conf.CheckLibWithHeader('lua', 'lua.h', 'C'):
print "lua library not found. Exiting"
Exit(-1)
if not conf.CheckLibWithHeader('luabind', 'luabind/luabind.hpp', 'CXX'):
print "luabind library not found. Exiting"
Exit(-1)
elif sys.platform.startswith("freebsd"):
env.ParseConfig('pkg-config --cflags --libs protobuf')
env.Append(CPPPATH = ['/usr/local/include', '/usr/local/include/libxml2'])
env.Append(LIBPATH = ['/usr/local/lib'])
if GetOption('stxxlroot') is not None:
env.Append(CPPPATH = GetOption('stxxlroot')+'/include')
env.Append(LIBPATH = GetOption('stxxlroot')+'/lib')
print 'STXXLROOT = ', GetOption('stxxlroot')
elif sys.platform == 'win32':
#SCons really wants to use Microsoft compiler
print "Compiling is not yet supported on Windows"
Exit(-1)
else:
print "Default platform"
if GetOption('stxxlroot') is not None:
env.Append(CPPPATH = GetOption('stxxlroot')+'/include')
env.Append(LIBPATH = GetOption('stxxlroot')+'/lib')
print 'STXXLROOT = ', GetOption('stxxlroot')
env.Append(CPPPATH = ['/usr/include', '/usr/include/include', '/usr/include/libxml2/'])
if not conf.CheckLibWithHeader('pthread', 'pthread.h', 'CXX'):
print "pthread not found. Exiting"
Exit(-1)
if not conf.CheckLibWithHeader('luajit-5.1', 'luajit-2.0/lua.h', 'CXX'):
print "luajit library not found. Checking for interpreter"
env.ParseConfig('pkg-config --cflags --libs lua5.1')
env.ParseConfig('pkg-config --cflags --libs luabind')
#Check if architecture optimizations shall be turned off
if GetOption('buildconfiguration') != 'debug' and sys.platform != 'darwin' and GetOption('nomarch') is None:
env.Append(CCFLAGS = ['-march=native'])
if not conf.CheckHeader('omp.h'):
print "Compiler does not support OpenMP. Exiting"
Exit(-1)
if not conf.CheckLibWithHeader('bz2', 'bzlib.h', 'CXX'):
print "bz2 library not found. Exiting"
Exit(-1)
if GetOption('withtools') is not None:
if not conf.CheckLibWithHeader('gdal', 'gdal/gdal.h', 'CXX'):
print "gdal library not found. Exiting"
Exit(-1)
if not conf.CheckLibWithHeader('osmpbf', 'osmpbf/osmpbf.h', 'CXX'):
print "osmpbf library not found. Exiting"
print "Either install libosmpbf-dev (Ubuntu) or use https://github.com/scrosby/OSM-binary"
Exit(-1)
if not conf.CheckLibWithHeader('protobuf', 'google/protobuf/descriptor.h', 'CXX'):
print "Google Protobuffer library not found. Exiting"
Exit(-1)
#check for protobuf 2.3.0
if not (conf.CheckProtobuf('2.3.0')):
print 'libprotobuf version >= 2.3.0 needed'
Exit(-1);
if not (env.Detect('protoc')):
print 'protobuffer compiler not found'
Exit(-1);
if not conf.CheckLibWithHeader('stxxl', 'stxxl.h', 'CXX'):
print "stxxl library not found. Exiting"
Exit(-1)
if not conf.CheckLibWithHeader('xml2', 'libxml/xmlreader.h', 'CXX'):
print "libxml2 library or header not found. Exiting"
Exit(-1)
if not conf.CheckLibWithHeader('z', 'zlib.h', 'CXX'):
print "zlib library or header not found. Exiting"
Exit(-1)
#Check BOOST installation
if not (conf.CheckBoost('1.44')):
print 'Boost version >= 1.44 needed'
Exit(-1);
if not conf.CheckLib('boost_system', language="C++"):
if not conf.CheckLib('boost_system-mt', language="C++"):
print "boost_system library not found. Exiting"
Exit(-1)
else:
print "using boost -mt"
env.Append(CCFLAGS = ' -lboost_system-mt')
env.Append(LINKFLAGS = ' -lboost_system-mt')
if not conf.CheckLibWithHeader('boost_thread', 'boost/thread.hpp', 'CXX'):
if not conf.CheckLibWithHeader('boost_thread-mt', 'boost/thread.hpp', 'CXX'):
print "boost thread library not found. Exiting"
Exit(-1)
else:
print "using boost -mt"
env.Append(CCFLAGS = ' -lboost_thread-mt')
env.Append(LINKFLAGS = ' -lboost_thread-mt')
if not conf.CheckLibWithHeader('boost_regex', 'boost/regex.hpp', 'CXX'):
if not conf.CheckLibWithHeader('boost_regex-mt', 'boost/regex.hpp', 'CXX'):
print "boost/regex.hpp not found. Exiting"
Exit(-1)
else:
print "using boost_regex -mt"
env.Append(CCFLAGS = ' -lboost_regex-mt')
env.Append(LINKFLAGS = ' -lboost_regex-mt')
if not conf.CheckLib('boost_filesystem', language="C++"):
if not conf.CheckLib('boost_filesystem-mt', language="C++"):
print "boost_filesystem library not found. Exiting"
Exit(-1)
else:
print "using boost -mt"
env.Append(CCFLAGS = ' -lboost_filesystem-mt')
env.Append(LINKFLAGS = ' -lboost_filesystem-mt')
if not conf.CheckCXXHeader('boost/archive/iterators/base64_from_binary.hpp'):
print "boost/archive/iterators/base64_from_binary.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/archive/iterators/binary_from_base64.hpp'):
print "boost/archive/iterators/binary_from_base64.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/archive/iterators/transform_width.hpp'):
print "boost/archive/iterators/transform_width.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/bind.hpp'):
print "boost/bind.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/circular_buffer.hpp'):
print "boost/circular_buffer.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/enable_shared_from_this.hpp'):
print "boost/bind.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/foreach.hpp'):
print "boost/foreach.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/lexical_cast.hpp'):
print "boost/foreach.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/logic/tribool.hpp'):
print "boost/foreach.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/math/tr1.hpp'):
print "boost/foreach.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/noncopyable.hpp'):
print "boost/noncopyable.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/property_tree/ptree.hpp'):
print "boost/property_tree/ptree.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/property_tree/ini_parser.hpp'):
print "boost/property_tree/ini_parser.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/shared_ptr.hpp'):
print "boost/shared_ptr.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/thread/mutex.hpp'):
print "boost/shared_ptr.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/thread/thread.hpp'):
print "boost/thread/thread.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/thread/condition.hpp'):
print "boost/thread/condition.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/thread/thread.hpp'):
print "boost/thread/thread.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/thread.hpp'):
print "boost thread header not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/tuple/tuple.hpp'):
print "boost thread header not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/unordered_map.hpp'):
print "boost thread header not found. Exiting"
Exit(-1)
#checks for intels thread building blocks library
#if not conf.CheckLibWithHeader('tbb', 'tbb/tbb.h', 'CXX'):
# print "Intel TBB library not found. Exiting"
# Exit(-1)
#if not conf.CheckCXXHeader('tbb/task_scheduler_init.h'):
# print "tbb/task_scheduler_init.h not found. Exiting"
# Exit(-1)
env.Program(target = 'osrm-extract', source = ["extractor.cpp", Glob('Util/*.cpp'), Glob('Extractor/*.cpp')])
env.Program(target = 'osrm-prepare', source = ["createHierarchy.cpp", Glob('Contractor/*.cpp'), Glob('Util/SRTMLookup/*.cpp'), Glob('Algorithms/*.cpp')])
env.Program(target = 'osrm-routed', source = ["routed.cpp", 'Descriptors/DescriptionFactory.cpp', Glob('ThirdParty/*.cc'), Glob('Server/DataStructures/*.cpp')], CCFLAGS = env['CCFLAGS'] + ['-DROUTED'])
if GetOption('withtools') is not None:
env.Program(target = 'Tools/osrm-component', source = ["Tools/componentAnalysis.cpp"])
env = conf.Finish()
+1 -1
View File
@@ -33,7 +33,7 @@ template <typename Iterator, class HandlerT>
struct APIGrammar : qi::grammar<Iterator> {
APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) {
api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query);
query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | geometry | alt_route | old_API) ) ;
query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | alt_route | old_API) ) ;
zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)];
output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)];
+15 -26
View File
@@ -20,15 +20,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef BASIC_DATASTRUCTURES_H
#define BASIC_DATASTRUCTURES_H
#include "../Util/StringUtil.h"
#include <boost/asio.hpp>
#include <boost/foreach.hpp>
#include <string>
#include <sstream>
#include <vector>
#include <boost/lexical_cast.hpp>
namespace http {
@@ -77,13 +70,15 @@ struct Reply {
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
std::string content;
static Reply stockReply(status_type status);
void setSize(const unsigned size) {
BOOST_FOREACH ( Header& h, headers) {
if("Content-Length" == h.name) {
std::string sizeString;
intToString(size,h.value);
}
}
void setSize(unsigned size) {
for (std::size_t i = 0; i < headers.size(); ++i) {
Header& h = headers[i];
if("Content-Length" == h.name) {
std::stringstream sizeString;
sizeString << size;
h.value = sizeString.str();
}
}
}
};
@@ -143,17 +138,11 @@ Reply Reply::stockReply(Reply::status_type status) {
Reply rep;
rep.status = status;
rep.content = ToString(status);
rep.headers.resize(3);
rep.headers[0].name = "Access-Control-Allow-Origin";
rep.headers[0].value = "*";
rep.headers[1].name = "Content-Length";
std::string s;
intToString(rep.content.size(), s);
rep.headers[1].value = s;
rep.headers[2].name = "Content-Type";
rep.headers[2].value = "text/html";
rep.headers.resize(2);
rep.headers[0].name = "Content-Length";
rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size());
rep.headers[1].name = "Content-Type";
rep.headers[1].value = "text/html";
return rep;
}
} // namespace http
+6 -5
View File
@@ -21,9 +21,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef CONNECTION_H
#define CONNECTION_H
#include "BasicDatastructures.h"
#include "RequestHandler.h"
#include "RequestParser.h"
#include <vector>
#include <boost/asio.hpp>
#include <boost/array.hpp>
@@ -32,9 +30,12 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <zlib.h>
#include "../DataStructures/Util.h"
#include "BasicDatastructures.h"
#include "RequestHandler.h"
#include "RequestParser.h"
#include <vector>
#include "zlib.h"
namespace http {
+32 -75
View File
@@ -20,107 +20,64 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include "QueryObjectsStorage.h"
#include "../../Util/GraphLoader.h"
QueryObjectsStorage::QueryObjectsStorage(
const std::string & hsgrPath,
const std::string & ramIndexPath,
const std::string & fileIndexPath,
const std::string & nodesPath,
const std::string & edgesPath,
const std::string & namesPath,
const std::string & timestampPath
) {
if( hsgrPath.empty() ) {
throw OSRMException("no hsgr file given in ini file");
}
if( ramIndexPath.empty() ) {
throw OSRMException("no ram index file given in ini file");
}
if( fileIndexPath.empty() ) {
throw OSRMException("no mem index file given in ini file");
}
if( nodesPath.empty() ) {
throw OSRMException("no nodes file given in ini file");
}
if( edgesPath.empty() ) {
throw OSRMException("no edges file given in ini file");
}
if( namesPath.empty() ) {
throw OSRMException("no names file given in ini file");
}
SimpleLogger().Write() << "loading graph data";
QueryObjectsStorage::QueryObjectsStorage(std::string hsgrPath, std::string ramIndexPath, std::string fileIndexPath, std::string nodesPath, std::string edgesPath, std::string namesPath, std::string timestampPath) {
INFO("loading graph data");
std::ifstream hsgrInStream(hsgrPath.c_str(), std::ios::binary);
if(!hsgrInStream) { ERR(hsgrPath << " not found"); }
//Deserialize road network graph
std::vector< QueryGraph::_StrNode> nodeList;
std::vector< QueryGraph::_StrEdge> edgeList;
const int n = readHSGRFromStream(
hsgrPath,
nodeList,
edgeList,
&checkSum
);
const int n = readHSGRFromStream(hsgrInStream, nodeList, edgeList, &checkSum);
SimpleLogger().Write() << "Data checksum is " << checkSum;
INFO("Data checksum is " << checkSum);
graph = new QueryGraph(nodeList, edgeList);
assert(0 == nodeList.size());
assert(0 == edgeList.size());
if(timestampPath.length()) {
SimpleLogger().Write() << "Loading Timestamp";
INFO("Loading Timestamp");
std::ifstream timestampInStream(timestampPath.c_str());
if(!timestampInStream) {
SimpleLogger().Write(logWARNING) << timestampPath << " not found";
}
if(!timestampInStream) { ERR(timestampPath << " not found"); }
getline(timestampInStream, timestamp);
timestampInStream.close();
}
if(!timestamp.length()) {
if(!timestamp.length())
timestamp = "n/a";
}
if(25 < timestamp.length()) {
if(25 < timestamp.length())
timestamp.resize(25);
}
SimpleLogger().Write() << "Loading auxiliary information";
INFO("Loading auxiliary information");
//Init nearest neighbor data structure
nodeHelpDesk = new NodeInformationHelpDesk(
ramIndexPath,
fileIndexPath,
nodesPath,
edgesPath,
n,
checkSum
);
std::ifstream nodesInStream(nodesPath.c_str(), std::ios::binary);
if(!nodesInStream) { ERR(nodesPath << " not found"); }
std::ifstream edgesInStream(edgesPath.c_str(), std::ios::binary);
if(!edgesInStream) { ERR(edgesPath << " not found"); }
nodeHelpDesk = new NodeInformationHelpDesk(ramIndexPath.c_str(), fileIndexPath.c_str(), n, checkSum);
nodeHelpDesk->initNNGrid(nodesInStream, edgesInStream);
//deserialize street name list
SimpleLogger().Write() << "Loading names index";
boost::filesystem::path names_file(namesPath);
if ( !boost::filesystem::exists( names_file ) ) {
throw OSRMException("names file does not exist");
}
if ( 0 == boost::filesystem::file_size( names_file ) ) {
throw OSRMException("names file is empty");
}
boost::filesystem::ifstream name_stream(names_file, std::ios::binary);
unsigned size = 0;
name_stream.read((char *)&size, sizeof(unsigned));
BOOST_ASSERT_MSG(0 != size, "name file empty");
INFO("Loading names index");
std::ifstream namesInStream(namesPath.c_str(), std::ios::binary);
if(!namesInStream) { ERR(namesPath << " not found"); }
unsigned size(0);
namesInStream.read((char *)&size, sizeof(unsigned));
// names = new std::vector<std::string>();
char buf[1024];
for( unsigned i = 0; i < size; ++i ) {
unsigned size_of_string = 0;
name_stream.read((char *)&size_of_string, sizeof(unsigned));
buf[size_of_string] = '\0'; // instead of memset
name_stream.read(buf, size_of_string);
for(unsigned i = 0; i < size; ++i) {
unsigned sizeOfString = 0;
namesInStream.read((char *)&sizeOfString, sizeof(unsigned));
buf[sizeOfString] = '\0'; // instead of memset
namesInStream.read(buf, sizeOfString);
names.push_back(buf);
}
std::vector<std::string>(names).swap(names);
BOOST_ASSERT_MSG(0 != names.size(), "could not load any names");
name_stream.close();
SimpleLogger().Write() << "All query data structures loaded";
hsgrInStream.close();
namesInStream.close();
INFO("All query data structures loaded");
}
QueryObjectsStorage::~QueryObjectsStorage() {
+6 -22
View File
@@ -22,24 +22,16 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef QUERYOBJECTSSTORAGE_H_
#define QUERYOBJECTSSTORAGE_H_
#include "../../Util/GraphLoader.h"
#include "../../Util/OSRMException.h"
#include "../../Util/SimpleLogger.h"
#include<vector>
#include<string>
#include "../../DataStructures/NodeInformationHelpDesk.h"
#include "../../DataStructures/QueryEdge.h"
#include "../../DataStructures/StaticGraph.h"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <vector>
#include <string>
struct QueryObjectsStorage {
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
typedef QueryGraph::InputEdge InputEdge;
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
typedef QueryGraph::InputEdge InputEdge;
NodeInformationHelpDesk * nodeHelpDesk;
std::vector<std::string> names;
@@ -47,15 +39,7 @@ struct QueryObjectsStorage {
std::string timestamp;
unsigned checkSum;
QueryObjectsStorage(
const std::string & hsgrPath,
const std::string & ramIndexPath,
const std::string & fileIndexPath,
const std::string & nodesPath,
const std::string & edgesPath,
const std::string & namesPath,
const std::string & timestampPath
);
QueryObjectsStorage(std::string hsgrPath, std::string ramIndexPath, std::string fileIndexPath, std::string nodesPath, std::string edgesPath, std::string namesPath, std::string timestampPath);
~QueryObjectsStorage();
};
+60 -57
View File
@@ -21,92 +21,95 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef REQUEST_HANDLER_H
#define REQUEST_HANDLER_H
#include "APIGrammar.h"
#include "BasicDatastructures.h"
#include "DataStructures/RouteParameters.h"
#include "../Library/OSRM.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
#include <boost/foreach.hpp>
#include <algorithm>
#include <cctype> // std::tolower
#include <string>
#include <iostream>
#include <boost/lexical_cast.hpp>
#include <boost/noncopyable.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include "APIGrammar.h"
#include "BasicDatastructures.h"
#include "../DataStructures/HashTable.h"
#include "../Plugins/BasePlugin.h"
#include "../Plugins/RouteParameters.h"
#include "../typedefs.h"
namespace http {
class RequestHandler : private boost::noncopyable {
public:
typedef APIGrammar<std::string::iterator, RouteParameters> APIGrammarParser;
explicit RequestHandler() { }
explicit RequestHandler() : _pluginCount(0) { }
void handle_request(const http::Request& req, http::Reply& rep){
~RequestHandler() {
for(unsigned i = 0; i < _pluginVector.size(); i++) {
BasePlugin * tempPointer = _pluginVector[i];
delete tempPointer;
}
}
void handle_request(const Request& req, Reply& rep){
//parse command
try {
std::string request(req.uri);
std::string request(req.uri);
{ //This block logs the current request to std out. should be moved to a logging component
time_t ltime;
struct tm *Tm;
ltime=time(NULL);
Tm=localtime(&ltime);
SimpleLogger().Write() <<
(Tm->tm_mday < 10 ? "0" : "" ) << Tm->tm_mday << "-" <<
(Tm->tm_mon+1 < 10 ? "0" : "" ) << (Tm->tm_mon+1) << "-" <<
1900+Tm->tm_year << " " << (Tm->tm_hour < 10 ? "0" : "" ) <<
Tm->tm_hour << ":" << (Tm->tm_min < 10 ? "0" : "" ) <<
Tm->tm_min << ":" << (Tm->tm_sec < 10 ? "0" : "" ) <<
Tm->tm_sec << " " << req.endpoint.to_string() << " " <<
req.referrer << ( 0 == req.referrer.length() ? "- " :" ") <<
req.agent << ( 0 == req.agent.length() ? "- " :" ") << req.uri;
INFO((Tm->tm_mday < 10 ? "0" : "" ) << Tm->tm_mday << "-" << (Tm->tm_mon+1 < 10 ? "0" : "" ) << (Tm->tm_mon+1) << "-" << 1900+Tm->tm_year << " " << (Tm->tm_hour < 10 ? "0" : "" ) << Tm->tm_hour << ":" << (Tm->tm_min < 10 ? "0" : "" ) << Tm->tm_min << ":" << (Tm->tm_sec < 10 ? "0" : "" ) << Tm->tm_sec << " " <<
req.endpoint.to_string() << " " << req.referrer << ( 0 == req.referrer.length() ? "- " :" ") << req.agent << ( 0 == req.agent.length() ? "- " :" ") << req.uri );
}
try {
RouteParameters routeParameters;
APIGrammarParser apiParser(&routeParameters);
APIGrammar<std::string::iterator, RouteParameters> apiParser(&routeParameters);
std::string::iterator it = request.begin();
const bool result = boost::spirit::qi::parse(
it,
request.end(),
apiParser
);
if ( !result || (it != request.end()) ) {
bool result = boost::spirit::qi::parse(it, request.end(), apiParser); // returns true if successful
if (!result || (it != request.end()) ) {
rep = http::Reply::stockReply(http::Reply::badRequest);
const int position = std::distance(request.begin(), it);
std::string tmp_position_string;
intToString(position, tmp_position_string);
rep.content += "Input seems to be malformed close to position ";
rep.content += "<br><pre>";
rep.content += request;
rep.content += tmp_position_string;
rep.content += "<br>";
const unsigned end = std::distance(request.begin(), it);
for(unsigned i = 0; i < end; ++i) {
rep.content += "&nbsp;";
}
rep.content += "^<br></pre>";
std::stringstream content;
int position = std::distance(request.begin(), it);
content << "Input seems to be malformed close to position " << position << "<br>";
content << "<pre>";
content << req.uri << "<br>";
for(unsigned i = 0, end = std::distance(request.begin(), it); i < end; ++i)
content << "&nbsp;";
content << "^" << "<br>";
content << "</pre>";
rep.content += content.str();
} else {
//parsing done, lets call the right plugin to handle the request
routing_machine->RunQuery(routeParameters, rep);
//Finished parsing, lets call the right plugin to handle the request
if(pluginMap.Holds(routeParameters.service)) {
rep.status = Reply::ok;
_pluginVector[pluginMap.Find(routeParameters.service)]->HandleRequest(routeParameters, rep );
} else {
rep = Reply::stockReply(Reply::badRequest);
}
return;
}
} catch(std::exception& e) {
rep = http::Reply::stockReply(http::Reply::internalServerError);
SimpleLogger().Write(logWARNING) <<
"[server error] code: " << e.what() << ", uri: " << req.uri;
rep = Reply::stockReply(Reply::internalServerError);
std::cerr << "[server error] code: " << e.what() << ", uri: " << req.uri << std::endl;
return;
}
};
void RegisterRoutingMachine(OSRM * osrm) {
routing_machine = osrm;
void RegisterPlugin(BasePlugin * plugin) {
std::cout << "[handler] registering plugin " << plugin->GetDescriptor() << std::endl;
pluginMap.Add(plugin->GetDescriptor(), _pluginCount);
_pluginVector.push_back(plugin);
++_pluginCount;
}
private:
OSRM * routing_machine;
HashTable<std::string, unsigned> pluginMap;
std::vector<BasePlugin *> _pluginVector;
unsigned _pluginCount;
};
} // namespace http
#endif // REQUEST_HANDLER_H
+1 -2
View File
@@ -21,10 +21,9 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef REQUEST_PARSER_H
#define REQUEST_PARSER_H
#include "BasicDatastructures.h"
#include <boost/logic/tribool.hpp>
#include <boost/tuple/tuple.hpp>
#include "BasicDatastructures.h"
namespace http {
+14 -34
View File
@@ -21,29 +21,21 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef SERVER_H
#define SERVER_H
#include "Connection.h"
#include "RequestHandler.h"
#include <vector>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <vector>
#include "Connection.h"
#include "RequestHandler.h"
namespace http {
class Server: private boost::noncopyable {
public:
explicit Server(
const std::string& address,
const std::string& port,
unsigned thread_pool_size
) :
threadPoolSize(thread_pool_size),
acceptor(ioService),
newConnection(new http::Connection(ioService, requestHandler)),
requestHandler()
{
explicit Server(const std::string& address, const std::string& port, unsigned thread_pool_size) : threadPoolSize(thread_pool_size), acceptor(ioService), newConnection(new Connection(ioService, requestHandler)), requestHandler(){
boost::asio::ip::tcp::resolver resolver(ioService);
boost::asio::ip::tcp::resolver::query query(address, port);
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
@@ -52,14 +44,7 @@ public:
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
acceptor.bind(endpoint);
acceptor.listen();
acceptor.async_accept(
newConnection->socket(),
boost::bind(
&Server::handleAccept,
this,
boost::asio::placeholders::error
)
);
acceptor.async_accept(newConnection->socket(), boost::bind(&Server::handleAccept, this, boost::asio::placeholders::error));
}
void Run() {
@@ -81,28 +66,23 @@ public:
}
private:
typedef boost::shared_ptr<Connection > ConnectionPtr;
void handleAccept(const boost::system::error_code& e) {
if (!e) {
newConnection->start();
newConnection.reset(
new http::Connection(ioService, requestHandler)
);
acceptor.async_accept(
newConnection->socket(),
boost::bind(
&Server::handleAccept,
this,
boost::asio::placeholders::error
)
);
newConnection.reset(new Connection(ioService, requestHandler));
acceptor.async_accept(newConnection->socket(), boost::bind(&Server::handleAccept, this, boost::asio::placeholders::error));
}
}
unsigned threadPoolSize;
boost::asio::io_service ioService;
boost::asio::ip::tcp::acceptor acceptor;
boost::shared_ptr<http::Connection> newConnection;
ConnectionPtr newConnection;
RequestHandler requestHandler;
};
} // namespace http
#endif // SERVER_H
@@ -1,6 +1,6 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
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
@@ -16,23 +16,13 @@ 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 MERCATORUTIL_H_
#define MERCATORUTIL_H_
#ifndef SERVERCONFIGURATION_H_
#define SERVERCONFIGURATION_H_
#include <cmath>
#include "../Util/BaseConfiguration.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
typedef BaseConfiguration ServerConfiguration;
inline double y2lat(double a) {
return 180/M_PI * (2 * atan(exp(a*M_PI/180)) - M_PI/2);
}
inline double lat2y(double a) {
return 180/M_PI * log(tan(M_PI/4+a*(M_PI/180)/2));
}
#endif /* MERCATORUTIL_H_ */
#endif /* SERVERCONFIGURATION_H_ */
+43 -27
View File
@@ -16,51 +16,67 @@ 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: 26.11.2010
Author: dennis
*/
#ifndef SERVERFACTORY_H_
#define SERVERFACTORY_H_
#include "Server.h"
#include "../Util/IniFile.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include <zlib.h>
#include <boost/noncopyable.hpp>
#include "Server.h"
#include "ServerConfiguration.h"
#include "../Util/InputFileUtil.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
typedef http::Server Server;
struct ServerFactory {
static Server * CreateServer(ServerConfiguration& serverConfig) {
if(!testDataFile(serverConfig.GetParameter("nodesData"))) {
ERR("nodes file not found");
}
if(!testDataFile(serverConfig.GetParameter("hsgrData"))) {
ERR("hsgr file not found");
}
if(!testDataFile(serverConfig.GetParameter("namesData"))) {
ERR("names file not found");
}
if(!testDataFile(serverConfig.GetParameter("ramIndex"))) {
ERR("ram index file not found");
}
if(!testDataFile(serverConfig.GetParameter("fileIndex"))) {
ERR("file index file not found");
}
struct ServerFactory : boost::noncopyable {
static Server * CreateServer( IniFile & serverConfig ) {
int threads = omp_get_num_procs();
if( serverConfig.GetParameter("IP").empty() ) {
if(serverConfig.GetParameter("IP") == "")
serverConfig.SetParameter("IP", "0.0.0.0");
}
if( serverConfig.GetParameter("Port").empty() ) {
if(serverConfig.GetParameter("Port") == "")
serverConfig.SetParameter("Port", "5000");
}
if(
stringToInt(serverConfig.GetParameter("Threads")) >= 1 &&
stringToInt(serverConfig.GetParameter("Threads")) <= threads
) {
if(stringToInt(serverConfig.GetParameter("Threads")) != 0 && stringToInt(serverConfig.GetParameter("Threads")) <= threads)
threads = stringToInt( serverConfig.GetParameter("Threads") );
}
SimpleLogger().Write() <<
"http 1.1 compression handled by zlib version " << zlibVersion();
Server * server = new Server(
serverConfig.GetParameter("IP"),
serverConfig.GetParameter("Port"),
threads
);
std::cout << "[server] http 1.1 compression handled by zlib version " << zlibVersion() << std::endl;
Server * server = new Server(serverConfig.GetParameter("IP"), serverConfig.GetParameter("Port"), threads);
return server;
}
static Server * CreateServer(const char * iniFile) {
IniFile serverConfig(iniFile);
ServerConfiguration serverConfig(iniFile);
return CreateServer(serverConfig);
}
};
+59 -79
View File
@@ -18,20 +18,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "../typedefs.h"
#include "../Algorithms/StronglyConnectedComponents.h"
#include "../DataStructures/BinaryHeap.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/GraphLoader.h"
#include "../Util/IniFile.h"
#include "../Util/InputFileUtil.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#define VERBOSE(x) x
#define VERBOSE2(x)
#ifdef NDEBUG
#undef VERBOSE
#undef VERBOSE2
#endif
#include <boost/foreach.hpp>
#include <fstream>
#include <istream>
#include <iostream>
@@ -39,84 +35,68 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <string>
#include <vector>
typedef QueryEdge::EdgeData EdgeData;
#include "../typedefs.h"
#include "../Algorithms/StronglyConnectedComponents.h"
#include "../DataStructures/BinaryHeap.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/BaseConfiguration.h"
#include "../Util/InputFileUtil.h"
#include "../Util/GraphLoader.h"
using namespace std;
typedef QueryEdge::EdgeData EdgeData;
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
typedef BaseConfiguration ContractorConfiguration;
std::vector<NodeInfo> internal_to_external_node_map;
std::vector<TurnRestriction> restrictions_vector;
std::vector<NodeID> bollard_node_IDs_vector;
std::vector<NodeID> traffic_light_node_IDs_vector;
std::vector<NodeInfo> internalToExternalNodeMapping;
std::vector<_Restriction> inputRestrictions;
std::vector<NodeID> bollardNodes;
std::vector<NodeID> trafficLightNodes;
int main (int argc, char * argv[]) {
LogPolicy::GetInstance().Unmute();
int main (int argc, char *argv[]) {
if(argc < 3) {
SimpleLogger().Write(logWARNING) <<
"usage:\n" << argv[0] << " <osrm> <osrm.restrictions>";
return -1;
ERR("usage: " << std::endl << argv[0] << " <osrm-data> <osrm-restrictions>");
}
std::string SRTM_ROOT;
INFO("Using restrictions from file: " << argv[2]);
std::ifstream restrictionsInstream(argv[2], ios::binary);
if(!restrictionsInstream.good()) {
ERR("Could not access <osrm-restrictions> files");
}
_Restriction restriction;
unsigned usableRestrictionsCounter(0);
restrictionsInstream.read((char*)&usableRestrictionsCounter, sizeof(unsigned));
inputRestrictions.resize(usableRestrictionsCounter);
restrictionsInstream.read((char *)&(inputRestrictions[0]), usableRestrictionsCounter*sizeof(_Restriction));
restrictionsInstream.close();
std::ifstream in;
in.open (argv[1], std::ifstream::in | std::ifstream::binary);
if (!in.is_open()) {
ERR("Cannot open " << argv[1]);
}
SimpleLogger().Write() <<
"Using restrictions from file: " << argv[2];
std::ifstream restriction_ifstream(argv[2], std::ios::binary);
if(!restriction_ifstream.good()) {
throw OSRMException("Could not access <osrm-restrictions> files");
}
uint32_t usable_restriction_count = 0;
restriction_ifstream.read(
(char*)&usable_restriction_count,
sizeof(uint32_t)
);
restrictions_vector.resize(usable_restriction_count);
restriction_ifstream.read(
(char *)&(restrictions_vector[0]),
usable_restriction_count*sizeof(TurnRestriction)
);
restriction_ifstream.close();
std::ifstream input_stream;
input_stream.open( argv[1], std::ifstream::in | std::ifstream::binary );
if (!input_stream.is_open()) {
throw OSRMException("Cannot open osrm file");
}
std::vector<ImportEdge> edge_list;
NodeID node_based_node_count = readBinaryOSRMGraphFromStream(
input_stream,
edge_list,
bollard_node_IDs_vector,
traffic_light_node_IDs_vector,
&internal_to_external_node_map,
restrictions_vector
);
input_stream.close();
SimpleLogger().Write() <<
restrictions_vector.size() << " restrictions, " <<
bollard_node_IDs_vector.size() << " bollard nodes, " <<
traffic_light_node_IDs_vector.size() << " traffic lights";
std::vector<ImportEdge> edgeList;
NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions);
in.close();
INFO(inputRestrictions.size() << " restrictions, " << bollardNodes.size() << " bollard nodes, " << trafficLightNodes.size() << " traffic lights");
/***
* Building an edge-expanded graph from node-based input an turn restrictions
*/
SimpleLogger().Write() << "Starting SCC graph traversal";
TarjanSCC * tarjan = new TarjanSCC (
node_based_node_count,
edge_list,
bollard_node_IDs_vector,
traffic_light_node_IDs_vector,
restrictions_vector,
internal_to_external_node_map
);
std::vector<ImportEdge>().swap(edge_list);
INFO("Starting SCC graph traversal");
TarjanSCC * tarjan = new TarjanSCC (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping);
std::vector<ImportEdge>().swap(edgeList);
tarjan->Run();
std::vector<TurnRestriction>().swap(restrictions_vector);
std::vector<NodeID>().swap(bollard_node_IDs_vector);
std::vector<NodeID>().swap(traffic_light_node_IDs_vector);
SimpleLogger().Write() << "finished component analysis";
std::vector<_Restriction>().swap(inputRestrictions);
std::vector<NodeID>().swap(bollardNodes);
std::vector<NodeID>().swap(trafficLightNodes);
INFO("finished component analysis");
return 0;
}
-93
View File
@@ -1,93 +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.
*/
#include "../Library/OSRM.h"
#include "../Util/SimpleLogger.h"
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
#include <stack>
#include <string>
#include <sstream>
//Dude, real recursions on the OS stack? You must be brave...
void print_tree(boost::property_tree::ptree const& pt, const unsigned recursion_depth)
{
boost::property_tree::ptree::const_iterator end = pt.end();
for (boost::property_tree::ptree::const_iterator it = pt.begin(); it != end; ++it) {
for(unsigned i = 0; i < recursion_depth; ++i) {
std::cout << " " << std::flush;
}
std::cout << it->first << ": " << it->second.get_value<std::string>() << std::endl;
print_tree(it->second, recursion_depth+1);
}
}
int main (int argc, char * argv[]) {
LogPolicy::GetInstance().Unmute();
try {
std::cout << "\n starting up engines, compile at "
<< __DATE__ << ", " __TIME__ << std::endl;
IniFile serverConfig((argc > 1 ? argv[1] : "server.ini"));
OSRM routing_machine((argc > 1 ? argv[1] : "server.ini"));
RouteParameters route_parameters;
route_parameters.zoomLevel = 18; //no generalization
route_parameters.printInstructions = true; //turn by turn instructions
route_parameters.alternateRoute = true; //get an alternate route, too
route_parameters.geometry = true; //retrieve geometry of route
route_parameters.compression = true; //polyline encoding
route_parameters.checkSum = UINT_MAX; //see wiki
route_parameters.service = "viaroute"; //that's routing
route_parameters.outputFormat = "json";
route_parameters.jsonpParameter = ""; //set for jsonp wrapping
route_parameters.language = ""; //unused atm
//route_parameters.hints.push_back(); // see wiki, saves I/O if done properly
FixedPointCoordinate start_coordinate(52.519930*COORDINATE_PRECISION,13.438640*COORDINATE_PRECISION);
FixedPointCoordinate target_coordinate(52.513191*COORDINATE_PRECISION,13.415852*COORDINATE_PRECISION);
route_parameters.coordinates.push_back(start_coordinate);
route_parameters.coordinates.push_back(target_coordinate);
http::Reply osrm_reply;
routing_machine.RunQuery(route_parameters, osrm_reply);
std::cout << osrm_reply.content << std::endl;
//attention: super-inefficient hack below:
std::stringstream ss;
ss << osrm_reply.content;
boost::property_tree::ptree pt;
boost::property_tree::read_json(ss, pt);
print_tree(pt, 0);
} catch (std::exception & e) {
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
return -1;
}
return 0;
}
+107
View File
@@ -0,0 +1,107 @@
/*
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 BASECONFIGURATION_H_
#define BASECONFIGURATION_H_
#include <iostream>
#include <string>
#include <exception>
#include <fstream>
#include "../DataStructures/HashTable.h"
class BaseConfiguration {
public:
BaseConfiguration(const char * configFile) {
std::ifstream config( configFile );
if(!config) {
std::cerr << "[config] .ini not found" << std::endl;
return;
}
std::string line;
try {
if (config.is_open()) {
while ( config.good() ) {
getline (config,line);
std::vector<std::string> tokens;
Tokenize(line, tokens);
if(2 == tokens.size() )
parameters.Add(tokens[0], tokens[1]);
}
config.close();
}
} catch(std::exception& e) {
ERR("[config] " << configFile << " not found -> Exception: " <<e.what());
if(config.is_open())
config.close();
}
}
std::string GetParameter(const char * key){
return GetParameter(std::string(key));
}
std::string GetParameter(std::string key) {
return parameters.Find(key);
}
void SetParameter(const char* key, const char* value) {
SetParameter(std::string(key), std::string(value));
}
void SetParameter(std::string key, std::string value) {
parameters.Set(key, value);
}
private:
void Tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters = "=") {
std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
std::string::size_type pos = str.find_first_of(delimiters, lastPos);
while (std::string::npos != pos || std::string::npos != lastPos) {
std::string temp = str.substr(lastPos, pos - lastPos);
TrimStringRight(temp);
TrimStringLeft(temp);
tokens.push_back( temp );
lastPos = str.find_first_not_of(delimiters, pos);
pos = str.find_first_of(delimiters, lastPos);
}
}
void TrimStringRight(std::string& str) {
std::string::size_type pos = str.find_last_not_of(" ");
if (pos != std::string::npos)
str.erase(pos+1);
else
str.erase( str.begin() , str.end() );
}
void TrimStringLeft(std::string& str) {
std::string::size_type pos = str.find_first_not_of(" ");
if (pos != std::string::npos)
str.erase(0, pos);
else
str.erase( str.begin() , str.end() );
}
HashTable<std::string, std::string> parameters;
};
#endif /* BASECONFIGURATION_H_ */
-34
View File
@@ -1,34 +0,0 @@
/*
* ContainerUtils.h
*
* Created on: 02.02.2013
* Author: dennis
*/
#ifndef CONTAINERUTILS_H_
#define CONTAINERUTILS_H_
#include <algorithm>
#include <vector>
template<typename T>
inline void sort_unique_resize(std::vector<T> & vector) {
std::sort(vector.begin(), vector.end());
unsigned number_of_unique_elements = std::unique(vector.begin(), vector.end()) - vector.begin();
vector.resize(number_of_unique_elements);
}
template<typename T>
inline void sort_unique_resize_shrink_vector(std::vector<T> & vector) {
sort_unique_resize(vector);
std::vector<T>().swap(vector);
}
template<typename T>
inline void remove_consecutive_duplicates_from_vector(std::vector<T> & vector) {
unsigned number_of_unique_elements = std::unique(vector.begin(), vector.end()) - vector.begin();
vector.resize(number_of_unique_elements);
}
#endif /* CONTAINERUTILS_H_ */
+64 -144
View File
@@ -21,20 +21,6 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef GRAPHLOADER_H
#define GRAPHLOADER_H
#include "OSRMException.h"
#include "../DataStructures/ImportNode.h"
#include "../DataStructures/ImportEdge.h"
#include "../DataStructures/QueryNode.h"
#include "../DataStructures/Restriction.h"
#include "../Util/SimpleLogger.h"
#include "../Util/UUID.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/unordered_map.hpp>
#include <cassert>
#include <cmath>
@@ -44,51 +30,40 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <iomanip>
#include <vector>
#include <boost/unordered_map.hpp>
#include "../DataStructures/ImportNode.h"
#include "../DataStructures/ImportEdge.h"
#include "../DataStructures/NodeCoords.h"
#include "../DataStructures/Restriction.h"
#include "../typedefs.h"
typedef boost::unordered_map<NodeID, NodeID> ExternalNodeMap;
template<class EdgeT>
struct _ExcessRemover {
inline bool operator()( const EdgeT & edge ) const {
inline bool operator()( EdgeT & edge ) const {
return edge.source() == UINT_MAX;
}
};
template<typename EdgeT>
NodeID readBinaryOSRMGraphFromStream(
std::istream &in,
std::vector<EdgeT>& edgeList,
std::vector<NodeID> &bollardNodes,
std::vector<NodeID> &trafficLightNodes,
std::vector<NodeInfo> * int2ExtNodeMap,
std::vector<TurnRestriction> & inputRestrictions
) {
const UUID uuid_orig;
UUID uuid_loaded;
in.read((char *) &uuid_loaded, sizeof(UUID));
if( !uuid_loaded.TestGraphUtil(uuid_orig) ) {
SimpleLogger().Write(logWARNING) <<
".osrm was prepared with different build.\n"
"Reprocess to get rid of this warning.";
}
NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, std::vector<NodeID> &bollardNodes, std::vector<NodeID> &trafficLightNodes, std::vector<NodeInfo> * int2ExtNodeMap, std::vector<_Restriction> & inputRestrictions) {
NodeID n, source, target;
EdgeID m;
short dir;// direction (0 = open, 1 = forward, 2+ = open)
ExternalNodeMap ext2IntNodeMap;
in.read((char*)&n, sizeof(NodeID));
SimpleLogger().Write() << "Importing n = " << n << " nodes ";
DEBUG("Importing n = " << n << " nodes ");
_Node node;
for (NodeID i=0; i<n; ++i) {
in.read((char*)&node, sizeof(_Node));
int2ExtNodeMap->push_back(NodeInfo(node.lat, node.lon, node.id));
ext2IntNodeMap.insert(std::make_pair(node.id, i));
if(node.bollard) {
if(node.bollard)
bollardNodes.push_back(i);
}
if(node.trafficLight) {
if(node.trafficLight)
trafficLightNodes.push_back(i);
}
}
//tighten vector sizes
@@ -96,11 +71,11 @@ NodeID readBinaryOSRMGraphFromStream(
std::vector<NodeID>(trafficLightNodes).swap(trafficLightNodes);
in.read((char*)&m, sizeof(unsigned));
SimpleLogger().Write() << " and " << m << " edges ";
DEBUG(" and " << m << " edges ");
for(unsigned i = 0; i < inputRestrictions.size(); ++i) {
ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(inputRestrictions[i].fromNode);
if( intNodeID == ext2IntNodeMap.end()) {
SimpleLogger().Write(logDEBUG) << "Unmapped from Node of restriction";
DEBUG("Unmapped from Node of restriction");
continue;
}
@@ -108,14 +83,14 @@ NodeID readBinaryOSRMGraphFromStream(
intNodeID = ext2IntNodeMap.find(inputRestrictions[i].viaNode);
if( intNodeID == ext2IntNodeMap.end()) {
SimpleLogger().Write(logDEBUG) << "Unmapped via node of restriction";
DEBUG("Unmapped via node of restriction");
continue;
}
inputRestrictions[i].viaNode = intNodeID->second;
intNodeID = ext2IntNodeMap.find(inputRestrictions[i].toNode);
if( intNodeID == ext2IntNodeMap.end()) {
SimpleLogger().Write(logDEBUG) << "Unmapped to node of restriction";
DEBUG("Unmapped to node of restriction");
continue;
}
inputRestrictions[i].toNode = intNodeID->second;
@@ -126,7 +101,7 @@ NodeID readBinaryOSRMGraphFromStream(
short type;
NodeID nameID;
int length;
bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow;
bool isRoundabout, ignoreInGrid, isAccessRestricted;
for (EdgeID i=0; i<m; ++i) {
in.read((char*)&source, sizeof(unsigned));
@@ -139,11 +114,10 @@ NodeID readBinaryOSRMGraphFromStream(
in.read((char*)&isRoundabout, sizeof(bool));
in.read((char*)&ignoreInGrid, sizeof(bool));
in.read((char*)&isAccessRestricted, sizeof(bool));
in.read((char*)&isContraFlow, sizeof(bool));
BOOST_ASSERT_MSG(length > 0, "loaded null length edge" );
BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
BOOST_ASSERT_MSG(0<=dir && dir<=2, "loaded bogus direction");
GUARANTEE(length > 0, "loaded null length edge" );
GUARANTEE(weight > 0, "loaded null weight");
GUARANTEE(0<=dir && dir<=2, "loaded bogus direction");
bool forward = true;
bool backward = true;
@@ -156,8 +130,7 @@ NodeID readBinaryOSRMGraphFromStream(
ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(source);
if( ext2IntNodeMap.find(source) == ext2IntNodeMap.end()) {
#ifndef NDEBUG
SimpleLogger().Write(logWARNING) <<
" unresolved source NodeID: " << source;
WARN(" unresolved source NodeID: " << source );
#endif
continue;
}
@@ -165,22 +138,19 @@ NodeID readBinaryOSRMGraphFromStream(
intNodeID = ext2IntNodeMap.find(target);
if(ext2IntNodeMap.find(target) == ext2IntNodeMap.end()) {
#ifndef NDEBUG
SimpleLogger().Write(logWARNING) <<
"unresolved target NodeID : " << target;
WARN("unresolved target NodeID : " << target );
#endif
continue;
}
target = intNodeID->second;
BOOST_ASSERT_MSG(source != UINT_MAX && target != UINT_MAX,
"nonexisting source or target"
);
GUARANTEE(source != UINT_MAX && target != UINT_MAX, "nonexisting source or target");
if(source > target) {
std::swap(source, target);
std::swap(forward, backward);
}
EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow );
EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted );
edgeList.push_back(inputEdge);
}
std::sort(edgeList.begin(), edgeList.end());
@@ -199,14 +169,14 @@ NodeID readBinaryOSRMGraphFromStream(
edgeList[i]._source = UINT_MAX;
} else {
//edge i-1 is open in both directions, but edge i is smaller in one direction. Close edge i-1 in this direction
edgeList[i-1].forward = !edgeList[i].isForward();
edgeList[i-1].backward = !edgeList[i].isBackward();
edgeList[i-1].forward = ~edgeList[i].isForward();
edgeList[i-1].backward = ~edgeList[i].isBackward();
}
} else if (edgeFlagsAreSuperSet2) {
if(edgeList[i-1].weight() <= edgeList[i].weight()) {
//edge i-1 is smaller for one direction. edge i is open in both. close edge i in the other direction
edgeList[i].forward = !edgeList[i-1].isForward();
edgeList[i].backward = !edgeList[i-1].isBackward();
edgeList[i].forward = ~edgeList[i-1].isForward();
edgeList[i].backward = ~edgeList[i-1].isBackward();
} else {
//edge i is smaller and goes in both direction. Throw away edge i-1
edgeList[i-1]._source = UINT_MAX;
@@ -214,10 +184,10 @@ NodeID readBinaryOSRMGraphFromStream(
}
}
}
typename std::vector<EdgeT>::iterator newEnd = std::remove_if(edgeList.begin(), edgeList.end(), _ExcessRemover<EdgeT>());
std::vector<ImportEdge>::iterator newEnd = std::remove_if(edgeList.begin(), edgeList.end(), _ExcessRemover<EdgeT>());
ext2IntNodeMap.clear();
std::vector<EdgeT>(edgeList.begin(), newEnd).swap(edgeList); //remove excess candidates.
SimpleLogger().Write() << "Graph loaded ok and has " << edgeList.size() << " edges";
std::vector<ImportEdge>(edgeList.begin(), newEnd).swap(edgeList); //remove excess candidates.
INFO("Graph loaded ok and has " << edgeList.size() << " edges");
return n;
}
template<typename EdgeT>
@@ -227,14 +197,14 @@ NodeID readDTMPGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
int dir, xcoord, ycoord;// direction (0 = open, 1 = forward, 2+ = open)
ExternalNodeMap ext2IntNodeMap;
in >> n;
SimpleLogger().Write(logDEBUG) << "Importing n = " << n << " nodes ";
for (NodeID i=0; i<n; ++i) {
DEBUG("Importing n = " << n << " nodes ");
for (NodeID i=0; i<n;++i) {
in >> id >> ycoord >> xcoord;
int2ExtNodeMap->push_back(NodeInfo(xcoord, ycoord, id));
ext2IntNodeMap.insert(std::make_pair(id, i));
}
in >> m;
SimpleLogger().Write(logDEBUG) << " and " << m << " edges";
DEBUG(" and " << m << " edges");
edgeList.reserve(m);
for (EdgeID i=0; i<m; ++i) {
@@ -245,9 +215,9 @@ NodeID readDTMPGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
int length;
in >> source >> target >> length >> dir >> speedType;
if(dir == 3) {
if(dir == 3)
dir = 0;
}
switch(speedType) {
case 1:
weight = 130;
@@ -297,50 +267,38 @@ NodeID readDTMPGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
}
weight = length*weight/3.6;
if(speedType == 13) {
if(speedType == 13)
weight = length;
}
assert(length > 0);
assert(weight > 0);
if(dir <0 || dir > 2) {
SimpleLogger().Write(logWARNING) << "direction bogus: " << dir;
}
if(dir <0 || dir > 2)
WARN("direction bogus: " << dir);
assert(0<=dir && dir<=2);
bool forward = true;
bool backward = true;
if (dir == 1) {
backward = false;
}
if (dir == 2) {
forward = false;
}
if (dir == 1) backward = false;
if (dir == 2) forward = false;
if(length == 0) {
throw OSRMException("loaded null length edge");
}
if(length == 0) { ERR("loaded null length edge"); }
// translate the external NodeIDs to internal IDs
ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(source);
if( ext2IntNodeMap.find(source) == ext2IntNodeMap.end()) {
throw OSRMException("unresolvable source Node ID");
ERR("after " << edgeList.size() << " edges" << "\n->" << source << "," << target << "," << length << "," << dir << "," << weight << "\n->unresolved source NodeID: " << source);
}
source = intNodeID->second;
intNodeID = ext2IntNodeMap.find(target);
if(ext2IntNodeMap.find(target) == ext2IntNodeMap.end()) {
throw OSRMException("unresolvable target Node ID");
}
if(ext2IntNodeMap.find(target) == ext2IntNodeMap.end()) { ERR("unresolved target NodeID : " << target); }
target = intNodeID->second;
if(source == UINT_MAX || target == UINT_MAX) {
throw OSRMException("nonexisting source or target" );
}
if(source == UINT_MAX || target == UINT_MAX) { ERR("nonexisting source or target" ); }
EdgeT inputEdge(source, target, 0, weight, forward, backward, type );
edgeList.push_back(inputEdge);
}
ext2IntNodeMap.clear();
std::vector<EdgeT>(edgeList.begin(), edgeList.end()).swap(edgeList); //remove excess candidates.
std::vector<ImportEdge>(edgeList.begin(), edgeList.end()).swap(edgeList); //remove excess candidates.
std::cout << "ok" << std::endl;
return n;
}
@@ -356,19 +314,17 @@ NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
in >> d;
in >> n;
in >> m;
SimpleLogger().Write(logDEBUG) <<
"expecting " << n << " nodes and " << m << " edges ...";
#ifndef DEBUG
std::cout << "expecting " << n << " nodes and " << m << " edges ..." << flush;
#endif
edgeList.reserve(m);
for (EdgeID i=0; i<m; i++) {
EdgeWeight weight;
in >> source >> target >> weight >> dir;
assert(weight > 0);
if(dir <0 || dir > 3) {
throw OSRMException( "[error] direction bogus");
}
if(dir <0 || dir > 3)
ERR( "[error] direction bogus: " << dir );
assert(0<=dir && dir<=3);
bool forward = true;
@@ -377,9 +333,7 @@ NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
if (dir == 2) forward = false;
if (dir == 3) {backward = true; forward = true;}
if(weight == 0) {
throw OSRMException("loaded null length edge");
}
if(weight == 0) { ERR("loaded null length edge"); }
if( nodeMap.find(source) == nodeMap.end()) {
nodeMap.insert(std::make_pair(source, numberOfNodes ));
@@ -401,53 +355,19 @@ NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
}
template<typename NodeT, typename EdgeT>
unsigned readHSGRFromStream(
const std::string & hsgr_filename,
std::vector<NodeT> & node_list,
std::vector<EdgeT> & edge_list,
unsigned * check_sum
) {
boost::filesystem::path hsgr_file(hsgr_filename);
if ( !boost::filesystem::exists( hsgr_file ) ) {
throw OSRMException("hsgr file does not exist");
}
if ( 0 == boost::filesystem::file_size( hsgr_file ) ) {
throw OSRMException("hsgr file is empty");
}
unsigned readHSGRFromStream(std::istream &in, std::vector<NodeT>& nodeList, std::vector<EdgeT> & edgeList, unsigned * checkSum) {
unsigned numberOfNodes = 0;
in.read((char*) checkSum, sizeof(unsigned));
in.read((char*) & numberOfNodes, sizeof(unsigned));
nodeList.resize(numberOfNodes + 1);
in.read((char*) &(nodeList[0]), numberOfNodes*sizeof(NodeT));
boost::filesystem::ifstream hsgr_input_stream(hsgr_file, std::ios::binary);
unsigned numberOfEdges = 0;
in.read((char*) &numberOfEdges, sizeof(unsigned));
edgeList.resize(numberOfEdges);
in.read((char*) &(edgeList[0]), numberOfEdges*sizeof(EdgeT));
UUID uuid_loaded, uuid_orig;
hsgr_input_stream.read((char *)&uuid_loaded, sizeof(UUID));
if( !uuid_loaded.TestGraphUtil(uuid_orig) ) {
SimpleLogger().Write(logWARNING) <<
".hsgr was prepared with different build. "
"Reprocess to get rid of this warning.";
}
unsigned number_of_nodes = 0;
hsgr_input_stream.read((char*) check_sum, sizeof(unsigned));
hsgr_input_stream.read((char*) & number_of_nodes, sizeof(unsigned));
BOOST_ASSERT_MSG( 0 != number_of_nodes, "number of nodes is zero");
node_list.resize(number_of_nodes + 1);
hsgr_input_stream.read(
(char*) &(node_list[0]),
number_of_nodes*sizeof(NodeT)
);
unsigned number_of_edges = 0;
hsgr_input_stream.read(
(char*) &number_of_edges,
sizeof(unsigned)
);
BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero");
edge_list.resize(number_of_edges);
hsgr_input_stream.read(
(char*) &(edge_list[0]),
number_of_edges*sizeof(EdgeT)
);
hsgr_input_stream.close();
return number_of_nodes;
return numberOfNodes;
}
#endif // GRAPHLOADER_H

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