1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3 
4 // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
5 
6 // Copyright (c) 2014-2017, Oracle and/or its affiliates.
7 
8 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
9 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
10 
11 // Licensed under the Boost Software License version 1.0.
12 // http://www.boost.org/users/license.html
13 
14 
15 #ifndef BOOST_TEST_MODULE
16 #define BOOST_TEST_MODULE test_point_iterator
17 #endif
18 
19 #include <cstddef>
20 #include <iostream>
21 #include <string>
22 #include <iterator>
23 #include <algorithm>
24 
25 #include <boost/test/included/unit_test.hpp>
26 
27 #include <boost/concept_check.hpp>
28 #include <boost/core/ignore_unused.hpp>
29 #include <boost/iterator/iterator_concepts.hpp>
30 #include <boost/tuple/tuple.hpp>
31 #include <boost/type_traits/is_const.hpp>
32 #include <boost/optional.hpp>
33 #include <boost/type_traits/is_reference.hpp>
34 
35 #include <boost/geometry/core/point_type.hpp>
36 
37 #include <boost/geometry/geometries/geometries.hpp>
38 #include <boost/geometry/geometries/adapted/boost_tuple.hpp>
39 #include <boost/geometry/geometries/register/linestring.hpp>
40 #include <boost/geometry/geometries/register/multi_point.hpp>
41 
42 #include <boost/geometry/algorithms/equals.hpp>
43 #include <boost/geometry/algorithms/make.hpp>
44 #include <boost/geometry/algorithms/num_points.hpp>
45 
46 #include <boost/geometry/policies/compare.hpp>
47 
48 #include <boost/geometry/util/condition.hpp>
49 
50 #include <boost/geometry/io/wkt/wkt.hpp>
51 #include <boost/geometry/io/dsv/write.hpp>
52 
53 #include <boost/geometry/iterators/point_iterator.hpp>
54 #include <boost/geometry/iterators/point_reverse_iterator.hpp>
55 
56 #include <boost/geometry/strategies/strategies.hpp>
57 
58 #include <test_common/with_pointer.hpp>
59 #include <test_geometries/copy_on_dereference_geometries.hpp>
60 
61 // At the end because of conflicts with Boost.QVM
62 #include <boost/assign/list_of.hpp>
63 
64 
65 namespace bg = ::boost::geometry;
66 namespace ba = ::boost::assign;
67 
68 typedef bg::model::point<double, 2, bg::cs::cartesian> point_type;
69 typedef bg::model::point<double, 3, bg::cs::cartesian> point_type_3d;
70 typedef bg::model::linestring<point_type> linestring_type;
71 typedef bg::model::polygon<point_type, false, false> polygon_type; //ccw, open
72 
73 // multi geometries
74 typedef bg::model::multi_point<point_type> multi_point_type;
75 typedef bg::model::multi_point<point_type_3d> multi_point_type_3d;
76 typedef bg::model::multi_linestring<linestring_type> multi_linestring_type;
77 typedef bg::model::multi_polygon<polygon_type> multi_polygon_type;
78 
79 typedef boost::tuple<double, double> tuple_point_type;
80 typedef boost::tuple<double, double, double> tuple_point_type_3d;
81 typedef std::vector<tuple_point_type> tuple_multi_point_type;
82 typedef std::vector<tuple_point_type_3d> tuple_multi_point_type_3d;
83 
84 template <typename T>
85 struct vector_as_multipoint : std::vector<T> {};
86 
87 template <typename T>
88 struct vector_as_linestring : std::vector<T> {};
89 
90 BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
BOOST_GEOMETRY_REGISTER_MULTI_POINT(tuple_multi_point_type)91 BOOST_GEOMETRY_REGISTER_MULTI_POINT(tuple_multi_point_type)
92 BOOST_GEOMETRY_REGISTER_MULTI_POINT(tuple_multi_point_type_3d)
93 
94 BOOST_GEOMETRY_REGISTER_MULTI_POINT_TEMPLATED(vector_as_multipoint)
95 BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(vector_as_linestring)
96 
97 
98 
99 template <typename Geometry>
100 inline Geometry from_wkt(std::string const& wkt)
101 {
102     Geometry geometry;
103     boost::geometry::read_wkt(wkt, geometry);
104     return geometry;
105 }
106 
107 
108 // this function is implemented because std::max_element() requires ForwardIterator
109 // but bg::point_iterator<> is InputIterator since it returns non-true reference
110 template <typename InputIt, typename Pred>
111 inline boost::optional<typename std::iterator_traits<InputIt>::value_type>
max_value(InputIt first,InputIt last,Pred pred)112 max_value(InputIt first, InputIt last, Pred pred)
113 {
114     typedef typename std::iterator_traits<InputIt>::value_type value_type;
115     if (first != last)
116     {
117         value_type found = *first++;
118         for (; first != last; )
119         {
120             value_type current = *first++;
121             if (pred(current, found))
122                 found = current;
123         }
124         return found;
125     }
126     return boost::none;
127 }
128 
129 
130 template <typename Iterator>
print_point_range(std::ostream & os,Iterator first,Iterator beyond,std::string const & header)131 inline std::ostream& print_point_range(std::ostream& os,
132                                        Iterator first,
133                                        Iterator beyond,
134                                        std::string const& header)
135 {
136     os << header << "(";
137     for (Iterator it = first; it != beyond; ++it)
138     {
139         os << " " << bg::dsv(*it);
140     }
141     os << " )";
142     return os;
143 }
144 
145 
146 template
147 <
148     typename Geometry,
149     bool Enable = true,
150     bool IsConst = boost::is_const<Geometry>::value
151 >
152 struct test_iterator_concepts
153 {
154     typedef bg::point_iterator<Geometry> iterator;
155     BOOST_CONCEPT_ASSERT((boost::BidirectionalIteratorConcept<iterator>));
156     BOOST_CONCEPT_ASSERT((boost_concepts::ReadableIteratorConcept<iterator>));
157     BOOST_CONCEPT_ASSERT((boost_concepts::LvalueIteratorConcept<iterator>));
158     BOOST_CONCEPT_ASSERT
159         ((boost_concepts::BidirectionalTraversalConcept<iterator>));
160 };
161 
162 template <typename Geometry>
163 struct test_iterator_concepts<Geometry, true, false>
164     : test_iterator_concepts<Geometry, true, true>
165 {
166     typedef bg::point_iterator<Geometry> iterator;
167     BOOST_CONCEPT_ASSERT
168         ((boost::Mutable_BidirectionalIteratorConcept<iterator>));
169     BOOST_CONCEPT_ASSERT
170         ((boost_concepts::WritableIteratorConcept<iterator>));
171     BOOST_CONCEPT_ASSERT
172         ((boost_concepts::SwappableIteratorConcept<iterator>));
173 };
174 
175 template <typename Geometry, bool IsConst>
176 struct test_iterator_concepts<Geometry, false, IsConst>
177 {};
178 
179 
180 
181 struct equals
182 {
183     template <typename Iterator>
number_of_elementsequals184     static inline std::size_t number_of_elements(Iterator begin,
185                                                  Iterator end)
186     {
187         std::size_t size = std::distance(begin, end);
188 
189         std::size_t num_elems(0);
190         for (Iterator it = begin; it != end; ++it)
191         {
192             ++num_elems;
193         }
194         BOOST_CHECK(size == num_elems);
195 
196         num_elems = 0;
197         for (Iterator it = end; it != begin; --it)
198         {
199             ++num_elems;
200         }
201         BOOST_CHECK(size == num_elems);
202 
203         return num_elems;
204     }
205 
206     template <typename Iterator1, typename Iterator2>
applyequals207     static inline bool apply(Iterator1 begin1, Iterator1 end1,
208                              Iterator2 begin2, Iterator2 end2)
209     {
210         std::size_t num_points1 = number_of_elements(begin1, end1);
211         std::size_t num_points2 = number_of_elements(begin2, end2);
212 
213         if (num_points1 != num_points2)
214         {
215             return false;
216         }
217 
218         Iterator1 it1 = begin1;
219         Iterator2 it2 = begin2;
220         for (; it1 != end1; ++it1, ++it2)
221         {
222             if (! bg::equals(*it1, *it2))
223             {
224                 return false;
225             }
226         }
227         return true;
228     }
229 };
230 
231 
232 template <bool Enable = true>
233 struct test_assignment
234 {
235     template <typename Iterator, typename ConstIterator, typename Value>
applytest_assignment236     static inline void apply(Iterator it, ConstIterator cit,
237                              Value const& value1, Value const& value2)
238     {
239 #ifdef BOOST_GEOMETRY_TEST_DEBUG
240         std::cout << "== before assignment ==" << std::endl;
241         std::cout << "value1: " << bg::wkt(value1) << std::endl;
242         std::cout << "value2: " << bg::wkt(value2) << std::endl;
243         std::cout << "*it   : " << bg::wkt(*it) << std::endl;
244         std::cout << "*cit  : " << bg::wkt(*cit) << std::endl;
245 #endif
246 
247         BOOST_CHECK(bg::equals(*it, value1));
248         BOOST_CHECK(! bg::equals(*it, value2));
249         BOOST_CHECK(bg::equals(*cit, value1));
250         BOOST_CHECK(! bg::equals(*cit, value2));
251 
252         *it = value2;
253         BOOST_CHECK(bg::equals(*it, value2));
254         BOOST_CHECK(! bg::equals(*it, value1));
255         BOOST_CHECK(bg::equals(*cit, value2));
256         BOOST_CHECK(! bg::equals(*cit, value1));
257 
258 #ifdef BOOST_GEOMETRY_TEST_DEBUG
259         std::cout << "== after 1st assignment ==" << std::endl;
260         std::cout << "value1: " << bg::wkt(value1) << std::endl;
261         std::cout << "value2: " << bg::wkt(value2) << std::endl;
262         std::cout << "*it   : " << bg::wkt(*it) << std::endl;
263         std::cout << "*cit  : " << bg::wkt(*cit) << std::endl;
264 #endif
265 
266         *it = value1;
267         BOOST_CHECK(bg::equals(*it, value1));
268         BOOST_CHECK(! bg::equals(*it, value2));
269         BOOST_CHECK(bg::equals(*cit, value1));
270         BOOST_CHECK(! bg::equals(*cit, value2));
271 
272 #ifdef BOOST_GEOMETRY_TEST_DEBUG
273         std::cout << "== after 2nd assignment ==" << std::endl;
274         std::cout << "value1: " << bg::wkt(value1) << std::endl;
275         std::cout << "value2: " << bg::wkt(value2) << std::endl;
276         std::cout << "*it   : " << bg::wkt(*it) << std::endl;
277         std::cout << "*cit  : " << bg::wkt(*cit) << std::endl;
278         std::cout << std::endl;
279 #endif
280     }
281 };
282 
283 template <>
284 struct test_assignment<false>
285 {
286     template <typename Iterator, typename ConstIterator, typename Value>
applytest_assignment287     static inline void apply(Iterator, ConstIterator,
288                              Value const&, Value const&)
289     {
290     }
291 };
292 
293 
294 template
295 <
296     typename Geometry,
297     typename PointRange,
298     bool EnableConceptChecks = true
299 >
300 struct test_point_iterator_of_geometry
301 {
302     typedef typename bg::point_type<Geometry>::type point_type;
303 
304     template <typename G>
base_testtest_point_iterator_of_geometry305     static inline void base_test(G& geometry,
306                                  PointRange const& point_range,
307                                  std::string const& header)
308     {
309         typedef bg::point_iterator<G> point_iterator;
310 
311         test_iterator_concepts<G, EnableConceptChecks>();
312 
313         point_iterator begin = bg::points_begin(geometry);
314         point_iterator end = bg::points_end(geometry);
315 
316         BOOST_CHECK(std::size_t(std::distance(begin, end))
317                     ==
318                     bg::num_points(geometry));
319 
320         BOOST_CHECK(equals::apply(begin, end,
321                                   bg::points_begin(point_range),
322                                   bg::points_end(point_range))
323                     );
324 
325         boost::ignore_unused(header);
326 
327 #ifdef BOOST_GEOMETRY_TEST_DEBUG
328         std::cout << header << " geometry: " << bg::wkt(geometry) << std::endl;
329         print_point_range(std::cout, begin, end, "point range: ");
330         std::cout << std::endl;
331 
332         typedef bg::point_iterator<PointRange const> point_range_iterator;
333 
334         print_point_range(std::cout,
335                           bg::points_begin(point_range),
336                           bg::points_end(point_range),
337                           "expected point range: ");
338         std::cout << std::endl;
339 #endif
340     }
341 
342     template <typename G, bool Enable>
343     struct test_reverse
344     {
345         template <typename Iterator>
applytest_point_iterator_of_geometry::test_reverse346         static inline void apply(Iterator first, Iterator last,
347                                  G const& geometry)
348         {
349             boost::ignore_unused(geometry);
350 
351             std::reverse(first, last);
352 #ifdef BOOST_GEOMETRY_TEST_DEBUG
353             print_point_range(std::cout, first, last, "reversed:\n")
354                 << std::endl;
355             std::cout << bg::wkt(geometry) << std::endl;
356             std::cout << std::endl;
357 #endif
358 
359             std::reverse(first, last);
360 #ifdef BOOST_GEOMETRY_TEST_DEBUG
361             print_point_range(std::cout, first, last, "re-reversed:\n")
362                 << std::endl;
363             std::cout << bg::wkt(geometry) << std::endl;
364             std::cout << std::endl;
365             std::cout << std::endl;
366 #endif
367         }
368     };
369 
370     template <typename G>
371     struct test_reverse<G, false>
372     {
373         template <typename Iterator>
applytest_point_iterator_of_geometry::test_reverse374         static inline void apply(Iterator, Iterator, G const&)
375         {
376         }
377     };
378 
applytest_point_iterator_of_geometry379     static inline void apply(Geometry geometry,
380                              PointRange const& point_range,
381                              point_type const& zero_point)
382     {
383         base_test<Geometry>(geometry, point_range, "non-const");
384 
385 #ifdef BOOST_GEOMETRY_TEST_DEBUG
386         std::cout << std::endl;
387 #endif
388 
389         base_test<Geometry const>(geometry, point_range, "const");
390 
391 #ifdef BOOST_GEOMETRY_TEST_DEBUG
392         std::cout << std::endl << std::endl;
393 #endif
394 
395         // testing construction of const and non-const iterator
396         typedef bg::point_iterator<Geometry> point_iterator;
397         typedef bg::point_iterator<Geometry const> const_point_iterator;
398 
399         point_iterator begin = bg::points_begin(geometry);
400         point_iterator end = bg::points_end(geometry);
401 
402         const_point_iterator const_begin = bg::points_begin(geometry);
403         const_point_iterator const_end = bg::points_end(geometry);
404 
405         // same for reverse iterator
406         typedef bg::point_reverse_iterator<Geometry> point_reverse_iterator;
407         typedef bg::point_reverse_iterator
408             <
409                 Geometry const
410             > const_point_reverse_iterator;
411 
412         point_reverse_iterator rbegin = bg::points_rbegin(geometry);
413         point_reverse_iterator rend = bg::points_rend(geometry);
414 
415         const_point_reverse_iterator const_rbegin = bg::points_rbegin(geometry);
416         const_point_reverse_iterator const_rend = bg::points_rend(geometry);
417 
418         // testing assignment of non-const to const iterator
419         const_begin = begin;
420         const_end = end;
421 
422         // testing assignment of non-const to const reverse_iterator
423         const_rbegin = rbegin;
424         const_rend = rend;
425 
426         // testing equality/inequality comparison
427         BOOST_CHECK(begin == const_begin);
428         BOOST_CHECK(end == const_end);
429         if (begin != end)
430         {
431             BOOST_CHECK(begin != const_end);
432             BOOST_CHECK(const_begin != end);
433         }
434 
435         // testing equality/inequality comparison for reverse_iterator
436         BOOST_CHECK(rbegin == const_rbegin);
437         BOOST_CHECK(rend == const_rend);
438         if (rbegin != rend)
439         {
440             BOOST_CHECK(rbegin != const_rend);
441             BOOST_CHECK(const_rbegin != rend);
442         }
443 
444         if (begin != end)
445         {
446             BOOST_CHECK(rbegin != rend);
447 
448             point_reverse_iterator rlast(rend);
449             --rlast;
450             BOOST_CHECK(bg::equals(*begin, *rlast));
451 
452             point_iterator last(end);
453             --last;
454             BOOST_CHECK(bg::equals(*rbegin, *last));
455         }
456 
457         // testing dereferencing/assignment
458 
459         bool const is_reference = boost::is_reference
460             <
461                 typename std::iterator_traits<point_iterator>::reference
462             >::value;
463 
464         if (begin != end)
465         {
466             if (BOOST_GEOMETRY_CONDITION(is_reference))
467             {
468                 point_type p = *begin;
469                 point_type q = zero_point;
470 
471                 test_assignment<is_reference>::apply(begin, const_begin, p, q);
472 
473                 *begin = q;
474                 test_assignment<is_reference>::apply(begin, const_begin, q, p);
475 
476                 *begin = p;
477             }
478         }
479 
480         // test with algorithms
481 #ifdef BOOST_GEOMETRY_TEST_DEBUG
482         print_point_range(std::cout, begin, end, "original:\n") << std::endl;
483         print_point_range(std::cout, rbegin, rend, "reverse traversal:\n")
484             << std::endl;
485         std::cout << bg::wkt(geometry) << std::endl;
486         std::cout << std::endl;
487 #endif
488         test_reverse<Geometry, is_reference>::apply(begin, end, geometry);
489 
490         typedef typename std::iterator_traits
491             <
492                 point_iterator
493             >::value_type point;
494         if (const_begin != const_end)
495         {
496             boost::optional<point>
497                 pt_max = max_value(const_begin, const_end, bg::less<point>());
498 
499             BOOST_CHECK(bool(pt_max)); // to avoid warnings
500 #ifdef BOOST_GEOMETRY_TEST_DEBUG
501             std::cout << "max point: " << bg::dsv(*pt_max) << std::endl;
502 #endif
503         }
504 #ifdef BOOST_GEOMETRY_TEST_DEBUG
505         std::cout << std::endl;
506         std::cout << std::endl;
507         std::cout << std::endl;
508 #endif
509     }
510 
applytest_point_iterator_of_geometry511     static inline void apply(Geometry geometry, PointRange const& point_range)
512     {
513         apply(geometry, point_range, bg::make_zero<point_type>());
514     }
515 };
516 
517 
518 //======================================================================
519 //======================================================================
520 
521 
BOOST_AUTO_TEST_CASE(test_linestring_point_iterator)522 BOOST_AUTO_TEST_CASE( test_linestring_point_iterator )
523 {
524 #ifdef BOOST_GEOMETRY_TEST_DEBUG
525     std::cout << "*** LINESTRING ***" << std::endl;
526 #endif
527 
528     typedef tuple_multi_point_type TMP;
529     typedef linestring_type L;
530 
531     typedef test_point_iterator_of_geometry<L, TMP> tester;
532 
533     tester::apply(from_wkt<L>("LINESTRING()"),
534                   TMP()
535                   );
536 
537     tester::apply(from_wkt<L>("LINESTRING(3 3,4 4,5 5)"),
538                   ba::tuple_list_of(3,3)(4,4)(5,5)
539                   );
540 
541 #ifdef BOOST_GEOMETRY_TEST_DEBUG
542     std::cout << std::endl << std::endl << std::endl;
543 #endif
544 }
545 
546 
547 //======================================================================
548 //======================================================================
549 
550 
BOOST_AUTO_TEST_CASE(test_polygon_point_iterator)551 BOOST_AUTO_TEST_CASE( test_polygon_point_iterator )
552 {
553 #ifdef BOOST_GEOMETRY_TEST_DEBUG
554     std::cout << "*** POLYGON ***" << std::endl;
555 #endif
556 
557     typedef tuple_multi_point_type TMP;
558     typedef polygon_type P;
559 
560     typedef test_point_iterator_of_geometry<P, TMP> tester;
561 
562     tester::apply(from_wkt<P>("POLYGON()"),
563                   TMP()
564                   );
565 
566     tester::apply(from_wkt<P>("POLYGON(())"),
567                   TMP()
568                   );
569 
570     tester::apply(from_wkt<P>("POLYGON((1 1,9 1,9 9,1 9),(5 5,6 5,6 6,5 6))"),
571                   ba::tuple_list_of(1,1)(9,1)(9,9)(1,9)(5,5)(6,5)(6,6)(5,6)
572                   );
573 
574     tester::apply(from_wkt<P>("POLYGON((3 3,4 4,5 5),(),(),(),(6 6,7 7,8 8),(),(),(9 9),())"),
575                   ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)
576                   );
577 
578     tester::apply(from_wkt<P>("POLYGON((),(3 3,4 4,5 5),(),(),(6 6,7 7,8 8),(),(),(9 9),())"),
579                   ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)
580                   );
581 
582 #ifdef BOOST_GEOMETRY_TEST_DEBUG
583     std::cout << std::endl << std::endl;
584 #endif
585 }
586 
587 
588 //======================================================================
589 //======================================================================
590 
591 
BOOST_AUTO_TEST_CASE(test_multipoint_point_iterator)592 BOOST_AUTO_TEST_CASE( test_multipoint_point_iterator )
593 {
594 #ifdef BOOST_GEOMETRY_TEST_DEBUG
595     std::cout << "*** MULTIPOINT ***" << std::endl;
596 #endif
597 
598     typedef tuple_multi_point_type TMP;
599     typedef multi_point_type MP;
600 
601     typedef test_point_iterator_of_geometry<MP, TMP> tester;
602 
603     tester::apply(from_wkt<MP>("MULTIPOINT()"),
604                   TMP()
605                   );
606 
607     tester::apply(from_wkt<MP>("MULTIPOINT(3 3,4 4,5 5)"),
608                   ba::tuple_list_of(3,3)(4,4)(5,5)
609                   );
610 
611 #ifdef BOOST_GEOMETRY_TEST_DEBUG
612     std::cout << std::endl << std::endl << std::endl;
613 #endif
614 }
615 
616 
617 //======================================================================
618 //======================================================================
619 
620 
BOOST_AUTO_TEST_CASE(test_multipoint_3d_point_iterator)621 BOOST_AUTO_TEST_CASE( test_multipoint_3d_point_iterator )
622 {
623 #ifdef BOOST_GEOMETRY_TEST_DEBUG
624     std::cout << "*** MULTIPOINT 3D ***" << std::endl;
625 #endif
626 
627     typedef tuple_multi_point_type_3d TMP;
628     typedef multi_point_type_3d MP;
629 
630     typedef test_point_iterator_of_geometry<MP, TMP> tester;
631 
632     tester::apply(from_wkt<MP>("MULTIPOINT()"),
633                   TMP()
634                   );
635 
636     tester::apply(from_wkt<MP>("MULTIPOINT(3 3 3,4 4 4,5 5 5)"),
637                   ba::tuple_list_of(3,3,3)(4,4,4)(5,5,5)
638                   );
639 
640 #ifdef BOOST_GEOMETRY_TEST_DEBUG
641     std::cout << std::endl << std::endl << std::endl;
642 #endif
643 }
644 
645 
646 //======================================================================
647 //======================================================================
648 
649 
BOOST_AUTO_TEST_CASE(test_multilinestring_point_iterator)650 BOOST_AUTO_TEST_CASE( test_multilinestring_point_iterator )
651 {
652 #ifdef BOOST_GEOMETRY_TEST_DEBUG
653     std::cout << "*** MULTILINESTRING ***" << std::endl;
654 #endif
655 
656     typedef tuple_multi_point_type TMP;
657     typedef multi_linestring_type ML;
658 
659     typedef test_point_iterator_of_geometry<ML, TMP> tester;
660 
661     tester::apply(from_wkt<ML>("MULTILINESTRING()"),
662                   TMP()
663                   );
664 
665     tester::apply(from_wkt<ML>("MULTILINESTRING(())"),
666                   TMP()
667                   );
668 
669     tester::apply(from_wkt<ML>("MULTILINESTRING((),(),())"),
670                   TMP()
671                   );
672 
673     tester::apply(from_wkt<ML>("MULTILINESTRING((1 1,2 2,3 3),(3 3,4 4,5 5),(6 6))"),
674                   ba::tuple_list_of(1,1)(2,2)(3,3)(3,3)(4,4)(5,5)(6,6)
675                   );
676 
677     tester::apply(from_wkt<ML>("MULTILINESTRING((),(),(1 1,2 2,3 3),(),(),(3 3,4 4,5 5),(),(6 6),(),(),())"),
678                   ba::tuple_list_of(1,1)(2,2)(3,3)(3,3)(4,4)(5,5)(6,6)
679                   );
680 
681 #ifdef BOOST_GEOMETRY_TEST_DEBUG
682     std::cout << std::endl << std::endl;
683 #endif
684 }
685 
686 
687 //======================================================================
688 //======================================================================
689 
690 
BOOST_AUTO_TEST_CASE(test_multipolygon_point_iterator)691 BOOST_AUTO_TEST_CASE( test_multipolygon_point_iterator )
692 {
693 #ifdef BOOST_GEOMETRY_TEST_DEBUG
694     std::cout << "*** MULTIPOLYGON ***" << std::endl;
695 #endif
696 
697     typedef tuple_multi_point_type TMP;
698     typedef multi_polygon_type MPL;
699 
700     typedef test_point_iterator_of_geometry<MPL, TMP> tester;
701 
702     tester::apply(from_wkt<MPL>("MULTIPOLYGON()"),
703                   TMP()
704                   );
705 
706     tester::apply(from_wkt<MPL>("MULTIPOLYGON( () )"),
707                   TMP()
708                   );
709 
710     tester::apply(from_wkt<MPL>("MULTIPOLYGON( (()) )"),
711                   TMP()
712                   );
713 
714     tester::apply(from_wkt<MPL>("MULTIPOLYGON( ((),()) )"),
715                   TMP()
716                   );
717 
718     tester::apply(from_wkt<MPL>("MULTIPOLYGON(((3 3,4 4,5 5),(6 6,7 7,8 8),(9 9)),((1 1,2 2,10 10),(11 11,12 12)))"),
719                   ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)\
720                   (1,1)(2,2)(10,10)(11,11)(12,12)
721                   );
722 
723     tester::apply(from_wkt<MPL>("MULTIPOLYGON(((3 3,4 4,5 5),(),(),(),(6 6,7 7,8 8),(),(),(9 9),()),((),(1 1,2 2,10 10),(),(),(),(11 11,12 12),(),(),(13 13),()))"),
724                   ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)\
725                   (1,1)(2,2)(10,10)(11,11)(12,12)(13,13)
726                   );
727 
728     tester::apply(from_wkt<MPL>("MULTIPOLYGON(((3 3,4 4,5 5),(),(),(),(6 6,7 7,8 8),(),(),(9 9),()),((),(1 1,2 2,10 10),(),(),(),(11 11,12 12),(),(),(13 13),()),((),(),()))"),
729                   ba::tuple_list_of(3,3)(4,4)(5,5)(6,6)(7,7)(8,8)(9,9)\
730                   (1,1)(2,2)(10,10)(11,11)(12,12)(13,13)
731                   );
732 
733 #ifdef BOOST_GEOMETRY_TEST_DEBUG
734     std::cout << std::endl << std::endl;
735 #endif
736 }
737 
738 
739 //======================================================================
740 //======================================================================
741 
742 
BOOST_AUTO_TEST_CASE(test_multipoint_of_point_pointers)743 BOOST_AUTO_TEST_CASE( test_multipoint_of_point_pointers )
744 {
745 #ifdef BOOST_GEOMETRY_TEST_DEBUG
746     std::cout << "*** MULTIPOINT OF POINT POINTERS ***" << std::endl;
747 #endif
748 
749     typedef tuple_multi_point_type TMP;
750     typedef vector_as_multipoint<test::test_point_xy*> MP;
751 
752     MP multipoint;
753     for (int i = 1; i < 10; i++)
754     {
755         test::test_point_xy* p = new test::test_point_xy;
756         p->x = i;
757         p->y = -i;
758         multipoint.push_back(p);
759     }
760 
761     test::test_point_xy* zero = new test::test_point_xy;
762     zero->x = 0;
763     zero->y = 0;
764 
765     typedef test_point_iterator_of_geometry<MP, TMP> tester;
766 
767     tester::apply(multipoint,
768                   ba::tuple_list_of(1,-1)(2,-2)(3,-3)(4,-4)(5,-5)(6,-6)\
769                   (7,-7)(8,-8)(9,-9),
770                   zero
771                   );
772 
773     for (unsigned int i = 0; i < multipoint.size(); i++)
774     {
775         delete multipoint[i];
776     }
777     delete zero;
778 }
779 
780 
781 //======================================================================
782 //======================================================================
783 
784 
BOOST_AUTO_TEST_CASE(test_linestring_of_point_pointers)785 BOOST_AUTO_TEST_CASE( test_linestring_of_point_pointers )
786 {
787 #ifdef BOOST_GEOMETRY_TEST_DEBUG
788     std::cout << "*** LINESTRING OF POINT POINTERS ***" << std::endl;
789 #endif
790 
791     typedef tuple_multi_point_type TMP;
792     typedef vector_as_linestring<test::test_point_xy*> L;
793 
794     L linestring;
795     for (int i = 1; i < 10; i++)
796     {
797         test::test_point_xy* p = new test::test_point_xy;
798         p->x = i;
799         p->y = -i;
800         linestring.push_back(p);
801     }
802 
803     test::test_point_xy* zero = new test::test_point_xy;
804     zero->x = 0;
805     zero->y = 0;
806 
807     typedef test_point_iterator_of_geometry<L, TMP> tester;
808 
809     tester::apply(linestring,
810                   ba::tuple_list_of(1,-1)(2,-2)(3,-3)(4,-4)(5,-5)(6,-6)\
811                   (7,-7)(8,-8)(9,-9),
812                   zero
813                   );
814 
815     for (unsigned int i = 0; i < linestring.size(); i++)
816     {
817         delete linestring[i];
818     }
819     delete zero;
820 }
821 
822 
823 //======================================================================
824 //======================================================================
825 
826 
BOOST_AUTO_TEST_CASE(test_multipoint_copy_on_dereference)827 BOOST_AUTO_TEST_CASE( test_multipoint_copy_on_dereference )
828 {
829 #ifdef BOOST_GEOMETRY_TEST_DEBUG
830     std::cout << "*** MULTIPOINT WITH COPY-ON-DEREFERENCE ITERATOR ***"
831               << std::endl;
832 #endif
833 
834     typedef tuple_multi_point_type TMP;
835     typedef multipoint_copy_on_dereference<point_type> MP;
836 
837     typedef test_point_iterator_of_geometry
838         <
839             MP, TMP, false // no concept checks
840         > tester;
841 
842     // bg::read_wkt does not work for this multipoint type so we have
843     // to initialize the multipoint manually
844     MP multipoint;
845     for (int i = 1; i < 10; ++i)
846     {
847         multipoint.push_back(point_type(i, -i));
848     }
849 
850     tester::apply(multipoint,
851                   // from_wkt<MP>("MULTIPOINT(1 -1,2 -2,3 -3,4 -4,5 -5,6 -6, 7 -7,8 -8,9 -9)"),
852                   ba::tuple_list_of(1,-1)(2,-2)(3,-3)(4,-4)(5,-5)(6,-6)\
853                   (7,-7)(8,-8)(9,-9)
854                   );
855 }
856 
857 
858 //======================================================================
859 //======================================================================
860 
861 
BOOST_AUTO_TEST_CASE(test_linestring_copy_on_dereference)862 BOOST_AUTO_TEST_CASE( test_linestring_copy_on_dereference )
863 {
864 #ifdef BOOST_GEOMETRY_TEST_DEBUG
865     std::cout << "*** LINESTRING WITH COPY-ON-DEREFERENCE ITERATOR ***"
866               << std::endl;
867 #endif
868 
869     typedef tuple_multi_point_type TMP;
870     typedef linestring_copy_on_dereference<point_type> L;
871 
872     typedef test_point_iterator_of_geometry
873         <
874             L, TMP, false // no concept checks
875         > tester;
876 
877     tester::apply(from_wkt<L>("LINESTRING(1 -1,2 -2,3 -3,4 -4,5 -5,6 -6, 7 -7,8 -8,9 -9)"),
878                   ba::tuple_list_of(1,-1)(2,-2)(3,-3)(4,-4)(5,-5)(6,-6)\
879                   (7,-7)(8,-8)(9,-9)
880                   );
881 }
882