// Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test // Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2011 Bruno Lalande, Paris, France. // Copyright (c) 2009-2011 Mateusz Loskot, London, UK. // 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) #include #include #include #include #include #include #include #include #include #include #define TEST_WITH_SVG #if defined(TEST_WITH_SVG) # include # include # include #endif template void test_sectionalize_part() { typedef typename bg::point_type::type point_type; typedef bg::model::box box_type; typedef bg::sections sections_type; typedef typename boost::range_value::type section_type; typedef bg::detail::sectionalize::sectionalize_part < Geometry, point_type, sections_type, 1, 10 > sectionalize_part; sections_type sections; section_type section; Geometry geometry; geometry.push_back(bg::make(1, 1)); bg::ring_identifier ring_id; int index = 0; int ndi = 0; sectionalize_part::apply(sections, section, index, ndi, geometry, ring_id); // There should not yet be anything generated, because it is only ONE point geometry.push_back(bg::make(2, 2)); sectionalize_part::apply(sections, section, index, ndi, geometry, ring_id); } template void test_sectionalize(std::string const caseid, G const& g, std::size_t section_count, std::string const& index_check, std::string const& dir_check) { typedef typename bg::point_type::type point; typedef bg::model::box box; typedef bg::sections sections; sections s; bg::sectionalize(g, s); BOOST_CHECK_EQUAL(s.size(), section_count); // Check if sections are consecutive and consistent int previous_index = -1; BOOST_FOREACH(typename sections::value_type const& sec, s) { if (sec.begin_index > 0) { BOOST_CHECK_EQUAL(previous_index, sec.begin_index); } BOOST_CHECK_EQUAL(int(sec.count), int(sec.end_index - sec.begin_index)); previous_index = sec.end_index; } // Output streams for sections, boxes, other std::ostringstream out_sections; std::ostringstream out_boxes; std::ostringstream out_dirs; for (typename sections::size_type i = 0; i < s.size(); i++) { box const& b = s[i].bounding_box; if (i > 0) { out_sections << "|"; out_dirs << "|"; out_boxes << "|"; } out_sections << s[i].begin_index << ".." << s[i].end_index; out_boxes << bg::get<0,0>(b) << " " << bg::get<0,1>(b) << ".." << bg::get<1,0>(b) << " " << bg::get<1,1>(b); for (int d = 0; d < DimensionCount; d++) { out_dirs << (d == 0 ? "" : " "); switch(s[i].directions[d]) { case -99: out_dirs << "DUP"; break; case -1 : out_dirs << "-"; break; case 0 : out_dirs << "."; break; case +1 : out_dirs << "+"; break; } } } if (! index_check.empty()) { BOOST_CHECK_EQUAL(out_sections.str(), index_check); } if (! dir_check.empty()) { BOOST_CHECK_EQUAL(out_dirs.str(), dir_check); } else { if (out_sections.str().length() < 80) { std::cout << std::endl << bg::wkt(g) << std::endl; std::cout << out_sections.str() << std::endl; //std::cout << out_boxes.str() << std::endl; } std::cout << out_dirs.str() << std::endl; } #if defined(TEST_WITH_SVG) { std::ostringstream filename; filename << "sectionalize_" << caseid << ".svg"; std::ofstream svg(filename.str().c_str()); typedef typename bg::point_type::type point_type; bg::svg_mapper mapper(svg, 500, 500); mapper.add(g); static const bool is_line = bg::geometry_id::type::value == 2; mapper.map(g, is_line ? "opacity:0.6;stroke:rgb(0,0,255);stroke-width:5" : "opacity:0.6;fill:rgb(0,0,255);stroke:rgb(0,0,0);stroke-width:0.5"); for (typename sections::size_type i = 0; i < s.size(); i++) { box b = s[i].bounding_box; bg::buffer(b, b, 0.01); mapper.map(b, s[i].duplicate ? "fill-opacity:0.4;stroke-opacity:0.6;fill:rgb(0,128,0);stroke:rgb(0,255,0);stroke-width:2.0" : "fill-opacity:0.2;stroke-opacity:0.4;fill:rgb(255,0,0);stroke:rgb(255,0,0);stroke-width:0.5"); std::ostringstream out; for (int d = 0; d < DimensionCount; d++) { out << (d == 0 ? "[" : " "); switch(s[i].directions[d]) { case -99: out << "DUP"; break; case -1 : out << "-"; break; case 0 : out << "."; break; case +1 : out << "+"; break; } } out << "] " << s[i].begin_index << ".." << s[i].end_index; point_type p; bg::centroid(b, p); mapper.text(p, out.str(), ""); } } #endif } template void test_sectionalize(std::string const& caseid, std::string const& wkt, std::size_t count2, std::string const& s2, std::string const d2, std::size_t count1, std::string const& s1, std::string const d1) { G g; bg::read_wkt(wkt, g); test_sectionalize<2, Reverse>(caseid + "_d2", g, count2, s2, d2); test_sectionalize<1, Reverse>(caseid + "_d1", g, count1, s1, d1); } template void test_all() { test_sectionalize_part<1, bg::model::linestring

>(); test_sectionalize, false>("ls", "LINESTRING(1 1,2 2,3 0,5 0,5 8)", 4, "0..1|1..2|2..3|3..4", "+ +|+ -|+ .|. +", 2, "0..3|3..4", "+|."); // These strings mean: // 0..1|1..2 -> first section: [0, 1] | second section [1, 2], etc // + +|+ - -> X increases, Y increases | X increases, Y decreases // +|. -> (only X considered) X increases | X constant test_sectionalize, false>("simplex", "POLYGON((0 0,0 7,4 2,2 0,0 0))", 4, "0..1|1..2|2..3|3..4", ". +|+ -|- -|- .", // . + - - -> 3 sections 3, "0..1|1..2|2..4", ".|+|-"); // CCW polygon - orientation is not (always) relevant for sections, // they are just generated in the order they come. test_sectionalize, false>("simplex_ccw", "POLYGON((0 0,2 0,4 2,0 7,0 0))", 4, "0..1|1..2|2..3|3..4", "+ .|+ +|- +|. -", // . + - - -> 3 sections 3, "0..2|2..3|3..4", "+|-|."); // Open polygon - closeness IS relevant for sections, the // last section which is not explicit here should be included. // So results are the same as the pre-previous one. test_sectionalize, false>("simplex_open", "POLYGON((0 0,0 7,4 2,2 0))", 4, "0..1|1..2|2..3|3..4", ". +|+ -|- -|- .", // . + - - -> 3 sections 3, "0..1|1..2|2..4", ".|+|-"); test_sectionalize, false>("first", "polygon((2.0 1.3, 2.4 1.7, 2.8 1.8, 3.4 1.2, 3.7 1.6,3.4 2.0, 4.1 3.0, 5.3 2.6, 5.4 1.2, 4.9 0.8, 2.9 0.7,2.0 1.3))", 8, "0..2|2..3|3..4|4..5|5..6|6..8|8..10|10..11", "+ +|+ -|+ +|- +|+ +|+ -|- -|- +", 4, "0..4|4..5|5..8|8..11", "+|-|+|-"); test_sectionalize, true>("first_reverse", "polygon((2.0 1.3, 2.4 1.7, 2.8 1.8, 3.4 1.2, 3.7 1.6,3.4 2.0, 4.1 3.0, 5.3 2.6, 5.4 1.2, 4.9 0.8, 2.9 0.7,2.0 1.3))", 8, "0..1|1..3|3..5|5..6|6..7|7..8|8..9|9..11", "+ -|+ +|- +|- -|+ -|- -|- +|- -", 4, "0..3|3..6|6..7|7..11", "+|-|+|-"); test_sectionalize, false>("second", "POLYGON((3 1,2 2,1 3,2 4,3 5,4 4,5 3,4 2,3 1))", 4, "0..2|2..4|4..6|6..8", "- +|+ +|+ -|- -", // - - - + + + + - - -> 3 sections 3, "0..2|2..6|6..8", "-|+|-"); // With holes test_sectionalize, false>("with_holes", "POLYGON((3 1,2 2,1 3,2 4,3 5,4 4,5 3,4 2,3 1), (3 2,2 2,3 4,3 2))", 7, "0..2|2..4|4..6|6..8|0..1|1..2|2..3", "- +|+ +|+ -|- -|- .|+ +|. -", // - - - + + + + - - - + . -> 6 sections 6, "0..2|2..6|6..8|0..1|1..2|2..3", "-|+|-|-|+|."); // With duplicates test_sectionalize, false>("with_dups", "LINESTRING(1 1,2 2,3 0,3 0,5 0,5 8)", 5, "0..1|1..2|2..3|3..4|4..5", "+ +|+ -|DUP DUP|+ .|. +", 4, "0..2|2..3|3..4|4..5", "+|DUP|+|."); // With two subsequent duplicate segments test_sectionalize, false>("with_subseq_dups", "LINESTRING(1 1,2 2,3 0,3 0,3 0,5 0,5 0,5 0,5 0,5 8)", 6, "0..1|1..2|2..4|4..5|5..8|8..9", "+ +|+ -|DUP DUP|+ .|DUP DUP|. +", 5, "0..2|2..4|4..5|5..8|8..9", "+|DUP|+|DUP|."); typedef bg::model::box

B; test_sectionalize<2, false, B>("box2", bg::make(0,0,4,4), 4, "0..1|1..2|2..3|3..4", ". +|+ .|. -|- ."); test_sectionalize<1, false, B>("box1", bg::make(0,0,4,4), 4, "0..1|1..2|2..3|3..4", ".|+|.|-"); return; // Buffer-case test_sectionalize, false>("buffer", "POLYGON((-1.1713 0.937043,2.8287 5.93704,2.90334 6.02339,2.98433 6.10382,2.98433 6.10382,3.07121 6.17786,3.16346 6.24507,3.16346 6.24507,3.16346 6.24507,3.26056 6.30508,3.36193 6.35752,3.36193 6.35752,3.46701 6.40211,3.57517 6.43858,3.57517 6.43858,3.57517 6.43858,3.57517 6.43858,3.68579 6.46672,3.79822 6.48637,3.79822 6.48637,3.91183 6.49741,4.02595 6.49978,4.02595 6.49978,4.02595 6.49978,4.13991 6.49346,4.25307 6.4785,4.25307 6.4785,4.36476 6.45497,4.47434 6.42302,4.47434 6.42302,4.47434 6.42302,4.47434 6.42302,7.47434 5.42302,6.84189 3.52566,4.39043 4.68765,0.390434 -0.312348,-1.1713 0.937043))", 8, "0..2|2..3|3..4|4..5|5..6|6..8|8..10|10..11", "+ +|+ -|+ +|- +|+ +|+ -|- -|- +", 4, "0..4|4..5|5..8|8..11", "+|-|+|-"); } int test_main(int, char* []) { //test_all >(); test_all >(); return 0; }