Barend Gehrels 85e0755ccd [traverse][fix] use two passes, in first pass avoid uu turns to get
the interior rings right at starting points. Second pass use uu, but
only switch source if there are only uu turns found. This fixes most
of the simple cases (complex cases can still go wrong)
2016-03-23 13:25:30 +01:00

534 lines
17 KiB
C++

// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2010-2015 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
// If defined, tests are run without rescaling-to-integer or robustness policy
// Test which would fail then are disabled automatically
// #define BOOST_GEOMETRY_NO_ROBUSTNESS
#include <boost/geometry/algorithms/correct.hpp>
#include <boost/geometry/algorithms/is_valid.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include "test_difference.hpp"
#include <algorithms/test_overlay.hpp>
#include <algorithms/overlay/overlay_cases.hpp>
#include <algorithms/overlay/multi_overlay_cases.hpp>
#ifdef HAVE_TTMATH
# include <boost/geometry/extensions/contrib/ttmath_stub.hpp>
#endif
template <typename P>
void test_all()
{
typedef bg::model::box<P> box;
typedef bg::model::polygon<P> polygon;
typedef bg::model::ring<P> ring;
typedef typename bg::coordinate_type<P>::type ct;
test_one<polygon, polygon, polygon>("simplex_normal",
simplex_normal[0], simplex_normal[1],
3, 12, 2.52636706856656,
3, 12, 3.52636706856656);
test_one<polygon, polygon, polygon>("simplex_with_empty",
simplex_normal[0], polygon_empty,
1, 4, 8.0,
0, 0, 0.0);
test_one<polygon, polygon, polygon>(
"star_ring", example_star, example_ring,
5, 22, 1.1901714,
5, 27, 1.6701714);
test_one<polygon, polygon, polygon>("two_bends",
two_bends[0], two_bends[1],
1, 5, 8.0,
1, 5, 8.0);
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
test_one<polygon, polygon, polygon>("star_comb_15",
star_comb_15[0], star_comb_15[1],
30, 160, 227.658275102812,
30, 198, 480.485775259312);
#endif
test_one<polygon, polygon, polygon>("new_hole",
new_hole[0], new_hole[1],
1, 9, 7.0,
1, 13, 14.0);
test_one<polygon, polygon, polygon>("crossed",
crossed[0], crossed[1],
1, 18, 19.5,
1, 7, 2.5);
test_one<polygon, polygon, polygon>("disjoint",
disjoint[0], disjoint[1],
1, 5, 1.0,
1, 5, 1.0);
// The too small one might be discarded (depending on point-type / compiler)
// We check area only
test_one<polygon, polygon, polygon>("distance_zero",
distance_zero[0], distance_zero[1],
-1, -1, 8.7048386,
-1, -1, 0.0098387,
tolerance(0.001));
test_one<polygon, polygon, polygon>("equal_holes_disjoint",
equal_holes_disjoint[0], equal_holes_disjoint[1],
1, 5, 9.0,
1, 5, 9.0);
test_one<polygon, polygon, polygon>("only_hole_intersections1",
only_hole_intersections[0], only_hole_intersections[1],
2, 10, 1.9090909,
4, 16, 10.9090909);
test_one<polygon, polygon, polygon>("only_hole_intersection2",
only_hole_intersections[0], only_hole_intersections[2],
3, 20, 30.9090909,
4, 16, 10.9090909);
test_one<polygon, polygon, polygon>("first_within_second",
first_within_second[1], first_within_second[0],
1, 10, 24,
0, 0, 0);
test_one<polygon, polygon, polygon>("fitting",
fitting[0], fitting[1],
1, 9, 21.0,
1, 4, 4.0,
1, 5, 25.0);
test_one<polygon, polygon, polygon>("identical",
identical[0], identical[1],
0, 0, 0.0,
0, 0, 0.0);
test_one<polygon, polygon, polygon>("intersect_exterior_and_interiors_winded",
intersect_exterior_and_interiors_winded[0], intersect_exterior_and_interiors_winded[1],
4, 20, 11.533333,
5, 26, 29.783333);
test_one<polygon, polygon, polygon>("intersect_holes_intersect_and_disjoint",
intersect_holes_intersect_and_disjoint[0], intersect_holes_intersect_and_disjoint[1],
2, 16, 15.75,
3, 17, 6.75);
test_one<polygon, polygon, polygon>("intersect_holes_intersect_and_touch",
intersect_holes_intersect_and_touch[0], intersect_holes_intersect_and_touch[1],
3, 21, 16.25,
3, 17, 6.25);
test_one<polygon, polygon, polygon>("intersect_holes_new_ring",
intersect_holes_new_ring[0], intersect_holes_new_ring[1],
3, 15, 9.8961,
4, 25, 121.8961,
tolerance(0.01));
test_one<polygon, polygon, polygon>("first_within_hole_of_second",
first_within_hole_of_second[0], first_within_hole_of_second[1],
1, 5, 1,
1, 10, 16);
test_one<polygon, polygon, polygon>("intersect_holes_disjoint",
intersect_holes_disjoint[0], intersect_holes_disjoint[1],
2, 14, 16.0,
2, 10, 6.0);
test_one<polygon, polygon, polygon>("intersect_holes_intersect",
intersect_holes_intersect[0], intersect_holes_intersect[1],
2, 16, 15.75,
2, 12, 5.75);
test_one<polygon, polygon, polygon>(
"case4", case_4[0], case_4[1],
6, 28, 2.77878787878788,
4, 22, 4.77878787878788);
test_one<polygon, polygon, polygon>(
"case5", case_5[0], case_5[1],
8, 36, 2.43452380952381,
7, 33, 3.18452380952381);
#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS
// Fails, a-b is partly generated, b-a does not have any output
// It failed already in 1.59
test_one<polygon, polygon, polygon>("case_58_iet",
case_58[0], case_58[2],
3, 12, 0.6666666667,
1, -1, 11.1666666667);
#endif
test_one<polygon, polygon, polygon>("case_80",
case_80[0], case_80[1],
1, 9, 44.5,
1, 10, 84.5);
#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS
// Fails, holes are not subtracted
test_one<polygon, polygon, polygon>("case_81",
case_81[0], case_81[1],
1, 8, 80.5,
1, 8, 83.0,
1, 12, 80.5 + 83.0);
#endif
test_one<polygon, polygon, polygon>("winded",
winded[0], winded[1],
3, 37, 61,
1, 15, 13);
test_one<polygon, polygon, polygon>("within_holes_disjoint",
within_holes_disjoint[0], within_holes_disjoint[1],
2, 15, 25,
1, 5, 1);
test_one<polygon, polygon, polygon>("side_side",
side_side[0], side_side[1],
1, 5, 1,
1, 5, 1,
1, 7, 2);
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
test_one<polygon, polygon, polygon>("buffer_mp1",
buffer_mp1[0], buffer_mp1[1],
1, 61, 10.2717,
1, 61, 10.2717);
if ( BOOST_GEOMETRY_CONDITION((boost::is_same<ct, double>::value)) )
{
test_one<polygon, polygon, polygon>("buffer_mp2",
buffer_mp2[0], buffer_mp2[1],
1, 91, 12.09857,
1, 155, 24.19714);
}
#endif
/*** TODO: self-tangencies for difference
test_one<polygon, polygon, polygon>("wrapped_a",
wrapped[0], wrapped[1],
3, 1, 61,
1, 0, 13);
test_one<polygon, polygon, polygon>("wrapped_b",
wrapped[0], wrapped[2],
3, 1, 61,
1, 0, 13);
***/
// Isovist - the # output polygons differ per compiler/pointtype, (very) small
// rings might be discarded. We check area only
test_one<polygon, polygon, polygon>("isovist",
isovist1[0], isovist1[1],
-1, -1, 0.279132,
-1, -1, 224.8892,
#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
tolerance(0.1));
#else
tolerance(0.001));
#endif
// SQL Server gives: 0.279121891701124 and 224.889211358929
// PostGIS gives: 0.279121991127244 and 224.889205853156
// No robustness gives: 0.279121991127106 and 224.825363749290
#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS
test_one<polygon, polygon, polygon>("geos_1",
geos_1[0], geos_1[1],
21, -1, 0.31640625,
9, -1, 0.01953125);
// Excluded this test in the normal suite, it is OK like this for many clang/gcc/msvc
// versions, but NOT OK for many other clang/gcc/msvc versions on other platforms
// It might depend on partition (order)
// 10, -1, 0.02148439); // change in partition might give these results
// SQL Server gives: 0.28937764436705 and 0.000786406897532288 with 44/35 rings
// PostGIS gives: 0.30859375 and 0.033203125 with 35/35 rings
#endif
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
test_one<polygon, polygon, polygon>("geos_2",
geos_2[0], geos_2[1],
1, -1, 138.6923828,
1, -1, 211.859375,
tolerance(0.01)); // MSVC 14 expects 138.69214 and 211.85913
test_one<polygon, polygon, polygon>("geos_3",
geos_3[0], geos_3[1],
1, -1, 16211128.5,
1, -1, 13180420.0,
1, -1, 16211128.5 + 13180420.0);
#endif
test_one<polygon, polygon, polygon>("geos_4",
geos_4[0], geos_4[1],
1, -1, 971.9163115,
1, -1, 1332.4163115);
test_one<polygon, polygon, polygon>("ggl_list_20110306_javier",
ggl_list_20110306_javier[0], ggl_list_20110306_javier[1],
1, -1, 71495.3331,
2, -1, 8960.49049,
1, -1, 71495.3331 + 8960.49049);
test_one<polygon, polygon, polygon>("ggl_list_20110307_javier",
ggl_list_20110307_javier[0], ggl_list_20110307_javier[1],
1, if_typed<ct, float>(14, 13), 16815.6,
1, 4, 3200.4,
tolerance(0.01));
if ( BOOST_GEOMETRY_CONDITION((! boost::is_same<ct, float>::value)) )
{
test_one<polygon, polygon, polygon>("ggl_list_20110716_enrico",
ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1],
3, -1, 35723.8506317139,
1, -1, 58456.4964294434,
1, -1, 35723.8506317139 + 58456.4964294434);
}
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
test_one<polygon, polygon, polygon>("ggl_list_20110820_christophe",
ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1],
1, -1, 2.8570121719168924,
1, -1, 64.498061986388564);
#endif
test_one<polygon, polygon, polygon>("ggl_list_20120717_volker",
ggl_list_20120717_volker[0], ggl_list_20120717_volker[1],
1, 11, 3370866.2295081965,
1, 5, 384.2295081964694,
tolerance(0.01));
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
// 2011-07-02 / 2014-06-19
// Interesting FP-precision case.
// sql server gives: 6.62295817619452E-05
// PostGIS gives: 0.0 (no output)
// Boost.Geometry gave results depending on FP-type, and compiler, and operating system.
// Since rescaling to integer results are equal w.r.t. compiler/FP type,
// however, some long spikes are still generated in the resulting difference
test_one<polygon, polygon, polygon>("ggl_list_20110627_phillip",
ggl_list_20110627_phillip[0], ggl_list_20110627_phillip[1],
if_typed_tt<ct>(1, 1), -1,
if_typed_tt<ct>(0.0000000000001105367, 0.000125137888971949),
1, -1, 3577.40960816756,
tolerance(0.01)
);
#endif
// Ticket 8310, one should be completely subtracted from the other.
test_one<polygon, polygon, polygon>("ticket_8310a",
ticket_8310a[0], ticket_8310a[1],
1, 10, 10.11562724,
0, 0, 0);
test_one<polygon, polygon, polygon>("ticket_8310b",
ticket_8310b[0], ticket_8310b[1],
1, 10, 10.12655608,
0, 0, 0);
test_one<polygon, polygon, polygon>("ticket_8310c",
ticket_8310c[0], ticket_8310c[1],
1, 10, 10.03103292,
0, 0, 0);
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
test_one<polygon, polygon, polygon>("ticket_9081_15",
ticket_9081_15[0], ticket_9081_15[1],
2, 10, 0.0334529710902111,
1, 4, 5.3469555172380723e-010);
#endif
test_one<polygon, polygon, polygon>("ticket_9081_314",
ticket_9081_314[0], ticket_9081_314[1],
2, 12, 0.0451236449624935,
0, 0, 0);
#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
test_one<polygon, polygon, polygon>("ticket_9563",
ticket_9563[0], ticket_9563[1],
0, 0, 0,
6, 24, 20.096189);
test_one<polygon, polygon, polygon>("ticket_10108_a",
ticket_10108_a[0], ticket_10108_a[1],
1, 4, 0.0145037,
1, 4, 0.029019232);
test_one<polygon, polygon, polygon>("ticket_10108_b",
ticket_10108_b[0], ticket_10108_b[1],
1, 5, 1081.68697,
1, 5, 1342.65795);
#endif
// From assemble-test, with a u/u case
test_one<polygon, polygon, polygon>("assemble_0210",
"POLYGON((0 0,0 10,10 10,10 0,0 0),(8.5 1,9.5 1,9.5 2,8.5 2,8.5 1))",
"POLYGON((2 0.5,0.5 2,0.5 8,2 9.5,6 9.5,8.5 8,8.5 2,7 0.5,2 0.5),(2 2,7 2,7 8,2 8,2 2))",
2, 23, 62.25,
0, 0, 0.0);
// Other combi's
{
test_one<polygon, polygon, ring>(
"star_ring_ring", example_star, example_ring,
5, 22, 1.1901714, 5, 27, 1.6701714);
test_one<polygon, ring, polygon>(
"ring_star_ring", example_ring, example_star,
5, 27, 1.6701714, 5, 22, 1.1901714);
static std::string const clip = "POLYGON((2.5 0.5,5.5 2.5))";
test_one<polygon, box, ring>("star_box",
clip, example_star,
4, 20, 2.833333, 4, 16, 0.833333);
test_one<polygon, ring, box>("box_star",
example_star, clip,
4, 16, 0.833333, 4, 20, 2.833333);
}
// Counter clockwise
{
typedef bg::model::polygon<P, false> polygon_ccw;
test_one<polygon, polygon_ccw, polygon_ccw>(
"star_ring_ccw", example_star, example_ring,
5, 22, 1.1901714, 5, 27, 1.6701714);
test_one<polygon, polygon, polygon_ccw>(
"star_ring_ccw1", example_star, example_ring,
5, 22, 1.1901714, 5, 27, 1.6701714);
test_one<polygon, polygon_ccw, polygon>(
"star_ring_ccw2", example_star, example_ring,
5, 22, 1.1901714, 5, 27, 1.6701714);
}
// Multi/box (should be moved to multi)
{
typedef bg::model::multi_polygon<polygon> mp;
static std::string const clip = "POLYGON((2 2,4 4))";
test_one<polygon, box, mp>("simplex_multi_box_mp",
clip, case_multi_simplex[0],
2, -1, 0.53333333333, 3, -1, 8.53333333333);
test_one<polygon, mp, box>("simplex_multi_mp_box",
case_multi_simplex[0], clip,
3, -1, 8.53333333333, 2, -1, 0.53333333333);
}
/***
Experimental (cut), does not work:
test_one<polygon, polygon, polygon>(
"polygon_pseudo_line",
"POLYGON((0 0,0 4,4 4,4 0,0 0))",
"POLYGON((2 -2,2 -1,2 6,2 -2))",
5, 22, 1.1901714,
5, 27, 1.6701714);
***/
#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS
test_one<polygon, polygon, polygon>("ticket_11725_2",
ticket_11725_2[0], ticket_11725_2[1],
2, -1, 7.5, 0, -1, 0.0);
test_one<polygon, polygon, polygon>("mysql_21977775",
mysql_21977775[0], mysql_21977775[1],
2, -1, 160.856568913, 2, -1, 92.3565689126);
#endif
test_one<polygon, polygon, polygon>("mysql_21965285",
mysql_21965285[0], mysql_21965285[1],
1, -1, 92.0,
1, -1, 14.0,
1, -1, 92.0 + 14.0);
}
// Test cases for integer coordinates / ccw / open
template <typename Point, bool ClockWise, bool Closed>
void test_specific()
{
typedef bg::model::polygon<Point, ClockWise, Closed> polygon;
ut_settings settings;
settings.test_validity = true;
test_one<polygon, polygon, polygon>("ggl_list_20120717_volker",
ggl_list_20120717_volker[0], ggl_list_20120717_volker[1],
1, 11, 3371540,
1, 4, 385,
1, 16, 3371540 + 385,
settings);
test_one<polygon, polygon, polygon>("ticket_10658",
ticket_10658[0], ticket_10658[1],
1, 6, 1510434,
0, 0, 0,
settings);
test_one<polygon, polygon, polygon>("ticket_11121",
ticket_11121[0], ticket_11121[1],
2, 8, 489763.5,
1, 4, 6731652.0,
settings);
{
ut_settings settings;
#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS
settings.test_validity = true;
#endif
// Generates spikes, both a-b and b-a
test_one<polygon, polygon, polygon>("ticket_11676",
ticket_11676[0], ticket_11676[1],
1, 18, 2537992.5,
2, 11, 294963.5,
1, -1, 2537992.5 + 294963.5,
settings);
}
}
int test_main(int, char* [])
{
test_all<bg::model::d2::point_xy<double> >();
test_specific<bg::model::d2::point_xy<int>, false, false>();
#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
test_all<bg::model::d2::point_xy<float> >();
#ifdef HAVE_TTMATH
std::cout << "Testing TTMATH" << std::endl;
test_all<bg::model::d2::point_xy<ttmath_big> >();
#endif
#endif
return 0;
}