From d32d4bb35f9b2b21cdc4e946fa7dc97dffc673c1 Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Wed, 27 Apr 2016 12:25:03 -0700 Subject: [PATCH] No need for line clipping to have its own source file --- Makefile | 7 +++-- clip.c | 84 --------------------------------------------------- clip.h | 1 - geometry.cpp | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++- tile.cpp | 1 - 5 files changed, 88 insertions(+), 90 deletions(-) delete mode 100644 clip.c delete mode 100644 clip.h diff --git a/Makefile b/Makefile index 0ed76d1..befde48 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ C = $(shell find . '(' -name '*.c' -o -name '*.cpp' ')') INCLUDES = -I/usr/local/include -I. LIBS = -L/usr/local/lib -tippecanoe: geojson.o jsonpull.o tile.o clip.o pool.o mbtiles.o geometry.o projection.o memfile.o clipper/clipper.o mvt.o +tippecanoe: geojson.o jsonpull.o tile.o pool.o mbtiles.o geometry.o projection.o memfile.o clipper.o mvt.o $(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread tippecanoe-enumerate: enumerate.o @@ -64,14 +64,15 @@ libjsonpull.a: jsonpull.o %.o: %.cpp $(H) $(CXX) $(PG) $(INCLUDES) $(FINAL_FLAGS) $(CXXFLAGS) -c $< +clipper.o: clipper/clipper.cpp $(H) + $(CXX) $(PG) $(INCLUDES) $(FINAL_FLAGS) $(CXXFLAGS) -c $< + clean: rm -f tippecanoe *.o 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) -geometry.o: clipper/clipper.hpp - TESTS = $(wildcard tests/*/out/*.json) SPACE = $(NULL) $(NULL) diff --git a/clip.c b/clip.c deleted file mode 100644 index 5464b28..0000000 --- a/clip.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "clip.h" - -#define INSIDE 0 -#define LEFT 1 -#define RIGHT 2 -#define BOTTOM 4 -#define TOP 8 - -static int computeOutCode(double x, double y, double xmin, double ymin, double xmax, double ymax) { - int code = INSIDE; - - if (x < xmin) { - code |= LEFT; - } else if (x > xmax) { - code |= RIGHT; - } - - if (y < ymin) { - code |= BOTTOM; - } else if (y > ymax) { - code |= TOP; - } - - return code; -} - -int clip(double *x0, double *y0, double *x1, double *y1, double xmin, double ymin, double xmax, double ymax) { - int outcode0 = computeOutCode(*x0, *y0, xmin, ymin, xmax, ymax); - int outcode1 = computeOutCode(*x1, *y1, xmin, ymin, xmax, ymax); - int accept = 0; - int changed = 0; - - while (1) { - if (!(outcode0 | outcode1)) { // Bitwise OR is 0. Trivially accept and get out of loop - accept = 1; - break; - } else if (outcode0 & outcode1) { // Bitwise AND is not 0. Trivially reject and get out of loop - break; - } else { - // failed both tests, so calculate the line segment to clip - // from an outside point to an intersection with clip edge - double x = *x0, y = *y0; - - // At least one endpoint is outside the clip rectangle; pick it. - int outcodeOut = outcode0 ? outcode0 : outcode1; - - // Now find the intersection point; - // use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0) - if (outcodeOut & TOP) { // point is above the clip rectangle - x = *x0 + (*x1 - *x0) * (ymax - *y0) / (*y1 - *y0); - y = ymax; - } else if (outcodeOut & BOTTOM) { // point is below the clip rectangle - x = *x0 + (*x1 - *x0) * (ymin - *y0) / (*y1 - *y0); - y = ymin; - } else if (outcodeOut & RIGHT) { // point is to the right of clip rectangle - y = *y0 + (*y1 - *y0) * (xmax - *x0) / (*x1 - *x0); - x = xmax; - } else if (outcodeOut & LEFT) { // point is to the left of clip rectangle - y = *y0 + (*y1 - *y0) * (xmin - *x0) / (*x1 - *x0); - x = xmin; - } - - // Now we move outside point to intersection point to clip - // and get ready for next pass. - if (outcodeOut == outcode0) { - *x0 = x; - *y0 = y; - outcode0 = computeOutCode(*x0, *y0, xmin, ymin, xmax, ymax); - changed = 1; - } else { - *x1 = x; - *y1 = y; - outcode1 = computeOutCode(*x1, *y1, xmin, ymin, xmax, ymax); - changed = 1; - } - } - } - - if (accept == 0) { - return 0; - } else { - return changed + 1; - } -} diff --git a/clip.h b/clip.h deleted file mode 100644 index 513a980..0000000 --- a/clip.h +++ /dev/null @@ -1 +0,0 @@ -int clip(double *x0, double *y0, double *x1, double *y1, double xmin, double ymin, double xmax, double ymax); diff --git a/geometry.cpp b/geometry.cpp index 2e12e07..cb868f3 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -14,11 +14,11 @@ extern "C" { #include #include "tile.h" -#include "clip.h" #include "projection.h" } static int pnpoly(drawvec &vert, size_t start, size_t nvert, long long testx, long long testy); +static int clip(double *x0, double *y0, double *x1, double *y1, double xmin, double ymin, double xmax, double ymax); 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; @@ -1310,3 +1310,86 @@ std::vector chop_polygon(std::vector &geoms) { geoms = out; } } + +#define INSIDE 0 +#define LEFT 1 +#define RIGHT 2 +#define BOTTOM 4 +#define TOP 8 + +static int computeOutCode(double x, double y, double xmin, double ymin, double xmax, double ymax) { + int code = INSIDE; + + if (x < xmin) { + code |= LEFT; + } else if (x > xmax) { + code |= RIGHT; + } + + if (y < ymin) { + code |= BOTTOM; + } else if (y > ymax) { + code |= TOP; + } + + return code; +} + +static int clip(double *x0, double *y0, double *x1, double *y1, double xmin, double ymin, double xmax, double ymax) { + int outcode0 = computeOutCode(*x0, *y0, xmin, ymin, xmax, ymax); + int outcode1 = computeOutCode(*x1, *y1, xmin, ymin, xmax, ymax); + int accept = 0; + int changed = 0; + + while (1) { + if (!(outcode0 | outcode1)) { // Bitwise OR is 0. Trivially accept and get out of loop + accept = 1; + break; + } else if (outcode0 & outcode1) { // Bitwise AND is not 0. Trivially reject and get out of loop + break; + } else { + // failed both tests, so calculate the line segment to clip + // from an outside point to an intersection with clip edge + double x = *x0, y = *y0; + + // At least one endpoint is outside the clip rectangle; pick it. + int outcodeOut = outcode0 ? outcode0 : outcode1; + + // Now find the intersection point; + // use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0) + if (outcodeOut & TOP) { // point is above the clip rectangle + x = *x0 + (*x1 - *x0) * (ymax - *y0) / (*y1 - *y0); + y = ymax; + } else if (outcodeOut & BOTTOM) { // point is below the clip rectangle + x = *x0 + (*x1 - *x0) * (ymin - *y0) / (*y1 - *y0); + y = ymin; + } else if (outcodeOut & RIGHT) { // point is to the right of clip rectangle + y = *y0 + (*y1 - *y0) * (xmax - *x0) / (*x1 - *x0); + x = xmax; + } else if (outcodeOut & LEFT) { // point is to the left of clip rectangle + y = *y0 + (*y1 - *y0) * (xmin - *x0) / (*x1 - *x0); + x = xmin; + } + + // Now we move outside point to intersection point to clip + // and get ready for next pass. + if (outcodeOut == outcode0) { + *x0 = x; + *y0 = y; + outcode0 = computeOutCode(*x0, *y0, xmin, ymin, xmax, ymax); + changed = 1; + } else { + *x1 = x; + *y1 = y; + outcode1 = computeOutCode(*x1, *y1, xmin, ymin, xmax, ymax); + changed = 1; + } + } + } + + if (accept == 0) { + return 0; + } else { + return changed + 1; + } +} diff --git a/tile.cpp b/tile.cpp index f1c7d32..389cb8e 100644 --- a/tile.cpp +++ b/tile.cpp @@ -25,7 +25,6 @@ extern "C" { #include "tile.h" #include "pool.h" -#include "clip.h" #include "mbtiles.h" #include "projection.h" }