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