]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/geometry/test/algorithms/is_valid_failure.cpp
import quincy beta 17.1.0
[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
92f5a8d4 4// Copyright (c) 2015-2018, Oracle and/or its affiliates.
7c673cae
FG
5
6// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
92f5a8d4 7// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
7c673cae
FG
8
9// Licensed under the Boost Software License version 1.0.
10// http://www.boost.org/users/license.html
11
12#ifndef BOOST_TEST_MODULE
13#define BOOST_TEST_MODULE test_is_valid_failure
14#endif
15
16#include <iostream>
17#include <string>
18
19#include <boost/variant/variant.hpp>
20
21#include <boost/test/included/unit_test.hpp>
22
23#include <boost/geometry/core/cs.hpp>
24#include <boost/geometry/geometries/geometries.hpp>
25#include <boost/geometry/algorithms/is_valid.hpp>
26#include <boost/geometry/algorithms/reverse.hpp>
27#include <boost/geometry/algorithms/validity_failure_type.hpp>
28#include <boost/geometry/io/wkt/wkt.hpp>
29
30#include <boost/geometry/strategies/strategies.hpp>
31
32#include <from_wkt.hpp>
33
34
35namespace bg = ::boost::geometry;
36
37typedef bg::validity_failure_type failure_type;
38
39typedef bg::model::point<double, 2, bg::cs::cartesian> point_type;
40typedef bg::model::segment<point_type> segment_type;
41typedef bg::model::box<point_type> box_type;
42typedef bg::model::linestring<point_type> linestring_type;
43typedef bg::model::multi_linestring<linestring_type> multi_linestring_type;
44typedef bg::model::multi_point<point_type> multi_point_type;
45
46
47char const* to_string(failure_type failure)
48{
49 switch (failure)
50 {
51 case bg::no_failure:
52 return "no_failure";
53 case bg::failure_few_points:
54 return "failure_few_points";
55 case bg::failure_wrong_topological_dimension:
56 return "failure_wrong_topological_dimension";
57 case bg::failure_spikes:
58 return "failure_spikes";
59 case bg::failure_duplicate_points:
60 return "failure_duplicate_points";
61 case bg::failure_not_closed:
62 return "failure_not_closed";
63 case bg::failure_self_intersections:
64 return "failure_self_intersections";
65 case bg::failure_wrong_orientation:
66 return "failure_wrong_orientation";
67 case bg::failure_interior_rings_outside:
68 return "failure_interior_rings_outside";
69 case bg::failure_nested_interior_rings:
70 return "failure_nested_interior_rings";
71 case bg::failure_disconnected_interior:
72 return "failure_disconnected_interior";
73 case bg::failure_intersecting_interiors:
74 return "failure_intersecting_interiors";
75 case bg::failure_wrong_corner_order:
76 return "failure_wrong_corner_order";
77 default:
78 return ""; // to avoid warnings (-Wreturn-type)
79 }
80}
81
82
83template <typename Geometry>
84struct test_failure
85{
86 static inline void apply(std::string const& case_id,
87 Geometry const& geometry,
88 failure_type expected)
89 {
90 failure_type detected;
91 bg::is_valid(geometry, detected);
92 std::string expected_msg = bg::validity_failure_type_message(expected);
93 std::string detected_msg;
94 bg::is_valid(geometry, detected_msg);
95 std::string detected_msg_short
96 = detected_msg.substr(0, expected_msg.length());
97
98#ifdef BOOST_GEOMETRY_TEST_DEBUG
99 std::cout << "----------------------" << std::endl;
100 std::cout << "case id: " << case_id << std::endl;
101 std::cout << "Geometry: " << bg::wkt(geometry) << std::endl;
102 std::cout << "Expected reason: " << expected_msg << std::endl;
103 std::cout << "Detected reason: " << detected_msg << std::endl;
104 std::cout << "Expected: " << to_string(expected) << std::endl;
105 std::cout << "Detected: " << to_string(detected) << std::endl;
106 std::cout << std::endl;
107#endif
108
109 BOOST_CHECK_MESSAGE(expected == detected,
110 "case id: " << case_id
111 << ", Geometry: " << bg::wkt(geometry)
112 << ", expected: " << to_string(expected)
113 << ", detected: " << to_string(detected));
114
115 BOOST_CHECK(detected_msg_short == expected_msg);
116
117#ifdef BOOST_GEOMETRY_TEST_DEBUG
118 std::cout << "----------------------" << std::endl;
119 std::cout << std::endl << std::endl;
120#endif
121 }
122
123 static inline void apply(std::string const& case_id,
124 std::string const& wkt,
125 failure_type expected)
126 {
127 Geometry geometry = from_wkt<Geometry>(wkt);
128 apply(case_id, geometry, expected);
129 }
130};
131
132
133BOOST_AUTO_TEST_CASE( test_failure_point )
134{
135#ifdef BOOST_GEOMETRY_TEST_DEBUG
136 std::cout << std::endl << std::endl;
137 std::cout << "************************************" << std::endl;
138 std::cout << " is_valid_failure: POINT " << std::endl;
139 std::cout << "************************************" << std::endl;
140#endif
141
142 typedef point_type G;
143 typedef test_failure<G> test;
144
145 test::apply("p01", "POINT(0 0)", bg::no_failure);
146}
147
148BOOST_AUTO_TEST_CASE( test_failure_multipoint )
149{
150#ifdef BOOST_GEOMETRY_TEST_DEBUG
151 std::cout << std::endl << std::endl;
152 std::cout << "************************************" << std::endl;
153 std::cout << " is_valid_failure: MULTIPOINT " << std::endl;
154 std::cout << "************************************" << std::endl;
155#endif
156
157 typedef multi_point_type G;
158 typedef test_failure<G> test;
159
160 test::apply("mp01", "MULTIPOINT()", bg::no_failure);
161 test::apply("mp02", "MULTIPOINT(0 0,0 0)", bg::no_failure);
162 test::apply("mp03", "MULTIPOINT(0 0,1 0,1 1,0 1)", bg::no_failure);
163 test::apply("mp04", "MULTIPOINT(0 0,1 0,1 1,1 0,0 1)", bg::no_failure);
164}
165
166BOOST_AUTO_TEST_CASE( test_failure_segment )
167{
168#ifdef BOOST_GEOMETRY_TEST_DEBUG
169 std::cout << std::endl << std::endl;
170 std::cout << "************************************" << std::endl;
171 std::cout << " is_valid_failure: SEGMENT " << std::endl;
172 std::cout << "************************************" << std::endl;
173#endif
174
175 typedef segment_type G;
176 typedef test_failure<G> test;
177
178 test::apply("s01",
179 "SEGMENT(0 0,0 0)",
180 bg::failure_wrong_topological_dimension);
181 test::apply("s02", "SEGMENT(0 0,1 0)", bg::no_failure);
182}
183
184BOOST_AUTO_TEST_CASE( test_failure_box )
185{
186#ifdef BOOST_GEOMETRY_TEST_DEBUG
187 std::cout << std::endl << std::endl;
188 std::cout << "************************************" << std::endl;
189 std::cout << " is_valid_failure: BOX " << std::endl;
190 std::cout << "************************************" << std::endl;
191#endif
192
193 typedef box_type G;
194 typedef test_failure<G> test;
195
196 // boxes where the max corner and below and/or to the left of min corner
197 test::apply("b01",
198 "BOX(0 0,-1 0)",
199 bg::failure_wrong_topological_dimension);
200 test::apply("b02", "BOX(0 0,0 -1)", bg::failure_wrong_corner_order);
201 test::apply("b03", "BOX(0 0,-1 -1)", bg::failure_wrong_corner_order);
202
203 // boxes of zero area; they are not 2-dimensional, so invalid
204 test::apply("b04", "BOX(0 0,0 0)", bg::failure_wrong_topological_dimension);
205 test::apply("b05", "BOX(0 0,1 0)", bg::failure_wrong_topological_dimension);
206 test::apply("b06", "BOX(0 0,0 1)", bg::failure_wrong_topological_dimension);
207
208 test::apply("b07", "BOX(0 0,1 1)", bg::no_failure);
209}
210
211BOOST_AUTO_TEST_CASE( test_failure_linestring )
212{
213#ifdef BOOST_GEOMETRY_TEST_DEBUG
214 std::cout << std::endl << std::endl;
215 std::cout << "************************************" << std::endl;
216 std::cout << " is_valid_failure: LINESTRING " << std::endl;
217 std::cout << "************************************" << std::endl;
218#endif
219
220 typedef linestring_type G;
221 typedef test_failure<G> test;
222
223 // empty linestring
224 test::apply("l01", "LINESTRING()", bg::failure_few_points);
225
226 // 1-point linestrings
227 test::apply("l02", "LINESTRING(0 0)", bg::failure_few_points);
228 test::apply("l03",
229 "LINESTRING(0 0,0 0)",
230 bg::failure_wrong_topological_dimension);
231 test::apply("l04",
232 "LINESTRING(0 0,0 0,0 0)",
233 bg::failure_wrong_topological_dimension);
234
235 // 2-point linestrings
236 test::apply("l05", "LINESTRING(0 0,1 2)", bg::no_failure);
237 test::apply("l06", "LINESTRING(0 0,1 2,1 2)", bg::no_failure);
238 test::apply("l07", "LINESTRING(0 0,0 0,1 2,1 2)", bg::no_failure);
239 test::apply("l08", "LINESTRING(0 0,0 0,0 0,1 2,1 2)", bg::no_failure);
240
241 // 3-point linestring
242 test::apply("l09", "LINESTRING(0 0,1 0,2 10)", bg::no_failure);
243
244 // linestrings with spikes
245 test::apply("l10", "LINESTRING(0 0,1 2,0 0)", bg::no_failure);
246}
247
248BOOST_AUTO_TEST_CASE( test_failure_multilinestring )
249{
250#ifdef BOOST_GEOMETRY_TEST_DEBUG
251 std::cout << std::endl << std::endl;
252 std::cout << "************************************" << std::endl;
253 std::cout << " is_valid_failure: MULTILINESTRING " << std::endl;
254 std::cout << "************************************" << std::endl;
255#endif
256
257 typedef multi_linestring_type G;
258 typedef test_failure<G> test;
259
260 // empty multilinestring
261 test::apply("mls01", "MULTILINESTRING()", bg::no_failure);
262
263 // multilinestring with empty linestring(s)
264 test::apply("mls02", "MULTILINESTRING(())", bg::failure_few_points);
265 test::apply("mls03", "MULTILINESTRING((),(),())", bg::failure_few_points);
266 test::apply("mls04",
267 "MULTILINESTRING((),(0 1,1 0))",
268 bg::failure_few_points);
269
270 // multilinestring with invalid linestrings
271 test::apply("mls05",
272 "MULTILINESTRING((0 0),(0 1,1 0))",
273 bg::failure_few_points);
274 test::apply("mls06",
275 "MULTILINESTRING((0 0,0 0),(0 1,1 0))",
276 bg::failure_wrong_topological_dimension);
277 test::apply("mls07", "MULTILINESTRING((0 0),(1 0))",
278 bg::failure_few_points);
279 test::apply("mls08",
280 "MULTILINESTRING((0 0,0 0),(1 0,1 0))",
281 bg::failure_wrong_topological_dimension);
282 test::apply("mls09",
283 "MULTILINESTRING((0 0),(0 0))",
284 bg::failure_few_points);
285 test::apply("mls10",
286 "MULTILINESTRING((0 0,1 0,0 0),(5 0))",
287 bg::failure_few_points);
288
289 // multilinstring that has linestrings with spikes
290 test::apply("mls11",
291 "MULTILINESTRING((0 0,1 0,0 0),(5 0,1 0,4 1))",
292 bg::no_failure);
293 test::apply("mls12",
294 "MULTILINESTRING((0 0,1 0,0 0),(1 0,2 0))",
295 bg::no_failure);
296
297 // valid multilinestrings
298 test::apply("mls13",
299 "MULTILINESTRING((0 0,1 0,2 0),(5 0,1 0,4 1))",
300 bg::no_failure);
301 test::apply("mls14",
302 "MULTILINESTRING((0 0,1 0,2 0),(1 0,2 0))",
303 bg::no_failure);
304 test::apply("mls15",
305 "MULTILINESTRING((0 0,1 1),(0 1,1 0))",
306 bg::no_failure);
307 test::apply("mls16",
308 "MULTILINESTRING((0 0,1 1,2 2),(0 1,1 0,2 2))",
309 bg::no_failure);
310}
311
312template <typename Point>
313inline void test_open_rings()
314{
315#ifdef BOOST_GEOMETRY_TEST_DEBUG
316 std::cout << std::endl << std::endl;
317 std::cout << "************************************" << std::endl;
318 std::cout << " is_valid_failure: RING (open) " << std::endl;
319 std::cout << "************************************" << std::endl;
320#endif
321
322 typedef bg::model::ring<Point, false, false> G; // ccw, open ring
323 typedef test_failure<G> test;
324
325 // not enough points
326 test::apply("r01", "POLYGON(())", bg::failure_few_points);
327 test::apply("r02", "POLYGON((0 0))", bg::failure_few_points);
328 test::apply("r03", "POLYGON((0 0,1 0))", bg::failure_few_points);
329
330 // duplicate points
331 test::apply("r04",
332 "POLYGON((0 0,0 0,0 0))",
333 bg::failure_wrong_topological_dimension);
334 test::apply("r05",
335 "POLYGON((0 0,1 0,1 0))",
336 bg::failure_wrong_topological_dimension);
337 test::apply("r06",
338 "POLYGON((0 0,1 0,0 0))",
339 bg::failure_wrong_topological_dimension);
340 test::apply("r07", "POLYGON((0 0,1 0,1 1,0 0,0 0))", bg::no_failure);
341 test::apply("r08", "POLYGON((0 0,1 0,1 0,1 1))", bg::no_failure);
342 test::apply("r09", "POLYGON((0 0,1 0,1 0,1 1,0 0))", bg::no_failure);
343
344 // with spikes
345 test::apply("r10", "POLYGON((0 0,2 0,2 2,0 2,1 2))", bg::failure_spikes);
346 test::apply("r11", "POLYGON((0 0,2 0,1 0,2 2))", bg::failure_spikes);
347 test::apply("r12",
348 "POLYGON((0 0,1 0,2 0,1 0,4 0,4 4))",
349 bg::failure_spikes);
350 test::apply("r13", "POLYGON((0 0,2 0,2 2,1 0))", bg::failure_spikes);
351 test::apply("r14", "POLYGON((0 0,2 0,1 0))", bg::failure_spikes);
352 test::apply("r15",
353 "POLYGON((0 0,5 0,5 5,4 4,5 5,0 5))",
354 bg::failure_spikes);
355 test::apply("r16",
356 "POLYGON((0 0,5 0,5 5,4 4,3 3,5 5,0 5))",
357 bg::failure_spikes);
358
359 // with spikes and duplicate points
360 test::apply("r17",
361 "POLYGON((0 0,0 0,2 0,2 0,1 0,1 0))",
362 bg::failure_spikes);
363
364 // with self-crossings
365 test::apply("r18",
366 "POLYGON((0 0,5 0,5 5,3 -1,0 5))",
367 bg::failure_self_intersections);
368
369 // with self-crossings and duplicate points
370 test::apply("r19",
371 "POLYGON((0 0,5 0,5 5,5 5,3 -1,0 5,0 5))",
372 bg::failure_self_intersections);
373
374 // with self-intersections
375 test::apply("r20",
376 "POLYGON((0 0,5 0,5 5,3 5,3 0,2 0,2 5,0 5))",
377 bg::failure_self_intersections);
378 test::apply("r21",
379 "POLYGON((0 0,5 0,5 5,3 5,3 0,2 5,0 5))",
380 bg::failure_self_intersections);
381 test::apply("r22",
382 "POLYGON((0 0,5 0,5 1,1 1,1 2,2 2,3 1,4 2,5 2,5 5,0 5))",
383 bg::failure_self_intersections);
384
385 // with self-intersections and duplicate points
386 test::apply("r23",
387 "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))",
388 bg::failure_self_intersections);
389
390 // next two suggested by Adam Wulkiewicz
391 test::apply("r24",
392 "POLYGON((0 0,5 0,5 5,0 5,4 4,2 2,0 5))",
393 bg::failure_self_intersections);
394 test::apply("r25",
395 "POLYGON((0 0,5 0,5 5,1 4,4 4,4 1,0 5))",
396 bg::failure_self_intersections);
397
398 // and a few more
399 test::apply("r26",
400 "POLYGON((0 0,5 0,5 5,4 4,1 4,1 1,4 1,4 4,0 5))",
401 bg::failure_self_intersections);
402 test::apply("r27",
403 "POLYGON((0 0,5 0,5 5,4 4,4 1,1 1,1 4,4 4,0 5))",
404 bg::failure_self_intersections);
405
406 // valid rings
407 test::apply("r28", "POLYGON((0 0,1 0,1 1))", bg::no_failure);
408 test::apply("r29", "POLYGON((1 0,1 1,0 0))", bg::no_failure);
409 test::apply("r30", "POLYGON((0 0,1 0,1 1,0 1))", bg::no_failure);
410 test::apply("r31", "POLYGON((1 0,1 1,0 1,0 0))", bg::no_failure);
411
412 // test cases coming from buffer
413 test::apply("r32",
414 "POLYGON((1.1713032141645456 -0.9370425713316364,\
415 5.1713032141645456 4.0629574286683638,\
416 4.7808688094430307 4.3753049524455756,\
417 4.7808688094430307 4.3753049524455756,\
418 0.7808688094430304 -0.6246950475544243,\
419 0.7808688094430304 -0.6246950475544243))",
420 bg::no_failure);
421
422 // wrong orientation
423 test::apply("r33",
424 "POLYGON((0 0,0 1,1 1,0 0))",
425 bg::failure_wrong_orientation);
426}
427
428template <typename Point>
429void test_closed_rings()
430{
431#ifdef BOOST_GEOMETRY_TEST_DEBUG
432 std::cout << std::endl << std::endl;
433 std::cout << "************************************" << std::endl;
434 std::cout << " is_valid_failure: RING (closed) " << std::endl;
435 std::cout << "************************************" << std::endl;
436#endif
437
438 typedef bg::model::ring<Point, false, true> G; // ccw, closed ring
439 typedef test_failure<G> test;
440
441 // not enough points
442 test::apply("r01c", "POLYGON(())", bg::failure_few_points);
443 test::apply("r02c", "POLYGON((0 0))", bg::failure_few_points);
444 test::apply("r03c", "POLYGON((0 0,0 0))", bg::failure_few_points);
445 test::apply("r04c", "POLYGON((0 0,1 0))", bg::failure_few_points);
446 test::apply("r05c", "POLYGON((0 0,1 0,1 0))", bg::failure_few_points);
447 test::apply("r06c", "POLYGON((0 0,1 0,2 0))", bg::failure_few_points);
448 test::apply("r07c",
449 "POLYGON((0 0,1 0,1 0,2 0))",
450 bg::failure_wrong_topological_dimension);
451 test::apply("r08c",
452 "POLYGON((0 0,1 0,2 0,2 0))",
453 bg::failure_wrong_topological_dimension);
454
455 // boundary not closed
456 test::apply("r09c", "POLYGON((0 0,1 0,1 1,1 2))", bg::failure_not_closed);
457 test::apply("r10c",
458 "POLYGON((0 0,1 0,1 0,1 1,1 1,1 2))",
459 bg::failure_not_closed);
460
461 // with spikes
462 test::apply("r11c", "POLYGON((0 0,1 0,1 0,2 0,0 0))", bg::failure_spikes);
463 test::apply("r12c",
464 "POLYGON((0 0,1 0,1 1,2 2,0.5 0.5,0 1,0 0))",
465 bg::failure_spikes);
466
467 // wrong orientation
468 test::apply("r13c",
469 "POLYGON((0 0,0 1,1 1,2 0,0 0))",
470 bg::failure_wrong_orientation);
471
472}
473
474BOOST_AUTO_TEST_CASE( test_failure_ring )
475{
476 test_open_rings<point_type>();
477 test_closed_rings<point_type>();
478}
479
480
481template <typename Point>
482void test_open_polygons()
483{
484#ifdef BOOST_GEOMETRY_TEST_DEBUG
485 std::cout << std::endl << std::endl;
486 std::cout << "************************************" << std::endl;
487 std::cout << " is_valid_failure: POLYGON (open) " << std::endl;
488 std::cout << "************************************" << std::endl;
489#endif
490
491 typedef bg::model::polygon<Point, false, false> G; // ccw, open
492 typedef test_failure<G> test;
493
494 // not enough points in exterior ring
495 test::apply("pg001", "POLYGON(())", bg::failure_few_points);
496 test::apply("pg002", "POLYGON((0 0))", bg::failure_few_points);
497 test::apply("pg003", "POLYGON((0 0,1 0))", bg::failure_few_points);
498
499 // not enough points in interior ring
500 test::apply("pg004",
501 "POLYGON((0 0,10 0,10 10,0 10),())",
502 bg::failure_few_points);
503 test::apply("pg005",
504 "POLYGON((0 0,10 0,10 10,0 10),(1 1))",
505 bg::failure_few_points);
506 test::apply("pg006",
507 "POLYGON((0 0,10 0,10 10,0 10),(1 1,2 2))",
508 bg::failure_few_points);
509
510 // duplicate points in exterior ring
511 test::apply("pg007",
512 "POLYGON((0 0,0 0,0 0))",
513 bg::failure_wrong_topological_dimension);
514 test::apply("pg008",
515 "POLYGON((0 0,1 0,1 0))",
516 bg::failure_wrong_topological_dimension);
517 test::apply("pg009",
518 "POLYGON((0 0,1 0,0 0))",
519 bg::failure_wrong_topological_dimension);
520 test::apply("pg010", "POLYGON((0 0,1 0,1 1,0 0,0 0))", bg::no_failure);
521 test::apply("pg011", "POLYGON((0 0,1 0,1 0,1 1))", bg::no_failure);
522 test::apply("pg012", "POLYGON((0 0,1 0,1 0,1 1,0 0))", bg::no_failure);
523
524 test::apply("pg013",
525 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 1,1 1))",
526 bg::failure_wrong_topological_dimension);
527 test::apply("pg014",
528 "POLYGON((0 0,10 0,10 10,0 10),(1 1,2 1,2 1))",
529 bg::failure_wrong_topological_dimension);
530 test::apply("pg015",
531 "POLYGON((0 0,10 0,10 10,0 10),(1 1,2 1,1 1))",
532 bg::failure_wrong_topological_dimension);
533 test::apply("pg016",
534 "POLYGON((0 0,10 0,10 10,0 10),(1 1,2 2,2 1,1 1,1 1))",
535 bg::no_failure);
536 test::apply("pg017",
537 "POLYGON((0 0,10 0,10 10,0 10),(1 1,2 2,2 2,2 1))",
538 bg::no_failure);
539 test::apply("pg018",
540 "POLYGON((0 0,10 0,10 10,0 10),(1 1,2 2,2 1,2 1,1 1))",
541 bg::no_failure);
542
543 // with spikes in exterior ring
544 test::apply("pg019", "POLYGON((0 0,2 0,2 2,0 2,1 2))", bg::failure_spikes);
545 test::apply("pg020", "POLYGON((0 0,2 0,1 0,2 2))", bg::failure_spikes);
546 test::apply("pg021",
547 "POLYGON((0 0,1 0,2 0,1 0,4 0,4 4))",
548 bg::failure_spikes);
549 test::apply("pg022", "POLYGON((0 0,2 0,2 2,1 0))", bg::failure_spikes);
550 test::apply("pg023", "POLYGON((0 0,2 0,1 0))", bg::failure_spikes);
551 test::apply("pg024",
552 "POLYGON((0 0,5 0,5 5,4 4,5 5,0 5))",
553 bg::failure_spikes);
554 test::apply("pg025",
555 "POLYGON((0 0,5 0,5 5,4 4,3 3,5 5,0 5))",
556 bg::failure_spikes);
557
558 // with spikes in interior ring
559 test::apply("pg026",
560 "POLYGON((0 0,10 0,10 10,0 10),(1 1,3 1,3 3,1 3,2 3))",
561 bg::failure_spikes);
562 test::apply("pg027",
563 "POLYGON((0 0,10 0,10 10,0 10),(1 1,3 1,2 1,3 3))",
564 bg::failure_spikes);
565 test::apply("pg028",
566 "POLYGON((0 0,10 0,10 10,0 10),(1 1,2 1,3 1,2 1,4 1,4 4))",
567 bg::failure_spikes);
568 test::apply("pg029",
569 "POLYGON((0 0,10 0,10 10,0 10),(1 1,3 1,3 3,2 1))",
570 bg::failure_spikes);
571 test::apply("pg030",
572 "POLYGON((0 0,10 0,10 10,0 10),(1 1,3 1,2 1))",
573 bg::failure_spikes);
574
575 // with self-crossings in exterior ring
576 test::apply("pg031",
577 "POLYGON((0 0,5 0,5 5,3 -1,0 5))",
578 bg::failure_self_intersections);
579
580 // example from Norvald Ryeng
581 test::apply("pg032",
582 "POLYGON((100 1300,140 1300,140 170,100 1700))",
583 bg::failure_wrong_orientation);
584 // and with point order reversed
585 test::apply("pg033",
586 "POLYGON((100 1300,100 1700,140 170,140 1300))",
587 bg::failure_self_intersections);
588
589 // with self-crossings in interior ring
590 // the self-crossing causes the area of the interior ring to have
591 // the wrong sign, hence the "wrong orientation" failure
592 test::apply("pg034",
593 "POLYGON((0 0,10 0,10 10,0 10),(3 3,3 7,4 6,2 6))",
594 bg::failure_wrong_orientation);
595
596 // with self-crossings between rings
597 test::apply("pg035",
598 "POLYGON((0 0,5 0,5 5,0 5),(1 1,2 1,1 -1))",
599 bg::failure_self_intersections);
600
601 // with self-intersections in exterior ring
602 test::apply("pg036",
603 "POLYGON((0 0,5 0,5 5,3 5,3 0,2 0,2 5,0 5))",
604 bg::failure_self_intersections);
605 test::apply("pg037",
606 "POLYGON((0 0,5 0,5 5,3 5,3 0,2 5,0 5))",
607 bg::failure_self_intersections);
608 test::apply("pg038",
609 "POLYGON((0 0,5 0,5 1,1 1,1 2,2 2,3 1,4 2,5 2,5 5,0 5))",
610 bg::failure_self_intersections);
611
612 // next two suggested by Adam Wulkiewicz
613 test::apply("pg039",
614 "POLYGON((0 0,5 0,5 5,0 5,4 4,2 2,0 5))",
615 bg::failure_self_intersections);
616 test::apply("pg040",
617 "POLYGON((0 0,5 0,5 5,1 4,4 4,4 1,0 5))",
618 bg::failure_self_intersections);
619 test::apply("pg041",
620 "POLYGON((0 0,5 0,5 5,4 4,1 4,1 1,4 1,4 4,0 5))",
621 bg::failure_self_intersections);
622 test::apply("pg042",
623 "POLYGON((0 0,5 0,5 5,4 4,4 1,1 1,1 4,4 4,0 5))",
624 bg::failure_self_intersections);
625
626 // with self-intersections in interior ring
627
628 // same comment as for pg034
629 test::apply("pg043",
630 "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))",
631 bg::failure_wrong_orientation);
632
633 // same comment as for pg034
634 test::apply("pg044",
635 "POLYGON((-10 -10,10 -10,10 10,-10 10),(0 0,5 0,5 5,3 5,3 0,2 5,0 5))",
636 bg::failure_wrong_orientation);
637
638 // same comment as for pg034
639 test::apply("pg045",
640 "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))",
641 bg::failure_wrong_orientation);
642
643 // with self-intersections between rings
644 // hole has common segment with exterior ring
645 test::apply("pg046",
646 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 10,2 10,2 1))",
647 bg::failure_self_intersections);
648 test::apply("pg047",
649 "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))",
650 bg::failure_self_intersections);
651 // hole touches exterior ring at one point
652 test::apply("pg048",
653 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 10,2 1))",
654 bg::no_failure);
655
656 // "hole" is outside the exterior ring, but touches it
657 // TODO: return the failure value failure_interior_rings_outside
658 test::apply("pg049",
659 "POLYGON((0 0,10 0,10 10,0 10),(5 10,4 11,6 11))",
660 bg::failure_self_intersections);
661
662 // hole touches exterior ring at vertex
663 test::apply("pg050",
664 "POLYGON((0 0,10 0,10 10,0 10),(0 0,1 4,4 1))",
665 bg::no_failure);
666
667 // "hole" is completely outside the exterior ring
668 test::apply("pg051",
669 "POLYGON((0 0,10 0,10 10,0 10),(20 20,20 21,21 21,21 20))",
670 bg::failure_interior_rings_outside);
671
672 // two "holes" completely outside the exterior ring, that touch
673 // each other
674 test::apply("pg052",
675 "POLYGON((0 0,10 0,10 10,0 10),(20 0,25 10,21 0),(30 0,25 10,31 0))",
676 bg::failure_interior_rings_outside);
677
678 // example from Norvald Ryeng
679 test::apply("pg053",
680 "POLYGON((58 31,56.57 30,62 33),(35 9,28 14,31 16),(23 11,29 5,26 4))",
681 bg::failure_interior_rings_outside);
682 // and with points reversed
683 test::apply("pg054",
684 "POLYGON((58 31,62 33,56.57 30),(35 9,31 16,28 14),(23 11,26 4,29 5))",
685 bg::failure_wrong_orientation);
686
687 // "hole" is completely inside another "hole"
688 test::apply("pg055",
689 "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))",
690 bg::failure_nested_interior_rings);
691 test::apply("pg056",
692 "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))",
693 bg::failure_wrong_orientation);
694
695 // "hole" is inside another "hole" (touching)
696 // TODO: return the failure value failure_nested_interior_rings
697 test::apply("pg057",
698 "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))",
699 bg::failure_self_intersections);
700 // TODO: return the failure value failure_nested_interior_rings
701 test::apply("pg058",
702 "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))",
703 bg::failure_self_intersections);
704 test::apply("pg058a",
705 "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))",
706 bg::failure_wrong_orientation);
707 // TODO: return the failure value failure_nested_interior_rings
708 test::apply("pg059",
709 "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))",
710 bg::failure_self_intersections);
711 test::apply("pg059a",
712 "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))",
713 bg::failure_wrong_orientation);
714 // TODO: return the failure value failure_nested_interior_rings
715 test::apply("pg060",
716 "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))",
717 bg::failure_self_intersections);
718 test::apply("pg060a",
719 "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))",
720 bg::failure_wrong_orientation);
721 // hole touches exterior ring at two points
722 test::apply("pg061",
723 "POLYGON((0 0,10 0,10 10,0 10),(5 0,0 5,5 5))",
724 bg::failure_disconnected_interior);
725
726 // cases with more holes
727 // two holes, touching the exterior at the same point
728 test::apply("pg062",
729 "POLYGON((0 0,10 0,10 10,0 10),(0 0,1 9,2 9),(0 0,9 2,9 1))",
730 bg::no_failure);
731 test::apply("pg063",
732 "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))",
733 bg::no_failure);
734 test::apply("pg063",
735 "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))",
736 bg::no_failure);
737 // two holes, one inside the other
738 // TODO: return the failure value failure_nested_interior_rings
739 test::apply("pg064",
740 "POLYGON((0 0,10 0,10 10,0 10),(0 0,1 9,9 1),(0 0,4 5,5 4))",
741 bg::failure_self_intersections);
742 // 1st hole touches has common segment with 2nd hole
743 test::apply("pg066",
744 "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))",
745 bg::failure_self_intersections);
746 // 1st hole touches 2nd hole at two points
747 test::apply("pg067",
748 "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))",
749 bg::failure_disconnected_interior);
750 // polygon with many holes, where the last two touch at two points
751 test::apply("pg068",
752 "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))",
753 bg::failure_disconnected_interior);
754 // two holes completely inside exterior ring but touching each
755 // other at a point
756 test::apply("pg069",
757 "POLYGON((0 0,10 0,10 10,0 10),(1 1,1 9,2 9),(1 1,9 2,9 1))",
758 bg::no_failure);
759 // four holes, each two touching at different points
760 test::apply("pg070",
761 "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))",
762 bg::no_failure);
763 // five holes, with two pairs touching each at some point, and
764 // fifth hole creating a disconnected component for the interior
765 test::apply("pg071",
766 "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))",
767 bg::failure_disconnected_interior);
768 // five holes, with two pairs touching each at some point, and
769 // fifth hole creating three disconnected components for the interior
770 test::apply("pg072",
771 "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))",
772 bg::failure_disconnected_interior);
773
774 // both examples: a polygon with one hole, where the hole contains
775 // the exterior ring
776 test::apply("pg073",
777 "POLYGON((0 0,1 0,1 1,0 1),(-10 -10,-10 10,10 10,10 -10))",
778 bg::failure_interior_rings_outside);
779 // TODO: return the failure value failure_interior_rings_outside
780 test::apply("pg074",
781 "POLYGON((-10 -10,1 0,1 1,0 1),(-10 -10,-10 10,10 10,10 -10))",
782 bg::failure_self_intersections);
783}
784
785template <typename Point>
786inline void test_doc_example_polygon()
787{
788#ifdef BOOST_GEOMETRY_TEST_DEBUG
789 std::cout << std::endl << std::endl;
790 std::cout << "************************************" << std::endl;
791 std::cout << " is_valid_failure: doc example polygon " << std::endl;
792 std::cout << "************************************" << std::endl;
793#endif
794
795 typedef bg::model::polygon<Point> CCW_CG;
796 typedef test_failure<CCW_CG> test;
797
798 test::apply("pg-doc",
799 "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))",
800 bg::failure_disconnected_interior);
801}
802
803BOOST_AUTO_TEST_CASE( test_failure_polygon )
804{
805 test_open_polygons<point_type>();
806 test_doc_example_polygon<point_type>();
807}
808
809
810template <typename Point>
811void test_open_multipolygons()
812{
813#ifdef BOOST_GEOMETRY_TEST_DEBUG
814 std::cout << std::endl << std::endl;
815 std::cout << "************************************" << std::endl;
816 std::cout << " is_valid_failure: MULTIPOLYGON (open) " << std::endl;
817 std::cout << "************************************" << std::endl;
818#endif
819
820 typedef bg::model::polygon<point_type,false,false> ccw_open_polygon_type;
821 typedef bg::model::multi_polygon<ccw_open_polygon_type> G;
822
823 typedef test_failure<G> test;
824
825 // not enough points
826 test::apply("mpg01", "MULTIPOLYGON()", bg::no_failure);
827 test::apply("mpg02", "MULTIPOLYGON((()))", bg::failure_few_points);
828 test::apply("mpg03", "MULTIPOLYGON(((0 0)),(()))", bg::failure_few_points);
829 test::apply("mpg04", "MULTIPOLYGON(((0 0,1 0)))", bg::failure_few_points);
830
831 // two disjoint polygons
832 test::apply("mpg05",
833 "MULTIPOLYGON(((0 0,1 0,1 1,0 1)),((2 2,3 2,3 3,2 3)))",
834 bg::no_failure);
835
836 // two disjoint polygons with multiple points
837 test::apply("mpg06",
838 "MULTIPOLYGON(((0 0,1 0,1 0,1 1,0 1)),((2 2,3 2,3 3,3 3,2 3)))",
839 bg::no_failure);
840
841 // two polygons touch at a point
842 test::apply("mpg07",
843 "MULTIPOLYGON(((0 0,1 0,1 1,0 1)),((1 1,2 1,2 2,1 2)))",
844 bg::no_failure);
845
846 // two polygons share a segment at a point
847 test::apply("mpg08",
848 "MULTIPOLYGON(((0 0,1.5 0,1.5 1,0 1)),((1 1,2 1,2 2,1 2)))",
849 bg::failure_self_intersections);
850
851 // one polygon inside another and boundaries touching
7c673cae
FG
852 test::apply("mpg09",
853 "MULTIPOLYGON(((0 0,10 0,10 10,0 10)),((0 0,9 1,9 2)))",
b32b8144 854 bg::failure_intersecting_interiors);
92f5a8d4
TL
855 test::apply("mpg09_2",
856 "MULTIPOLYGON(((0 0,5 1,10 0,10 10,0 10)),((1 1,9 1,9 2)))",
857 bg::failure_intersecting_interiors);
7c673cae
FG
858
859 // one polygon inside another and boundaries not touching
860 test::apply("mpg10",
861 "MULTIPOLYGON(((0 0,10 0,10 10,0 10)),((1 1,9 1,9 2)))",
862 bg::failure_intersecting_interiors);
863
864 // free space is disconnected
865 test::apply("mpg11",
866 "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)))",
867 bg::no_failure);
868
869 // multi-polygon with a polygon inside the hole of another polygon
870 test::apply("mpg12",
871 "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)))",
872 bg::no_failure);
873 test::apply("mpg13",
874 "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)))",
875 bg::no_failure);
876
877 // test case suggested by Barend Gehrels: take two valid polygons P1 and
878 // P2 with holes H1 and H2, respectively, and consider P2 to be
879 // fully inside H1; now invalidate the multi-polygon by
880 // considering H2 as a hole of P1 and H1 as a hole of P2; this
881 // should be invalid
882 //
883 // first the valid case:
884 test::apply("mpg14",
885 "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)))",
886 bg::no_failure);
887 // and the invalid case:
888 test::apply("mpg15",
889 "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)))",
890 bg::failure_interior_rings_outside);
891
892 test::apply
893 ("mpg16",
894 "MULTIPOLYGON(((-1 4,8 -10,-10 10,7 -6,8 -2,\
895 -10 10,-10 1,-3 -4,4 1,-1 2,4 3,-8 10,-5 -9,-1 6,-5 0)),\
896 ((-10 -3,-8 1,2 -8,-2 6,-4 0,8 -5,-1 5,8 2)),\
897 ((-6 -10,1 10,4 -8,-7 -2,2 0,-4 3,-10 9)),\
898 ((10 -1,-2 8,-7 3,-6 8,-9 -7,7 -5)),\
899 ((7 7,-4 -4,9 -8,-10 -6)))",
900 bg::failure_wrong_orientation);
901
902 test::apply
903 ("mpg17",
904 "MULTIPOLYGON(((-1 4,8 -10,-10 10,7 -6,8 -2,\
905 -10 10,-10 1,-3 -4,4 1,-1 2,4 3,-8 10,-5 -9,-1 6,-5 0)),\
906 ((-10 -3,-8 1,2 -8,-2 6,-4 0,8 -5,-1 5,8 2)),\
907 ((-6 -10,-10 9,-4 3,2 0,-7 -2,4 -8,1 10)),\
908 ((10 -1,-2 8,-7 3,-6 8,-9 -7,7 -5)),\
909 ((7 7,-10 -6,9 -8,-4 -4)))",
910 bg::failure_spikes);
911
912 // test cases coming from buffer
913 {
914 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)))";
915
916 G open_mpgn = from_wkt<G>(wkt);
917 bg::reverse(open_mpgn);
918
919 test::apply("mpg18", open_mpgn, bg::failure_wrong_orientation);
920 }
921 {
922 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)))";
923
924 G open_mpgn = from_wkt<G>(wkt);
925 bg::reverse(open_mpgn);
926
927 // polygon has a self-touching point
928 test::apply("mpg19", open_mpgn, bg::failure_self_intersections);
929 }
930 {
931 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)))";
932
933 G open_mpgn = from_wkt<G>(wkt);
934 bg::reverse(open_mpgn);
935
936 // polygon contains a spike
937 test::apply("mpg20", open_mpgn, bg::failure_spikes);
938 }
939}
940
941BOOST_AUTO_TEST_CASE( test_failure_multipolygon )
942{
943 test_open_multipolygons<point_type>();
944}
945
946BOOST_AUTO_TEST_CASE( test_failure_variant )
947{
948#ifdef BOOST_GEOMETRY_TEST_DEBUG
949 std::cout << std::endl << std::endl;
950 std::cout << "************************************" << std::endl;
951 std::cout << " is_valid_failure: variant support" << std::endl;
952 std::cout << "************************************" << std::endl;
953#endif
954
955 typedef bg::model::polygon<point_type> polygon_type; // cw, closed
956
957 typedef boost::variant
958 <
959 linestring_type, multi_linestring_type, polygon_type
960 > variant_geometry;
961 typedef test_failure<variant_geometry> test;
962
963 variant_geometry vg;
964
965 linestring_type valid_linestring =
966 from_wkt<linestring_type>("LINESTRING(0 0,1 0)");
967 multi_linestring_type invalid_multi_linestring =
968 from_wkt<multi_linestring_type>("MULTILINESTRING((0 0,1 0),(0 0))");
969 polygon_type valid_polygon =
970 from_wkt<polygon_type>("POLYGON((0 0,1 1,1 0,0 0))");
971 polygon_type invalid_polygon =
972 from_wkt<polygon_type>("POLYGON((0 0,2 2,2 0,1 0))");
973
974 vg = valid_linestring;
975 test::apply("v01", vg, bg::no_failure);
976 vg = invalid_multi_linestring;
977 test::apply("v02", vg, bg::failure_few_points);
978 vg = valid_polygon;
979 test::apply("v03", vg, bg::no_failure);
980 vg = invalid_polygon;
981 test::apply("v04", vg, bg::failure_not_closed);
982}