// Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test // Copyright (c) 2007-2012 Barend Gehrels, 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) #ifndef BOOST_GEOMETRY_TEST_INTERSECTION_HPP #define BOOST_GEOMETRY_TEST_INTERSECTION_HPP #include #include #include #include #include #include #include #include #include #include #include #if defined(TEST_WITH_SVG) # include #endif #include template typename bg::default_area_result::type test_intersection(std::string const& caseid, G1 const& g1, G2 const& g2, std::size_t expected_count = 0, int expected_point_count = 0, double expected_length_or_area = 0, double percentage = 0.0001, bool debug = false) { bool const is_line = bg::geometry_id::type::value == 2; if (debug) { std::cout << std::endl << "case " << caseid << std::endl; } typedef typename bg::coordinate_type::type coordinate_type; typedef typename bg::point_type::type point_type; if (! debug) { // Check _inserter behaviour with stratey typedef bg::strategy_intersection < typename bg::cs_tag::type, G1, G2, point_type, typename bg::rescale_policy_type::type, CalculationType > strategy; std::vector clip; bg::detail::intersection::intersection_insert(g1, g2, std::back_inserter(clip), strategy()); } // Check normal behaviour std::vector intersection_output; bg::intersection(g1, g2, intersection_output); typename bg::default_area_result::type length_or_area = 0; int n = 0; for (typename std::vector::iterator it = intersection_output.begin(); it != intersection_output.end(); ++it) { if (expected_point_count > 0) { n += bg::num_points(*it, true); } // instead of specialization we check it run-time here length_or_area += is_line ? bg::length(*it) : bg::area(*it); if (debug) { std::cout << std::setprecision(20) << bg::wkt(*it) << std::endl; } } #if ! defined(BOOST_GEOMETRY_NO_BOOST_TEST) #if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) if (expected_point_count > 0) { BOOST_CHECK_MESSAGE(bg::math::abs(n - expected_point_count) < 3, "intersection: " << caseid << " #points expected: " << expected_point_count << " detected: " << n << " type: " << (type_for_assert_message()) ); } #endif if (expected_count > 0) { BOOST_CHECK_MESSAGE(intersection_output.size() == expected_count, "intersection: " << caseid << " #outputs expected: " << expected_count << " detected: " << intersection_output.size() << " type: " << (type_for_assert_message()) ); } double const detected_length_or_area = boost::numeric_cast(length_or_area); BOOST_CHECK_CLOSE(detected_length_or_area, expected_length_or_area, percentage); #endif #if defined(TEST_WITH_SVG) { bool const ccw = bg::point_order::value == bg::counterclockwise || bg::point_order::value == bg::counterclockwise; bool const open = bg::closure::value == bg::open || bg::closure::value == bg::open; std::ostringstream filename; filename << "intersection_" << caseid << "_" << string_from_type::name() << string_from_type::name() << (ccw ? "_ccw" : "") << (open ? "_open" : "") #if defined(BOOST_GEOMETRY_NO_ROBUSTNESS) << "_no_rob" #endif << ".svg"; std::ofstream svg(filename.str().c_str()); bg::svg_mapper mapper(svg, 500, 500); mapper.add(g1); mapper.add(g2); mapper.map(g1, is_line ? "opacity:0.6;stroke:rgb(0,255,0);stroke-width:5" : "fill-opacity:0.5;fill:rgb(153,204,0);" "stroke:rgb(153,204,0);stroke-width:3"); mapper.map(g2, "fill-opacity:0.3;fill:rgb(51,51,153);" "stroke:rgb(51,51,153);stroke-width:3"); for (typename std::vector::const_iterator it = intersection_output.begin(); it != intersection_output.end(); ++it) { mapper.map(*it, "fill-opacity:0.2;stroke-opacity:0.4;fill:rgb(255,0,0);" "stroke:rgb(255,0,255);stroke-width:8"); } } #endif if (debug) { std::cout << "end case " << caseid << std::endl; } return length_or_area; } template typename bg::default_area_result::type test_one(std::string const& caseid, std::string const& wkt1, std::string const& wkt2, std::size_t expected_count = 0, int expected_point_count = 0, double expected_length_or_area = 0, double percentage = 0.0001, bool debug = false) { G1 g1; bg::read_wkt(wkt1, g1); G2 g2; bg::read_wkt(wkt2, g2); // Reverse if necessary bg::correct(g1); bg::correct(g2); return test_intersection(caseid, g1, g2, expected_count, expected_point_count, expected_length_or_area, percentage, debug); } template void test_one_lp(std::string const& caseid, std::string const& wkt_areal, std::string const& wkt_linear, std::size_t expected_count = 0, int expected_point_count = 0, double expected_length = 0, double percentage = 0.0001, bool debug1 = false, bool debug2 = false) { Areal areal; bg::read_wkt(wkt_areal, areal); bg::correct(areal); Linear linear; bg::read_wkt(wkt_linear, linear); test_intersection(caseid, areal, linear, expected_count, expected_point_count, expected_length, percentage, debug1); // A linestring reversed should deliver exactly the same. bg::reverse(linear); test_intersection(caseid + "_rev", areal, linear, expected_count, expected_point_count, expected_length, percentage, debug2); } template void test_point_output(std::string const& wkt1, std::string const& wkt2, unsigned int expected_count) { Geometry1 g1; bg::read_wkt(wkt1, g1); bg::correct(g1); Geometry2 g2; bg::read_wkt(wkt2, g2); bg::correct(g2); std::vector::type> points; bg::intersection(g1, g2, points); BOOST_CHECK_EQUAL(points.size(), expected_count); } #endif