这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 1.32.1

* Fix null pointer crash when reading filter output that does not
tag features with their extent
* Add `--clip-bounding-box` option to clip input geometry

## 1.32.0

* Fix a bug that allowed coalescing of features with mismatched attributes
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ the same layer, enclose them in an `all` expression so they will all be evaluate
* `-aw` or `--detect-longitude-wraparound`: Detect when adjacent points within a feature jump to the other side of the world, and try to fix the geometry.
* `-pw` or `--use-source-polygon-winding`: Instead of respecting GeoJSON polygon ring order, use the original polygon winding in the source data to distinguish inner (clockwise) and outer (counterclockwise) polygon rings.
* `-pW` or `--reverse-source-polygon-winding`: Instead of respecting GeoJSON polygon ring order, use the opposite of the original polygon winding in the source data to distinguish inner (counterclockwise) and outer (clockwise) polygon rings.
* `--clip-bounding-box=`*minlon*`,`*minlat*`,`*maxlon*`,`*maxlat*: Clip all features to the specified bounding box.

### Setting or disabling tile size limits

Expand Down
20 changes: 14 additions & 6 deletions geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -595,16 +595,20 @@ drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *reduced, double
}

drawvec clip_point(drawvec &geom, int z, long long buffer) {
drawvec out;

long long min = 0;
long long area = 1LL << (32 - z);

min -= buffer * area / 256;
area += buffer * area / 256;

return clip_point(geom, min, min, area, area);
}

drawvec clip_point(drawvec &geom, long long minx, long long miny, long long maxx, long long maxy) {
drawvec out;

for (size_t i = 0; i < geom.size(); i++) {
if (geom[i].x >= min && geom[i].y >= min && geom[i].x <= area && geom[i].y <= area) {
if (geom[i].x >= minx && geom[i].y >= miny && geom[i].x <= maxx && geom[i].y <= maxy) {
out.push_back(geom[i]);
}
}
Expand Down Expand Up @@ -646,13 +650,17 @@ bool point_within_tile(long long x, long long y, int z) {
}

drawvec clip_lines(drawvec &geom, int z, long long buffer) {
drawvec out;

long long min = 0;
long long area = 1LL << (32 - z);
min -= buffer * area / 256;
area += buffer * area / 256;

return clip_lines(geom, min, min, area, area);
}

drawvec clip_lines(drawvec &geom, long long minx, long long miny, long long maxx, long long maxy) {
drawvec out;

for (size_t i = 0; i < geom.size(); i++) {
if (i > 0 && (geom[i - 1].op == VT_MOVETO || geom[i - 1].op == VT_LINETO) && geom[i].op == VT_LINETO) {
double x1 = geom[i - 1].x;
Expand All @@ -661,7 +669,7 @@ drawvec clip_lines(drawvec &geom, int z, long long buffer) {
double x2 = geom[i - 0].x;
double y2 = geom[i - 0].y;

int c = clip(&x1, &y1, &x2, &y2, min, min, area, area);
int c = clip(&x1, &y1, &x2, &y2, minx, miny, maxx, maxy);

if (c > 1) { // clipped
out.push_back(draw(VT_MOVETO, x1, y1));
Expand Down
4 changes: 4 additions & 0 deletions geometry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,8 @@ void check_polygon(drawvec &geom);
double get_area(drawvec &geom, size_t i, size_t j);
double get_mp_area(drawvec &geom);

drawvec simple_clip_poly(drawvec &geom, long long x1, long long y1, long long x2, long long y2);
drawvec clip_lines(drawvec &geom, long long x1, long long y1, long long x2, long long y2);
drawvec clip_point(drawvec &geom, long long x1, long long y1, long long x2, long long y2);

#endif
22 changes: 22 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ long long MAX_FILES;
static long long diskfree;
char **av;

std::vector<clipbbox> clipbboxes;

void checkdisk(std::vector<struct reader> *r) {
long long used = 0;
for (size_t i = 0; i < r->size(); i++) {
Expand Down Expand Up @@ -2594,6 +2596,7 @@ int main(int argc, char **argv) {
{"detect-longitude-wraparound", no_argument, &additional[A_DETECT_WRAPAROUND], 1},
{"use-source-polygon-winding", no_argument, &prevent[P_USE_SOURCE_POLYGON_WINDING], 1},
{"reverse-source-polygon-winding", no_argument, &prevent[P_REVERSE_SOURCE_POLYGON_WINDING], 1},
{"clip-bounding-box", required_argument, 0, '~'},

{"Filtering tile contents", 0, 0, 0},
{"prefilter", required_argument, 0, 'C'},
Expand Down Expand Up @@ -2682,6 +2685,17 @@ int main(int argc, char **argv) {
max_tilestats_sample_values = atoi(optarg);
} else if (strcmp(opt, "tile-stats-values-limit") == 0) {
max_tilestats_values = atoi(optarg);
} else if (strcmp(opt, "clip-bounding-box") == 0) {
clipbbox clip;
if (sscanf(optarg, "%lf,%lf,%lf,%lf", &clip.lon1, &clip.lat1, &clip.lon2, &clip.lat2) == 4) {
clipbboxes.push_back(clip);
} else {
fprintf(stderr, "%s: Can't parse bounding box --%s=%s\n", argv[0], opt, optarg);
exit(EXIT_FAILURE);
}
} else {
fprintf(stderr, "%s: Unrecognized option --%s\n", argv[0], opt);
exit(EXIT_FAILURE);
}
break;
}
Expand Down Expand Up @@ -3003,6 +3017,14 @@ int main(int argc, char **argv) {
}
}

// Wait until here to project the bounding box, so that the behavior is
// the same no matter what order the projection and bounding box are
// specified in
for (auto &c : clipbboxes) {
projection->project(c.lon1, c.lat1, 32, &c.minx, &c.maxy);
projection->project(c.lon2, c.lat2, 32, &c.maxx, &c.miny);
}

if (max_tilestats_sample_values < max_tilestats_values) {
max_tilestats_sample_values = max_tilestats_values;
}
Expand Down
14 changes: 14 additions & 0 deletions main.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ struct index {
}
};

struct clipbbox {
double lon1;
double lat1;
double lon2;
double lat2;

long long minx;
long long miny;
long long maxx;
long long maxy;
};

extern std::vector<clipbbox> clipbboxes;

void checkdisk(std::vector<struct reader> *r);

extern int geometry_scale;
Expand Down
2 changes: 2 additions & 0 deletions man/tippecanoe.1
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,8 @@ the line or polygon within one tile unit of its proper location. You can probabl
\fB\fC\-pw\fR or \fB\fC\-\-use\-source\-polygon\-winding\fR: Instead of respecting GeoJSON polygon ring order, use the original polygon winding in the source data to distinguish inner (clockwise) and outer (counterclockwise) polygon rings.
.IP \(bu 2
\fB\fC\-pW\fR or \fB\fC\-\-reverse\-source\-polygon\-winding\fR: Instead of respecting GeoJSON polygon ring order, use the opposite of the original polygon winding in the source data to distinguish inner (counterclockwise) and outer (clockwise) polygon rings.
.IP \(bu 2
\fB\fC\-\-clip\-bounding\-box=\fR\fIminlon\fP\fB\fC,\fR\fIminlat\fP\fB\fC,\fR\fImaxlon\fP\fB\fC,\fR\fImaxlat\fP: Clip all features to the specified bounding box.
.RE
.SS Setting or disabling tile size limits
.RS
Expand Down
2 changes: 1 addition & 1 deletion plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std::
}

json_object *extent = json_hash_get(tippecanoe, "extent");
if (extent != NULL && sequence->type == JSON_NUMBER) {
if (extent != NULL && extent->type == JSON_NUMBER) {
sf.extent = extent->number;
}

Expand Down
39 changes: 39 additions & 0 deletions serial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,45 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf) {
sf.geometry = fix_polygon(sf.geometry);
}

for (auto &c : clipbboxes) {
if (sf.t == VT_POLYGON) {
sf.geometry = simple_clip_poly(sf.geometry, c.minx >> geometry_scale, c.miny >> geometry_scale, c.maxx >> geometry_scale, c.maxy >> geometry_scale);
} else if (sf.t == VT_LINE) {
sf.geometry = clip_lines(sf.geometry, c.minx >> geometry_scale, c.miny >> geometry_scale, c.maxx >> geometry_scale, c.maxy >> geometry_scale);
sf.geometry = remove_noop(sf.geometry, sf.t, 0);
} else if (sf.t == VT_POINT) {
sf.geometry = clip_point(sf.geometry, c.minx >> geometry_scale, c.miny >> geometry_scale, c.maxx >> geometry_scale, c.maxy >> geometry_scale);
}

sf.bbox[0] = LLONG_MAX;
sf.bbox[1] = LLONG_MAX;
sf.bbox[2] = LLONG_MIN;
sf.bbox[3] = LLONG_MIN;

for (auto &g : sf.geometry) {
long long x = g.x << geometry_scale;
long long y = g.y << geometry_scale;

if (x < sf.bbox[0]) {
sf.bbox[0] = x;
}
if (y < sf.bbox[1]) {
sf.bbox[1] = y;
}
if (x > sf.bbox[2]) {
sf.bbox[2] = x;
}
if (y > sf.bbox[3]) {
sf.bbox[3] = y;
}
}
}

if (sf.geometry.size() == 0) {
// Feature was clipped away
return 1;
}

if (!sf.has_id) {
if (additional[A_GENERATE_IDS]) {
sf.has_id = true;
Expand Down
Loading