From ecc5acbdb953e172fcc652b55ed19b8b581e2146 Mon Sep 17 00:00:00 2001 From: artemp Date: Mon, 24 Feb 2014 15:20:06 +0000 Subject: [PATCH] attempt to handle multi-polygons in shape.input --- include/mapnik/geom_util.hpp | 41 ++++++++++++++++++++++++++++++++ plugins/input/shape/shape_io.cpp | 14 +++++++---- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/include/mapnik/geom_util.hpp b/include/mapnik/geom_util.hpp index 81d5f16c6..405e191e4 100644 --- a/include/mapnik/geom_util.hpp +++ b/include/mapnik/geom_util.hpp @@ -247,6 +247,47 @@ double path_length(PathType & path) return length; } +template +bool hit_test_first(PathType & path, double x, double y, double tol) +{ + bool inside=false; + double x0 = 0; + double y0 = 0; + double x1 = 0; + double y1 = 0; + path.rewind(0); + unsigned command = path.vertex(&x0, &y0); + if (command == SEG_END) + { + return false; + } + unsigned count = 0; + mapnik::geometry_type::types geom_type = static_cast(path.type()); + while (SEG_END != (command = path.vertex(&x1, &y1))) + { + if (command == SEG_CLOSE) + { + break; + } + ++count; + if (command == SEG_MOVETO) + { + x0 = x1; + y0 = y1; + continue; + } + + if ((((y1 <= y) && (y < y0)) || + ((y0 <= y) && (y < y1))) && + (x < (x0 - x1) * (y - y1)/ (y0 - y1) + x1)) + inside=!inside; + + x0 = x1; + y0 = y1; + } + return inside; +} + namespace label { template diff --git a/plugins/input/shape/shape_io.cpp b/plugins/input/shape/shape_io.cpp index 85e3f966e..a0587dd4e 100644 --- a/plugins/input/shape/shape_io.cpp +++ b/plugins/input/shape/shape_io.cpp @@ -25,12 +25,13 @@ // mapnik #include #include +#include // boost using mapnik::datasource_exception; using mapnik::geometry_type; - +using mapnik::hit_test_first; const std::string shape_io::SHP = ".shp"; const std::string shape_io::DBF = ".dbf"; const std::string shape_io::INDEX = ".index"; @@ -156,9 +157,9 @@ void shape_io::read_polygon(shape_file::record_type & record, mapnik::geometry_c parts[i] = record.read_ndr_integer(); } + std::unique_ptr poly(new geometry_type(mapnik::geometry_type::types::Polygon)); for (int k = 0; k < num_parts; ++k) { - std::unique_ptr poly(new geometry_type(mapnik::geometry_type::types::Polygon)); int start = parts[k]; int end; if (k == num_parts - 1) @@ -172,14 +173,19 @@ void shape_io::read_polygon(shape_file::record_type & record, mapnik::geometry_c double x = record.read_double(); double y = record.read_double(); + if (k > 0 && !hit_test_first(*poly, x, y, 0)) + { + geom.push_back(poly.release()); + poly.reset(new geometry_type(mapnik::geometry_type::types::Polygon)); + } poly->move_to(x, y); - for (int j=start+1;jline_to(x, y); } poly->close_path(); - geom.push_back(poly.release()); } + geom.push_back(poly.release()); }