#include "catch.hpp" #include #include TEST_CASE("vertex_adapters") { SECTION("polygon") { mapnik::geometry::polygon g; g.emplace_back(); g.back().emplace_back(1,1); g.back().emplace_back(2,2); g.back().emplace_back(100,100); g.back().emplace_back(1,1); mapnik::geometry::polygon_vertex_adapter va(g); double x,y; unsigned cmd; cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_MOVETO ); REQUIRE( x == 1 ); REQUIRE( y == 1 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == 2 ); REQUIRE( y == 2 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == 100 ); REQUIRE( y == 100 ); // close cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_CLOSE ); REQUIRE( x == 0 ); REQUIRE( y == 0 ); // end cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_END ); REQUIRE( x == 0 ); REQUIRE( y == 0 ); } SECTION("polygon with hole") { mapnik::geometry::polygon g; g.emplace_back(); g.back().emplace_back(0,0); g.back().emplace_back(-10,0); g.back().emplace_back(-10,10); g.back().emplace_back(0,10); g.back().emplace_back(0,0); std::vector > interior_rings; mapnik::geometry::linear_ring hole; hole.emplace_back(-7,7); hole.emplace_back(-7,3); hole.emplace_back(-3,3); hole.emplace_back(-3,7); hole.emplace_back(-7,7); g.push_back(std::move(hole)); mapnik::geometry::linear_ring hole_in_hole; hole_in_hole.emplace_back(-6,4); hole_in_hole.emplace_back(-6,6); hole_in_hole.emplace_back(-4,6); hole_in_hole.emplace_back(-4,4); hole_in_hole.emplace_back(-6,4); g.push_back(std::move(hole_in_hole)); mapnik::geometry::polygon_vertex_adapter va(g); double x,y; unsigned cmd; // exterior ring cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_MOVETO ); REQUIRE( x == 0 ); REQUIRE( y == 0 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -10 ); REQUIRE( y == 0 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -10 ); REQUIRE( y == 10 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == 0 ); REQUIRE( y == 10 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_CLOSE ); REQUIRE( x == 0 ); REQUIRE( y == 0 ); // exterior ring via ring_vertex_adapter mapnik::geometry::ring_vertex_adapter va2(g.front()); cmd = va2.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_MOVETO ); REQUIRE( x == 0 ); REQUIRE( y == 0 ); cmd = va2.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -10 ); REQUIRE( y == 0 ); cmd = va2.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -10 ); REQUIRE( y == 10 ); cmd = va2.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == 0 ); REQUIRE( y == 10 ); cmd = va2.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_CLOSE ); REQUIRE( x == 0 ); REQUIRE( y == 0 ); // since ring adapter is only for exterior, next should be END cmd = va2.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_END ); REQUIRE( x == 0 ); REQUIRE( y == 0 ); // first hole for polygon_adapter cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_MOVETO ); REQUIRE( x == -7 ); REQUIRE( y == 7 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -7 ); REQUIRE( y == 3 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -3 ); REQUIRE( y == 3 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -3 ); REQUIRE( y == 7 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_CLOSE ); REQUIRE( x == 0 ); REQUIRE( y == 0 ); // second hole cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_MOVETO ); REQUIRE( x == -6 ); REQUIRE( y == 4 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -6 ); REQUIRE( y == 6 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -4 ); REQUIRE( y == 6 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -4 ); REQUIRE( y == 4 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_CLOSE ); REQUIRE( x == 0 ); REQUIRE( y == 0 ); mapnik::geometry::correct(g); va.rewind(0); // exterior ring: flipped winding order from correct cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_MOVETO ); REQUIRE( x == 0 ); REQUIRE( y == 0 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == 0 ); REQUIRE( y == 10 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -10 ); REQUIRE( y == 10 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -10 ); REQUIRE( y == 0 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_CLOSE ); REQUIRE( x == 0 ); REQUIRE( y == 0 ); // first hole: flipped winding order from correct cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_MOVETO ); REQUIRE( x == -7 ); REQUIRE( y == 7 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -3 ); REQUIRE( y == 7 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -3 ); REQUIRE( y == 3 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -7 ); REQUIRE( y == 3 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_CLOSE ); REQUIRE( x == 0 ); REQUIRE( y == 0 ); // second hole: correct appears not to have changed winding order cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_MOVETO ); REQUIRE( x == -6 ); REQUIRE( y == 4 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -6 ); REQUIRE( y == 6 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -4 ); REQUIRE( y == 6 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_LINETO ); REQUIRE( x == -4 ); REQUIRE( y == 4 ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_CLOSE ); REQUIRE( x == 0 ); REQUIRE( y == 0 ); } SECTION("polygon with empty exterior ring") { mapnik::geometry::polygon g; g.emplace_back(); mapnik::geometry::polygon_vertex_adapter va(g); double x = 0, y = 0; unsigned cmd; cmd = va.vertex(&x,&y); CHECK( cmd == mapnik::SEG_END ); CHECK( x == Approx(0) ); CHECK( y == Approx(0) ); } SECTION("polygon with empty interior ring") { mapnik::geometry::polygon g; g.emplace_back(); g.back().emplace_back(-1, -1); g.back().emplace_back( 1, -1); g.back().emplace_back( 1, 1); g.back().emplace_back(-1, 1); g.back().emplace_back(-1, -1); // Emplace empty interior ring g.emplace_back(); mapnik::geometry::polygon_vertex_adapter va(g); double x,y; unsigned cmd; cmd = va.vertex(&x,&y); CHECK( cmd == mapnik::SEG_MOVETO ); CHECK( x == Approx(-1) ); CHECK( y == Approx(-1) ); cmd = va.vertex(&x,&y); CHECK( cmd == mapnik::SEG_LINETO ); CHECK( x == Approx(1) ); CHECK( y == Approx(-1) ); cmd = va.vertex(&x,&y); CHECK( cmd == mapnik::SEG_LINETO ); CHECK( x == Approx(1) ); CHECK( y == Approx(1) ); cmd = va.vertex(&x,&y); CHECK( cmd == mapnik::SEG_LINETO ); CHECK( x == Approx(-1) ); CHECK( y == Approx(1) ); cmd = va.vertex(&x,&y); CHECK( cmd == mapnik::SEG_CLOSE ); CHECK( x == Approx(0) ); CHECK( y == Approx(0) ); cmd = va.vertex(&x,&y); CHECK( cmd == mapnik::SEG_CLOSE ); CHECK( x == Approx(0) ); CHECK( y == Approx(0) ); cmd = va.vertex(&x,&y); REQUIRE( cmd == mapnik::SEG_END ); REQUIRE( x == Approx(0) ); REQUIRE( y == Approx(0) ); } }