Factoring out geometry parsing from feature parsing

This commit is contained in:
Erica Fischer
2024-11-21 15:44:46 -08:00
parent 72731a9fce
commit 0a4f6fe546
4 changed files with 134 additions and 124 deletions
+1 -1
View File
@@ -199,7 +199,7 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object *geom
} }
drawvec dv; drawvec dv;
parse_geometry(t, coordinates, dv, VT_MOVETO, sst->fname, sst->line, feature); parse_coordinates(t, coordinates, dv, VT_MOVETO, sst->fname, sst->line, feature);
serial_feature sf; serial_feature sf;
sf.layer = layer; sf.layer = layer;
+1 -1
View File
@@ -223,7 +223,7 @@ serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std::
} }
drawvec dv; drawvec dv;
parse_geometry(t, coordinates, dv, VT_MOVETO, "Filter output", jp->line, j); parse_coordinates(t, coordinates, dv, VT_MOVETO, "Filter output", jp->line, j);
if (mb_geometry[t] == VT_POLYGON) { if (mb_geometry[t] == VT_POLYGON) {
dv = fix_polygon(dv, false, false); dv = fix_polygon(dv, false, false);
} }
+80 -70
View File
@@ -53,7 +53,7 @@ void json_context(json_object *j) {
free(s); // stringify free(s); // stringify
} }
void parse_geometry(int t, json_object *j, drawvec &out, int op, const char *fname, int line, json_object *feature) { void parse_coordinates(int t, json_object *j, drawvec &out, int op, const char *fname, int line, json_object *feature) {
if (j == NULL || j->type != JSON_ARRAY) { if (j == NULL || j->type != JSON_ARRAY) {
fprintf(stderr, "%s:%d: expected array for geometry type %d: ", fname, line, t); fprintf(stderr, "%s:%d: expected array for geometry type %d: ", fname, line, t);
json_context(feature); json_context(feature);
@@ -72,7 +72,7 @@ void parse_geometry(int t, json_object *j, drawvec &out, int op, const char *fna
} }
} }
parse_geometry(within, j->value.array.array[i], out, op, fname, line, feature); parse_coordinates(within, j->value.array.array[i], out, op, fname, line, feature);
} }
} else { } else {
if (j->value.array.length >= 2 && j->value.array.array[0]->type == JSON_NUMBER && j->value.array.array[1]->type == JSON_NUMBER) { if (j->value.array.length >= 2 && j->value.array.array[0]->type == JSON_NUMBER && j->value.array.array[1]->type == JSON_NUMBER) {
@@ -178,52 +178,8 @@ static std::vector<mvt_geometry> to_feature(drawvec &geom) {
return out; return out;
} }
std::vector<mvt_layer> parse_layers(FILE *fp, int z, unsigned x, unsigned y, int extent, bool fix_longitudes) { std::pair<int, drawvec> parse_geometry(json_object *geometry, json_pull *jp, json_object *j,
std::map<std::string, mvt_layer> ret; int z, int x, int y, int extent, bool fix_longitudes) {
std::shared_ptr<std::string> tile_stringpool = std::make_shared<std::string>();
json_pull *jp = json_begin_file(fp);
while (1) {
json_object *j = json_read(jp);
if (j == NULL) {
if (jp->error != NULL) {
fprintf(stderr, "Filter output:%d: %s: ", jp->line, jp->error);
if (jp->root != NULL) {
json_context(jp->root);
} else {
fprintf(stderr, "\n");
}
exit(EXIT_JSON);
}
json_free(jp->root);
break;
}
json_object *type = json_hash_get(j, "type");
if (type == NULL || type->type != JSON_STRING) {
continue;
}
if (strcmp(type->value.string.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: ", jp->line);
json_context(j);
json_free(j);
exit(EXIT_JSON);
}
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: ", jp->line);
json_context(j);
json_free(j);
exit(EXIT_JSON);
}
json_object *geometry_type = json_hash_get(geometry, "type"); json_object *geometry_type = json_hash_get(geometry, "type");
if (geometry_type == NULL) { if (geometry_type == NULL) {
fprintf(stderr, "Filter output:%d: null geometry (additional not reported): ", jp->line); fprintf(stderr, "Filter output:%d: null geometry (additional not reported): ", jp->line);
@@ -239,7 +195,7 @@ std::vector<mvt_layer> parse_layers(FILE *fp, int z, unsigned x, unsigned y, int
json_object *coordinates = json_hash_get(geometry, "coordinates"); json_object *coordinates = json_hash_get(geometry, "coordinates");
if (coordinates == NULL || coordinates->type != JSON_ARRAY) { if (coordinates == NULL || coordinates->type != JSON_ARRAY) {
fprintf(stderr, "Filter output:%d: feature without coordinates array: ", jp->line); fprintf(stderr, "Filter output:%d: geometry without coordinates array: ", jp->line);
json_context(j); json_context(j);
exit(EXIT_JSON); exit(EXIT_JSON);
} }
@@ -256,28 +212,8 @@ std::vector<mvt_layer> parse_layers(FILE *fp, int z, unsigned x, unsigned y, int
exit(EXIT_JSON); exit(EXIT_JSON);
} }
std::string layername = "unknown";
json_object *tippecanoe = json_hash_get(j, "tippecanoe");
json_object *layer = NULL;
if (tippecanoe != NULL) {
layer = json_hash_get(tippecanoe, "layer");
if (layer != NULL && layer->type == JSON_STRING) {
layername = std::string(layer->value.string.string);
}
}
if (ret.count(layername) == 0) {
mvt_layer l;
l.name = layername;
l.version = 2;
l.extent = extent;
ret.insert(std::pair<std::string, mvt_layer>(layername, l));
}
auto l = ret.find(layername);
drawvec dv; drawvec dv;
parse_geometry(t, coordinates, dv, VT_MOVETO, "Filter output", jp->line, j); parse_coordinates(t, coordinates, dv, VT_MOVETO, "Filter output", jp->line, j);
// handle longitude wraparound // handle longitude wraparound
// //
@@ -359,6 +295,80 @@ std::vector<mvt_layer> parse_layers(FILE *fp, int z, unsigned x, unsigned y, int
dv = close_poly(dv); dv = close_poly(dv);
} }
return std::pair<int, drawvec>(t, dv);
}
std::vector<mvt_layer> parse_layers(FILE *fp, int z, unsigned x, unsigned y, int extent, bool fix_longitudes) {
std::map<std::string, mvt_layer> ret;
std::shared_ptr<std::string> tile_stringpool = std::make_shared<std::string>();
json_pull *jp = json_begin_file(fp);
while (1) {
json_object *j = json_read(jp);
if (j == NULL) {
if (jp->error != NULL) {
fprintf(stderr, "Filter output:%d: %s: ", jp->line, jp->error);
if (jp->root != NULL) {
json_context(jp->root);
} else {
fprintf(stderr, "\n");
}
exit(EXIT_JSON);
}
json_free(jp->root);
break;
}
json_object *type = json_hash_get(j, "type");
if (type == NULL || type->type != JSON_STRING) {
continue;
}
if (strcmp(type->value.string.string, "Feature") != 0) {
continue;
}
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: ", jp->line);
json_context(j);
json_free(j);
exit(EXIT_JSON);
}
std::string layername = "unknown";
json_object *tippecanoe = json_hash_get(j, "tippecanoe");
json_object *layer = NULL;
if (tippecanoe != NULL) {
layer = json_hash_get(tippecanoe, "layer");
if (layer != NULL && layer->type == JSON_STRING) {
layername = std::string(layer->value.string.string);
}
}
if (ret.count(layername) == 0) {
mvt_layer l;
l.name = layername;
l.version = 2;
l.extent = extent;
ret.insert(std::pair<std::string, mvt_layer>(layername, l));
}
auto l = ret.find(layername);
json_object *geometry = json_hash_get(j, "geometry");
if (geometry == NULL) {
fprintf(stderr, "Filter output:%d: filtered feature with no geometry: ", jp->line);
json_context(j);
json_free(j);
exit(EXIT_JSON);
}
std::pair<int, drawvec> parsed_geometry = parse_geometry(geometry, jp, j, z, x, y, extent, fix_longitudes);
int t = parsed_geometry.first;
drawvec &dv = parsed_geometry.second;
if (dv.size() > 0) { if (dv.size() > 0) {
mvt_feature feature; mvt_feature feature;
feature.type = mb_geometry[t]; feature.type = mb_geometry[t];
+1 -1
View File
@@ -11,7 +11,7 @@ extern int geometry_within[GEOM_TYPES];
extern int mb_geometry[GEOM_TYPES]; extern int mb_geometry[GEOM_TYPES];
void json_context(json_object *j); void json_context(json_object *j);
void parse_geometry(int t, json_object *j, drawvec &out, int op, const char *fname, int line, json_object *feature); void parse_coordinates(int t, json_object *j, drawvec &out, int op, const char *fname, int line, json_object *feature);
std::vector<mvt_layer> parse_layers(FILE *fp, int z, unsigned x, unsigned y, int extent, bool fix_longitudes); std::vector<mvt_layer> parse_layers(FILE *fp, int z, unsigned x, unsigned y, int extent, bool fix_longitudes);
serial_val stringify_value(json_object *value, const char *reading, int line, json_object *feature); serial_val stringify_value(json_object *value, const char *reading, int line, json_object *feature);