1 // Boost.Geometry (aka GGL, Generic Geometry Library) 2 3 // Copyright (c) 2014-2019, Oracle and/or its affiliates. 4 5 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle 6 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle 7 8 // Licensed under the Boost Software License version 1.0. 9 // http://www.boost.org/users/license.html 10 11 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_AREAL_HPP 12 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_AREAL_HPP 13 14 #include <boost/range.hpp> 15 16 #include <boost/geometry/core/closure.hpp> 17 #include <boost/geometry/core/exterior_ring.hpp> 18 #include <boost/geometry/core/interior_rings.hpp> 19 #include <boost/geometry/core/ring_type.hpp> 20 #include <boost/geometry/core/tags.hpp> 21 22 #include <boost/geometry/algorithms/detail/check_iterator_range.hpp> 23 #include <boost/geometry/algorithms/detail/is_simple/failure_policy.hpp> 24 #include <boost/geometry/algorithms/detail/is_valid/has_duplicates.hpp> 25 26 #include <boost/geometry/algorithms/dispatch/is_simple.hpp> 27 28 29 namespace boost { namespace geometry 30 { 31 32 33 #ifndef DOXYGEN_NO_DETAIL 34 namespace detail { namespace is_simple 35 { 36 37 38 template <typename Ring, typename CSTag> 39 struct is_simple_ring 40 { applyboost::geometry::detail::is_simple::is_simple_ring41 static inline bool apply(Ring const& ring) 42 { 43 simplicity_failure_policy policy; 44 return ! boost::empty(ring) 45 && ! detail::is_valid::has_duplicates 46 < 47 Ring, geometry::closure<Ring>::value, CSTag 48 >::apply(ring, policy); 49 } 50 }; 51 52 53 template <typename Polygon, typename CSTag> 54 class is_simple_polygon 55 { 56 private: 57 template <typename InteriorRings> 58 static inline are_simple_interior_rings(InteriorRings const & interior_rings)59 bool are_simple_interior_rings(InteriorRings const& interior_rings) 60 { 61 return 62 detail::check_iterator_range 63 < 64 is_simple_ring 65 < 66 typename boost::range_value<InteriorRings>::type, 67 CSTag 68 > 69 >::apply(boost::begin(interior_rings), 70 boost::end(interior_rings)); 71 } 72 73 public: apply(Polygon const & polygon)74 static inline bool apply(Polygon const& polygon) 75 { 76 return 77 is_simple_ring 78 < 79 typename ring_type<Polygon>::type, 80 CSTag 81 >::apply(exterior_ring(polygon)) 82 && 83 are_simple_interior_rings(geometry::interior_rings(polygon)); 84 } 85 }; 86 87 88 }} // namespace detail::is_simple 89 #endif // DOXYGEN_NO_DETAIL 90 91 92 93 94 #ifndef DOXYGEN_NO_DISPATCH 95 namespace dispatch 96 { 97 98 99 // A Ring is a Polygon. 100 // A Polygon is always a simple geometric object provided that it is valid. 101 // 102 // Reference (for polygon validity): OGC 06-103r4 (6.1.11.1) 103 template <typename Ring> 104 struct is_simple<Ring, ring_tag> 105 { 106 template <typename Strategy> applyboost::geometry::dispatch::is_simple107 static inline bool apply(Ring const& ring, Strategy const&) 108 { 109 return detail::is_simple::is_simple_ring 110 < 111 Ring, 112 typename Strategy::cs_tag 113 >::apply(ring); 114 } 115 }; 116 117 118 // A Polygon is always a simple geometric object provided that it is valid. 119 // 120 // Reference (for validity of Polygons): OGC 06-103r4 (6.1.11.1) 121 template <typename Polygon> 122 struct is_simple<Polygon, polygon_tag> 123 { 124 template <typename Strategy> applyboost::geometry::dispatch::is_simple125 static inline bool apply(Polygon const& polygon, Strategy const&) 126 { 127 return detail::is_simple::is_simple_polygon 128 < 129 Polygon, 130 typename Strategy::cs_tag 131 >::apply(polygon); 132 } 133 }; 134 135 136 // Not clear what the definition is. 137 // Right now we consider a MultiPolygon as simple if it is valid. 138 // 139 // Reference (for validity of MultiPolygons): OGC 06-103r4 (6.1.14) 140 template <typename MultiPolygon> 141 struct is_simple<MultiPolygon, multi_polygon_tag> 142 { 143 template <typename Strategy> applyboost::geometry::dispatch::is_simple144 static inline bool apply(MultiPolygon const& multipolygon, Strategy const&) 145 { 146 return 147 detail::check_iterator_range 148 < 149 detail::is_simple::is_simple_polygon 150 < 151 typename boost::range_value<MultiPolygon>::type, 152 typename Strategy::cs_tag 153 >, 154 true // allow empty multi-polygon 155 >::apply(boost::begin(multipolygon), boost::end(multipolygon)); 156 } 157 }; 158 159 160 } // namespace dispatch 161 #endif // DOXYGEN_NO_DISPATCH 162 163 164 }} // namespace boost::geometry 165 166 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_AREAL_HPP 167