Replace recursive unpacking procedure by a stack'ed implementation.

This commit is contained in:
DennisOSRM 2011-12-17 20:17:40 +01:00
parent 84bba8aa20
commit ecb979a14b
3 changed files with 120 additions and 37 deletions

View File

@ -22,7 +22,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
#define DOUGLASPEUCKER_H_
#include <cfloat>
#include <stack>
#include "../DataStructures/SimpleStack.h"
/*This class object computes the bitvector of indicating generalized input points
* according to the (Ramer-)Douglas-Peucker algorithm.
@ -39,7 +39,7 @@ class DouglasPeucker {
private:
typedef std::pair<std::size_t, std::size_t> PairOfPoints;
//Stack to simulate the recursion
std::stack<PairOfPoints > recursionStack;
SimpleStack<PairOfPoints > recursionStack;
double ComputeDistanceOfPointToLine(const _Coordinate& inputPoint, const _Coordinate& source, const _Coordinate& target) {
double r;
@ -81,6 +81,7 @@ public:
std::size_t leftBorderOfRange = 0;
std::size_t rightBorderOfRange = 1;
//Sweep linerarily over array and identify those ranges that need to be checked
recursionStack.hint(inputVector.size());
do {
assert(inputVector[leftBorderOfRange].necessary);
assert(inputVector[inputVector.size()-1].necessary);

View File

@ -23,6 +23,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <climits>
#include <deque>
#include "SimpleStack.h"
#include <boost/thread.hpp>
@ -36,7 +37,7 @@ struct _HeapData {
_HeapData( NodeID p ) : parent(p) { }
};
typedef boost::thread_specific_ptr<BinaryHeap< NodeID, NodeID, int, _HeapData> > HeapPtr;
typedef boost::thread_specific_ptr<BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > > HeapPtr;
template<class EdgeData, class GraphT>
class SearchEngine {
@ -57,13 +58,15 @@ public:
}
inline void InitializeThreadLocalStorageIfNecessary() {
if(!_forwardHeap.get())
_forwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData>(nodeHelpDesk->getNumberOfNodes()));
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>(nodeHelpDesk->getNumberOfNodes()));
if(!_backwardHeap.get()) {
_backwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
}
else
_backwardHeap->Clear();
}
@ -117,10 +120,7 @@ public:
pathNode = _backwardHeap->GetData(pathNode).parent;
packedPath.push_back(pathNode);
}
for(deque<NodeID>::size_type i = 0;i < packedPath.size() - 1;i++){
_UnpackEdge(packedPath[i], packedPath[i + 1], path);
}
_UnpackPath(packedPath, path);
return _upperbound;
}
@ -226,23 +226,34 @@ private:
}
}
inline bool _UnpackEdge(const NodeID source, const NodeID target, std::vector<_PathData> & path) const {
assert(source != target);
//find edge first.
inline void _UnpackPath(const std::deque<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const {
const std::deque<NodeID>::size_type sizeOfPackedPath = packedPath.size();
SimpleStack<std::pair<NodeID, NodeID> > recursionStack(sizeOfPackedPath);
//We have to push the path in reverse order onto the stack because it's LIFO.
for(std::deque<NodeID>::size_type i = sizeOfPackedPath-1; i > 0; --i){
recursionStack.push(std::make_pair(packedPath[i-1], packedPath[i]));
}
std::pair<NodeID, NodeID> edge;
while(!recursionStack.empty()) {
edge = recursionStack.top();
recursionStack.pop();
typename GraphT::EdgeIterator smallestEdge = SPECIAL_EDGEID;
int smallestWeight = INT_MAX;
for(typename GraphT::EdgeIterator eit = _graph->BeginEdges(source);eit < _graph->EndEdges(source);eit++){
for(typename GraphT::EdgeIterator eit = _graph->BeginEdges(edge.first);eit < _graph->EndEdges(edge.first);++eit){
const int weight = _graph->GetEdgeData(eit).distance;
if(_graph->GetTarget(eit) == target && weight < smallestWeight && _graph->GetEdgeData(eit).forward){
if(_graph->GetTarget(eit) == edge.second && weight < smallestWeight && _graph->GetEdgeData(eit).forward){
smallestEdge = eit;
smallestWeight = weight;
}
}
if(smallestEdge == SPECIAL_EDGEID){
for(typename GraphT::EdgeIterator eit = _graph->BeginEdges(target);eit < _graph->EndEdges(target);eit++){
for(typename GraphT::EdgeIterator eit = _graph->BeginEdges(edge.second);eit < _graph->EndEdges(edge.second);++eit){
const int weight = _graph->GetEdgeData(eit).distance;
if(_graph->GetTarget(eit) == source && weight < smallestWeight && _graph->GetEdgeData(eit).backward){
if(_graph->GetTarget(eit) == edge.first && weight < smallestWeight && _graph->GetEdgeData(eit).backward){
smallestEdge = eit;
smallestWeight = weight;
}
@ -254,13 +265,13 @@ private:
const EdgeData& ed = _graph->GetEdgeData(smallestEdge);
if(ed.shortcut) {//unpack
const NodeID middle = ed.via;
_UnpackEdge(source, middle, path);
_UnpackEdge(middle, target, path);
return false;
//again, we need to this in reversed order
recursionStack.push(std::make_pair(middle, edge.second));
recursionStack.push(std::make_pair(edge.first, middle));
} else {
assert(!ed.shortcut);
path.push_back(_PathData(ed.via, ed.nameID, ed.turnInstruction, ed.distance) );
return true;
unpackedPath.push_back(_PathData(ed.via, ed.nameID, ed.turnInstruction, ed.distance) );
}
}
}
};

View File

@ -0,0 +1,71 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef SIMPLESTACK_H_
#define SIMPLESTACK_H_
#include <cassert>
#include <vector>
template<typename StackItemT, class ContainerT = std::vector<StackItemT> >
class SimpleStack {
private:
int last;
ContainerT arr;
public:
SimpleStack() : last(-1) {
}
SimpleStack(std::size_t size_hint) : last(-1) {
hint(size_hint);
}
inline void hint(std::size_t size_hint) {
arr.reserve(size_hint);
}
inline void push(StackItemT t) {
++last;
arr.push_back(t);
}
inline void pop() {
arr.pop_back();
--last;
}
inline StackItemT top() {
assert (last >= 0);
return arr[last];
}
inline int size() {
return last+1;
}
inline bool empty() {
return (-1 == last);
}
};
#endif /* SIMPLESTACK_H_ */