Skip to content

Commit

Permalink
test: Improve geos_helpers coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
eyal0 committed Feb 10, 2021
1 parent 907183d commit c2994fc
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 19 deletions.
2 changes: 1 addition & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ common_tests_SOURCES = common.hpp common.cpp common_tests.cpp boost_unit_test.cp
backtrack_tests_SOURCES = backtrack.hpp backtrack.cpp backtrack_tests.cpp boost_unit_test.cpp bg_helpers.hpp bg_helpers.cpp eulerian_paths.hpp eulerian_paths.cpp segmentize.hpp segmentize.cpp merge_near_points.hpp merge_near_points.cpp bg_operators.hpp bg_operators.cpp geos_helpers.hpp geos_helpers.cpp
trim_paths_tests_SOURCES = trim_paths.hpp trim_paths.cpp trim_paths_tests.cpp boost_unit_test.cpp bg_helpers.hpp bg_helpers.cpp eulerian_paths.hpp eulerian_paths.cpp segmentize.hpp segmentize.cpp merge_near_points.hpp merge_near_points.cpp bg_operators.hpp bg_operators.cpp geos_helpers.hpp geos_helpers.cpp
outline_bridges_tests_SOURCES = outline_bridges_tests.cpp outline_bridges.hpp outline_bridges.cpp bg_operators.hpp bg_operators.cpp bg_helpers.hpp bg_helpers.cpp eulerian_paths.hpp eulerian_paths.cpp segmentize.hpp segmentize.cpp boost_unit_test.cpp merge_near_points.hpp merge_near_points.cpp geos_helpers.hpp geos_helpers.cpp
geos_helpers_tests_SOURCES = geos_helpers_tests.cpp geos_helpers.cpp geos_helpers.hpp boost_unit_test.cpp
geos_helpers_tests_SOURCES = geos_helpers_tests.cpp geos_helpers.cpp geos_helpers.hpp boost_unit_test.cpp bg_operators.cpp bg_helpers.cpp eulerian_paths.cpp segmentize.cpp merge_near_points.cpp

TESTS = $(check_PROGRAMS)

Expand Down
1 change: 1 addition & 0 deletions bg_operators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ bg::model::multi_polygon<polygon_type_t> operator-(
}

template multi_polygon_type_fp operator-(const multi_polygon_type_fp&, const multi_polygon_type_fp&);
template multi_polygon_type_fp operator-(const multi_polygon_type_fp&, const box_type_fp&);

template <typename rhs_t>
multi_polygon_type_fp operator-(const box_type_fp& lhs, const rhs_t& rhs) {
Expand Down
6 changes: 3 additions & 3 deletions geos_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,12 @@ multi_linestring_type_fp from_geos(const std::unique_ptr<geos::geom::MultiLineSt

template <>
multi_polygon_type_fp from_geos(const std::unique_ptr<geos::geom::Geometry>& g) {
auto mp = boost::dynamic_pointer_cast<geos::geom::MultiPolygon>(g->clone());
if (mp) {
if (dynamic_cast<geos::geom::MultiPolygon*>(g.get())) {
auto mp = boost::dynamic_pointer_cast<geos::geom::MultiPolygon>(g->clone());
return from_geos(mp);
}
if (dynamic_cast<geos::geom::Polygon*>(g.get())) {
auto p = boost::dynamic_pointer_cast<geos::geom::Polygon>(g->clone());
if (p) {
return multi_polygon_type_fp{from_geos(p)};
}
geos::io::WKTWriter writer;
Expand Down
91 changes: 76 additions & 15 deletions geos_helpers_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,91 @@
#ifdef GEOS_VERSION
#include <geos/io/WKTReader.h>
#endif // GEOS_VERSION
#include <boost/pointer_cast.hpp>

BOOST_AUTO_TEST_SUITE(geos_helpers_tests)

// Confirm that both geos and boost support clockwise rings.
BOOST_AUTO_TEST_CASE(direction) {
BOOST_AUTO_TEST_SUITE(boost_geometry)

// Holes are counter-clockwise
BOOST_AUTO_TEST_CASE(polygon_with_holes_direction) {
auto box = bg::return_envelope<box_type_fp>(point_type_fp(0,0));
bg::expand(box, point_type_fp(10,10));
polygon_type_fp poly;
bg::convert(box, poly);
BOOST_CHECK_EQUAL(poly.outer()[1], point_type_fp(0,10));
bg::reverse(poly);
bg::correct(poly);
BOOST_CHECK_EQUAL(poly.outer()[1], point_type_fp(0,10));
auto hole = bg::return_envelope<box_type_fp>(point_type_fp(3,3));
bg::expand(hole, point_type_fp(7,7));
multi_polygon_type_fp mpoly;
bg::convert(box, mpoly);
mpoly = mpoly - hole;
BOOST_CHECK_EQUAL(mpoly[0].outer()[1], point_type_fp(0,10));
BOOST_CHECK_EQUAL(mpoly[0].inners()[0][1], point_type_fp(7,3));
bg::reverse(mpoly);
BOOST_CHECK_EQUAL(mpoly[0].outer()[1], point_type_fp(10,0));
BOOST_CHECK_EQUAL(mpoly[0].inners()[0][1], point_type_fp(3,7));
bg::correct(mpoly);
BOOST_CHECK_EQUAL(mpoly[0].outer()[1], point_type_fp(0,10));
BOOST_CHECK_EQUAL(mpoly[0].inners()[0][1], point_type_fp(7,3));
}

BOOST_AUTO_TEST_SUITE_END()

#ifdef GEOS_VERSION

BOOST_AUTO_TEST_SUITE(geos_geometry)

BOOST_AUTO_TEST_CASE(polygon_with_holes_direction) {
// Convert it through well-known text, which is sure to create a
// valid polygon in geos.
geos::io::WKTReader reader;
std::stringstream ss;
ss << bg::wkt(poly);
auto geos_geo = reader.read(ss.str());
const auto* geos_poly = dynamic_cast<geos::geom::Polygon*>(geos_geo.get());
BOOST_CHECK_EQUAL(geos_poly->getExteriorRing()->getPointN(1)->getX(), 0);
BOOST_CHECK_EQUAL(geos_poly->getExteriorRing()->getPointN(1)->getY(), 10);
#endif // GEOS_VERSION
auto geos_geo = reader.read("MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0),(3 3,7 3,7 7,3 7,3 3)))");
auto* geos_poly = dynamic_cast<geos::geom::MultiPolygon*>(geos_geo.get());
geos_poly->normalize();
BOOST_CHECK_EQUAL(geos_poly->getGeometryN(0)->getExteriorRing()->getPointN(1)->getX(), 0);
BOOST_CHECK_EQUAL(geos_poly->getGeometryN(0)->getExteriorRing()->getPointN(1)->getY(), 10);
BOOST_CHECK_EQUAL(geos_poly->getGeometryN(0)->getInteriorRingN(0)->getPointN(1)->getX(), 7);
BOOST_CHECK_EQUAL(geos_poly->getGeometryN(0)->getInteriorRingN(0)->getPointN(1)->getY(), 3);

// Now convert a reversed version.
geos_geo = reader.read("MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(3 3,3 7,7 7,7 3,3 3)))");
geos_poly = dynamic_cast<geos::geom::MultiPolygon*>(geos_geo.get());
geos_poly->normalize();
BOOST_CHECK_EQUAL(geos_poly->getGeometryN(0)->getExteriorRing()->getPointN(1)->getX(), 0);
BOOST_CHECK_EQUAL(geos_poly->getGeometryN(0)->getExteriorRing()->getPointN(1)->getY(), 10);
BOOST_CHECK_EQUAL(geos_poly->getGeometryN(0)->getInteriorRingN(0)->getPointN(1)->getX(), 7);
BOOST_CHECK_EQUAL(geos_poly->getGeometryN(0)->getInteriorRingN(0)->getPointN(1)->getY(), 3);
}

BOOST_AUTO_TEST_SUITE(roundtrip)

BOOST_AUTO_TEST_CASE(multi_linestring) {
multi_linestring_type_fp mls{{{0,0}, {1,1}}, {{2,2},{3,3}}};
BOOST_CHECK_EQUAL(from_geos(to_geos(mls)), mls);
}

BOOST_AUTO_TEST_CASE(linestring) {
linestring_type_fp ls{{0,0}, {1,1}};
BOOST_CHECK_EQUAL(from_geos(to_geos(ls)), ls);
}

BOOST_AUTO_TEST_CASE(polygon) {
polygon_type_fp poly{{{0,0}, {0,10}, {10,10}, {10,0}, {0,0}}};
BOOST_CHECK(bg::equals(from_geos(to_geos(poly)), poly));
}

BOOST_AUTO_TEST_CASE(ring) {
ring_type_fp ring{{0,0}, {0,10}, {10,10}, {10,0}, {0,0}};
BOOST_CHECK_EQUAL(from_geos(to_geos(ring)), ring);
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_CASE(convert_multi_polygon_exception) {
linestring_type_fp ls{{0,0}, {1,1}};
auto geos_ls = boost::dynamic_pointer_cast<geos::geom::Geometry>(to_geos(ls));
BOOST_CHECK_THROW(from_geos<multi_polygon_type_fp>(geos_ls), std::logic_error);
}

BOOST_AUTO_TEST_SUITE_END()

#endif // GEOS_VERSION

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit c2994fc

Please sign in to comment.