From 1f66428df23a7616226aa7bdca79b7022b65e0fb Mon Sep 17 00:00:00 2001 From: Dan Baston Date: Wed, 22 Jan 2025 16:37:19 -0500 Subject: [PATCH 1/8] Envelope: add getPerimeter and intersection() overload --- include/geos/geom/Envelope.h | 22 ++++++++++++++++++++++ src/geom/Envelope.cpp | 18 ++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/include/geos/geom/Envelope.h b/include/geos/geom/Envelope.h index e64fdf8b11..61e074be8c 100644 --- a/include/geos/geom/Envelope.h +++ b/include/geos/geom/Envelope.h @@ -292,6 +292,18 @@ class GEOS_DLL Envelope { return getWidth() * getHeight(); } + /** \brief + * Gets the perimeter of this envelope. + * + * @return the perimeter of the envelope + * @return 0.0 if the envelope is null + */ + double + getPerimeter() const + { + return 2*getWidth() + 2*getHeight(); + } + /** \brief * Returns true if this Envelope covers a finite region */ @@ -376,6 +388,16 @@ class GEOS_DLL Envelope { */ bool intersection(const Envelope& env, Envelope& result) const; + /** \brief + * Computes the intersection of two [Envelopes](@ref Envelope). + * + * @param env the envelope to intersect with + * @return the envelope representing the intersection of + * the envelopes (this will be the null envelope + * if either argument is null, or they do not intersect) + */ + Envelope intersection(const Envelope& env) const; + /** \brief * Translates this envelope by given amounts in the X and Y direction. * diff --git a/src/geom/Envelope.cpp b/src/geom/Envelope.cpp index 74899e743d..f52292e507 100644 --- a/src/geom/Envelope.cpp +++ b/src/geom/Envelope.cpp @@ -202,6 +202,24 @@ Envelope::intersection(const Envelope& env, Envelope& result) const return true; } +/*public*/ +Envelope +Envelope::intersection(const Envelope& env) const +{ + Envelope ret; + + if(isNull() || env.isNull() || ! intersects(env)) { + return ret; + } + + double intMinX = minx > env.minx ? minx : env.minx; + double intMinY = miny > env.miny ? miny : env.miny; + double intMaxX = maxx < env.maxx ? maxx : env.maxx; + double intMaxY = maxy < env.maxy ? maxy : env.maxy; + ret.init(intMinX, intMaxX, intMinY, intMaxY); + return ret; +} + /*public*/ void Envelope::translate(double transX, double transY) From b063661ccccb1c8a6fdfa0a4cca72f5b8361c8b4 Mon Sep 17 00:00:00 2001 From: Dan Baston Date: Wed, 22 Jan 2025 16:38:16 -0500 Subject: [PATCH 2/8] Area: add ofRing overload for CoordinateXY vec --- include/geos/algorithm/Area.h | 8 ++++++ src/algorithm/Area.cpp | 47 ++++++++++++++++++++++------------- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/include/geos/algorithm/Area.h b/include/geos/algorithm/Area.h index c3c799f877..51f188eda5 100644 --- a/include/geos/algorithm/Area.h +++ b/include/geos/algorithm/Area.h @@ -44,6 +44,14 @@ class GEOS_DLL Area { */ static double ofRing(const std::vector& ring); + /** + * Computes the area for a ring. + * + * @param ring the coordinates forming the ring + * @return the area of the ring + */ + static double ofRing(const std::vector& ring); + /** * Computes the area for a ring. * diff --git a/src/algorithm/Area.cpp b/src/algorithm/Area.cpp index 3d2375c957..2be5b5316f 100644 --- a/src/algorithm/Area.cpp +++ b/src/algorithm/Area.cpp @@ -30,23 +30,8 @@ using geos::geom::CoordinateXY; namespace geos { namespace algorithm { // geos.algorithm -/* public static */ -double -Area::ofRing(const std::vector& ring) -{ - return std::abs(ofRingSigned(ring)); -} - -/* public static */ -double -Area::ofRing(const geom::CoordinateSequence* ring) -{ - return std::abs(ofRingSigned(ring)); -} - -/* public static */ -double -Area::ofRingSigned(const std::vector& ring) +template +double signedRingArea(const T& ring) { std::size_t rlen = ring.size(); if(rlen < 3) { @@ -66,6 +51,34 @@ Area::ofRingSigned(const std::vector& ring) sum += x * (y2 - y1); } return sum / 2.0; + +} + +/* public static */ +double +Area::ofRing(const std::vector& ring) +{ + return std::abs(ofRingSigned(ring)); +} + +double +Area::ofRing(const std::vector& ring) +{ + return std::abs(signedRingArea(ring)); +} + +/* public static */ +double +Area::ofRing(const geom::CoordinateSequence* ring) +{ + return std::abs(ofRingSigned(ring)); +} + +/* public static */ +double +Area::ofRingSigned(const std::vector& ring) +{ + return signedRingArea(ring); } /* public static */ From ab0a0d28ccd87178093001bc66106414b72f7a94 Mon Sep 17 00:00:00 2001 From: Dan Baston Date: Wed, 22 Jan 2025 16:39:09 -0500 Subject: [PATCH 3/8] Length: add ofLine overload for CoordinateXY vec --- include/geos/algorithm/Length.h | 10 ++++++++++ src/algorithm/Length.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/include/geos/algorithm/Length.h b/include/geos/algorithm/Length.h index e9aa94e635..75c0ca1202 100644 --- a/include/geos/algorithm/Length.h +++ b/include/geos/algorithm/Length.h @@ -22,6 +22,8 @@ #include #include +#include + namespace geos { namespace algorithm { // geos::algorithm @@ -41,6 +43,14 @@ class GEOS_DLL Length { */ static double ofLine(const geom::CoordinateSequence* ring); + /** + * Computes the length of a linestring specified by a sequence of points. + * + * @param ring the points specifying the linestring + * @return the length of the linestring + */ + static double ofLine(const std::vector& ring); + }; diff --git a/src/algorithm/Length.cpp b/src/algorithm/Length.cpp index 1466510d2a..68897dac4e 100644 --- a/src/algorithm/Length.cpp +++ b/src/algorithm/Length.cpp @@ -55,6 +55,32 @@ Length::ofLine(const geom::CoordinateSequence* pts) return len; } +double +Length::ofLine(const std::vector& pts) +{ + if (pts.size() < 2) { + return 0; + } + + double len = 0; + double x0 = pts[0].x; + double y0 = pts[0].y; + + for(std::size_t i = 1; i < pts.size(); i++) { + const geom::CoordinateXY& pi = pts[i]; + double x1 = pi.x; + double y1 = pi.y; + double dx = x1 - x0; + double dy = y1 - y0; + + len += std::sqrt(dx * dx + dy * dy); + + x0 = x1; + y0 = y1; + } + + return len; +} } // namespace geos.algorithm } //namespace geos From b1545e9395662704c08e12c7ea4b29af5e1d60ce Mon Sep 17 00:00:00 2001 From: Dan Baston Date: Wed, 22 Jan 2025 16:39:48 -0500 Subject: [PATCH 4/8] CoordinateSequence: add setPoints overload for CoordinateXY vec --- include/geos/geom/CoordinateSequence.h | 3 +++ src/geom/CoordinateSequence.cpp | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/geos/geom/CoordinateSequence.h b/include/geos/geom/CoordinateSequence.h index c135ce18da..2d952f1371 100644 --- a/include/geos/geom/CoordinateSequence.h +++ b/include/geos/geom/CoordinateSequence.h @@ -400,6 +400,9 @@ class GEOS_DLL CoordinateSequence { /// Substitute Coordinate list with a copy of the given vector void setPoints(const std::vector& v); + /// Substitute Coordinate list with a copy of the given vector + void setPoints(const std::vector& v); + /// @} /// \defgroup add Adding methods /// @{ diff --git a/src/geom/CoordinateSequence.cpp b/src/geom/CoordinateSequence.cpp index 599ca6ffb2..b5fc591bd8 100644 --- a/src/geom/CoordinateSequence.cpp +++ b/src/geom/CoordinateSequence.cpp @@ -575,11 +575,25 @@ CoordinateSequence::setPoints(const std::vector& v) m_hasz = false; m_hasm = false; - m_vect.resize(3 * v.size()); + m_vect.resize(m_stride * v.size()); const double* cbuf = reinterpret_cast(v.data()); m_vect.assign(cbuf, cbuf + m_vect.size()); } +void +CoordinateSequence::setPoints(const std::vector& v) +{ + m_stride = 3; + m_hasdim = false; + m_hasz = false; + m_hasm = false; + + m_vect.resize(m_stride * v.size()); + for (std::size_t i = 0; i < v.size(); i++) { + setAt(v[i], i); + } +} + void CoordinateSequence::toVector(std::vector& out) const { From ed12b033db549a207fad45eeae1363bbcdb4f036 Mon Sep 17 00:00:00 2001 From: Dan Baston Date: Mon, 3 Feb 2025 13:30:46 -0500 Subject: [PATCH 5/8] CI: Switch C++14 builds to C++17 --- .github/workflows/ci.yml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2ddfda4e9b..1aaa77f216 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,7 @@ jobs: - cxx_compiler: g++ c_compiler: gcc build_type: Coverage - cxxstd: 14 + cxxstd: 17 arch: 64 packages: g++ cmake: 3.15.* @@ -51,7 +51,7 @@ jobs: - cxx_compiler: g++-7 c_compiler: gcc-7 build_type: Release - cxxstd: 14 + cxxstd: 17 arch: 64 packages: 'g++-7-multilib gcc-7-multilib' cmake: 3.17.* @@ -60,7 +60,7 @@ jobs: - cxx_compiler: g++-7 c_compiler: gcc-7 build_type: Release - cxxstd: 14 + cxxstd: 17 arch: 32 packages: 'g++-7-multilib gcc-7-multilib g++-multilib gcc-multilib' cmake: 3.18.* @@ -69,7 +69,7 @@ jobs: - cxx_compiler: g++-8 c_compiler: gcc-8 build_type: Release - cxxstd: 14 + cxxstd: 17 arch: 64 packages: 'g++-8-multilib gcc-8-multilib' cmake: 3.21.* @@ -78,7 +78,7 @@ jobs: - cxx_compiler: g++-9 c_compiler: gcc-9 build_type: Release - cxxstd: 14 + cxxstd: 17 arch: 64 packages: 'g++-9-multilib gcc-9-multilib' cmake: 3.23.* @@ -87,7 +87,7 @@ jobs: - cxx_compiler: g++-10 c_compiler: gcc-10 build_type: Release - cxxstd: 14 + cxxstd: 17 arch: 64 packages: 'g++-10-multilib gcc-10-multilib' cmake: 3.25.* @@ -129,7 +129,7 @@ jobs: - cxx_compiler: clang++-7 c_compiler: clang-7 build_type: Release - cxxstd: 14 + cxxstd: 17 arch: 64 packages: 'clang-7' cmake: 3.15.* @@ -138,7 +138,7 @@ jobs: - cxx_compiler: clang++-8 c_compiler: clang-8 build_type: Release - cxxstd: 14 + cxxstd: 17 arch: 64 packages: 'clang-8' cmake: 3.17.* @@ -147,7 +147,7 @@ jobs: - cxx_compiler: clang++-9 c_compiler: clang-9 build_type: Release - cxxstd: 14 + cxxstd: 17 arch: 64 packages: 'clang-9' cmake: 3.20.* @@ -156,7 +156,7 @@ jobs: - cxx_compiler: clang++-10 c_compiler: clang-10 build_type: Release - cxxstd: 14 + cxxstd: 17 arch: 64 packages: 'clang-10' cmake: 3.21.* @@ -168,7 +168,7 @@ jobs: - cxx_compiler: clang++-11 c_compiler: clang-11 build_type: Debug - cxxstd: 14 + cxxstd: 17 arch: 64 packages: 'clang-11' cmake: 3.23.* @@ -177,7 +177,7 @@ jobs: - cxx_compiler: clang++-12 c_compiler: clang-12 build_type: ASAN - cxxstd: 14 + cxxstd: 17 arch: 64 packages: 'clang-12' cmake: 3.25.* @@ -392,7 +392,7 @@ jobs: matrix: ci: - os: windows-2019 - cxxstd: 14 + cxxstd: 17 arch: x86 - os: windows-2022 From aecc295f059c6a00054a8ec7dd305df66d11eb35 Mon Sep 17 00:00:00 2001 From: Dan Baston Date: Mon, 3 Feb 2025 10:22:05 -0500 Subject: [PATCH 6/8] geos_unit: Add --data argument to specify resource directory --- tests/unit/geos_unit.cpp | 63 ++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/tests/unit/geos_unit.cpp b/tests/unit/geos_unit.cpp index 8e008c8b2a..298f60aa0b 100644 --- a/tests/unit/geos_unit.cpp +++ b/tests/unit/geos_unit.cpp @@ -17,6 +17,8 @@ #include #include +std::string RESOURCE_DIR; + namespace tut { test_runner_singleton runner; } @@ -41,6 +43,7 @@ usage() << " --list list all registered test groups\n" // << " --verbose run unit tests verbosely; displays non-error information\n" // << " --version print version information and exit\n" + << " --data specify a directory containing test data files\n" << " --help print this message and exit\n" << endl << "Examples:\n" @@ -53,19 +56,31 @@ usage() } int -main(int argc, const char* argv[]) -{ +main(int argc, const char* argv[]) { tut::reporter visi; - if((argc == 2 && std::string(argv[1]) == "--help") || argc > 3) { - usage(); - return 0; - } - //-- check options valid - if (argc >= 2 && argv[1][0] == '-') { - bool isValidOpt = std::string(argv[1]) == "--list"; - if (! isValidOpt) { - std::cerr << "Invalid option: " << argv[1] << std::endl; + bool listOnly = false; + std::string grpname; + std::string testName; + + for (std::size_t i = 1; i < static_cast(argc); i++) { + std::string arg = argv[i]; + if (arg == "--help") { + usage(); + return EXIT_SUCCESS; + } else if (arg == "--list") { + listOnly = true; + } else if (arg == "--data" && (i + 1) < static_cast(argc)) { + RESOURCE_DIR = argv[++i]; + } else if (arg[0] == '-') { + std::cerr << "Invalid option: " << argv << std::endl; + return EXIT_FAILURE; + } else if (grpname.empty()) { + grpname = arg; + } else if (testName.empty()) { + testName = arg; + } else { + std::cerr << "Unexpected positional argument: " << arg << std::endl; return EXIT_FAILURE; } } @@ -77,10 +92,7 @@ main(int argc, const char* argv[]) tut::runner.get().set_callback(&visi); try { - if (argc == 1) { - tut::runner.get().run_tests(); - } - else if (argc == 2 && std::string(argv[1]) == "--list") { + if (listOnly) { tut::groupnames gl = tut::runner.get().list_groups(); tut::groupnames::const_iterator b = gl.begin(); tut::groupnames::const_iterator e = gl.end(); @@ -94,20 +106,15 @@ main(int argc, const char* argv[]) ++b; } return EXIT_SUCCESS; - } - else if (argc == 2) { - tut::runner.get().run_tests(argv[1]); - } - else if(argc == 3) { - // TODO - mloskot - check if test group with given name exists - // TODO - mloskot - check if test case with given number exists - std::string grpname(argv[1]); - if(grpname.empty()) { - throw std::runtime_error("missing test group name"); + } else { + if (!testName.empty()) { + tut::test_result result; + tut::runner.get().run_test(grpname, std::atoi(testName.c_str()), result); + } else if (!grpname.empty()) { + tut::runner.get().run_tests(grpname); + } else { + tut::runner.get().run_tests(); } - - tut::test_result result; - tut::runner.get().run_test(grpname, std::atoi(argv[2]), result); } } catch(const tut::no_such_group& ex) { From f7627b42c1922b2ee360d7449dfb048aeb758012 Mon Sep 17 00:00:00 2001 From: Dan Baston Date: Mon, 3 Feb 2025 10:22:34 -0500 Subject: [PATCH 7/8] tut: report skip messages --- tests/unit/tut/tut_console_reporter.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/tut/tut_console_reporter.hpp b/tests/unit/tut/tut_console_reporter.hpp index c30459e062..a51c178867 100644 --- a/tests/unit/tut/tut_console_reporter.hpp +++ b/tests/unit/tut/tut_console_reporter.hpp @@ -149,8 +149,8 @@ class console_reporter : public tut::callback assert( (tr.result != tut::test_result::dummy) && "Should never be called"); } // switch - if ( (tr.result != tut::test_result::ok) && - (tr.result != tut::test_result::skipped) ) + if ( (tr.result != tut::test_result::ok) /*&& + (tr.result != tut::test_result::skipped) */) { not_passed.push_back(tr); } @@ -258,7 +258,7 @@ class console_reporter : public tut::callback bool all_ok() const override { - return not_passed.empty(); + return not_passed.size() == static_cast::size_type>(skipped_count); } private: From 96f73a45adf090b1fa03342b78677a9181e50601 Mon Sep 17 00:00:00 2001 From: Dan Baston Date: Wed, 22 Jan 2025 16:40:14 -0500 Subject: [PATCH 8/8] Add GEOSGridIntersectionFractions, GEOSSubdivideByGrid --- benchmarks/operation/CMakeLists.txt | 8 + .../operation/GridIntersectionPerfTest.cpp | 121 ++++ capi/geos_c.cpp | 13 + capi/geos_c.h.in | 68 ++ capi/geos_ts_c.cpp | 37 ++ include/geos/operation/grid/Cell.h | 107 ++++ include/geos/operation/grid/Crossing.h | 52 ++ include/geos/operation/grid/FloodFill.h | 144 +++++ include/geos/operation/grid/Grid.h | 284 ++++++++ .../geos/operation/grid/GridIntersection.h | 106 +++ include/geos/operation/grid/Matrix.h | 177 +++++ .../geos/operation/grid/PerimeterDistance.h | 42 ++ include/geos/operation/grid/Side.h | 33 + include/geos/operation/grid/Traversal.h | 76 +++ include/geos/operation/grid/TraversalAreas.h | 48 ++ src/operation/grid/Cell.cpp | 279 ++++++++ src/operation/grid/FloodFill.cpp | 42 ++ src/operation/grid/Grid.cpp | 99 +++ src/operation/grid/GridIntersection.cpp | 540 ++++++++++++++++ src/operation/grid/PerimeterDistance.cpp | 64 ++ src/operation/grid/Traversal.cpp | 106 +++ src/operation/grid/TraversalAreas.cpp | 280 ++++++++ tests/resources/antarctica.wkt | 1 + tests/resources/regression4.wkt | 1 + tests/resources/regression6.wkt | 1 + tests/resources/russia.wkt | 1 + tests/unit/CMakeLists.txt | 2 +- .../GEOSGridIntersectionFractionsTest.cpp | 62 ++ tests/unit/capi/GEOSSubdivideByGridTest.cpp | 56 ++ .../operation/grid/GridIntersectionTest.cpp | 604 ++++++++++++++++++ tests/unit/utility.h | 43 ++ 31 files changed, 3496 insertions(+), 1 deletion(-) create mode 100644 benchmarks/operation/GridIntersectionPerfTest.cpp create mode 100644 include/geos/operation/grid/Cell.h create mode 100644 include/geos/operation/grid/Crossing.h create mode 100644 include/geos/operation/grid/FloodFill.h create mode 100644 include/geos/operation/grid/Grid.h create mode 100644 include/geos/operation/grid/GridIntersection.h create mode 100644 include/geos/operation/grid/Matrix.h create mode 100644 include/geos/operation/grid/PerimeterDistance.h create mode 100644 include/geos/operation/grid/Side.h create mode 100644 include/geos/operation/grid/Traversal.h create mode 100644 include/geos/operation/grid/TraversalAreas.h create mode 100644 src/operation/grid/Cell.cpp create mode 100644 src/operation/grid/FloodFill.cpp create mode 100644 src/operation/grid/Grid.cpp create mode 100644 src/operation/grid/GridIntersection.cpp create mode 100644 src/operation/grid/PerimeterDistance.cpp create mode 100644 src/operation/grid/Traversal.cpp create mode 100644 src/operation/grid/TraversalAreas.cpp create mode 100644 tests/resources/antarctica.wkt create mode 100644 tests/resources/regression4.wkt create mode 100644 tests/resources/regression6.wkt create mode 100644 tests/resources/russia.wkt create mode 100644 tests/unit/capi/GEOSGridIntersectionFractionsTest.cpp create mode 100644 tests/unit/capi/GEOSSubdivideByGridTest.cpp create mode 100644 tests/unit/operation/grid/GridIntersectionTest.cpp diff --git a/benchmarks/operation/CMakeLists.txt b/benchmarks/operation/CMakeLists.txt index 0294a6eb39..4a6f5937a7 100644 --- a/benchmarks/operation/CMakeLists.txt +++ b/benchmarks/operation/CMakeLists.txt @@ -27,4 +27,12 @@ if (benchmark_FOUND) $) target_link_libraries(perf_coverage_union PRIVATE benchmark::benchmark geos geos_cxx_flags) + + add_executable(perf_grid_intersection GridIntersectionPerfTest.cpp) + target_include_directories(perf_grid_intersection PUBLIC + $ + $ + $) + target_link_libraries(perf_grid_intersection + benchmark::benchmark geos geos_cxx_flags) endif() diff --git a/benchmarks/operation/GridIntersectionPerfTest.cpp b/benchmarks/operation/GridIntersectionPerfTest.cpp new file mode 100644 index 0000000000..c880142f69 --- /dev/null +++ b/benchmarks/operation/GridIntersectionPerfTest.cpp @@ -0,0 +1,121 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2025 ISciences LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +using geos::geom::CoordinateXY; +using geos::geom::Envelope; +using geos::geom::Geometry; +using Grid = geos::operation::grid::Grid; + +template +struct GridIntersection { + static double Intersection(const Envelope& env, int nx, int ny, const Geometry& g) { + Grid grid(env, env.getWidth() / nx, env.getHeight() / ny); + if constexpr (AreaOnly) { + auto result = geos::operation::grid::GridIntersection::grid_intersection(grid, g); + float area = 0; + for (std::size_t i = 0; i < result->rows(); i++) { + for (std::size_t j = 0; j < result->cols(); j++) { + area += (*result)(i, j); + } + } + return static_cast(area); + } else { + auto subdivided = geos::operation::grid::GridIntersection::subdivide_polygon(grid, g, true); + return subdivided->getArea(); + } + } +}; + +using GridIntersectionAreaOnly = GridIntersection; +using GridIntersectionFull = GridIntersection; + +template +struct SingleIntersection { + + static double Intersection(const Envelope& env, int nx, int ny, const Geometry& g) { + double dx = env.getWidth() / nx; + double dy = env.getHeight() / ny; + + double x0 = env.getMinX(); + double y0 = env.getMinY(); + + const auto& gfact = *g.getFactory(); + auto prepGeom = geos::geom::prep::PreparedGeometryFactory::prepare(&g); + + double area = 0; + + for (int i = 0; i < nx; i++) { + for (int j = 0; j < ny; j++) { + Envelope subEnv(x0 + i*dx, x0 + (i+1)*dx, y0 + j*dy, y0 + (j+1)*dy); + auto cellGeom = gfact.toGeometry(&subEnv); + if (!prepGeom->intersects(cellGeom.get())) { + continue; + } + + std::unique_ptr isect; + if constexpr (UseRectangleIntersection) { + geos::operation::intersection::Rectangle rect(x0 + i*dx, y0 + j*dy, x0 + (i+1)*dx, y0 + (j+1)*dy); + isect = geos::operation::intersection::RectangleIntersection::clip(g, rect); + } else { + isect = g.intersection(cellGeom.get()); + } + + area += isect->getArea(); + } + } + + return area; + } +}; + +using PolygonIntersection = SingleIntersection; +using RectangleIntersection = SingleIntersection; + +template +static void BM_GridIntersection(benchmark::State& state) +{ + auto nCells = state.range(0); + + auto nx = static_cast(std::ceil(std::sqrt(nCells))); + auto ny = static_cast(std::ceil(std::sqrt(nCells))); + + CoordinateXY center; + Envelope env(0, nx, 0, ny); + env.centre(center); + + auto geom = geos::benchmark::createSineStar(center, env.getWidth() / 2, 500); + + for (auto _ : state) { + Impl::Intersection(env, nx, ny, *geom); + } + +} + +BENCHMARK_TEMPLATE(BM_GridIntersection, GridIntersectionAreaOnly)->Range(1000, 1000000); +BENCHMARK_TEMPLATE(BM_GridIntersection, GridIntersectionFull)->Range(1000, 1000000); +BENCHMARK_TEMPLATE(BM_GridIntersection, RectangleIntersection)->Range(1000, 1000000); +BENCHMARK_TEMPLATE(BM_GridIntersection, PolygonIntersection)->Range(1000, 1000000); + +BENCHMARK_MAIN(); diff --git a/capi/geos_c.cpp b/capi/geos_c.cpp index 633c6b07c6..abc5c7bed7 100644 --- a/capi/geos_c.cpp +++ b/capi/geos_c.cpp @@ -713,6 +713,19 @@ extern "C" { return GEOSClipByRect_r(handle, g, xmin, ymin, xmax, ymax); } + Geometry* + GEOSSubdivideByGrid(const Geometry* g, double xmin, double ymin, double xmax, double ymax, + unsigned nx, unsigned ny, int include_exterior) + { + return GEOSSubdivideByGrid_r(handle, g, xmin, ymin, xmax, ymax, nx, ny, include_exterior); + } + + int + GEOSGridIntersectionFractions(const Geometry* g, double xmin, double ymin, double xmax, double ymax, + unsigned nx, unsigned ny, float* buf) + { + return GEOSGridIntersectionFractions_r(handle, g, xmin, ymin, xmax, ymax, nx, ny, buf); + } Geometry* GEOSGeom_transformXY(const GEOSGeometry* g, GEOSTransformXYCallback callback, void* userdata) { diff --git a/capi/geos_c.h.in b/capi/geos_c.h.in index 19b9e115b8..82184e36f6 100644 --- a/capi/geos_c.h.in +++ b/capi/geos_c.h.in @@ -1035,6 +1035,24 @@ extern GEOSGeometry GEOS_DLL *GEOSClipByRect_r( double xmin, double ymin, double xmax, double ymax); +/** \see GEOSSubdivideByGrid */ +extern GEOSGeometry GEOS_DLL *GEOSSubdivideByGrid_r( + GEOSContextHandle_t handle, + const GEOSGeometry* g, + double xmin, double ymin, + double xmax, double ymax, + unsigned nx, unsigned ny, + int include_exterior); + +/** \see GEOSGridIntersectionFractions */ +extern int GEOS_DLL GEOSGridIntersectionFractions_r( + GEOSContextHandle_t handle, + const GEOSGeometry* g, + double xmin, double ymin, + double xmax, double ymax, + unsigned nx, unsigned ny, + float* buf); + /** \see GEOSPolygonize */ extern GEOSGeometry GEOS_DLL *GEOSPolygonize_r( GEOSContextHandle_t handle, @@ -3788,6 +3806,56 @@ extern GEOSGeometry GEOS_DLL *GEOSClipByRect( double xmin, double ymin, double xmax, double ymax); +/** +* Compute the intersection of a geometry with each polygon in +* a rectangular grid. +* \param g The input geometry to be clipped +* \param xmin Left bound of grd +* \param ymin Lower bound of grid +* \param xmax Right bound of grid +* \param ymax Upper bound of grid +* \param nx number of columns in grid +* \param ny number of rows in grid +* \param include_exterior whether to include portions of the + input geometry that do not intersect the grid in + the returned result. +* \return A geometry collection whose components represent the +* intersection with each cell in the grid. +* Caller is responsible for freeing with GEOSGeom_destroy(). +* \see GEOSGetGridIntersectionFractions +* +* \since 3.14.0 +*/ +extern GEOSGeometry GEOS_DLL *GEOSSubdivideByGrid( + const GEOSGeometry* g, + double xmin, double ymin, + double xmax, double ymax, + unsigned nx, unsigned ny, + int include_exterior); + +/** +* Determine the fraction of each cell in a rectangular grid +* that is covered by a polygon. +* \param g The input geometry +* \param xmin Left bound of grd +* \param ymin Lower bound of grid +* \param xmax Right bound of grid +* \param ymax Upper bound of grid +* \param nx number of columns in grid +* \param ny number of rows in grid +* \param buf a buffer of size nx*ny to which the grid cell +* coverage fractions will be written in row-major order +* \return 1 if the operation was successful, 0 on exception +* +* \since 3.14.0 +*/ +extern int GEOS_DLL GEOSGridIntersectionFractions( + const GEOSGeometry* g, + double xmin, double ymin, + double xmax, double ymax, + unsigned nx, unsigned ny, + float* buf); + /** * Find paths shared between the two given lineal geometries. * diff --git a/capi/geos_ts_c.cpp b/capi/geos_ts_c.cpp index ace450b49f..a2d7090021 100644 --- a/capi/geos_ts_c.cpp +++ b/capi/geos_ts_c.cpp @@ -80,6 +80,8 @@ #include #include #include +#include +#include #include #include #include @@ -1725,6 +1727,41 @@ extern "C" { }); } + Geometry* + GEOSSubdivideByGrid_r(GEOSContextHandle_t extHandle, const Geometry* g, double xmin, double ymin, + double xmax, double ymax, unsigned nx, unsigned ny, int include_exterior) + { + return execute(extHandle, [&]() { + Envelope env(xmin, xmax, ymin, ymax); + double dx = env.getWidth() / static_cast(nx); + double dy = env.getHeight() / static_cast(ny); + geos::operation::grid::Grid grid(env, dx, dy); + + return geos::operation::grid::GridIntersection::subdivide_polygon(grid, *g, include_exterior).release(); + }); + } + + int + GEOSGridIntersectionFractions_r(GEOSContextHandle_t extHandle, const Geometry* g, double xmin, double ymin, + double xmax, double ymax, unsigned nx, unsigned ny, float* buf) + { + return execute(extHandle, 0, [&]() { + Envelope env(xmin, xmax, ymin, ymax); + double dx = env.getWidth() / static_cast(nx); + double dy = env.getHeight() / static_cast(ny); + geos::operation::grid::Grid grid(env, dx, dy); + + // Matrix wants a shared_ptr, but we don't actually want anything to be freed because + // buf is externally owned. So we give it an empty deleter. + std::shared_ptr bufPtr(buf, [](float*) {}); + + auto cov = std::make_shared>(ny, nx, bufPtr); + geos::operation::grid::GridIntersection isect(grid, *g, cov); + + return 1; + }); + } + Geometry* GEOSGeom_transformXY_r(GEOSContextHandle_t handle, const GEOSGeometry* g, GEOSTransformXYCallback callback, void* userdata) { diff --git a/include/geos/operation/grid/Cell.h b/include/geos/operation/grid/Cell.h new file mode 100644 index 0000000000..4a44ce9af4 --- /dev/null +++ b/include/geos/operation/grid/Cell.h @@ -0,0 +1,107 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#pragma once + +#include +#include + +#include +#include + +namespace geos::operation::grid { + +/** + * @brief The Cell class stores information about the spatial extent of a `Grid` cell and + * any cases where a line crosses that cell (recorded in a `Traversal`). + */ +class Cell +{ + + public: + Cell(double xmin, double ymin, double xmax, double ymax) + : m_box{ xmin, ymin, xmax, ymax } + { + } + + explicit Cell(const geom::Envelope& b) + : m_box{ b } + { + } + + const geom::Envelope& box() const { return m_box; } + + double width() const; + + double height() const; + + double area() const; + + /// Force the last Coordinate processed (via `take`) to be considered as an + /// exit point, provided that it lies on the boundary of this Cell. + void force_exit(); + + /// Returns whether the cell can be determined to be wholly or partially + /// covered by a polygon. + bool determined() const; + + /// Return the total length of a linear geometry within this Cell + double traversal_length() const; + + /// Return the fraction of this Cell that is covered by a polygon + double covered_fraction() const; + + /// Return a newly constructed geometry representing the portion of this Cell + /// that is covered by a polygon + std::unique_ptr covered_polygons(const geom::GeometryFactory&) const; + + /// Return the last (most recent) traversal to which a coordinate has been + /// added. The traversal may or may not be completed. + Traversal& last_traversal(); + + /** + * Attempt to take a coordinate and add it to a Traversal in progress, or start a new Traversal + * + * @param c Coordinate to process + * @param prev_original The last *uninterpolated* coordinate preceding `c` in the + * boundary being processed + * + * @return `true` if the Coordinate was inside this cell, `false` otherwise + */ + bool take(const geom::CoordinateXY& c, const geom::CoordinateXY* prev_original = nullptr); + + private: + std::vector*> get_coord_lists() const; + + enum class Location + { + INSIDE, + OUTSIDE, + BOUNDARY + }; + + geom::Envelope m_box; + + std::vector m_traversals; + + Side side(const geom::CoordinateXY& c) const; + + Location location(const geom::CoordinateXY& c) const; + + /// If no Traversals have been started or the most recent Traversal has been completed, + /// return a new Traversal. Otherwise, return the most recent Traversal. + Traversal& traversal_in_progress(); +}; + +} diff --git a/include/geos/operation/grid/Crossing.h b/include/geos/operation/grid/Crossing.h new file mode 100644 index 0000000000..c0b8ed2df9 --- /dev/null +++ b/include/geos/operation/grid/Crossing.h @@ -0,0 +1,52 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#pragma once + +#include +#include + +namespace geos::operation::grid { + +class Crossing +{ + public: + Crossing(Side s, double x, double y) + : m_side{ s } + , m_coord{ x, y } + { + } + + Crossing(Side s, const geom::CoordinateXY& c) + : m_side{ s } + , m_coord{ c } + { + } + + const Side& side() const + { + return m_side; + } + + const geom::CoordinateXY& coord() const + { + return m_coord; + } + + private: + Side m_side; + geom::CoordinateXY m_coord; +}; + +} diff --git a/include/geos/operation/grid/FloodFill.h b/include/geos/operation/grid/FloodFill.h new file mode 100644 index 0000000000..6b8476f425 --- /dev/null +++ b/include/geos/operation/grid/FloodFill.h @@ -0,0 +1,144 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#pragma once + +#include +#include + +#include + +namespace geos::geom { + class Geometry; +} + +namespace geos::algorithm::locate { + class PointOnGeometryLocator; +} + +namespace geos::operation::grid { + +template +struct fill_values +{ + static T EXTERIOR; +}; + +template<> +struct fill_values +{ + static constexpr float EXTERIOR{ 0.0f }; // Cell is known to be entirely outside the polygon + static constexpr float INTERIOR{ 1.0f }; // Cell is known to be entirely within the polygon + static constexpr float FILLABLE{ -1.0f }; // Cell location relative to polygon unknown, but + // can be determined by fill. + static constexpr float UNKNOWN{ -2.0f }; // Cell location relative to polygon unknown + // and cannot be determined from a flood fill + // (must be explicitly tested) +}; + +class FloodFill +{ + + public: + FloodFill(const geom::Geometry& g, const Grid& extent); + + ~FloodFill(); + + template + void flood(Matrix& arr) const; + + bool cell_is_inside(size_t i, size_t j) const; + + private: + Grid m_extent; + const geom::Geometry& m_g; + std::unique_ptr m_loc; +}; + +template +void +flood_from_pixel(Matrix& arr, size_t i, size_t j, T fill_value) +{ + std::queue> locations; + + locations.emplace(i, j); + + while (!locations.empty()) { + i = locations.front().first; + j = locations.front().second; + locations.pop(); + + if (arr(i, j) == fill_value) { + continue; + } + + // Left + if (j > 0 && arr(i, j - 1) == fill_values::FILLABLE) { + locations.emplace(i, j - 1); + } + + auto j0 = j; + + // Fill along this row until we hit something + for (; j < arr.cols() && arr(i, j) == fill_values::FILLABLE; j++) { + arr(i, j) = fill_value; + } + + auto j1 = j; + + // Initiate scanlines above our current row + if (i > 0) { + for (j = j0; j < j1; j++) { + // Up + if (arr(i - 1, j) == fill_values::FILLABLE) { + locations.emplace(i - 1, j); + } + } + } + + // Initiate scanlines below our current row + if (i < arr.rows() - 1) { + for (j = j0; j < j1; j++) { + // Down + if (arr(i + 1, j) == fill_values::FILLABLE) { + locations.emplace(i + 1, j); + } + } + } + } +} + +template +void +FloodFill::flood(Matrix& arr) const +{ + + for (size_t i = 0; i < arr.rows(); i++) { + for (size_t j = 0; j < arr.cols(); j++) { + if (arr(i, j) == fill_values::UNKNOWN) { + throw std::runtime_error("Cell with unknown position encountered."); + } else if (arr(i, j) == fill_values::FILLABLE) { + // Cell position relative to polygon is unknown but can + // be determined from adjacent cells. + if (cell_is_inside(i, j)) { + flood_from_pixel(arr, i, j, fill_values::INTERIOR); + } else { + flood_from_pixel(arr, i, j, fill_values::EXTERIOR); + } + } + } + } +} + +} diff --git a/include/geos/operation/grid/Grid.h b/include/geos/operation/grid/Grid.h new file mode 100644 index 0000000000..bb92666792 --- /dev/null +++ b/include/geos/operation/grid/Grid.h @@ -0,0 +1,284 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#pragma once + +#include +#include +#include + +#include + +constexpr double DEFAULT_GRID_COMPAT_TOL = 1e-6; + +namespace geos::operation::grid { +struct infinite_extent +{ + static constexpr size_t padding = 1; +}; + +struct bounded_extent +{ + static constexpr size_t padding = 0; +}; + +template +class Grid +{ + + public: + Grid(const geom::Envelope& extent, double dx, double dy) + : m_extent{ extent } + , m_domain{} + , m_dx{ dx } + , m_dy{ dy } + , m_num_rows{ 2 * extent_tag::padding + (extent.getMaxY() > extent.getMinY() ? static_cast(std::round(extent.getHeight() / dy)) : 0) } + , m_num_cols{ 2 * extent_tag::padding + (extent.getMaxX() > extent.getMinX() ? static_cast(std::round(extent.getWidth() / dx)) : 0) } { + static_assert(std::is_same_v); + } + + Grid(const geom::Envelope& extent, double dx, double dy, const geom::Envelope& domain) + : m_extent{ extent } + , m_domain{ domain } + , m_dx{ dx } + , m_dy{ dy } + , m_num_rows{ 2 * extent_tag::padding + (extent.getMaxY() > extent.getMinY() ? static_cast(std::round(extent.getHeight() / dy)) : 0) } + , m_num_cols{ 2 * extent_tag::padding + (extent.getMaxX() > extent.getMinX() ? static_cast(std::round(extent.getWidth() / dx)) : 0) } + { + static_assert(std::is_same_v); + } + + + static Grid make_empty() + { + if constexpr (std::is_same_v) { + return Grid({ 0, 0, 0, 0 }, 0, 0); + } else { + return Grid({ 0, 0, 0, 0 }, 0, 0, geom::Envelope()); + } + } + + size_t get_column(double x) const + { + if (extent_tag::padding) { + if (x < m_extent.getMinX()) + return 0; + if (x > m_extent.getMaxX()) + return m_num_cols - 1; + if (x == m_extent.getMaxX()) // special case, returning the cell for which xmax is the right + return m_num_cols - 2; + } else { + if (x < m_extent.getMinX() || x > m_extent.getMaxX()) + throw std::out_of_range("x"); + + if (x == m_extent.getMaxX()) + return m_num_cols - 1; + } + + // Since we've already range-checked our x value, make sure that + // the computed column index is no greater than the column index + // associated with xmax. + return std::min( + extent_tag::padding + static_cast(std::floor((x - m_extent.getMinX()) / m_dx)), + get_column(m_extent.getMaxX())); + } + + size_t get_row(double y) const + { + if (extent_tag::padding) { + if (y > m_extent.getMaxY()) + return 0; + if (y < m_extent.getMinY()) + return m_num_rows - 1; + if (y == m_extent.getMinY()) // special case, returning the cell for which ymin is the bottom + return m_num_rows - 2; + } else { + if (y < m_extent.getMinY() || y > m_extent.getMaxY()) + throw std::out_of_range("y"); + + if (y == m_extent.getMinY()) + return m_num_rows - 1; + } + + // Since we've already range-checked our y value, make sure that + // the computed row index is no greater than the column index + // associated with ymin. + return std::min( + extent_tag::padding + static_cast(std::floor((m_extent.getMaxY() - y) / m_dy)), + get_row(m_extent.getMinY())); + } + + std::size_t get_cell(double x, double y) const + { + return get_row(y) * cols() + get_column(x); + } + + bool empty() const { return m_num_rows <= 2 * extent_tag::padding && m_num_cols <= 2 * extent_tag::padding; } + + size_t rows() const { return m_num_rows; } + + size_t cols() const { return m_num_cols; } + + size_t size() const { return rows() * cols(); } + + double xmin() const { return m_extent.getMinX(); } + + double xmax() const { return m_extent.getMaxX(); } + + double ymin() const { return m_extent.getMinY(); } + + double ymax() const { return m_extent.getMaxY(); } + + double dx() const { return m_dx; } + + double dy() const { return m_dy; } + + const geom::Envelope& extent() const { return m_extent; } + + size_t row_offset(const Grid& other) const { return static_cast(std::round(std::abs(other.m_extent.getMaxY() - m_extent.getMaxY()) / m_dy)); } + + size_t col_offset(const Grid& other) const { return static_cast(std::round(std::abs(m_extent.getMinX() - other.m_extent.getMinX()) / m_dx)); } + + double x_for_col(size_t col) const { return m_extent.getMinX() + (static_cast(col - extent_tag::padding) + 0.5) * m_dx; } + + double y_for_row(size_t row) const { return m_extent.getMaxY() - (static_cast(row - extent_tag::padding) + 0.5) * m_dy; } + + Grid shrink_to_fit(const geom::Envelope& b) const + { + if (b.getArea() == 0) { + return make_empty(); + } + + if (b.getMinX() < m_extent.getMinX() || b.getMinY() < m_extent.getMinY() || b.getMaxX() > m_extent.getMaxX() || b.getMaxY() > m_extent.getMaxY()) { + throw std::range_error("Cannot shrink extent to bounds larger than original."); + } + + size_t col0 = get_column(b.getMinX()); + size_t row1 = get_row(b.getMaxY()); + + // Shrink xmin and ymax to fit the upper-left corner of the supplied extent + double snapped_xmin = m_extent.getMinX() + static_cast(col0 - extent_tag::padding) * m_dx; + double snapped_ymax = m_extent.getMaxY() - static_cast(row1 - extent_tag::padding) * m_dy; + + // Make sure x0 and y1 are within the reduced extent. Because of + // floating point round-off errors, this is not always the case. + if (b.getMinX() < snapped_xmin) { + snapped_xmin -= m_dx; + col0--; + } + + if (b.getMaxY() > snapped_ymax) { + snapped_ymax += m_dy; + row1--; + } + + size_t col1 = get_column(b.getMaxX()); + size_t row0 = get_row(b.getMinY()); + + size_t num_rows = 1 + (row0 - row1); + size_t num_cols = 1 + (col1 - col0); + + // If xmax or ymin falls cleanly on a cell boundary, we don't + // need as many rows or columns as we otherwise would, because + // we assume that the rightmost cell of the grid is a closed + // interval in x, and the lowermost cell of the grid is a + // closed interval in y. + if (num_rows > 2 && (snapped_ymax - static_cast(num_rows - 1) * m_dy <= b.getMinY())) { + num_rows--; + } + if (num_cols > 2 && (snapped_xmin + static_cast(num_cols - 1) * m_dx >= b.getMaxX())) { + num_cols--; + } + + // Perform offsets relative to the new xmin, ymax origin + // points. If this is not done, then floating point roundoff + // error can cause progressive shrink() calls with the same + // inputs to produce different results. + geom::Envelope reduced_box = { + snapped_xmin, + std::max(snapped_xmin + static_cast(num_cols) * m_dx, b.getMaxX()), + std::min(snapped_ymax - static_cast(num_rows) * m_dy, b.getMinY()), + snapped_ymax + }; + + // Fudge computed xmax and ymin, if needed, to prevent extent + // from growing during a shrink operation. + if (reduced_box.getMaxX() > m_extent.getMaxX()) { + if (std::round(reduced_box.getWidth() / m_dx) == + std::round((m_extent.getMaxX() - reduced_box.getMinX()) / m_dx)) { + reduced_box = geom::Envelope(reduced_box.getMinX(), m_extent.getMaxX(), reduced_box.getMinY(), reduced_box.getMaxY()); + } else { + throw std::runtime_error("Shrink operation failed."); + } + } + if (reduced_box.getMinY() < m_extent.getMinY()) { + if (std::round(reduced_box.getHeight() / m_dy) == + std::round((reduced_box.getMaxY() - m_extent.getMinY()) / m_dy)) { + reduced_box = geom::Envelope(reduced_box.getMinX(), reduced_box.getMaxX(), m_extent.getMinY(), reduced_box.getMaxY()); + } else { + throw std::runtime_error("Shrink operation failed."); + } + } + + if constexpr (std::is_same_v) { + Grid reduced{ reduced_box, m_dx, m_dy }; + + if (b.getMinX() < reduced.xmin() || b.getMinY() < reduced.ymin() || b.getMaxX() > reduced.xmax() || b.getMaxY() > reduced.ymax()) { + throw std::runtime_error("Shrink operation failed."); + } + + return reduced; + } else { + Grid reduced{ reduced_box, m_dx, m_dy , m_domain }; + + if (b.getMinX() < reduced.xmin() || b.getMinY() < reduced.ymin() || b.getMaxX() > reduced.xmax() || b.getMaxY() > reduced.ymax()) { + throw std::runtime_error("Shrink operation failed."); + } + + return reduced; + + } + } + + bool operator==(const Grid& b) const + { + return m_extent == b.m_extent && + m_dx == b.m_dx && + m_dy == b.m_dy; + } + + bool operator!=(const Grid& b) const + { + return !(*this == b); + } + + geom::Envelope grid_cell(size_t row, size_t col) const; + + private: + geom::Envelope m_extent; + geom::Envelope m_domain; + + double m_dx; + double m_dy; + + size_t m_num_rows; + size_t m_num_cols; +}; + +Grid +make_infinite(const Grid& grid, const geom::Envelope& domain); +Grid +make_finite(const Grid& grid); + +} diff --git a/include/geos/operation/grid/GridIntersection.h b/include/geos/operation/grid/GridIntersection.h new file mode 100644 index 0000000000..5e939b1966 --- /dev/null +++ b/include/geos/operation/grid/GridIntersection.h @@ -0,0 +1,106 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#pragma once + +#include + +#include +#include +#include + +namespace geos::geom { + class Geometry; + class LineString; +} + +namespace geos::operation::grid { + +class Cell; + +/** + * @brief The GridIntersection class computes and stores information about intersection of a Grid and a Geometry. + * For a polygonal geometry, the fraction of each grid cell covered by polygon is stored. + * For a linear geometry, the length of the line in each grid cell is stored. + * + * Intersection information returned as `Raster` with an equivalent resolution to the input `Grid`. The spatial + * extent may be reduced from the input `Grid.` + */ +class GEOS_DLL GridIntersection +{ + + public: + /** + * @brief Compute the fraction of each cell in a rectangular grid that is covered by a Geometry. + * A matrix can be provided to which the fractions will be added. + */ + GridIntersection(const Grid& raster_grid, const geom::Geometry& g, std::shared_ptr> cov = nullptr); + + /** + * @brief Compute the fraction of each cell in a rectangular grid that is covered by an Envelope. + * A matrix can be provided to which the fractions will be added. + */ + GridIntersection(const Grid& raster_grid, const geom::Envelope& box, std::shared_ptr> cov = nullptr); + + /** + * @brief Return the intersection result matrix + */ + std::shared_ptr> results() { return m_results; } + + /** + * @brief Partition a polygonal geometry by a grid + */ + static std::unique_ptr subdivide_polygon(const Grid& p_grid, const geom::Geometry& g, bool includeExterior); + + static std::shared_ptr> + grid_intersection(const Grid& raster_grid, const geom::Geometry& g); + + static std::shared_ptr> + grid_intersection(const Grid& raster_grid, const geom::Envelope& box); + + /** + * @brief Determines the bounding box of the raster-vector intersection. Considers the bounding boxes + * of individual polygon components separately to avoid unnecessary computation for sparse + * multi-polygons. + * + * @param raster_extent Envelope representing the extent of the vector + * @param geometry Geometry to be processed + * + * @return the portion of `raster_extent` that intersects one or more `component_boxes` + */ + static geom::Envelope + processing_region(const geom::Envelope& raster_extent, const geom::Geometry& geometry); + + private: + void process(const geom::Geometry& g); + + void process_line(const geom::LineString& ls, bool exterior_ring); + + void process_rectangular_ring(const geom::Envelope& box, bool exterior_ring); + + void add_ring_results(size_t i0, size_t j0, const Matrix& areas, bool exterior_ring); + + void set_areal(bool areal); + + static Matrix collect_areas(const Matrix>& cells, + const Grid& finite_ring_grid, + const geom::Geometry& g); + + Grid m_geometry_grid; + std::shared_ptr> m_results; + bool m_first_geom; + bool m_areal; +}; + +} diff --git a/include/geos/operation/grid/Matrix.h b/include/geos/operation/grid/Matrix.h new file mode 100644 index 0000000000..6352c06631 --- /dev/null +++ b/include/geos/operation/grid/Matrix.h @@ -0,0 +1,177 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include + +namespace geos::operation::grid { + +template +class Matrix +{ + + public: + using value_type = T; + + Matrix(size_t rows, size_t cols, std::shared_ptr data) + : m_data{ data } + , m_rows{ rows } + , m_cols{ cols } + {} + + Matrix(size_t rows, size_t cols) + : m_rows{ rows } + , m_cols{ cols } + { + if (m_rows > 0 && m_cols > 0) { + // new T[]() initializes to zero + m_data = std::shared_ptr(new T[m_rows * m_cols]()); + } + } + + Matrix(size_t rows, size_t cols, T value) + : m_rows{ rows } + , m_cols{ cols } + { + if (m_rows > 0 && m_cols > 0) { + // new T[] does not initialize + m_data = std::shared_ptr(new T[m_rows * m_cols]); + } + + std::fill(m_data.get(), m_data.get() + m_rows * m_cols, value); + } + + explicit Matrix(const std::vector>& data) + : m_rows{ data.size() } + , m_cols{ data[0].size() } + { + m_data = std::shared_ptr(new T[m_rows * m_cols]()); + + auto lastpos = m_data.get(); + for (auto& row : data) { + lastpos = std::copy(row.begin(), row.end(), lastpos); + } + } + + Matrix(Matrix&& m) noexcept + : m_rows{ m.rows() } + , m_cols{ m.cols() } + { + m_data = std::move(m.m_data); + } + + T& operator()(size_t row, size_t col) + { + check(row, col); + return m_data.get()[row * m_cols + col]; + } + + const T& operator()(size_t row, size_t col) const + { + check(row, col); + return m_data.get()[row * m_cols + col]; + } + + bool operator!=(const Matrix& other) const { + return !(*this == other); + } + + bool operator==(const Matrix& other) const + { + if (m_rows != other.m_rows) { + return false; + } + if (m_cols != other.m_cols) { + return false; + } + + return 0 == memcmp(m_data.get(), other.m_data.get(), m_rows * m_cols * sizeof(T)); + } + + void increment(size_t row, size_t col, const T& val) + { + check(row, col); + m_data.get()[row * m_cols + col] += val; + } + + size_t rows() const { return m_rows; } + size_t cols() const { return m_cols; } + + T* row(size_t row) + { + return &(m_data[row * m_cols]); + } + + T* data() + { + return m_data.get(); + } + + const T* data() const + { + return m_data.get(); + } + + T* release() + { + return m_data.release(); + } + +#ifdef MATRIX_CHECK_BOUNDS + void check(size_t row, size_t col) const + { + if (row + 1 > m_rows) { + throw std::out_of_range("Row " + std::to_string(row) + " is out of range."); + } + if (col + 1 > m_cols) { + throw std::out_of_range("Col " + std::to_string(col) + " is out of range."); + } + } +#else + void check(size_t, size_t) const + { + } +#endif + + private: + std::shared_ptr m_data; + + size_t m_rows; + size_t m_cols; +}; + +template +std::ostream& +operator<<(std::ostream& os, const Matrix& m) +{ + for (size_t i = 0; i < m.rows(); i++) { + for (size_t j = 0; j < m.cols(); j++) { + if (m(i, j) != 0) { + os << std::right << std::fixed << std::setw(10) << std::setprecision(6) << m(i, j) << " "; + } else { + os << " "; + } + } + os << std::endl; + } + + return os; +} + +} diff --git a/include/geos/operation/grid/PerimeterDistance.h b/include/geos/operation/grid/PerimeterDistance.h new file mode 100644 index 0000000000..8325b836c8 --- /dev/null +++ b/include/geos/operation/grid/PerimeterDistance.h @@ -0,0 +1,42 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#pragma once + +namespace geos::geom { + class CoordinateXY; + class Envelope; +} + +namespace geos::operation::grid { + +/** Calculates the clockwise distance along the edge of an Envelope + * from the lower left corner of the Envelope to a supplied Coordinate + * lying exactly on the boundary of the Envelope. + */ +double +perimeter_distance(const geom::Envelope& env, const geom::CoordinateXY& c); + +double +perimeter_distance(double xmin, double ymin, double xmax, double ymax, double x, double y); + +/** Calculates the counter-clockwise distance between two locations on the perimeter + * of an Envelope. The locations are specified as clockwise distances from the + * lower left corner of the Envelope, consistent with the `perimeter_distance` + * function. + */ +double +perimeter_distance_ccw(double measure1, double measure2, double perimeter); + +} diff --git a/include/geos/operation/grid/Side.h b/include/geos/operation/grid/Side.h new file mode 100644 index 0000000000..b9015f7a14 --- /dev/null +++ b/include/geos/operation/grid/Side.h @@ -0,0 +1,33 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#pragma once + +#include + +namespace geos::operation::grid { + +enum class Side +{ + NONE, + LEFT, + RIGHT, + TOP, + BOTTOM +}; + +std::ostream& +operator<<(std::ostream& os, const Side& s); + +} diff --git a/include/geos/operation/grid/Traversal.h b/include/geos/operation/grid/Traversal.h new file mode 100644 index 0000000000..f80100956a --- /dev/null +++ b/include/geos/operation/grid/Traversal.h @@ -0,0 +1,76 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#pragma once + +#include + +#include +#include + +namespace geos::operation::grid { + +/** + * @brief The Traversal class records the coordinates of a line that are + * within a grid cell, as well as the `Side` from which the line + * entered and exited the cell. + */ +class Traversal +{ + public: + Traversal() + : m_entry{ Side::NONE } + , m_exit{ Side::NONE } + { + } + + bool is_closed_ring() const; + + bool empty() const; + + bool entered() const; + + bool exited() const; + + bool traversed() const; + + bool multiple_unique_coordinates() const; + + /// Begin a Traversal on the specified `Side` + void enter(const geom::CoordinateXY& c, Side s); + + /// Complete a Traversal on the specified `Side` + void exit(const geom::CoordinateXY& c, Side s); + + Side entry_side() const { return m_entry; } + + Side exit_side() const { return m_exit; } + + const geom::CoordinateXY& last_coordinate() const; + + const geom::CoordinateXY& exit_coordinate() const; + + void add(const geom::CoordinateXY& c); + + void force_exit(Side s) { m_exit = s; } + + const std::vector& coords() const { return m_coords; } + + private: + std::vector m_coords; + Side m_entry; + Side m_exit; +}; + +} diff --git a/include/geos/operation/grid/TraversalAreas.h b/include/geos/operation/grid/TraversalAreas.h new file mode 100644 index 0000000000..b77e5aa2b1 --- /dev/null +++ b/include/geos/operation/grid/TraversalAreas.h @@ -0,0 +1,48 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#pragma once + +#include + +namespace geos::operation::grid { + +/** + * @brief Return the total area of counter-clockwise closed rings formed by this box and the provided Coordinate sequences + * + * @param box boundary of the area to consider (Cell) + * @param coord_lists vector of Coordinate vectors representing points that traverse `box`. Either the first and + * last coordinate of each vector must lie on the boundary of `box`, or the coordinates + * must form a closed ring that does not intersect the boundary of `box.` Clockwise-oriented + * closed rings will be considered holes. + * @return total area + */ +double +left_hand_area(const geom::Envelope& box, const std::vector*>& coord_lists); + +/** + * @brief Return an areal geometry representing the closed rings formed by this box and the provided Coordinate sequences + * + * @param gfact GeometryFactory to create result geometry + * @param box boundary of the area to consider (Cell) + * @param coord_lists vector of Coordinate vectors representing points that traverse `box`. Either the first and + * last coordinate of each vector must lie on the boundary of `box`, or the coordinates + * must form a closed ring that does not intersect the boundary of `box.` Clockwise-oriented + * closed rings will be considered holes. + * @return a Polygon or MultiPolygon geometry + */ +std::unique_ptr +left_hand_rings(const geom::GeometryFactory& gfact, const geom::Envelope& box, const std::vector*>& coord_lists); + +} diff --git a/src/operation/grid/Cell.cpp b/src/operation/grid/Cell.cpp new file mode 100644 index 0000000000..7e6a01bd5b --- /dev/null +++ b/src/operation/grid/Cell.cpp @@ -0,0 +1,279 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#include + +#include +#include +#include +#include + +using geos::geom::CoordinateXY; +using geos::geom::Geometry; +using geos::geom::GeometryFactory; + +namespace geos::operation::grid { + +static bool +strictly_contains(const geom::Envelope& e, const geom::CoordinateXY& c) { + return e.getMinX() < c.x && e.getMaxX() > c.x && e.getMinY() < c.y && e.getMaxY() > c.y; +} + +static Crossing +crossing(const geom::Envelope& e, const CoordinateXY& c1, const CoordinateXY& c2) +{ + // vertical line + if (c1.x == c2.x) { + if (c2.y >= e.getMaxY()) { + return Crossing{ Side::TOP, c1.x, e.getMaxY() }; + } else if (c2.y <= e.getMinY()) { + return Crossing{ Side::BOTTOM, c1.x, e.getMinY() }; + } else { + throw std::runtime_error("Never get here."); + } + } + + // horizontal line + if (c1.y == c2.y) { + if (c2.x >= e.getMaxX()) { + return Crossing{ Side::RIGHT, e.getMaxX(), c1.y }; + } else if (c2.x <= e.getMinX()) { + return Crossing{ Side::LEFT, e.getMinX(), c1.y }; + } else { + throw std::runtime_error("Never get here"); + } + } + + double m = std::abs((c2.y - c1.y) / (c2.x - c1.x)); + + bool up = c2.y > c1.y; + bool right = c2.x > c1.x; + + if (up) { + if (right) { + // 1st quadrant + double y2 = c1.y + m * (e.getMaxX() - c1.x); + + if (y2 < e.getMaxY()) { + return Crossing{ Side::RIGHT, e.getMaxX(), std::clamp(y2, e.getMinY(), e.getMaxY()) }; + } else { + double x2 = c1.x + (e.getMaxY() - c1.y) / m; + return Crossing{ Side::TOP, std::clamp(x2, e.getMinX(), e.getMaxX()), e.getMaxY() }; + } + } else { + // 2nd quadrant + double y2 = c1.y + m * (c1.x - e.getMinX()); + + if (y2 < e.getMaxY()) { + return Crossing{ Side::LEFT, e.getMinX(), std::clamp(y2, e.getMinY(), e.getMaxY()) }; + } else { + double x2 = c1.x - (e.getMaxY() - c1.y) / m; + return Crossing{ Side::TOP, std::clamp(x2, e.getMinX(), e.getMaxX()), e.getMaxY() }; + } + } + } else { + if (right) { + // 4th quadrant + double y2 = c1.y - m * (e.getMaxX() - c1.x); + + if (y2 > e.getMinY()) { + return Crossing{ Side::RIGHT, e.getMaxX(), std::clamp(y2, e.getMinY(), e.getMaxY()) }; + } else { + double x2 = c1.x + (c1.y - e.getMinY()) / m; + return Crossing{ Side::BOTTOM, std::clamp(x2, e.getMinX(), e.getMaxX()), e.getMinY() }; + } + } else { + // 3rd quadrant + double y2 = c1.y - m * (c1.x - e.getMinX()); + + if (y2 > e.getMinY()) { + return Crossing{ Side::LEFT, e.getMinX(), std::clamp(y2, e.getMinY(), e.getMaxY()) }; + } else { + double x2 = c1.x - (c1.y - e.getMinY()) / m; + return Crossing{ Side::BOTTOM, std::clamp(x2, e.getMinX(), e.getMaxX()), e.getMinY() }; + } + } + } +} + + +double +Cell::height() const +{ + return m_box.getHeight(); +} + +double +Cell::width() const +{ + return m_box.getWidth(); +} + +double +Cell::area() const +{ + return m_box.getArea(); +} + +Side +Cell::side(const CoordinateXY& c) const +{ + if (c.x == m_box.getMinX()) { + return Side::LEFT; + } else if (c.x == m_box.getMaxX()) { + return Side::RIGHT; + } else if (c.y == m_box.getMinY()) { + return Side::BOTTOM; + } else if (c.y == m_box.getMaxY()) { + return Side::TOP; + } + + return Side::NONE; +} + +void +Cell::force_exit() +{ + if (last_traversal().exited()) { + return; + } + + const CoordinateXY& last = last_traversal().last_coordinate(); + + if (location(last) == Location::BOUNDARY) { + last_traversal().force_exit(side(last)); + } +} + +Cell::Location +Cell::location(const CoordinateXY& c) const +{ + if (strictly_contains(m_box, c)) { + return Cell::Location::INSIDE; + } + + if (m_box.contains(c)) { + return Cell::Location::BOUNDARY; + } + + return Cell::Location::OUTSIDE; +} + +Traversal& +Cell::traversal_in_progress() +{ + if (m_traversals.empty() || m_traversals.back().exited() || m_traversals.back().is_closed_ring()) { + m_traversals.emplace_back(); + } + + return m_traversals[m_traversals.size() - 1]; +} + +Traversal& +Cell::last_traversal() +{ + return m_traversals.at(m_traversals.size() - 1); +} + +bool +Cell::take(const CoordinateXY& c, const CoordinateXY* prev_original) +{ + Traversal& t = traversal_in_progress(); + + if (t.empty()) { + // std::cout << "Entering " << m_box << " from " << side(c) << " at " << c << std::endl; + + t.enter(c, side(c)); + return true; + } + + if (location(c) != Cell::Location::OUTSIDE) { + // std::cout << "Still in " << m_box << " with " << c << std::endl; + + t.add(c); + + if (t.is_closed_ring()) { + t.force_exit(Side::NONE); + } + + return true; + } + + // We need to calculate the coordinate of the cell exit point using only uninterpolated coordinates. + // (The previous point in the traversal may be an interpolated coordinate.) If an interpolated coordinate + // is used, it can cause an error in the relative position two traversals, inverting the fraction of + // the cell that is considered covered. (See robustness regression test #7). + Crossing x = prev_original ? crossing(m_box, *prev_original, c) : crossing(m_box, t.last_coordinate(), c); + t.exit(x.coord(), x.side()); + + // std::cout << "Leaving " << m_box << " from " << x.side() << " at " << x.coord(); + // std::cout << " on the way to " << c << std::endl; + + return false; +} + +double +Cell::traversal_length() const +{ + return std::accumulate(m_traversals.begin(), m_traversals.end(), 0.0, [](double tot, const Traversal& t) { + return tot + algorithm::Length::ofLine(t.coords()); + }); +} + +bool +Cell::determined() const +{ + for (const auto& t : m_traversals) { + if (!t.traversed() && !t.is_closed_ring()) { + continue; + } + + if (t.multiple_unique_coordinates()) { + return true; + } + } + + return false; +} + +std::vector*> +Cell::get_coord_lists() const +{ + std::vector*> coord_lists; + coord_lists.reserve(m_traversals.size()); + + for (const auto& t : m_traversals) { + if (t.traversed() || t.is_closed_ring()) { + coord_lists.push_back(&t.coords()); + } + } + + return coord_lists; +} + +double +Cell::covered_fraction() const +{ + auto coord_lists = get_coord_lists(); + return left_hand_area(m_box, coord_lists) / area(); +} + +std::unique_ptr +Cell::covered_polygons(const GeometryFactory& gfact) const +{ + auto coord_lists = get_coord_lists(); + return left_hand_rings(gfact, m_box, coord_lists); +} + +} diff --git a/src/operation/grid/FloodFill.cpp b/src/operation/grid/FloodFill.cpp new file mode 100644 index 0000000000..33939df8c0 --- /dev/null +++ b/src/operation/grid/FloodFill.cpp @@ -0,0 +1,42 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#include +#include +#include +#include + +using geos::geom::Geometry; + +namespace geos::operation::grid { + +FloodFill::FloodFill(const Geometry& g, const Grid& extent) + : m_extent{ extent } + , m_g{ g } + , m_loc{ nullptr } +{ + m_loc = std::make_unique(m_g); +} + +FloodFill::~FloodFill() = default; + +bool +FloodFill::cell_is_inside(size_t i, size_t j) const +{ + geom::CoordinateXY p( m_extent.x_for_col(j), m_extent.y_for_row(i) ); + + return m_loc->locate(&p) == geom::Location::INTERIOR; +} + +} diff --git a/src/operation/grid/Grid.cpp b/src/operation/grid/Grid.cpp new file mode 100644 index 0000000000..dcd462df41 --- /dev/null +++ b/src/operation/grid/Grid.cpp @@ -0,0 +1,99 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#include + +using geos::geom::Envelope; + +namespace geos::operation::grid { + +template<> +Envelope +Grid::grid_cell(size_t row, size_t col) const +{ + // The ternary clauses below are used to make sure that the cells along + // the right and bottom edges of our grid are slightly larger than m_dx,dy + // if needed to make sure that we capture our whole extent. This is necessary + // because xmin + nx*m_dx may be less than xmax because of floating point + // errors. + return { + xmin() + static_cast(col) * dx(), + row == (rows() - 1) ? ymin() : (ymax() - static_cast(row + 1) * dy()), + col == (cols() - 1) ? xmax() : (xmin() + static_cast(col + 1) * dx()), + ymax() - static_cast(row) * dy() + }; +} + +template<> +Envelope +Grid::grid_cell(size_t row, size_t col) const +{ + double cell_xmin, cell_xmax, cell_ymin, cell_ymax; + + constexpr double PADDED_CELL_SIZE = 1.0; + + if (col == 0) { + cell_xmin = std::min(xmin() - PADDED_CELL_SIZE, m_domain.getMinX()); + } else if (col == cols() - 1) { + cell_xmin = xmax(); // because rightmost col of regular may have different width from others + } else { + cell_xmin = xmin() + static_cast(col - 1) * dx(); + } + + switch (cols() - col) { + case 1: + cell_xmax = std::max(xmax() + PADDED_CELL_SIZE, m_domain.getMaxX()); + break; + case 2: + cell_xmax = xmax(); + break; + default: + cell_xmax = xmin() + static_cast(col) * dx(); + } + + if (row == 0) { + cell_ymax = std::max(xmax() + PADDED_CELL_SIZE, m_domain.getMaxX()); + } else if (row == rows() - 1) { + cell_ymax = ymin(); // because bottom row of regular may have different height from others + } else { + cell_ymax = ymax() - static_cast(row - 1) * dy(); + } + + switch (rows() - row) { + case 1: + cell_ymin = std::min(xmin() - PADDED_CELL_SIZE, m_domain.getMinY()); + break; + case 2: + cell_ymin = ymin(); + break; + default: + cell_ymin = ymax() - static_cast(row) * dy(); + } + + return { cell_xmin, cell_xmax, cell_ymin, cell_ymax }; +} + +Grid +make_infinite(const Grid& grid, const Envelope& domain) +{ + return { grid.extent(), grid.dx(), grid.dy() , domain }; +} + +Grid +make_finite(const Grid& grid) +{ + return { grid.extent(), grid.dx(), grid.dy() }; +} + +} diff --git a/src/operation/grid/GridIntersection.cpp b/src/operation/grid/GridIntersection.cpp new file mode 100644 index 0000000000..7ff3b771df --- /dev/null +++ b/src/operation/grid/GridIntersection.cpp @@ -0,0 +1,540 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "geos/operation/overlayng/CoverageUnion.h" + +using geos::geom::Geometry; +using geos::geom::LineString; +using geos::geom::Polygon; +using geos::geom::Envelope; +using geos::geom::CoordinateXY; + +namespace geos::operation::grid { + +std::shared_ptr> +GridIntersection::grid_intersection(const Grid& raster_grid, const Geometry& g) +{ + GridIntersection rci(raster_grid, g); + return rci.results(); +} + +std::shared_ptr> +GridIntersection::grid_intersection(const Grid& raster_grid, const Envelope& box) +{ + GridIntersection rci(raster_grid, box); + return rci.results(); +} + +static Cell* +get_cell(Matrix>& cells, const Grid& ex, size_t row, size_t col) +{ + if (cells(row, col) == nullptr) { + cells(row, col) = std::make_unique(ex.grid_cell(row, col)); + } + + return cells(row, col).get(); +} + +Envelope +GridIntersection::processing_region(const Envelope& raster_extent, const Geometry& g) +{ + Envelope ret; + + auto ngeoms = g.getNumGeometries(); + for (size_t i = 0; i < ngeoms; i++) { + if (ret == raster_extent) { + // No more expansion is possible + return ret; + } + + const Envelope& box = *g.getGeometryN(i)->getEnvelopeInternal(); + + Envelope isect = raster_extent.intersection(box); + if (ret.isNull()) { + ret = isect; + } else if (!ret.contains(isect)) { + ret.expandToInclude(isect); + } + } + + return ret; +} + +GridIntersection::GridIntersection(const Grid& raster_grid, const Geometry& g, std::shared_ptr> cov) + : m_geometry_grid{ make_infinite(raster_grid, *g.getEnvelopeInternal()) } + , m_results{ cov ? cov : std::make_shared>(raster_grid.rows(), raster_grid.cols()) } + , m_first_geom{ true } + , m_areal{ false } +{ + if (g.getDimension() == 0) { + throw std::invalid_argument("Unsupported geometry type."); + } + + if (!m_geometry_grid.empty()) { + process(g); + } +} + +GridIntersection::GridIntersection(const Grid& raster_grid, const Envelope& box, std::shared_ptr> cov) + : m_geometry_grid{ make_infinite(raster_grid, box) } + , m_results{ cov ? cov : std::make_shared>(raster_grid.rows(), raster_grid.cols()) } +{ + if (!m_geometry_grid.empty()) { + process_rectangular_ring(box, true); + } +} + +void +GridIntersection::process(const Geometry& g) +{ + auto type = g.getGeometryTypeId(); + + if (type == geom::GEOS_POLYGON) { + set_areal(true); + + const Polygon& p = static_cast(g); + + process_line(*p.getExteriorRing(), true); + auto nrings = p.getNumInteriorRing(); + for (std::size_t i = 0; i < nrings; i++) { + process_line(*p.getInteriorRingN(i), false); + } + } else if (type == geom::GEOS_LINESTRING || type == geom::GEOS_LINEARRING) { + set_areal(false); + + process_line(static_cast(g), true); + } else if (type == geom::GEOS_GEOMETRYCOLLECTION || type == geom::GEOS_MULTILINESTRING || type == geom::GEOS_MULTIPOLYGON) { + auto ngeoms = g.getNumGeometries(); + for (std::size_t i = 0; i < ngeoms; i++) { + process(*g.getGeometryN(i)); + } + } else { + throw std::invalid_argument("Unsupported geometry type."); + } +} + +static Grid +get_box_grid(const Envelope& box, const Grid& geometry_grid) +{ + Envelope cropped_ring_extent = geometry_grid.extent().intersection(box); + return geometry_grid.shrink_to_fit(cropped_ring_extent); +} + +static Grid +get_ring_grid(const Geometry& ls, const Grid& geometry_grid) +{ + return get_box_grid(*ls.getEnvelopeInternal(), geometry_grid); +} + +void +GridIntersection::process_rectangular_ring(const Envelope& box, bool exterior_ring) +{ + if (!box.intersects(m_geometry_grid.extent())) { + return; + } + + auto ring_grid = get_box_grid(box, m_geometry_grid); + + auto row_min = ring_grid.get_row(box.getMaxY()); + auto row_max = ring_grid.get_row(box.getMinY()); + auto col_min = ring_grid.get_column(box.getMinX()); + auto col_max = ring_grid.get_column(box.getMaxX()); + + Matrix areas(ring_grid.rows() - 2, ring_grid.cols() - 2); + + // upper-left + if (row_min > 0 && col_min > 0) { + auto ul = ring_grid.grid_cell(row_min, col_min); + areas(row_min - 1, col_min - 1) = static_cast(ul.intersection(box).getArea() / ul.getArea()); + } + + // upper-right + if (row_min > 0 && col_max < ring_grid.cols() - 1) { + auto ur = ring_grid.grid_cell( row_min, col_max); + auto frac = ur.intersection(box).getArea() / ur.getArea(); + areas(row_min - 1, col_max - 1) = static_cast(frac); + } + + // lower-left + if (row_max < ring_grid.rows() - 1 && col_min > 0) { + auto ll = ring_grid.grid_cell(row_max, col_min); + areas(row_max - 1, col_min - 1) = static_cast(ll.intersection(box).getArea() / ll.getArea()); + } + + // lower-right + if (row_max < ring_grid.rows() - 1 && col_max < ring_grid.cols() - 1) { + auto lr = ring_grid.grid_cell(row_max, col_max); + areas(row_max - 1, col_max - 1) = static_cast(lr.intersection(box).getArea() / lr.getArea()); + } + + // left + if (col_min > 0) { + auto left = ring_grid.grid_cell(row_min + 1, col_min); + auto frac = left.intersection(box).getArea() / left.getArea(); + for (size_t row = row_min + 1; row < row_max; row++) { + areas(row - 1, col_min - 1) = static_cast(frac); + } + } + + // right + if (col_max < ring_grid.cols() - 1) { + auto right = ring_grid.grid_cell(row_min + 1, col_max); + auto frac = right.intersection(box).getArea() / right.getArea(); + for (size_t row = row_min + 1; row < row_max; row++) { + areas(row - 1, col_max - 1) = static_cast(frac); + } + } + + // top + if (row_min > 0) { + auto top = ring_grid.grid_cell(row_min, col_min + 1); + auto frac = top.intersection(box).getArea() / top.getArea(); + for (size_t col = col_min + 1; col < col_max; col++) { + areas(row_min - 1, col - 1) = static_cast(frac); + } + } + + // bottom + if (row_max < ring_grid.rows() - 1) { + auto bottom = ring_grid.grid_cell(row_max, col_min + 1); + auto frac = bottom.intersection(box).getArea() / bottom.getArea(); + for (size_t col = col_min + 1; col < col_max; col++) { + areas(row_max - 1, col - 1) = static_cast(frac); + } + } + + // interior + for (size_t row = row_min + 1; row < row_max; row++) { + for (size_t col = col_min + 1; col < col_max; col++) { + areas(row - 1, col - 1) = 1.0f; + } + } + + // Transfer these areas to our global set + size_t i0 = ring_grid.row_offset(m_geometry_grid); + size_t j0 = ring_grid.col_offset(m_geometry_grid); + + add_ring_results(i0, j0, areas, exterior_ring); +} + +void +GridIntersection::set_areal(bool areal) +{ + if (m_first_geom) { + m_first_geom = false; + m_areal = areal; + } else { + if (m_areal != areal) { + throw std::runtime_error("Mixed-type geometries not supported."); + } + } +} + +Matrix +GridIntersection::collect_areas(const Matrix>& cells, + const Grid& finite_ring_grid, + const Geometry& g) +{ + + // Create a matrix of areas using the FILLABLE placeholder value, which means that + // a known state (interior/exterior) can be propated from an adjacent cell. + Matrix areas(cells.rows() - 2, + cells.cols() - 2, + fill_values::FILLABLE); + + FloodFill ff(g, finite_ring_grid); + + // Mark all cells that have been traversed as being either INTERIOR or EXTERIOR. + for (size_t i = 1; i <= areas.rows(); i++) { + for (size_t j = 1; j <= areas.cols(); j++) { + if (cells(i, j) != nullptr) { + // When we encounter a cell that has been processed (ie, it is not nullptr) + // but whose traversals contains no linear segments, we have no way to know + // if it is inside of the polygon. So we perform point-in-polygon test and set + // the covered fraction to 1.0 if needed. + + if (!cells(i, j)->determined()) { + areas(i - 1, j - 1) = ff.cell_is_inside(i - 1, j - 1) ? fill_values::INTERIOR : fill_values::EXTERIOR; + } else { + areas(i - 1, j - 1) = static_cast(cells(i, j)->covered_fraction()); + } + } + } + } + + // Propagate INTERIOR and EXTERIOR values to all remaining FILLABLE cells + ff.flood(areas); + + return areas; +} + +Matrix +collect_lengths(const Matrix>& cells) +{ + Matrix lengths(cells.rows() - 2, + cells.cols() - 2, + fill_values::EXTERIOR); + + for (size_t i = 1; i <= lengths.rows(); i++) { + for (size_t j = 1; j <= lengths.cols(); j++) { + if (cells(i, j) != nullptr) { + lengths(i - 1, j - 1) = static_cast(cells(i, j)->traversal_length()); + } + } + } + + return lengths; +} + +void +traverse_cells(Matrix>& cells, std::vector& coords, const Grid& ring_grid, bool areal) +{ + size_t pos = 0; + size_t row = ring_grid.get_row(coords.front().y); + size_t col = ring_grid.get_column(coords.front().x); + const CoordinateXY* last_exit = nullptr; + + while (pos < coords.size()) { + Cell& cell = *get_cell(cells, ring_grid, row, col); + + while (pos < coords.size()) { + const CoordinateXY* next_coord = last_exit ? last_exit : &coords[pos]; + const CoordinateXY* prev_coord = pos > 0 ? &coords[pos - 1] : nullptr; + + cell.take(*next_coord, prev_coord); + + if (cell.last_traversal().exited()) { + // Only push our exit coordinate if it's not same as the + // coordinate we just took. This covers the case where + // the next coordinate in the stack falls exactly on + // the cell boundary. + const CoordinateXY& exc = cell.last_traversal().exit_coordinate(); + if (exc != *next_coord) { + last_exit = &exc; + } + break; + } else { + if (last_exit) { + last_exit = nullptr; + } else { + pos++; + } + } + } + + cell.force_exit(); + + if (cell.last_traversal().exited()) { + // When we start in the middle of a cell, for a polygon (areal) calculation, + // we need to save the coordinates from our incomplete traversal and reprocess + // them at the end of the line. The effect is just to restructure the polygon + // so that the start/end coordinate falls on a cell boundary. + if (areal && !cell.last_traversal().traversed()) { + for (const auto& coord : cell.last_traversal().coords()) { + coords.push_back(coord); + } + } + + switch (cell.last_traversal().exit_side()) { + case Side::TOP: + row--; + break; + case Side::BOTTOM: + row++; + break; + case Side::LEFT: + col--; + break; + case Side::RIGHT: + col++; + break; + default: + throw std::runtime_error("Invalid traversal"); + } + } + } +} + +void +GridIntersection::process_line(const LineString& ls, bool exterior_ring) +{ + const Envelope& geom_box = *ls.getEnvelopeInternal(); + + const Envelope intersection = geom_box.intersection(m_geometry_grid.extent()); + if (intersection.getArea() == 0) { + return; + } + + const geom::CoordinateSequence& coords = *ls.getCoordinatesRO(); + + if (m_areal) { + if (coords.size() < 4) { + // Component cannot have any area, just skip it. + return; + } + + if (coords.size() == 5 && algorithm::Area::ofRing(&coords) == geom_box.getArea()) { + process_rectangular_ring(geom_box, exterior_ring); + return; + } + } + + Grid ring_grid = get_ring_grid(ls, m_geometry_grid); + + size_t rows = ring_grid.rows(); + size_t cols = ring_grid.cols(); + + // Short circuit for small geometries that are entirely contained within a single grid cell. + if (rows == (1 + 2 * infinite_extent::padding) && + cols == (1 + 2 * infinite_extent::padding) && + ring_grid.grid_cell(1, 1).contains(geom_box)) { + + size_t i0 = ring_grid.row_offset(m_geometry_grid); + size_t j0 = ring_grid.col_offset(m_geometry_grid); + + if (m_areal) { + auto ring_area = static_cast(algorithm::Area::ofRing(&coords) / ring_grid.grid_cell(1, 1).getArea()); + + if (exterior_ring) { + m_results->increment(i0, j0, ring_area); + } else { + m_results->increment(i0, j0, -1 * ring_area); + } + } else { + m_results->increment(i0, j0, static_cast(algorithm::Length::ofLine(&coords))); + } + + return; + } + + std::vector coordsVec; + coords.toVector(coordsVec); + + if (m_areal && !algorithm::Orientation::isCCW(&coords)) { + std::reverse(coordsVec.begin(), coordsVec.end()); + } + + Matrix> cells(ring_grid.rows(), ring_grid.cols()); + traverse_cells(cells, coordsVec, ring_grid, m_areal); + + // Compute the fraction covered for all cells and assign it to + // the area matrix + // TODO avoid copying matrix when geometry has only one polygon, and polygon has only one ring + Matrix areas = m_areal ? collect_areas(cells, make_finite(ring_grid), ls) : collect_lengths(cells); + + // Transfer these areas to our global set + size_t i0 = ring_grid.row_offset(m_geometry_grid); + size_t j0 = ring_grid.col_offset(m_geometry_grid); + + add_ring_results(i0, j0, areas, exterior_ring || !m_areal); +} + +void +GridIntersection::add_ring_results(size_t i0, size_t j0, const Matrix& areas, bool exterior_ring) +{ + float factor = exterior_ring ? 1.0f : -1.0f; + + for (size_t i = 0; i < areas.rows(); i++) { + for (size_t j = 0; j < areas.cols(); j++) { + m_results->increment(i0 + i, j0 + j, factor * areas(i, j)); + } + } +} + +void +traverse_ring(Matrix>& cells, const Grid& grid, const LineString& g, bool want_ccw) +{ + const geom::CoordinateSequence& seq = *g.getCoordinatesRO(); + + std::vector coords; + seq.toVector(coords); + + if (want_ccw != algorithm::Orientation::isCCW(&seq)) { + std::reverse(coords.begin(), coords.end()); + } + traverse_cells(cells, coords, grid, true); +} + +std::unique_ptr +GridIntersection::subdivide_polygon(const Grid& p_grid, const Geometry& g, bool includeExterior) +{ + const geom::GeometryFactory& gfact = *g.getFactory(); + + Grid grid = make_infinite(p_grid, *g.getEnvelopeInternal()); + Matrix> cells(grid.rows(), grid.cols()); + + std::size_t ngeoms = g.getNumGeometries(); + for (std::size_t i = 0; i < ngeoms; i++) { + const Polygon& gi = static_cast(*g.getGeometryN(i)); + const LineString& shell = *gi.getExteriorRing(); + traverse_ring(cells, grid, shell, true); + + std::size_t nrings = gi.getNumInteriorRing(); + for (std::size_t j = 0; j < nrings; j++) { + traverse_ring(cells, grid, *gi.getInteriorRingN(j), false); + } + } + + auto areas = collect_areas(cells, p_grid, g); + + std::vector> geoms; + std::vector> edge_geoms; + + for (std::size_t i = 0; i < cells.rows(); i++) { + bool row_edge = i == 0 || i == (cells.rows() - 1); + + for (std::size_t j = 0; j < cells.cols(); j++) { + bool edge = row_edge || (j == 0 || j == (cells.cols() - 1)); + + if (cells(i, j) != nullptr) { + if (edge) { + if (includeExterior) { + edge_geoms.push_back(cells(i, j)->covered_polygons(gfact)); + } + } else if (areas(i - 1, j - 1) == fill_values::INTERIOR) { + // Cell is completely covered by polygon + Envelope env = cells(i, j)->box(); + geoms.push_back(gfact.toGeometry(&env)); + } else if (areas(i - 1, j - 1) != fill_values::EXTERIOR) { + // Cell is partly covered by polygon + geoms.push_back(cells(i, j)->covered_polygons(gfact)); + } + } else if (!edge && areas(i - 1, j - 1) == fill_values::INTERIOR) { + // Cell is entirely covered by polygon + Envelope env = grid.grid_cell(i, j); + geoms.push_back(gfact.toGeometry(&env)); + } + } + } + + if (!edge_geoms.empty()) { + auto edge_coll = gfact.createGeometryCollection(std::move(edge_geoms)); + geoms.push_back(overlayng::CoverageUnion::geomunion(edge_coll.get())); + } + + return gfact.createGeometryCollection(std::move(geoms)); +} + +} diff --git a/src/operation/grid/PerimeterDistance.cpp b/src/operation/grid/PerimeterDistance.cpp new file mode 100644 index 0000000000..dae646f5de --- /dev/null +++ b/src/operation/grid/PerimeterDistance.cpp @@ -0,0 +1,64 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#include + +#include +#include +#include + +namespace geos::operation::grid { + +double +perimeter_distance(double xmin, double ymin, double xmax, double ymax, double x, double y) +{ + if (x == xmin) { + // Left + return y - ymin; + } + + if (y == ymax) { + // Top + return (ymax - ymin) + x - xmin; + } + + if (x == xmax) { + // Right + return (xmax - xmin) + (ymax - ymin) + ymax - y; + } + + if (y == ymin) { + // Bottom + return (xmax - xmin) + 2 * (ymax - ymin) + (xmax - x); + } + + throw std::runtime_error("Cannot calculate perimeter distance for point not on boundary."); +} + +double +perimeter_distance(const geom::Envelope& b, const geom::CoordinateXY& c) +{ + return perimeter_distance(b.getMinX(), b.getMinY(), b.getMaxX(), b.getMaxY(), c.x, c.y); +} + +double +perimeter_distance_ccw(double measure1, double measure2, double perimeter) +{ + if (measure2 <= measure1) { + return measure1 - measure2; + } + return perimeter + measure1 - measure2; +} + +} diff --git a/src/operation/grid/Traversal.cpp b/src/operation/grid/Traversal.cpp new file mode 100644 index 0000000000..7e8a4d0c60 --- /dev/null +++ b/src/operation/grid/Traversal.cpp @@ -0,0 +1,106 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#include +#include + +#include + +using geos::geom::CoordinateXY; + +namespace geos::operation::grid { + +void +Traversal::add(const CoordinateXY& c) +{ + m_coords.push_back(c); +} + +bool +Traversal::empty() const +{ + return m_coords.empty(); +} + +void +Traversal::enter(const CoordinateXY& c, Side s) +{ + if (!m_coords.empty()) { + throw std::runtime_error("Traversal already started"); + } + + add(c); + m_entry = s; +} + +void +Traversal::exit(const CoordinateXY& c, Side s) +{ + add(c); + m_exit = s; +} + +bool +Traversal::is_closed_ring() const +{ + return m_coords.size() >= 3 && m_coords[0] == m_coords[m_coords.size() - 1]; +} + +bool +Traversal::entered() const +{ + return m_entry != Side::NONE; +} + +bool +Traversal::exited() const +{ + return m_exit != Side::NONE; +} + +bool +Traversal::multiple_unique_coordinates() const +{ + for (size_t i = 1; i < m_coords.size(); i++) { + if (m_coords[0] != m_coords[i]) { + return true; + } + } + + return false; +} + +bool +Traversal::traversed() const +{ + return entered() && exited(); +} + +const CoordinateXY& +Traversal::last_coordinate() const +{ + return m_coords.at(m_coords.size() - 1); +} + +const CoordinateXY& +Traversal::exit_coordinate() const +{ + if (!exited()) { + throw std::runtime_error("Can't get exit coordinate from incomplete traversal."); + } + + return last_coordinate(); +} + +} \ No newline at end of file diff --git a/src/operation/grid/TraversalAreas.cpp b/src/operation/grid/TraversalAreas.cpp new file mode 100644 index 0000000000..7db1415876 --- /dev/null +++ b/src/operation/grid/TraversalAreas.cpp @@ -0,0 +1,280 @@ +/********************************************************************** + * + * GEOS - Geometry Engine Open Source + * http://geos.osgeo.org + * + * Copyright (C) 2018-2025 ISciences, LLC + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU Lesser General Public Licence as published + * by the Free Software Foundation. + * See the COPYING file for more information. + * + **********************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +using geos::geom::CoordinateSequence; +using geos::geom::CoordinateXY; +using geos::geom::Geometry; +using geos::geom::GeometryFactory; +using geos::geom::Envelope; + +namespace geos::operation::grid { + +struct CoordinateChain +{ + double start; // perimeter distance value of the first coordinate + double stop; // perimeter distance value of the last coordinate + const std::vector* coordinates; + bool visited; + + CoordinateChain(double p_start, double p_stop, const std::vector* p_coords) + : start{ p_start } + , stop{ p_stop } + , coordinates{ p_coords } + , visited{ false } + { + } +}; + +static double +exit_to_entry_perimeter_distance_ccw(const CoordinateChain& c1, const CoordinateChain& c2, double perimeter) +{ + return perimeter_distance_ccw(c1.stop, c2.start, perimeter); +} + +static CoordinateChain* +next_chain(std::vector& chains, + const CoordinateChain* chain, + const CoordinateChain* kill, + double perimeter) +{ + + CoordinateChain* min = nullptr; + double min_distance = std::numeric_limits::max(); + + for (CoordinateChain& candidate : chains) { + if (candidate.visited && std::addressof(candidate) != kill) { + continue; + } + + double distance = exit_to_entry_perimeter_distance_ccw(*chain, candidate, perimeter); + if (distance < min_distance) { + min_distance = distance; + min = std::addressof(candidate); + } + } + + if (min == nullptr) { + throw std::runtime_error("Failed to find next CoordinateChain"); + } + + return min; +} + +template +bool +has_multiple_unique_coordinates(const T& vec) +{ + for (std::size_t i = 1; i < vec.size(); i++) { + if (vec[i] != vec[0]) { + return true; + } + } + + return false; +} + +/** + * @brief Identify counter-clockwise rings formed by the supplied coordinate vectors and the boundary of this box. + * + * @param box Box to be included in rings + * @param coord_lists A list of coordinate vectors, with each vector representing a traversal of `box` or a closed ring. + * @param visitor Function be applied to each ring identified. Because `coord_lists` may include both clockwise and + * counter-clockwise closed rings, `visitor` will be provided with the orientation of each ring as an + * argument. + */ +template +void +visit_rings(const Envelope& box, const std::vector*>& coord_lists, F&& visitor) +{ + std::vector chains; + chains.reserve(coord_lists.size() + 4); + + for (const auto& coords : coord_lists) { + if (!has_multiple_unique_coordinates(*coords)) { + continue; + } + + if (coords->front() == coords->back() && has_multiple_unique_coordinates(*coords)) { + // Closed ring. Check orientation. + + // TODO: Remove copy + CoordinateSequence seq(0, false, false); + seq.setPoints(*coords); + bool is_ccw = algorithm::Orientation::isCCW(&seq); + visitor(*coords, is_ccw); + } else { + double start = perimeter_distance(box, coords->front()); + double stop = perimeter_distance(box, coords->back()); + + chains.emplace_back(start, stop, coords); + } + } + + double height{ box.getHeight() }; + double width{ box.getWidth() }; + double perimeter{ box.getPerimeter() }; + + // create coordinate lists for corners + std::vector bottom_left = { CoordinateXY(box.getMinX(), box.getMinY()) }; + std::vector top_left = { CoordinateXY(box.getMinX(), box.getMaxY()) }; + std::vector top_right = { CoordinateXY(box.getMaxX(), box.getMaxY()) }; + std::vector bottom_right = { CoordinateXY(box.getMaxX(), box.getMinY()) }; + + // Add chains for corners + chains.emplace_back(0.0, 0.0, &bottom_left); + chains.emplace_back(height, height, &top_left); + chains.emplace_back(height + width, height + width, &top_right); + chains.emplace_back(2 * height + width, 2 * height + width, &bottom_right); + + std::vector coords; + for (auto& chain_ref : chains) { + if (chain_ref.visited || chain_ref.coordinates->size() == 1) { + continue; + } + + coords.clear(); + + CoordinateChain* chain = std::addressof(chain_ref); + CoordinateChain* first_chain = chain; + do { + chain->visited = true; + coords.insert(coords.end(), chain->coordinates->cbegin(), chain->coordinates->cend()); + chain = next_chain(chains, chain, first_chain, perimeter); + } while (chain != first_chain); + + coords.push_back(coords[0]); + + if (has_multiple_unique_coordinates(coords)) { + visitor(coords, true); + } + } +} + +double +left_hand_area(const Envelope& box, const std::vector*>& coord_lists) +{ + double ccw_sum = 0; + double cw_sum = 0; + bool found_a_ring = false; + + visit_rings(box, coord_lists, [&cw_sum, &ccw_sum, &found_a_ring](const std::vector& coords, bool is_ccw) { + found_a_ring = true; + + if (is_ccw) { + ccw_sum += algorithm::Area::ofRing(coords); + } else { + cw_sum += algorithm::Area::ofRing(coords); + } + }); + + if (!found_a_ring) { + throw std::runtime_error("Cannot determine coverage fraction (it is either 0 or 100%)"); + } + + // If this box has only clockwise rings (holes) then the area + // of those holes should be subtracted from the complete box area. + if (ccw_sum == 0.0 && cw_sum > 0) { + return box.getArea() - cw_sum; + } else { + return ccw_sum - cw_sum; + } +} + +std::unique_ptr +left_hand_rings(const GeometryFactory& gfact, const Envelope& box, const std::vector*>& coord_lists) +{ + using geom::LinearRing; + + std::vector> shells; + std::vector> holes; + + bool found_a_ring = false; + + visit_rings(box, coord_lists, [&gfact, &shells, &holes, &found_a_ring](const std::vector& coords, bool is_ccw) { + found_a_ring = true; + + // finding a collapsed ring is sufficient to determine whether the cell interior is inside our outside, + // but we don't want to actually construct the ring. + if (algorithm::Area::ofRing(coords) == 0) { + return; + } + + CoordinateSequence seq(0, false, false); + seq.setPoints(coords); + auto ring = gfact.createLinearRing(std::move(seq)); + + if (is_ccw) { + shells.push_back(std::move(ring)); + } else { + holes.push_back(std::move(ring)); + } + }); + + if (!found_a_ring) { + throw std::runtime_error("Cannot determine coverage fraction (it is either 0 or 100%)"); + } + + if (shells.empty() && !holes.empty()) { + CoordinateSequence seq(5, false, false); + seq.setAt(CoordinateXY{box.getMinX(), box.getMinY()}, 0); + seq.setAt(CoordinateXY{box.getMaxX(), box.getMinY()}, 1); + seq.setAt(CoordinateXY{box.getMaxX(), box.getMaxY()}, 2); + seq.setAt(CoordinateXY{box.getMinX(), box.getMaxY()}, 3); + seq.setAt(CoordinateXY{box.getMinX(), box.getMinY()}, 4); + + gfact.createLinearRing(std::move(seq)); + } + + if (holes.empty()) { + std::vector> polygons; + for (auto& shell : shells) { + polygons.push_back(gfact.createPolygon(std::move(shell))); + } + + if (polygons.size() == 1) { + return std::move(polygons.front()); + } else { + return gfact.createMultiPolygon(std::move(polygons)); + } + } else if (shells.size() == 1) { + return gfact.createPolygon(std::move(shells.front()), std::move(holes)); + } else { + operation::polygonize::Polygonizer polygonizer; + + for (const auto& shell : shells) { + polygonizer.add(static_cast(shell.get())); + } + for (const auto& hole : holes) { + polygonizer.add(static_cast(hole.get())); + } + + auto polygonized = polygonizer.getPolygons(); + return gfact.createMultiPolygon(std::move(polygonized)); + } +} + +} diff --git a/tests/resources/antarctica.wkt b/tests/resources/antarctica.wkt new file mode 100644 index 0000000000..d417b087d6 --- /dev/null +++ b/tests/resources/antarctica.wkt @@ -0,0 +1 @@ +MULTIPOLYGON (((-59.572094692611529 -80.040178725096297,-59.865849371974718 -80.549656671061854,-60.1596557277702 -81.000326837079314,-62.255393439367083 -80.863177585776654,-64.488125372969762 -80.921933689292558,-65.741666429289836 -80.588827406739142,-65.741666429289836 -80.549656671061854,-66.29003089055513 -80.25577280061799,-64.037687750897646 -80.294943536295179,-61.883245612217138 -80.392870375488286,-61.138975796133451 -79.9813709451481,-60.610119188058405 -79.628679294756125,-59.572094692611529 -80.040178725096297)),((-159.208183560197654 -79.497059421708727,-161.127601284814659 -79.634208673011301,-162.439846768218388 -79.281465346187019,-163.027407803376974 -78.928773695794959,-163.066604377270323 -78.869965915846763,-163.712895677728739 -78.595667413241529,-163.712895677728739 -78.595666605797277,-163.105800951163815 -78.223337911134294,-161.245113491846382 -78.380175883140168,-160.246208055644502 -78.693645121422662,-159.482404548154477 -79.046337579258989,-159.208183560197654 -79.497059421708727)),((-45.154757656421026 -78.047069600586738,-43.920827806155756 -78.478102722333261,-43.489949713706096 -79.085559991368456,-43.372437506674373 -79.516644789547271,-43.333266770997085 -80.026122735512928,-44.880536668464288 -80.339643650227714,-46.506173875502014 -80.594356784994318,-48.386420864441789 -80.829484551922349,-50.482106899606464 -81.025441583173119,-52.851988084511788 -80.966685479657301,-54.164259406131606 -80.633527520671578,-53.98799109558405 -80.222028090331406,-51.8531343247422 -79.947729587726087,-50.991326463410587 -79.614623305172657,-50.364594692574741 -79.183486830561634,-49.914131232286508 -78.811209004886692,-49.306958991073117 -78.458569030926924,-48.660616014182523 -78.047017924154446,-48.660616014182523 -78.047018731598683,-48.1513964503784 -78.047069600586738,-46.662856818211026 -77.831475525065031,-45.154757656421026 -78.047069600586738)),((-121.211511393857123 -73.500990499006036,-119.918851278292053 -73.65772511814734,-118.724143032691913 -73.481353454735199,-119.292118700011955 -73.834096781559481,-120.232217163709976 -74.088809916326156,-121.622829956684257 -74.010468444971607,-122.621734585441899 -73.657777602023884,-122.621735392886137 -73.657776794579632,-122.406244670229029 -73.32461883559391,-121.211511393857123 -73.500990499006036)),((-125.559566406895314 -73.481353454735199,-124.031881877266855 -73.873267517236741,-124.619468750641531 -73.834096781559481,-125.912180542638907 -73.736118265934095,-127.28312964568191 -73.461768894340821,-127.283130453126162 -73.461768086896569,-126.558471843097209 -73.246225687807168,-125.559566406895314 -73.481353454735199)),((-98.981549648823901 -71.933334248999785,-97.884743211645031 -72.070535176734737,-96.787936774466232 -71.952971293270707,-96.200349901091442 -72.521205342752182,-96.983764614636215 -72.442863871397634,-98.19808325884685 -72.482034607074922,-99.432013109112205 -72.442863871397634,-100.783455166409212 -72.501619974913552,-101.80186845580134 -72.305662943662782,-102.330725063876386 -71.894164320766848,-102.330725063876386 -71.89416351332261,-101.703967454824436 -71.717791849910384,-100.4309185453141 -71.854992777645322,-98.981549648823901 -71.933334248999785)),((-68.451345994730417 -70.955822855766741,-68.333833787698694 -71.406493021784186,-68.510127936462425 -71.798407084285728,-68.784297247986984 -72.170735778948625,-69.959470994736421 -72.307885030251299,-71.075888637970138 -72.50384206150207,-72.388134121373781 -72.484256693663426,-71.898499925408288 -72.092342631161884,-73.073621995725432 -72.229491882464544,-74.190039638959064 -72.366692810199496,-74.953894822881381 -72.07275726332324,-75.01262508818121 -71.661257832983068,-73.915818651002326 -71.269344577925779,-73.915818651002326 -71.269343770481527,-73.230330776650561 -71.151779887017511,-72.074716559523551 -71.190950622694771,-71.780961880160362 -70.681472676729129,-71.72217993842844 -70.30919565849851,-71.741791144483187 -69.505782165656797,-71.173815477163146 -69.035474955368414,-70.253251512315728 -68.878740336227196,-69.72444658067306 -69.251017354457815,-69.489422166609586 -69.623346049120727,-69.058518235943808 -70.074016215138187,-68.725541144471066 -70.505152689749281,-68.451345994730417 -70.955822855766741)),((-58.614142829000912 -64.152467130133147,-59.045072597882864 -64.368009529222633,-59.789342413966551 -64.211223233649051,-60.611927863188697 -64.309201749274436,-61.297415737540376 -64.544329516202566,-62.022100185785433 -64.799094327401363,-62.511760219966902 -65.093029874277519,-62.648857794837369 -65.484942321890657,-62.590127529537739 -65.857219340121361,-62.120078701410705 -66.190325622674706,-62.805566575762384 -66.425505066034958,-63.745690070232371 -66.503846537389592,-64.294106207929957 -66.837004496375215,-64.881693081304633 -67.150473734657723,-65.508424852140564 -67.581610209268916,-65.665081956633287 -67.95388722749945,-65.31254533553809 -68.365334981407415,-64.783714565679333 -68.678907572554493,-63.961103278241097 -68.913983663050175,-63.197299770751044 -69.227556254197253,-62.78595536970775 -69.619418640266503,-62.570516323482906 -69.991747334929499,-62.276735805903542 -70.383661397431041,-61.806661139560589 -70.716767679984471,-61.512906460197399 -71.089044698215076,-61.375808885327132 -72.010073750953126,-61.081976691315532 -72.38235076918383,-61.003661058177187 -72.774264831685372,-60.69026933454316 -73.166178894187084,-60.827366909413428 -73.695242207991186,-61.375808885327132 -74.106741638331371,-61.96336992048569 -74.439847920884887,-63.295200771727963 -74.576997172187376,-63.745690070232371 -74.929740499011729,-64.352836473229587 -75.262846781565159,-65.860987311451765 -75.635123799795778,-67.192818162694124 -75.791910095369445,-68.446281704365759 -76.007452494458761,-69.797723761662837 -76.222994893548176,-70.600723843046239 -76.634494323888447,-72.206775682245365 -76.673665059565721,-73.969536302369676 -76.634494323888447,-75.555976935514025 -76.712887471675202,-77.240370246067613 -76.712887471675202,-76.926978522433586 -77.104801534176744,-75.399293992804928 -77.281069844724385,-74.28287634957141 -77.555420023761812,-73.656118740519446 -77.908111674153957,-74.772536383753078 -78.221632588868673,-76.496100429984011 -78.123654073243287,-77.925858120419264 -78.378418884442254,-77.984665900367474 -78.789918314782341,-78.02378495961247 -79.18183318472822,-76.848637051079123 -79.51493946728165,-76.633223843070397 -79.887216485512269,-75.360097418911749 -80.259545180175252,-73.244851854124619 -80.416331475748763,-71.442946336539222 -80.690629978353982,-70.013162807887767 -81.004150893068783,-68.191646084247537 -81.317671807783569,-65.704278530526665 -81.47445810335725,-63.256030036050703 -81.748756605962484,-61.55202551944231 -82.042692152838541,-59.691415574773458 -82.375850111824349,-58.712121344626212 -82.846105645680353,-58.222487148660917 -83.21843434034335,-57.008116828017819 -82.865691013519083,-55.362894253141548 -82.571755466642827,-53.619770677288244 -82.258234551928041,-51.543644171746024 -82.003521417161352,-49.761349860215461 -81.729171238123755,-47.27393063006221 -81.709585870285295,-44.825707973802508 -81.84673512158777,-42.808363409992381 -82.081914564948107,-42.162020433101787 -81.650829766769291,-40.771433478343596 -81.356894219893221,-38.244817674297053 -81.337308852054591,-36.266669684380219 -81.121714776532983,-34.386396857224355 -80.906172377443482,-32.31029618989831 -80.769023126140738,-30.097097947701997 -80.592651462728696,-28.549802212018704 -80.337938327962007,-29.254901292425131 -79.985195001137654,-29.685805223090966 -79.632503350745679,-29.685805223090966 -79.260226332514975,-31.62480831554663 -79.299397068192235,-33.681323615033961 -79.456131687333453,-35.639912075328255 -79.456131687333453,-35.914107225069017 -79.083854669102919,-35.777009650198721 -78.33924814876498,-35.326546189910431 -78.123654073243287,-33.896762661258862 -77.888526306315242,-32.212369350705302 -77.653450215819575,-30.99805070649461 -77.359514668943319,-29.783732062284059 -77.065579122067263,-28.882779303491361 -76.673665059565721,-27.511751878355653 -76.497345072585787,-26.16033565927475 -76.36014414485075,-25.474821946706868 -76.281802673496287,-23.927552049239779 -76.242580261386735,-22.45859778491095 -76.105431010084246,-21.22469377286177 -75.909473978833475,-20.010375128651077 -75.67434621190543,-18.91354285325616 -75.439218444977286,-17.522981736714172 -75.125697530262499,-16.641588507544014 -74.792539571276876,-15.701490851290259 -74.498604024400635,-15.407710333710867 -74.106741638331371,-16.465320196996373 -73.871613871403412,-16.112783575901261 -73.460114441063155,-15.446855231171952 -73.146541849916076,-14.408804897508986 -72.950584818665305,-13.311972622113984 -72.715457051737332,-12.293507656289563 -72.401936137022545,-11.510067104528588 -72.010073750953126,-11.020432908563038 -71.539766540664829,-10.295774298534155 -71.265416361627302,-9.101015183946089 -71.324224141575513,-8.611380987980596 -71.657330424128844,-7.416621873392415 -71.696501159806033,-7.377451137715241 -71.324224141575513,-6.868231573911117 -70.932310079073972,-5.790984666354774 -71.030288594699272,-5.53637488445267 -71.402617289362254,-4.341667446296867 -71.461373392878073,-3.048981492515594 -71.28505340589814,-1.795492112627784 -71.167437846001832,-0.659489101555522 -71.226245625950042,-0.228636847322065 -71.637745056290299,0.868195428072937 -71.304638773736784,1.886686232113533 -71.128267110324742,3.022637566753417 -70.991117859022069,4.139055209987049 -70.853916931287046,5.157546014027673 -70.618789164359086,6.273911980828927 -70.462054545217796,7.135719842160626 -70.246512146128381,7.742866245157842 -69.893768819304029,8.487110223025326 -70.148533630502996,9.525134718472202 -70.011332702768215,10.249845004933434 -70.481639913056512,10.81782067225339 -70.834331563448501,11.953823683325652 -70.63837453219773,12.404287143613942 -70.246512146128381,13.422777947654396 -69.972161967090955,14.734997592842006 -70.030918070606774,15.126756626046586 -70.403246765269756,15.949342075268646 -70.030918070606774,17.02658898282516 -69.913354187142744,18.201711053142333 -69.874183451465484,19.259372592860046 -69.893768819304029,20.375738559661471 -70.011332702768215,21.452985467217815 -70.070140482716255,21.923034295344735 -70.403246765269756,22.569403110451447 -70.697182312145827,23.666183709414213 -70.520810648733701,24.841357456163593 -70.481639913056512,25.977308790803647 -70.481639913056512,27.093726434037279 -70.462054545217796,28.092580193806867 -70.32485361748293,29.150241733524581 -70.207289734018985,30.031583286262531 -69.932939554981289,30.971732618948607 -69.756619568001454,31.990171746556854 -69.658641052376069,32.754052768695288 -69.384290873338458,33.302443068176757 -68.835642191695712,33.8704187354966 -68.50258758557456,34.908494907375854 -68.659270528283486,35.300202264148226 -69.012013855107938,36.162010125479782 -69.247141622035969,37.200034620926573 -69.168748474249043,37.905107863116797 -69.521440124641202,38.649403517416914 -69.776204935840184,39.667894321457339 -69.541077168912039,40.020430942552565 -69.109940694300946,40.921357863129089 -68.933620707321182,41.959434035008229 -68.600514424767667,42.938702426939102 -68.463313497032715,44.113876173688624 -68.267408142214236,44.897290887233424 -68.051865743124921,45.719928012887834 -67.816737976196777,46.503342726432635 -67.601195577107461,47.443440382686305 -67.718759460571476,48.344418979695121 -67.366067810179416,48.990736118369597 -67.091717631141904,49.930885451055673 -67.111302998980449,50.753470900277733 -66.876175232052404,50.949324578663919 -66.523483581660429,51.791547072157044 -66.249133402622903,52.614132521378934 -66.053176371372132,53.613037957580815 -65.89639007579855,54.533550245996054 -65.818048604444002,55.414943475166211 -65.876804707959906,56.355041131419881 -65.974783223585376,57.158092889235689 -66.249133402622903,57.255968051996462 -66.680218200801633,58.137361281166619 -67.013324483355149,58.744507684163949 -67.287674662392675,59.939318475184251 -67.40523854585669,60.605220981697443 -67.679588724894217,61.427806430919333 -67.95388722749945,62.387489455011661 -68.012695007447547,63.190489536395233 -67.816737976196777,64.052349074159025 -67.40523854585669,64.992446730412922 -67.620729268513713,65.971715122343966 -67.738344828410035,66.911864455029757 -67.85590871187415,67.891132846960915 -67.934301859660806,68.890038283162909 -67.934301859660806,69.712623732384742 -68.972791442998371,69.673452996707482 -69.227556254197253,69.555940789675816 -69.678226420214713,68.596257765583488 -69.932939554981289,67.812739699174159 -70.305268249644286,67.949888950476662 -70.697182312145827,69.066306593710266 -70.67754526787499,68.929157342407763 -71.069459330376532,68.41998945503596 -71.441788025039529,67.949888950476662 -71.853287455379615,68.713769972615154 -72.166808370094415,69.869306675093952 -72.264786885719801,71.024895054004588 -72.088415222307759,71.573285353486057 -71.696501159806033,71.906288283174916 -71.324224141575513,72.454626906224036 -71.010703226860628,73.081410353492089 -70.716767679984471,73.336020135394193 -70.364024353160204,73.864876743469239 -69.874183451465484,74.491556837872707 -69.776204935840184,75.627559848944969 -69.73703420016281,76.62646528514685 -69.619418640266503,77.644904412755267 -69.462684021125298,78.13453860872059 -69.070769958623757,78.428370802732246 -68.698441263960675,79.113858677083925 -68.326215922162433,80.093127069014855 -68.071502787395758,80.935349562507753 -67.875545756144987,81.483791538421457 -67.542387797159265,82.05176720574147 -67.366067810179416,82.776425815770409 -67.209281514605919,83.775331251972403 -67.30726003023122,84.676206496116635 -67.209281514605919,85.65552656447997 -67.091717631141904,86.752358839874859 -67.150473734657723,87.477017449903798 -66.876175232052404,87.986288690140242 -66.20991099051335,88.358410679073955 -66.484261169550862,88.828407830768555 -66.95456837983923,89.670630324261566 -67.150473734657723,90.6303650247863 -67.228866882444464,91.590099725310807 -67.111302998980449,92.608538852919054 -67.189696146767204,93.548636509172951 -67.209281514605919,94.175419956441004 -67.111302998980449,95.017590773501666 -67.170110778928645,95.781471795640272 -67.385653178017975,96.682398716216795 -67.248503926715486,97.759645623773139 -67.248503926715486,98.680209588620556 -67.111302998980449,99.718182407635055 -67.248503926715486,100.384188267012775 -66.915345967729678,100.893356154384691 -66.582239685176248,101.578895705168549 -66.307889506138636,102.832410923272647 -65.56328379324512,103.478676385514774 -65.700484720979972,104.242557407653095 -65.974783223585376,104.90845991416623 -66.327526550409658,106.181560500108759 -66.934931335568393,107.160880568472095 -66.95456837983923,108.081392856887163 -66.95456837983923,109.158639764443677 -66.837004496375215,110.235834995567842 -66.699803568640363,111.058472121222081 -66.425505066034958,111.743959995573931 -66.131569519158887,112.860377638807478 -66.092347107049321,113.604673293107368 -65.876804707959906,114.388088006652055 -66.072761739210677,114.897307570456263 -66.386282653925477,115.602380812646544 -66.699803568640363,116.699161411609424 -66.660632832962989,117.384700962393225 -66.915345967729678,118.579460076981292 -67.170110778928645,119.832923618653098 -67.268089294553945,120.870999790532181 -67.189696146767204,121.654414504077096 -66.876175232052404,122.320368687022352 -66.562654317337689,123.221295607598933 -66.484261169550862,124.122274204607635 -66.6214620972859,125.160247023622247 -66.719388936478907,126.10039635630838 -66.562654317337689,127.001426629749318 -66.562654317337689,127.88276818248724 -66.660632832962989,128.803280470902422 -66.75861134858846,129.704259067911181 -66.582239685176248,130.78145429903546 -66.425505066034958,131.799945103075885 -66.386282653925477,132.935896437716139 -66.386282653925477,133.856460402563386 -66.288304138300091,134.757387323139909 -66.209962666945628,135.031582472880729 -65.720070088818616,135.070753208557818 -65.30857065847843,135.697484979393579 -65.582869161083664,135.873804966373513 -66.033591003533417,136.206704543197787 -66.445090433873673,136.61804894424111 -66.778196716427018,137.460271437733951 -66.95456837983923,138.596222772374148 -66.895760599891133,139.908442417561474 -66.876175232052404,140.80942101457029 -66.817367452104378,142.121692336190193 -66.817367452104378,143.061841668876156 -66.797782084265663,144.374061314063709 -66.837004496375215,145.490427280865021 -66.915345967729678,146.195552199487821 -67.228866882444464,145.999698521101521 -67.601195577107461,146.646067336208233 -67.895131123983703,147.723262567332341 -68.130258890911662,148.839628534133709 -68.385023702110544,150.132314487914897 -68.561292012658186,151.483704868779597 -68.718129984663975,152.502247349252485 -68.874812927372986,153.638198683892568 -68.894501648076101,154.28456749899928 -68.561292012658186,155.165857375304853 -68.835642191695712,155.929790073875466 -69.14921478284279,156.811131626613388 -69.384290873338458,158.025527785472406 -69.482269388963942,159.181012811518741 -69.599833272427958,159.670698683916527 -69.991747334929499,160.806650018556496 -70.226875101857544,161.570479364262809 -70.579618428681812,162.686897007496356 -70.736353047823201,163.842433709974927 -70.716767679984471,164.919680617531213 -70.77552378350029,166.11443973211945 -70.755938415661745,167.309095493842989 -70.834331563448501,168.425616489941177 -70.971480814751061,169.46358930895596 -71.206660258111398,170.501665480835044 -71.402617289362254,171.206790399457617 -71.696501159806033,171.089226515993772 -72.088415222307759,170.560421584350735 -72.441158549132112,170.109958124062388 -72.891828715149387,169.757369826535154 -73.244520365541547,169.287320998408319 -73.656019795881633,167.975101353220765 -73.81280609145513,167.387488641629744 -74.16549774184719,166.094802687848443 -74.381040140936605,165.644390903992445 -74.772954203438147,164.958851353208587 -75.145282898101229,164.234192743179705 -75.45880381281593,163.822796665703919 -75.870303243156201,163.568238560234278 -76.242580261386735,163.470260044608978 -76.693302103836558,163.489897088879758 -77.065579122067263,164.057872756199771 -77.457441508136426,164.273363478856965 -77.829770202799324,164.743463983416149 -78.182513529623776,166.60412560451735 -78.319611104494058,166.995781284857429 -78.750747579105251,165.193875767272033 -78.907483005690693,163.666217075859578 -79.123025404780023,161.766384719081117 -79.162247816889675,160.924162225588333 -79.73048186637098,160.747893915040748 -80.200737400227155,160.31696414615871 -80.573066094889967,159.78821089094842 -80.945394789553049,161.120015903974405 -81.278501072106479,161.629287144210906 -81.690000502446566,162.490991652678048 -82.06227752067727,163.705336135104773 -82.395435479662893,165.095948928078855 -82.708956394377779,166.60412560451735 -83.022477309092579,168.895665318067955 -83.335998223807366,169.404781529007579 -83.825890801934378,172.283933954149376 -84.041433201023708,172.477048781624177 -84.117914320815672,173.224083286835395 -84.413710219254412,175.985671828513119 -84.158997084487638,178.277211542064066 -84.472517999202438,180.0 -84.71338,180 -90,-180.0 -90.0,-180.0 -84.71338,-179.942499356178928 -84.721443373552489,-179.058677334691197 -84.139411716649093,-177.256771817105744 -84.452932631363879,-177.140806673265786 -84.417941227148319,-176.084672818077593 -84.099259128758419,-175.947234613627757 -84.110448710216616,-175.829882168662522 -84.117914320815672,-174.382502814815695 -84.534323012223567,-173.116559414745467 -84.117914320815672,-172.889105598012804 -84.061018568862337,-169.951222907571434 -83.884646905450126,-168.999988980158633 -84.117914320815672,-168.530198534193232 -84.237390232274478,-167.022099372403318 -84.570496514827909,-164.182143521155069 -84.825209649594584,-161.929774543281383 -85.138730564309384,-158.071379564424944 -85.373910007669707,-155.192252977499294 -85.09955982863211,-150.942098965438021 -85.295516859882881,-148.533072883071497 -85.609037774597667,-145.888918226332976 -85.31510222772161,-143.107718478600447 -85.040752048683913,-142.892279432375631 -84.570496514827909,-146.829068366463304 -84.531274102718342,-150.060731574483952 -84.296146335790382,-150.902928229760732 -83.904232273288841,-153.586201138300197 -83.688689874199355,-153.409906989536466 -83.238019708182065,-153.037759162386408 -82.826520277841809,-152.665637173452751 -82.454191583178812,-152.861516690055055 -82.042692152838541,-154.526298794553895 -81.768393650233321,-155.290179816692387 -81.415650323409039,-156.837449714159504 -81.102129408694253,-154.408786587522229 -81.16093718864245,-152.097661506132823 -81.004150893068783,-150.648292609642624 -81.337308852054591,-148.865998298112061 -81.043373305178335,-147.220749885019501 -80.671044610515438,-146.417748996191847 -80.337938327962007,-146.770286424731182 -79.926438897621921,-148.062946540296366 -79.652088718584224,-149.53190080462511 -79.358204848140446,-151.588416104112412 -79.299397068192235,-153.390321621697808 -79.162247816889675,-155.329376390585765 -79.064269301264204,-155.97566769104418 -78.691939799157041,-157.268301968393047 -78.378418884442254,-158.051768358370111 -78.025675557617902,-158.365134243787963 -76.889207458654951,-157.875474209606352 -76.987237650712615,-156.974573127245947 -77.300758565427515,-155.329376390585765 -77.202728373369752,-153.742832404576745 -77.065579122067263,-152.92024695535477 -77.496663920245993,-151.333780483994303 -77.398737081052801,-150.001949632751945 -77.183143005531193,-148.748486091080338 -76.908844502925973,-147.612483080008076 -76.575738220372529,-146.104408948989999 -76.477759704747058,-146.143528008234995 -76.105431010084246,-146.496091274990476 -75.733153991853541,-146.202309949967002 -75.380410665029189,-144.909623996185758 -75.204039001616962,-144.322037122811082 -75.53719696060277,-142.794352593182623 -75.341239929352,-141.638764214271617 -75.086475118152947,-140.209006523836166 -75.066889750314388,-138.857590304755348 -74.968911234688917,-137.506199923890449 -74.733783467760958,-136.428901339901927 -74.518241068671642,-135.214582695691291 -74.302698669582142,-134.431193820362608 -74.361454773097961,-133.745654269578552 -74.439847920884887,-132.257167928732059 -74.302698669582142,-130.925311239273583 -74.47901865656199,-129.554283814137762 -74.459433288723432,-128.24203833073426 -74.322284037420701,-126.890622111653244 -74.420262553046172,-125.402082479485784 -74.518241068671642,-124.011495524727607 -74.47901865656199,-122.562152466453611 -74.498604024400635,-121.073612834286237 -74.518241068671642,-119.702559570934227 -74.47901865656199,-118.684145474097932 -74.185083109685834,-117.469800991671207 -74.02834849054463,-116.216311611783411 -74.243890889633946,-115.021552497195415 -74.06751922622189,-113.944331427855076 -73.71482757582983,-113.297988450964482 -74.02834849054463,-112.94545182986937 -74.381040140936605,-112.299083014762587 -74.714198099922413,-111.261058519315625 -74.420262553046172,-110.066325242943734 -74.792539571276876,-108.714909023862731 -74.910103454740891,-107.559346483168113 -75.184453633778418,-106.149148322355018 -75.125697530262499,-104.876073574628663 -74.949325866850458,-103.367948574622659 -74.988496602527647,-102.016506517325652 -75.125697530262499,-100.645530768622308 -75.302017517242433,-100.116699998763266 -74.870932719063532,-100.763042975653946 -74.537826436510187,-101.252703009835528 -74.185083109685834,-102.545337287184509 -74.106741638331371,-103.113312954504536 -73.734412943668389,-103.328752000729281 -73.362084249005562,-103.681288621824393 -72.617530212544153,-102.917485114334355 -72.754679463846813,-101.605239630930726 -72.813435567362632,-100.312527838933448 -72.754679463846813,-99.137379930400101 -72.911414082988102,-98.118889126359477 -73.205349629864173,-97.688036872126105 -73.558041280256333,-96.336594814828914 -73.616849060204359,-95.043960537479848 -73.47969980890187,-93.672907274128107 -73.283742777650929,-92.439003262078955 -73.166178894187084,-91.420564134470709 -73.401306661115129,-90.088733283228436 -73.322913513328203,-89.226951260112941 -72.558722432595957,-88.42395117872951 -73.009392598613402,-87.268336961602614 -73.185764262025629,-86.01482174349843 -73.087785746400158,-85.192236294276569 -73.47969980890187,-83.879990810872755 -73.518870544578974,-82.66564632844603 -73.636434428043088,-81.470913052074138 -73.851976827132404,-80.687446662096988 -73.47969980890187,-80.295790981756994 -73.126956482077432,-79.296885545555 -73.518870544578974,-77.925858120419264 -73.420892028953588,-76.907367316378753 -73.636434428043088,-76.221879442027074 -73.969540710596419,-74.890048590784801 -73.871613871403412,-73.852024095337924 -73.656019795881633,-72.833533291297414 -73.401306661115129,-71.619214647086864 -73.264157409812384,-70.209042324489957 -73.146541849916076,-68.935915900331224 -73.009392598613402,-67.956621670184091 -72.793850199524087,-67.36906063502559 -72.480329284809301,-67.134036220962031 -72.049244486630386,-67.251548427993669 -71.637745056290299,-67.564940151627894 -71.245830993788758,-67.917476772723006 -70.853916931287046,-68.230842658140915 -70.462054545217796,-68.485452440043019 -70.109311218393515,-68.544208543558938 -69.717397155891973,-68.446281704365759 -69.325534769822724,-67.976232876238896 -68.953206075159727,-67.584499681250321 -68.54170664481947,-67.427842576757513 -68.149844258750221,-67.623670416927695 -67.718759460571476,-67.741182623959332 -67.326845398069935,-67.251548427993669 -66.876175232052404,-66.703183966728574 -66.582239685176248,-66.056815151621862 -66.209962666945628,-65.371327277270098 -65.89639007579855,-64.568275519454403 -65.602506205354672,-64.176542324465828 -65.171423022064445,-63.62815202498453 -64.897072843026749,-63.001394415932566 -64.642308031827866,-62.041685553623978 -64.583551928311948,-61.414927944572014 -64.270031013597162,-60.709854702381705 -64.074073982346391,-59.887269253159559 -63.956510098882369,-59.16258480491453 -63.701745287683572,-58.594557461162282 -63.388224372968601,-57.811142747617509 -63.270660489504579,-57.223581712458838 -63.525425300703638,-57.595729539608868 -63.858531583257069,-58.614142829000912 -64.152467130133147))) diff --git a/tests/resources/regression4.wkt b/tests/resources/regression4.wkt new file mode 100644 index 0000000000..902b46f58f --- /dev/null +++ b/tests/resources/regression4.wkt @@ -0,0 +1 @@ +POLYGON (( -160.9833333333333201 70.3166666666666771, -160.9825524224175126 70.3243221706814268, -160.9343861897786212 70.3256700303819571, -160.9322825113932254 70.3326568603515625, -160.8927174886067633 70.3340098063151089, -160.8906158447265398 70.3409901936849025, -160.8510508219400776 70.3423431396484489, -160.8489573160807140 70.3492964002821282, -160.8260426839192405 70.3507035997178889, -160.8239573160807083 70.3576297336154539, -160.8010426839192633 70.3590369330512289, -160.7989573160807026 70.3659630669487939, -160.7760426839192576 70.3673702663845546, -160.7739491780598655 70.3743235270182339, -160.7343841552734318 70.3756764729817803, -160.7322906494140398 70.3826297336154596, -160.7093760172525947 70.3840369330512203, -160.7073031955295050 70.3909216986762232, -160.6926968044704722 70.3924116346571225, -160.6907023111978958 70.3990356445312528, -160.6842976888020758 70.4009643554687585, -160.6823031955294994 70.4075883653428889, -160.6676968044704665 70.4090783013237882, -160.6656239827473769 70.4159630669487910, -160.6427093505859318 70.4173702663845518, -160.6406127929687386 70.4243340386284871, -160.5843872070312273 70.4256659613715357, -160.5822906494140341 70.4326297336154568, -160.5593760172525890 70.4340369330512175, -160.5573689778645701 70.4407023111979242, -160.5509643554687216 70.4426310221354299, -160.5489573160807026 70.4492964002821225, -160.5260426839192576 70.4507035997178832, -160.5239573160806970 70.4576297336154624, -160.5010426839192519 70.4590369330512232, -160.4989698621961622 70.4659216986762260, -160.4843634711371294 70.4674116346571253, -160.4822852240668283 70.4743140326606010, -160.4510481092664804 70.4756859673394160, -160.4489698621961509 70.4825883653428917, -160.4343634711371465 70.4840783013237910, -160.4322906494140284 70.4909630669487939, -160.4093760172525833 70.4923702663845546, -160.4072906494140511 70.4992964002821338, -160.3843760172525776 70.5007035997178946, -160.3822906494140454 70.5076297336154596, -160.3593760172525720 70.5090369330512203, -160.3572906494140398 70.5159630669487996, -160.3343760172525947 70.5173702663845603, -160.3322906494140341 70.5242964002821253, -160.3093760172525890 70.5257035997178860, -160.3073031955294994 70.5325883653428889, -160.2926968044704665 70.5340783013237882, -160.2906239827473769 70.5409630669487910, -160.2677093505859034 70.5423702663845518, -160.2656365288628137 70.5492550320095546, -160.2510301378038093 70.5507449679904539, -160.2489573160807197 70.5576297336154568, -160.2260426839192462 70.5590369330512175, -160.2239573160807140 70.5659630669487967, -160.2010426839192405 70.5673702663845575, -160.1989698621961509 70.5742550320095603, -160.1843634711371180 70.5757449679904596, -160.1823031955294994 70.5825883653428860, -160.1676968044704665 70.5840783013237996, -160.1656185574001370 70.5909806993272610, -160.1499999999999773 70.5916666666666828, -160.1495382029882251 70.5871398380253936, -160.1597137451171875 70.5806961059570312, -160.1950531005859375 70.5678329467773438, -160.1874237060546875 70.5665512084960938, -160.1719665527343750 70.5705490112304688, -160.1408440792089891 70.5832494497494167, -160.1403579186419961 70.5831998566917349, -160.1382598876953125 70.5764846801757812, -160.1165771484375000 70.5690612792968750, -160.1071729397799572 70.5669787037403751, -160.1068854437933737 70.5660237630208371, -160.1033072568295097 70.5661226426814494, -160.1022796630859375 70.5658950805664062, -160.0744781494140625 70.5653457641601562, -160.0601806640625000 70.5670700073242188, -160.0594408379018034 70.5673348478175484, -160.0593861897786212 70.5673363579644217, -160.0593800978870149 70.5673565913247813, -160.0484161376953125 70.5712814331054688, -160.0425947116933685 70.5751988854332239, -160.0343760172525833 70.5757035997178974, -160.0332192618348017 70.5795458545753007, -160.0000000000000000 70.5770568847656250, -159.9951477050781250 70.5766906738281250, -159.9772644042968750 70.5767059326171875, -159.9175491703567786 70.5820980463596896, -159.9159815400432194 70.5768917155312749, -159.9211883544921875 70.5740509033203125, -159.9156036376953125 70.5664901733398438, -159.9165039062500000 70.5490798950195312, -159.9098052978515625 70.5376129150390625, -159.9116973876953125 70.5364456176757812, -159.9290771484375000 70.5385360717773438, -159.9432067871093750 70.5310668945312500, -159.9379272460937500 70.5277786254882812, -159.9213867187500000 70.5289306640625000, -159.9104919433593750 70.5314788818359375, -159.9062652587890625 70.5273971557617188, -159.9132672534269943 70.5164356132204233, -159.9157023111978901 70.5157023111979271, -159.9162097090517705 70.5140171409690311, -159.9232342816385994 70.5089201692917555, -159.9685956122317805 70.5083609215974008, -159.9905548095703125 70.5100021362304688, -159.9973227125775566 70.5080067528721059, -160.0239427354600537 70.5076785617404624, -160.0252809729229853 70.5032334220974661, -160.0330810546875000 70.5029144287109375, -160.0373807466494043 70.4995870417929353, -160.0409942626952784 70.4992184109158018, -160.0410528466941287 70.4967453271401752, -160.0458679199218750 70.4930191040039062, -160.0490570068359375 70.4832000732421875, -160.0455474853515625 70.4740600585937500, -160.0501821072706718 70.4715429794480315, -160.0509172227647241 70.4744076199001768, -160.0987850613063870 70.4755672878689268, -160.0999999999999659 70.4708333333333456, -160.1034216986761862 70.4718634711371550, -160.1049380832247948 70.4867285834418453, -160.1124999999999829 70.4875000000000114, -160.1121466742621351 70.4767422146267393, -160.1043246510614040 70.4688953185463163, -160.1143398728970624 70.4669366850548613, -160.1774244520399009 70.4663133409288207, -160.1790602776703452 70.4646888843790720, -160.1836700439453125 70.4648437500000000, -160.1943654405694133 70.4631267797047798, -160.2002563476562500 70.4621810913085938, -160.1944274902343750 70.4599304199218750, -160.1832275390625000 70.4595031738281250, -160.1731109619140625 70.4618911743164062, -160.1539459228515625 70.4584426879882812, -160.1374969482421875 70.4583435058593750, -160.1116027832031250 70.4630126953125000, -160.1051483154296875 70.4619979858398438, -160.1124114990234375 70.4577407836914062, -160.1017456054687500 70.4562683105468750, -160.0963626688391912 70.4582532060109230, -160.0852966308593750 70.4623336791992188, -160.0566253662109375 70.4612960815429688, -160.0326885965444035 70.4662224621687869, -160.0314203802561792 70.4662582353471834, -160.0052947998046875 70.4659500122070312, -159.9956143208813728 70.4672682338481309, -159.9927424112955521 70.4673492431640653, -159.9924618388073725 70.4682579265360403, -159.9763730785450377 70.4751751247769107, -159.9677318996853330 70.4757168240017506, -159.9666019326352284 70.4793761292170586, -159.9664916992187500 70.4794235229492188, -159.9372458159930659 70.4833206584574441, -159.9119698648650569 70.4827160605293415, -159.9111480712890625 70.4785003662109375, -159.9089050292968750 70.4668655395507812, -159.9165236339602245 70.4620367604732820, -159.9181557549370609 70.4673221164279653, -159.9249232670388210 70.4669088691466499, -159.9251403808593750 70.4673995971679688, -159.9316349945957825 70.4664990282591788, -159.9406009250216982 70.4659515380859460, -159.9409807297367649 70.4647215581642428, -159.9491834136809985 70.4584184431334108, -159.9572809855143021 70.4575744628906335, -159.9589973656810855 70.4520159932426253, -159.9671630859375000 70.4490203857421875, -159.9792872911450274 70.4412200284780852, -159.9826219346788037 70.4408725314670221, -159.9827049103819832 70.4390212327149925, -159.9862670898437500 70.4367294311523438, -160.0000000000000000 70.4356918334960938, -160.0100250244140625 70.4349365234375000, -160.0110015869140625 70.4330749511718750, -160.0000000000000000 70.4321899414062500, -159.9915313720703125 70.4315109252929688, -159.9852447509765625 70.4277267456054688, -159.9860992431640625 70.4139404296875000, -159.9934997558593750 70.4045867919921875, -160.0000000000000000 70.4012145996093750, -160.0029317463873326 70.3996944348159417, -160.0072809855143134 70.3992411295572964, -160.0079434409041426 70.3970957783998159, -160.0082397460937500 70.3969421386718750, -160.0081384179545125 70.3964643483486583, -160.0093163384331660 70.3926496717665060, -160.0156836615668396 70.3906836615668539, -160.0173568022463257 70.3852649625993791, -160.0385742187500000 70.3836059570312500, -160.0591735839843750 70.3780059814453125, -160.0592498779296875 70.3741760253906250, -160.0464782714843750 70.3732147216796875, -160.0466308593750000 70.3704605102539062, -160.0604248046875000 70.3670120239257812, -160.0622307572400587 70.3661611180114193, -160.0656014336479984 70.3659498426649321, -160.0660989553873890 70.3643385492640903, -160.0821228027343750 70.3567886352539062, -160.0834655761718750 70.3504791259765625, -160.0841719822707887 70.3502086271622744, -160.0989347669813299 70.3492831759982664, -160.1000140093981940 70.3457881241746037, -160.1129784330251766 70.3435309254181220, -160.1177673339843750 70.3426971435546875, -160.1500051955506194 70.3437551591474062, -160.1761169433593750 70.3446121215820312, -160.1820831298828125 70.3428268432617188, -160.1412811279296875 70.3374710083007812, -160.1221313476562500 70.3391189575195312, -160.1085354621890531 70.3374973958521821, -160.1357577853732437 70.3371466742621578, -160.1392422146267052 70.3336866590711907, -160.1440911187065694 70.3329800075954950, -160.1475755479600593 70.3295199924045278, -160.1499999999999773 70.3291666666666799, -160.1496466742621294 70.3267422146267478, -160.1457704678962841 70.3228535999887043, -160.1464233398437500 70.3224487304687500, -160.1481018066406250 70.3204193115234375, -160.1419648259427504 70.3187125772465151, -160.1416666666666515 70.3166666666666771, -160.1440911187065694 70.3163133409288292, -160.1455615517751028 70.3148532106221609, -160.1524047851562500 70.3132247924804688, -160.1731258360557035 70.3038236832779262, -160.1732577853732380 70.3038133409288264, -160.1733489691119132 70.3037224481505092, -160.1794281005859375 70.3009643554687500, -160.1896003127014581 70.2955054140337836, -160.1899244520399179 70.2954800075954864, -160.1902464758053668 70.2951586490920448, -160.2432681694295411 70.2667044331368515, -160.2482577853732550 70.2663133409288321, -160.2491019520068392 70.2654750890478397, -160.2581024169921875 70.2636108398437500, -160.2630157470703125 70.2613449096679688, -160.2735748291015625 70.2553558349609375, -160.2761888700981956 70.2509027931929921, -160.2779235839843750 70.2479476928710938, -160.2681579589843750 70.2473831176757812, -160.2635040283203125 70.2541351318359375, -160.2466278076171875 70.2614593505859375, -160.2322235107421875 70.2650909423828125, -160.2155761718750000 70.2756195068359375, -160.1850433349609375 70.2874603271484375, -160.1462097167968750 70.3105239868164062, -160.1375274658203125 70.3115005493164062, -160.1333333333332973 70.3135017715816844, -160.1208343505859375 70.3194656372070312, -160.1040039062500000 70.3240127563476562, -160.0967840009483325 70.3250899815801631, -160.0760526869032105 70.3256700303819571, -160.0752511884767273 70.3283322969502080, -160.0668996962055530 70.3333095903322771, -160.0591047498914747 70.3341047498914946, -160.0586865393359801 70.3382044390617551, -160.0571136474609375 70.3391418457031250, -160.0571289062500000 70.3411407470703125, -160.0571746826171875 70.3463821411132812, -160.0500471323438205 70.3496318950801367, -160.0260479397243785 70.3506859673394160, -160.0246305698019853 70.3553935987190471, -160.0215911865234375 70.3553619384765625, -160.0122132726726250 70.3583509414070960, -160.0010426839192519 70.3590369330512289, -160.0000853759974859 70.3622164406300641, -160.0000000000000000 70.3622436523437500, -159.9973602294921875 70.3630828857421875, -159.9857482910156250 70.3647384643554688, -159.9813385047624195 70.3670450472822040, -159.9760426839192746 70.3673702663845546, -159.9751690038058882 70.3702720666331913, -159.9657877522629690 70.3751790243399284, -159.9633081850181497 70.3750308800864133, -159.9543609619140625 70.3716125488281250, -159.9491833301713086 70.3681206576527813, -159.9489698621961793 70.3674116346571310, -159.9479827141537953 70.3673109398735335, -159.9241099966595812 70.3512107350518505, -159.9240358140733349 70.3509643554687614, -159.9235098183070249 70.3508059636047847, -159.9169616699218750 70.3463897705078125, -159.9168132865604548 70.3463202782209720, -159.9156239827473769 70.3423702663845631, -159.9072857567877293 70.3418582561619274, -159.8976898193359375 70.3373641967773438, -159.8993072509765625 70.3342666625976562, -159.9016152280907477 70.3331685967571048, -159.9073031955294937 70.3325883653428860, -159.9080502736945846 70.3301069963120824, -159.9295349121093750 70.3198852539062500, -159.9259643554687500 70.3122177124023438, -159.9223937988281250 70.3099060058593750, -159.9165344238281250 70.3061218261718750, -159.9056091308593750 70.3029098510742188, -159.9066162109375000 70.2997741699218750, -159.9157104492187500 70.2956314086914062, -159.9101409912109375 70.2942352294921875, -159.8964080810546875 70.2963943481445312, -159.8881683349609375 70.2952651977539062, -159.8875732421875000 70.2879867553710938, -159.8997802734375000 70.2850952148437500, -159.8980255126953125 70.2751998901367188, -159.9039154052734375 70.2723541259765625, -159.9139404296875000 70.2712478637695312, -159.9151916503906250 70.2664260864257812, -159.8931427001953125 70.2567977905273438, -159.8773040771484375 70.2522277832031250, -159.8710937500000000 70.2520675659179688, -159.8531951904296875 70.2514190673828125, -159.8463961890863914 70.2491673929405351, -159.8414001464843750 70.2475128173828125, -159.8300170898437500 70.2308502197265625, -159.8236236572265625 70.2274780273437500, -159.8099365234375000 70.2260131835937500, -159.7902832031250000 70.2120437622070312, -159.7767639160156250 70.1971588134765625, -159.7745056152343750 70.1859436035156250, -159.7653198242187500 70.1843185424804688, -159.7568008977869454 70.1797294779442780, -159.7565911187065808 70.1795199924045221, -159.7563455963188233 70.1794842113796165, -159.7550659179687500 70.1787948608398438, -159.7542296198355700 70.1791758411005162, -159.7509460449218750 70.1806716918945312, -159.7534332275390625 70.1878509521484375, -159.7670593261718750 70.1929473876953125, -159.7695312500000000 70.1977844238281250, -159.7554168701171875 70.2007598876953125, -159.7603607177734375 70.2044677734375000, -159.7590942382812500 70.2176055908203125, -159.7701721191406250 70.2204055786132812, -159.7847900390625000 70.2272567749023438, -159.7902679443359375 70.2335586547851562, -159.8325805664062500 70.2499618530273438, -159.8383636474609375 70.2569198608398438, -159.8397064208984375 70.2627487182617188, -159.8278503417968750 70.2769470214843750, -159.8277130126953125 70.2880172729492188, -159.8283233642578125 70.2887191772460938, -159.8324279785156250 70.2934112548828125, -159.8507843017578125 70.3004760742187500, -159.8573338197330713 70.3048582971549365, -159.8573410796615235 70.3048631547070499, -159.8578635479240688 70.3066903670914201, -159.8558654785156250 70.3076019287109375, -159.8307189941406250 70.3086471557617188, -159.8086547851562500 70.3062515258789062, -159.8021697998046875 70.3077774047851562, -159.8023071289062500 70.3099136352539062, -159.8352813720703125 70.3131790161132812, -159.8412780761718750 70.3173751831054688, -159.8391909831912585 70.3244646735475953, -159.8326653374565751 70.3265306260850735, -159.8334486142531716 70.3439704981944516, -159.8316650390625000 70.3500289916992188, -159.8338241287316350 70.3523314307644227, -159.8340445624457402 70.3572394476996550, -159.8402768163971643 70.3592125345782335, -159.8408036749281393 70.3597743730608585, -159.8427412245008554 70.3658942328559078, -159.8559954163540340 70.3673046616428337, -159.8574399592656903 70.3680114101975818, -159.8594078911675354 70.3742275661892478, -159.8731298973524986 70.3756877768721694, -159.8740395418763001 70.3761328241929078, -159.8760019938150947 70.3823313395182311, -159.8840013292100650 70.3848639594184107, -159.8830462077743562 70.3942143284155861, -159.8760768674642350 70.3998853325593785, -159.8674682617187273 70.4008015950520871, -159.8659581907011784 70.4149911227805489, -159.8649621430305388 70.4158872054498914, -159.8590632120768191 70.4177547878689296, -159.8578558860228895 70.4366316225165434, -159.8295288085937500 70.4367980957031250, -159.8220672607421875 70.4389114379882812, -159.8199475474874021 70.4422912030111803, -159.8177636040581433 70.4423689100477475, -159.8165606615060597 70.4461681874133916, -159.8007049560546875 70.4540328979492188, -159.8021746648878434 70.4589641147802865, -159.8007120768229186 70.4594272189670221, -159.7995133024142262 70.4856443815166642, -159.7972106933593750 70.4881134033203125, -159.7870358800602162 70.4919158076994705, -159.7625074917552297 70.4910717190257543, -159.7635979301503539 70.4829857905983914, -159.7673346625433908 70.4818027072482778, -159.7657053629557140 70.4760148790147696, -159.7645858044466536 70.4756604057893838, -159.7652893066406250 70.4704437255859375, -159.7572021484375000 70.4665451049804688, -159.7075958251953125 70.4642028808593750, -159.6923675537109375 70.4617843627929688, -159.6872558593750000 70.4582824707031250, -159.6896209716796875 70.4503250122070312, -159.6839752197265625 70.4502029418945312, -159.6750030517578125 70.4562606811523438, -159.6635437011718750 70.4574813842773438, -159.6598865782578116 70.4590326985690183, -159.6594219631618898 70.4590616861979271, -159.6593604843950516 70.4592558622272378, -159.6503601074218750 70.4630737304687500, -159.6388244628906250 70.4608840942382812, -159.5971527099609375 70.4662322998046875, -159.5955086495526700 70.4671439433644196, -159.5844353569878251 70.4673526340060903, -159.5823313395182197 70.4739980061848996, -159.5760019938150833 70.4760019938151174, -159.5751021846660080 70.4788441155548639, -159.5710144042968750 70.4780654907226562, -159.5581970214843750 70.4794158935546875, -159.5440216064453125 70.4832382202148438, -159.5307464599609375 70.4830627441406250, -159.5281896951975114 70.4839682649943455, -159.5260988023545963 70.4840291341145928, -159.5258564648467825 70.4847946174102304, -159.5204925537109375 70.4866943359375000, -159.5124390185941934 70.4921165467203537, -159.5094078911675126 70.4924391004774407, -159.5087165824826343 70.4946227546066950, -159.5008668425938367 70.4999077559943714, -159.4927412245008611 70.5007724338107664, -159.4918955017988651 70.5034438593235677, -159.4821319580078125 70.5067214965820312, -159.4774322509765625 70.5060043334960938, -159.4770050048828125 70.5021438598632812, -159.4625396728515625 70.5029602050781250, -159.4624272995735907 70.5029827078622020, -159.4617801242404482 70.4924431694878564, -159.4541666666666515 70.4916666666666742, -159.4538085937499829 70.4941236707899463, -159.4482577853732437 70.4996466742621664, -159.4458333333333258 70.5000000000000142, -159.4433781941731638 70.4996422661675410, -159.4409750242846258 70.4972325799776911, -159.4350585937500000 70.4799423217773438, -159.4385070800781250 70.4748229980468750, -159.4331970214843750 70.4740676879882812, -159.4317529759928789 70.4755065250199237, -159.4162750244140625 70.4909286499023438, -159.4089050292968750 70.4938888549804688, -159.3882141113281250 70.4955902099609375, -159.3704681396484375 70.5000305175781250, -159.3635892084686816 70.5031848648242487, -159.3423203776488606 70.5129377284845305, -159.3353933161941711 70.5128312206063299, -159.3255920410156250 70.5119552612304688, -159.3188162769413907 70.5125763383175865, -159.3005280816670393 70.5122951459407545, -159.3000793457031250 70.5073699951171875, -159.2950286865234375 70.5038604736328125, -159.2863616943359375 70.5022506713867188, -159.2825164794921875 70.5045700073242188, -159.2892608642578125 70.5107498168945312, -159.2872674417421024 70.5120912553543491, -159.2868805065615447 70.5120853059852806, -159.2780914306640625 70.5113296508789062, -159.2768683047203524 70.5119313621547974, -159.2657775878906250 70.5173873901367188, -159.3458251953125000 70.5168380737304688, -159.3700256347656250 70.5100250244140625, -159.4018402099609375 70.5066680908203125, -159.4381806232519523 70.5099643727143501, -159.4461669921875000 70.5106887817382812, -159.4582366943359375 70.5084533691406250, -159.4609832763671875 70.5092620849609375, -159.4587707519531250 70.5144500732421875, -159.4619353486277475 70.5139963259248645, -159.4668745771983538 70.5132881277107089, -159.4676079644097229 70.5160681830512175, -159.5231991149358919 70.5170841726592386, -159.5199432373046875 70.5179977416992188, -159.5254364013671875 70.5196151733398438, -159.5408172607421875 70.5171432495117188, -159.5483398437500000 70.5124664306640625, -159.5514221191406250 70.5105438232421875, -159.5461730957031250 70.5014877319335938, -159.5491685309393119 70.5010150148103776, -159.5509406195746465 70.5077317979600764, -159.6070810953775947 70.5089131673177150, -159.6075330474425584 70.5072000393323037, -159.6207733154296875 70.4990005493164062, -159.6168800234653986 70.4893244337132074, -159.6173463609483463 70.4842054578993213, -159.6237477620442462 70.4827534993489735, -159.6259357028537238 70.4910471598307424, -159.6570810953776061 70.4922465006510492, -159.6590514718765235 70.4847779027420387, -159.6615362323906027 70.4838066878863145, -159.6724771629287432 70.4828630827068281, -159.6719970703125000 70.4854812622070312, -159.6745450309478542 70.4857754494428121, -159.6759396023220461 70.4910614013671903, -159.7237477620442689 70.4922465006510492, -159.7253417315310173 70.4862045417668384, -159.7328238520922241 70.4855689247288808, -159.7342030843098826 70.4907969156901117, -159.7407969156900833 70.4925364176432367, -159.7425364176432083 70.4991302490234517, -159.7491302490234375 70.5008697509765767, -159.7508697509765625 70.5074635823567775, -159.7574635823567633 70.5092030843099025, -159.7592646280924384 70.5160295274522610, -159.7782664776273123 70.5170760424453391, -159.7827955195436402 70.5187951153213106, -159.7842544555663835 70.5243245442708400, -159.7990788777669309 70.5256754557291714, -159.8009211222330634 70.5326578776041799, -159.8157455444335824 70.5340087890625114, -159.8175364176432254 70.5407969156901089, -159.8243630303276746 70.5425977918836935, -159.8256369696723027 70.5657355414496692, -159.8324635823567519 70.5675364176432396, -159.8342030843098769 70.5741302490234403, -159.8409913804795792 70.5759209526909785, -159.8411779296381781 70.5779686376555020, -159.8393707275390625 70.5813598632812500, -159.8328552246093750 70.5779876708984375, -159.8304919215405562 70.5779275869221152, -159.8169737287505825 70.5775839040545634, -159.8134372287326244 70.5744327121310846, -159.8019561767578125 70.5755672878689353, -159.7999764885421428 70.5774046692061603, -159.7949981689453125 70.5782928466796875, -159.7971198078381860 70.5800560017596155, -159.7972106933593750 70.5801315307617188, -159.8146667480468750 70.5809555053710938, -159.8329772949218750 70.5873641967773438, -159.8370056152343750 70.5905838012695312, -159.8418700159244565 70.5910648213934877, -159.8424835205078125 70.5911254882812500, -159.8483581542968750 70.5848693847656250, -159.8493930790312447 70.5851997183000321, -159.8509355333116275 70.5910461425781364, -159.8794194333511882 70.5921697072769518, -159.8828878828906568 70.5941448846655248, -159.8842030843098883 70.5991302490234460, -159.8893107971621816 70.6004777018123093, -159.8913256023811016 70.6028738136264167, -159.8925364176432140 70.6074635823567860, -159.8991302490234148 70.6092030843099110, -159.9009355333116105 70.6160461425781278, -159.9219507129646445 70.6168750990751306, -159.9327100352054458 70.6184707194074406, -159.9342688666449703 70.6243794759114678, -159.9657311333550354 70.6256205240885464, -159.9676079644097229 70.6327348497178917, -159.9840852477242379 70.6330359902493825, -159.9738616943359375 70.6378173828125000, -159.9794616699218750 70.6381378173828125, -159.9940323294213158 70.6332177841417348, -160.0320810953776061 70.6339131673177150, -160.0335787657286346 70.6282366955019540, -160.0396423339843750 70.6271743774414062, -160.0442704660728168 70.6250860739380926, -160.0574020385742244 70.6243628607855953, -160.0589563275058538 70.6184722387249764, -160.0618695057885930 70.6171603438691733, -160.0824020385742017 70.6160295274522696, -160.0842030843098769 70.6092030843099110, -160.0909913804796076 70.6074123806423728, -160.0914994874014496 70.6018349026595473, -160.0976028021570130 70.5913465311878667, -160.0987477620442689 70.5910868326823078, -160.1008811102973084 70.5991733127170278, -160.1020868414236134 70.5994468434513607, -160.1009826660156250 70.6015701293945312, -160.1173248291015625 70.6020889282226562, -160.1188507080078125 70.6040878295898438, -160.1264495849609375 70.6017608642578125, -160.1292115778481957 70.6000118132574102, -160.1337710910373175 70.6012145996093778, -160.1324912177191777 70.6076914469401089, -160.1092646280924328 70.6089704725477532, -160.1074635823567576 70.6157969156901117, -160.1008697509765568 70.6175364176432367, -160.0990687052408816 70.6243628607855953, -160.0759312947591013 70.6256371392144189, -160.0740687052408759 70.6326961941189353, -160.0509312947590956 70.6339704725477588, -160.0490788777669309 70.6409912109375142, -160.0342544555664119 70.6423421223958456, -160.0324122111002509 70.6493245442708400, -160.0175877888997320 70.6506754557291714, -160.0157455444335994 70.6576578776041799, -160.0009211222330521 70.6590087890625114, -159.9990788777669195 70.6659912109375057, -159.9842544555664006 70.6673421223958371, -159.9824020385742074 70.6743628607856067, -159.9592646280924271 70.6756371392144160, -159.9574122111002623 70.6826578776041714, -159.9425877888997434 70.6840087890625171, -159.9407311333550297 70.6910461425781307, -159.9249999999999829 70.6916666666666771, -159.9242233276366960 70.6992801242404596, -159.9010426839192576 70.7007035997178974, -159.8989520602756045 70.7076473659939353, -159.8677146063910470 70.7090193006727503, -159.8656239827473939 70.7159630669487882, -159.8427093505859204 70.7173702663845631, -159.8406239827473883 70.7242964002821282, -159.8177093505859148 70.7257035997178889, -159.8156365288628251 70.7325883653428917, -159.8010301378038207 70.7340783013237910, -159.7989573160807311 70.7409630669487939, -159.7760426839192576 70.7423702663845546, -159.7739573160807254 70.7492964002821338, -159.7510426839192519 70.7507035997178946, -159.7489698621961622 70.7575883653428974, -159.7343634711371294 70.7590783013237967, -159.7323031955295107 70.7659216986762232, -159.7176968044704779 70.7674116346571225, -159.7156365288628308 70.7742550320095631, -159.7010301378037980 70.7757449679904624, -159.6989698621961793 70.7825883653428889, -159.6843634711371465 70.7840783013238024, -159.6822906494140568 70.7909630669487910, -159.6593760172525833 70.7923702663845660, -159.6572906494140511 70.7992964002821310, -159.6343760172526061 70.8007035997178917, -159.6322825113932140 70.8076568603515710, -159.5927174886067519 70.8090098063151174, -159.5906158447265568 70.8159901936849110, -159.5510508219400947 70.8173431396484432, -159.5489473130967895 70.8243299696180628, -159.5010526869031935 70.8256700303819571, -159.4989473130967781 70.8326633029514028, -159.4510526869032105 70.8340033637152828, -159.4489459567599567 70.8410007052951443, -159.3927207099066834 70.8423326280382071, -159.3906126234266480 70.8493340386284842, -159.3343873765733463 70.8506659613715328, -159.3318852742512775 70.8589762369791742, -159.3176983303493728 70.8575931125217124, -159.3154879936211330 70.8502518204674772, -159.2643851511340642 70.8586238046427752, -159.2826114230685732 70.8590311686198078, -159.2828850640190694 70.8659349229600792, -159.2507709079318374 70.8672078450520928, -159.2505177815754962 70.8608188205295306, -159.2507302768226793 70.8602125184035003, -159.2433166503906250 70.8600463867187500, -159.2297668457031250 70.8621978759765625, -159.2165985107421875 70.8647918701171875, -159.1899871826171875 70.8625030517578125, -159.1835174560546875 70.8636016845703125, -159.1805114746093750 70.8597869873046875, -159.1834506397768507 70.8585718778956135, -159.1677098592122377 70.8576314290364735, -159.1657024807400092 70.8509643554687614, -159.1592975192599795 70.8490356445312557, -159.1573031955294937 70.8424116346571253, -159.1426968044704608 70.8409216986762260, -159.1407023111979129 70.8342976888020956, -159.1342976888020644 70.8323689778645900, -159.1323689778645587 70.8259643554687557, -159.1243570963541458 70.8235521104600849, -159.1260080973307254 70.8173190646701443, -159.1511802704342813 70.8170838501441295, -159.1338653564453125 70.8157043457031250, -159.1170806884765625 70.8178558349609375, -159.0931701660156250 70.8155059814453125, -159.0893249511718750 70.8165435791015625, -159.0794067382812500 70.8101577758789062, -159.0744323730468750 70.7974700927734375, -159.0654144287109375 70.7962646484375000, -159.0437927246093750 70.7989578247070312, -159.0235443115234375 70.7970352172851562, -158.9989624771594094 70.7926359269649481, -159.0011247422959855 70.7992987738715414, -159.0673472086588447 70.8007405598958428, -159.0657158745659672 70.8173472086588589, -159.0261203342013800 70.8159525553385549, -159.0238800048827841 70.8090484619140739, -158.9844533284505133 70.8076182047526146, -158.9822079128689154 70.8006988525390710, -158.9094587537977361 70.7993011474609517, -158.9067603217230840 70.7909861246744896, -158.5761298285590044 70.7923509385850735, -158.5734269883897412 70.8006805419921932, -158.5427836100260208 70.7992757161458428, -158.5400936550564097 70.7909861246744896, -158.5094502766926894 70.7923909505208400, -158.5072163899739337 70.7992750379774378, -158.4761169433593579 70.8007249620225849, -158.4734269883897468 70.8090138753255331, -158.4508229573567633 70.8075734456380275, -158.4499999999999886 70.8000000000000114, -158.3842546251084968 70.8005764431423756, -158.3824337429470575 70.8076721191406335, -158.3675662570529425 70.8089945475260549, -158.3658157348632756 70.8158159044053974, -158.3591842651367188 70.8175174289279568, -158.3571183946397412 70.8255672878689353, -158.3508619520399350 70.8241923014323049, -158.3490907457139656 70.8172902425130388, -158.3259092542860174 70.8160430908203296, -158.3237850613064097 70.8077660454644189, -158.3175286187066035 70.8091410319010492, -158.3157453748914918 70.8160902235243128, -158.1842546251085082 70.8172431098090414, -158.1824125501844662 70.8244215223524378, -158.0759207831488595 70.8255784776475821, -158.0740805731879277 70.8327494303385521, -158.0009194268120609 70.8339172363281335, -157.9990829467773494 70.8410739474826556, -157.9509170532226392 70.8422593858507099, -157.9490829467773381 70.8494072808159814, -157.9009170532226562 70.8505927191840357, -157.8990829467773267 70.8577406141493213, -157.8509170532226449 70.8589260525173756, -157.8490843031141537 70.8660681830512260, -157.8092490302191777 70.8672651502821225, -157.8074176364474681 70.8744015163845660, -157.7675823635525205 70.8755984836154624, -157.7657533433702213 70.8827256944444599, -157.7342466566297503 70.8839409722222342, -157.7324200100368898 70.8910590277777857, -157.7009133232964189 70.8922743055555742, -157.6990907457139599 70.8993764241536581, -157.6759092542860117 70.9006235758463674, -157.6740907457139542 70.9077097574869981, -157.6509092542860060 70.9089569091796932, -157.6490866767035470 70.9160590277777914, -157.6175799899631045 70.9172743055555657, -157.6157533433702156 70.9243923611111171, -157.5842466566297730 70.9256076388889056, -157.5824200100368842 70.9327256944444571, -157.5509133232964416 70.9339409722222314, -157.5490907457139542 70.9410430908203296, -157.5259092542860060 70.9422902425130388, -157.5240866767035470 70.9493923611111228, -157.4925799899631045 70.9506076388888971, -157.4907574123806171 70.9577097574869953, -157.4675759209526689 70.9589569091797046, -157.4657574123806398 70.9660430908203210, -157.4425759209526916 70.9672902425130303, -157.4407670762803662 70.9743387858073049, -157.4258995903862797 70.9756612141927263, -157.4240907457139542 70.9827097574869867, -157.4009092542860060 70.9839569091796960, -157.3990907457139770 70.9910430908203267, -157.3759092542860003 70.9922902425130360, -157.3740907457139713 70.9993764241536525, -157.3509092542860230 71.0006235758463617, -157.3490907457139656 71.0077097574869924, -157.3259092542860174 71.0089569091797017, -157.3240907457139599 71.0160430908203182, -157.3009092542860117 71.0172902425130275, -157.2991004096137146 71.0243387858073021, -157.2842329237195997 71.0256612141927235, -157.2824337429470347 71.0326721191406421, -157.2675662570529482 71.0339945475260492, -157.2657670762803548 71.0410054524739678, -157.2508995903862683 71.0423278808593892, -157.2491004096137033 71.0493387858073078, -157.2342329237196168 71.0506612141927150, -157.2324824015299214 71.0574825710720575, -157.2258509318033646 71.0591840955946310, -157.2241004096136976 71.0660054524739735, -157.2092329237196111 71.0673278808593949, -157.2074337429470461 71.0743387858072992, -157.1925662570529312 71.0756612141927206, -157.1908157348632642 71.0824825710720631, -157.1841842651367074 71.0841840955946367, -157.1824337429470404 71.0910054524739650, -157.1675662570529255 71.0923278808593864, -157.1657670762803605 71.0993387858073049, -157.1508995903862740 71.1006612141927263, -157.1491492377386976 71.1074825710720688, -157.1425174289279312 71.1091840955946282, -157.1407670762803548 71.1160054524739706, -157.1258995903862683 71.1173278808593921, -157.1241004096137033 71.1243387858073106, -157.1092329237196168 71.1256612141927178, -157.1074825710720404 71.1324825710720603, -157.1008507622612740 71.1341840955946338, -157.0991004096136976 71.1410054524739763, -157.0842329237196111 71.1423278808593835, -157.0825581359355567 71.1488535080694930, -157.0825805664062500 71.1488800048828125, -157.0825479265652689 71.1488932877628741, -157.0824198404947651 71.1493923611111256, -157.0812065614184974 71.1494391602868319, -157.0751190185546875 71.1519165039062500, -157.0664449542050818 71.1521733668596568, -157.0658952501084968 71.1575619167751938, -157.0510301378037923 71.1590783013238024, -157.0489698621961736 71.1659216986762289, -157.0343634711371408 71.1674116346571282, -157.0323689778645644 71.1740358140733633, -157.0259643554687443 71.1759641859266594, -157.0239698621961679 71.1825883653428946, -157.0093634711371351 71.1840783013237939, -157.0073031955294880 71.1909216986762345, -156.9926968044704836 71.1924116346571338, -156.9906365288628365 71.1992550320095603, -156.9760301378038037 71.2007449679904596, -156.9739698621961566 71.2075883653429003, -156.9593634711371237 71.2090783013237996, -156.9573031955295050 71.2159216986762260, -156.9426968044704722 71.2174116346571395, -156.9406365288628251 71.2242550320095660, -156.9260301378037923 71.2257449679904653, -156.9239698621961736 71.2325883653428917, -156.9093634711371408 71.2340783013238052, -156.9073689778645644 71.2407024807400262, -156.9009643554687443 71.2426308525933365, -156.8989573160807254 71.2492964002821338, -156.8760426839192519 71.2507035997178946, -156.8739698621961622 71.2575883653428974, -156.8593634711371294 71.2590783013237967, -156.8573031955295107 71.2659216986762232, -156.8426968044704779 71.2674116346571367, -156.8406365288628308 71.2742550320095631, -156.8260301378037980 71.2757449679904624, -156.8239698621961509 71.2825883653429031, -156.8093634711371465 71.2840783013238024, -156.8072906494140568 71.2909630669488052, -156.7843760172525833 71.2923702663845660, -156.7823689778645644 71.2990358140733633, -156.7791666666666401 71.3000000000000114, -156.7594533284504905 71.3007149590386433, -156.7572224934895644 71.3075902303060047, -156.7344441731770530 71.3090764363606979, -156.7322224934895587 71.3159235636393447, -156.7094441731770758 71.3174097696940237, -156.7072875976562329 71.3240558200412522, -156.7009792751735802 71.3256805419921989, -156.6991770426432140 71.3090930514865562, -156.6764784071180259 71.3076527913411553, -156.6743194580078011 71.3150936550564438, -156.6825568305121408 71.3177668253580919, -156.6840138753254905 71.3324734157986313, -156.6594441731770644 71.3340764363606894, -156.6572214762369697 71.3409267849392563, -156.6343126085069173 71.3423472086588646, -156.6325103759765511 71.3257597181532219, -156.6098117404513630 71.3243194580078210, -156.6076527913411383 71.3317603217231095, -156.6158901638454779 71.3344334920247576, -156.6173472086588276 71.3491488986545335, -156.5926459418402601 71.3506805419922046, -156.5908440483940751 71.3340952555338674, -156.5674892849392279 71.3325714111328324, -156.5658803304036155 71.3177636040581717, -156.5593543158636862 71.3156458536784044, -156.5572363959418283 71.3091195000542655, -156.5427636040581376 71.3075471666124230, -156.5406456841362797 71.3010208129882983, -156.5343543158637090 71.2989791870117386, -156.5322133382161383 71.2923816257053033, -156.4927866617838390 71.2909517076280537, -156.4905463324652715 71.2840477837456774, -156.4515730116102361 71.2826527913411638, -156.4489017062716698 71.2908845689561730, -156.4349063449435562 71.2923472086588674, -156.4323123508029312 71.2843541463216326, -156.4260209825303605 71.2823125203450729, -156.4239030626084741 71.2757861667209340, -156.4094302707248119 71.2742138332790915, -156.4072163899739394 71.2673916286892535, -156.3761169433593636 71.2659417046441064, -156.3738739013671761 71.2590299818251083, -156.2932396782768762 71.2576527913411581, -156.2905463324652544 71.2659522162543482, -156.2515730116102191 71.2673472086588617, -156.2488745795355669 71.2590320163303090, -156.1761254204643876 71.2576346503363851, -156.1738891601562216 71.2507431030273608, -156.1511108398437386 71.2492568969726676, -156.1488745795355726 71.2423653496636433, -156.0760331895615991 71.2409662882487140, -156.0743194580077784 71.2343126085069542, -156.0908562554253365 71.2325159708659044, -156.0923472086588220 71.2181450737847399, -156.0849063449435619 71.2159861246744867, -156.0822994656032847 71.2240188598632926, -156.0765730116102077 71.2256805419922046, -156.0738891601562273 71.2174097696940294, -156.0511108398437159 71.2159235636393362, -156.0489030626084741 71.2091195000542712, -156.0341447618272355 71.2075161404080035, -156.0326527913411212 71.1932396782769246, -156.0406456841362512 71.1906458536784044, -156.0426876491970347 71.1843541463216241, -156.0489790174696054 71.1823125203450644, -156.0511199951171761 71.1757149590386433, -156.0910990397135265 71.1742650349935104, -156.0909583197699533 71.1673704359266566, -156.0099063449435448 71.1659861246744896, -156.0072363959418169 71.1742138332790972, -155.9927636040581262 71.1757861667209397, -155.9905497233072538 71.1826083713107778, -155.9591583251952898 71.1840718587239678, -155.9575469970702954 71.1989030626085224, -155.9510209825303662 71.2010208129882898, -155.9488830566405966 71.2076090494791742, -155.9182396782768762 71.2090138753255388, -155.9155697292751483 71.2007861667209312, -155.9007619222005019 71.1991773817274520, -155.8992340087890511 71.1757614135742358, -155.8759792751735915 71.1743194580078296, -155.8749999999999716 71.1833333333333513, -155.8427215576171534 71.1839962429470603, -155.8402187771267222 71.1923094007704123, -155.7343905978732437 71.1910118950737996, -155.7322767469617872 71.1839904785156392, -155.6424492730034501 71.1826722886827383, -155.6416666666666515 71.1750000000000114, -155.5843909369574476 71.1743460761176294, -155.5823031955295050 71.1674116346571282, -155.5673645019531079 71.1658877902560931, -155.5659806993272412 71.1343814425998460, -155.5592975192599852 71.1323689778646013, -155.5573691474066607 71.1259643554687671, -155.5509641859266310 71.1240356445312614, -155.5490358140733349 71.1176310221354271, -155.5426308525933052 71.1157023111979356, -155.5406365288628479 71.1090783013237910, -155.5260301378038150 71.1075883653428917, -155.5240358140733292 71.1009643554687614, -155.5174116346570941 71.0989698621961992, -155.5159216986762090 71.0843634711371664, -155.5076905992295906 71.0818854437934107, -155.5092554728190066 71.0759769015842124, -155.5157024807400035 71.0740356445312642, -155.5176968044704608 71.0674116346571338, -155.5323031955294937 71.0659216986762345, -155.5343760172525833 71.0590369330512317, -155.5572906494140568 71.0576297336154710, -155.5593760172525890 71.0507035997178917, -155.5822906494140625 71.0492964002821310, -155.5842975192599624 71.0426310221354242, -155.5907024807399921 71.0407023111979328, -155.5931147257486771 71.0326904296875057, -155.6073016696506102 71.0340735541449817, -155.6097813924153570 71.0423095703125114, -155.6322901407877453 71.0409647623698106, -155.6343634711371351 71.0340783013238024, -155.6492285834418396 71.0325619167751796, -155.6507809109157847 71.0173444959852560, -155.6989473130967667 71.0159966362847399, -155.7009641859266367 71.0092976888020928, -155.7075883653428718 71.0073031955295306, -155.7090783013237854 70.9926968044704978, -155.7157024807400205 70.9907023111979356, -155.7181147257486771 70.9826904296875085, -155.7489517211913892 70.9840186225043510, -155.7514480590820085 70.9923095703125142, -155.7656350029839416 70.9909264458550524, -155.7677093505859318 70.9840369330512289, -155.7906239827473769 70.9826297336154681, -155.7926308525933052 70.9759643554687614, -155.7990358140733349 70.9740356445312557, -155.8010301378038207 70.9674116346571253, -155.8156365288628251 70.9659216986762260, -155.8181147257486998 70.9576904296875171, -155.8240230984157790 70.9592556423611285, -155.8260301378037980 70.9659216986762260, -155.8406365288628308 70.9674116346571253, -155.8431147257486771 70.9756429036458485, -155.8656234741210938 70.9742980957031335, -155.8677247789170792 70.9673190646701499, -155.9989418877495666 70.9660142686632014, -156.0010301378038093 70.9590783013237996, -156.0083333333333258 70.9583333333333428, -156.0164635552300183 70.9575039333767421, -156.0159186469183794 70.9507215711805657, -155.9927093505859261 70.9492964002821367, -155.9907023111978788 70.9426310221354299, -155.9842976888020587 70.9407023111979242, -155.9823689778645530 70.9342976888020900, -155.9757449679904369 70.9323031955295278, -155.9742550320095233 70.9176968044704950, -155.9668982611761976 70.9154819064670221, -155.9674150254991218 70.9090528700086935, -155.9902187771266995 70.9076904296875057, -155.9927147759331376 70.9159806993272639, -156.0162753585201187 70.9170154805646149, -156.0185852050781250 70.9108352661132812, -156.0458526611328125 70.9115295410156250, -156.0530090332031250 70.9129562377929688, -156.0829252815353243 70.9123336153657533, -156.0833022233963447 70.9086383155009941, -156.0817565917968750 70.9087066650390625, -156.0807036597872468 70.9083066585004786, -156.0177480061848598 70.9076680501302263, -156.0168202600663960 70.9046636562145096, -156.0060424804687500 70.9009246826171875, -156.0070558843460731 70.9004967707923157, -155.9510779486761862 70.8993245442708400, -155.9490169949001483 70.8926496717665060, -155.9426496717664747 70.8906836615668539, -155.9406836615668226 70.8843163384331660, -155.9343163384331490 70.8823503282335139, -155.9323503282334968 70.8759830050998403, -155.9243445502386862 70.8735110812717153, -155.9260050455728788 70.8674302842882042, -155.9423221164279312 70.8657301161024407, -155.9406873914930429 70.8590555826823021, -155.9160112169053605 70.8575086805555685, -155.9176391601562273 70.8507225884331717, -155.9423221164279312 70.8491753472222285, -155.9407626681857266 70.8426740858290032, -155.9326778835720120 70.8401777479383838, -155.9343634711371180 70.8340053982204978, -155.9749999999999659 70.8333333333333428, -155.9743299696180259 70.8093861897786496, -155.9676310221353788 70.8073689778645985, -155.9657023111979015 70.8009643554687642, -155.9592976888020530 70.7990356445312585, -155.9573031955294766 70.7924116346571282, -155.9410237630208087 70.7907511393229214, -155.9425591362847001 70.7843190511067775, -155.9490356445312216 70.7823689778645928, -155.9509643554687273 70.7759643554687585, -155.9589762369791401 70.7735521104600735, -155.9575581868489280 70.7590057373047046, -155.9291666666666458 70.7583333333333400, -155.9249999999999829 70.7583333333333400, -155.8927215576171648 70.7589962429470631, -155.8907024807400035 70.7657023111979271, -155.8826905992295906 70.7681145562066121, -155.8842554728190066 70.7740230984158103, -155.8907024807400035 70.7759643554687585, -155.8926968044704893 70.7825883653428889, -155.9073031955294937 70.7840783013238024, -155.9092975192599795 70.7907023111979328, -155.9157024807400092 70.7926310221354242, -155.9176308525933052 70.7990356445312585, -155.9256427341037181 70.8014478895399435, -155.9242272271050354 70.8159684922960224, -155.8927146063910527 70.8173526340060846, -155.8907024807400035 70.8240356445312642, -155.8842975192599738 70.8259643554687557, -155.8822733561197822 70.8326873779297017, -155.6833333333333371 70.8333333333333428, -155.6824362860785413 70.8245388454861171, -155.6668665568033703 70.8257900661892421, -155.6674165513780395 70.8326341417100878, -155.6833333333333371 70.8333333333333428, -155.6840086195203980 70.8407457139757071, -155.6922465006510379 70.8429189046224081, -155.6905086941189040 70.8505798339843835, -155.6592692057291458 70.8493804931640767, -155.6574635823567689 70.8425364176432453, -155.6508697509765398 70.8407969156901203, -155.6491302490234148 70.8342030843099053, -155.6425364176432140 70.8324635823567803, -155.6407455444335710 70.8256754557291828, -155.6259211222330521 70.8243245442708513, -155.6240687052408873 70.8173038058810818, -155.6124999999999829 70.8166666666666771, -155.6083333333333201 70.8166666666666771, -155.6075883653428775 70.8239698621961935, -155.5993572658962592 70.8264478895399350, -155.6009221394856752 70.8323564317491474, -155.6075883653428775 70.8343634711371664, -155.6090783013237626 70.8489698621961850, -155.6173094007703810 70.8514478895399407, -155.6157631768120666 70.8673095703125142, -155.6093193901909615 70.8657748752170278, -155.6073031955295107 70.8590783013237910, -155.5924380832248062 70.8575619167751825, -155.5907511393229186 70.8410237630208428, -155.5677101982964246 70.8423672146267478, -155.5656187269422617 70.8493140326606010, -155.5343812730577042 70.8506859673394160, -155.5318852742512945 70.8589762369791742, -155.4924468994140625 70.8576483832465414, -155.4907511393228958 70.8410237630208428, -155.4843190511067519 70.8425591362847342, -155.4823031955295107 70.8492550320095660, -155.4749999999999943 70.8500000000000085, -155.4757865058051038 70.8575469970703296, -155.4923221164279425 70.8592698838975821, -155.4907569037543169 70.8656609429253592, -155.4826778835720233 70.8681555853949732, -155.4840315077039747 70.8989288330078296, -155.4909079657660413 70.9010521782769274, -155.4924253675672503 70.9156144883897639, -155.4990169949001597 70.9176496717665117, -155.5009830050998119 70.9240169949001853, -155.5089887830945941 70.9264889187283103, -155.5075951470269047 70.9493130154079950, -155.4510771009657049 70.9506788465711935, -155.4489476521809763 70.9575744628906335, -155.4343856811523210 70.9590922037760521, -155.4322681003146442 70.9659498426649407, -155.4093985663519959 70.9673834906684107, -155.4072809855143191 70.9742411295572992, -155.3927190144856638 70.9757588704427178, -155.3906836615668396 70.9823503282335224, -155.3843163384331376 70.9843163384331746, -155.3823503282334855 70.9906836615668482, -155.3759830050998119 70.9926496717665003, -155.3739220513237740 70.9993245442708485, -155.3094112820095347 71.0006754557291799, -155.3072625054253422 71.0076344807942803, -155.2760708279079722 71.0090321858724138, -155.2735109117295735 71.0173221164279624, -155.2593870374891480 71.0159125434027914, -155.2573503282334855 71.0093163384331660, -155.2509830050998119 71.0073503282335139, -155.2489347669813355 71.0007168240017421, -155.2260652330186588 70.9992831759982721, -155.2240169949001540 70.9926496717665003, -155.2176496717664804 70.9906836615668482, -155.2155887179904425 70.9840087890625142, -155.1833333333333087 70.9833333333333485, -155.1674763997395701 70.9840582953559220, -155.1658942328558908 70.9989254421658131, -155.1576653374565922 71.0015306260850849, -155.1592946370442689 71.0073184543185931, -155.1656646728515341 71.0093353271484489, -155.1676686604817519 71.0156646728515710, -155.1739980061848883 71.0176686604817888, -155.1760745578341982 71.0242275661892535, -155.1905921088324476 71.0257724338107721, -155.1927547878689211 71.0326032850477560, -155.2155785454643819 71.0340633816189353, -155.2177412245008554 71.0408942328559192, -155.2322587754991048 71.0424391004774378, -155.2344078911675069 71.0492275661892450, -155.2489254421657847 71.0507724338107778, -155.2510881212022298 71.0576032850477617, -155.2756679958767165 71.0591756184895900, -155.2742050170898267 71.0742513020833400, -155.2510881212022298 71.0757300482856067, -155.2489118787977418 71.0826032850477532, -155.2260881212022525 71.0840633816189325, -155.2239062839084056 71.0909545898437614, -155.1927603827582232 71.0923787434895900, -155.1905785454644047 71.0992699517144189, -155.1677547878689154 71.1007300482855982, -155.1651360405815865 71.1090013292100878, -155.1510759141710025 71.1075653076172074, -155.1489980061848826 71.1010019938151174, -155.1426686604817462 71.0989980061849138, -155.1406646728515568 71.0926686604817775, -155.1343353271484204 71.0906646728515739, -155.1323313395182026 71.0843353271484517, -155.1260019938150947 71.0823313395182481, -155.1239980061848769 71.0760019938151117, -155.1176686604817689 71.0739980061849081, -155.1151360405815751 71.0659986707899378, -155.0758110894097115 71.0673784044053889, -155.0742275661892222 71.0822587754991417, -155.0659986707899236 71.0848639594184135, -155.0673950195312329 71.1072448730468949, -155.0739980061848939 71.1093353271484574, -155.0760938856336679 71.1159545898437671, -155.1090013292100593 71.1174591064453239, -155.1073387993706376 71.1242835150824817, -155.0743320041232494 71.1257924397786638, -155.0759897867838504 71.1325971815321338, -155.1006679958767336 71.1341756184895928, -155.0990675184461622 71.1506679958767450, -155.0926927354600480 71.1490743001302235, -155.0905785454643819 71.1423967149522696, -155.0674740261501654 71.1409186469184220, -155.0657087537977361 71.1243320041232749, -155.0427558051215158 71.1257266574435931, -155.0401360405815865 71.1340013292100792, -155.0343482123480783 71.1323720296224167, -155.0323313395182083 71.1260019938151231, -155.0257724338107437 71.1239254421658131, -155.0242275661892108 71.1094078911675496, -155.0159986707899122 71.1068027072482778, -155.0171457176541310 71.1027279620002872, -155.0165405273437500 71.1027603149414062, -155.0000000000000000 71.0920257568359375, -154.9999404120397344 71.0919871074228240, -154.9991960313584798 71.0992746988932396, -154.9677605523003194 71.1007120768229299, -154.9651360405815694 71.1090013292100878, -154.9510759141709855 71.1075653076172074, -154.9488949245876483 71.1006768120659842, -154.8749999999999716 71.1000000000000085, -154.8743920220268819 71.0758487277560960, -154.8678812662760151 71.0745622422960253, -154.8654144287109204 71.0839131673177178, -154.8598403036083937 71.0826488170852144, -154.8614501953125000 71.0844039916992188, -154.8480377197265625 71.0860290527343750, -154.8433380126953125 71.0765914916992188, -154.8438446579781953 71.0756470768746738, -154.8427320692274236 71.0757168240017450, -154.8406144883897468 71.0825744628906335, -154.8260521782768819 71.0840922037760521, -154.8235110812716755 71.0923221164279653, -154.8093872070312216 71.0909125434027942, -154.8072625054253422 71.0840321858724025, -154.7760708279079722 71.0826344807942831, -154.7739345974392222 71.0757168240017450, -154.7510654025607550 71.0742831759982749, -154.7489345974392165 71.0673834906684192, -154.7260654025607494 71.0659498426649492, -154.7239478217230726 71.0590922037760606, -154.7093855116102361 71.0575744628906421, -154.7072811550563927 71.0507588704427206, -154.6927188449435562 71.0492411295573021, -154.6906012641058794 71.0423834906684135, -154.6677320692274122 71.0409498426649435, -154.6656012641058737 71.0340501573350878, -154.6427320692274066 71.0326165093316035, -154.6406012641058965 71.0257168240017478, -154.6177320692274009 71.0242831759982778, -154.6156144883897241 71.0174255371093892, -154.6010521782768876 71.0159077962239706, -154.5989478217230726 71.0090922037760492, -154.5843855116102361 71.0075744628906307, -154.5823503282334741 71.0009830050998403, -154.5743445502386919 70.9985110812717153, -154.5759416368272241 70.9926625569661525, -154.5823503282334741 70.9906836615668482, -154.5843163384331547 70.9843163384331746, -154.5906836615668283 70.9823503282335224, -154.5926496717664804 70.9759830050998346, -154.5990169949001540 70.9740169949001825, -154.6009830050998062 70.9676496717665088, -154.6076344807942462 70.9655958387586878, -154.6090321858723655 70.9344041612413321, -154.6173221164279425 70.9318444146050524, -154.6157250298393819 70.9259958902994896, -154.6076778835720233 70.9235110812717124, -154.6091244167751597 70.9090189615885578, -154.6655897352430316 70.9076544867621692, -154.6677188449435505 70.9007588704427150, -154.6822811550564154 70.8992411295573106, -154.6844129774305259 70.8923363579644246, -154.7742631700303662 70.8909915500217096, -154.7746493869357494 70.8845116509331774, -154.7676496717664634 70.8823503282335139, -154.7651777479383384 70.8743445502387317, -154.7427324083116105 70.8757151285807367, -154.7401777479383611 70.8839887830946225, -154.7174041748046704 70.8825981987847342, -154.7158420138888744 70.8576778835720660, -154.7091016981336509 70.8592946370442860, -154.7075412326388744 70.8742662217882042, -154.6843987358940922 70.8757168240017421, -154.6822679307725537 70.8826165093316121, -154.6593987358940865 70.8840501573350821, -154.6568444146050183 70.8923221164279624, -154.6427205403645644 70.8909125434027914, -154.6406012641058965 70.8840501573350821, -154.6174587673610858 70.8825995551215442, -154.6159077962239508 70.8677188449435818, -154.6093163384331319 70.8656836615668482, -154.6072811550563983 70.8590922037760578, -154.5924530029296591 70.8575469970703296, -154.5908803304036212 70.8424530029297017, -154.5743445502386919 70.8407301161024350, -154.5759680853949476 70.8341010199652885, -154.5923221164279369 70.8323967827691092, -154.5906985812716812 70.8257676866319628, -154.5833333333333144 70.8250000000000171, -154.5791666666666515 70.8250000000000171, -154.5175879584418226 70.8255771213107721, -154.5154517279730726 70.8339006212022753, -154.5091952853732380 70.8325256347656307, -154.5074127197265454 70.8255794949001825, -154.4583333333333428 70.8250000000000171, -154.4574178059895928 70.8339762369791828, -154.3507829454210025 70.8326751708984546, -154.3490844726562443 70.8160237630208513, -154.3424199422200331 70.8176147460937671, -154.3407511393229186 70.8339762369791828, -154.3343190511067746 70.8324408637152914, -154.3322806464301209 70.8256700303819571, -154.2843860202365533 70.8243299696180628, -154.2822853936089302 70.8173526340060846, -154.2510479397243728 70.8159806993272696, -154.2489698621961622 70.8090783013237939, -154.2343634711371578 70.8075883653428946, -154.2323691474066720 70.8009643554687642, -154.2243572658962592 70.7985521104600792, -154.2259221394856752 70.7926435682508810, -154.2339760674370552 70.7902187771267535, -154.2325585259331433 70.7756778293185818, -154.1843860202365306 70.7743299696180657, -154.1818852742513002 70.7660237630208400, -154.1676983303493955 70.7674068874783160, -154.1656187269422560 70.7743140326605982, -154.1343812730577270 70.7756859673394274, -154.1322853936089246 70.7826473659939381, -154.1010479397243955 70.7840193006727532, -154.0989573160807140 70.7909630669487910, -154.0760426839192689 70.7923702663845660, -154.0739573160807083 70.7992964002821310, -154.0510426839192633 70.8007035997178917, -154.0489698621961736 70.8075883653428946, -154.0343634711371408 70.8090783013237939, -154.0322853936089302 70.8159806993272696, -154.0010479397243728 70.8173526340060846, -153.9990358140733520 70.8240356445312642, -153.9926308525933223 70.8259643554687557, -153.9907024807399978 70.8323689778645900, -153.9842975192599681 70.8342976888020956, -153.9823031955295107 70.8409216986762260, -153.9676968044704779 70.8424116346571253, -153.9657024807400205 70.8490356445312557, -153.9592975192599624 70.8509643554687614, -153.9573691474066663 70.8573689778645956, -153.9509641859266367 70.8592976888021013, -153.9490358140733406 70.8657023111979214, -153.9426308525933109 70.8676310221354271, -153.9407024807400148 70.8740356445312614, -153.9342975192599852 70.8759643554687671, -153.9322853936089359 70.8826473659939325, -153.9010479397243785 70.8840193006727475, -153.8989422268337535 70.8910135904948078, -153.7760577731662295 70.8923197428385521, -153.7735519409179688 70.9006429036458456, -153.7010557386610117 70.8993398030599025, -153.6989437527126654 70.8923251681857778, -153.6583333333333314 70.8916666666666799, -153.6541666666666686 70.8916666666666799, -153.4010601467556398 70.8923119439019160, -153.3989473130967838 70.8993299696180657, -153.3510526869031878 70.9006700303819599, -153.3489473130967724 70.9076633029514056, -153.3010526869032049 70.9090033637152857, -153.2989520602755817 70.9159806993272639, -153.2677146063910527 70.9173526340060931, -153.2652186075846146 70.9256429036458513, -153.1174499511718636 70.9243462456597342, -153.1166666666666458 70.9166666666666856, -153.1254611545138857 70.9157694498697992, -153.1242099338107607 70.9002000596788378, -153.1173658582899293 70.9007497151692831, -153.1166666666666458 70.9166666666666856, -153.1094078911675069 70.9158942328559192, -153.1068027072482494 70.9076653374566064, -153.1010148790147412 70.9092946370442831, -153.0984693739149236 70.9173346625434107, -153.0590627034505076 70.9159522162543539, -153.0583333333333087 70.9000000000000057, -153.0740383572048415 70.8993103027343921, -153.0756429036458144 70.8925601535373318, -153.0592488606770587 70.8910237630208400, -153.0583333333333087 70.9000000000000057, -153.0508165147569173 70.9008165147569542, -153.0490207248263630 70.9173472086588674, -153.0427124023437386 70.9157223171658160, -153.0405558268228958 70.9090762668185874, -153.0159861246744697 70.9074734157986200, -153.0176045735676951 70.9010477701823021, -153.0256805419921591 70.8984269883897724, -153.0235215928819343 70.8909861246744981, -153.0094319661458258 70.8924479166666828, -153.0067603217230783 70.9006805419922017, -152.9090545654296704 70.8993004692925410, -152.9083333333333030 70.8750000000000142, -152.9009209526909672 70.8743245442708485, -152.8990790473090158 70.8673421223958400, -152.8842542860242872 70.8659912109375085, -152.8824123806423358 70.8590087890625142, -152.8675876193576357 70.8576578776041828, -152.8654144287109204 70.8494201660156335, -152.8176062689886976 70.8506052652994924, -152.8157969156901004 70.8574635823567860, -152.8092030843098712 70.8592030843099110, -152.8074635823567462 70.8657969156901117, -152.8008697509765454 70.8675364176432367, -152.7991302490234204 70.8741302490234517, -152.7925364176432197 70.8758697509765767, -152.7904144287109318 70.8839131673177150, -152.7799814588025527 70.8836545481774181, -152.7799224853515625 70.8838729858398438, -152.7787864657365731 70.8836249259239111, -152.7426062689887090 70.8827280680338703, -152.7407969156900833 70.8758697509765767, -152.7327534993489451 70.8737477620442888, -152.7331788175176257 70.8718726671381489, -152.7244959262404222 70.8724264578416552, -152.7256429036458201 70.8679477267795193, -152.7175821940103901 70.8660237630208485, -152.7168868804299393 70.8728409263918735, -152.7076416015625000 70.8732223510742188, -152.7037435178066858 70.8748699411416823, -152.6653551175386383 70.8744835994252611, -152.6599884033203125 70.8731155395507812, -152.6587560839484183 70.8724807991739141, -152.6574337429470347 70.8673278808593921, -152.6469397427157446 70.8663944638794590, -152.6443023681640625 70.8650360107421875, -152.6410573649864943 70.8601250995680374, -152.6408159044053718 70.8591840955946282, -152.6403579314574301 70.8590665933831190, -152.6289049325830547 70.8417338953633617, -152.6324825710720177 70.8408159044053889, -152.6335057745788504 70.8368279736663169, -152.6358337402343750 70.8355407714843750, -152.6442222849770189 70.8334200055952152, -152.6574242485893933 70.8327097574869953, -152.6582548220327453 70.8294726014923697, -152.6646790627150665 70.8244407597621120, -152.6660054524739394 70.8241004096137203, -152.6660722404676562 70.8233495413131635, -152.6677093505859375 70.8220672607421875, -152.6841438723817248 70.8000993693073326, -152.6877353539676960 70.8004013376509675, -152.6923951139767155 70.8070059073868521, -152.6925174289279425 70.8074825710720575, -152.6927787151269058 70.8075496093247665, -152.7088011246580379 70.8302591739547012, -152.7089945475260322 70.8324337429470603, -152.7106317615249509 70.8328538502524481, -152.7205963134765625 70.8469772338867188, -152.7332916259765625 70.8563232421875000, -152.7339215728921999 70.8564587435895845, -152.7342329237195884 70.8576721191406307, -152.7416666666666458 70.8583333333333485, -152.7458333333333087 70.8583333333333485, -152.7458333333333087 70.8250000000000171, -152.7462903649555983 70.8198622870769725, -152.7464006212022412 70.8186228434244924, -152.7535993787977304 70.8105438232421989, -152.7550540500216698 70.8048750135633753, -152.7647104899088504 70.8035993787977560, -152.7700866699218523 70.7994327121310931, -152.7897104899088276 70.8005672878689296, -152.8020718044704722 70.8120402018229242, -152.8061228434244754 70.8089006212022696, -152.8083333333333087 70.8083333333333371, -152.8407477484808794 70.8077473958333456, -152.8425174289279482 70.8008507622612910, -152.8493859185112740 70.7990882025824817, -152.8505672878688983 70.7727895100911581, -152.8660993787977134 70.7563771565755246, -152.8673278808593636 70.7425662570529568, -152.8741492377386919 70.7408159044053946, -152.8758507622612797 70.7341840955946282, -152.8826721191406079 70.7324337429470518, -152.8833333333333258 70.7250000000000085, -152.8844919840494754 70.7209472656250142, -152.8895063612195884 70.7172841389973996, -152.8938269721136862 70.7160491943359517, -152.8978396945529425 70.7131174723307367, -152.9229936387803548 70.7118825276692746, -152.9270063612196111 70.7089508056640739, -152.9381174723307026 70.7073337131076443, -152.9313269721137090 70.7006174723307339, -152.9243825276692519 70.6986321343316035, -152.9256174723307140 70.6811730278862882, -152.9285491943359148 70.6771603054470603, -152.9297841389973769 70.6686730278862996, -152.9381174723307026 70.6590701633029568, -152.9368825276692405 70.6395063612196310, -152.9327158610025776 70.6338026258680713, -152.9339508056640398 70.6311730278862910, -152.9368825276692405 70.6271603054470631, -152.9381174723307026 70.6228396945529653, -152.9452158610025947 70.6146603054470603, -152.9458333333333258 70.6125000000000114, -152.9532670762803548 70.6131612141927150, -152.9541666666666515 70.6166666666666742, -152.9565911187065694 70.6170199924045221, -152.9642422146267222 70.6246466742621664, -152.9815911187065751 70.6253533257378621, -152.9892422146267279 70.6329800075954921, -152.9940911187065922 70.6336866590711878, -153.0017422146267165 70.6413133409288321, -153.0041666666666629 70.6416666666666799, -153.0045199924045107 70.6565911187066007, -153.0183827718098826 70.6704793294270956, -153.0475463867187216 70.6711866590711963, -153.0517422146267279 70.6670199924045193, -153.0749999999999886 70.6666666666666714, -153.0783159044053718 70.6675174289279653, -153.0797339545355840 70.6730438232421960, -153.0827660454643819 70.6769561767578267, -153.0839006212022468 70.6813771565755360, -153.0878960503472115 70.6865322536892506, -153.0938771565755019 70.6880672878689325, -153.1019561767577954 70.6952660454644217, -153.1074825710720404 70.6966840955946338, -153.1089006212022525 70.7022104899088646, -153.1134904649522355 70.7077141655816064, -153.1249999999999716 70.7083333333333428, -153.1256429036458258 70.7104682074652828, -153.1334832085503308 70.7196238199869924, -153.1396348741319287 70.7214762369791714, -153.1478651258680372 70.7285237630208456, -153.1521348741319173 70.7298095703125114, -153.1645316229925982 70.7410237630208485, -153.1908888075086566 70.7423736572265796, -153.1924116346571054 70.7573031955295306, -153.1979683770073564 70.7589762369791799, -153.2061982896592838 70.7660237630208400, -153.2124999999999773 70.7666666666666799, -153.2188268025716127 70.7660491943359489, -153.2228398640950502 70.7631174723307339, -153.2549033270941834 70.7618825276692860, -153.2645065307617074 70.7702158610026117, -153.2743552313910413 70.7716491699218864, -153.2749999999999773 70.8000000000000114, -153.2813771565755019 70.8005672878689296, -153.2852895100911326 70.8035993787977560, -153.2938771565755189 70.8047339545356067, -153.2977895100911212 70.8077660454644189, -153.3237850613064097 70.8089006212022696, -153.3255672878689211 70.8019561767578267, -153.3327660454644104 70.7938771565755331, -153.3342207166883497 70.7882083468967096, -153.3438771565755019 70.7869327121310903, -153.3477895100911326 70.7839006212022639, -153.3772104899088333 70.7827660454644274, -153.3852895100911269 70.7755672878689381, -153.3897104899088504 70.7744327121310874, -153.3936228434244526 70.7714006212022610, -153.4007466634114394 70.7702660454644246, -153.4061228434244697 70.7744327121310874, -153.4249999999999829 70.7750000000000057, -153.4315911187065922 70.7753533257378535, -153.4350755479600537 70.7788133409288349, -153.4458333333333258 70.7791666666666828, -153.4469397650824476 70.7752966986762289, -153.4575966729057939 70.7660491943359489, -153.4729934692382756 70.7672841389974110, -153.4786975436740306 70.7714508056640739, -153.5116414388020587 70.7701711018880246, -153.5160490247938299 70.7646603054470660, -153.5172843085394732 70.7603396945529681, -153.5202156914604927 70.7563269721137260, -153.5214509752061645 70.7520063612196282, -153.5243823581271556 70.7479936387803860, -153.5258026123046875 70.7382351345486171, -153.5333333333333314 70.7375000000000114, -153.5354809231228046 70.7381303575303946, -153.5395190768771556 70.7410363091362910, -153.5521475897894845 70.7422970241970575, -153.5561857435438355 70.7452029758029681, -153.5729809231228273 70.7464636908637203, -153.5770190768771499 70.7493696424696310, -153.5938142564561417 70.7506303575303974, -153.6103524102104814 70.7660363091362967, -153.6156417846679574 70.7672970241970631, -153.6174999660915717 70.7548221164279596, -153.6777589586045849 70.7535363091362939, -153.6797968546549384 70.7604807535807367, -153.6841357760958999 70.7659634060329950, -153.7075507269965158 70.7673712836371607, -153.7089635213216070 70.7795630560980982, -153.7047968546549441 70.7853525797526117, -153.7041666666666515 70.7958333333333485, -153.7047843085394732 70.8021603054470603, -153.7084472656249829 70.8071746826172017, -153.7146601359049498 70.8089508056640682, -153.7229166666666629 70.8161156548394217, -153.7311731974283759 70.8089508056640682, -153.7354934692382642 70.8077158610026203, -153.7395065307617017 70.8047841389974053, -153.7438268025716184 70.8035491943359432, -153.7561731974283816 70.7922841389974025, -153.8073255750867929 70.7910244411892506, -153.8092597113715101 70.7842597113715328, -153.8146601359049441 70.7827158610026146, -153.8187499999999943 70.7797281901041799, -153.8228398640950445 70.7827158610026146, -153.8421357896592667 70.7839508056640767, -153.8478398640950502 70.7797841389973996, -153.8588024563259467 70.7785491943359517, -153.8645065307617017 70.7827158610026146, -153.8674033270941663 70.7839508056640767, -153.8770065307617188 70.7756174723307367, -153.8825651380750799 70.7740281846788264, -153.8839509752061474 70.7645063612196310, -153.8910490247938299 70.7563269721137260, -153.8924018012152715 70.7424692789713703, -153.9021601359049498 70.7410491943359432, -153.9061731974283873 70.7381174723307424, -153.9124999999999943 70.7375000000000114, -153.9128533257378422 70.7399244520399435, -153.9225487603081604 70.7496459960937614, -153.9517144097222001 70.7503533257378621, -153.9579784817165660 70.7441202799479214, -153.9586866590711622 70.7309088812934164, -153.9683820936414804 70.7211873372395985, -153.9833333333333201 70.7208333333333456, -153.9855438232421818 70.7202660454644274, -153.9894561767578125 70.7172339545356010, -153.9980438232421704 70.7160993787977503, -154.0019561767578011 70.7130672878689381, -154.0176038953993043 70.7119327121310874, -154.0282469007703980 70.7214162190755360, -154.0300540500217039 70.7284583197699703, -154.0407792833116218 70.7298750135633725, -154.0422339545355896 70.7355438232421960, -154.0468124389648494 70.7410339355468807, -154.0647104899088333 70.7422339545356067, -154.0686228434244640 70.7452660454644189, -154.0907574123806398 70.7464569091796989, -154.0922339545355726 70.7522104899088617, -154.0952660454643990 70.7561228434244924, -154.0965418497721373 70.7657792833116446, -154.1022104899088561 70.7672339545355982, -154.1061228434244583 70.7702660454644246, -154.1116490681966127 70.7716840955946225, -154.1133619520399236 70.7783589680989706, -154.1196183946397582 70.7797339545356010, -154.1217390272352361 70.7714711507161525, -154.1397104899088504 70.7702660454644246, -154.1437499999999829 70.7671352810329921, -154.1477895100911439 70.7702660454644246, -154.1612850613064154 70.7714006212022610, -154.1633509318033930 70.7633507622612967, -154.1688771565755189 70.7619327121310846, -154.1727895100911496 70.7589006212022724, -154.1855438232421704 70.7577660454644217, -154.1910273234049384 70.7531931559244924, -154.1922339545355953 70.7367533365885492, -154.1879687839084170 70.7312500000000171, -154.1910993787977304 70.7272104899088703, -154.1922339545355953 70.7227895100911610, -154.2035993787977475 70.7105438232422046, -154.2047339545355840 70.7061228434244953, -154.2140304565429574 70.6958736843533018, -154.2186228434244697 70.6994327121310846, -154.2407574123806455 70.7006235758463646, -154.2425723605685732 70.7076955159505331, -154.2605438232421875 70.7089006212022610, -154.2644561767578182 70.7119327121310874, -154.2757466634114394 70.7130672878689381, -154.2812500000000000 70.7088019476996692, -154.2852895100911326 70.7119327121310874, -154.3083333333333371 70.7125000000000057, -154.3092466566297674 70.7160590277777885, -154.3249999999999886 70.7166666666666828, -154.3255672878689211 70.6977895100911553, -154.3297339545355840 70.6924133300781392, -154.3285222371419252 70.6759039984809192, -154.3202660454643933 70.6737850613064325, -154.3214006212022582 70.6561228434244839, -154.3244327121310846 70.6522104899088674, -154.3249999999999886 70.6458333333333428, -154.3399244520399236 70.6461866590711907, -154.3479159884982721 70.6541527642144160, -154.3517422146267393 70.6503533257378535, -154.3565911187066035 70.6496466742621578, -154.3642422146267279 70.6420199924045278, -154.3690911187065922 70.6413133409288321, -154.3725755479600537 70.6378533257378507, -154.4041666666666686 70.6375000000000028, -154.4107577853732494 70.6371466742621692, -154.4163085937499886 70.6316236707899350, -154.4170199924045050 70.6267422146267450, -154.4204800075954722 70.6232577853732693, -154.4208333333333201 70.6208333333333371, -154.4208333333333201 70.6125000000000114, -154.4202660454644160 70.6102895100911496, -154.4172339545355896 70.6063771565755331, -154.4160993787977247 70.5977895100911610, -154.4077660454643990 70.5884372287326443, -154.4093107435438412 70.5841518825954921, -154.4160430908202954 70.5824242485894189, -154.4172902425130189 70.5592424180772610, -154.4230438232421818 70.5577660454644189, -154.4269561767578125 70.5547339545355925, -154.4313771565755076 70.5535993787977560, -154.4352895100911383 70.5505672878689296, -154.4397104899088617 70.5494327121310789, -154.4477895100911553 70.5422339545356039, -154.4541666666666515 70.5416666666666714, -154.4549472384982494 70.5493187798394246, -154.4979682074652487 70.5506429036458371, -154.5020317925346944 70.5535237630208485, -154.5083333333333258 70.5541666666666742, -154.5083333333333258 70.5500000000000114, -154.5104431152343523 70.5493320041232721, -154.5145568847655966 70.5465013292100735, -154.5187764485676780 70.5451653374566092, -154.5312235514322765 70.5340013292100849, -154.5489169650607550 70.5325876871744839, -154.5510881212022412 70.5257300482855953, -154.5739118787977304 70.5242699517144160, -154.5760938856336679 70.5173787434895871, -154.6062764485676837 70.5159986707899407, -154.6145568847656193 70.5090013292100792, -154.6168351915147241 70.5076653374566007, -154.6228902180989451 70.5118320041232778, -154.6585018581814097 70.5131679958767421, -154.6661482069227134 70.5079060872395900, -154.6960944281683794 70.5090932210286496, -154.6923346625433737 70.5145568847656392, -154.6909986707899236 70.5359693739149378, -154.6979431152343523 70.5381679958767478, -154.7020568847655966 70.5409986707899463, -154.7210018581814097 70.5423346625434107, -154.7270568847656023 70.5381679958767478, -154.7367055257161326 70.5366309271918510, -154.7383015950520644 70.5216349283854242, -154.7532975938584912 70.5200388590494924, -154.7550533718532790 70.5090169270833371, -154.8574466281466755 70.5076497395833428, -154.8590013292100593 70.4978902180989735, -154.8618320041232437 70.4937764485677150, -154.8635979546440922 70.4881985134548756, -154.9075219048393990 70.4867919921875057, -154.9083333333333030 70.4791666666666714, -154.9166666666666572 70.4791666666666714, -154.9190911187065751 70.4788133409288235, -154.9225755479600650 70.4753533257378564, -154.9315911187065922 70.4746466742621607, -154.9392422146267165 70.4670199924045164, -154.9458333333333258 70.4666666666666686, -155.0065911187065808 70.4670199924045164, -155.0100755479600423 70.4704800075954978, -155.0249999999999773 70.4708333333333456, -155.0312889946831376 70.4701778835720631, -155.0395443386501597 70.4631554497612882, -155.0742607964409672 70.4617933485243100, -155.0757168240017165 70.4385654025607693, -155.0823503282335025 70.4365169949001881, -155.0839887830946111 70.4312110053168539, -155.0868445502387090 70.4271223280164946, -155.0884830050998175 70.4218163384331746, -155.0948503282334912 70.4198503282335082, -155.0964887830945997 70.4145443386501881, -155.0993445502386976 70.4104556613498289, -155.1006554497612626 70.4080874972873403, -155.0956685384114451 70.4009484185112910, -155.0841525607638687 70.3991536458333371, -155.0826778835720461 70.3883666992187642, -155.1021223280164918 70.3868445502387203, -155.1074896918402715 70.3830956353081660, -155.1083333333333201 70.3750000000000142, -155.1322113037109318 70.3742913140191035, -155.1344533284505189 70.3673817952473968, -155.1742902967664861 70.3659369574652800, -155.1749999999999829 70.3333333333333428, -155.1938017103406935 70.3339762369791686, -155.2020316229926209 70.3410237630208428, -155.2156365288628308 70.3424116346571253, -155.2177146063910413 70.3493140326606010, -155.2492211235893933 70.3506978352864678, -155.2507746378580578 70.3659274631076528, -155.2688017103407105 70.3673095703125142, -155.2729166666666458 70.3702270507812528, -155.2770316229926095 70.3673095703125142, -155.2839670817057254 70.3660237630208343, -155.2936982896592610 70.3743570963541742, -155.3114618937174214 70.3757188585069571, -155.3131427341037067 70.3813015407986171, -155.3166431003146499 70.3862382676866360, -155.3229683770073564 70.3881429036458428, -155.3270316229926209 70.3910237630208400, -155.3294884575737740 70.3923095703125057, -155.3353649563259467 70.3881429036458428, -155.3396350436740363 70.3868570963541771, -155.3478649563259353 70.3798095703125028, -155.3521350436740249 70.3785237630208371, -155.3603649563259523 70.3714762369791771, -155.3777186075846259 70.3701904296875114, -155.3791666666666629 70.3750000000000142, -155.3857577853732437 70.3753533257378479, -155.3892422146267336 70.3788133409288292, -155.3958333333333144 70.3791666666666771, -155.4146223280164918 70.3798221164279596, -155.4187110053168226 70.3826778835720575, -155.4324808756510379 70.3841128879123374, -155.4339887830946054 70.3937889946831632, -155.4382629394531250 70.3993045383029568, -155.4825373331705691 70.4006944444444542, -155.4840969509548358 70.4156616210937614, -155.4901775783962421 70.4173221164279539, -155.4926496717664861 70.4093163384331717, -155.4979556613498062 70.4076778835720631, -155.5028518676757585 70.4042578803168482, -155.5051496717664747 70.3968163384331689, -155.5104556613498232 70.3951778835720603, -155.5145443386501540 70.3923221164279624, -155.5326107449001540 70.3909077962239706, -155.5339887830945997 70.3645443386501768, -155.5368445502386976 70.3604556613498318, -155.5381554497612626 70.3330874972873374, -155.5333921644422617 70.3262685139974053, -155.5406836615668169 70.3240169949001768, -155.5416666666666572 70.3208333333333400, -155.5427163018120496 70.3173472086588589, -155.5781170315212592 70.3159861246744811, -155.5802215576171648 70.3089962429470603, -155.6438017103407105 70.3076904296875114, -155.6496782090928832 70.3035237630208343, -155.6604683770073621 70.3048095703125000, -155.6663448757595347 70.3089762369791771, -155.6713716295030281 70.3063456217447964, -155.6743572658962478 70.3021348741319514, -155.6756427341037181 70.2978651258680571, -155.6785239325629107 70.2938015407986114, -155.6806147257486828 70.2868570963541686, -155.6950614081488595 70.2882656521267393, -155.6958333333333258 70.2958333333333343, -155.7032670762803832 70.2964945475260521, -155.7050175984700502 70.3033159044053946, -155.7105438232421761 70.3047339545355925, -155.7160761515299328 70.3093478732639028, -155.7166666666666686 70.3333333333333428, -155.7399244520399293 70.3329800075954950, -155.7434088812933908 70.3295199924045278, -155.7649244520399066 70.3288133409288321, -155.7704784817165660 70.3232869466145871, -155.7708333333333144 70.3166666666666771, -155.7549012925889542 70.3159525553385549, -155.7535595364040830 70.2934390597873318, -155.7603776719834912 70.2881554497612910, -155.7706685384114564 70.2865515814887232, -155.7756554497612740 70.2794125027126739, -155.7743445502387090 70.2687110053168453, -155.7672921074761234 70.2604203965928917, -155.7714887830946111 70.2544125027126825, -155.7700205485026004 70.2377593994140739, -155.7646223280164861 70.2339887830946310, -155.7520443386501654 70.2326778835720518, -155.7479556613498062 70.2298221164279539, -155.7395443386501768 70.2285112169053889, -155.7354556613498175 70.2256554497612910, -155.7166666666666686 70.2250000000000085, -155.7163133409288207 70.2225755479600764, -155.7128533257378251 70.2190911187066007, -155.7121466742621294 70.2142422146267364, -155.7086866590711622 70.2107577853732749, -155.7083333333333144 70.1875000000000000, -155.7094424777560562 70.1835167778862967, -155.7144939846462535 70.1797715928819485, -155.7521726820203867 70.1785617404513999, -155.7561606513129107 70.1756049262152857, -155.7783665974934877 70.1743262396918510, -155.7796105278862626 70.1659084743923671, -155.7756050957573564 70.1605061848958371, -155.7749999999999773 70.1375000000000028, -155.7645316229926209 70.1381429036458428, -155.7586551242404482 70.1423095703125057, -155.7382617526584170 70.1409386528862910, -155.7285239325629220 70.1298360188802121, -155.7304307725694343 70.1256764729817803, -155.7604683770073564 70.1243570963541742, -155.7645316229926209 70.1214762369791771, -155.7745746188693374 70.1199456108941064, -155.7839760674370666 70.1089670817057282, -155.7823455810546704 70.1001705593533018, -155.7771350436740363 70.0964762369791714, -155.7708097669813299 70.0945716010199646, -155.7673094007703867 70.0896348741319457, -155.7659688313802064 70.0591122097439296, -155.7520316229926038 70.0576904296875114, -155.7479683770073677 70.0548095703125000, -155.7395316229926152 70.0535237630208343, -155.7313017103406878 70.0464762369791742, -155.7145316229926095 70.0451904296875085, -155.7063017103407105 70.0381429036458343, -155.6757498847113652 70.0368008083767393, -155.6750339084201187 70.0278903537326443, -155.6790913899739621 70.0221679687500114, -155.6688017103406878 70.0131429036458428, -155.6631701999240249 70.0114471435546903, -155.6624999999999943 69.9875000000000256, -155.6688771565755189 69.9880672878689438, -155.6729166666666515 69.9911978827582715, -155.6769561767578125 69.9880672878689438, -155.6980438232421875 69.9869327121310931, -155.7019561767577898 69.9839006212022809, -155.7076248168945085 69.9824459499783131, -155.7089006212022468 69.9727895100911610, -155.7119327121310732 69.9688771565755445, -155.7130672878689097 69.9644561767578352, -155.7160993787977361 69.9605438232422046, -155.7166666666666686 69.9333333333333513, -155.7173278808593579 69.9258995903863081, -155.7241490681965956 69.9241490681966411, -155.7255672878689268 69.9186228434245010, -155.7327660454643876 69.9105438232422074, -155.7339892917209170 69.8967931111653797, -155.7394561767578125 69.8922339545356124, -155.7522104899088333 69.8910993787977617, -155.7575866699218636 69.8869327121310988, -155.7948242187499943 69.8880969577365647, -155.7994327121310789 69.8936228434244953, -155.8007085164387888 69.9032792833116474, -155.8063771565755076 69.9047339545356152, -155.8144561767578011 69.9119327121310903, -155.8188771565755246 69.9130672878689410, -155.8227895100911269 69.9160993787977674, -155.8285837809244754 69.9175864325629561, -155.8369327121310732 69.9269561767578267, -155.8374999999999773 69.9291666666666742, -155.8440911187065865 69.9288133409288406, -155.8642422146267279 69.9086866590712077, -155.8690911187065922 69.9079800075955120, -155.8729173448350593 69.9041805691189495, -155.8809088812934078 69.9121466742621749, -155.8857577853732437 69.9128533257378706, -155.8892422146267336 69.9163133409288378, -155.9058795505099795 69.9170199924045335, -155.9100755479600480 69.9128533257378706, -155.9225489298502509 69.9121466742621749, -155.9309088812933908 69.9204800075955006, -155.9416666666666629 69.9208333333333343, -155.9423321194118728 69.8841154310438526, -155.9573031955295050 69.8825883653428974, -155.9597813924153513 69.8743572658962933, -155.9729683770073621 69.8756427341037494, -155.9788448757595347 69.8798094007704123, -155.9896350436740420 69.8785239325629561, -155.9936982896592781 69.8756427341037494, -156.0229683770073734 69.8743572658962933, -156.0270316229926095 69.8714760674370865, -156.0406365288628479 69.8700883653428946, -156.0423094007703924 69.8645316229926436, -156.0451905992295849 69.8604683770073933, -156.0470241970486143 69.8543779161241503, -156.0603649563259410 69.8423094007704179, -156.0749999999999886 69.8416666666666828, -156.0774244520399350 69.8413133409288349, -156.0871458265516480 69.8316182454427263, -156.0878533257378535 69.8107871161567033, -156.0836866590711622 69.8065911187066206, -156.0829800075954665 69.7975755479600934, -156.0795199924044994 69.7940911187066177, -156.0791666666666515 69.7708333333333570, -156.0791666666666515 69.7666666666666799, -156.1107577853732664 69.7663133409288321, -156.1142422146267279 69.7628533257378649, -156.1208333333333371 69.7625000000000171, -156.1229934692382812 69.7618823581271954, -156.1270065307617188 69.7589509752061758, -156.1313268025716070 69.7577156914605183, -156.1353398640950445 69.7547843085395129, -156.1438268025715956 69.7535490247938554, -156.1530602349175183 69.7455366346571424, -156.1547843085394902 69.7395065307617301, -156.1743823581271613 69.7188268025716269, -156.1757351345486029 69.7049692789713760, -156.1854934692382812 69.7035490247938583, -156.1989117092556398 69.6913063897027030, -156.2006176418728103 69.6853398640950701, -156.2035490247938299 69.6813268025716326, -156.2050930447048529 69.6759263780382128, -156.2104934692382869 69.6743823581271897, -156.2145065307617244 69.6714509752061844, -156.2213024563259580 69.6702156914605268, -156.2270065307617131 69.6743823581271897, -156.2338024563259467 69.6756176418728472, -156.2395065307617017 69.6714509752061844, -156.2521601359049441 69.6702156914605268, -156.2603398640950445 69.6631176418728444, -156.2646601359049328 69.6618823581271869, -156.2728398640950331 69.6547843085395186, -156.2979934692382642 69.6535490247938611, -156.3020065307617017 69.6506176418728415, -156.3063268025716184 69.6493823581271840, -156.3103398640950559 69.6464509752061787, -156.3229934692382699 69.6452156914605212, -156.3270065307617074 69.6422843085395158, -156.3354934692382869 69.6410490247938583, -156.3395065307617244 69.6381176418728529, -156.3438268025716127 69.6368823581271812, -156.3488411797417541 69.6332194010416856, -156.3499999999999659 69.6291666666666913, -156.3522104899088276 69.6297339545356095, -156.3561228434244583 69.6327660454644217, -156.3740943060980726 69.6339709811740590, -156.3749999999999716 69.6375000000000171, -156.3791666666666345 69.6375000000000171, -156.3857577853732437 69.6378533257378649, -156.3892422146267052 69.6413133409288321, -156.3940911187065694 69.6420199924045278, -156.3975755479600593 69.6454800075955092, -156.4149244520399122 69.6461866590712049, -156.4184088812933737 69.6496466742621720, -156.4642130533854072 69.6503533257378677, -156.4684088812933851 69.6461866590712049, -156.4732577853732494 69.6454800075955092, -156.4767422146267108 69.6420199924045278, -156.4808824327256787 69.6413133409288321, -156.4892422146267279 69.6496466742621720, -156.4940911187065637 69.6503533257378677, -156.4975755479600537 69.6538133409288349, -156.5065911187065808 69.6545199924045306, -156.5100755479600423 69.6579800075954978, -156.5274244520399236 69.6586866590711935, -156.5312499999999716 69.6624854193793510, -156.5350755479600480 69.6586866590711935, -156.5524244520399009 69.6579800075954978, -156.5559088812933908 69.6545199924045306, -156.6058797200520587 69.6538133409288349, -156.6100755479600366 69.6579800075954978, -156.6249999999999716 69.6583333333333456, -156.6274244520399179 69.6579800075954978, -156.6309088812933794 69.6545199924045306, -156.6399244520399066 69.6538133409288349, -156.6475755479600593 69.6461866590712049, -156.6524244520399236 69.6454800075955092, -156.6559088812933851 69.6420199924045278, -156.6624999999999943 69.6416666666666799, -156.6772104899088447 69.6422339545356124, -156.6811228434244470 69.6452660454644246, -156.6980438232421591 69.6464006212022753, -156.7019561767577898 69.6494327121310874, -156.7174133300781023 69.6505672878689381, -156.7238627115885379 69.6455686781141736, -156.7249999999999943 69.6500000000000199, -156.7315911187065751 69.6503533257378677, -156.7350755479600650 69.6538133409288349, -156.7440911187065922 69.6545199924045306, -156.7475755479600537 69.6579800075954978, -156.7565911187065808 69.6586866590711935, -156.7600755479600423 69.6621466742621749, -156.7624999999999886 69.6625000000000227, -156.7916666666666572 69.6625000000000227, -156.8063771565755076 69.6619327121310903, -156.8144561767578011 69.6547339545356010, -156.8605438232421818 69.6535993787977645, -156.8644561767577841 69.6505672878689381, -156.8730438232421704 69.6494327121310874, -156.8769561767578011 69.6464006212022753, -156.9032548692491105 69.6452190823025319, -156.9047339545355726 69.6394561767578324, -156.9173122829861029 69.6259034898546219, -156.9208333333333201 69.6250000000000142, -156.9208333333333201 69.6208333333333513, -156.9249999999999829 69.6208333333333513, -156.9357577853732550 69.6204800075955035, -156.9392422146267165 69.6170199924045363, -156.9649244520399236 69.6163133409288406, -156.9684088812933851 69.6128533257378592, -156.9815911187065751 69.6121466742621635, -156.9850755479600650 69.6086866590711963, -156.9933797200520758 69.6079800075955006, -156.9979173448350593 69.6124860975477588, -157.0059088812933794 69.6045199924045335, -157.0274244520399236 69.6038133409288378, -157.0309088812933851 69.6003533257378706, -157.0350463867187329 69.5996466742621749, -157.0392422146267108 69.6038133409288378, -157.0565911187065922 69.6045199924045335, -157.0600755479600537 69.6079800075955006, -157.0690911187065808 69.6086866590711963, -157.0725755479600423 69.6121466742621635, -157.0975463867187329 69.6128533257378592, -157.1017422146267108 69.6086866590711963, -157.1440911187065694 69.6079800075955006, -157.1475755479600593 69.6045199924045335, -157.1541666666666401 69.6041666666666856, -157.1563771565755019 69.6035993787977674, -157.1686228434244583 69.5922339545356010, -157.1782792833116105 69.5909581502278769, -157.1800175984700445 69.5841842651367415, -157.1855438232421704 69.5827660454644246, -157.1977895100911269 69.5714006212022724, -157.2022104899088504 69.5702660454644217, -157.2102895100911439 69.5630672878689467, -157.2355438232421818 69.5619327121310960, -157.2394561767578125 69.5589006212022696, -157.2449824015299384 69.5574824015299669, -157.2464006212022412 69.5519561767578267, -157.2535993787977304 69.5438771565755331, -157.2541666666666629 69.5291666666666828, -157.2532609727647355 69.5256376478407248, -157.2352895100911212 69.5244327121310874, -157.2313771565755189 69.5214006212022753, -157.2227895100911326 69.5202660454644246, -157.2188771565755019 69.5172339545356124, -157.2092207166883497 69.5159581502278741, -157.2077660454643819 69.5102895100911553, -157.2035993787977191 69.5049133300781392, -157.2047339545355840 69.4977895100911667, -157.2089006212022468 69.4924133300781364, -157.2077660454643819 69.4894561767578267, -157.2047339545355840 69.4855438232422102, -157.2034637451171761 69.4759292602539205, -157.1938771565754962 69.4672339545356010, -157.1894561767578011 69.4660993787977645, -157.1855438232421704 69.4630672878689381, -157.1769561767578125 69.4619327121310874, -157.1688771565755189 69.4547339545356124, -157.1666666666666572 69.4541666666666799, -157.1666666666666572 69.4375000000000142, -157.1672843085394788 69.4353398640950701, -157.1702156914604984 69.4313268025716326, -157.1714509752061417 69.4270065307617301, -157.1785490247938242 69.4188268025716297, -157.1798838297525833 69.4051528930664290, -157.1854934692382812 69.4035490247938469, -157.1895065307617188 69.4006176418728415, -157.1992058648003194 69.3992058648003649, -157.2006176418728103 69.3895065307617358, -157.2047843085394732 69.3838024563259665, -157.2032352023654482 69.3752799140082601, -157.1979934692382699 69.3714509752061730, -157.1958333333333258 69.3708333333333513, -157.1954800075954779 69.3684088812934192, -157.1878533257378194 69.3607577853732806, -157.1875000000000000 69.3583333333333485, -157.1871419270833314 69.3558764987521812, -157.1815911187065922 69.3503533257378564, -157.1791666666666458 69.3500000000000227, -157.1749999999999829 69.3500000000000227, -157.1753536648220404 69.3267140706380331, -157.1809088812933908 69.3211866590712020, -157.1833333333333087 69.3208333333333542, -157.1958333333333258 69.3208333333333542, -157.1965035332573564 69.2968860202365562, -157.2032024807400035 69.2948691474067004, -157.2051808675130076 69.2882978651258838, -157.2164472791883441 69.2865810818142478, -157.2214760674370382 69.2794884575738052, -157.2201905992295963 69.2728649563259751, -157.2118572658962421 69.2631337483724110, -157.2132110595703125 69.2382775200737939, -157.2271350436740249 69.2368572658962762, -157.2311982896592610 69.2339760674370837, -157.2438017103407049 69.2326905992296133, -157.2478649563259410 69.2298094007704208, -157.2771350436740363 69.2285239325629504, -157.2811982896592724 69.2256427341037437, -157.2865358140733463 69.2240358140733605, -157.2874999999999943 69.2208333333333456, -157.2940911187065751 69.2211866590711935, -157.3017422146267279 69.2288133409288378, -157.3308795505099624 69.2295199924045335, -157.3350755479600593 69.2253533257378564, -157.3642128838432939 69.2246466742621607, -157.3684088812933908 69.2288133409288378, -157.3982577853732607 69.2295199924045335, -157.4142422146267108 69.2454800075955035, -157.4190911187065751 69.2461866590711992, -157.4225755479600650 69.2496466742621664, -157.4274244520399293 69.2503533257378621, -157.4309088812933908 69.2538133409288292, -157.4433795505099738 69.2545199924045249, -157.4475755479600707 69.2503533257378621, -157.4524244520399066 69.2496466742621664, -157.4559088812933965 69.2461866590711992, -157.4690911187065865 69.2454800075955035, -157.4725755479600480 69.2420199924045221, -157.5100462171766367 69.2413133409288406, -157.5142422146267336 69.2454800075955035, -157.5190911187065979 69.2461866590711992, -157.5225755479600593 69.2496466742621664, -157.5291666666666686 69.2500000000000142, -157.5399244520399122 69.2503533257378621, -157.5434088812934021 69.2538133409288292, -157.5565911187065922 69.2545199924045249, -157.5600755479600537 69.2579800075955063, -157.5649244520399179 69.2586866590712020, -157.5684088812933794 69.2621466742621692, -157.5774244520399066 69.2628533257378649, -157.5871422661675183 69.2725448608398580, -157.5874999999999773 69.2750000000000199, -157.5958333333333314 69.2750000000000199, -157.5965138753255133 69.2770972357856039, -157.5993194580078125 69.2812360975477617, -157.6006805419921761 69.2854305691189438, -157.6087515936957288 69.2950449625651146, -157.6312639024522468 69.2965138753255303, -157.6354027642144047 69.2993194580078296, -157.6867704603407105 69.3007169935438583, -157.6875000000000000 69.3208333333333542, -157.6908157348632642 69.3216842651367386, -157.6916666666666629 69.3250000000000171, -157.6949824015299271 69.3258509318034015, -157.6958333333333258 69.3291666666666799, -157.6958333333333258 69.3625000000000114, -157.6990736219617872 69.3634263780382128, -157.7006176418728103 69.3688268025716326, -157.7118823581271556 69.3811731974283958, -157.7131176418728273 69.3854934692382983, -157.7167805989583371 69.3905078464084397, -157.7229934692382756 69.3922843085395158, -157.7270065307617131 69.3952156914605212, -157.7396601359049271 69.3964509752061787, -157.7436731974283646 69.3993823581271840, -157.7754691229926038 69.4006176418728415, -157.7811731974283873 69.3964509752061787, -157.8104934692382812 69.3952156914605212, -157.8145065307617188 69.3922843085395158, -157.8354934692382585 69.3910490247938583, -157.8395065307616960 69.3881176418728387, -157.8688268025716184 69.3868823581271812, -157.8728398640950559 69.3839509752061758, -157.8813268025716070 69.3827156914605183, -157.8853398640950445 69.3797843085395129, -157.8938268025715956 69.3785490247938554, -157.8978398640950331 69.3756176418728501, -157.9115003797743100 69.3743823581271926, -157.9131176418728160 69.3854934692382983, -157.9160490247938355 69.3895065307617358, -157.9172843085394788 69.3938268025716241, -157.9300354003906079 69.4076677110460167, -157.9458333333333258 69.4083333333333456, -157.9690911187065865 69.4079800075954978, -157.9725755479600480 69.4045199924045306, -157.9833333333333201 69.4041666666666828, -157.9855438232421818 69.4035993787977645, -157.9894561767578125 69.4005672878689381, -157.9980438232421704 69.3994327121310874, -158.0061228434244640 69.3922339545356124, -158.0272104899088390 69.3910993787977617, -158.0311228434244697 69.3880672878689353, -158.0355438232421932 69.3869327121310988, -158.0394561767577954 69.3839006212022724, -158.0647104899088333 69.3827660454644217, -158.0727895100911269 69.3755672878689325, -158.0866004096137090 69.3743387858073106, -158.0883509318033759 69.3675175984700729, -158.0916666666666686 69.3666666666666885, -158.0937889946831660 69.3660112169053917, -158.1029032389322708 69.3582578870985458, -158.1048221164279539 69.3520443386501881, -158.1128707885742131 69.3425828721788378, -158.1229556613498062 69.3410112169054003, -158.1312110053168283 69.3339887830946395, -158.1354556613498232 69.3326778835720603, -158.1478776719835082 69.3214887830946367, -158.1533540513780451 69.3197976006402001, -158.1550240410698791 69.3090816921658188, -158.1742941962347970 69.3075731065538321, -158.1756934271918453 69.2719058566623431, -158.1791666666666742 69.2708333333333428, -158.2107577853732607 69.2704800075954950, -158.2184088812933851 69.2628533257378649, -158.2607577853732721 69.2621466742621692, -158.2642422146267336 69.2586866590712020, -158.2750000000000057 69.2583333333333542, -158.3115804036458201 69.2589172363281449, -158.3124999999999716 69.2625000000000171, -158.3208333333333258 69.2625000000000171, -158.3666666666666458 69.2625000000000171, -158.3980438232421761 69.2630672878689353, -158.4019561767577784 69.2660993787977617, -158.4272104899088447 69.2672339545355982, -158.4311228434244470 69.2702660454644246, -158.4343214246961509 69.2714006212022753, -158.4477895100911269 69.2589006212022724, -158.4616004096137090 69.2576721191406364, -158.4634134928385265 69.2506074693468037, -158.4791666666666572 69.2500000000000142, -158.4916666666666458 69.2500000000000142, -158.4922841389973769 69.2563268025716354, -158.4966332329643990 69.2617645263672017, -158.5116973876952784 69.2632351345486228, -158.5132683648003251 69.2740283542209312, -158.5188269721136862 69.2756176418728415, -158.5228396945529425 69.2785490247938469, -158.5604936387803718 69.2797843085395186, -158.5645063612195997 69.2827156914605240, -158.5688269721136976 69.2839509752061815, -158.5728396945529255 69.2868823581271869, -158.6021603054470290 69.2881176418728444, -158.6061730278862569 69.2910490247938498, -158.6271603054470347 69.2922843085395073, -158.6311730278862626 69.2952156914605126, -158.6409315321180316 69.2966359456380303, -158.6416666666666515 69.3041666666666885, -158.7022104899088504 69.3047339545356067, -158.7061228434244526 69.3077660454644189, -158.7090799967447765 69.3089006212022696, -158.7144561767578068 69.3047339545356067, -158.7199825710720233 69.3033157348632898, -158.7214006212022355 69.2977895100911638, -158.7244327121310619 69.2938771565755331, -158.7259141710069343 69.2881040785047873, -158.7590799967447879 69.2869327121310903, -158.7645833333333201 69.2911978827582686, -158.7686228434244526 69.2880672878689410, -158.7833333333333030 69.2875000000000085, -158.7916666666666572 69.2875000000000085, -158.8065911187065922 69.2871466742621749, -158.8100755479600537 69.2836866590711935, -158.8166666666666629 69.2833333333333456, -158.8199825710720177 69.2824824015299612, -158.8208333333333258 69.2791666666666828, -158.8201195610893990 69.2632386949327383, -158.8083333333333087 69.2625000000000171, -158.7853776719834968 69.2631554497612996, -158.7794125027126597 69.2673221164279624, -158.7260769314235915 69.2659871419270985, -158.7239644368489451 69.2591459486219776, -158.7145443386501427 69.2576778835720575, -158.7104556613498119 69.2548221164279596, -158.6853776719835025 69.2535112169053946, -158.6812889946831433 69.2506554497612967, -158.6770443386501483 69.2493445502387317, -158.6729556613498175 69.2464887830946338, -158.6687110053168226 69.2451778835720688, -158.6646223280164634 69.2423221164279710, -158.6603776719834968 69.2410112169053917, -158.6562889946831376 69.2381554497612939, -158.6437110053168169 69.2368445502387289, -158.6396223280164861 69.2339887830946310, -158.6270443386501654 69.2326778835720660, -158.6229556613498062 69.2298221164279681, -158.6187110053168112 69.2285112169054031, -158.6145833333333144 69.2256281534830862, -158.6085791693793112 69.2298221164279681, -158.5799126519096944 69.2284491644965385, -158.5756266276041515 69.2229187011718921, -158.5785112169053548 69.2187889946831802, -158.5798509385850537 69.1590952555338703, -158.5979556613498005 69.1576778835720631, -158.6062110053168226 69.1506554497613024, -158.6187889946831433 69.1493445502387232, -158.6228776719834741 69.1464887830946253, -158.6271223280164691 69.1451778835720603, -158.6312110053168283 69.1423221164279624, -158.6365169949001483 69.1406836615668539, -158.6381554497612569 69.1353776719835196, -158.6451778835720177 69.1271223280165117, -158.6458333333333144 69.1208333333333513, -158.6815911187065922 69.1211866590711992, -158.6850755479600537 69.1246466742621664, -158.6916666666666345 69.1250000000000142, -158.6940911187065808 69.1253533257378621, -158.6979166666666572 69.1291520860460196, -158.7017422146267052 69.1253533257378621, -158.7600463867187273 69.1246466742621664, -158.7642422146267052 69.1288133409288292, -158.7808797200520701 69.1295199924045249, -158.7850755479600480 69.1253533257378621, -158.8100463867187386 69.1246466742621664, -158.8142422146267165 69.1288133409288292, -158.9041666666666401 69.1291666666666771, -158.9190911187065751 69.1288133409288292, -158.9225755479600650 69.1253533257378621, -158.9399244520399179 69.1246466742621664, -158.9434088812933794 69.1211866590711992, -158.9499999999999886 69.1208333333333513, -158.9541666666666515 69.1208333333333513, -158.9857577853732380 69.1204800075955035, -158.9892422146267279 69.1170199924045221, -159.0149244520399066 69.1163133409288264, -159.0184088812933965 69.1128533257378592, -159.0308797200520701 69.1121466742621635, -159.0350755479600480 69.1163133409288264, -159.0690911187065808 69.1170199924045221, -159.0725755479600423 69.1204800075955035, -159.1899244520399179 69.1211866590711992, -159.1934088812933794 69.1246466742621664, -159.1958333333333258 69.1250000000000142, -159.1999999999999886 69.1250000000000142, -159.2065911187065694 69.1253533257378621, -159.2184088812933851 69.1371466742621692, -159.2482577853732550 69.1378533257378649, -159.2517422146267165 69.1413133409288321, -159.2708333333333144 69.1416666666666799, -159.2716842651367131 69.1383507622612967, -159.2749999999999773 69.1375000000000171, -159.3149244520399179 69.1371466742621692, -159.3184088812933794 69.1336866590711878, -159.3600462171766310 69.1329800075955063, -159.3642422146267279 69.1371466742621692, -159.3933795505099624 69.1378533257378649, -159.3975755479600593 69.1336866590711878, -159.4274244520399293 69.1329800075955063, -159.4309088812933908 69.1295199924045249, -159.4350462171766480 69.1288133409288292, -159.4392422146267165 69.1329800075955063, -159.4607577853732607 69.1336866590711878, -159.4642422146267222 69.1371466742621692, -159.5249999999999773 69.1375000000000171, -159.5249999999999773 69.1166666666666742, -159.5315911187065865 69.1163133409288264, -159.5350755479600480 69.1128533257378592, -159.5374999999999943 69.1125000000000114, -159.5625000000000000 69.1125000000000114, -159.5625000000000000 69.0958333333333456, -159.5577660454644047 69.0946183946397667, -159.5589006212022412 69.0769561767578324, -159.5619327121310675 69.0730438232422017, -159.5630672878689040 69.0644561767578296, -159.5660993787977304 69.0605438232421989, -159.5666666666666629 69.0541666666666742, -159.5730438232421875 69.0535993787977560, -159.5769561767577898 69.0505672878689438, -159.5813771565755133 69.0494327121310931, -159.5852895100911439 69.0464006212022667, -159.6605438232421648 69.0452660454644160, -159.6644561767577954 69.0422339545356039, -159.6855438232421704 69.0410993787977532, -159.6894561767578011 69.0380672878689410, -159.7313771565755189 69.0369327121310903, -159.7352895100911496 69.0339006212022639, -159.7699186537000742 69.0327307807074817, -159.7708333333333144 69.0291666666666828, -159.8065911187065922 69.0288133409288349, -159.8142422146267165 69.0211866590711907, -159.8392128838433166 69.0204800075954950, -159.8434088812933851 69.0246466742621720, -159.8642128838432939 69.0253533257378535, -159.8687499999999773 69.0208479139540003, -159.8725755479600537 69.0246466742621720, -159.8767128838433109 69.0253533257378535, -159.8809088812934078 69.0211866590711907, -159.8892128838432996 69.0204800075954950, -159.8937499999999829 69.0249854193793482, -159.8979166666666458 69.0208479139540003, -159.9017422146267222 69.0246466742621720, -159.9541666666666515 69.0250000000000057, -159.9565911187065979 69.0246466742621720, -159.9600755479600593 69.0211866590711907, -159.9874999999999829 69.0208333333333428, -159.9982577853732550 69.0211866590711907, -160.0020833333333314 69.0249854193793482, -160.0059088812934078 69.0211866590711907, -160.0100462171766367 69.0204800075954950, -160.0142422146267336 69.0246466742621720, -160.0440911187066035 69.0253533257378535, -160.0475755479600650 69.0288133409288349, -160.0808795505099624 69.0295199924045306, -160.0850755479600593 69.0253533257378535, -160.1267128838433109 69.0246466742621720, -160.1309088812934078 69.0288133409288349, -160.1600462171766424 69.0295199924045306, -160.1642422146267393 69.0253533257378535, -160.1982577853732437 69.0246466742621720, -160.2079755995008554 69.0149549696180742, -160.2083333333333144 69.0125000000000171, -160.2200237698025092 69.0131880018446253, -160.2216495090060562 69.0243570963541799, -160.2813268025716127 69.0256174723307367, -160.2853398640950502 69.0285491943359517, -160.3088024563259637 69.0297841389974138, -160.3154541015624943 69.0249254014757128, -160.3166666666666629 69.0291666666666828, -160.3291666666666515 69.0291666666666828, -160.3940911187065694 69.0295199924045306, -160.3975755479600309 69.0329800075955120, -160.4333333333333087 69.0333333333333456, -160.4374999999999716 69.0333333333333456, -160.4940911187065637 69.0336866590711935, -160.4975755479600537 69.0371466742621749, -160.5267130533853788 69.0378533257378706, -160.5309088812933851 69.0336866590711935, -160.5607577853732266 69.0329800075955120, -160.5663123236761862 69.0274532741970717, -160.5666666666666345 69.0166666666666799, -160.5663133409287866 69.0100755479600849, -160.5625145806206433 69.0062500000000227, -160.5663133409287866 69.0024244520399463, -160.5666666666666345 68.9916666666666885, -160.5475755479600366 68.9920199924045363, -160.5440911187065751 68.9954800075955035, -160.5166666666666515 68.9958333333333513, -160.5059088812933794 68.9954800075955035, -160.5024244520398895 68.9920199924045363, -160.4934088812933624 68.9913133409288406, -160.4899244520399009 68.9878533257378592, -160.4791666666666288 68.9875000000000114, -160.4797339545355612 68.9852895100911638, -160.4869327121310505 68.9772104899088703, -160.4883507622612626 68.9716840955946395, -160.4951249864365934 68.9699459499783245, -160.4965362548827841 68.9592624240451642, -160.5061228434244640 68.9505672878689495, -160.5119171142577841 68.9490804036458513, -160.5202660454643819 68.9397104899088760, -160.5214006212022184 68.9352895100911667, -160.5285993787977077 68.9272104899088731, -160.5301344129773895 68.9212293836805685, -160.5367533365885038 68.9160993787977674, -160.5656653510199305 68.9172726101345603, -160.5702660454643933 68.9227895100911638, -160.5717329237195941 68.9285054524739706, -160.5855438232421477 68.9297339545356067, -160.5894561767577784 68.9327660454644331, -160.6124999999999829 68.9333333333333513, -160.6124999999999829 68.9125000000000227, -160.6130672878688870 68.9102895100911610, -160.6202660454643762 68.9022104899088674, -160.6217207166883441 68.8965416802300581, -160.6313771565754962 68.8952660454644246, -160.6352895100911269 68.8922339545356124, -160.6397104899088220 68.8910993787977617, -160.6436228434244526 68.8880672878689353, -160.6480438232421477 68.8869327121310988, -160.6519561767577784 68.8839006212022724, -160.6563771565755019 68.8827660454644217, -160.6602895100911326 68.8797339545356095, -160.6647104899088276 68.8785993787977588, -160.6686228434244583 68.8755672878689467, -160.6897104899088333 68.8744327121310960, -160.6936228434244640 68.8714006212022696, -160.7022104899088220 68.8702660454644331, -160.7061228434244526 68.8672339545356067, -160.7324215359157620 68.8660525851779681, -160.7341840955945997 68.8591840955946424, -160.7422339545355499 68.8571183946397696, -160.7408589680989337 68.8508619520399492, -160.7341840955945997 68.8491492377387289, -160.7324825710720120 68.8425174289279624, -160.7258507622612456 68.8408159044054031, -160.7249999999999659 68.8375000000000199, -160.7246466742621180 68.8309088812934249, -160.7211866590711509 68.8274244520399492, -160.7208333333333030 68.8208333333333542, -160.5017422146267165 68.8211866590712020, -160.4979166666666401 68.8249854193793595, -160.4933797200520473 68.8204800075955063, -160.4850755479600366 68.8211866590712020, -160.4808797200520587 68.8253533257378649, -160.4684088812933851 68.8246466742621692, -160.4649244520398952 68.8211866590712020, -160.4517130533853901 68.8204783121745010, -160.4461866590711452 68.8149244520399463, -160.4458333333332973 68.8125000000000142, -160.4464006212022298 68.8102895100911667, -160.4535993787977191 68.8022104899088731, -160.4550174289279312 68.7966840955946282, -160.4605438232421477 68.7952660454644302, -160.4644561767577784 68.7922339545356039, -160.4730438232421648 68.7910993787977532, -160.4769561767577954 68.7880672878689410, -160.4855438232421534 68.7869327121310903, -160.4894561767577841 68.7839006212022781, -160.5105438232421591 68.7827660454644274, -160.5144561767577898 68.7797339545356010, -160.5199825710720347 68.7783159044054031, -160.5217451307508441 68.7714474148220631, -160.5480438232421534 68.7702660454644246, -160.5519561767577841 68.7672339545356124, -160.5579372829860745 68.7656989203559164, -160.5619327121310391 68.7605438232422017, -160.5624999999999716 68.7583333333333542, -160.5612382676866048 68.7541432698567831, -160.5563015407985858 68.7506429036458542, -160.5520317925347058 68.7493570963541885, -160.5479682074652601 68.7464762369791771, -160.5228651258680372 68.7451904296875114, -160.5188015407985915 68.7423095703125142, -160.5061984592013573 68.7410237630208485, -160.5021348741319116 68.7381429036458513, -160.4936984592013687 68.7368570963541856, -160.4896348741319230 68.7339762369791885, -160.4770317925346887 68.7326904296875227, -160.4729682074652430 68.7298095703125114, -160.4549170600043055 68.7284257676866446, -160.4464762369791515 68.7188015407986228, -160.4448689778645587 68.7134643554687727, -160.4395317925346944 68.7118570963541799, -160.4271348741319230 68.7006429036458428, -160.4228651258680145 68.6993570963541771, -160.4188015407985972 68.6964762369791799, -160.4051968044704495 68.6950883653428974, -160.4031239827473598 68.6882035997178946, -160.3799431694878308 68.6867801242404710, -160.3784216986761919 68.6718634711371720, -160.3709832085503137 68.6696238199869953, -160.3631429036458087 68.6604682074652999, -160.3615356445312159 68.6551310221354356, -160.3561984592013516 68.6535237630208428, -160.3503217909070884 68.6493570963541799, -160.3478651258680259 68.6506429036458456, -160.3438015407985802 68.6535237630208428, -160.3374999999999773 68.6541666666666828, -160.3369327121310448 68.6477895100911581, -160.3327660454643819 68.6424133300781421, -160.3339006212022184 68.6227895100911667, -160.3420325385199305 68.6136630588107721, -160.3339162190754905 68.6115804036458456, -160.3255672878688927 68.6022104899088703, -160.3249999999999886 68.6000000000000085, -160.3260053846571225 68.5964836968316121, -160.3658525254991218 68.5951765272352532, -160.3674608018663150 68.5841274685329978, -160.3788355509440180 68.5824717203776117, -160.3827156914605041 68.5771603054470518, -160.3847011990017393 68.5702158610026089, -160.4063268025716127 68.5714508056640710, -160.4103398640950502 68.5743825276692860, -160.4188268025716013 68.5756174723307339, -160.4245308770073848 68.5797841389974110, -160.4313268025716184 68.5785491943359489, -160.4370308770073734 68.5743825276692860, -160.4408059014214416 68.5761559380425467, -160.4416666666666345 68.5791666666666799, -160.4438771565755246 68.5797339545355982, -160.4479166666666572 68.5828647189670164, -160.4519561767578182 68.5797339545355982, -160.4699276394314325 68.5785288492838703, -160.4708333333333314 68.5750000000000028, -160.4772481282551837 68.5755296495225792, -160.4810852050781023 68.5786370171441177, -160.4968509250216755 68.5796963161892563, -160.5034081353081206 68.5740539550781421, -160.5049333360459798 68.5675788031684164, -160.5092739529079608 68.5661370171441149, -160.5144185384114337 68.5703036838107778, -160.5272481282551666 68.5713629828559164, -160.5310852050780852 68.5744703504774407, -160.5343509250216698 68.5755296495225792, -160.5409081353081433 68.5698872884114792, -160.5421963161892052 68.5644185384114735, -160.5453036838107437 68.5605814615885549, -160.5466000027126370 68.5550788031684135, -160.5509406195746180 68.5536370171441121, -160.5560852050780909 68.5578036838107749, -160.5605814615885265 68.5588629828559135, -160.5644185384114166 68.5619703504774520, -160.5958333333333030 68.5625000000000142, -160.5964945475260208 68.5550662570529710, -160.5999999999999659 68.5541666666666885, -160.6022104899088276 68.5547339545356067, -160.6061228434244583 68.5577660454644189, -160.6154517279730669 68.5589006212022696, -160.6175723605685448 68.5506378173828352, -160.6355438232421591 68.5494327121310931, -160.6394561767577898 68.5464006212022667, -160.6522104899088390 68.5452660454644302, -160.6561228434244413 68.5422339545356039, -160.6772104899088163 68.5410993787977532, -160.6811228434244470 68.5380672878689410, -160.6897104899088333 68.5369327121310903, -160.6936228434244640 68.5339006212022781, -160.6980438232421591 68.5327660454644274, -160.7019561767577898 68.5297339545356010, -160.7063771565754848 68.5285993787977645, -160.7102895100911155 68.5255672878689381, -160.7188771565755019 68.5244327121310874, -160.7227895100911326 68.5214006212022753, -160.7283159044053491 68.5199825710720631, -160.7291666666666288 68.5166666666666799, -160.7522104899088333 68.5172339545356124, -160.7561228434244640 68.5202660454644246, -160.7632466634114223 68.5214006212022753, -160.7686228434244526 68.5172339545356124, -160.7840799967447651 68.5160993787977617, -160.7894561767577954 68.5202660454644246, -160.8090799967447708 68.5214006212022753, -160.8145965576171648 68.5171251085069599, -160.8352895100911155 68.5369327121310903, -160.8397104899088390 68.5380672878689410, -160.8436228434244413 68.5410993787977532, -160.8491492377386862 68.5425174289279653, -160.8505672878688983 68.5480438232422102, -160.8560421413845347 68.5546084933810960, -160.8617858886718466 68.5533209906684249, -160.8630672878688870 68.5436228434245010, -160.8676795111761919 68.5380923800998403, -160.9112850613063870 68.5369327121310903, -160.9134056939018933 68.5451955159505388, -160.9313771565755076 68.5464006212022667, -160.9352895100911098 68.5494327121310931, -160.9590799967447765 68.5505672878689438, -160.9644561767577784 68.5464006212022667, -160.9772104899088276 68.5452660454644302, -160.9811228434244583 68.5422339545356039, -160.9897104899088163 68.5410993787977532, -160.9948655870225593 68.5371039496527885, -160.9966840955945884 68.5300174289279624, -161.0033159044053548 68.5283159044054031, -161.0050174289279141 68.5216840955946367, -161.0105438232421591 68.5202660454644246, -161.0144561767577898 68.5172339545356124, -161.0313771565755019 68.5160993787977617, -161.0352895100911326 68.5130672878689353, -161.0382466634114280 68.5119327121310846, -161.0436228434244583 68.5160993787977617, -161.0532792833116105 68.5173750135633810, -161.0547339545355783 68.5230438232422046, -161.0587293836805429 68.5281989203559192, -161.0647104899088333 68.5297339545356010, -161.0698655870225480 68.5337293836805657, -161.0714006212022298 68.5397104899088703, -161.0759904649522412 68.5452141655816121, -161.0980438232421648 68.5464006212022667, -161.1019561767577954 68.5494327121310931, -161.1257466634114337 68.5505672878689438, -161.1311228434244640 68.5464006212022667, -161.1416666666666515 68.5458333333333485, -161.1423085530598769 68.5658237033420335, -161.1505405002170050 68.5672715928819656, -161.1561604817707973 68.5631049262152885, -161.1778377956813983 68.5618950737847399, -161.1801510281032677 68.5702016194661610, -161.2041666666666515 68.5708333333333542, -161.2063771565754848 68.5714006212022724, -161.2102895100911155 68.5744327121310846, -161.2188771565755019 68.5755672878689353, -161.2227895100911326 68.5785993787977617, -161.2283159044053491 68.5800174289279596, -161.2300838894313983 68.5869072808159927, -161.2772104899088390 68.5880672878689381, -161.2811228434244697 68.5910993787977645, -161.2833333333333030 68.5916666666666828, -161.2842451307508327 68.5881140814887260, -161.3105438232421704 68.5869327121310874, -161.3198961046006730 68.5785993787977617, -161.3230438232421591 68.5797339545356124, -161.3269561767577898 68.5827660454644246, -161.3291666666666515 68.5833333333333428, -161.3315911187065694 68.5829800075954950, -161.3350755479600593 68.5795199924045278, -161.3416666666666401 68.5791666666666799, -161.3521474202473769 68.5785363091362967, -161.3603525797525720 68.5714636908637374, -161.3771474202473826 68.5702029758029710, -161.3812499999999659 68.5672505696614678, -161.3853525797525776 68.5702029758029710, -161.4239718967013744 68.5714965820312727, -161.4256303575303662 68.5771474202474138, -161.4299692789713276 68.5826300726996720, -161.4521474202473712 68.5839636908637260, -161.4561859130859034 68.5868696424696367, -161.4615546332465215 68.5884453667534899, -161.4635314941405966 68.5951812744140739, -161.5212297227647298 68.5964636908637289, -161.5270833333333087 68.5922505696614735, -161.5327524820963276 68.5963307698567917, -161.5450775146484261 68.5950744628906364, -161.5465372721353958 68.5804487440321395, -161.5503963894313983 68.5785363091362967, -161.5561859130859261 68.5827029758029596, -161.5604807535807197 68.5839636908637260, -161.5654354519313927 68.5875291612413349, -161.5672970241970177 68.5811859130859602, -161.5702029758029425 68.5771474202474138, -161.5720645480685675 68.5708041720920249, -161.5770192464192405 68.5743696424696338, -161.5878963894313927 68.5756303575304003, -161.5936859130859204 68.5714636908637374, -161.6499999999999773 68.5708333333333542, -161.6508507622612569 68.5675174289279710, -161.6579372829860972 68.5656989203559135, -161.6630672878688983 68.5590799967448135, -161.6618262396918340 68.5467298719618157, -161.6550174289279198 68.5449825710720688, -161.6535993787977361 68.5394561767578239, -161.6505672878689097 68.5355438232422074, -161.6499999999999773 68.5291666666666828, -161.6607577853732494 68.5288133409288349, -161.6684088812933737 68.5211866590711907, -161.6916666666666345 68.5208333333333428, -161.6922339545355669 68.5272104899088674, -161.6952660454643933 68.5311228434244981, -161.6967329237195941 68.5368387858073049, -161.7116004096137090 68.5381612141927263, -161.7133110894097001 68.5448265923394189, -161.7174133300781023 68.5464006212022667, -161.7240322536892165 68.5412706163194656, -161.7259107801649236 68.5339504665798813, -161.7507466634114337 68.5327660454644274, -161.7561228434244640 68.5369327121310903, -161.7772104899088390 68.5380672878689410, -161.7811228434244697 68.5410993787977532, -161.7924133300781193 68.5422339545356039, -161.7977895100911212 68.5380672878689410, -161.8230438232421591 68.5369327121310903, -161.8269561767577898 68.5339006212022781, -161.8313771565755133 68.5327660454644274, -161.8352895100911155 68.5297339545356010, -161.8522104899088276 68.5285993787977645, -161.8561228434244583 68.5255672878689381, -161.8647104899088447 68.5244327121310874, -161.8686228434244754 68.5214006212022753, -161.8907575819227134 68.5202097574869953, -161.8916666666666515 68.5166666666666799, -161.8910993787977191 68.5144561767578324, -161.8869327121310562 68.5090799967448021, -161.8881737603081490 68.4967298719618185, -161.8952097574869526 68.4949242485894274, -161.8958333333333144 68.4833333333333485, -161.9024244520399236 68.4829800075955006, -161.9059088812933851 68.4795199924045335, -161.9083333333333030 68.4791666666666714, -161.9357577853732550 68.4788133409288378, -161.9434088812933794 68.4711866590711935, -161.9482577853732437 68.4704800075954978, -161.9517422146267336 68.4670199924045306, -161.9565911187065694 68.4663133409288349, -161.9600755479600593 68.4628533257378677, -161.9642130533854072 68.4621466742621720, -161.9684088812933851 68.4663133409288349, -161.9808797200520587 68.4670199924045306, -161.9850755479600650 68.4628533257378677, -161.9874999999999829 68.4625000000000199, -161.9880672878689154 68.4647104899088674, -161.9952660454644047 68.4727895100911610, -161.9967390272352361 68.4785288492838617, -162.0147104899088504 68.4797339545356039, -162.0186228434244526 68.4827660454644302, -162.0230438232421761 68.4839006212022667, -162.0269561767578068 68.4869327121310931, -162.0355438232421648 68.4880672878689438, -162.0394561767577954 68.4910993787977560, -162.0480438232421818 68.4922339545356067, -162.0531989203558965 68.4962293836805713, -162.0547339545355783 68.5022104899088617, -162.0577660454644047 68.5061228434244924, -162.0589006212022412 68.5105438232422017, -162.0619327121310675 68.5144561767578324, -162.0634128146701300 68.5202236599392478, -162.0924133300781023 68.5214006212022753, -162.0977895100911326 68.5172339545356124, -162.1022104899088276 68.5160993787977617, -162.1061228434244583 68.5130672878689353, -162.1257466634114337 68.5119327121310846, -162.1311228434244640 68.5160993787977617, -162.1509372287326300 68.5172339545356124, -162.1602895100911326 68.5089006212022724, -162.1632466634114564 68.5077660454644217, -162.1686228434244583 68.5119327121310846, -162.1833333333333087 68.5125000000000028, -162.1938142564561360 68.5118696424696338, -162.2020190768771499 68.5047970241970603, -162.2438142564561474 68.5035363091362939, -162.2478524102104984 68.5006303575303974, -162.2521475897894732 68.4993696424696310, -162.2577524820963504 68.4953358968099053, -162.2701276991102191 68.4965972900390767, -162.2708333333333144 68.5083333333333542, -162.2708333333333144 68.5125000000000028, -162.2857577853732494 68.5121466742621692, -162.2892422146267108 68.5086866590712020, -162.2958333333333201 68.5083333333333400, -162.2970967610677064 68.5042419433593892, -162.3062110053168396 68.4964887830946338, -162.3104556613498062 68.4951778835720688, -162.3145443386501654 68.4923221164279710, -162.3229556613498232 68.4910112169053917, -162.3289208306206604 68.4868445502387289, -162.3396223280164747 68.4881554497612939, -162.3437110053168340 68.4910112169053917, -162.3479556613498005 68.4923221164279710, -162.3520443386501597 68.4951778835720688, -162.3604556613498175 68.4964887830946338, -162.3664208306206547 68.5006554497612967, -162.3742563883463390 68.4990837944878592, -162.3757578531900947 68.4799028184678917, -162.3989347669813128 68.4784498426649435, -162.4013147989908816 68.4707421196831802, -162.4080874972873119 68.4660112169054003, -162.4104556613498005 68.4673221164279653, -162.4164208306206376 68.4714887830946282, -162.4199469672308851 68.4695370144314381, -162.4214887830946168 68.4645443386501853, -162.4243445502387146 68.4604556613498403, -162.4249999999999829 68.4583333333333428, -162.4541666666666515 68.4583333333333428, -162.4605438232421761 68.4577660454644246, -162.4699137369791515 68.4494171142578267, -162.4714006212022355 68.4436228434244924, -162.4759195963541458 68.4382042778862996, -162.4866126166449476 68.4367916531033131, -162.4874999999999829 68.4333333333333371, -162.4916666666666458 68.4333333333333371, -162.4920199924044937 68.4357577853732693, -162.4954800075954608 68.4392422146267450, -162.4958333333333087 68.4416666666666771, -162.5024244520399179 68.4420199924045249, -162.5059088812933794 68.4454800075954921, -162.5208333333333144 68.4458333333333400, -162.5232577853732323 68.4454800075954921, -162.5309088812933851 68.4378533257378621, -162.5440911187065751 68.4371466742621664, -162.5475755479600366 68.4336866590711850, -162.5600463867187386 68.4329800075954893, -162.5642422146267165 68.4371466742621664, -162.5666666666666345 68.4375000000000142, -162.5690911187065808 68.4371466742621664, -162.5788089328341925 68.4274549696180685, -162.5791666666666515 68.4250000000000114, -162.5798278808593693 68.4175662570529539, -162.5855438232421761 68.4160993787977532, -162.5894561767578068 68.4130672878689268, -162.5991126166449590 68.4117916531033075, -162.6009090847439040 68.4047902425130303, -162.6230438232421704 68.4035993787977503, -162.6284200032552008 68.3994327121310874, -162.6480438232421761 68.4005672878689381, -162.6534200032551780 68.4047339545356010, -162.6563771565755019 68.4035993787977503, -162.6602895100911326 68.4005672878689381, -162.6730438232421818 68.3994327121310874, -162.6769561767577841 68.3964006212022610, -162.6897104899088333 68.3952660454644104, -162.6936228434244640 68.3922339545355982, -162.6980438232421591 68.3910993787977475, -162.7019561767577898 68.3880672878689353, -162.7313771565754905 68.3869327121310846, -162.7352895100911212 68.3839006212022582, -162.7438771565755076 68.3827660454644217, -162.7477895100911383 68.3797339545355953, -162.7605438232421591 68.3785993787977446, -162.7686228434244526 68.3714006212022696, -162.7772104899088390 68.3702660454644189, -162.7811228434244697 68.3672339545355925, -162.7874999999999943 68.3666666666666742, -162.7874999999999943 68.3500000000000085, -162.7686228434244526 68.3505672878689268, -162.7636372884114451 68.3544311523437642, -162.7619327121310562 68.3477895100911468, -162.7577660454643933 68.3424133300781307, -162.7589006212022298 68.3394561767578210, -162.7619327121310562 68.3355438232421903, -162.7630672878688927 68.3144561767578153, -162.7661980523003251 68.3104166666666686, -162.7619327121310562 68.3049133300781364, -162.7635067409939040 68.3008110894097342, -162.7701249864366275 68.2991126166449760, -162.7714006212022468 68.2894561767578239, -162.7744327121310448 68.2855438232421932, -162.7749999999999773 68.2833333333333456, -162.7746466742621294 68.2809088812934135, -162.7711866590711622 68.2774244520399378, -162.7704752604166458 68.2725429958767478, -162.7645836724175297 68.2666809082031278, -162.7607577853732437 68.2704800075954950, -162.7541666666666629 68.2708333333333428, -162.7548221164279312 68.2645443386501825, -162.7589887830945941 68.2585791693793453, -162.7576158311631787 68.2299126519097285, -162.7521223280164691 68.2256554497612910, -162.7466457790798415 68.2239644368489593, -162.7450208875867759 68.2135355631510549, -162.7376654730902601 68.2112643771701386, -162.7214887830945997 68.1937889946831604, -162.7200208875867986 68.1843688964843864, -162.7145443386501427 68.1826778835720546, -162.7104556613498119 68.1798221164279568, -162.6881869845919937 68.1784261067708428, -162.6874999999999716 68.1500000000000057, -162.6883507622612797 68.1466840955946225, -162.6964006212022298 68.1446183946397639, -162.6952660454643933 68.1227895100911525, -162.6922339545355669 68.1188771565755218, -162.6916666666666345 68.1125000000000114, -162.6987494574652544 68.1117775811089672, -162.7006429036458144 68.1076995849609546, -162.6915167914496294 68.0970426771376083, -162.6829111735025890 68.0944517347547986, -162.6840857611761919 68.0798356797960338, -162.7489451090494583 68.0785037570529710, -162.7506429036458258 68.0728649563259722, -162.7633117675781023 68.0590074327257213, -162.8146348741319400 68.0576905992296162, -162.8186984592013573 68.0548094007704236, -162.8367251925998005 68.0534274631076528, -162.8374999999999773 68.0458333333333343, -162.8381910536024009 68.0216296725803176, -162.8521223280164634 68.0201778835720745, -162.8603776719834855 68.0131554497612996, -162.8839887830945941 68.0116753472222371, -162.8826778835720290 67.9812110053168652, -162.8798221164279312 67.9771223280165202, -162.8781836615668226 67.9718163384331859, -162.8728776719835025 67.9701778835720631, -162.8687889946831433 67.9673221164279653, -162.8666666666666458 67.9666666666666828, -162.8666666666666458 67.9625000000000199, -162.8857577853732437 67.9621466742621720, -162.8892422146267336 67.9586866590712049, -162.8940911187065694 67.9579800075955092, -162.8979173448350650 67.9541805691189467, -162.9059088812933851 67.9621466742621720, -162.9267130533854129 67.9628533257378677, -162.9309088812933908 67.9586866590712049, -162.9357577853732550 67.9579800075955092, -162.9392422146267165 67.9545199924045278, -162.9416666666666629 67.9541666666666799, -162.9410993787977304 67.9605438232422046, -162.9380672878689040 67.9644561767578352, -162.9369327121310675 67.9779517279731067, -162.9438771565754962 67.9797339545356039, -162.9477895100911269 67.9827660454644302, -162.9605438232421761 67.9839006212022809, -162.9644561767578068 67.9869327121310931, -162.9840799967447822 67.9880672878689438, -162.9894561767577841 67.9839006212022809, -163.0230438232421761 67.9827660454644302, -163.0269561767578068 67.9797339545356039, -163.0291666666666401 67.9791666666666714, -163.0357577853732494 67.9788133409288378, -163.0392422146267108 67.9753533257378706, -163.0440911187065751 67.9746466742621749, -163.0475755479600650 67.9711866590712077, -163.0565911187065922 67.9704800075955120, -163.0600755479600537 67.9670199924045306, -163.0732577853732437 67.9663133409288349, -163.0767422146267336 67.9628533257378677, -163.0899244520399236 67.9621466742621720, -163.0975755479600480 67.9545199924045278, -163.1065911187065751 67.9538133409288463, -163.1163089328341869 67.9441218058268390, -163.1170199924044937 67.9392422146267592, -163.1204800075954608 67.9357577853732835, -163.1211866590711566 67.9309088812934192, -163.1246466742621237 67.9274244520399577, -163.1249999999999716 67.8958333333333570, -163.1246419270833314 67.8933764987521897, -163.1190911187065922 67.8878533257378649, -163.1142422146267279 67.8871466742621692, -163.1065911187065751 67.8795199924045392, -163.1041666666666572 67.8791666666666913, -163.0923804389105669 67.8784279717339558, -163.0910112169053718 67.8478776719835253, -163.0881554497612740 67.8437889946831802, -163.0874999999999773 67.8375000000000199, -163.0883507622612569 67.8341842651367415, -163.0938771565755019 67.8327660454644246, -163.1019561767577954 67.8255672878689495, -163.1063771565755189 67.8244327121310988, -163.1102895100911212 67.8214006212022724, -163.1162706163194400 67.8198655870225906, -163.1202660454644047 67.8147104899088760, -163.1217424180772468 67.8089569091797131, -163.1333333333333258 67.8083333333333513, -163.1357577853732437 67.8079800075955035, -163.1392422146267336 67.8045199924045363, -163.1440911187065694 67.8038133409288406, -163.1475755479600593 67.8003533257378592, -163.1565911187065865 67.7996466742621777, -163.1600755479600480 67.7961866590711963, -163.1649244520399122 67.7954800075955006, -163.1684088812934021 67.7920199924045335, -163.1708333333333201 67.7916666666666856, -163.1732577853732380 67.7920199924045335, -163.1767422146267279 67.7954800075955006, -163.1815911187065922 67.7961866590711963, -163.1850755479600537 67.7996466742621777, -163.1933795505099738 67.8003533257378592, -163.1979166666666572 67.7958479139540060, -163.2017422146267336 67.7996466742621777, -163.2190911187065865 67.8003533257378592, -163.2225755479600480 67.8038133409288406, -163.2308831108940694 67.8045199924045363, -163.2434088812933908 67.7920199924045335, -163.2458333333333087 67.7916666666666856, -163.2449824015299384 67.7883509318034072, -163.2369327121310505 67.7862850613064438, -163.2383076985676951 67.7800286187066092, -163.2449824015299384 67.7783157348632983, -163.2466842651367074 67.7716842651367415, -163.2500000000000000 67.7708333333333570, -163.2605438232421875 67.7702660454644246, -163.2644561767577898 67.7672339545356124, -163.2674133300781136 67.7660993787977617, -163.2727895100911439 67.7702660454644246, -163.2966834174262090 67.7714006212022753, -163.3034623887803605 67.7657472398546190, -163.3048751831054517 67.7550540500217267, -163.3118764241536383 67.7532574123806626, -163.3130672878689040 67.7311228434245010, -163.3170625474717781 67.7259677463107863, -163.3230438232421875 67.7244327121310903, -163.3352895100911439 67.7130672878689381, -163.3406599256727247 67.7116890801324018, -163.3422339545355726 67.7075866699218949, -163.3380672878689097 67.7022104899088788, -163.3374999999999773 67.7000000000000171, -163.3371466742621294 67.6725755479600934, -163.3336866590711622 67.6690911187066177, -163.3333333333333144 67.6666666666666856, -163.3311228434244526 67.6672339545356039, -163.3257466634114508 67.6714006212022809, -163.3061228434244754 67.6702660454644302, -163.3022104899088447 67.6672339545356039, -163.2842390272352304 67.6660290188259665, -163.2833333333333314 67.6625000000000227, -163.2836866590711793 67.6559088812934135, -163.2871466742621465 67.6524244520399520, -163.2874999999999943 67.6333333333333542, -163.3041666666666458 67.6333333333333542, -163.3107577853732550 67.6329800075955063, -163.3246458265516310 67.6191175672743299, -163.3253533257378365 67.5982871161566976, -163.3211866590711736 67.5940911187066149, -163.3204800075954779 67.5725755479600849, -163.3125135633680429 67.5645836724175552, -163.3187340630425126 67.5583319769965414, -163.3225755479600423 67.5621466742621664, -163.3308810763888630 67.5628533257378621, -163.3371443006727191 67.5566211276584312, -163.3378533257378251 67.5475755479600934, -163.3413133409288207 67.5440911187066177, -163.3420199924044880 67.5350755479600906, -163.3454800075954836 67.5315911187066149, -163.3458333333333314 67.5291666666666828, -163.3458333333333314 67.5250000000000199, -163.3467329237195997 67.5214945475260606, -163.3541666666666572 67.5208333333333428, -163.3535993787977247 67.5144561767578324, -163.3505672878688983 67.5105438232422017, -163.3492957221137090 67.5009194268120893, -163.3438771565755019 67.4964006212022696, -163.3259938557942519 67.4952014499240676, -163.3160993787977304 67.4842929416232806, -163.3172893948025148 67.4634875827365619, -163.3227895100911269 67.4589006212022753, -163.3272104899088504 67.4577660454644246, -163.3311228434244526 67.4547339545356124, -163.3438771565755019 67.4535993787977617, -163.3477895100911326 67.4505672878689353, -163.3535524156358463 67.4490883721245780, -163.3547809176974681 67.4217449612087876, -163.3605438232421818 67.4202660454644302, -163.3644561767578125 67.4172339545356039, -163.3772104899088333 67.4160993787977532, -163.3811228434244640 67.4130672878689410, -163.3897104899088504 67.4119327121310903, -163.3936228434244526 67.4089006212022781, -163.3991490681966070 67.4074824015299612, -163.3999999999999773 67.4041666666666828, -163.3993949042425982 67.3769939846462762, -163.3952282375759353 67.3713740030924697, -163.3964384290906935 67.3353273179796190, -163.4131050957573734 67.3175486246745010, -163.4116809421115306 67.3090504964192888, -163.3978273179795906 67.3077282375759722, -163.3938393486870666 67.3047717624240533, -163.3853273179796020 67.3035615709093094, -163.3812499999999943 67.3005388047960196, -163.3755406697590900 67.3047717624240533, -163.3394939846462535 67.3035615709093094, -163.3355060153537295 67.3006050957573905, -163.3311606513129277 67.2993949042426323, -163.3271726820203753 67.2964384290907276, -163.3186606513129107 67.2952282375759694, -163.3105060153537238 67.2881050957573876, -163.2394939846462592 67.2868949042426436, -163.2355060153537067 67.2839384290907248, -163.2311606513129334 67.2827282375759665, -163.2271726820203810 67.2797717624240619, -163.2208333333333314 67.2791666666666828, -163.2183764987521499 67.2788085937500142, -163.2128533257378251 67.2732577853732749, -163.2121419270833087 67.2683764987521897, -163.2065911187065694 67.2628533257378649, -163.2041666666666515 67.2625000000000171, -163.2017422146267336 67.2628533257378649, -163.1933822631835938 67.2711866590711907, -163.1767422146267279 67.2704800075954950, -163.1690911187065751 67.2628533257378649, -163.1600755479600480 67.2621466742621692, -163.1482577853732607 67.2503533257378621, -163.1458333333333144 67.2500000000000142, -163.1449825710720347 67.2466842651367358, -163.1394561767577898 67.2452660454644189, -163.1355438232421591 67.2422339545356067, -163.1311228434244640 67.2410993787977560, -163.1272104899088333 67.2380672878689438, -163.0727895100911269 67.2369327121310931, -163.0647104899088333 67.2297339545356039, -163.0519561767577841 67.2285993787977532, -163.0426038953992816 67.2202660454644274, -163.0311228434244697 67.2214006212022781, -163.0272104899088390 67.2244327121310903, -163.0227895100911439 67.2255672878689410, -163.0174133300781136 67.2297339545356039, -163.0144561767577898 67.2285993787977532, -163.0105438232421591 67.2255672878689410, -163.0083333333333258 67.2250000000000085, -163.0079800075954779 67.2225755479600906, -162.9961866590711566 67.2107577853732749, -162.9954800075954608 67.2059088812934107, -162.9836866590711679 67.1940911187066092, -162.9833333333333201 67.1916666666666771, -162.9809088812933737 67.1920199924045249, -162.9774244520399122 67.1954800075955063, -162.9517422146267336 67.1961866590712020, -162.9440911187065808 67.2038133409288321, -162.9333333333333087 67.2041666666666799, -162.9225755479600650 67.2038133409288321, -162.9190911187065751 67.2003533257378649, -162.9142422146267108 67.1996466742621692, -162.9107577853732494 67.1961866590712020, -162.8475755479600480 67.1954800075955063, -162.8440911187065865 67.1920199924045249, -162.8416666666666401 67.1916666666666771, -162.8406185574001483 67.1881859673394217, -162.8103651258680316 67.1868572658962790, -162.8063015407985858 67.1839760674370865, -162.7978651258680429 67.1826905992296162, -162.7896348741319343 67.1756427341037465, -162.7811984592013630 67.1743572658962762, -162.7771348741319173 67.1714760674370837, -162.7593712700737569 67.1701143052843008, -162.7573689778645587 67.1634641859266566, -162.7520317925346944 67.1618572658962876, -162.7479682074652487 67.1589760674370808, -162.7436984592013687 67.1576905992296105, -162.7396348741319230 67.1548095703125085, -162.7311984592013800 67.1535237630208428, -162.7229682074652715 67.1464762369791828, -162.7091047498914804 67.1450619167751910, -162.7075127495659501 67.1294559054904596, -162.7020833333333201 67.1256062825520985, -162.6979682074652658 67.1285237630208513, -162.6936984592013573 67.1298095703125171, -162.6839670817057026 67.1381429036458428, -162.6728651258680429 67.1368570963541771, -162.6646348741319343 67.1298095703125171, -162.6478651258680372 67.1285237630208513, -162.6438015407985915 67.1256429036458542, -162.6340491400824533 67.1241566975911610, -162.6333333333333258 67.1125000000000114, -162.6257198757595290 67.1132765028211935, -162.6249999999999716 67.1250000000000142, -162.6102895100911212 67.1244327121310960, -162.6063771565754905 67.1214006212022696, -162.5769561767577898 67.1202660454644189, -162.5715799967447595 67.1160993787977560, -162.5436228434244583 67.1172339545356067, -162.5382466634114280 67.1214006212022696, -162.5227895100911155 67.1202660454644189, -162.5174133300781136 67.1160993787977560, -162.5061228434244640 67.1172339545356067, -162.5022104899088333 67.1202660454644189, -162.4977895100911383 67.1214006212022696, -162.4938771565755076 67.1244327121310960, -162.4686228434244697 67.1255672878689325, -162.4632466634114394 67.1297339545356095, -162.4508965386284558 67.1284929063585167, -162.4499999999999886 67.1250000000000142, -162.4505672878688927 67.1227895100911667, -162.4547339545355840 67.1174133300781364, -162.4535993787977191 67.1061228434244867, -162.4505672878688927 67.1022104899088703, -162.4493442111544823 67.0884599473741474, -162.4438771565754962 67.0839006212022753, -162.4352895100911383 67.0827660454644246, -162.4313771565755076 67.0797339545355982, -162.4255984836154312 67.0782511393229299, -162.4249999999999829 67.0583333333333513, -162.4572784423828011 67.0576704237196282, -162.4593760172525947 67.0507035997178917, -162.4822906494140398 67.0492964002821310, -162.4843634711371294 67.0424116346571282, -162.4989698621961622 67.0409216986762289, -162.5009643554687386 67.0342976888020985, -162.5073689778645587 67.0323689778645928, -162.5092976888020644 67.0259643554687585, -162.5159216986762090 67.0239698621961963, -162.5174435085720290 67.0090511745876825, -162.5402187771267108 67.0076904296875142, -162.5427195231119697 67.0159969753689353, -162.5902187771267222 67.0173095703125057, -162.5926523844400720 67.0092258029514056, -162.5990844726562443 67.0076904296875142, -162.6007720947265511 67.0242353651258753, -162.6153154161241048 67.0256429036458456, -162.6173095703124716 67.0181145562066121, -162.6092556423610915 67.0156897650824845, -162.6076904296874943 67.0097812228732721, -162.6157023111979072 67.0073689778646013, -162.6176435682508554 67.0009223090277857, -162.6235521104600537 66.9993570963541742, -162.6260481092664634 67.0076473659939325, -162.6575544569227247 67.0090311686197992, -162.6590783013237740 67.0239698621961963, -162.6657023111978901 67.0259643554687585, -162.6676968044704665 67.0325883653428889, -162.6825619167751427 67.0341047498915117, -162.6841122097439154 67.0493021647135521, -162.6999999999999886 67.0500000000000114, -162.7041666666666515 67.0500000000000114, -162.7905846489800297 67.0493370903863024, -162.7927480061848655 67.0423312717013999, -162.9325917561848769 67.0409990098741417, -162.9340674506293283 67.0174526638455035, -162.9485110812716755 67.0160112169053974, -162.9510738796657847 67.0243106418185874, -162.9905927870008497 67.0256893581814381, -162.9927446153428718 67.0326578776041799, -163.0572553846571111 67.0340087890625114, -163.0594126383463447 67.0409952799479356, -163.1405873616536439 67.0423380533854356, -163.1427446153428775 67.0493245442708456, -163.2072553846571168 67.0506754557291771, -163.2094131469726506 67.0576636420356067, -163.2989201863606752 67.0590030246310960, -163.3010779486762090 67.0659912109375114, -163.3655887179904482 67.0673421223958428, -163.3677424112955521 67.0743170844184107, -163.4155909220377509 67.0756829155816092, -163.4177464803059650 67.0826636420355982, -163.5072535196939896 67.0840030246310874, -163.5094138251410527 67.0909990098741389, -163.6155861748589189 67.0923343234592124, -163.6177437676323621 67.0993211534288321, -163.6739228990342667 67.1006788465711992, -163.6760708279079779 67.1076344807942888, -163.7072625054253479 67.1090321858724081, -163.7093985663519788 67.1159498426649463, -163.7322681003146556 67.1173834906684164, -163.7343163384331604 67.1240169949001881, -163.7409910413953753 67.1260779486762260, -163.7416666666666458 67.1583333333333456, -163.7416666666666458 67.1625000000000085, -163.7422473483615306 67.2074130588107721, -163.7493764241536383 67.2092425876193715, -163.7506235758463333 67.2324240790473198, -163.7577097574869640 67.2342425876193772, -163.7589569091796875 67.2574240790473254, -163.7660054524739621 67.2592329237196367, -163.7673278808593693 67.2741004096137374, -163.7743387858072879 67.2758995903863024, -163.7756612141926951 67.2907670762804031, -163.7824824015299328 67.2925175984700701, -163.7841842651367017 67.2991490681966269, -163.7908157348632585 67.3008509318033958, -163.7925175984700559 67.3074824015299669, -163.7993387858072936 67.3092329237196338, -163.8006612141927008 67.3241004096137345, -163.8074824015299384 67.3258509318034015, -163.8091842651367074 67.3324824015299583, -163.8160430908203011 67.3342425876193715, -163.8166666666666629 67.3458333333333456, -163.8166666666666629 67.3500000000000227, -163.8241004096137203 67.3506612141927263, -163.8258509318033873 67.3574824015299640, -163.8326721191406250 67.3592329237196310, -163.8339945475260322 67.3741004096137317, -163.8408157348632699 67.3758509318033987, -163.8425175984700388 67.3824824015299697, -163.8493387858072765 67.3842329237196367, -163.8506612141927121 67.3991004096137374, -163.8574824015299498 67.4008509318034044, -163.8591842651367188 67.4074824015299612, -163.8658157348632756 67.4091842651367301, -163.8675175984700445 67.4158157348633011, -163.8741490681966013 67.4175175984700701, -163.8758509318033703 67.4241490681966269, -163.8824824015299271 67.4258509318033958, -163.8841842651366960 67.4324824015299669, -163.8908157348632812 67.4341842651367358, -163.8925662570529482 67.4410054524739735, -163.9074337429470347 67.4423278808593949, -163.9091842651367017 67.4491490681966326, -163.9158157348632585 67.4508509318034015, -163.9175175984700559 67.4574824015299583, -163.9241490681966127 67.4591842651367415, -163.9258509318033816 67.4658157348632983, -163.9326721191406193 67.4675662570529653, -163.9333333333333371 67.4750000000000227, -163.9406365288628251 67.4757449679904653, -163.9426310221354015 67.4823691474067004, -163.9490356445312216 67.4842975192599965, -163.9509643554687273 67.4907024807400404, -163.9573689778645473 67.4926308525933365, -163.9592976888020530 67.4990358140733662, -163.9657023111979015 67.5009641859266623, -163.9676310221353788 67.5073691474067061, -163.9740356445312273 67.5092975192600022, -163.9759643554687329 67.5157024807400319, -163.9823689778645530 67.5176308525933280, -163.9843634711371294 67.5242550320095631, -163.9989698621961622 67.5257449679904624, -164.0009643554687386 67.5323691474066976, -164.0073689778645587 67.5342975192599937, -164.0092976888020644 67.5407024807400376, -164.0157023111978845 67.5426308525933337, -164.0176310221353901 67.5490358140733633, -164.0240356445312386 67.5509641859266594, -164.0260301378037866 67.5575883653428946, -164.0406365288628194 67.5590783013238081, -164.0426310221353958 67.5657024807400290, -164.0490356445312159 67.5676308525933393, -164.0510301378037923 67.5742550320095603, -164.0656365288628251 67.5757449679904738, -164.0676310221354015 67.5823691474066948, -164.0740356445312216 67.5842975192600051, -164.0760301378037980 67.5909216986762260, -164.0906365288628308 67.5924116346571395, -164.0927093505859204 67.5992964002821282, -164.1156239827473655 67.6007035997179031, -164.1176968044704552 67.6075883653429059, -164.1323031955294880 67.6090783013238052, -164.1343634711371351 67.6159216986762317, -164.1492285834418112 67.6174380832248403, -164.1499999999999773 67.6250000000000142, -164.1657311333550240 67.6256206936306654, -164.1673233628639537 67.6316557570920338, -164.1709787518346673 67.6328458662276830, -164.1990644666883554 67.6339540269639912, -164.2009311252169823 67.6410296969943801, -164.2240688747829722 67.6423036363389940, -164.2259355333115991 67.6493793063693687, -164.2573978000216925 67.6506206936306569, -164.2591221588016310 67.6571565696514625, -164.2607574462890625 67.6575546264648438, -164.2616948096438989 67.6578083586400396, -164.2907311333550240 67.6589540269639969, -164.2926045735677008 67.6660551283094804, -164.3323954264322708 67.6672782050238908, -164.3342644585503365 67.6743630303277115, -164.3574022081162980 67.6756369696723254, -164.3592688666449533 67.6827126397027143, -164.3907311333550183 67.6839540269639883, -164.3926021999782847 67.6910459730360401, -164.4240644666883497 67.6922873602973283, -164.4259311252170050 67.6993630303277030, -164.4490688747829665 67.7006369696723311, -164.4509355333116218 67.7077126397027058, -164.4823978000216869 67.7089540269639940, -164.4842644585503137 67.7160296969943829, -164.5074520534938927 67.7173063490126026, -164.5089131673177008 67.7237477620442831, -164.5017269781722291 67.7256435999799749, -164.5036163330078125 67.7257537841796875, -164.5479888916015625 67.7386322021484375, -164.5502204739463252 67.7395050829368017, -164.5509155273437329 67.7326905992296133, -164.5589762369791345 67.7346145629882983, -164.5573625352647298 67.7409155951606152, -164.5545579838560570 67.7412016947954072, -164.5758781439687084 67.7495410501460924, -164.5749932183159672 67.7450627644856951, -164.5763888888888573 67.7416666666666885, -164.5825052897135095 67.7423794216580006, -164.5838012695312216 67.7489386664496749, -164.5775142383214416 67.7501810065124062, -164.6226348876953125 67.7678298950195312, -164.6609649658203125 67.7852935791015625, -164.7165462822032111 67.8051102324237718, -164.7162899441188983 67.8046990288628706, -164.7180555555555372 67.8000000000000256, -164.7325676812065751 67.8006898668077440, -164.7332621256510379 67.8075046115451556, -164.7254888321730846 67.8082968934296133, -164.7415771484375000 67.8140182495117188, -164.7423623379930291 67.8148571522831105, -164.7410237630208201 67.8092368231879590, -164.7568854437933794 67.8076905992296162, -164.7593634711371351 67.8159216986762345, -164.7739698621961679 67.8174116346571338, -164.7760426839192576 67.8242964002821367, -164.7989573160807026 67.8257035997178974, -164.8010301378037923 67.8325883653429003, -164.8156365288628251 67.8340783013237996, -164.8177093505859148 67.8409630669488024, -164.8406239827473883 67.8423702663845631, -164.8426968044704779 67.8492550320095660, -164.8573031955295107 67.8507449679904653, -164.8583333333333201 67.8541666666666856, -164.8583333333333201 67.8583333333333485, -164.8824161105685562 67.8589262220594804, -164.8842468261718466 67.8660591973198990, -164.9157531738281079 67.8672741360134779, -164.9175662570529255 67.8743387858073106, -164.9324337429470404 67.8756612141927320, -164.9342424180772468 67.8827097574869924, -164.9574242485894047 67.8839569091797017, -164.9592424180772525 67.8910430908203324, -164.9824242485893819 67.8922902425130417, -164.9842424180772298 67.8993764241536724, -165.0074242485893876 67.9006235758463674, -165.0092329237195941 67.9076721191406421, -165.0241004096137090 67.9089945475260635, -165.0259090847439154 67.9160430908203381, -165.0490909152560732 67.9172902425130474, -165.0509090847439211 67.9243764241536638, -165.0740909152560505 67.9256235758463731, -165.0758995903862569 67.9326721191406477, -165.0907670762803718 67.9339945475260549, -165.0923280598030942 67.9400768948618037, -165.0961032076319555 67.9411950520859023, -165.1240865071614508 67.9422741360134808, -165.1259134928385208 67.9493925306532276, -165.1574200100368728 67.9506074693468065, -165.1592329237195997 67.9576721191406392, -165.1741004096137146 67.9589945475260606, -165.1758995903862797 67.9660054524739792, -165.1833333333333087 67.9666666666666828, -165.1875000000000000 67.9666666666666828, -165.1990907457139599 67.9672902425130303, -165.2008509318033589 67.9741492377387146, -165.2074824015299441 67.9758507622612882, -165.2092329237196111 67.9826721191406307, -165.2241004096136976 67.9839945475260521, -165.2259092542860230 67.9910430908203125, -165.2490907457139713 67.9922902425130218, -165.2509092542860003 67.9993764241536525, -165.2740907457139485 68.0006235758463617, -165.2759092542860060 68.0077097574869782, -165.2990907457139542 68.0089569091796875, -165.3009092542860117 68.0160430908203182, -165.3240907457139599 68.0172902425130275, -165.3259092542860174 68.0243764241536439, -165.3490907457139656 68.0256235758463532, -165.3509156968858349 68.0327348497178832, -165.3907509697808109 68.0339318169487939, -165.3925799899630817 68.0410590277777771, -165.4240866767035527 68.0422743055555657, -165.4259133232964416 68.0493923611111171, -165.4574200100368842 68.0506076388888914, -165.4592503865559650 68.0577406141493100, -165.5074162801106752 68.0589260525173643, -165.5092503865559763 68.0660739474826499, -165.5574162801106581 68.0672593858507042, -165.5592503865559877 68.0744072808159757, -165.6074162801106695 68.0755927191840300, -165.6092503865559706 68.0827406141493157, -165.6574162801106809 68.0839260525173700, -165.6592522515190922 68.0910807291666771, -165.7240810818142336 68.0922526041666742, -165.7259206136067746 68.0994205050998289, -165.8240793863932083 68.1005794949001739, -165.8259170532226392 68.1077406141493071, -165.8740829467773210 68.1089260525173614, -165.8758509318033703 68.1158159044053946, -165.8791666666666629 68.1166666666666742, -165.9072794596353901 68.1173326280381985, -165.9093760172525833 68.1242964002821196, -165.9322906494140284 68.1257035997178946, -165.9343814425998005 68.1326473659939325, -165.9656185574001483 68.1340193006727475, -165.9676968044704495 68.1409216986762232, -165.9825619167751540 68.1424380832248318, -165.9840783013237626 68.1573031955295221, -165.9907023111978788 68.1592976888020843, -165.9926968044704552 68.1659216986762146, -166.0075619167751597 68.1674380832248374, -166.0091047498914634 68.1825619167751853, -166.0239698621961679 68.1840783013237939, -166.0259643554687159 68.1907023111979242, -166.0323689778645644 68.1926310221354299, -166.0343634711371408 68.1992550320095603, -166.0489698621961452 68.2007449679904596, -166.0510301378037923 68.2075883653428860, -166.0656365288628251 68.2090783013237854, -166.0676968044704722 68.2159216986762260, -166.0823031955295050 68.2174116346571253, -166.0843634711371237 68.2242550320095518, -166.0989698621961566 68.2257449679904511, -166.1010426839192462 68.2326297336154539, -166.1239573160807197 68.2340369330512146, -166.1260301378038093 68.2409216986762175, -166.1406365288628137 68.2424116346571310, -166.1427093505859034 68.2492964002821196, -166.1656239827473769 68.2507035997178946, -166.1677093505859091 68.2576297336154596, -166.1906239827473826 68.2590369330512203, -166.1927147759331262 68.2659806993272582, -166.2239518907334741 68.2673526340060874, -166.2260481092664577 68.2743140326605982, -166.2572852240668055 68.2756859673394132, -166.2593814425998175 68.2826473659939239, -166.2906185574001654 68.2840193006727532, -166.2927174886067405 68.2909901936849053, -166.3322825113932026 68.2923431396484375, -166.3343841552734261 68.2993235270182311, -166.3739491780598883 68.3006764729817775, -166.3760528564452841 68.3076633029513971, -166.4239471435546704 68.3090033637152914, -166.4260538736978958 68.3160007052951528, -166.4822794596354072 68.3173326280382014, -166.4843872070312329 68.3243340386284785, -166.5406127929687443 68.3256659613715414, -166.5427222357855612 68.3326727973090300, -166.6156110975477134 68.3339938693576414, -166.6177242702907790 68.3410129123263914, -166.7322757297091869 68.3423204210069457, -166.7343814425998119 68.3493147108290060, -166.7652187771267052 68.3506429036458343, -166.7676981608072708 68.3424068874783046, -166.7818854437933851 68.3410237630208428, -166.7843102349175126 68.3490776909722229, -166.7902187771267108 68.3506429036458343, -166.7927178276909501 68.3423424614800439, -166.8320522732204552 68.3410237630208428, -166.8339762369791401 68.3490844726562585, -166.8176968044704722 68.3507449679904653, -166.8156158447265511 68.3576568603515682, -166.7760508219400890 68.3590098063151146, -166.7739471435546648 68.3659966362847342, -166.7260528564453068 68.3673366970486143, -166.7239471435546818 68.3743299696180600, -166.6760528564452954 68.3756700303819542, -166.6739461263020701 68.3826673719618157, -166.6177205403645587 68.3839992947048643, -166.6156127929687329 68.3910007052951414, -166.5593872070312216 68.3923326280382042, -166.5572794596353958 68.3993340386284814, -166.5010538736978845 68.4006659613715300, -166.4989471435546591 68.4076633029513914, -166.4510528564453011 68.4090033637152857, -166.4489491780598769 68.4159901936849053, -166.4093841552734148 68.4173431396484517, -166.4072852240668112 68.4243140326606039, -166.3916666666666515 68.4250000000000114, -166.3874999999999886 68.4250000000000114, -166.3760426839192519 68.4257035997178917, -166.3739573160807197 68.4326297336154568, -166.3510426839192462 68.4340369330512175, -166.3489698621961566 68.4409216986762203, -166.3343634711371237 68.4424116346571196, -166.3323689778645758 68.4490356445312642, -166.3259643554687273 68.4509643554687557, -166.3239698621961509 68.4575883653428860, -166.3090057373046591 68.4591149224175410, -166.3083333333333087 68.4875000000000114, -166.3083333333333087 68.4916666666666742, -166.3075883653428662 68.4989698621961907, -166.3007035997178491 68.5010426839192803, -166.2992801242404255 68.5242234971788235, -166.2843634711371408 68.5257449679904624, -166.2823689778645644 68.5323689778645928, -166.2759643554687159 68.5342976888020985, -166.2739698621961679 68.5409216986762289, -166.2593634711371351 68.5424116346571282, -166.2573689778645587 68.5490356445312585, -166.2509643554687386 68.5509643554687642, -166.2490356445312329 68.5573689778645985, -166.2426310221353845 68.5592976888020900, -166.2407023111979072 68.5657023111979242, -166.2342976888020587 68.5676310221354299, -166.2323689778645530 68.5740356445312642, -166.2259223090277658 68.5759769015842124, -166.2243570963541401 68.5818854437934107, -166.2326575385199305 68.5843844943576499, -166.2339762369791458 68.6235521104600821, -166.2257019042968409 68.6260430230034757, -166.2243570963541401 68.6485521104600735, -166.2324110243055202 68.6509769015842153, -166.2339762369791458 68.6568854437934135, -166.2259643554687329 68.6592976888020985, -166.2240356445312273 68.6657023111979328, -166.2176310221354072 68.6676310221354242, -166.2157023111979015 68.6740356445312585, -166.2092976888020530 68.6759643554687642, -166.2073689778645473 68.6823689778645985, -166.2006852891709912 68.6843814425998431, -166.1993570963541345 68.7152187771267506, -166.2074110243055429 68.7176435682508782, -166.2089762369791401 68.7235521104600764, -166.2007449679904312 68.7260301378038321, -166.1999999999999886 68.7333333333333485, -166.1999999999999886 68.7375000000000114, -166.1993211534287980 68.7655897352430685, -166.1910112169053662 68.7681555853949789, -166.1923648410373175 68.7989288330078210, -166.1992411295572651 68.8010521782769189, -166.2007588704426837 68.8156144883897696, -166.2076165093315865 68.8177320692274463, -166.2090501573350423 68.8406012641059135, -166.2159077962239451 68.8427188449435903, -166.2174255371093636 68.8572811550564410, -166.2256554497612626 68.8598222520616474, -166.2241797553168112 68.8839887830946225, -166.1094143337673472 68.8826666937934107, -166.1072519938150833 68.8756652832031335, -165.9760813395182026 68.8743347167968807, -165.9739179823133384 68.8673295762803974, -165.8010820176866105 68.8660037570529653, -165.7985110812716698 68.8576778835720660, -165.7926625569661212 68.8592749701605982, -165.7901777479383441 68.8673221164279568, -165.7677324083116162 68.8659515380859517, -165.7655887179904255 68.8590087890625142, -165.7333333333333201 68.8583333333333485, -165.7291666666666572 68.8583333333333485, -165.3092566596137090 68.8589019775390767, -165.3074118720160470 68.8660909016927150, -165.1675881279839189 68.8672424316406335, -165.1657472398545963 68.8744160970052235, -165.0925862630208201 68.8755839029948049, -165.0907450358072879 68.8827575683593807, -164.9509216308593693 68.8839090983072992, -164.9490783691406079 68.8910909016927206, -164.8791666666666629 68.8916666666666799, -164.8749999999999716 68.8916666666666799, -164.8592468261718693 68.8922743055555742, -164.8574117024739394 68.8994242350260606, -164.7175882975260208 68.9005757649739650, -164.7157484266492986 68.9077443440755388, -164.6592515733506730 68.9089223225911525, -164.6574123806423415 68.9160881890191064, -164.6041666666666572 68.9166666666666856, -164.5999999999999943 68.9166666666666856, -164.4342559814452898 68.9172373453776146, -164.4324117024739280 68.9244245741102617, -164.2842549641926837 68.9255754258897753, -164.2824137369791515 68.9327494303385606, -164.2092529296874659 68.9339172363281421, -164.2074161105685448 68.9410739474826499, -164.1592505560980726 68.9422593858507042, -164.1574198404947822 68.9493923611111228, -164.1259134928385208 68.9506076388888971, -164.1240909152560619 68.9577097574869953, -164.1009090847439040 68.9589569091797046, -164.0990909152560562 68.9660430908203210, -164.0759090847438983 68.9672902425130303, -164.0740865071614394 68.9743923611111285, -164.0583333333333087 68.9750000000000085, -164.0541666666666458 68.9750000000000085, -164.0259180704752566 68.9755889892578296, -164.0240819295247263 68.9827443440755275, -163.9675847371419195 68.9839223225911553, -163.9657533433702099 68.9910590277777942, -163.9342466566297674 68.9922743055555685, -163.9324240790473084 68.9993764241536525, -163.9092425876193602 69.0006235758463617, -163.9074337429470347 69.0076721191406364, -163.8925662570529482 69.0089945475260578, -163.8907670762803832 69.0160054524739763, -163.8758995903862683 69.0173278808593835, -163.8741004096137033 69.0243387858073021, -163.8592329237196168 69.0256612141927235, -163.8574240790472913 69.0327097574869981, -163.8342425876193431 69.0339569091796932, -163.8324240790473141 69.0410430908203239, -163.8092425876193374 69.0422902425130331, -163.8074240790473084 69.0493764241536638, -163.7842425876193602 69.0506235758463731, -163.7824176364474624 69.0577348497178889, -163.7425823635525148 69.0589318169487996, -163.7407509697808052 69.0660681830512289, -163.7009156968858292 69.0672651502821253, -163.6991004096136919 69.0743387858072992, -163.6842329237196054 69.0756612141927206, -163.6824337429470404 69.0826721191406392, -163.6675662570529539 69.0839945475260606, -163.6657670762803605 69.0910054524739650, -163.6508995903862740 69.0923278808593864, -163.6490829467773267 69.0994072808159814, -163.6250000000000000 69.1000000000000085, -163.6250000000000000 69.1041666666666856, -163.6241004096137033 69.1076721191406449, -163.6092329237196168 69.1089945475260521, -163.6074240790472913 69.1160430908203267, -163.5842425876193431 69.1172902425130360, -163.5824337429470461 69.1243387858073106, -163.5675662570529312 69.1256612141927178, -163.5657670762803662 69.1326721191406364, -163.5508995903862797 69.1339945475260578, -163.5491004096137146 69.1410054524739763, -163.5342329237195997 69.1423278808593835, -163.5324337429470347 69.1493387858073021, -163.5175662570529482 69.1506612141927235, -163.5158157348632812 69.1574824015299612, -163.5091842651366960 69.1591842651367301, -163.5074824015299271 69.1658157348633011, -163.5008509318033703 69.1675175984700701, -163.4991490681966013 69.1741490681966269, -163.4925175984700445 69.1758509318033958, -163.4907670762803775 69.1826721191406335, -163.4758995903862626 69.1839945475260549, -163.4741004096136976 69.1910054524739735, -163.4592329237196111 69.1923278808593949, -163.4574824015299441 69.1991490681966326, -163.4508509318033589 69.2008509318034015, -163.4490907457139599 69.2077097574869953, -163.4259092542860117 69.2089569091797046, -163.4240907457139542 69.2160430908203210, -163.4009092542860060 69.2172902425130303, -163.3991004096137090 69.2243387858073049, -163.3842329237195941 69.2256612141927263, -163.3824337429470290 69.2326721191406449, -163.3675662570529425 69.2339945475260521, -163.3657670762803775 69.2410054524739706, -163.3508995903862626 69.2423278808593921, -163.3491004096136976 69.2493387858073106, -163.3342329237196111 69.2506612141927178, -163.3324824015299441 69.2574824015299555, -163.3258509318033589 69.2591842651367386, -163.3240866767035584 69.2660591973198905, -163.3083333333333087 69.2666666666666799, -163.3083333333333087 69.2708333333333428, -163.3074337429470404 69.2743387858073021, -163.2925662570529255 69.2756612141927235, -163.2907670762803605 69.2826721191406421, -163.2758995903862740 69.2839945475260492, -163.2741004096137090 69.2910054524739678, -163.2592329237195941 69.2923278808593892, -163.2574824015299271 69.2991490681966269, -163.2508509318033703 69.3008509318033958, -163.2491490681966013 69.3074824015299669, -163.2425175984700445 69.3091842651367358, -163.2407533433702156 69.3160591973198876, -163.2249999999999943 69.3166666666666771, -163.2256752861870552 69.3092544555664176, -163.2324635823567576 69.3074635823567888, -163.2342030843098826 69.3008697509765739, -163.2407969156900833 69.2991302490234489, -163.2425364176432083 69.2925364176432481, -163.2505798339843750 69.2904144287109460, -163.2488420274522412 69.2827534993489706, -163.2259318033854072 69.2839680989583542, -163.2241302490234318 69.2907969156901231, -163.2175364176432026 69.2925364176432481, -163.2157969156900776 69.2991302490234489, -163.2092030843098769 69.3008697509765739, -163.2074635823567519 69.3074635823567888, -163.2008697509765511 69.3092030843099138, -163.1990687052408759 69.3160296969943772, -163.1759312947590956 69.3173036363389912, -163.1741302490234204 69.3241302490234546, -163.1675364176432197 69.3258697509765796, -163.1657311333550240 69.3327126397027058, -163.1499999999999773 69.3333333333333428, -163.1493021647135322 69.3492211235894302, -163.1343634711371351 69.3507449679904653, -163.1323689778645587 69.3573691474067004, -163.1259643554687386 69.3592975192599965, -163.1240356445312329 69.3657024807400262, -163.1176310221354129 69.3676308525933365, -163.1156239827473939 69.3742964002821338, -163.0924146864149122 69.3757215711805770, -163.0912445068359204 69.3902850680881187, -163.1006429036458201 69.3931147257487169, -163.0992980957031193 69.4156234741211051, -163.0924116346571111 69.4176968044704950, -163.0909216986761976 69.4323031955295278, -163.0840783013237569 69.4343634711371749, -163.0825883653428718 69.4489698621961935, -163.0759643554687273 69.4509641859266651, -163.0740356445312216 69.4573691474066948, -163.0660237630208087 69.4597813924153797, -163.0676489935980840 69.4659167819553147, -163.0839762369791401 69.4675821940104328, -163.0826158311631673 69.4909183078342210, -163.0761847601996237 69.4914350721571310, -163.0735521104600423 69.4826905992296133, -163.0427147759331490 69.4840184529622604, -163.0407023111978901 69.4907024807400404, -163.0340783013237740 69.4926968044704978, -163.0325619167751654 69.5075619167751881, -163.0249999999999773 69.5083333333333542, -163.0249999999999773 69.5125000000000171, -163.0257198757595347 69.5242233276367330, -163.0406843397352361 69.5257498847113879, -163.0423095703124829 69.5318852742513229, -163.0342976888020701 69.5342975192599937, -163.0323031955294937 69.5409216986762289, -163.0176147460937273 69.5424199422200644, -163.0160237630208258 69.5490844726562614, -163.0325619167751654 69.5507714165581774, -163.0341098361544994 69.5659467909071338, -163.0572906494140568 69.5673702663845717, -163.0593814425998005 69.5743140326606095, -163.0906185574001483 69.5756859673394246, -163.0926968044704779 69.5825883653429003, -163.1075619167751540 69.5841047498915088, -163.1083333333333201 69.5916666666666828, -163.1010301378038037 69.5924116346571395, -163.0989573160807140 69.5992964002821282, -163.0760426839192689 69.6007035997179031, -163.0739573160807083 69.6076297336154681, -163.0507765028211793 69.6090532090929059, -163.0490844726562329 69.6256427341037494, -163.0260437011718579 69.6242996215820540, -163.0239698621961679 69.6174116346571310, -163.0166666666666515 69.6166666666666885, -163.0173804389105783 69.6325946384006187, -163.0406497531466812 69.6340530395507926, -163.0423221164279255 69.6401775783962904, -163.0342430962456319 69.6426723904080092, -163.0326778835720347 69.6490632798936815, -163.0492241753472058 69.6507875230577440, -163.0506554497612797 69.6657299465603472, -163.0343383789062273 69.6674302842882156, -163.0326778835720347 69.6735109117296219, -163.0409166124131843 69.6760550604926436, -163.0423221164279255 69.6907418145073905, -163.0264889187282904 69.6923221164279738, -163.0240169949001654 69.6843163384331774, -163.0176496717664918 69.6823503282335253, -163.0155893961588447 69.6756785074869924, -162.9598222520616275 69.6743445502387289, -162.9572811550564211 69.6825746324327469, -162.9427188449435562 69.6840920342339558, -162.9406144883897412 69.6909079657660726, -162.9257113986544994 69.6924609714084369, -162.9249999999999829 69.7083333333333570, -162.9406185574001711 69.7090193006727645, -162.9427093505859148 69.7159630669488024, -162.9656239827473883 69.7173702663845631, -162.9677205403645530 69.7243340386284842, -163.0242479112413037 69.7256730821397781, -163.0254221598307254 69.7402850680881272, -163.0176310221353901 69.7426308525933365, -163.0157023111979129 69.7490358140733662, -163.0090783013237683 69.7510301378038378, -163.0075568305121294 69.7659467909071367, -162.9843760172526004 69.7673702663845745, -162.9822804768880076 69.7743298000759751, -162.9583333333333144 69.7750000000000199, -162.9575883653428718 69.7823031955295363, -162.9509643554687273 69.7842975192600079, -162.9489573160807083 69.7909630669488052, -162.9260426839192633 69.7923702663845660, -162.9239573160807026 69.7992964002821310, -162.9010426839192576 69.8007035997179059, -162.8989491780598655 69.8076570298936758, -162.8593841552734318 69.8090096367730268, -162.8572852240668283 69.8159806993272696, -162.8257788764105669 69.8173645019531506, -162.8242285834418226 69.8325619167751910, -162.8093634711371465 69.8340783013237996, -162.8072906494140568 69.8409630669488024, -162.7843760172525833 69.8423702663845631, -162.7823031955294937 69.8492550320095660, -162.7676968044704608 69.8507449679904653, -162.7656365288628422 69.8575883653429059, -162.7510301378038093 69.8590783013238052, -162.7489573160807197 69.8659630669488081, -162.7260426839192462 69.8673702663845688, -162.7240356445312273 69.8740358140733662, -162.7176310221354072 69.8759641859266623, -162.7156158447265568 69.8826570298936787, -162.6760508219400947 69.8840096367730297, -162.6740356445312443 69.8907024807400319, -162.6676310221353958 69.8926308525933422, -162.6656138102213447 69.8993298000759751, -162.6416666666666515 69.9000000000000199, -162.6408952501084855 69.9075619167751796, -162.6260301378038093 69.9090783013237882, -162.6239471435546591 69.9159966362847314, -162.5760528564453011 69.9173366970486114, -162.5739698621961509 69.9242550320095546, -162.5593634711371465 69.9257449679904539, -162.5573031955294994 69.9325883653428804, -162.5426968044704665 69.9340783013237939, -162.5407023111978901 69.9407023111979242, -162.5342976888020701 69.9426310221354157, -162.5323031955294937 69.9492550320095461, -162.5176968044704608 69.9507449679904596, -162.5156365288628137 69.9575883653428860, -162.5010301378038093 69.9590783013237854, -162.4990356445312329 69.9657023111979157, -162.4958333333333087 69.9666666666666828, -162.4916666666666458 69.9666666666666828, -162.4908952501084798 69.9742285834418425, -162.4760301378038037 69.9757449679904511, -162.4740356445312273 69.9823689778645814, -162.4676310221354072 69.9842976888020871, -162.4657023111979015 69.9907023111979214, -162.4576904296874886 69.9931145562066064, -162.4590735541449362 70.0073018391927064, -162.4673095703124659 70.0097812228732721, -162.4659813774956376 70.0406185574001796, -162.4592976888020530 70.0426310221354242, -162.4568854437933965 70.0506429036458371, -162.4426981608072822 70.0492597791883753, -162.4402187771267165 70.0410237630208314, -162.4260314941406023 70.0424068874783075, -162.4239444308810505 70.0493394639756985, -162.3507524278428491 70.0506659613715357, -162.3495778401692462 70.0652852376302064, -162.3589762369791458 70.0681145562066092, -162.3574110243055202 70.0740230984158075, -162.3509643554687329 70.0759643554687557, -162.3489437527126427 70.0826748318142450, -162.3083333333333371 70.0833333333333428, -162.3091057671441035 70.0905921088324675, -162.3156646728515682 70.0926686604817775, -162.3176686604817576 70.0989980061848996, -162.3256679958767279 70.1015306260850792, -162.3239718967013800 70.1075558132595518, -162.3094078911675240 70.1091057671441007, -162.3072452121310789 70.1159366183810846, -162.2844214545355896 70.1173967149522639, -162.2822452121310732 70.1242699517144104, -162.2594214545355840 70.1257300482855896, -162.2572452121310675 70.1326032850477503, -162.2344214545355783 70.1340633816189296, -162.2322452121310619 70.1409366183810761, -162.2094214545355726 70.1423967149522696, -162.2068027072482437 70.1506679958767450, -162.2010148790147639 70.1490386962890682, -162.1984693739149179 70.1409986707899407, -162.1844092475043340 70.1424346923828210, -162.1822587754991218 70.1492275661892393, -162.1677412245008725 70.1507724338107721, -162.1656646728515625 70.1573313395182367, -162.1593353271484261 70.1593353271484403, -162.1573313395182367 70.1656646728515625, -162.1510019938151004 70.1676686604817803, -162.1489254421657904 70.1742275661892450, -162.1344078911675410 70.1757724338107636, -162.1322396172417371 70.1826212565104299, -162.1010937160915830 70.1840454101562585, -162.0989980061848996 70.1906646728515682, -162.0926686604817633 70.1926686604817718, -162.0905921088324533 70.1992275661892364, -162.0760745578342039 70.2007724338107693, -162.0739254421658018 70.2075608995225764, -162.0594078911675240 70.2091057671441092, -162.0572587754991218 70.2158942328559021, -162.0427412245008725 70.2174391004774350, -162.0405785454643990 70.2242699517144189, -162.0177547878689097 70.2257300482855982, -162.0155921088324646 70.2325608995225821, -162.0010745578341869 70.2341057671441007, -161.9989980061848769 70.2406646728515653, -161.9926686604817689 70.2426686604817831, -161.9906646728515511 70.2489980061849053, -161.9843353271484432 70.2510019938151089, -161.9823313395182254 70.2573313395182311, -161.9760019938150890 70.2593353271484489, -161.9739254421657790 70.2658942328559135, -161.9594078911675297 70.2674391004774321, -161.9573313395182197 70.2739980061848968, -161.9510019938150833 70.2760019938151146, -161.9489980061848939 70.2823313395182367, -161.9426686604817576 70.2843353271484403, -161.9405921088324476 70.2908942328559050, -161.9260745578341982 70.2924391004774378, -161.9239254421657961 70.2992275661892450, -161.9094078911675183 70.3007724338107778, -161.9068027072482607 70.3090013292100764, -161.9010148790147525 70.3073720296223996, -161.8984693739149350 70.2993320041232721, -161.8926815456814268 70.3009613037109489, -161.8901360405815808 70.3090013292100764, -161.8340550740559820 70.3076327853732721, -161.8337858412000685 70.3008385552300439, -161.8506679958767336 70.2990420871310846, -161.8489952935112797 70.2923828125000085, -161.8177603827582516 70.2909545898437500, -161.8156646728515398 70.2843353271484403, -161.8076653374565979 70.2818027072482749, -161.8093614366319457 70.2757775200737882, -161.8256679958767279 70.2740420871310789, -161.8240117390950559 70.2674482557508782, -161.8094078911675240 70.2658942328559135, -161.8068027072482664 70.2576653374566007, -161.7743320041232664 70.2591237386067746, -161.7759184095594378 70.2656382242838617, -161.7840013292100707 70.2681972927517364, -161.7823871188693374 70.2840013292100707, -161.7760258992512945 70.2824069552951443, -161.7739118787977191 70.2757300482855953, -161.7510881212022582 70.2742699517144160, -161.7488979763454893 70.2673526340060874, -161.6761020236544937 70.2659806993272582, -161.6739980061848883 70.2593353271484489, -161.6676686604817519 70.2573313395182311, -161.6656646728515625 70.2510019938151089, -161.6576653374565922 70.2484693739149435, -161.6593853420681342 70.2423594156901174, -161.7155665079752396 70.2409752739800410, -161.7181972927517393 70.2326653374566092, -161.7572362263997263 70.2340348985460139, -161.7594368828667371 70.2409854465060874, -161.8572297837999088 70.2423478868272610, -161.8598639594183908 70.2506679958767393, -161.8840013292100650 70.2491621229383725, -161.8825349595811645 70.2340460883246607, -161.8427636040581490 70.2326310899522639, -161.8405665079752396 70.2256913926866417, -161.7844334920247320 70.2243086073133753, -161.7823313395182083 70.2176686604817775, -161.7743320041232664 70.2151360405815979, -161.7764350043402715 70.2076653374566035, -161.8322330050998232 70.2090247260199760, -161.8348639594183851 70.2173346625434078, -161.8590013292100593 70.2158287896050410, -161.8575703938801951 70.2010776095920193, -161.8510019938150890 70.1989980061849081, -161.8489118787977361 70.1923967149522667, -161.8243320041232494 70.1908243815104242, -161.8257503933376711 70.1673594156901146, -161.8992779201931285 70.1659735785590328, -161.8995344373914804 70.1595052083333428, -161.8926686604817746 70.1573313395182367, -161.8901360405815808 70.1493320041232664, -161.8594273885091184 70.1507110595703125, -161.8572363959418396 70.1576310899522610, -161.8177636040581433 70.1590355767144160, -161.8156646728515398 70.1656646728515625, -161.8093353271484318 70.1676686604817803, -161.8073313395182140 70.1739980061849025, -161.8010019938151061 70.1760019938151061, -161.7989118787977247 70.1826032850477475, -161.7760881212022355 70.1840633816189268, -161.7739030626084968 70.1909644232855925, -161.7340543958875685 70.1923821343316092, -161.7334535386827099 70.2075415717230982, -161.7572452121310675 70.2090633816189325, -161.7593353271484204 70.2156646728515739, -161.7673346625433908 70.2181972927517393, -161.7652316623263857 70.2256679958767478, -161.7427552964952042 70.2242719862196196, -161.7405921088324590 70.2174391004774350, -161.7260745578341812 70.2158942328559021, -161.7239980061848996 70.2093353271484375, -161.7208333333333314 70.2083333333333428, -161.7166666666666686 70.2083333333333428, -161.7092544555663949 70.2090087890625085, -161.7073920355902601 70.2160678439670249, -161.6426079644097058 70.2172654893663264, -161.6407455444335710 70.2243245442708428, -161.6258338080511976 70.2256832546658103, -161.6245622422960082 70.2321187337239650, -161.6339131673177008 70.2345855712890739, -161.6324610392252623 70.2409868028428832, -161.6175877888997263 70.2423421223958400, -161.6154144287109204 70.2505798339843750, -161.5592739529079722 70.2493984646267364, -161.5570810953775833 70.2410868326822992, -161.4592763264973883 70.2422587076822964, -161.4570810953775890 70.2505798339843750, -161.4342649671766310 70.2493648952908103, -161.4323939005533646 70.2422726101345489, -161.4083333333333314 70.2416666666666742, -161.4075503879123232 70.2493418375651117, -161.3010572645399066 70.2506547715928917, -161.2989473130967610 70.2576633029513999, -161.2510526869031935 70.2590033637152800, -161.2489573160807197 70.2659630669487854, -161.2260426839192462 70.2673702663845603, -161.2239520602755931 70.2743140326605982, -161.1927146063910357 70.2756859673394132, -161.1906158447265511 70.2826568603515653, -161.1510508219400890 70.2840098063151117, -161.1489491780598939 70.2909901936849053, -161.1093841552734318 70.2923431396484375, -161.1073031955295107 70.2992550320095546, -161.0926968044704779 70.3007449679904539, -161.0906239827473883 70.3076297336154568, -161.0677093505859148 70.3090369330512175, -161.0656239827473826 70.3159630669487967, -161.0427093505859091 70.3173702663845575, -161.0406365288628194 70.3242550320095603, -161.0260301378038150 70.3257449679904596, -161.0235521104600593 70.3339762369791686, -161.0176435682508611 70.3324110243055571, -161.0156365288628422 70.3257449679904596, -161.0007714165581376 70.3242285834418510, -160.9999999999999716 70.3166666666666771, -160.9958333333333087 70.3166666666666771, -160.9833333333333201 70.3166666666666771)) diff --git a/tests/resources/regression6.wkt b/tests/resources/regression6.wkt new file mode 100644 index 0000000000..c109266e48 --- /dev/null +++ b/tests/resources/regression6.wkt @@ -0,0 +1 @@ +POLYGON ((146.375 -33.475, 146.425 -33.475, 146.475 -33.475, 146.475 -33.525, 146.525 -33.525, 146.575 -33.525, 146.575 -33.575, 146.625 -33.575, 146.675 -33.575, 146.725 -33.575, 146.775 -33.575, 146.775 -33.525, 146.825 -33.525, 146.875 -33.525, 146.925 -33.525, 146.975 -33.525, 147.025 -33.525, 147.075 -33.525, 147.125 -33.525, 147.125 -33.575, 147.175 -33.575, 147.225 -33.575, 147.225 -33.525, 147.275 -33.525, 147.325 -33.525, 147.375 -33.525, 147.375 -33.575, 147.375 -33.625, 147.375 -33.675, 147.375 -33.725, 147.375 -33.775, 147.375 -33.825, 147.375 -33.875, 147.375 -33.925, 147.375 -33.975, 147.375 -34.025, 147.375 -34.075, 147.375 -34.125, 147.375 -34.175, 147.325 -34.175, 147.275 -34.175, 147.275 -34.125, 147.225 -34.125, 147.225 -34.175, 147.225 -34.225, 147.175 -34.225, 147.175 -34.275, 147.225 -34.275, 147.225 -34.325, 147.175 -34.325, 147.175 -34.375, 147.125 -34.375, 147.075 -34.375, 147.075 -34.425, 147.125 -34.425, 147.125 -34.475, 147.125 -34.525, 147.125 -34.575, 147.175 -34.575, 147.175 -34.625, 147.175 -34.675, 147.175 -34.725, 147.225 -34.725, 147.225 -34.775, 147.225 -34.825, 147.175 -34.825, 147.175 -34.875, 147.225 -34.875, 147.225 -34.925, 147.275 -34.925, 147.275 -34.975, 147.325 -34.975, 147.375 -34.975, 147.375 -35.025, 147.375 -35.075, 147.375 -35.125, 147.375 -35.175, 147.375 -35.225, 147.325 -35.225, 147.325 -35.175, 147.275 -35.175, 147.275 -35.225, 147.275 -35.275, 147.275 -35.325, 147.275 -35.375, 147.225 -35.375, 147.225 -35.325, 147.175 -35.325, 147.125 -35.325, 147.125 -35.375, 147.125 -35.425, 147.075 -35.425, 147.025 -35.425, 147.025 -35.475, 146.975 -35.475, 146.925 -35.475, 146.925 -35.425, 146.875 -35.425, 146.825 -35.425, 146.775 -35.425, 146.775 -35.475, 146.725 -35.475, 146.725 -35.525, 146.675 -35.525, 146.675 -35.475, 146.625 -35.475, 146.625 -35.425, 146.575 -35.425, 146.525 -35.425, 146.525 -35.475, 146.525 -35.525, 146.475 -35.525, 146.475 -35.475, 146.425 -35.475, 146.375 -35.475, 146.325 -35.475, 146.275 -35.475, 146.225 -35.475, 146.175 -35.475, 146.125 -35.475, 146.075 -35.475, 146.025 -35.475, 146.025 -35.425, 146.025 -35.375, 146.025 -35.325, 145.975 -35.325, 145.925 -35.325, 145.925 -35.275, 145.925 -35.225, 145.975 -35.225, 145.975 -35.175, 145.975 -35.125, 145.975 -35.075, 146.025 -35.075, 146.025 -35.025, 146.025 -34.975, 146.025 -34.925, 146.025 -34.875, 146.075 -34.875, 146.125 -34.875, 146.125 -34.825, 146.125 -34.775, 146.175 -34.775, 146.175 -34.725, 146.175 -34.675, 146.175 -34.625, 146.225 -34.625, 146.225 -34.575, 146.275 -34.575, 146.275 -34.525, 146.275 -34.475, 146.325 -34.475, 146.325 -34.425, 146.325 -34.375, 146.375 -34.375, 146.375 -34.325, 146.425 -34.325, 146.425 -34.275, 146.425 -34.225, 146.375 -34.225, 146.375 -34.175, 146.425 -34.175, 146.425 -34.125, 146.425 -34.075, 146.425 -34.025, 146.475 -34.025, 146.475 -33.975, 146.475 -33.925, 146.425 -33.925, 146.375 -33.925, 146.375 -33.875, 146.375 -33.825, 146.325 -33.825, 146.275 -33.825, 146.275 -33.775, 146.225 -33.775, 146.225 -33.725, 146.175 -33.725, 146.175 -33.675, 146.125 -33.675, 146.125 -33.625, 146.175 -33.625, 146.175 -33.575, 146.175 -33.525, 146.225 -33.525, 146.275 -33.525, 146.325 -33.525, 146.375 -33.525, 146.375 -33.475), (147.175 -35.225, 147.175 -35.175, 147.125 -35.175, 147.125 -35.225, 147.175 -35.225)) diff --git a/tests/resources/russia.wkt b/tests/resources/russia.wkt new file mode 100644 index 0000000000..f072d6629b --- /dev/null +++ b/tests/resources/russia.wkt @@ -0,0 +1 @@ +MULTIPOLYGON (((143.648007440362875 50.747600409541519,144.654147577085638 48.976390692737596,143.173927850517231 49.306551418650372,142.558668247650104 47.861575018904915,143.533492466404056 46.836728013692493,143.505277134372619 46.137907619809482,142.747700636973917 46.740764878926569,142.092030064054512 45.966755276058791,141.906925083585037 46.805928860046549,142.018442824470895 47.780132961612935,141.904444614835057 48.85918854429957,142.135800002205684 49.615163072297463,142.179983351815309 50.952342434281917,141.594075962490052 51.935434882202543,141.68254601457366 53.301966457728781,142.606934035410774 53.762145087287905,142.209748976815405 54.225475979216867,142.65478641171299 54.365880845753878,142.914615513276573 53.704577541714741,143.260847609632066 52.740760403039047,143.235267775647657 51.756660264688747,143.648007440362875 50.747600409541519)),((22.731098667092652 54.327536932993326,20.892244500418656 54.312524929412575,19.660640089606403 54.426083889373984,19.888481479581344 54.866160386771497,21.268448927503499 55.190481675835287,22.315723504330606 55.0152985703659,22.757763706155288 54.856574408581423,22.651051873472568 54.582740993866707,22.731098667092652 54.327536932993326)),((-175.01425 66.58435,-174.33983 66.33556,-174.57182 67.06219,-171.85731 66.91308,-169.89958 65.97724,-170.89107 65.54139,-172.53025 65.43791,-172.555 64.46079,-172.95533 64.25269,-173.89184 64.2826,-174.65392 64.63125,-175.98353 64.92288,-176.20716 65.35667,-177.22266 65.52024,-178.35993 65.39052,-178.90332 65.74044,-178.68611 66.11211,-179.88377 65.87456,-179.43268 65.40411,-180.0 64.979708702198366,-180.0 68.963636363636368,-177.55 68.2,-174.92825 67.20589,-175.01425 66.58435)),((180.0 70.832199208546683,178.903425000000112 70.78114,178.7253 71.0988,180.0 71.515714336428218,180.0 70.832199208546683)),((-178.69378 70.89302,-180.0 70.832199208546683,-180.0 71.51571433642826,-179.871875 71.55762,-179.02433 71.55553,-177.577945 71.26948,-177.663575 71.13277,-178.69378 70.89302)),((143.60385 73.21244,142.08763 73.20544,140.038155 73.31692,139.86312 73.36983,140.81171 73.76506,142.06207 73.85758,143.48283 73.47525,143.60385 73.21244)),((150.73167 75.08406,149.575925 74.68892,147.977465 74.778355,146.11919 75.17298,146.358485 75.49682,148.22223 75.345845,150.73167 75.08406)),((145.086285 75.562625,144.3 74.82,140.61381 74.84768,138.95544 74.61148,136.97439 75.26167,137.51176 75.94917,138.831075 76.13676,141.471615 76.09289,145.086285 75.562625)),((57.5356925799924 70.72046397570216,56.944979282463947 70.632743231886678,53.677375115784201 70.76265778266847,53.412016635965387 71.206661688920207,51.601894565645722 71.474759019650492,51.455753615124223 72.014881089965144,52.478275180883571 72.22944163684096,52.444168735570855 72.774731350384855,54.427613559797663 73.627547512497586,53.50828982932515 73.749813951300155,55.902458937407658 74.627486477345343,55.631932814359715 75.081412258597169,57.868643833248854 75.609390367323215,61.170044386647504 76.251883450008137,64.498368361270224 76.439055487769281,66.210977003855106 76.809782213031241,68.157059767534832 76.939696763812918,68.852211134725138 76.544811306454619,68.180572544227658 76.23364166940911,64.637326287703019 75.737754625136233,61.583507521414759 75.260884507946798,58.47708214705338 74.309056301562833,56.986785516188007 73.333043524866241,55.419335971910954 72.371267605265984,55.622837762276305 71.54059479439033,57.5356925799924 70.72046397570216)),((106.970130000000125 76.97419,107.240000000000151 76.48,108.1538 76.723350000000153,111.077260000000166 76.71,113.33151 76.22224,114.13417 75.84764,113.88539 75.327790000000135,112.77918 75.03186,110.151250000000203 74.47673,109.4 74.18,110.64 74.04,112.11919 73.787740000000127,113.019540000000262 73.976930000000152,113.529580000000323 73.335050000000109,113.96881 73.594880000000103,115.56782 73.75285,118.776330000000229 73.58772,119.02 73.12,123.200660000000113 72.97122,123.257770000000193 73.735030000000108,125.380000000000194 73.56,126.97644 73.56549,128.59126 73.03871,129.05157 72.39872,128.460000000000122 71.98,129.715990000000232 71.19304,131.28858000000028 70.786990000000117,132.253500000000173 71.836300000000108,133.857660000000322 71.386420000000157,135.56193 71.655250000000137,137.49755 71.34763,138.23409000000018 71.62803,139.869830000000121 71.487830000000145,139.14791 72.416190000000114,140.46817 72.849410000000148,149.5 72.2,150.351180000000198 71.60643,152.968900000000218 70.84222,157.00688 71.03141,158.99779 70.86672,159.830310000000253 70.45324,159.70866 69.72198,160.940530000000336 69.437280000000101,162.279070000000132 69.64204,164.052480000000145 69.66823,165.940370000000229 69.47199,167.83567 69.58269,169.577630000000198 68.6938,170.816880000000282 69.01363,170.008200000000187 69.65276,170.453450000000288 70.09703,173.643910000000261 69.81743,175.724030000000226 69.877250000000231,178.6 69.4,180.0 68.96363636363661,180.0 64.97970870219838,179.99281 64.97433,178.707200000000256 64.53493,177.411280000000176 64.60821,178.313000000000244 64.07593,178.908250000000209 63.251970000000142,179.37034 62.982620000000111,179.48636 62.56894,179.228250000000145 62.304100000000147,177.3643 62.5219,174.569290000000223 61.76915,173.68013 61.65261,172.15 60.95,170.698500000000109 60.33618,170.330850000000311 59.88177,168.90046 60.57355,166.294980000000322 59.788550000000214,165.840000000000231 60.16,164.87674 59.7316,163.539290000000136 59.86871,163.217110000000247 59.21101,162.017330000000101 58.24328,162.05297 57.83912,163.19191 57.615030000000104,163.057940000000173 56.159240000000125,162.129580000000232 56.12219,161.70146 55.285680000000156,162.117490000000174 54.85514,160.368770000000353 54.34433,160.021730000000247 53.20257,158.530940000000186 52.958680000000243,158.23118 51.94269,156.789790000000295 51.01105,156.420000000000158 51.7,155.99182 53.15895,155.433660000000117 55.381030000000123,155.91442000000032 56.767920000000146,156.75815 57.3647,156.810350000000113 57.83204,158.364330000000194 58.05575,160.150640000000152 59.314770000000124,161.87204 60.343000000000131,163.66969 61.140900000000101,164.473550000000131 62.55061,163.2584200000002 62.46627,162.65791 61.6425,160.121480000000105 60.54423,159.30232 61.773960000000102,156.720680000000101 61.43442,154.218060000000349 59.758180000000124,155.04375 59.14495,152.81185 58.88385,151.265730000000275 58.78089,151.338150000000127 59.50396,149.78371 59.655730000000148,148.54481 59.16448,145.48722 59.33637,142.197820000000178 59.03998,138.958480000000321 57.08805,135.12619 54.72959,136.70171 54.603550000000126,137.19342 53.97732,138.1647 53.755010000000254,138.80463 54.254550000000108,139.90151 54.18968000000018,141.34531 53.089570000000123,141.37923 52.23877,140.597420000000199 51.239670000000103,140.51308 50.045530000000127,140.061930000000217 48.446710000000166,138.554720000000231 46.99965,138.21971 46.30795,136.86232 45.143500000000188,135.515350000000211 43.989,134.869390000000266 43.39821,133.536870000000278 42.81147,132.906270000000148 42.798490000000101,132.27807000000027 43.284560000000113,130.935870000000165 42.55274,130.78 42.220000000000198,130.640000000000185 42.395,130.63386640840983 42.903014634770557,131.14468794161499 42.929989732426947,131.288555129115622 44.111519680348266,131.025190000000265 44.96796,131.88345421765959 45.321161607436522,133.097120000000217 45.14409,133.769643996313192 46.116926988299156,134.112350000000191 47.212480000000141,134.50081 47.578450000000146,135.026311476786788 48.478229885443909,133.373595819228029 48.183441677434843,132.506690000000134 47.78896,130.987260000000134 47.79013,130.582293328982672 48.729687404976204,129.397817824420514 49.440600084015614,127.657400000000365 49.76027,127.287455682484932 50.739797268265448,126.939156528837856 51.35389415140591,126.564399041857001 51.784255479532703,125.946348911646481 52.79279857035695,125.068211297710462 53.161044826868931,123.57147 53.4588,122.245747918793057 53.431725979213695,121.003084751470368 53.251401068731241,120.177088657716894 52.753886216841209,120.725789015792003 52.516226304730907,120.7382 51.96411,120.182080000000184 51.64355,119.27939 50.58292,119.288460728025854 50.142882798861962,117.879244419426499 49.510983384797044,116.678800897286209 49.888531399121405,115.485695428531443 49.805177313834747,114.962109816550395 50.140247300815133,114.362456496235353 50.248302720737485,112.897739699354389 49.543565375356991,111.581230910286678 49.377968248077678,110.662010532678863 49.130128078805853,109.402449171996722 49.292960516957692,108.475167270951289 49.282547715850711,107.86817589725112 49.793705145865886,106.888804152455322 50.27429596618029,105.886591424586896 50.406019192092174,104.62158 50.275320000000164,103.676545444760364 50.089966132195144,102.255890000000107 50.510560000000112,102.06521 51.259910000000104,100.889480421962645 51.516855780638423,99.981732212323578 51.634006252643957,98.861490513100506 52.047366034546712,97.825739780674525 51.01099518493325,98.231761509191728 50.42240062112873,97.259760000000227 49.72605,95.81402000000017 49.977460000000121,94.815949334698786 50.013433335970888,94.147566359435615 50.480536607457168,93.10421 50.49529,92.23471154171969 50.802170722041751,90.713667433640779 50.331811835321105,88.805566847695587 49.470520738312473,87.751264276076853 49.297197984405557,87.359970330762707 49.214980780629162,86.829356723989662 49.82667470966814,85.5412699726825 49.692858588248157,85.11555952346211 50.117302964877638,84.416377394553052 50.311399644565824,83.935114780618932 50.889245510453577,83.383003778012466 51.069182847693895,81.945985548839957 50.812195949906339,80.56844689323546 51.388336493528442,80.035559523441719 50.864750881547224,77.800915561844334 53.404414984747547,76.525179477854778 54.177003485727141,76.891100294913457 54.490524400441927,74.384820000000133 53.54685000000012,73.425678745420527 53.489810289109755,73.508516066384374 54.035616766976602,72.224150018202209 54.376655381886792,71.180131056609497 54.133285224008262,70.865266554655165 55.169733588270105,69.068166945272907 55.385250149143502,68.169100376258911 54.97039175070438,65.666870000000102 54.601250000000164,65.178533563095954 54.354227810272079,61.436600000000141 54.00625,60.97806644068325 53.664993394579142,61.699986199800634 52.979996446334269,60.739993117114551 52.719986477257748,60.927268507740251 52.447548326215014,59.967533807215574 51.960420437215674,61.588003371024143 51.272658799843185,61.337424350841019 50.799070136104262,59.932807244715576 50.842194118851836,59.642282342370578 50.545442206415714,58.36332000000013 51.06364,56.77798 51.04355,55.716940000000108 50.621710000000149,54.532878452376195 51.026239732459373,52.328723585831057 51.718652248738096,50.766648390512188 51.692762356159875,48.702381626181051 50.605128485712839,48.577841424357615 49.874759629915644,47.549480421749394 50.454698391311126,46.751596307162771 49.356005764353739,47.043671502476599 49.152038886097586,46.466445753776298 48.39415233010493,47.315240000000159 47.71585,48.05725 47.74377,48.694733514201886 47.075628160177899,48.593250000000154 46.561040000000105,49.101160000000135 46.399330000000106,48.645410000000112 45.80629,47.67591 45.641490000000118,46.68201 44.609200000000101,47.59094 43.660160000000133,47.49252 42.98658,48.584370000000177 41.80888,47.98728315612604 41.405819200194401,47.81566572448466 41.151416124021353,47.373315464066394 41.219732367511142,46.686070591016716 41.827137152669906,46.404950799348939 41.860675157227433,45.7764 42.092440000000238,45.470279168485916 42.502780666670049,44.537622918482072 42.711992702803684,43.931210000000107 42.554960000000108,43.755990000000196 42.74083,42.394400000000161 43.2203,40.922190000000143 43.382150000000138,40.076964959479852 43.553104153002494,39.955008579271095 43.434997666999294,38.68 44.28,37.539120000000111 44.65721,36.675460000000129 45.24469,37.40317 45.404510000000101,38.23295 46.24087,37.67372 46.63657,39.14767 47.044750000000136,39.12120000000013 47.26336,38.223538038899477 47.102189846375978,38.255112339029807 47.54640045835697,38.77057 47.825620000000242,39.738277622238996 47.898937079452082,39.89562000000015 48.23241,39.67465 48.783820000000134,40.080789015469492 49.307429917999372,40.069040000000115 49.60105,38.59498823421356 49.926461900423732,38.010631137857075 49.915661526074729,37.393459506995242 50.383953355503678,36.626167840325394 50.225590928745135,35.356116163888117 50.577197374059153,35.37791 50.77394,35.022183058417937 51.207572333371502,34.224815708154409 51.255993150428935,34.141978387190619 51.566413479206204,34.391730584457235 51.768881740925906,33.752699822735877 52.33507457133166,32.71576053236717 52.238465481162166,32.412058139787774 52.288694973349777,32.159440000000217 52.061250000000115,31.78597 52.10168,31.540018344862261 52.742052313846443,31.305200636527985 53.073995876673308,31.49764 53.167430000000138,32.304519484188376 53.132726141972853,32.693643019346126 53.351420803432148,32.405598585751164 53.618045355842014,31.731272820774592 53.794029446012019,31.791424187962406 53.974638576872195,31.384472283663825 54.157056382862379,30.757533807098781 54.811770941784403,30.971835971813249 55.081547756564134,30.873909132620071 55.550976467503517,29.896294386522442 55.789463202530499,29.37157189303079 55.670090643936277,29.229513380660393 55.918344224666413,28.17670942557794 56.169129950578792,27.855282016722526 56.759326483784378,27.770015903440992 57.244258124411203,27.288184848751655 57.474528306703917,27.716685825315778 57.79189911562446,27.420150000000206 58.724570000000142,28.131699253051863 59.300825100330997,27.98112 59.47537,29.1177 60.028050000000121,28.07 60.503520000000151,30.211107212044652 61.780027777749694,31.139991082491036 62.357692776124452,31.516092156711267 62.867687486412905,30.035872430142803 63.552813625738565,30.44468468600374 64.204453436939076,29.544429559047018 64.948671576590556,30.21765 65.80598,29.054588657352383 66.944286200622031,29.977426385220696 67.698297024192755,28.445943637818772 68.364612942164001,28.591929559043365 69.064776923286701,29.39955 69.156920000000184,31.10108000000011 69.55811,32.132720000000262 69.905950000000246,33.77547 69.301420000000121,36.51396 69.06342,40.292340000000166 67.9324,41.059870000000132 67.45713000000012,41.125950000000188 66.791580000000124,40.01583 66.266180000000134,38.38295 65.999530000000107,33.918710000000175 66.75961,33.18444 66.63253,34.81477 65.900150000000139,34.878574253078767 65.436212877048206,34.943910000000159 64.414370000000162,36.23129 64.10945,37.012730000000118 63.849830000000111,37.141970000000157 64.33471,36.539579035089815 64.76446,37.176040000000143 65.143220000000127,39.59345 64.520790000000176,40.435600000000107 64.76446,39.762600000000162 65.49682,42.093090000000103 66.47623,43.016040000000118 66.418580000000105,43.949750000000137 66.06908,44.53226 66.756340000000137,43.69839 67.35245,44.187950000000143 67.95051,43.45282 68.57079,46.250000000000142 68.25,46.821340000000163 67.68997,45.55517 67.56652,45.562020000000103 67.010050000000206,46.349150000000151 66.667670000000101,47.894160000000255 66.884550000000161,48.13876 67.52238,50.227660000000157 67.998670000000146,53.717430000000178 68.85738000000012,54.47171 68.80815,53.485820000000132 68.20131,54.72628 68.09702,55.442680000000138 68.43866,57.317020000000156 68.46628,58.80200000000022 68.88082,59.941420000000193 68.278440000000103,61.07784000000018 68.94069,60.03 69.52,60.55 69.85,63.504000000000161 69.54739,64.888115 69.234835000000146,68.512160000000137 68.092330000000175,69.18068 68.615630000000124,68.16444 69.14436,68.13522 69.35649,66.930080000000117 69.454610000000116,67.25976 69.92873,66.724920000000139 70.708890000000139,66.69466 71.028970000000243,68.540060000000125 71.934500000000241,69.196360000000112 72.84336000000016,69.94 73.040000000000134,72.58754 72.776290000000103,72.79603 72.22006,71.848110000000105 71.40898,72.47011 71.09019,72.79188 70.39114,72.564700000000215 69.02085,73.66787 68.4079,73.2387 67.7404,71.280000000000115 66.320000000000164,72.423010000000176 66.172670000000181,72.82077 66.53267,73.92099000000016 66.789460000000133,74.186510000000197 67.28429,75.052 67.760470000000169,74.469260000000162 68.32899,74.935840000000127 68.98918,73.84236 69.07146,73.601870000000218 69.62763,74.3998 70.63175,73.1011 71.447170000000256,74.890820000000218 72.12119,74.65926 72.83227,75.158010000000189 72.854970000000122,75.68351 72.300560000000132,75.288980000000123 71.33556,76.35911 71.152870000000149,75.903130000000175 71.87401,77.576650000000114 72.26717,79.652020000000135 72.32011,81.5 71.75,80.610710000000125 72.582850000000121,80.51109 73.6482,82.25 73.850000000000108,84.65526 73.805910000000182,86.82230000000024 73.93688,86.00956 74.459670000000159,87.166820000000172 75.11643,88.315710000000109 75.14393,90.26 75.64,92.90058 75.77333,93.234210000000161 76.0472,95.860000000000156 76.1400000000001,96.67821 75.91548,98.922540000000225 76.44689,100.759670000000227 76.43028,101.03532 76.86189,101.990840000000134 77.287540000000206,104.351600000000104 77.69792,106.066640000000149 77.37389,104.70500000000024 77.1274,106.970130000000125 76.97419)),((105.07547 78.30689,99.43814 77.921,101.2649 79.23399,102.08635 79.34641,102.837815 79.28129,105.37243 78.71334,105.07547 78.30689)),((51.13618655783128 80.547280178540944,49.793684523320707 80.415427761548216,48.894411248577541 80.339566758943704,48.754936557821765 80.175468248200843,47.586119012244154 80.010181179515342,46.502825962109654 80.247246812654367,47.072455275262911 80.559424140129465,44.846958042181114 80.589809882317184,46.799138624871233 80.771917629713641,48.318477410684665 80.784009914869955,48.522806023966695 80.514568996900152,49.097189568890911 80.753985907708426,50.039767693894618 80.918885403151819,51.522932977103693 80.69972565380192,51.13618655783128 80.547280178540944)),((99.93976 78.88094,97.75794 78.7562,94.97259 79.044745,93.31288 79.4265,92.5454 80.14379,91.18107 80.34146,93.77766 81.0246,95.940895 81.2504,97.88385 80.746975,100.186655 79.780135,99.93976 78.88094))) diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index f7c302de6b..650890ae62 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -29,7 +29,7 @@ foreach(_testfile ${_testfiles}) if (NOT ${_testname} MATCHES "^capi::") string(CONCAT _testname "geos::" ${_testname}) endif() - add_test(NAME unit-${_cmake_testname} COMMAND test_geos_unit ${_testname}) + add_test(NAME unit-${_cmake_testname} COMMAND test_geos_unit ${_testname} "--data" "${CMAKE_CURRENT_LIST_DIR}/../resources") endforeach() # Run all the unit tests in one go, for faster memory checking diff --git a/tests/unit/capi/GEOSGridIntersectionFractionsTest.cpp b/tests/unit/capi/GEOSGridIntersectionFractionsTest.cpp new file mode 100644 index 0000000000..412f963771 --- /dev/null +++ b/tests/unit/capi/GEOSGridIntersectionFractionsTest.cpp @@ -0,0 +1,62 @@ +#include +#include + +#include "capi_test_utils.h" + +namespace tut { +// +// Test Group +// + +// Common data used in test cases. +struct test_capigeosgridintersectionfractions_data : public capitest::utility {}; + +typedef test_group group; +typedef group::object object; + +group test_capigeosgridintersectionfractions_group("capi::GEOSGridIntersectionFractions"); + +template<> +template<> +void object::test<1>() +{ + set_test_name("basic rectangle"); + + input_ = fromWKT("POLYGON ((0.5 0.5, 2.5 0.5, 2.5 2.5, 0.5 2.5, 0.5 0.5))"); + + std::vector result_vec(3*4); + int result = GEOSGridIntersectionFractions(input_, 1, 0, 5, 3, 4, 3, result_vec.data()); + ensure_equals(result, 1); + + std::vector expected = { 0.5, 0.25, 0, 0, 1, 0.5, 0, 0, 0.5, 0.25, 0, 0}; + + ensure(result_vec == expected); +} + +template<> +template<> +void object::test<2>() +{ + set_test_name("curved input"); + + input_ = fromWKT("CURVEPOLYGON ((0.5 0.5, 2.5 0.5, 2.5 2.5, 0.5 2.5, 0.5 0.5))"); + + std::vector result_vec; + int result = GEOSGridIntersectionFractions(input_, 1, 0, 5, 3, 4, 3, result_vec.data()); + ensure_equals(result, 0); +} + +template<> +template<> +void object::test<3>() +{ + set_test_name("non-areal input"); + + input_ = fromWKT("POINT (3 8)"); + + std::vector result_vec; + int result = GEOSGridIntersectionFractions(input_, 1, 0, 5, 3, 4, 3, result_vec.data()); + ensure_equals(result, 0); +} + +} diff --git a/tests/unit/capi/GEOSSubdivideByGridTest.cpp b/tests/unit/capi/GEOSSubdivideByGridTest.cpp new file mode 100644 index 0000000000..d734c5bcab --- /dev/null +++ b/tests/unit/capi/GEOSSubdivideByGridTest.cpp @@ -0,0 +1,56 @@ +#include +#include + +#include "capi_test_utils.h" + +namespace tut { + +struct test_capigeossubdividebygrid_data : public capitest::utility {}; + +typedef test_group group; +typedef group::object object; + +group test_capigeossubdividebygrid_group("capi::GEOSSubdivideByGrid"); + +template<> +template<> +void object::test<1>() +{ + set_test_name("rectangle overlapping grid"); + + input_ = fromWKT("POLYGON ((0.5 0.5, 2.5 0.5, 2.5 2.5, 0.5 2.5, 0.5 0.5))"); + expected_ = fromWKT("GEOMETRYCOLLECTION (" + "POLYGON ((2 2.5, 1 2.5, 1 2, 2 2, 2 2.5))," + "POLYGON ((2.5 2, 2.5 2.5, 2 2.5, 2 2, 2.5 2))," + "POLYGON ((1 1, 2 1, 2 2, 1 2, 1 1))," + "POLYGON ((2.5 1, 2.5 2, 2 2, 2 1, 2.5 1))," + "POLYGON ((1 0.5, 2 0.5, 2 1, 1 1, 1 0.5))," + "POLYGON ((2 0.5, 2.5 0.5, 2.5 1, 2 1, 2 0.5)))"); + + result_ = GEOSSubdivideByGrid(input_, 1, 0, 5, 3, 4, 3, false); + + ensure_geometry_equals_identical(expected_, result_); +} + +template<> +template<> +void object::test<2>() +{ + set_test_name("includeExterior = true"); + + input_ = fromWKT("POLYGON ((0.5 0.5, 2.5 0.5, 2.5 2.5, 0.5 2.5, 0.5 0.5))"); + expected_ = fromWKT("GEOMETRYCOLLECTION (" + "POLYGON ((2 2.5, 1 2.5, 1 2, 2 2, 2 2.5))," + "POLYGON ((2.5 2, 2.5 2.5, 2 2.5, 2 2, 2.5 2))," + "POLYGON ((1 1, 2 1, 2 2, 1 2, 1 1))," + "POLYGON ((2.5 1, 2.5 2, 2 2, 2 1, 2.5 1))," + "POLYGON ((1 0.5, 2 0.5, 2 1, 1 1, 1 0.5))," + "POLYGON ((2 0.5, 2.5 0.5, 2.5 1, 2 1, 2 0.5))," + "POLYGON ((0.5 2.5, 1 2.5, 1 2, 1 1, 1 0.5, 0.5 0.5, 0.5 1, 0.5 2, 0.5 2.5)))"); + + result_ = GEOSSubdivideByGrid(input_, 1, 0, 5, 3, 4, 3, true); + + ensure_geometry_equals_identical(expected_, result_); +} + +} \ No newline at end of file diff --git a/tests/unit/operation/grid/GridIntersectionTest.cpp b/tests/unit/operation/grid/GridIntersectionTest.cpp new file mode 100644 index 0000000000..7734419031 --- /dev/null +++ b/tests/unit/operation/grid/GridIntersectionTest.cpp @@ -0,0 +1,604 @@ +#include + +#include +#include +#include + +#include + +using namespace geos::operation::grid; +using geos::geom::CoordinateXY; +using geos::geom::Envelope; +using geos::geom::Geometry; + +namespace tut { +struct test_gridintersectiontest_data : GEOSTestBase { + geos::io::WKTReader wkt_reader_; + + static void + check_cell_intersections(const Matrix& actual, const std::vector>& v) + { + Matrix expected{ v }; + + ensure_equals(actual, expected); + } +}; + +typedef test_group group; +typedef group::object object; + +group test_gridintersectiontest_group("geos::operation::grid::GridIntersection"); + +template<> template<> void object::test<1> +() +{ + set_test_name("basic rectangle"); + + Grid ex{ { 0, 3, 0, 3 }, 1, 1 }; // 3x3 grid + + auto g = wkt_reader_.read("POLYGON ((0.5 0.5, 2.5 0.5, 2.5 2.5, 0.5 2.5, 0.5 0.5))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { { 0.25, 0.5, 0.25 }, { 0.50, 1.0, 0.50 }, { 0.25, 0.5, 0.25 } }); + + // check alternate interface for rectangles + auto rci2 = GridIntersection::grid_intersection(ex, *g->getEnvelopeInternal()); + + ensure_equals(*rci, *rci2); +} + +template<> template<> void object::test<2> +() +{ + set_test_name("basic rectangular line"); + + Grid ex{ { 0, 3, 0, 3 }, 1, 1 }; // 3x3 grid + + auto g = wkt_reader_.read("LINESTRING (0.5 0.5, 2.5 0.5, 2.5 2.5, 0.5 2.5, 0.5 0.5)"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { { 1.00, 1.00, 1.00 }, { 1.00, 0, 1.00 }, { 1.00, 1.00, 1.00 } }); +} + +template<> template<> void object::test<3> +() +{ + set_test_name("basic rectangle with GeometryCollection"); + + Grid ex{ { 0, 3, 0, 3 }, 1, 1 }; // 3x3 grid + + auto g = wkt_reader_.read( + "GEOMETRYCOLLECTION (" + "MULTIPOLYGON (((0.5 0.5, 1.5 0.5, 1.5 1.5, 0.5 1.5, 0.5 0.5))," + " ((1.5 1.5, 2.5 1.5, 2.5 2.5, 1.5 2.5, 1.5 1.5)))," + "POLYGON ((0.5 1.5, 1.5 1.5, 1.5 2.5, 0.5 2.5, 0.5 1.5))," + "POLYGON ((1.5 0.5, 2.5 0.5, 2.5 1.5, 1.5 1.5, 1.5 0.5)))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { { 0.25, 0.5, 0.25 }, { 0.50, 1.0, 0.50 }, { 0.25, 0.5, 0.25 } }); +} + +template<> template<> void object::test<4> +() +{ + set_test_name("unsupported geometry"); + + Grid extent{ { 0, 3, 0, 3 }, 1, 1 }; // 3x3 grid + + auto g = wkt_reader_.read("POINT (3 7)"); + + ensure_THROW( GridIntersection::grid_intersection(extent, *g), std::exception); +} + +template<> template<> void object::test<5> +() +{ + set_test_name("basic non-rectangle"); + + Grid ex{ { 0, 3, 0, 3 }, 1, 1 }; // 3x3 grid + + auto g = wkt_reader_.read("POLYGON ((0.5 0.5, 2.5 0.5, 2.5 2.0, 2.0 2.0, 2.0 2.5, 0.5 2.5, 0.5 0.5))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { { 0.25, 0.5, 0.00 }, { 0.50, 1.0, 0.50 }, { 0.25, 0.5, 0.25 } }); +} + +template<> template<> void object::test<6> +() +{ + set_test_name("small polygon optimization"); + + Grid ex{ { 0, 3, 0, 3 }, 1, 1 }; // 3x3 grid + + // small polygon entirely contained in a single cell + auto g = wkt_reader_.read("POLYGON ((0.5 0.5, 0.6 0.5, 0.6 0.6, 0.5 0.5))"); + double g_area = g->getArea(); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + ensure_equals(rci->rows(), 3ul); + ensure_equals(rci->cols(), 3ul); + ensure_equals((*rci)(2, 0), static_cast(g_area)); +} + +template<> template<> void object::test<7> +() +{ + set_test_name("zero-area polygon"); + + Grid ex{ { 0, 3, 0, 3 }, 1, 1 }; // 3x3 grid + auto g = wkt_reader_.read("POLYGON ((0 0, 3 3, 0 0))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 } }); +} + +template<> template<> void object::test<8> +() { + set_test_name("Small line optimization"); + + Grid ex{ { 0, 3, 0, 3 }, 1, 1 }; // 3x3 grid + + // small line entirely contained in a single cell + auto g = wkt_reader_.read("LINESTRING (0.5 0.5, 0.6 0.5, 0.6 0.6, 0.5 0.5)"); + double g_length = g->getLength(); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + ensure_equals(rci->rows(), 3u); + ensure_equals(rci->cols(), 3u); + ensure_equals((*rci)(2, 0), static_cast(g_length)); +} + +template<> template<> void object::test<9> +() { + set_test_name("basic line"); + + Grid ex{ { 0, 3, 0, 3 }, 1, 1 }; // 3x3 grid + + auto g = wkt_reader_.read("LINESTRING (0.5 0.5, 2.5 0.5, 2.5 2.5, 0.5 2.5)"); + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { { 0.50, 1.00, 1.00 }, { 0, 0, 1.00 }, { 0.50, 1.00, 1.00 } }); +} + +template<> template<> void object::test<10> +() { + set_test_name("geometry extent larger than raster"); + // Process a geometry using four 3x3 tiles + + // +-----+-----+ + // | 1 | 2 | + // +-----+-----+ + // | 3 | 4 | + // +-----+-----+ + + Envelope b3{ 0, 3, 0, 3 }; + Envelope b2 = b3; + b2.translate(3, 3); + Envelope b1 = b3; + b1.translate(0, 3); + Envelope b4 = b3; + b4.translate(3, 0); + + Grid g1{ b1, 1, 1 }; + Grid g2{ b2, 1, 1 }; + Grid g3{ b3, 1, 1 }; + Grid g4{ b4, 1, 1 }; + + auto g = wkt_reader_.read( "POLYGON ((0.5 0.5, 4.5 0.5, 4.5 5.5, 0.5 5.5, 0.5 0.5))"); + + auto ll = GridIntersection::grid_intersection(g3, *g); + + check_cell_intersections(*ll, { { 0.50, 1.0, 1.0 }, { 0.50, 1.0, 1.0 }, { 0.25, 0.5, 0.5 } }); + + auto lr = GridIntersection::grid_intersection(g4, *g); + + check_cell_intersections(*lr, { { 1.00, 0.50, 0.0 }, { 1.00, 0.50, 0.0 }, { 0.50, 0.25, 0.0 } }); + + auto ur = GridIntersection::grid_intersection(g2, *g); + + check_cell_intersections(*ur, { { 0.50, 0.25, 0.0 }, { 1.00, 0.50, 0.0 }, { 1.00, 0.50, 0.0 } }); + + auto ul = GridIntersection::grid_intersection(g1, *g); + + check_cell_intersections(*ul, { { 0.25, 0.5, 0.5 }, { 0.50, 1.0, 1.0 }, { 0.50, 1.0, 1.0 } }); +} + +template<> template<> void object::test<11> +() { + set_test_name("geometry entirely outside raster"); + + Grid ex{ { -3, 0, -3, 0 }, 1, 1 }; // 3x3 grid + + auto g = wkt_reader_.read("POLYGON ((1.5 0.5, 2.5 1.5, 1.5 2.5, 0.5 1.5, 1.5 0.5))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 } }); + + // check alternate pathway for rectangles + auto rci_rect = GridIntersection::grid_intersection(ex, *g->getEnvelopeInternal()); + + check_cell_intersections(*rci_rect, { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 } }); +} + +template<> template<> void object::test<12> +() { + set_test_name("Invalid geometry with detached inner ring outside raster"); + + Grid ex{ {0, 3, 0, 3}, 1, 1 }; // 3x3 grid + + auto g = wkt_reader_.read("POLYGON ((1.5 0.5, 2.5 1.5, 1.5 2.5, 0.5 1.5, 1.5 0.5), (100 100, 100 101, 101 101, 100 100))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + ensure_equals(rci->rows(), 3u); + ensure_equals(rci->cols(), 3u); +} + +template<> template<> void object::test<13> +() { + set_test_name("diagonals"); + + Grid ex{ {0, 3, 0, 3}, 1, 1 }; // 3x3 grid + + auto g = wkt_reader_.read("POLYGON ((1.5 0.5, 2.5 1.5, 1.5 2.5, 0.5 1.5, 1.5 0.5))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { + { 0.00, 0.25, 0.00 }, + { 0.25, 1.00, 0.25 }, + { 0.00, 0.25, 0.00 }, + }); +} + +template<> template<> void object::test<14> +() { + set_test_name("starting on cell boundary"); + + // Situation found in Canada using 0.5-degree global grid + Grid ex{ { 0, 2, 0, 2 }, 1, 1 }; // 2x2 grid + + auto g = wkt_reader_.read("POLYGON ((1 1.5, 1.5 1.5, 1.5 0.5, 0.5 0.5, 0.5 1.5, 1 1.5))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { + { 0.25, 0.25 }, + { 0.25, 0.25 }, + }); +} + +template<> template<> void object::test<15> +() { + set_test_name("bouncing off boundary"); + + // Situation found in Trinidad and Tobago using 0.5-degree global grid + Grid ex{ { 0, 2, -1, 2 }, 1, 1 }; // 3x2 grid + + auto g = wkt_reader_.read("POLYGON ((0.5 1.5, 0.5 0.5, 0.5 0, 1.5 0.5, 1.5 1.5, 0.5 1.5))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { { 0.25, 0.25 }, { 0.4375, 0.3125 }, { 0.0, 0.0 } }); +} + +template<> template<> void object::test<16> +() { + set_test_name("bouncing off boundary (2)"); + + Grid extent{ { 0, 2, 0, 2 }, 1, 1 }; + + auto g = wkt_reader_.read("POLYGON ((0.5 0.5, 1.5 0.5, 1.5 1.5, 0.5 1.5, 1 1.2, 0.5 0.5))"); + + ensure_NO_THROW(GridIntersection(extent, *g)); +} + +template<> template<> void object::test<17> +() { + set_test_name("follows grid boundary"); + + // Occurs on the Libya-Egypt border, for example + + Grid ex{ { 0, 3, 0, 3 }, 1, 1 }; + + auto g = wkt_reader_.read("POLYGON ((0.5 0.5, 2 0.5, 2 1.5, 2 2.5, 0.5 2.5, 0.5 0.5))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { + { 0.25, 0.5, 0.0 }, + { 0.50, 1.0, 0.0 }, + { 0.25, 0.5, 0.0 }, + }); +} + +template<> template<> void object::test<18> +() { + set_test_name("starts on vertical boundary, moving up"); + Grid ex{ { 0, 4, 0, 3 }, 1, 1 }; // 4x3 grid + + auto g = wkt_reader_.read("POLYGON ((3 0.5, 3 2.5, 0.5 2.5, 0.5 0.5, 3 0.5))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { + { 0.25, 0.5, 0.5, 0.0 }, + { 0.50, 1.0, 1.0, 0.0 }, + { 0.25, 0.5, 0.5, 0.0 }, + }); +} + +template<> template<> void object::test<19> +() { + set_test_name("starts on vertical boundary, moving down"); + Grid ex{ { 0, 4, 0, 3 }, 1, 1 }; // 4x3 grid + + auto g = wkt_reader_.read("POLYGON ((0.5 2.5, 0.5 0.5, 3 0.5, 3 2.5, 0.5 2.5))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { + { 0.25, 0.5, 0.5, 0.0 }, + { 0.50, 1.0, 1.0, 0.0 }, + { 0.25, 0.5, 0.5, 0.0 }, + }); +} + +template<> template<> void object::test<20> +() { + set_test_name("starts on vertical boundary, moving down at rightmost extent of grid"); + Grid ex{ { 0, 3, 0, 3 }, 1, 1 }; // 3x3 grid + + auto g = wkt_reader_.read("POLYGON ((3 2.5, 3 0.5, 0.5 0.5, 0.5 2.5, 3 2.5))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { + { 0.25, 0.5, 0.5 }, + { 0.50, 1.0, 1.0 }, + { 0.25, 0.5, 0.5 }, + }); +} + +template<> template<> void object::test<21> +() { + set_test_name("starts on horizontal boundary, moving right"); + Grid ex{ { 0, 3, 0, 4 }, 1, 1 }; // 3x4 grid + + auto g = wkt_reader_.read("POLYGON ((0.5 1, 2.5 1, 2.5 3.5, 0.5 3.5, 0.5 1))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { { 0.25, 0.5, 0.25 }, { 0.50, 1.0, 0.50 }, { 0.50, 1.0, 0.50 }, { 0.0, 0.0, 0.0 } }); +} + +template<> template<> void object::test<22> +() { + set_test_name("starts on horizontal boundary, moving left"); + Grid ex{ { 0, 3, 0, 4 }, 1, 1 }; // 3x4 grid + + auto g = wkt_reader_.read("POLYGON ((2.5 3, 0.5 3, 0.5 3.5, 0.25 3.5, 0.25 0.5, 2.5 0.5, 2.5 3))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { + { 0.125, 0.00, 0.00 }, + { 0.750, 1.00, 0.50 }, + { 0.750, 1.00, 0.50 }, + { 0.375, 0.50, 0.25 }, + }); +} + +template<> template<> void object::test<23> +() { + set_test_name("Regression test - Fiji"); + + // Just make sure this polygon doesn't throw an exception. It caused some problems where the + // rightmost edge was interpreted to be exactly on a cell wall. + Grid extent{ { -180.5, 180.5, -90.5, 90.5 }, 0.5, 0.5 }; + + auto g = wkt_reader_.read("MULTIPOLYGON (((178.3736000000001 -17.33992000000002, 178.71806000000007 -17.62845999999996, 178.5527099999999 -18.150590000000008, 177.93266000000008 -18.287990000000036, 177.38145999999992 -18.164319999999975, 177.28504000000007 -17.72464999999997, 177.67087 -17.381139999999974, 178.12557000000007 -17.50480999999995, 178.3736000000001 -17.33992000000002)), ((179.36414266196417 -16.801354076946836, 178.7250593629972 -17.012041674368007, 178.5968385951172 -16.63915000000003, 179.0966093629972 -16.43398427754741, 179.4135093629972 -16.379054277547382, 180.00000000000003 -16.06713266364241, 180.00000000000003 -16.555216566639146, 179.36414266196417 -16.801354076946836)), ((-179.91736938476527 -16.501783135649347, -179.99999999999997 -16.555216566639146, -179.99999999999997 -16.06713266364241, -179.79332010904858 -16.020882256741217, -179.91736938476527 -16.501783135649347)))"); + + ensure_NO_THROW(GridIntersection(extent, *g)); +} + +template<> template<> void object::test<24>() { + set_test_name("small polygon"); + + Grid ex{ { 0, 10, 0, 10 }, 10, 10 }; // Single cell + + auto g = wkt_reader_.read("POLYGON ((3 3, 4 3, 4 4, 3 4, 3 3))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { { 0.01f } }); +} + +template<> template<> void object::test<25>() { + set_test_name("Fill handled correctly"); + + Grid ex{ { 0, 3, 0, 5 }, 1, 1 }; // 3x5 grid + + auto g = wkt_reader_.read("POLYGON ((0.5 0.2, 2.2 0.2, 2.2 0.4, 0.7 0.4, 0.7 2.2, 2.2 2.2, 2.2 0.6, 2.4 0.6, 2.4 4.8, 0.5 4.8, 0.5 0.2))"); + + auto rci = GridIntersection::grid_intersection(ex, *g); + + check_cell_intersections(*rci, { + { 0.40f, 0.80f, 0.32f }, + { 0.50f, 1.00f, 0.40f }, + { 0.44f, 0.80f, 0.36f }, + { 0.20f, 0.00f, 0.20f }, + { 0.22f, 0.20f, 0.12f }, + }); +} + +template<> template<> void object::test<26>() { + set_test_name("Robustness regression test #1"); + // This test exercises some challenging behavior where a polygon follows + // ymin, but the grid resolution is such that ymin < (ymax - ny*dy) + + Grid extent{ { -180, 180, -90, 90 }, 1.0 / 6, 1.0 / 6 }; + + auto g = wkt_reader_.read(load_resource("antarctica.wkt")); + ensure_NO_THROW(GridIntersection(extent, *g)); +} + +template<> template<> void object::test<27>() { + set_test_name("Robustness regression test #2"); + // This test exercises some challenging behavior where a polygon follows + // xmax, but the grid resolution is such that xmax < (xmin + nx*m_dx) + + Grid extent{ { -180, 180, -90, 90 }, 1.0 / 6, 1.0 / 6 }; + + auto g = wkt_reader_.read(load_resource("russia.wkt")); + + ensure_NO_THROW(GridIntersection(extent, *g)); +} + +template<> template<> void object::test<29>() { + set_test_name("robustness regression test #3"); + // The situation in this case was causing some kind of infinite loop, ultimately exhausting memory + + Grid extent{ { 179.96666666664618, 179.99999999997954, -16.541666666669137, -16.475000000002474 }, 0.0083333333333328596, 0.0083333333333328596 }; + + auto g = wkt_reader_.read("POLYGON ((179.9715827094184135 -16.5409617106119526, 180.0000000000000000 -16.5326999999999984, 179.9872884114583655 -16.5342697143554425, 179.9715827094184135 -16.5409617106119526))"); + Envelope env = g->getEnvelopeInternal()->intersection(extent.extent()); + extent = extent.shrink_to_fit(env); + + ensure_NO_THROW( GridIntersection::grid_intersection(extent, *g)); +} + +template<> template<> void object::test<30>() +{ + set_test_name("Robustness regression test #4"); + + Grid extent{ { -166.84166666666667, -152.625, 66.991666666666674, 71.358333333333334 }, 0.0083333333333333332, 0.0083333333333333332 }; + + auto g = wkt_reader_.read(load_resource("regression4.wkt")); + + ensure_NO_THROW(GridIntersection(extent, *g)); +} + +template<> template<> void object::test<31>() { + set_test_name("robustness regression test #5"); + + Grid extent{ { 0, 10, 0, 10 }, 1, 1 }; + + auto g = wkt_reader_.read("POINT (2 2)")->buffer(1, 30); + + ensure_NO_THROW( GridIntersection::grid_intersection(extent, *g)); +} + +template<> template<> void object::test<32>() { + set_test_name("Robustness regression test #6"); + + Grid ex{ { 145.925, 147.375, -35.525, -33.475 }, 0.05, 0.05 }; + + auto g = wkt_reader_.read(load_resource("regression6.wkt")); + GridIntersection gi(ex, *g); + const auto& result = *gi.results(); + + float tot = 0; + + for (size_t i = 0; i < result.rows(); i++) { + for (size_t j = 0; j < result.cols(); j++) { + tot += result(i, j); + if (result(i, j) < 0 || result(i, j) > 1) { + fail(); + } + } + } + + ensure_equals(tot, 823.0f); +} + +template<> template<> void object::test<33>() { + set_test_name("robustness regression test #7"); + + Grid ex{ { 487800, 492800, 5813800, 5818800 }, 100, 100 }; + + auto g = wkt_reader_.read("POLYGON ((492094.9283999996 5816959.8553, 492374.9335527361 5816811.352641133, 492374.9335527363 5816811.352641133, 492094.9283999996 5816959.8553))"); + ex = ex.shrink_to_fit(*g->getEnvelopeInternal()); + + double total_area = g->getArea(); + double cell_area = ex.dx() * ex.dy(); + double max_possible_frac = total_area / cell_area; + + auto result = GridIntersection::grid_intersection(ex, *g); + + for (std::size_t i = 0; i < result->rows(); i++) { + for (std::size_t j = 0; j < result->cols(); j++) { + auto frac = (*result)(i, j); + ensure((frac >= 0 && frac <= static_cast(max_possible_frac))); + } + } +} + +template<> template<> void object::test<34>() { + set_test_name("Processing region is empty when there are no polygons"); + + Envelope raster_extent{ 0, 10, 0, 10 }; + + auto g = wkt_reader_.read("POLYGON EMPTY"); + + ensure_equals(GridIntersection::processing_region(raster_extent, *g).getArea(), 0); +} + +template<> template<> void object::test<35>() { + set_test_name("Processing region is empty when all polygons are outside of it"); + + Envelope raster_extent{ 40, 50, 40, 50 }; + + auto g = wkt_reader_.read("MULTIPOLYGON (((60 60, 70 60, 70 70, 60 70, 60 60)), ((20 20, 30 20, 30 30, 20 30, 20 20)))"); + + ensure_equals(GridIntersection::processing_region(raster_extent, *g).getArea(), 0); +} + +template<> template<> void object::test<36>() { + set_test_name("subdividing a simple polygon"); + + Envelope e(0, 10, 0, 10); + Grid ext(e, 1, 2); + + auto g = wkt_reader_.read("POLYGON ((1 3, 9 5, 8 9, 1 3))") ; + + auto subdivided = GridIntersection::subdivide_polygon(ext, *g, false); + + ensure_equals(g->getArea(), subdivided->getArea()); +} + +template<> template<> void object::test<37>() { + set_test_name("subdividing a polygon that partially intersects grid"); + + Envelope e(0, 10, 0, 10); + Grid ext(e, 1, 1); + + auto g = wkt_reader_.read("POLYGON ((8.5 8.7, 12 8, 12 12, 8 12, 8.5 8.7))"); + + auto subdivided = GridIntersection::subdivide_polygon(ext, *g, true); + + ensure_equals("", subdivided->getArea(), g->getArea(), 1e-8); +} + +template<> template<> void object::test<38>() { + set_test_name("subdividing a polygon that contains the grid intersects grid"); + + Envelope e(0, 10, 0, 10); + Grid ext(e, 1, 1); + + auto g = wkt_reader_.read("POINT (5 5)")->buffer(20); + + auto subdivided = GridIntersection::subdivide_polygon(ext, *g, true); + + ensure_equals("", subdivided->getArea(), g->getArea(), 1e-8); +} + +} \ No newline at end of file diff --git a/tests/unit/utility.h b/tests/unit/utility.h index d0311655c8..575b4a928a 100644 --- a/tests/unit/utility.h +++ b/tests/unit/utility.h @@ -30,6 +30,20 @@ #include #include +#include +#include + +#if defined(__GNUC__) && !defined(__clang__) +#define HAVE_STD_FILESYSTEM (__GNUC__ > 8) +#else +#define HAVE_STD_FILESYSTEM 1 +#endif +#if HAVE_STD_FILESYSTEM +#include +#endif + +extern std::string RESOURCE_DIR; + using geos::geom::Coordinate; using geos::geom::CoordinateSequence; using geos::geom::Geometry; @@ -562,6 +576,35 @@ struct wkb_hex_decoder { } }; +// Base class with helpers +struct GEOSTestBase { + + static std::string load_resource(const std::string& fname) { +#if HAVE_STD_FILESYSTEM + if (RESOURCE_DIR == "") { + skip("geos_unit resource directory is not defined. Set it using --data"); + } + + auto fpath = std::filesystem::relative(RESOURCE_DIR) / fname; + if (!std::filesystem::exists(fpath)) { + std::stringstream ss; + ss << "Could not read " << std::filesystem::absolute(fpath); + skip(ss.str()); + } + + std::ifstream file(fpath); + std::stringstream contents; + contents << file.rdbuf(); + + return contents.str(); +#else + (void) fname; + skip("std::filesystem is not available"); + return ""; +#endif + } + +}; } // namespace tut