pax_global_header00006660000000000000000000000064133710457640014524gustar00rootroot0000000000000052 comment=c83a2ab18a225254f128b6f5115aa39d04f2de21 geometry.hpp-1.0.0/000077500000000000000000000000001337104576400141435ustar00rootroot00000000000000geometry.hpp-1.0.0/.clang-format000066400000000000000000000050751337104576400165250ustar00rootroot00000000000000--- # Mapbox.Variant C/C+ style Language: Cpp AccessModifierOffset: -2 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false AlignEscapedNewlinesLeft: false AlignOperands: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: true AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false AlwaysBreakTemplateDeclarations: true BinPackArguments: true BinPackParameters: true BraceWrapping: AfterClass: true AfterControlStatement: true AfterEnum: true AfterFunction: true AfterNamespace: false AfterObjCDeclaration: true AfterStruct: true AfterUnion: true BeforeCatch: true BeforeElse: true IndentBraces: false BreakBeforeBinaryOperators: None BreakBeforeBraces: Custom BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false ColumnLimit: 0 CommentPragmas: '^ IWYU pragma:' ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] IncludeCategories: - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 - Regex: '^(<|"(gtest|isl|json)/)' Priority: 3 - Regex: '.*' Priority: 1 IndentCaseLabels: false IndentWidth: 4 IndentWrappedFunctionNames: false KeepEmptyLinesAtTheStartOfBlocks: true MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None ObjCBlockIndentWidth: 2 ObjCSpaceAfterProperty: false ObjCSpaceBeforeProtocolList: true PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Left ReflowComments: true SortIncludes: false SpaceAfterCStyleCast: false SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Cpp11 TabWidth: 4 UseTab: Never geometry.hpp-1.0.0/.clang-tidy000066400000000000000000000020701337104576400161760ustar00rootroot00000000000000--- Checks: '*,-cert-err58-cpp' WarningsAsErrors: '*' HeaderFilterRegex: '\/include\/' AnalyzeTemporaryDtors: false CheckOptions: - key: google-readability-braces-around-statements.ShortStatementLines value: '1' - key: google-readability-function-size.StatementThreshold value: '800' - key: google-readability-namespace-comments.ShortNamespaceLines value: '10' - key: google-readability-namespace-comments.SpacesBeforeComments value: '2' - key: modernize-loop-convert.MaxCopySize value: '16' - key: modernize-loop-convert.MinConfidence value: reasonable - key: modernize-loop-convert.NamingStyle value: CamelCase - key: modernize-pass-by-value.IncludeStyle value: llvm - key: modernize-replace-auto-ptr.IncludeStyle value: llvm - key: modernize-use-nullptr.NullMacros value: 'NULL' ... geometry.hpp-1.0.0/.gitignore000066400000000000000000000000671337104576400161360ustar00rootroot00000000000000mason_packages cmake-build .toolchain .mason local.env geometry.hpp-1.0.0/.gitmodules000066400000000000000000000000001337104576400163060ustar00rootroot00000000000000geometry.hpp-1.0.0/.travis.yml000066400000000000000000000040601337104576400162540ustar00rootroot00000000000000language: generic matrix: include: # clang-tidy/format specific job - os: linux sudo: false env: CLANG_FORMAT CLANG_TIDY addons: apt: sources: [ 'ubuntu-toolchain-r-test' ] packages: [ 'libstdc++6', 'libstdc++-5-dev' ] script: - make tidy - make format - os: linux sudo: false env: CXX=g++-4.9 addons: apt: sources: [ 'ubuntu-toolchain-r-test' ] packages: [ 'g++-4.9' ] - os: linux sudo: false env: CXX=g++-5 addons: apt: sources: [ 'ubuntu-toolchain-r-test' ] packages: [ 'g++-5' ] - os: linux sudo: false env: CXX=clang++ addons: apt: sources: [ 'ubuntu-toolchain-r-test' ] packages: [ 'libstdc++6', 'libstdc++-5-dev' ] - os: linux sudo: required env: CXXFLAGS="-fsanitize=address,undefined,integer -fno-sanitize-recover=all" addons: apt: sources: [ 'ubuntu-toolchain-r-test' ] packages: [ 'libstdc++6', 'libstdc++-5-dev' ] # coverage build - os: linux sudo: false env: CXXFLAGS="--coverage" LDFLAGS="--coverage" addons: apt: sources: [ 'ubuntu-toolchain-r-test' ] packages: [ 'libstdc++6', 'libstdc++-5-dev' ] script: - make debug - make test # MASON_LLVM_RELEASE comes from the setup.sh script - mason install llvm-cov ${MASON_LLVM_RELEASE} - mason link llvm-cov ${MASON_LLVM_RELEASE} - curl -S -f https://codecov.io/bash -o codecov - chmod +x codecov - ./codecov -x "llvm-cov gcov" -Z env: global: - CMAKE_VERSION="3.8.2" install: # set up the environment by installing mason and clang++ - ./scripts/setup.sh --config local.env # put mason and clang++ on PATH - source local.env - mason install cmake ${CMAKE_VERSION} - mason link cmake ${CMAKE_VERSION} - which cmake script: - make release - make test - make clean - make debug - make test - make clean geometry.hpp-1.0.0/CMakeLists.txt000066400000000000000000000044041337104576400167050ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.8) project(hpp_skel LANGUAGES CXX) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED on) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/mason.cmake) option(WERROR "Add -Werror flag to build (turns warnings into errors)" ON) # configure optimization if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(OPTIMIZATION_FLAGS "-O0 -DDEBUG") message("-- Configuring debug build") else() set(OPTIMIZATION_FLAGS "-O3 -DNDEBUG") message("-- Configuring release build") endif() # Enable extra warnings to adhere to https://github.com/mapbox/cpp/issues/37 set(DESIRED_WARNINGS "-Wall -Wextra -Wconversion -Wunreachable-code -Wuninitialized -pedantic-errors -Wold-style-cast -Wno-error=unused-variable -Wshadow -Wfloat-equal -Weffc++") if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") set(DESIRED_WARNINGS "${DESIRED_WARNINGS} -Wmost") endif() # Note: -D_GLIBCXX_USE_CXX11_ABI=0 is needed to support mason packages that are precompiled libs # Currently we only depend on a header only library, but this will help avoid issues when more libs are added via mason set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPTIMIZATION_FLAGS} -D_GLIBCXX_USE_CXX11_ABI=0 ${DESIRED_WARNINGS}") if (WERROR) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") endif() # mason_use is a mason function within the mason.cmake file and provides ready-to-go vars, like "STATIC_LIBS" and "INCLUDE_DIRS" mason_use(catch VERSION 1.9.6 HEADER_ONLY) include_directories(SYSTEM ${MASON_PACKAGE_catch_INCLUDE_DIRS}) mason_use(benchmark VERSION 1.2.0) include_directories(SYSTEM ${MASON_PACKAGE_benchmark_INCLUDE_DIRS}) mason_use(variant VERSION 1.1.5 HEADER_ONLY) include_directories(SYSTEM ${MASON_PACKAGE_variant_INCLUDE_DIRS}) include_directories("${PROJECT_SOURCE_DIR}/include") file(GLOB TEST_SOURCES test/*.cpp) add_executable(unit-tests ${TEST_SOURCES}) # libbenchmark.a supports threads and therefore needs pthread support find_package(Threads REQUIRED) file(GLOB BENCH_SOURCES bench/*.cpp) add_executable(bench-tests ${BENCH_SOURCES}) # link benchmark static library to the bench-tests binary so the bench tests know where to find the benchmark impl code target_link_libraries(bench-tests ${MASON_PACKAGE_benchmark_STATIC_LIBS} ${CMAKE_THREAD_LIBS_INIT}) geometry.hpp-1.0.0/LICENSE000066400000000000000000000013241337104576400151500ustar00rootroot00000000000000Copyright (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.geometry.hpp-1.0.0/Makefile000066400000000000000000000020711337104576400156030ustar00rootroot00000000000000 # Whether to turn compiler warnings into errors export WERROR ?= true export BUILD_DIR ?= cmake-build default: release release: mkdir -p ./$(BUILD_DIR) && cd ./$(BUILD_DIR) && cmake ../ -DCMAKE_BUILD_TYPE=Release -DWERROR=$(WERROR) && VERBOSE=1 cmake --build . debug: mkdir -p ./$(BUILD_DIR) && cd ./$(BUILD_DIR) && cmake ../ -DCMAKE_BUILD_TYPE=Debug -DWERROR=$(WERROR) && VERBOSE=1 cmake --build . test: @if [ -f ./$(BUILD_DIR)/unit-tests ]; then ./$(BUILD_DIR)/unit-tests; else echo "Please run 'make release' or 'make debug' first" && exit 1; fi bench: @if [ -f ./$(BUILD_DIR)/bench-tests ]; then ./$(BUILD_DIR)/bench-tests; else echo "Please run 'make release' or 'make debug' first" && exit 1; fi tidy: ./scripts/clang-tidy.sh coverage: ./scripts/coverage.sh clean: rm -rf ./$(BUILD_DIR) rm -f *.profraw rm -f *.profdata @echo "run 'make distclean' to also clear mason_packages, .mason, and .toolchain directories" distclean: clean rm -rf mason_packages rm -rf .mason rm -rf .toolchain rm -f local.env format: ./scripts/format.sh .PHONY: test bench geometry.hpp-1.0.0/README.md000066400000000000000000000043231337104576400154240ustar00rootroot00000000000000# geometry.hpp [![badge](https://mapbox.s3.amazonaws.com/cpp-assets/hpp-skel-badge_blue.svg)](https://github.com/mapbox/hpp-skel) 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::feature::feature` (experimental) ### Design These types are designed to be easy to parse and serialize to [GeoJSON](http://geojson.org/). They should also be a robust and high performance container for data processing and conversion. ### Goals - Header-only - Fast compile - c++11/c++14 compatibility - No external dependencies for usage of core types (point, line_string, etc) - Minimal dependencies for usage of enclosing `geometry` type (`mapbox::variant`) - Easily [adaptable to `boost::geometry`](http://www.boost.org/doc/libs/1_56_0/libs/geometry/doc/html/geometry/examples/example__adapting_a_legacy_geometry_object_model.html) ### Usage Using a single type directly (requires no external dependencies): ```cpp #include #include using mapbox::geometry::point; int main() { point pt(1.0,0.0); std::clog << "x: " << pt.x << " y: " << pt.y << "\n"; } ``` Creating a geometry collection (depends on https://github.com/mapbox/variant): ```cpp #include #include #include using mapbox::geometry::geometry_collection; using mapbox::geometry::geometry; using mapbox::geometry::point; using point_type = point; struct printer { printer() {} void operator()(point_type const& pt) const { std::clog << "x: " << pt.x << " y: " << pt.y << "\n"; } template void operator()(T const& g) const { std::clog << "encountered non-point geometry\n"; } }; int main() { geometry_collection gc; gc.emplace_back(point_type(1.0,0.0)); geometry const& geom = gc.at(0); printer visitor; mapbox::util::apply_visitor(visitor,geom); } ``` geometry.hpp-1.0.0/bench/000077500000000000000000000000001337104576400152225ustar00rootroot00000000000000geometry.hpp-1.0.0/bench/geometry.cpp000066400000000000000000000013621337104576400175630ustar00rootroot00000000000000#include #include #include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wconversion" static void BM_polygon_allocation(benchmark::State& state) // NOLINT google-runtime-references { std::size_t s = state.range(0); std::default_random_engine generator; std::uniform_int_distribution distribution(-99, 99); auto dice = std::bind(distribution, generator); while (state.KeepRunning()) { mapbox::geometry::linear_ring r; r.reserve(s); r.emplace_back(dice(), dice()); } state.SetLabel(std::to_string((s * 16) / 1024) + "kb"); } BENCHMARK(BM_polygon_allocation)->Range(1024, 1 << 29); #pragma GCC diagnostic pop geometry.hpp-1.0.0/bench/main.cpp000066400000000000000000000002271337104576400166530ustar00rootroot00000000000000#include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" BENCHMARK_MAIN(); #pragma GCC diagnostic pop geometry.hpp-1.0.0/cmake/000077500000000000000000000000001337104576400152235ustar00rootroot00000000000000geometry.hpp-1.0.0/cmake/mason.cmake000066400000000000000000000242551337104576400173520ustar00rootroot00000000000000string(RANDOM LENGTH 16 MASON_INVOCATION) # 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() # Path to Mason executable if (NOT MASON_COMMAND) set(MASON_COMMAND "${CMAKE_SOURCE_DIR}/.mason/mason") endif() # Determine 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_S OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT MASON_PLATFORM) if (UNAME_S STREQUAL "Darwin") set(MASON_PLATFORM "macos") else() set(MASON_PLATFORM "linux") endif() endif() # Determine platform version string if(MASON_PLATFORM STREQUAL "ios") set(MASON_PLATFORM_VERSION "8.0") # Deployment target version elseif(MASON_PLATFORM STREQUAL "android") if (ANDROID_ABI STREQUAL "armeabi") set(MASON_PLATFORM_VERSION "arm-v5-9") elseif(ANDROID_ABI STREQUAL "arm64-v8a") set(MASON_PLATFORM_VERSION "arm-v8-21") elseif(ANDROID_ABI STREQUAL "x86") set(MASON_PLATFORM_VERSION "x86-9") elseif(ANDROID_ABI STREQUAL "x86_64") set(MASON_PLATFORM_VERSION "x86-64-21") elseif(ANDROID_ABI STREQUAL "mips") set(MASON_PLATFORM_VERSION "mips-9") elseif(ANDROID_ABI STREQUAL "mips64") set(MASON_PLATFORM_VERSION "mips64-21") else() set(MASON_PLATFORM_VERSION "arm-v7-9") endif() elseif(NOT MASON_PLATFORM_VERSION) execute_process( COMMAND uname -m OUTPUT_VARIABLE MASON_PLATFORM_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) endif() if(MASON_PLATFORM STREQUAL "macos") set(MASON_PLATFORM "osx") endif() set(ENV{MASON_PLATFORM} "${MASON_PLATFORM}") set(ENV{MASON_PLATFORM_VERSION} "${MASON_PLATFORM_VERSION}") include(CMakeParseArguments) 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(STATUS "[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(STATUS "[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() # Create a config file if it doesn't exist in the package # TODO: remove this once all packages have a mason.ini file if(NOT EXISTS "${_INSTALL_PATH}/mason.ini") # Change pkg-config files file(GLOB_RECURSE _PKGCONFIG_FILES "${_INSTALL_PATH}/*.pc") foreach(_PKGCONFIG_FILE IN ITEMS ${_PKGCONFIG_FILES}) file(READ "${_PKGCONFIG_FILE}" _PKGCONFIG_FILE_CONTENT) string(REGEX REPLACE "(^|\n)prefix=[^\n]*" "\\1prefix=${_INSTALL_PATH}" _PKGCONFIG_FILE_CONTENT "${_PKGCONFIG_FILE_CONTENT}") file(WRITE "${_PKGCONFIG_FILE}" "${_PKGCONFIG_FILE_CONTENT}") endforeach() if(NOT EXISTS "${MASON_COMMAND}") message(FATAL_ERROR "[Mason] Could not find Mason command at ${MASON_COMMAND}") endif() set(_FAILED) set(_ERROR) execute_process( COMMAND ${MASON_COMMAND} config ${_PACKAGE} ${_VERSION} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_FILE "${_INSTALL_PATH}/mason.ini" RESULT_VARIABLE _FAILED ERROR_VARIABLE _ERROR) if(_FAILED) message(FATAL_ERROR "[Mason] Could not get configuration for package ${_PACKAGE} ${_VERSION}: ${_ERROR}") endif() 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() geometry.hpp-1.0.0/codecov.yml000066400000000000000000000000361337104576400163070ustar00rootroot00000000000000ignore: - "bench" - "test"geometry.hpp-1.0.0/include/000077500000000000000000000000001337104576400155665ustar00rootroot00000000000000geometry.hpp-1.0.0/include/mapbox/000077500000000000000000000000001337104576400170545ustar00rootroot00000000000000geometry.hpp-1.0.0/include/mapbox/feature.hpp000066400000000000000000000070751337104576400212310ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include namespace mapbox { namespace feature { struct value; struct null_value_t { }; constexpr bool operator==(const null_value_t&, const null_value_t&) { return true; } constexpr bool operator!=(const null_value_t&, const null_value_t&) { return false; } constexpr bool operator<(const null_value_t&, const null_value_t&) { return false; } constexpr null_value_t null_value = null_value_t(); // Multiple numeric types (uint64_t, int64_t, double) are present in order to support // the widest possible range of JSON numbers, which do not have a maximum range. // Implementations that produce `value`s should use that order for type preference, // using uint64_t for positive integers, int64_t for negative integers, and double // for non-integers and integers outside the range of 64 bits. using value_base = mapbox::util::variant>, mapbox::util::recursive_wrapper>>; struct value : value_base { using value_base::value_base; }; using property_map = std::unordered_map; // The same considerations and requirement for numeric types apply as for `value_base`. using identifier = mapbox::util::variant; template struct feature { using coordinate_type = T; using geometry_type = mapbox::geometry::geometry; // Fully qualified to avoid GCC -fpermissive error. geometry_type geometry; property_map properties; identifier id; feature() : geometry(), properties(), id() {} feature(geometry_type const& geom_) : geometry(geom_), properties(), id() {} feature(geometry_type&& geom_) : geometry(std::move(geom_)), properties(), id() {} feature(geometry_type const& geom_, property_map const& prop_) : geometry(geom_), properties(prop_), id() {} feature(geometry_type&& geom_, property_map&& prop_) : geometry(std::move(geom_)), properties(std::move(prop_)), id() {} feature(geometry_type const& geom_, property_map const& prop_, identifier const& id_) : geometry(geom_), properties(prop_), id(id_) {} feature(geometry_type&& geom_, property_map&& prop_, identifier&& id_) : geometry(std::move(geom_)), properties(std::move(prop_)), id(std::move(id_)) {} }; template constexpr bool operator==(feature const& lhs, feature const& rhs) { return lhs.id == rhs.id && lhs.geometry == rhs.geometry && lhs.properties == rhs.properties; } template constexpr bool operator!=(feature const& lhs, feature const& rhs) { return !(lhs == rhs); } template class Cont = std::vector> struct feature_collection : Cont> { using coordinate_type = T; using feature_type = feature; using container_type = Cont; using size_type = typename container_type::size_type; template feature_collection(Args&&... args) : container_type(std::forward(args)...) { } feature_collection(std::initializer_list args) : container_type(std::move(args)) {} }; } // namespace feature } // namespace mapbox geometry.hpp-1.0.0/include/mapbox/geometry.hpp000066400000000000000000000006741337104576400214270ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include #include #include #include #include geometry.hpp-1.0.0/include/mapbox/geometry/000077500000000000000000000000001337104576400207075ustar00rootroot00000000000000geometry.hpp-1.0.0/include/mapbox/geometry/box.hpp000066400000000000000000000012671337104576400222160ustar00rootroot00000000000000#pragma once #include namespace mapbox { namespace geometry { template struct box { using coordinate_type = T; using point_type = point; constexpr box(point_type const& min_, point_type const& max_) : min(min_), max(max_) { } point_type min; point_type max; }; template constexpr bool operator==(box const& lhs, box const& rhs) { return lhs.min == rhs.min && lhs.max == rhs.max; } template constexpr bool operator!=(box const& lhs, box const& rhs) { return lhs.min != rhs.min || lhs.max != rhs.max; } } // namespace geometry } // namespace mapbox geometry.hpp-1.0.0/include/mapbox/geometry/empty.hpp000066400000000000000000000010741337104576400225600ustar00rootroot00000000000000#pragma once namespace mapbox { namespace geometry { struct empty { }; // this Geometry type represents the empty point set, ∅, for the coordinate space (OGC Simple Features). constexpr bool operator==(empty, empty) { return true; } constexpr bool operator!=(empty, empty) { return false; } constexpr bool operator<(empty, empty) { return false; } constexpr bool operator>(empty, empty) { return false; } constexpr bool operator<=(empty, empty) { return true; } constexpr bool operator>=(empty, empty) { return true; } } // namespace geometry } // namespace mapbox geometry.hpp-1.0.0/include/mapbox/geometry/envelope.hpp000066400000000000000000000015131337104576400232350ustar00rootroot00000000000000#pragma once #include #include #include namespace mapbox { namespace geometry { template box envelope(G const& geometry) { using limits = std::numeric_limits; T min_t = limits::has_infinity ? -limits::infinity() : limits::min(); T max_t = limits::has_infinity ? limits::infinity() : limits::max(); point min(max_t, max_t); point max(min_t, min_t); for_each_point(geometry, [&](point const& point) { if (min.x > point.x) min.x = point.x; if (min.y > point.y) min.y = point.y; if (max.x < point.x) max.x = point.x; if (max.y < point.y) max.y = point.y; }); return box(min, max); } } // namespace geometry } // namespace mapbox geometry.hpp-1.0.0/include/mapbox/geometry/for_each_point.hpp000066400000000000000000000022731337104576400244030ustar00rootroot00000000000000#pragma once #include namespace mapbox { namespace geometry { template void for_each_point(mapbox::geometry::empty const&, F&&) { } template auto for_each_point(Point&& point, F&& f) -> decltype(point.x, point.y, void()) { f(std::forward(point)); } template auto for_each_point(Container&& container, F&& f) -> decltype(container.begin(), container.end(), void()); template void for_each_point(mapbox::util::variant const& geom, F&& f) { mapbox::util::variant::visit(geom, [&](auto const& g) { for_each_point(g, f); }); } template void for_each_point(mapbox::util::variant& geom, F&& f) { mapbox::util::variant::visit(geom, [&](auto& g) { for_each_point(g, f); }); } template auto for_each_point(Container&& container, F&& f) -> decltype(container.begin(), container.end(), void()) { for (auto& e : container) { for_each_point(e, f); } } } // namespace geometry } // namespace mapbox geometry.hpp-1.0.0/include/mapbox/geometry/geometry.hpp000066400000000000000000000035001337104576400232510ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include #include #include // stl #include namespace mapbox { namespace geometry { template class Cont = std::vector> struct geometry_collection; template class Cont = std::vector> using geometry_base = mapbox::util::variant, line_string, polygon, multi_point, multi_line_string, multi_polygon, geometry_collection>; template class Cont = std::vector> struct geometry : geometry_base { using coordinate_type = T; using geometry_base::geometry_base; }; template class Cont> struct geometry_collection : Cont> { using coordinate_type = T; using geometry_type = geometry; using container_type = Cont; using size_type = typename container_type::size_type; template geometry_collection(Args&&... args) : container_type(std::forward(args)...) { } geometry_collection(std::initializer_list args) : container_type(std::move(args)) {} }; } // namespace geometry } // namespace mapbox geometry.hpp-1.0.0/include/mapbox/geometry/line_string.hpp000066400000000000000000000012431337104576400237350ustar00rootroot00000000000000#pragma once // mapbox #include // stl #include namespace mapbox { namespace geometry { template class Cont = std::vector> struct line_string : Cont> { using coordinate_type = T; using point_type = point; using container_type = Cont; using size_type = typename container_type::size_type; template line_string(Args&&... args) : container_type(std::forward(args)...) { } line_string(std::initializer_list args) : container_type(std::move(args)) {} }; } // namespace geometry } // namespace mapbox geometry.hpp-1.0.0/include/mapbox/geometry/multi_line_string.hpp000066400000000000000000000013311337104576400251450ustar00rootroot00000000000000#pragma once // mapbox #include // stl #include namespace mapbox { namespace geometry { template class Cont = std::vector> struct multi_line_string : Cont> { using coordinate_type = T; using line_string_type = line_string; using container_type = Cont; using size_type = typename container_type::size_type; template multi_line_string(Args&&... args) : container_type(std::forward(args)...) { } multi_line_string(std::initializer_list args) : container_type(std::move(args)) {} }; } // namespace geometry } // namespace mapbox geometry.hpp-1.0.0/include/mapbox/geometry/multi_point.hpp000066400000000000000000000012431337104576400237630ustar00rootroot00000000000000#pragma once // mapbox #include // stl #include namespace mapbox { namespace geometry { template class Cont = std::vector> struct multi_point : Cont> { using coordinate_type = T; using point_type = point; using container_type = Cont; using size_type = typename container_type::size_type; template multi_point(Args&&... args) : container_type(std::forward(args)...) { } multi_point(std::initializer_list args) : container_type(std::move(args)) {} }; } // namespace geometry } // namespace mapbox geometry.hpp-1.0.0/include/mapbox/geometry/multi_polygon.hpp000066400000000000000000000012651337104576400243250ustar00rootroot00000000000000#pragma once // mapbox #include // stl #include namespace mapbox { namespace geometry { template class Cont = std::vector> struct multi_polygon : Cont> { using coordinate_type = T; using polygon_type = polygon; using container_type = Cont; using size_type = typename container_type::size_type; template multi_polygon(Args&&... args) : container_type(std::forward(args)...) { } multi_polygon(std::initializer_list args) : container_type(std::move(args)) {} }; } // namespace geometry } // namespace mapbox geometry.hpp-1.0.0/include/mapbox/geometry/point.hpp000066400000000000000000000012461337104576400225540ustar00rootroot00000000000000#pragma once namespace mapbox { namespace geometry { template struct point { using coordinate_type = T; constexpr point() : x(), y() { } constexpr point(T x_, T y_) : x(x_), y(y_) { } T x; T y; }; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" template constexpr bool operator==(point const& lhs, point const& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; } #pragma GCC diagnostic pop template constexpr bool operator!=(point const& lhs, point const& rhs) { return !(lhs == rhs); } } // namespace geometry } // namespace mapbox geometry.hpp-1.0.0/include/mapbox/geometry/point_arithmetic.hpp000066400000000000000000000043051337104576400247640ustar00rootroot00000000000000#pragma once namespace mapbox { namespace geometry { template point operator+(point const& lhs, point const& rhs) { return point(lhs.x + rhs.x, lhs.y + rhs.y); } template point operator+(point const& lhs, T const& rhs) { return point(lhs.x + rhs, lhs.y + rhs); } template point operator-(point const& lhs, point const& rhs) { return point(lhs.x - rhs.x, lhs.y - rhs.y); } template point operator-(point const& lhs, T const& rhs) { return point(lhs.x - rhs, lhs.y - rhs); } template point operator*(point const& lhs, point const& rhs) { return point(lhs.x * rhs.x, lhs.y * rhs.y); } template point operator*(point const& lhs, T const& rhs) { return point(lhs.x * rhs, lhs.y * rhs); } template point operator/(point const& lhs, point const& rhs) { return point(lhs.x / rhs.x, lhs.y / rhs.y); } template point operator/(point const& lhs, T const& rhs) { return point(lhs.x / rhs, lhs.y / rhs); } template point& operator+=(point& lhs, point const& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; } template point& operator+=(point& lhs, T const& rhs) { lhs.x += rhs; lhs.y += rhs; return lhs; } template point& operator-=(point& lhs, point const& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; } template point& operator-=(point& lhs, T const& rhs) { lhs.x -= rhs; lhs.y -= rhs; return lhs; } template point& operator*=(point& lhs, point const& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; return lhs; } template point& operator*=(point& lhs, T const& rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; } template point& operator/=(point& lhs, point const& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; } template point& operator/=(point& lhs, T const& rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; } } // namespace geometry } // namespace mapbox geometry.hpp-1.0.0/include/mapbox/geometry/polygon.hpp000066400000000000000000000022531337104576400231110ustar00rootroot00000000000000#pragma once // mapbox #include // stl #include namespace mapbox { namespace geometry { template class Cont = std::vector> struct linear_ring : Cont> { using coordinate_type = T; using point_type = point; using container_type = Cont; using size_type = typename container_type::size_type; template linear_ring(Args&&... args) : container_type(std::forward(args)...) { } linear_ring(std::initializer_list args) : container_type(std::move(args)) {} }; template class Cont = std::vector> struct polygon : Cont> { using coordinate_type = T; using linear_ring_type = linear_ring; using container_type = Cont; using size_type = typename container_type::size_type; template polygon(Args&&... args) : container_type(std::forward(args)...) { } polygon(std::initializer_list args) : container_type(std::move(args)) {} }; } // namespace geometry } // namespace mapbox geometry.hpp-1.0.0/include/mapbox/geometry_io.hpp000066400000000000000000000044521337104576400221140ustar00rootroot00000000000000#pragma once #include #include #include #include namespace mapbox { namespace geometry { std::ostream& operator<<(std::ostream& os, const empty&) { return os << "[]"; } template std::ostream& operator<<(std::ostream& os, const point& point) { return os << "[" << point.x << "," << point.y << "]"; } template class C, class... Args> std::ostream& operator<<(std::ostream& os, const C& cont) { os << "["; for (auto it = cont.cbegin();;) { os << *it; if (++it == cont.cend()) { break; } os << ","; } return os << "]"; } template std::ostream& operator<<(std::ostream& os, const line_string& geom) { return os << static_cast::container_type>(geom); } template std::ostream& operator<<(std::ostream& os, const linear_ring& geom) { return os << static_cast::container_type>(geom); } template std::ostream& operator<<(std::ostream& os, const polygon& geom) { return os << static_cast::container_type>(geom); } template std::ostream& operator<<(std::ostream& os, const multi_point& geom) { return os << static_cast::container_type>(geom); } template std::ostream& operator<<(std::ostream& os, const multi_line_string& geom) { return os << static_cast::container_type>(geom); } template std::ostream& operator<<(std::ostream& os, const multi_polygon& geom) { return os << static_cast::container_type>(geom); } template std::ostream& operator<<(std::ostream& os, const geometry& geom) { geometry::visit(geom, [&](const auto& g) { os << g; }); return os; } template std::ostream& operator<<(std::ostream& os, const geometry_collection& geom) { return os << static_cast::container_type>(geom); } } // namespace geometry namespace feature { std::ostream& operator<<(std::ostream& os, const null_value_t&) { return os << "[]"; } } // namespace feature } // namespace mapbox geometry.hpp-1.0.0/scripts/000077500000000000000000000000001337104576400156325ustar00rootroot00000000000000geometry.hpp-1.0.0/scripts/clang-tidy.sh000077500000000000000000000022071337104576400202250ustar00rootroot00000000000000#!/usr/bin/env bash set -eu set -o pipefail # https://clang.llvm.org/extra/clang-tidy/ # to speed up re-runs, only re-create environment if needed if [[ ! -f local.env ]]; then # automatically setup environment ./scripts/setup.sh --config local.env fi # source the environment source local.env PATH_TO_CLANG_TIDY_SCRIPT="$(pwd)/mason_packages/.link/share/run-clang-tidy.py" # to speed up re-runs, only install clang-tidy if needed if [[ ! -f PATH_TO_CLANG_TIDY_SCRIPT ]]; then # The MASON_LLVM_RELEASE variable comes from `local.env` mason install clang-tidy ${MASON_LLVM_RELEASE} # We link the tools to make it easy to know ${PATH_TO_CLANG_TIDY_SCRIPT} mason link clang-tidy ${MASON_LLVM_RELEASE} fi # build the compile_commands.json file if it does not exist if [[ ! -f cmake-build/compile_commands.json ]]; then # the build automatically puts the compile commands in the ./build directory make fi # change into the build directory so that clang-tidy can find the files # at the right paths (since this is where the actual build happens) cd cmake-build ${PATH_TO_CLANG_TIDY_SCRIPT} -fix -checks=-hicpp-no-assembler geometry.hpp-1.0.0/scripts/coverage.sh000077500000000000000000000020161337104576400177630ustar00rootroot00000000000000#!/usr/bin/env bash set -eu set -o pipefail # http://clang.llvm.org/docs/UsersManual.html#profiling-with-instrumentation # https://www.bignerdranch.com/blog/weve-got-you-covered/ # automatically setup environment ./scripts/setup.sh --config local.env source local.env make clean export CXXFLAGS="-fprofile-instr-generate -fcoverage-mapping" export LDFLAGS="-fprofile-instr-generate" mason install llvm-cov ${MASON_LLVM_RELEASE} mason link llvm-cov ${MASON_LLVM_RELEASE} make debug rm -f *profraw rm -f *gcov rm -f *profdata LLVM_PROFILE_FILE="code-%p.profraw" make test CXX_MODULE="./cmake-build/unit-tests" llvm-profdata merge -output=code.profdata code-*.profraw llvm-cov report ${CXX_MODULE} -instr-profile=code.profdata -use-color llvm-cov show ${CXX_MODULE} -instr-profile=code.profdata src/*.cpp -filename-equivalence -use-color llvm-cov show ${CXX_MODULE} -instr-profile=code.profdata src/*.cpp -filename-equivalence -use-color --format html > /tmp/coverage.html echo "open /tmp/coverage.html for HTML version of this report" geometry.hpp-1.0.0/scripts/format.sh000077500000000000000000000015251337104576400174640ustar00rootroot00000000000000#!/usr/bin/env bash set -eu set -o pipefail : ' Runs clang-format on the code in include/ Return `1` if there are files to be formatted, and automatically formats them. Returns `0` if everything looks properly formatted. ' # Set up the environment by installing mason and clang++ ./scripts/setup.sh --config local.env source local.env # Add clang-format as a dep mason install clang-format ${MASON_LLVM_RELEASE} mason link clang-format ${MASON_LLVM_RELEASE} # Run clang-format on all cpp and hpp files in the /src directory find include/ bench/ test/ -type f -name '*.hpp' -or -name '*.cpp' \ | xargs -I{} clang-format -i -style=file {} # Print list of modified files dirty=$(git ls-files --modified include/ bench/ test/) if [[ $dirty ]]; then echo "The following files have been modified:" echo $dirty exit 1 else exit 0 figeometry.hpp-1.0.0/scripts/setup.sh000077500000000000000000000111701337104576400173310ustar00rootroot00000000000000#!/usr/bin/env bash set -eu set -o pipefail export MASON_RELEASE="${_MASON_RELEASE:-v0.18.0}" export MASON_LLVM_RELEASE="${_MASON_LLVM_RELEASE:-5.0.1}" PLATFORM=$(uname | tr A-Z a-z) if [[ ${PLATFORM} == 'darwin' ]]; then PLATFORM="osx" fi MASON_URL="https://s3.amazonaws.com/mason-binaries/${PLATFORM}-$(uname -m)" llvm_toolchain_dir="$(pwd)/.toolchain" function run() { local config=${1} # unbreak bash shell due to rvm bug on osx: https://github.com/direnv/direnv/issues/210#issuecomment-203383459 # this impacts any usage of scripts that are source'd (like this one) if [[ "${TRAVIS_OS_NAME:-}" == "osx" ]]; then echo 'shell_session_update() { :; }' > ~/.direnvrc fi # # COMPILER TOOLCHAIN # # We install clang++ without the mason client for a couple reasons: # 1) decoupling makes it viable to use a custom branch of mason that might # modify the upstream s3 bucket in a such a way that does not give # it access to build tools like clang++ # 2) Allows us to short-circuit and use a global clang++ install if it # is available to save space for local builds. GLOBAL_CLANG="${HOME}/.mason/mason_packages/${PLATFORM}-$(uname -m)/clang++/${MASON_LLVM_RELEASE}" GLOBAL_LLVM="${HOME}/.mason/mason_packages/${PLATFORM}-$(uname -m)/llvm/${MASON_LLVM_RELEASE}" if [[ -d ${GLOBAL_LLVM} ]]; then echo "Detected '${GLOBAL_LLVM}/bin/clang++', using it" local llvm_toolchain_dir=${GLOBAL_LLVM} elif [[ -d ${GLOBAL_CLANG} ]]; then echo "Detected '${GLOBAL_CLANG}/bin/clang++', using it" local llvm_toolchain_dir=${GLOBAL_CLANG} elif [[ -d ${GLOBAL_CLANG} ]]; then echo "Detected '${GLOBAL_CLANG}/bin/clang++', using it" local llvm_toolchain_dir=${GLOBAL_CLANG} elif [[ ! -d ${llvm_toolchain_dir} ]]; then BINARY="${MASON_URL}/clang++/${MASON_LLVM_RELEASE}.tar.gz" echo "Downloading ${BINARY}" mkdir -p ${llvm_toolchain_dir} curl -sSfL ${BINARY} | tar --gunzip --extract --strip-components=1 --directory=${llvm_toolchain_dir} fi # # MASON # function setup_mason() { local install_dir=${1} local mason_release=${2} mkdir -p ${install_dir} curl -sSfL https://github.com/mapbox/mason/archive/${mason_release}.tar.gz | tar --gunzip --extract --strip-components=1 --directory=${install_dir} } setup_mason $(pwd)/.mason ${MASON_RELEASE} # # ENV SETTINGS # echo "export PATH=${llvm_toolchain_dir}/bin:$(pwd)/.mason:$(pwd)/mason_packages/.link/bin:"'${PATH}' > ${config} echo "export CXX=${CXX:-${llvm_toolchain_dir}/bin/clang++}" >> ${config} echo "export MASON_RELEASE=${MASON_RELEASE}" >> ${config} echo "export MASON_LLVM_RELEASE=${MASON_LLVM_RELEASE}" >> ${config} # https://github.com/google/sanitizers/wiki/AddressSanitizerAsDso RT_BASE=${llvm_toolchain_dir}/lib/clang/${MASON_LLVM_RELEASE}/lib/$(uname | tr A-Z a-z)/libclang_rt if [[ $(uname -s) == 'Darwin' ]]; then RT_PRELOAD=${RT_BASE}.asan_osx_dynamic.dylib else RT_PRELOAD=${RT_BASE}.asan-x86_64.so fi echo "export MASON_LLVM_RT_PRELOAD=${RT_PRELOAD}" >> ${config} SUPPRESSION_FILE="/tmp/leak_suppressions.txt" # Add suppressions as needed #echo "leak:__strdup" > ${SUPPRESSION_FILE} echo "export ASAN_SYMBOLIZER_PATH=${llvm_toolchain_dir}/bin/llvm-symbolizer" >> ${config} echo "export MSAN_SYMBOLIZER_PATH=${llvm_toolchain_dir}/bin/llvm-symbolizer" >> ${config} echo "export UBSAN_OPTIONS=print_stacktrace=1" >> ${config} if [[ -f ${SUPPRESSION_FILE} ]]; then echo "export LSAN_OPTIONS=suppressions=${SUPPRESSION_FILE}" >> ${config} fi echo "export ASAN_OPTIONS=symbolize=1:abort_on_error=1:detect_container_overflow=1:check_initialization_order=1:detect_stack_use_after_return=1" >> ${config} echo 'export MASON_SANITIZE="-fsanitize=address,undefined -fno-sanitize=vptr,function"' >> ${config} echo 'export MASON_SANITIZE_CXXFLAGS="${MASON_SANITIZE} -fno-sanitize=vptr,function -fsanitize-address-use-after-scope -fno-omit-frame-pointer -fno-common"' >> ${config} echo 'export MASON_SANITIZE_LDFLAGS="${MASON_SANITIZE}"' >> ${config} exit 0 } function usage() { >&2 echo "Usage" >&2 echo "" >&2 echo "$ ./scripts/setup.sh --config local.env" >&2 echo "$ source local.env" >&2 echo "" exit 1 } if [[ ! ${1:-} ]]; then usage fi # https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash for i in "$@" do case $i in --config) if [[ ! ${2:-} ]]; then usage fi shift run $@ ;; -h | --help) usage shift ;; *) usage ;; esac done geometry.hpp-1.0.0/test/000077500000000000000000000000001337104576400151225ustar00rootroot00000000000000geometry.hpp-1.0.0/test/empty.cpp000066400000000000000000000004301337104576400167610ustar00rootroot00000000000000#include #include using mapbox::geometry::empty; TEST_CASE("test empty") { empty n1; empty n2; CHECK(n1 == n2); CHECK(!(n1 != n2)); CHECK(!(n1 < n2)); CHECK(!(n1 > n2)); CHECK(n1 <= n2); CHECK(n1 >= n2); } geometry.hpp-1.0.0/test/envelope.cpp000066400000000000000000000022331337104576400174430ustar00rootroot00000000000000#include #include using mapbox::geometry::box; using mapbox::geometry::envelope; using mapbox::geometry::geometry; using mapbox::geometry::geometry_collection; using mapbox::geometry::line_string; using mapbox::geometry::multi_line_string; using mapbox::geometry::multi_point; using mapbox::geometry::multi_polygon; using mapbox::geometry::point; using mapbox::geometry::polygon; TEST_CASE("test envelope") { CHECK(envelope(point(0, 0)) == box({0, 0}, {0, 0})); CHECK(envelope(line_string({{0, 1}, {2, 3}})) == box({0, 1}, {2, 3})); CHECK(envelope(polygon({{{0, 1}, {2, 3}}})) == box({0, 1}, {2, 3})); CHECK(envelope(multi_point({{0, 0}})) == box({0, 0}, {0, 0})); CHECK(envelope(multi_line_string({{{0, 1}, {2, 3}}})) == box({0, 1}, {2, 3})); CHECK(envelope(multi_polygon({{{{0, 1}, {2, 3}}}})) == box({0, 1}, {2, 3})); CHECK(envelope(geometry(point(0, 0))) == box({0, 0}, {0, 0})); CHECK(envelope(geometry_collection({point(0, 0)})) == box({0, 0}, {0, 0})); } geometry.hpp-1.0.0/test/feature.cpp000066400000000000000000000031161337104576400172620ustar00rootroot00000000000000#include #include using mapbox::geometry::point; using mapbox::feature::feature; using mapbox::feature::feature_collection; using mapbox::feature::null_value; using mapbox::feature::null_value_t; TEST_CASE("test feature") { feature pf{point()}; CHECK(pf.geometry.is>()); CHECK(pf.properties.empty()); 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; REQUIRE(p["bool"].is()); CHECK(p["bool"] == true); REQUIRE(p["string"].is()); CHECK(p["string"] == std::string("foo")); REQUIRE(p["double"].is()); CHECK(p["double"] == 2.5); REQUIRE(p["uint"].is()); CHECK(p["uint"] == uint64_t(10)); REQUIRE(p["int"].is()); CHECK(p["int"] == int64_t(-10)); REQUIRE(p["null"].is()); CHECK(p["null"] == null_value); p["null"] = null_value_t{}; REQUIRE(p["null"].is()); CHECK(p["null"] == null_value); CHECK(p == p); CHECK(!(p != p)); CHECK(pf == pf); CHECK(!(pf != pf)); CHECK(p.size() == 6); feature id1{point()}; id1.id = {uint64_t(1)}; feature id2{point()}; id1.id = {uint64_t(2)}; CHECK(id1 == id1); CHECK(id1 != id2); } TEST_CASE("test feature collection") { feature_collection fc1; CHECK(fc1.empty()); CHECK(fc1 == fc1); CHECK(!(fc1 != fc1)); } geometry.hpp-1.0.0/test/for_each_point.cpp000066400000000000000000000033361337104576400206120ustar00rootroot00000000000000#include #include #include using mapbox::geometry::for_each_point; using mapbox::geometry::geometry; using mapbox::geometry::line_string; using mapbox::geometry::point; using mapbox::geometry::polygon; struct point_counter { std::size_t count = 0; template void operator()(Point const& /*unused*/) { count++; } }; TEST_CASE("test for each point") { auto count_points = [](auto const& g0) { point_counter counter; for_each_point(g0, counter); return counter.count; }; CHECK(count_points(point()) == 1); CHECK(count_points(line_string({{0, 1}, {2, 3}})) == 2); CHECK(count_points(geometry(polygon({{{0, 1}, {2, 3}}}))) == 2); auto point_negator = [](point& p) { p *= static_cast(-1); }; point p(1, 2); for_each_point(p, point_negator); CHECK(p == point(-1, -2)); line_string ls({{0, 1}, {2, 3}}); for_each_point(ls, point_negator); CHECK(ls == line_string({{0, -1}, {-2, -3}})); geometry g(polygon({{{0, 1}, {2, 3}}})); for_each_point(g, point_negator); CHECK(g == geometry(polygon({{{0, -1}, {-2, -3}}}))); // Custom geometry type using my_geometry = mapbox::util::variant>; CHECK(count_points(my_geometry(point())) == 1); // Custom point type struct my_point { int16_t x; int16_t y; }; CHECK(count_points(std::vector({my_point{0, 1}})) == 1); CHECK(count_points(mapbox::util::variant(my_point{0, 1})) == 1); } geometry.hpp-1.0.0/test/geometry.cpp000066400000000000000000000063271337104576400174710ustar00rootroot00000000000000#include #include using mapbox::geometry::empty; using mapbox::geometry::geometry; using mapbox::geometry::geometry_collection; using mapbox::geometry::line_string; using mapbox::geometry::multi_line_string; using mapbox::geometry::multi_point; using mapbox::geometry::multi_polygon; using mapbox::geometry::point; using mapbox::geometry::polygon; TEST_CASE("test empty in geometry") { geometry g0; CHECK(g0.is()); empty n1; geometry g1(n1); CHECK(g1.is()); CHECK(g0 == g1); } TEST_CASE("test point in geometry") { point p1(1, 2); geometry g1(p1); CHECK(g1.is>()); geometry g2(p1); CHECK(g2.is>()); CHECK(g1 == g2); } TEST_CASE("test multi point in geometry") { multi_point mp1; mp1.emplace_back(1, 2); geometry g1(mp1); CHECK(g1.is>()); geometry g2(mp1); CHECK(g2.is>()); CHECK(g1 == g2); } TEST_CASE("test line string in geometry") { line_string ls1; ls1.emplace_back(1, 2); ls1.emplace_back(3, 4); geometry g1(ls1); CHECK(g1.is>()); geometry g2(ls1); CHECK(g2.is>()); CHECK(g1 == g2); } TEST_CASE("test multi line string in geometry") { multi_line_string mls1 = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}; geometry g1(mls1); CHECK(g1.is>()); geometry g2(mls1); CHECK(g2.is>()); CHECK(g1 == g2); } TEST_CASE("test polygon in geometry") { polygon poly1 = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}; geometry g1(poly1); CHECK(g1.is>()); geometry g2(poly1); CHECK(g2.is>()); CHECK(g1 == g2); } TEST_CASE("test multi polygon in geometry") { multi_polygon mp1 = {{{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}}; geometry g1(mp1); CHECK(g1.is>()); geometry g2(mp1); CHECK(g2.is>()); CHECK(g1 == g2); } TEST_CASE("test geometry") { geometry eg; // default constructed geometry is empty CHECK(eg.is()); geometry pg{point()}; CHECK(pg.is>()); geometry lsg{line_string()}; CHECK(lsg.is>()); geometry pgg{polygon()}; CHECK(pgg.is>()); geometry mpg{multi_point()}; CHECK(mpg.is>()); geometry mlsg{multi_line_string()}; CHECK(mlsg.is>()); geometry mpgg{multi_polygon()}; CHECK(mpgg.is>()); geometry gcg{geometry_collection()}; CHECK(gcg.is>()); CHECK(pg == pg); CHECK(!(pg != pg)); CHECK(pg != lsg); } TEST_CASE("test geometry collection") { geometry_collection gc1; CHECK(gc1.empty()); CHECK(gc1 == gc1); CHECK(!(gc1 != gc1)); } geometry.hpp-1.0.0/test/geometry_collection.cpp000066400000000000000000000003211337104576400216700ustar00rootroot00000000000000#include #include TEST_CASE("test geometry collection with out geometry compiles correctly") { mapbox::geometry::geometry_collection gc; CHECK(gc.empty()); } geometry.hpp-1.0.0/test/io.cpp000066400000000000000000000036201337104576400162360ustar00rootroot00000000000000#include #include #include TEST_CASE("operator<<") { mapbox::geometry::empty empty; mapbox::geometry::point point{10, 20}; mapbox::geometry::point point2{30, 40}; mapbox::geometry::line_string lineString{point, point2}; mapbox::geometry::polygon polygon{mapbox::geometry::linear_ring{point, point2}}; mapbox::geometry::multi_point multiPoint{point, point2}; mapbox::geometry::multi_line_string multiLineString{lineString, lineString}; mapbox::geometry::multi_polygon multiPolygon{polygon}; mapbox::geometry::geometry_collection collection{multiPolygon}; std::stringstream stream; stream << empty << std::endl; stream << point << std::endl; stream << lineString << std::endl; stream << polygon << std::endl; stream << multiPoint << std::endl; stream << multiLineString << std::endl; stream << multiPolygon << std::endl; stream << collection << std::endl; stream << mapbox::geometry::geometry{collection} << std::endl; std::string line; std::getline(stream, line); CHECK(line == std::string("[]")); std::getline(stream, line); CHECK(line == std::string("[10,20]")); std::getline(stream, line); CHECK(line == std::string("[[10,20],[30,40]]")); std::getline(stream, line); CHECK(line == std::string("[[[10,20],[30,40]]]")); std::getline(stream, line); CHECK(line == std::string("[[10,20],[30,40]]")); std::getline(stream, line); CHECK(line == std::string("[[[10,20],[30,40]],[[10,20],[30,40]]]")); std::getline(stream, line); CHECK(line == std::string("[[[[10,20],[30,40]]]]")); std::getline(stream, line); CHECK(line == std::string("[[[[[10,20],[30,40]]]]]")); std::getline(stream, line); CHECK(line == std::string("[[[[[10,20],[30,40]]]]]")); } geometry.hpp-1.0.0/test/line_string.cpp000066400000000000000000000017301337104576400201440ustar00rootroot00000000000000#include #include using mapbox::geometry::line_string; using mapbox::geometry::point; TEST_CASE("test line string - double") { line_string ls1; CHECK(ls1.empty()); point p1(1.5, 1.6); ls1.push_back(p1); CHECK(ls1.size() == 1); ls1.emplace_back(2.5, 2.6); CHECK(ls1.size() == 2); line_string ls2(std::size_t(10)); CHECK(ls2.size() == 10); CHECK(ls1 == ls1); CHECK(!(ls1 != ls1)); CHECK(ls1 != ls2); } TEST_CASE("test line string - int64_t") { line_string ls1; CHECK(ls1.empty()); point p1(1, 2); ls1.push_back(p1); CHECK(ls1.size() == 1); ls1.emplace_back(3, 4); CHECK(ls1.size() == 2); line_string ls2(std::size_t(10)); CHECK(ls2.size() == 10); CHECK(ls1 == ls1); CHECK(!(ls1 != ls1)); CHECK(ls1 != ls2); line_string ls3 = {{1, 2}, {3, 4}}; CHECK(ls1 == ls3); } geometry.hpp-1.0.0/test/main.cpp000066400000000000000000000000571337104576400165540ustar00rootroot00000000000000#define CATCH_CONFIG_MAIN #include geometry.hpp-1.0.0/test/multi_line_string.cpp000066400000000000000000000026551337104576400213650ustar00rootroot00000000000000#include #include using mapbox::geometry::line_string; using mapbox::geometry::multi_line_string; using mapbox::geometry::point; TEST_CASE("test multi line string - double") { multi_line_string mls1; CHECK(mls1.empty()); line_string ls1; point p1(1.5, 1.6); point p2(2.4, 1.9); ls1.push_back(p1); ls1.push_back(p2); mls1.push_back(ls1); CHECK(mls1.size() == 1); mls1.emplace_back(); CHECK(mls1.size() == 2); multi_line_string mls2(std::size_t(10)); CHECK(mls2.size() == 10); CHECK(mls1 == mls1); CHECK(!(mls1 != mls1)); CHECK(mls1 != mls2); } TEST_CASE("test multi line string - int64_t") { multi_line_string mls1; CHECK(mls1.empty()); line_string ls1; point p1(1, 2); point p2(3, 4); ls1.push_back(p1); ls1.push_back(p2); mls1.push_back(ls1); CHECK(mls1.size() == 1); mls1.emplace_back(); auto& ls2 = mls1.back(); ls2.emplace_back(10, 5); ls2.emplace_back(9, 8); ls2.emplace_back(-4, 5); CHECK(mls1.size() == 2); multi_line_string mls2(std::size_t(10)); CHECK(mls2.size() == 10); CHECK(mls1 == mls1); CHECK(!(mls1 != mls1)); CHECK(mls1 != mls2); multi_line_string mls3 = {{{1, 2}, {3, 4}}, {{10, 5}, {9, 8}, {-4, 5}}}; CHECK(mls1 == mls3); } geometry.hpp-1.0.0/test/multi_point.cpp000066400000000000000000000017301337104576400201720ustar00rootroot00000000000000#include #include using mapbox::geometry::multi_point; using mapbox::geometry::point; TEST_CASE("test multi point - double") { multi_point mp1; CHECK(mp1.empty()); point p1(1.5, 1.6); mp1.push_back(p1); CHECK(mp1.size() == 1); mp1.emplace_back(2.5, 2.6); CHECK(mp1.size() == 2); multi_point mp2(std::size_t(10)); CHECK(mp2.size() == 10); CHECK(mp1 == mp1); CHECK(!(mp1 != mp1)); CHECK(mp1 != mp2); } TEST_CASE("test multi point - int64_t") { multi_point mp1; CHECK(mp1.empty()); point p1(1, 2); mp1.push_back(p1); CHECK(mp1.size() == 1); mp1.emplace_back(3, 4); CHECK(mp1.size() == 2); multi_point mp2(std::size_t(10)); CHECK(mp2.size() == 10); CHECK(mp1 == mp1); CHECK(!(mp1 != mp1)); CHECK(mp1 != mp2); multi_point mp3 = {{1, 2}, {3, 4}}; CHECK(mp1 == mp3); } geometry.hpp-1.0.0/test/multi_polygon.cpp000066400000000000000000000020531337104576400205270ustar00rootroot00000000000000#include #include using mapbox::geometry::multi_polygon; using mapbox::geometry::polygon; TEST_CASE("test multi polygon - double") { polygon poly1 = {{{1.1, 2.2}, {3.3, 4.4}, {5.5, 6.6}}, {{7.7, 8.8}, {9.9, 10.0}, {11.1, 12.2}}}; multi_polygon mp1; CHECK(mp1.empty()); mp1.push_back(poly1); CHECK(mp1.size() == 1); multi_polygon mp2(std::size_t(10)); CHECK(mp2.size() == 10); CHECK(mp1 == mp1); CHECK(!(mp1 != mp1)); CHECK(mp1 != mp2); } TEST_CASE("test multi polygon - int64_t") { polygon poly1 = {{{1, 2}, {3, 4}, {5, 6}}, {{7, 8}, {9, 10}, {11, 12}}}; multi_polygon mp1; CHECK(mp1.empty()); mp1.push_back(poly1); CHECK(mp1.size() == 1); multi_polygon mp2(std::size_t(10)); CHECK(mp2.size() == 10); CHECK(mp1 == mp1); CHECK(!(mp1 != mp1)); CHECK(mp1 != mp2); multi_polygon mp3 = {{{{1, 2}, {3, 4}, {5, 6}}, {{7, 8}, {9, 10}, {11, 12}}}}; CHECK(mp1 == mp3); } geometry.hpp-1.0.0/test/point.cpp000066400000000000000000000037451337104576400167700ustar00rootroot00000000000000#include #include #include using mapbox::geometry::point; TEST_CASE("test point init - double") { point p1; CHECK(p1.x == Approx(0.0)); CHECK(p1.y == Approx(0.0)); point p2{1.5, 1.9}; CHECK(p2.x == Approx(1.5)); CHECK(p2.y == Approx(1.9)); point p3(2.4, 9.3); CHECK(p3.x == Approx(2.4)); CHECK(p3.y == Approx(9.3)); } TEST_CASE("test point init - int64_t") { point p1; CHECK(p1.x == 0); CHECK(p1.y == 0); point p2{2, 3}; CHECK(p2.x == 2); CHECK(p2.y == 3); point p3(-5, 9); CHECK(p3.x == -5); CHECK(p3.y == 9); point p4(-5, 9); CHECK(p3 == p4); } TEST_CASE("test point operators") { point p2(2, 3); point p3(4, 6); CHECK((p2 + p3) == point(6, 9)); CHECK((p2 + 1u) == point(3, 4)); CHECK((p3 - p2) == point(2, 3)); CHECK((p3 - 1u) == point(3, 5)); CHECK((p3 * p2) == point(8, 18)); CHECK((p2 * 2u) == point(4, 6)); CHECK((p3 / p2) == point(2, 2)); CHECK((p3 / 2u) == point(2, 3)); { point p(2, 3); CHECK((p += p3) == point(6, 9)); } { point p(2, 3); CHECK((p += 1u) == point(3, 4)); } { point p(4, 6); CHECK((p -= p2) == point(2, 3)); } { point p(4, 6); CHECK((p -= 1u) == point(3, 5)); } { point p(4, 6); CHECK((p *= p2) == point(8, 18)); } { point p(2, 3); CHECK((p *= 2u) == point(4, 6)); } { point p(4, 6); CHECK((p /= p2) == point(2, 2)); } { point p(4, 6); CHECK((p /= 2u) == point(2, 3)); } } geometry.hpp-1.0.0/test/polygon.cpp000066400000000000000000000025631337104576400173230ustar00rootroot00000000000000#include #include using mapbox::geometry::linear_ring; using mapbox::geometry::point; using mapbox::geometry::polygon; TEST_CASE("test polygon - double") { polygon poly1; CHECK(poly1.empty()); linear_ring lr1; point p1(1.5, 1.6); point p2(2.4, 1.9); lr1.push_back(p1); lr1.push_back(p2); poly1.push_back(lr1); CHECK(poly1.size() == 1); poly1.emplace_back(); CHECK(poly1.size() == 2); polygon poly2(std::size_t(10)); CHECK(poly2.size() == 10); CHECK(poly1 == poly1); CHECK(!(poly1 != poly1)); CHECK(poly1 != poly2); } TEST_CASE("test polygon - int64_t") { polygon poly1; CHECK(poly1.empty()); linear_ring lr1; point p1(1, 2); point p2(3, 4); lr1.push_back(p1); lr1.push_back(p2); poly1.push_back(lr1); CHECK(poly1.size() == 1); poly1.emplace_back(); auto& lr2 = poly1.back(); lr2.emplace_back(10, 5); lr2.emplace_back(9, 8); lr2.emplace_back(-4, 5); CHECK(poly1.size() == 2); polygon poly2(std::size_t(10)); CHECK(poly2.size() == 10); CHECK(poly1 == poly1); CHECK(!(poly1 != poly1)); CHECK(poly1 != poly2); polygon poly3 = {{{1, 2}, {3, 4}}, {{10, 5}, {9, 8}, {-4, 5}}}; CHECK(poly1 == poly3); }