Merge pull request #3678 from mapycz/fix-polygon-closing-on-reprojection
fix closing polygons on reprojection
This commit is contained in:
commit
4d7e95c0c0
7 changed files with 292 additions and 24 deletions
|
@ -26,8 +26,8 @@
|
||||||
#include <mapnik/markers_placements/line.hpp>
|
#include <mapnik/markers_placements/line.hpp>
|
||||||
#include <mapnik/markers_placements/point.hpp>
|
#include <mapnik/markers_placements/point.hpp>
|
||||||
#include <mapnik/markers_placements/interior.hpp>
|
#include <mapnik/markers_placements/interior.hpp>
|
||||||
#include <mapnik/markers_placements/vertext_first.hpp>
|
#include <mapnik/markers_placements/vertex_first.hpp>
|
||||||
#include <mapnik/markers_placements/vertext_last.hpp>
|
#include <mapnik/markers_placements/vertex_last.hpp>
|
||||||
#include <mapnik/symbolizer_enumerations.hpp>
|
#include <mapnik/symbolizer_enumerations.hpp>
|
||||||
|
|
||||||
namespace mapnik
|
namespace mapnik
|
||||||
|
|
|
@ -41,42 +41,67 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
double x0, y0;
|
geometry::point<double> p0;
|
||||||
unsigned command0 = this->locator_.vertex(&x0, &y0);
|
geometry::point<double> p1;
|
||||||
|
geometry::point<double> p_next;
|
||||||
|
geometry::point<double> move_to;
|
||||||
|
unsigned cmd0 = SEG_END;
|
||||||
|
unsigned cmd1 = SEG_END;
|
||||||
|
unsigned cmd_next = SEG_END;
|
||||||
|
|
||||||
if (agg::is_stop(command0))
|
while ((cmd_next = this->locator_.vertex(&p_next.x, &p_next.y)) != SEG_END)
|
||||||
|
{
|
||||||
|
switch (cmd_next)
|
||||||
|
{
|
||||||
|
case SEG_MOVETO:
|
||||||
|
move_to = p_next;
|
||||||
|
p0 = p_next;
|
||||||
|
cmd0 = cmd_next;
|
||||||
|
break;
|
||||||
|
case SEG_LINETO:
|
||||||
|
p1 = p0;
|
||||||
|
cmd1 = cmd0;
|
||||||
|
p0 = p_next;
|
||||||
|
cmd0 = cmd_next;
|
||||||
|
break;
|
||||||
|
case SEG_CLOSE:
|
||||||
|
p1 = p0;
|
||||||
|
cmd1 = cmd0;
|
||||||
|
p0 = move_to;
|
||||||
|
cmd0 = cmd_next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty geometry
|
||||||
|
if (cmd0 == SEG_END)
|
||||||
{
|
{
|
||||||
this->done_ = true;
|
this->done_ = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
double next_x, next_y;
|
// Last point
|
||||||
double x1 = x0, y1 = y0;
|
x = p0.x;
|
||||||
unsigned command1 = command0;
|
y = p0.y;
|
||||||
|
|
||||||
while (!agg::is_stop(command0 = this->locator_.vertex(&next_x, &next_y)))
|
// Line or polygon
|
||||||
|
if (cmd0 == SEG_LINETO || cmd0 == SEG_CLOSE)
|
||||||
{
|
{
|
||||||
command1 = command0;
|
angle = std::atan2(p0.y - p1.y, p0.x - p1.x);
|
||||||
x1 = x0;
|
|
||||||
y1 = y0;
|
|
||||||
x0 = next_x;
|
|
||||||
y0 = next_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
x = x0;
|
|
||||||
y = y0;
|
|
||||||
|
|
||||||
if (agg::is_line_to(command1))
|
|
||||||
{
|
|
||||||
angle = std::atan2(y0 - y1, x0 - x1);
|
|
||||||
if (!this->set_direction(angle))
|
if (!this->set_direction(angle))
|
||||||
{
|
{
|
||||||
|
this->done_ = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
angle = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this->push_to_detector(x, y, angle, ignore_placement))
|
if (!this->push_to_detector(x, y, angle, ignore_placement))
|
||||||
{
|
{
|
||||||
|
this->done_ = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ struct transform_path_adapter
|
||||||
while (!ok)
|
while (!ok)
|
||||||
{
|
{
|
||||||
command = geom_.vertex(x,y);
|
command = geom_.vertex(x,y);
|
||||||
if (command == SEG_END)
|
if (command == SEG_END || command == SEG_CLOSE)
|
||||||
{
|
{
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 75ecac5c3bd44f1c9111d9b3fba785a1713f2444
|
Subproject commit 85a94e315d0c2d4b3c7248ee9a7fc0197cac2002
|
126
test/unit/symbolizer/marker_placement_vertex_last.cpp
Normal file
126
test/unit/symbolizer/marker_placement_vertex_last.cpp
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
#include <mapnik/vertex_adapters.hpp>
|
||||||
|
#include <mapnik/label_collision_detector.hpp>
|
||||||
|
#include <mapnik/markers_placements/vertex_last.hpp>
|
||||||
|
|
||||||
|
using namespace mapnik;
|
||||||
|
|
||||||
|
TEST_CASE("marker placement vertex last") {
|
||||||
|
|
||||||
|
SECTION("empty geometry") {
|
||||||
|
|
||||||
|
mapnik::geometry::line_string<double> g;
|
||||||
|
using va_type = mapnik::geometry::line_string_vertex_adapter<double>;
|
||||||
|
va_type va(g);
|
||||||
|
|
||||||
|
using detector_type = mapnik::label_collision_detector4;
|
||||||
|
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
|
||||||
|
|
||||||
|
using placement_type = mapnik::markers_vertex_last_placement<va_type, detector_type>;
|
||||||
|
|
||||||
|
mapnik::markers_placement_params params {
|
||||||
|
mapnik::box2d<double>(0, 0, 10, 10),
|
||||||
|
agg::trans_affine(),
|
||||||
|
0, 0, false, false, DIRECTION_AUTO };
|
||||||
|
|
||||||
|
placement_type placement(va, detector, params);
|
||||||
|
|
||||||
|
double x, y, angle;
|
||||||
|
CHECK( !placement.get_point(x, y, angle, true) );
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("point") {
|
||||||
|
|
||||||
|
mapnik::geometry::point<double> g(2.0, 3.0);
|
||||||
|
using va_type = mapnik::geometry::point_vertex_adapter<double>;
|
||||||
|
va_type va(g);
|
||||||
|
|
||||||
|
using detector_type = mapnik::label_collision_detector4;
|
||||||
|
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
|
||||||
|
|
||||||
|
using placement_type = mapnik::markers_vertex_last_placement<va_type, detector_type>;
|
||||||
|
|
||||||
|
mapnik::markers_placement_params params {
|
||||||
|
mapnik::box2d<double>(0, 0, 10, 10),
|
||||||
|
agg::trans_affine(),
|
||||||
|
0, 0, false, false, DIRECTION_AUTO };
|
||||||
|
|
||||||
|
placement_type placement(va, detector, params);
|
||||||
|
|
||||||
|
double x, y, angle;
|
||||||
|
|
||||||
|
CHECK( placement.get_point(x, y, angle, true) );
|
||||||
|
CHECK( x == Approx(2.0) );
|
||||||
|
CHECK( y == Approx(3.0) );
|
||||||
|
CHECK( angle == Approx(0.0) );
|
||||||
|
|
||||||
|
CHECK( !placement.get_point(x, y, angle, true) );
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("line string") {
|
||||||
|
|
||||||
|
mapnik::geometry::line_string<double> g;
|
||||||
|
g.emplace_back(1.0, 1.0);
|
||||||
|
g.emplace_back(2.0, 3.0);
|
||||||
|
using va_type = mapnik::geometry::line_string_vertex_adapter<double>;
|
||||||
|
va_type va(g);
|
||||||
|
|
||||||
|
using detector_type = mapnik::label_collision_detector4;
|
||||||
|
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
|
||||||
|
|
||||||
|
using placement_type = mapnik::markers_vertex_last_placement<va_type, detector_type>;
|
||||||
|
|
||||||
|
mapnik::markers_placement_params params {
|
||||||
|
mapnik::box2d<double>(0, 0, 10, 10),
|
||||||
|
agg::trans_affine(),
|
||||||
|
0, 0, false, false, DIRECTION_AUTO };
|
||||||
|
|
||||||
|
placement_type placement(va, detector, params);
|
||||||
|
|
||||||
|
double x, y, angle;
|
||||||
|
|
||||||
|
CHECK( placement.get_point(x, y, angle, true) );
|
||||||
|
CHECK( x == Approx(2.0) );
|
||||||
|
CHECK( y == Approx(3.0) );
|
||||||
|
CHECK( angle == Approx(1.1071487178) );
|
||||||
|
|
||||||
|
CHECK( !placement.get_point(x, y, angle, true) );
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("polygon") {
|
||||||
|
|
||||||
|
mapnik::geometry::polygon<double> g;
|
||||||
|
g.emplace_back();
|
||||||
|
auto & exterior = g.back();
|
||||||
|
exterior.emplace_back(2.0, 3.0);
|
||||||
|
exterior.emplace_back(1.0, 1.0);
|
||||||
|
exterior.emplace_back(0.0, 2.0);
|
||||||
|
exterior.emplace_back(2.0, 3.0);
|
||||||
|
using va_type = mapnik::geometry::polygon_vertex_adapter<double>;
|
||||||
|
va_type va(g);
|
||||||
|
|
||||||
|
using detector_type = mapnik::label_collision_detector4;
|
||||||
|
detector_type detector(mapnik::box2d<double>(0, 0, 100, 100));
|
||||||
|
|
||||||
|
using placement_type = mapnik::markers_vertex_last_placement<va_type, detector_type>;
|
||||||
|
|
||||||
|
mapnik::markers_placement_params params {
|
||||||
|
mapnik::box2d<double>(0, 0, 10, 10),
|
||||||
|
agg::trans_affine(),
|
||||||
|
0, 0, false, false, DIRECTION_AUTO };
|
||||||
|
|
||||||
|
placement_type placement(va, detector, params);
|
||||||
|
|
||||||
|
double x, y, angle;
|
||||||
|
|
||||||
|
CHECK( placement.get_point(x, y, angle, true) );
|
||||||
|
CHECK( x == Approx(2.0) );
|
||||||
|
CHECK( y == Approx(3.0) );
|
||||||
|
CHECK( angle == Approx(0.463647609) );
|
||||||
|
|
||||||
|
CHECK( !placement.get_point(x, y, angle, true) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
117
test/unit/vertex_adapter/transform_path_adapter.cpp
Normal file
117
test/unit/vertex_adapter/transform_path_adapter.cpp
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
#include <mapnik/transform_path_adapter.hpp>
|
||||||
|
#include <mapnik/geometry/correct.hpp>
|
||||||
|
#include <mapnik/vertex_adapters.hpp>
|
||||||
|
#include <mapnik/transform_path_adapter.hpp>
|
||||||
|
#include <mapnik/view_transform.hpp>
|
||||||
|
#include <mapnik/proj_transform.hpp>
|
||||||
|
#include <mapnik/projection.hpp>
|
||||||
|
|
||||||
|
TEST_CASE("transform_path_adapter") {
|
||||||
|
|
||||||
|
SECTION("polygon closing - epsg 2330") {
|
||||||
|
mapnik::geometry::polygon<double> g;
|
||||||
|
g.emplace_back();
|
||||||
|
auto & exterior = g.back();
|
||||||
|
|
||||||
|
exterior.emplace_back(88.1844308217992, 69.3553916041731);
|
||||||
|
exterior.emplace_back(88.1846166524913, 69.3552821191223);
|
||||||
|
exterior.emplace_back(88.1845090893871, 69.3553454342903);
|
||||||
|
exterior.emplace_back(88.1844308217992, 69.3553916041731);
|
||||||
|
|
||||||
|
using va_type = mapnik::geometry::polygon_vertex_adapter<double>;
|
||||||
|
using path_type = mapnik::transform_path_adapter<mapnik::view_transform, va_type>;
|
||||||
|
|
||||||
|
va_type va(g);
|
||||||
|
mapnik::box2d<double> extent(16310607, 7704513, 16310621, 7704527);
|
||||||
|
mapnik::view_transform tr(512, 512, extent);
|
||||||
|
mapnik::projection proj1("+init=epsg:2330");
|
||||||
|
mapnik::projection proj2("+init=epsg:4326");
|
||||||
|
mapnik::proj_transform prj_trans(proj1, proj2);
|
||||||
|
path_type path(tr, va, prj_trans);
|
||||||
|
|
||||||
|
double x,y;
|
||||||
|
unsigned cmd;
|
||||||
|
|
||||||
|
cmd = path.vertex(&x, &y);
|
||||||
|
CHECK( cmd == mapnik::SEG_MOVETO );
|
||||||
|
CHECK( x == Approx(110.4328050613) );
|
||||||
|
CHECK( y == Approx(20.2204537392) );
|
||||||
|
|
||||||
|
cmd = path.vertex(&x, &y);
|
||||||
|
CHECK( cmd == mapnik::SEG_LINETO );
|
||||||
|
CHECK( x == Approx(342.1220560074) );
|
||||||
|
CHECK( y == Approx(486.732225963) );
|
||||||
|
|
||||||
|
cmd = path.vertex(&x, &y);
|
||||||
|
CHECK( cmd == mapnik::SEG_LINETO );
|
||||||
|
CHECK( x == Approx(207.9962329183) );
|
||||||
|
CHECK( y == Approx(216.9376912798) );
|
||||||
|
|
||||||
|
// close
|
||||||
|
cmd = path.vertex(&x, &y);
|
||||||
|
CHECK( cmd == mapnik::SEG_CLOSE );
|
||||||
|
CHECK( x == 0 );
|
||||||
|
CHECK( y == 0 );
|
||||||
|
|
||||||
|
// end
|
||||||
|
cmd = path.vertex(&x, &y);
|
||||||
|
CHECK( cmd == mapnik::SEG_END );
|
||||||
|
CHECK( x == 0 );
|
||||||
|
CHECK( y == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("polygon closing - epsg 32633") {
|
||||||
|
mapnik::geometry::polygon<double> g;
|
||||||
|
g.emplace_back();
|
||||||
|
auto & exterior = g.back();
|
||||||
|
|
||||||
|
exterior.emplace_back(13, 13);
|
||||||
|
exterior.emplace_back(14, 13);
|
||||||
|
exterior.emplace_back(14, 14);
|
||||||
|
exterior.emplace_back(14, 14);
|
||||||
|
|
||||||
|
using va_type = mapnik::geometry::polygon_vertex_adapter<double>;
|
||||||
|
using path_type = mapnik::transform_path_adapter<mapnik::view_transform, va_type>;
|
||||||
|
|
||||||
|
va_type va(g);
|
||||||
|
mapnik::box2d<double> extent(166022, 0, 833978, 9329005);
|
||||||
|
mapnik::view_transform tr(512, 512, extent);
|
||||||
|
mapnik::projection proj1("+init=epsg:32633");
|
||||||
|
mapnik::projection proj2("+init=epsg:4326");
|
||||||
|
mapnik::proj_transform prj_trans(proj1, proj2);
|
||||||
|
path_type path(tr, va, prj_trans);
|
||||||
|
|
||||||
|
double x,y;
|
||||||
|
unsigned cmd;
|
||||||
|
|
||||||
|
cmd = path.vertex(&x, &y);
|
||||||
|
CHECK( cmd == mapnik::SEG_MOVETO );
|
||||||
|
CHECK( x == Approx(89.7250280748) );
|
||||||
|
CHECK( y == Approx(433.0795069885) );
|
||||||
|
|
||||||
|
cmd = path.vertex(&x, &y);
|
||||||
|
CHECK( cmd == mapnik::SEG_LINETO );
|
||||||
|
CHECK( x == Approx(172.873973465) );
|
||||||
|
CHECK( y == Approx(433.1145779929) );
|
||||||
|
|
||||||
|
cmd = path.vertex(&x, &y);
|
||||||
|
CHECK( cmd == mapnik::SEG_LINETO );
|
||||||
|
CHECK( x == Approx(173.2194366775) );
|
||||||
|
CHECK( y == Approx(427.0442504759) );
|
||||||
|
|
||||||
|
// close
|
||||||
|
cmd = path.vertex(&x, &y);
|
||||||
|
CHECK( cmd == mapnik::SEG_CLOSE );
|
||||||
|
CHECK( x == 0 );
|
||||||
|
CHECK( y == 0 );
|
||||||
|
|
||||||
|
// end
|
||||||
|
cmd = path.vertex(&x, &y);
|
||||||
|
CHECK( cmd == mapnik::SEG_END );
|
||||||
|
CHECK( x == 0 );
|
||||||
|
CHECK( y == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue