// 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 argc, char** argv) { std::vector args; for (int i=1;i 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()) { if (quiet) std::clog << "\x1b[1;32m.\x1b[0m"; else 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(); } }