From 51b388d953abe08f2c7146d90b5a46201f41cc59 Mon Sep 17 00:00:00 2001 From: Daniel Patterson Date: Thu, 19 Apr 2018 16:27:11 -0700 Subject: [PATCH 1/9] Use faster method for calculating distances. fix cmakelist --- CMakeLists.txt | 8 +- .../routing_algorithms/routing_base.hpp | 2 +- include/util/coordinate_calculation.hpp | 3 + src/util/coordinate_calculation.cpp | 39 + .../cheap-ruler-cpp-2.5.4/.clang-format | 18 + third_party/cheap-ruler-cpp-2.5.4/.gitignore | 2 + third_party/cheap-ruler-cpp-2.5.4/.travis.yml | 25 + .../cheap-ruler-cpp-2.5.4/CMakeLists.txt | 27 + third_party/cheap-ruler-cpp-2.5.4/LICENSE | 15 + third_party/cheap-ruler-cpp-2.5.4/README.md | 199 ++ .../cheap-ruler-cpp-2.5.4/cmake/build.cmake | 11 + .../cheap-ruler-cpp-2.5.4/cmake/mason.cmake | 235 ++ .../include/mapbox/cheap_ruler.hpp | 354 +++ .../test/cheap_ruler.cpp | 200 ++ .../test/fixtures/lines.hpp | 8 + .../test/fixtures/turf.hpp | 1894 +++++++++++++++++ third_party/geometry.hpp-0.9.2/.gitignore | 2 + third_party/geometry.hpp-0.9.2/.gitmodules | 3 + third_party/geometry.hpp-0.9.2/.travis.yml | 50 + third_party/geometry.hpp-0.9.2/LICENSE | 13 + third_party/geometry.hpp-0.9.2/Makefile | 19 + third_party/geometry.hpp-0.9.2/README.md | 83 + .../include/mapbox/geometry.hpp | 13 + .../include/mapbox/geometry/box.hpp | 34 + .../include/mapbox/geometry/envelope.hpp | 33 + .../include/mapbox/geometry/feature.hpp | 91 + .../mapbox/geometry/for_each_point.hpp | 45 + .../include/mapbox/geometry/geometry.hpp | 58 + .../include/mapbox/geometry/line_string.hpp | 21 + .../mapbox/geometry/multi_line_string.hpp | 21 + .../include/mapbox/geometry/multi_point.hpp | 21 + .../include/mapbox/geometry/multi_polygon.hpp | 21 + .../include/mapbox/geometry/point.hpp | 35 + .../mapbox/geometry/point_arithmetic.hpp | 119 ++ .../include/mapbox/geometry/polygon.hpp | 31 + .../geometry.hpp-0.9.2/tests/collection.cpp | 5 + third_party/geometry.hpp-0.9.2/tests/test.cpp | 260 +++ 37 files changed, 4016 insertions(+), 2 deletions(-) create mode 100644 third_party/cheap-ruler-cpp-2.5.4/.clang-format create mode 100644 third_party/cheap-ruler-cpp-2.5.4/.gitignore create mode 100644 third_party/cheap-ruler-cpp-2.5.4/.travis.yml create mode 100644 third_party/cheap-ruler-cpp-2.5.4/CMakeLists.txt create mode 100644 third_party/cheap-ruler-cpp-2.5.4/LICENSE create mode 100644 third_party/cheap-ruler-cpp-2.5.4/README.md create mode 100644 third_party/cheap-ruler-cpp-2.5.4/cmake/build.cmake create mode 100644 third_party/cheap-ruler-cpp-2.5.4/cmake/mason.cmake create mode 100644 third_party/cheap-ruler-cpp-2.5.4/include/mapbox/cheap_ruler.hpp create mode 100644 third_party/cheap-ruler-cpp-2.5.4/test/cheap_ruler.cpp create mode 100644 third_party/cheap-ruler-cpp-2.5.4/test/fixtures/lines.hpp create mode 100644 third_party/cheap-ruler-cpp-2.5.4/test/fixtures/turf.hpp create mode 100644 third_party/geometry.hpp-0.9.2/.gitignore create mode 100644 third_party/geometry.hpp-0.9.2/.gitmodules create mode 100644 third_party/geometry.hpp-0.9.2/.travis.yml create mode 100644 third_party/geometry.hpp-0.9.2/LICENSE create mode 100644 third_party/geometry.hpp-0.9.2/Makefile create mode 100644 third_party/geometry.hpp-0.9.2/README.md create mode 100644 third_party/geometry.hpp-0.9.2/include/mapbox/geometry.hpp create mode 100644 third_party/geometry.hpp-0.9.2/include/mapbox/geometry/box.hpp create mode 100644 third_party/geometry.hpp-0.9.2/include/mapbox/geometry/envelope.hpp create mode 100644 third_party/geometry.hpp-0.9.2/include/mapbox/geometry/feature.hpp create mode 100644 third_party/geometry.hpp-0.9.2/include/mapbox/geometry/for_each_point.hpp create mode 100644 third_party/geometry.hpp-0.9.2/include/mapbox/geometry/geometry.hpp create mode 100644 third_party/geometry.hpp-0.9.2/include/mapbox/geometry/line_string.hpp create mode 100644 third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_line_string.hpp create mode 100644 third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_point.hpp create mode 100644 third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_polygon.hpp create mode 100644 third_party/geometry.hpp-0.9.2/include/mapbox/geometry/point.hpp create mode 100644 third_party/geometry.hpp-0.9.2/include/mapbox/geometry/point_arithmetic.hpp create mode 100644 third_party/geometry.hpp-0.9.2/include/mapbox/geometry/polygon.hpp create mode 100644 third_party/geometry.hpp-0.9.2/tests/collection.cpp create mode 100644 third_party/geometry.hpp-0.9.2/tests/test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4dbc5a2ebc7..e1767b961d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -424,6 +424,12 @@ include_directories(SYSTEM ${RAPIDJSON_INCLUDE_DIR}) set(MICROTAR_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/microtar/src") include_directories(SYSTEM ${MICROTAR_INCLUDE_DIR}) + +set(MBXGEOM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/geometry.hpp-0.9.2/include") +include_directories(SYSTEM ${MBXGEOM_INCLUDE_DIR}) +set(CHEAPRULER_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/cheap-ruler-cpp-2.5.4/include") +include_directories(SYSTEM ${CHEAPRULER_INCLUDE_DIR}) + add_library(MICROTAR OBJECT "${CMAKE_CURRENT_SOURCE_DIR}/third_party/microtar/src/microtar.c") set_property(TARGET MICROTAR PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -867,4 +873,4 @@ if (ENABLE_NODE_BINDINGS) endforeach() add_library(check-headers STATIC EXCLUDE_FROM_ALL ${sources}) set_target_properties(check-headers PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${check_headers_dir}) -endif() +endif() \ No newline at end of file diff --git a/include/engine/routing_algorithms/routing_base.hpp b/include/engine/routing_algorithms/routing_base.hpp index 000f1b14d23..0c0808a3f49 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -415,7 +415,7 @@ template EdgeDistance computeEdgeDistance(const FacadeT &faca auto geometry_range = facade.GetUncompressedForwardGeometry(geometry_index.id); for (auto current = geometry_range.begin(); current < geometry_range.end() - 1; ++current) { - total_distance += util::coordinate_calculation::haversineDistance( + total_distance += util::coordinate_calculation::fccApproximateDistance( facade.GetCoordinateOfNode(*current), facade.GetCoordinateOfNode(*std::next(current))); } diff --git a/include/util/coordinate_calculation.hpp b/include/util/coordinate_calculation.hpp index aa60504ed8b..c946842a23e 100644 --- a/include/util/coordinate_calculation.hpp +++ b/include/util/coordinate_calculation.hpp @@ -43,6 +43,9 @@ inline double radToDeg(const double radian) //! Takes the squared euclidean distance of the input coordinates. Does not return meters! std::uint64_t squaredEuclideanDistance(const Coordinate lhs, const Coordinate rhs); +double fccApproximateDistance(const Coordinate first_coordinate, + const Coordinate second_coordinate); + double haversineDistance(const Coordinate first_coordinate, const Coordinate second_coordinate); double greatCircleDistance(const Coordinate first_coordinate, const Coordinate second_coordinate); diff --git a/src/util/coordinate_calculation.cpp b/src/util/coordinate_calculation.cpp index ae968203d73..e1d9aa19352 100644 --- a/src/util/coordinate_calculation.cpp +++ b/src/util/coordinate_calculation.cpp @@ -5,6 +5,8 @@ #include +#include + #include #include #include @@ -18,6 +20,30 @@ namespace util namespace coordinate_calculation { +namespace +{ +mapbox::cheap_ruler::CheapRuler cheap_ruler_cache[] = { + mapbox::cheap_ruler::CheapRuler(-90, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(-80, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(-70, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(-60, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(-50, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(-40, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(-30, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(-20, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(-10, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(0, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(10, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(20, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(30, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(40, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(50, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(60, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(70, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(80, mapbox::cheap_ruler::CheapRuler::Meters), + mapbox::cheap_ruler::CheapRuler(90, mapbox::cheap_ruler::CheapRuler::Meters)}; +} + // Does not project the coordinates! std::uint64_t squaredEuclideanDistance(const Coordinate lhs, const Coordinate rhs) { @@ -32,6 +58,19 @@ std::uint64_t squaredEuclideanDistance(const Coordinate lhs, const Coordinate rh return result; } +// Uses method described here: +// https://www.gpo.gov/fdsys/pkg/CFR-2005-title47-vol4/pdf/CFR-2005-title47-vol4-sec73-208.pdf +// should be within 0.1% or so of Vincenty method (assuming 19 buckets are enough) +// Should be more faster and more precise than Haversine +double fccApproximateDistance(const Coordinate coordinate_1, const Coordinate coordinate_2) +{ + const auto lon1 = static_cast(util::toFloating(coordinate_1.lon)); + const auto lat1 = static_cast(util::toFloating(coordinate_1.lat)); + const auto lon2 = static_cast(util::toFloating(coordinate_2.lon)); + const auto lat2 = static_cast(util::toFloating(coordinate_2.lat)); + return cheap_ruler_cache[std::lround(lat1 / 10) + 9].distance({lon1, lat1}, {lon2, lat2}); +} + double haversineDistance(const Coordinate coordinate_1, const Coordinate coordinate_2) { auto lon1 = static_cast(coordinate_1.lon); diff --git a/third_party/cheap-ruler-cpp-2.5.4/.clang-format b/third_party/cheap-ruler-cpp-2.5.4/.clang-format new file mode 100644 index 00000000000..ff0f39e73bb --- /dev/null +++ b/third_party/cheap-ruler-cpp-2.5.4/.clang-format @@ -0,0 +1,18 @@ +Standard: Cpp11 +IndentWidth: 4 +AccessModifierOffset: -4 +UseTab: Never +BinPackParameters: false +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AllowShortBlocksOnASingleLine: false +AllowShortFunctionsOnASingleLine: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +AlwaysBreakTemplateDeclarations: true +NamespaceIndentation: None +PointerBindsToType: true +SpacesInParentheses: false +BreakBeforeBraces: Attach +ColumnLimit: 100 +Cpp11BracedListStyle: false +SpacesBeforeTrailingComments: 1 diff --git a/third_party/cheap-ruler-cpp-2.5.4/.gitignore b/third_party/cheap-ruler-cpp-2.5.4/.gitignore new file mode 100644 index 00000000000..7117dfc1b4a --- /dev/null +++ b/third_party/cheap-ruler-cpp-2.5.4/.gitignore @@ -0,0 +1,2 @@ +build/ +mason_packages/ diff --git a/third_party/cheap-ruler-cpp-2.5.4/.travis.yml b/third_party/cheap-ruler-cpp-2.5.4/.travis.yml new file mode 100644 index 00000000000..260d944a36d --- /dev/null +++ b/third_party/cheap-ruler-cpp-2.5.4/.travis.yml @@ -0,0 +1,25 @@ +language: generic + +matrix: + include: + - os: linux + env: CXX=g++-4.9 + sudo: required + dist: trusty + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'g++-4.9', 'cmake', 'cmake-data' ] + - os: linux + env: CXX=g++-5 + sudo: required + dist: trusty + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'g++-5', 'cmake', 'cmake-data' ] + +cache: apt + +script: + - cmake . && make && ./cheap_ruler diff --git a/third_party/cheap-ruler-cpp-2.5.4/CMakeLists.txt b/third_party/cheap-ruler-cpp-2.5.4/CMakeLists.txt new file mode 100644 index 00000000000..31bc80592da --- /dev/null +++ b/third_party/cheap-ruler-cpp-2.5.4/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR) +project(cheap_ruler LANGUAGES CXX C) + +include(cmake/build.cmake) +include(cmake/mason.cmake) + +set(CMAKE_OSX_DEPLOYMENT_TARGET 10.10) +set(CMAKE_CONFIGURATION_TYPES Debug Release) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -Wextra -Wpedantic -Wshadow") + +mason_use(geometry VERSION 0.9.2 HEADER_ONLY) +mason_use(gtest VERSION 1.8.0) +mason_use(variant VERSION 1.1.4 HEADER_ONLY) + +add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) + +add_executable(cheap_ruler + ${PROJECT_SOURCE_DIR}/test/cheap_ruler.cpp +) + +target_include_directories(cheap_ruler + PUBLIC ${PROJECT_SOURCE_DIR}/include +) + +target_add_mason_package(cheap_ruler PRIVATE geometry) +target_add_mason_package(cheap_ruler PRIVATE gtest) +target_add_mason_package(cheap_ruler PRIVATE variant) diff --git a/third_party/cheap-ruler-cpp-2.5.4/LICENSE b/third_party/cheap-ruler-cpp-2.5.4/LICENSE new file mode 100644 index 00000000000..6f4f868bbc9 --- /dev/null +++ b/third_party/cheap-ruler-cpp-2.5.4/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2017, Mapbox + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/third_party/cheap-ruler-cpp-2.5.4/README.md b/third_party/cheap-ruler-cpp-2.5.4/README.md new file mode 100644 index 00000000000..40ceab3e40d --- /dev/null +++ b/third_party/cheap-ruler-cpp-2.5.4/README.md @@ -0,0 +1,199 @@ +# cheap-ruler-cpp + +Port to C++ of [Cheap Ruler](https://github.com/mapbox/cheap-ruler), a collection of very fast approximations to common geodesic measurements. + +[![Build Status](https://travis-ci.org/mapbox/cheap-ruler-cpp.svg?branch=master)](https://travis-ci.org/mapbox/cheap-ruler-cpp) + +# Usage + +```cpp +#include + +namespace cr = mapbox::cheap_ruler; +``` + +All `point`, `line_string`, `polygon`, and `box` references are [mapbox::geometry](https://github.com/mapbox/geometry.hpp) data structures. + +## Create a ruler object + +#### `CheapRuler(double latitude, Unit unit)` + +Creates a ruler object that will approximate measurements around the given latitude with an optional distance unit. Once created, the ruler object has access to the [methods](#methods) below. + +```cpp +auto ruler = cr::CheapRuler(32.8351); +auto milesRuler = cr::CheapRuler(32.8351, cr::CheapRuler::Miles); +``` + +Possible units: + +* `cheap_ruler::CheapRuler::Unit` +* `cheap_ruler::CheapRuler::Kilometers` +* `cheap_ruler::CheapRuler::Miles` +* `cheap_ruler::CheapRuler::NauticalMiles` +* `cheap_ruler::CheapRuler::Meters` +* `cheap_ruler::CheapRuler::Yards` +* `cheap_ruler::CheapRuler::Feet` +* `cheap_ruler::CheapRuler::Inches` + +#### `CheapRuler::fromTile(uint32_t y, uint32_t z)` + +Creates a ruler object from tile coordinates (`y` and `z` integers). Convenient in tile-reduce scripts. + +```cpp +auto ruler = cr::CheapRuler::fromTile(11041, 15); +``` + +## Methods + +#### `distance(point a, point b)` + +Given two points of the form [x = longitude, y = latitude], returns the distance (`double`). + +```cpp +cr::point point_a{-96.9148, 32.8351}; +cr::point point_b{-96.9146, 32.8386}; +auto distance = ruler.distance(point_a, point_b); +std::clog << distance; // 0.388595 +``` + +#### `bearing(point a, point b)` + +Returns the bearing (`double`) between two points in angles. + +```cpp +cr::point point_a{-96.9148, 32.8351}; +cr::point point_b{-96.9146, 32.8386}; +auto bearing = ruler.bearing(point_a, point_b); +std::clog << bearing; // 2.76206 +``` + +#### `destination(point origin, double distance, double bearing)` + +Returns a new point (`point`) given distance and bearing from the starting point. + +```cpp +cr::point point_a{-96.9148, 32.8351}; +auto dest = ruler.destination(point_a, 1.0, -175); +std::clog << dest.x << ", " << dest.y; // -96.9148, 32.8261 +``` + +#### `offset(point origin, double dx, double dy)` + +Returns a new point (`point`) given easting and northing offsets from the starting point. + +```cpp +cr::point point_a{-96.9148, 32.8351}; +auto os = ruler.offset(point_a, 10.0, -5.0); +std::clog << os.x << ", " << os.y; // -96.808, 32.79 +``` + +#### `lineDistance(const line_string& points)` + +Given a line (an array of points), returns the total line distance (`double`). + +```cpp +cr::line_string line_a{{ -96.9, 32.8 }, { -96.8, 32.8 }, { -96.2, 32.3 }}; +auto line_distance = ruler.lineDistance(line_a); +std::clog << line_distance; // 88.2962 +``` + +#### `area(polygon poly)` + +Given a polygon (an array of rings, where each ring is an array of points), returns the area (`double`). + +```cpp +cr::linear_ring ring{{ -96.9, 32.8 }, { -96.8, 32.8 }, { -96.2, 32.3 }, { -96.9, 32.8 }}; +auto area = ruler.area(cr::polygon{ ring }); +std::clog << area; // +``` + +#### `along(const line_string& line, double distance)` + +Returns the point (`point`) at a specified distance along the line. + +```cpp +cr::linear_ring ring{{ -96.9, 32.8 }, { -96.8, 32.8 }, { -96.2, 32.3 }, { -96.9, 32.8 }}; +auto area = ruler.area(cr::polygon{ ring }); +std::clog << area; // 259.581 +``` + +#### `pointOnLine(const line_string& line, point p)` + +Returns a tuple of the form `std::pair` where point is closest point on the line from the given point, index is the start index of the segment with the closest point, and t is a parameter from 0 to 1 that indicates where the closest point is on that segment. + +```cpp +cr::line_string line{{ -96.9, 32.8 }, { -96.8, 32.8 }, { -96.2, 32.3 }}; +cr::point point{-96.9, 32.79}; +auto pol = ruler.pointOnLine(line, point); +auto point = std::get<0>(pol); +std::clog << point.x << ", " << point.y; // -96.9, 32.8 (point) +std::clog << std::get<1>(pol); // 0 (index) +std::clog << std::get<2>(pol); // 0. (t) +``` + +#### `lineSlice(point start, point stop, const line_string& line)` + +Returns a part of the given line (`line_string`) between the start and the stop points (or their closest points on the line). + +```cpp +cr::line_string line{{ -96.9, 32.8 }, { -96.8, 32.8 }, { -96.2, 32.3 }}; +cr::point start_point{-96.9, 32.8}; +cr::point stop_point{-96.8, 32.8}; +auto slice = ruler.lineSlice(start_point, stop_point, line); +std::clog << slice[0].x << ", " << slice[0].y; // -96.9, 32.8 +std::clog << slice[1].x << ", " << slice[1].y; // -96.8, 32.8 +``` + +#### `lineSliceAlong(double start, double stop, const line_string& line)` + +Returns a part of the given line (`line_string`) between the start and the stop points indicated by distance along the line. + +```cpp +cr::line_string line{{ -96.9, 32.8 }, { -96.8, 32.8 }, { -96.2, 32.3 }}; +auto slice = ruler.lineSliceAlong(0.1, 1.2, line); +``` + +#### `bufferPoint(point p, double buffer)` + +Given a point, returns a bounding box object ([w, s, e, n]) created from the given point buffered by a given distance. + +```cpp +cr::point point{-96.9, 32.8}; +auto box = ruler.bufferPoint(point, 0.1); +``` + +#### `bufferBBox(box bbox, double buffer)` + +Given a bounding box, returns the box buffered by a given distance. + +```cpp +cr::box bbox({ 30, 38 }, { 40, 39 }); +auto bbox2 = ruler.bufferBBox(bbox, 1); +``` + +#### `insideBBox(point p, box bbox)` + +Returns true (`bool`) if the given point is inside in the given bounding box, otherwise false. + +```cpp +cr::box bbox({ 30, 38 }, { 40, 39 }); +auto inside = ruler.insideBBox({ 35, 38.5 }, bbox); +std::clog << inside; // true +``` + +# Develop + +```shell +# create targets +cmake . + +# build +make + +# test +./cheap_ruler + +# or just do it all in one! +cmake . && make && ./cheap_ruler +``` diff --git a/third_party/cheap-ruler-cpp-2.5.4/cmake/build.cmake b/third_party/cheap-ruler-cpp-2.5.4/cmake/build.cmake new file mode 100644 index 00000000000..79168336d6d --- /dev/null +++ b/third_party/cheap-ruler-cpp-2.5.4/cmake/build.cmake @@ -0,0 +1,11 @@ +# Generate source groups so the files are properly sorted in IDEs like Xcode. +function(create_source_groups target) + get_target_property(sources ${target} SOURCES) + foreach(file ${sources}) + get_filename_component(file "${file}" ABSOLUTE) + string(REGEX REPLACE "^${CMAKE_SOURCE_DIR}/" "" group "${file}") + get_filename_component(group "${group}" DIRECTORY) + string(REPLACE "/" "\\" group "${group}") + source_group("${group}" FILES "${file}") + endforeach() +endfunction() diff --git a/third_party/cheap-ruler-cpp-2.5.4/cmake/mason.cmake b/third_party/cheap-ruler-cpp-2.5.4/cmake/mason.cmake new file mode 100644 index 00000000000..bc31feeb5f2 --- /dev/null +++ b/third_party/cheap-ruler-cpp-2.5.4/cmake/mason.cmake @@ -0,0 +1,235 @@ +# Mason CMake + +include(CMakeParseArguments) + +function(mason_detect_platform) + # Determine platform + if(NOT MASON_PLATFORM) + # we call uname -s manually here since + # CMAKE_HOST_SYSTEM_NAME will not be defined before the project() call + execute_process( + COMMAND uname -s + OUTPUT_VARIABLE UNAME + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if (UNAME STREQUAL "Darwin") + set(MASON_PLATFORM "osx" PARENT_SCOPE) + else() + set(MASON_PLATFORM "linux" PARENT_SCOPE) + endif() + endif() + + # Determine platform version string + if(NOT MASON_PLATFORM_VERSION) + # Android Studio only passes ANDROID_ABI, but we need to adjust that to the Mason + if(MASON_PLATFORM STREQUAL "android" AND NOT MASON_PLATFORM_VERSION) + if (ANDROID_ABI STREQUAL "armeabi") + set(MASON_PLATFORM_VERSION "arm-v5-9" PARENT_SCOPE) + elseif (ANDROID_ABI STREQUAL "armeabi-v7a") + set(MASON_PLATFORM_VERSION "arm-v7-9" PARENT_SCOPE) + elseif (ANDROID_ABI STREQUAL "arm64-v8a") + set(MASON_PLATFORM_VERSION "arm-v8-21" PARENT_SCOPE) + elseif (ANDROID_ABI STREQUAL "x86") + set(MASON_PLATFORM_VERSION "x86-9" PARENT_SCOPE) + elseif (ANDROID_ABI STREQUAL "x86_64") + set(MASON_PLATFORM_VERSION "x86-64-21" PARENT_SCOPE) + elseif (ANDROID_ABI STREQUAL "mips") + set(MASON_PLATFORM_VERSION "mips-9" PARENT_SCOPE) + elseif (ANDROID_ABI STREQUAL "mips64") + set(MASON_PLATFORM_VERSION "mips-64-9" PARENT_SCOPE) + else() + message(FATAL_ERROR "Unknown ANDROID_ABI '${ANDROID_ABI}'.") + endif() + elseif(MASON_PLATFORM STREQUAL "ios") + set(MASON_PLATFORM_VERSION "8.0" PARENT_SCOPE) + else() + execute_process( + COMMAND uname -m + OUTPUT_VARIABLE MASON_PLATFORM_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(MASON_PLATFORM_VERSION "${MASON_PLATFORM_VERSION}" PARENT_SCOPE) + endif() + endif() +endfunction() + +function(mason_use _PACKAGE) + if(NOT _PACKAGE) + message(FATAL_ERROR "[Mason] No package name given") + endif() + + cmake_parse_arguments("" "HEADER_ONLY" "VERSION" "" ${ARGN}) + + if(_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "[Mason] mason_use() called with unrecognized arguments: ${_UNPARSED_ARGUMENTS}") + endif() + + if(NOT _VERSION) + message(FATAL_ERROR "[Mason] Specifying a version is required") + endif() + + if(MASON_PACKAGE_${_PACKAGE}_INVOCATION STREQUAL "${MASON_INVOCATION}") + # Check that the previous invocation of mason_use didn't select another version of this package + if(NOT MASON_PACKAGE_${_PACKAGE}_VERSION STREQUAL ${_VERSION}) + message(FATAL_ERROR "[Mason] Already using ${_PACKAGE} ${MASON_PACKAGE_${_PACKAGE}_VERSION}. Cannot select version ${_VERSION}.") + endif() + else() + if(_HEADER_ONLY) + set(_PLATFORM_ID "headers") + else() + set(_PLATFORM_ID "${MASON_PLATFORM}-${MASON_PLATFORM_VERSION}") + endif() + + set(_SLUG "${_PLATFORM_ID}/${_PACKAGE}/${_VERSION}") + set(_INSTALL_PATH "${MASON_PACKAGE_DIR}/${_SLUG}") + file(RELATIVE_PATH _INSTALL_PATH_RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${_INSTALL_PATH}") + + if(NOT EXISTS "${_INSTALL_PATH}") + set(_CACHE_PATH "${MASON_PACKAGE_DIR}/.binaries/${_SLUG}.tar.gz") + if (NOT EXISTS "${_CACHE_PATH}") + # Download the package + set(_URL "${MASON_REPOSITORY}/${_SLUG}.tar.gz") + message("[Mason] Downloading package ${_URL}...") + + set(_FAILED) + set(_ERROR) + # Note: some CMake versions are compiled without SSL support + get_filename_component(_CACHE_DIR "${_CACHE_PATH}" DIRECTORY) + file(MAKE_DIRECTORY "${_CACHE_DIR}") + execute_process( + COMMAND curl --retry 3 -s -f -S -L "${_URL}" -o "${_CACHE_PATH}.tmp" + RESULT_VARIABLE _FAILED + ERROR_VARIABLE _ERROR) + if(_FAILED) + message(FATAL_ERROR "[Mason] Failed to download ${_URL}: ${_ERROR}") + else() + # We downloaded to a temporary file to prevent half-finished downloads + file(RENAME "${_CACHE_PATH}.tmp" "${_CACHE_PATH}") + endif() + endif() + + # Unpack the package + message("[Mason] Unpacking package to ${_INSTALL_PATH_RELATIVE}...") + file(MAKE_DIRECTORY "${_INSTALL_PATH}") + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xzf "${_CACHE_PATH}" + WORKING_DIRECTORY "${_INSTALL_PATH}") + endif() + + # Error out if there is no config file. + if(NOT EXISTS "${_INSTALL_PATH}/mason.ini") + message(FATAL_ERROR "[Mason] Could not find mason.ini for package ${_PACKAGE} ${_VERSION}") + endif() + + set(MASON_PACKAGE_${_PACKAGE}_PREFIX "${_INSTALL_PATH}" CACHE STRING "${_PACKAGE} ${_INSTALL_PATH}" FORCE) + mark_as_advanced(MASON_PACKAGE_${_PACKAGE}_PREFIX) + + # Load the configuration from the ini file + file(STRINGS "${_INSTALL_PATH}/mason.ini" _CONFIG_FILE) + foreach(_LINE IN LISTS _CONFIG_FILE) + string(REGEX MATCH "^([a-z_]+) *= *" _KEY "${_LINE}") + if (_KEY) + string(LENGTH "${_KEY}" _KEY_LENGTH) + string(SUBSTRING "${_LINE}" ${_KEY_LENGTH} -1 _VALUE) + string(REGEX REPLACE ";.*$" "" _VALUE "${_VALUE}") # Trim trailing commas + string(REPLACE "{prefix}" "${_INSTALL_PATH}" _VALUE "${_VALUE}") + string(STRIP "${_VALUE}" _VALUE) + string(REPLACE "=" "" _KEY "${_KEY}") + string(STRIP "${_KEY}" _KEY) + string(TOUPPER "${_KEY}" _KEY) + if(_KEY STREQUAL "INCLUDE_DIRS" OR _KEY STREQUAL "STATIC_LIBS" ) + separate_arguments(_VALUE) + endif() + set(MASON_PACKAGE_${_PACKAGE}_${_KEY} "${_VALUE}" CACHE STRING "${_PACKAGE} ${_KEY}" FORCE) + mark_as_advanced(MASON_PACKAGE_${_PACKAGE}_${_KEY}) + endif() + endforeach() + + # Compare version in the package to catch errors early on + if(NOT _VERSION STREQUAL MASON_PACKAGE_${_PACKAGE}_VERSION) + message(FATAL_ERROR "[Mason] Package at ${_INSTALL_PATH_RELATIVE} has version '${MASON_PACKAGE_${_PACKAGE}_VERSION}', but required '${_VERSION}'") + endif() + + if(NOT _PACKAGE STREQUAL MASON_PACKAGE_${_PACKAGE}_NAME) + message(FATAL_ERROR "[Mason] Package at ${_INSTALL_PATH_RELATIVE} has name '${MASON_PACKAGE_${_PACKAGE}_NAME}', but required '${_NAME}'") + endif() + + if(NOT _HEADER_ONLY) + if(NOT MASON_PLATFORM STREQUAL MASON_PACKAGE_${_PACKAGE}_PLATFORM) + message(FATAL_ERROR "[Mason] Package at ${_INSTALL_PATH_RELATIVE} has platform '${MASON_PACKAGE_${_PACKAGE}_PLATFORM}', but required '${MASON_PLATFORM}'") + endif() + + if(NOT MASON_PLATFORM_VERSION STREQUAL MASON_PACKAGE_${_PACKAGE}_PLATFORM_VERSION) + message(FATAL_ERROR "[Mason] Package at ${_INSTALL_PATH_RELATIVE} has platform version '${MASON_PACKAGE_${_PACKAGE}_PLATFORM_VERSION}', but required '${MASON_PLATFORM_VERSION}'") + endif() + endif() + + # Concatenate the static libs and libraries + set(_LIBRARIES) + list(APPEND _LIBRARIES ${MASON_PACKAGE_${_PACKAGE}_STATIC_LIBS} ${MASON_PACKAGE_${_PACKAGE}_LDFLAGS}) + set(MASON_PACKAGE_${_PACKAGE}_LIBRARIES "${_LIBRARIES}" CACHE STRING "${_PACKAGE} _LIBRARIES" FORCE) + mark_as_advanced(MASON_PACKAGE_${_PACKAGE}_LIBRARIES) + + if(NOT _HEADER_ONLY) + string(REGEX MATCHALL "(^| +)-L *([^ ]+)" MASON_PACKAGE_${_PACKAGE}_LIBRARY_DIRS "${MASON_PACKAGE_${_PACKAGE}_LDFLAGS}") + string(REGEX REPLACE "(^| +)-L *" "\\1" MASON_PACKAGE_${_PACKAGE}_LIBRARY_DIRS "${MASON_PACKAGE_${_PACKAGE}_LIBRARY_DIRS}") + set(MASON_PACKAGE_${_PACKAGE}_LIBRARY_DIRS "${MASON_PACKAGE_${_PACKAGE}_LIBRARY_DIRS}" CACHE STRING "${_PACKAGE} ${MASON_PACKAGE_${_PACKAGE}_LIBRARY_DIRS}" FORCE) + mark_as_advanced(MASON_PACKAGE_${_PACKAGE}_LIBRARY_DIRS) + endif() + + # Store invocation ID to prevent different versions of the same package in one invocation + set(MASON_PACKAGE_${_PACKAGE}_INVOCATION "${MASON_INVOCATION}" CACHE INTERNAL "${_PACKAGE} invocation ID" FORCE) + endif() +endfunction() + +macro(target_add_mason_package _TARGET _VISIBILITY _PACKAGE) + if (NOT MASON_PACKAGE_${_PACKAGE}_INVOCATION) + message(FATAL_ERROR "[Mason] Package ${_PACKAGE} has not been initialized yet") + endif() + + target_include_directories(${_TARGET} ${_VISIBILITY} "${MASON_PACKAGE_${_PACKAGE}_INCLUDE_DIRS}") + target_compile_definitions(${_TARGET} ${_VISIBILITY} "${MASON_PACKAGE_${_PACKAGE}_DEFINITIONS}") + target_compile_options(${_TARGET} ${_VISIBILITY} "${MASON_PACKAGE_${_PACKAGE}_OPTIONS}") + target_link_libraries(${_TARGET} ${_VISIBILITY} "${MASON_PACKAGE_${_PACKAGE}_LIBRARIES}") +endmacro() + +# Setup + +string(RANDOM LENGTH 16 MASON_INVOCATION) + +# Read environment variables if CMake is run in command mode +if (CMAKE_ARGC) + set(MASON_PLATFORM "$ENV{MASON_PLATFORM}") + set(MASON_PLATFORM_VERSION "$ENV{MASON_PLATFORM_VERSION}") + set(MASON_PACKAGE_DIR "$ENV{MASON_PACKAGE_DIR}") + set(MASON_REPOSITORY "$ENV{MASON_REPOSITORY}") +endif() + +# Directory where Mason packages are located; typically ends with mason_packages +if (NOT MASON_PACKAGE_DIR) + set(MASON_PACKAGE_DIR "${CMAKE_SOURCE_DIR}/mason_packages") +endif() + +# URL prefix of where packages are located. +if (NOT MASON_REPOSITORY) + set(MASON_REPOSITORY "https://mason-binaries.s3.amazonaws.com") +endif() + +mason_detect_platform() + +# Execute commands if CMake is run in command mode +if (CMAKE_ARGC) + # Collect remaining arguments for passing to mason_use + set(_MASON_ARGS) + foreach(I RANGE 4 ${CMAKE_ARGC}) + list(APPEND _MASON_ARGS "${CMAKE_ARGV${I}}") + endforeach() + + # Install the package + mason_use(${_MASON_ARGS}) + + # Optionally print variables + if(DEFINED MASON_PACKAGE_${CMAKE_ARGV4}_${CMAKE_ARGV3}) + # CMake can't write to stdout with message() + execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${MASON_PACKAGE_${CMAKE_ARGV4}_${CMAKE_ARGV3}}") + endif() +endif() diff --git a/third_party/cheap-ruler-cpp-2.5.4/include/mapbox/cheap_ruler.hpp b/third_party/cheap-ruler-cpp-2.5.4/include/mapbox/cheap_ruler.hpp new file mode 100644 index 00000000000..d5ae7428b28 --- /dev/null +++ b/third_party/cheap-ruler-cpp-2.5.4/include/mapbox/cheap_ruler.hpp @@ -0,0 +1,354 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include + +namespace mapbox { +namespace cheap_ruler { + +using box = geometry::box; +using line_string = geometry::line_string; +using linear_ring = geometry::linear_ring; +using multi_line_string = geometry::multi_line_string; +using point = geometry::point; +using polygon = geometry::polygon; + +class CheapRuler { +public: + enum Unit { + Kilometers, + Miles, + NauticalMiles, + Meters, + Metres = Meters, + Yards, + Feet, + Inches + }; + + // + // A collection of very fast approximations to common geodesic measurements. Useful + // for performance-sensitive code that measures things on a city scale. Point coordinates + // are in the [x = longitude, y = latitude] form. + // + explicit CheapRuler(double latitude, Unit unit = Kilometers) { + double m = 0.; + + switch (unit) { + case Kilometers: + m = 1.; + break; + case Miles: + m = 1000. / 1609.344; + break; + case NauticalMiles: + m = 1000. / 1852.; + break; + case Meters: + m = 1000.; + break; + case Yards: + m = 1000. / 0.9144; + break; + case Feet: + m = 1000. / 0.3048; + break; + case Inches: + m = 1000. / 0.0254; + break; + } + + auto cos = std::cos(latitude * M_PI / 180.); + auto cos2 = 2. * cos * cos - 1.; + auto cos3 = 2. * cos * cos2 - cos; + auto cos4 = 2. * cos * cos3 - cos2; + auto cos5 = 2. * cos * cos4 - cos3; + + // multipliers for converting longitude and latitude + // degrees into distance (http://1.usa.gov/1Wb1bv7) + kx = m * (111.41513 * cos - 0.09455 * cos3 + 0.00012 * cos5); + ky = m * (111.13209 - 0.56605 * cos2 + 0.0012 * cos4); + } + + static CheapRuler fromTile(uint32_t y, uint32_t z) { + double n = M_PI * (1. - 2. * (y + 0.5) / std::pow(2., z)); + double latitude = std::atan(0.5 * (std::exp(n) - std::exp(-n))) * 180. / M_PI; + + return CheapRuler(latitude); + } + + // + // Given two points of the form [x = longitude, y = latitude], returns the distance. + // + double distance(point a, point b) { + auto dx = (a.x - b.x) * kx; + auto dy = (a.y - b.y) * ky; + + return std::sqrt(dx * dx + dy * dy); + } + + // + // Returns the bearing between two points in angles. + // + double bearing(point a, point b) { + auto dx = (b.x - a.x) * kx; + auto dy = (b.y - a.y) * ky; + + if (!dx && !dy) { + return 0.; + } + + auto value = std::atan2(dx, dy) * 180. / M_PI; + + if (value > 180.) { + value -= 360.; + } + + return value; + } + + // + // Returns a new point given distance and bearing from the starting point. + // + point destination(point origin, double dist, double bearing_) { + auto a = (90. - bearing_) * M_PI / 180.; + + return offset(origin, std::cos(a) * dist, std::sin(a) * dist); + } + + // + // Returns a new point given easting and northing offsets from the starting point. + // + point offset(point origin, double dx, double dy) { + return point(origin.x + dx / kx, origin.y + dy / ky); + } + + // + // Given a line (an array of points), returns the total line distance. + // + double lineDistance(const line_string& points) { + double total = 0.; + + for (unsigned i = 0; i < points.size() - 1; ++i) { + total += distance(points[i], points[i + 1]); + } + + return total; + } + + // + // Given a polygon (an array of rings, where each ring is an array of points), + // returns the area. + // + double area(polygon poly) { + double sum = 0.; + + for (unsigned i = 0; i < poly.size(); ++i) { + auto& ring = poly[i]; + + for (unsigned j = 0, len = ring.size(), k = len - 1; j < len; k = j++) { + sum += (ring[j].x - ring[k].x) * (ring[j].y + ring[k].y) * (i ? -1. : 1.); + } + } + + return (std::abs(sum) / 2.) * kx * ky; + } + + // + // Returns the point at a specified distance along the line. + // + point along(const line_string& line, double dist) { + double sum = 0.; + + if (dist <= 0.) { + return line[0]; + } + + for (unsigned i = 0; i < line.size() - 1; ++i) { + auto p0 = line[i]; + auto p1 = line[i + 1]; + auto d = distance(p0, p1); + + sum += d; + + if (sum > dist) { + return interpolate(p0, p1, (dist - (sum - d)) / d); + } + } + + return line[line.size() - 1]; + } + + // + // Returns a tuple of the form where point is closest point on the line + // from the given point, index is the start index of the segment with the closest point, + // and t is a parameter from 0 to 1 that indicates where the closest point is on that segment. + // + std::tuple pointOnLine(const line_string& line, point p) { + double minDist = std::numeric_limits::infinity(); + double minX = 0., minY = 0., minI = 0., minT = 0.; + + for (unsigned i = 0; i < line.size() - 1; ++i) { + auto t = 0.; + auto x = line[i].x; + auto y = line[i].y; + auto dx = (line[i + 1].x - x) * kx; + auto dy = (line[i + 1].y - y) * ky; + + if (dx != 0. || dy != 0.) { + t = ((p.x - x) * kx * dx + (p.y - y) * ky * dy) / (dx * dx + dy * dy); + + if (t > 1) { + x = line[i + 1].x; + y = line[i + 1].y; + + } else if (t > 0) { + x += (dx / kx) * t; + y += (dy / ky) * t; + } + } + + dx = (p.x - x) * kx; + dy = (p.y - y) * ky; + + auto sqDist = dx * dx + dy * dy; + + if (sqDist < minDist) { + minDist = sqDist; + minX = x; + minY = y; + minI = i; + minT = t; + } + } + + return std::make_tuple( + point(minX, minY), minI, ::fmax(0., ::fmin(1., minT))); + } + + // + // Returns a part of the given line between the start and the stop points (or their closest + // points on the line). + // + line_string lineSlice(point start, point stop, const line_string& line) { + auto getPoint = [](auto tuple) { return std::get<0>(tuple); }; + auto getIndex = [](auto tuple) { return std::get<1>(tuple); }; + auto getT = [](auto tuple) { return std::get<2>(tuple); }; + + auto p1 = pointOnLine(line, start); + auto p2 = pointOnLine(line, stop); + + if (getIndex(p1) > getIndex(p2) || (getIndex(p1) == getIndex(p2) && getT(p1) > getT(p2))) { + auto tmp = p1; + p1 = p2; + p2 = tmp; + } + + line_string slice = { getPoint(p1) }; + + auto l = getIndex(p1) + 1; + auto r = getIndex(p2); + + if (line[l] != slice[0] && l <= r) { + slice.push_back(line[l]); + } + + for (unsigned i = l + 1; i <= r; ++i) { + slice.push_back(line[i]); + } + + if (line[r] != getPoint(p2)) { + slice.push_back(getPoint(p2)); + } + + return slice; + }; + + // + // Returns a part of the given line between the start and the stop points + // indicated by distance along the line. + // + line_string lineSliceAlong(double start, double stop, const line_string& line) { + double sum = 0.; + line_string slice; + + for (unsigned i = 0; i < line.size() - 1; ++i) { + auto p0 = line[i]; + auto p1 = line[i + 1]; + auto d = distance(p0, p1); + + sum += d; + + if (sum > start && slice.size() == 0) { + slice.push_back(interpolate(p0, p1, (start - (sum - d)) / d)); + } + + if (sum >= stop) { + slice.push_back(interpolate(p0, p1, (stop - (sum - d)) / d)); + return slice; + } + + if (sum > start) { + slice.push_back(p1); + } + } + + return slice; + }; + + // + // Given a point, returns a bounding box object ([w, s, e, n]) + // created from the given point buffered by a given distance. + // + box bufferPoint(point p, double buffer) { + auto v = buffer / ky; + auto h = buffer / kx; + + return box( + point(p.x - h, p.y - v), + point(p.x + h, p.y + v) + ); + } + + // + // Given a bounding box, returns the box buffered by a given distance. + // + box bufferBBox(box bbox, double buffer) { + auto v = buffer / ky; + auto h = buffer / kx; + + return box( + point(bbox.min.x - h, bbox.min.y - v), + point(bbox.max.x + h, bbox.max.y + v) + ); + } + + // + // Returns true if the given point is inside in the given bounding box, otherwise false. + // + bool insideBBox(point p, box bbox) { + return p.x >= bbox.min.x && + p.x <= bbox.max.x && + p.y >= bbox.min.y && + p.y <= bbox.max.y; + } + + static point interpolate(point a, point b, double t) { + double dx = b.x - a.x; + double dy = b.y - a.y; + + return point(a.x + dx * t, a.y + dy * t); + } + +private: + double ky; + double kx; +}; + +} // namespace cheap_ruler +} // namespace mapbox diff --git a/third_party/cheap-ruler-cpp-2.5.4/test/cheap_ruler.cpp b/third_party/cheap-ruler-cpp-2.5.4/test/cheap_ruler.cpp new file mode 100644 index 00000000000..0ac73c81fb0 --- /dev/null +++ b/third_party/cheap-ruler-cpp-2.5.4/test/cheap_ruler.cpp @@ -0,0 +1,200 @@ +#include +#include + +#include "fixtures/lines.hpp" +#include "fixtures/turf.hpp" + +namespace cr = mapbox::cheap_ruler; + +class CheapRulerTest : public ::testing::Test { +protected: + cr::CheapRuler ruler = cr::CheapRuler(32.8351); + cr::CheapRuler milesRuler = cr::CheapRuler(32.8351, cr::CheapRuler::Miles); +}; + +void assertErr(double expected, double actual, double maxError) { + // Add a negligible fraction to make sure we + // don't divide by zero. + double error = std::abs((actual - expected) / + (expected == 0. ? expected + 0.000001 : expected)); + + if (error > maxError) { + FAIL() << "expected is " << expected << " but got " << actual; + } +} + +TEST_F(CheapRulerTest, distance) { + for (unsigned i = 0; i < points.size() - 1; ++i) { + auto expected = turf_distance[i]; + auto actual = ruler.distance(points[i], points[i + 1]); + + assertErr(expected, actual, .003); + } +} + +TEST_F(CheapRulerTest, distanceInMiles) { + auto d = ruler.distance({ 30.5, 32.8351 }, { 30.51, 32.8451 }); + auto d2 = milesRuler.distance({ 30.5, 32.8351 }, { 30.51, 32.8451 }); + + assertErr(d / d2, 1.609344, 1e-12); +} + +TEST_F(CheapRulerTest, bearing) { + for (unsigned i = 0; i < points.size() - 1; ++i) { + auto expected = turf_bearing[i]; + auto actual = ruler.bearing(points[i], points[i + 1]); + + assertErr(expected, actual, .005); + } +} + +TEST_F(CheapRulerTest, destination) { + for (unsigned i = 0; i < points.size(); ++i) { + auto bearing = (i % 360) - 180.; + auto expected = turf_destination[i]; + auto actual = ruler.destination(points[i], 1.0, bearing); + + assertErr(expected.x, actual.x, 1e-6); // longitude + assertErr(expected.y, actual.y, 1e-6); // latitude + } +} + +TEST_F(CheapRulerTest, lineDistance) { + for (unsigned i = 0; i < lines.size(); ++i) { + auto expected = turf_lineDistance[i]; + auto actual = ruler.lineDistance(lines[i]); + + assertErr(expected, actual, 0.003); + } +} + +TEST_F(CheapRulerTest, area) { + for (unsigned i = 0, j = 0; i < lines.size(); ++i) { + if (lines[i].size() < 3) { + continue; + } + + cr::linear_ring ring; + for (auto point : lines[i]) { + ring.push_back(point); + } + ring.push_back(lines[i][0]); + + auto expected = turf_area[j++]; + auto actual = ruler.area(cr::polygon{ ring }); + + assertErr(expected, actual, 0.003); + } +} + +TEST_F(CheapRulerTest, along) { + for (unsigned i = 0; i < lines.size(); ++i) { + auto expected = turf_along[i]; + auto actual = ruler.along(lines[i], turf_along_dist[i]); + + assertErr(expected.x, actual.x, 1e-6); // along longitude + assertErr(expected.y, actual.y, 1e-6); // along latitude + } +} + +TEST_F(CheapRulerTest, alongWithDist) { + ASSERT_EQ(ruler.along(lines[0], -5), lines[0][0]); +} + +TEST_F(CheapRulerTest, alongWithDistGreaterThanLength) { + ASSERT_EQ(ruler.along(lines[0], 1000), lines[0][lines[0].size() - 1]); +} + +TEST_F(CheapRulerTest, pointOnLine) { + // not Turf comparison because pointOnLine is bugged https://github.com/Turfjs/turf/issues/344 + cr::line_string line = {{ -77.031669, 38.878605 }, { -77.029609, 38.881946 }}; + auto result = ruler.pointOnLine(line, { -77.034076, 38.882017 }); + + ASSERT_EQ(std::get<0>(result), cr::point(-77.03052697027461, 38.880457194811896)); // point + ASSERT_EQ(std::get<1>(result), 0u); // index + ASSERT_EQ(std::get<2>(result), 0.5543833618360235); // t + + ASSERT_EQ(std::get<2>(ruler.pointOnLine(line, { -80., 38. })), 0.) << "t is not less than 0"; + ASSERT_EQ(std::get<2>(ruler.pointOnLine(line, { -75., 38. })), 1.) << "t is not bigger than 1"; +} + +TEST_F(CheapRulerTest, lineSlice) { + for (unsigned i = 0; i < lines.size(); ++i) { + auto line = lines[i]; + auto dist = ruler.lineDistance(line); + auto start = ruler.along(line, dist * 0.3); + auto stop = ruler.along(line, dist * 0.7); + auto expected = turf_lineSlice[i]; + auto actual = ruler.lineDistance(ruler.lineSlice(start, stop, line)); + + assertErr(expected, actual, 1e-5); + } +} + +TEST_F(CheapRulerTest, lineSliceAlong) { + for (unsigned i = 0; i < lines.size(); ++i) { + if (i == 46) { + // skip due to Turf bug https://github.com/Turfjs/turf/issues/351 + continue; + }; + + auto line = lines[i]; + auto dist = ruler.lineDistance(line); + auto expected = turf_lineSlice[i]; + auto actual = ruler.lineDistance(ruler.lineSliceAlong(dist * 0.3, dist * 0.7, line)); + + assertErr(expected, actual, 1e-5); + } +} + +TEST_F(CheapRulerTest, lineSliceReverse) { + auto line = lines[0]; + auto dist = ruler.lineDistance(line); + auto start = ruler.along(line, dist * 0.7); + auto stop = ruler.along(line, dist * 0.3); + auto actual = ruler.lineDistance(ruler.lineSlice(start, stop, line)); + + ASSERT_EQ(actual, 0.018676802802910702); +} + +TEST_F(CheapRulerTest, bufferPoint) { + for (unsigned i = 0; i < points.size(); ++i) { + auto expected = turf_bufferPoint[i]; + auto actual = milesRuler.bufferPoint(points[i], 0.1); + + assertErr(expected.min.x, actual.min.x, 2e-7); + assertErr(expected.min.x, actual.min.x, 2e-7); + assertErr(expected.max.y, actual.max.y, 2e-7); + assertErr(expected.max.y, actual.max.y, 2e-7); + } +} + +TEST_F(CheapRulerTest, bufferBBox) { + cr::box bbox({ 30, 38 }, { 40, 39 }); + cr::box bbox2 = ruler.bufferBBox(bbox, 1); + + ASSERT_EQ(bbox2, cr::box({ 29.989319515875376, 37.99098271225711 }, { 40.01068048412462, 39.00901728774289 })); +} + +TEST_F(CheapRulerTest, insideBBox) { + cr::box bbox({ 30, 38 }, { 40, 39 }); + + ASSERT_TRUE(ruler.insideBBox({ 35, 38.5 }, bbox)); + ASSERT_FALSE(ruler.insideBBox({ 45, 45 }, bbox)); +} + +TEST_F(CheapRulerTest, fromTile) { + auto ruler1 = cr::CheapRuler(50.5); + auto ruler2 = cr::CheapRuler::fromTile(11041, 15); + + cr::point p1(30.5, 50.5); + cr::point p2(30.51, 50.51); + + assertErr(ruler1.distance(p1, p2), ruler2.distance(p1, p2), 2e-5); +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +} diff --git a/third_party/cheap-ruler-cpp-2.5.4/test/fixtures/lines.hpp b/third_party/cheap-ruler-cpp-2.5.4/test/fixtures/lines.hpp new file mode 100644 index 00000000000..d2ec79d3435 --- /dev/null +++ b/third_party/cheap-ruler-cpp-2.5.4/test/fixtures/lines.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace cr = mapbox::cheap_ruler; + +static const cr::multi_line_string lines = {{{ -96.920341, 32.838261 }, { -96.920421, 32.838295 }, { -96.920421, 32.838295 }, { -96.920536, 32.838297 }, { -96.920684, 32.838293 }, { -96.920818, 32.838342 }}, {{ -96.920349, 32.838306 }, { -96.920421, 32.838295 }}, {{ -96.919874, 32.837479 }, { -96.920097, 32.837684 }, { -96.92018, 32.837844 }, { -96.92029, 32.838216 }, { -96.920341, 32.838261 }}, {{ -96.915781, 32.834689 }, { -96.915735, 32.834529 }, { -96.91573, 32.834443 }, { -96.915733, 32.834286 }, { -96.915853, 32.8337 }}, {{ -96.915092, 32.836889 }, { -96.915915, 32.836977 }}, {{ -96.914617, 32.83752 }, { -96.914507, 32.838106 }, { -96.914319, 32.839063 }}, {{ -96.915671, 32.833443 }, { -96.915427, 32.833817 }, { -96.91532, 32.833963 }, { -96.915247, 32.834072 }, { -96.915062, 32.834252 }, { -96.914775, 32.834518 }}, {{ -96.9104, 32.837119 }, { -96.910567, 32.837069 }, { -96.9111, 32.836941 }}, {{ -96.91441, 32.836582 }, { -96.914225, 32.836544 }, { -96.914158, 32.836499 }, { -96.914107, 32.836449 }, { -96.914075, 32.836393 }, { -96.914059, 32.836292 }, { -96.914091, 32.836073 }, { -96.914649, 32.834919 }, { -96.914837, 32.834601 }, { -96.914858, 32.834583 }, { -96.914912, 32.834563 }, { -96.914968, 32.834561 }, { -96.91503, 32.83457 }, { -96.915081, 32.834592 }, { -96.915116, 32.834628 }, { -96.915134, 32.834671 }, { -96.91514, 32.834718 }, { -96.915124, 32.834793 }, { -96.914931, 32.835336 }, { -96.914888, 32.835509 }, { -96.91481, 32.835911 }}, {{ -96.914155, 32.836758 }, { -96.913391, 32.836697 }, { -96.912991, 32.836643 }, { -96.912847, 32.836589 }, { -96.912761, 32.836508 }, { -96.912573, 32.836433 }}, {{ -96.917377, 32.837281 }, { -96.917589, 32.837317 }, { -96.918117, 32.837339 }}, {{ -96.920815, 32.836594 }, { -96.919732, 32.836643 }, { -96.918975, 32.836702 }, { -96.918077, 32.836729 }, { -96.916661, 32.83672 }, { -96.916358, 32.836774 }}, {{ -96.911543, 32.836925 }, { -96.911806, 32.837006 }, { -96.911994, 32.837028 }, { -96.912326, 32.837114 }, { -96.912552, 32.837202 }, { -96.912656, 32.83729 }}, {{ -96.914657, 32.836659 }, { -96.914518, 32.837522 }, { -96.914472, 32.837673 }, { -96.914383, 32.837772 }, { -96.914284, 32.837858 }, { -96.914153, 32.837905 }, { -96.914024, 32.837912 }, { -96.913925, 32.837885 }, { -96.913804, 32.837828 }, { -96.913678, 32.837729 }, { -96.913391, 32.837479 }, { -96.913278, 32.837328 }, { -96.913252, 32.837238 }, { -96.913262, 32.837148 }, { -96.913305, 32.837078 }, { -96.91337, 32.837024 }, { -96.91348, 32.837004 }, { -96.914483, 32.83688 }}, {{ -96.915915, 32.836977 }, { -96.916183, 32.837004 }, { -96.916425, 32.837042 }, { -96.916862, 32.837164 }}, {{ -96.915183, 32.840102 }, { -96.915151, 32.839929 }, { -96.915113, 32.839539 }, { -96.915008, 32.838973 }, { -96.914949, 32.83873 }, { -96.914909, 32.838491 }, { -96.914834, 32.838234 }}, {{ -96.914728, 32.842674 }, { -96.914772, 32.84257 }, { -96.914872, 32.842277 }, { -96.914974, 32.841939 }, { -96.915014, 32.841646 }, { -96.915065, 32.84138 }, { -96.915113, 32.84099 }, { -96.915175, 32.840321 }, { -96.915193, 32.839827 }, { -96.915204, 32.839345 }, { -96.91525, 32.839045 }, { -96.915325, 32.838759 }, { -96.915483, 32.838464 }, { -96.915658, 32.838236 }, { -96.915907, 32.837943 }, { -96.91621, 32.837709 }, { -96.91636, 32.837612 }, { -96.916588, 32.837481 }, { -96.916948, 32.837324 }, { -96.91731, 32.837188 }, { -96.918026, 32.837098 }, { -96.918847, 32.83706 }, { -96.919391, 32.83704 }, { -96.919847, 32.83701 }, { -96.920174, 32.836961 }}, {{ -96.914603, 32.839688 }, { -96.914335, 32.841087 }, { -96.914099, 32.841896 }, { -96.913823, 32.842577 }, { -96.91377, 32.842674 }}, {{ -96.915915, 32.836977 }, { -96.916105, 32.837042 }, { -96.916183, 32.837116 }, { -96.916218, 32.837164 }, { -96.916232, 32.83722 }, { -96.916223, 32.837308 }, { -96.916202, 32.837355 }, { -96.916006, 32.837556 }, { -96.915714, 32.837779 }, { -96.915588, 32.83784 }, { -96.915419, 32.837871 }, { -96.915293, 32.837867 }, { -96.91514, 32.837828 }, { -96.915062, 32.837774 }, { -96.915014, 32.837734 }, { -96.914925, 32.837614 }, { -96.914888, 32.837515 }, { -96.914831, 32.837297 }}, {{ -96.917743, 32.833443 }, { -96.917766, 32.836553 }}, {{ -96.912399, 32.842674 }, { -96.911487, 32.841373 }, { -96.9104, 32.841399 }}, {{ -96.91072, 32.84264 }, { -96.910717, 32.842674 }}, {{ -96.911584, 32.833443 }, { -96.911581, 32.833684 }, { -96.911559, 32.835271 }, { -96.911554, 32.83642 }}, {{ -96.920403, 32.833443 }, { -96.920397, 32.833894 }}, {{ -96.9104, 32.833662 }, { -96.911581, 32.833684 }}, {{ -96.914775, 32.834518 }, { -96.914512, 32.835038 }, { -96.914327, 32.835437 }, { -96.914016, 32.836136 }, { -96.913973, 32.83621 }, { -96.913906, 32.83628 }, { -96.913769, 32.836359 }, { -96.913675, 32.836384 }, { -96.913203, 32.836445 }}, {{ -96.9104, 32.837231 }, { -96.910695, 32.837202 }, { -96.911025, 32.837182 }, { -96.911355, 32.837168 }, { -96.911948, 32.837168 }, { -96.912391, 32.837222 }, { -96.912656, 32.83729 }, { -96.913072, 32.83752 }}, {{ -96.916189, 32.83818 }, { -96.918117, 32.837339 }}, {{ -96.918165, 32.84179 }, { -96.917329, 32.840988 }, { -96.91702, 32.840704 }, { -96.916811, 32.840587 }, { -96.916661, 32.840519 }, { -96.916368, 32.840454 }, { -96.916164, 32.840438 }, { -96.915263, 32.840458 }}, {{ -96.914137, 32.840553 }, { -96.914316, 32.840555 }}, {{ -96.91415, 32.840452 }, { -96.914054, 32.841182 }, { -96.913976, 32.841572 }, { -96.913842, 32.842049 }, { -96.913691, 32.842414 }, { -96.913569, 32.842674 }}, {{ -96.914919, 32.842674 }, { -96.91492, 32.842671 }, { -96.9151, 32.842171 }, { -96.915244, 32.84152 }, { -96.915322, 32.840979 }, { -96.915376, 32.840569 }, { -96.915384, 32.840454 }}, {{ -96.915474, 32.833443 }, { -96.915379, 32.833664 }, { -96.915314, 32.833772 }, { -96.915261, 32.833849 }, { -96.915081, 32.834083 }, { -96.914775, 32.834518 }}, {{ -96.913072, 32.83752 }, { -96.913195, 32.837608 }, { -96.913675, 32.838002 }, { -96.913694, 32.838011 }, { -96.91396, 32.838241 }, { -96.914054, 32.838345 }, { -96.914161, 32.838507 }, { -96.914255, 32.838714 }, { -96.914292, 32.83889 }, { -96.914319, 32.839063 }, { -96.914182, 32.840098 }, { -96.91415, 32.840452 }}, {{ -96.917406, 32.836557 }, { -96.91588, 32.836517 }, { -96.915778, 32.836501 }, { -96.915727, 32.836481 }, { -96.91569, 32.836458 }, { -96.915644, 32.836422 }, { -96.915609, 32.836382 }, { -96.915588, 32.836348 }, { -96.915572, 32.836305 }, { -96.915564, 32.836235 }, { -96.915564, 32.836154 }, { -96.915668, 32.835469 }, { -96.915754, 32.834827 }, { -96.915781, 32.834689 }, { -96.915835, 32.834556 }, { -96.916052, 32.834074 }, { -96.916283, 32.833443 }}, {{ -96.915384, 32.840454 }, { -96.915408, 32.839794 }, { -96.915411, 32.839345 }, { -96.915459, 32.839068 }, { -96.91554, 32.838845 }, { -96.915636, 32.838687 }, { -96.915765, 32.838529 }, { -96.915945, 32.838358 }, { -96.916189, 32.83818 }}, {{ -96.919421, 32.837159 }, { -96.919557, 32.837216 }, { -96.919697, 32.837288 }, { -96.919812, 32.8374 }, { -96.919874, 32.837479 }, { -96.920172, 32.838358 }, { -96.920295, 32.838845 }, { -96.920333, 32.839068 }, { -96.920327, 32.839422 }, { -96.920223, 32.839746 }, { -96.920072, 32.840046 }, { -96.919898, 32.840276 }, { -96.919812, 32.840355 }, { -96.919426, 32.84067 }, { -96.918012, 32.84172 }, { -96.91753, 32.84207 }, { -96.917374, 32.842196 }, { -96.916727, 32.842674 }}, {{ -96.916981, 32.842674 }, { -96.917079, 32.842602 }, { -96.917487, 32.842291 }, { -96.918114, 32.841826 }, { -96.919984, 32.840454 }, { -96.920236, 32.840233 }, { -96.920429, 32.839965 }, { -96.920512, 32.839816 }, { -96.92059, 32.839557 }, { -96.920612, 32.839271 }, { -96.920604, 32.839181 }, { -96.920574, 32.839043 }, { -96.920416, 32.83857 }, { -96.920365, 32.83839 }, { -96.920341, 32.838261 }, { -96.9203, 32.838119 }, { -96.920282, 32.837943 }, { -96.920274, 32.83775 }, { -96.920295, 32.837603 }, { -96.920319, 32.837536 }, { -96.920397, 32.837407 }, { -96.920515, 32.837288 }, { -96.920601, 32.837227 }, { -96.920727, 32.83717 }}, {{ -96.91441, 32.836582 }, { -96.914188, 32.836571 }, { -96.913203, 32.836445 }}, {{ -96.914324, 32.840454 }, { -96.91415, 32.840452 }}, {{ -96.921387, 32.836595 }, { -96.920815, 32.836594 }, { -96.917766, 32.836553 }, { -96.917406, 32.836557 }, { -96.915851, 32.836621 }, { -96.915459, 32.836621 }, { -96.915129, 32.836607 }}, {{ -96.918117, 32.837339 }, { -96.918324, 32.837252 }, { -96.918586, 32.837186 }, { -96.918844, 32.837161 }, { -96.919421, 32.837159 }, { -96.920727, 32.83717 }, { -96.921387, 32.83717 }}, {{ -96.913203, 32.836445 }, { -96.913142, 32.836438 }, { -96.912999, 32.836438 }, { -96.912774, 32.836427 }, { -96.912573, 32.836433 }, { -96.911554, 32.83642 }, { -96.9104, 32.836416 }}, {{ -96.915253, 32.840564 }, { -96.915376, 32.840569 }, { -96.915816, 32.840562 }, { -96.916197, 32.840567 }, { -96.916478, 32.840598 }, { -96.916623, 32.840641 }, { -96.916757, 32.840702 }, { -96.916913, 32.840794 }, { -96.917326, 32.841157 }, { -96.917452, 32.841272 }, { -96.917956, 32.841761 }, { -96.918061, 32.841867 }}, {{ -96.9145, 32.842674 }, { -96.914547, 32.842534 }, { -96.914708, 32.841971 }, { -96.914802, 32.841473 }, { -96.914858, 32.841078 }, { -96.914882, 32.840742 }, { -96.914907, 32.840224 }, { -96.914915, 32.839706 }, { -96.914885, 32.839084 }, { -96.914826, 32.83811 }, { -96.914831, 32.837297 }}, {{ -96.914987, 32.836886 }, { -96.915092, 32.836889 }}, {{ -96.914526, 32.836763 }, { -96.914155, 32.836758 }, { -96.9104, 32.836758 }}, {{ -96.921387, 32.836813 }, { -96.918825, 32.836796 }, { -96.916358, 32.836774 }, { -96.915003, 32.836767 }}, {{ -96.914831, 32.837297 }, { -96.914872, 32.836663 }, { -96.915033, 32.835872 }, { -96.91514, 32.83546 }, { -96.915226, 32.835212 }, { -96.915853, 32.8337 }, { -96.91595, 32.833443 }}, {{ -96.915092, 32.836889 }, { -96.916398, 32.836891 }, { -96.919547, 32.836963 }, { -96.921322, 32.836952 }, { -96.921387, 32.836952 }}, {{ -96.9104, 32.837008 }, { -96.910671, 32.836977 }, { -96.9111, 32.836941 }, { -96.911543, 32.836925 }, { -96.912637, 32.836898 }, { -96.913501, 32.836886 }, { -96.914528, 32.83688 }}, {{ -96.91577, 32.833443 }, { -96.915671, 32.833693 }, { -96.915344, 32.834518 }, { -96.91481, 32.835911 }, { -96.914754, 32.836127 }, { -96.914657, 32.836659 }, { -96.914617, 32.83752 }, { -96.914595, 32.838561 }, { -96.914603, 32.839688 }, { -96.914587, 32.840693 }, { -96.914512, 32.841211 }, { -96.914421, 32.841666 }, { -96.914284, 32.842196 }, { -96.914097, 32.842674 }}, {{ -96.914316, 32.840555 }, { -96.915253, 32.840564 }}, {{ -96.916862, 32.837164 }, { -96.917377, 32.837281 }}, {{ -96.915129, 32.836607 }, { -96.91441, 32.836582 }}, {{ -96.915263, 32.840458 }, { -96.914324, 32.840454 }}, {{ -96.914528, 32.83688 }, { -96.914987, 32.836886 }}, {{ -96.915003, 32.836767 }, { -96.914526, 32.836763 }}}; +static const cr::line_string points = {{ -96.920341, 32.838261 }, { -96.920421, 32.838295 }, { -96.920421, 32.838295 }, { -96.920536, 32.838297 }, { -96.920684, 32.838293 }, { -96.920818, 32.838342 }, { -96.920349, 32.838306 }, { -96.920421, 32.838295 }, { -96.919874, 32.837479 }, { -96.920097, 32.837684 }, { -96.92018, 32.837844 }, { -96.92029, 32.838216 }, { -96.920341, 32.838261 }, { -96.915781, 32.834689 }, { -96.915735, 32.834529 }, { -96.91573, 32.834443 }, { -96.915733, 32.834286 }, { -96.915853, 32.8337 }, { -96.915092, 32.836889 }, { -96.915915, 32.836977 }, { -96.914617, 32.83752 }, { -96.914507, 32.838106 }, { -96.914319, 32.839063 }, { -96.915671, 32.833443 }, { -96.915427, 32.833817 }, { -96.91532, 32.833963 }, { -96.915247, 32.834072 }, { -96.915062, 32.834252 }, { -96.914775, 32.834518 }, { -96.9104, 32.837119 }, { -96.910567, 32.837069 }, { -96.9111, 32.836941 }, { -96.91441, 32.836582 }, { -96.914225, 32.836544 }, { -96.914158, 32.836499 }, { -96.914107, 32.836449 }, { -96.914075, 32.836393 }, { -96.914059, 32.836292 }, { -96.914091, 32.836073 }, { -96.914649, 32.834919 }, { -96.914837, 32.834601 }, { -96.914858, 32.834583 }, { -96.914912, 32.834563 }, { -96.914968, 32.834561 }, { -96.91503, 32.83457 }, { -96.915081, 32.834592 }, { -96.915116, 32.834628 }, { -96.915134, 32.834671 }, { -96.91514, 32.834718 }, { -96.915124, 32.834793 }, { -96.914931, 32.835336 }, { -96.914888, 32.835509 }, { -96.91481, 32.835911 }, { -96.914155, 32.836758 }, { -96.913391, 32.836697 }, { -96.912991, 32.836643 }, { -96.912847, 32.836589 }, { -96.912761, 32.836508 }, { -96.912573, 32.836433 }, { -96.917377, 32.837281 }, { -96.917589, 32.837317 }, { -96.918117, 32.837339 }, { -96.920815, 32.836594 }, { -96.919732, 32.836643 }, { -96.918975, 32.836702 }, { -96.918077, 32.836729 }, { -96.916661, 32.83672 }, { -96.916358, 32.836774 }, { -96.911543, 32.836925 }, { -96.911806, 32.837006 }, { -96.911994, 32.837028 }, { -96.912326, 32.837114 }, { -96.912552, 32.837202 }, { -96.912656, 32.83729 }, { -96.914657, 32.836659 }, { -96.914518, 32.837522 }, { -96.914472, 32.837673 }, { -96.914383, 32.837772 }, { -96.914284, 32.837858 }, { -96.914153, 32.837905 }, { -96.914024, 32.837912 }, { -96.913925, 32.837885 }, { -96.913804, 32.837828 }, { -96.913678, 32.837729 }, { -96.913391, 32.837479 }, { -96.913278, 32.837328 }, { -96.913252, 32.837238 }, { -96.913262, 32.837148 }, { -96.913305, 32.837078 }, { -96.91337, 32.837024 }, { -96.91348, 32.837004 }, { -96.914483, 32.83688 }, { -96.915915, 32.836977 }, { -96.916183, 32.837004 }, { -96.916425, 32.837042 }, { -96.916862, 32.837164 }, { -96.915183, 32.840102 }, { -96.915151, 32.839929 }, { -96.915113, 32.839539 }, { -96.915008, 32.838973 }, { -96.914949, 32.83873 }, { -96.914909, 32.838491 }, { -96.914834, 32.838234 }, { -96.914728, 32.842674 }, { -96.914772, 32.84257 }, { -96.914872, 32.842277 }, { -96.914974, 32.841939 }, { -96.915014, 32.841646 }, { -96.915065, 32.84138 }, { -96.915113, 32.84099 }, { -96.915175, 32.840321 }, { -96.915193, 32.839827 }, { -96.915204, 32.839345 }, { -96.91525, 32.839045 }, { -96.915325, 32.838759 }, { -96.915483, 32.838464 }, { -96.915658, 32.838236 }, { -96.915907, 32.837943 }, { -96.91621, 32.837709 }, { -96.91636, 32.837612 }, { -96.916588, 32.837481 }, { -96.916948, 32.837324 }, { -96.91731, 32.837188 }, { -96.918026, 32.837098 }, { -96.918847, 32.83706 }, { -96.919391, 32.83704 }, { -96.919847, 32.83701 }, { -96.920174, 32.836961 }, { -96.914603, 32.839688 }, { -96.914335, 32.841087 }, { -96.914099, 32.841896 }, { -96.913823, 32.842577 }, { -96.91377, 32.842674 }, { -96.915915, 32.836977 }, { -96.916105, 32.837042 }, { -96.916183, 32.837116 }, { -96.916218, 32.837164 }, { -96.916232, 32.83722 }, { -96.916223, 32.837308 }, { -96.916202, 32.837355 }, { -96.916006, 32.837556 }, { -96.915714, 32.837779 }, { -96.915588, 32.83784 }, { -96.915419, 32.837871 }, { -96.915293, 32.837867 }, { -96.91514, 32.837828 }, { -96.915062, 32.837774 }, { -96.915014, 32.837734 }, { -96.914925, 32.837614 }, { -96.914888, 32.837515 }, { -96.914831, 32.837297 }, { -96.917743, 32.833443 }, { -96.917766, 32.836553 }, { -96.912399, 32.842674 }, { -96.911487, 32.841373 }, { -96.9104, 32.841399 }, { -96.91072, 32.84264 }, { -96.910717, 32.842674 }, { -96.911584, 32.833443 }, { -96.911581, 32.833684 }, { -96.911559, 32.835271 }, { -96.911554, 32.83642 }, { -96.920403, 32.833443 }, { -96.920397, 32.833894 }, { -96.9104, 32.833662 }, { -96.911581, 32.833684 }, { -96.914775, 32.834518 }, { -96.914512, 32.835038 }, { -96.914327, 32.835437 }, { -96.914016, 32.836136 }, { -96.913973, 32.83621 }, { -96.913906, 32.83628 }, { -96.913769, 32.836359 }, { -96.913675, 32.836384 }, { -96.913203, 32.836445 }, { -96.9104, 32.837231 }, { -96.910695, 32.837202 }, { -96.911025, 32.837182 }, { -96.911355, 32.837168 }, { -96.911948, 32.837168 }, { -96.912391, 32.837222 }, { -96.912656, 32.83729 }, { -96.913072, 32.83752 }, { -96.916189, 32.83818 }, { -96.918117, 32.837339 }, { -96.918165, 32.84179 }, { -96.917329, 32.840988 }, { -96.91702, 32.840704 }, { -96.916811, 32.840587 }, { -96.916661, 32.840519 }, { -96.916368, 32.840454 }, { -96.916164, 32.840438 }, { -96.915263, 32.840458 }, { -96.914137, 32.840553 }, { -96.914316, 32.840555 }, { -96.91415, 32.840452 }, { -96.914054, 32.841182 }, { -96.913976, 32.841572 }, { -96.913842, 32.842049 }, { -96.913691, 32.842414 }, { -96.913569, 32.842674 }, { -96.914919, 32.842674 }, { -96.91492, 32.842671 }, { -96.9151, 32.842171 }, { -96.915244, 32.84152 }, { -96.915322, 32.840979 }, { -96.915376, 32.840569 }, { -96.915384, 32.840454 }, { -96.915474, 32.833443 }, { -96.915379, 32.833664 }, { -96.915314, 32.833772 }, { -96.915261, 32.833849 }, { -96.915081, 32.834083 }, { -96.914775, 32.834518 }, { -96.913072, 32.83752 }, { -96.913195, 32.837608 }, { -96.913675, 32.838002 }, { -96.913694, 32.838011 }, { -96.91396, 32.838241 }, { -96.914054, 32.838345 }, { -96.914161, 32.838507 }, { -96.914255, 32.838714 }, { -96.914292, 32.83889 }, { -96.914319, 32.839063 }, { -96.914182, 32.840098 }, { -96.91415, 32.840452 }, { -96.917406, 32.836557 }, { -96.91588, 32.836517 }, { -96.915778, 32.836501 }, { -96.915727, 32.836481 }, { -96.91569, 32.836458 }, { -96.915644, 32.836422 }, { -96.915609, 32.836382 }, { -96.915588, 32.836348 }, { -96.915572, 32.836305 }, { -96.915564, 32.836235 }, { -96.915564, 32.836154 }, { -96.915668, 32.835469 }, { -96.915754, 32.834827 }, { -96.915781, 32.834689 }, { -96.915835, 32.834556 }, { -96.916052, 32.834074 }, { -96.916283, 32.833443 }, { -96.915384, 32.840454 }, { -96.915408, 32.839794 }, { -96.915411, 32.839345 }, { -96.915459, 32.839068 }, { -96.91554, 32.838845 }, { -96.915636, 32.838687 }, { -96.915765, 32.838529 }, { -96.915945, 32.838358 }, { -96.916189, 32.83818 }, { -96.919421, 32.837159 }, { -96.919557, 32.837216 }, { -96.919697, 32.837288 }, { -96.919812, 32.8374 }, { -96.919874, 32.837479 }, { -96.920172, 32.838358 }, { -96.920295, 32.838845 }, { -96.920333, 32.839068 }, { -96.920327, 32.839422 }, { -96.920223, 32.839746 }, { -96.920072, 32.840046 }, { -96.919898, 32.840276 }, { -96.919812, 32.840355 }, { -96.919426, 32.84067 }, { -96.918012, 32.84172 }, { -96.91753, 32.84207 }, { -96.917374, 32.842196 }, { -96.916727, 32.842674 }, { -96.916981, 32.842674 }, { -96.917079, 32.842602 }, { -96.917487, 32.842291 }, { -96.918114, 32.841826 }, { -96.919984, 32.840454 }, { -96.920236, 32.840233 }, { -96.920429, 32.839965 }, { -96.920512, 32.839816 }, { -96.92059, 32.839557 }, { -96.920612, 32.839271 }, { -96.920604, 32.839181 }, { -96.920574, 32.839043 }, { -96.920416, 32.83857 }, { -96.920365, 32.83839 }, { -96.920341, 32.838261 }, { -96.9203, 32.838119 }, { -96.920282, 32.837943 }, { -96.920274, 32.83775 }, { -96.920295, 32.837603 }, { -96.920319, 32.837536 }, { -96.920397, 32.837407 }, { -96.920515, 32.837288 }, { -96.920601, 32.837227 }, { -96.920727, 32.83717 }, { -96.91441, 32.836582 }, { -96.914188, 32.836571 }, { -96.913203, 32.836445 }, { -96.914324, 32.840454 }, { -96.91415, 32.840452 }, { -96.921387, 32.836595 }, { -96.920815, 32.836594 }, { -96.917766, 32.836553 }, { -96.917406, 32.836557 }, { -96.915851, 32.836621 }, { -96.915459, 32.836621 }, { -96.915129, 32.836607 }, { -96.918117, 32.837339 }, { -96.918324, 32.837252 }, { -96.918586, 32.837186 }, { -96.918844, 32.837161 }, { -96.919421, 32.837159 }, { -96.920727, 32.83717 }, { -96.921387, 32.83717 }, { -96.913203, 32.836445 }, { -96.913142, 32.836438 }, { -96.912999, 32.836438 }, { -96.912774, 32.836427 }, { -96.912573, 32.836433 }, { -96.911554, 32.83642 }, { -96.9104, 32.836416 }, { -96.915253, 32.840564 }, { -96.915376, 32.840569 }, { -96.915816, 32.840562 }, { -96.916197, 32.840567 }, { -96.916478, 32.840598 }, { -96.916623, 32.840641 }, { -96.916757, 32.840702 }, { -96.916913, 32.840794 }, { -96.917326, 32.841157 }, { -96.917452, 32.841272 }, { -96.917956, 32.841761 }, { -96.918061, 32.841867 }, { -96.9145, 32.842674 }, { -96.914547, 32.842534 }, { -96.914708, 32.841971 }, { -96.914802, 32.841473 }, { -96.914858, 32.841078 }, { -96.914882, 32.840742 }, { -96.914907, 32.840224 }, { -96.914915, 32.839706 }, { -96.914885, 32.839084 }, { -96.914826, 32.83811 }, { -96.914831, 32.837297 }, { -96.914987, 32.836886 }, { -96.915092, 32.836889 }, { -96.914526, 32.836763 }, { -96.914155, 32.836758 }, { -96.9104, 32.836758 }, { -96.921387, 32.836813 }, { -96.918825, 32.836796 }, { -96.916358, 32.836774 }, { -96.915003, 32.836767 }, { -96.914831, 32.837297 }, { -96.914872, 32.836663 }, { -96.915033, 32.835872 }, { -96.91514, 32.83546 }, { -96.915226, 32.835212 }, { -96.915853, 32.8337 }, { -96.91595, 32.833443 }, { -96.915092, 32.836889 }, { -96.916398, 32.836891 }, { -96.919547, 32.836963 }, { -96.921322, 32.836952 }, { -96.921387, 32.836952 }, { -96.9104, 32.837008 }, { -96.910671, 32.836977 }, { -96.9111, 32.836941 }, { -96.911543, 32.836925 }, { -96.912637, 32.836898 }, { -96.913501, 32.836886 }, { -96.914528, 32.83688 }, { -96.91577, 32.833443 }, { -96.915671, 32.833693 }, { -96.915344, 32.834518 }, { -96.91481, 32.835911 }, { -96.914754, 32.836127 }, { -96.914657, 32.836659 }, { -96.914617, 32.83752 }, { -96.914595, 32.838561 }, { -96.914603, 32.839688 }, { -96.914587, 32.840693 }, { -96.914512, 32.841211 }, { -96.914421, 32.841666 }, { -96.914284, 32.842196 }, { -96.914097, 32.842674 }, { -96.914316, 32.840555 }, { -96.915253, 32.840564 }, { -96.916862, 32.837164 }, { -96.917377, 32.837281 }, { -96.915129, 32.836607 }, { -96.91441, 32.836582 }, { -96.915263, 32.840458 }, { -96.914324, 32.840454 }, { -96.914528, 32.83688 }, { -96.914987, 32.836886 }, { -96.915003, 32.836767 }, { -96.914526, 32.836763 }}; diff --git a/third_party/cheap-ruler-cpp-2.5.4/test/fixtures/turf.hpp b/third_party/cheap-ruler-cpp-2.5.4/test/fixtures/turf.hpp new file mode 100644 index 00000000000..42301aa97bc --- /dev/null +++ b/third_party/cheap-ruler-cpp-2.5.4/test/fixtures/turf.hpp @@ -0,0 +1,1894 @@ +#pragma once + +#include + +// Pre-computed test expectations with turf.js + +namespace cr = mapbox::cheap_ruler; + +static const std::vector turf_distance = { + 0.008378522721530966, + 0, + 0.010749717813535198, + 0.013838610971284946, + 0.013657697587927904, + 0.044013281621164545, + 0.0068391514197623125, + 0.10416972567189697, + 0.030891354635076577, + 0.019413765237647276, + 0.04263542169525046, + 0.0069116261879168155, + 0.582645708508002, + 0.018308680637617696, + 0.009577172911626559, + 0.017465334500943574, + 0.06613851306063838, + 0.3617719377192654, + 0.07753561751121403, + 0.13551122988625394, + 0.06598639029222791, + 0.10788718733352708, + 0.637754036319657, + 0.04744046409407494, + 0.019071666981656257, + 0.013911884201543205, + 0.026453803385838824, + 0.03993584290435518, + 0.5008820538480422, + 0.016568611251168885, + 0.05180738530903197, + 0.3119106296673429, + 0.017798808015935193, + 0.008016350616268752, + 0.007324494221885543, + 0.006909617037766451, + 0.01133329359318173, + 0.024542232038179984, + 0.13854858779974746, + 0.039494712699750543, + 0.002803669222998928, + 0.005515366276063487, + 0.005238469974132169, + 0.005880339789619507, + 0.005357898801346142, + 0.0051705154162532425, + 0.005070109623060704, + 0.0052577908286051914, + 0.00847519939173927, + 0.06303372152921366, + 0.019657925611790725, + 0.045304719345077606, + 0.11235257808731806, + 0.07172313743043487, + 0.03786245739823775, + 0.014737426160375995, + 0.012073619242440572, + 0.01944992465839253, + 0.4587699541978461, + 0.02021344170822001, + 0.04940583279333197, + 0.26541509069849073, + 0.10136117015958783, + 0.071051047335519, + 0.0839785094261126, + 0.13233952591634118, + 0.028947596386964588, + 0.450310288271311, + 0.02617846959013443, + 0.01773953006642692, + 0.03246883345774803, + 0.023279127631702524, + 0.013794142444291755, + 0.19974484175602678, + 0.0968663637124452, + 0.017337159580454113, + 0.013800054342251185, + 0.013308139694942028, + 0.01331222080564702, + 0.012080965868250661, + 0.009727373321527968, + 0.012964274265275947, + 0.016122067768646026, + 0.03863515912787102, + 0.019839914076975624, + 0.010301365066689631, + 0.010054214744799303, + 0.008762005427975264, + 0.008542780137735616, + 0.010518226790403411, + 0.09474686301917724, + 0.1342649575551186, + 0.02522592703114516, + 0.023008194493208647, + 0.04303616022369959, + 0.36251220899321573, + 0.019473754396392998, + 0.043524753809585405, + 0.06371623663872246, + 0.02758552742766217, + 0.026845476675765343, + 0.029432835806681268, + 0.4939597997561797, + 0.012276958817933555, + 0.03390371747191658, + 0.03878525490806829, + 0.03280401819558517, + 0.02996855089043349, + 0.043610944953640665, + 0.07463799480713804, + 0.054973280670314324, + 0.05362263439641399, + 0.03364472557328668, + 0.03257474948646934, + 0.035982127999637514, + 0.03017661243030025, + 0.04004558186048798, + 0.03846182853667192, + 0.017689723726582205, + 0.02581380073796066, + 0.03790654917278124, + 0.0370593711860446, + 0.06765988226898403, + 0.07684458549068582, + 0.05088930944950997, + 0.04274689073720004, + 0.031042698873467, + 0.6025557457581485, + 0.15761319510469404, + 0.09264826777038944, + 0.08001841776554604, + 0.011871825072563895, + 0.664627433433829, + 0.01917232375926572, + 0.01099493090349843, + 0.006261363451393286, + 0.0063648042581234765, + 0.009824297643237445, + 0.005584056437412894, + 0.028902860335050025, + 0.03687758065157599, + 0.013590391879516907, + 0.016166117999544854, + 0.011783888353457304, + 0.01494235041421174, + 0.009445375968215059, + 0.0063181221302946585, + 0.015727070675584043, + 0.011541912177440836, + 0.024826353234049702, + 0.5077727699239808, + 0.345931459929503, + 0.845643164225681, + 0.16794289804370816, + 0.10162406414747382, + 0.14123839370037056, + 0.003792191683109981, + 1.0299547040985766, + 0.026807856101721112, + 0.17653371969231604, + 0.12780393266727977, + 0.8908493894032292, + 0.05016778892928127, + 0.934681359703447, + 0.1104041562314812, + 0.31259370205263126, + 0.06284566928645681, + 0.0476296971944526, + 0.0830049159968845, + 0.009159661389404805, + 0.009991588429808441, + 0.015528991567811172, + 0.009214628598242817, + 0.04463082981364765, + 0.2761646624698818, + 0.02775785294501277, + 0.030920921663565613, + 0.030880088364676584, + 0.055419986988230405, + 0.041834856384027466, + 0.02589530670378627, + 0.046540107091908624, + 0.3004110613744119, + 0.20301909742424815, + 0.4951043096230534, + 0.11858115408807053, + 0.04279910991149764, + 0.023470200843156975, + 0.01592837521137288, + 0.028320290449247595, + 0.01914740566847937, + 0.08423100623656579, + 0.10575781800339631, + 0.016729639837999192, + 0.01928515125899576, + 0.08169190304672652, + 0.043987800607954874, + 0.054514411329818525, + 0.04298134155196387, + 0.031085953544609714, + 0.12615909276179177, + 0.0003465282173637971, + 0.058103130282949, + 0.07365046853595525, + 0.060615225341305666, + 0.04588259821425726, + 0.012813260692314313, + 0.7798777201137593, + 0.02613612797608842, + 0.013461529716750041, + 0.009893951634252595, + 0.030991193644600953, + 0.05620493774258541, + 0.3699038744925965, + 0.015097946393717242, + 0.06271302769749793, + 0.0020384128886200997, + 0.03567165517083371, + 0.014525490144668496, + 0.020607956055678806, + 0.0246435390331219, + 0.019879489642093223, + 0.019407494266871623, + 0.11583263922549474, + 0.03948876108912776, + 0.5294244867375493, + 0.1426857432967834, + 0.009697385429695126, + 0.00525992849031739, + 0.00430141196125398, + 0.005875039927428631, + 0.005522219552694836, + 0.0042607480963535544, + 0.005011184230011202, + 0.007821903345226908, + 0.009009616491770123, + 0.07680989084065051, + 0.07186045769829646, + 0.015555751145719514, + 0.015630740713881576, + 0.057320516556811474, + 0.07343146368625852, + 0.7843452939662691, + 0.07344594465684656, + 0.04994298205930179, + 0.031135505320641476, + 0.025933641798745768, + 0.01973190434263985, + 0.021311914846065032, + 0.025391967733273624, + 0.030199067305597543, + 0.3226950750643045, + 0.014203685630096484, + 0.01534037036997655, + 0.016453107333170788, + 0.010525597809363562, + 0.10166018086042491, + 0.05537516038147018, + 0.025057187459666765, + 0.03937935331770495, + 0.03732606414021839, + 0.03623014247507323, + 0.0303133933027351, + 0.01190830530874745, + 0.05028800045819346, + 0.17635692976160655, + 0.05953594686309811, + 0.020222535641001925, + 0.0805146256571518, + 0.02373659967645878, + 0.012165928750908704, + 0.0514820122407643, + 0.07815653280919697, + 0.23201058369437041, + 0.0340423547943379, + 0.03484151181059308, + 0.018298598649656068, + 0.029716445173173824, + 0.03187810305202435, + 0.010038564502119844, + 0.015603661528300027, + 0.0546445315444071, + 0.0205808711039938, + 0.014522895203654958, + 0.016252765900716146, + 0.019648594042289334, + 0.021480373184972493, + 0.016468148859886997, + 0.007782615606278065, + 0.016094168571066846, + 0.017228336077233373, + 0.01051829618341627, + 0.013373893984522116, + 0.5939814038121429, + 0.020783632669147317, + 0.09311654260907076, + 0.45806162186901805, + 0.016262433777165904, + 0.8009278300362112, + 0.05345785152641949, + 0.2849887196254366, + 0.033647685486223135, + 0.14550079382917516, + 0.03663536045894266, + 0.030880282999975885, + 0.29087772423039293, + 0.021630884822714493, + 0.02556252999484156, + 0.024271715891829745, + 0.05392513908839965, + 0.12206094837643991, + 0.06168160301572301, + 0.7690944309219785, + 0.005753846170923199, + 0.01336445751002951, + 0.02106355972240177, + 0.01879685972329176, + 0.0952444313427708, + 0.1078511795464463, + 0.6469708160164086, + 0.011508214196305674, + 0.04112686678910598, + 0.035610088844009874, + 0.026485811067702324, + 0.014370051474837841, + 0.014242735913957073, + 0.017811674662530638, + 0.05585618250055378, + 0.01738598064185313, + 0.07195021868945746, + 0.015339399943488055, + 0.34467463670324133, + 0.016179746130454448, + 0.06440448684565248, + 0.05608468433498269, + 0.04424636779988501, + 0.037440464051362185, + 0.057664402696718915, + 0.05762190400375552, + 0.06924174005124464, + 0.10847808154508215, + 0.0904310617110173, + 0.047983949715355446, + 0.009818685405935522, + 0.054721988898462984, + 0.034677157404038546, + 0.3509325669208246, + 1.0268344467822377, + 0.23944522020834375, + 0.23057234097441315, + 0.12663716357349866, + 0.06110408862755362, + 0.0706237379606926, + 0.08926016309905949, + 0.04690508445469457, + 0.028732090191940274, + 0.17809611583512075, + 0.029989165393382068, + 0.391596040835184, + 0.12205539606742612, + 0.29440576356307174, + 0.16589103850643355, + 0.006074718243210164, + 1.0268328659759098, + 0.02556053511771133, + 0.04029260310233885, + 0.041439782865155726, + 0.10228632526932319, + 0.08075810970675557, + 0.09598294305539697, + 0.39953051109714005, + 0.029306409486832358, + 0.09671994873655325, + 0.1627823795415789, + 0.02458907783680164, + 0.05986464703306779, + 0.09584181947018754, + 0.11580850896272278, + 0.12535825153862024, + 0.11179598232834778, + 0.058041800368261356, + 0.05131909973307807, + 0.0603260376812227, + 0.05596616469177014, + 0.23658290631261256, + 0.0875715634398609, + 0.40697930337242394, + 0.04985868432498091, + 0.2230670459299213, + 0.06725351272770712, + 0.4384349898078352, + 0.08775397845174246, + 0.3979923162137123, + 0.04290208100438889, + 0.013320545764006694, + 0.04458140027621235 +}; + +static const std::vector turf_bearing = { + -63.16835850131531, + 0, + -88.81417863186009, + -91.84236975943857, + -66.48043977763521, + 95.21979003833424, + -100.30570881383704, + 150.61043051772228, + -42.426806215464694, + -23.550372000573976, + -13.952505152879574, + -43.59833577993832, + 132.99198010189937, + 166.41929543157306, + 177.20325520034712, + -179.08016176339177, + -170.23703380143226, + 11.337660289434671, + -82.74731094370897, + 63.53130497081162, + 8.962738746772079, + 9.37241746920313, + -168.57228731224598, + 28.730760752589035, + 31.624597764846637, + 29.367864287830926, + 40.81330085442227, + 42.194625737959534, + 54.716993037210045, + -109.61289479694872, + -105.95081303007647, + -97.35442495838333, + 103.73738360872167, + 128.63753291604394, + 139.40255086492127, + 154.353076115606, + 172.41822883056525, + -173.00067170261374, + -157.88885299734986, + -153.5843194614746, + -135.57055814036255, + -113.78745742707413, + -92.43386994136272, + -80.19821514884795, + -62.824367973789435, + -39.24535094117481, + -19.378190579597625, + -6.122391240486928, + 10.162381849878825, + 16.628046997768607, + 11.796298622071708, + 9.259418658966705, + 33.013988074027225, + 95.42809952694313, + 99.12772053947573, + 114.05171960306723, + 138.26425923091327, + 115.39825807756951, + -78.13409883483345, + -78.57409383589719, + -87.160852199759, + -108.19195718984352, + 86.91738524340066, + 84.70017282115018, + 87.95033104208615, + 90.43302815253836, + 78.02446742577152, + 87.86117672643189, + -69.86932102730815, + -82.07107484952823, + -72.86553078555735, + -65.13553755018475, + -44.79817086959291, + -110.571105457802, + 7.7069914618379975, + 14.357081966766243, + 37.06518971504373, + 44.04525332938273, + 66.87692305523359, + 86.3047355297261, + 107.98313958114178, + 119.27773275782387, + 133.08034139008478, + 136.03334417898122, + 147.83958090135633, + 166.35653589386422, + -174.66648287441066, + -152.70026365512155, + -134.67606484413284, + -102.21019447457768, + -98.37013738611591, + -85.39045487355833, + -83.16251407128772, + -79.41426027366361, + -71.6199202393354, + 25.647805187311675, + 171.1662911122707, + 175.31992210998703, + 171.14075667901446, + 168.46991110160218, + 171.99557069100132, + 166.22310505740552, + 1.1490813990525728, + -160.4320410335643, + -163.99994946634425, + -165.7728900157161, + -173.45680597027817, + -170.84905103756142, + -174.09621979366605, + -175.5476650357732, + -178.24648292689753, + -178.90151317182918, + -172.65900564120977, + -167.57442915983086, + -155.7719187979583, + -147.18225435271103, + -144.4718825804975, + -132.58756100092145, + -127.58358614976032, + -124.36541206185082, + -117.43139970416347, + -114.09107335076804, + -98.50829769899121, + -93.15284638637799, + -92.50530269529919, + -94.47703726903666, + -100.11192008297043, + 59.77360017983539, + 9.143285027353551, + 13.771320155516808, + 18.804056386135507, + 24.65786911308088, + -162.44500486120558, + -67.84560294942295, + -41.52913748098395, + -31.493999863996763, + -11.862722004156867, + 4.911415384854547, + 20.5768593094366, + 39.328103571820634, + 47.73104506840779, + 60.04949187845642, + 77.68453534325027, + 92.16377287776062, + 106.8766740367609, + 129.48750446573763, + 134.76457530705628, + 148.07063441375706, + 162.56674425873655, + 167.60958213096342, + -147.58932438111154, + -0.35602290379352103, + 36.377431696616014, + 149.50345988748333, + 88.36898545914883, + -12.223747274643541, + 4.239696760480642, + -175.4876519466847, + 0.5992644178179116, + 0.6673420115819962, + 0.2094907113015796, + -111.81827272749739, + 0.6404507036839922, + 91.57935182920652, + -88.72964175221959, + -72.73595760634777, + 23.023787324470447, + 21.284935274447214, + 20.497437869075558, + 26.023401004269186, + 38.80671567232787, + 55.538280861535505, + 72.4357211583551, + 81.25555219912327, + 71.54335789800336, + -96.67318521343546, + -94.1256029846292, + -92.8904417068675, + -89.99983922215844, + -81.74515005128639, + -73.017109535514, + -56.65379972139568, + -75.85450215095052, + -117.43602194323526, + -0.5191133757264856, + 138.78810984843733, + 137.56824257563747, + 123.6752409593202, + 118.34970554664147, + 104.79079949099777, + 95.33306354879424, + 88.48636023444747, + 84.26539611797256, + -89.23804769018248, + 126.44610739090022, + 6.304981289653255, + 9.538566926163998, + 13.280042951632822, + 19.166182380726028, + 21.51585631114597, + -89.9996339244023, + -164.35486815306686, + -163.17151075342585, + -169.4719802936045, + -173.09313538953987, + -173.68544129286698, + -176.6550060133922, + -179.38201633291828, + 19.85934450173753, + 26.825916744943097, + 30.042999793582226, + 32.87625705680969, + 30.58584499722022, + 25.48436330531482, + -49.58528537111213, + -45.66818093662166, + -60.58696099977996, + -44.178097235571066, + -37.213574067968544, + -29.02801030830766, + -20.88386390872622, + -10.016986251287301, + -7.470516078862877, + 6.345968960148908, + 4.343209329511361, + -144.91638104371413, + 91.78645944829398, + 100.57490882565328, + 115.0198771218778, + 126.49515676679046, + 132.9667450433102, + 143.6768700122894, + 152.57244080955854, + 162.6386056371201, + 174.5149571496929, + 180, + -172.73016111884994, + -173.57809345551524, + -170.66439195019734, + -161.16292504839234, + -159.27915118031842, + -162.90191364007953, + 6.149002598385885, + -178.25002252904207, + -179.67835798380287, + -171.71629870718354, + -163.02862431499696, + -152.95560774414605, + -145.55034082696017, + -138.50963007714628, + -130.96610418046026, + -110.60445245954395, + -63.488932754631335, + -58.5296285047684, + -40.784935262998765, + -33.4011304023945, + -15.899450270318724, + -11.98079922175284, + -8.147813628278488, + 0.8158694642281521, + 15.093060659786769, + 22.923229163325363, + 32.44078804116013, + 42.447012241263664, + 45.83427921173283, + 48.52837549516453, + 49.16371967470212, + 46.12898587570745, + 48.67322750744069, + -89.99993112361511, + -131.16855313987196, + -132.21634274729973, + -131.43505191524252, + -131.12876979883848, + -136.22759997049272, + -148.82348281194703, + -154.91921385645844, + -165.80042858245199, + -176.30209430550704, + 175.72884637650225, + 169.64893781173248, + 164.32272447851253, + 166.609539892841, + 171.1155850861851, + 166.3637807513156, + 175.0886195159549, + 178.0053467715306, + -173.15552476803634, + -163.24971275122377, + -153.06780391136738, + -140.2005052574728, + -130.17077601985082, + -118.29848203781941, + 96.31992932289273, + 93.37488183764101, + 98.65620852739153, + -13.220894289645209, + 90.78374679182464, + -122.38574263089491, + 90.11906042024525, + 90.91606631491278, + 89.24226505678728, + 87.1952301524552, + 89.99989371956251, + 92.89042347389294, + -73.7442223661134, + -116.5749747098209, + -106.68941539794253, + -96.5786003424879, + -90.23620894320432, + -89.42530845705083, + -89.99982105641459, + 96.0164612641722, + 97.77709140355806, + 89.99996123049279, + 93.32997836025105, + 87.96524189628325, + 90.86961377588838, + 90.23605053342526, + -44.50763881494917, + -87.22999594921937, + -91.08466221917038, + -89.10502963081117, + -82.51948924863764, + -70.55890852242291, + -61.55042515193161, + -54.93400664520933, + -43.708432529297596, + -42.630819035108374, + -40.89066031737039, + -39.768718845646205, + 74.90365235947708, + -164.2486209384613, + -166.49009116775852, + -170.9886716825588, + -173.2072838154825, + -176.56563073545988, + -177.67795564677132, + -179.256576114407, + 177.6794175196906, + 177.08641995168978, + -179.7039343413944, + -162.31174704216053, + -88.05239082476302, + 104.83933395089112, + 90.91884342553296, + 89.99898193057349, + -89.65566421438635, + 90.45177683075481, + 90.60742069201243, + 90.35190900335593, + 15.252229486307309, + -176.88983601147055, + -170.29517886206932, + -167.69014730626628, + -163.75539093753457, + -160.78980004585748, + -162.40423641636087, + 11.815918282011998, + -89.89521786054206, + -88.44037032865228, + -90.4221071958824, + -89.99998237874593, + 89.64945709813418, + -97.7527834928843, + -95.70334593407169, + -92.4612675583479, + -91.68219351312248, + -90.94678497047079, + -90.39810804835399, + -163.10988605669783, + 18.40425036657263, + 18.419844554057384, + 17.853582297033203, + 12.289104432473655, + 8.709879040159981, + 2.2353614586368535, + 1.0172614149903392, + -0.34171312935348624, + 0.7663441543155729, + 6.935793519460202, + 9.538556916896354, + 12.252956857370524, + 18.19480908504452, + -175.0372577909854, + -89.34475877505189, + -158.31621119967375, + -74.8695322495171, + 109.63776192527479, + 92.36950183161946, + -10.475734036813332, + 90.2902405855761, + -177.25427215646803, + -89.10855416703986, + -173.55458838862484, + 90.5716881361661 +}; + +static const std::vector turf_destination = { + { -96.92034100000001, 32.82927060622736 }, + { -96.92060772614725, 32.829305975369245 }, + { -96.92079439543319, 32.82931008237797 }, + { -96.92109595102636, 32.829318926002884 }, + { -96.92143033606274, 32.82932450415998 }, + { -96.92175049436656, 32.82938581393253 }, + { -96.92146736784431, 32.82936485157204 }, + { -96.92172490097579, 32.82937161249924 }, + { -96.9213630235027, 32.8285760913059 }, + { -96.92177070843935, 32.82880428175528 }, + { -96.92203788361117, 32.82899017678576 }, + { -96.92233149855905, 32.82939076851167 }, + { -96.92256548517682, 32.82946704822662 }, + { -96.91818769656206, 32.82592900640833 }, + { -96.91832325986564, 32.825805632710264 }, + { -96.91849903664684, 32.82575891598141 }, + { -96.91868196749337, 32.82564384425943 }, + { -96.91898098457527, 32.82510240477685 }, + { -96.91839818728636, 32.8283385839573 }, + { -96.91939827432712, 32.82847636744433 }, + { -96.91827631973166, 32.82907174007224 }, + { -96.91834125479305, 32.82971268589303 }, + { -96.91832704128093, 32.8307271881736 }, + { -96.91985130136207, 32.82516722942136 }, + { -96.91977856038616, 32.825603791320425 }, + { -96.91984148408056, 32.8258148548345 }, + { -96.91993702946877, 32.82599140014963 }, + { -96.91991915091329, 32.826241406696084 }, + { -96.91979779876095, 32.826579853154904 }, + { -96.91558705439019, 32.82925571745485 }, + { -96.91591658029526, 32.829282976817495 }, + { -96.91661047207285, 32.829234607705295 }, + { -96.92007967053509, 32.82895758586908 }, + { -96.9200521621881, 32.82900388634131 }, + { -96.92014087867756, 32.829045483451324 }, + { -96.92024377268062, 32.82908435082749 }, + { -96.92036379723118, 32.829119461406734 }, + { -96.92049790317056, 32.829111787443004 }, + { -96.92067803914178, 32.82898830051573 }, + { -96.92138209750365, 32.82793197154348 }, + { -96.9217141663508, 32.827713770769876 }, + { -96.92187716351988, 32.82779766780548 }, + { -96.92207102285543, 32.827881631620734 }, + { -96.92226470339185, 32.82798563055431 }, + { -96.92246216268975, 32.828102632325134 }, + { -96.92264635970814, 32.82823460404209 }, + { -96.92281225401825, 32.828382512213935 }, + { -96.92295880519139, 32.828539322759674 }, + { -96.92309097382822, 32.82870200101877 }, + { -96.92319872369181, 32.82889451176149 }, + { -96.92312705780591, 32.829556819195616 }, + { -96.9232028626346, 32.82985088699453 }, + { -96.9232411573597, 32.83037567828073 }, + { -96.92269992821585, 32.83134715565532 }, + { -96.9220470103152, 32.83141228122331 }, + { -96.92175545672075, 32.831486016562685 }, + { -96.92171723372269, 32.83156132277095 }, + { -96.921734306369, 32.8316111604673 }, + { -96.92164664653896, 32.831668489803576 }, + { -96.9265483183977, 32.83265027046581 }, + { -96.92685511412476, 32.832821461731555 }, + { -96.92747508633266, 32.83298002241657 }, + { -96.9302621268373, 32.832372910939625 }, + { -96.92926537384224, 32.832561085283594 }, + { -96.92859171846636, 32.832760503071036 }, + { -96.92777413074916, 32.8329291215357 }, + { -96.92643558565632, 32.833062897544984 }, + { -96.92620707047061, 32.83326078761194 }, + { -96.92146356644531, 32.83355674791104 }, + { -96.92179503322653, 32.8337837342936 }, + { -96.92204845102395, 32.83395270229553 }, + { -96.9224428137804, 32.834186607151885 }, + { -96.92272809550946, 32.834423403814895 }, + { -96.92288827790685, 32.83466104696409 }, + { -96.92494226054892, 32.83418049103243 }, + { -96.92485328363847, 32.83519469016151 }, + { -96.92485407643412, 32.835497598333895 }, + { -96.92480870102905, 32.83574916926978 }, + { -96.92475014863298, 32.83598835649724 }, + { -96.92465640380966, 32.83618911335752 }, + { -96.92456145502362, 32.83635039301763 }, + { -96.92449329255402, 32.83647814848498 }, + { -96.92439990743493, 32.836576332621924 }, + { -96.92429828977875, 32.83663289816016 }, + { -96.92403241904934, 32.83653879771671 }, + { -96.92393731871984, 32.836543983800375 }, + { -96.92392597882305, 32.8366104088374 }, + { -96.92394738757146, 32.83667702518138 }, + { -96.92399854388823, 32.83676378512602 }, + { -96.92406844480034, 32.8368666409214 }, + { -96.92418009097368, 32.837003544787805 }, + { -96.92518146526312, 32.837036448933326 }, + { -96.92660860730805, 32.83729030555763 }, + { -96.9268684835029, 32.83747406688541 }, + { -96.92709910606104, 32.837668685163564 }, + { -96.92752148718918, 32.837947112682556 }, + { -96.92582495878467, 32.84104130174476 }, + { -96.92577181513958, 32.841024204874486 }, + { -96.92570941035605, 32.84078977453039 }, + { -96.92557675694083, 32.8403789633218 }, + { -96.92548692274416, 32.840290723966085 }, + { -96.92541287907572, 32.840206009324746 }, + { -96.92530063370805, 32.84010277239874 }, + { -96.92515475186458, 32.84469596626941 }, + { -96.92515515797638, 32.84474454442302 }, + { -96.9252083791398, 32.84460346030672 }, + { -96.92526044659823, 32.84441666763957 }, + { -96.9252473860237, 32.844274120357106 }, + { -96.92524221144033, 32.84415777262634 }, + { -96.92523092269901, 32.843916578859954 }, + { -96.92523052056168, 32.84339549372804 }, + { -96.9251830757581, 32.843048472162685 }, + { -96.92512558963632, 32.842712469390584 }, + { -96.92510010191579, 32.842557440932126 }, + { -96.92510061543786, 32.842415342624996 }, + { -96.92518115035102, 32.84226313063035 }, + { -96.9252757385188, 32.84217676144705 }, + { -96.92544139007872, 32.84202419192918 }, + { -96.92565814381041, 32.84192937929272 }, + { -96.92571903404281, 32.84197028113293 }, + { -96.92585506965108, 32.841975855439806 }, + { -96.92612027958023, 32.84195406060516 }, + { -96.92638469759416, 32.84195185543719 }, + { -96.92700035587634, 32.84199419917395 }, + { -96.92771828543378, 32.84208705149566 }, + { -96.92815651411966, 32.842196372537174 }, + { -96.92850407135272, 32.84229412289962 }, + { -96.92871998933195, 32.84237126366221 }, + { -96.92303556750609, 32.845222756364045 }, + { -96.92265144507935, 32.84674456312207 }, + { -96.9222967307011, 32.84767464651239 }, + { -96.92189950489244, 32.8484749696396 }, + { -96.92172276419579, 32.848689496153796 }, + { -96.9237410893001, 32.843108190296135 }, + { -96.923802546131, 32.84328701670827 }, + { -96.92374965829724, 32.843472940765764 }, + { -96.9236514626933, 32.84363092836846 }, + { -96.92353000280231, 32.84379494600556 }, + { -96.92338332178431, 32.84398896076638 }, + { -96.9232224556523, 32.84413994035114 }, + { -96.92288446231687, 32.844442853078014 }, + { -96.92244837426914, 32.8447656678973 }, + { -96.92217622162691, 32.8449243543985 }, + { -96.92185905928895, 32.84505088281731 }, + { -96.92158293218587, 32.84514022404786 }, + { -96.92127788623063, 32.84519234965051 }, + { -96.92104596927354, 32.84522723186053 }, + { -96.92084223019, 32.84527384359657 }, + { -96.92059571034834, 32.84523815846969 }, + { -96.92039946444064, 32.84522115078961 }, + { -96.92018153243328, 32.84508279557485 }, + { -96.92293075844712, 32.8413060685728 }, + { -96.92278981214417, 32.844490946195606 }, + { -96.91725748845279, 32.85068440564823 }, + { -96.91617826911245, 32.84945342488996 }, + { -96.91492269293347, 32.84954698255384 }, + { -96.91507279822012, 32.85085305805673 }, + { -96.91489851558394, 32.85094963157779 }, + { -96.91559254022775, 32.84177868407015 }, + { -96.91541578881139, 32.842077197188324 }, + { -96.91521892350433, 32.84371915343081 }, + { -96.91503791956701, 32.844920536056705 }, + { -96.92370969579733, 32.84199332911104 }, + { -96.92352559723263, 32.84249151740852 }, + { -96.9133495208793, 32.842304086578224 }, + { -96.91435055467473, 32.84236802303858 }, + { -96.91736376818267, 32.843241314011124 }, + { -96.91691918097388, 32.843797947525246 }, + { -96.91655185513237, 32.84423091241846 }, + { -96.91605785663661, 32.84496119834133 }, + { -96.91583122001299, 32.845063795761554 }, + { -96.91558001680603, 32.84515969596507 }, + { -96.91525830338438, 32.84526189106002 }, + { -96.91497913504723, 32.84530737397885 }, + { -96.9143215696874, 32.84538613848035 }, + { -96.91133267086113, 32.84618717915156 }, + { -96.91144147769786, 32.84617049140981 }, + { -96.91158505725988, 32.84616007150336 }, + { -96.91172846628058, 32.84615291651313 }, + { -96.91213476159362, 32.84615702435345 }, + { -96.912391, 32.84621239377265 }, + { -96.91246923814964, 32.84627902435345 }, + { -96.91269853223814, 32.84650491651311 }, + { -96.91562893644198, 32.84715807150331 }, + { -96.91737052114979, 32.846307491409796 }, + { -96.91723228122223, 32.85074617915096 }, + { -96.91621037304874, 32.84992913847948 }, + { -96.91571580146685, 32.84962737397773 }, + { -96.9153216256599, 32.84948989105859 }, + { -96.91498690323063, 32.84939869596327 }, + { -96.91450969112039, 32.84930779575933 }, + { -96.91412204438035, 32.84926319833858 }, + { -96.9130380189888, 32.84925191241467 }, + { -96.9117296694325, 32.849312947520374 }, + { -96.91172705571321, 32.84927831400496 }, + { -96.91138023411317, 32.849136023030674 }, + { -96.91110422918695, 32.84982408656827 }, + { -96.91084713208613, 32.850169517397084 }, + { -96.91053498353314, 32.85059932909671 }, + { -96.91020684510828, 32.85091453604562 }, + { -96.909908771174, 32.851122153415716 }, + { -96.9110838227085, 32.85106719716819 }, + { -96.91091104294216, 32.851006684047555 }, + { -96.91091850811969, 32.85044663157913 }, + { -96.91089125672022, 32.849733058059954 }, + { -96.91079932847259, 32.84912698255514 }, + { -96.9106847733917, 32.84864942489266 }, + { -96.91052563309422, 32.848464405656216 }, + { -96.9104503638796, 32.84138094620757 }, + { -96.91019122863675, 32.84152706857188 }, + { -96.909963680057, 32.84155779559022 }, + { -96.90974976319653, 32.84155515080656 }, + { -96.90941051524207, 32.841707158486976 }, + { -96.90894698098482, 32.84205784361321 }, + { -96.907088047852, 32.8449732318619 }, + { -96.90705712898402, 32.844972349651776 }, + { -96.90738505824653, 32.845275224047036 }, + { -96.90725393055232, 32.845190882816425 }, + { -96.90737174860608, 32.84532535439583 }, + { -96.9073195827836, 32.84533166789337 }, + { -96.9072824639789, 32.84539385307118 }, + { -96.90723443684865, 32.84549894034094 }, + { -96.90713155058394, 32.845570960754024 }, + { -96.90702084565024, 32.84563794599061 }, + { -96.9067482915646, 32.846564928343774 }, + { -96.90658305728276, 32.846808940736665 }, + { -96.90970849593005, 32.84280201671265 }, + { -96.90805395125876, 32.84264819030043 }, + { -96.90782578893621, 32.84251649621324 }, + { -96.90765104983556, 32.84237896970015 }, + { -96.90749277157009, 32.84223664656806 }, + { -96.90732799202755, 32.842079563171204 }, + { -96.90717674658113, 32.84191675639983 }, + { -96.90704206968707, 32.84175826366903 }, + { -96.90691499740588, 32.84158912290766 }, + { -96.90679856537491, 32.841391372546596 }, + { -96.90669280511362, 32.84118105150652 }, + { -96.9066938088171, 32.84036519919393 }, + { -96.90667954376929, 32.839590855466795 }, + { -96.90660899268886, 32.8393190606389 }, + { -96.9065682357046, 32.83905085547807 }, + { -96.90669333896665, 32.83843228118014 }, + { -96.90683531022513, 32.83766337935074 }, + { -96.9058493401867, 32.844535191894416 }, + { -96.90579009265895, 32.8437347614251 }, + { -96.90571275338846, 32.84314413061774 }, + { -96.90568335053055, 32.8427243426205 }, + { -96.90568992027882, 32.84235744093508 }, + { -96.90571448391348, 32.84205446940046 }, + { -96.90577507033056, 32.84175047218241 }, + { -96.90588970181872, 32.841432493758276 }, + { -96.90607139760981, 32.84110657890376 }, + { -96.90924427251379, 32.83993677269292 }, + { -96.90932412469623, 32.839844120427756 }, + { -96.90941109238025, 32.839765667714516 }, + { -96.9094761887729, 32.83972646038609 }, + { -96.90949143753902, 32.83965354450662 }, + { -96.9097457551243, 32.840379966340876 }, + { -96.90982829424877, 32.84071377238854 }, + { -96.90982905264774, 32.840783009315054 }, + { -96.90978899510543, 32.840982723954376 }, + { -96.9096541510239, 32.84115196330865 }, + { -96.9094755291208, 32.84129677452172 }, + { -96.90927714334165, 32.84137120486853 }, + { -96.9091700108835, 32.84129430174039 }, + { -96.90876609180499, 32.84145311262188 }, + { -96.90733733141684, 32.8423466850824 }, + { -96.90684390666796, 32.8425400667973 }, + { -96.90667976396954, 32.842509305466734 }, + { -96.90602783642515, 32.84283044883231 }, + { -96.9062802255586, 32.84267354468892 }, + { -96.90637988293022, 32.84244464082416 }, + { -96.90679282812866, 32.84197678503523 }, + { -96.90742804933328, 32.84135502510003 }, + { -96.9093096344923, 32.83982640878158 }, + { -96.90957633247281, 32.839448983750096 }, + { -96.90978728295761, 32.83902479767383 }, + { -96.90989146055402, 32.8387198981243 }, + { -96.90999388620241, 32.838305332592356 }, + { -96.91004354245484, 32.83786414846141 }, + { -96.910066394355, 32.83761939299617 }, + { -96.91007046155549, 32.8373271133384 }, + { -96.90994976743183, 32.83670035648537 }, + { -96.90993922639949, 32.83636716925954 }, + { -96.90995885480693, 32.83608559832425 }, + { -96.90996464686559, 32.835791690151794 }, + { -96.90999659070908, 32.83546449101174 }, + { -96.91004166908012, 32.83512104695675 }, + { -96.91011885853125, 32.83482440380857 }, + { -96.91020213813562, 32.8346086071453 }, + { -96.91034250605827, 32.834331702289695 }, + { -96.91052593504799, 32.834065734289304 }, + { -96.91068039981232, 32.83385874790652 }, + { -96.91087788560367, 32.83365678760608 }, + { -96.90463542953506, 32.83292489754698 }, + { -96.90449088650593, 32.83277112153798 }, + { -96.90358630936747, 32.83250350307465 }, + { -96.90479021695444, 32.83637208523084 }, + { -96.90470246266294, 32.836230910887174 }, + { -96.91202899207734, 32.8322360224265 }, + { -96.91154896132278, 32.83209846174101 }, + { -96.90859475679387, 32.83192227047514 }, + { -96.90833234079028, 32.83179248980202 }, + { -96.90687768221198, 32.83172416046592 }, + { -96.90658876308076, 32.83159332277057 }, + { -96.90636454683248, 32.8314500165631 }, + { -96.90946092710227, 32.83205428121599 }, + { -96.90977902424702, 32.83184115564981 }, + { -96.91015472158404, 32.83165067826693 }, + { -96.91052898267965, 32.83150288697713 }, + { -96.9112247739368, 32.83137981917697 }, + { -96.91265206016878, 32.83127151173788 }, + { -96.91343580663084, 32.831154000995156 }, + { -96.90537803849678, 32.83031332274312 }, + { -96.90544558911877, 32.830192512197605 }, + { -96.90543348303062, 32.83008060402599 }, + { -96.90534168189792, 32.82995963230952 }, + { -96.90527614279657, 32.829857630539124 }, + { -96.90439482744506, 32.82973863160623 }, + { -96.90338069160265, 32.829630667791726 }, + { -96.90837537183168, 32.83367677072692 }, + { -96.90864247408625, 32.83358197150447 }, + { -96.9092286278605, 32.833477300486074 }, + { -96.90975778683836, 32.833386787416 }, + { -96.91018890496235, 32.8333244613814 }, + { -96.91048593761097, 32.833276350803445 }, + { -96.91077383813835, 32.833248483428406 }, + { -96.91108555891405, 32.83325388631932 }, + { -96.911656037352, 32.83353258584669 }, + { -96.91194125915716, 32.833565607685266 }, + { -96.91260613703052, 32.83397497679704 }, + { -96.91287366825213, 32.834003717435394 }, + { -96.90947673989618, 32.83473585312356 }, + { -96.9096893960709, 32.83452340666632 }, + { -96.91001755333926, 32.83389040012315 }, + { -96.91028013353335, 32.833324854811124 }, + { -96.91050608380527, 32.83286479129949 }, + { -96.91070135504911, 32.83246622940192 }, + { -96.91089890631574, 32.831888188170744 }, + { -96.91108067612203, 32.83131268588944 }, + { -96.91122561582051, 32.83063574006906 }, + { -96.91134268123285, 32.82960936744224 }, + { -96.91152479752446, 32.828746583956615 }, + { -96.91185890321435, 32.82828840477211 }, + { -96.9121429460756, 32.828246844255986 }, + { -96.91175689101942, 32.828078915978715 }, + { -96.91156667517494, 32.82803463270799 }, + { -96.90799324737107, 32.82799800640653 }, + { -96.91916255109285, 32.82801904822771 }, + { -96.91678353408332, 32.82797076851257 }, + { -96.91450013877316, 32.827920176786314 }, + { -96.91332930884246, 32.827887281755665 }, + { -96.91334197954883, 32.82839409130596 }, + { -96.91356812298534, 32.82773961249966 }, + { -96.91391466280625, 32.8269308515725 }, + { -96.91420753589344, 32.82650381393292 }, + { -96.91447968982843, 32.82624350416024 }, + { -96.915293077956, 32.8247219260031 }, + { -96.91557662496521, 32.82445808237808 }, + { -96.91490527680895, 32.82789997536924 }, + { -96.91639800000002, 32.82790060622736 }, + { -96.91973372334664, 32.82797397536925 }, + { -96.92169538978655, 32.827967082377995 }, + { -96.92194694254597, 32.82797392600294 }, + { -96.91114632526379, 32.82803950416009 }, + { -96.91160348003399, 32.82802081393272 }, + { -96.91221835065487, 32.82799985157229 }, + { -96.91284688086124, 32.82800161249959 }, + { -96.9141260137614, 32.827995091306086 }, + { -96.91517469340017, 32.82800628175562 }, + { -96.91638586344432, 32.82802617678628 }, + { -96.91781138884836, 32.824617768514706 }, + { -96.91789537076589, 32.82489904823005 }, + { -96.91775069192848, 32.82575800640849 }, + { -96.91739830014022, 32.82718763270885 }, + { -96.91752308915034, 32.82744291597945 }, + { -96.91760604628695, 32.82801684425629 }, + { -96.91774511911717, 32.828922404771156 }, + { -96.91790124953417, 32.830010583954504 }, + { -96.91808638066573, 32.831187367439334 }, + { -96.91824645048688, 32.83224474006578 }, + { -96.91834638886598, 32.832817685886084 }, + { -96.91842915877513, 32.83333018816722 }, + { -96.91846471341049, 32.83392022939806 }, + { -96.9184489944202, 32.83446079129487 }, + { -96.91883781971728, 32.83240685481398 }, + { -96.91994337233697, 32.83248340012787 }, + { -96.9217193101751, 32.82915340668562 }, + { -96.92239995502872, 32.82934285314428 }, + { -96.92031602448525, 32.828743717456945 }, + { -96.91975955095923, 32.82879597681961 }, + { -96.92077369032383, 32.83275160768903 }, + { -96.91999391775727, 32.83282958585012 }, + { -96.9203551842353, 32.829339886339575 }, + { -96.92096990474985, 32.82943248344921 }, + { -96.92113979465543, 32.82940235082567 }, + { -96.9208148234328, 32.8294894614045 } +}; + +static const std::vector turf_lineDistance = { + 0.04662454909427901, + 0.0068391514197623125, + 0.09985216775589113, + 0.1114897011108262, + 0.07753561751121403, + 0.173873577625755, + 0.14681366156746842, + 0.06837599656020085, + 0.43073382183261627, + 0.15584656488988174, + 0.06961927450155198, + 0.4176778492245252, + 0.11346010319030365, + 0.4069191477510672, + 0.0912702817480534, + 0.21057858475480964, + 0.9731217926415133, + 0.3421517057131934, + 0.24832380027187234, + 0.345931459929503, + 0.269566962191182, + 0.003792191683109981, + 0.33114550846131696, + 0.05016778892928127, + 0.1104041562314812, + 0.2820059822767088, + 0.2592491201412077, + 0.20301909742424815, + 0.3324775424083908, + 0.016729639837999192, + 0.2542614100810735, + 0.2514112112841453, + 0.13668774071427742, + 0.3699064116077255, + 0.5100540014631532, + 0.27709292806311164, + 0.7806905867697003, + 0.7768297872678829, + 0.11390017527821808, + 0.016262433777165904, + 0.585110693926173, + 0.30913282118994834, + 0.26207433401586333, + 0.32168722472380185, + 0.6017929391701553, + 0.009818685405935522, + 0.3856097243248631, + 0.5966547247562556, + 0.44360635693488976, + 0.5884269163801416, + 0.3863202991166816, + 1.0477201274090444, + 0.0875715634398609, + 0.04985868432498091, + 0.06725351272770712, + 0.08775397845174246, + 0.04290208100438889, + 0.04458140027621235 +}; + +static const std::vector turf_area = { + 0.00001385291315291015, + 0.00038253063343961127, + 0.0004601665282670179, + 0.000025503489092274364, + 0.000595225685418049, + 0.0000274562733203963, + 0.010106783304640774, + 0.001104280981730458, + 0.00007467453869082208, + 0.00026115590644638464, + 0.0004233598602508744, + 0.010634164210050902, + 0.0001950421991985674, + 0.00045308678876159587, + 0.11642042926261091, + 0.0023790522112468416, + 0.008515769374449783, + 0.007485271287917676, + 0.0000991431197074571, + 0.006085169973921119, + 0.004123438747704956, + 0.010246920654428558, + 0.0017456776108892168, + 0.0012524502918429697, + 0.0002985554527856464, + 0.013319422885021871, + 0.03301062700761473, + 0.005952119850683508, + 0.07276896988546715, + 0.044671110786017286, + 0.00008921566232195025, + 0.0011521493461515583, + 0.002598288702578828, + 0.00017084098623693146, + 0.009460656476931052, + 0.008810544363699217, + 0.00009774280666531308, + 0.000016747619827861367, + 0.005292114515450739, + 0.00050350329460907, + 0.0013371547851014247, + 0.017404511466653897 +}; + +static const std::vector turf_along_dist = { + 0.023312274547139505, + 0.0034195757098811562, + 0.049926083877945567, + 0.0557448505554131, + 0.038767808755607015, + 0.0869367888128775, + 0.07340683078373421, + 0.034187998280100426, + 0.21536691091630814, + 0.07792328244494087, + 0.03480963725077599, + 0.2088389246122626, + 0.05673005159515183, + 0.2034595738755336, + 0.0456351408740267, + 0.10528929237740482, + 0.48656089632075666, + 0.1710758528565967, + 0.12416190013593617, + 0.1729657299647515, + 0.134783481095591, + 0.0018960958415549904, + 0.16557275423065848, + 0.025083894464640634, + 0.0552020781157406, + 0.1410029911383544, + 0.12962456007060386, + 0.10150954871212407, + 0.1662387712041954, + 0.008364819918999596, + 0.12713070504053675, + 0.12570560564207264, + 0.06834387035713871, + 0.18495320580386276, + 0.2550270007315766, + 0.13854646403155582, + 0.39034529338485013, + 0.38841489363394144, + 0.05695008763910904, + 0.008131216888582952, + 0.2925553469630865, + 0.15456641059497417, + 0.13103716700793167, + 0.16084361236190092, + 0.30089646958507765, + 0.004909342702967761, + 0.19280486216243156, + 0.2983273623781278, + 0.22180317846744488, + 0.2942134581900708, + 0.1931601495583408, + 0.5238600637045222, + 0.04378578171993045, + 0.024929342162490455, + 0.03362675636385356, + 0.04387698922587123, + 0.021451040502194443, + 0.022290700138106176 +}; + +static const std::vector turf_along = { + { -96.92058074705263, 32.838295790638604 }, + { -96.92038500000224, 32.838300500005154 }, + { -96.92017837949811, 32.837840876146984 }, + { -96.91575185809616, 32.834193910150304 }, + { -96.91550349979606, 32.83693300067325 }, + { -96.91447049297071, 32.838291837950294 }, + { -96.91528382138036, 32.83401702016945 }, + { -96.91074827033752, 32.837025468206356 }, + { -96.91465325332314, 32.83491180557744 }, + { -96.9133254981959, 32.83668815734806 }, + { -96.91774498947463, 32.8373234997933 }, + { -96.91858548156746, 32.8367137123682 }, + { -96.912125005592, 32.837061935308064 }, + { -96.91369409219625, 32.83774164388782 }, + { -96.91639766393256, 32.837037707584614 }, + { -96.91504330753082, 32.83916332521944 }, + { -96.91553969265065, 32.83839013773005 }, + { -96.91430070726516, 32.841204555275795 }, + { -96.91571233411688, 32.837779806500336 }, + { -96.9177544997986, 32.83499800000052 }, + { -96.91166706734954, 32.841629875937976 }, + { -96.9107185000003, 32.84265700000001 }, + { -96.91156370689538, 32.83493146645441 }, + { -96.92040000000762, 32.83366850000004 }, + { -96.91099049992684, 32.83367300138629 }, + { -96.91421262070213, 32.83569407895492 }, + { -96.91178370739728, 32.83716800028003 }, + { -96.91715300456607, 32.83775950369486 }, + { -96.9169767353908, 32.840679780152996 }, + { -96.91422649999899, 32.840554000031844 }, + { -96.91397243336206, 32.841584696234726 }, + { -96.91523149763671, 32.84157652148576 }, + { -96.91515150426642, 32.83399134463128 }, + { -96.9142729703425, 32.83879948063655 }, + { -96.9156392575161, 32.835658314541256 }, + { -96.91543436762962, 32.83921014952233 }, + { -96.91983675113876, 32.84033226350925 }, + { -96.92009207607055, 32.840359219198234 }, + { -96.91380542577559, 32.836522062530115 }, + { -96.91423699999902, 32.840453000030095 }, + { -96.91825697483056, 32.836559607150164 }, + { -96.91973317221228, 32.83716163055561 }, + { -96.91180206194203, 32.83642316543709 }, + { -96.91691026889121, 32.84079238934942 }, + { -96.91491045374221, 32.840000370933915 }, + { -96.9150394999991, 32.83688750001095 }, + { -96.91246302385605, 32.83675801387829 }, + { -96.91819499264128, 32.8367903863771 }, + { -96.91518494007596, 32.83533040554249 }, + { -96.91823942303637, 32.83693311262287 }, + { -96.91246139013954, 32.83690233470654 }, + { -96.91460659817584, 32.83801219845079 }, + { -96.91478449997625, 32.840559500872736 }, + { -96.91711949983032, 32.83722250026362 }, + { -96.91476949994939, 32.83659450051385 }, + { -96.91479349998943, 32.84045600087646 }, + { -96.91475749999225, 32.836883000209426 }, + { -96.91476449999463, 32.83676500022616 } +}; + +static const std::vector turf_lineSlice = { + 0.018676803463204973, + 0.0027403004691342625, + 0.0398660924057463, + 0.04446856326668934, + 0.031068781600570992, + 0.06935062861161241, + 0.05864407770725445, + 0.02738946433808026, + 0.17194340067724667, + 0.062425250268892694, + 0.027897179178562482, + 0.16737293529254177, + 0.04543404915442931, + 0.1626655495109919, + 0.036564726727473594, + 0.08399080442136823, + 0.3888893870284878, + 0.13649098383658884, + 0.09926948806782267, + 0.13795991467073365, + 0.10778696255372587, + 0.0015123931765971925, + 0.1320632508079359, + 0.020007277614733015, + 0.04424096972304277, + 0.11264746401401557, + 0.10385609012115837, + 0.08127435006240627, + 0.13303959829411355, + 0.006704402992819479, + 0.10142852122895935, + 0.10028174144491304, + 0.054573146193032135, + 0.14766725949326992, + 0.20376574794349672, + 0.11058823108803342, + 0.31189004060932496, + 0.3103422255762966, + 0.04563922619445161, + 0.006517162427091035, + 0.23447174477127802, + 0.12386733468968403, + 0.10502105512101395, + 0.12872246637948387, + 0.2400138878407706, + 0.003934657129647942, + 0.1545266007655544, + 0.23909936135356857, + 0.17696967699870225, + 0.23580214129066726, + 0.15480959152734855, + 0.41791703759808313, + 0.035094313148852196, + 0.01997359910854999, + 0.026950444653916276, + 0.03516739283887676, + 0.01719229231376514, + 0.0178652399166501 +}; + +static const std::vector turf_bufferPoint = { + {{ -96.92206300843843, 32.83681412509083 }, { -96.91861893543, 32.83970785132817 }}, + {{ -96.92214300909791, 32.836848125090825 }, { -96.91869893477045, 32.839741851328164 }}, + {{ -96.92214300909791, 32.836848125090825 }, { -96.91869893477045, 32.839741851328164 }}, + {{ -96.92225800913668, 32.836850125090805 }, { -96.91881393473163, 32.83974385132815 }}, + {{ -96.9224060090591, 32.836846125090815 }, { -96.91896193480923, 32.83973985132816 }}, + {{ -96.92254001000953, 32.83689512509079 }, { -96.91909593385867, 32.83978885132814 }}, + {{ -96.92207100931128, 32.83685912509082 }, { -96.91862693455705, 32.83975285132816 }}, + {{ -96.92214300909791, 32.836848125090825 }, { -96.91869893477045, 32.839741851328164 }}, + {{ -96.92159599327083, 32.83603212509119 }, { -96.91815195059978, 32.838925851328526 }}, + {{ -96.92181899724693, 32.836237125091095 }, { -96.9183749466231, 32.83913085132843 }}, + {{ -96.92190200035026, 32.83639712509101 }, { -96.91845794351933, 32.83929085132836 }}, + {{ -96.92201200756558, 32.836769125090846 }, { -96.91856793630295, 32.83966285132819 }}, + {{ -96.92206300843843, 32.83681412509083 }, { -96.91861893543, 32.83970785132817 }}, + {{ -96.91750293916103, 32.83324212509243 }, { -96.91405900471734, 32.83613585132978 }}, + {{ -96.91745693605817, 32.833082125092524 }, { -96.91401300782061, 32.83597585132986 }}, + {{ -96.91745193439041, 32.83299612509255 }, { -96.91400800948864, 32.83588985132989 }}, + {{ -96.91745493134579, 32.832839125092626 }, { -96.91401101253369, 32.835732851329965 }}, + {{ -96.91757491998197, 32.83225312509288 }, { -96.91413102389916, 32.83514685133023 }}, + {{ -96.91681398182763, 32.83544212509144 }, { -96.91336996204461, 32.83833585132879 }}, + {{ -96.91763698353438, 32.83553012509141 }, { -96.91419296033762, 32.83842385132875 }}, + {{ -96.91633899406605, 32.836073125091154 }, { -96.91289494980445, 32.8389668513285 }}, + {{ -96.91622900543202, 32.836659125090904 }, { -96.91278493843684, 32.83955285132824 }}, + {{ -96.91604102399457, 32.83761612509046 }, { -96.91259691987165, 32.840509851327816 }}, + {{ -96.91739291499829, 32.831996125093006 }, { -96.91394902888356, 32.834889851330345 }}, + {{ -96.91714892225083, 32.83237012509284 }, { -96.91370502162997, 32.83526385133019 }}, + {{ -96.91704192508207, 32.83251612509276 }, { -96.91359801879831, 32.8354098513301 }}, + {{ -96.91696892719582, 32.83262512509271 }, { -96.91352501668426, 32.835518851330065 }}, + {{ -96.91678393068645, 32.83280512509264 }, { -96.91334001319315, 32.83569885132999 }}, + {{ -96.91649693584488, 32.833071125092516 }, { -96.91305300803398, 32.83596485132987 }}, + {{ -96.9121219862885, 32.83567212509135 }, { -96.90867795758311, 32.83856585132869 }}, + {{ -96.91228898531874, 32.83562212509136 }, { -96.90884495855302, 32.838515851328715 }}, + {{ -96.91282198283616, 32.83549412509143 }, { -96.90937796103594, 32.83838785132877 }}, + {{ -96.91613197587343, 32.83513512509158 }, { -96.9126879679997, 32.838028851328936 }}, + {{ -96.91594697513642, 32.835097125091615 }, { -96.91250296873679, 32.83799085132895 }}, + {{ -96.91587997426367, 32.83505212509162 }, { -96.91243596960967, 32.837945851328975 }}, + {{ -96.91582897329396, 32.835002125091656 }, { -96.91238497057954, 32.837895851328994 }}, + {{ -96.91579697220784, 32.83494612509167 }, { -96.91235297166578, 32.837839851329015 }}, + {{ -96.915780970249, 32.83484512509171 }, { -96.9123369736249, 32.83773885132906 }}, + {{ -96.91581296600165, 32.83462612509182 }, { -96.91236897787286, 32.83751985132916 }}, + {{ -96.91637094362142, 32.833472125092335 }, { -96.91292700025633, 32.83636585132968 }}, + {{ -96.91655893745447, 32.833154125092484 }, { -96.91311500642416, 32.83604785132982 }}, + {{ -96.9165799371054, 32.83313612509249 }, { -96.91313600677327, 32.83602985132983 }}, + {{ -96.91663393671753, 32.8331161250925 }, { -96.91319000716118, 32.836009851329834 }}, + {{ -96.91668993667875, 32.83311412509251 }, { -96.91324600719997, 32.83600785132984 }}, + {{ -96.91675193685329, 32.83312312509249 }, { -96.91330800702542, 32.83601685132983 }}, + {{ -96.91680293727993, 32.833145125092486 }, { -96.91335900659871, 32.83603885132984 }}, + {{ -96.91683793797807, 32.833181125092466 }, { -96.91339400590047, 32.83607485132981 }}, + {{ -96.91685593881195, 32.83322412509245 }, { -96.91341200506646, 32.836117851329796 }}, + {{ -96.91686193972342, 32.83327112509243 }, { -96.91341800415486, 32.836164851329784 }}, + {{ -96.91684594117791, 32.8333461250924 }, { -96.9134020027002, 32.836239851329736 }}, + {{ -96.9166529517084, 32.83388912509215 }, { -96.91320899216815, 32.83678285132949 }}, + {{ -96.9166099550635, 32.834062125092075 }, { -96.91316598881261, 32.836955851329414 }}, + {{ -96.91653196285982, 32.83446412509189 }, { -96.91308798101515, 32.83735785132922 }}, + {{ -96.91587697928689, 32.83531112509151 }, { -96.9124329645857, 32.83820485132886 }}, + {{ -96.91511297810382, 32.83525012509153 }, { -96.91166896576897, 32.83814385132888 }}, + {{ -96.91471297705651, 32.83519612509156 }, { -96.91126896681644, 32.83808985132891 }}, + {{ -96.91456897600918, 32.83514212509158 }, { -96.9111249678639, 32.838035851328925 }}, + {{ -96.91448297443822, 32.83506112509162 }, { -96.9110389694351, 32.83795485132896 }}, + {{ -96.91429497298361, 32.834986125091646 }, { -96.9108509708899, 32.83787985132899 }}, + {{ -96.91909898943054, 32.83583412509127 }, { -96.91565495444063, 32.83872785132861 }}, + {{ -96.91931099012878, 32.835870125091255 }, { -96.9158669537423, 32.83876385132859 }}, + {{ -96.91983899055546, 32.83589212509124 }, { -96.91639495331553, 32.838785851328595 }}, + {{ -96.92253697610617, 32.83514712509158 }, { -96.91909296776691, 32.83804085132892 }}, + {{ -96.9214539770565, 32.83519612509156 }, { -96.91800996681643, 32.83808985132891 }}, + {{ -96.9206969782008, 32.835255125091535 }, { -96.91725296567199, 32.83814885132888 }}, + {{ -96.91979897872444, 32.83528212509151 }, { -96.91635496514823, 32.838175851328856 }}, + {{ -96.9183829785499, 32.83527312509153 }, { -96.91493896532283, 32.838166851328864 }}, + {{ -96.91807997959722, 32.8353271250915 }, { -96.91463596427536, 32.83822085132884 }}, + {{ -96.91326498252585, 32.835478125091434 }, { -96.9098209613463, 32.83837185132878 }}, + {{ -96.91352798409686, 32.83555912509139 }, { -96.91008395977508, 32.83845285132874 }}, + {{ -96.91371598452355, 32.83558112509138 }, { -96.91027195934834, 32.83847485132872 }}, + {{ -96.9140479861915, 32.83566712509135 }, { -96.91060395768008, 32.838560851328694 }}, + {{ -96.9142739878983, 32.8357551250913 }, { -96.91082995597309, 32.83864885132865 }}, + {{ -96.91437798960509, 32.835843125091266 }, { -96.91093395426604, 32.83873685132861 }}, + {{ -96.91637897736683, 32.835212125091545 }, { -96.91293496650609, 32.83810585132889 }}, + {{ -96.91623999410484, 32.836075125091156 }, { -96.91279594976567, 32.8389688513285 }}, + {{ -96.91619399703357, 32.836226125091095 }, { -96.9127499468365, 32.83911985132844 }}, + {{ -96.91610499895377, 32.83632512509105 }, { -96.91266094491604, 32.8392188513284 }}, + {{ -96.91600600062179, 32.836411125091 }, { -96.91256194324774, 32.83930485132834 }}, + {{ -96.91587500153341, 32.83645812509098 }, { -96.912430942336, 32.839351851328324 }}, + {{ -96.91574600166918, 32.83646512509099 }, { -96.91230194220022, 32.83935885132834 }}, + {{ -96.91564700114552, 32.83643812509099 }, { -96.912202942724, 32.83933185132834 }}, + {{ -96.91552600003993, 32.83638112509103 }, { -96.91208194382972, 32.83927485132837 }}, + {{ -96.91539999811975, 32.83628212509107 }, { -96.91195594575017, 32.839175851328406 }}, + {{ -96.91511299327082, 32.83603212509119 }, { -96.91166895059978, 32.838925851328526 }}, + {{ -96.91499999034212, 32.83588112509125 }, { -96.91155595352893, 32.838774851328594 }}, + {{ -96.91497398859653, 32.835791125091305 }, { -96.91152995527474, 32.83868485132864 }}, + {{ -96.91498398685096, 32.835701125091326 }, { -96.91153995702057, 32.838594851328665 }}, + {{ -96.9150269854933, 32.83563112509135 }, { -96.91158295837842, 32.8385248513287 }}, + {{ -96.91509198444597, 32.83557712509138 }, { -96.91164795942592, 32.83847085132873 }}, + {{ -96.91520198405807, 32.8355571250914 }, { -96.91175795981388, 32.83845085132874 }}, + {{ -96.91620498165308, 32.835433125091456 }, { -96.9127609622192, 32.8383268513288 }}, + {{ -96.91763698353438, 32.83553012509141 }, { -96.91419296033762, 32.83842385132875 }}, + {{ -96.91790498405807, 32.8355571250914 }, { -96.91446095981388, 32.83845085132874 }}, + {{ -96.91814698479507, 32.83559512509137 }, { -96.91470295907675, 32.83848885132871 }}, + {{ -96.91858398716128, 32.83571712509132 }, { -96.9151399567102, 32.83861085132867 }}, + {{ -96.91690504414862, 32.83865512509 }, { -96.91346089971469, 32.84154885132734 }}, + {{ -96.91687304079277, 32.838482125090074 }, { -96.91342890307102, 32.84137585132741 }}, + {{ -96.91683503322767, 32.838092125090256 }, { -96.91339091063722, 32.840985851327595 }}, + {{ -96.91673002224884, 32.837526125090506 }, { -96.91328592161763, 32.840419851327844 }}, + {{ -96.91667101753538, 32.837283125090615 }, { -96.91322692633173, 32.84017685132796 }}, + {{ -96.9166310128996, 32.83704412509072 }, { -96.9131869309682, 32.83993785132806 }}, + {{ -96.91655600791474, 32.83678712509084 }, { -96.91311193595378, 32.83968085132818 }}, + {{ -96.9164500940436, 32.84122712508884 }, { -96.91300584981255, 32.844120851326174 }}, + {{ -96.91649409202596, 32.84112312508889 }, { -96.9130498518305, 32.84401685132623 }}, + {{ -96.91659408634168, 32.840830125089006 }, { -96.91314985751559, 32.84372385132636 }}, + {{ -96.91669607978447, 32.84049212508917 }, { -96.91325186407373, 32.843385851326516 }}, + {{ -96.91673607410037, 32.8401991250893 }, { -96.91329186975865, 32.84309285132664 }}, + {{ -96.91678706894014, 32.83993312508942 }, { -96.91334287491964, 32.84282685132677 }}, + {{ -96.91683506137448, 32.8395431250896 }, { -96.91339088248637, 32.842436851326944 }}, + {{ -96.91689704839683, 32.8388741250899 }, { -96.91345289546588, 32.84176785132724 }}, + {{ -96.9169150388142, 32.838380125090126 }, { -96.91347090504988, 32.84127385132747 }}, + {{ -96.91692602946458, 32.83789812509034 }, { -96.91348191440086, 32.84079185132768 }}, + {{ -96.91697202364541, 32.83759812509048 }, { -96.91352792022083, 32.84049185132781 }}, + {{ -96.9170470180979, 32.83731212509061 }, { -96.91360292576915, 32.84020585132795 }}, + {{ -96.91720501237589, 32.83701712509073 }, { -96.91376093149196, 32.83991085132807 }}, + {{ -96.91738000795353, 32.836789125090846 }, { -96.91393593591498, 32.83968285132819 }}, + {{ -96.91762900227046, 32.836496125090974 }, { -96.91418494159886, 32.83938985132831 }}, + {{ -96.91793199773183, 32.836262125091075 }, { -96.91448794613815, 32.839155851328414 }}, + {{ -96.91808199585044, 32.83616512509112 }, { -96.9146379480198, 32.83905885132847 }}, + {{ -96.91830999330962, 32.83603412509118 }, { -96.914865950561, 32.83892785132853 }}, + {{ -96.91866999026453, 32.83587712509125 }, { -96.91522595360651, 32.8387708513286 }}, + {{ -96.91903198762677, 32.83574112509132 }, { -96.91558795624465, 32.838634851328656 }}, + {{ -96.9197479858812, 32.83565112509135 }, { -96.91630395799046, 32.8385448513287 }}, + {{ -96.92056898514417, 32.83561312509138 }, { -96.91712495872758, 32.838506851328724 }}, + {{ -96.92111298475629, 32.83559312509138 }, { -96.91766895911556, 32.838486851328724 }}, + {{ -96.92156898417443, 32.83556312509139 }, { -96.9181249596975, 32.838456851328736 }}, + {{ -96.92189598322406, 32.83551412509142 }, { -96.91845196064797, 32.83840785132876 }}, + {{ -96.91632503611791, 32.838241125090185 }, { -96.91288090774655, 32.84113485132754 }}, + {{ -96.91605706325616, 32.83964012508955 }, { -96.91261288060439, 32.8425338513269 }}, + {{ -96.91582107895027, 32.84044912508918 }, { -96.91237686490803, 32.843342851326526 }}, + {{ -96.91554509216175, 32.841130125088874 }, { -96.91210085169466, 32.84402385132622 }}, + {{ -96.9154920940436, 32.84122712508884 }, { -96.91204784981255, 32.844120851326174 }}, + {{ -96.91763698353438, 32.83553012509141 }, { -96.91419296033762, 32.83842385132875 }}, + {{ -96.91782698479507, 32.83559512509137 }, { -96.91438295907676, 32.83848885132871 }}, + {{ -96.91790498623033, 32.83566912509136 }, { -96.91446095764131, 32.83856285132869 }}, + {{ -96.91793998716128, 32.83571712509132 }, { -96.9144959567102, 32.83861085132867 }}, + {{ -96.91795398824742, 32.83577312509131 }, { -96.91450995562391, 32.83866685132865 }}, + {{ -96.91794498995421, 32.83586112509127 }, { -96.91450095391689, 32.8387548513286 }}, + {{ -96.91792399086579, 32.835908125091244 }, { -96.91447995300516, 32.83880185132858 }}, + {{ -96.91772799476429, 32.83610912509115 }, { -96.9142839491061, 32.83900285132848 }}, + {{ -96.91743599908953, 32.83633212509104 }, { -96.91399194478024, 32.839225851328386 }}, + {{ -96.91731000027268, 32.83639312509102 }, { -96.91386594359693, 32.83928685132837 }}, + {{ -96.91714100087395, 32.836424125091014 }, { -96.91369694299557, 32.839317851328346 }}, + {{ -96.91701500079637, 32.83642012509102 }, { -96.91357094307315, 32.839313851328356 }}, + {{ -96.91686200003993, 32.83638112509103 }, { -96.9134179438297, 32.83927485132837 }}, + {{ -96.91678399899256, 32.836327125091046 }, { -96.91333994487724, 32.839220851328385 }}, + {{ -96.91673599821672, 32.83628712509106 }, { -96.91329194565319, 32.83918085132841 }}, + {{ -96.91664699588924, 32.83616712509113 }, { -96.91320294798099, 32.83906085132847 }}, + {{ -96.91660999396908, 32.83606812509117 }, { -96.91316594990144, 32.838961851328506 }}, + {{ -96.91655298974086, 32.83585012509127 }, { -96.91310895413027, 32.8387438513286 }}, + {{ -96.91946491499829, 32.831996125093006 }, { -96.91602102888356, 32.834889851330345 }}, + {{ -96.91948797531097, 32.8351061250916 }, { -96.9160439685622, 32.83799985132893 }}, + {{ -96.9141210940436, 32.84122712508884 }, { -96.91067684981255, 32.844120851326174 }}, + {{ -96.91320906880432, 32.83992612508941 }, { -96.90976487505543, 32.842819851326766 }}, + {{ -96.9121220693087, 32.83995212508941 }, { -96.90867787455099, 32.84284585132676 }}, + {{ -96.91244209338399, 32.84119312508886 }, { -96.90899785047226, 32.844086851326196 }}, + {{ -96.9124390940436, 32.84122712508884 }, { -96.90899484981256, 32.844120851326174 }}, + {{ -96.91330591499829, 32.831996125093006 }, { -96.90986202888357, 32.834889851330345 }}, + {{ -96.9133029196717, 32.83223712509289 }, { -96.90985902420945, 32.835130851330234 }}, + {{ -96.91328095044784, 32.83382412509218 }, { -96.90983699342891, 32.83671785132952 }}, + {{ -96.9132759727315, 32.834973125091665 }, { -96.90983197114207, 32.837866851329 }}, + {{ -96.92212491499828, 32.831996125093006 }, { -96.91868102888355, 32.834889851330345 }}, + {{ -96.92211892374401, 32.8324471250928 }, { -96.91867502013655, 32.83534085133014 }}, + {{ -96.91212191924508, 32.8322151250929 }, { -96.90867802463615, 32.83510885133024 }}, + {{ -96.9133029196717, 32.83223712509289 }, { -96.90985902420945, 32.835130851330234 }}, + {{ -96.91649693584488, 32.833071125092516 }, { -96.91305300803398, 32.83596485132987 }}, + {{ -96.9162339459292, 32.833591125092276 }, { -96.91278999794821, 32.83648485132962 }}, + {{ -96.91604895366716, 32.8339901250921 }, { -96.91260499020915, 32.836883851329446 }}, + {{ -96.9157379672235, 32.8346891250918 }, { -96.91229397665084, 32.83758285132914 }}, + {{ -96.91569496865867, 32.834763125091754 }, { -96.91225097521547, 32.83765685132909 }}, + {{ -96.91562797001627, 32.83483312509173 }, { -96.91218397385767, 32.83772685132906 }}, + {{ -96.91549097154844, 32.83491212509169 }, { -96.9120469723253, 32.83780585132903 }}, + {{ -96.9153969720333, 32.83493712509168 }, { -96.91195297184036, 32.837830851329024 }}, + {{ -96.91492497321636, 32.834998125091644 }, { -96.91148097065712, 32.83789185132899 }}, + {{ -96.91212198846075, 32.835784125091294 }, { -96.90867795541052, 32.83867785132863 }}, + {{ -96.9124169878983, 32.8357551250913 }, { -96.90897295597308, 32.83864885132865 }}, + {{ -96.91274698751039, 32.835735125091325 }, { -96.90930295636103, 32.83862885132866 }}, + {{ -96.91307698723887, 32.835721125091325 }, { -96.90963295663262, 32.838614851328664 }}, + {{ -96.91366998723886, 32.835721125091325 }, { -96.9102259566326, 32.838614851328664 }}, + {{ -96.91411298828622, 32.835775125091295 }, { -96.91066895558512, 32.83866885132864 }}, + {{ -96.91437798960509, 32.835843125091266 }, { -96.91093395426604, 32.83873685132861 }}, + {{ -96.91479399406605, 32.836073125091154 }, { -96.91134994980445, 32.8389668513285 }}, + {{ -96.91791100686734, 32.83673312509086 }, { -96.91446693700134, 32.83962685132821 }}, + {{ -96.91983899055546, 32.83589212509124 }, { -96.91639495331553, 32.838785851328595 }}, + {{ -96.9198870768939, 32.84034312508924 }, { -96.9164428669647, 32.84323685132657 }}, + {{ -96.91905106133568, 32.8395411250896 }, { -96.91560688252517, 32.84243485132695 }}, + {{ -96.91874205582643, 32.83925712508973 }, { -96.91529788803521, 32.84215085132708 }}, + {{ -96.91853305355679, 32.839140125089784 }, { -96.91508889030517, 32.84203385132712 }}, + {{ -96.9183830522377, 32.83907212508981 }, { -96.91493889162446, 32.84196585132715 }}, + {{ -96.9180900509768, 32.83900712508984 }, { -96.91464589288553, 32.84190085132718 }}, + {{ -96.91788605066641, 32.83899112508985 }, { -96.91444189319596, 32.84188485132719 }}, + {{ -96.9169850510544, 32.83901112508983 }, { -96.91354089280793, 32.84190485132717 }}, + {{ -96.91585905289725, 32.83910612508979 }, { -96.91241489096481, 32.84199985132713 }}, + {{ -96.91603805293605, 32.839108125089794 }, { -96.91259389092602, 32.84200185132714 }}, + {{ -96.915872050938, 32.83900512508984 }, { -96.91242789292434, 32.84189885132718 }}, + {{ -96.91577606509908, 32.83973512508951 }, { -96.91233187876121, 32.84262885132685 }}, + {{ -96.91569807266481, 32.84012512508934 }, { -96.91225387119442, 32.843018851326676 }}, + {{ -96.91556408191846, 32.84060212508912 }, { -96.91211986193943, 32.84349585132646 }}, + {{ -96.9154130889995, 32.84096712508895 }, { -96.91196885485739, 32.8438608513263 }}, + {{ -96.9152910940436, 32.84122712508884 }, { -96.91184684981255, 32.844120851326174 }}, + {{ -96.9166410940436, 32.84122712508884 }, { -96.91319684981255, 32.844120851326174 }}, + {{ -96.9166420939854, 32.841224125088836 }, { -96.91319784987074, 32.844117851326175 }}, + {{ -96.91682208428526, 32.84072412508907 }, { -96.9133778595723, 32.84361785132641 }}, + {{ -96.91696607165603, 32.84007312508936 }, { -96.91352187220332, 32.8429668513267 }}, + {{ -96.91704406116109, 32.839532125089605 }, { -96.91359988269978, 32.84242585132694 }}, + {{ -96.91709805320761, 32.83912212508979 }, { -96.91365389065439, 32.84201585132713 }}, + {{ -96.91710605097681, 32.83900712508984 }, { -96.91366189288554, 32.84190085132718 }}, + {{ -96.91719591499829, 32.831996125093006 }, { -96.91375202888356, 32.834889851330345 }}, + {{ -96.91710091928385, 32.83221712509291 }, { -96.91365702459737, 32.83511085133024 }}, + {{ -96.91703592137819, 32.832325125092865 }, { -96.91359202250273, 32.835218851330204 }}, + {{ -96.91698292287138, 32.83240212509282 }, { -96.91353902100933, 32.83529585133016 }}, + {{ -96.91680292740914, 32.832636125092705 }, { -96.91335901647092, 32.83552985133006 }}, + {{ -96.91649693584488, 32.833071125092516 }, { -96.91305300803398, 32.83596485132987 }}, + {{ -96.91479399406605, 32.836073125091154 }, { -96.91134994980445, 32.8389668513285 }}, + {{ -96.91491699577286, 32.836161125091124 }, { -96.9114729480974, 32.83905485132847 }}, + {{ -96.91539700341482, 32.836555125090946 }, { -96.91195294045433, 32.83944885132829 }}, + {{ -96.91541600358939, 32.83656412509095 }, { -96.91197194027974, 32.839457851328284 }}, + {{ -96.91568200805051, 32.83679412509083 }, { -96.91223793581798, 32.83968785132818 }}, + {{ -96.9157760100677, 32.83689812509079 }, { -96.91233193380047, 32.83979185132812 }}, + {{ -96.91588301320994, 32.837060125090716 }, { -96.91243893065779, 32.83995385132806 }}, + {{ -96.91597701722505, 32.83726712509063 }, { -96.91253292664213, 32.840160851327965 }}, + {{ -96.9160140206389, 32.83744312509054 }, { -96.91256992322779, 32.84033685132788 }}, + {{ -96.91604102399457, 32.83761612509046 }, { -96.91259691987165, 32.840509851327816 }}, + {{ -96.91590404407103, 32.83865112509 }, { -96.9124598997923, 32.84154485132734 }}, + {{ -96.915872050938, 32.83900512508984 }, { -96.91242789292434, 32.84189885132718 }}, + {{ -96.91912797538855, 32.835110125091596 }, { -96.91568396848461, 32.838003851328935 }}, + {{ -96.91760197461278, 32.83507012509161 }, { -96.91415796926053, 32.837963851328965 }}, + {{ -96.91749997430246, 32.83505412509162 }, { -96.91405596957087, 32.83794785132897 }}, + {{ -96.91744897391457, 32.835034125091624 }, { -96.91400496995882, 32.83792785132896 }}, + {{ -96.91741197346849, 32.83501112509164 }, { -96.91396797040495, 32.837904851328986 }}, + {{ -96.91736597277028, 32.83497512509165 }, { -96.91392197110326, 32.83786885132899 }}, + {{ -96.91733097199452, 32.83493512509168 }, { -96.91388697187915, 32.83782885132902 }}, + {{ -96.91730997133509, 32.8349011250917 }, { -96.91386597253866, 32.837794851329036 }}, + {{ -96.91729397050113, 32.834858125091706 }, { -96.91384997337273, 32.83775185132905 }}, + {{ -96.91728596914353, 32.83478812509174 }, { -96.91384197473054, 32.83768185132909 }}, + {{ -96.9172859675726, 32.83470712509179 }, { -96.91384197630171, 32.837600851329114 }}, + {{ -96.91738995428774, 32.83402212509209 }, { -96.91394598958846, 32.83691585132943 }}, + {{ -96.91747594183725, 32.833380125092376 }, { -96.91403200204074, 32.83627385132972 }}, + {{ -96.91750293916103, 32.83324212509243 }, { -96.91405900471734, 32.83613585132978 }}, + {{ -96.9175569365818, 32.833109125092506 }, { -96.91411300729696, 32.83600285132985 }}, + {{ -96.9177739272346, 32.83262712509272 }, { -96.91433001664547, 32.83552085133007 }}, + {{ -96.91800491499829, 32.831996125093006 }, { -96.91456102888357, 32.834889851330345 }}, + {{ -96.91710605097681, 32.83900712508984 }, { -96.91366189288554, 32.84190085132718 }}, + {{ -96.91713003817407, 32.83834712509014 }, { -96.9136859056901, 32.84124085132747 }}, + {{ -96.91713302946458, 32.83789812509034 }, { -96.91368891440086, 32.84079185132768 }}, + {{ -96.91718102409155, 32.83762112509046 }, { -96.91373691977464, 32.840514851327804 }}, + {{ -96.91726201976603, 32.83739812509056 }, { -96.91381792410078, 32.8402918513279 }}, + {{ -96.91735801670134, 32.83724012509064 }, { -96.91391392716592, 32.840133851327984 }}, + {{ -96.91748701363667, 32.83708212509072 }, { -96.91404293023102, 32.83997585132805 }}, + {{ -96.91766701031987, 32.836911125090786 }, { -96.91422293354829, 32.83980485132813 }}, + {{ -96.91791100686734, 32.83673312509086 }, { -96.91446693700134, 32.83962685132821 }}, + {{ -96.9211429870643, 32.83571212509132 }, { -96.91769895680719, 32.838605851328666 }}, + {{ -96.92127898816983, 32.83576912509129 }, { -96.9178349557015, 32.83866285132864 }}, + {{ -96.92141898956629, 32.83584112509127 }, { -96.91797495430484, 32.83873485132861 }}, + {{ -96.92153399173858, 32.83595312509122 }, { -96.91808995213223, 32.83884685132857 }}, + {{ -96.92159599327083, 32.83603212509119 }, { -96.91815195059978, 32.838925851328526 }}, + {{ -96.92189401031986, 32.836911125090786 }, { -96.91844993354829, 32.83980485132813 }}, + {{ -96.92201701976603, 32.83739812509056 }, { -96.91857292410077, 32.8402918513279 }}, + {{ -96.92205502409155, 32.83762112509046 }, { -96.91861091977464, 32.840514851327804 }}, + {{ -96.92204903095816, 32.83797512509031 }, { -96.91860491290703, 32.84086885132764 }}, + {{ -96.92194503724296, 32.83829912509015 }, { -96.91850090662132, 32.84119285132749 }}, + {{ -96.92179404306233, 32.83859912509002 }, { -96.91834990080113, 32.84149285132736 }}, + {{ -96.9216200475239, 32.83882912508992 }, { -96.91817589633894, 32.84172285132727 }}, + {{ -96.92153404905635, 32.83890812508988 }, { -96.91808989480624, 32.84180185132723 }}, + {{ -96.92114805516688, 32.839223125089745 }, { -96.91770388869487, 32.842116851327084 }}, + {{ -96.91973407553594, 32.84027312508926 }, { -96.91628986832288, 32.84316685132661 }}, + {{ -96.91925208232587, 32.8406231250891 }, { -96.91580786153199, 32.84351685132645 }}, + {{ -96.91909608477026, 32.84074912508905 }, { -96.91565185908723, 32.8436428513264 }}, + {{ -96.9184490940436, 32.84122712508884 }, { -96.91500484981255, 32.844120851326174 }}, + {{ -96.91870309404361, 32.84122712508884 }, { -96.91525884981256, 32.844120851326174 }}, + {{ -96.91880109264676, 32.841155125088875 }, { -96.9153568512096, 32.84404885132621 }}, + {{ -96.91920908661328, 32.84084412508902 }, { -96.91576485724394, 32.84373785132635 }}, + {{ -96.91983607759231, 32.840379125089214 }, { -96.91639186626621, 32.84327285132656 }}, + {{ -96.92170605097681, 32.83900712508984 }, { -96.91826189288554, 32.84190085132718 }}, + {{ -96.92195804668978, 32.83878612508993 }, { -96.91851389717318, 32.84167985132728 }}, + {{ -96.9221510414911, 32.838518125090054 }, { -96.91870690237259, 32.84141185132741 }}, + {{ -96.92223403860082, 32.83836912509012 }, { -96.91878990526328, 32.841262851327464 }}, + {{ -96.92231203357683, 32.838110125090246 }, { -96.918867910288, 32.841003851327585 }}, + {{ -96.92233402802918, 32.83782412509037 }, { -96.91888991583646, 32.84071785132771 }}, + {{ -96.92232602628341, 32.837734125090414 }, { -96.91888191758245, 32.84062785132776 }}, + {{ -96.92229602360662, 32.83759612509048 }, { -96.91885192025964, 32.84048985132782 }}, + {{ -96.92213801443192, 32.83712312509069 }, { -96.91869392943565, 32.84001685132803 }}, + {{ -96.92208701094057, 32.83694312509076 }, { -96.91864293292753, 32.83983685132811 }}, + {{ -96.92206300843843, 32.83681412509083 }, { -96.91861893543, 32.83970785132817 }}, + {{ -96.92202200568417, 32.836672125090885 }, { -96.91857793818467, 32.83956585132823 }}, + {{ -96.92200400227046, 32.836496125090974 }, { -96.91855994159886, 32.83938985132831 }}, + {{ -96.92199599852705, 32.836303125091064 }, { -96.9185519453428, 32.8391968513284 }}, + {{ -96.92201699567589, 32.83615612509112 }, { -96.91857294819438, 32.83904985132846 }}, + {{ -96.92204099437637, 32.836089125091156 }, { -96.91859694949407, 32.8389828513285 }}, + {{ -96.92211899187434, 32.83596012509121 }, { -96.91867495199645, 32.83885385132855 }}, + {{ -96.9222369895663, 32.83584112509127 }, { -96.91879295430485, 32.83873485132861 }}, + {{ -96.92232298838319, 32.8357801250913 }, { -96.91887895548814, 32.83867385132864 }}, + {{ -96.92244898727766, 32.83572312509131 }, { -96.91900495659381, 32.83861685132866 }}, + {{ -96.91613197587343, 32.83513512509158 }, { -96.9126879679997, 32.838028851328936 }}, + {{ -96.91590997566009, 32.8351241250916 }, { -96.91246596821304, 32.83801785132894 }}, + {{ -96.91492497321636, 32.834998125091644 }, { -96.91148097065712, 32.83789185132899 }}, + {{ -96.9160460509768, 32.83900712508984 }, { -96.91260189288553, 32.84190085132718 }}, + {{ -96.915872050938, 32.83900512508984 }, { -96.91242789292434, 32.84189885132718 }}, + {{ -96.92310897612555, 32.83514812509159 }, { -96.91966496774752, 32.838041851328924 }}, + {{ -96.92253697610617, 32.83514712509158 }, { -96.91909296776691, 32.83804085132892 }}, + {{ -96.91948797531097, 32.8351061250916 }, { -96.9160439685622, 32.83799985132893 }}, + {{ -96.91912797538855, 32.835110125091596 }, { -96.91568396848461, 32.838003851328935 }}, + {{ -96.91757297662981, 32.83517412509158 }, { -96.91412896724319, 32.838067851328915 }}, + {{ -96.91718097662981, 32.83517412509158 }, { -96.91373696724318, 32.838067851328915 }}, + {{ -96.91685097635828, 32.835160125091576 }, { -96.91340696751473, 32.838053851328915 }}, + {{ -96.91983899055546, 32.83589212509124 }, { -96.91639495331553, 32.838785851328595 }}, + {{ -96.92004598886807, 32.83580512509128 }, { -96.91660195500317, 32.838698851328616 }}, + {{ -96.92030798758799, 32.835739125091315 }, { -96.91686395628346, 32.83863285132866 }}, + {{ -96.9205659871031, 32.83571412509132 }, { -96.91712195676841, 32.83860785132867 }}, + {{ -96.9211429870643, 32.83571212509132 }, { -96.91769895680719, 32.838605851328666 }}, + {{ -96.92244898727766, 32.83572312509131 }, { -96.91900495659381, 32.83861685132866 }}, + {{ -96.92310898727766, 32.83572312509131 }, { -96.9196649565938, 32.83861685132866 }}, + {{ -96.91492497321636, 32.834998125091644 }, { -96.91148097065712, 32.83789185132899 }}, + {{ -96.9148639730806, 32.83499112509165 }, { -96.9114199707929, 32.83788485132899 }}, + {{ -96.9147209730806, 32.83499112509165 }, { -96.91127697079291, 32.83788485132899 }}, + {{ -96.91449597286727, 32.834980125091654 }, { -96.91105197100629, 32.837873851329 }}, + {{ -96.91429497298361, 32.834986125091646 }, { -96.9108509708899, 32.83787985132899 }}, + {{ -96.9132759727315, 32.834973125091665 }, { -96.90983197114207, 32.837866851329 }}, + {{ -96.91212197265392, 32.83496912509166 }, { -96.90867797121963, 32.83786285132901 }}, + {{ -96.91697505311063, 32.839117125089786 }, { -96.9135308907514, 32.842010851327124 }}, + {{ -96.91709805320761, 32.83912212508979 }, { -96.91365389065439, 32.84201585132713 }}, + {{ -96.91753805307184, 32.83911512508979 }, { -96.9140938907902, 32.84200885132714 }}, + {{ -96.91791905316883, 32.83912012508979 }, { -96.91447489069319, 32.842013851327124 }}, + {{ -96.91820005377018, 32.83915112508977 }, { -96.91475589009175, 32.842044851327124 }}, + {{ -96.91834505460432, 32.839194125089755 }, { -96.91490088925751, 32.84208785132709 }}, + {{ -96.91847905578763, 32.83925512508973 }, { -96.91503488807402, 32.842148851327075 }}, + {{ -96.9186350575723, 32.83934712508969 }, { -96.91519088628907, 32.84224085132703 }}, + {{ -96.9190480646141, 32.83971012508952 }, { -96.91560387924628, 32.84260385132687 }}, + {{ -96.91917406684502, 32.83982512508947 }, { -96.91572987701505, 32.8427188513268 }}, + {{ -96.91967807633132, 32.84031412508924 }, { -96.91623386752738, 32.843207851326596 }}, + {{ -96.91978307838768, 32.8404201250892 }, { -96.9163388654707, 32.84331385132655 }}, + {{ -96.9162220940436, 32.84122712508884 }, { -96.91277784981256, 32.844120851326174 }}, + {{ -96.91626909132755, 32.841087125088904 }, { -96.912824852529, 32.84398085132624 }}, + {{ -96.91643008040526, 32.84052412508915 }, { -96.91298586345285, 32.84341785132649 }}, + {{ -96.91652407074426, 32.84002612508938 }, { -96.91307987311522, 32.84291985132673 }}, + {{ -96.91658006308158, 32.83963112508957 }, { -96.91313588077902, 32.8425248513269 }}, + {{ -96.91660405656359, 32.839295125089706 }, { -96.91315988729797, 32.842188851327045 }}, + {{ -96.9166290465152, 32.83877712508994 }, { -96.91318489734778, 32.84167085132729 }}, + {{ -96.91663703646707, 32.83825912509018 }, { -96.91319290739735, 32.84115285132752 }}, + {{ -96.91660702440191, 32.83763712509046 }, { -96.91316291946426, 32.840530851327806 }}, + {{ -96.9165480055096, 32.83666312509089 }, { -96.91310393835924, 32.83955685132825 }}, + {{ -96.91655298974086, 32.83585012509127 }, { -96.91310895413027, 32.8387438513286 }}, + {{ -96.91670898176945, 32.83543912509145 }, { -96.91326496210282, 32.838332851328786 }}, + {{ -96.91681398182763, 32.83544212509144 }, { -96.91336996204461, 32.83833585132879 }}, + {{ -96.91624797938387, 32.83531612509151 }, { -96.91280396448872, 32.83820985132885 }}, + {{ -96.91587697928689, 32.83531112509151 }, { -96.9124329645857, 32.83820485132886 }}, + {{ -96.9121219792869, 32.83531112509151 }, { -96.9086779645857, 32.83820485132886 }}, + {{ -96.92310898035362, 32.83536612509148 }, { -96.91966496351884, 32.83825985132882 }}, + {{ -96.9205469800239, 32.83534912509149 }, { -96.9171029638486, 32.838242851328836 }}, + {{ -96.91807997959722, 32.8353271250915 }, { -96.91463596427536, 32.83822085132884 }}, + {{ -96.91672497946146, 32.83532012509149 }, { -96.91328096441114, 32.838213851328845 }}, + {{ -96.91655298974086, 32.83585012509127 }, { -96.91310895413027, 32.8387438513286 }}, + {{ -96.91659397744439, 32.835216125091556 }, { -96.91314996642849, 32.838109851328895 }}, + {{ -96.91675496210344, 32.834425125091904 }, { -96.91331098177162, 32.83731885132925 }}, + {{ -96.91686195411319, 32.8340131250921 }, { -96.91341798976302, 32.83690685132943 }}, + {{ -96.91694794930363, 32.83376512509221 }, { -96.9135039945733, 32.836658851329545 }}, + {{ -96.91757491998197, 32.83225312509288 }, { -96.91413102389916, 32.83514685133023 }}, + {{ -96.91767191499827, 32.831996125093006 }, { -96.91422802888354, 32.834889851330345 }}, + {{ -96.91681398182763, 32.83544212509144 }, { -96.91336996204461, 32.83833585132879 }}, + {{ -96.91811998186644, 32.835444125091456 }, { -96.91467596200583, 32.838337851328795 }}, + {{ -96.92126898326285, 32.835516125091424 }, { -96.91782496060918, 32.83840985132876 }}, + {{ -96.92304398304951, 32.835505125091416 }, { -96.91959996082257, 32.838398851328755 }}, + {{ -96.92310898304952, 32.835505125091416 }, { -96.91966496082256, 32.838398851328755 }}, + {{ -96.91212198413564, 32.835561125091395 }, { -96.90867795973627, 32.838454851328734 }}, + {{ -96.91239298353439, 32.83553012509141 }, { -96.90894896033761, 32.83842385132875 }}, + {{ -96.91282198283616, 32.83549412509143 }, { -96.90937796103594, 32.83838785132877 }}, + {{ -96.91326498252585, 32.835478125091434 }, { -96.9098209613463, 32.83837185132878 }}, + {{ -96.9143589820022, 32.83545112509144 }, { -96.91091496187005, 32.838344851328785 }}, + {{ -96.91522298176945, 32.83543912509145 }, { -96.91177896210282, 32.838332851328786 }}, + {{ -96.91624998165308, 32.835433125091456 }, { -96.9128059622192, 32.8383268513288 }}, + {{ -96.91749191499827, 32.831996125093006 }, { -96.91404802888356, 32.834889851330345 }}, + {{ -96.91739291984624, 32.83224612509289 }, { -96.91394902403492, 32.835139851330226 }}, + {{ -96.91706593584487, 32.833071125092516 }, { -96.91362200803398, 32.83596485132987 }}, + {{ -96.91653196285982, 32.83446412509189 }, { -96.91308798101515, 32.83735785132922 }}, + {{ -96.91647596704895, 32.83468012509178 }, { -96.91303197682542, 32.83757385132914 }}, + {{ -96.91637897736683, 32.835212125091545 }, { -96.91293496650609, 32.83810585132889 }}, + {{ -96.91633899406605, 32.836073125091154 }, { -96.91289494980445, 32.8389668513285 }}, + {{ -96.91631701425736, 32.837114125090686 }, { -96.91287292961024, 32.84000785132803 }}, + {{ -96.91632503611791, 32.838241125090185 }, { -96.91288090774655, 32.84113485132754 }}, + {{ -96.91630905561304, 32.83924612508974 }, { -96.91286488824862, 32.84213985132708 }}, + {{ -96.91623406566167, 32.8397641250895 }, { -96.91278987819858, 32.84265785132684 }}, + {{ -96.91614307448836, 32.84021912508929 }, { -96.9126988693706, 32.84311285132663 }}, + {{ -96.91600608477026, 32.84074912508905 }, { -96.91256185908722, 32.8436428513264 }}, + {{ -96.91581909404358, 32.84122712508884 }, { -96.91237484981255, 32.844120851326174 }}, + {{ -96.91603805293605, 32.839108125089794 }, { -96.91259389092602, 32.84200185132714 }}, + {{ -96.91697505311063, 32.839117125089786 }, { -96.9135308907514, 32.842010851327124 }}, + {{ -96.91858398716128, 32.83571712509132 }, { -96.9151399567102, 32.83861085132867 }}, + {{ -96.91909898943054, 32.83583412509127 }, { -96.91565495444063, 32.83872785132861 }}, + {{ -96.91685097635828, 32.835160125091576 }, { -96.91340696751473, 32.838053851328915 }}, + {{ -96.91613197587343, 32.83513512509158 }, { -96.9126879679997, 32.838028851328936 }}, + {{ -96.9169850510544, 32.83901112508983 }, { -96.91354089280793, 32.84190485132717 }}, + {{ -96.9160460509768, 32.83900712508984 }, { -96.91260189288553, 32.84190085132718 }}, + {{ -96.91624998165308, 32.835433125091456 }, { -96.9128059622192, 32.8383268513288 }}, + {{ -96.91670898176945, 32.83543912509145 }, { -96.91326496210282, 32.838332851328786 }}, + {{ -96.91672497946146, 32.83532012509149 }, { -96.91328096441114, 32.838213851328845 }}, + {{ -96.91624797938387, 32.83531612509151 }, { -96.91280396448872, 32.83820985132885 }} +}; diff --git a/third_party/geometry.hpp-0.9.2/.gitignore b/third_party/geometry.hpp-0.9.2/.gitignore new file mode 100644 index 00000000000..204298f2389 --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/.gitignore @@ -0,0 +1,2 @@ +mason_packages +test diff --git a/third_party/geometry.hpp-0.9.2/.gitmodules b/third_party/geometry.hpp-0.9.2/.gitmodules new file mode 100644 index 00000000000..44fba9a2fd4 --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/.gitmodules @@ -0,0 +1,3 @@ +[submodule ".mason"] + path = .mason + url = https://github.com/mapbox/mason.git diff --git a/third_party/geometry.hpp-0.9.2/.travis.yml b/third_party/geometry.hpp-0.9.2/.travis.yml new file mode 100644 index 00000000000..a567bdc5d8d --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/.travis.yml @@ -0,0 +1,50 @@ +language: generic +sudo: false + +matrix: + include: + - os: linux + env: CXX=g++-4.9 + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'g++-4.9' ] + - os: linux + env: CXX=g++-5 + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'g++-5' ] + - os: linux + env: CXX=g++-6 + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'g++-6' ] + - os: linux + env: CXX=clang++-3.8 + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'libstdc++-4.9-dev' ] + before_script: + - git submodule update --init + - .mason/mason install clang++ 3.8.1 + - export PATH=$(.mason/mason prefix clang++ 3.8.1)/bin:$PATH + - os: linux + env: CXX=clang++-3.9 + addons: + apt: + sources: [ 'ubuntu-toolchain-r-test' ] + packages: [ 'libstdc++-4.9-dev' ] + before_script: + - git submodule update --init + - .mason/mason install clang++ 3.9.1 + - export PATH=$(.mason/mason prefix clang++ 3.9.1)/bin:$PATH + - os: osx + osx_image: xcode7.3 + +cache: apt + +script: + - make test diff --git a/third_party/geometry.hpp-0.9.2/LICENSE b/third_party/geometry.hpp-0.9.2/LICENSE new file mode 100644 index 00000000000..8f6a86bd07e --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2016, Mapbox + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/third_party/geometry.hpp-0.9.2/Makefile b/third_party/geometry.hpp-0.9.2/Makefile new file mode 100644 index 00000000000..ec95379ec22 --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/Makefile @@ -0,0 +1,19 @@ +CXXFLAGS += -I include -std=c++14 -DDEBUG -O0 -Wall -Wextra -Werror +MASON ?= .mason/mason + +VARIANT = 1.1.4 + +default: test + +$(MASON): + git submodule update --init + +mason_packages/headers/variant/$(VARIANT): + $(MASON) install variant $(VARIANT) + +test: tests/* include/mapbox/geometry/* mason_packages/headers/variant/$(VARIANT) Makefile + $(CXX) tests/*.cpp $(CXXFLAGS) `$(MASON) cflags variant $(VARIANT)` -o test + ./test + +clean: + rm -f test diff --git a/third_party/geometry.hpp-0.9.2/README.md b/third_party/geometry.hpp-0.9.2/README.md new file mode 100644 index 00000000000..972614a3bc9 --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/README.md @@ -0,0 +1,83 @@ +# geometry.hpp + +Provides header-only, generic C++ interfaces for geometry types, geometry collections, and features. + + - `mapbox::geometry::point` + - `mapbox::geometry::multi_point` + - `mapbox::geometry::line_string` + - `mapbox::geometry::multi_line_string` + - `mapbox::geometry::polygon` + - `mapbox::geometry::multi_polygon` + - `mapbox::geometry::geometry_collection` + - `mapbox::geometry::feature` (experimental) + +### Design + +These types are designed to be easy to parse and serialize to [GeoJSON](http://geojson.org/). + +They should also be a robust and high performance container for data processing and conversion. + + +### Goals + + - Header-only + - Fast compile + - c++11/c++14 compatibility + - No external dependencies for usage of core types (point, line_string, etc) + - Minimal dependencies for usage of enclosing `geometry` type (`mapbox::variant`) + - Easily [adaptable to `boost::geometry`](http://www.boost.org/doc/libs/1_56_0/libs/geometry/doc/html/geometry/examples/example__adapting_a_legacy_geometry_object_model.html) + + +### Usage + +Using a single type directly (requires no external dependencies): + +```cpp +#include +#include + +using mapbox::geometry::point; + +int main() { + point pt(1.0,0.0); + std::clog << "x: " << pt.x << " y: " << pt.y << "\n"; +} +``` + +Creating a geometry collection (depends on https://github.com/mapbox/variant): + +```cpp +#include +#include +#include + +using mapbox::geometry::geometry_collection; +using mapbox::geometry::geometry; +using mapbox::geometry::point; + +using point_type = point; + +struct printer +{ + printer() {} + + void operator()(point_type const& pt) const + { + std::clog << "x: " << pt.x << " y: " << pt.y << "\n"; + } + + template + void operator()(T const& g) const + { + std::clog << "encountered non-point geometry\n"; + } +}; + +int main() { + geometry_collection gc; + gc.emplace_back(point_type(1.0,0.0)); + geometry const& geom = gc.at(0); + printer visitor; + mapbox::util::apply_visitor(visitor,geom); +} +``` diff --git a/third_party/geometry.hpp-0.9.2/include/mapbox/geometry.hpp b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry.hpp new file mode 100644 index 00000000000..e232453179e --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/box.hpp b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/box.hpp new file mode 100644 index 00000000000..bf81b703ecd --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/box.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + +namespace mapbox { +namespace geometry { + +template +struct box +{ + using point_type = point; + + constexpr box(point_type const& min_, point_type const& max_) + : min(min_), max(max_) + {} + + point_type min; + point_type max; +}; + +template +constexpr bool operator==(box const& lhs, box const& rhs) +{ + return lhs.min == rhs.min && lhs.max == rhs.max; +} + +template +constexpr bool operator!=(box const& lhs, box const& rhs) +{ + return lhs.min != rhs.min || lhs.max != rhs.max; +} + +} // namespace geometry +} // namespace mapbox diff --git a/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/envelope.hpp b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/envelope.hpp new file mode 100644 index 00000000000..86035839858 --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/envelope.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +#include + +namespace mapbox { +namespace geometry { + +template +box envelope(G const& geometry) +{ + using limits = std::numeric_limits; + + T min_t = limits::has_infinity ? -limits::infinity() : limits::min(); + T max_t = limits::has_infinity ? limits::infinity() : limits::max(); + + point min(max_t, max_t); + point max(min_t, min_t); + + for_each_point(geometry, [&] (point const& point) { + if (min.x > point.x) min.x = point.x; + if (min.y > point.y) min.y = point.y; + if (max.x < point.x) max.x = point.x; + if (max.y < point.y) max.y = point.y; + }); + + return box(min, max); +} + +} // namespace geometry +} // namespace mapbox diff --git a/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/feature.hpp b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/feature.hpp new file mode 100644 index 00000000000..20d2ddf6b8f --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/feature.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include + +#include + +#include +#include +#include +#include +#include + +namespace mapbox { +namespace geometry { + +struct value; + +struct null_value_t +{ + constexpr null_value_t() {} + constexpr null_value_t(std::nullptr_t) {} +}; + +constexpr bool operator==(const null_value_t&, const null_value_t&) { return true; } +constexpr bool operator!=(const null_value_t&, const null_value_t&) { return false; } +constexpr bool operator<(const null_value_t&, const null_value_t&) { return false; } + +constexpr null_value_t null_value = null_value_t(); + +// Multiple numeric types (uint64_t, int64_t, double) are present in order to support +// the widest possible range of JSON numbers, which do not have a maximum range. +// Implementations that produce `value`s should use that order for type preference, +// using uint64_t for positive integers, int64_t for negative integers, and double +// for non-integers and integers outside the range of 64 bits. +using value_base = mapbox::util::variant>, + mapbox::util::recursive_wrapper>>; + +struct value : value_base +{ + using value_base::value_base; +}; + +using property_map = std::unordered_map; + +// The same considerations and requirement for numeric types apply as for `value_base`. +using identifier = mapbox::util::variant; + +template +struct feature +{ + using coordinate_type = T; + using geometry_type = mapbox::geometry::geometry; // Fully qualified to avoid GCC -fpermissive error. + + geometry_type geometry; + property_map properties {}; + std::experimental::optional id {}; + + // GCC 4.9 does not support C++14 aggregates with non-static data member + // initializers. + feature(geometry_type geometry_, + property_map properties_ = property_map {}, + std::experimental::optional id_ = std::experimental::optional {}) + : geometry(std::move(geometry_)), + properties(std::move(properties_)), + id(std::move(id_)) {} +}; + +template +constexpr bool operator==(feature const& lhs, feature const& rhs) +{ + return lhs.id == rhs.id && lhs.geometry == rhs.geometry && lhs.properties == rhs.properties; +} + +template +constexpr bool operator!=(feature const& lhs, feature const& rhs) +{ + return !(lhs == rhs); +} + +template class Cont = std::vector> +struct feature_collection : Cont> +{ + using coordinate_type = T; + using feature_type = feature; + using container_type = Cont; + using container_type::container_type; +}; + +} // namespace geometry +} // namespace mapbox diff --git a/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/for_each_point.hpp b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/for_each_point.hpp new file mode 100644 index 00000000000..44d6e77bd0f --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/for_each_point.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include + +namespace mapbox { +namespace geometry { + +template +auto for_each_point(Point&& point, F&& f) + -> decltype(point.x, point.y, void()) +{ + f(std::forward(point)); +} + +template +auto for_each_point(Container&& container, F&& f) + -> decltype(container.begin(), container.end(), void()); + +template +void for_each_point(mapbox::util::variant const& geom, F&& f) +{ + mapbox::util::variant::visit(geom, [&] (auto const& g) { + for_each_point(g, f); + }); +} + +template +void for_each_point(mapbox::util::variant & geom, F&& f) +{ + mapbox::util::variant::visit(geom, [&] (auto & g) { + for_each_point(g, f); + }); +} + +template +auto for_each_point(Container&& container, F&& f) + -> decltype(container.begin(), container.end(), void()) +{ + for (auto& e: container) { + for_each_point(e, f); + } +} + +} // namespace geometry +} // namespace mapbox diff --git a/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/geometry.hpp b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/geometry.hpp new file mode 100644 index 00000000000..a9d072be7e2 --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/geometry.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include + +// stl +#include + +namespace mapbox { +namespace geometry { + +template class Cont = std::vector> +struct geometry_collection; + +template +using geometry_base = mapbox::util::variant, + line_string, + polygon, + multi_point, + multi_line_string, + multi_polygon, + geometry_collection>; + +template +struct geometry : geometry_base +{ + using coordinate_type = T; + using geometry_base::geometry_base; + + /* + * The default constructor would create a point geometry with default-constructed coordinates; + * i.e. (0, 0). Since this is not particularly useful, and could hide bugs, it is disabled. + */ + geometry() = delete; +}; + +template class Cont> +struct geometry_collection : Cont> +{ + using coordinate_type = T; + using geometry_type = geometry; + using container_type = Cont; + + geometry_collection() = default; + geometry_collection(geometry_collection const&) = default; + geometry_collection(geometry_collection &&) = default; + geometry_collection(std::initializer_list && args) + : container_type(std::forward>(args)) {}; +}; + +} // namespace geometry +} // namespace mapbox diff --git a/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/line_string.hpp b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/line_string.hpp new file mode 100644 index 00000000000..6d811ce2210 --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/line_string.hpp @@ -0,0 +1,21 @@ +#pragma once + +// mapbox +#include +// stl +#include + +namespace mapbox { +namespace geometry { + +template class Cont = std::vector> +struct line_string : Cont > +{ + using coordinate_type = T; + using point_type = point; + using container_type = Cont; + using container_type::container_type; +}; + +} // namespace geometry +} // namespace mapbox diff --git a/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_line_string.hpp b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_line_string.hpp new file mode 100644 index 00000000000..07a7a1d609d --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_line_string.hpp @@ -0,0 +1,21 @@ +#pragma once + +// mapbox +#include +// stl +#include + +namespace mapbox { +namespace geometry { + +template class Cont = std::vector> +struct multi_line_string : Cont> +{ + using coordinate_type = T; + using line_string_type = line_string; + using container_type = Cont; + using container_type::container_type; +}; + +} // namespace geometry +} // namespace mapbox diff --git a/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_point.hpp b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_point.hpp new file mode 100644 index 00000000000..a3c73cff912 --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_point.hpp @@ -0,0 +1,21 @@ +#pragma once + +// mapbox +#include +// stl +#include + +namespace mapbox { +namespace geometry { + +template class Cont = std::vector> +struct multi_point : Cont> +{ + using coordinate_type = T; + using point_type = point; + using container_type = Cont; + using container_type::container_type; +}; + +} // namespace geometry +} // namespace mapbox diff --git a/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_polygon.hpp b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_polygon.hpp new file mode 100644 index 00000000000..ad230a04c85 --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_polygon.hpp @@ -0,0 +1,21 @@ +#pragma once + +// mapbox +#include +// stl +#include + +namespace mapbox { +namespace geometry { + +template class Cont = std::vector> +struct multi_polygon : Cont> +{ + using coordinate_type = T; + using polygon_type = polygon; + using container_type = Cont; + using container_type::container_type; +}; + +} // namespace geometry +} // namespace mapbox diff --git a/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/point.hpp b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/point.hpp new file mode 100644 index 00000000000..0cba4996e7f --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/point.hpp @@ -0,0 +1,35 @@ +#pragma once + +namespace mapbox { +namespace geometry { + +template +struct point +{ + using coordinate_type = T; + + constexpr point() + : x(), y() + {} + constexpr point(T x_, T y_) + : x(x_), y(y_) + {} + + T x; + T y; +}; + +template +constexpr bool operator==(point const& lhs, point const& rhs) +{ + return lhs.x == rhs.x && lhs.y == rhs.y; +} + +template +constexpr bool operator!=(point const& lhs, point const& rhs) +{ + return !(lhs == rhs); +} + +} // namespace geometry +} // namespace mapbox diff --git a/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/point_arithmetic.hpp b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/point_arithmetic.hpp new file mode 100644 index 00000000000..0c4c63278a5 --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/point_arithmetic.hpp @@ -0,0 +1,119 @@ +#pragma once + +namespace mapbox { +namespace geometry { + +template +point operator+(point const& lhs, point const& rhs) +{ + return point(lhs.x + rhs.x, lhs.y + rhs.y); +} + +template +point operator+(point const& lhs, T const& rhs) +{ + return point(lhs.x + rhs, lhs.y + rhs); +} + +template +point operator-(point const& lhs, point const& rhs) +{ + return point(lhs.x - rhs.x, lhs.y - rhs.y); +} + +template +point operator-(point const& lhs, T const& rhs) +{ + return point(lhs.x - rhs, lhs.y - rhs); +} + +template +point operator*(point const& lhs, point const& rhs) +{ + return point(lhs.x * rhs.x, lhs.y * rhs.y); +} + +template +point operator*(point const& lhs, T const& rhs) +{ + return point(lhs.x * rhs, lhs.y * rhs); +} + +template +point operator/(point const& lhs, point const& rhs) +{ + return point(lhs.x / rhs.x, lhs.y / rhs.y); +} + +template +point operator/(point const& lhs, T const& rhs) +{ + return point(lhs.x / rhs, lhs.y / rhs); +} + +template +point& operator+=(point& lhs, point const& rhs) +{ + lhs.x += rhs.x; + lhs.y += rhs.y; + return lhs; +} + +template +point& operator+=(point& lhs, T const& rhs) +{ + lhs.x += rhs; + lhs.y += rhs; + return lhs; +} + +template +point& operator-=(point& lhs, point const& rhs) +{ + lhs.x -= rhs.x; + lhs.y -= rhs.y; + return lhs; +} + +template +point& operator-=(point& lhs, T const& rhs) +{ + lhs.x -= rhs; + lhs.y -= rhs; + return lhs; +} + +template +point& operator*=(point& lhs, point const& rhs) +{ + lhs.x *= rhs.x; + lhs.y *= rhs.y; + return lhs; +} + +template +point& operator*=(point& lhs, T const& rhs) +{ + lhs.x *= rhs; + lhs.y *= rhs; + return lhs; +} + +template +point& operator/=(point& lhs, point const& rhs) +{ + lhs.x /= rhs.x; + lhs.y /= rhs.y; + return lhs; +} + +template +point& operator/=(point& lhs, T const& rhs) +{ + lhs.x /= rhs; + lhs.y /= rhs; + return lhs; +} + +} // namespace geometry +} // namespace mapbox diff --git a/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/polygon.hpp b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/polygon.hpp new file mode 100644 index 00000000000..99a66aa1259 --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/polygon.hpp @@ -0,0 +1,31 @@ +#pragma once + +// mapbox +#include + +// stl +#include + +namespace mapbox { +namespace geometry { + +template class Cont = std::vector> +struct linear_ring : Cont> +{ + using coordinate_type = T; + using point_type = point; + using container_type = Cont; + using container_type::container_type; +}; + +template class Cont = std::vector> +struct polygon : Cont> +{ + using coordinate_type = T; + using linear_ring_type = linear_ring; + using container_type = Cont; + using container_type::container_type; +}; + +} // namespace geometry +} // namespace mapbox diff --git a/third_party/geometry.hpp-0.9.2/tests/collection.cpp b/third_party/geometry.hpp-0.9.2/tests/collection.cpp new file mode 100644 index 00000000000..a3105a4e883 --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/tests/collection.cpp @@ -0,0 +1,5 @@ +#include + +void test() { + mapbox::geometry::geometry_collection gc; +} diff --git a/third_party/geometry.hpp-0.9.2/tests/test.cpp b/third_party/geometry.hpp-0.9.2/tests/test.cpp new file mode 100644 index 00000000000..fcbde4fdcb5 --- /dev/null +++ b/third_party/geometry.hpp-0.9.2/tests/test.cpp @@ -0,0 +1,260 @@ +#include + +#include + +using namespace mapbox::geometry; + +static void testPoint() { + point p1; + assert(int(p1.x) == 0); + assert(int(p1.y) == 0); + + point p2(2, 3); + point p3(4, 6); + + assert((p2 + p3) == point(6, 9)); + assert((p2 + 1u) == point(3, 4)); + assert((p3 - p2) == point(2, 3)); + assert((p3 - 1u) == point(3, 5)); + assert((p3 * p2) == point(8, 18)); + assert((p2 * 2u) == point(4, 6)); + assert((p3 / p2) == point(2, 2)); + assert((p3 / 2u) == point(2, 3)); + + { point p(2, 3); assert((p += p3) == point(6, 9)); } + { point p(2, 3); assert((p += 1u) == point(3, 4)); } + { point p(4, 6); assert((p -= p2) == point(2, 3)); } + { point p(4, 6); assert((p -= 1u) == point(3, 5)); } + { point p(4, 6); assert((p *= p2) == point(8, 18)); } + { point p(2, 3); assert((p *= 2u) == point(4, 6)); } + { point p(4, 6); assert((p /= p2) == point(2, 2)); } + { point p(4, 6); assert((p /= 2u) == point(2, 3)); } +} + +static void testMultiPoint() { + multi_point mp1; + assert(mp1.size() == 0); + + multi_point mp2(10); + assert(mp2.size() == 10); + + assert(mp1 == mp1); + assert(!(mp1 != mp1)); + assert(mp1 != mp2); +} + +static void testLineString() { + line_string ls1; + assert(ls1.size() == 0); + + line_string ls2(10); + assert(ls2.size() == 10); + + assert(ls1 == ls1); + assert(!(ls1 != ls1)); + assert(ls1 != ls2); +} + +static void testMultiLineString() { + multi_line_string mls1; + assert(mls1.size() == 0); + + multi_line_string mls2(10); + assert(mls2.size() == 10); + + assert(mls1 == mls1); + assert(!(mls1 != mls1)); + assert(mls1 != mls2); +} + +static void testPolygon() { + polygon pg1; + assert(pg1.size() == 0); + + polygon pg2({{{0, 1}}}); + assert(pg2.size() == 1); + assert(pg2[0].size() == 1); + assert(pg2[0][0] == point(0, 1)); + + assert(pg1 == pg1); + assert(!(pg1 != pg1)); + assert(pg1 != pg2); +} + +static void testMultiPolygon() { + multi_polygon mpg1; + assert(mpg1.size() == 0); + + multi_polygon mpg2(10); + assert(mpg2.size() == 10); + + assert(mpg1 == mpg1); + assert(!(mpg1 != mpg1)); + assert(mpg1 != mpg2); +} + +static void testGeometry() { + geometry pg { point() }; + assert(pg.is>()); + + geometry lsg { line_string() }; + assert(lsg.is>()); + + geometry pgg { polygon() }; + assert(pgg.is>()); + + geometry mpg { multi_point() }; + assert(mpg.is>()); + + geometry mlsg { multi_line_string() }; + assert(mlsg.is>()); + + geometry mpgg { multi_polygon() }; + assert(mpgg.is>()); + + geometry gcg { geometry_collection() }; + assert(gcg.is>()); + + assert(pg == pg); + assert(!(pg != pg)); + assert(pg != lsg); +} + +static void testGeometryCollection() { + geometry_collection gc1; + assert(gc1.size() == 0); + + assert(gc1 == gc1); + assert(!(gc1 != gc1)); +} + +static void testFeature() { + feature pf { point() }; + assert(pf.geometry.is>()); + assert(pf.properties.size() == 0); + + auto &p = pf.properties; + + p["bool"] = true; + p["string"] = std::string("foo"); + p["double"] = 2.5; + p["uint"] = uint64_t(10); + p["int"] = int64_t(-10); + p["null"] = null_value; + + assert(p["bool"].is()); + assert(p["bool"] == true); + assert(p["string"].is()); + assert(p["string"] == std::string("foo")); + assert(p["double"].is()); + assert(p["double"] == 2.5); + assert(p["uint"].is()); + assert(p["uint"] == uint64_t(10)); + assert(p["int"].is()); + assert(p["int"] == int64_t(-10)); + assert(p["null"].is()); + assert(p["null"] == null_value); + + p["null"] = null_value_t{}; + assert(p["null"].is()); + assert(p["null"] == null_value); + + assert(p == p); + assert(!(p != p)); + + assert(pf == pf); + assert(!(pf != pf)); + + assert(p.size() == 6); + + feature id1 { point() }; + id1.id = { uint64_t(1) }; + + feature id2 { point() }; + id1.id = { uint64_t(2) }; + + assert(id1 == id1); + assert(id1 != id2); +} + +static void testFeatureCollection() { + feature_collection fc1; + assert(fc1.size() == 0); + + assert(fc1 == fc1); + assert(!(fc1 != fc1)); +} + +struct point_counter { + std::size_t count = 0; + template + void operator()(Point const&) { count++; }; +}; + +static void testForEachPoint() { + auto count_points = [] (auto const& g) { + point_counter counter; + for_each_point(g, counter); + return counter.count; + }; + + assert(count_points(point()) == 1); + assert(count_points(line_string({{0, 1}, {2, 3}})) == 2); + assert(count_points(geometry(polygon({{{0, 1}, {2, 3}}}))) == 2); + + auto point_negator = [] (point& p) { p *= -1.0; }; + + point p(1, 2); + for_each_point(p, point_negator); + assert(p == point(-1, -2)); + + line_string ls({{0, 1}, {2, 3}}); + for_each_point(ls, point_negator); + assert(ls == line_string({{0, -1}, {-2, -3}})); + + geometry g(polygon({{{0, 1}, {2, 3}}})); + for_each_point(g, point_negator); + assert(g == geometry(polygon({{{0, -1}, {-2, -3}}}))); + + // Custom geometry type + using my_geometry = mapbox::util::variant>; + assert(count_points(my_geometry(point())) == 1); + + // Custom point type + struct my_point { + int16_t x; + int16_t y; + }; + assert(count_points(std::vector({my_point{0, 1}})) == 1); + assert(count_points(mapbox::util::variant(my_point{0, 1})) == 1); +} + +static void testEnvelope() { + assert(envelope(point(0, 0)) == box({0, 0}, {0, 0})); + assert(envelope(line_string({{0, 1}, {2, 3}})) == box({0, 1}, {2, 3})); + assert(envelope(polygon({{{0, 1}, {2, 3}}})) == box({0, 1}, {2, 3})); + + assert(envelope(multi_point({{0, 0}})) == box({0, 0}, {0, 0})); + assert(envelope(multi_line_string({{{0, 1}, {2, 3}}})) == box({0, 1}, {2, 3})); + assert(envelope(multi_polygon({{{{0, 1}, {2, 3}}}})) == box({0, 1}, {2, 3})); + + assert(envelope(geometry(point(0, 0))) == box({0, 0}, {0, 0})); + assert(envelope(geometry_collection({point(0, 0)})) == box({0, 0}, {0, 0})); +} + +int main() { + testPoint(); + testMultiPoint(); + testLineString(); + testMultiLineString(); + testPolygon(); + testMultiPolygon(); + testGeometry(); + testGeometryCollection(); + testFeature(); + testFeatureCollection(); + + testForEachPoint(); + testEnvelope(); + return 0; +} From 3430374830a874f7488967a9dbfc56212ca79d0d Mon Sep 17 00:00:00 2001 From: Huyen Chau Nguyen Date: Wed, 25 Apr 2018 10:59:07 -0400 Subject: [PATCH 2/9] refactor cheap ruler cache --- src/util/coordinate_calculation.cpp | 39 +++++++++++++---------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/util/coordinate_calculation.cpp b/src/util/coordinate_calculation.cpp index e1d9aa19352..cf0b29dd1ce 100644 --- a/src/util/coordinate_calculation.cpp +++ b/src/util/coordinate_calculation.cpp @@ -22,26 +22,23 @@ namespace coordinate_calculation namespace { -mapbox::cheap_ruler::CheapRuler cheap_ruler_cache[] = { - mapbox::cheap_ruler::CheapRuler(-90, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(-80, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(-70, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(-60, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(-50, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(-40, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(-30, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(-20, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(-10, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(0, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(10, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(20, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(30, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(40, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(50, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(60, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(70, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(80, mapbox::cheap_ruler::CheapRuler::Meters), - mapbox::cheap_ruler::CheapRuler(90, mapbox::cheap_ruler::CheapRuler::Meters)}; +class CheapRulerContainer { +public: + CheapRulerContainer(const int number_of_rulers) + : cheap_ruler_cache(number_of_rulers, mapbox::cheap_ruler::CheapRuler(0)), step(180. / number_of_rulers){ + for (int n = 0; n < number_of_rulers; n++) { + cheap_ruler_cache[n] = mapbox::cheap_ruler::CheapRuler(-90 + step * n, mapbox::cheap_ruler::CheapRuler::Meters); + } + }; + mapbox::cheap_ruler::CheapRuler& getRuler(const double lat) { + return cheap_ruler_cache[std::min((int)std::round((lat + 90)/step), (int)cheap_ruler_cache.size() - 1)]; + }; + +private: + std::vector cheap_ruler_cache; + const double step; +}; +CheapRulerContainer cheap_ruler_container(3600); } // Does not project the coordinates! @@ -68,7 +65,7 @@ double fccApproximateDistance(const Coordinate coordinate_1, const Coordinate co const auto lat1 = static_cast(util::toFloating(coordinate_1.lat)); const auto lon2 = static_cast(util::toFloating(coordinate_2.lon)); const auto lat2 = static_cast(util::toFloating(coordinate_2.lat)); - return cheap_ruler_cache[std::lround(lat1 / 10) + 9].distance({lon1, lat1}, {lon2, lat2}); + return cheap_ruler_container.getRuler(lat1).distance({lon1, lat1}, {lon2, lat2}); } double haversineDistance(const Coordinate coordinate_1, const Coordinate coordinate_2) From 42f819caacc93b3f4d58d4353f58d9b52fd45f11 Mon Sep 17 00:00:00 2001 From: Huyen Chau Nguyen Date: Wed, 25 Apr 2018 11:00:13 -0400 Subject: [PATCH 3/9] change haversine computation to cheap ruler in distance tables --- features/support/data_classes.js | 8 +- features/testbot/distance.feature | 19 ++ features/testbot/distance_matrix.feature | 237 ++++++++++++----------- include/engine/geospatial_query.hpp | 8 +- 4 files changed, 157 insertions(+), 115 deletions(-) diff --git a/features/support/data_classes.js b/features/support/data_classes.js index a383540d6e0..1fad997a014 100644 --- a/features/support/data_classes.js +++ b/features/support/data_classes.js @@ -21,7 +21,8 @@ module.exports = { matchRe = want.match(/^\/(.*)\/$/), // we use this for matching before/after bearing matchBearingListAbs = want.match(/^((\d+)->(\d+))(,(\d+)->(\d+))*\s+\+\-(.+)$/), - matchIntersectionListAbs = want.match(/^(((((true|false):\d+)\s{0,1})+,{0,1})+;{0,1})+\s+\+\-(.+)$/); + matchIntersectionListAbs = want.match(/^(((((true|false):\d+)\s{0,1})+,{0,1})+;{0,1})+\s+\+\-(.+)$/), + matchRangeNumbers = want.match(/\d+\+\-\d+/); function inRange(margin, got, want) { var fromR = parseFloat(want) - margin, @@ -105,6 +106,11 @@ module.exports = { return inRange(margin, got, matchAbs[1]); } else if (matchRe) { // regex: /a,b,.*/ return got.match(matchRe[1]); + } else if (matchRangeNumbers) { + let real_want_and_margin = want.split('+-'), + margin = parseFloat(real_want_and_margin[1].trim()), + real_want = parseFloat(real_want_and_margin[0].trim()); + return inRange(margin, got, real_want); } else { return false; } diff --git a/features/testbot/distance.feature b/features/testbot/distance.feature index 8500c1df13a..1b76f45a653 100644 --- a/features/testbot/distance.feature +++ b/features/testbot/distance.feature @@ -226,3 +226,22 @@ Feature: Distance calculation | x | v | xv,xv | 424m +-1 | | x | w | xw,xw | 360m +-1 | | x | y | xy,xy | 316m +-1 | + + + # Check rounding errors + Scenario: Distances Long distances + Given a grid size of 1000 meters + Given the node map + """ + a b c d + """ + + And the ways + | nodes | + | abcd | + + When I route I should get + | from | to | distance | + | a | b | 1000m +-3 | + | a | c | 2000m +-3 | + | a | d | 3000m +-3 | diff --git a/features/testbot/distance_matrix.feature b/features/testbot/distance_matrix.feature index 46f60d7de1b..104727350fd 100644 --- a/features/testbot/distance_matrix.feature +++ b/features/testbot/distance_matrix.feature @@ -17,9 +17,9 @@ Feature: Basic Distance Matrix | ab | When I request a travel distance matrix I should get - | | a | b | - | a | 0 | 100 | - | b | 100 | 0 | + | | a | b | + | a | 0 | 100+-1 | + | b | 100+-1 | 0 | Scenario: Testbot - Travel distance matrix of minimal network with toll exclude Given the query options @@ -39,11 +39,11 @@ Feature: Basic Distance Matrix | bd | motorway | yes | not drivable for exclude=toll and exclude=motorway,toll | When I request a travel distance matrix I should get - | | a | b | c | d | - | a | 0 | 100 | | | - | b | 100 | 0 | | | - | c | | | 0 | 100 | - | d | | | 100 | 0 | + | | a | b | c | d | + | a | 0 | 100+-1 | | | + | b | 100+-1 | 0 | | | + | c | | | 0 | 100+-1 | + | d | | | 100+-1 | 0 | Scenario: Testbot - Travel distance matrix of minimal network with motorway exclude Given the query options @@ -63,8 +63,8 @@ Feature: Basic Distance Matrix | bd | residential | | When I request a travel distance matrix I should get - | | a | b | c | d | - | a | 0 | 300 | 100 | 200 | + | | a | b | c | d | + | a | 0 | 300+-2 | 100+-2 | 200+-2 | Scenario: Testbot - Travel distance matrix of minimal network disconnected motorway exclude @@ -85,8 +85,8 @@ Feature: Basic Distance Matrix | efgh | residential | | When I request a travel distance matrix I should get - | | a | b | e | - | a | 0 | 50 | | + | | a | b | e | + | a | 0 | 50+-1 | | Scenario: Testbot - Travel distance matrix of minimal network with motorway and toll excludes @@ -107,8 +107,8 @@ Feature: Basic Distance Matrix | efgh | residential | | | When I request a travel distance matrix I should get - | | a | b | e | g | - | a | 0 | 100 | | | + | | a | b | e | g | + | a | 0 | 100+-1 | | | Scenario: Testbot - Travel distance matrix with different way speeds Given the node map @@ -123,22 +123,22 @@ Feature: Basic Distance Matrix | cd | tertiary | When I request a travel distance matrix I should get - | | a | b | c | d | - | a | 0 | 100 | 200 | 299.9 | - | b | 100 | 0 | 100 | 200 | - | c | 200 | 100 | 0 | 100 | - | d | 299.9 | 200 | 100 | 0 | + | | a | b | c | d | + | a | 0 | 100+-1 | 200+-1 | 300+-1 | + | b | 100+-1 | 0 | 100+-1 | 200+-1 | + | c | 200+-1 | 100+-1 | 0 | 100+-1 | + | d | 300+-1 | 200+-1 | 100+-1 | 0 | When I request a travel distance matrix I should get - | | a | b | c | d | - | a | 0 | 100 | 200 | 299.9 | + | | a | b | c | d | + | a | 0 | 100+-1 | 200+-1 | 300+-1 | When I request a travel distance matrix I should get - | | a | - | a | 0 | - | b | 100 | - | c | 200 | - | d | 299.9 | + | | a | + | a | 0 | + | b | 100+-1 | + | c | 200+-1 | + | d | 300+-1 | Scenario: Testbot - Travel distance matrix of small grid Given the node map @@ -156,11 +156,11 @@ Feature: Basic Distance Matrix | cf | When I request a travel distance matrix I should get - | | a | b | e | f | - | a | 0 | 100 | 200 | 299.9 | - | b | 100 | 0 | 100 | 200 | - | e | 200 | 100 | 0 | 100 | - | f | 299.9 | 200 | 100 | 0 | + | | a | b | e | f | + | a | 0 | 100+-1 | 200+-1 | 300+-1 | + | b | 100+-1 | 0 | 100+-1 | 200+-1 | + | e | 200+-1 | 100+-1 | 0 | 100+-1 | + | f | 300+-1 | 200+-1 | 100+-1 | 0 | Scenario: Testbot - Travel distance matrix of network with unroutable parts Given the node map @@ -173,9 +173,9 @@ Feature: Basic Distance Matrix | ab | yes | When I request a travel distance matrix I should get - | | a | b | - | a | 0 | 100 | - | b | | 0 | + | | a | b | + | a | 0 | 100+-1 | + | b | | 0 | Scenario: Testbot - Travel distance matrix of network with oneways Given the node map @@ -191,11 +191,11 @@ Feature: Basic Distance Matrix | by | | When I request a travel distance matrix I should get - | | x | y | d | e | - | x | 0 | 299.9 | 399.9 | 299.9 | - | y | 499.9 | 0 | 299.9 | 200 | - | d | 200 | 299.9 | 0 | 300 | - | e | 299.9 | 399.9 | 100 | 0 | + | | x | y | d | e | + | x | 0 | 300+-2 | 400+-2 | 300+-2 | + | y | 500+-2 | 0 | 300+-2 | 200+-2 | + | d | 200+-2 | 300+-2 | 0 | 300+-2 | + | e | 300+-2 | 400+-2 | 100+-2 | 0 | Scenario: Testbot - Rectangular travel distance matrix Given the node map @@ -213,47 +213,47 @@ Feature: Basic Distance Matrix | cf | When I request a travel distance matrix I should get - | | a | b | e | f | - | a | 0 | 100 | 200 | 299.9 | + | | a | b | e | f | + | a | 0 | 100+-1 | 200+-1 | 300+-1 | When I request a travel distance matrix I should get - | | a | - | a | 0 | - | b | 100 | - | e | 200 | - | f | 299.9 | + | | a | + | a | 0 | + | b | 100+-1 | + | e | 200+-1 | + | f | 300+-1 | When I request a travel distance matrix I should get - | | a | b | e | f | - | a | 0 | 100 | 200 | 299.9 | - | b | 100 | 0 | 100 | 200 | + | | a | b | e | f | + | a | 0 | 100+-1 | 200+-1 | 300+-1 | + | b | 100+-1 | 0 | 100+-1 | 200+-1 | When I request a travel distance matrix I should get - | | a | b | - | a | 0 | 100 | - | b | 100 | 0 | - | e | 200 | 100 | - | f | 299.9 | 200 | + | | a | b | + | a | 0 | 100+-1 | + | b | 100+-1 | 0 | + | e | 200+-1 | 100+-1 | + | f | 300+-1 | 200+-1 | When I request a travel distance matrix I should get - | | a | b | e | f | - | a | 0 | 100 | 200 | 299.9 | - | b | 100 | 0 | 100 | 200 | - | e | 200 | 100 | 0 | 100 | + | | a | b | e | f | + | a | 0 | 100+-1 | 200+-1 | 300+-1 | + | b | 100+-1 | 0 | 100+-1 | 200+-1 | + | e | 200+-1 | 100+-1 | 0 | 100+-1 | When I request a travel distance matrix I should get - | | a | b | e | - | a | 0 | 100 | 200 | - | b | 100 | 0 | 100 | - | e | 200 | 100 | 0 | - | f | 299.9 | 200 | 100 | + | | a | b | e | + | a | 0 | 100+-1 | 200+-1 | + | b | 100+-1 | 0 | 100+-1 | + | e | 200+-1 | 100+-1 | 0 | + | f | 300+-1 | 200+-1 | 100+-1 | When I request a travel distance matrix I should get - | | a | b | e | f | - | a | 0 | 100 | 200 | 299.9 | - | b | 100 | 0 | 100 | 200 | - | e | 200 | 100 | 0 | 100 | - | f | 299.9 | 200 | 100 | 0 | + | | a | b | e | f | + | a | 0 | 100+-1 | 200+-1 | 300+-1 | + | b | 100+-1 | 0 | 100+-1 | 200+-1 | + | e | 200+-1 | 100+-1 | 0 | 100+-1 | + | f | 300+-1 | 200+-1 | 100+-1 | 0 | Scenario: Testbot - Travel distance 3x2 matrix @@ -273,9 +273,9 @@ Feature: Basic Distance Matrix When I request a travel distance matrix I should get - | | b | e | f | - | a | 100 | 200 | 299.9 | - | b | 0 | 100 | 200 | + | | b | e | f | + | a | 100+-1 | 200+-1 | 300+-1 | + | b | 0 | 100+-1 | 200+-1 | Scenario: Testbot - All coordinates are from same small component Given a grid size of 300 meters @@ -295,9 +295,9 @@ Feature: Basic Distance Matrix | fg | When I request a travel distance matrix I should get - | | f | g | - | f | 0 | 300 | - | g | 300 | 0 | + | | f | g | + | f | 0 | 300+-2 | + | g | 300+-2 | 0 | Scenario: Testbot - Coordinates are from different small component and snap to big CC Given a grid size of 300 meters @@ -329,11 +329,11 @@ Feature: Basic Distance Matrix | i | h | 300m | When I request a travel distance matrix I should get - | | f | g | h | i | - | f | 0 | 300 | 0 | 300 | - | g | 300 | 0 | 300 | 0 | - | h | 0 | 300 | 0 | 300 | - | i | 300 | 0 | 300 | 0 | + | | f | g | h | i | + | f | 0 | 300+-2 | 0 | 300+-2 | + | g | 300+-2 | 0 | 300+-2 | 0 | + | h | 0 | 300+-2 | 0 | 300+-2 | + | i | 300+-2 | 0 | 300+-2 | 0 | Scenario: Testbot - Travel distance matrix with loops Given the node map @@ -350,11 +350,11 @@ Feature: Basic Distance Matrix | da | yes | When I request a travel distance matrix I should get - | | 1 | 2 | 3 | 4 | - | 1 | 0 | 100 | 399.9 | 499.9 | - | 2 | 699.9 | 0 | 299.9 | 399.9 | - | 3 | 399.9 | 499.9 | 0 | 100 | - | 4 | 299.9 | 399.9 | 699.9 | 0 | + | | 1 | 2 | 3 | 4 | + | 1 | 0 | 100+-1 | 400+-1 | 500+-1 | + | 2 | 700+-1 | 0 | 300+-1 | 400+-1 | + | 3 | 400+-1 | 500+-1 | 0 | 100+-1 | + | 4 | 300+-1 | 400+-1 | 700+-1 | 0 | Scenario: Testbot - Travel distance matrix based on segment durations @@ -391,12 +391,12 @@ Feature: Basic Distance Matrix | ce | When I request a travel distance matrix I should get - | | a | b | c | d | e | - | a | 0 | 100 | 200 | 299.9 | 399.9 | - | b | 100 | 0 | 100 | 200 | 300 | - | c | 200 | 100 | 0 | 100 | 200 | - | d | 299.9 | 200 | 100 | 0 | 300 | - | e | 399.9 | 300 | 200 | 300 | 0 | + | | a | b | c | d | e | + | a | 0 | 100+-2 | 200+-2 | 300+-2 | 400+-2 | + | b | 100+-2 | 0 | 100+-2 | 200+-2 | 300+-2 | + | c | 200+-2 | 100+-2 | 0 | 100+-2 | 200+-2 | + | d | 300+-2 | 200+-2 | 100+-2 | 0 | 300+-2 | + | e | 400+-2 | 300+-2 | 200+-2 | 300+-2 | 0 | Scenario: Testbot - Travel distance matrix for alternative loop paths Given the profile file @@ -435,15 +435,15 @@ Feature: Basic Distance Matrix | ca | yes | When I request a travel distance matrix I should get - | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | - | 1 | 0 | 1099.8 | 300 | 200 | 599.9 | 499.9 | 899.9 | 799.9 | - | 2 | 100 | 0 | 399.9 | 299.9 | 699.9 | 599.9 | 999.8 | 899.9 | - | 3 | 899.9 | 799.9 | 0 | 1099.8 | 299.9 | 200 | 599.9 | 499.9 | - | 4 | 999.8 | 899.9 | 100 | 0 | 399.9 | 300 | 699.9 | 599.9 | - | 5 | 599.9 | 499.9 | 899.9 | 799.9 | 0 | 1099.8 | 300 | 200 | - | 6 | 699.9 | 599.9 | 999.8 | 899.9 | 100 | 0 | 399.9 | 299.9 | - | 7 | 299.9 | 200 | 599.9 | 499.9 | 899.9 | 799.9 | 0 | 1099.8 | - | 8 | 399.9 | 300 | 699.9 | 599.9 | 999.8 | 899.9 | 100 | 0 | + | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | + | 1 | 0 | 1100+-5 | 300+-5 | 200+-5 | 600+-5 | 500+-5 | 900+-5 | 800+-5 | + | 2 | 100+-5 | 0 | 400+-5 | 300+-5 | 700+-5 | 600+-5 | 1000+-5 | 900+-5 | + | 3 | 900+-5 | 800+-5 | 0 | 1100+-5 | 300+-5 | 200+-5 | 600+-5 | 500+-5 | + | 4 | 1000+-5 | 900+-5 | 100+-5 | 0 | 400+-5 | 300+-5 | 700+-5 | 600+-5 | + | 5 | 600+-5 | 500+-5 | 900+-5 | 800+-5 | 0 | 1100+-5 | 300+-5 | 200+-5 | + | 6 | 700+-5 | 600+-5 | 1000+-5 | 900+-5 | 100+-5 | 0 | 400+-5 | 300+-5 | + | 7 | 300+-5 | 200+-5 | 600+-5 | 500+-5 | 900+-5 | 800+-5 | 0 | 1100+-5 | + | 8 | 400+-5 | 300+-5 | 700+-5 | 600+-5 | 1000+-5 | 900+-5 | 100+-5 | 0 | Scenario: Testbot - Travel distance matrix with ties Given the node map @@ -465,18 +465,35 @@ Feature: Basic Distance Matrix | a | c | ac,ac | 200m | 20s | 20 | When I route I should get - | from | to | route | distance | - | a | b | ab,ab | 299.9m | - | a | c | ac,ac | 200m | - | a | d | ab,bd,bd | 499.9m | + | from | to | route | distance | + | a | b | ab,ab | 300m +- 1 | + | a | c | ac,ac | 200m | + | a | d | ab,bd,bd | 500m +- 1 | When I request a travel distance matrix I should get - | | a | b | c | d | - | a | 0 | 299.9 | 200 | 499.9 | + | | a | b | c | d | + | a | 0 | 300+-2 | 200+-2 | 500+-2 | When I request a travel distance matrix I should get - | | a | - | a | 0 | - | b | 299.9 | - | c | 200 | - | d | 499.9 | + | | a | + | a | 0 | + | b | 300+-2 | + | c | 200+-2 | + | d | 500+-2 | + + + # Check rounding errors + Scenario: Testbot - Long distances in tables + Given a grid size of 1000 meters + Given the node map + """ + a b c d + """ + + And the ways + | nodes | + | abcd | + + When I request a travel distance matrix I should get + | | a | b | c | d | + | a | 0 | 1000+-3 | 2000+-3 | 3000+-3 | diff --git a/include/engine/geospatial_query.hpp b/include/engine/geospatial_query.hpp index cd53f34f469..4ecfc8118bd 100644 --- a/include/engine/geospatial_query.hpp +++ b/include/engine/geospatial_query.hpp @@ -465,7 +465,7 @@ template class GeospatialQuery current < forward_geometry.begin() + data.fwd_segment_position; ++current) { - forward_distance_offset += util::coordinate_calculation::haversineDistance( + forward_distance_offset += util::coordinate_calculation::fccApproximateDistance( datafacade.GetCoordinateOfNode(*current), datafacade.GetCoordinateOfNode(*std::next(current))); } @@ -475,7 +475,7 @@ template class GeospatialQuery EdgeWeight forward_weight = forward_weights[data.fwd_segment_position]; EdgeDuration forward_duration = forward_durations[data.fwd_segment_position]; - EdgeDistance forward_distance = util::coordinate_calculation::haversineDistance( + EdgeDistance forward_distance = util::coordinate_calculation::fccApproximateDistance( datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position)), point_on_segment); @@ -494,7 +494,7 @@ template class GeospatialQuery current < forward_geometry.end() - data.fwd_segment_position - 2; ++current) { - reverse_distance_offset += util::coordinate_calculation::haversineDistance( + reverse_distance_offset += util::coordinate_calculation::fccApproximateDistance( datafacade.GetCoordinateOfNode(*current), datafacade.GetCoordinateOfNode(*std::next(current))); } @@ -503,7 +503,7 @@ template class GeospatialQuery reverse_weights[reverse_weights.size() - data.fwd_segment_position - 1]; EdgeDuration reverse_duration = reverse_durations[reverse_durations.size() - data.fwd_segment_position - 1]; - EdgeDistance reverse_distance = util::coordinate_calculation::haversineDistance( + EdgeDistance reverse_distance = util::coordinate_calculation::fccApproximateDistance( point_on_segment, datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position + 1))); From 0bebb7e885e0ef8045b2b63611499c6f241b901b Mon Sep 17 00:00:00 2001 From: Huyen Chau Nguyen Date: Wed, 25 Apr 2018 16:18:36 -0400 Subject: [PATCH 4/9] only use half of rulers because earth is symmetric --- src/util/coordinate_calculation.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/util/coordinate_calculation.cpp b/src/util/coordinate_calculation.cpp index cf0b29dd1ce..72b59ef28dd 100644 --- a/src/util/coordinate_calculation.cpp +++ b/src/util/coordinate_calculation.cpp @@ -25,20 +25,20 @@ namespace class CheapRulerContainer { public: CheapRulerContainer(const int number_of_rulers) - : cheap_ruler_cache(number_of_rulers, mapbox::cheap_ruler::CheapRuler(0)), step(180. / number_of_rulers){ + : cheap_ruler_cache(number_of_rulers, mapbox::cheap_ruler::CheapRuler(0)), step(90.0 / number_of_rulers) { for (int n = 0; n < number_of_rulers; n++) { - cheap_ruler_cache[n] = mapbox::cheap_ruler::CheapRuler(-90 + step * n, mapbox::cheap_ruler::CheapRuler::Meters); + cheap_ruler_cache[n] = mapbox::cheap_ruler::CheapRuler(step * (n + 0.5), mapbox::cheap_ruler::CheapRuler::Meters); } }; mapbox::cheap_ruler::CheapRuler& getRuler(const double lat) { - return cheap_ruler_cache[std::min((int)std::round((lat + 90)/step), (int)cheap_ruler_cache.size() - 1)]; + return cheap_ruler_cache[std::min((int)std::floor(abs(lat)/step), (int)cheap_ruler_cache.size() - 1)]; }; private: std::vector cheap_ruler_cache; const double step; }; -CheapRulerContainer cheap_ruler_container(3600); +CheapRulerContainer cheap_ruler_container(1800); } // Does not project the coordinates! @@ -65,7 +65,7 @@ double fccApproximateDistance(const Coordinate coordinate_1, const Coordinate co const auto lat1 = static_cast(util::toFloating(coordinate_1.lat)); const auto lon2 = static_cast(util::toFloating(coordinate_2.lon)); const auto lat2 = static_cast(util::toFloating(coordinate_2.lat)); - return cheap_ruler_container.getRuler(lat1).distance({lon1, lat1}, {lon2, lat2}); + return cheap_ruler_container.getRuler(0.5*(lat1+lat2)).distance({lon1, lat1}, {lon2, lat2}); } double haversineDistance(const Coordinate coordinate_1, const Coordinate coordinate_2) From bef07639ed76973d2495b055d696c80158756521 Mon Sep 17 00:00:00 2001 From: Huyen Chau Nguyen Date: Wed, 25 Apr 2018 16:37:37 -0400 Subject: [PATCH 5/9] clang format --- src/util/coordinate_calculation.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/util/coordinate_calculation.cpp b/src/util/coordinate_calculation.cpp index 72b59ef28dd..388d41ef85a 100644 --- a/src/util/coordinate_calculation.cpp +++ b/src/util/coordinate_calculation.cpp @@ -22,19 +22,26 @@ namespace coordinate_calculation namespace { -class CheapRulerContainer { -public: +class CheapRulerContainer +{ + public: CheapRulerContainer(const int number_of_rulers) - : cheap_ruler_cache(number_of_rulers, mapbox::cheap_ruler::CheapRuler(0)), step(90.0 / number_of_rulers) { - for (int n = 0; n < number_of_rulers; n++) { - cheap_ruler_cache[n] = mapbox::cheap_ruler::CheapRuler(step * (n + 0.5), mapbox::cheap_ruler::CheapRuler::Meters); + : cheap_ruler_cache(number_of_rulers, mapbox::cheap_ruler::CheapRuler(0)), + step(90.0 / number_of_rulers) + { + for (int n = 0; n < number_of_rulers; n++) + { + cheap_ruler_cache[n] = mapbox::cheap_ruler::CheapRuler( + step * (n + 0.5), mapbox::cheap_ruler::CheapRuler::Meters); } }; - mapbox::cheap_ruler::CheapRuler& getRuler(const double lat) { - return cheap_ruler_cache[std::min((int)std::floor(abs(lat)/step), (int)cheap_ruler_cache.size() - 1)]; + mapbox::cheap_ruler::CheapRuler &getRuler(const double lat) + { + return cheap_ruler_cache[std::min((int)std::floor(abs(lat) / step), + (int)cheap_ruler_cache.size() - 1)]; }; -private: + private: std::vector cheap_ruler_cache; const double step; }; @@ -65,7 +72,7 @@ double fccApproximateDistance(const Coordinate coordinate_1, const Coordinate co const auto lat1 = static_cast(util::toFloating(coordinate_1.lat)); const auto lon2 = static_cast(util::toFloating(coordinate_2.lon)); const auto lat2 = static_cast(util::toFloating(coordinate_2.lat)); - return cheap_ruler_container.getRuler(0.5*(lat1+lat2)).distance({lon1, lat1}, {lon2, lat2}); + return cheap_ruler_container.getRuler(0.5 * (lat1 + lat2)).distance({lon1, lat1}, {lon2, lat2}); } double haversineDistance(const Coordinate coordinate_1, const Coordinate coordinate_2) From 195eed1d70fafe92cab8d12ecacab162b08c48fc Mon Sep 17 00:00:00 2001 From: Huyen Chau Nguyen Date: Wed, 25 Apr 2018 17:31:35 -0400 Subject: [PATCH 6/9] make eslint happy --- features/support/data_classes.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/support/data_classes.js b/features/support/data_classes.js index 1fad997a014..e276f20edb5 100644 --- a/features/support/data_classes.js +++ b/features/support/data_classes.js @@ -108,9 +108,9 @@ module.exports = { return got.match(matchRe[1]); } else if (matchRangeNumbers) { let real_want_and_margin = want.split('+-'), - margin = parseFloat(real_want_and_margin[1].trim()), - real_want = parseFloat(real_want_and_margin[0].trim()); - return inRange(margin, got, real_want); + margin = parseFloat(real_want_and_margin[1].trim()), + real_want = parseFloat(real_want_and_margin[0].trim()); + return inRange(margin, got, real_want); } else { return false; } From df38ab51304747894cf3d97b3e09a67b4fbecff1 Mon Sep 17 00:00:00 2001 From: Michael Krasnyk Date: Thu, 26 Apr 2018 20:06:58 +0200 Subject: [PATCH 7/9] Use mapbox::util::optional instead of std::experimental::optional --- .../geometry.hpp-0.9.2/include/mapbox/geometry/feature.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/feature.hpp b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/feature.hpp index 20d2ddf6b8f..91354442eed 100644 --- a/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/feature.hpp +++ b/third_party/geometry.hpp-0.9.2/include/mapbox/geometry/feature.hpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include namespace mapbox { namespace geometry { @@ -54,13 +54,13 @@ struct feature geometry_type geometry; property_map properties {}; - std::experimental::optional id {}; + mapbox::util::optional id {}; // GCC 4.9 does not support C++14 aggregates with non-static data member // initializers. feature(geometry_type geometry_, property_map properties_ = property_map {}, - std::experimental::optional id_ = std::experimental::optional {}) + mapbox::util::optional id_ = mapbox::util::optional {}) : geometry(std::move(geometry_)), properties(std::move(properties_)), id(std::move(id_)) {} From cdf0dde2622ed23b5bf409c9b6dc20fa20c5ec44 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Thu, 26 Apr 2018 20:38:17 +0000 Subject: [PATCH 8/9] Optimize distance calculation by getting rid of rounding --- src/util/coordinate_calculation.cpp | 33 +++++++++++++++++++---------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/util/coordinate_calculation.cpp b/src/util/coordinate_calculation.cpp index 388d41ef85a..a45eb520978 100644 --- a/src/util/coordinate_calculation.cpp +++ b/src/util/coordinate_calculation.cpp @@ -27,26 +27,36 @@ class CheapRulerContainer public: CheapRulerContainer(const int number_of_rulers) : cheap_ruler_cache(number_of_rulers, mapbox::cheap_ruler::CheapRuler(0)), - step(90.0 / number_of_rulers) + step(90.0 * COORDINATE_PRECISION / number_of_rulers) { for (int n = 0; n < number_of_rulers; n++) { cheap_ruler_cache[n] = mapbox::cheap_ruler::CheapRuler( - step * (n + 0.5), mapbox::cheap_ruler::CheapRuler::Meters); + step * (n + 0.5) / COORDINATE_PRECISION, mapbox::cheap_ruler::CheapRuler::Meters); } }; - mapbox::cheap_ruler::CheapRuler &getRuler(const double lat) + + mapbox::cheap_ruler::CheapRuler &getRuler(const FixedLatitude lat_1, const FixedLatitude lat_2) { - return cheap_ruler_cache[std::min((int)std::floor(abs(lat) / step), - (int)cheap_ruler_cache.size() - 1)]; + auto lat = (lat_1 + lat_2) / util::FixedLatitude{2}; + return getRuler(lat); + } + + mapbox::cheap_ruler::CheapRuler &getRuler(const FixedLatitude lat) + { + BOOST_ASSERT(step > 2); + // the |lat| > 0 -> |lat|-1 > -1 -> (|lat|-1)/step > -1/step > -1/2 >= -1 -> bin >= 0 + std::size_t bin = (std::abs(static_cast(lat)) - 1) / step; + BOOST_ASSERT(bin < cheap_ruler_cache.size()); + return cheap_ruler_cache[bin]; }; private: std::vector cheap_ruler_cache; - const double step; + const int step; }; CheapRulerContainer cheap_ruler_container(1800); -} +} // namespace // Does not project the coordinates! std::uint64_t squaredEuclideanDistance(const Coordinate lhs, const Coordinate rhs) @@ -72,7 +82,8 @@ double fccApproximateDistance(const Coordinate coordinate_1, const Coordinate co const auto lat1 = static_cast(util::toFloating(coordinate_1.lat)); const auto lon2 = static_cast(util::toFloating(coordinate_2.lon)); const auto lat2 = static_cast(util::toFloating(coordinate_2.lat)); - return cheap_ruler_container.getRuler(0.5 * (lat1 + lat2)).distance({lon1, lat1}, {lon2, lat2}); + return cheap_ruler_container.getRuler(coordinate_1.lat, coordinate_2.lat) + .distance({lon1, lat1}, {lon2, lat2}); } double haversineDistance(const Coordinate coordinate_1, const Coordinate coordinate_2) @@ -466,6 +477,6 @@ double computeArea(const std::vector &polygon) return area / 2.; } -} // ns coordinate_calculation -} // ns util -} // ns osrm +} // namespace coordinate_calculation +} // namespace util +} // namespace osrm From 6f6052489bd8db09517979b70ab8c1bbd9032a44 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Thu, 26 Apr 2018 21:07:35 +0000 Subject: [PATCH 9/9] Make cheap rulers static --- src/util/coordinate_calculation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/coordinate_calculation.cpp b/src/util/coordinate_calculation.cpp index a45eb520978..cb9adb10a9b 100644 --- a/src/util/coordinate_calculation.cpp +++ b/src/util/coordinate_calculation.cpp @@ -55,7 +55,7 @@ class CheapRulerContainer std::vector cheap_ruler_cache; const int step; }; -CheapRulerContainer cheap_ruler_container(1800); +static CheapRulerContainer cheap_ruler_container(1800); } // namespace // Does not project the coordinates!