mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 08:25:40 +02:00
Start getting features (just geometry so far) back from the prefilter
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|||||||
+133
-1
@@ -15,14 +15,15 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include "mvt.hpp"
|
#include "mvt.hpp"
|
||||||
#include "plugin.hpp"
|
|
||||||
#include "projection.hpp"
|
#include "projection.hpp"
|
||||||
#include "geometry.hpp"
|
#include "geometry.hpp"
|
||||||
|
#include "serial.hpp"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "jsonpull/jsonpull.h"
|
#include "jsonpull/jsonpull.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "plugin.hpp"
|
||||||
#include "write_json.hpp"
|
#include "write_json.hpp"
|
||||||
#include "read_json.hpp"
|
#include "read_json.hpp"
|
||||||
|
|
||||||
@@ -203,9 +204,140 @@ mvt_layer parse_layer(int fd, unsigned z, unsigned x, unsigned y, mvt_layer cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
json_end(jp);
|
json_end(jp);
|
||||||
|
fclose(f);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serial_feature parse_feature(json_pull *jp, unsigned z, unsigned x, unsigned y) {
|
||||||
|
serial_feature sf;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
json_object *j = json_read(jp);
|
||||||
|
if (j == NULL) {
|
||||||
|
if (jp->error != NULL) {
|
||||||
|
fprintf(stderr, "Filter output:%d: %s\n", jp->line, jp->error);
|
||||||
|
if (jp->root != NULL) {
|
||||||
|
json_context(jp->root);
|
||||||
|
}
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
json_free(jp->root);
|
||||||
|
sf.t = -1;
|
||||||
|
return sf;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object *type = json_hash_get(j, "type");
|
||||||
|
if (type == NULL || type->type != JSON_STRING) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strcmp(type->string, "Feature") != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object *geometry = json_hash_get(j, "geometry");
|
||||||
|
if (geometry == NULL) {
|
||||||
|
fprintf(stderr, "Filter output:%d: filtered feature with no geometry\n", jp->line);
|
||||||
|
json_context(j);
|
||||||
|
json_free(j);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object *properties = json_hash_get(j, "properties");
|
||||||
|
if (properties == NULL || (properties->type != JSON_HASH && properties->type != JSON_NULL)) {
|
||||||
|
fprintf(stderr, "Filter output:%d: feature without properties hash\n", jp->line);
|
||||||
|
json_context(j);
|
||||||
|
json_free(j);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object *geometry_type = json_hash_get(geometry, "type");
|
||||||
|
if (geometry_type == NULL) {
|
||||||
|
fprintf(stderr, "Filter output:%d: null geometry (additional not reported)\n", jp->line);
|
||||||
|
json_context(j);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (geometry_type->type != JSON_STRING) {
|
||||||
|
fprintf(stderr, "Filter output:%d: geometry type is not a string\n", jp->line);
|
||||||
|
json_context(j);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object *coordinates = json_hash_get(geometry, "coordinates");
|
||||||
|
if (coordinates == NULL || coordinates->type != JSON_ARRAY) {
|
||||||
|
fprintf(stderr, "Filter output:%d: feature without coordinates array\n", jp->line);
|
||||||
|
json_context(j);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int t;
|
||||||
|
for (t = 0; t < GEOM_TYPES; t++) {
|
||||||
|
if (strcmp(geometry_type->string, geometry_names[t]) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (t >= GEOM_TYPES) {
|
||||||
|
fprintf(stderr, "Filter output:%d: Can't handle geometry type %s\n", jp->line, geometry_type->string);
|
||||||
|
json_context(j);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawvec dv;
|
||||||
|
parse_geometry(t, coordinates, dv, VT_MOVETO, "Filter output", jp->line, j);
|
||||||
|
if (mb_geometry[t] == VT_POLYGON) {
|
||||||
|
dv = fix_polygon(dv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scale and offset geometry from global to tile
|
||||||
|
for (size_t i = 0; i < dv.size(); i++) {
|
||||||
|
unsigned sx = 0, sy = 0;
|
||||||
|
if (z != 0) {
|
||||||
|
sx = x << (32 - z);
|
||||||
|
sy = y << (32 - z);
|
||||||
|
}
|
||||||
|
dv[i].x -= sx;
|
||||||
|
dv[i].y -= sy;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dv.size() > 0) {
|
||||||
|
sf.t = mb_geometry[t];
|
||||||
|
sf.geometry = dv;
|
||||||
|
sf.segment = 0;
|
||||||
|
sf.layer = 0; // XXX
|
||||||
|
sf.seq = 0; // XXX
|
||||||
|
sf.index = 0; // XXX
|
||||||
|
sf.bbox[0] = sf.bbox[1] = sf.bbox[2] = sf.bbox[3] = 0; // XXX
|
||||||
|
sf.extent = 0; // XXX
|
||||||
|
sf.m = 0; // XXX
|
||||||
|
sf.metapos = 0; // XXX
|
||||||
|
sf.has_id = false;
|
||||||
|
|
||||||
|
json_object *id = json_hash_get(j, "id");
|
||||||
|
if (id != NULL) {
|
||||||
|
sf.id = atoll(id->string);
|
||||||
|
sf.has_id = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < properties->length; i++) {
|
||||||
|
serial_val v;
|
||||||
|
v.type = -1;
|
||||||
|
|
||||||
|
stringify_value(properties->values[i], v.type, v.s, "Filter output", jp->line, j);
|
||||||
|
|
||||||
|
if (v.type >= 0) {
|
||||||
|
sf.kv.insert(std::pair<std::string, serial_val>(std::string(properties->keys[i]->string), v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json_free(j);
|
||||||
|
return sf;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_free(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static pthread_mutex_t pipe_lock = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t pipe_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
void setup_filter(const char *filter, int *write_to, int *read_from, pid_t *pid, unsigned z, unsigned x, unsigned y) {
|
void setup_filter(const char *filter, int *write_to, int *read_from, pid_t *pid, unsigned z, unsigned x, unsigned y) {
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
mvt_layer filter_layer(const char *filter, mvt_layer &layer, unsigned z, unsigned x, unsigned y);
|
mvt_layer filter_layer(const char *filter, mvt_layer &layer, unsigned z, unsigned x, unsigned y);
|
||||||
void setup_filter(const char *filter, int *write_to, int *read_from, pid_t *pid, unsigned z, unsigned x, unsigned y);
|
void setup_filter(const char *filter, int *write_to, int *read_from, pid_t *pid, unsigned z, unsigned x, unsigned y);
|
||||||
|
serial_feature parse_feature(json_pull *jp, unsigned z, unsigned x, unsigned y);
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ int deserialize_ulong_long_io(FILE *f, unsigned long long *n, long long *geompos
|
|||||||
int deserialize_uint_io(FILE *f, unsigned *n, long long *geompos);
|
int deserialize_uint_io(FILE *f, unsigned *n, long long *geompos);
|
||||||
int deserialize_byte_io(FILE *f, signed char *n, long long *geompos);
|
int deserialize_byte_io(FILE *f, signed char *n, long long *geompos);
|
||||||
|
|
||||||
|
struct serial_val {
|
||||||
|
int type;
|
||||||
|
std::string s;
|
||||||
|
};
|
||||||
|
|
||||||
struct serial_feature {
|
struct serial_feature {
|
||||||
long long layer;
|
long long layer;
|
||||||
int segment;
|
int segment;
|
||||||
@@ -47,6 +52,7 @@ struct serial_feature {
|
|||||||
|
|
||||||
// XXX This isn't serialized. Should it be here?
|
// XXX This isn't serialized. Should it be here?
|
||||||
long long bbox[4];
|
long long bbox[4];
|
||||||
|
std::map<std::string, serial_val> kv;
|
||||||
};
|
};
|
||||||
|
|
||||||
void serialize_feature(FILE *geomfile, serial_feature *sf, long long *geompos, const char *fname, long long wx, long long wy, bool include_minzoom);
|
void serialize_feature(FILE *geomfile, serial_feature *sf, long long *geompos, const char *fname, long long wx, long long wy, bool include_minzoom);
|
||||||
|
|||||||
@@ -35,9 +35,14 @@
|
|||||||
#include "serial.hpp"
|
#include "serial.hpp"
|
||||||
#include "options.hpp"
|
#include "options.hpp"
|
||||||
#include "main.hpp"
|
#include "main.hpp"
|
||||||
#include "plugin.hpp"
|
|
||||||
#include "write_json.hpp"
|
#include "write_json.hpp"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "jsonpull/jsonpull.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "plugin.hpp"
|
||||||
|
|
||||||
#define CMD_BITS 3
|
#define CMD_BITS 3
|
||||||
|
|
||||||
#define XSTRINGIFY(s) STRINGIFY(s)
|
#define XSTRINGIFY(s) STRINGIFY(s)
|
||||||
@@ -1450,6 +1455,8 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
|
|||||||
FILE *prefilter_fp = NULL;
|
FILE *prefilter_fp = NULL;
|
||||||
pthread_t prefilter_writer;
|
pthread_t prefilter_writer;
|
||||||
run_prefilter_args rpa; // here so it stays in scope until joined
|
run_prefilter_args rpa; // here so it stays in scope until joined
|
||||||
|
FILE *prefilter_read_fp;
|
||||||
|
json_pull *prefilter_jp;
|
||||||
|
|
||||||
if (prefilter != NULL) {
|
if (prefilter != NULL) {
|
||||||
setup_filter(prefilter, &prefilter_write, &prefilter_read, &prefilter_pid, z, tx, ty);
|
setup_filter(prefilter, &prefilter_write, &prefilter_read, &prefilter_pid, z, tx, ty);
|
||||||
@@ -1497,6 +1504,13 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
|
|||||||
perror("pthread_create (prefilter writer)");
|
perror("pthread_create (prefilter writer)");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prefilter_read_fp = fdopen(prefilter_read, "r");
|
||||||
|
if (prefilter_read_fp == NULL) {
|
||||||
|
perror("fdopen prefilter output");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
prefilter_jp = json_begin_file(prefilter_read_fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -1505,8 +1519,7 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
|
|||||||
if (prefilter == NULL) {
|
if (prefilter == NULL) {
|
||||||
sf = next_feature(geoms, geompos_in, metabase, meta_off, z, tx, ty, initial_x, initial_y, &original_features, &unclipped_features, nextzoom, maxzoom, minzoom, max_zoom_increment, pass, passes, along, alongminus, buffer, within, &first_time, line_detail, geomfile, geompos, &oprogress, todo, fname, child_shards);
|
sf = next_feature(geoms, geompos_in, metabase, meta_off, z, tx, ty, initial_x, initial_y, &original_features, &unclipped_features, nextzoom, maxzoom, minzoom, max_zoom_increment, pass, passes, along, alongminus, buffer, within, &first_time, line_detail, geomfile, geompos, &oprogress, todo, fname, child_shards);
|
||||||
} else {
|
} else {
|
||||||
// XXX parse prefilter
|
sf = parse_feature(prefilter_jp, z, tx, ty);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sf.t < 0) {
|
if (sf.t < 0) {
|
||||||
@@ -1586,7 +1599,8 @@ long long write_tile(FILE *geoms, long long *geompos_in, char *metabase, char *s
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (prefilter != NULL) {
|
if (prefilter != NULL) {
|
||||||
if (close(prefilter_read) != 0) {
|
json_end(prefilter_jp);
|
||||||
|
if (fclose(prefilter_read_fp) != 0) {
|
||||||
perror("close output from prefilter");
|
perror("close output from prefilter");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user