// Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test // Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands. // This file was modified by Oracle on 2019. // Modifications copyright (c) 2019, Oracle and/or its affiliates. // 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(TEST_WITH_SVG) # include #endif template inline void test_assemble(std::string const& id, Geometry const& p, Geometry const& q, char operation = 'i') { std::vector u, i, d1, d2; bg::detail::union_::union_insert(p, q, std::back_inserter(u)); bg::detail::intersection::intersection_insert(p, q, std::back_inserter(i)); bg::detail::difference::difference_insert(p, q, std::back_inserter(d1)); bg::detail::difference::difference_insert(q, p, std::back_inserter(d2)); if (operation == 'i') { typedef typename bg::default_area_result::type type; type area_p = bg::area(p); type area_q = bg::area(q); type area_i = 0, area_u = 0, area_d1 = 0, area_d2 = 0; BOOST_FOREACH(Geometry const& g, u) { area_u += bg::area(g); } BOOST_FOREACH(Geometry const& g, i) { area_i += bg::area(g); } BOOST_FOREACH(Geometry const& g, d1) { area_d1 += bg::area(g); } BOOST_FOREACH(Geometry const& g, d2) { area_d2 += bg::area(g); } type diff = (area_p + area_q) - area_u - area_i; type diff_d1 = (area_u - area_q) - area_d1; type diff_d2 = (area_u - area_p) - area_d2; bool ok = bg::math::abs(diff) < 0.001 && bg::math::abs(diff_d1) < 0.001 && bg::math::abs(diff_d2) < 0.001; BOOST_CHECK_MESSAGE(ok, id << " diff: " << diff << " d1: " << diff_d1 << " d2: " << diff_d2); } #if defined(TEST_WITH_SVG) { std::ostringstream filename; filename << "assemble_" << id << "_" << operation << ".svg"; std::ofstream svg(filename.str().c_str()); bg::svg_mapper::type> mapper(svg, 500, 500); mapper.add(p); mapper.add(q); mapper.map(p, "fill-opacity:0.3;fill:rgb(51,51,153);stroke:rgb(51,51,153);stroke-width:3"); mapper.map(q, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:3"); std::string linestyle = "opacity:0.7;fill:none;stroke-opacity:1;stroke-miterlimit:4;"; std::vector const& v = operation == 'i' ? i : operation == 'u' ? u : operation == 'd' ? d1 : d2 ; BOOST_FOREACH(Geometry const& geometry, v) { mapper.map(geometry, linestyle + "stroke-width:3;stroke-linejoin:round;stroke-linecap:square;stroke-dasharray:12,12;stroke:rgb(255,0,0);"); } } #endif } template inline bool int_ok(Polygon const& poly) { typename bg::point_type::type const& pi = bg::interior_rings(poly)[0].front(); return bg::within(pi, bg::exterior_ring(poly)); } template void generate() { static std::string exteriors[4] = { "(0 0,0 10,10 10,10 0,0 0)", "(1 1,1 9,8 9,8 1,1 1)", "(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)", "(3 3,3 7,6 7,6 3,3 3)" }; static std::string interiors[4] = { "(2 2,2 8,7 8,7 2,2 2)", "(8.5 1,8.5 2,9.5 2,9.5 1,8.5 1)", "(4 4,4 5,5 5,5 4,4 4)", "(6 4,6 5,9 5,9 4,6 4)" }; for (int pe = 0; pe < 4; pe++) { for (int qe = 0; qe < 4; qe++) { for (int pi = 0; pi < 4; pi++) { for (int qi = 0; qi < 4; qi++) { std::string ps = "POLYGON(" + exteriors[pe] + "," + interiors[pi] + ")"; std::string qs = "POLYGON(" + exteriors[qe] + "," + interiors[qi] + ")"; typedef bg::model::d2::point_xy point_type; bg::model::polygon p, q; bg::read_wkt(ps, p); bg::read_wkt(qs, q); bg::correct(p); bg::correct(q); if (! bg::intersects(p) && ! bg::intersects(q) && int_ok(p) && int_ok(q) ) { std::ostringstream out; out << pe << qe << pi << qi; test_assemble(out.str(), p, q); #if defined(TEST_WITH_SVG) test_assemble(out.str(), p, q, 'u'); test_assemble(out.str(), p, q, 'd'); test_assemble(out.str(), p, q, 'r'); #endif } } } } } } #if ! defined(GEOMETRY_TEST_MULTI) int test_main(int, char* []) { generate(); return 0; } #endif