migrating Algorithms directory to C++11
This commit is contained in:
parent
0d8f2e1b18
commit
c33c6188a8
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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 += ",";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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_ */
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user