mirror of
https://github.com/mapbox/tippecanoe.git
synced 2025-01-22 04:18:01 +00:00
Merge pull request #187 from mapbox/earcut-polygon
Upgrade Clipper to 07b828b1 to fix self-intersecting polygons
This commit is contained in:
commit
bd5dc4ad18
13
.travis.yml
13
.travis.yml
@ -1,4 +1,4 @@
|
|||||||
language: c
|
language: generic
|
||||||
|
|
||||||
sudo: false
|
sudo: false
|
||||||
|
|
||||||
@ -6,25 +6,24 @@ matrix:
|
|||||||
include:
|
include:
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
env: COVERAGE=gcov-4.9
|
env: COVERAGE=gcov-4.9 CC="gcc-4.9" CXX="g++-4.9"
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: [ 'g++-4.9', 'protobuf-compiler', 'libprotobuf-dev' ]
|
packages: [ 'g++-4.9' ]
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: clang
|
compiler: clang
|
||||||
|
env: CC="clang-3.5" CXX="clang++-3.5"
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
packages: [ 'protobuf-compiler', 'libprotobuf-dev' ]
|
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ]
|
||||||
|
packages: [ 'clang-3.5' ]
|
||||||
- os: osx
|
- os: osx
|
||||||
compiler: clang
|
compiler: clang
|
||||||
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- if [[ $(uname -s) == 'Darwin' ]]; then brew install protobuf; fi;
|
|
||||||
- if [ -n "${COVERAGE}" ]; then
|
- if [ -n "${COVERAGE}" ]; then
|
||||||
export CXX=g++-4.9;
|
|
||||||
export CC=gcc-4.9;
|
|
||||||
export CXXFLAGS="--coverage -g";
|
export CXXFLAGS="--coverage -g";
|
||||||
export CFLAGS="--coverage -g";
|
export CFLAGS="--coverage -g";
|
||||||
export LDFLAGS="--coverage";
|
export LDFLAGS="--coverage";
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
## 1.10.0
|
||||||
|
|
||||||
|
* Upgrade Clipper to fix potential crashes and improve polygon topology
|
||||||
|
|
||||||
## 1.9.16
|
## 1.9.16
|
||||||
|
|
||||||
* Switch to protozero as the library for reading and writing protocol buffers
|
* Switch to protozero as the library for reading and writing protocol buffers
|
||||||
|
4
Makefile
4
Makefile
@ -60,6 +60,8 @@ clean:
|
|||||||
indent:
|
indent:
|
||||||
clang-format -i -style="{BasedOnStyle: Google, IndentWidth: 8, UseTab: Always, AllowShortIfStatementsOnASingleLine: false, ColumnLimit: 0, ContinuationIndentWidth: 8, SpaceAfterCStyleCast: true, IndentCaseLabels: false, AllowShortBlocksOnASingleLine: false, AllowShortFunctionsOnASingleLine: false}" $(C) $(H)
|
clang-format -i -style="{BasedOnStyle: Google, IndentWidth: 8, UseTab: Always, AllowShortIfStatementsOnASingleLine: false, ColumnLimit: 0, ContinuationIndentWidth: 8, SpaceAfterCStyleCast: true, IndentCaseLabels: false, AllowShortBlocksOnASingleLine: false, AllowShortFunctionsOnASingleLine: false}" $(C) $(H)
|
||||||
|
|
||||||
|
geometry.o: clipper/clipper.hpp
|
||||||
|
|
||||||
TESTS = $(wildcard tests/*/out/*.json)
|
TESTS = $(wildcard tests/*/out/*.json)
|
||||||
SPACE = $(NULL) $(NULL)
|
SPACE = $(NULL) $(NULL)
|
||||||
|
|
||||||
@ -67,7 +69,7 @@ test: tippecanoe tippecanoe-decode $(addsuffix .check,$(TESTS)) parallel-test pb
|
|||||||
|
|
||||||
# Work around Makefile and filename punctuation limits: _ for space, @ for :, % for /
|
# Work around Makefile and filename punctuation limits: _ for space, @ for :, % for /
|
||||||
%.json.check:
|
%.json.check:
|
||||||
./tippecanoe -f -o $@.mbtiles $(subst @,:,$(subst %,/,$(subst _, ,$(patsubst %.json.check,%,$(word 4,$(subst /, ,$@)))))) $(wildcard $(subst $(SPACE),/,$(wordlist 1,2,$(subst /, ,$@)))/*.json) < /dev/null
|
./tippecanoe -ad -f -o $@.mbtiles $(subst @,:,$(subst %,/,$(subst _, ,$(patsubst %.json.check,%,$(word 4,$(subst /, ,$@)))))) $(wildcard $(subst $(SPACE),/,$(wordlist 1,2,$(subst /, ,$@)))/*.json) < /dev/null
|
||||||
./tippecanoe-decode $@.mbtiles > $@.out
|
./tippecanoe-decode $@.mbtiles > $@.out
|
||||||
cmp $(patsubst %.check,%,$@) $@.out
|
cmp $(patsubst %.check,%,$@) $@.out
|
||||||
rm $@.out $@.mbtiles
|
rm $@.out $@.mbtiles
|
||||||
|
1147
clipper/clipper.cpp
1147
clipper/clipper.cpp
File diff suppressed because it is too large
Load Diff
@ -58,6 +58,7 @@
|
|||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <unordered_map>
|
||||||
#if defined(CLIPPER_IMPL_INCLUDE)
|
#if defined(CLIPPER_IMPL_INCLUDE)
|
||||||
#include CLIPPER_IMPL_INCLUDE
|
#include CLIPPER_IMPL_INCLUDE
|
||||||
#endif
|
#endif
|
||||||
@ -77,7 +78,7 @@ enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
|
|||||||
static cInt const loRange = 0x7FFF;
|
static cInt const loRange = 0x7FFF;
|
||||||
static cInt const hiRange = 0x7FFF;
|
static cInt const hiRange = 0x7FFF;
|
||||||
#else
|
#else
|
||||||
typedef signed long long cInt;
|
typedef std::int64_t cInt;
|
||||||
static cInt const loRange = 0x3FFFFFFF;
|
static cInt const loRange = 0x3FFFFFFF;
|
||||||
static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
|
static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
|
||||||
typedef signed long long long64; //used by Int128 class
|
typedef signed long long long64; //used by Int128 class
|
||||||
@ -235,6 +236,7 @@ struct LocalMinimum;
|
|||||||
struct OutPt;
|
struct OutPt;
|
||||||
struct OutRec;
|
struct OutRec;
|
||||||
struct Join;
|
struct Join;
|
||||||
|
struct OutPtIntersect;
|
||||||
|
|
||||||
typedef std::vector < OutRec* > PolyOutList;
|
typedef std::vector < OutRec* > PolyOutList;
|
||||||
typedef std::vector < TEdge* > EdgeList;
|
typedef std::vector < TEdge* > EdgeList;
|
||||||
@ -377,6 +379,19 @@ private:
|
|||||||
bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2);
|
bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2);
|
||||||
void JoinCommonEdges();
|
void JoinCommonEdges();
|
||||||
void DoSimplePolygons();
|
void DoSimplePolygons();
|
||||||
|
bool FindIntersectLoop(std::unordered_multimap<int, OutPtIntersect> & dupeRec,
|
||||||
|
std::list<std::pair<int, OutPtIntersect> > & iList,
|
||||||
|
OutRec * outRec_parent,
|
||||||
|
int idx_origin,
|
||||||
|
int idx_prev,
|
||||||
|
std::set<int> & visited,
|
||||||
|
OutPt * orig_pt,
|
||||||
|
OutPt * prev_pt);
|
||||||
|
bool FixIntersects(std::unordered_multimap<int, OutPtIntersect> & dupeRec,
|
||||||
|
OutPt * op_j,
|
||||||
|
OutPt * op_k,
|
||||||
|
OutRec * outRec_j,
|
||||||
|
OutRec * outRec_k);
|
||||||
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
|
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
|
||||||
void FixupFirstLefts2(OutRec* InnerOutRec, OutRec* OuterOutRec);
|
void FixupFirstLefts2(OutRec* InnerOutRec, OutRec* OuterOutRec);
|
||||||
void FixupFirstLefts3(OutRec* OldOutRec, OutRec* NewOutRec);
|
void FixupFirstLefts3(OutRec* OldOutRec, OutRec* NewOutRec);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -10,8 +11,6 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
|
||||||
#include <google/protobuf/io/coded_stream.h>
|
|
||||||
#include "mvt.hh"
|
#include "mvt.hh"
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
|
|
||||||
|
@ -2544,6 +2544,7 @@ int main(int argc, char **argv) {
|
|||||||
{"reverse", no_argument, &additional[A_REVERSE], 1},
|
{"reverse", no_argument, &additional[A_REVERSE], 1},
|
||||||
{"reorder", no_argument, &additional[A_REORDER], 1},
|
{"reorder", no_argument, &additional[A_REORDER], 1},
|
||||||
{"drop-lines", no_argument, &additional[A_LINE_DROP], 1},
|
{"drop-lines", no_argument, &additional[A_LINE_DROP], 1},
|
||||||
|
{"check-polygons", no_argument, &additional[A_DEBUG_POLYGON], 1},
|
||||||
{"drop-polygons", no_argument, &additional[A_POLYGON_DROP], 1},
|
{"drop-polygons", no_argument, &additional[A_POLYGON_DROP], 1},
|
||||||
{"prefer-radix-sort", no_argument, &additional[A_PREFER_RADIX_SORT], 1},
|
{"prefer-radix-sort", no_argument, &additional[A_PREFER_RADIX_SORT], 1},
|
||||||
|
|
||||||
|
316
geometry.cc
316
geometry.cc
@ -18,6 +18,8 @@ extern "C" {
|
|||||||
#include "projection.h"
|
#include "projection.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pnpoly(drawvec &vert, size_t start, size_t nvert, long long testx, long long testy);
|
||||||
|
|
||||||
drawvec decode_geometry(FILE *meta, long long *geompos, int z, unsigned tx, unsigned ty, int detail, long long *bbox, unsigned initial_x, unsigned initial_y) {
|
drawvec decode_geometry(FILE *meta, long long *geompos, int z, unsigned tx, unsigned ty, int detail, long long *bbox, unsigned initial_x, unsigned initial_y) {
|
||||||
drawvec out;
|
drawvec out;
|
||||||
|
|
||||||
@ -204,36 +206,209 @@ drawvec shrink_lines(drawvec &geom, int z, int detail, int basezoom, long long *
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void decode_clipped(ClipperLib::PolyNode *t, drawvec &out) {
|
double get_area(drawvec &geom, int i, int j) {
|
||||||
// To make the GeoJSON come out right, we need to do each of the
|
double area = 0;
|
||||||
// outer rings followed by its children if any, and then go back
|
for (unsigned k = i; k < j; k++) {
|
||||||
// to do any outer-ring children of those children as a new top level.
|
area += (long double) geom[k].x * (long double) geom[i + ((k - i + 1) % (j - i))].y;
|
||||||
|
area -= (long double) geom[k].y * (long double) geom[i + ((k - i + 1) % (j - i))].x;
|
||||||
|
}
|
||||||
|
area /= 2;
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reverse_ring(drawvec &geom, int start, int end) {
|
||||||
|
drawvec tmp;
|
||||||
|
|
||||||
|
for (unsigned i = start; i < end; i++) {
|
||||||
|
tmp.push_back(geom[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = start; i < end; i++) {
|
||||||
|
geom[i] = tmp[end - 1 - i];
|
||||||
|
if (i == start) {
|
||||||
|
geom[i].op = VT_MOVETO;
|
||||||
|
} else if (i == end - 1) {
|
||||||
|
geom[i].op = VT_LINETO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ring {
|
||||||
|
drawvec data;
|
||||||
|
long double area;
|
||||||
|
long long parent;
|
||||||
|
std::vector<size_t> children;
|
||||||
|
|
||||||
|
ring(drawvec &_data) {
|
||||||
|
data = _data;
|
||||||
|
area = get_area(_data, 0, _data.size());
|
||||||
|
parent = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const ring &o) const {
|
||||||
|
if (fabs(this->area) < fabs(o.area)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void decode_rings(ClipperLib::PolyNode *t, std::vector<ring> &out) {
|
||||||
|
// Supposedly outer ring
|
||||||
|
|
||||||
ClipperLib::Path p = t->Contour;
|
ClipperLib::Path p = t->Contour;
|
||||||
|
drawvec dv;
|
||||||
for (size_t i = 0; i < p.size(); i++) {
|
for (size_t i = 0; i < p.size(); i++) {
|
||||||
out.push_back(draw((i == 0) ? VT_MOVETO : VT_LINETO, p[i].X, p[i].Y));
|
dv.push_back(draw((i == 0) ? VT_MOVETO : VT_LINETO, p[i].X, p[i].Y));
|
||||||
}
|
}
|
||||||
if (p.size() > 0) {
|
if (p.size() > 0) {
|
||||||
out.push_back(draw(VT_LINETO, p[0].X, p[0].Y));
|
dv.push_back(draw(VT_LINETO, p[0].X, p[0].Y));
|
||||||
}
|
}
|
||||||
|
out.push_back(dv);
|
||||||
|
|
||||||
|
// Supposedly inner rings
|
||||||
|
|
||||||
for (int n = 0; n < t->ChildCount(); n++) {
|
for (int n = 0; n < t->ChildCount(); n++) {
|
||||||
ClipperLib::Path p = t->Childs[n]->Contour;
|
ClipperLib::Path p = t->Childs[n]->Contour;
|
||||||
|
drawvec dv;
|
||||||
for (size_t i = 0; i < p.size(); i++) {
|
for (size_t i = 0; i < p.size(); i++) {
|
||||||
out.push_back(draw((i == 0) ? VT_MOVETO : VT_LINETO, p[i].X, p[i].Y));
|
dv.push_back(draw((i == 0) ? VT_MOVETO : VT_LINETO, p[i].X, p[i].Y));
|
||||||
}
|
}
|
||||||
if (p.size() > 0) {
|
if (p.size() > 0) {
|
||||||
out.push_back(draw(VT_LINETO, p[0].X, p[0].Y));
|
dv.push_back(draw(VT_LINETO, p[0].X, p[0].Y));
|
||||||
}
|
}
|
||||||
|
out.push_back(dv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recurse to supposedly outer rings (children of the children)
|
||||||
|
|
||||||
for (int n = 0; n < t->ChildCount(); n++) {
|
for (int n = 0; n < t->ChildCount(); n++) {
|
||||||
for (int m = 0; m < t->Childs[n]->ChildCount(); m++) {
|
for (int m = 0; m < t->Childs[n]->ChildCount(); m++) {
|
||||||
decode_clipped(t->Childs[n]->Childs[m], out);
|
decode_rings(t->Childs[n]->Childs[m], out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void decode_clipped(ClipperLib::PolyNode *t, drawvec &out) {
|
||||||
|
// The output of Clipper supposedly produces the outer rings
|
||||||
|
// as top level objects, with links to any inner-ring children
|
||||||
|
// they may have, each of which then has links to any outer rings
|
||||||
|
// that it has, and so on. This doesn't actually work.
|
||||||
|
|
||||||
|
// So instead, we pull out all the rings, sort them by absolute area,
|
||||||
|
// and go through them, looking for the
|
||||||
|
// smallest parent that contains a point from it, since we are
|
||||||
|
// guaranteed that at least one point in the polygon is strictly
|
||||||
|
// inside its parent (not on one of its boundary lines).
|
||||||
|
|
||||||
|
// Once we have that, we can run through the outer rings that have
|
||||||
|
// an even number of parents,
|
||||||
|
|
||||||
|
std::vector<ring> rings;
|
||||||
|
decode_rings(t, rings);
|
||||||
|
std::sort(rings.begin(), rings.end());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < rings.size(); i++) {
|
||||||
|
for (size_t j = i + 1; j < rings.size(); j++) {
|
||||||
|
for (size_t k = 0; k < rings[i].data.size(); k++) {
|
||||||
|
if (pnpoly(rings[j].data, 0, rings[j].data.size(), rings[i].data[k].x, rings[i].data[k].y)) {
|
||||||
|
rings[i].parent = j;
|
||||||
|
rings[j].children.push_back(i);
|
||||||
|
goto nextring;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextring:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t ii = rings.size(); ii > 0; ii--) {
|
||||||
|
size_t i = ii - 1;
|
||||||
|
|
||||||
|
if (rings[i].parent < 0) {
|
||||||
|
if (rings[i].area < 0) {
|
||||||
|
rings[i].area = -rings[i].area;
|
||||||
|
reverse_ring(rings[i].data, 0, rings[i].data.size());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((rings[i].area > 0) == (rings[rings[i].parent].area > 0)) {
|
||||||
|
rings[i].area = -rings[i].area;
|
||||||
|
reverse_ring(rings[i].data, 0, rings[i].data.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t ii = rings.size(); ii > 0; ii--) {
|
||||||
|
size_t i = ii - 1;
|
||||||
|
|
||||||
|
if (rings[i].area > 0) {
|
||||||
|
#if 0
|
||||||
|
fprintf(stderr, "ring area %Lf at %lld\n", rings[i].area, (long long) out.size());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (size_t j = 0; j < rings[i].data.size(); j++) {
|
||||||
|
out.push_back(rings[i].data[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t j = 0; j < rings[i].children.size(); j++) {
|
||||||
|
#if 0
|
||||||
|
fprintf(stderr, "ring area %Lf at %lld\n", rings[rings[i].children[j]].area, (long long) out.size());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (size_t k = 0; k < rings[rings[i].children[j]].data.size(); k++) {
|
||||||
|
out.push_back(rings[rings[i].children[j]].data[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
rings[rings[i].children[j]].parent = -2;
|
||||||
|
}
|
||||||
|
} else if (rings[i].parent != -2) {
|
||||||
|
fprintf(stderr, "Found ring with child area but no parent %lld\n", (long long) i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump(drawvec &geom) {
|
||||||
|
ClipperLib::Clipper clipper(ClipperLib::ioStrictlySimple);
|
||||||
|
|
||||||
|
bool has_area = 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double area = get_area(geom, i, j);
|
||||||
|
if (area != 0) {
|
||||||
|
has_area = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClipperLib::Path path;
|
||||||
|
printf("{ ClipperLib::Path path; ");
|
||||||
|
|
||||||
|
drawvec tmp;
|
||||||
|
for (size_t k = i; k < j; k++) {
|
||||||
|
printf("path.push_back(IntPoint(%lld,%lld)); ", geom[k].x, geom[k].y);
|
||||||
|
path.push_back(ClipperLib::IntPoint(geom[k].x, geom[k].y));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!clipper.AddPath(path, ClipperLib::ptSubject, true)) {
|
||||||
|
}
|
||||||
|
printf("clipper.AddPath(path, ClipperLib::ptSubject, true); }\n");
|
||||||
|
|
||||||
|
i = j - 1;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unexpected operation in polygon %d\n", (int) geom[i].op);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("clipper.Execute(ClipperLib::ctUnion, clipped));\n");
|
||||||
|
}
|
||||||
|
|
||||||
drawvec clean_or_clip_poly(drawvec &geom, int z, int detail, int buffer, bool clip) {
|
drawvec clean_or_clip_poly(drawvec &geom, int z, int detail, int buffer, bool clip) {
|
||||||
ClipperLib::Clipper clipper(ClipperLib::ioStrictlySimple);
|
ClipperLib::Clipper clipper(ClipperLib::ioStrictlySimple);
|
||||||
|
|
||||||
@ -248,12 +423,7 @@ drawvec clean_or_clip_poly(drawvec &geom, int z, int detail, int buffer, bool cl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double area = 0;
|
double area = get_area(geom, i, j);
|
||||||
for (size_t k = i; k < j; k++) {
|
|
||||||
area += (long double) geom[k].x * (long double) geom[i + ((k - i + 1) % (j - i))].y;
|
|
||||||
area -= (long double) geom[k].y * (long double) geom[i + ((k - i + 1) % (j - i))].x;
|
|
||||||
}
|
|
||||||
area = area / 2;
|
|
||||||
if (area != 0) {
|
if (area != 0) {
|
||||||
has_area = true;
|
has_area = true;
|
||||||
}
|
}
|
||||||
@ -329,6 +499,102 @@ drawvec clean_or_clip_poly(drawvec &geom, int z, int detail, int buffer, bool cl
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* pnpoly:
|
||||||
|
Copyright (c) 1970-2003, Wm. Randolph Franklin
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice in the documentation and/or other materials provided with the distribution.
|
||||||
|
The name of W. Randolph Franklin may not be used to endorse or promote products derived from this Software without specific prior written permission.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int pnpoly(drawvec &vert, size_t start, size_t nvert, long long testx, long long testy) {
|
||||||
|
int i, j, c = 0;
|
||||||
|
for (i = 0, j = nvert - 1; i < nvert; j = i++) {
|
||||||
|
if (((vert[i + start].y > testy) != (vert[j + start].y > testy)) &&
|
||||||
|
(testx < (vert[j + start].x - vert[i + start].x) * (testy - vert[i + start].y) / (double) (vert[j + start].y - vert[i + start].y) + vert[i + start].x))
|
||||||
|
c = !c;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_polygon(drawvec &geom, drawvec &before) {
|
||||||
|
for (size_t i = 0; i + 1 < geom.size(); i++) {
|
||||||
|
for (size_t j = i + 1; j + 1 < geom.size(); j++) {
|
||||||
|
if (geom[i + 1].op == VT_LINETO && geom[j + 1].op == VT_LINETO) {
|
||||||
|
double s1_x = geom[i + 1].x - geom[i + 0].x;
|
||||||
|
double s1_y = geom[i + 1].y - geom[i + 0].y;
|
||||||
|
double s2_x = geom[j + 1].x - geom[j + 0].x;
|
||||||
|
double s2_y = geom[j + 1].y - geom[j + 0].y;
|
||||||
|
|
||||||
|
double s, t;
|
||||||
|
s = (-s1_y * (geom[i + 0].x - geom[j + 0].x) + s1_x * (geom[i + 0].y - geom[j + 0].y)) / (-s2_x * s1_y + s1_x * s2_y);
|
||||||
|
t = (s2_x * (geom[i + 0].y - geom[j + 0].y) - s2_y * (geom[i + 0].x - geom[j + 0].x)) / (-s2_x * s1_y + s1_x * s2_y);
|
||||||
|
|
||||||
|
if (t > 0 && t < 1 && s > 0 && s < 1) {
|
||||||
|
printf("Internal error: self-intersecting polygon. %lld,%lld to %lld,%lld intersects %lld,%lld to %lld,%lld\n",
|
||||||
|
geom[i + 0].x, geom[i + 0].y,
|
||||||
|
geom[i + 1].x, geom[i + 1].y,
|
||||||
|
geom[j + 0].x, geom[j + 0].y,
|
||||||
|
geom[j + 1].x, geom[j + 1].y);
|
||||||
|
dump(before);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t outer_start = -1;
|
||||||
|
size_t outer_len = 0;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double area = get_area(geom, i, j);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
fprintf(stderr, "looking at %lld to %lld, area %f\n", (long long) i, (long long) j, area);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (area > 0) {
|
||||||
|
outer_start = i;
|
||||||
|
outer_len = j - i;
|
||||||
|
} else {
|
||||||
|
for (size_t k = i; k < j; k++) {
|
||||||
|
if (!pnpoly(geom, outer_start, outer_len, geom[k].x, geom[k].y)) {
|
||||||
|
bool on_edge = false;
|
||||||
|
|
||||||
|
for (size_t l = outer_start; l < outer_start + outer_len; l++) {
|
||||||
|
if (geom[k].x == geom[l].x || geom[k].y == geom[l].y) {
|
||||||
|
on_edge = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!on_edge) {
|
||||||
|
printf("%lld,%lld at %lld not in outer ring (%lld to %lld)\n", geom[k].x, geom[k].y, (long long) k, (long long) outer_start, (long long) (outer_start + outer_len));
|
||||||
|
|
||||||
|
dump(before);
|
||||||
|
#if 0
|
||||||
|
for (size_t l = outer_start; l < outer_start + outer_len; l++) {
|
||||||
|
fprintf(stderr, " %lld,%lld", geom[l].x, geom[l].y);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
drawvec close_poly(drawvec &geom) {
|
drawvec close_poly(drawvec &geom) {
|
||||||
drawvec out;
|
drawvec out;
|
||||||
|
|
||||||
@ -532,12 +798,7 @@ drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *reduced, double
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double area = 0;
|
double area = get_area(geom, i, j);
|
||||||
for (size_t k = i; k < j; k++) {
|
|
||||||
area += (long double) geom[k].x * (long double) geom[i + ((k - i + 1) % (j - i))].y;
|
|
||||||
area -= (long double) geom[k].y * (long double) geom[i + ((k - i + 1) % (j - i))].x;
|
|
||||||
}
|
|
||||||
area = area / 2;
|
|
||||||
|
|
||||||
// XXX There is an ambiguity here: If the area of a ring is 0 and it is followed by holes,
|
// XXX There is an ambiguity here: If the area of a ring is 0 and it is followed by holes,
|
||||||
// we don't know whether the area-0 ring was a hole too or whether it was the outer ring
|
// we don't know whether the area-0 ring was a hole too or whether it was the outer ring
|
||||||
@ -931,12 +1192,7 @@ drawvec fix_polygon(drawvec &geom) {
|
|||||||
// Reverse ring if winding order doesn't match
|
// Reverse ring if winding order doesn't match
|
||||||
// inner/outer expectation
|
// inner/outer expectation
|
||||||
|
|
||||||
double area = 0;
|
double area = get_area(ring, 0, ring.size());
|
||||||
for (size_t k = 0; k < ring.size(); k++) {
|
|
||||||
area += (long double) ring[k].x * (long double) ring[(k + 1) % ring.size()].y;
|
|
||||||
area -= (long double) ring[k].y * (long double) ring[(k + 1) % ring.size()].x;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((area > 0) != outer) {
|
if ((area > 0) != outer) {
|
||||||
drawvec tmp;
|
drawvec tmp;
|
||||||
for (int a = ring.size() - 1; a >= 0; a--) {
|
for (int a = ring.size() - 1; a >= 0; a--) {
|
||||||
@ -977,6 +1233,12 @@ std::vector<drawvec> chop_polygon(std::vector<drawvec> &geoms) {
|
|||||||
|
|
||||||
for (size_t i = 0; i < geoms.size(); i++) {
|
for (size_t i = 0; i < geoms.size(); i++) {
|
||||||
if (geoms[i].size() > 700) {
|
if (geoms[i].size() > 700) {
|
||||||
|
static bool warned = false;
|
||||||
|
if (!warned) {
|
||||||
|
fprintf(stderr, "Warning: splitting up polygon with more than 700 sides\n");
|
||||||
|
warned = true;
|
||||||
|
}
|
||||||
|
|
||||||
long long midx = 0, midy = 0, count = 0;
|
long long midx = 0, midy = 0, count = 0;
|
||||||
long long maxx = LLONG_MIN, maxy = LLONG_MIN, minx = LLONG_MAX, miny = LLONG_MAX;
|
long long maxx = LLONG_MIN, maxy = LLONG_MIN, minx = LLONG_MAX, miny = LLONG_MAX;
|
||||||
|
|
||||||
|
@ -31,3 +31,4 @@ drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds);
|
|||||||
drawvec reorder_lines(drawvec &geom);
|
drawvec reorder_lines(drawvec &geom);
|
||||||
drawvec fix_polygon(drawvec &geom);
|
drawvec fix_polygon(drawvec &geom);
|
||||||
std::vector<drawvec> chop_polygon(std::vector<drawvec> &geoms);
|
std::vector<drawvec> chop_polygon(std::vector<drawvec> &geoms);
|
||||||
|
void check_polygon(drawvec &geom, drawvec &before);
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
}, "features": [
|
}, "features": [
|
||||||
{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [
|
{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [
|
||||||
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
||||||
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 186.943359, 35.460670 ], [ 179.912109, 36.527295 ], [ 175.781250, 37.160317 ], [ 161.718750, 45.336702 ], [ 156.796875, 55.028022 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.811557 ], [ 177.539062, 67.339861 ], [ 179.912109, 67.542167 ], [ 186.943359, 68.007571 ], [ 186.943359, 63.743631 ], [ 182.109375, 62.593341 ], [ 179.912109, 61.689872 ], [ 174.023438, 58.859224 ], [ 171.562500, 54.418930 ], [ 174.023438, 47.279229 ], [ 179.912109, 45.274886 ], [ 182.460938, 44.339565 ], [ 186.943359, 44.024422 ], [ 186.943359, 35.460670 ] ] ], [ [ [ -177.539062, 44.339565 ], [ -164.882812, 43.389082 ], [ -153.281250, 46.619261 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.183902 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.510643 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.689872 ], [ -185.976562, 58.859224 ], [ -187.031250, 56.992883 ], [ -187.031250, 65.730626 ], [ -182.460938, 67.339861 ], [ -180.000000, 67.542167 ], [ -169.101562, 68.269387 ], [ -156.093750, 68.138852 ], [ -144.492188, 66.089364 ], [ -134.648438, 62.431074 ], [ -131.835938, 55.379110 ], [ -133.593750, 48.690960 ], [ -146.250000, 38.616870 ], [ -169.453125, 34.957995 ], [ -180.000000, 36.527295 ], [ -184.218750, 37.160317 ], [ -187.031250, 38.891033 ], [ -187.031250, 50.457504 ], [ -185.976562, 47.279229 ], [ -177.539062, 44.339565 ] ] ] ] } }
|
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -177.539062, 44.339565 ], [ -164.882812, 43.389082 ], [ -153.281250, 46.619261 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.183902 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.510643 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.689872 ], [ -185.976562, 58.859224 ], [ -187.031250, 56.992883 ], [ -187.031250, 65.730626 ], [ -182.460938, 67.339861 ], [ -180.000000, 67.542167 ], [ -169.101562, 68.269387 ], [ -156.093750, 68.138852 ], [ -144.492188, 66.089364 ], [ -134.648438, 62.431074 ], [ -131.835938, 55.379110 ], [ -133.593750, 48.690960 ], [ -146.250000, 38.616870 ], [ -169.453125, 34.957995 ], [ -180.000000, 36.527295 ], [ -184.218750, 37.160317 ], [ -187.031250, 38.891033 ], [ -187.031250, 50.457504 ], [ -185.976562, 47.279229 ], [ -177.539062, 44.339565 ] ], [ [ 186.943359, 35.460670 ], [ 179.912109, 36.527295 ], [ 175.781250, 37.160317 ], [ 161.718750, 45.336702 ], [ 156.796875, 55.028022 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.811557 ], [ 177.539062, 67.339861 ], [ 179.912109, 67.542167 ], [ 186.943359, 68.007571 ], [ 186.943359, 63.743631 ], [ 182.109375, 62.593341 ], [ 179.912109, 61.689872 ], [ 174.023438, 58.859224 ], [ 171.562500, 54.418930 ], [ 174.023438, 47.279229 ], [ 179.912109, 45.274886 ], [ 182.460938, 44.339565 ], [ 186.943359, 44.024422 ], [ 186.943359, 35.460670 ] ] ] } }
|
||||||
,
|
,
|
||||||
{ "type": "Feature", "properties": { "zoom": "z0-2" }, "geometry": { "type": "LineString", "coordinates": [ [ -112.851562, 55.178868 ], [ -117.773438, 44.590467 ], [ -104.414062, 51.179343 ] ] } }
|
{ "type": "Feature", "properties": { "zoom": "z0-2" }, "geometry": { "type": "LineString", "coordinates": [ [ -112.851562, 55.178868 ], [ -117.773438, 44.590467 ], [ -104.414062, 51.179343 ] ] } }
|
||||||
] }
|
] }
|
||||||
@ -204,13 +204,13 @@
|
|||||||
,
|
,
|
||||||
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 15, "y": 5 }, "features": [
|
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 15, "y": 5 }, "features": [
|
||||||
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
||||||
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 172.309570, 55.776573 ], [ 171.562500, 54.370959 ], [ 174.023438, 47.279229 ], [ 180.439453, 45.058001 ], [ 180.439453, 40.647304 ], [ 169.991455, 40.647304 ], [ 169.425659, 40.979898 ], [ 161.718750, 45.336702 ], [ 157.500000, 53.722717 ], [ 157.060547, 54.514704 ], [ 157.060547, 55.307264 ], [ 157.648315, 56.022948 ], [ 172.441406, 56.022948 ], [ 172.309570, 55.776573 ] ] ] } }
|
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 171.562500, 54.370959 ], [ 174.023438, 47.279229 ], [ 180.439453, 45.058001 ], [ 180.439453, 40.647304 ], [ 169.991455, 40.647304 ], [ 169.425659, 40.979898 ], [ 161.718750, 45.336702 ], [ 157.500000, 53.722717 ], [ 157.060547, 54.514704 ], [ 157.060547, 55.307264 ], [ 157.648315, 56.022948 ], [ 172.441406, 56.022948 ], [ 172.309570, 55.776573 ], [ 171.562500, 54.370959 ] ] ] } }
|
||||||
] }
|
] }
|
||||||
] }
|
] }
|
||||||
,
|
,
|
||||||
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 15, "y": 4 }, "features": [
|
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 15, "y": 4 }, "features": [
|
||||||
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
||||||
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 61.650771 ], [ 174.023438, 58.816586 ], [ 172.309570, 55.776573 ], [ 172.172241, 55.528631 ], [ 157.241821, 55.528631 ], [ 157.500000, 55.841398 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.776466 ], [ 175.187988, 66.513260 ], [ 175.676880, 66.687784 ], [ 180.439453, 66.687784 ], [ 180.439453, 61.850966 ], [ 180.000000, 61.650771 ] ] ] } }
|
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 174.023438, 58.816586 ], [ 172.309570, 55.776573 ], [ 172.172241, 55.528631 ], [ 157.241821, 55.528631 ], [ 157.500000, 55.841398 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.776466 ], [ 175.187988, 66.513260 ], [ 175.676880, 66.687784 ], [ 180.439453, 66.687784 ], [ 180.439453, 61.850966 ], [ 180.000000, 61.650771 ], [ 174.023438, 58.816586 ] ] ] } }
|
||||||
] }
|
] }
|
||||||
] }
|
] }
|
||||||
,
|
,
|
||||||
@ -234,7 +234,7 @@
|
|||||||
,
|
,
|
||||||
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 9 }, "features": [
|
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 9 }, "features": [
|
||||||
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
||||||
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -179.868164, 61.710706 ], [ -180.219727, 61.551493 ], [ -180.219727, 61.710706 ], [ -179.868164, 61.710706 ] ] ] } }
|
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -180.219727, 61.710706 ], [ -179.868164, 61.710706 ], [ -180.219727, 61.551493 ], [ -180.219727, 61.710706 ] ] ] } }
|
||||||
] }
|
] }
|
||||||
] }
|
] }
|
||||||
,
|
,
|
||||||
@ -438,25 +438,25 @@
|
|||||||
,
|
,
|
||||||
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 11 }, "features": [
|
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 11 }, "features": [
|
||||||
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
||||||
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 173.485107, 48.922499 ], [ 174.023438, 47.279229 ], [ 180.219727, 45.135555 ], [ 180.219727, 40.813809 ], [ 169.708557, 40.813809 ], [ 169.425659, 40.979898 ], [ 168.750000, 41.376809 ], [ 168.530273, 41.504464 ], [ 168.530273, 49.066668 ], [ 173.435669, 49.066668 ], [ 173.485107, 48.922499 ] ] ] } }
|
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 174.023438, 47.279229 ], [ 180.219727, 45.135555 ], [ 180.219727, 40.813809 ], [ 169.708557, 40.813809 ], [ 169.425659, 40.979898 ], [ 168.750000, 41.376809 ], [ 168.530273, 41.504464 ], [ 168.530273, 49.066668 ], [ 173.435669, 49.066668 ], [ 173.485107, 48.922499 ], [ 174.023438, 47.279229 ] ] ] } }
|
||||||
] }
|
] }
|
||||||
] }
|
] }
|
||||||
,
|
,
|
||||||
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 10 }, "features": [
|
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 10 }, "features": [
|
||||||
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
||||||
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 172.309570, 55.776573 ], [ 171.562500, 54.369359 ], [ 173.485107, 48.922499 ], [ 173.531799, 48.777913 ], [ 168.530273, 48.777913 ], [ 168.530273, 55.899956 ], [ 172.375488, 55.899956 ], [ 172.309570, 55.776573 ] ] ] } }
|
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 171.562500, 54.369359 ], [ 173.485107, 48.922499 ], [ 173.531799, 48.777913 ], [ 168.530273, 48.777913 ], [ 168.530273, 55.899956 ], [ 172.375488, 55.899956 ], [ 172.309570, 55.776573 ], [ 171.562500, 54.369359 ] ] ] } }
|
||||||
] }
|
] }
|
||||||
] }
|
] }
|
||||||
,
|
,
|
||||||
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 9 }, "features": [
|
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 9 }, "features": [
|
||||||
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
||||||
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 179.901123, 61.606396 ], [ 174.023438, 58.815164 ], [ 172.306824, 55.776573 ], [ 172.240906, 55.652798 ], [ 168.530273, 55.652798 ], [ 168.530273, 61.710706 ], [ 180.131836, 61.710706 ], [ 179.901123, 61.606396 ] ] ] } }
|
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 174.023438, 58.815164 ], [ 172.306824, 55.776573 ], [ 172.240906, 55.652798 ], [ 168.530273, 55.652798 ], [ 168.530273, 61.710706 ], [ 180.131836, 61.710706 ], [ 179.901123, 61.606396 ], [ 174.023438, 58.815164 ] ] ] } }
|
||||||
] }
|
] }
|
||||||
] }
|
] }
|
||||||
,
|
,
|
||||||
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 8 }, "features": [
|
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 8 }, "features": [
|
||||||
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
||||||
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 61.650771 ], [ 179.901123, 61.606396 ], [ 179.670410, 61.501734 ], [ 168.530273, 61.501734 ], [ 168.530273, 64.135775 ], [ 170.507812, 64.775296 ], [ 175.190735, 66.513260 ], [ 175.435181, 66.600676 ], [ 180.219727, 66.600676 ], [ 180.219727, 61.751031 ], [ 180.000000, 61.650771 ] ] ] } }
|
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27.00000000,27,1.4e27,{\"foo\":\"bar\"}]", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 179.901123, 61.606396 ], [ 179.670410, 61.501734 ], [ 168.530273, 61.501734 ], [ 168.530273, 64.135775 ], [ 170.507812, 64.775296 ], [ 175.190735, 66.513260 ], [ 175.435181, 66.600676 ], [ 180.219727, 66.600676 ], [ 180.219727, 61.751031 ], [ 180.000000, 61.650771 ], [ 179.901123, 61.606396 ] ] ] } }
|
||||||
] }
|
] }
|
||||||
] }
|
] }
|
||||||
,
|
,
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -12,7 +12,7 @@
|
|||||||
}, "features": [
|
}, "features": [
|
||||||
{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [
|
{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [
|
||||||
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
{ "type": "FeatureCollection", "properties": { "layer": "in" }, "features": [
|
||||||
{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -3.076172, 61.015725 ], [ -15.380859, 52.908902 ], [ -10.019531, 50.007739 ], [ -5.009766, 8.059230 ], [ -17.050781, -21.943046 ], [ -75.058594, -30.977609 ], [ -118.037109, -8.928487 ], [ -135.000000, 29.075375 ], [ -113.027344, 53.014783 ], [ -111.884766, 53.383328 ], [ -117.070312, 60.020952 ], [ -113.027344, 69.005675 ], [ -93.076172, 75.004940 ], [ -74.003906, 79.004962 ], [ -33.046875, 79.004962 ], [ -3.076172, 61.015725 ] ], [ [ -111.884766, 53.383328 ], [ -103.007812, 39.027719 ], [ -71.015625, 29.075375 ], [ -37.001953, 34.016242 ], [ -15.380859, 52.908902 ], [ -28.037109, 59.040555 ], [ -81.035156, 63.035039 ], [ -111.884766, 53.383328 ] ] ] } }
|
{ "type": "Feature", "properties": { }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -103.007812, 39.027719 ], [ -71.015625, 29.075375 ], [ -37.001953, 34.016242 ], [ -15.380859, 52.908902 ], [ -10.019531, 50.007739 ], [ -5.009766, 8.059230 ], [ -17.050781, -21.943046 ], [ -75.058594, -30.977609 ], [ -118.037109, -8.928487 ], [ -135.000000, 29.075375 ], [ -113.027344, 53.014783 ], [ -111.884766, 53.383328 ], [ -103.007812, 39.027719 ] ] ], [ [ [ -117.070312, 60.020952 ], [ -113.027344, 69.005675 ], [ -93.076172, 75.004940 ], [ -74.003906, 79.004962 ], [ -33.046875, 79.004962 ], [ -3.076172, 61.015725 ], [ -15.380859, 52.908902 ], [ -28.037109, 59.040555 ], [ -81.035156, 63.035039 ], [ -111.884766, 53.383328 ], [ -117.070312, 60.020952 ] ] ] ] } }
|
||||||
] }
|
] }
|
||||||
] }
|
] }
|
||||||
] }
|
] }
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
7
tile.cc
7
tile.cc
@ -462,7 +462,14 @@ void *partial_feature_worker(void *v) {
|
|||||||
// Scaling may have made the polygon degenerate.
|
// Scaling may have made the polygon degenerate.
|
||||||
// Give Clipper a chance to try to fix it.
|
// Give Clipper a chance to try to fix it.
|
||||||
for (size_t i = 0; i < geoms.size(); i++) {
|
for (size_t i = 0; i < geoms.size(); i++) {
|
||||||
|
drawvec before;
|
||||||
|
if (additional[A_DEBUG_POLYGON]) {
|
||||||
|
before = geoms[i];
|
||||||
|
}
|
||||||
geoms[i] = clean_or_clip_poly(geoms[i], 0, 0, 0, false);
|
geoms[i] = clean_or_clip_poly(geoms[i], 0, 0, 0, false);
|
||||||
|
if (additional[A_DEBUG_POLYGON]) {
|
||||||
|
check_polygon(geoms[i], before);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
tile.h
2
tile.h
@ -50,6 +50,8 @@ static int additional_options[] = {
|
|||||||
A_REORDER,
|
A_REORDER,
|
||||||
#define A_LINE_DROP ((int) 'l')
|
#define A_LINE_DROP ((int) 'l')
|
||||||
A_LINE_DROP,
|
A_LINE_DROP,
|
||||||
|
#define A_DEBUG_POLYGON ((int) 'd')
|
||||||
|
A_DEBUG_POLYGON,
|
||||||
#define A_POLYGON_DROP ((int) 'p')
|
#define A_POLYGON_DROP ((int) 'p')
|
||||||
A_POLYGON_DROP,
|
A_POLYGON_DROP,
|
||||||
#define A_PREFER_RADIX_SORT ((int) 'R')
|
#define A_PREFER_RADIX_SORT ((int) 'R')
|
||||||
|
Loading…
Reference in New Issue
Block a user