Use faster method for calculating distances.
fix cmakelist
This commit is contained in:
parent
6843eb1479
commit
a6cf2eee7e
@ -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()
|
@ -415,7 +415,7 @@ template <typename FacadeT> 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)));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <mapbox/cheap_ruler.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
@ -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<double>(util::toFloating(coordinate_1.lon));
|
||||
const auto lat1 = static_cast<double>(util::toFloating(coordinate_1.lat));
|
||||
const auto lon2 = static_cast<double>(util::toFloating(coordinate_2.lon));
|
||||
const auto lat2 = static_cast<double>(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<int>(coordinate_1.lon);
|
||||
|
18
third_party/cheap-ruler-cpp-2.5.4/.clang-format
vendored
Normal file
18
third_party/cheap-ruler-cpp-2.5.4/.clang-format
vendored
Normal file
@ -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
|
2
third_party/cheap-ruler-cpp-2.5.4/.gitignore
vendored
Normal file
2
third_party/cheap-ruler-cpp-2.5.4/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
build/
|
||||
mason_packages/
|
25
third_party/cheap-ruler-cpp-2.5.4/.travis.yml
vendored
Normal file
25
third_party/cheap-ruler-cpp-2.5.4/.travis.yml
vendored
Normal file
@ -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
|
27
third_party/cheap-ruler-cpp-2.5.4/CMakeLists.txt
vendored
Normal file
27
third_party/cheap-ruler-cpp-2.5.4/CMakeLists.txt
vendored
Normal file
@ -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)
|
15
third_party/cheap-ruler-cpp-2.5.4/LICENSE
vendored
Normal file
15
third_party/cheap-ruler-cpp-2.5.4/LICENSE
vendored
Normal file
@ -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.
|
199
third_party/cheap-ruler-cpp-2.5.4/README.md
vendored
Normal file
199
third_party/cheap-ruler-cpp-2.5.4/README.md
vendored
Normal file
@ -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.
|
||||
|
||||
[](https://travis-ci.org/mapbox/cheap-ruler-cpp)
|
||||
|
||||
# Usage
|
||||
|
||||
```cpp
|
||||
#include <mapbox/cheap_ruler.hpp>
|
||||
|
||||
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<point, unsigned>` 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
|
||||
```
|
11
third_party/cheap-ruler-cpp-2.5.4/cmake/build.cmake
vendored
Normal file
11
third_party/cheap-ruler-cpp-2.5.4/cmake/build.cmake
vendored
Normal file
@ -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()
|
235
third_party/cheap-ruler-cpp-2.5.4/cmake/mason.cmake
vendored
Normal file
235
third_party/cheap-ruler-cpp-2.5.4/cmake/mason.cmake
vendored
Normal file
@ -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()
|
354
third_party/cheap-ruler-cpp-2.5.4/include/mapbox/cheap_ruler.hpp
vendored
Normal file
354
third_party/cheap-ruler-cpp-2.5.4/include/mapbox/cheap_ruler.hpp
vendored
Normal file
@ -0,0 +1,354 @@
|
||||
#pragma once
|
||||
|
||||
#include <mapbox/geometry.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
namespace mapbox {
|
||||
namespace cheap_ruler {
|
||||
|
||||
using box = geometry::box<double>;
|
||||
using line_string = geometry::line_string<double>;
|
||||
using linear_ring = geometry::linear_ring<double>;
|
||||
using multi_line_string = geometry::multi_line_string<double>;
|
||||
using point = geometry::point<double>;
|
||||
using polygon = geometry::polygon<double>;
|
||||
|
||||
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 <point, index, t> 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<point, unsigned, double> pointOnLine(const line_string& line, point p) {
|
||||
double minDist = std::numeric_limits<double>::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
|
200
third_party/cheap-ruler-cpp-2.5.4/test/cheap_ruler.cpp
vendored
Normal file
200
third_party/cheap-ruler-cpp-2.5.4/test/cheap_ruler.cpp
vendored
Normal file
@ -0,0 +1,200 @@
|
||||
#include <mapbox/cheap_ruler.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#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();
|
||||
}
|
8
third_party/cheap-ruler-cpp-2.5.4/test/fixtures/lines.hpp
vendored
Normal file
8
third_party/cheap-ruler-cpp-2.5.4/test/fixtures/lines.hpp
vendored
Normal file
File diff suppressed because one or more lines are too long
1894
third_party/cheap-ruler-cpp-2.5.4/test/fixtures/turf.hpp
vendored
Normal file
1894
third_party/cheap-ruler-cpp-2.5.4/test/fixtures/turf.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
third_party/geometry.hpp-0.9.2/.gitignore
vendored
Normal file
2
third_party/geometry.hpp-0.9.2/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
mason_packages
|
||||
test
|
3
third_party/geometry.hpp-0.9.2/.gitmodules
vendored
Normal file
3
third_party/geometry.hpp-0.9.2/.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule ".mason"]
|
||||
path = .mason
|
||||
url = https://github.com/mapbox/mason.git
|
50
third_party/geometry.hpp-0.9.2/.travis.yml
vendored
Normal file
50
third_party/geometry.hpp-0.9.2/.travis.yml
vendored
Normal file
@ -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
|
13
third_party/geometry.hpp-0.9.2/LICENSE
vendored
Normal file
13
third_party/geometry.hpp-0.9.2/LICENSE
vendored
Normal file
@ -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.
|
19
third_party/geometry.hpp-0.9.2/Makefile
vendored
Normal file
19
third_party/geometry.hpp-0.9.2/Makefile
vendored
Normal file
@ -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
|
83
third_party/geometry.hpp-0.9.2/README.md
vendored
Normal file
83
third_party/geometry.hpp-0.9.2/README.md
vendored
Normal file
@ -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 <mapbox/geometry/point.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using mapbox::geometry::point;
|
||||
|
||||
int main() {
|
||||
point<double> 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 <mapbox/geometry/geometry.hpp>
|
||||
#include <mapbox/variant.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using mapbox::geometry::geometry_collection;
|
||||
using mapbox::geometry::geometry;
|
||||
using mapbox::geometry::point;
|
||||
|
||||
using point_type = point<double>;
|
||||
|
||||
struct printer
|
||||
{
|
||||
printer() {}
|
||||
|
||||
void operator()(point_type const& pt) const
|
||||
{
|
||||
std::clog << "x: " << pt.x << " y: " << pt.y << "\n";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator()(T const& g) const
|
||||
{
|
||||
std::clog << "encountered non-point geometry\n";
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
geometry_collection<double> gc;
|
||||
gc.emplace_back(point_type(1.0,0.0));
|
||||
geometry<double> const& geom = gc.at(0);
|
||||
printer visitor;
|
||||
mapbox::util::apply_visitor(visitor,geom);
|
||||
}
|
||||
```
|
13
third_party/geometry.hpp-0.9.2/include/mapbox/geometry.hpp
vendored
Normal file
13
third_party/geometry.hpp-0.9.2/include/mapbox/geometry.hpp
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <mapbox/geometry/point.hpp>
|
||||
#include <mapbox/geometry/line_string.hpp>
|
||||
#include <mapbox/geometry/polygon.hpp>
|
||||
#include <mapbox/geometry/multi_point.hpp>
|
||||
#include <mapbox/geometry/multi_line_string.hpp>
|
||||
#include <mapbox/geometry/multi_polygon.hpp>
|
||||
#include <mapbox/geometry/geometry.hpp>
|
||||
#include <mapbox/geometry/feature.hpp>
|
||||
#include <mapbox/geometry/point_arithmetic.hpp>
|
||||
#include <mapbox/geometry/for_each_point.hpp>
|
||||
#include <mapbox/geometry/envelope.hpp>
|
34
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/box.hpp
vendored
Normal file
34
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/box.hpp
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <mapbox/geometry/point.hpp>
|
||||
|
||||
namespace mapbox {
|
||||
namespace geometry {
|
||||
|
||||
template <typename T>
|
||||
struct box
|
||||
{
|
||||
using point_type = point<T>;
|
||||
|
||||
constexpr box(point_type const& min_, point_type const& max_)
|
||||
: min(min_), max(max_)
|
||||
{}
|
||||
|
||||
point_type min;
|
||||
point_type max;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr bool operator==(box<T> const& lhs, box<T> const& rhs)
|
||||
{
|
||||
return lhs.min == rhs.min && lhs.max == rhs.max;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool operator!=(box<T> const& lhs, box<T> const& rhs)
|
||||
{
|
||||
return lhs.min != rhs.min || lhs.max != rhs.max;
|
||||
}
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace mapbox
|
33
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/envelope.hpp
vendored
Normal file
33
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/envelope.hpp
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <mapbox/geometry/box.hpp>
|
||||
#include <mapbox/geometry/for_each_point.hpp>
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace mapbox {
|
||||
namespace geometry {
|
||||
|
||||
template <typename G, typename T = typename G::coordinate_type>
|
||||
box<T> envelope(G const& geometry)
|
||||
{
|
||||
using limits = std::numeric_limits<T>;
|
||||
|
||||
T min_t = limits::has_infinity ? -limits::infinity() : limits::min();
|
||||
T max_t = limits::has_infinity ? limits::infinity() : limits::max();
|
||||
|
||||
point<T> min(max_t, max_t);
|
||||
point<T> max(min_t, min_t);
|
||||
|
||||
for_each_point(geometry, [&] (point<T> 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<T>(min, max);
|
||||
}
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace mapbox
|
91
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/feature.hpp
vendored
Normal file
91
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/feature.hpp
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
|
||||
#include <mapbox/geometry/geometry.hpp>
|
||||
|
||||
#include <mapbox/variant.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <experimental/optional>
|
||||
|
||||
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<null_value_t, bool, uint64_t, int64_t, double, std::string,
|
||||
mapbox::util::recursive_wrapper<std::vector<value>>,
|
||||
mapbox::util::recursive_wrapper<std::unordered_map<std::string, value>>>;
|
||||
|
||||
struct value : value_base
|
||||
{
|
||||
using value_base::value_base;
|
||||
};
|
||||
|
||||
using property_map = std::unordered_map<std::string, value>;
|
||||
|
||||
// The same considerations and requirement for numeric types apply as for `value_base`.
|
||||
using identifier = mapbox::util::variant<uint64_t, int64_t, double, std::string>;
|
||||
|
||||
template <class T>
|
||||
struct feature
|
||||
{
|
||||
using coordinate_type = T;
|
||||
using geometry_type = mapbox::geometry::geometry<T>; // Fully qualified to avoid GCC -fpermissive error.
|
||||
|
||||
geometry_type geometry;
|
||||
property_map properties {};
|
||||
std::experimental::optional<identifier> 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<identifier> id_ = std::experimental::optional<identifier> {})
|
||||
: geometry(std::move(geometry_)),
|
||||
properties(std::move(properties_)),
|
||||
id(std::move(id_)) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
constexpr bool operator==(feature<T> const& lhs, feature<T> const& rhs)
|
||||
{
|
||||
return lhs.id == rhs.id && lhs.geometry == rhs.geometry && lhs.properties == rhs.properties;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr bool operator!=(feature<T> const& lhs, feature<T> const& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <class T, template <typename...> class Cont = std::vector>
|
||||
struct feature_collection : Cont<feature<T>>
|
||||
{
|
||||
using coordinate_type = T;
|
||||
using feature_type = feature<T>;
|
||||
using container_type = Cont<feature_type>;
|
||||
using container_type::container_type;
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace mapbox
|
45
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/for_each_point.hpp
vendored
Normal file
45
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/for_each_point.hpp
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <mapbox/geometry/geometry.hpp>
|
||||
|
||||
namespace mapbox {
|
||||
namespace geometry {
|
||||
|
||||
template <typename Point, typename F>
|
||||
auto for_each_point(Point&& point, F&& f)
|
||||
-> decltype(point.x, point.y, void())
|
||||
{
|
||||
f(std::forward<Point>(point));
|
||||
}
|
||||
|
||||
template <typename Container, typename F>
|
||||
auto for_each_point(Container&& container, F&& f)
|
||||
-> decltype(container.begin(), container.end(), void());
|
||||
|
||||
template <typename...Types, typename F>
|
||||
void for_each_point(mapbox::util::variant<Types...> const& geom, F&& f)
|
||||
{
|
||||
mapbox::util::variant<Types...>::visit(geom, [&] (auto const& g) {
|
||||
for_each_point(g, f);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename...Types, typename F>
|
||||
void for_each_point(mapbox::util::variant<Types...> & geom, F&& f)
|
||||
{
|
||||
mapbox::util::variant<Types...>::visit(geom, [&] (auto & g) {
|
||||
for_each_point(g, f);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Container, typename F>
|
||||
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
|
58
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/geometry.hpp
vendored
Normal file
58
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/geometry.hpp
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <mapbox/geometry/point.hpp>
|
||||
#include <mapbox/geometry/line_string.hpp>
|
||||
#include <mapbox/geometry/polygon.hpp>
|
||||
#include <mapbox/geometry/multi_point.hpp>
|
||||
#include <mapbox/geometry/multi_line_string.hpp>
|
||||
#include <mapbox/geometry/multi_polygon.hpp>
|
||||
|
||||
#include <mapbox/variant.hpp>
|
||||
|
||||
// stl
|
||||
#include <vector>
|
||||
|
||||
namespace mapbox {
|
||||
namespace geometry {
|
||||
|
||||
template <typename T, template <typename...> class Cont = std::vector>
|
||||
struct geometry_collection;
|
||||
|
||||
template <typename T>
|
||||
using geometry_base = mapbox::util::variant<point<T>,
|
||||
line_string<T>,
|
||||
polygon<T>,
|
||||
multi_point<T>,
|
||||
multi_line_string<T>,
|
||||
multi_polygon<T>,
|
||||
geometry_collection<T>>;
|
||||
|
||||
template <typename T>
|
||||
struct geometry : geometry_base<T>
|
||||
{
|
||||
using coordinate_type = T;
|
||||
using geometry_base<T>::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 <typename T, template <typename...> class Cont>
|
||||
struct geometry_collection : Cont<geometry<T>>
|
||||
{
|
||||
using coordinate_type = T;
|
||||
using geometry_type = geometry<T>;
|
||||
using container_type = Cont<geometry_type>;
|
||||
|
||||
geometry_collection() = default;
|
||||
geometry_collection(geometry_collection const&) = default;
|
||||
geometry_collection(geometry_collection &&) = default;
|
||||
geometry_collection(std::initializer_list<geometry_type> && args)
|
||||
: container_type(std::forward<std::initializer_list<geometry_type>>(args)) {};
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace mapbox
|
21
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/line_string.hpp
vendored
Normal file
21
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/line_string.hpp
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
// mapbox
|
||||
#include <mapbox/geometry/point.hpp>
|
||||
// stl
|
||||
#include <vector>
|
||||
|
||||
namespace mapbox {
|
||||
namespace geometry {
|
||||
|
||||
template <typename T, template <typename...> class Cont = std::vector>
|
||||
struct line_string : Cont<point<T> >
|
||||
{
|
||||
using coordinate_type = T;
|
||||
using point_type = point<T>;
|
||||
using container_type = Cont<point_type>;
|
||||
using container_type::container_type;
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace mapbox
|
21
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_line_string.hpp
vendored
Normal file
21
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_line_string.hpp
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
// mapbox
|
||||
#include <mapbox/geometry/line_string.hpp>
|
||||
// stl
|
||||
#include <vector>
|
||||
|
||||
namespace mapbox {
|
||||
namespace geometry {
|
||||
|
||||
template <typename T, template <typename...> class Cont = std::vector>
|
||||
struct multi_line_string : Cont<line_string<T>>
|
||||
{
|
||||
using coordinate_type = T;
|
||||
using line_string_type = line_string<T>;
|
||||
using container_type = Cont<line_string_type>;
|
||||
using container_type::container_type;
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace mapbox
|
21
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_point.hpp
vendored
Normal file
21
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_point.hpp
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
// mapbox
|
||||
#include <mapbox/geometry/point.hpp>
|
||||
// stl
|
||||
#include <vector>
|
||||
|
||||
namespace mapbox {
|
||||
namespace geometry {
|
||||
|
||||
template <typename T, template <typename...> class Cont = std::vector>
|
||||
struct multi_point : Cont<point<T>>
|
||||
{
|
||||
using coordinate_type = T;
|
||||
using point_type = point<T>;
|
||||
using container_type = Cont<point_type>;
|
||||
using container_type::container_type;
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace mapbox
|
21
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_polygon.hpp
vendored
Normal file
21
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/multi_polygon.hpp
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
// mapbox
|
||||
#include <mapbox/geometry/polygon.hpp>
|
||||
// stl
|
||||
#include <vector>
|
||||
|
||||
namespace mapbox {
|
||||
namespace geometry {
|
||||
|
||||
template <typename T, template <typename...> class Cont = std::vector>
|
||||
struct multi_polygon : Cont<polygon<T>>
|
||||
{
|
||||
using coordinate_type = T;
|
||||
using polygon_type = polygon<T>;
|
||||
using container_type = Cont<polygon_type>;
|
||||
using container_type::container_type;
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace mapbox
|
35
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/point.hpp
vendored
Normal file
35
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/point.hpp
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
namespace mapbox {
|
||||
namespace geometry {
|
||||
|
||||
template <typename T>
|
||||
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 <typename T>
|
||||
constexpr bool operator==(point<T> const& lhs, point<T> const& rhs)
|
||||
{
|
||||
return lhs.x == rhs.x && lhs.y == rhs.y;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool operator!=(point<T> const& lhs, point<T> const& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace mapbox
|
119
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/point_arithmetic.hpp
vendored
Normal file
119
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/point_arithmetic.hpp
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
#pragma once
|
||||
|
||||
namespace mapbox {
|
||||
namespace geometry {
|
||||
|
||||
template <typename T>
|
||||
point<T> operator+(point<T> const& lhs, point<T> const& rhs)
|
||||
{
|
||||
return point<T>(lhs.x + rhs.x, lhs.y + rhs.y);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
point<T> operator+(point<T> const& lhs, T const& rhs)
|
||||
{
|
||||
return point<T>(lhs.x + rhs, lhs.y + rhs);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
point<T> operator-(point<T> const& lhs, point<T> const& rhs)
|
||||
{
|
||||
return point<T>(lhs.x - rhs.x, lhs.y - rhs.y);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
point<T> operator-(point<T> const& lhs, T const& rhs)
|
||||
{
|
||||
return point<T>(lhs.x - rhs, lhs.y - rhs);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
point<T> operator*(point<T> const& lhs, point<T> const& rhs)
|
||||
{
|
||||
return point<T>(lhs.x * rhs.x, lhs.y * rhs.y);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
point<T> operator*(point<T> const& lhs, T const& rhs)
|
||||
{
|
||||
return point<T>(lhs.x * rhs, lhs.y * rhs);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
point<T> operator/(point<T> const& lhs, point<T> const& rhs)
|
||||
{
|
||||
return point<T>(lhs.x / rhs.x, lhs.y / rhs.y);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
point<T> operator/(point<T> const& lhs, T const& rhs)
|
||||
{
|
||||
return point<T>(lhs.x / rhs, lhs.y / rhs);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
point<T>& operator+=(point<T>& lhs, point<T> const& rhs)
|
||||
{
|
||||
lhs.x += rhs.x;
|
||||
lhs.y += rhs.y;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
point<T>& operator+=(point<T>& lhs, T const& rhs)
|
||||
{
|
||||
lhs.x += rhs;
|
||||
lhs.y += rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
point<T>& operator-=(point<T>& lhs, point<T> const& rhs)
|
||||
{
|
||||
lhs.x -= rhs.x;
|
||||
lhs.y -= rhs.y;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
point<T>& operator-=(point<T>& lhs, T const& rhs)
|
||||
{
|
||||
lhs.x -= rhs;
|
||||
lhs.y -= rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
point<T>& operator*=(point<T>& lhs, point<T> const& rhs)
|
||||
{
|
||||
lhs.x *= rhs.x;
|
||||
lhs.y *= rhs.y;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
point<T>& operator*=(point<T>& lhs, T const& rhs)
|
||||
{
|
||||
lhs.x *= rhs;
|
||||
lhs.y *= rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
point<T>& operator/=(point<T>& lhs, point<T> const& rhs)
|
||||
{
|
||||
lhs.x /= rhs.x;
|
||||
lhs.y /= rhs.y;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
point<T>& operator/=(point<T>& lhs, T const& rhs)
|
||||
{
|
||||
lhs.x /= rhs;
|
||||
lhs.y /= rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace mapbox
|
31
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/polygon.hpp
vendored
Normal file
31
third_party/geometry.hpp-0.9.2/include/mapbox/geometry/polygon.hpp
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
// mapbox
|
||||
#include <mapbox/geometry/point.hpp>
|
||||
|
||||
// stl
|
||||
#include <vector>
|
||||
|
||||
namespace mapbox {
|
||||
namespace geometry {
|
||||
|
||||
template <typename T, template <typename...> class Cont = std::vector>
|
||||
struct linear_ring : Cont<point<T>>
|
||||
{
|
||||
using coordinate_type = T;
|
||||
using point_type = point<T>;
|
||||
using container_type = Cont<point_type>;
|
||||
using container_type::container_type;
|
||||
};
|
||||
|
||||
template <typename T, template <typename...> class Cont = std::vector>
|
||||
struct polygon : Cont<linear_ring<T>>
|
||||
{
|
||||
using coordinate_type = T;
|
||||
using linear_ring_type = linear_ring<T>;
|
||||
using container_type = Cont<linear_ring_type>;
|
||||
using container_type::container_type;
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace mapbox
|
5
third_party/geometry.hpp-0.9.2/tests/collection.cpp
vendored
Normal file
5
third_party/geometry.hpp-0.9.2/tests/collection.cpp
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
#include <mapbox/geometry.hpp>
|
||||
|
||||
void test() {
|
||||
mapbox::geometry::geometry_collection<double> gc;
|
||||
}
|
260
third_party/geometry.hpp-0.9.2/tests/test.cpp
vendored
Normal file
260
third_party/geometry.hpp-0.9.2/tests/test.cpp
vendored
Normal file
@ -0,0 +1,260 @@
|
||||
#include <mapbox/geometry.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
using namespace mapbox::geometry;
|
||||
|
||||
static void testPoint() {
|
||||
point<double> p1;
|
||||
assert(int(p1.x) == 0);
|
||||
assert(int(p1.y) == 0);
|
||||
|
||||
point<uint32_t> p2(2, 3);
|
||||
point<uint32_t> p3(4, 6);
|
||||
|
||||
assert((p2 + p3) == point<uint32_t>(6, 9));
|
||||
assert((p2 + 1u) == point<uint32_t>(3, 4));
|
||||
assert((p3 - p2) == point<uint32_t>(2, 3));
|
||||
assert((p3 - 1u) == point<uint32_t>(3, 5));
|
||||
assert((p3 * p2) == point<uint32_t>(8, 18));
|
||||
assert((p2 * 2u) == point<uint32_t>(4, 6));
|
||||
assert((p3 / p2) == point<uint32_t>(2, 2));
|
||||
assert((p3 / 2u) == point<uint32_t>(2, 3));
|
||||
|
||||
{ point<uint32_t> p(2, 3); assert((p += p3) == point<uint32_t>(6, 9)); }
|
||||
{ point<uint32_t> p(2, 3); assert((p += 1u) == point<uint32_t>(3, 4)); }
|
||||
{ point<uint32_t> p(4, 6); assert((p -= p2) == point<uint32_t>(2, 3)); }
|
||||
{ point<uint32_t> p(4, 6); assert((p -= 1u) == point<uint32_t>(3, 5)); }
|
||||
{ point<uint32_t> p(4, 6); assert((p *= p2) == point<uint32_t>(8, 18)); }
|
||||
{ point<uint32_t> p(2, 3); assert((p *= 2u) == point<uint32_t>(4, 6)); }
|
||||
{ point<uint32_t> p(4, 6); assert((p /= p2) == point<uint32_t>(2, 2)); }
|
||||
{ point<uint32_t> p(4, 6); assert((p /= 2u) == point<uint32_t>(2, 3)); }
|
||||
}
|
||||
|
||||
static void testMultiPoint() {
|
||||
multi_point<double> mp1;
|
||||
assert(mp1.size() == 0);
|
||||
|
||||
multi_point<double> mp2(10);
|
||||
assert(mp2.size() == 10);
|
||||
|
||||
assert(mp1 == mp1);
|
||||
assert(!(mp1 != mp1));
|
||||
assert(mp1 != mp2);
|
||||
}
|
||||
|
||||
static void testLineString() {
|
||||
line_string<double> ls1;
|
||||
assert(ls1.size() == 0);
|
||||
|
||||
line_string<double> ls2(10);
|
||||
assert(ls2.size() == 10);
|
||||
|
||||
assert(ls1 == ls1);
|
||||
assert(!(ls1 != ls1));
|
||||
assert(ls1 != ls2);
|
||||
}
|
||||
|
||||
static void testMultiLineString() {
|
||||
multi_line_string<double> mls1;
|
||||
assert(mls1.size() == 0);
|
||||
|
||||
multi_line_string<double> mls2(10);
|
||||
assert(mls2.size() == 10);
|
||||
|
||||
assert(mls1 == mls1);
|
||||
assert(!(mls1 != mls1));
|
||||
assert(mls1 != mls2);
|
||||
}
|
||||
|
||||
static void testPolygon() {
|
||||
polygon<double> pg1;
|
||||
assert(pg1.size() == 0);
|
||||
|
||||
polygon<double> pg2({{{0, 1}}});
|
||||
assert(pg2.size() == 1);
|
||||
assert(pg2[0].size() == 1);
|
||||
assert(pg2[0][0] == point<double>(0, 1));
|
||||
|
||||
assert(pg1 == pg1);
|
||||
assert(!(pg1 != pg1));
|
||||
assert(pg1 != pg2);
|
||||
}
|
||||
|
||||
static void testMultiPolygon() {
|
||||
multi_polygon<double> mpg1;
|
||||
assert(mpg1.size() == 0);
|
||||
|
||||
multi_polygon<double> mpg2(10);
|
||||
assert(mpg2.size() == 10);
|
||||
|
||||
assert(mpg1 == mpg1);
|
||||
assert(!(mpg1 != mpg1));
|
||||
assert(mpg1 != mpg2);
|
||||
}
|
||||
|
||||
static void testGeometry() {
|
||||
geometry<double> pg { point<double>() };
|
||||
assert(pg.is<point<double>>());
|
||||
|
||||
geometry<double> lsg { line_string<double>() };
|
||||
assert(lsg.is<line_string<double>>());
|
||||
|
||||
geometry<double> pgg { polygon<double>() };
|
||||
assert(pgg.is<polygon<double>>());
|
||||
|
||||
geometry<double> mpg { multi_point<double>() };
|
||||
assert(mpg.is<multi_point<double>>());
|
||||
|
||||
geometry<double> mlsg { multi_line_string<double>() };
|
||||
assert(mlsg.is<multi_line_string<double>>());
|
||||
|
||||
geometry<double> mpgg { multi_polygon<double>() };
|
||||
assert(mpgg.is<multi_polygon<double>>());
|
||||
|
||||
geometry<double> gcg { geometry_collection<double>() };
|
||||
assert(gcg.is<geometry_collection<double>>());
|
||||
|
||||
assert(pg == pg);
|
||||
assert(!(pg != pg));
|
||||
assert(pg != lsg);
|
||||
}
|
||||
|
||||
static void testGeometryCollection() {
|
||||
geometry_collection<double> gc1;
|
||||
assert(gc1.size() == 0);
|
||||
|
||||
assert(gc1 == gc1);
|
||||
assert(!(gc1 != gc1));
|
||||
}
|
||||
|
||||
static void testFeature() {
|
||||
feature<double> pf { point<double>() };
|
||||
assert(pf.geometry.is<point<double>>());
|
||||
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<bool>());
|
||||
assert(p["bool"] == true);
|
||||
assert(p["string"].is<std::string>());
|
||||
assert(p["string"] == std::string("foo"));
|
||||
assert(p["double"].is<double>());
|
||||
assert(p["double"] == 2.5);
|
||||
assert(p["uint"].is<uint64_t>());
|
||||
assert(p["uint"] == uint64_t(10));
|
||||
assert(p["int"].is<int64_t>());
|
||||
assert(p["int"] == int64_t(-10));
|
||||
assert(p["null"].is<null_value_t>());
|
||||
assert(p["null"] == null_value);
|
||||
|
||||
p["null"] = null_value_t{};
|
||||
assert(p["null"].is<null_value_t>());
|
||||
assert(p["null"] == null_value);
|
||||
|
||||
assert(p == p);
|
||||
assert(!(p != p));
|
||||
|
||||
assert(pf == pf);
|
||||
assert(!(pf != pf));
|
||||
|
||||
assert(p.size() == 6);
|
||||
|
||||
feature<double> id1 { point<double>() };
|
||||
id1.id = { uint64_t(1) };
|
||||
|
||||
feature<double> id2 { point<double>() };
|
||||
id1.id = { uint64_t(2) };
|
||||
|
||||
assert(id1 == id1);
|
||||
assert(id1 != id2);
|
||||
}
|
||||
|
||||
static void testFeatureCollection() {
|
||||
feature_collection<double> fc1;
|
||||
assert(fc1.size() == 0);
|
||||
|
||||
assert(fc1 == fc1);
|
||||
assert(!(fc1 != fc1));
|
||||
}
|
||||
|
||||
struct point_counter {
|
||||
std::size_t count = 0;
|
||||
template <class Point>
|
||||
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<double>()) == 1);
|
||||
assert(count_points(line_string<double>({{0, 1}, {2, 3}})) == 2);
|
||||
assert(count_points(geometry<double>(polygon<double>({{{0, 1}, {2, 3}}}))) == 2);
|
||||
|
||||
auto point_negator = [] (point<double>& p) { p *= -1.0; };
|
||||
|
||||
point<double> p(1, 2);
|
||||
for_each_point(p, point_negator);
|
||||
assert(p == point<double>(-1, -2));
|
||||
|
||||
line_string<double> ls({{0, 1}, {2, 3}});
|
||||
for_each_point(ls, point_negator);
|
||||
assert(ls == line_string<double>({{0, -1}, {-2, -3}}));
|
||||
|
||||
geometry<double> g(polygon<double>({{{0, 1}, {2, 3}}}));
|
||||
for_each_point(g, point_negator);
|
||||
assert(g == geometry<double>(polygon<double>({{{0, -1}, {-2, -3}}})));
|
||||
|
||||
// Custom geometry type
|
||||
using my_geometry = mapbox::util::variant<point<double>>;
|
||||
assert(count_points(my_geometry(point<double>())) == 1);
|
||||
|
||||
// Custom point type
|
||||
struct my_point {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
};
|
||||
assert(count_points(std::vector<my_point>({my_point{0, 1}})) == 1);
|
||||
assert(count_points(mapbox::util::variant<my_point>(my_point{0, 1})) == 1);
|
||||
}
|
||||
|
||||
static void testEnvelope() {
|
||||
assert(envelope(point<double>(0, 0)) == box<double>({0, 0}, {0, 0}));
|
||||
assert(envelope(line_string<double>({{0, 1}, {2, 3}})) == box<double>({0, 1}, {2, 3}));
|
||||
assert(envelope(polygon<double>({{{0, 1}, {2, 3}}})) == box<double>({0, 1}, {2, 3}));
|
||||
|
||||
assert(envelope(multi_point<double>({{0, 0}})) == box<double>({0, 0}, {0, 0}));
|
||||
assert(envelope(multi_line_string<double>({{{0, 1}, {2, 3}}})) == box<double>({0, 1}, {2, 3}));
|
||||
assert(envelope(multi_polygon<double>({{{{0, 1}, {2, 3}}}})) == box<double>({0, 1}, {2, 3}));
|
||||
|
||||
assert(envelope(geometry<int>(point<int>(0, 0))) == box<int>({0, 0}, {0, 0}));
|
||||
assert(envelope(geometry_collection<int>({point<int>(0, 0)})) == box<int>({0, 0}, {0, 0}));
|
||||
}
|
||||
|
||||
int main() {
|
||||
testPoint();
|
||||
testMultiPoint();
|
||||
testLineString();
|
||||
testMultiLineString();
|
||||
testPolygon();
|
||||
testMultiPolygon();
|
||||
testGeometry();
|
||||
testGeometryCollection();
|
||||
testFeature();
|
||||
testFeatureCollection();
|
||||
|
||||
testForEachPoint();
|
||||
testEnvelope();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user