pax_global_header00006660000000000000000000000064131274453060014517gustar00rootroot0000000000000052 comment=b0e41cc5635ff8d50e7e1edb73cadf1d2a7ddc83 geometry.hpp-0.9.2/000077500000000000000000000000001312744530600141505ustar00rootroot00000000000000geometry.hpp-0.9.2/.gitignore000066400000000000000000000000241312744530600161340ustar00rootroot00000000000000mason_packages test geometry.hpp-0.9.2/.gitmodules000066400000000000000000000001171312744530600163240ustar00rootroot00000000000000[submodule ".mason"] path = .mason url = https://github.com/mapbox/mason.git geometry.hpp-0.9.2/.mason/000077500000000000000000000000001312744530600153435ustar00rootroot00000000000000geometry.hpp-0.9.2/.travis.yml000066400000000000000000000023231312744530600162610ustar00rootroot00000000000000language: 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 geometry.hpp-0.9.2/LICENSE000066400000000000000000000013241312744530600151550ustar00rootroot00000000000000Copyright (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-0.9.2/Makefile000066400000000000000000000006701312744530600156130ustar00rootroot00000000000000CXXFLAGS += -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 geometry.hpp-0.9.2/README.md000066400000000000000000000041401312744530600154260ustar00rootroot00000000000000# 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 #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-0.9.2/include/000077500000000000000000000000001312744530600155735ustar00rootroot00000000000000geometry.hpp-0.9.2/include/mapbox/000077500000000000000000000000001312744530600170615ustar00rootroot00000000000000geometry.hpp-0.9.2/include/mapbox/geometry.hpp000066400000000000000000000007431312744530600214310ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include #include #include #include #include #include geometry.hpp-0.9.2/include/mapbox/geometry/000077500000000000000000000000001312744530600207145ustar00rootroot00000000000000geometry.hpp-0.9.2/include/mapbox/geometry/box.hpp000066400000000000000000000012051312744530600222130ustar00rootroot00000000000000#pragma once #include namespace mapbox { namespace geometry { template struct box { 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-0.9.2/include/mapbox/geometry/envelope.hpp000066400000000000000000000015151312744530600232440ustar00rootroot00000000000000#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-0.9.2/include/mapbox/geometry/feature.hpp000066400000000000000000000057141312744530600230670ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include #include 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>, 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 {}; std::experimental::optional 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 {}, std::experimental::optional id_ = std::experimental::optional {}) : geometry(std::move(geometry_)), properties(std::move(properties_)), 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 container_type::container_type; }; } // namespace geometry } // namespace mapbox geometry.hpp-0.9.2/include/mapbox/geometry/for_each_point.hpp000066400000000000000000000021441312744530600244050ustar00rootroot00000000000000#pragma once #include namespace mapbox { namespace geometry { 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-0.9.2/include/mapbox/geometry/geometry.hpp000066400000000000000000000035311312744530600232620ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include #include // stl #include namespace mapbox { namespace geometry { template class Cont = std::vector> struct geometry_collection; template using geometry_base = mapbox::util::variant, line_string, polygon, multi_point, multi_line_string, multi_polygon, geometry_collection>; template struct geometry : geometry_base { using coordinate_type = T; using geometry_base::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 class Cont> struct geometry_collection : Cont> { using coordinate_type = T; using geometry_type = geometry; using container_type = Cont; geometry_collection() = default; geometry_collection(geometry_collection const&) = default; geometry_collection(geometry_collection &&) = default; geometry_collection(std::initializer_list && args) : container_type(std::forward>(args)) {}; }; } // namespace geometry } // namespace mapbox geometry.hpp-0.9.2/include/mapbox/geometry/line_string.hpp000066400000000000000000000006671312744530600237530ustar00rootroot00000000000000#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 container_type::container_type; }; } // namespace geometry } // namespace mapbox geometry.hpp-0.9.2/include/mapbox/geometry/multi_line_string.hpp000066400000000000000000000007321312744530600251560ustar00rootroot00000000000000#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 container_type::container_type; }; } // namespace geometry } // namespace mapbox geometry.hpp-0.9.2/include/mapbox/geometry/multi_point.hpp000066400000000000000000000006661312744530600240000ustar00rootroot00000000000000#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 container_type::container_type; }; } // namespace geometry } // namespace mapbox geometry.hpp-0.9.2/include/mapbox/geometry/multi_polygon.hpp000066400000000000000000000007021312744530600243250ustar00rootroot00000000000000#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 container_type::container_type; }; } // namespace geometry } // namespace mapbox geometry.hpp-0.9.2/include/mapbox/geometry/point.hpp000066400000000000000000000010641312744530600225570ustar00rootroot00000000000000#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; }; template constexpr bool operator==(point const& lhs, point const& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; } template constexpr bool operator!=(point const& lhs, point const& rhs) { return !(lhs == rhs); } } // namespace geometry } // namespace mapbox geometry.hpp-0.9.2/include/mapbox/geometry/point_arithmetic.hpp000066400000000000000000000043051312744530600247710ustar00rootroot00000000000000#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-0.9.2/include/mapbox/geometry/polygon.hpp000066400000000000000000000013231312744530600231130ustar00rootroot00000000000000#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 container_type::container_type; }; template class Cont = std::vector> struct polygon : Cont> { using coordinate_type = T; using linear_ring_type = linear_ring; using container_type = Cont; using container_type::container_type; }; } // namespace geometry } // namespace mapbox geometry.hpp-0.9.2/tests/000077500000000000000000000000001312744530600153125ustar00rootroot00000000000000geometry.hpp-0.9.2/tests/collection.cpp000066400000000000000000000001461312744530600201520ustar00rootroot00000000000000#include void test() { mapbox::geometry::geometry_collection gc; } geometry.hpp-0.9.2/tests/test.cpp000066400000000000000000000162701312744530600170030ustar00rootroot00000000000000#include #include using namespace mapbox::geometry; static void testPoint() { point p1; assert(int(p1.x) == 0); assert(int(p1.y) == 0); point p2(2, 3); point p3(4, 6); assert((p2 + p3) == point(6, 9)); assert((p2 + 1u) == point(3, 4)); assert((p3 - p2) == point(2, 3)); assert((p3 - 1u) == point(3, 5)); assert((p3 * p2) == point(8, 18)); assert((p2 * 2u) == point(4, 6)); assert((p3 / p2) == point(2, 2)); assert((p3 / 2u) == point(2, 3)); { point p(2, 3); assert((p += p3) == point(6, 9)); } { point p(2, 3); assert((p += 1u) == point(3, 4)); } { point p(4, 6); assert((p -= p2) == point(2, 3)); } { point p(4, 6); assert((p -= 1u) == point(3, 5)); } { point p(4, 6); assert((p *= p2) == point(8, 18)); } { point p(2, 3); assert((p *= 2u) == point(4, 6)); } { point p(4, 6); assert((p /= p2) == point(2, 2)); } { point p(4, 6); assert((p /= 2u) == point(2, 3)); } } static void testMultiPoint() { multi_point mp1; assert(mp1.size() == 0); multi_point mp2(10); assert(mp2.size() == 10); assert(mp1 == mp1); assert(!(mp1 != mp1)); assert(mp1 != mp2); } static void testLineString() { line_string ls1; assert(ls1.size() == 0); line_string ls2(10); assert(ls2.size() == 10); assert(ls1 == ls1); assert(!(ls1 != ls1)); assert(ls1 != ls2); } static void testMultiLineString() { multi_line_string mls1; assert(mls1.size() == 0); multi_line_string mls2(10); assert(mls2.size() == 10); assert(mls1 == mls1); assert(!(mls1 != mls1)); assert(mls1 != mls2); } static void testPolygon() { polygon pg1; assert(pg1.size() == 0); polygon pg2({{{0, 1}}}); assert(pg2.size() == 1); assert(pg2[0].size() == 1); assert(pg2[0][0] == point(0, 1)); assert(pg1 == pg1); assert(!(pg1 != pg1)); assert(pg1 != pg2); } static void testMultiPolygon() { multi_polygon mpg1; assert(mpg1.size() == 0); multi_polygon mpg2(10); assert(mpg2.size() == 10); assert(mpg1 == mpg1); assert(!(mpg1 != mpg1)); assert(mpg1 != mpg2); } static void testGeometry() { geometry pg { point() }; assert(pg.is>()); geometry lsg { line_string() }; assert(lsg.is>()); geometry pgg { polygon() }; assert(pgg.is>()); geometry mpg { multi_point() }; assert(mpg.is>()); geometry mlsg { multi_line_string() }; assert(mlsg.is>()); geometry mpgg { multi_polygon() }; assert(mpgg.is>()); geometry gcg { geometry_collection() }; assert(gcg.is>()); assert(pg == pg); assert(!(pg != pg)); assert(pg != lsg); } static void testGeometryCollection() { geometry_collection gc1; assert(gc1.size() == 0); assert(gc1 == gc1); assert(!(gc1 != gc1)); } static void testFeature() { feature pf { point() }; assert(pf.geometry.is>()); 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()); assert(p["bool"] == true); assert(p["string"].is()); assert(p["string"] == std::string("foo")); assert(p["double"].is()); assert(p["double"] == 2.5); assert(p["uint"].is()); assert(p["uint"] == uint64_t(10)); assert(p["int"].is()); assert(p["int"] == int64_t(-10)); assert(p["null"].is()); assert(p["null"] == null_value); p["null"] = null_value_t{}; assert(p["null"].is()); assert(p["null"] == null_value); assert(p == p); assert(!(p != p)); assert(pf == pf); assert(!(pf != pf)); assert(p.size() == 6); feature id1 { point() }; id1.id = { uint64_t(1) }; feature id2 { point() }; id1.id = { uint64_t(2) }; assert(id1 == id1); assert(id1 != id2); } static void testFeatureCollection() { feature_collection fc1; assert(fc1.size() == 0); assert(fc1 == fc1); assert(!(fc1 != fc1)); } struct point_counter { std::size_t count = 0; template 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()) == 1); assert(count_points(line_string({{0, 1}, {2, 3}})) == 2); assert(count_points(geometry(polygon({{{0, 1}, {2, 3}}}))) == 2); auto point_negator = [] (point& p) { p *= -1.0; }; point p(1, 2); for_each_point(p, point_negator); assert(p == point(-1, -2)); line_string ls({{0, 1}, {2, 3}}); for_each_point(ls, point_negator); assert(ls == line_string({{0, -1}, {-2, -3}})); geometry g(polygon({{{0, 1}, {2, 3}}})); for_each_point(g, point_negator); assert(g == geometry(polygon({{{0, -1}, {-2, -3}}}))); // Custom geometry type using my_geometry = mapbox::util::variant>; assert(count_points(my_geometry(point())) == 1); // Custom point type struct my_point { int16_t x; int16_t y; }; assert(count_points(std::vector({my_point{0, 1}})) == 1); assert(count_points(mapbox::util::variant(my_point{0, 1})) == 1); } static void testEnvelope() { assert(envelope(point(0, 0)) == box({0, 0}, {0, 0})); assert(envelope(line_string({{0, 1}, {2, 3}})) == box({0, 1}, {2, 3})); assert(envelope(polygon({{{0, 1}, {2, 3}}})) == box({0, 1}, {2, 3})); assert(envelope(multi_point({{0, 0}})) == box({0, 0}, {0, 0})); assert(envelope(multi_line_string({{{0, 1}, {2, 3}}})) == box({0, 1}, {2, 3})); assert(envelope(multi_polygon({{{{0, 1}, {2, 3}}}})) == box({0, 1}, {2, 3})); assert(envelope(geometry(point(0, 0))) == box({0, 0}, {0, 0})); assert(envelope(geometry_collection({point(0, 0)})) == box({0, 0}, {0, 0})); } int main() { testPoint(); testMultiPoint(); testLineString(); testMultiLineString(); testPolygon(); testMultiPolygon(); testGeometry(); testGeometryCollection(); testFeature(); testFeatureCollection(); testForEachPoint(); testEnvelope(); return 0; }