migrating Algorithms directory to C++11

This commit is contained in:
Dennis Luxen 2014-05-05 12:35:08 +02:00
parent 0d8f2e1b18
commit c33c6188a8
8 changed files with 429 additions and 465 deletions

View File

@ -30,14 +30,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "DouglasPeucker.h" #include "DouglasPeucker.h"
#include "../DataStructures/SegmentInformation.h" #include "../DataStructures/SegmentInformation.h"
#include <cmath>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <limits> #include <limits>
// These thresholds are more or less heuristically chosen. DouglasPeucker::DouglasPeucker()
static double DouglasPeuckerThresholds[19] = {262144., // z0 : douglas_peucker_thresholds({262144., // z0
131072., // z1 131072., // z1
65536., // z2 65536., // z2
32768., // z3 32768., // z3
@ -56,7 +54,9 @@ static double DouglasPeuckerThresholds[19] = {262144., // z0
.65, // z16 .65, // z16
.5, // z17 .5, // z17
.35 // z18 .35 // z18
}; })
{
}
void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level) void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level)
{ {
@ -74,7 +74,7 @@ void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const
if (input_geometry[right_border].necessary) if (input_geometry[right_border].necessary)
{ {
recursion_stack.push(std::make_pair(left_border, right_border)); recursion_stack.emplace(left_border, right_border);
left_border = right_border; left_border = right_border;
} }
++right_border; ++right_border;
@ -100,23 +100,23 @@ void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const
input_geometry[pair.first].location, input_geometry[pair.first].location,
input_geometry[pair.second].location); input_geometry[pair.second].location);
const double distance = std::abs(temp_dist); const double distance = std::abs(temp_dist);
if (distance > DouglasPeuckerThresholds[zoom_level] && distance > max_distance) if (distance > douglas_peucker_thresholds[zoom_level] && distance > max_distance)
{ {
farthest_element_index = i; farthest_element_index = i;
max_distance = distance; max_distance = distance;
} }
} }
if (max_distance > DouglasPeuckerThresholds[zoom_level]) if (max_distance > douglas_peucker_thresholds[zoom_level])
{ {
// mark idx as necessary // mark idx as necessary
input_geometry[farthest_element_index].necessary = true; input_geometry[farthest_element_index].necessary = true;
if (1 < (farthest_element_index - pair.first)) if (1 < (farthest_element_index - pair.first))
{ {
recursion_stack.push(std::make_pair(pair.first, farthest_element_index)); recursion_stack.emplace(pair.first, farthest_element_index);
} }
if (1 < (pair.second - farthest_element_index)) if (1 < (pair.second - farthest_element_index))
{ {
recursion_stack.push(std::make_pair(farthest_element_index, pair.second)); recursion_stack.emplace(farthest_element_index, pair.second);
} }
} }
} }

View File

@ -44,6 +44,8 @@ struct SegmentInformation;
class DouglasPeucker class DouglasPeucker
{ {
private: private:
std::vector<double> douglas_peucker_thresholds;
typedef std::pair<unsigned, unsigned> GeometryRange; typedef std::pair<unsigned, unsigned> GeometryRange;
// Stack to simulate the recursion // Stack to simulate the recursion
std::stack<GeometryRange> recursion_stack; std::stack<GeometryRange> recursion_stack;
@ -53,6 +55,7 @@ class DouglasPeucker
const FixedPointCoordinate &segB) const; const FixedPointCoordinate &segB) const;
public: public:
DouglasPeucker();
void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level); void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level);
}; };

View File

@ -33,22 +33,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <iostream> #include <iostream>
#if defined(__x86_64__) #if defined(__x86_64__)
#include <cpuid.h> #include <cpuid.h>
#else #else
#include <boost/crc.hpp> // for boost::crc_32_type #include <boost/crc.hpp> // for boost::crc_32_type
inline void __get_cpuid( inline void __get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
int param, {
unsigned *eax, *ecx = 0;
unsigned *ebx, }
unsigned *ecx,
unsigned *edx
) { *ecx = 0; }
#endif #endif
template<class ContainerT> template <class ContainerT> class IteratorbasedCRC32
class IteratorbasedCRC32 { {
private: private:
typedef typename ContainerT::iterator IteratorType; typedef typename ContainerT::iterator IteratorType;
unsigned crc; unsigned crc;
@ -57,10 +54,10 @@ private:
#if !defined(__x86_64__) #if !defined(__x86_64__)
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor; boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor;
#endif #endif
unsigned SoftwareBasedCRC32( char *str, unsigned len ) unsigned SoftwareBasedCRC32(char *str, unsigned len)
{ {
#if !defined(__x86_64__) #if !defined(__x86_64__)
CRC32_processor.process_bytes( str, len); CRC32_processor.process_bytes(str, len);
return CRC32_processor.checksum(); return CRC32_processor.checksum();
#else #else
return 0; return 0;
@ -68,30 +65,28 @@ private:
} }
// adapted from http://byteworm.com/2010/10/13/crc32/ // adapted from http://byteworm.com/2010/10/13/crc32/
unsigned SSE42BasedCRC32( char *str, unsigned len ) unsigned SSE42BasedCRC32(char *str, unsigned len)
{ {
#if defined(__x86_64__) #if defined(__x86_64__)
unsigned q = len/sizeof(unsigned); unsigned q = len / sizeof(unsigned);
unsigned r = len%sizeof(unsigned); unsigned r = len % sizeof(unsigned);
unsigned *p = (unsigned*)str; unsigned *p = (unsigned *)str;
//crc=0; // crc=0;
while (q--) { while (q--)
__asm__ __volatile__( {
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;" __asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
:"=S"(crc) : "=S"(crc)
:"0"(crc), "c"(*p) : "0"(crc), "c"(*p));
);
++p; ++p;
} }
str=(char*)p; str = (char *)p;
while (r--) { while (r--)
__asm__ __volatile__( {
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;" __asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
:"=S"(crc) : "=S"(crc)
:"0"(crc), "c"(*str) : "0"(crc), "c"(*str));
);
++str; ++str;
} }
#endif #endif
@ -102,7 +97,7 @@ private:
{ {
unsigned eax = 0, ebx = 0, ecx = 0, edx = 0; unsigned eax = 0, ebx = 0, ecx = 0, edx = 0;
// on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl. // on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl.
__get_cpuid( 1, &eax, &ebx, &ecx, &edx ); __get_cpuid(1, &eax, &ebx, &ecx, &edx);
return ecx; return ecx;
} }
@ -111,33 +106,34 @@ private:
static const int SSE42_BIT = 0x00100000; static const int SSE42_BIT = 0x00100000;
const unsigned ecx = cpuid(); const unsigned ecx = cpuid();
const bool has_SSE42 = ecx & SSE42_BIT; const bool has_SSE42 = ecx & SSE42_BIT;
if (has_SSE42) { if (has_SSE42)
{
SimpleLogger().Write() << "using hardware based CRC32 computation"; SimpleLogger().Write() << "using hardware based CRC32 computation";
} else { }
else
{
SimpleLogger().Write() << "using software based CRC32 computation"; SimpleLogger().Write() << "using software based CRC32 computation";
} }
return has_SSE42; return has_SSE42;
} }
public: public:
IteratorbasedCRC32() : crc(0) IteratorbasedCRC32() : crc(0) { use_SSE42_CRC_function = DetectNativeCRC32Support(); }
{
use_SSE42_CRC_function = DetectNativeCRC32Support();
}
unsigned operator()( IteratorType iter, const IteratorType end ) unsigned operator()(IteratorType iter, const IteratorType end)
{ {
unsigned crc = 0; unsigned crc = 0;
while(iter != end) { while (iter != end)
char * data = reinterpret_cast<char*>(&(*iter) ); {
char *data = reinterpret_cast<char *>(&(*iter));
if (use_SSE42_CRC_function) if (use_SSE42_CRC_function)
{ {
crc = SSE42BasedCRC32( data, sizeof(typename ContainerT::value_type) ); crc = SSE42BasedCRC32(data, sizeof(typename ContainerT::value_type));
} }
else else
{ {
crc = SoftwareBasedCRC32( data, sizeof(typename ContainerT::value_type) ); crc = SoftwareBasedCRC32(data, sizeof(typename ContainerT::value_type));
} }
++iter; ++iter;
} }

View File

@ -34,7 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/archive/iterators/base64_from_binary.hpp> #include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp> #include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp> #include <boost/archive/iterators/transform_width.hpp>
#include <boost/foreach.hpp>
#include <algorithm> #include <algorithm>
#include <string> #include <string>

View File

@ -27,87 +27,99 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "PolylineCompressor.h" #include "PolylineCompressor.h"
void PolylineCompressor::encodeVectorSignedNumber( void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output)
std::vector<int> & numbers, const
std::string & output {
) const { const unsigned end = numbers.size();
for(unsigned i = 0; i < numbers.size(); ++i) { for (unsigned i = 0; i < end; ++i)
{
numbers[i] <<= 1; numbers[i] <<= 1;
if (numbers[i] < 0) { if (numbers[i] < 0)
{
numbers[i] = ~(numbers[i]); numbers[i] = ~(numbers[i]);
} }
} }
for(unsigned i = 0; i < numbers.size(); ++i) { for (unsigned i = 0; i < end; ++i)
{
encodeNumber(numbers[i], output); encodeNumber(numbers[i], output);
} }
} }
void PolylineCompressor::encodeNumber(int number_to_encode, std::string & output) const { void PolylineCompressor::encodeNumber(int number_to_encode, std::string &output) const
while (number_to_encode >= 0x20) { {
int nextValue = (0x20 | (number_to_encode & 0x1f)) + 63; while (number_to_encode >= 0x20)
output += static_cast<char>(nextValue); {
if(92 == nextValue) { int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
output += static_cast<char>(nextValue); output += static_cast<char>(next_value);
if (92 == next_value)
{
output += static_cast<char>(next_value);
} }
number_to_encode >>= 5; number_to_encode >>= 5;
} }
number_to_encode += 63; number_to_encode += 63;
output += static_cast<char>(number_to_encode); output += static_cast<char>(number_to_encode);
if(92 == number_to_encode) { if (92 == number_to_encode)
{
output += static_cast<char>(number_to_encode); output += static_cast<char>(number_to_encode);
} }
} }
void PolylineCompressor::printEncodedString( void PolylineCompressor::printEncodedString(const std::vector<SegmentInformation> &polyline,
const std::vector<SegmentInformation> & polyline, std::string &output) const
std::string & output {
) const { std::vector<int> delta_numbers;
std::vector<int> deltaNumbers;
output += "\""; output += "\"";
if(!polyline.empty()) { if (!polyline.empty())
FixedPointCoordinate lastCoordinate = polyline[0].location; {
deltaNumbers.push_back( lastCoordinate.lat ); FixedPointCoordinate last_coordinate = polyline[0].location;
deltaNumbers.push_back( lastCoordinate.lon ); delta_numbers.emplace_back(last_coordinate.lat);
for(unsigned i = 1; i < polyline.size(); ++i) { delta_numbers.emplace_back(last_coordinate.lon);
if(!polyline[i].necessary) { for (unsigned i = 1; i < polyline.size(); ++i)
continue; {
if (polyline[i].necessary)
{
int lat_diff = polyline[i].location.lat - last_coordinate.lat;
int lon_diff = polyline[i].location.lon - last_coordinate.lon;
delta_numbers.emplace_back(lat_diff);
delta_numbers.emplace_back(lon_diff);
last_coordinate = polyline[i].location;
} }
deltaNumbers.push_back(polyline[i].location.lat - lastCoordinate.lat);
deltaNumbers.push_back(polyline[i].location.lon - lastCoordinate.lon);
lastCoordinate = polyline[i].location;
} }
encodeVectorSignedNumber(deltaNumbers, output); encodeVectorSignedNumber(delta_numbers, output);
}
output += "\"";
}
void PolylineCompressor::printEncodedString(
const std::vector<FixedPointCoordinate>& polyline,
std::string &output
) const {
std::vector<int> deltaNumbers(2*polyline.size());
output += "\"";
if(!polyline.empty()) {
deltaNumbers[0] = polyline[0].lat;
deltaNumbers[1] = polyline[0].lon;
for(unsigned i = 1; i < polyline.size(); ++i) {
deltaNumbers[(2*i)] = (polyline[i].lat - polyline[i-1].lat);
deltaNumbers[(2*i)+1] = (polyline[i].lon - polyline[i-1].lon);
}
encodeVectorSignedNumber(deltaNumbers, output);
} }
output += "\""; output += "\"";
} }
void PolylineCompressor::printUnencodedString( void PolylineCompressor::printEncodedString(const std::vector<FixedPointCoordinate> &polyline,
const std::vector<FixedPointCoordinate> & polyline, std::string &output) const
std::string & output {
) const { std::vector<int> delta_numbers(2 * polyline.size());
output += "\"";
if (!polyline.empty())
{
delta_numbers[0] = polyline[0].lat;
delta_numbers[1] = polyline[0].lon;
for (unsigned i = 1; i < polyline.size(); ++i)
{
int lat_diff = polyline[i].lat - polyline[i - 1].lat;
int lon_diff = polyline[i].lon - polyline[i - 1].lon;
delta_numbers[(2 * i)] = (lat_diff);
delta_numbers[(2 * i) + 1] = (lon_diff);
}
encodeVectorSignedNumber(delta_numbers, output);
}
output += "\"";
}
void PolylineCompressor::printUnencodedString(const std::vector<FixedPointCoordinate> &polyline,
std::string &output) const
{
output += "["; output += "[";
std::string tmp; std::string tmp;
for(unsigned i = 0; i < polyline.size(); i++) { for (unsigned i = 0; i < polyline.size(); i++)
{
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lat, tmp); FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lat, tmp);
output += "["; output += "[";
output += tmp; output += tmp;
@ -115,21 +127,23 @@ void PolylineCompressor::printUnencodedString(
output += ", "; output += ", ";
output += tmp; output += tmp;
output += "]"; output += "]";
if( i < polyline.size()-1 ) { if (i < polyline.size() - 1)
{
output += ","; output += ",";
} }
} }
output += "]"; output += "]";
} }
void PolylineCompressor::printUnencodedString( void PolylineCompressor::printUnencodedString(const std::vector<SegmentInformation> &polyline,
const std::vector<SegmentInformation> & polyline, std::string &output) const
std::string & output {
) const {
output += "["; output += "[";
std::string tmp; std::string tmp;
for(unsigned i = 0; i < polyline.size(); i++) { for (unsigned i = 0; i < polyline.size(); i++)
if(!polyline[i].necessary) { {
if (!polyline[i].necessary)
{
continue; continue;
} }
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lat, tmp); FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lat, tmp);
@ -139,7 +153,8 @@ void PolylineCompressor::printUnencodedString(
output += ", "; output += ", ";
output += tmp; output += tmp;
output += "]"; output += "]";
if( i < polyline.size()-1 ) { if (i < polyline.size() - 1)
{
output += ","; output += ",";
} }
} }

View File

@ -34,36 +34,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string> #include <string>
#include <vector> #include <vector>
class PolylineCompressor { class PolylineCompressor
private: {
void encodeVectorSignedNumber( private:
std::vector<int> & numbers, void encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output) const;
std::string & output
) const;
void encodeNumber(int number_to_encode, std::string & output) const; void encodeNumber(int number_to_encode, std::string &output) const;
public: public:
void printEncodedString( void printEncodedString(const std::vector<SegmentInformation> &polyline,
const std::vector<SegmentInformation> & polyline, std::string &output) const;
std::string & output
) const;
void printEncodedString( void printEncodedString(const std::vector<FixedPointCoordinate> &polyline,
const std::vector<FixedPointCoordinate>& polyline, std::string &output) const;
std::string &output
) const;
void printUnencodedString( void printUnencodedString(const std::vector<FixedPointCoordinate> &polyline,
const std::vector<FixedPointCoordinate> & polyline, std::string &output) const;
std::string & output
) const;
void printUnencodedString(
const std::vector<SegmentInformation> & polyline,
std::string & output
) const;
void printUnencodedString(const std::vector<SegmentInformation> &polyline,
std::string &output) const;
}; };
#endif /* POLYLINECOMPRESSOR_H_ */ #endif /* POLYLINECOMPRESSOR_H_ */

View File

@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_ #ifndef STRONGLYCONNECTEDCOMPONENTS_H_
#define STRONGLYCONNECTEDCOMPONENTS_H_ #define STRONGLYCONNECTEDCOMPONENTS_H_
#include "../typedefs.h"
#include "../DataStructures/DeallocatingVector.h" #include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h" #include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/ImportEdge.h" #include "../DataStructures/ImportEdge.h"
@ -42,51 +43,58 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/integer.hpp> #include <boost/integer.hpp>
#include <boost/make_shared.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#ifdef __APPLE__ #ifdef __APPLE__
#include <gdal.h> #include <gdal.h>
#include <ogrsf_frmts.h> #include <ogrsf_frmts.h>
#else #else
#include <gdal/gdal.h> #include <gdal/gdal.h>
#include <gdal/ogrsf_frmts.h> #include <gdal/ogrsf_frmts.h>
#endif #endif
#include <memory>
#include <stack> #include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector> #include <vector>
class TarjanSCC { namespace std
private: {
template <> struct hash<std::pair<NodeID, NodeID>>
{
size_t operator()(const std::pair<NodeID, NodeID> &pair) const
{
return std::hash<int>()(pair.first) ^ std::hash<int>()(pair.second);
}
};
}
struct TarjanNode { class TarjanSCC
TarjanNode() : index(UINT_MAX), lowlink(UINT_MAX), onStack(false) {} {
private:
struct TarjanNode
{
TarjanNode() : index(UINT_MAX), low_link(UINT_MAX), on_stack(false) {}
unsigned index; unsigned index;
unsigned lowlink; unsigned low_link;
bool onStack; bool on_stack;
}; };
struct TarjanEdgeData { struct TarjanEdgeData
{
int distance; int distance;
unsigned nameID:31; unsigned name_id : 31;
bool shortcut:1; bool shortcut : 1;
short type; short type;
bool isAccessRestricted:1; bool forward : 1;
bool forward:1; bool backward : 1;
bool backward:1; bool reversedEdge : 1;
bool roundabout:1;
bool ignoreInGrid:1;
bool reversedEdge:1;
}; };
struct TarjanStackFrame { struct TarjanStackFrame
explicit TarjanStackFrame( {
NodeID v, explicit TarjanStackFrame(NodeID v, NodeID parent) : v(v), parent(parent) {}
NodeID parent
) : v(v), parent(parent) { }
NodeID v; NodeID v;
NodeID parent; NodeID parent;
}; };
@ -96,131 +104,117 @@ private:
typedef std::pair<NodeID, NodeID> RestrictionSource; typedef std::pair<NodeID, NodeID> RestrictionSource;
typedef std::pair<NodeID, bool> restriction_target; typedef std::pair<NodeID, bool> restriction_target;
typedef std::vector<restriction_target> EmanatingRestrictionsVector; typedef std::vector<restriction_target> EmanatingRestrictionsVector;
typedef boost::unordered_map<RestrictionSource, unsigned> RestrictionMap; typedef std::unordered_map<RestrictionSource, unsigned> RestrictionMap;
std::vector<NodeInfo> m_coordinate_list; std::vector<NodeInfo> m_coordinate_list;
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list; std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
boost::shared_ptr<TarjanDynamicGraph> m_node_based_graph; std::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
boost::unordered_set<NodeID> m_barrier_node_list; std::unordered_set<NodeID> m_barrier_node_list;
boost::unordered_set<NodeID> m_traffic_light_list; std::unordered_set<NodeID> m_traffic_light_list;
unsigned m_restriction_counter; unsigned m_restriction_counter;
RestrictionMap m_restriction_map; RestrictionMap m_restriction_map;
struct EdgeBasedNode { public:
bool operator<(const EdgeBasedNode & other) const { TarjanSCC(int number_of_nodes,
return other.id < id; std::vector<NodeBasedEdge> &input_edges,
} std::vector<NodeID> &bn,
bool operator==(const EdgeBasedNode & other) const { std::vector<NodeID> &tl,
return id == other.id; std::vector<TurnRestriction> &irs,
} std::vector<NodeInfo> &nI)
NodeID id; : m_coordinate_list(nI), m_restriction_counter(irs.size())
int lat1;
int lat2;
int lon1;
int lon2:31;
bool belongsToTinyComponent:1;
NodeID nameID;
unsigned weight:31;
bool ignoreInGrid:1;
};
public:
TarjanSCC(
int number_of_nodes,
std::vector<NodeBasedEdge> & input_edges,
std::vector<NodeID> & bn,
std::vector<NodeID> & tl,
std::vector<TurnRestriction> & irs,
std::vector<NodeInfo> & nI
) :
m_coordinate_list(nI),
m_restriction_counter(irs.size())
{ {
BOOST_FOREACH(const TurnRestriction & restriction, irs) { for (const TurnRestriction &restriction : irs)
std::pair<NodeID, NodeID> restrictionSource = std::make_pair( {
restriction.fromNode, restriction.viaNode std::pair<NodeID, NodeID> restrictionSource = {restriction.fromNode,
); restriction.viaNode};
unsigned index; unsigned index;
RestrictionMap::iterator restriction_iterator = m_restriction_map.find(restrictionSource); RestrictionMap::iterator restriction_iterator =
if(restriction_iterator == m_restriction_map.end()) { m_restriction_map.find(restrictionSource);
if (restriction_iterator == m_restriction_map.end())
{
index = m_restriction_bucket_list.size(); index = m_restriction_bucket_list.size();
m_restriction_bucket_list.resize(index+1); m_restriction_bucket_list.resize(index + 1);
m_restriction_map.insert(std::make_pair(restrictionSource, index)); m_restriction_map.emplace(restrictionSource, index);
} else { }
else
{
index = restriction_iterator->second; index = restriction_iterator->second;
//Map already contains an is_only_*-restriction // Map already contains an is_only_*-restriction
if(m_restriction_bucket_list.at(index).begin()->second) { if (m_restriction_bucket_list.at(index).begin()->second)
{
continue; continue;
} else if(restriction.flags.isOnly) { }
//We are going to insert an is_only_*-restriction. There can be only one. else if (restriction.flags.isOnly)
{
// We are going to insert an is_only_*-restriction. There can be only one.
m_restriction_bucket_list.at(index).clear(); m_restriction_bucket_list.at(index).clear();
} }
} }
m_restriction_bucket_list.at(index).push_back( m_restriction_bucket_list.at(index)
std::make_pair(restriction.toNode, restriction.flags.isOnly) .emplace_back(restriction.toNode, restriction.flags.isOnly);
);
} }
m_barrier_node_list.insert(bn.begin(), bn.end()); m_barrier_node_list.insert(bn.begin(), bn.end());
m_traffic_light_list.insert(tl.begin(), tl.end()); m_traffic_light_list.insert(tl.begin(), tl.end());
DeallocatingVector< TarjanEdge > edge_list; DeallocatingVector<TarjanEdge> edge_list;
BOOST_FOREACH(const NodeBasedEdge & input_edge, input_edges) { for (const NodeBasedEdge &input_edge : input_edges)
{
if (input_edge.source() == input_edge.target())
{
continue;
}
TarjanEdge edge; TarjanEdge edge;
if(!input_edge.isForward()) { if (input_edge.isForward())
edge.source = input_edge.target(); {
edge.target = input_edge.source();
edge.data.backward = input_edge.isForward();
edge.data.forward = input_edge.isBackward();
} else {
edge.source = input_edge.source(); edge.source = input_edge.source();
edge.target = input_edge.target(); edge.target = input_edge.target();
edge.data.forward = input_edge.isForward(); edge.data.forward = input_edge.isForward();
edge.data.backward = input_edge.isBackward(); edge.data.backward = input_edge.isBackward();
} }
if(edge.source == edge.target) { else
continue; {
edge.source = input_edge.target();
edge.target = input_edge.source();
edge.data.backward = input_edge.isForward();
edge.data.forward = input_edge.isBackward();
} }
edge.data.distance = (std::max)((int)input_edge.weight(), 1 ); edge.data.distance = (std::max)((int)input_edge.weight(), 1);
BOOST_ASSERT( edge.data.distance > 0 ); BOOST_ASSERT(edge.data.distance > 0);
edge.data.shortcut = false; edge.data.shortcut = false;
edge.data.roundabout = input_edge.isRoundabout(); // edge.data.roundabout = input_edge.isRoundabout();
edge.data.ignoreInGrid = input_edge.ignoreInGrid(); // edge.data.ignoreInGrid = input_edge.ignoreInGrid();
edge.data.nameID = input_edge.name(); edge.data.name_id = input_edge.name();
edge.data.type = input_edge.type(); edge.data.type = input_edge.type();
edge.data.isAccessRestricted = input_edge.isAccessRestricted(); // edge.data.isAccessRestricted = input_edge.isAccessRestricted();
edge.data.reversedEdge = false; edge.data.reversedEdge = false;
edge_list.push_back( edge ); edge_list.push_back(edge);
if( edge.data.backward ) { if (edge.data.backward)
std::swap( edge.source, edge.target ); {
std::swap(edge.source, edge.target);
edge.data.forward = input_edge.isBackward(); edge.data.forward = input_edge.isBackward();
edge.data.backward = input_edge.isForward(); edge.data.backward = input_edge.isForward();
edge.data.reversedEdge = true; edge.data.reversedEdge = true;
edge_list.push_back( edge ); edge_list.push_back(edge);
} }
} }
std::vector<NodeBasedEdge>().swap(input_edges); std::vector<NodeBasedEdge>().swap(input_edges);
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(0 == input_edges.size() && 0 == input_edges.capacity(),
0 == input_edges.size() && 0 == input_edges.capacity(), "input edge vector not properly deallocated");
"input edge vector not properly deallocated"
);
std::sort( edge_list.begin(), edge_list.end() ); std::sort(edge_list.begin(), edge_list.end());
m_node_based_graph = boost::make_shared<TarjanDynamicGraph>( m_node_based_graph = std::make_shared<TarjanDynamicGraph>(number_of_nodes, edge_list);
number_of_nodes,
edge_list
);
} }
~TarjanSCC() { ~TarjanSCC() { m_node_based_graph.reset(); }
m_node_based_graph.reset();
}
void Run() { void Run()
//remove files from previous run if exist {
// remove files from previous run if exist
DeleteFileIfExists("component.dbf"); DeleteFileIfExists("component.dbf");
DeleteFileIfExists("component.shx"); DeleteFileIfExists("component.shx");
DeleteFileIfExists("component.shp"); DeleteFileIfExists("component.shp");
@ -230,121 +224,108 @@ public:
OGRRegisterAll(); OGRRegisterAll();
const char *pszDriverName = "ESRI Shapefile"; const char *pszDriverName = "ESRI Shapefile";
OGRSFDriver * poDriver = OGRSFDriverRegistrar::GetRegistrar()-> OGRSFDriver *poDriver =
GetDriverByName( pszDriverName ); OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(pszDriverName);
if( NULL == poDriver ) { if (NULL == poDriver)
{
throw OSRMException("ESRI Shapefile driver not available"); throw OSRMException("ESRI Shapefile driver not available");
} }
OGRDataSource * poDS = poDriver->CreateDataSource( OGRDataSource *poDS = poDriver->CreateDataSource("component.shp", NULL);
"component.shp",
NULL
);
if( NULL == poDS ) { if (NULL == poDS)
{
throw OSRMException("Creation of output file failed"); throw OSRMException("Creation of output file failed");
} }
OGRLayer * poLayer = poDS->CreateLayer( OGRLayer *poLayer = poDS->CreateLayer("component", NULL, wkbLineString, NULL);
"component",
NULL,
wkbLineString,
NULL
);
if( NULL == poLayer ) { if (NULL == poLayer)
{
throw OSRMException("Layer creation failed."); throw OSRMException("Layer creation failed.");
} }
//The following is a hack to distinguish between stuff that happens // The following is a hack to distinguish between stuff that happens
//before the recursive call and stuff that happens after // before the recursive call and stuff that happens after
std::stack<std::pair<bool, TarjanStackFrame> > recursion_stack; std::stack<std::pair<bool, TarjanStackFrame>> recursion_stack;
//true = stuff before, false = stuff after call // true = stuff before, false = stuff after call
std::stack<NodeID> tarjan_stack; std::stack<NodeID> tarjan_stack;
std::vector<unsigned> components_index( std::vector<unsigned> components_index(m_node_based_graph->GetNumberOfNodes(), UINT_MAX);
m_node_based_graph->GetNumberOfNodes(),
UINT_MAX
);
std::vector<NodeID> component_size_vector; std::vector<NodeID> component_size_vector;
std::vector<TarjanNode> tarjan_node_list( std::vector<TarjanNode> tarjan_node_list(m_node_based_graph->GetNumberOfNodes());
m_node_based_graph->GetNumberOfNodes()
);
unsigned component_index = 0, size_of_current_component = 0; unsigned component_index = 0, size_of_current_component = 0;
int index = 0; int index = 0;
for( NodeID last_node = m_node_based_graph->GetNumberOfNodes();
NodeID node = 0, last_node = m_node_based_graph->GetNumberOfNodes(); for (NodeID node = 0; node < last_node; ++node)
node < last_node; {
++node if (UINT_MAX == components_index[node])
) { {
if(UINT_MAX == components_index[node]) { recursion_stack.emplace(true, TarjanStackFrame(node, node));
recursion_stack.push(
std::make_pair(true, TarjanStackFrame(node,node))
);
} }
while(!recursion_stack.empty()) { while (!recursion_stack.empty())
bool before_recursion = recursion_stack.top().first; {
const bool before_recursion = recursion_stack.top().first;
TarjanStackFrame currentFrame = recursion_stack.top().second; TarjanStackFrame currentFrame = recursion_stack.top().second;
NodeID v = currentFrame.v; NodeID v = currentFrame.v;
recursion_stack.pop(); recursion_stack.pop();
if(before_recursion) { if (before_recursion)
//Mark frame to handle tail of recursion {
recursion_stack.push(std::make_pair(false, currentFrame)); // Mark frame to handle tail of recursion
recursion_stack.emplace(false, currentFrame);
//Mark essential information for SCC // Mark essential information for SCC
tarjan_node_list[v].index = index; tarjan_node_list[v].index = index;
tarjan_node_list[v].lowlink = index; tarjan_node_list[v].low_link = index;
tarjan_stack.push(v); tarjan_stack.push(v);
tarjan_node_list[v].onStack = true; tarjan_node_list[v].on_stack = true;
++index; ++index;
//Traverse outgoing edges // Traverse outgoing edges
for( EdgeID end_edge = m_node_based_graph->EndEdges(v);
TarjanDynamicGraph::EdgeIterator e2 = m_node_based_graph->BeginEdges(v); for (auto e2 = m_node_based_graph->BeginEdges(v); e2 < end_edge; ++e2)
e2 < m_node_based_graph->EndEdges(v); {
++e2
) {
const TarjanDynamicGraph::NodeIterator vprime = const TarjanDynamicGraph::NodeIterator vprime =
m_node_based_graph->GetTarget(e2); m_node_based_graph->GetTarget(e2);
if(UINT_MAX == tarjan_node_list[vprime].index) { if (UINT_MAX == tarjan_node_list[vprime].index)
recursion_stack.push( {
std::make_pair( recursion_stack.emplace(true, TarjanStackFrame(vprime, v));
true, }
TarjanStackFrame(vprime, v) else
) {
); if (tarjan_node_list[vprime].on_stack &&
} else { tarjan_node_list[vprime].index < tarjan_node_list[v].low_link)
if( {
tarjan_node_list[vprime].onStack && tarjan_node_list[v].low_link = tarjan_node_list[vprime].index;
tarjan_node_list[vprime].index < tarjan_node_list[v].lowlink
) {
tarjan_node_list[v].lowlink = tarjan_node_list[vprime].index;
} }
} }
} }
} else { }
tarjan_node_list[currentFrame.parent].lowlink = else
std::min( {
tarjan_node_list[currentFrame.parent].lowlink, tarjan_node_list[currentFrame.parent].low_link =
tarjan_node_list[v].lowlink std::min(tarjan_node_list[currentFrame.parent].low_link,
); tarjan_node_list[v].low_link);
//after recursion, lets do cycle checking // after recursion, lets do cycle checking
//Check if we found a cycle. This is the bottom part of the recursion // Check if we found a cycle. This is the bottom part of the recursion
if(tarjan_node_list[v].lowlink == tarjan_node_list[v].index) { if (tarjan_node_list[v].low_link == tarjan_node_list[v].index)
{
NodeID vprime; NodeID vprime;
do { do
vprime = tarjan_stack.top(); tarjan_stack.pop(); {
tarjan_node_list[vprime].onStack = false; vprime = tarjan_stack.top();
tarjan_stack.pop();
tarjan_node_list[vprime].on_stack = false;
components_index[vprime] = component_index; components_index[vprime] = component_index;
++size_of_current_component; ++size_of_current_component;
} while( v != vprime); } while (v != vprime);
component_size_vector.push_back(size_of_current_component); component_size_vector.emplace_back(size_of_current_component);
if(size_of_current_component > 1000) { if (size_of_current_component > 1000)
SimpleLogger().Write() << {
"large component [" << component_index << "]=" << SimpleLogger().Write() << "large component [" << component_index
size_of_current_component; << "]=" << size_of_current_component;
} }
++component_index; ++component_index;
@ -354,115 +335,99 @@ public:
} }
} }
SimpleLogger().Write() << SimpleLogger().Write() << "identified: " << component_size_vector.size()
"identified: " << component_size_vector.size() << << " many components, marking small components";
" many components, marking small components";
// TODO/C++11: prime candidate for lambda function // TODO/C++11: prime candidate for lambda function
unsigned size_one_counter = 0; unsigned size_one_counter = 0;
for(unsigned i = 0, end = component_size_vector.size(); i < end; ++i){ for (unsigned i = 0, end = component_size_vector.size(); i < end; ++i)
if(1 == component_size_vector[i]) { {
if (1 == component_size_vector[i])
{
++size_one_counter; ++size_one_counter;
} }
} }
SimpleLogger().Write() << SimpleLogger().Write() << "identified " << size_one_counter << " SCCs of size 1";
"identified " << size_one_counter << " SCCs of size 1";
uint64_t total_network_distance = 0; uint64_t total_network_distance = 0;
p.reinit(m_node_based_graph->GetNumberOfNodes()); p.reinit(m_node_based_graph->GetNumberOfNodes());
for( NodeID last_u_node = m_node_based_graph->GetNumberOfNodes();
TarjanDynamicGraph::NodeIterator u = 0, last_u_node = m_node_based_graph->GetNumberOfNodes(); for (auto u = 0; u < last_u_node; ++u)
u < last_u_node; {
++u
) {
p.printIncrement(); p.printIncrement();
for( EdgeID last_edge = m_node_based_graph->EndEdges(u);
TarjanDynamicGraph::EdgeIterator e1 = m_node_based_graph->BeginEdges(u), last_edge = m_node_based_graph->EndEdges(u); for (auto e1 = m_node_based_graph->BeginEdges(u); e1 < last_edge; ++e1)
e1 < last_edge; {
++e1 if (!m_node_based_graph->GetEdgeData(e1).reversedEdge)
) { {
if(!m_node_based_graph->GetEdgeData(e1).reversedEdge) {
continue; continue;
} }
const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1); const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1);
total_network_distance += 100*FixedPointCoordinate::ApproximateDistance( total_network_distance +=
m_coordinate_list[u].lat, 100 * FixedPointCoordinate::ApproximateDistance(m_coordinate_list[u].lat,
m_coordinate_list[u].lon, m_coordinate_list[u].lon,
m_coordinate_list[v].lat, m_coordinate_list[v].lat,
m_coordinate_list[v].lon m_coordinate_list[v].lon);
);
if( SHRT_MAX != m_node_based_graph->GetEdgeData(e1).type ) { if (SHRT_MAX != m_node_based_graph->GetEdgeData(e1).type)
{
BOOST_ASSERT(e1 != UINT_MAX); BOOST_ASSERT(e1 != UINT_MAX);
BOOST_ASSERT(u != UINT_MAX); BOOST_ASSERT(u != UINT_MAX);
BOOST_ASSERT(v != UINT_MAX); BOOST_ASSERT(v != UINT_MAX);
const unsigned size_of_containing_component = const unsigned size_of_containing_component =
std::min( std::min(component_size_vector[components_index[u]],
component_size_vector[components_index[u]], component_size_vector[components_index[v]]);
component_size_vector[components_index[v]]
);
//edges that end on bollard nodes may actually be in two distinct components // edges that end on bollard nodes may actually be in two distinct components
if(size_of_containing_component < 10) { if (size_of_containing_component < 10)
{
OGRLineString lineString; OGRLineString lineString;
lineString.addPoint( lineString.addPoint(m_coordinate_list[u].lon / COORDINATE_PRECISION,
m_coordinate_list[u].lon/COORDINATE_PRECISION, m_coordinate_list[u].lat / COORDINATE_PRECISION);
m_coordinate_list[u].lat/COORDINATE_PRECISION lineString.addPoint(m_coordinate_list[v].lon / COORDINATE_PRECISION,
); m_coordinate_list[v].lat / COORDINATE_PRECISION);
lineString.addPoint(
m_coordinate_list[v].lon/COORDINATE_PRECISION,
m_coordinate_list[v].lat/COORDINATE_PRECISION
);
OGRFeature * poFeature = OGRFeature::CreateFeature( OGRFeature *poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn());
poLayer->GetLayerDefn()
);
poFeature->SetGeometry( &lineString ); poFeature->SetGeometry(&lineString);
if( OGRERR_NONE != poLayer->CreateFeature(poFeature) ) { if (OGRERR_NONE != poLayer->CreateFeature(poFeature))
throw OSRMException( {
"Failed to create feature in shapefile." throw OSRMException("Failed to create feature in shapefile.");
);
} }
OGRFeature::DestroyFeature( poFeature ); OGRFeature::DestroyFeature(poFeature);
} }
} }
} }
} }
OGRDataSource::DestroyDataSource( poDS ); OGRDataSource::DestroyDataSource(poDS);
std::vector<NodeID>().swap(component_size_vector); std::vector<NodeID>().swap(component_size_vector);
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(0 == component_size_vector.size() && 0 == component_size_vector.capacity(),
0 == component_size_vector.size() && "component_size_vector not properly deallocated");
0 == component_size_vector.capacity(),
"component_size_vector not properly deallocated"
);
std::vector<NodeID>().swap(components_index); std::vector<NodeID>().swap(components_index);
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(0 == components_index.size() && 0 == components_index.capacity(),
0 == components_index.size() && 0 == components_index.capacity(), "icomponents_index not properly deallocated");
"icomponents_index not properly deallocated"
);
SimpleLogger().Write() SimpleLogger().Write() << "total network distance: " << (uint64_t)total_network_distance /
<< "total network distance: " << 100 / 1000. << " km";
(uint64_t)total_network_distance/100/1000. <<
" km";
} }
private: private:
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const { unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const
std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v); {
RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source); std::pair<NodeID, NodeID> restriction_source = {u, v};
if (restriction_iterator != m_restriction_map.end()) { RestrictionMap::const_iterator restriction_iterator =
m_restriction_map.find(restriction_source);
if (restriction_iterator != m_restriction_map.end())
{
const unsigned index = restriction_iterator->second; const unsigned index = restriction_iterator->second;
BOOST_FOREACH( for (const RestrictionSource &restriction_target : m_restriction_bucket_list.at(index))
const RestrictionSource & restriction_target, {
m_restriction_bucket_list.at(index) if (restriction_target.second)
) { {
if(restriction_target.second) {
return restriction_target.first; return restriction_target.first;
} }
} }
@ -470,21 +435,19 @@ private:
return UINT_MAX; return UINT_MAX;
} }
bool CheckIfTurnIsRestricted( bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
const NodeID u, {
const NodeID v, // only add an edge if turn is not a U-turn except it is the end of dead-end street.
const NodeID w std::pair<NodeID, NodeID> restriction_source = {u, v};
) const { RestrictionMap::const_iterator restriction_iterator =
//only add an edge if turn is not a U-turn except it is the end of dead-end street. m_restriction_map.find(restriction_source);
std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v); if (restriction_iterator != m_restriction_map.end())
RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source); {
if (restriction_iterator != m_restriction_map.end()) {
const unsigned index = restriction_iterator->second; const unsigned index = restriction_iterator->second;
BOOST_FOREACH( for (const restriction_target &restriction_target : m_restriction_bucket_list.at(index))
const restriction_target & restriction_target, {
m_restriction_bucket_list.at(index) if (w == restriction_target.first)
) { {
if(w == restriction_target.first) {
return true; return true;
} }
} }
@ -492,8 +455,10 @@ private:
return false; return false;
} }
void DeleteFileIfExists(const std::string & file_name) const { void DeleteFileIfExists(const std::string &file_name) const
if (boost::filesystem::exists(file_name) ) { {
if (boost::filesystem::exists(file_name))
{
boost::filesystem::remove(file_name); boost::filesystem::remove(file_name);
} }
} }

View File

@ -27,8 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../typedefs.h" #include "../typedefs.h"
#include "../Algorithms/StronglyConnectedComponents.h" #include "../Algorithms/StronglyConnectedComponents.h"
#include "../DataStructures/BinaryHeap.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h" #include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/QueryEdge.h" #include "../DataStructures/QueryEdge.h"
#include "../DataStructures/TurnInstructions.h" #include "../DataStructures/TurnInstructions.h"
@ -38,11 +36,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include "../Util/UUID.h" #include "../Util/UUID.h"
#include <boost/foreach.hpp>
#include <fstream> #include <fstream>
#include <istream> #include <memory>
#include <iostream>
#include <cstring>
#include <string> #include <string>
#include <vector> #include <vector>
@ -98,9 +93,12 @@ int main(int argc, char *argv[])
} }
std::vector<ImportEdge> edge_list; std::vector<ImportEdge> edge_list;
NodeID node_based_node_count = readBinaryOSRMGraphFromStream( const NodeID node_based_node_count = readBinaryOSRMGraphFromStream(input_stream,
input_stream, edge_list, bollard_node_IDs_vector, traffic_light_node_IDs_vector, edge_list,
&internal_to_external_node_map, restrictions_vector); bollard_node_IDs_vector,
traffic_light_node_IDs_vector,
&internal_to_external_node_map,
restrictions_vector);
input_stream.close(); input_stream.close();
BOOST_ASSERT_MSG(restrictions_vector.size() == usable_restriction_count, BOOST_ASSERT_MSG(restrictions_vector.size() == usable_restriction_count,
@ -116,16 +114,15 @@ int main(int argc, char *argv[])
*/ */
SimpleLogger().Write() << "Starting SCC graph traversal"; SimpleLogger().Write() << "Starting SCC graph traversal";
TarjanSCC *tarjan = new TarjanSCC(node_based_node_count, edge_list, bollard_node_IDs_vector, std::shared_ptr<TarjanSCC> tarjan = std::make_shared<TarjanSCC>(node_based_node_count,
traffic_light_node_IDs_vector, restrictions_vector, edge_list,
bollard_node_IDs_vector,
traffic_light_node_IDs_vector,
restrictions_vector,
internal_to_external_node_map); internal_to_external_node_map);
std::vector<ImportEdge>().swap(edge_list); std::vector<ImportEdge>().swap(edge_list);
tarjan->Run(); 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"; SimpleLogger().Write() << "finished component analysis";
} }
catch (const std::exception &e) catch (const std::exception &e)