1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 
5 // Use, modification and distribution is subject to the Boost Software License,
6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 
9 #ifndef BOOST_GEOMETRY_POLICIES_COMPARE_HPP
10 #define BOOST_GEOMETRY_POLICIES_COMPARE_HPP
11 
12 
13 #include <cstddef>
14 
15 #include <boost/geometry/strategies/compare.hpp>
16 #include <boost/geometry/util/math.hpp>
17 
18 
19 namespace boost { namespace geometry
20 {
21 
22 
23 #ifndef DOXYGEN_NO_DETAIL
24 namespace detail { namespace compare
25 {
26 
27 
28 template
29 <
30     int Direction,
31     typename Point,
32     typename Strategy,
33     std::size_t Dimension,
34     std::size_t DimensionCount
35 >
36 struct compare_loop
37 {
38     typedef typename strategy::compare::detail::select_strategy
39         <
40             Strategy, Direction, Point, Dimension
41         >::type compare_type;
42 
43     typedef typename geometry::coordinate_type<Point>::type coordinate_type;
44 
applyboost::geometry::detail::compare::compare_loop45     static inline bool apply(Point const& left, Point const& right)
46     {
47         coordinate_type const& cleft = geometry::get<Dimension>(left);
48         coordinate_type const& cright = geometry::get<Dimension>(right);
49 
50         if (geometry::math::equals(cleft, cright))
51         {
52             return compare_loop
53                 <
54                     Direction, Point, Strategy,
55                     Dimension + 1, DimensionCount
56                 >::apply(left, right);
57         }
58         else
59         {
60             compare_type compare;
61             return compare(cleft, cright);
62         }
63     }
64 };
65 
66 template
67 <
68     int Direction,
69     typename Point,
70     typename Strategy,
71     std::size_t DimensionCount
72 >
73 struct compare_loop<Direction, Point, Strategy, DimensionCount, DimensionCount>
74 {
applyboost::geometry::detail::compare::compare_loop75     static inline bool apply(Point const&, Point const&)
76     {
77         // On coming here, points are equal. Return true if
78         // direction = 0 (equal), false if -1/1 (greater/less)
79         return Direction == 0;
80     }
81 };
82 
83 
84 template <int Direction, typename Point, typename Strategy>
85 struct compare_in_all_dimensions
86 {
operator ()boost::geometry::detail::compare::compare_in_all_dimensions87     inline bool operator()(Point const& left, Point const& right) const
88     {
89         return detail::compare::compare_loop
90             <
91                 Direction, Point, Strategy,
92                 0, geometry::dimension<Point>::type::value
93             >::apply(left, right);
94     }
95 };
96 
97 
98 template <typename Point, typename Strategy, std::size_t Dimension>
99 class compare_in_one_dimension
100 {
101     Strategy compare;
102 
103 public :
operator ()(Point const & left,Point const & right) const104     inline bool operator()(Point const& left, Point const& right) const
105     {
106         typedef typename geometry::coordinate_type<Point>::type coordinate_type;
107 
108         coordinate_type const& cleft = get<Dimension>(left);
109         coordinate_type const& cright = get<Dimension>(right);
110         return compare(cleft, cright);
111     }
112 };
113 
114 }} // namespace detail::compare
115 
116 #endif
117 
118 #ifndef DOXYGEN_NO_DISPATCH
119 namespace dispatch
120 {
121 
122 template
123 <
124     int Direction,
125     typename Point,
126     typename Strategy,
127     int Dimension
128 >
129 struct compare_geometries
130     : detail::compare::compare_in_one_dimension
131         <
132             Point,
133             typename strategy::compare::detail::select_strategy
134                 <
135                     Strategy, Direction, Point, Dimension
136                 >::type,
137             Dimension
138         >
139 {};
140 
141 
142 // Specialization with -1: compare in all dimensions
143 template <int Direction, typename Point, typename Strategy>
144 struct compare_geometries<Direction, Point, Strategy, -1>
145     : detail::compare::compare_in_all_dimensions<Direction, Point, Strategy>
146 {};
147 
148 
149 
150 } // namespace dispatch
151 #endif // DOXYGEN_NO_DISPATCH
152 
153 
154 /*!
155 \brief Less functor, to sort points in ascending order.
156 \ingroup compare
157 \details This functor compares points and orders them on x,
158     then on y, then on z coordinate.
159 \tparam Geometry the geometry
160 \tparam Dimension the dimension to sort on, defaults to -1,
161     indicating ALL dimensions. That's to say, first on x,
162     on equal x-es then on y, etc.
163     If a dimension is specified, only that dimension is considered
164 \tparam Strategy underlying coordinate comparing functor,
165     defaults to the default comparison strategies
166     related to the point coordinate system. If specified, the specified
167     strategy is used. This can e.g. be std::less<double>.
168 */
169 template
170 <
171     typename Point,
172     int Dimension = -1,
173     typename Strategy = strategy::compare::default_strategy
174 >
175 struct less
176     : dispatch::compare_geometries
177         <
178             1, // indicates ascending
179             Point,
180             Strategy,
181             Dimension
182         >
183 {
184     typedef Point first_argument_type;
185     typedef Point second_argument_type;
186     typedef bool result_type;
187 };
188 
189 
190 /*!
191 \brief Greater functor
192 \ingroup compare
193 \details Can be used to sort points in reverse order
194 \see Less functor
195 */
196 template
197 <
198     typename Point,
199     int Dimension = -1,
200     typename Strategy = strategy::compare::default_strategy
201 >
202 struct greater
203     : dispatch::compare_geometries
204         <
205             -1,  // indicates descending
206             Point,
207             Strategy,
208             Dimension
209         >
210 {};
211 
212 
213 /*!
214 \brief Equal To functor, to compare if points are equal
215 \ingroup compare
216 \tparam Geometry the geometry
217 \tparam Dimension the dimension to compare on, defaults to -1,
218     indicating ALL dimensions.
219     If a dimension is specified, only that dimension is considered
220 \tparam Strategy underlying coordinate comparing functor
221 */
222 template
223 <
224     typename Point,
225     int Dimension = -1,
226     typename Strategy = strategy::compare::default_strategy
227 >
228 struct equal_to
229     : dispatch::compare_geometries
230         <
231             0,
232             Point,
233             Strategy,
234             Dimension
235         >
236 {};
237 
238 
239 }} // namespace boost::geometry
240 
241 
242 #endif // BOOST_GEOMETRY_POLICIES_COMPARE_HPP
243