1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
6 // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
7 
8 // This file was modified by Oracle on 2020.
9 // Modifications copyright (c) 2020 Oracle and/or its affiliates.
10 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
11 
12 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
13 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
14 
15 // Use, modification and distribution is subject to the Boost Software License,
16 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
17 // http://www.boost.org/LICENSE_1_0.txt)
18 
19 #ifndef BOOST_GEOMETRY_ALGORITHMS_REVERSE_HPP
20 #define BOOST_GEOMETRY_ALGORITHMS_REVERSE_HPP
21 
22 #include <algorithm>
23 
24 #include <boost/range/begin.hpp>
25 #include <boost/range/end.hpp>
26 
27 #include <boost/variant/apply_visitor.hpp>
28 #include <boost/variant/static_visitor.hpp>
29 #include <boost/variant/variant_fwd.hpp>
30 
31 #include <boost/geometry/algorithms/detail/interior_iterator.hpp>
32 #include <boost/geometry/algorithms/detail/multi_modify.hpp>
33 #include <boost/geometry/core/interior_rings.hpp>
34 #include <boost/geometry/core/tags.hpp>
35 #include <boost/geometry/geometries/concepts/check.hpp>
36 
37 
38 namespace boost { namespace geometry
39 {
40 
41 
42 #ifndef DOXYGEN_NO_DETAIL
43 namespace detail { namespace reverse
44 {
45 
46 
47 struct range_reverse
48 {
49     template <typename Range>
applyboost::geometry::detail::reverse::range_reverse50     static inline void apply(Range& range)
51     {
52         std::reverse(boost::begin(range), boost::end(range));
53     }
54 };
55 
56 
57 struct polygon_reverse: private range_reverse
58 {
59     template <typename Polygon>
applyboost::geometry::detail::reverse::polygon_reverse60     static inline void apply(Polygon& polygon)
61     {
62         range_reverse::apply(exterior_ring(polygon));
63 
64         typename interior_return_type<Polygon>::type
65             rings = interior_rings(polygon);
66 
67         for (typename detail::interior_iterator<Polygon>::type
68                 it = boost::begin(rings); it != boost::end(rings); ++it)
69         {
70             range_reverse::apply(*it);
71         }
72     }
73 };
74 
75 
76 }} // namespace detail::reverse
77 #endif // DOXYGEN_NO_DETAIL
78 
79 
80 #ifndef DOXYGEN_NO_DISPATCH
81 namespace dispatch
82 {
83 
84 
85 template <typename Geometry, typename Tag = typename tag<Geometry>::type>
86 struct reverse
87 {
applyboost::geometry::dispatch::reverse88     static inline void apply(Geometry&)
89     {}
90 };
91 
92 
93 template <typename Ring>
94 struct reverse<Ring, ring_tag>
95     : detail::reverse::range_reverse
96 {};
97 
98 
99 template <typename LineString>
100 struct reverse<LineString, linestring_tag>
101     : detail::reverse::range_reverse
102 {};
103 
104 
105 template <typename Polygon>
106 struct reverse<Polygon, polygon_tag>
107     : detail::reverse::polygon_reverse
108 {};
109 
110 
111 template <typename Geometry>
112 struct reverse<Geometry, multi_linestring_tag>
113     : detail::multi_modify
114         <
115             Geometry,
116             detail::reverse::range_reverse
117         >
118 {};
119 
120 
121 template <typename Geometry>
122 struct reverse<Geometry, multi_polygon_tag>
123     : detail::multi_modify
124         <
125             Geometry,
126             detail::reverse::polygon_reverse
127         >
128 {};
129 
130 
131 
132 } // namespace dispatch
133 #endif
134 
135 
136 namespace resolve_variant
137 {
138 
139 template <typename Geometry>
140 struct reverse
141 {
applyboost::geometry::resolve_variant::reverse142     static void apply(Geometry& geometry)
143     {
144         concepts::check<Geometry>();
145         dispatch::reverse<Geometry>::apply(geometry);
146     }
147 };
148 
149 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
150 struct reverse<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
151 {
152     struct visitor: boost::static_visitor<void>
153     {
154         template <typename Geometry>
operator ()boost::geometry::resolve_variant::reverse::visitor155         void operator()(Geometry& geometry) const
156         {
157             reverse<Geometry>::apply(geometry);
158         }
159     };
160 
applyboost::geometry::resolve_variant::reverse161     static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
162     {
163         boost::apply_visitor(visitor(), geometry);
164     }
165 };
166 
167 } // namespace resolve_variant
168 
169 
170 /*!
171 \brief Reverses the points within a geometry
172 \details Generic function to reverse a geometry. It resembles the std::reverse
173    functionality, but it takes the geometry type into account. Only for a ring
174    or for a linestring it is the same as the std::reverse.
175 \ingroup reverse
176 \tparam Geometry \tparam_geometry
177 \param geometry \param_geometry which will be reversed
178 
179 \qbk{[include reference/algorithms/reverse.qbk]}
180 */
181 template <typename Geometry>
reverse(Geometry & geometry)182 inline void reverse(Geometry& geometry)
183 {
184     resolve_variant::reverse<Geometry>::apply(geometry);
185 }
186 
187 }} // namespace boost::geometry
188 
189 
190 #endif // BOOST_GEOMETRY_ALGORITHMS_REVERSE_HPP
191