diff --git a/CMakeLists.txt b/CMakeLists.txt index 9239071..a9c10a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/build") # set compiler flags, see http://stackoverflow.com/questions/7724569/debug-vs-release-in-cmake -set(CMAKE_CXX_FLAGS "-Ofast -fno-signed-zeros -fno-trapping-math -Wall -Wno-format-extra-args -Wextra -Wformat-nonliteral -Wformat-security -Wformat=2 -Wextra -Wno-implicit-fallthrough -pedantic") +set(CMAKE_CXX_FLAGS "-Ofast -fno-signed-zeros -fno-trapping-math -Wall -Wno-format-extra-args -Wextra -Wformat-nonliteral -Wformat-security -Wformat=2 -Wextra -Wno-implicit-fallthrough -pedantic -Wno-keyword-macro") set(CMAKE_CXX_FLAGS_SANITIZE "-Og -g -fsanitize=address -fsanitize=leak -fsanitize=undefined -DLOGLEVEL=3 -DPFAEDLE_DBG=1") set(CMAKE_CXX_FLAGS_PROFILE "-g -pg -DLOGLEVEL=3 -DPFAEDLE_DBG=1") set(CMAKE_CXX_FLAGS_DEBUG "-Og -g -DLOGLEVEL=3 -DPFAEDLE_DBG=1") diff --git a/src/util/3rdparty/MurmurHash3.cpp b/src/util/3rdparty/MurmurHash3.cpp index aa7982d..23ac4fb 100644 --- a/src/util/3rdparty/MurmurHash3.cpp +++ b/src/util/3rdparty/MurmurHash3.cpp @@ -16,57 +16,48 @@ #if defined(_MSC_VER) -#define FORCE_INLINE __forceinline +#define FORCE_INLINE __forceinline #include -#define ROTL32(x,y) _rotl(x,y) -#define ROTL64(x,y) _rotl64(x,y) +#define ROTL32(x, y) _rotl(x, y) +#define ROTL64(x, y) _rotl64(x, y) #define BIG_CONSTANT(x) (x) // Other compilers -#else // defined(_MSC_VER) +#else // defined(_MSC_VER) -#define FORCE_INLINE inline __attribute__((always_inline)) +#define FORCE_INLINE inline __attribute__((always_inline)) -inline uint32_t rotl32 ( uint32_t x, int8_t r ) -{ +inline uint32_t rotl32(uint32_t x, int8_t r) { return (x << r) | (x >> (32 - r)); } -inline uint64_t rotl64 ( uint64_t x, int8_t r ) -{ +inline uint64_t rotl64(uint64_t x, int8_t r) { return (x << r) | (x >> (64 - r)); } -#define ROTL32(x,y) rotl32(x,y) -#define ROTL64(x,y) rotl64(x,y) +#define ROTL32(x, y) rotl32(x, y) +#define ROTL64(x, y) rotl64(x, y) #define BIG_CONSTANT(x) (x##LLU) -#endif // !defined(_MSC_VER) +#endif // !defined(_MSC_VER) //----------------------------------------------------------------------------- // Block read - if your platform needs to do endian-swapping or can only // handle aligned reads, do the conversion here -FORCE_INLINE uint32_t getblock32 ( const uint32_t * p, int i ) -{ - return p[i]; -} +FORCE_INLINE uint32_t getblock32(const uint32_t *p, int i) { return p[i]; } -FORCE_INLINE uint64_t getblock64 ( const uint64_t * p, int i ) -{ - return p[i]; -} +FORCE_INLINE uint64_t getblock64(const uint64_t *p, int i) { return p[i]; } //----------------------------------------------------------------------------- // Finalization mix - force all bits of a hash block to avalanche -FORCE_INLINE uint32_t fmix32 ( uint32_t h ) -{ +FORCE_INLINE uint32_t fmix32(uint32_t h) { h ^= h >> 16; h *= 0x85ebca6b; h ^= h >> 13; @@ -78,8 +69,7 @@ FORCE_INLINE uint32_t fmix32 ( uint32_t h ) //---------- -FORCE_INLINE uint64_t fmix64 ( uint64_t k ) -{ +FORCE_INLINE uint64_t fmix64(uint64_t k) { k ^= k >> 33; k *= BIG_CONSTANT(0xff51afd7ed558ccd); k ^= k >> 33; @@ -91,10 +81,8 @@ FORCE_INLINE uint64_t fmix64 ( uint64_t k ) //----------------------------------------------------------------------------- -void MurmurHash3_x86_32 ( const void * key, int len, - uint32_t seed, void * out ) -{ - const uint8_t * data = (const uint8_t*)key; +void MurmurHash3_x86_32(const void *key, int len, uint32_t seed, void *out) { + const uint8_t *data = (const uint8_t *)key; const int nblocks = len / 4; uint32_t h1 = seed; @@ -105,34 +93,40 @@ void MurmurHash3_x86_32 ( const void * key, int len, //---------- // body - const uint32_t * blocks = (const uint32_t *)(data + nblocks*4); + const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4); - for(int i = -nblocks; i; i++) - { - uint32_t k1 = getblock32(blocks,i); + for (int i = -nblocks; i; i++) { + uint32_t k1 = getblock32(blocks, i); k1 *= c1; - k1 = ROTL32(k1,15); + k1 = ROTL32(k1, 15); k1 *= c2; - + h1 ^= k1; - h1 = ROTL32(h1,13); - h1 = h1*5+0xe6546b64; + h1 = ROTL32(h1, 13); + h1 = h1 * 5 + 0xe6546b64; } //---------- // tail - const uint8_t * tail = (const uint8_t*)(data + nblocks*4); + const uint8_t *tail = (const uint8_t *)(data + nblocks * 4); uint32_t k1 = 0; - switch(len & 3) - { - case 3: k1 ^= tail[2] << 16; - case 2: k1 ^= tail[1] << 8; - case 1: k1 ^= tail[0]; - k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + switch (len & 3) { + case 3: + k1 ^= tail[2] << 16; + // fall through + case 2: + k1 ^= tail[1] << 8; + // fall through + case 1: + k1 ^= tail[0]; + k1 *= c1; + k1 = ROTL32(k1, 15); + k1 *= c2; + h1 ^= k1; }; //---------- @@ -142,15 +136,14 @@ void MurmurHash3_x86_32 ( const void * key, int len, h1 = fmix32(h1); - *(uint32_t*)out = h1; -} + *(uint32_t *)out = h1; +} //----------------------------------------------------------------------------- -void MurmurHash3_x86_128 ( const void * key, const int len, - uint32_t seed, void * out ) -{ - const uint8_t * data = (const uint8_t*)key; +void MurmurHash3_x86_128(const void *key, const int len, uint32_t seed, + void *out) { + const uint8_t *data = (const uint8_t *)key; const int nblocks = len / 16; uint32_t h1 = seed; @@ -158,104 +151,170 @@ void MurmurHash3_x86_128 ( const void * key, const int len, uint32_t h3 = seed; uint32_t h4 = seed; - const uint32_t c1 = 0x239b961b; + const uint32_t c1 = 0x239b961b; const uint32_t c2 = 0xab0e9789; - const uint32_t c3 = 0x38b34ae5; + const uint32_t c3 = 0x38b34ae5; const uint32_t c4 = 0xa1e38b93; //---------- // body - const uint32_t * blocks = (const uint32_t *)(data + nblocks*16); + const uint32_t *blocks = (const uint32_t *)(data + nblocks * 16); - for(int i = -nblocks; i; i++) - { - uint32_t k1 = getblock32(blocks,i*4+0); - uint32_t k2 = getblock32(blocks,i*4+1); - uint32_t k3 = getblock32(blocks,i*4+2); - uint32_t k4 = getblock32(blocks,i*4+3); + for (int i = -nblocks; i; i++) { + uint32_t k1 = getblock32(blocks, i * 4 + 0); + uint32_t k2 = getblock32(blocks, i * 4 + 1); + uint32_t k3 = getblock32(blocks, i * 4 + 2); + uint32_t k4 = getblock32(blocks, i * 4 + 3); - k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + k1 *= c1; + k1 = ROTL32(k1, 15); + k1 *= c2; + h1 ^= k1; - h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b; + h1 = ROTL32(h1, 19); + h1 += h2; + h1 = h1 * 5 + 0x561ccd1b; - k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2; + k2 *= c2; + k2 = ROTL32(k2, 16); + k2 *= c3; + h2 ^= k2; - h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747; + h2 = ROTL32(h2, 17); + h2 += h3; + h2 = h2 * 5 + 0x0bcaa747; - k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3; + k3 *= c3; + k3 = ROTL32(k3, 17); + k3 *= c4; + h3 ^= k3; - h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35; + h3 = ROTL32(h3, 15); + h3 += h4; + h3 = h3 * 5 + 0x96cd1c35; - k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4; + k4 *= c4; + k4 = ROTL32(k4, 18); + k4 *= c1; + h4 ^= k4; - h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17; + h4 = ROTL32(h4, 13); + h4 += h1; + h4 = h4 * 5 + 0x32ac3b17; } //---------- // tail - const uint8_t * tail = (const uint8_t*)(data + nblocks*16); + const uint8_t *tail = (const uint8_t *)(data + nblocks * 16); uint32_t k1 = 0; uint32_t k2 = 0; uint32_t k3 = 0; uint32_t k4 = 0; - switch(len & 15) - { - case 15: k4 ^= tail[14] << 16; - case 14: k4 ^= tail[13] << 8; - case 13: k4 ^= tail[12] << 0; - k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4; - - case 12: k3 ^= tail[11] << 24; - case 11: k3 ^= tail[10] << 16; - case 10: k3 ^= tail[ 9] << 8; - case 9: k3 ^= tail[ 8] << 0; - k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3; - - case 8: k2 ^= tail[ 7] << 24; - case 7: k2 ^= tail[ 6] << 16; - case 6: k2 ^= tail[ 5] << 8; - case 5: k2 ^= tail[ 4] << 0; - k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2; - - case 4: k1 ^= tail[ 3] << 24; - case 3: k1 ^= tail[ 2] << 16; - case 2: k1 ^= tail[ 1] << 8; - case 1: k1 ^= tail[ 0] << 0; - k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + switch (len & 15) { + case 15: + k4 ^= tail[14] << 16; + // fall through + case 14: + k4 ^= tail[13] << 8; + // fall through + case 13: + k4 ^= tail[12] << 0; + k4 *= c4; + k4 = ROTL32(k4, 18); + k4 *= c1; + h4 ^= k4; + // fall through + case 12: + k3 ^= tail[11] << 24; + // fall through + case 11: + k3 ^= tail[10] << 16; + // fall through + case 10: + k3 ^= tail[9] << 8; + // fall through + case 9: + k3 ^= tail[8] << 0; + k3 *= c3; + k3 = ROTL32(k3, 17); + k3 *= c4; + h3 ^= k3; + // fall through + case 8: + k2 ^= tail[7] << 24; + // fall through + case 7: + k2 ^= tail[6] << 16; + // fall through + case 6: + k2 ^= tail[5] << 8; + // fall through + case 5: + k2 ^= tail[4] << 0; + k2 *= c2; + k2 = ROTL32(k2, 16); + k2 *= c3; + h2 ^= k2; + // fall through + case 4: + k1 ^= tail[3] << 24; + // fall through + case 3: + k1 ^= tail[2] << 16; + // fall through + case 2: + k1 ^= tail[1] << 8; + // fall through + case 1: + k1 ^= tail[0] << 0; + k1 *= c1; + k1 = ROTL32(k1, 15); + k1 *= c2; + h1 ^= k1; }; //---------- // finalization - h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len; + h1 ^= len; + h2 ^= len; + h3 ^= len; + h4 ^= len; - h1 += h2; h1 += h3; h1 += h4; - h2 += h1; h3 += h1; h4 += h1; + h1 += h2; + h1 += h3; + h1 += h4; + h2 += h1; + h3 += h1; + h4 += h1; h1 = fmix32(h1); h2 = fmix32(h2); h3 = fmix32(h3); h4 = fmix32(h4); - h1 += h2; h1 += h3; h1 += h4; - h2 += h1; h3 += h1; h4 += h1; + h1 += h2; + h1 += h3; + h1 += h4; + h2 += h1; + h3 += h1; + h4 += h1; - ((uint32_t*)out)[0] = h1; - ((uint32_t*)out)[1] = h2; - ((uint32_t*)out)[2] = h3; - ((uint32_t*)out)[3] = h4; + ((uint32_t *)out)[0] = h1; + ((uint32_t *)out)[1] = h2; + ((uint32_t *)out)[2] = h3; + ((uint32_t *)out)[3] = h4; } //----------------------------------------------------------------------------- -void MurmurHash3_x64_128 ( const void * key, const int len, - const uint32_t seed, void * out ) -{ - const uint8_t * data = (const uint8_t*)key; +void MurmurHash3_x64_128(const void *key, const int len, const uint32_t seed, + void *out) { + const uint8_t *data = (const uint8_t *)key; const int nblocks = len / 16; uint64_t h1 = seed; @@ -267,56 +326,99 @@ void MurmurHash3_x64_128 ( const void * key, const int len, //---------- // body - const uint64_t * blocks = (const uint64_t *)(data); + const uint64_t *blocks = (const uint64_t *)(data); - for(int i = 0; i < nblocks; i++) - { - uint64_t k1 = getblock64(blocks,i*2+0); - uint64_t k2 = getblock64(blocks,i*2+1); + for (int i = 0; i < nblocks; i++) { + uint64_t k1 = getblock64(blocks, i * 2 + 0); + uint64_t k2 = getblock64(blocks, i * 2 + 1); - k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1; + k1 *= c1; + k1 = ROTL64(k1, 31); + k1 *= c2; + h1 ^= k1; - h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729; + h1 = ROTL64(h1, 27); + h1 += h2; + h1 = h1 * 5 + 0x52dce729; - k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2; + k2 *= c2; + k2 = ROTL64(k2, 33); + k2 *= c1; + h2 ^= k2; - h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5; + h2 = ROTL64(h2, 31); + h2 += h1; + h2 = h2 * 5 + 0x38495ab5; } //---------- // tail - const uint8_t * tail = (const uint8_t*)(data + nblocks*16); + const uint8_t *tail = (const uint8_t *)(data + nblocks * 16); uint64_t k1 = 0; uint64_t k2 = 0; - switch(len & 15) - { - case 15: k2 ^= ((uint64_t)tail[14]) << 48; - case 14: k2 ^= ((uint64_t)tail[13]) << 40; - case 13: k2 ^= ((uint64_t)tail[12]) << 32; - case 12: k2 ^= ((uint64_t)tail[11]) << 24; - case 11: k2 ^= ((uint64_t)tail[10]) << 16; - case 10: k2 ^= ((uint64_t)tail[ 9]) << 8; - case 9: k2 ^= ((uint64_t)tail[ 8]) << 0; - k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2; - - case 8: k1 ^= ((uint64_t)tail[ 7]) << 56; - case 7: k1 ^= ((uint64_t)tail[ 6]) << 48; - case 6: k1 ^= ((uint64_t)tail[ 5]) << 40; - case 5: k1 ^= ((uint64_t)tail[ 4]) << 32; - case 4: k1 ^= ((uint64_t)tail[ 3]) << 24; - case 3: k1 ^= ((uint64_t)tail[ 2]) << 16; - case 2: k1 ^= ((uint64_t)tail[ 1]) << 8; - case 1: k1 ^= ((uint64_t)tail[ 0]) << 0; - k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1; + switch (len & 15) { + case 15: + k2 ^= ((uint64_t)tail[14]) << 48; + // fall through + case 14: + k2 ^= ((uint64_t)tail[13]) << 40; + // fall through + case 13: + k2 ^= ((uint64_t)tail[12]) << 32; + // fall through + case 12: + k2 ^= ((uint64_t)tail[11]) << 24; + // fall through + case 11: + k2 ^= ((uint64_t)tail[10]) << 16; + // fall through + case 10: + k2 ^= ((uint64_t)tail[9]) << 8; + // fall through + case 9: + k2 ^= ((uint64_t)tail[8]) << 0; + k2 *= c2; + k2 = ROTL64(k2, 33); + k2 *= c1; + h2 ^= k2; + // fall through + case 8: + k1 ^= ((uint64_t)tail[7]) << 56; + // fall through + case 7: + k1 ^= ((uint64_t)tail[6]) << 48; + // fall through + case 6: + k1 ^= ((uint64_t)tail[5]) << 40; + // fall through + case 5: + k1 ^= ((uint64_t)tail[4]) << 32; + // fall through + case 4: + k1 ^= ((uint64_t)tail[3]) << 24; + // fall through + case 3: + k1 ^= ((uint64_t)tail[2]) << 16; + // fall through + case 2: + k1 ^= ((uint64_t)tail[1]) << 8; + // fall through + case 1: + k1 ^= ((uint64_t)tail[0]) << 0; + k1 *= c1; + k1 = ROTL64(k1, 31); + k1 *= c2; + h1 ^= k1; }; //---------- // finalization - h1 ^= len; h2 ^= len; + h1 ^= len; + h2 ^= len; h1 += h2; h2 += h1; @@ -327,9 +429,8 @@ void MurmurHash3_x64_128 ( const void * key, const int len, h1 += h2; h2 += h1; - ((uint64_t*)out)[0] = h1; - ((uint64_t*)out)[1] = h2; + ((uint64_t *)out)[0] = h1; + ((uint64_t *)out)[1] = h2; } //----------------------------------------------------------------------------- - diff --git a/src/util/Misc.h b/src/util/Misc.h index feb3207..d27e79e 100644 --- a/src/util/Misc.h +++ b/src/util/Misc.h @@ -9,8 +9,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -114,6 +116,21 @@ inline bool isFloatingPoint(const std::string& str) { return ss.eof() && ! ss.fail(); } +// _____________________________________________________________________________ +inline std::string formatFloat(double f, size_t digits) { + std::stringstream ss; + ss << std::fixed << std::setprecision(digits) << f; + std::string ret = ss.str(); + + if (ret.find('.') != std::string::npos) { + auto p = ret.find_last_not_of('0'); + if (ret[p] == '.') return ret.substr(0, p); + return ret.substr(0, p + 1); + } + + return ret; +} + // _____________________________________________________________________________ inline double atof(const char* p, uint8_t mn) { // this atof implementation works only on "normal" float strings like diff --git a/src/util/geo/Box.h b/src/util/geo/Box.h index b65f1d3..1415937 100644 --- a/src/util/geo/Box.h +++ b/src/util/geo/Box.h @@ -24,6 +24,9 @@ class Box { Point& getLowerLeft() { return _ll; } Point& getUpperRight() { return _ur; } + Point getUpperLeft() { return {_ll.getX(), _ur.getY()}; } + Point getLowerRight() { return {_ur.getX(), _ll.getY()}; } + void setLowerLeft(const Point& ll) { _ll = ll; } void setUpperRight(const Point& ur) { _ur = ur; } diff --git a/src/util/geo/Geo.h b/src/util/geo/Geo.h index 8b7f966..ce6020b 100644 --- a/src/util/geo/Geo.h +++ b/src/util/geo/Geo.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -742,6 +743,19 @@ inline double angBetween(const Point& p1, const Point& q1) { return angBetween(p1.getX(), p1.getY(), q1.getX(), q1.getY()); } +// _____________________________________________________________________________ +template +inline double angBetween(const Point& p1, const MultiPoint& points) { + double sinSum = 0; + double cosSum = 0; + for (auto q1 : points) { + double a = angBetween(p1.getX(), p1.getY(), q1.getX(), q1.getY()); + sinSum += sin(a); + cosSum += cos(a); + } + return atan2(sinSum / points.size(), cosSum / points.size()); +} + // _____________________________________________________________________________ inline double dist(double x1, double y1, double x2, double y2) { return sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); @@ -932,19 +946,19 @@ inline Line lineFromWKT(std::string wkt) { // _____________________________________________________________________________ template inline std::string getWKT(const Point& p) { - std::stringstream ss; - ss << std::fixed << std::setprecision(6) << "POINT (" << p.getX() << " " << p.getY() << ")"; - return ss.str(); + return std::string("POINT (") + formatFloat(p.getX(), 6) + " " + + formatFloat(p.getY(), 6) + ")"; } // _____________________________________________________________________________ template inline std::string getWKT(const std::vector>& p) { std::stringstream ss; - ss << std::fixed << std::setprecision(6) << "MULTIPOINT ("; + ss << "MULTIPOINT ("; for (size_t i = 0; i < p.size(); i++) { if (i) ss << ", "; - ss << "(" << p[i].getX() << " " << p[i].getY() << ")"; + ss << "(" << formatFloat(p.getX(), 6) << " " << formatFloat(p.getY(), 6) + << ")"; } ss << ")"; return ss.str(); @@ -954,10 +968,10 @@ inline std::string getWKT(const std::vector>& p) { template inline std::string getWKT(const Line& l) { std::stringstream ss; - ss << std::fixed << std::setprecision(6) << "LINESTRING ("; + ss << "LINESTRING ("; for (size_t i = 0; i < l.size(); i++) { if (i) ss << ", "; - ss << l[i].getX() << " " << l[i].getY(); + ss << formatFloat(l[i].getX(), 6) << " " << formatFloat(l[i].getY(), 6); } ss << ")"; return ss.str(); @@ -967,14 +981,15 @@ inline std::string getWKT(const Line& l) { template inline std::string getWKT(const std::vector>& ls) { std::stringstream ss; - ss << std::fixed << std::setprecision(6) << "MULTILINESTRING ("; + ss << "MULTILINESTRING ("; for (size_t j = 0; j < ls.size(); j++) { if (j) ss << ", "; ss << "("; for (size_t i = 0; i < ls[j].size(); i++) { if (i) ss << ", "; - ss << ls[j][i].getX() << " " << ls[j][i].getY(); + ss << formatFloat(ls[j][i].getX(), 6) << " " + << formatFloat(ls[j][i].getY(), 6); } ss << ")"; } @@ -994,11 +1009,16 @@ template inline std::string getWKT(const Box& l) { std::stringstream ss; ss << "POLYGON (("; - ss << l.getLowerLeft().getX() << " " << l.getLowerLeft().getY(); - ss << ", " << l.getUpperRight().getX() << " " << l.getLowerLeft().getY(); - ss << ", " << l.getUpperRight().getX() << " " << l.getUpperRight().getY(); - ss << ", " << l.getLowerLeft().getX() << " " << l.getUpperRight().getY(); - ss << ", " << l.getLowerLeft().getX() << " " << l.getLowerLeft().getY(); + ss << formatFloat(l.getLowerLeft().getX(), 6) << " " + << formatFloat(l.getLowerLeft().getY(), 6); + ss << ", " << formatFloat(l.getUpperRight().getX(), 6) << " " + << formatFloat(l.getLowerLeft().getY(), 6); + ss << ", " << formatFloat(l.getUpperRight().getX(), 6) << " " + << formatFloat(l.getUpperRight().getY(), 6); + ss << ", " << formatFloat(l.getLowerLeft().getX(), 6) << " " + << formatFloat(l.getUpperRight().getY(), 6); + ss << ", " << formatFloat(l.getLowerLeft().getX(), 6) << " " + << formatFloat(l.getLowerLeft().getY(), 6); ss << "))"; return ss.str(); } @@ -1009,9 +1029,11 @@ inline std::string getWKT(const Polygon& p) { std::stringstream ss; ss << "POLYGON (("; for (size_t i = 0; i < p.getOuter().size(); i++) { - ss << p.getOuter()[i].getX() << " " << p.getOuter()[i].getY() << ", "; + ss << formatFloat(p.getOuter()[i].getX(), 6) << " " + << formatFloat(p.getOuter()[i].getY(), 6) << ", "; } - ss << p.getOuter().front().getX() << " " << p.getOuter().front().getY(); + ss << formatFloat(p.getOuter().front().getX(), 6) << " " + << formatFloat(p.getOuter().front().getY(), 6); ss << "))"; return ss.str(); } @@ -1026,11 +1048,11 @@ inline std::string getWKT(const std::vector>& ls) { if (j) ss << ", "; ss << "(("; for (size_t i = 0; i < ls[j].getOuter().size(); i++) { - ss << ls[j].getOuter()[i].getX() << " " << ls[j].getOuter()[i].getY() - << ", "; + ss << formatFloat(ls[j].getOuter()[i].getX(), 6) << " " + << formatFloat(ls[j].getOuter()[i].getY(), 6) << ", "; } - ss << ls[j].getOuter().front().getX() << " " - << ls[j].getOuter().front().getY(); + ss << formatFloat(ls[j].getOuter().front().getX(), 6) << " " + << formatFloat(ls[j].getOuter().front().getY(), 6); ss << "))"; } @@ -1224,7 +1246,8 @@ inline double parallelity(const Box& box, const MultiLine& multiline) { // _____________________________________________________________________________ template