[mapbox-geometry] 01/02: Imported Upstream version 0.9.1
Bas Couwenberg
sebastic at debian.org
Sat Jun 10 20:46:11 UTC 2017
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch master
in repository mapbox-geometry.
commit 614bafb4c85ac71d2af13bda3f364f61143cccbe
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Fri Jun 9 09:25:40 2017 +0200
Imported Upstream version 0.9.1
---
.gitignore | 2 +
.gitmodules | 3 +
.travis.yml | 44 +++++
LICENSE | 13 ++
Makefile | 19 ++
README.md | 83 ++++++++
include/mapbox/geometry.hpp | 13 ++
include/mapbox/geometry/box.hpp | 34 ++++
include/mapbox/geometry/envelope.hpp | 33 ++++
include/mapbox/geometry/feature.hpp | 82 ++++++++
include/mapbox/geometry/for_each_point.hpp | 45 +++++
include/mapbox/geometry/geometry.hpp | 58 ++++++
include/mapbox/geometry/line_string.hpp | 21 +++
include/mapbox/geometry/multi_line_string.hpp | 21 +++
include/mapbox/geometry/multi_point.hpp | 21 +++
include/mapbox/geometry/multi_polygon.hpp | 21 +++
include/mapbox/geometry/point.hpp | 35 ++++
include/mapbox/geometry/point_arithmetic.hpp | 119 ++++++++++++
include/mapbox/geometry/polygon.hpp | 31 +++
tests/collection.cpp | 5 +
tests/test.cpp | 260 ++++++++++++++++++++++++++
21 files changed, 963 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..204298f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+mason_packages
+test
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..44fba9a
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule ".mason"]
+ path = .mason
+ url = https://github.com/mapbox/mason.git
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..537c0d8
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,44 @@
+language: generic
+sudo: false
+
+matrix:
+ include:
+ - os: linux
+ env: CXX=g++-5
+ addons:
+ apt:
+ sources: [ 'ubuntu-toolchain-r-test' ]
+ packages: [ 'g++-5' ]
+ - os: linux
+ env: CXX=g++-6
+ addons:
+ apt:
+ sources: [ 'ubuntu-toolchain-r-test' ]
+ packages: [ 'g++-6' ]
+ - os: linux
+ env: CXX=clang++-3.8
+ addons:
+ apt:
+ sources: [ 'ubuntu-toolchain-r-test' ]
+ packages: [ 'libstdc++-4.9-dev' ]
+ before_script:
+ - git submodule update --init
+ - .mason/mason install clang++ 3.8.1
+ - export PATH=$(.mason/mason prefix clang++ 3.8.1)/bin:$PATH
+ - os: linux
+ env: CXX=clang++-3.9
+ addons:
+ apt:
+ sources: [ 'ubuntu-toolchain-r-test' ]
+ packages: [ 'libstdc++-4.9-dev' ]
+ before_script:
+ - git submodule update --init
+ - .mason/mason install clang++ 3.9.1
+ - export PATH=$(.mason/mason prefix clang++ 3.9.1)/bin:$PATH
+ - os: osx
+ osx_image: xcode7.3
+
+cache: apt
+
+script:
+ - make test
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8f6a86b
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,13 @@
+Copyright (c) 2016, Mapbox
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..ec95379
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,19 @@
+CXXFLAGS += -I include -std=c++14 -DDEBUG -O0 -Wall -Wextra -Werror
+MASON ?= .mason/mason
+
+VARIANT = 1.1.4
+
+default: test
+
+$(MASON):
+ git submodule update --init
+
+mason_packages/headers/variant/$(VARIANT):
+ $(MASON) install variant $(VARIANT)
+
+test: tests/* include/mapbox/geometry/* mason_packages/headers/variant/$(VARIANT) Makefile
+ $(CXX) tests/*.cpp $(CXXFLAGS) `$(MASON) cflags variant $(VARIANT)` -o test
+ ./test
+
+clean:
+ rm -f test
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..972614a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,83 @@
+# geometry.hpp
+
+Provides header-only, generic C++ interfaces for geometry types, geometry collections, and features.
+
+ - `mapbox::geometry::point`
+ - `mapbox::geometry::multi_point`
+ - `mapbox::geometry::line_string`
+ - `mapbox::geometry::multi_line_string`
+ - `mapbox::geometry::polygon`
+ - `mapbox::geometry::multi_polygon`
+ - `mapbox::geometry::geometry_collection`
+ - `mapbox::geometry::feature` (experimental)
+
+### Design
+
+These types are designed to be easy to parse and serialize to [GeoJSON](http://geojson.org/).
+
+They should also be a robust and high performance container for data processing and conversion.
+
+
+### Goals
+
+ - Header-only
+ - Fast compile
+ - c++11/c++14 compatibility
+ - No external dependencies for usage of core types (point, line_string, etc)
+ - Minimal dependencies for usage of enclosing `geometry` type (`mapbox::variant`)
+ - Easily [adaptable to `boost::geometry`](http://www.boost.org/doc/libs/1_56_0/libs/geometry/doc/html/geometry/examples/example__adapting_a_legacy_geometry_object_model.html)
+
+
+### Usage
+
+Using a single type directly (requires no external dependencies):
+
+```cpp
+#include <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);
+}
+```
diff --git a/include/mapbox/geometry.hpp b/include/mapbox/geometry.hpp
new file mode 100644
index 0000000..e232453
--- /dev/null
+++ b/include/mapbox/geometry.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <mapbox/geometry/point.hpp>
+#include <mapbox/geometry/line_string.hpp>
+#include <mapbox/geometry/polygon.hpp>
+#include <mapbox/geometry/multi_point.hpp>
+#include <mapbox/geometry/multi_line_string.hpp>
+#include <mapbox/geometry/multi_polygon.hpp>
+#include <mapbox/geometry/geometry.hpp>
+#include <mapbox/geometry/feature.hpp>
+#include <mapbox/geometry/point_arithmetic.hpp>
+#include <mapbox/geometry/for_each_point.hpp>
+#include <mapbox/geometry/envelope.hpp>
diff --git a/include/mapbox/geometry/box.hpp b/include/mapbox/geometry/box.hpp
new file mode 100644
index 0000000..bf81b70
--- /dev/null
+++ b/include/mapbox/geometry/box.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <mapbox/geometry/point.hpp>
+
+namespace mapbox {
+namespace geometry {
+
+template <typename T>
+struct box
+{
+ using point_type = point<T>;
+
+ constexpr box(point_type const& min_, point_type const& max_)
+ : min(min_), max(max_)
+ {}
+
+ point_type min;
+ point_type max;
+};
+
+template <typename T>
+constexpr bool operator==(box<T> const& lhs, box<T> const& rhs)
+{
+ return lhs.min == rhs.min && lhs.max == rhs.max;
+}
+
+template <typename T>
+constexpr bool operator!=(box<T> const& lhs, box<T> const& rhs)
+{
+ return lhs.min != rhs.min || lhs.max != rhs.max;
+}
+
+} // namespace geometry
+} // namespace mapbox
diff --git a/include/mapbox/geometry/envelope.hpp b/include/mapbox/geometry/envelope.hpp
new file mode 100644
index 0000000..8603583
--- /dev/null
+++ b/include/mapbox/geometry/envelope.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <mapbox/geometry/box.hpp>
+#include <mapbox/geometry/for_each_point.hpp>
+
+#include <limits>
+
+namespace mapbox {
+namespace geometry {
+
+template <typename G, typename T = typename G::coordinate_type>
+box<T> envelope(G const& geometry)
+{
+ using limits = std::numeric_limits<T>;
+
+ T min_t = limits::has_infinity ? -limits::infinity() : limits::min();
+ T max_t = limits::has_infinity ? limits::infinity() : limits::max();
+
+ point<T> min(max_t, max_t);
+ point<T> max(min_t, min_t);
+
+ for_each_point(geometry, [&] (point<T> const& point) {
+ if (min.x > point.x) min.x = point.x;
+ if (min.y > point.y) min.y = point.y;
+ if (max.x < point.x) max.x = point.x;
+ if (max.y < point.y) max.y = point.y;
+ });
+
+ return box<T>(min, max);
+}
+
+} // namespace geometry
+} // namespace mapbox
diff --git a/include/mapbox/geometry/feature.hpp b/include/mapbox/geometry/feature.hpp
new file mode 100644
index 0000000..81ce65e
--- /dev/null
+++ b/include/mapbox/geometry/feature.hpp
@@ -0,0 +1,82 @@
+#pragma once
+
+#include <mapbox/geometry/geometry.hpp>
+
+#include <mapbox/variant.hpp>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+#include <unordered_map>
+#include <experimental/optional>
+
+namespace mapbox {
+namespace geometry {
+
+struct value;
+
+struct null_value_t
+{
+ constexpr null_value_t() {}
+ constexpr null_value_t(std::nullptr_t) {}
+};
+
+constexpr bool operator==(const null_value_t&, const null_value_t&) { return true; }
+constexpr bool operator!=(const null_value_t&, const null_value_t&) { return false; }
+constexpr bool operator<(const null_value_t&, const null_value_t&) { return false; }
+
+constexpr null_value_t null_value = null_value_t();
+
+// Multiple numeric types (uint64_t, int64_t, double) are present in order to support
+// the widest possible range of JSON numbers, which do not have a maximum range.
+// Implementations that produce `value`s should use that order for type preference,
+// using uint64_t for positive integers, int64_t for negative integers, and double
+// for non-integers and integers outside the range of 64 bits.
+using value_base = mapbox::util::variant<null_value_t, bool, uint64_t, int64_t, double, std::string,
+ mapbox::util::recursive_wrapper<std::vector<value>>,
+ mapbox::util::recursive_wrapper<std::unordered_map<std::string, value>>>;
+
+struct value : value_base
+{
+ using value_base::value_base;
+};
+
+using property_map = std::unordered_map<std::string, value>;
+
+// The same considerations and requirement for numeric types apply as for `value_base`.
+using identifier = mapbox::util::variant<uint64_t, int64_t, double, std::string>;
+
+template <class T>
+struct feature
+{
+ using coordinate_type = T;
+ using geometry_type = mapbox::geometry::geometry<T>; // Fully qualified to avoid GCC -fpermissive error.
+
+ geometry_type geometry;
+ property_map properties {};
+ std::experimental::optional<identifier> id {};
+};
+
+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
diff --git a/include/mapbox/geometry/for_each_point.hpp b/include/mapbox/geometry/for_each_point.hpp
new file mode 100644
index 0000000..44d6e77
--- /dev/null
+++ b/include/mapbox/geometry/for_each_point.hpp
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <mapbox/geometry/geometry.hpp>
+
+namespace mapbox {
+namespace geometry {
+
+template <typename Point, typename F>
+auto for_each_point(Point&& point, F&& f)
+ -> decltype(point.x, point.y, void())
+{
+ f(std::forward<Point>(point));
+}
+
+template <typename Container, typename F>
+auto for_each_point(Container&& container, F&& f)
+ -> decltype(container.begin(), container.end(), void());
+
+template <typename...Types, typename F>
+void for_each_point(mapbox::util::variant<Types...> const& geom, F&& f)
+{
+ mapbox::util::variant<Types...>::visit(geom, [&] (auto const& g) {
+ for_each_point(g, f);
+ });
+}
+
+template <typename...Types, typename F>
+void for_each_point(mapbox::util::variant<Types...> & geom, F&& f)
+{
+ mapbox::util::variant<Types...>::visit(geom, [&] (auto & g) {
+ for_each_point(g, f);
+ });
+}
+
+template <typename Container, typename F>
+auto for_each_point(Container&& container, F&& f)
+ -> decltype(container.begin(), container.end(), void())
+{
+ for (auto& e: container) {
+ for_each_point(e, f);
+ }
+}
+
+} // namespace geometry
+} // namespace mapbox
diff --git a/include/mapbox/geometry/geometry.hpp b/include/mapbox/geometry/geometry.hpp
new file mode 100644
index 0000000..a9d072b
--- /dev/null
+++ b/include/mapbox/geometry/geometry.hpp
@@ -0,0 +1,58 @@
+#pragma once
+
+#include <mapbox/geometry/point.hpp>
+#include <mapbox/geometry/line_string.hpp>
+#include <mapbox/geometry/polygon.hpp>
+#include <mapbox/geometry/multi_point.hpp>
+#include <mapbox/geometry/multi_line_string.hpp>
+#include <mapbox/geometry/multi_polygon.hpp>
+
+#include <mapbox/variant.hpp>
+
+// stl
+#include <vector>
+
+namespace mapbox {
+namespace geometry {
+
+template <typename T, template <typename...> class Cont = std::vector>
+struct geometry_collection;
+
+template <typename T>
+using geometry_base = mapbox::util::variant<point<T>,
+ line_string<T>,
+ polygon<T>,
+ multi_point<T>,
+ multi_line_string<T>,
+ multi_polygon<T>,
+ geometry_collection<T>>;
+
+template <typename T>
+struct geometry : geometry_base<T>
+{
+ using coordinate_type = T;
+ using geometry_base<T>::geometry_base;
+
+ /*
+ * The default constructor would create a point geometry with default-constructed coordinates;
+ * i.e. (0, 0). Since this is not particularly useful, and could hide bugs, it is disabled.
+ */
+ geometry() = delete;
+};
+
+template <typename T, template <typename...> class Cont>
+struct geometry_collection : Cont<geometry<T>>
+{
+ using coordinate_type = T;
+ using geometry_type = geometry<T>;
+ using container_type = Cont<geometry_type>;
+
+ geometry_collection() = default;
+ geometry_collection(geometry_collection const&) = default;
+ geometry_collection(geometry_collection &&) = default;
+ geometry_collection(std::initializer_list<geometry_type> && args)
+ : container_type(std::forward<std::initializer_list<geometry_type>>(args)) {};
+};
+
+} // namespace geometry
+} // namespace mapbox
diff --git a/include/mapbox/geometry/line_string.hpp b/include/mapbox/geometry/line_string.hpp
new file mode 100644
index 0000000..6d811ce
--- /dev/null
+++ b/include/mapbox/geometry/line_string.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+// mapbox
+#include <mapbox/geometry/point.hpp>
+// stl
+#include <vector>
+
+namespace mapbox {
+namespace geometry {
+
+template <typename T, template <typename...> class Cont = std::vector>
+struct line_string : Cont<point<T> >
+{
+ using coordinate_type = T;
+ using point_type = point<T>;
+ using container_type = Cont<point_type>;
+ using container_type::container_type;
+};
+
+} // namespace geometry
+} // namespace mapbox
diff --git a/include/mapbox/geometry/multi_line_string.hpp b/include/mapbox/geometry/multi_line_string.hpp
new file mode 100644
index 0000000..07a7a1d
--- /dev/null
+++ b/include/mapbox/geometry/multi_line_string.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+// mapbox
+#include <mapbox/geometry/line_string.hpp>
+// stl
+#include <vector>
+
+namespace mapbox {
+namespace geometry {
+
+template <typename T, template <typename...> class Cont = std::vector>
+struct multi_line_string : Cont<line_string<T>>
+{
+ using coordinate_type = T;
+ using line_string_type = line_string<T>;
+ using container_type = Cont<line_string_type>;
+ using container_type::container_type;
+};
+
+} // namespace geometry
+} // namespace mapbox
diff --git a/include/mapbox/geometry/multi_point.hpp b/include/mapbox/geometry/multi_point.hpp
new file mode 100644
index 0000000..a3c73cf
--- /dev/null
+++ b/include/mapbox/geometry/multi_point.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+// mapbox
+#include <mapbox/geometry/point.hpp>
+// stl
+#include <vector>
+
+namespace mapbox {
+namespace geometry {
+
+template <typename T, template <typename...> class Cont = std::vector>
+struct multi_point : Cont<point<T>>
+{
+ using coordinate_type = T;
+ using point_type = point<T>;
+ using container_type = Cont<point_type>;
+ using container_type::container_type;
+};
+
+} // namespace geometry
+} // namespace mapbox
diff --git a/include/mapbox/geometry/multi_polygon.hpp b/include/mapbox/geometry/multi_polygon.hpp
new file mode 100644
index 0000000..ad230a0
--- /dev/null
+++ b/include/mapbox/geometry/multi_polygon.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+// mapbox
+#include <mapbox/geometry/polygon.hpp>
+// stl
+#include <vector>
+
+namespace mapbox {
+namespace geometry {
+
+template <typename T, template <typename...> class Cont = std::vector>
+struct multi_polygon : Cont<polygon<T>>
+{
+ using coordinate_type = T;
+ using polygon_type = polygon<T>;
+ using container_type = Cont<polygon_type>;
+ using container_type::container_type;
+};
+
+} // namespace geometry
+} // namespace mapbox
diff --git a/include/mapbox/geometry/point.hpp b/include/mapbox/geometry/point.hpp
new file mode 100644
index 0000000..0cba499
--- /dev/null
+++ b/include/mapbox/geometry/point.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+namespace mapbox {
+namespace geometry {
+
+template <typename T>
+struct point
+{
+ using coordinate_type = T;
+
+ constexpr point()
+ : x(), y()
+ {}
+ constexpr point(T x_, T y_)
+ : x(x_), y(y_)
+ {}
+
+ T x;
+ T y;
+};
+
+template <typename T>
+constexpr bool operator==(point<T> const& lhs, point<T> const& rhs)
+{
+ return lhs.x == rhs.x && lhs.y == rhs.y;
+}
+
+template <typename T>
+constexpr bool operator!=(point<T> const& lhs, point<T> const& rhs)
+{
+ return !(lhs == rhs);
+}
+
+} // namespace geometry
+} // namespace mapbox
diff --git a/include/mapbox/geometry/point_arithmetic.hpp b/include/mapbox/geometry/point_arithmetic.hpp
new file mode 100644
index 0000000..3940e5b
--- /dev/null
+++ b/include/mapbox/geometry/point_arithmetic.hpp
@@ -0,0 +1,119 @@
+#pragma once
+
+namespace mapbox {
+namespace geometry {
+
+template <typename T>
+constexpr 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>
+constexpr point<T> operator+(point<T> const& lhs, T const& rhs)
+{
+ return point<T>(lhs.x + rhs, lhs.y + rhs);
+}
+
+template <typename T>
+constexpr 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>
+constexpr point<T> operator-(point<T> const& lhs, T const& rhs)
+{
+ return point<T>(lhs.x - rhs, lhs.y - rhs);
+}
+
+template <typename T>
+constexpr 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>
+constexpr point<T> operator*(point<T> const& lhs, T const& rhs)
+{
+ return point<T>(lhs.x * rhs, lhs.y * rhs);
+}
+
+template <typename T>
+constexpr 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>
+constexpr point<T> operator/(point<T> const& lhs, T const& rhs)
+{
+ return point<T>(lhs.x / rhs, lhs.y / rhs);
+}
+
+template <typename T>
+constexpr point<T>& operator+=(point<T>& lhs, point<T> const& rhs)
+{
+ lhs.x += rhs.x;
+ lhs.y += rhs.y;
+ return lhs;
+}
+
+template <typename T>
+constexpr point<T>& operator+=(point<T>& lhs, T const& rhs)
+{
+ lhs.x += rhs;
+ lhs.y += rhs;
+ return lhs;
+}
+
+template <typename T>
+constexpr point<T>& operator-=(point<T>& lhs, point<T> const& rhs)
+{
+ lhs.x -= rhs.x;
+ lhs.y -= rhs.y;
+ return lhs;
+}
+
+template <typename T>
+constexpr point<T>& operator-=(point<T>& lhs, T const& rhs)
+{
+ lhs.x -= rhs;
+ lhs.y -= rhs;
+ return lhs;
+}
+
+template <typename T>
+constexpr point<T>& operator*=(point<T>& lhs, point<T> const& rhs)
+{
+ lhs.x *= rhs.x;
+ lhs.y *= rhs.y;
+ return lhs;
+}
+
+template <typename T>
+constexpr point<T>& operator*=(point<T>& lhs, T const& rhs)
+{
+ lhs.x *= rhs;
+ lhs.y *= rhs;
+ return lhs;
+}
+
+template <typename T>
+constexpr point<T>& operator/=(point<T>& lhs, point<T> const& rhs)
+{
+ lhs.x /= rhs.x;
+ lhs.y /= rhs.y;
+ return lhs;
+}
+
+template <typename T>
+constexpr point<T>& operator/=(point<T>& lhs, T const& rhs)
+{
+ lhs.x /= rhs;
+ lhs.y /= rhs;
+ return lhs;
+}
+
+} // namespace geometry
+} // namespace mapbox
diff --git a/include/mapbox/geometry/polygon.hpp b/include/mapbox/geometry/polygon.hpp
new file mode 100644
index 0000000..99a66aa
--- /dev/null
+++ b/include/mapbox/geometry/polygon.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+// mapbox
+#include <mapbox/geometry/point.hpp>
+
+// stl
+#include <vector>
+
+namespace mapbox {
+namespace geometry {
+
+template <typename T, template <typename...> class Cont = std::vector>
+struct linear_ring : Cont<point<T>>
+{
+ using coordinate_type = T;
+ using point_type = point<T>;
+ using container_type = Cont<point_type>;
+ using container_type::container_type;
+};
+
+template <typename T, template <typename...> class Cont = std::vector>
+struct polygon : Cont<linear_ring<T>>
+{
+ using coordinate_type = T;
+ using linear_ring_type = linear_ring<T>;
+ using container_type = Cont<linear_ring_type>;
+ using container_type::container_type;
+};
+
+} // namespace geometry
+} // namespace mapbox
diff --git a/tests/collection.cpp b/tests/collection.cpp
new file mode 100644
index 0000000..a3105a4
--- /dev/null
+++ b/tests/collection.cpp
@@ -0,0 +1,5 @@
+#include <mapbox/geometry.hpp>
+
+void test() {
+ mapbox::geometry::geometry_collection<double> gc;
+}
diff --git a/tests/test.cpp b/tests/test.cpp
new file mode 100644
index 0000000..fcbde4f
--- /dev/null
+++ b/tests/test.cpp
@@ -0,0 +1,260 @@
+#include <mapbox/geometry.hpp>
+
+#include <cassert>
+
+using namespace mapbox::geometry;
+
+static void testPoint() {
+ point<double> p1;
+ assert(int(p1.x) == 0);
+ assert(int(p1.y) == 0);
+
+ point<uint32_t> p2(2, 3);
+ point<uint32_t> p3(4, 6);
+
+ assert((p2 + p3) == point<uint32_t>(6, 9));
+ assert((p2 + 1u) == point<uint32_t>(3, 4));
+ assert((p3 - p2) == point<uint32_t>(2, 3));
+ assert((p3 - 1u) == point<uint32_t>(3, 5));
+ assert((p3 * p2) == point<uint32_t>(8, 18));
+ assert((p2 * 2u) == point<uint32_t>(4, 6));
+ assert((p3 / p2) == point<uint32_t>(2, 2));
+ assert((p3 / 2u) == point<uint32_t>(2, 3));
+
+ { point<uint32_t> p(2, 3); assert((p += p3) == point<uint32_t>(6, 9)); }
+ { point<uint32_t> p(2, 3); assert((p += 1u) == point<uint32_t>(3, 4)); }
+ { point<uint32_t> p(4, 6); assert((p -= p2) == point<uint32_t>(2, 3)); }
+ { point<uint32_t> p(4, 6); assert((p -= 1u) == point<uint32_t>(3, 5)); }
+ { point<uint32_t> p(4, 6); assert((p *= p2) == point<uint32_t>(8, 18)); }
+ { point<uint32_t> p(2, 3); assert((p *= 2u) == point<uint32_t>(4, 6)); }
+ { point<uint32_t> p(4, 6); assert((p /= p2) == point<uint32_t>(2, 2)); }
+ { point<uint32_t> p(4, 6); assert((p /= 2u) == point<uint32_t>(2, 3)); }
+}
+
+static void testMultiPoint() {
+ multi_point<double> mp1;
+ assert(mp1.size() == 0);
+
+ multi_point<double> mp2(10);
+ assert(mp2.size() == 10);
+
+ assert(mp1 == mp1);
+ assert(!(mp1 != mp1));
+ assert(mp1 != mp2);
+}
+
+static void testLineString() {
+ line_string<double> ls1;
+ assert(ls1.size() == 0);
+
+ line_string<double> ls2(10);
+ assert(ls2.size() == 10);
+
+ assert(ls1 == ls1);
+ assert(!(ls1 != ls1));
+ assert(ls1 != ls2);
+}
+
+static void testMultiLineString() {
+ multi_line_string<double> mls1;
+ assert(mls1.size() == 0);
+
+ multi_line_string<double> mls2(10);
+ assert(mls2.size() == 10);
+
+ assert(mls1 == mls1);
+ assert(!(mls1 != mls1));
+ assert(mls1 != mls2);
+}
+
+static void testPolygon() {
+ polygon<double> pg1;
+ assert(pg1.size() == 0);
+
+ polygon<double> pg2({{{0, 1}}});
+ assert(pg2.size() == 1);
+ assert(pg2[0].size() == 1);
+ assert(pg2[0][0] == point<double>(0, 1));
+
+ assert(pg1 == pg1);
+ assert(!(pg1 != pg1));
+ assert(pg1 != pg2);
+}
+
+static void testMultiPolygon() {
+ multi_polygon<double> mpg1;
+ assert(mpg1.size() == 0);
+
+ multi_polygon<double> mpg2(10);
+ assert(mpg2.size() == 10);
+
+ assert(mpg1 == mpg1);
+ assert(!(mpg1 != mpg1));
+ assert(mpg1 != mpg2);
+}
+
+static void testGeometry() {
+ geometry<double> pg { point<double>() };
+ assert(pg.is<point<double>>());
+
+ geometry<double> lsg { line_string<double>() };
+ assert(lsg.is<line_string<double>>());
+
+ geometry<double> pgg { polygon<double>() };
+ assert(pgg.is<polygon<double>>());
+
+ geometry<double> mpg { multi_point<double>() };
+ assert(mpg.is<multi_point<double>>());
+
+ geometry<double> mlsg { multi_line_string<double>() };
+ assert(mlsg.is<multi_line_string<double>>());
+
+ geometry<double> mpgg { multi_polygon<double>() };
+ assert(mpgg.is<multi_polygon<double>>());
+
+ geometry<double> gcg { geometry_collection<double>() };
+ assert(gcg.is<geometry_collection<double>>());
+
+ assert(pg == pg);
+ assert(!(pg != pg));
+ assert(pg != lsg);
+}
+
+static void testGeometryCollection() {
+ geometry_collection<double> gc1;
+ assert(gc1.size() == 0);
+
+ assert(gc1 == gc1);
+ assert(!(gc1 != gc1));
+}
+
+static void testFeature() {
+ feature<double> pf { point<double>() };
+ assert(pf.geometry.is<point<double>>());
+ assert(pf.properties.size() == 0);
+
+ auto &p = pf.properties;
+
+ p["bool"] = true;
+ p["string"] = std::string("foo");
+ p["double"] = 2.5;
+ p["uint"] = uint64_t(10);
+ p["int"] = int64_t(-10);
+ p["null"] = null_value;
+
+ assert(p["bool"].is<bool>());
+ assert(p["bool"] == true);
+ assert(p["string"].is<std::string>());
+ assert(p["string"] == std::string("foo"));
+ assert(p["double"].is<double>());
+ assert(p["double"] == 2.5);
+ assert(p["uint"].is<uint64_t>());
+ assert(p["uint"] == uint64_t(10));
+ assert(p["int"].is<int64_t>());
+ assert(p["int"] == int64_t(-10));
+ assert(p["null"].is<null_value_t>());
+ assert(p["null"] == null_value);
+
+ p["null"] = null_value_t{};
+ assert(p["null"].is<null_value_t>());
+ assert(p["null"] == null_value);
+
+ assert(p == p);
+ assert(!(p != p));
+
+ assert(pf == pf);
+ assert(!(pf != pf));
+
+ assert(p.size() == 6);
+
+ feature<double> id1 { point<double>() };
+ id1.id = { uint64_t(1) };
+
+ feature<double> id2 { point<double>() };
+ id1.id = { uint64_t(2) };
+
+ assert(id1 == id1);
+ assert(id1 != id2);
+}
+
+static void testFeatureCollection() {
+ feature_collection<double> fc1;
+ assert(fc1.size() == 0);
+
+ assert(fc1 == fc1);
+ assert(!(fc1 != fc1));
+}
+
+struct point_counter {
+ std::size_t count = 0;
+ template <class Point>
+ void operator()(Point const&) { count++; };
+};
+
+static void testForEachPoint() {
+ auto count_points = [] (auto const& g) {
+ point_counter counter;
+ for_each_point(g, counter);
+ return counter.count;
+ };
+
+ assert(count_points(point<double>()) == 1);
+ assert(count_points(line_string<double>({{0, 1}, {2, 3}})) == 2);
+ assert(count_points(geometry<double>(polygon<double>({{{0, 1}, {2, 3}}}))) == 2);
+
+ auto point_negator = [] (point<double>& p) { p *= -1.0; };
+
+ point<double> p(1, 2);
+ for_each_point(p, point_negator);
+ assert(p == point<double>(-1, -2));
+
+ line_string<double> ls({{0, 1}, {2, 3}});
+ for_each_point(ls, point_negator);
+ assert(ls == line_string<double>({{0, -1}, {-2, -3}}));
+
+ geometry<double> g(polygon<double>({{{0, 1}, {2, 3}}}));
+ for_each_point(g, point_negator);
+ assert(g == geometry<double>(polygon<double>({{{0, -1}, {-2, -3}}})));
+
+ // Custom geometry type
+ using my_geometry = mapbox::util::variant<point<double>>;
+ assert(count_points(my_geometry(point<double>())) == 1);
+
+ // Custom point type
+ struct my_point {
+ int16_t x;
+ int16_t y;
+ };
+ assert(count_points(std::vector<my_point>({my_point{0, 1}})) == 1);
+ assert(count_points(mapbox::util::variant<my_point>(my_point{0, 1})) == 1);
+}
+
+static void testEnvelope() {
+ assert(envelope(point<double>(0, 0)) == box<double>({0, 0}, {0, 0}));
+ assert(envelope(line_string<double>({{0, 1}, {2, 3}})) == box<double>({0, 1}, {2, 3}));
+ assert(envelope(polygon<double>({{{0, 1}, {2, 3}}})) == box<double>({0, 1}, {2, 3}));
+
+ assert(envelope(multi_point<double>({{0, 0}})) == box<double>({0, 0}, {0, 0}));
+ assert(envelope(multi_line_string<double>({{{0, 1}, {2, 3}}})) == box<double>({0, 1}, {2, 3}));
+ assert(envelope(multi_polygon<double>({{{{0, 1}, {2, 3}}}})) == box<double>({0, 1}, {2, 3}));
+
+ assert(envelope(geometry<int>(point<int>(0, 0))) == box<int>({0, 0}, {0, 0}));
+ assert(envelope(geometry_collection<int>({point<int>(0, 0)})) == box<int>({0, 0}, {0, 0}));
+}
+
+int main() {
+ testPoint();
+ testMultiPoint();
+ testLineString();
+ testMultiLineString();
+ testPolygon();
+ testMultiPolygon();
+ testGeometry();
+ testGeometryCollection();
+ testFeature();
+ testFeatureCollection();
+
+ testForEachPoint();
+ testEnvelope();
+ return 0;
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/mapbox-geometry.git
More information about the Pkg-grass-devel
mailing list