File indexing completed on 2025-01-18 09:35:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_GEOMETRY_ALGORITHMS_CORRECT_CLOSURE_HPP
0015 #define BOOST_GEOMETRY_ALGORITHMS_CORRECT_CLOSURE_HPP
0016
0017 #include <boost/geometry/algorithms/detail/multi_modify.hpp>
0018 #include <boost/geometry/algorithms/disjoint.hpp>
0019
0020 #include <boost/geometry/core/closure.hpp>
0021 #include <boost/geometry/core/exterior_ring.hpp>
0022 #include <boost/geometry/core/interior_rings.hpp>
0023 #include <boost/geometry/core/tags.hpp>
0024
0025 #include <boost/geometry/geometries/adapted/boost_variant.hpp>
0026 #include <boost/geometry/geometries/concepts/check.hpp>
0027
0028 #include <boost/geometry/util/range.hpp>
0029 #include <boost/range/size.hpp>
0030
0031 namespace boost { namespace geometry
0032 {
0033
0034
0035 #if defined(_MSC_VER)
0036 #pragma warning(push)
0037 #pragma warning(disable : 4127)
0038 #endif
0039
0040 #ifndef DOXYGEN_NO_DETAIL
0041 namespace detail { namespace correct_closure
0042 {
0043
0044 struct nop
0045 {
0046 template <typename Geometry>
0047 static inline void apply(Geometry& )
0048 {}
0049 };
0050
0051
0052 struct close_or_open_ring
0053 {
0054 template <typename Ring>
0055 static inline void apply(Ring& r)
0056 {
0057 auto size = boost::size(r);
0058 if (size <= 2)
0059 {
0060 return;
0061 }
0062
0063
0064 bool const disjoint = geometry::disjoint(*boost::begin(r), *(boost::end(r) - 1));
0065 closure_selector const closure = geometry::closure<Ring>::value;
0066
0067 if (disjoint && closure == closed)
0068 {
0069
0070 geometry::append(r, *boost::begin(r));
0071 }
0072 else if (! disjoint && closure == open)
0073 {
0074
0075 range::resize(r, size - 1);
0076 }
0077 }
0078 };
0079
0080
0081 struct close_or_open_polygon
0082 {
0083 template <typename Polygon>
0084 static inline void apply(Polygon& poly)
0085 {
0086 close_or_open_ring::apply(exterior_ring(poly));
0087
0088 auto&& rings = interior_rings(poly);
0089 auto const end = boost::end(rings);
0090 for (auto it = boost::begin(rings); it != end; ++it)
0091 {
0092 close_or_open_ring::apply(*it);
0093 }
0094 }
0095 };
0096
0097 }}
0098 #endif
0099
0100
0101 #ifndef DOXYGEN_NO_DISPATCH
0102 namespace dispatch
0103 {
0104
0105 template <typename Geometry, typename Tag = typename tag<Geometry>::type>
0106 struct correct_closure: not_implemented<Tag>
0107 {};
0108
0109 template <typename Point>
0110 struct correct_closure<Point, point_tag>
0111 : detail::correct_closure::nop
0112 {};
0113
0114 template <typename LineString>
0115 struct correct_closure<LineString, linestring_tag>
0116 : detail::correct_closure::nop
0117 {};
0118
0119 template <typename Segment>
0120 struct correct_closure<Segment, segment_tag>
0121 : detail::correct_closure::nop
0122 {};
0123
0124
0125 template <typename Box>
0126 struct correct_closure<Box, box_tag>
0127 : detail::correct_closure::nop
0128 {};
0129
0130 template <typename Ring>
0131 struct correct_closure<Ring, ring_tag>
0132 : detail::correct_closure::close_or_open_ring
0133 {};
0134
0135 template <typename Polygon>
0136 struct correct_closure<Polygon, polygon_tag>
0137 : detail::correct_closure::close_or_open_polygon
0138 {};
0139
0140
0141 template <typename MultiPoint>
0142 struct correct_closure<MultiPoint, multi_point_tag>
0143 : detail::correct_closure::nop
0144 {};
0145
0146
0147 template <typename MultiLineString>
0148 struct correct_closure<MultiLineString, multi_linestring_tag>
0149 : detail::correct_closure::nop
0150 {};
0151
0152
0153 template <typename Geometry>
0154 struct correct_closure<Geometry, multi_polygon_tag>
0155 : detail::multi_modify
0156 <
0157 detail::correct_closure::close_or_open_polygon
0158 >
0159 {};
0160
0161
0162 }
0163 #endif
0164
0165
0166 namespace resolve_variant
0167 {
0168
0169 template <typename Geometry, typename Tag = typename tag<Geometry>::type>
0170 struct correct_closure
0171 {
0172 static inline void apply(Geometry& geometry)
0173 {
0174 concepts::check<Geometry const>();
0175 dispatch::correct_closure<Geometry>::apply(geometry);
0176 }
0177 };
0178
0179 template <typename Geometry>
0180 struct correct_closure<Geometry, dynamic_geometry_tag>
0181 {
0182 static void apply(Geometry& geometry)
0183 {
0184 traits::visit<Geometry>::apply([](auto & g)
0185 {
0186 correct_closure<util::remove_cref_t<decltype(g)>>::apply(g);
0187 }, geometry);
0188 }
0189 };
0190
0191 template <typename Geometry>
0192 struct correct_closure<Geometry, geometry_collection_tag>
0193 {
0194 static void apply(Geometry& geometry)
0195 {
0196 detail::visit_breadth_first([](auto & g)
0197 {
0198 correct_closure<util::remove_cref_t<decltype(g)>>::apply(g);
0199 return true;
0200 }, geometry);
0201 }
0202 };
0203
0204 }
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219 template <typename Geometry>
0220 inline void correct_closure(Geometry& geometry)
0221 {
0222 resolve_variant::correct_closure<Geometry>::apply(geometry);
0223 }
0224
0225
0226 #if defined(_MSC_VER)
0227 #pragma warning(pop)
0228 #endif
0229
0230 }}
0231
0232
0233 #endif