]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/geometry/test/algorithms/is_valid_failure.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / geometry / test / algorithms / is_valid_failure.cpp
CommitLineData
7c673cae
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2// Unit Test
3
4// Copyright (c) 2015, Oracle and/or its affiliates.
5
6// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
7
8// Licensed under the Boost Software License version 1.0.
9// http://www.boost.org/users/license.html
10
11#ifndef BOOST_TEST_MODULE
12#define BOOST_TEST_MODULE test_is_valid_failure
13#endif
14
15#include <iostream>
16#include <string>
17
18#include <boost/variant/variant.hpp>
19
20#include <boost/test/included/unit_test.hpp>
21
22#include <boost/geometry/core/cs.hpp>
23#include <boost/geometry/geometries/geometries.hpp>
24#include <boost/geometry/algorithms/is_valid.hpp>
25#include <boost/geometry/algorithms/reverse.hpp>
26#include <boost/geometry/algorithms/validity_failure_type.hpp>
27#include <boost/geometry/io/wkt/wkt.hpp>
28
29#include <boost/geometry/strategies/strategies.hpp>
30
31#include <from_wkt.hpp>
32
33
34namespace bg = ::boost::geometry;
35
36typedef bg::validity_failure_type failure_type;
37
38typedef bg::model::point<double, 2, bg::cs::cartesian> point_type;
39typedef bg::model::segment<point_type> segment_type;
40typedef bg::model::box<point_type> box_type;
41typedef bg::model::linestring<point_type> linestring_type;
42typedef bg::model::multi_linestring<linestring_type> multi_linestring_type;
43typedef bg::model::multi_point<point_type> multi_point_type;
44
45
46char const* to_string(failure_type failure)
47{
48 switch (failure)
49 {
50 case bg::no_failure:
51 return "no_failure";
52 case bg::failure_few_points:
53 return "failure_few_points";
54 case bg::failure_wrong_topological_dimension:
55 return "failure_wrong_topological_dimension";
56 case bg::failure_spikes:
57 return "failure_spikes";
58 case bg::failure_duplicate_points:
59 return "failure_duplicate_points";
60 case bg::failure_not_closed:
61 return "failure_not_closed";
62 case bg::failure_self_intersections:
63 return "failure_self_intersections";
64 case bg::failure_wrong_orientation:
65 return "failure_wrong_orientation";
66 case bg::failure_interior_rings_outside:
67 return "failure_interior_rings_outside";
68 case bg::failure_nested_interior_rings:
69 return "failure_nested_interior_rings";
70 case bg::failure_disconnected_interior:
71 return "failure_disconnected_interior";
72 case bg::failure_intersecting_interiors:
73 return "failure_intersecting_interiors";
74 case bg::failure_wrong_corner_order:
75 return "failure_wrong_corner_order";
76 default:
77 return ""; // to avoid warnings (-Wreturn-type)
78 }
79}
80
81
82template <typename Geometry>
83struct test_failure
84{
85 static inline void apply(std::string const& case_id,
86 Geometry const& geometry,
87 failure_type expected)
88 {
89 failure_type detected;
90 bg::is_valid(geometry, detected);
91 std::string expected_msg = bg::validity_failure_type_message(expected);
92 std::string detected_msg;
93 bg::is_valid(geometry, detected_msg);
94 std::string detected_msg_short
95 = detected_msg.substr(0, expected_msg.length());
96
97#ifdef BOOST_GEOMETRY_TEST_DEBUG
98 std::cout << "----------------------" << std::endl;
99 std::cout << "case id: " << case_id << std::endl;
100 std::cout << "Geometry: " << bg::wkt(geometry) << std::endl;
101 std::cout << "Expected reason: " << expected_msg << std::endl;
102 std::cout << "Detected reason: " << detected_msg << std::endl;
103 std::cout << "Expected: " << to_string(expected) << std::endl;
104 std::cout << "Detected: " << to_string(detected) << std::endl;
105 std::cout << std::endl;
106#endif
107
108 BOOST_CHECK_MESSAGE(expected == detected,
109 "case id: " << case_id
110 << ", Geometry: " << bg::wkt(geometry)
111 << ", expected: " << to_string(expected)
112 << ", detected: " << to_string(detected));
113
114 BOOST_CHECK(detected_msg_short == expected_msg);
115
116#ifdef BOOST_GEOMETRY_TEST_DEBUG
117 std::cout << "----------------------" << std::endl;
118 std::cout << std::endl << std::endl;
119#endif
120 }
121
122 static inline void apply(std::string const& case_id,
123 std::string const& wkt,
124 failure_type expected)
125 {
126 Geometry geometry = from_wkt<Geometry>(wkt);
127 apply(case_id, geometry, expected);
128 }
129};
130
131
132BOOST_AUTO_TEST_CASE( test_failure_point )
133{
134#ifdef BOOST_GEOMETRY_TEST_DEBUG
135 std::cout << std::endl << std::endl;
136 std::cout << "************************************" << std::endl;
137 std::cout << " is_valid_failure: POINT " << std::endl;
138 std::cout << "************************************" << std::endl;
139#endif
140
141 typedef point_type G;
142 typedef test_failure<G> test;
143
144 test::apply("p01", "POINT(0 0)", bg::no_failure);
145}
146
147BOOST_AUTO_TEST_CASE( test_failure_multipoint )
148{
149#ifdef BOOST_GEOMETRY_TEST_DEBUG
150 std::cout << std::endl << std::endl;
151 std::cout << "************************************" << std::endl;
152 std::cout << " is_valid_failure: MULTIPOINT " << std::endl;
153 std::cout << "************************************" << std::endl;
154#endif
155
156 typedef multi_point_type G;
157 typedef test_failure<G> test;
158
159 test::apply("mp01", "MULTIPOINT()", bg::no_failure);
160 test::apply("mp02", "MULTIPOINT(0 0,0 0)", bg::no_failure);
161 test::apply("mp03", "MULTIPOINT(0 0,1 0,1 1,0 1)", bg::no_failure);
162 test::apply("mp04", "MULTIPOINT(0 0,1 0,1 1,1 0,0 1)", bg::no_failure);
163}
164
165BOOST_AUTO_TEST_CASE( test_failure_segment )
166{
167#ifdef BOOST_GEOMETRY_TEST_DEBUG
168 std::cout << std::endl << std::endl;
169 std::cout << "************************************" << std::endl;
170 std::cout << " is_valid_failure: SEGMENT " << std::endl;
171 std::cout << "************************************" << std::endl;
172#endif
173
174 typedef segment_type G;
175 typedef test_failure<G> test;
176
177 test::apply("s01",
178 "SEGMENT(0 0,0 0)",
179 bg::failure_wrong_topological_dimension);
180 test::apply("s02", "SEGMENT(0 0,1 0)", bg::no_failure);
181}
182
183BOOST_AUTO_TEST_CASE( test_failure_box )
184{
185#ifdef BOOST_GEOMETRY_TEST_DEBUG
186 std::cout << std::endl << std::endl;
187 std::cout << "************************************" << std::endl;
188 std::cout << " is_valid_failure: BOX " << std::endl;
189 std::cout << "************************************" << std::endl;
190#endif
191
192 typedef box_type G;
193 typedef test_failure<G> test;
194
195 // boxes where the max corner and below and/or to the left of min corner
196 test::apply("b01",
197 "BOX(0 0,-1 0)",
198 bg::failure_wrong_topological_dimension);
199 test::apply("b02", "BOX(0 0,0 -1)", bg::failure_wrong_corner_order);
200 test::apply("b03", "BOX(0 0,-1 -1)", bg::failure_wrong_corner_order);
201
202 // boxes of zero area; they are not 2-dimensional, so invalid
203 test::apply("b04", "BOX(0 0,0 0)", bg::failure_wrong_topological_dimension);
204 test::apply("b05", "BOX(0 0,1 0)", bg::failure_wrong_topological_dimension);
205 test::apply("b06", "BOX(0 0,0 1)", bg::failure_wrong_topological_dimension);
206
207 test::apply("b07", "BOX(0 0,1 1)", bg::no_failure);
208}
209
210BOOST_AUTO_TEST_CASE( test_failure_linestring )
211{
212#ifdef BOOST_GEOMETRY_TEST_DEBUG
213 std::cout << std::endl << std::endl;
214 std::cout << "************************************" << std::endl;
215 std::cout << " is_valid_failure: LINESTRING " << std::endl;
216 std::cout << "************************************" << std::endl;
217#endif
218
219 typedef linestring_type G;
220 typedef test_failure<G> test;
221
222 // empty linestring
223 test::apply("l01", "LINESTRING()", bg::failure_few_points);
224
225 // 1-point linestrings
226 test::apply("l02", "LINESTRING(0 0)", bg::failure_few_points);
227 test::apply("l03",
228 "LINESTRING(0 0,0 0)",
229 bg::failure_wrong_topological_dimension);
230 test::apply("l04",
231 "LINESTRING(0 0,0 0,0 0)",
232 bg::failure_wrong_topological_dimension);
233
234 // 2-point linestrings
235 test::apply("l05", "LINESTRING(0 0,1 2)", bg::no_failure);
236 test::apply("l06", "LINESTRING(0 0,1 2,1 2)", bg::no_failure);
237 test::apply("l07", "LINESTRING(0 0,0 0,1 2,1 2)", bg::no_failure);
238 test::apply("l08", "LINESTRING(0 0,0 0,0 0,1 2,1 2)", bg::no_failure);
239
240 // 3-point linestring
241 test::apply("l09", "LINESTRING(0 0,1 0,2 10)", bg::no_failure);
242
243 // linestrings with spikes
244 test::apply("l10", "LINESTRING(0 0,1 2,0 0)", bg::no_failure);
245}
246
247BOOST_AUTO_TEST_CASE( test_failure_multilinestring )
248{
249#ifdef BOOST_GEOMETRY_TEST_DEBUG
250 std::cout << std::endl << std::endl;
251 std::cout << "************************************" << std::endl;
252 std::cout << " is_valid_failure: MULTILINESTRING " << std::endl;
253 std::cout << "************************************" << std::endl;
254#endif
255
256 typedef multi_linestring_type G;
257 typedef test_failure<G> test;
258
259 // empty multilinestring
260 test::apply("mls01", "MULTILINESTRING()", bg::no_failure);
261
262 // multilinestring with empty linestring(s)
263 test::apply("mls02", "MULTILINESTRING(())", bg::failure_few_points);
264 test::apply("mls03", "MULTILINESTRING((),(),())", bg::failure_few_points);
265 test::apply("mls04",
266 "MULTILINESTRING((),(0 1,1 0))",
267 bg::failure_few_points);
268
269 // multilinestring with invalid linestrings
270 test::apply("mls05",
271 "MULTILINESTRING((0 0),(0 1,1 0))",
272 bg::failure_few_points);
273 test::apply("mls06",
274 "MULTILINESTRING((0 0,0 0),(0 1,1 0))",
275 bg::failure_wrong_topological_dimension);
276 test::apply("mls07", "MULTILINESTRING((0 0),(1 0))",
277 bg::failure_few_points);
278 test::apply("mls08",
279 "MULTILINESTRING((0 0,0 0),(1 0,1 0))",
280 bg::failure_wrong_topological_dimension);
281 test::apply("mls09",
282 "MULTILINESTRING((0 0),(0 0))",
283 bg::failure_few_points);
284 test::apply("mls10",
285 "MULTILINESTRING((0 0,1 0,0 0),(5 0))",
286 bg::failure_few_points);
287
288 // multilinstring that has linestrings with spikes
289 test::apply("mls11",
290 "MULTILINESTRING((0 0,1 0,0 0),(5 0,1 0,4 1))",
291 bg::no_failure);
292 test::apply("mls12",
293 "MULTILINESTRING((0 0,1 0,0 0),(1 0,2 0))",
294 bg::no_failure);
295
296 // valid multilinestrings
297 test::apply("mls13",
298 "MULTILINESTRING((0 0,1 0,2 0),(5 0,1 0,4 1))",
299 bg::no_failure);
300 test::apply("mls14",
301 "MULTILINESTRING((0 0,1 0,2 0),(1 0,2 0))",
302 bg::no_failure);
303 test::apply("mls15",
304 "MULTILINESTRING((0 0,1 1),(0 1,1 0))",
305 bg::no_failure);
306 test::apply("mls16",
307 "MULTILINESTRING((0 0,1 1,2 2),(0 1,1 0,2 2))",
308 bg::no_failure);
309}
310
311template <typename Point>
312inline void test_open_rings()
313{
314#ifdef BOOST_GEOMETRY_TEST_DEBUG
315 std::cout << std::endl << std::endl;
316 std::cout << "************************************" << std::endl;
317 std::cout << " is_valid_failure: RING (open) " << std::endl;
318 std::cout << "************************************" << std::endl;
319#endif
320
321 typedef bg::model::ring<Point, false, false> G; // ccw, open ring
322 typedef test_failure<G> test;
323
324 // not enough points
325 test::apply("r01", "POLYGON(())", bg::failure_few_points);
326 test::apply("r02", "POLYGON((0 0))", bg::failure_few_points);
327 test::apply("r03", "POLYGON((0 0,1 0))", bg::failure_few_points);
328
329 // duplicate points
330 test::apply("r04",
331 "POLYGON((0 0,0 0,0 0))",
332 bg::failure_wrong_topological_dimension);
333 test::apply("r05",
334 "POLYGON((0 0,1 0,1 0))",
335 bg::failure_wrong_topological_dimension);
336 test::apply("r06",
337 "POLYGON((0 0,1 0,0 0))",
338 bg::failure_wrong_topological_dimension);
339 test::apply("r07", "POLYGON((0 0,1 0,1 1,0 0,0 0))", bg::no_failure);
340 test::apply("r08", "POLYGON((0 0,1 0,1 0,1 1))", bg::no_failure);
341 test::apply("r09", "POLYGON((0 0,1 0,1 0,1 1,0 0))", bg::no_failure);
342
343 // with spikes
344 test::apply("r10", "POLYGON((0 0,2 0,2 2,0 2,1 2))", bg::failure_spikes);
345 test::apply("r11", "POLYGON((0 0,2 0,1 0,2 2))", bg::failure_spikes);
346 test::apply("r12",
347 "POLYGON((0 0,1 0,2 0,1 0,4 0,4 4))",
348 bg::failure_spikes);
349 test::apply("r13", "POLYGON((0 0,2 0,2 2,1 0))", bg::failure_spikes);
350 test::apply("r14", "POLYGON((0 0,2 0,1 0))", bg::failure_spikes);
351 test::apply("r15",
352 "POLYGON((0 0,5 0,5 5,4 4,5 5,0 5))",
353 bg::failure_spikes);
354 test::apply("r16",
355 "POLYGON((0 0,5 0,5 5,4 4,3 3,5 5,0 5))",
356 bg::failure_spikes);
357
358 // with spikes and duplicate points
359 test::apply("r17",
360 "POLYGON((0 0,0 0,2 0,2 0,1 0,1 0))",
361 bg::failure_spikes);
362
363 // with self-crossings
364 test::apply("r18",
365 "POLYGON((0 0,5 0,5 5,3 -1,0 5))",
366 bg::failure_self_intersections);
367
368 // with self-crossings and duplicate points
369 test::apply("r19",
370 "POLYGON((0 0,5 0,5 5,5 5,3 -1,0 5,0 5))",
371 bg::failure_self_intersections);
372
373 // with self-intersections
374 test::apply("r20",
375 "POLYGON((0 0,5 0,5 5,3 5,3 0,2 0,2 5,0 5))",
376 bg::failure_self_intersections);
377 test::apply("r21",
378 "POLYGON((0 0,5 0,5 5,3 5,3 0,2 5,0 5))",
379 bg::failure_self_intersections);
380 test::apply("r22",
381 "POLYGON((0 0,5 0,5 1,1 1,1 2,2 2,3 1,4 2,5 2,5 5,0 5))",
382 bg::failure_self_intersections);
383
384 // with self-intersections and duplicate points
385 test::apply("r23",
386 "POLYGON((0 0,5 0,5 5,3 5,3 5,3 0,3 0,2 0,2 0,2 5,2 5,0 5))",
387 bg::failure_self_intersections);
388
389 // next two suggested by Adam Wulkiewicz
390 test::apply("r24",
391 "POLYGON((0 0,5 0,5 5,0 5,4 4,2 2,0 5))",
392 bg::failure_self_intersections);
393 test::apply("r25",
394 "POLYGON((0 0,5 0,5 5,1 4,4 4,4 1,0 5))",
395 bg::failure_self_intersections);
396
397 // and a few more
398 test::apply("r26",
399 "POLYGON((0 0,5 0,5 5,4 4,1 4,1 1,4 1,4 4,0 5))",
400 bg::failure_self_intersections);
401 test::apply("r27",
402 "POLYGON((0 0,5 0,5 5,4 4,4 1,1 1,1 4,4 4,0 5))",
403 bg::failure_self_intersections);
404
405 // valid rings
406 test::apply("r28", "POLYGON((0 0,1 0,1 1))", bg::no_failure);
407 test::apply("r29", "POLYGON((1 0,1 1,0 0))", bg::no_failure);
408 test::apply("r30", "POLYGON((0 0,1 0,1 1,0 1))", bg::no_failure);
409 test::apply("r31", "POLYGON((1 0,1 1,0 1,0 0))", bg::no_failure);
410
411 // test cases coming from buffer
412 test::apply("r32",
413 "POLYGON((1.1713032141645456 -0.9370425713316364,\
414 5.1713032141645456 4.0629574286683638,\
415 4.7808688094430307 4.3753049524455756,\
416 4.7808688094430307 4.3753049524455756,\
417 0.7808688094430304 -0.6246950475544243,\
418 0.7808688094430304 -0.6246950475544243))",
419 bg::no_failure);
420
421 // wrong orientation
422 test::apply("r33",
423 "POLYGON((0 0,0 1,1 1,0 0))",
424 bg::failure_wrong_orientation);
425}
426
427template <typename Point>
428void test_closed_rings()
429{
430#ifdef BOOST_GEOMETRY_TEST_DEBUG
431 std::cout << std::endl << std::endl;
432 std::cout << "************************************" << std::endl;
433 std::cout << " is_valid_failure: RING (closed) " << std::endl;
434 std::cout << "************************************" << std::endl;
435#endif
436
437 typedef bg::model::ring<Point, false, true> G; // ccw, closed ring
438 typedef test_failure<G> test;
439
440 // not enough points
441 test::apply("r01c", "POLYGON(())", bg::failure_few_points);
442 test::apply("r02c", "POLYGON((0 0))", bg::failure_few_points);
443 test::apply("r03c", "POLYGON((0 0,0 0))", bg::failure_few_points);
444 test::apply("r04c", "POLYGON((0 0,1 0))", bg::failure_few_points);
445 test::apply("r05c", "POLYGON((0 0,1 0,1 0))", bg::failure_few_points);
446 test::apply("r06c", "POLYGON((0 0,1 0,2 0))", bg::failure_few_points);
447 test::apply("r07c",
448 "POLYGON((0 0,1 0,1 0,2 0))",
449 bg::failure_wrong_topological_dimension);
450 test::apply("r08c",
451 "POLYGON((0 0,1 0,2 0,2 0))",
452 bg::failure_wrong_topological_dimension);
453
454 // boundary not closed
455 test::apply("r09c", "POLYGON((0 0,1 0,1 1,1 2))", bg::failure_not_closed);
456 test::apply("r10c",
457 "POLYGON((0 0,1 0,1 0,1 1,1 1,1 2))",
458 bg::failure_not_closed);
459
460 // with spikes
461 test::apply("r11c", "POLYGON((0 0,1 0,1 0,2 0,0 0))", bg::failure_spikes);
462 test::apply("r12c",
463 "POLYGON((0 0,1 0,1 1,2 2,0.5 0.5,0 1,0 0))",
464 bg::failure_spikes);
465
466 // wrong orientation
467 test::apply("r13c",
468 "POLYGON((0 0,0 1,1 1,2 0,0 0))",
469 bg::failure_wrong_orientation);
470
471}
472
473BOOST_AUTO_TEST_CASE( test_failure_ring )
474{
475 test_open_rings<point_type>();
476 test_closed_rings<point_type>();
477}
478
479
480template <typename Point>
481void test_open_polygons()
482{
483#ifdef BOOST_GEOMETRY_TEST_DEBUG
484 std::cout << std::endl << std::endl;
485 std::cout << "************************************" << std::endl;
486 std::cout << " is_valid_failure: POLYGON (open) " << std::endl;
487 std::cout << "************************************" << std::endl;
488#endif
489
490 typedef bg::model::polygon<Point, false, false> G; // ccw, open
491 typedef test_failure<G> test;
492
493 // not enough points in exterior ring
494 test::apply("pg001", "POLYGON(())", bg::failure_few_points);
495 test::apply("pg002", "POLYGON((0 0))", bg::failure_few_points);
496 test::apply("pg003", "POLYGON((0 0,1 0))", bg::failure_few_points);
497
498 // not enough points in interior ring
499 test::apply("pg004",
500 "POLYGON((0 0,10 0,10 10,0 10),())",
501 bg::failure_few_points);
502 test::apply("pg005",
503 "POLYGON((0 0,10 0,10 10,0 10),(1 1))",
504 bg::failure_few_points);
505 test::apply("pg006",
506 "POLYGON((0 0,10 0,10 10,0 10),(1 1,2 2))",
507 bg::failure_few_points);
508
509 // duplicate points in exterior ring
510 test::apply("pg007",
511 "POLYGON((0 0,0 0,0 0))",
512 bg::failure_wrong_topological_dimension);
513 test::apply("pg008",
514 "POLYGON((0 0,1 0,1 0))",
515 bg::failure_wrong_topological_dimension);
516 test::apply("pg009",
517 "POLYGON((0 0,1 0,0 0))",
518 bg::failure_wrong_topological_dimension);
519 test::apply("pg010", "POLYGON((0 0,1 0,1 1,0 0,0 0))", bg::no_failure);
520 test::apply("pg011", "POLYGON((0 0,1 0,1 0,1 1))", bg::no_failure);
521 test::apply("pg012", "POLYGON((0 0,1 0,1 0,1 1,0 0))", bg::no_failure);
522
523 test::apply("pg013",
524 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 1,1 1))",
525 bg::failure_wrong_topological_dimension);
526 test::apply("pg014",
527 "POLYGON((0 0,10 0,10 10,0 10),(1 1,2 1,2 1))",
528 bg::failure_wrong_topological_dimension);
529 test::apply("pg015",
530 "POLYGON((0 0,10 0,10 10,0 10),(1 1,2 1,1 1))",
531 bg::failure_wrong_topological_dimension);
532 test::apply("pg016",
533 "POLYGON((0 0,10 0,10 10,0 10),(1 1,2 2,2 1,1 1,1 1))",
534 bg::no_failure);
535 test::apply("pg017",
536 "POLYGON((0 0,10 0,10 10,0 10),(1 1,2 2,2 2,2 1))",
537 bg::no_failure);
538 test::apply("pg018",
539 "POLYGON((0 0,10 0,10 10,0 10),(1 1,2 2,2 1,2 1,1 1))",
540 bg::no_failure);
541
542 // with spikes in exterior ring
543 test::apply("pg019", "POLYGON((0 0,2 0,2 2,0 2,1 2))", bg::failure_spikes);
544 test::apply("pg020", "POLYGON((0 0,2 0,1 0,2 2))", bg::failure_spikes);
545 test::apply("pg021",
546 "POLYGON((0 0,1 0,2 0,1 0,4 0,4 4))",
547 bg::failure_spikes);
548 test::apply("pg022", "POLYGON((0 0,2 0,2 2,1 0))", bg::failure_spikes);
549 test::apply("pg023", "POLYGON((0 0,2 0,1 0))", bg::failure_spikes);
550 test::apply("pg024",
551 "POLYGON((0 0,5 0,5 5,4 4,5 5,0 5))",
552 bg::failure_spikes);
553 test::apply("pg025",
554 "POLYGON((0 0,5 0,5 5,4 4,3 3,5 5,0 5))",
555 bg::failure_spikes);
556
557 // with spikes in interior ring
558 test::apply("pg026",
559 "POLYGON((0 0,10 0,10 10,0 10),(1 1,3 1,3 3,1 3,2 3))",
560 bg::failure_spikes);
561 test::apply("pg027",
562 "POLYGON((0 0,10 0,10 10,0 10),(1 1,3 1,2 1,3 3))",
563 bg::failure_spikes);
564 test::apply("pg028",
565 "POLYGON((0 0,10 0,10 10,0 10),(1 1,2 1,3 1,2 1,4 1,4 4))",
566 bg::failure_spikes);
567 test::apply("pg029",
568 "POLYGON((0 0,10 0,10 10,0 10),(1 1,3 1,3 3,2 1))",
569 bg::failure_spikes);
570 test::apply("pg030",
571 "POLYGON((0 0,10 0,10 10,0 10),(1 1,3 1,2 1))",
572 bg::failure_spikes);
573
574 // with self-crossings in exterior ring
575 test::apply("pg031",
576 "POLYGON((0 0,5 0,5 5,3 -1,0 5))",
577 bg::failure_self_intersections);
578
579 // example from Norvald Ryeng
580 test::apply("pg032",
581 "POLYGON((100 1300,140 1300,140 170,100 1700))",
582 bg::failure_wrong_orientation);
583 // and with point order reversed
584 test::apply("pg033",
585 "POLYGON((100 1300,100 1700,140 170,140 1300))",
586 bg::failure_self_intersections);
587
588 // with self-crossings in interior ring
589 // the self-crossing causes the area of the interior ring to have
590 // the wrong sign, hence the "wrong orientation" failure
591 test::apply("pg034",
592 "POLYGON((0 0,10 0,10 10,0 10),(3 3,3 7,4 6,2 6))",
593 bg::failure_wrong_orientation);
594
595 // with self-crossings between rings
596 test::apply("pg035",
597 "POLYGON((0 0,5 0,5 5,0 5),(1 1,2 1,1 -1))",
598 bg::failure_self_intersections);
599
600 // with self-intersections in exterior ring
601 test::apply("pg036",
602 "POLYGON((0 0,5 0,5 5,3 5,3 0,2 0,2 5,0 5))",
603 bg::failure_self_intersections);
604 test::apply("pg037",
605 "POLYGON((0 0,5 0,5 5,3 5,3 0,2 5,0 5))",
606 bg::failure_self_intersections);
607 test::apply("pg038",
608 "POLYGON((0 0,5 0,5 1,1 1,1 2,2 2,3 1,4 2,5 2,5 5,0 5))",
609 bg::failure_self_intersections);
610
611 // next two suggested by Adam Wulkiewicz
612 test::apply("pg039",
613 "POLYGON((0 0,5 0,5 5,0 5,4 4,2 2,0 5))",
614 bg::failure_self_intersections);
615 test::apply("pg040",
616 "POLYGON((0 0,5 0,5 5,1 4,4 4,4 1,0 5))",
617 bg::failure_self_intersections);
618 test::apply("pg041",
619 "POLYGON((0 0,5 0,5 5,4 4,1 4,1 1,4 1,4 4,0 5))",
620 bg::failure_self_intersections);
621 test::apply("pg042",
622 "POLYGON((0 0,5 0,5 5,4 4,4 1,1 1,1 4,4 4,0 5))",
623 bg::failure_self_intersections);
624
625 // with self-intersections in interior ring
626
627 // same comment as for pg034
628 test::apply("pg043",
629 "POLYGON((-10 -10,10 -10,10 10,-10 10),(0 0,5 0,5 5,3 5,3 0,2 0,2 5,0 5))",
630 bg::failure_wrong_orientation);
631
632 // same comment as for pg034
633 test::apply("pg044",
634 "POLYGON((-10 -10,10 -10,10 10,-10 10),(0 0,5 0,5 5,3 5,3 0,2 5,0 5))",
635 bg::failure_wrong_orientation);
636
637 // same comment as for pg034
638 test::apply("pg045",
639 "POLYGON((-10 -10,10 -10,10 10,-10 10),(0 0,5 0,5 1,1 1,1 2,2 2,3 1,4 2,5 2,5 5,0 5))",
640 bg::failure_wrong_orientation);
641
642 // with self-intersections between rings
643 // hole has common segment with exterior ring
644 test::apply("pg046",
645 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 10,2 10,2 1))",
646 bg::failure_self_intersections);
647 test::apply("pg047",
648 "POLYGON((0 0,0 0,10 0,10 10,0 10,0 10),(1 1,1 10,1 10,2 10,2 10,2 1))",
649 bg::failure_self_intersections);
650 // hole touches exterior ring at one point
651 test::apply("pg048",
652 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 10,2 1))",
653 bg::no_failure);
654
655 // "hole" is outside the exterior ring, but touches it
656 // TODO: return the failure value failure_interior_rings_outside
657 test::apply("pg049",
658 "POLYGON((0 0,10 0,10 10,0 10),(5 10,4 11,6 11))",
659 bg::failure_self_intersections);
660
661 // hole touches exterior ring at vertex
662 test::apply("pg050",
663 "POLYGON((0 0,10 0,10 10,0 10),(0 0,1 4,4 1))",
664 bg::no_failure);
665
666 // "hole" is completely outside the exterior ring
667 test::apply("pg051",
668 "POLYGON((0 0,10 0,10 10,0 10),(20 20,20 21,21 21,21 20))",
669 bg::failure_interior_rings_outside);
670
671 // two "holes" completely outside the exterior ring, that touch
672 // each other
673 test::apply("pg052",
674 "POLYGON((0 0,10 0,10 10,0 10),(20 0,25 10,21 0),(30 0,25 10,31 0))",
675 bg::failure_interior_rings_outside);
676
677 // example from Norvald Ryeng
678 test::apply("pg053",
679 "POLYGON((58 31,56.57 30,62 33),(35 9,28 14,31 16),(23 11,29 5,26 4))",
680 bg::failure_interior_rings_outside);
681 // and with points reversed
682 test::apply("pg054",
683 "POLYGON((58 31,62 33,56.57 30),(35 9,31 16,28 14),(23 11,26 4,29 5))",
684 bg::failure_wrong_orientation);
685
686 // "hole" is completely inside another "hole"
687 test::apply("pg055",
688 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 9,9 9,9 1),(2 2,2 8,8 8,8 2))",
689 bg::failure_nested_interior_rings);
690 test::apply("pg056",
691 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 9,9 9,9 1),(2 2,8 2,8 8,2 8))",
692 bg::failure_wrong_orientation);
693
694 // "hole" is inside another "hole" (touching)
695 // TODO: return the failure value failure_nested_interior_rings
696 test::apply("pg057",
697 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 9,9 9,9 1),(2 2,2 8,8 8,9 6,8 2))",
698 bg::failure_self_intersections);
699 // TODO: return the failure value failure_nested_interior_rings
700 test::apply("pg058",
701 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 9,9 9,9 1),(2 2,2 8,8 8,9 6,8 2))",
702 bg::failure_self_intersections);
703 test::apply("pg058a",
704 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 9,9 9,9 1),(2 2,8 2,9 6,8 8,2 8))",
705 bg::failure_wrong_orientation);
706 // TODO: return the failure value failure_nested_interior_rings
707 test::apply("pg059",
708 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 9,9 9,9 1),(2 2,2 8,8 8,9 6,8 2))",
709 bg::failure_self_intersections);
710 test::apply("pg059a",
711 "POLYGON((0 0,10 0,10 10,0 10),(1 1,9 1,9 9,1 9),(2 2,2 8,8 8,9 6,8 2))",
712 bg::failure_wrong_orientation);
713 // TODO: return the failure value failure_nested_interior_rings
714 test::apply("pg060",
715 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 9,9 9,9 1),(2 2,2 8,8 8,9 6,8 2))",
716 bg::failure_self_intersections);
717 test::apply("pg060a",
718 "POLYGON((0 0,10 0,10 10,0 10),(1 1,9 1,9 9,1 9),(2 2,8 2,9 6,8 8,2 8))",
719 bg::failure_wrong_orientation);
720 // hole touches exterior ring at two points
721 test::apply("pg061",
722 "POLYGON((0 0,10 0,10 10,0 10),(5 0,0 5,5 5))",
723 bg::failure_disconnected_interior);
724
725 // cases with more holes
726 // two holes, touching the exterior at the same point
727 test::apply("pg062",
728 "POLYGON((0 0,10 0,10 10,0 10),(0 0,1 9,2 9),(0 0,9 2,9 1))",
729 bg::no_failure);
730 test::apply("pg063",
731 "POLYGON((0 0,0 0,10 0,10 10,0 10,0 0),(0 0,0 0,1 9,2 9),(0 0,0 0,9 2,9 1))",
732 bg::no_failure);
733 test::apply("pg063",
734 "POLYGON((0 10,0 0,0 0,0 0,10 0,10 10),(2 9,0 0,0 0,1 9),(9 1,0 0,0 0,9 2))",
735 bg::no_failure);
736 // two holes, one inside the other
737 // TODO: return the failure value failure_nested_interior_rings
738 test::apply("pg064",
739 "POLYGON((0 0,10 0,10 10,0 10),(0 0,1 9,9 1),(0 0,4 5,5 4))",
740 bg::failure_self_intersections);
741 // 1st hole touches has common segment with 2nd hole
742 test::apply("pg066",
743 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 5,5 5,5 1),(5 4,5 8,8 8,8 4))",
744 bg::failure_self_intersections);
745 // 1st hole touches 2nd hole at two points
746 test::apply("pg067",
747 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 9,9 9,9 8,2 8,2 1),(2 5,5 8,5 5))",
748 bg::failure_disconnected_interior);
749 // polygon with many holes, where the last two touch at two points
750 test::apply("pg068",
751 "POLYGON((0 0,20 0,20 20,0 20),(1 18,1 19,2 19,2 18),(3 18,3 19,4 19,4 18),(5 18,5 19,6 19,6 18),(7 18,7 19,8 19,8 18),(9 18,9 19,10 19,10 18),(11 18,11 19,12 19,12 18),(13 18,13 19,14 19,14 18),(15 18,15 19,16 19,16 18),(17 18,17 19,18 19,18 18),(1 1,1 9,9 9,9 8,2 8,2 1),(2 5,5 8,5 5))",
752 bg::failure_disconnected_interior);
753 // two holes completely inside exterior ring but touching each
754 // other at a point
755 test::apply("pg069",
756 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 9,2 9),(1 1,9 2,9 1))",
757 bg::no_failure);
758 // four holes, each two touching at different points
759 test::apply("pg070",
760 "POLYGON((0 0,10 0,10 10,0 10),(0 10,2 1,1 1),(0 10,4 1,3 1),(10 10,9 1,8 1),(10 10,7 1,6 1))",
761 bg::no_failure);
762 // five holes, with two pairs touching each at some point, and
763 // fifth hole creating a disconnected component for the interior
764 test::apply("pg071",
765 "POLYGON((0 0,10 0,10 10,0 10),(0 10,2 1,1 1),(0 10,4 1,3 1),(10 10,9 1,8 1),(10 10,7 1,6 1),(4 1,4 4,6 4,6 1))",
766 bg::failure_disconnected_interior);
767 // five holes, with two pairs touching each at some point, and
768 // fifth hole creating three disconnected components for the interior
769 test::apply("pg072",
770 "POLYGON((0 0,10 0,10 10,0 10),(0 10,2 1,1 1),(0 10,4 1,3 1),(10 10,9 1,8 1),(10 10,7 1,6 1),(4 1,4 4,6 4,6 1,5 0))",
771 bg::failure_disconnected_interior);
772
773 // both examples: a polygon with one hole, where the hole contains
774 // the exterior ring
775 test::apply("pg073",
776 "POLYGON((0 0,1 0,1 1,0 1),(-10 -10,-10 10,10 10,10 -10))",
777 bg::failure_interior_rings_outside);
778 // TODO: return the failure value failure_interior_rings_outside
779 test::apply("pg074",
780 "POLYGON((-10 -10,1 0,1 1,0 1),(-10 -10,-10 10,10 10,10 -10))",
781 bg::failure_self_intersections);
782}
783
784template <typename Point>
785inline void test_doc_example_polygon()
786{
787#ifdef BOOST_GEOMETRY_TEST_DEBUG
788 std::cout << std::endl << std::endl;
789 std::cout << "************************************" << std::endl;
790 std::cout << " is_valid_failure: doc example polygon " << std::endl;
791 std::cout << "************************************" << std::endl;
792#endif
793
794 typedef bg::model::polygon<Point> CCW_CG;
795 typedef test_failure<CCW_CG> test;
796
797 test::apply("pg-doc",
798 "POLYGON((0 0,0 10,10 10,10 0,0 0),(0 0,9 1,9 2,0 0),(0 0,2 9,1 9,0 0),(2 9,9 2,9 9,2 9))",
799 bg::failure_disconnected_interior);
800}
801
802BOOST_AUTO_TEST_CASE( test_failure_polygon )
803{
804 test_open_polygons<point_type>();
805 test_doc_example_polygon<point_type>();
806}
807
808
809template <typename Point>
810void test_open_multipolygons()
811{
812#ifdef BOOST_GEOMETRY_TEST_DEBUG
813 std::cout << std::endl << std::endl;
814 std::cout << "************************************" << std::endl;
815 std::cout << " is_valid_failure: MULTIPOLYGON (open) " << std::endl;
816 std::cout << "************************************" << std::endl;
817#endif
818
819 typedef bg::model::polygon<point_type,false,false> ccw_open_polygon_type;
820 typedef bg::model::multi_polygon<ccw_open_polygon_type> G;
821
822 typedef test_failure<G> test;
823
824 // not enough points
825 test::apply("mpg01", "MULTIPOLYGON()", bg::no_failure);
826 test::apply("mpg02", "MULTIPOLYGON((()))", bg::failure_few_points);
827 test::apply("mpg03", "MULTIPOLYGON(((0 0)),(()))", bg::failure_few_points);
828 test::apply("mpg04", "MULTIPOLYGON(((0 0,1 0)))", bg::failure_few_points);
829
830 // two disjoint polygons
831 test::apply("mpg05",
832 "MULTIPOLYGON(((0 0,1 0,1 1,0 1)),((2 2,3 2,3 3,2 3)))",
833 bg::no_failure);
834
835 // two disjoint polygons with multiple points
836 test::apply("mpg06",
837 "MULTIPOLYGON(((0 0,1 0,1 0,1 1,0 1)),((2 2,3 2,3 3,3 3,2 3)))",
838 bg::no_failure);
839
840 // two polygons touch at a point
841 test::apply("mpg07",
842 "MULTIPOLYGON(((0 0,1 0,1 1,0 1)),((1 1,2 1,2 2,1 2)))",
843 bg::no_failure);
844
845 // two polygons share a segment at a point
846 test::apply("mpg08",
847 "MULTIPOLYGON(((0 0,1.5 0,1.5 1,0 1)),((1 1,2 1,2 2,1 2)))",
848 bg::failure_self_intersections);
849
850 // one polygon inside another and boundaries touching
7c673cae
FG
851 test::apply("mpg09",
852 "MULTIPOLYGON(((0 0,10 0,10 10,0 10)),((0 0,9 1,9 2)))",
b32b8144 853 bg::failure_intersecting_interiors);
7c673cae
FG
854
855 // one polygon inside another and boundaries not touching
856 test::apply("mpg10",
857 "MULTIPOLYGON(((0 0,10 0,10 10,0 10)),((1 1,9 1,9 2)))",
858 bg::failure_intersecting_interiors);
859
860 // free space is disconnected
861 test::apply("mpg11",
862 "MULTIPOLYGON(((0 0,1 0,1 1,0 1)),((1 1,2 1,2 2,1 2)),((0 1,0 2,-1 2,-1 -1)),((1 2,1 3,0 3,0 2)))",
863 bg::no_failure);
864
865 // multi-polygon with a polygon inside the hole of another polygon
866 test::apply("mpg12",
867 "MULTIPOLYGON(((0 0,100 0,100 100,0 100),(1 1,1 99,99 99,99 1)),((2 2,98 2,98 98,2 98)))",
868 bg::no_failure);
869 test::apply("mpg13",
870 "MULTIPOLYGON(((0 0,100 0,100 100,0 100),(1 1,1 99,99 99,99 1)),((1 1,98 2,98 98,2 98)))",
871 bg::no_failure);
872
873 // test case suggested by Barend Gehrels: take two valid polygons P1 and
874 // P2 with holes H1 and H2, respectively, and consider P2 to be
875 // fully inside H1; now invalidate the multi-polygon by
876 // considering H2 as a hole of P1 and H1 as a hole of P2; this
877 // should be invalid
878 //
879 // first the valid case:
880 test::apply("mpg14",
881 "MULTIPOLYGON(((0 0,100 0,100 100,0 100),(1 1,1 99,99 99,99 1)),((2 2,98 2,98 98,2 98),(3 3,3 97,97 97,97 3)))",
882 bg::no_failure);
883 // and the invalid case:
884 test::apply("mpg15",
885 "MULTIPOLYGON(((0 0,100 0,100 100,0 100),(3 3,3 97,97 97,97 3)),((2 2,98 2,98 98,2 98),(1 1,1 99,99 99,99 1)))",
886 bg::failure_interior_rings_outside);
887
888 test::apply
889 ("mpg16",
890 "MULTIPOLYGON(((-1 4,8 -10,-10 10,7 -6,8 -2,\
891 -10 10,-10 1,-3 -4,4 1,-1 2,4 3,-8 10,-5 -9,-1 6,-5 0)),\
892 ((-10 -3,-8 1,2 -8,-2 6,-4 0,8 -5,-1 5,8 2)),\
893 ((-6 -10,1 10,4 -8,-7 -2,2 0,-4 3,-10 9)),\
894 ((10 -1,-2 8,-7 3,-6 8,-9 -7,7 -5)),\
895 ((7 7,-4 -4,9 -8,-10 -6)))",
896 bg::failure_wrong_orientation);
897
898 test::apply
899 ("mpg17",
900 "MULTIPOLYGON(((-1 4,8 -10,-10 10,7 -6,8 -2,\
901 -10 10,-10 1,-3 -4,4 1,-1 2,4 3,-8 10,-5 -9,-1 6,-5 0)),\
902 ((-10 -3,-8 1,2 -8,-2 6,-4 0,8 -5,-1 5,8 2)),\
903 ((-6 -10,-10 9,-4 3,2 0,-7 -2,4 -8,1 10)),\
904 ((10 -1,-2 8,-7 3,-6 8,-9 -7,7 -5)),\
905 ((7 7,-10 -6,9 -8,-4 -4)))",
906 bg::failure_spikes);
907
908 // test cases coming from buffer
909 {
910 std::string wkt = "MULTIPOLYGON(((1.1713032141645456 -0.9370425713316364,5.1713032141645456 4.0629574286683638,4.7808688094430307 4.3753049524455756,4.7808688094430307 4.3753049524455756,0.7808688094430304 -0.6246950475544243,0.7808688094430304 -0.6246950475544243,1.1713032141645456 -0.9370425713316364)))";
911
912 G open_mpgn = from_wkt<G>(wkt);
913 bg::reverse(open_mpgn);
914
915 test::apply("mpg18", open_mpgn, bg::failure_wrong_orientation);
916 }
917 {
918 std::string wkt = "MULTIPOLYGON(((5.2811206375710933 9.9800205994776228,5.2446420208654896 10.0415020265598844,5.1807360092909640 10.1691699739962242,5.1261005500004773 10.3010716408018013,5.0810140527710059 10.4365348863171388,5.0457062680576819 10.5748694208940446,5.0203571162381344 10.7153703234534277,5.0050957707794934 10.8573216336015328,5.0000000000000000 10.9999999999999964,5.0050957707794925 11.1426783663984619,5.0203571162381344 11.2846296765465670,5.0457062680576801 11.4251305791059501,5.0810140527710042 11.5634651136828559,5.1261005500004755 11.6989283591981934,5.1807360092909622 11.8308300260037704,5.2446420208654869 11.9584979734401102,5.3174929343376363 12.0812816349111927,5.3989175181512774 12.1985553330226910,5.4885008512914810 12.3097214678905669,5.5857864376269024 12.4142135623730923,5.6902785321094269 12.5114991487085145,5.8014446669773028 12.6010824818487190,5.9187183650888020 12.6825070656623602,6.0415020265598844 12.7553579791345104,6.1691699739962260 12.8192639907090360,6.3010716408018030 12.8738994499995236,6.4365348863171405 12.9189859472289950,6.5748694208940472 12.9542937319423199,6.7153703234534312 12.9796428837618656,6.8573216336015381 12.9949042292205075,7.0000000000000036 13.0000000000000000,7.1426783663984690 12.9949042292205075,7.2846296765465750 12.9796428837618656,7.4251305791059590 12.9542937319423181,7.5634651136828657 12.9189859472289932,7.6989283591982032 12.8738994499995201,7.8308300260037802 12.8192639907090324,7.9584979734401209 12.7553579791345069,8.0812816349112033 12.6825070656623566,8.1985553330227017 12.6010824818487137,8.3097214678905793 12.5114991487085092,8.4142135623731029 12.4142135623730869,8.5114991487085252 12.3097214678905598,8.6010824818487297 12.1985553330226821,8.6825070656623708 12.0812816349111838,8.7553579791345193 11.9584979734400996,8.8192639907090431 11.8308300260037580,8.8738994499995290 11.6989283591981810,8.9189859472290003 11.5634651136828417,8.9542937319423235 11.4251305791059359,8.9796428837618691 11.2846296765465510,8.9949042292205093 11.1426783663984441,9.0000000000000000 11.0000000000000000,8.9949042292205075 10.8573216336015346,8.9796428837618656 10.7153703234534294,8.9542937319423181 10.5748694208940464,8.9189859472289950 10.4365348863171405,8.8738994499995236 10.3010716408018030,8.8192639907090360 10.1691699739962278,8.7553579791345122 10.0415020265598862,8.7188787869375428 9.9800200826281831,8.8573216336015381 9.9949042292205075,9.0000000000000036 10.0000000000000000,9.1426783663984690 9.9949042292205075,9.2846296765465759 9.9796428837618656,9.4251305791059590 9.9542937319423181,9.5634651136828648 9.9189859472289932,9.6989283591982041 9.8738994499995201,9.8308300260037793 9.8192639907090324,9.9584979734401209 9.7553579791345069,10.0812816349112033 9.6825070656623566,10.1985553330227017 9.6010824818487137,10.3097214678905793 9.5114991487085092,10.4142135623731029 9.4142135623730869,10.5114991487085252 9.3097214678905598,10.6010824818487297 9.1985553330226821,10.6825070656623708 9.0812816349111838,10.7553579791345193 8.9584979734400996,10.8192639907090431 8.8308300260037580,10.8738994499995290 8.6989283591981810,10.9189859472290003 8.5634651136828417,10.9542937319423235 8.4251305791059359,10.9796428837618691 8.2846296765465510,10.9949042292205093 8.1426783663984441,11.0000000000000000 8.0000000000000000,10.9949042292205075 7.8573216336015355,10.9796428837618656 7.7153703234534294,10.9542937319423181 7.5748694208940464,10.9189859472289950 7.4365348863171405,10.8738994499995236 7.3010716408018030,10.8192639907090360 7.1691699739962269,10.7553579791345122 7.0415020265598862,10.6825070656623620 6.9187183650888047,10.6010824818487208 6.8014446669773063,10.5114991487085163 6.6902785321094296,10.4142135623730958 6.5857864376269051,10.3097214678905704 6.4885008512914837,10.1985553330226946 6.3989175181512792,10.0812816349111962 6.3174929343376380,9.9584979734401138 6.2446420208654887,9.8308300260037740 6.1807360092909640,9.6989283591981970 6.1261005500004764,9.5634651136828595 6.0810140527710050,9.4251305791059536 6.0457062680576810,9.2846296765465706 6.0203571162381344,9.1426783663984654 6.0050957707794925,9.0000000000000018 6.0000000000000000,8.8573216336015363 6.0050957707794925,8.7153703234534312 6.0203571162381344,8.5748694208940481 6.0457062680576810,8.4365348863171423 6.0810140527710050,8.3010716408018048 6.1261005500004764,8.1691699739962278 6.1807360092909622,8.0415020265598880 6.2446420208654878,7.9187183650888064 6.3174929343376363,7.8014446669773072 6.3989175181512783,7.6902785321094314 6.4885008512914819,7.5857864376269060 6.5857864376269033,7.4885008512914846 6.6902785321094278,7.3989175181512810 6.8014446669773045,7.3174929343376389 6.9187183650888029,7.2446420208654896 7.0415020265598844,7.1807360092909640 7.1691699739962251,7.1261005500004773 7.3010716408018013,7.0810140527710059 7.4365348863171379,7.0457062680576819 7.5748694208940437,7.0203571162381344 7.7153703234534268,7.0050957707794934 7.8573216336015328,7.0000000000000000 7.9999999999999973,7.0050957707794925 8.1426783663984619,7.0203571162381344 8.2846296765465670,7.0457062680576801 8.4251305791059501,7.0810140527710042 8.5634651136828559,7.1261005500004755 8.6989283591981934,7.1807360092909622 8.8308300260037704,7.2446420208654869 8.9584979734401102,7.2811219724467575 9.0199799990140797,7.1426783663984654 9.0050957707794925,7.0000000000000009 9.0000000000000000,6.8573216336015363 9.0050957707794925,6.7188786030357956 9.0199806804111571,6.7553579791345184 8.9584979734400996,6.8192639907090431 8.8308300260037580,6.8738994499995290 8.6989283591981810,6.9189859472290003 8.5634651136828417,6.9542937319423235 8.4251305791059359,6.9796428837618683 8.2846296765465510,6.9949042292205084 8.1426783663984441,7.0000000000000000 8.0000000000000000,6.9949042292205075 7.8573216336015355,6.9796428837618656 7.7153703234534294,6.9542937319423190 7.5748694208940464,6.9189859472289950 7.4365348863171405,6.8738994499995236 7.3010716408018030,6.8192639907090369 7.1691699739962269,6.7553579791345113 7.0415020265598862,6.6825070656623620 6.9187183650888047,6.6010824818487208 6.8014446669773063,6.5114991487085163 6.6902785321094296,6.4142135623730949 6.5857864376269051,6.3097214678905704 6.4885008512914837,6.1985553330226946 6.3989175181512792,6.0812816349111953 6.3174929343376380,5.9584979734401138 6.2446420208654887,5.8308300260037731 6.1807360092909640,5.6989283591981970 6.1261005500004764,5.5634651136828603 6.0810140527710050,5.4251305791059536 6.0457062680576810,5.2846296765465715 6.0203571162381344,5.1426783663984654 6.0050957707794925,5.0000000000000009 6.0000000000000000,4.8573216336015363 6.0050957707794925,4.7153703234534312 6.0203571162381344,4.5748694208940481 6.0457062680576810,4.4365348863171423 6.0810140527710050,4.3010716408018048 6.1261005500004764,4.1691699739962287 6.1807360092909622,4.0415020265598880 6.2446420208654878,3.9187183650888064 6.3174929343376363,3.8014446669773077 6.3989175181512783,3.6902785321094314 6.4885008512914819,3.5857864376269064 6.5857864376269033,3.4885008512914846 6.6902785321094278,3.3989175181512805 6.8014446669773045,3.3174929343376389 6.9187183650888029,3.2446420208654896 7.0415020265598844,3.1807360092909640 7.1691699739962251,3.1261005500004773 7.3010716408018013,3.0810140527710059 7.4365348863171379,3.0457062680576819 7.5748694208940437,3.0203571162381349 7.7153703234534268,3.0050957707794934 7.8573216336015328,3.0000000000000000 7.9999999999999973,3.0050957707794925 8.1426783663984619,3.0203571162381344 8.2846296765465670,3.0457062680576801 8.4251305791059501,3.0810140527710042 8.5634651136828559,3.1261005500004755 8.6989283591981934,3.1807360092909618 8.8308300260037704,3.2446420208654869 8.9584979734401102,3.3174929343376358 9.0812816349111927,3.3989175181512770 9.1985553330226910,3.4885008512914810 9.3097214678905669,3.5857864376269024 9.4142135623730923,3.6902785321094269 9.5114991487085145,3.8014446669773028 9.6010824818487190,3.9187183650888020 9.6825070656623602,4.0415020265598844 9.7553579791345104,4.1691699739962260 9.8192639907090360,4.3010716408018030 9.8738994499995236,4.4365348863171405 9.9189859472289950,4.5748694208940472 9.9542937319423199,4.7153703234534312 9.9796428837618656,4.8573216336015381 9.9949042292205075,5.0000000000000036 10.0000000000000000,5.1426783663984690 9.9949042292205075)))";
919
920 G open_mpgn = from_wkt<G>(wkt);
921 bg::reverse(open_mpgn);
922
923 // polygon has a self-touching point
924 test::apply("mpg19", open_mpgn, bg::failure_self_intersections);
925 }
926 {
927 std::string wkt = "MULTIPOLYGON(((-1.1713032141645421 0.9370425713316406,-1.2278293047051545 0.8616467945203863,-1.2795097139219473 0.7828504914601357,-1.3261404828502752 0.7009646351604617,-1.3675375811487496 0.6163123916860891,-1.4035376333829217 0.5292278447680804,-1.4339985637934827 0.4400546773279756,-1.4588001570043776 0.3491448151183161,-1.4778445324579732 0.2568570378324778,-1.4910565307049013 0.1635555631651331,-1.4983840100240693 0.0696086094114048,-1.4997980522022116 -0.0246130577225216,-1.4952930766608652 -0.1187375883622537,-1.4848868624803642 -0.2123935159867641,-1.4686204782339323 -0.3052112234370423,-1.4465581199087858 -0.3968244016261590,-1.4187868575539013 -0.4868714951938814,-1.3854162916543107 -0.5749971294005020,-1.3465781205880585 -0.6608535126285795,-1.3024256208728704 -0.7441018089575634,-1.2531330422537639 -0.8244134753943718,-1.1988949200189114 -0.9014715584824893,-1.1399253072577331 -0.9749719451724563,-1.0764569300911435 -1.0446245630171400,-1.0087402692078766 -1.1101545249551616,-0.9370425713316382 -1.1713032141645441,-0.8616467945203836 -1.2278293047051563,-0.7828504914601331 -1.2795097139219491,-0.7009646351604588 -1.3261404828502767,-0.6163123916860862 -1.3675375811487509,-0.5292278447680773 -1.4035376333829228,-0.4400546773279725 -1.4339985637934838,-0.3491448151183129 -1.4588001570043785,-0.2568570378324746 -1.4778445324579736,-0.1635555631651299 -1.4910565307049017,-0.0696086094114016 -1.4983840100240695,0.0246130577225248 -1.4997980522022114,0.1187375883622569 -1.4952930766608650,0.2123935159867673 -1.4848868624803639,0.3052112234370455 -1.4686204782339316,0.3968244016261621 -1.4465581199087849,0.4868714951938845 -1.4187868575539002,0.5749971294005050 -1.3854162916543096,0.6608535126285824 -1.3465781205880569,0.7441018089575662 -1.3024256208728686,0.8244134753943745 -1.2531330422537621,0.9014715584824917 -1.1988949200189096,0.9749719451724583 -1.1399253072577313,1.0446245630171418 -1.0764569300911420,1.1101545249551634 -1.0087402692078746,1.1713032141645456 -0.9370425713316364,5.1713032141645456 4.0629574286683638,5.1713032141645439 4.0629574286683621,5.2278293047051561 4.1383532054796159,5.2795097139219491 4.2171495085398671,5.3261404828502767 4.2990353648395407,5.3675375811487509 4.3836876083139131,5.4035376333829230 4.4707721552319217,5.4339985637934838 4.5599453226720268,5.4588001570043785 4.6508551848816859,5.4778445324579739 4.7431429621675241,5.4910565307049017 4.8364444368348689,5.4983840100240693 4.9303913905885972,5.4997980522022116 5.0246130577225232,5.4952930766608645 5.1187375883622552,5.4848868624803639 5.2123935159867658,5.4686204782339320 5.3052112234370439,5.4465581199087856 5.3968244016261604,5.4187868575539007 5.4868714951938822,5.3854162916543107 5.5749971294005025,5.3465781205880578 5.6608535126285799,5.3024256208728699 5.7441018089575637,5.2531330422537632 5.8244134753943726,5.1988949200189110 5.9014715584824895,5.1399253072577329 5.9749719451724559,5.0764569300911440 6.0446245630171394,5.0087402692078768 6.1101545249551616,4.9370425713316379 6.1713032141645439,4.8616467945203841 6.2278293047051561,4.7828504914601337 6.2795097139219482,4.7009646351604593 6.3261404828502759,4.6163123916860869 6.3675375811487509,4.5292278447680783 6.4035376333829230,4.4400546773279732 6.4339985637934838,4.3491448151183141 6.4588001570043785,4.2568570378324750 6.4778445324579739,4.1635555631651311 6.4910565307049017,4.0696086094114028 6.4983840100240693,3.9753869422774759 6.4997980522022116,3.8812624116377439 6.4952930766608645,3.7876064840132333 6.4848868624803639,3.6947887765629552 6.4686204782339320,3.6031755983738387 6.4465581199087847,3.5131285048061165 6.4187868575539007,3.4250028705994957 6.3854162916543098,3.3391464873714183 6.3465781205880578,3.2558981910424345 6.3024256208728691,3.1755865246056261 6.2531330422537623,3.0985284415175087 6.1988949200189101,3.0250280548275423 6.1399253072577320,2.9553754369828584 6.0764569300911422,2.8898454750448366 6.0087402692078751,2.8286967858354544 5.9370425713316362,-1.1713032141645456 0.9370425713316364,-1.1713032141645421 0.9370425713316406)))";
928
929 G open_mpgn = from_wkt<G>(wkt);
930 bg::reverse(open_mpgn);
931
932 // polygon contains a spike
933 test::apply("mpg20", open_mpgn, bg::failure_spikes);
934 }
935}
936
937BOOST_AUTO_TEST_CASE( test_failure_multipolygon )
938{
939 test_open_multipolygons<point_type>();
940}
941
942BOOST_AUTO_TEST_CASE( test_failure_variant )
943{
944#ifdef BOOST_GEOMETRY_TEST_DEBUG
945 std::cout << std::endl << std::endl;
946 std::cout << "************************************" << std::endl;
947 std::cout << " is_valid_failure: variant support" << std::endl;
948 std::cout << "************************************" << std::endl;
949#endif
950
951 typedef bg::model::polygon<point_type> polygon_type; // cw, closed
952
953 typedef boost::variant
954 <
955 linestring_type, multi_linestring_type, polygon_type
956 > variant_geometry;
957 typedef test_failure<variant_geometry> test;
958
959 variant_geometry vg;
960
961 linestring_type valid_linestring =
962 from_wkt<linestring_type>("LINESTRING(0 0,1 0)");
963 multi_linestring_type invalid_multi_linestring =
964 from_wkt<multi_linestring_type>("MULTILINESTRING((0 0,1 0),(0 0))");
965 polygon_type valid_polygon =
966 from_wkt<polygon_type>("POLYGON((0 0,1 1,1 0,0 0))");
967 polygon_type invalid_polygon =
968 from_wkt<polygon_type>("POLYGON((0 0,2 2,2 0,1 0))");
969
970 vg = valid_linestring;
971 test::apply("v01", vg, bg::no_failure);
972 vg = invalid_multi_linestring;
973 test::apply("v02", vg, bg::failure_few_points);
974 vg = valid_polygon;
975 test::apply("v03", vg, bg::no_failure);
976 vg = invalid_polygon;
977 test::apply("v04", vg, bg::failure_not_closed);
978}