Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:30:47

0001 // Boost.Geometry
0002 
0003 // Copyright (c) 2017 Barend Gehrels, Amsterdam, the Netherlands.
0004 // Copyright (c) 2024 Adam Wulkiewicz, Lodz, Poland.
0005 
0006 // This file was modified by Oracle on 2020-2023.
0007 // Modifications copyright (c) 2020-2023 Oracle and/or its affiliates.
0008 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
0009 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0010 
0011 // Use, modification and distribution is subject to the Boost Software License,
0012 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0013 // http://www.boost.org/LICENSE_1_0.txt)
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 // Silence warning C4127: conditional expression is constant
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 // Close a ring, if not closed, or open it
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         // TODO: This requires relate(pt, pt) strategy
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             // Close it by adding first point
0071             geometry::append(r, *boost::begin(r));
0072         }
0073         else if (! disjoint && closure == open)
0074         {
0075             // Open it by removing last point
0076             range::resize(r, size - 1);
0077         }
0078     }
0079 };
0080 
0081 // Close/open exterior ring and all its interior rings
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 }} // namespace detail::correct_closure
0099 #endif // DOXYGEN_NO_DETAIL
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 } // namespace dispatch
0164 #endif // DOXYGEN_NO_DISPATCH
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 } // namespace resolve_variant
0206 
0207 
0208 // TODO: This algorithm should use relate(pt, pt) strategy
0209 
0210 
0211 /*!
0212 \brief Closes or opens a geometry, according to its type
0213 \details Corrects a geometry w.r.t. closure points to all rings which do not
0214     have a closing point and are typed as they should have one, the first point
0215     is appended.
0216 \ingroup correct_closure
0217 \tparam Geometry \tparam_geometry
0218 \param geometry \param_geometry which will be corrected if necessary
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 }} // namespace boost::geometry
0232 
0233 
0234 #endif // BOOST_GEOMETRY_ALGORITHMS_CORRECT_CLOSURE_HPP