diff --git a/include/mapnik/transform_expression.hpp b/include/mapnik/transform_expression.hpp index 0b9ed99ad..7b5b55c75 100644 --- a/include/mapnik/transform_expression.hpp +++ b/include/mapnik/transform_expression.hpp @@ -71,7 +71,7 @@ struct translate_node translate_node(expr_node const& tx, boost::optional const& ty) : tx_(tx) - , ty_(ty ? *ty : value_null()) {} + , ty_(ty ? expr_node(*ty) : value_null()) {} }; struct scale_node @@ -82,7 +82,7 @@ struct scale_node scale_node(expr_node const& sx, boost::optional const& sy) : sx_(sx) - , sy_(sy ? *sy : value_null()) {} + , sy_(sy ? expr_node(*sy) : value_null()) {} }; struct rotate_node @@ -104,8 +104,8 @@ struct rotate_node boost::optional const& cx, boost::optional const& cy) : angle_(angle) - , cx_(cx ? *cx : value_null()) - , cy_(cy ? *cy : value_null()) {} + , cx_(cx ? expr_node(*cx) : value_null()) + , cy_(cy ? expr_node(*cy) : value_null()) {} rotate_node(expr_node const& angle, boost::optional const& center) diff --git a/tests/cpp_tests/geometry_converters_test.cpp b/tests/cpp_tests/geometry_converters_test.cpp new file mode 100644 index 000000000..a549f9aa2 --- /dev/null +++ b/tests/cpp_tests/geometry_converters_test.cpp @@ -0,0 +1,175 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +#if BOOST_VERSION >= 104700 +#include +#include +#include +#endif + +#include +#include + +struct output_geometry_backend +{ + output_geometry_backend(boost::ptr_vector & paths, mapnik::eGeomType type) + : paths_(paths), + type_(type) {} + + template + void add_path(T & path) + { + mapnik::vertex2d vtx(mapnik::vertex2d::no_init); + path.rewind(0); + std::auto_ptr geom_ptr(new mapnik::geometry_type(type_)); + + while ((vtx.cmd = path.vertex(&vtx.x, &vtx.y)) != mapnik::SEG_END) + { + //std::cerr << vtx.x << "," << vtx.y << " cmd=" << vtx.cmd << std::endl; + geom_ptr->push_vertex(vtx.x, vtx.y, (mapnik::CommandType)vtx.cmd); + } + paths_.push_back(geom_ptr); + } + boost::ptr_vector & paths_; + mapnik::eGeomType type_; +}; + +boost::optional linestring_bbox_clipping(mapnik::box2d bbox, + std::string wkt_in) +{ + using namespace mapnik; + agg::trans_affine tr; + projection src; + projection dst; + proj_transform prj_trans(src,dst); + line_symbolizer sym; + CoordTransform t(bbox.width(),bbox.height(), bbox); + boost::ptr_vector output_paths; + output_geometry_backend backend(output_paths, mapnik::LineString); + + typedef boost::mpl::vector conv_types; + vertex_converter, output_geometry_backend, line_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, conv_types> + converter(bbox, backend, sym, t, prj_trans, tr, 1.0); + + converter.set(); + + boost::ptr_vector p; + if (!mapnik::from_wkt(wkt_in , p)) + { + throw std::runtime_error("Failed to parse WKT"); + } + + BOOST_FOREACH( geometry_type & geom, p) + { + converter.apply(geom); + } + + std::string wkt_out; + if (mapnik::util::to_wkt(wkt_out, output_paths)) + { + return boost::optional(wkt_out); + } + + return boost::optional(); +} + +boost::optional polygon_bbox_clipping(mapnik::box2d bbox, + std::string wkt_in) +{ + using namespace mapnik; + agg::trans_affine tr; + projection src; + projection dst; + proj_transform prj_trans(src,dst); + polygon_symbolizer sym; + CoordTransform t(bbox.width(),bbox.height(), bbox); + boost::ptr_vector output_paths; + output_geometry_backend backend(output_paths, mapnik::Polygon); + + typedef boost::mpl::vector conv_types; + vertex_converter, output_geometry_backend, polygon_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, conv_types> + converter(bbox, backend, sym, t, prj_trans, tr, 1.0); + + converter.set(); + + boost::ptr_vector p; + if (!mapnik::from_wkt(wkt_in , p)) + { + throw std::runtime_error("Failed to parse WKT"); + } + + BOOST_FOREACH( geometry_type & geom, p) + { + converter.apply(geom); + } + + std::string wkt_out; + if (mapnik::util::to_wkt(wkt_out, output_paths)) + { + return boost::optional(wkt_out); + } + + return boost::optional(); +} + +int main( int, char*[] ) +{ + // LineString/bbox clipping + { + std::string wkt_in("LineString(0 0,200 200)"); + boost::optional result = linestring_bbox_clipping(mapnik::box2d(50,50,150,150),wkt_in); + BOOST_TEST(result); + BOOST_TEST_EQ(*result,std::string("LineString(50 50,150 150)")); + } + // Polygon/bbox clipping +#if 0 + // these tests will fail + { + std::string wkt_in("Polygon((50 50,150 50,150 150,50 150,50 50))"); + boost::optional result = polygon_bbox_clipping(mapnik::box2d(50,50,150,150),wkt_in); + BOOST_TEST(result); + BOOST_TEST_EQ(*result,std::string("Polygon((50 50,150 50,150 150,50 150,50 50))")); + } + + { + std::string wkt_in("Polygon((60 60,140 60,140 160,60 140,60 60))"); + boost::optional result = polygon_bbox_clipping(mapnik::box2d(50,50,150,150),wkt_in); + BOOST_TEST(result); + BOOST_TEST_EQ(*result,std::string("Polygon((60 60,140 60,140 160,60 140,60 60))")); + } + + { + std::string wkt_in("Polygon((0 0,10 0,10 10,0 10,0 0))"); + boost::optional result = polygon_bbox_clipping(mapnik::box2d(50,50,150,150),wkt_in); + BOOST_TEST(result); + BOOST_TEST_EQ(*result, std::string("GeometryCollection EMPTY")); + } +#endif + { + std::string wkt_in("Polygon((0 0,100 200,200 0,0 0 ))"); + boost::optional result = polygon_bbox_clipping(mapnik::box2d(50,50,150,150),wkt_in); + BOOST_TEST(result); + BOOST_TEST_EQ(*result,std::string("Polygon((50 50,50 100,75 150,125 150,150 100,150 50,50 50))")); + } + + if (!::boost::detail::test_errors()) + { + std::clog << "C++ geometry conversions: \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(); + } +}