diff --git a/tests/cpp_tests/clipping_test.cpp b/tests/cpp_tests/clipping_test.cpp new file mode 100644 index 000000000..23757aa7b --- /dev/null +++ b/tests/cpp_tests/clipping_test.cpp @@ -0,0 +1,123 @@ + +// mapnik +#include +#include + +// boost +#include +#include +#include + +// stl +#include +#include +#include +#include + +// agg +#include "agg_conv_clip_polygon.h" +#include "agg_conv_clip_polyline.h" +//#include "agg_path_storage.h" +//#include "agg_conv_clipper.h" + + +template +std::string dump_path(T & path) +{ + unsigned cmd = 1; + double x = 0; + double y = 0; + unsigned idx = 0; + std::ostringstream s; + path.rewind(0); + while ((cmd = path.vertex(&x, &y)) != mapnik::SEG_END) + { + if (idx > 0) s << ","; + s << x << " " << y << " " << cmd; + idx++; + } + return s.str(); +} + +std::string clip_line(mapnik::box2d const& bbox, + mapnik::geometry_type & geom) +{ + typedef agg::conv_clip_polyline line_clipper; + line_clipper clipped(geom); + clipped.clip_box(bbox.minx(),bbox.miny(),bbox.maxx(),bbox.maxy()); + return dump_path(clipped); +} + +void parse_geom(mapnik::geometry_type & geom, + std::string const& geom_string) { + std::vector vertices; + boost::split(vertices, geom_string, boost::is_any_of(",")); + BOOST_FOREACH(std::string const& vert, vertices) + { + std::vector commands; + boost::split(commands, vert, boost::is_any_of(" ")); + if (commands.size() != 3) + { + throw std::runtime_error(std::string("could not parse geometry '") + geom_string + "'"); + } + double x = 0; + double y = 0; + int c = 0; + if (mapnik::util::string2double(commands[0],x) + && mapnik::util::string2double(commands[1],y) + && mapnik::util::string2int(commands[2],c)) + { + geom.push_vertex(x,y,(mapnik::CommandType)c); + } + else + { + throw std::runtime_error(std::string("could not parse geometry '") + geom_string + "'"); + } + } +} + +int main( int, char*[] ) +{ + try { + std::string filename("tests/cpp_tests/data/cases.txt"); + std::ifstream stream(filename.c_str(),std::ios_base::in | std::ios_base::binary); + if (!stream.is_open()) + throw std::runtime_error("could not open: '" + filename + "'"); + + std::string csv_line; + while(std::getline(stream,csv_line,'\n')) + { + if (csv_line.empty() || csv_line[0] == '#') continue; + std::vector parts; + boost::split(parts, csv_line, boost::is_any_of(";")); + // first part is clipping box + mapnik::box2d bbox; + if (!bbox.from_string(parts[0])) { + throw std::runtime_error(std::string("could not parse bbox '") + parts[0] + "'"); + } + // second part is input geometry + mapnik::geometry_type geom; + parse_geom(geom,parts[1]); + //std::clog << dump_path(geom) << "\n"; + // third part is expected, clipped geometry + BOOST_TEST_EQ(clip_line(bbox,geom),parts[2]); + } + stream.close(); + } + catch (std::exception const& ex) + { + std::cerr << ex.what() << "\n"; + } + + if (!::boost::detail::test_errors()) + { + std::clog << "C++ clipping: \x1b[1;32m✓ \x1b[0m\n"; +#if BOOST_VERSION >= 104600 + ::boost::detail::report_errors_remind().called_report_errors_function = true; +#endif + } + else + { + return ::boost::report_errors(); + } +} diff --git a/tests/cpp_tests/data/cases.txt b/tests/cpp_tests/data/cases.txt new file mode 100644 index 000000000..d2d0b07c2 --- /dev/null +++ b/tests/cpp_tests/data/cases.txt @@ -0,0 +1,7 @@ +# testcase format is: +# ;; +# SEG_END=0 SEG_MOVETO = 1 SEG_LINETO = 2 SEG_CLOSE = (0x40 | 0x0f) +50,50,150,150;0 0 1,200 200 2;50 50 1,150 150 2 +50,50,150,150;50 50 1,150 50 2,150 150 2,50 150 2,50 50 2;50 50 1,150 50 2,150 150 2,50 150 2,50 50 2 +# TODO - should the close path be kept after clipping? +50,50,150,150;50 50 1,150 50 2,150 150 2,50 150 2,50 50 2,0 0 79;50 50 1,150 50 2,150 150 2,50 150 2,50 50 2, 0 0 79 \ No newline at end of file