diff --git a/clip.cpp b/clip.cpp index be3cedaf..7bc95082 100644 --- a/clip.cpp +++ b/clip.cpp @@ -449,6 +449,16 @@ drawvec clip_poly(drawvec &geom, drawvec const &bounds) { return ret; } +drawvec clip_point_poly(drawvec &geom, drawvec const &bounds) { + drawvec out; + for (auto const &p : geom) { + if (pnpoly_mp(bounds, p.x, p.y)) { + out.push_back(p); + } + } + return out; +} + void to_tile_scale(drawvec &geom, int z, int detail) { if (32 - detail - z < 0) { for (size_t i = 0; i < geom.size(); i++) { @@ -1139,6 +1149,27 @@ bool pnpoly_mp(std::vector const &geom, long long x, long long y) return found; } +bool pnpoly_mp(drawvec const &geom, long long x, long long y) { + // assumes rings are properly nested, so inside a hole matches twice + bool found = false; + + for (size_t i = 0; i < geom.size(); i++) { + if (geom[i].op == VT_MOVETO) { + size_t j; + for (j = i + 1; j < geom.size(); j++) { + if (geom[j].op != VT_LINETO) { + break; + } + } + + found ^= pnpoly(geom, i, j - i, x, y); + i = j - 1; + } + } + + return found; +} + clipbbox parse_clip_poly(std::string arg) { json_pull *jp = json_begin_string(arg.c_str()); json_object *j = json_read_tree(jp); @@ -1990,6 +2021,9 @@ std::string overzoom(std::vector const &tiles, int nz, int nx, int geom = clip_lines(geom, c.minx, c.miny, c.maxx, c.maxy); } else if (t == VT_POINT) { geom = clip_point(geom, c.minx, c.miny, c.maxx, c.maxy); + if (c.dv.size() > 0 && geom.size() > 0) { + geom = clip_point_poly(geom, c.dv); + } } } } diff --git a/geometry.hpp b/geometry.hpp index 45161f3b..bc616058 100644 --- a/geometry.hpp +++ b/geometry.hpp @@ -99,6 +99,7 @@ drawvec clip_lines(drawvec &geom, long long x1, long long y1, long long x2, long drawvec clip_point(drawvec &geom, long long x1, long long y1, long long x2, long long y2); void visvalingam(drawvec &ls, size_t start, size_t end, double threshold, size_t retain); int pnpoly(const drawvec &vert, size_t start, size_t nvert, long long testx, long long testy); +bool pnpoly_mp(drawvec const &geom, long long x, long long y); double distance_from_line(long long point_x, long long point_y, long long segA_x, long long segA_y, long long segB_x, long long segB_y); struct input_tile {