geometry/test/algorithms/point_on_surface.cpp

366 lines
18 KiB
C++

// Boost.Geometry (aka GGL, Generic Geometry Library)
// Unit Test
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014, 2015.
// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// 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)
// Instead of having a separate (and nearly similar) unit test to test multipolygons,
// we now include them here and compile them by default. Only undefining the next line
// will avoid testing multi-geometries
#define BOOST_GEOMETRY_UNIT_TEST_MULTI
#include <geometry_test_common.hpp>
// The include to test
#include <boost/geometry/algorithms/point_on_surface.hpp>
// Helper includes
#include <boost/geometry/algorithms/correct.hpp>
#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
#include <boost/geometry/strategies/strategies.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
// Include from unit tests
#include <algorithms/test_overlay.hpp>
#include <algorithms/predef_relop.hpp>
#include <algorithms/overlay/overlay_cases.hpp>
#if defined(BOOST_GEOMETRY_UNIT_TEST_MULTI)
# include <boost/geometry/algorithms/detail/extreme_points.hpp>
#endif
#if defined(TEST_WITH_SVG)
# include <boost/geometry/io/svg/svg_mapper.hpp>
#endif
template <typename Geometry>
void test_geometry(std::string const& case_id, Geometry const& geometry, double /*expected_x*/ = 0, double /*expected_y*/ = 0)
{
//std::cout << case_id << std::endl;
typedef typename bg::point_type<Geometry>::type point_type;
point_type point;
bg::point_on_surface(geometry, point);
BOOST_CHECK_MESSAGE(bg::within(point, geometry),
case_id << " generated point_on_surface (dim 1) is not within geometry");
#ifdef BOOST_GEOMETRY_POINT_ON_SURFACE_COMPLETE
// For the algorithm we also check generation in the other dimension
point_type right_point;
bg::detail::point_on_surface::calculate_point_on_surface<0>(geometry, right_point);
BOOST_CHECK_MESSAGE(bg::within(right_point, geometry),
case_id << " generated point_on_surface (dim 0) is not within geometry");
point_type returned_point = bg::return_point_on_surface(geometry);
#endif
#if defined(TEST_WITH_SVG)
{
std::ostringstream filename;
filename << "point_on_surface_" << case_id << "_"
<< string_from_type<typename bg::coordinate_type<Geometry>::type>::name()
<< ".svg";
std::ofstream svg(filename.str().c_str());
// To map the intermediate products:
bg::model::linestring<point_type> top_points;
typedef bg::model::linestring<point_type> intruder_type;
std::vector<intruder_type> top_intruders;
bg::extreme_points<1>(geometry, top_points, top_intruders);
#ifdef BOOST_GEOMETRY_POINT_ON_SURFACE_COMPLETE
bg::model::linestring<point_type> right_points;
std::vector<bg::model::linestring<point_type> > right_intruders;
bg::extreme_points<0>(geometry, right_points, right_intruders);
#endif
bg::svg_mapper<point_type> mapper(svg, 500, 500);
mapper.add(geometry);
mapper.map(geometry, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:1");
// Top (red/magenta)
mapper.map(top_points, "stroke:rgb(255,0,0);stroke-width:2");
BOOST_FOREACH(intruder_type const& intruder, top_intruders)
{
mapper.map(intruder, "stroke:rgb(255,0,255);stroke-width:2");
}
mapper.map(point, "opacity:0.8;fill:rgb(255,128,0);stroke:rgb(0,0,100);stroke-width:1", 3);
#ifdef BOOST_GEOMETRY_POINT_ON_SURFACE_COMPLETE
//// Right (blue/cyan)
// (mostly commented, makes the picture less clear)
//mapper.map(right_points, "stroke:rgb(0,0,255);stroke-width:2");
//BOOST_FOREACH(intruder_type const& intruder, right_intruders)
//{
// mapper.map(intruder, "stroke:rgb(0,255,255);stroke-width:2");
//}
mapper.map(right_point, "opacity:0.8;fill:rgb(0,128,255);stroke:rgb(0,0,100);stroke-width:1", 3);
#endif
}
#endif
}
template <typename Geometry>
void test_geometry(std::string const& case_id, std::string const& wkt, double expected_x = 0, double expected_y = 0)
{
Geometry geometry;
bg::read_wkt(wkt, geometry);
bg::correct(geometry);
test_geometry(case_id, geometry, expected_x, expected_y);
}
template <typename Point>
void test_point_order_and_type()
{
typedef bg::model::polygon<Point, false, false> ccw_open_polygon;
typedef bg::model::polygon<Point, true, false> cw_open_polygon;
typedef bg::model::polygon<Point, false, true> ccw_closed_polygon;
typedef bg::model::polygon<Point, true, true> cw_closed_polygon;
test_geometry<ccw_open_polygon>("with_hole_ccw_open", "POLYGON((0 0,9 0,9 9,0 9),(2 2,2 7,7 7,7 2))", 0, 0);
test_geometry<cw_open_polygon>("with_hole_cw_open", "POLYGON((0 0,0 9,9 9,9 0),(2 2,7 2,7 7,2 7))", 0, 0);
test_geometry<ccw_closed_polygon>("with_hole_ccw_closed", "POLYGON((0 0,9 0,9 9,0 9,0 0),(2 2,2 7,7 7,7 2,2 2))", 0, 0);
test_geometry<cw_closed_polygon>("with_hole_cw_closed", "POLYGON((0 0,0 9,9 9,9 0,0 0),(2 2,7 2,7 7,2 7,2 2))", 0, 0);
test_geometry<cw_closed_polygon>("t1", "POLYGON((0 0,0 10,10 0,0 0))", 0, 0);
test_geometry<cw_closed_polygon>("t2", "POLYGON((0 0,10 0,0 -10,0 0))", 0, 0);
test_geometry<cw_closed_polygon>("t3", "POLYGON((0 0,0 -10,-10 0,0 0))", 0, 0);
test_geometry<cw_closed_polygon>("t4", "POLYGON((0 0,-10 0,0 10,0 0))", 0, 0);
}
template <typename Point>
void test_all()
{
typedef bg::model::polygon<Point> polygon;
// Specific test-cases for point-on-surface:
test_geometry<polygon>("ice", "polygon((5 0,0 5,1 6,2 5,4 8,6 5,7 6,8 5,9 6,10 5,5 0))", 0, 0);
test_geometry<polygon>("intruding", "polygon((5 0,0 5,1 6,2 5,4 8,6 5,7 6,8 5,9 6,10 5,7 2,4 7,6 1,5 0))", 0, 0);
test_geometry<polygon>("intruding2", "polygon((5 0,3 2,4 6,2 3,0 5,1 6,2 5,4 8,6 5,7 6,8 5,9 6,10 5,7 2,4 7,6 1,5 0))", 0, 0);
test_geometry<polygon>("intruding3", "polygon((5 0,3 2,3 6,2 3,0 5,1 6,3 7,2 5,4 8,6 5,5 7,7 6,8 5,9 6,10 5,7 2,5 6,6 1,5 0))", 0, 0);
test_geometry<polygon>("intruding4", "polygon((5 0,3 2,3 6,2 3,0 5,1 6,3 7,2 5,4 8,6 5,5 8,7 6,8 5,9 6,10 5,7 2,5 6,6 1,5 0))", 0, 0);
test_geometry<polygon>("intruding5", "polygon((5 0,3 2,3 6,2 3,0 5,1 6,3 8,2 5,4 8,6 5,5 8,7 6,8 5,9 6,10 5,7 2,5 6,6 1,5 0))", 0, 0);
test_geometry<polygon>("ice_int", "polygon((5 0,0 5,1 6,2 5,4 8,6 5,7 6,8 5,9 6,10 5,5 0),(3 4,4 3,5 4,4 7,3 4))", 0, 0);
test_geometry<polygon>("ice_int2", "polygon((5 0,0 5,1 6,2 5,4 8,6 5,7 6,8 5,9 6,10 5,5 0),(4 7,3 4,4 3,5 4,4 7))", 0, 0);
test_geometry<polygon>("ice_in3", "polygon((5 0,0 5,1 6,2 5,4 8,6 5,7 6,8 5,9 6,10 5,5 0),(3 4,5 4,5 6,3 6,3 4))", 0, 0);
test_geometry<polygon>("simplex_normal", simplex_normal[0], 0, 0);
test_geometry<polygon>("sqr", "polygon((0 0,0 5,0 10,5 10,10 10,10 5,10 0,5 0,0 0))", 0, 0);
test_geometry<polygon>("self_tangent", "polygon((0 0,5 10,10 0,9 0,7 4,8 0,7 0,5 10,3 0,2 0,3 4,1 0,0 0))", 0, 0);
test_geometry<polygon>("self_tangent2", "polygon((5 0,2 3,4 8,1.5 3.5,0 5,1 6,2 5,4 8,6 5,7 6,8 5,9 6,10 5,5 0))", 0, 0);
test_geometry<polygon>("self_tangent_int", "polygon((5 0,0 5,1 6,2 5,4 8,6 5,7 6,8 5,9 6,10 5,5 0),(3 4,4 3,5 4,4 8,3 4))", 0, 0);
test_geometry<polygon>("self_tangent_int2", "polygon((5 0,2 3,3.5 7,1.5 3.5,0 5,1 6,2 5,4 8,6 5,7 6,8 5,9 6,10 5,5 0),(3 4,4 3,5 4,4 8,3 4))", 0, 0);
test_geometry<polygon>("self_tangent_int3", "polygon((5 0,2 3,4 8,1.5 3.5,0 5,1 6,2 5,4 8,6 5,7 6,8 5,9 6,10 5,5 0),(3 4,4 3,5 4,4 8,3 4))", 0, 0);
test_geometry<polygon>("self_tangent_int3", "polygon((5 0,2 3,4 8,1.5 3.5,0 5,1 6,2 5,4 8,6 5,7 6,8 5,9 6,10 5,5 0),(3 4,4 3,5 4,4 8,3 4))", 0, 0);
test_geometry<polygon>("disjoint_simplex0", disjoint_simplex[0], 0, 0);
test_geometry<polygon>("disjoint_simplex1", disjoint_simplex[1], 0, 0);
test_geometry<polygon>("ticket_10643", "POLYGON((1074699.93 703064.65, 1074703.90 703064.58, 1074704.53 703061.40, 1074702.10 703054.62, 1074699.93 703064.65))");
test_geometry<polygon>("ticket_10643_2", "POLYGON((699.93 64.65, 703.90 64.58, 704.53 61.40, 702.10 54.62, 699.93 64.65))");
#if defined(BOOST_GEOMETRY_UNIT_TEST_MULTI)
{
typedef bg::model::multi_polygon<polygon> multi_polygon;
test_geometry<multi_polygon>("mp_simplex", "multipolygon(((0 0,0 5,5 0, 0 0)),((7 1,7 6,10 1,7 1)))", 0, 0);
// Wrapped polygon in two orders
test_geometry<multi_polygon>("mp_wrapped1",
"multipolygon("
"((4 10,9 11,10 16,11 11,16 10,11 9,10 4,9 9,4 10))"
","
"((0 10,10 20,20 10,10 0,0 10),(10 2,18 10,10 18,2 10,10 2))"
")",
0, 0);
test_geometry<multi_polygon>("mp_wrapped2",
"multipolygon("
"((0 10,10 20,20 10,10 0,0 10),(10 2,18 10,10 18,2 10,10 2))"
","
"((4 10,9 11,10 16,11 11,16 10,11 9,10 4,9 9,4 10))"
")",
0, 0);
}
#endif
// Overlay testcases
test_geometry<polygon>("buffer_mp1", buffer_mp1[0], 0, 0);
test_geometry<polygon>("buffer_mp2", buffer_mp2[0], 0, 0);
test_geometry<polygon>("buffer_rt_a", buffer_rt_a[0], 0, 0);
test_geometry<polygon>("buffer_rt_f", buffer_rt_f[0], 0, 0);
test_geometry<polygon>("buffer_rt_g", buffer_rt_g[0], 0, 0);
test_geometry<polygon>("buffer_rt_i", buffer_rt_i[0], 0, 0);
test_geometry<polygon>("buffer_rt_j", buffer_rt_j[0], 0, 0);
test_geometry<polygon>("buffer_rt_l", buffer_rt_l[0], 0, 0);
test_geometry<polygon>("buffer_rt_m1", buffer_rt_m1[0], 0, 0);
test_geometry<polygon>("buffer_rt_m2", buffer_rt_m2[0], 0, 0);
test_geometry<polygon>("buffer_rt_n", buffer_rt_n[0], 0, 0);
test_geometry<polygon>("buffer_rt_q", buffer_rt_q[0], 0, 0);
test_geometry<polygon>("buffer_rt_r", buffer_rt_r[0], 0, 0);
test_geometry<polygon>("buffer_rt_t", buffer_rt_t[0], 0, 0);
test_geometry<polygon>("case_10", case_10[0], 0, 0);
test_geometry<polygon>("case_11", case_11[0], 0, 0);
test_geometry<polygon>("case_12", case_12[0], 0, 0);
test_geometry<polygon>("case_13", case_13[0], 0, 0);
test_geometry<polygon>("case_14", case_14[0], 0, 0);
test_geometry<polygon>("case_15", case_15[0], 0, 0);
test_geometry<polygon>("case_16", case_16[0], 0, 0);
test_geometry<polygon>("case_17", case_17[0], 0, 0);
test_geometry<polygon>("case_18", case_18[0], 0, 0);
test_geometry<polygon>("case_19", case_19[0], 0, 0);
test_geometry<polygon>("case_1", case_1[0], 0, 0);
test_geometry<polygon>("case_20", case_20[0], 0, 0);
test_geometry<polygon>("case_21", case_21[0], 0, 0);
test_geometry<polygon>("case_22", case_22[0], 0, 0);
test_geometry<polygon>("case_23", case_23[0], 0, 0);
test_geometry<polygon>("case_24", case_24[0], 0, 0);
test_geometry<polygon>("case_25", case_25[0], 0, 0);
test_geometry<polygon>("case_26", case_26[0], 0, 0);
test_geometry<polygon>("case_27", case_27[0], 0, 0);
test_geometry<polygon>("case_28", case_28[0], 0, 0);
test_geometry<polygon>("case_29", case_29[0], 0, 0);
test_geometry<polygon>("case_2", case_2[0], 0, 0);
test_geometry<polygon>("case_30", case_30[0], 0, 0);
test_geometry<polygon>("case_31", case_31[0], 0, 0);
test_geometry<polygon>("case_32", case_32[0], 0, 0);
test_geometry<polygon>("case_33", case_33[0], 0, 0);
test_geometry<polygon>("case_34", case_34[0], 0, 0);
test_geometry<polygon>("case_35", case_35[0], 0, 0);
test_geometry<polygon>("case_36", case_36[0], 0, 0);
test_geometry<polygon>("case_37", case_37[0], 0, 0);
test_geometry<polygon>("case_38", case_38[0], 0, 0);
test_geometry<polygon>("case_39", case_39[0], 0, 0);
test_geometry<polygon>("case_3", case_3[0], 0, 0);
test_geometry<polygon>("case_40", case_40[0], 0, 0);
test_geometry<polygon>("case_41", case_41[0], 0, 0);
test_geometry<polygon>("case_42", case_42[0], 0, 0);
test_geometry<polygon>("case_43", case_43[0], 0, 0);
test_geometry<polygon>("case_44", case_44[0], 0, 0);
test_geometry<polygon>("case_45", case_45[0], 0, 0);
test_geometry<polygon>("case_46", case_46[0], 0, 0);
test_geometry<polygon>("case_47", case_47[0], 0, 0);
test_geometry<polygon>("case_49", case_49[0], 0, 0);
test_geometry<polygon>("case_4", case_4[0], 0, 0);
test_geometry<polygon>("case_50", case_50[0], 0, 0);
test_geometry<polygon>("case_51", case_51[0], 0, 0);
test_geometry<polygon>("case_52", case_52[0], 0, 0);
test_geometry<polygon>("case_53", case_53[0], 0, 0);
test_geometry<polygon>("case_54", case_54[0], 0, 0);
test_geometry<polygon>("case_55", case_55[0], 0, 0);
test_geometry<polygon>("case_56", case_56[0], 0, 0);
test_geometry<polygon>("case_57", case_57[0], 0, 0);
test_geometry<polygon>("case_58", case_58[0], 0, 0);
test_geometry<polygon>("case_59", case_59[0], 0, 0);
test_geometry<polygon>("case_5", case_5[0], 0, 0);
test_geometry<polygon>("case_60", case_60[0], 0, 0);
test_geometry<polygon>("case_61", case_61[0], 0, 0);
test_geometry<polygon>("case_6", case_6[0], 0, 0);
test_geometry<polygon>("case_70", case_70[0], 0, 0);
test_geometry<polygon>("case_71", case_71[0], 0, 0);
test_geometry<polygon>("case_72", case_72[0], 0, 0);
test_geometry<polygon>("case_79", case_79[0], 0, 0);
test_geometry<polygon>("case_7", case_7[0], 0, 0);
test_geometry<polygon>("case_8", case_8[0], 0, 0);
test_geometry<polygon>("case_9", case_9[0], 0, 0);
test_geometry<polygon>("case_many_situations", case_many_situations[0], 0, 0);
test_geometry<polygon>("ccw_case_1", ccw_case_1[0], 0, 0);
test_geometry<polygon>("ccw_case_9", ccw_case_9[0], 0, 0);
test_geometry<polygon>("collinear_opposite_left", collinear_opposite_left[0], 0, 0);
test_geometry<polygon>("collinear_opposite_right", collinear_opposite_right[0], 0, 0);
test_geometry<polygon>("collinear_opposite_straight", collinear_opposite_straight[0], 0, 0);
test_geometry<polygon>("collinear_overlaps", collinear_overlaps[0], 0, 0);
test_geometry<polygon>("dz_1", dz_1[0], 0, 0);
test_geometry<polygon>("dz_2", dz_2[0], 0, 0);
test_geometry<polygon>("dz_3", dz_3[0], 0, 0);
test_geometry<polygon>("dz_4", dz_4[0], 0, 0);
test_geometry<polygon>("geos_1", geos_1[0], 0, 0);
test_geometry<polygon>("geos_2", geos_2[0], 0, 0);
test_geometry<polygon>("geos_3", geos_3[0], 0, 0);
test_geometry<polygon>("geos_4", geos_4[0], 0, 0);
test_geometry<polygon>("ggl_list_20110306_javier", ggl_list_20110306_javier[0], 0, 0);
test_geometry<polygon>("ggl_list_20110307_javier", ggl_list_20110307_javier[0], 0, 0);
test_geometry<polygon>("ggl_list_20110627_phillip", ggl_list_20110627_phillip[0], 0, 0);
test_geometry<polygon>("ggl_list_20110716_enrico", ggl_list_20110716_enrico[0], 0, 0);
test_geometry<polygon>("ggl_list_20110820_christophe ", ggl_list_20110820_christophe [0], 0, 0);
test_geometry<polygon>("ggl_list_20120717_volker", ggl_list_20120717_volker[0], 0, 0);
test_geometry<polygon>("hv_1", hv_1[0], 0, 0);
test_geometry<polygon>("hv_2", hv_2[0], 0, 0);
test_geometry<polygon>("hv_3", hv_3[0], 0, 0);
test_geometry<polygon>("hv_4", hv_4[0], 0, 0);
test_geometry<polygon>("hv_5", hv_5[0], 0, 0);
test_geometry<polygon>("hv_6", hv_6[0], 0, 0);
test_geometry<polygon>("hv_7", hv_7[0], 0, 0);
test_geometry<polygon>("isovist", isovist[0], 0, 0);
test_geometry<polygon>("open_case_1", open_case_1[0], 0, 0);
test_geometry<polygon>("open_case_9", open_case_9[0], 0, 0);
test_geometry<polygon>("pie_16_2_15_0", pie_16_2_15_0[0], 0, 0);
test_geometry<polygon>("pie_16_4_12", pie_16_4_12[0], 0, 0);
test_geometry<polygon>("pie_20_20_7_100", pie_20_20_7_100[0], 0, 0);
test_geometry<polygon>("pie_23_16_16", pie_23_16_16[0], 0, 0);
test_geometry<polygon>("pie_23_21_12_500", pie_23_21_12_500[0], 0, 0);
test_geometry<polygon>("pie_23_23_3_2000", pie_23_23_3_2000[0], 0, 0);
test_geometry<polygon>("pie_4_13_15", pie_4_13_15[0], 0, 0);
test_geometry<polygon>("pie_5_12_12_0_7s", pie_5_12_12_0_7s[0], 0, 0);
test_geometry<polygon>("snl_1", snl_1[0], 0, 0);
test_geometry<polygon>("ticket_17", ticket_17[0], 0, 0);
test_geometry<polygon>("ticket_5103", ticket_5103[0], 0, 0);
test_geometry<polygon>("ticket_7462", ticket_7462[0], 0, 0);
test_geometry<polygon>("ticket_8310a", ticket_8310a[0], 0, 0);
test_geometry<polygon>("ticket_8310b", ticket_8310b[0], 0, 0);
test_geometry<polygon>("ticket_8310c", ticket_8310c[0], 0, 0);
test_geometry<polygon>("ticket_8254", ticket_8254[0], 0, 0);
}
template <typename Point>
void test_dense(std::string const& case_id, double size)
{
typedef bg::model::polygon<Point> polygon;
polygon poly;
bg::append(poly, Point(-size, 0));
double thres = 3.14158 / 8;
for ( double a = thres ; a > -thres ; a -= 0.01 )
{
bg::append(poly, Point(size * ::cos(a), size * ::sin(a)));
}
bg::append(poly, Point(-size, 0));
test_geometry(case_id, poly);
}
int test_main(int, char* [])
{
test_all<bg::model::d2::point_xy<double> >();
test_point_order_and_type<bg::model::d2::point_xy<double> >();
test_point_order_and_type<bg::model::d2::point_xy<int> >();
test_dense<bg::model::d2::point_xy<double> >("dense1", 100);
test_dense<bg::model::d2::point_xy<double> >("dense2", 1000000);
return 0;
}