1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3 
4 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
5 
6 // Use, modification and distribution is subject to the Boost Software License,
7 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9 
10 #include <geometry_test_common.hpp>
11 
12 #include <algorithm>
13 
14 #include <boost/geometry/algorithms/make.hpp>
15 #include <boost/geometry/io/dsv/write.hpp>
16 
17 #include <boost/geometry/policies/compare.hpp>
18 
19 #include <boost/geometry/strategies/strategies.hpp>
20 
21 #include <boost/geometry/geometries/point.hpp>
22 #include <boost/geometry/geometries/adapted/c_array.hpp>
23 #include <boost/geometry/geometries/adapted/boost_tuple.hpp>
24 
25 #include <test_common/test_point.hpp>
26 
27 BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian)
BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)28 BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
29 
30 
31 template <typename Container>
32 inline std::string coordinates(Container const& points)
33 {
34     std::ostringstream out;
35     for (typename boost::range_const_iterator<Container>::type it = boost::begin(points);
36         it != boost::end(points);
37         ++it)
38     {
39         out << bg::dsv(*it);
40     }
41     return out.str();
42 }
43 
44 template <typename P>
test_2d_compare()45 void test_2d_compare()
46 {
47     P p1 = bg::make<P>(3, 1);
48     P p2 = bg::make<P>(3, 1);
49     P p3 = bg::make<P>(1, 3);
50     P p4 = bg::make<P>(5, 2);
51     P p5 = bg::make<P>(3, 2);
52 
53     // Test in all dimensions
54     {
55         bg::equal_to<P> et;
56         bg::less<P> lt;
57         bg::greater<P> gt;
58 
59         BOOST_CHECK_EQUAL(et(p1, p2), true);
60         BOOST_CHECK_EQUAL(et(p1, p3), false);
61         BOOST_CHECK_EQUAL(et(p1, p4), false);
62         BOOST_CHECK_EQUAL(et(p1, p5), false);
63         BOOST_CHECK_EQUAL(et(p3, p4), false);
64 
65         BOOST_CHECK_EQUAL(lt(p1, p2), false);
66         BOOST_CHECK_EQUAL(lt(p1, p3), false);
67         BOOST_CHECK_EQUAL(lt(p1, p4), true);
68         BOOST_CHECK_EQUAL(lt(p1, p5), true);
69         BOOST_CHECK_EQUAL(lt(p3, p4), true);
70 
71         BOOST_CHECK_EQUAL(gt(p1, p2), false);
72         BOOST_CHECK_EQUAL(gt(p1, p3), true);
73         BOOST_CHECK_EQUAL(gt(p1, p4), false);
74         BOOST_CHECK_EQUAL(gt(p1, p5), false);
75         BOOST_CHECK_EQUAL(gt(p3, p4), false);
76     }
77 
78 
79     // Test in dimension 0, X
80     {
81         bg::equal_to<P, 0> et;
82         bg::less<P, 0> lt;
83         bg::greater<P, 0> gt;
84 
85         BOOST_CHECK_EQUAL(et(p1, p2), true);
86         BOOST_CHECK_EQUAL(et(p1, p3), false);
87         BOOST_CHECK_EQUAL(et(p1, p4), false);
88         BOOST_CHECK_EQUAL(et(p1, p5), true);
89         BOOST_CHECK_EQUAL(et(p3, p4), false);
90 
91         BOOST_CHECK_EQUAL(lt(p1, p2), false);
92         BOOST_CHECK_EQUAL(lt(p1, p3), false);
93         BOOST_CHECK_EQUAL(lt(p1, p4), true);
94         BOOST_CHECK_EQUAL(lt(p1, p5), false);
95         BOOST_CHECK_EQUAL(lt(p3, p4), true);
96 
97         BOOST_CHECK_EQUAL(gt(p1, p2), false);
98         BOOST_CHECK_EQUAL(gt(p1, p3), true);
99         BOOST_CHECK_EQUAL(gt(p1, p4), false);
100         BOOST_CHECK_EQUAL(gt(p1, p5), false);
101         BOOST_CHECK_EQUAL(gt(p3, p4), false);
102     }
103 
104     // Test in dimension 1, Y
105     {
106         bg::equal_to<P, 1> et;
107         bg::less<P, 1> lt;
108         bg::greater<P, 1> gt;
109 
110         BOOST_CHECK_EQUAL(et(p1, p2), true);
111         BOOST_CHECK_EQUAL(et(p1, p3), false);
112         BOOST_CHECK_EQUAL(et(p1, p4), false);
113         BOOST_CHECK_EQUAL(et(p1, p5), false);
114         BOOST_CHECK_EQUAL(et(p3, p4), false);
115 
116         BOOST_CHECK_EQUAL(lt(p1, p2), false);
117         BOOST_CHECK_EQUAL(lt(p1, p3), true);
118         BOOST_CHECK_EQUAL(lt(p1, p4), true);
119         BOOST_CHECK_EQUAL(lt(p1, p5), true);
120         BOOST_CHECK_EQUAL(lt(p3, p4), false);
121 
122         BOOST_CHECK_EQUAL(gt(p1, p2), false);
123         BOOST_CHECK_EQUAL(gt(p1, p3), false);
124         BOOST_CHECK_EQUAL(gt(p1, p4), false);
125         BOOST_CHECK_EQUAL(gt(p1, p5), false);
126         BOOST_CHECK_EQUAL(gt(p3, p4), true);
127     }
128 }
129 
130 
131 template <typename P>
test_2d_sort()132 void test_2d_sort()
133 {
134     std::vector<P> v;
135     v.push_back(bg::make<P>(3, 1));
136     v.push_back(bg::make<P>(2, 3));
137     v.push_back(bg::make<P>(2, 2));
138     v.push_back(bg::make<P>(1, 3));
139 
140     // Sort on coordinates in order x,y,z
141     std::sort(v.begin(), v.end(), bg::less<P>());
142     std::string s = coordinates(v);
143     BOOST_CHECK_EQUAL(s, "(1, 3)(2, 2)(2, 3)(3, 1)");
144 
145     // Reverse sort
146     std::sort(v.begin(), v.end(), bg::greater<P>());
147     s = coordinates(v);
148     BOOST_CHECK_EQUAL(s, "(3, 1)(2, 3)(2, 2)(1, 3)");
149 
150     // Sort backwards on coordinates in order x,y,z
151     //std::sort(v.begin(), v.end(), bg::greater<P>());
152     //std::string s = coordinates(v);
153     //BOOST_CHECK_EQUAL(s, "(1, 3)(2, 2)(2, 3)(3, 1)");
154 
155     // Refill to remove duplicate coordinates
156     v.clear();
157     v.push_back(bg::make<P>(4, 1));
158     v.push_back(bg::make<P>(3, 2));
159     v.push_back(bg::make<P>(2, 3));
160     v.push_back(bg::make<P>(1, 4));
161 
162     // Sort ascending on only x-coordinate
163     std::sort(v.begin(), v.end(), bg::less<P, 0>());
164     s = coordinates(v);
165     BOOST_CHECK_EQUAL(s, "(1, 4)(2, 3)(3, 2)(4, 1)");
166 
167     // Sort ascending on only y-coordinate
168     std::sort(v.begin(), v.end(), bg::less<P, 1>());
169     s = coordinates(v);
170     BOOST_CHECK_EQUAL(s, "(4, 1)(3, 2)(2, 3)(1, 4)");
171 
172     // Sort descending on only x-coordinate
173     std::sort(v.begin(), v.end(), bg::greater<P, 0>());
174     s = coordinates(v);
175     //BOOST_CHECK_EQUAL(s, "(4, 1)(3, 2)(2, 3)(1, 4)");
176 
177     // Sort descending on only y-coordinate
178     std::sort(v.begin(), v.end(), bg::greater<P, 1>());
179     s = coordinates(v);
180     BOOST_CHECK_EQUAL(s, "(1, 4)(2, 3)(3, 2)(4, 1)");
181 
182     // Make non-unique vector
183     v.push_back(bg::make<P>(4, 1));
184     v.push_back(bg::make<P>(3, 2));
185     v.push_back(bg::make<P>(2, 3));
186     v.push_back(bg::make<P>(1, 4));
187     v.push_back(bg::make<P>(1, 5));
188     std::sort(v.begin(), v.end(), bg::less<P>());
189     s = coordinates(v);
190     BOOST_CHECK_EQUAL(s, "(1, 4)(1, 4)(1, 5)(2, 3)(2, 3)(3, 2)(3, 2)(4, 1)(4, 1)");
191 
192 
193     std::vector<P> v2;
194     std::unique_copy(v.begin(), v.end(), std::back_inserter(v2), bg::equal_to<P>());
195     s = coordinates(v2);
196     BOOST_CHECK_EQUAL(s, "(1, 4)(1, 5)(2, 3)(3, 2)(4, 1)");
197 }
198 
199 
200 template <typename P>
test_spherical()201 void test_spherical()
202 {
203     typedef typename bg::coordinate_type<P>::type ct;
204 
205     std::vector<P> v;
206     v.push_back(bg::make<P>( 179.73, 71.56)); // east
207     v.push_back(bg::make<P>( 177.47, 71.23)); // less east
208     v.push_back(bg::make<P>(-178.78, 70.78)); // further east, = west, this is the most right point
209 
210     // Sort on coordinates in order x,y,z
211     std::sort(v.begin(), v.end(), bg::less<P>());
212     std::string s = coordinates(v);
213     BOOST_CHECK_EQUAL(s, "(177.47, 71.23)(179.73, 71.56)(-178.78, 70.78)");
214 
215     // Sort ascending on only x-coordinate
216     std::sort(v.begin(), v.end(), bg::less<P, 0>());
217     s = coordinates(v);
218     BOOST_CHECK_EQUAL(s, "(177.47, 71.23)(179.73, 71.56)(-178.78, 70.78)");
219 
220     // Sort ascending on only x-coordinate, but override with std-comparison,
221     // (so this is the normal sorting behaviour that would have been used
222     // if it would not have been spherical)
223     std::sort(v.begin(), v.end(), bg::less<P, 0, std::less<ct> >());
224     s = coordinates(v);
225     BOOST_CHECK_EQUAL(s, "(-178.78, 70.78)(177.47, 71.23)(179.73, 71.56)");
226 }
227 
228 
test_main(int,char * [])229 int test_main(int, char* [])
230 {
231     test_2d_compare<bg::model::point<int, 2, bg::cs::cartesian> >();
232     test_2d_compare<bg::model::point<double, 2, bg::cs::cartesian> >();
233 
234     test_2d_sort<bg::model::point<int, 2, bg::cs::cartesian> >();
235     test_2d_sort<bg::model::point<float, 2, bg::cs::cartesian> >();
236     test_2d_sort<boost::tuple<double, double> >();
237     test_2d_sort<bg::model::point<double, 2, bg::cs::cartesian> >();
238 
239     test_spherical<bg::model::point<double, 2, bg::cs::spherical<bg::degree> > >();
240 
241     return 0;
242 }
243