-
Notifications
You must be signed in to change notification settings - Fork 827
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
+ add geometry conversions tests (clipping,smothing...)
- Loading branch information
Showing
1 changed file
with
176 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
#include <boost/version.hpp> | ||
|
||
#include <mapnik/layer.hpp> | ||
#include <mapnik/feature_type_style.hpp> | ||
#include <mapnik/debug.hpp> | ||
#include <mapnik/ctrans.hpp> | ||
#include <mapnik/vertex_converters.hpp> | ||
#include <mapnik/geometry.hpp> | ||
#include <mapnik/wkt/wkt_factory.hpp> | ||
|
||
#if BOOST_VERSION >= 104700 | ||
#include <mapnik/util/geometry_to_wkb.hpp> | ||
#include <mapnik/util/geometry_to_wkt.hpp> | ||
#include <mapnik/util/geometry_to_svg.hpp> | ||
#endif | ||
|
||
#include <boost/detail/lightweight_test.hpp> | ||
#include <iostream> | ||
|
||
struct output_geometry_backend | ||
{ | ||
output_geometry_backend(boost::ptr_vector<mapnik::geometry_type> & paths, mapnik::eGeomType type) | ||
: paths_(paths), | ||
type_(type) {} | ||
|
||
template <typename T> | ||
void add_path(T & path) | ||
{ | ||
mapnik::vertex2d vtx(mapnik::vertex2d::no_init); | ||
path.rewind(0); | ||
std::auto_ptr<mapnik::geometry_type> 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<mapnik::geometry_type> & paths_; | ||
mapnik::eGeomType type_; | ||
}; | ||
|
||
boost::optional<std::string> linestring_bbox_clipping(mapnik::box2d<double> 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<mapnik::geometry_type> output_paths; | ||
output_geometry_backend backend(output_paths, mapnik::LineString); | ||
|
||
typedef boost::mpl::vector<clip_line_tag> conv_types; | ||
vertex_converter<box2d<double>, output_geometry_backend, line_symbolizer, | ||
CoordTransform, proj_transform, agg::trans_affine, conv_types> | ||
converter(bbox, backend, sym, t, prj_trans, tr, 1.0); | ||
|
||
converter.template set<clip_line_tag>(); | ||
|
||
boost::ptr_vector<geometry_type> 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<std::string>(wkt_out); | ||
} | ||
|
||
return boost::optional<std::string>(); | ||
} | ||
|
||
boost::optional<std::string> polygon_bbox_clipping(mapnik::box2d<double> 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<mapnik::geometry_type> output_paths; | ||
output_geometry_backend backend(output_paths, mapnik::Polygon); | ||
|
||
typedef boost::mpl::vector<clip_poly_tag> conv_types; | ||
vertex_converter<box2d<double>, output_geometry_backend, polygon_symbolizer, | ||
CoordTransform, proj_transform, agg::trans_affine, conv_types> | ||
converter(bbox, backend, sym, t, prj_trans, tr, 1.0); | ||
|
||
converter.template set<clip_poly_tag>(); | ||
|
||
boost::ptr_vector<geometry_type> 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<std::string>(wkt_out); | ||
} | ||
|
||
return boost::optional<std::string>(); | ||
} | ||
|
||
int main( int, char*[] ) | ||
{ | ||
// LineString/bbox clipping | ||
{ | ||
std::string wkt_in("LineString(0 0,200 200)"); | ||
boost::optional<std::string> result = linestring_bbox_clipping(mapnik::box2d<double>(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<std::string> result = polygon_bbox_clipping(mapnik::box2d<double>(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<std::string> result = polygon_bbox_clipping(mapnik::box2d<double>(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<std::string> result = polygon_bbox_clipping(mapnik::box2d<double>(50,50,150,150),wkt_in); | ||
BOOST_TEST(result); | ||
BOOST_TEST_EQ(*result,std::string("Polygon EMPTY")); | ||
} | ||
#endif | ||
{ | ||
std::string wkt_in("Polygon((0 0, 100 200, 200 0, 0 0 ))"); | ||
boost::optional<std::string> result = polygon_bbox_clipping(mapnik::box2d<double>(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(); | ||
} | ||
} |