Bump geometry.hpp dependency from 0.9.2 to 1.0.0

This commit is contained in:
Dennis Luxen 2019-11-14 11:34:37 +01:00
parent 0b139ff05d
commit 24eee8f4e8
30 changed files with 420 additions and 437 deletions

View File

@ -16,6 +16,7 @@
- CHANGED: default car height was reduced to 2 meters. [#5389](https://github.com/Project-OSRM/osrm-backend/pull/5389)
- Misc:
- CHANGED: Reduce memory usage for raster source handling. [#5572](https://github.com/Project-OSRM/osrm-backend/pull/5572)
- CHANGED: Bump geometry.hpp dependency to v1.0.0
# 5.21.0
- Changes from 5.20.0

View File

@ -425,7 +425,7 @@ 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")
set(MBXGEOM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/geometry.hpp-1.0.0/include")
include_directories(SYSTEM ${MBXGEOM_INCLUDE_DIR})
set(CHEAPRULER_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/cheap-ruler-cpp-2.5.4/include")
include_directories(SYSTEM ${CHEAPRULER_INCLUDE_DIR})
@ -883,4 +883,4 @@ if (ENABLE_NODE_BINDINGS)
endforeach()
add_library(check-headers STATIC EXCLUDE_FROM_ALL ${sources})
set_target_properties(check-headers PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${check_headers_dir})
endif()
endif()

View File

@ -1,2 +0,0 @@
mason_packages
test

View File

@ -1,3 +0,0 @@
[submodule ".mason"]
path = .mason
url = https://github.com/mapbox/mason.git

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,5 +0,0 @@
#include <mapbox/geometry.hpp>
void test() {
mapbox::geometry::geometry_collection<double> gc;
}

View File

@ -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;
}

View File

@ -0,0 +1,5 @@
mason_packages
cmake-build
.toolchain
.mason
local.env

View File

View File

@ -0,0 +1,81 @@
language: 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

41
third_party/geometry.hpp-1.0.0/Makefile vendored Normal file
View File

@ -0,0 +1,41 @@
# 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

View File

@ -1,5 +1,7 @@
# 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`
@ -9,7 +11,7 @@ Provides header-only, generic C++ interfaces for geometry types, geometry collec
- `mapbox::geometry::polygon`
- `mapbox::geometry::multi_polygon`
- `mapbox::geometry::geometry_collection`
- `mapbox::geometry::feature` (experimental)
- `mapbox::feature::feature` (experimental)
### Design

View File

@ -1,6 +1,6 @@
#pragma once
#include <mapbox/geometry/geometry.hpp>
#include <mapbox/geometry.hpp>
#include <mapbox/variant.hpp>
@ -8,17 +8,14 @@
#include <string>
#include <vector>
#include <unordered_map>
#include <mapbox/optional.hpp>
namespace mapbox {
namespace geometry {
namespace feature {
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; }
@ -44,7 +41,7 @@ struct value : 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>;
using identifier = mapbox::util::variant<null_value_t, uint64_t, int64_t, double, std::string>;
template <class T>
struct feature
@ -53,16 +50,34 @@ struct feature
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 {};
property_map properties;
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_)),
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_)) {}
};
@ -84,8 +99,15 @@ 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;
using size_type = typename container_type::size_type;
template <class... Args>
feature_collection(Args&&... args) : container_type(std::forward<Args>(args)...)
{
}
feature_collection(std::initializer_list<feature_type> args)
: container_type(std::move(args)) {}
};
} // namespace geometry
} // namespace feature
} // namespace mapbox

View File

@ -7,7 +7,6 @@
#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>

View File

@ -8,11 +8,13 @@ namespace geometry {
template <typename T>
struct box
{
using point_type = point<T>;
using coordinate_type = T;
using point_type = point<coordinate_type>;
constexpr box(point_type const& min_, point_type const& max_)
: min(min_), max(max_)
{}
{
}
point_type min;
point_type max;

View File

@ -0,0 +1,18 @@
#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

View File

@ -14,12 +14,12 @@ 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();
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) {
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;

View File

@ -5,6 +5,11 @@
namespace mapbox {
namespace geometry {
template <typename F>
void for_each_point(mapbox::geometry::empty const&, F&&)
{
}
template <typename Point, typename F>
auto for_each_point(Point&& point, F&& f)
-> decltype(point.x, point.y, void())
@ -16,18 +21,18 @@ template <typename Container, typename F>
auto for_each_point(Container&& container, F&& f)
-> decltype(container.begin(), container.end(), void());
template <typename...Types, typename F>
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) {
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)
template <typename... Types, typename F>
void for_each_point(mapbox::util::variant<Types...>& geom, F&& f)
{
mapbox::util::variant<Types...>::visit(geom, [&] (auto & g) {
mapbox::util::variant<Types...>::visit(geom, [&](auto& g) {
for_each_point(g, f);
});
}
@ -36,7 +41,8 @@ template <typename Container, typename F>
auto for_each_point(Container&& container, F&& f)
-> decltype(container.begin(), container.end(), void())
{
for (auto& e: container) {
for (auto& e : container)
{
for_each_point(e, f);
}
}

View File

@ -0,0 +1,56 @@
#pragma once
#include <mapbox/geometry/empty.hpp>
#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, template <typename...> class Cont = std::vector>
using geometry_base = mapbox::util::variant<empty,
point<T>,
line_string<T, Cont>,
polygon<T, Cont>,
multi_point<T, Cont>,
multi_line_string<T, Cont>,
multi_polygon<T, Cont>,
geometry_collection<T, Cont>>;
template <typename T, template <typename...> class Cont = std::vector>
struct geometry : geometry_base<T, Cont>
{
using coordinate_type = T;
using geometry_base<T>::geometry_base;
};
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>;
using size_type = typename container_type::size_type;
template <class... Args>
geometry_collection(Args&&... args) : container_type(std::forward<Args>(args)...)
{
}
geometry_collection(std::initializer_list<geometry_type> args)
: container_type(std::move(args)) {}
};
} // namespace geometry
} // namespace mapbox

View File

@ -9,12 +9,19 @@ namespace mapbox {
namespace geometry {
template <typename T, template <typename...> class Cont = std::vector>
struct line_string : Cont<point<T> >
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;
using size_type = typename container_type::size_type;
template <class... Args>
line_string(Args&&... args) : container_type(std::forward<Args>(args)...)
{
}
line_string(std::initializer_list<point_type> args)
: container_type(std::move(args)) {}
};
} // namespace geometry

View File

@ -14,7 +14,14 @@ 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;
using size_type = typename container_type::size_type;
template <class... Args>
multi_line_string(Args&&... args) : container_type(std::forward<Args>(args)...)
{
}
multi_line_string(std::initializer_list<line_string_type> args)
: container_type(std::move(args)) {}
};
} // namespace geometry

View File

@ -14,7 +14,14 @@ 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;
using size_type = typename container_type::size_type;
template <class... Args>
multi_point(Args&&... args) : container_type(std::forward<Args>(args)...)
{
}
multi_point(std::initializer_list<point_type> args)
: container_type(std::move(args)) {}
};
} // namespace geometry

View File

@ -14,7 +14,14 @@ 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;
using size_type = typename container_type::size_type;
template <class... Args>
multi_polygon(Args&&... args) : container_type(std::forward<Args>(args)...)
{
}
multi_polygon(std::initializer_list<polygon_type> args)
: container_type(std::move(args)) {}
};
} // namespace geometry

View File

@ -10,21 +10,28 @@ struct point
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 <typename T>
constexpr bool operator==(point<T> const& lhs, point<T> const& rhs)
{
return lhs.x == rhs.x && lhs.y == rhs.y;
}
#pragma GCC diagnostic pop
template <typename T>
constexpr bool operator!=(point<T> const& lhs, point<T> const& rhs)
{

View File

@ -15,7 +15,14 @@ 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;
using size_type = typename container_type::size_type;
template <class... Args>
linear_ring(Args&&... args) : container_type(std::forward<Args>(args)...)
{
}
linear_ring(std::initializer_list<point_type> args)
: container_type(std::move(args)) {}
};
template <typename T, template <typename...> class Cont = std::vector>
@ -24,7 +31,14 @@ 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;
using size_type = typename container_type::size_type;
template <class... Args>
polygon(Args&&... args) : container_type(std::forward<Args>(args)...)
{
}
polygon(std::initializer_list<linear_ring_type> args)
: container_type(std::move(args)) {}
};
} // namespace geometry

View File

@ -0,0 +1,98 @@
#pragma once
#include <mapbox/geometry/empty.hpp>
#include <mapbox/feature.hpp>
#include <iostream>
#include <string>
namespace mapbox {
namespace geometry {
std::ostream& operator<<(std::ostream& os, const empty&)
{
return os << "[]";
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const point<T>& point)
{
return os << "[" << point.x << "," << point.y << "]";
}
template <typename T, template <class, class...> class C, class... Args>
std::ostream& operator<<(std::ostream& os, const C<T, Args...>& cont)
{
os << "[";
for (auto it = cont.cbegin();;)
{
os << *it;
if (++it == cont.cend())
{
break;
}
os << ",";
}
return os << "]";
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const line_string<T>& geom)
{
return os << static_cast<typename line_string<T>::container_type>(geom);
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const linear_ring<T>& geom)
{
return os << static_cast<typename linear_ring<T>::container_type>(geom);
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const polygon<T>& geom)
{
return os << static_cast<typename polygon<T>::container_type>(geom);
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const multi_point<T>& geom)
{
return os << static_cast<typename multi_point<T>::container_type>(geom);
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const multi_line_string<T>& geom)
{
return os << static_cast<typename multi_line_string<T>::container_type>(geom);
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const multi_polygon<T>& geom)
{
return os << static_cast<typename multi_polygon<T>::container_type>(geom);
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const geometry<T>& geom)
{
geometry<T>::visit(geom, [&](const auto& g) { os << g; });
return os;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const geometry_collection<T>& geom)
{
return os << static_cast<typename geometry_collection<T>::container_type>(geom);
}
} // namespace geometry
namespace feature {
std::ostream& operator<<(std::ostream& os, const null_value_t&)
{
return os << "[]";
}
} // namespace feature
} // namespace mapbox