1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2014-2017, 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>
39 struct is_simple_ring
40 {
41     template <typename Strategy>
applyboost::geometry::detail::is_simple::is_simple_ring42     static inline bool apply(Ring const& ring, Strategy const&)
43     {
44         return apply(ring);
45     }
46 
applyboost::geometry::detail::is_simple::is_simple_ring47     static inline bool apply(Ring const& ring)
48     {
49         simplicity_failure_policy policy;
50         return ! boost::empty(ring)
51             && ! detail::is_valid::has_duplicates
52                     <
53                         Ring, geometry::closure<Ring>::value
54                     >::apply(ring, policy);
55     }
56 };
57 
58 
59 template <typename Polygon>
60 class is_simple_polygon
61 {
62 private:
63     template <typename InteriorRings>
64     static inline
are_simple_interior_rings(InteriorRings const & interior_rings)65     bool are_simple_interior_rings(InteriorRings const& interior_rings)
66     {
67         return
68             detail::check_iterator_range
69                 <
70                     is_simple_ring
71                         <
72                             typename boost::range_value<InteriorRings>::type
73                         >
74                 >::apply(boost::begin(interior_rings),
75                          boost::end(interior_rings));
76     }
77 
78 public:
79     template <typename Strategy>
apply(Polygon const & polygon,Strategy const &)80     static inline bool apply(Polygon const& polygon, Strategy const&)
81     {
82         return apply(polygon);
83     }
84 
apply(Polygon const & polygon)85     static inline bool apply(Polygon const& polygon)
86     {
87         return
88             is_simple_ring
89                 <
90                     typename ring_type<Polygon>::type
91                 >::apply(exterior_ring(polygon))
92             &&
93             are_simple_interior_rings(geometry::interior_rings(polygon));
94     }
95 };
96 
97 
98 }} // namespace detail::is_simple
99 #endif // DOXYGEN_NO_DETAIL
100 
101 
102 
103 
104 #ifndef DOXYGEN_NO_DISPATCH
105 namespace dispatch
106 {
107 
108 
109 // A Ring is a Polygon.
110 // A Polygon is always a simple geometric object provided that it is valid.
111 //
112 // Reference (for polygon validity): OGC 06-103r4 (6.1.11.1)
113 template <typename Ring>
114 struct is_simple<Ring, ring_tag>
115     : detail::is_simple::is_simple_ring<Ring>
116 {};
117 
118 
119 // A Polygon is always a simple geometric object provided that it is valid.
120 //
121 // Reference (for validity of Polygons): OGC 06-103r4 (6.1.11.1)
122 template <typename Polygon>
123 struct is_simple<Polygon, polygon_tag>
124     : detail::is_simple::is_simple_polygon<Polygon>
125 {};
126 
127 
128 // Not clear what the definition is.
129 // Right now we consider a MultiPolygon as simple if it is valid.
130 //
131 // Reference (for validity of MultiPolygons): OGC 06-103r4 (6.1.14)
132 template <typename MultiPolygon>
133 struct is_simple<MultiPolygon, multi_polygon_tag>
134 {
135     template <typename Strategy>
applyboost::geometry::dispatch::is_simple136     static inline bool apply(MultiPolygon const& multipolygon, Strategy const&)
137     {
138         return
139             detail::check_iterator_range
140                 <
141                     detail::is_simple::is_simple_polygon
142                         <
143                             typename boost::range_value<MultiPolygon>::type
144                         >,
145                     true // allow empty multi-polygon
146                 >::apply(boost::begin(multipolygon), boost::end(multipolygon));
147     }
148 };
149 
150 
151 } // namespace dispatch
152 #endif // DOXYGEN_NO_DISPATCH
153 
154 
155 }} // namespace boost::geometry
156 
157 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_AREAL_HPP
158