mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 08:25:40 +02:00
Merge branch 'master' into plugins
This commit is contained in:
@@ -1,3 +1,7 @@
|
|||||||
|
## 1.16.4
|
||||||
|
|
||||||
|
* Use Wagyu's quick_lr_clip() instead of a separate implementation
|
||||||
|
|
||||||
## 1.16.3
|
## 1.16.3
|
||||||
|
|
||||||
* Upgrade Wagyu to bfbf2893
|
* Upgrade Wagyu to bfbf2893
|
||||||
|
|||||||
+21
-104
@@ -12,6 +12,7 @@
|
|||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
#include <mapbox/geometry.hpp>
|
#include <mapbox/geometry.hpp>
|
||||||
#include <mapbox/geometry/wagyu/wagyu.hpp>
|
#include <mapbox/geometry/wagyu/wagyu.hpp>
|
||||||
|
#include <mapbox/geometry/wagyu/quick_clip.hpp>
|
||||||
#include "geometry.hpp"
|
#include "geometry.hpp"
|
||||||
#include "projection.hpp"
|
#include "projection.hpp"
|
||||||
#include "serial.hpp"
|
#include "serial.hpp"
|
||||||
@@ -424,103 +425,13 @@ drawvec close_poly(drawvec &geom) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool inside(draw d, int edge, long long minx, long long miny, long long maxx, long long maxy) {
|
|
||||||
switch (edge) {
|
|
||||||
case 0: // top
|
|
||||||
return d.y > miny;
|
|
||||||
|
|
||||||
case 1: // right
|
|
||||||
return d.x < maxx;
|
|
||||||
|
|
||||||
case 2: // bottom
|
|
||||||
return d.y < maxy;
|
|
||||||
|
|
||||||
case 3: // left
|
|
||||||
return d.x > minx;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "internal error inside\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static draw intersect(draw a, draw b, int edge, long long minx, long long miny, long long maxx, long long maxy) {
|
|
||||||
// The casts to double are because the product of coordinates
|
|
||||||
// can overflow a long long if the tile buffer is large.
|
|
||||||
|
|
||||||
switch (edge) {
|
|
||||||
case 0: // top
|
|
||||||
return draw(VT_LINETO, a.x + (double) (b.x - a.x) * (miny - a.y) / (b.y - a.y), miny);
|
|
||||||
|
|
||||||
case 1: // right
|
|
||||||
return draw(VT_LINETO, maxx, a.y + (double) (b.y - a.y) * (maxx - a.x) / (b.x - a.x));
|
|
||||||
|
|
||||||
case 2: // bottom
|
|
||||||
return draw(VT_LINETO, a.x + (double) (b.x - a.x) * (maxy - a.y) / (b.y - a.y), maxy);
|
|
||||||
|
|
||||||
case 3: // left
|
|
||||||
return draw(VT_LINETO, minx, a.y + (double) (b.y - a.y) * (minx - a.x) / (b.x - a.x));
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "internal error intersecting\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// http://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm
|
|
||||||
static drawvec clip_poly1(drawvec &geom, long long minx, long long miny, long long maxx, long long maxy) {
|
|
||||||
drawvec out = geom;
|
|
||||||
|
|
||||||
for (int edge = 0; edge < 4; edge++) {
|
|
||||||
if (out.size() > 0) {
|
|
||||||
drawvec in = out;
|
|
||||||
out.resize(0);
|
|
||||||
|
|
||||||
draw S = in[in.size() - 1];
|
|
||||||
|
|
||||||
for (size_t e = 0; e < in.size(); e++) {
|
|
||||||
draw E = in[e];
|
|
||||||
|
|
||||||
if (inside(E, edge, minx, miny, maxx, maxy)) {
|
|
||||||
if (!inside(S, edge, minx, miny, maxx, maxy)) {
|
|
||||||
out.push_back(intersect(S, E, edge, minx, miny, maxx, maxy));
|
|
||||||
}
|
|
||||||
out.push_back(E);
|
|
||||||
} else if (inside(S, edge, minx, miny, maxx, maxy)) {
|
|
||||||
out.push_back(intersect(S, E, edge, minx, miny, maxx, maxy));
|
|
||||||
}
|
|
||||||
|
|
||||||
S = E;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.size() > 0) {
|
|
||||||
// If the polygon begins and ends outside the edge,
|
|
||||||
// the starting and ending points will be left as the
|
|
||||||
// places where it intersects the edge. Need to add
|
|
||||||
// another point to close the loop.
|
|
||||||
|
|
||||||
if (out[0].x != out[out.size() - 1].x || out[0].y != out[out.size() - 1].y) {
|
|
||||||
out.push_back(out[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.size() < 3) {
|
|
||||||
// fprintf(stderr, "Polygon degenerated to a line segment\n");
|
|
||||||
out.clear();
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
out[0].op = VT_MOVETO;
|
|
||||||
for (size_t i = 1; i < out.size(); i++) {
|
|
||||||
out[i].op = VT_LINETO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
drawvec simple_clip_poly(drawvec &geom, long long minx, long long miny, long long maxx, long long maxy) {
|
drawvec simple_clip_poly(drawvec &geom, long long minx, long long miny, long long maxx, long long maxy) {
|
||||||
drawvec out;
|
drawvec out;
|
||||||
|
|
||||||
|
mapbox::geometry::point<long long> min(minx, miny);
|
||||||
|
mapbox::geometry::point<long long> max(maxx, maxy);
|
||||||
|
mapbox::geometry::box<long long> bbox(min, max);
|
||||||
|
|
||||||
for (size_t i = 0; i < geom.size(); i++) {
|
for (size_t i = 0; i < geom.size(); i++) {
|
||||||
if (geom[i].op == VT_MOVETO) {
|
if (geom[i].op == VT_MOVETO) {
|
||||||
size_t j;
|
size_t j;
|
||||||
@@ -530,19 +441,25 @@ drawvec simple_clip_poly(drawvec &geom, long long minx, long long miny, long lon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drawvec tmp;
|
mapbox::geometry::linear_ring<long long> ring;
|
||||||
for (size_t k = i; k < j; k++) {
|
for (size_t k = i; k < j; k++) {
|
||||||
tmp.push_back(geom[k]);
|
ring.push_back(mapbox::geometry::point<long long>(geom[k].x, geom[k].y));
|
||||||
}
|
}
|
||||||
tmp = clip_poly1(tmp, minx, miny, maxx, maxy);
|
|
||||||
if (tmp.size() > 0) {
|
optional_linear_ring<long long> lr = mapbox::geometry::wagyu::quick_clip::quick_lr_clip(ring, bbox);
|
||||||
if (tmp[0].x != tmp[tmp.size() - 1].x || tmp[0].y != tmp[tmp.size() - 1].y) {
|
|
||||||
fprintf(stderr, "Internal error: Polygon ring not closed\n");
|
if (lr) {
|
||||||
exit(EXIT_FAILURE);
|
for (size_t k = 0; k < lr->size(); k++) {
|
||||||
|
if (k == 0) {
|
||||||
|
out.push_back(draw(VT_MOVETO, (*lr)[k].x, (*lr)[k].y));
|
||||||
|
} else {
|
||||||
|
out.push_back(draw(VT_LINETO, (*lr)[k].x, (*lr)[k].y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lr->size() > 0 && (*lr)[0] != (*lr)[lr->size() - 1]) {
|
||||||
|
out.push_back(draw(VT_LINETO, (*lr)[0].x, (*lr)[0].y));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
for (size_t k = 0; k < tmp.size(); k++) {
|
|
||||||
out.push_back(tmp[k]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i = j - 1;
|
i = j - 1;
|
||||||
|
|||||||
@@ -0,0 +1,137 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <mapbox/geometry/box.hpp>
|
||||||
|
#include <mapbox/geometry/multi_polygon.hpp>
|
||||||
|
#include <mapbox/geometry/polygon.hpp>
|
||||||
|
#include <mapbox/geometry/wagyu/wagyu.hpp>
|
||||||
|
|
||||||
|
#include <experimental/optional>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using optional_linear_ring = std::experimental::optional<mapbox::geometry::linear_ring<T>>;
|
||||||
|
|
||||||
|
namespace mapbox {
|
||||||
|
namespace geometry {
|
||||||
|
namespace wagyu {
|
||||||
|
namespace quick_clip {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
mapbox::geometry::point<T> intersect(mapbox::geometry::point<T> a,
|
||||||
|
mapbox::geometry::point<T> b,
|
||||||
|
size_t edge,
|
||||||
|
mapbox::geometry::box<T> const& box) {
|
||||||
|
switch (edge) {
|
||||||
|
case 0:
|
||||||
|
return mapbox::geometry::point<T>(
|
||||||
|
static_cast<T>(a.x + static_cast<double>(b.x - a.x) * (box.min.y - a.y) / (b.y - a.y)),
|
||||||
|
box.min.y);
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
return mapbox::geometry::point<T>(
|
||||||
|
box.max.x,
|
||||||
|
static_cast<T>(a.y + static_cast<double>(b.y - a.y) * (box.max.x - a.x) / (b.x - a.x)));
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
return mapbox::geometry::point<T>(
|
||||||
|
static_cast<T>(a.x + static_cast<double>(b.x - a.x) * (box.max.y - a.y) / (b.y - a.y)),
|
||||||
|
box.max.y);
|
||||||
|
|
||||||
|
default: // case 3
|
||||||
|
return mapbox::geometry::point<T>(
|
||||||
|
box.min.x,
|
||||||
|
static_cast<T>(a.y + static_cast<double>(b.y - a.y) * (box.min.x - a.x) / (b.x - a.x)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool inside(mapbox::geometry::point<T> p, size_t edge, mapbox::geometry::box<T> const& b) {
|
||||||
|
switch (edge) {
|
||||||
|
case 0:
|
||||||
|
return p.y > b.min.y;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
return p.x < b.max.x;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
return p.y < b.max.y;
|
||||||
|
|
||||||
|
default: // case 3
|
||||||
|
return p.x > b.min.x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
optional_linear_ring<T> quick_lr_clip(mapbox::geometry::linear_ring<T> const& ring,
|
||||||
|
mapbox::geometry::box<T> const& b) {
|
||||||
|
mapbox::geometry::linear_ring<T> out = ring;
|
||||||
|
|
||||||
|
for (size_t edge = 0; edge < 4; edge++) {
|
||||||
|
if (out.size() > 0) {
|
||||||
|
mapbox::geometry::linear_ring<T> in = out;
|
||||||
|
mapbox::geometry::point<T> S = in[in.size() - 1];
|
||||||
|
out.resize(0);
|
||||||
|
|
||||||
|
for (size_t e = 0; e < in.size(); e++) {
|
||||||
|
mapbox::geometry::point<T> E = in[e];
|
||||||
|
|
||||||
|
if (inside(E, edge, b)) {
|
||||||
|
if (!inside(S, edge, b)) {
|
||||||
|
out.push_back(intersect(S, E, edge, b));
|
||||||
|
}
|
||||||
|
out.push_back(E);
|
||||||
|
} else if (inside(S, edge, b)) {
|
||||||
|
out.push_back(intersect(S, E, edge, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
S = E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out.size() < 3) {
|
||||||
|
return optional_linear_ring<T>();
|
||||||
|
}
|
||||||
|
// Close the ring if the first/last point was outside
|
||||||
|
if (out[0] != out[out.size() - 1]) {
|
||||||
|
out.push_back(out[0]);
|
||||||
|
}
|
||||||
|
return optional_linear_ring<T>(std::move(out));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
mapbox::geometry::multi_polygon<T> clip(mapbox::geometry::polygon<T> const& poly,
|
||||||
|
mapbox::geometry::box<T> const& b,
|
||||||
|
fill_type subject_fill_type) {
|
||||||
|
mapbox::geometry::multi_polygon<T> result;
|
||||||
|
wagyu<T> clipper;
|
||||||
|
for (auto const& lr : poly) {
|
||||||
|
auto new_lr = quick_clip::quick_lr_clip(lr, b);
|
||||||
|
if (new_lr) {
|
||||||
|
clipper.add_ring(*new_lr, polygon_type_subject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clipper.execute(clip_type_union, result, subject_fill_type, fill_type_even_odd);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
mapbox::geometry::multi_polygon<T> clip(mapbox::geometry::multi_polygon<T> const& mp,
|
||||||
|
mapbox::geometry::box<T> const& b,
|
||||||
|
fill_type subject_fill_type) {
|
||||||
|
mapbox::geometry::multi_polygon<T> result;
|
||||||
|
wagyu<T> clipper;
|
||||||
|
for (auto const& poly : mp) {
|
||||||
|
for (auto const& lr : poly) {
|
||||||
|
auto new_lr = quick_clip::quick_lr_clip(lr, b);
|
||||||
|
if (new_lr) {
|
||||||
|
clipper.add_ring(*new_lr, polygon_type_subject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clipper.execute(clip_type_union, result, subject_fill_type, fill_type_even_odd);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -485,15 +485,15 @@ bool first_is_bottom_point(const_point_ptr<T> btmPt1, const_point_ptr<T> btmPt2)
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
point_ptr<T> get_bottom_point(point_ptr<T> pp) {
|
point_ptr<T> get_bottom_point(point_ptr<T> pp) {
|
||||||
point_ptr<T> dups = 0;
|
point_ptr<T> dups = nullptr;
|
||||||
point_ptr<T> p = pp->next;
|
point_ptr<T> p = pp->next;
|
||||||
while (p != pp) {
|
while (p != pp) {
|
||||||
if (p->y > pp->y) {
|
if (p->y > pp->y) {
|
||||||
pp = p;
|
pp = p;
|
||||||
dups = 0;
|
dups = nullptr;
|
||||||
} else if (p->y == pp->y && p->x <= pp->x) {
|
} else if (p->y == pp->y && p->x <= pp->x) {
|
||||||
if (p->x < pp->x) {
|
if (p->x < pp->x) {
|
||||||
dups = 0;
|
dups = nullptr;
|
||||||
pp = p;
|
pp = p;
|
||||||
} else {
|
} else {
|
||||||
if (p->next != pp && p->prev != pp) {
|
if (p->next != pp && p->prev != pp) {
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
#define VERSION "tippecanoe v1.16.3\n"
|
#define VERSION "tippecanoe v1.16.4\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user