• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, Oracle and/or its affiliates.
7 
8 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
9 
10 // Licensed under the Boost Software License version 1.0.
11 // http://www.boost.org/users/license.html
12 
13 
14 #ifndef BOOST_TEST_MODULE
15 #define BOOST_TEST_MODULE test_segment_iterator
16 #endif
17 
18 #include <algorithm>
19 #include <iostream>
20 #include <iterator>
21 #include <string>
22 #include <vector>
23 
24 #include <boost/test/included/unit_test.hpp>
25 
26 #include <boost/assign/list_of.hpp>
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 
32 #include <boost/geometry/geometries/geometries.hpp>
33 #include <boost/geometry/geometries/adapted/boost_tuple.hpp>
34 #include <boost/geometry/geometries/register/linestring.hpp>
35 #include <boost/geometry/geometries/register/multi_linestring.hpp>
36 
37 #include <boost/geometry/io/wkt/wkt.hpp>
38 #include <boost/geometry/io/dsv/write.hpp>
39 
40 #include <boost/geometry/core/closure.hpp>
41 
42 #include <boost/geometry/algorithms/convert.hpp>
43 #include <boost/geometry/algorithms/equals.hpp>
44 #include <boost/geometry/algorithms/num_segments.hpp>
45 
46 #include <boost/geometry/policies/compare.hpp>
47 
48 #include <boost/geometry/iterators/segment_iterator.hpp>
49 
50 #include <test_common/with_pointer.hpp>
51 #include <test_geometries/copy_on_dereference_geometries.hpp>
52 
53 namespace ba = ::boost::assign;
54 namespace bg = ::boost::geometry;
55 namespace bgm = bg::model;
56 
57 typedef bgm::point<double, 2, bg::cs::cartesian> point_type;
58 typedef bgm::linestring<point_type> linestring_type;
59 typedef bgm::ring<point_type, true, true> ring_cw_closed_type;
60 typedef bgm::ring<point_type, true, false> ring_cw_open_type;
61 typedef bgm::polygon<point_type, true, true> polygon_cw_closed_type;
62 typedef bgm::polygon<point_type, true, false> polygon_cw_open_type;
63 
64 // multi-geometries
65 typedef bgm::multi_linestring<linestring_type> multi_linestring_type;
66 typedef bgm::multi_polygon<polygon_cw_closed_type> multi_polygon_cw_closed_type;
67 typedef bgm::multi_polygon<polygon_cw_open_type> multi_polygon_cw_open_type;
68 
69 // tuple-based geometries
70 typedef boost::tuple<double, double> tuple_point_type;
71 typedef std::vector<tuple_point_type> tuple_linestring_type;
72 typedef std::vector<tuple_linestring_type> tuple_multi_linestring_type;
73 
74 BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
BOOST_GEOMETRY_REGISTER_LINESTRING(tuple_linestring_type)75 BOOST_GEOMETRY_REGISTER_LINESTRING(tuple_linestring_type)
76 BOOST_GEOMETRY_REGISTER_MULTI_LINESTRING(tuple_multi_linestring_type)
77 
78 BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(std::vector)
79 
80 
81 template <typename Geometry>
82 inline Geometry from_wkt(std::string const& wkt)
83 {
84     Geometry geometry;
85     boost::geometry::read_wkt(wkt, geometry);
86     return geometry;
87 }
88 
89 template <typename Iterator>
print_geometry_range(std::ostream & os,Iterator first,Iterator beyond,std::string const & header)90 inline std::ostream& print_geometry_range(std::ostream& os,
91                                           Iterator first,
92                                           Iterator beyond,
93                                           std::string const& header)
94 {
95     os << header << "(";
96     for (Iterator it = first; it != beyond; ++it)
97     {
98         os << " " << bg::dsv(*it);
99     }
100     os << " )";
101     return os;
102 }
103 
104 template <typename Geometry>
105 struct test_iterator_concepts
106 {
107     typedef bg::segment_iterator<Geometry> iterator;
108     BOOST_CONCEPT_ASSERT(( boost::BidirectionalIteratorConcept<iterator> ));
109     BOOST_CONCEPT_ASSERT(( boost_concepts::ReadableIteratorConcept<iterator> ));
110     BOOST_CONCEPT_ASSERT
111         (( boost_concepts::BidirectionalTraversalConcept<iterator> ));
112 };
113 
114 struct equals
115 {
116     template <typename Iterator>
number_of_elementsequals117     static inline std::size_t number_of_elements(Iterator begin,
118                                                  Iterator end)
119     {
120         std::size_t size = std::distance(begin, end);
121 
122         std::size_t num_elems(0);
123         for (Iterator it = begin; it != end; ++it)
124         {
125             ++num_elems;
126         }
127         BOOST_CHECK(size == num_elems);
128 
129         num_elems = 0;
130         for (Iterator it = end; it != begin; --it)
131         {
132             ++num_elems;
133         }
134         BOOST_CHECK(size == num_elems);
135 
136         return num_elems;
137     }
138 
139     template <typename Iterator1, typename Iterator2>
applyequals140     static inline bool apply(Iterator1 begin1, Iterator1 end1,
141                              Iterator2 begin2, Iterator2 end2)
142     {
143         std::size_t num_points1 = number_of_elements(begin1, end1);
144         std::size_t num_points2 = number_of_elements(begin2, end2);
145 
146         if (num_points1 != num_points2)
147         {
148             return false;
149         }
150 
151         Iterator1 it1 = begin1;
152         Iterator2 it2 = begin2;
153         for (; it1 != end1; ++it1, ++it2)
154         {
155             if (! bg::equals(*it1, *it2))
156             {
157                 return false;
158             }
159         }
160         return true;
161     }
162 };
163 
164 
165 template <typename Geometry, typename SegmentRange>
166 struct test_segment_iterator_of_geometry
167 {
168     template <typename G>
base_testtest_segment_iterator_of_geometry169     static inline void base_test(G const& geometry,
170                                  SegmentRange const& segment_range,
171                                  std::string const& header,
172                                  bool check_num_segments)
173     {
174         boost::ignore_unused(header);
175 
176         typedef bg::segment_iterator<G const> segment_iterator;
177 
178         test_iterator_concepts<G const>();
179 
180         segment_iterator begin = bg::segments_begin(geometry);
181         segment_iterator end = bg::segments_end(geometry);
182 
183         if (check_num_segments)
184         {
185             BOOST_CHECK(std::size_t(std::distance(begin, end))
186                         ==
187                         bg::num_segments(geometry));
188         }
189 
190         BOOST_CHECK(equals::apply(begin, end,
191                                   bg::segments_begin(segment_range),
192                                   bg::segments_end(segment_range))
193                     );
194 
195 #ifdef BOOST_GEOMETRY_TEST_DEBUG
196         std::string closure
197             = (
198                (bg::closure<Geometry>::value == bg::closed)
199                ? "closed"
200                : "open"
201                );
202 
203         std::cout << header << " geometry (WKT): "
204                   << bg::wkt(geometry) << std::endl;
205         std::cout << header << " geometry (DSV): "
206                   << bg::dsv(geometry) << std::endl;
207         std::cout << "geometry's closure: " << closure << std::endl;
208         print_geometry_range(std::cout, begin, end, "segment range: ");
209 
210         std::cout << std::endl;
211 
212         print_geometry_range(std::cout,
213                              bg::segments_begin(segment_range),
214                              bg::segments_end(segment_range),
215                              "expected segment range: ");
216         std::cout << std::endl;
217 #endif
218 
219         // testing dereferencing
220         typedef typename std::iterator_traits
221             <
222                 segment_iterator
223             >::value_type value_type;
224 
225         if (bg::segments_begin(geometry) != bg::segments_end(geometry))
226         {
227             value_type first_segment = *bg::segments_begin(geometry);
228 
229             boost::ignore_unused(first_segment);
230 
231 #ifdef BOOST_GEOMETRY_TEST_DEBUG
232             typedef bg::model::segment
233                 <
234                     bg::model::point<double, 2, bg::cs::cartesian>
235                 > other_segment;
236             other_segment other_seg;
237             // convert is used as a workaround for geometries whose
238             // point is a pointer. WKT does not seem to work for
239             // segment iterators created this way.
240             bg::convert(first_segment, other_seg);
241             std::cout << "first segment in geometry: "
242                       << bg::wkt(other_seg)
243                       << std::endl;
244             std::cout << "first segment in geometry (DSV): "
245                       << bg::dsv(first_segment)
246                       << std::endl;
247 
248             std::cout << std::endl << std::endl;
249 #endif
250         }
251 
252         // test copying all segments to a vector
253         std::vector<value_type> segments;
254         std::copy(bg::segments_begin(geometry),
255                   bg::segments_end(geometry),
256                   std::back_inserter(segments));
257 
258         BOOST_CHECK(std::size_t( std::distance(bg::segments_begin(geometry),
259                                                bg::segments_end(geometry)) )
260                     ==
261                     segments.size());
262     }
263 
applytest_segment_iterator_of_geometry264     static inline void apply(Geometry geometry,
265                              SegmentRange const& segment_range,
266                              bool check_num_segments = true)
267     {
268         base_test<Geometry>(geometry, segment_range, "const",
269                             check_num_segments);
270     }
271 };
272 
273 //======================================================================
274 //======================================================================
275 
276 template <typename ClosedGeometry, typename ExpectedResult>
277 struct dual_tester
278 {
279     template <typename OpenGeometry>
applydual_tester280     static inline void apply(OpenGeometry const& open_g,
281                              ExpectedResult expected,
282                              bool check_num_segments = true)
283     {
284         typedef test_segment_iterator_of_geometry
285             <
286                 OpenGeometry, ExpectedResult
287             > otester;
288 
289         typedef test_segment_iterator_of_geometry
290             <
291                 ClosedGeometry, ExpectedResult
292             > ctester;
293 
294         otester::apply(open_g, expected, check_num_segments);
295 
296 #ifdef BOOST_GEOMETRY_TEST_DEBUG
297         std::cout << std::endl << std::endl;
298 #endif
299 
300         ClosedGeometry closed_g;
301 
302         bg::convert(open_g, closed_g);
303 
304         ctester::apply(closed_g, expected, check_num_segments);
305     }
306 };
307 
308 //======================================================================
309 //======================================================================
310 
BOOST_AUTO_TEST_CASE(test_linestring_segment_iterator)311 BOOST_AUTO_TEST_CASE( test_linestring_segment_iterator )
312 {
313 #ifdef BOOST_GEOMETRY_TEST_DEBUG
314     std::cout << "*** LINESTRING ***" << std::endl;
315 #endif
316 
317     typedef tuple_multi_linestring_type TML;
318     typedef linestring_type G;
319 
320     typedef test_segment_iterator_of_geometry<G, TML> tester;
321 
322     tester::apply(from_wkt<G>("LINESTRING(0 0,1 1,2 2,3 3,4 4)"),
323                   ba::list_of<tuple_linestring_type>
324                   ( ba::tuple_list_of(0,0)(1,1) )
325                   ( ba::tuple_list_of(1,1)(2,2) )
326                   ( ba::tuple_list_of(2,2)(3,3) )
327                   ( ba::tuple_list_of(3,3)(4,4) )
328                   );
329 
330     // linestring with no points
331     tester::apply(from_wkt<G>("LINESTRING()"),
332                   ba::list_of<tuple_linestring_type>()
333                   );
334 
335     // linestring with a single point
336     tester::apply(from_wkt<G>("LINESTRING(1 0)"),
337                   ba::list_of<tuple_linestring_type>
338                   ( ba::tuple_list_of(1,0)(1,0) ),
339                   false
340                   );
341 
342 #ifdef BOOST_GEOMETRY_TEST_DEBUG
343     std::cout << std::endl << std::endl << std::endl;
344 #endif
345 }
346 
347 //======================================================================
348 //======================================================================
349 
BOOST_AUTO_TEST_CASE(test_ring_segment_iterator)350 BOOST_AUTO_TEST_CASE( test_ring_segment_iterator )
351 {
352 #ifdef BOOST_GEOMETRY_TEST_DEBUG
353     std::cout << "*** RING ***" << std::endl;
354 #endif
355 
356     typedef tuple_multi_linestring_type TML;
357     typedef ring_cw_open_type OG;
358     typedef ring_cw_closed_type CG;
359 
360     typedef dual_tester<CG, TML> tester;
361 
362     tester::apply(from_wkt<OG>("POLYGON((0 0,0 10,10 10,10 0))"),
363                   ba::list_of<tuple_linestring_type>
364                   ( ba::tuple_list_of(0,0)(0,10) )
365                   ( ba::tuple_list_of(0,10)(10,10) )
366                   ( ba::tuple_list_of(10,10)(10,0) )
367                   ( ba::tuple_list_of(10,0)(0,0) )
368                   );
369 
370     // open ring with no points
371     tester::apply(from_wkt<OG>("POLYGON(())"),
372                   ba::list_of<tuple_linestring_type>()
373                   );
374 
375     // open ring with a single point (one segment)
376     tester::apply(from_wkt<OG>("POLYGON((0 0))"),
377                   ba::list_of<tuple_linestring_type>
378                   ( ba::tuple_list_of(0,0)(0,0) ),
379                   false
380                   );
381 
382     // open ring with a two points (two segments)
383     tester::apply(from_wkt<OG>("POLYGON((0 0,0 10))"),
384                   ba::list_of<tuple_linestring_type>
385                   ( ba::tuple_list_of(0,0)(0,10) )
386                   ( ba::tuple_list_of(0,10)(0,0) )
387                   );
388 
389     // open ring with a three points (three segments)
390     tester::apply(from_wkt<OG>("POLYGON((0 0,0 10,10 10))"),
391                   ba::list_of<tuple_linestring_type>
392                   ( ba::tuple_list_of(0,0)(0,10) )
393                   ( ba::tuple_list_of(0,10)(10,10) )
394                   ( ba::tuple_list_of(10,10)(0,0) )
395                   );
396 
397     tester::apply(from_wkt<CG>("POLYGON((0 0,0 10,10 10,10 0,0 0))"),
398                   ba::list_of<tuple_linestring_type>
399                   ( ba::tuple_list_of(0,0)(0,10) )
400                   ( ba::tuple_list_of(0,10)(10,10) )
401                   ( ba::tuple_list_of(10,10)(10,0) )
402                   ( ba::tuple_list_of(10,0)(0,0) )
403                   );
404 
405     // closed ring with no points
406     tester::apply(from_wkt<CG>("POLYGON(())"),
407                   ba::list_of<tuple_linestring_type>()
408                   );
409 
410     // closed ring with a single point (one segment)
411     tester::apply(from_wkt<CG>("POLYGON((0 0))"),
412                   ba::list_of<tuple_linestring_type>
413                   ( ba::tuple_list_of(0,0)(0,0) ),
414                   false
415                   );
416 
417     // closed ring with two points (one segment)
418     tester::apply(from_wkt<CG>("POLYGON((0 0,0 0))"),
419                   ba::list_of<tuple_linestring_type>
420                   ( ba::tuple_list_of(0,0)(0,0) )
421                   );
422 
423     // closed ring with three points (two segments)
424     tester::apply(from_wkt<CG>("POLYGON((0 0,0 10,0 0))"),
425                   ba::list_of<tuple_linestring_type>
426                   ( ba::tuple_list_of(0,0)(0,10) )
427                   ( ba::tuple_list_of(0,10)(0,0) )
428                   );
429 
430     // closed ring with four points (three segments)
431     tester::apply(from_wkt<CG>("POLYGON((0 0,0 10,10 10,0 0))"),
432                   ba::list_of<tuple_linestring_type>
433                   ( ba::tuple_list_of(0,0)(0,10) )
434                   ( ba::tuple_list_of(0,10)(10,10) )
435                   ( ba::tuple_list_of(10,10)(0,0) )
436                   );
437 
438 #ifdef BOOST_GEOMETRY_TEST_DEBUG
439     std::cout << std::endl << std::endl << std::endl;
440 #endif
441 }
442 
443 //======================================================================
444 //======================================================================
445 
BOOST_AUTO_TEST_CASE(test_polygon_segment_iterator)446 BOOST_AUTO_TEST_CASE( test_polygon_segment_iterator )
447 {
448 #ifdef BOOST_GEOMETRY_TEST_DEBUG
449     std::cout << "*** POLYGON ***" << std::endl;
450 #endif
451 
452     typedef tuple_multi_linestring_type TML;
453     typedef polygon_cw_open_type OG;
454     typedef polygon_cw_closed_type CG;
455 
456     typedef dual_tester<CG, TML> tester;
457 
458     tester::apply(from_wkt<OG>("POLYGON((0 0,0 10,10 10,10 0),(1 1,9 1,9 9,1 9))"),
459                   ba::list_of<tuple_linestring_type>
460                   ( ba::tuple_list_of(0,0)(0,10) )
461                   ( ba::tuple_list_of(0,10)(10,10) )
462                   ( ba::tuple_list_of(10,10)(10,0) )
463                   ( ba::tuple_list_of(10,0)(0,0) )
464                   ( ba::tuple_list_of(1,1)(9,1) )
465                   ( ba::tuple_list_of(9,1)(9,9) )
466                   ( ba::tuple_list_of(9,9)(1,9) )
467                   ( ba::tuple_list_of(1,9)(1,1) )
468                   );
469 
470     // open polygon with no points
471     tester::apply(from_wkt<OG>("POLYGON(())"),
472                   ba::list_of<tuple_linestring_type>()
473                   );
474 
475     // open polygons with single-point rings
476     tester::apply(from_wkt<OG>("POLYGON((0 0,0 10,10 10,10 0),(1 1))"),
477                   ba::list_of<tuple_linestring_type>
478                   ( ba::tuple_list_of(0,0)(0,10) )
479                   ( ba::tuple_list_of(0,10)(10,10) )
480                   ( ba::tuple_list_of(10,10)(10,0) )
481                   ( ba::tuple_list_of(10,0)(0,0) )
482                   ( ba::tuple_list_of(1,1)(1,1) ),
483                   false
484                   );
485 
486     tester::apply(from_wkt<OG>("POLYGON((0 0),(1 1,9 1,9 9,1 9))"),
487                   ba::list_of<tuple_linestring_type>
488                   ( ba::tuple_list_of(0,0)(0,0) )
489                   ( ba::tuple_list_of(1,1)(9,1) )
490                   ( ba::tuple_list_of(9,1)(9,9) )
491                   ( ba::tuple_list_of(9,9)(1,9) )
492                   ( ba::tuple_list_of(1,9)(1,1) ),
493                   false
494                   );
495 
496 
497     tester::apply(from_wkt<CG>("POLYGON((0 0,0 10,10 10,10 0,0 0),(1 1,9 1,9 9,1 9,1 1))"),
498                   ba::list_of<tuple_linestring_type>
499                   ( ba::tuple_list_of(0,0)(0,10) )
500                   ( ba::tuple_list_of(0,10)(10,10) )
501                   ( ba::tuple_list_of(10,10)(10,0) )
502                   ( ba::tuple_list_of(10,0)(0,0) )
503                   ( ba::tuple_list_of(1,1)(9,1) )
504                   ( ba::tuple_list_of(9,1)(9,9) )
505                   ( ba::tuple_list_of(9,9)(1,9) )
506                   ( ba::tuple_list_of(1,9)(1,1) )
507                   );
508 
509     // closed polygons with no points
510     tester::apply(from_wkt<CG>("POLYGON(())"),
511                   ba::list_of<tuple_linestring_type>()
512                   );
513     tester::apply(from_wkt<CG>("POLYGON((),())"),
514                   ba::list_of<tuple_linestring_type>()
515                   );
516     tester::apply(from_wkt<CG>("POLYGON((),(),())"),
517                   ba::list_of<tuple_linestring_type>()
518                   );
519 
520     // closed polygons with single-point rings
521     tester::apply(from_wkt<CG>("POLYGON((0 0,0 10,10 10,10 0,0 0),(1 1))"),
522                   ba::list_of<tuple_linestring_type>
523                   ( ba::tuple_list_of(0,0)(0,10) )
524                   ( ba::tuple_list_of(0,10)(10,10) )
525                   ( ba::tuple_list_of(10,10)(10,0) )
526                   ( ba::tuple_list_of(10,0)(0,0) )
527                   ( ba::tuple_list_of(1,1)(1,1) ),
528                   false
529                   );
530 
531     tester::apply(from_wkt<CG>("POLYGON((0 0),(1 1,9 1,9 9,1 9,1 1))"),
532                   ba::list_of<tuple_linestring_type>
533                   ( ba::tuple_list_of(0,0)(0,0) )
534                   ( ba::tuple_list_of(1,1)(9,1) )
535                   ( ba::tuple_list_of(9,1)(9,9) )
536                   ( ba::tuple_list_of(9,9)(1,9) )
537                   ( ba::tuple_list_of(1,9)(1,1) ),
538                   false
539                   );
540 
541 #ifdef BOOST_GEOMETRY_TEST_DEBUG
542     std::cout << std::endl << std::endl << std::endl;
543 #endif
544 }
545 
546 //======================================================================
547 //======================================================================
548 
BOOST_AUTO_TEST_CASE(test_multi_linestring_segment_iterator)549 BOOST_AUTO_TEST_CASE( test_multi_linestring_segment_iterator )
550 {
551 #ifdef BOOST_GEOMETRY_TEST_DEBUG
552     std::cout << "*** MULTILINESTRING ***" << std::endl;
553 #endif
554 
555     typedef tuple_multi_linestring_type TML;
556     typedef multi_linestring_type G;
557 
558     typedef test_segment_iterator_of_geometry<G, TML> tester;
559 
560     tester::apply(from_wkt<G>("MULTILINESTRING((0 0,1 1,2 2,3 3,4 4),(5 5,6 6,7 7,8 8),(9 9,10 10))"),
561                   ba::list_of<tuple_linestring_type>
562                   ( ba::tuple_list_of(0,0)(1,1) )
563                   ( ba::tuple_list_of(1,1)(2,2) )
564                   ( ba::tuple_list_of(2,2)(3,3) )
565                   ( ba::tuple_list_of(3,3)(4,4) )
566                   ( ba::tuple_list_of(5,5)(6,6) )
567                   ( ba::tuple_list_of(6,6)(7,7) )
568                   ( ba::tuple_list_of(7,7)(8,8) )
569                   ( ba::tuple_list_of(9,9)(10,10) )
570                   );
571 
572     // empty multi-linestrings
573     tester::apply(from_wkt<G>("MULTILINESTRING()"),
574                   ba::list_of<tuple_linestring_type>()
575                   );
576     tester::apply(from_wkt<G>("MULTILINESTRING(())"),
577                   ba::list_of<tuple_linestring_type>()
578                   );
579     tester::apply(from_wkt<G>("MULTILINESTRING((),())"),
580                   ba::list_of<tuple_linestring_type>()
581                   );
582 
583     // multi-linestring with a linestring with one point
584     tester::apply(from_wkt<G>("MULTILINESTRING((0 0,1 1,2 2,3 3,4 4),(5 5),(9 9,10 10))"),
585                   ba::list_of<tuple_linestring_type>
586                   ( ba::tuple_list_of(0,0)(1,1) )
587                   ( ba::tuple_list_of(1,1)(2,2) )
588                   ( ba::tuple_list_of(2,2)(3,3) )
589                   ( ba::tuple_list_of(3,3)(4,4) )
590                   ( ba::tuple_list_of(5,5)(5,5) )
591                   ( ba::tuple_list_of(9,9)(10,10) ),
592                   false
593                   );
594 
595 #ifdef BOOST_GEOMETRY_TEST_DEBUG
596     std::cout << std::endl << std::endl << std::endl;
597 #endif
598 }
599 
600 //======================================================================
601 //======================================================================
602 
BOOST_AUTO_TEST_CASE(test_multi_polygon_segment_iterator)603 BOOST_AUTO_TEST_CASE( test_multi_polygon_segment_iterator )
604 {
605 #ifdef BOOST_GEOMETRY_TEST_DEBUG
606     std::cout << "*** MULTIPOLYGON ***" << std::endl;
607 #endif
608 
609     typedef tuple_multi_linestring_type TML;
610     typedef multi_polygon_cw_open_type OG;
611     typedef multi_polygon_cw_closed_type CG;
612 
613     typedef dual_tester<CG, TML> tester;
614 
615     tester::apply(from_wkt<OG>("MULTIPOLYGON(((0 0,0 10,10 10,10 0),(1 1,9 1,9 9,1 9)),((20 0,20 10,30 10,30 0),(21 1,29 1,29 9,21 9)))"),
616                   ba::list_of<tuple_linestring_type>
617                   ( ba::tuple_list_of(0,0)(0,10) )
618                   ( ba::tuple_list_of(0,10)(10,10) )
619                   ( ba::tuple_list_of(10,10)(10,0) )
620                   ( ba::tuple_list_of(10,0)(0,0) )
621                   ( ba::tuple_list_of(1,1)(9,1) )
622                   ( ba::tuple_list_of(9,1)(9,9) )
623                   ( ba::tuple_list_of(9,9)(1,9) )
624                   ( ba::tuple_list_of(1,9)(1,1) )
625                   ( ba::tuple_list_of(20,0)(20,10) )
626                   ( ba::tuple_list_of(20,10)(30,10) )
627                   ( ba::tuple_list_of(30,10)(30,0) )
628                   ( ba::tuple_list_of(30,0)(20,0) )
629                   ( ba::tuple_list_of(21,1)(29,1) )
630                   ( ba::tuple_list_of(29,1)(29,9) )
631                   ( ba::tuple_list_of(29,9)(21,9) )
632                   ( ba::tuple_list_of(21,9)(21,1) )
633                   );
634 
635     tester::apply(from_wkt<CG>("MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0),(1 1,9 1,9 9,1 9,1 1)),((20 0,20 10,30 10,30 0,20 0),(21 1,29 1,29 9,21 9,21 1)))"),
636                   ba::list_of<tuple_linestring_type>
637                   ( ba::tuple_list_of(0,0)(0,10) )
638                   ( ba::tuple_list_of(0,10)(10,10) )
639                   ( ba::tuple_list_of(10,10)(10,0) )
640                   ( ba::tuple_list_of(10,0)(0,0) )
641                   ( ba::tuple_list_of(1,1)(9,1) )
642                   ( ba::tuple_list_of(9,1)(9,9) )
643                   ( ba::tuple_list_of(9,9)(1,9) )
644                   ( ba::tuple_list_of(1,9)(1,1) )
645                   ( ba::tuple_list_of(20,0)(20,10) )
646                   ( ba::tuple_list_of(20,10)(30,10) )
647                   ( ba::tuple_list_of(30,10)(30,0) )
648                   ( ba::tuple_list_of(30,0)(20,0) )
649                   ( ba::tuple_list_of(21,1)(29,1) )
650                   ( ba::tuple_list_of(29,1)(29,9) )
651                   ( ba::tuple_list_of(29,9)(21,9) )
652                   ( ba::tuple_list_of(21,9)(21,1) )
653                   );
654 
655     // test empty closed multi-polygons
656     tester::apply(from_wkt<CG>("MULTIPOLYGON()"),
657                   ba::list_of<tuple_linestring_type>()
658                   );
659     tester::apply(from_wkt<CG>("MULTIPOLYGON((()))"),
660                   ba::list_of<tuple_linestring_type>()
661                   );
662     tester::apply(from_wkt<CG>("MULTIPOLYGON(((),()))"),
663                   ba::list_of<tuple_linestring_type>()
664                   );
665     tester::apply(from_wkt<CG>("MULTIPOLYGON(((),(),()))"),
666                   ba::list_of<tuple_linestring_type>()
667                   );
668     tester::apply(from_wkt<CG>("MULTIPOLYGON(((),(),()),(()))"),
669                   ba::list_of<tuple_linestring_type>()
670                   );
671     tester::apply(from_wkt<CG>("MULTIPOLYGON(((),(),()),((),()))"),
672                   ba::list_of<tuple_linestring_type>()
673                   );
674 
675 #ifdef BOOST_GEOMETRY_TEST_DEBUG
676     std::cout << std::endl << std::endl << std::endl;
677 #endif
678 }
679 
680 //======================================================================
681 //======================================================================
682 
BOOST_AUTO_TEST_CASE(test_linestring_of_point_pointers)683 BOOST_AUTO_TEST_CASE( test_linestring_of_point_pointers )
684 {
685 #ifdef BOOST_GEOMETRY_TEST_DEBUG
686     std::cout << "*** LINESTRING OF POINT POINTERS ***" << std::endl;
687 #endif
688 
689     typedef tuple_multi_linestring_type TML;
690     typedef std::vector<test::test_point_xy*> L;
691 
692     std::vector<test::test_point_xy*> linestring;
693     for (int i = 1; i < 10; i++)
694     {
695         test::test_point_xy* p = new test::test_point_xy;
696         p->x = i;
697         p->y = -i;
698         linestring.push_back(p);
699     }
700 
701     test::test_point_xy* zero = new test::test_point_xy;
702     zero->x = 0;
703     zero->y = 0;
704     delete zero;
705 
706     typedef test_segment_iterator_of_geometry<L, TML> tester;
707 
708     tester::apply(linestring,
709                   ba::list_of<tuple_linestring_type>
710                   ( ba::tuple_list_of(1,-1)(2,-2) )
711                   ( ba::tuple_list_of(2,-2)(3,-3) )
712                   ( ba::tuple_list_of(3,-3)(4,-4) )
713                   ( ba::tuple_list_of(4,-4)(5,-5) )
714                   ( ba::tuple_list_of(5,-5)(6,-6) )
715                   ( ba::tuple_list_of(6,-6)(7,-7) )
716                   ( ba::tuple_list_of(7,-7)(8,-8) )
717                   ( ba::tuple_list_of(8,-8)(9,-9) )
718                   );
719 
720     for (unsigned int i = 0; i < linestring.size(); i++)
721     {
722         delete linestring[i];
723     }
724 }
725 
726 //======================================================================
727 //======================================================================
728 
BOOST_AUTO_TEST_CASE(test_linestring_copy_on_dereference)729 BOOST_AUTO_TEST_CASE( test_linestring_copy_on_dereference )
730 {
731 #ifdef BOOST_GEOMETRY_TEST_DEBUG
732     std::cout << "*** LINESTRING WITH COPY-ON-DEREFERENCE ITERATOR ***"
733               << std::endl;
734 #endif
735 
736     typedef tuple_multi_linestring_type TML;
737     typedef linestring_copy_on_dereference<point_type> L;
738 
739     typedef test_segment_iterator_of_geometry<L, TML> tester;
740 
741     tester::apply(from_wkt<L>("LINESTRING(1 -1,2 -2,3 -3,4 -4,5 -5,6 -6, 7 -7,8 -8,9 -9)"),
742                   ba::list_of<tuple_linestring_type>
743                   ( ba::tuple_list_of(1,-1)(2,-2) )
744                   ( ba::tuple_list_of(2,-2)(3,-3) )
745                   ( ba::tuple_list_of(3,-3)(4,-4) )
746                   ( ba::tuple_list_of(4,-4)(5,-5) )
747                   ( ba::tuple_list_of(5,-5)(6,-6) )
748                   ( ba::tuple_list_of(6,-6)(7,-7) )
749                   ( ba::tuple_list_of(7,-7)(8,-8) )
750                   ( ba::tuple_list_of(8,-8)(9,-9) )
751                   );
752 }
753