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