diff --git a/Algorithms/DouglasPeucker.h b/Algorithms/DouglasPeucker.h index 6f6ef303f..e151aa47a 100644 --- a/Algorithms/DouglasPeucker.h +++ b/Algorithms/DouglasPeucker.h @@ -22,7 +22,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #define DOUGLASPEUCKER_H_ #include -#include +#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 PairOfPoints; //Stack to simulate the recursion - std::stack recursionStack; + SimpleStack 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); diff --git a/DataStructures/SearchEngine.h b/DataStructures/SearchEngine.h index f1d56771b..abc0edc31 100644 --- a/DataStructures/SearchEngine.h +++ b/DataStructures/SearchEngine.h @@ -23,6 +23,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #include #include +#include "SimpleStack.h" #include @@ -36,7 +37,7 @@ struct _HeapData { _HeapData( NodeID p ) : parent(p) { } }; -typedef boost::thread_specific_ptr > HeapPtr; +typedef boost::thread_specific_ptr > > HeapPtr; template 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 >(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 >(nodeHelpDesk->getNumberOfNodes())); + } else _backwardHeap->Clear(); } @@ -117,10 +120,7 @@ public: pathNode = _backwardHeap->GetData(pathNode).parent; packedPath.push_back(pathNode); } - for(deque::size_type i = 0;i < packedPath.size() - 1;i++){ - _UnpackEdge(packedPath[i], packedPath[i + 1], path); - } - + _UnpackPath(packedPath, path); return _upperbound; } @@ -226,41 +226,52 @@ private: } } - inline bool _UnpackEdge(const NodeID source, const NodeID target, std::vector<_PathData> & path) const { - assert(source != target); - //find edge first. - typename GraphT::EdgeIterator smallestEdge = SPECIAL_EDGEID; - int smallestWeight = INT_MAX; - for(typename GraphT::EdgeIterator eit = _graph->BeginEdges(source);eit < _graph->EndEdges(source);eit++){ - const int weight = _graph->GetEdgeData(eit).distance; - if(_graph->GetTarget(eit) == target && weight < smallestWeight && _graph->GetEdgeData(eit).forward){ - smallestEdge = eit; - smallestWeight = weight; - } + inline void _UnpackPath(const std::deque & packedPath, std::vector<_PathData> & unpackedPath) const { + const std::deque::size_type sizeOfPackedPath = packedPath.size(); + SimpleStack > recursionStack(sizeOfPackedPath); + + //We have to push the path in reverse order onto the stack because it's LIFO. + for(std::deque::size_type i = sizeOfPackedPath-1; i > 0; --i){ + recursionStack.push(std::make_pair(packedPath[i-1], packedPath[i])); } - if(smallestEdge == SPECIAL_EDGEID){ - for(typename GraphT::EdgeIterator eit = _graph->BeginEdges(target);eit < _graph->EndEdges(target);eit++){ + std::pair 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(edge.first);eit < _graph->EndEdges(edge.first);++eit){ const int weight = _graph->GetEdgeData(eit).distance; - if(_graph->GetTarget(eit) == source && weight < smallestWeight && _graph->GetEdgeData(eit).backward){ + if(_graph->GetTarget(eit) == edge.second && weight < smallestWeight && _graph->GetEdgeData(eit).forward){ smallestEdge = eit; smallestWeight = weight; } } - } - assert(smallestWeight != INT_MAX); + if(smallestEdge == SPECIAL_EDGEID){ + 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) == edge.first && weight < smallestWeight && _graph->GetEdgeData(eit).backward){ + smallestEdge = eit; + smallestWeight = weight; + } + } + } - const EdgeData& ed = _graph->GetEdgeData(smallestEdge); - if(ed.shortcut) {//unpack - const NodeID middle = ed.via; - _UnpackEdge(source, middle, path); - _UnpackEdge(middle, target, path); - return false; - } else { - assert(!ed.shortcut); - path.push_back(_PathData(ed.via, ed.nameID, ed.turnInstruction, ed.distance) ); - return true; + assert(smallestWeight != INT_MAX); + + const EdgeData& ed = _graph->GetEdgeData(smallestEdge); + if(ed.shortcut) {//unpack + const NodeID middle = ed.via; + //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); + unpackedPath.push_back(_PathData(ed.via, ed.nameID, ed.turnInstruction, ed.distance) ); + } } } }; diff --git a/DataStructures/SimpleStack.h b/DataStructures/SimpleStack.h new file mode 100644 index 000000000..0335bcccb --- /dev/null +++ b/DataStructures/SimpleStack.h @@ -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 +#include + +template > +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_ */