[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