1 // Boost.Polygon library polygon_segment_test.cpp file
2 
3 //          Copyright Andrii Sydorchuk 2012.
4 // Distributed under the Boost Software License, Version 1.0.
5 //    (See accompanying file LICENSE_1_0.txt or copy at
6 //          http://www.boost.org/LICENSE_1_0.txt)
7 
8 // See http://www.boost.org for updates, documentation, and revision history.
9 
10 #define BOOST_TEST_MODULE POLYGON_SEGMENT_TEST
11 #include <boost/mpl/list.hpp>
12 #include <boost/test/test_case_template.hpp>
13 
14 #include "boost/polygon/segment_concept.hpp"
15 #include "boost/polygon/segment_data.hpp"
16 #include "boost/polygon/segment_traits.hpp"
17 using namespace boost::polygon;
18 
19 typedef boost::mpl::list<int> test_types;
20 
BOOST_AUTO_TEST_CASE_TEMPLATE(segment_data_test,T,test_types)21 BOOST_AUTO_TEST_CASE_TEMPLATE(segment_data_test, T, test_types) {
22   typedef point_data<T> point_type;
23   typedef segment_data<T> segment_type;
24   point_type point1(1, 2);
25   point_type point2(3, 4);
26   segment_type segment1(point1, point2);
27   segment_type segment2;
28   segment2 = segment1;
29 
30   BOOST_CHECK(segment1.low() == point1);
31   BOOST_CHECK(segment1.high() == point2);
32   BOOST_CHECK(segment1.get(LOW) == point1);
33   BOOST_CHECK(segment1.get(HIGH) == point2);
34   BOOST_CHECK(segment1 == segment2);
35   BOOST_CHECK(!(segment1 != segment2));
36   BOOST_CHECK(!(segment1 < segment2));
37   BOOST_CHECK(!(segment1 > segment1));
38   BOOST_CHECK(segment1 <= segment2);
39   BOOST_CHECK(segment1 >= segment2);
40 
41   segment1.low(point2);
42   segment1.high(point1);
43   BOOST_CHECK(segment1.low() == point2);
44   BOOST_CHECK(segment1.high() == point1);
45   BOOST_CHECK(!(segment1 == segment2));
46   BOOST_CHECK(segment1 != segment2);
47 
48   segment2.set(LOW, point2);
49   segment2.set(HIGH, point1);
50   BOOST_CHECK(segment1 == segment2);
51 }
52 
BOOST_AUTO_TEST_CASE_TEMPLATE(segment_traits_test,T,test_types)53 BOOST_AUTO_TEST_CASE_TEMPLATE(segment_traits_test, T, test_types) {
54   typedef point_data<T> point_type;
55   typedef segment_data<T> segment_type;
56 
57   point_type point1(1, 2);
58   point_type point2(3, 4);
59   segment_type segment =
60       segment_mutable_traits<segment_type>::construct(point1, point2);
61 
62   BOOST_CHECK(segment_traits<segment_type>::get(segment, LOW) == point1);
63   BOOST_CHECK(segment_traits<segment_type>::get(segment, HIGH) == point2);
64 
65   segment_mutable_traits<segment_type>::set(segment, LOW, point2);
66   segment_mutable_traits<segment_type>::set(segment, HIGH, point1);
67   BOOST_CHECK(segment_traits<segment_type>::get(segment, LOW) == point2);
68   BOOST_CHECK(segment_traits<segment_type>::get(segment, HIGH) == point1);
69 }
70 
71 template <typename T>
72 struct Segment {
73   typedef T coordinate_type;
74   typedef point_data<T> point_type;
75   point_type p0;
76   point_type p1;
77 };
78 
79 namespace boost {
80 namespace polygon {
81   template <typename T>
82   struct geometry_concept< Segment<T> > {
83     typedef segment_concept type;
84   };
85 
86   template <typename T>
87   struct segment_traits< Segment<T> > {
88     typedef T coordinate_type;
89     typedef point_data<T> point_type;
90 
getboost::polygon::segment_traits91     static point_type get(const Segment<T>& segment, direction_1d dir) {
92       return dir.to_int() ? segment.p1 : segment.p0;
93     }
94   };
95 
96   template <typename T>
97   struct segment_mutable_traits< Segment<T> > {
98     typedef T coordinate_type;
99     typedef point_data<T> point_type;
100 
setboost::polygon::segment_mutable_traits101     static void set(
102         Segment<T>& segment, direction_1d dir, const point_type& point) {
103       dir.to_int() ? segment.p1 = point : segment.p0 = point;;
104     }
105 
constructboost::polygon::segment_mutable_traits106     static Segment<T> construct(
107         const point_type& point1, const point_type& point2) {
108       Segment<T> segment;
109       segment.p0 = point1;
110       segment.p1 = point2;
111       return segment;
112     }
113   };
114 }
115 }
116 
BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test1,T,test_types)117 BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test1, T, test_types) {
118   typedef point_data<T> point_type;
119   typedef Segment<T> segment_type;
120 
121   point_type point1(1, 2);
122   point_type point2(3, 4);
123   point_type point3(2, 3);
124   segment_type segment1 = construct<segment_type>(point1, point2);
125   BOOST_CHECK(segment1.p0 == point1);
126   BOOST_CHECK(segment1.p1 == point2);
127   BOOST_CHECK(get(segment1, LOW) == point1);
128   BOOST_CHECK(low(segment1) == point1);
129   BOOST_CHECK(get(segment1, HIGH) == point2);
130   BOOST_CHECK(high(segment1) == point2);
131   BOOST_CHECK(center(segment1) == point3);
132 
133   set(segment1, LOW, point2);
134   set(segment1, HIGH, point1);
135   BOOST_CHECK(segment1.p0 == point2);
136   BOOST_CHECK(segment1.p1 == point1);
137   BOOST_CHECK(get(segment1, LOW) == point2);
138   BOOST_CHECK(get(segment1, HIGH) == point1);
139   low(segment1, point1);
140   high(segment1, point2);
141   BOOST_CHECK(segment1.p0 == point1);
142   BOOST_CHECK(segment1.p1 == point2);
143 
144   segment_data<T> segment2 = copy_construct< segment_data<T> >(segment1);
145   BOOST_CHECK(segment1.p0 == segment2.low());
146   BOOST_CHECK(segment1.p1 == segment2.high());
147   BOOST_CHECK(equivalence(segment1, segment2));
148 
149   segment_data<T> segment3 = construct< segment_data<T> >(point2, point1);
150   assign(segment1, segment3);
151   BOOST_CHECK(segment1.p0 == point2);
152   BOOST_CHECK(segment1.p1 == point1);
153   BOOST_CHECK(!equivalence(segment1, segment2));
154 }
155 
BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test2,T,test_types)156 BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test2, T, test_types) {
157   typedef point_data<T> point_type;
158   typedef Segment<T> segment_type;
159 
160   point_type point1(1, 2);
161   point_type point2(2, 4);
162   point_type point3(0, 0);
163   point_type point4(5, 10);
164   point_type point5(1, 3);
165   point_type point6(2, 3);
166   point_type point7(100, 201);
167   point_type point8(100, 200);
168   point_type point9(100, 199);
169   segment_type segment1 = construct<segment_type>(point1, point2);
170   segment_type segment2 = construct<segment_type>(point2, point1);
171   segment_type segment3 = construct<segment_type>(point1, point5);
172 
173   BOOST_CHECK(orientation(segment1, point1) == 0);
174   BOOST_CHECK(orientation(segment1, point2) == 0);
175   BOOST_CHECK(orientation(segment1, point3) == 0);
176   BOOST_CHECK(orientation(segment1, point4) == 0);
177   BOOST_CHECK(orientation(segment1, point5) == 1);
178   BOOST_CHECK(orientation(segment2, point5) == -1);
179   BOOST_CHECK(orientation(segment1, point6) == -1);
180   BOOST_CHECK(orientation(segment2, point6) == 1);
181   BOOST_CHECK(orientation(segment1, point7) == 1);
182   BOOST_CHECK(orientation(segment2, point7) == -1);
183   BOOST_CHECK(orientation(segment1, point8) == 0);
184   BOOST_CHECK(orientation(segment1, point9) == -1);
185   BOOST_CHECK(orientation(segment2, point9) == 1);
186   BOOST_CHECK(orientation(segment3, point6) == -1);
187   BOOST_CHECK(orientation(segment3, point3) == 1);
188 }
189 
BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test3,T,test_types)190 BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test3, T, test_types) {
191   typedef point_data<T> point_type;
192   typedef Segment<T> segment_type;
193 
194   segment_type segment1 = construct<segment_type>(
195       point_type(0, 0), point_type(1, 2));
196   segment_type segment2 = construct<segment_type>(
197       point_type(0, 0), point_type(2, 4));
198   segment_type segment3 = construct<segment_type>(
199       point_type(0, 0), point_type(2, 3));
200   segment_type segment4 = construct<segment_type>(
201       point_type(0, 0), point_type(2, 5));
202   segment_type segment5 = construct<segment_type>(
203       point_type(0, 2), point_type(2, 0));
204 
205   BOOST_CHECK(orientation(segment1, segment2) == 0);
206   BOOST_CHECK(orientation(segment1, segment3) == -1);
207   BOOST_CHECK(orientation(segment3, segment1) == 1);
208   BOOST_CHECK(orientation(segment1, segment4) == 1);
209   BOOST_CHECK(orientation(segment4, segment1) == -1);
210   BOOST_CHECK(orientation(segment1, segment5) == -1);
211   BOOST_CHECK(orientation(segment5, segment1) == 1);
212 }
213 
BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test4,T,test_types)214 BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test4, T, test_types) {
215   typedef point_data<T> point_type;
216   typedef Segment<T> segment_type;
217 
218   point_type point1(1, 2);
219   point_type point2(3, 6);
220   point_type point3(2, 4);
221   point_type point4(4, 8);
222   point_type point5(0, 0);
223   segment_type segment = construct<segment_type>(point1, point2);
224 
225   BOOST_CHECK(contains(segment, point1, true));
226   BOOST_CHECK(contains(segment, point2, true));
227   BOOST_CHECK(!contains(segment, point1, false));
228   BOOST_CHECK(!contains(segment, point2, false));
229   BOOST_CHECK(contains(segment, point3, false));
230   BOOST_CHECK(!contains(segment, point4, true));
231   BOOST_CHECK(!contains(segment, point5, true));
232 }
233 
BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test5,T,test_types)234 BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test5, T, test_types) {
235   typedef point_data<T> point_type;
236   typedef Segment<T> segment_type;
237 
238   point_type point1(0, 0);
239   point_type point2(10, 0);
240   point_type point3(5, 0);
241   point_type point4(-1, 0);
242   point_type point5(11, 0);
243   segment_type segment = construct<segment_type>(point1, point2);
244 
245   BOOST_CHECK(contains(segment, point1, true));
246   BOOST_CHECK(contains(segment, point2, true));
247   BOOST_CHECK(!contains(segment, point1, false));
248   BOOST_CHECK(!contains(segment, point2, false));
249   BOOST_CHECK(contains(segment, point3, false));
250   BOOST_CHECK(!contains(segment, point4, true));
251   BOOST_CHECK(!contains(segment, point5, true));
252 }
253 
BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test6,T,test_types)254 BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test6, T, test_types) {
255   typedef point_data<T> point_type;
256   typedef Segment<T> segment_type;
257 
258   point_type point1(0, 0);
259   point_type point2(1, 2);
260   point_type point3(2, 4);
261   point_type point4(3, 6);
262   point_type point5(4, 8);
263   point_type point6(5, 10);
264   segment_type segment1 = construct<segment_type>(point2, point5);
265   segment_type segment2 = construct<segment_type>(point3, point4);
266   segment_type segment3 = construct<segment_type>(point1, point3);
267   segment_type segment4 = construct<segment_type>(point4, point6);
268 
269   BOOST_CHECK(contains(segment1, segment2, false));
270   BOOST_CHECK(!contains(segment2, segment1, true));
271   BOOST_CHECK(!contains(segment1, segment3, true));
272   BOOST_CHECK(!contains(segment1, segment4, true));
273   BOOST_CHECK(contains(segment1, segment1, true));
274   BOOST_CHECK(!contains(segment1, segment1, false));
275 }
276 
277 template<typename T>
278 struct Transformer {
scaleTransformer279   void scale(T& x, T& y) const {
280     x *= 2;
281     y *= 2;
282   }
283 
transformTransformer284   void transform(T& x, T& y) const {
285     T tmp = x;
286     x = y;
287     y = tmp;
288   }
289 };
290 
BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test7,T,test_types)291 BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test7, T, test_types) {
292   typedef point_data<T> point_type;
293   typedef Segment<T> segment_type;
294 
295   point_type point1(1, 2);
296   point_type point2(4, 6);
297   segment_type segment1 = construct<segment_type>(point1, point2);
298 
299   scale_up(segment1, 3);
300   BOOST_CHECK(low(segment1) == point_type(3, 6));
301   BOOST_CHECK(high(segment1) == point_type(12, 18));
302 
303   scale_down(segment1, 3);
304   BOOST_CHECK(low(segment1) == point1);
305   BOOST_CHECK(high(segment1) == point2);
306   BOOST_CHECK(length(segment1) == 5);
307 
308   move(segment1, HORIZONTAL, 1);
309   move(segment1, VERTICAL, 2);
310   BOOST_CHECK(low(segment1) == point_type(2, 4));
311   BOOST_CHECK(high(segment1) == point_type(5, 8));
312   BOOST_CHECK(length(segment1) == 5);
313 
314   convolve(segment1, point_type(1, 2));
315   BOOST_CHECK(low(segment1) == point_type(3, 6));
316   BOOST_CHECK(high(segment1) == point_type(6, 10));
317 
318   deconvolve(segment1, point_type(2, 4));
319   BOOST_CHECK(low(segment1) == point1);
320   BOOST_CHECK(high(segment1) == point2);
321 
322   scale(segment1, Transformer<T>());
323   BOOST_CHECK(low(segment1) == point_type(2, 4));
324   BOOST_CHECK(high(segment1) == point_type(8, 12));
325   transform(segment1, Transformer<T>());
326   BOOST_CHECK(low(segment1) == point_type(4, 2));
327   BOOST_CHECK(high(segment1) == point_type(12, 8));
328 }
329 
BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test8,T,test_types)330 BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test8, T, test_types) {
331   typedef point_data<T> point_type;
332   typedef Segment<T> segment_type;
333 
334   segment_type segment1 = construct<segment_type>(
335       point_type(0, 0), point_type(1, 2));
336   segment_type segment2 = construct<segment_type>(
337       point_type(1, 2), point_type(2, 4));
338   segment_type segment3 = construct<segment_type>(
339       point_type(2, 4), point_type(0, 4));
340   segment_type segment4 = construct<segment_type>(
341       point_type(0, 4), point_type(0, 0));
342 
343   BOOST_CHECK(abuts(segment1, segment2, HIGH));
344   BOOST_CHECK(abuts(segment2, segment3, HIGH));
345   BOOST_CHECK(abuts(segment3, segment4, HIGH));
346   BOOST_CHECK(abuts(segment4, segment1, HIGH));
347 
348   BOOST_CHECK(!abuts(segment1, segment2, LOW));
349   BOOST_CHECK(!abuts(segment2, segment3, LOW));
350   BOOST_CHECK(!abuts(segment3, segment4, LOW));
351   BOOST_CHECK(!abuts(segment4, segment1, LOW));
352 
353   BOOST_CHECK(abuts(segment2, segment1));
354   BOOST_CHECK(abuts(segment3, segment2));
355   BOOST_CHECK(abuts(segment4, segment3));
356   BOOST_CHECK(abuts(segment1, segment4));
357 
358   BOOST_CHECK(!abuts(segment1, segment3));
359   BOOST_CHECK(!abuts(segment2, segment4));
360 }
361 
BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test9,T,test_types)362 BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test9, T, test_types) {
363   typedef point_data<T> point_type;
364   typedef Segment<T> segment_type;
365 
366   segment_type segment1 = construct<segment_type>(
367       point_type(0, 0), point_type(2, 2));
368   segment_type segment2 = construct<segment_type>(
369       point_type(1, 1), point_type(3, 3));
370   segment_type segment3 = construct<segment_type>(
371       point_type(2, 2), point_type(-1, -1));
372   segment_type segment4 = construct<segment_type>(
373       point_type(1, 3), point_type(3, 1));
374   segment_type segment5 = construct<segment_type>(
375       point_type(2, 2), point_type(1, 3));
376 
377   BOOST_CHECK(intersects(segment1, segment2, false));
378   BOOST_CHECK(intersects(segment1, segment2, true));
379   BOOST_CHECK(intersects(segment1, segment3, false));
380   BOOST_CHECK(intersects(segment1, segment3, true));
381   BOOST_CHECK(intersects(segment2, segment3, false));
382   BOOST_CHECK(intersects(segment2, segment3, true));
383   BOOST_CHECK(intersects(segment4, segment3, false));
384   BOOST_CHECK(intersects(segment4, segment3, true));
385   BOOST_CHECK(intersects(segment4, segment2, false));
386   BOOST_CHECK(intersects(segment4, segment2, true));
387   BOOST_CHECK(!intersects(segment3, segment5, false));
388   BOOST_CHECK(intersects(segment3, segment5, true));
389 }
390 
BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test10,T,test_types)391 BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test10, T, test_types) {
392   typedef point_data<T> point_type;
393   typedef Segment<T> segment_type;
394 
395   segment_type segment1 = construct<segment_type>(
396       point_type(0, 0), point_type(0, 2));
397   segment_type segment2 = construct<segment_type>(
398       point_type(0, 1), point_type(0, 3));
399   segment_type segment3 = construct<segment_type>(
400       point_type(0, 1), point_type(0, 2));
401   segment_type segment4 = construct<segment_type>(
402       point_type(0, 2), point_type(0, 3));
403   segment_type segment5 = construct<segment_type>(
404       point_type(0, 2), point_type(2, 2));
405   segment_type segment6 = construct<segment_type>(
406       point_type(0, 1), point_type(1, 1));
407 
408   BOOST_CHECK(intersects(segment1, segment1, false));
409   BOOST_CHECK(intersects(segment1, segment1, true));
410   BOOST_CHECK(intersects(segment1, segment2, false));
411   BOOST_CHECK(intersects(segment1, segment2, true));
412   BOOST_CHECK(intersects(segment1, segment3, false));
413   BOOST_CHECK(intersects(segment1, segment3, true));
414   BOOST_CHECK(intersects(segment2, segment3, false));
415   BOOST_CHECK(intersects(segment2, segment3, true));
416   BOOST_CHECK(!intersects(segment1, segment4, false));
417   BOOST_CHECK(intersects(segment1, segment4, true));
418   BOOST_CHECK(!intersects(segment1, segment5, false));
419   BOOST_CHECK(intersects(segment1, segment5, true));
420   BOOST_CHECK(intersects(segment1, segment6, false));
421   BOOST_CHECK(intersects(segment1, segment6, true));
422 }
423 
BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test11,T,test_types)424 BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test11, T, test_types) {
425   typedef point_data<T> point_type;
426   typedef Segment<T> segment_type;
427 
428   point_type point1(1, 2);
429   point_type point2(7, 10);
430   segment_type segment1 = construct<segment_type>(point1, point2);
431 
432   BOOST_CHECK(euclidean_distance(segment1, point1) == 0.0);
433   BOOST_CHECK(euclidean_distance(segment1, point2) == 0.0);
434   BOOST_CHECK(euclidean_distance(segment1, point_type(10, 14)) == 5.0);
435   BOOST_CHECK(euclidean_distance(segment1, point_type(-3, -1)) == 5.0);
436   BOOST_CHECK(euclidean_distance(segment1, point_type(0, 9)) == 5.0);
437   BOOST_CHECK(euclidean_distance(segment1, point_type(8, 3)) == 5.0);
438 }
439 
BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test12,T,test_types)440 BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test12, T, test_types) {
441   typedef point_data<T> point_type;
442   typedef Segment<T> segment_type;
443 
444   segment_type segment1 = construct<segment_type>(
445       point_type(0, 0), point_type(3, 4));
446   segment_type segment2 = construct<segment_type>(
447       point_type(2, 0), point_type(0, 2));
448   segment_type segment3 = construct<segment_type>(
449       point_type(1, -7), point_type(10, 5));
450   segment_type segment4 = construct<segment_type>(
451       point_type(7, 7), point_type(10, 11));
452 
453   BOOST_CHECK(euclidean_distance(segment1, segment2) == 0.0);
454   BOOST_CHECK(euclidean_distance(segment1, segment3) == 5.0);
455   BOOST_CHECK(euclidean_distance(segment1, segment4) == 5.0);
456 }
457