Merge remote-tracking branch 'origin/master' into nested_namespace
This commit is contained in:
commit
d7c44f0bc0
180
CMakeLists.txt
180
CMakeLists.txt
@ -1,8 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR AND NOT MSVC_IDE)
|
||||
message(FATAL_ERROR "In-source builds are not allowed.
|
||||
@ -33,7 +33,6 @@ option(ENABLE_COVERAGE "Build with coverage instrumentalisation" OFF)
|
||||
option(ENABLE_SANITIZER "Use memory sanitizer for Debug build" OFF)
|
||||
option(ENABLE_LTO "Use LTO if available" OFF)
|
||||
option(ENABLE_FUZZING "Fuzz testing using LLVM's libFuzzer" OFF)
|
||||
option(ENABLE_GOLD_LINKER "Use GNU gold linker if available" ON)
|
||||
option(ENABLE_NODE_BINDINGS "Build NodeJs bindings" OFF)
|
||||
option(ENABLE_CLANG_TIDY "Enables clang-tidy checks" OFF)
|
||||
|
||||
@ -113,29 +112,12 @@ include(CheckCXXCompilerFlag)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(bitness 32)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(bitness 64)
|
||||
message(STATUS "Building on a 64 bit system")
|
||||
else()
|
||||
message(STATUS "Building on a 32 bit system")
|
||||
endif()
|
||||
|
||||
if(WIN32 AND MSVC_VERSION LESS 1900)
|
||||
message(FATAL_ERROR "Building with Microsoft compiler needs Latest Visual Studio 2015 (Community or better)")
|
||||
endif()
|
||||
|
||||
# Strictly require GCC>=5.0 and Clang>=3.4 - GCC 4.8 is already too old for C++14.
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)
|
||||
message(FATAL_ERROR "GCC>=5.0 required. In case you are on Ubuntu upgrade via ppa:ubuntu-toolchain-r/test")
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4)
|
||||
message(FATAL_ERROR "Clang>=3.4 required. In case you are on Ubuntu upgrade via http://apt.llvm.org")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/include/)
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/include/)
|
||||
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/sol2-3.3.0/include)
|
||||
@ -190,26 +172,6 @@ add_library(osrm_customize src/osrm/customizer.cpp $<TARGET_OBJECTS:CUSTOMIZER>
|
||||
add_library(osrm_update $<TARGET_OBJECTS:UPDATER> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
|
||||
add_library(osrm_store $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
|
||||
|
||||
if(ENABLE_GOLD_LINKER)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
|
||||
if("${LD_VERSION}" MATCHES "GNU gold")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold -Wl,--disable-new-dtags")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=gold -Wl,--disable-new-dtags")
|
||||
set(OSRM_LDFLAGS "${OSRM_LDFLAGS} -fuse-ld=gold -Wl,--disable-new-dtags")
|
||||
message(STATUS "Using GNU gold as linker.")
|
||||
|
||||
# Issue 2785: check gold binutils version and don't use gc-sections for versions prior 2.25
|
||||
string(REGEX REPLACE ".*\\(GNU Binutils[^\\)0-9]+([0-9]+\\.[0-9]+)[^\\)]*\\).*" "\\1" GOLD_BINUTILS_VERSION "${LD_VERSION}")
|
||||
if ("${GOLD_BINUTILS_VERSION}" VERSION_LESS "2.26")
|
||||
message(STATUS "Disabling gc-sections on gold binutils < 2.26, see: https://sourceware.org/bugzilla/show_bug.cgi?id=17639")
|
||||
set(LD_AVOID_GC_SECTIONS TRUE)
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "GNU gold linker isn't available.")
|
||||
set(ENABLE_GOLD_LINKER OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Explicitly set the build type to Release if no other type is specified
|
||||
# on the command line. Without this, cmake defaults to an unoptimized,
|
||||
# non-debug build, which almost nobody wants.
|
||||
@ -247,74 +209,17 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og -ggdb")
|
||||
endif()
|
||||
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES MinRelSize OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)
|
||||
message(STATUS "Configuring release mode optimizations")
|
||||
# Check if LTO is available
|
||||
check_cxx_compiler_flag("-Wl,-flto" LTO_AVAILABLE)
|
||||
|
||||
if(ENABLE_LTO AND LTO_AVAILABLE)
|
||||
set(OLD_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
# GCC in addition allows parallelizing LTO
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
include(ProcessorCount)
|
||||
ProcessorCount(NPROC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto=${NPROC}")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
|
||||
endif()
|
||||
set(CHECK_LTO_SRC "int main(){return 0;}")
|
||||
check_cxx_source_compiles("${CHECK_LTO_SRC}" LTO_WORKS)
|
||||
if(LTO_WORKS)
|
||||
message(STATUS "LTO working")
|
||||
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -flto")
|
||||
set(OSRM_LDFLAGS "${OSRM_LDFLAGS} -flto")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -flto")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -flto")
|
||||
else()
|
||||
message(STATUS "LTO broken")
|
||||
set(CMAKE_CXX_FLAGS "${OLD_CXX_FLAGS}")
|
||||
set(ENABLE_LTO Off)
|
||||
endif()
|
||||
|
||||
# Since gcc 4.9 the LTO format is non-standart ('slim'), so we need to use the build-in tools
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND NOT MINGW)
|
||||
find_program(GCC_AR gcc-ar)
|
||||
find_program(GCC_RANLIB gcc-ranlib)
|
||||
if ("${GCC_AR}" STREQUAL "GCC_AR-NOTFOUND" OR "${GCC_RANLIB}" STREQUAL "GCC_RANLIB-NOTFOUND")
|
||||
message(WARNING "GCC specific binutils not found. In case of linker issues export env vars: AR=gcc-ar, NM=gcc-nm, RANLIB=gcc-ranlib")
|
||||
else()
|
||||
message(STATUS "Using GCC specific binutils for LTO:")
|
||||
message(STATUS " ${GCC_AR}")
|
||||
message(STATUS " ${GCC_RANLIB}")
|
||||
set(CMAKE_AR ${GCC_AR})
|
||||
set(CMAKE_RANLIB ${GCC_RANLIB})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Same for clang LTO requires their own toolchain
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
find_program(LLVM_AR llvm-ar)
|
||||
find_program(LLVM_RANLIB llvm-ranlib)
|
||||
if ("${LLVM_AR}" STREQUAL "LLVM_AR-NOTFOUND" OR "${LLVM_RANLIB}" STREQUAL "LLVM_RANLIB-NOTFOUND")
|
||||
message(WARNING "LLVM specific binutils not found.")
|
||||
else()
|
||||
message(STATUS "Using LLVM specific binutils for LTO:")
|
||||
message(STATUS " ${LLVM_AR}")
|
||||
message(STATUS " ${LLVM_RANLIB}")
|
||||
set(CMAKE_AR ${LLVM_AR})
|
||||
set(CMAKE_RANLIB ${LLVM_RANLIB})
|
||||
endif()
|
||||
endif()
|
||||
if(ENABLE_LTO AND (CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES MinRelSize OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo))
|
||||
include(CheckIPOSupported)
|
||||
check_ipo_supported(RESULT LTO_SUPPORTED OUTPUT error)
|
||||
if(LTO_SUPPORTED)
|
||||
message(STATUS "IPO / LTO enabled")
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
else()
|
||||
message(WARNING "IPO / LTO not supported: <${error}>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# TODO: this was added for Mason, we are not sure if it is true after migration to Conan
|
||||
if(UNIX AND NOT APPLE AND ENABLE_CONAN AND (LTO_WORKS OR ENABLE_GOLD_LINKER))
|
||||
message(WARNING "ENABLE_CONAN and ENABLE_LTO/ENABLE_GOLD_LINKER may not work on all linux systems currently")
|
||||
endif()
|
||||
|
||||
set(MAYBE_COVERAGE_LIBRARIES "")
|
||||
if (ENABLE_COVERAGE)
|
||||
if (NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
@ -352,14 +257,6 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
add_dependency_defines(-DWIN32)
|
||||
set(OPTIONAL_SOCKET_LIBS ws2_32 wsock32)
|
||||
endif()
|
||||
|
||||
# -fpermissive is required for parallel_do Intel TBB internal issue with GCC < 5
|
||||
# https://github.com/Project-OSRM/osrm-backend/pull/3603#issuecomment-277688589
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)
|
||||
message(STATUS "Adding -fpermissive for GCC version < 5 bug (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51048). See #3603.")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")
|
||||
endif()
|
||||
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
|
||||
# using Intel C++
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -ipo -fPIC")
|
||||
@ -377,48 +274,6 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
target_link_libraries(osrm-extract wsock32 ws2_32)
|
||||
endif()
|
||||
|
||||
# Configuring linker
|
||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} "-Wl,--version" ERROR_QUIET OUTPUT_VARIABLE LINKER_VERSION)
|
||||
# For ld.gold and ld.bfs (the GNU linkers) we optimize hard
|
||||
if("${LINKER_VERSION}" MATCHES "GNU gold" OR "${LINKER_VERSION}" MATCHES "GNU ld")
|
||||
message(STATUS "Setting linker optimizations")
|
||||
if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR "${LD_AVOID_GC_SECTIONS}"))
|
||||
# Tell compiler to put every function in separate section, linker can then match sections and functions
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections")
|
||||
# Tell linker to do dead code and data eminination during link time discarding sections
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -Wl,--gc-sections")
|
||||
endif()
|
||||
# Default linker optimization flags
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -Wl,-O1 -Wl,--hash-style=gnu -Wl,--sort-common")
|
||||
|
||||
else()
|
||||
message(STATUS "Using unknown linker, not setting linker optimizations")
|
||||
endif ()
|
||||
set(OSRM_LDFLAGS "${OSRM_LDFLAGS} ${LINKER_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
|
||||
|
||||
# Activate C++1y
|
||||
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
|
||||
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -std=c++17")
|
||||
endif()
|
||||
|
||||
# Configuring other platform dependencies
|
||||
if(APPLE)
|
||||
execute_process(COMMAND xcrun --sdk macosx --show-sdk-path OUTPUT_VARIABLE CMAKE_OSX_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
|
||||
string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
|
||||
if(OSXLIBSTD)
|
||||
message(STATUS "linking against ${OSXLIBSTD}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${OSXLIBSTD}")
|
||||
elseif(DARWIN_VERSION GREATER 12)
|
||||
message(STATUS "linking against libc++")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(MAYBE_RT_LIBRARY -lrt)
|
||||
endif()
|
||||
@ -432,11 +287,6 @@ 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-2778eb8/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)
|
||||
target_no_warning(MICROTAR unused-variable)
|
||||
@ -550,12 +400,7 @@ if(ENABLE_CONAN)
|
||||
# expat and bzip2 are used from conan rather than the system
|
||||
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/include)
|
||||
else()
|
||||
if (BUILD_ROUTED)
|
||||
# osrm-routed requires newer boost:asio
|
||||
find_package(Boost 1.70 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||
else()
|
||||
find_package(Boost 1.60 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||
endif()
|
||||
find_package(Boost 1.70 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||
add_dependency_includes(${Boost_INCLUDE_DIRS})
|
||||
|
||||
find_package(TBB REQUIRED)
|
||||
@ -602,7 +447,6 @@ if(ENABLE_CCACHE AND (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILE
|
||||
message(STATUS "Using ccache to speed up incremental builds")
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||
set(ENV{CCACHE_CPP2} "true")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
# - Check whether the CXX compiler supports a given flag.
|
||||
# CHECK_CXX_COMPILER_FLAG(<flag> <var>)
|
||||
# <flag> - the compiler flag
|
||||
# <var> - variable to store the result
|
||||
# This internally calls the check_cxx_source_compiles macro. See help
|
||||
# for CheckCXXSourceCompiles for a listing of variables that can
|
||||
# modify the build.
|
||||
|
||||
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
INCLUDE(CheckCXXSourceCompiles)
|
||||
|
||||
MACRO (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT)
|
||||
SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
|
||||
SET(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
|
||||
CHECK_CXX_SOURCE_COMPILES("int main() { return 0;}" ${_RESULT}
|
||||
# Some compilers do not fail with a bad flag
|
||||
FAIL_REGEX "unrecognized .*option" # GNU
|
||||
FAIL_REGEX "ignoring unknown option" # MSVC
|
||||
FAIL_REGEX "[Uu]nknown option" # HP
|
||||
FAIL_REGEX "[Ww]arning: [Oo]ption" # SunPro
|
||||
FAIL_REGEX "command option .* is not recognized" # XL
|
||||
)
|
||||
SET (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
|
||||
ENDMACRO (CHECK_CXX_COMPILER_FLAG)
|
@ -36,7 +36,10 @@
|
||||
# This is because, the lua location is not standardized and may exist in
|
||||
# locations other than lua/
|
||||
|
||||
include(FindPkgConfig)
|
||||
if(NOT PKG_CONFIG_FOUND)
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(PkgConfig)
|
||||
endif()
|
||||
|
||||
unset(_lua_include_subdirs)
|
||||
unset(_lua_library_names)
|
||||
|
@ -1,7 +1,7 @@
|
||||
# https://github.com/sbellus/json-cmake/blob/9913da8800b95322d393894d3525d634568f305e/JSONParser.cmake
|
||||
# MIT Licensed - https://github.com/sbellus/json-cmake/blob/master/LICENSE
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
|
||||
if (DEFINED JSonParserGuard)
|
||||
return()
|
||||
|
@ -5,7 +5,7 @@ RUN mkdir -p /src && mkdir -p /opt
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get -y --no-install-recommends install ca-certificates cmake make git gcc g++ libbz2-dev libxml2-dev wget \
|
||||
libzip-dev libboost1.74-all-dev lua5.4 liblua5.4-dev -o APT::Install-Suggests=0 -o APT::Install-Recommends=0
|
||||
libzip-dev libboost1.74-all-dev lua5.4 liblua5.4-dev pkg-config -o APT::Install-Suggests=0 -o APT::Install-Recommends=0
|
||||
|
||||
RUN NPROC=${BUILD_CONCURRENCY:-$(nproc)} && \
|
||||
ldconfig /usr/local/lib && \
|
||||
|
@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 2.8.8)
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
|
||||
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR AND NOT MSVC_IDE)
|
||||
message(FATAL_ERROR "In-source builds are not allowed.
|
||||
@ -12,20 +12,18 @@ endif()
|
||||
|
||||
project(osrm-example C CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
set(bitness 32)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(bitness 64)
|
||||
message(STATUS "Building on a 64 bit system")
|
||||
else()
|
||||
message(STATUS "Building on a 32 bit system")
|
||||
endif()
|
||||
|
||||
if(WIN32 AND MSVC_VERSION LESS 1900)
|
||||
message(FATAL_ERROR "Building with Microsoft compiler needs Latest Visual Studio 2015 (Community or better)")
|
||||
endif()
|
||||
|
||||
link_directories(${LibOSRM_LIBRARY_DIRS})
|
||||
add_executable(osrm-example example.cpp)
|
||||
|
||||
|
86
include/util/cheap_ruler.hpp
Normal file
86
include/util/cheap_ruler.hpp
Normal file
@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
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;
|
||||
};
|
||||
} // namespace geometry
|
||||
|
||||
namespace cheap_ruler
|
||||
{
|
||||
|
||||
using point = geometry::point<double>;
|
||||
|
||||
class CheapRuler
|
||||
{
|
||||
|
||||
// Values that define WGS84 ellipsoid model of the Earth
|
||||
static constexpr double RE = 6378.137; // equatorial radius
|
||||
static constexpr double FE = 1.0 / 298.257223563; // flattening
|
||||
|
||||
static constexpr double E2 = FE * (2 - FE);
|
||||
static constexpr double RAD = M_PI / 180.0;
|
||||
|
||||
public:
|
||||
explicit CheapRuler(double latitude)
|
||||
{
|
||||
// Curvature formulas from https://en.wikipedia.org/wiki/Earth_radius#Meridional
|
||||
double mul = RAD * RE * 1000;
|
||||
double coslat = std::cos(latitude * RAD);
|
||||
double w2 = 1 / (1 - E2 * (1 - coslat * coslat));
|
||||
double w = std::sqrt(w2);
|
||||
|
||||
// multipliers for converting longitude and latitude degrees into distance
|
||||
kx = mul * w * coslat; // based on normal radius of curvature
|
||||
ky = mul * w * w2 * (1 - E2); // based on meridonal radius of curvature
|
||||
}
|
||||
|
||||
double squareDistance(point a, point b) const
|
||||
{
|
||||
auto dx = longDiff(a.x, b.x) * kx;
|
||||
auto dy = (a.y - b.y) * ky;
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
|
||||
//
|
||||
// Given two points of the form [x = longitude, y = latitude], returns the distance.
|
||||
//
|
||||
double distance(point a, point b) const { return std::sqrt(squareDistance(a, b)); }
|
||||
|
||||
//
|
||||
// Returns the bearing between two points in angles.
|
||||
//
|
||||
double bearing(point a, point b) const
|
||||
{
|
||||
auto dx = longDiff(b.x, a.x) * kx;
|
||||
auto dy = (b.y - a.y) * ky;
|
||||
|
||||
return std::atan2(dx, dy) / RAD;
|
||||
}
|
||||
|
||||
private:
|
||||
double ky;
|
||||
double kx;
|
||||
static double longDiff(double a, double b) { return std::remainder(a - b, 360); }
|
||||
};
|
||||
|
||||
} // namespace cheap_ruler
|
||||
} // namespace mapbox
|
@ -8,13 +8,13 @@ namespace osrm::util
|
||||
|
||||
template <typename It, typename Value> inline void static_assert_iter_value()
|
||||
{
|
||||
using IterValueType = typename std::iterator_traits;<It>::value_type;
|
||||
using IterValueType = typename std::iterator_traits<It>::value_type;
|
||||
static_assert(std::is_same<IterValueType, Value>::value, "");
|
||||
}
|
||||
|
||||
template <typename It, typename Category> inline void static_assert_iter_category()
|
||||
{
|
||||
using IterCategoryType = typename std::iterator_traits;<It>::iterator_category;
|
||||
using IterCategoryType = typename std::iterator_traits<It>::iterator_category;
|
||||
static_assert(std::is_base_of<Category, IterCategoryType>::value, "");
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,4 @@
|
||||
# node-cmake requires CMake 3.1 features; for the osrm project we only
|
||||
# require CMake 2.8.11 so that we can build e.g. on Trusty by default.
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
|
||||
message(STATUS "Building node_osrm")
|
||||
|
||||
|
@ -1,12 +1,11 @@
|
||||
#include "util/coordinate_calculation.hpp"
|
||||
#include "util/cheap_ruler.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/trigonometry_table.hpp"
|
||||
#include "util/web_mercator.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <mapbox/cheap_ruler.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
@ -26,8 +25,8 @@ class CheapRulerContainer
|
||||
{
|
||||
for (int n = 0; n < number_of_rulers; n++)
|
||||
{
|
||||
cheap_ruler_cache[n] = mapbox::cheap_ruler::CheapRuler(
|
||||
step * (n + 0.5) / COORDINATE_PRECISION, mapbox::cheap_ruler::CheapRuler::Meters);
|
||||
cheap_ruler_cache[n] =
|
||||
mapbox::cheap_ruler::CheapRuler(step * (n + 0.5) / COORDINATE_PRECISION);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,18 +0,0 @@
|
||||
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
|
@ -1,2 +0,0 @@
|
||||
build/
|
||||
mason_packages/
|
25
third_party/cheap-ruler-cpp-2778eb8/.travis.yml
vendored
25
third_party/cheap-ruler-cpp-2778eb8/.travis.yml
vendored
@ -1,25 +0,0 @@
|
||||
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
|
@ -1,27 +0,0 @@
|
||||
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-2778eb8/LICENSE
vendored
15
third_party/cheap-ruler-cpp-2778eb8/LICENSE
vendored
@ -1,15 +0,0 @@
|
||||
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-2778eb8/README.md
vendored
199
third_party/cheap-ruler-cpp-2778eb8/README.md
vendored
@ -1,199 +0,0 @@
|
||||
# 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
|
||||
```
|
@ -1,11 +0,0 @@
|
||||
# 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()
|
@ -1,235 +0,0 @@
|
||||
# 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()
|
@ -1,390 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <mapbox/geometry/box.hpp>
|
||||
#include <mapbox/geometry/multi_line_string.hpp>
|
||||
#include <mapbox/geometry/polygon.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#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 {
|
||||
|
||||
// Values that define WGS84 ellipsoid model of the Earth
|
||||
static constexpr double RE = 6378.137; // equatorial radius
|
||||
static constexpr double FE = 1.0 / 298.257223563; // flattening
|
||||
|
||||
static constexpr double E2 = FE * (2 - FE);
|
||||
static constexpr double RAD = M_PI / 180.0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Curvature formulas from https://en.wikipedia.org/wiki/Earth_radius#Meridional
|
||||
double mul = RAD * RE * m;
|
||||
double coslat = std::cos(latitude * RAD);
|
||||
double w2 = 1 / (1 - E2 * (1 - coslat * coslat));
|
||||
double w = std::sqrt(w2);
|
||||
|
||||
// multipliers for converting longitude and latitude degrees into distance
|
||||
kx = mul * w * coslat; // based on normal radius of curvature
|
||||
ky = mul * w * w2 * (1 - E2); // based on meridonal radius of curvature
|
||||
}
|
||||
|
||||
static CheapRuler fromTile(uint32_t y, uint32_t z) {
|
||||
assert(z < 32);
|
||||
double n = M_PI * (1. - 2. * (y + 0.5) / double(uint32_t(1) << z));
|
||||
double latitude = std::atan(std::sinh(n)) / RAD;
|
||||
|
||||
return CheapRuler(latitude);
|
||||
}
|
||||
|
||||
double squareDistance(point a, point b) const {
|
||||
auto dx = longDiff(a.x, b.x) * kx;
|
||||
auto dy = (a.y - b.y) * ky;
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
|
||||
//
|
||||
// Given two points of the form [x = longitude, y = latitude], returns the distance.
|
||||
//
|
||||
double distance(point a, point b) const {
|
||||
return std::sqrt(squareDistance(a, b));
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the bearing between two points in angles.
|
||||
//
|
||||
double bearing(point a, point b) const {
|
||||
auto dx = longDiff(b.x, a.x) * kx;
|
||||
auto dy = (b.y - a.y) * ky;
|
||||
|
||||
return std::atan2(dx, dy) / RAD;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns a new point given distance and bearing from the starting point.
|
||||
//
|
||||
point destination(point origin, double dist, double bearing_) const {
|
||||
auto a = bearing_ * RAD;
|
||||
|
||||
return offset(origin, std::sin(a) * dist, std::cos(a) * dist);
|
||||
}
|
||||
|
||||
//
|
||||
// Returns a new point given easting and northing offsets from the starting point.
|
||||
//
|
||||
point offset(point origin, double dx, double dy) const {
|
||||
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 (size_t i = 1; i < points.size(); ++i) {
|
||||
total += distance(points[i - 1], points[i]);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
//
|
||||
// Given a polygon (an array of rings, where each ring is an array of points),
|
||||
// returns the area.
|
||||
//
|
||||
double area(polygon poly) const {
|
||||
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 += longDiff(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) const {
|
||||
double sum = 0.;
|
||||
|
||||
if (line.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
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 the distance from a point `p` to a line segment `a` to `b`.
|
||||
//
|
||||
double pointToSegmentDistance(const point& p, const point& a, const point& b) const {
|
||||
auto t = 0.0;
|
||||
auto x = a.x;
|
||||
auto y = a.y;
|
||||
auto dx = longDiff(b.x, x) * kx;
|
||||
auto dy = (b.y - y) * ky;
|
||||
|
||||
if (dx != 0.0 || dy != 0.0) {
|
||||
t = (longDiff(p.x, x) * kx * dx + (p.y - y) * ky * dy) / (dx * dx + dy * dy);
|
||||
if (t > 1.0) {
|
||||
x = b.x;
|
||||
y = b.y;
|
||||
} else if (t > 0.0) {
|
||||
x += (dx / kx) * t;
|
||||
y += (dy / ky) * t;
|
||||
}
|
||||
}
|
||||
return distance(p, { x, y });
|
||||
}
|
||||
|
||||
//
|
||||
// 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) const {
|
||||
double minDist = std::numeric_limits<double>::infinity();
|
||||
double minX = 0., minY = 0., minI = 0., minT = 0.;
|
||||
|
||||
if (line.empty()) {
|
||||
return std::make_tuple(point(), 0., 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 = longDiff(line[i + 1].x, x) * kx;
|
||||
auto dy = (line[i + 1].y - y) * ky;
|
||||
|
||||
if (dx != 0. || dy != 0.) {
|
||||
t = (longDiff(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;
|
||||
}
|
||||
}
|
||||
|
||||
auto sqDist = squareDistance(p, {x, y});
|
||||
|
||||
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) const {
|
||||
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) const {
|
||||
double sum = 0.;
|
||||
line_string slice;
|
||||
|
||||
for (size_t i = 1; i < line.size(); ++i) {
|
||||
auto p0 = line[i - 1];
|
||||
auto p1 = line[i];
|
||||
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) const {
|
||||
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) const {
|
||||
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.
|
||||
//
|
||||
static bool insideBBox(point p, box bbox) {
|
||||
return p.y >= bbox.min.y &&
|
||||
p.y <= bbox.max.y &&
|
||||
longDiff(p.x, bbox.min.x) >= 0 &&
|
||||
longDiff(p.x, bbox.max.x) <= 0;
|
||||
}
|
||||
|
||||
static point interpolate(point a, point b, double t) {
|
||||
double dx = longDiff(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;
|
||||
static double longDiff(double a, double b) {
|
||||
return std::remainder(a - b, 360);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace cheap_ruler
|
||||
} // namespace mapbox
|
@ -1,276 +0,0 @@
|
||||
#include <mapbox/cheap_ruler.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
#include <random>
|
||||
|
||||
#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) {
|
||||
{
|
||||
cr::line_string emptyLine {};
|
||||
auto expected = 0.0;
|
||||
auto actual = ruler.lineDistance(emptyLine);
|
||||
assertErr(expected, actual, 0.0);
|
||||
}
|
||||
|
||||
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) {
|
||||
{
|
||||
cr::point emptyPoint {};
|
||||
cr::line_string emptyLine {};
|
||||
auto expected = emptyPoint;
|
||||
auto actual = ruler.along(emptyLine, 0.0);
|
||||
|
||||
assertErr(expected.x, actual.x, 0.0);
|
||||
assertErr(expected.y, actual.y, 0.0);
|
||||
}
|
||||
|
||||
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 });
|
||||
|
||||
assertErr(std::get<0>(result).x, -77.03052689033436, 1e-6);
|
||||
assertErr(std::get<0>(result).y, 38.880457324462576, 1e-6);
|
||||
ASSERT_EQ(std::get<1>(result), 0u); // index
|
||||
assertErr(std::get<2>(result), 0.5544221677861756, 1e-6); // 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, pointToSegmentDistance) {
|
||||
cr::point p{ -77.034076, 38.882017 };
|
||||
cr::point p0{ -77.031669, 38.878605 };
|
||||
cr::point p1{ -77.029609, 38.881946 };
|
||||
const auto distance = ruler.pointToSegmentDistance(p, p0, p1);
|
||||
assertErr(0.37461484020420416, distance, 1e-6);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
/// @todo Should update turf_lineSlice and revert maxError back.
|
||||
assertErr(expected, actual, 1e-4);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CheapRulerTest, lineSliceAlong) {
|
||||
{
|
||||
cr::line_string emptyLine {};
|
||||
auto expected = ruler.lineDistance(emptyLine);
|
||||
auto actual = ruler.lineDistance(ruler.lineSliceAlong(0.0, 0.0, emptyLine));
|
||||
assertErr(expected, actual, 0.0);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
/// @todo Should update turf_lineSlice and revert maxError back.
|
||||
assertErr(expected, actual, 1e-4);
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
assertErr(0.018676476689649835, actual, 1e-6);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
assertErr(bbox2.min.x, 29.989319515875376, 1e-6);
|
||||
assertErr(bbox2.min.y, 37.99098271225711, 1e-6);
|
||||
assertErr(bbox2.max.x, 40.01068048412462, 1e-6);
|
||||
assertErr(bbox2.max.y, 39.00901728774289, 1e-6);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
TEST_F(CheapRulerTest, longitudeWrap) {
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::bernoulli_distribution d(0.5); // true with prob 0.5
|
||||
|
||||
auto r = cr::CheapRuler(50.5);
|
||||
cr::polygon poly(1);
|
||||
auto& ring = poly[0];
|
||||
cr::line_string line;
|
||||
cr::point origin(0, 50.5); // Greenwich
|
||||
auto rad = 1000.0;
|
||||
// construct a regular dodecagon
|
||||
for (int i = -180; i <= 180; i += 30) {
|
||||
auto p = r.destination(origin, rad, i);
|
||||
// shift randomly east/west to the international date line
|
||||
p.x += d(gen) ? 180 : -180;
|
||||
ring.push_back(p);
|
||||
line.push_back(p);
|
||||
}
|
||||
auto p = r.lineDistance(line);
|
||||
auto a = r.area(poly);
|
||||
// cheap_ruler does planar calculations, so the perimeter and area of a
|
||||
// planar regular dodecagon with circumradius rad are used in these checks.
|
||||
// For the record, the results for rad = 1000 km are:
|
||||
// perimeter area
|
||||
// planar 6211.657082 3000000
|
||||
// WGS84 6187.959236 2996317.6328
|
||||
// error 0.38% 0.12%
|
||||
assertErr(12 * rad / sqrt(2 + sqrt(3.0)), p, 1e-12);
|
||||
assertErr(3 * rad * rad, a, 1e-12);
|
||||
for (int j = 1; j < (int)line.size(); ++j) {
|
||||
auto azi = r.bearing(line[j-1], line[j]);
|
||||
// offset expect and actual by 1 to make err criterion absolute
|
||||
assertErr(1, std::remainder(270 - 15 + 30*j - azi, 360) + 1, 1e-12);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
2
third_party/geometry.hpp-0.9.2/.gitignore
vendored
2
third_party/geometry.hpp-0.9.2/.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
mason_packages
|
||||
test
|
3
third_party/geometry.hpp-0.9.2/.gitmodules
vendored
3
third_party/geometry.hpp-0.9.2/.gitmodules
vendored
@ -1,3 +0,0 @@
|
||||
[submodule ".mason"]
|
||||
path = .mason
|
||||
url = https://github.com/mapbox/mason.git
|
50
third_party/geometry.hpp-0.9.2/.travis.yml
vendored
50
third_party/geometry.hpp-0.9.2/.travis.yml
vendored
@ -1,50 +0,0 @@
|
||||
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
13
third_party/geometry.hpp-0.9.2/LICENSE
vendored
@ -1,13 +0,0 @@
|
||||
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
19
third_party/geometry.hpp-0.9.2/Makefile
vendored
@ -1,19 +0,0 @@
|
||||
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
83
third_party/geometry.hpp-0.9.2/README.md
vendored
@ -1,83 +0,0 @@
|
||||
# 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);
|
||||
}
|
||||
```
|
@ -1,13 +0,0 @@
|
||||
#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>
|
@ -1,34 +0,0 @@
|
||||
#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
|
@ -1,33 +0,0 @@
|
||||
#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
|
@ -1,91 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <mapbox/geometry/geometry.hpp>
|
||||
|
||||
#include <mapbox/variant.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <mapbox/optional.hpp>
|
||||
|
||||
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 {};
|
||||
mapbox::util::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 {},
|
||||
mapbox::util::optional<identifier> id_ = mapbox::util::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
|
@ -1,45 +0,0 @@
|
||||
#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
|
@ -1,58 +0,0 @@
|
||||
#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
|
@ -1,21 +0,0 @@
|
||||
#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
|
@ -1,21 +0,0 @@
|
||||
#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
|
@ -1,21 +0,0 @@
|
||||
#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
|
@ -1,21 +0,0 @@
|
||||
#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
|
@ -1,35 +0,0 @@
|
||||
#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
|
@ -1,119 +0,0 @@
|
||||
#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
|
@ -1,31 +0,0 @@
|
||||
#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
|
@ -1,5 +0,0 @@
|
||||
#include <mapbox/geometry.hpp>
|
||||
|
||||
void test() {
|
||||
mapbox::geometry::geometry_collection<double> gc;
|
||||
}
|
260
third_party/geometry.hpp-0.9.2/tests/test.cpp
vendored
260
third_party/geometry.hpp-0.9.2/tests/test.cpp
vendored
@ -1,260 +0,0 @@
|
||||
#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