mirror of
https://github.com/mapbox/tippecanoe.git
synced 2025-04-10 04:19:54 +00:00
Start trying to validate .prj files for shapefiles
This commit is contained in:
parent
27139eb295
commit
dbd89f44c3
139
projection.cpp
139
projection.cpp
@ -2,11 +2,146 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <ctype.h>
|
||||
#include "projection.hpp"
|
||||
|
||||
struct wkt {
|
||||
std::string s;
|
||||
std::vector<wkt> sublist;
|
||||
|
||||
wkt(std::string s_) {
|
||||
s = s_;
|
||||
}
|
||||
};
|
||||
|
||||
static int peekc(FILE *f) {
|
||||
int c = getc(f);
|
||||
ungetc(c, f);
|
||||
return c;
|
||||
}
|
||||
|
||||
static void parsewkt(FILE *f, std::vector<wkt> &w) {
|
||||
int c;
|
||||
|
||||
while ((c = getc(f)) != EOF) {
|
||||
if (c == ' ' || c == '\t' || c == '\n' || c == ',') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '"') {
|
||||
std::string s;
|
||||
|
||||
while ((c = getc(f)) != EOF) {
|
||||
if (c == '"' && peekc(f) == '"') {
|
||||
getc(f);
|
||||
s.push_back('"');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '"') {
|
||||
break;
|
||||
}
|
||||
|
||||
s.push_back(c);
|
||||
}
|
||||
|
||||
w.push_back(wkt(s));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isalpha(c)) {
|
||||
std::string s;
|
||||
s.push_back(tolower(c));
|
||||
|
||||
while ((c = peekc(f)) != EOF && isalpha(c)) {
|
||||
s.push_back(tolower(c));
|
||||
c = getc(f);
|
||||
}
|
||||
|
||||
w.push_back(wkt(s));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isdigit(c) || c == '.' || c == '-') {
|
||||
std::string s;
|
||||
s.push_back(c);
|
||||
|
||||
while ((c = peekc(f)) != EOF && (isdigit(c) || c == '.')) {
|
||||
s.push_back(c);
|
||||
c = getc(f);
|
||||
}
|
||||
|
||||
w.push_back(wkt(s));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == ')' || c == ']') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (c == '(' || c == '[') {
|
||||
if (w.size() == 0) {
|
||||
fprintf(stderr, "[ or ( in projection without a leading token\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
parsewkt(f, w[w.size() - 1].sublist);
|
||||
continue;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Unexpected character %c in projection\n", c);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
wkt *find(std::vector<wkt> *w, std::string s) {
|
||||
for (size_t i = 0; i < w->size(); i++) {
|
||||
if ((*w)[i].s == s) {
|
||||
return &(*w)[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void warn_wgs84(FILE *f) {
|
||||
std::vector<wkt> w;
|
||||
parsewkt(f, w);
|
||||
|
||||
wkt *geogcs = find(&w, "geogcs");
|
||||
if (geogcs == NULL) {
|
||||
fprintf(stderr, "Warning: expected geographic coordinate system for projection\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wkt *datum = find(&(geogcs->sublist), "datum");
|
||||
if (datum == NULL) {
|
||||
fprintf(stderr, "Warning: expected datum in projection\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wkt *spheroid = find(&(datum->sublist), "spheroid");
|
||||
if (spheroid == NULL || spheroid->sublist.size() == 0) {
|
||||
fprintf(stderr, "Warning: expected spheroid in projection\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (spheroid->sublist[0].s != "WGS_1984") {
|
||||
fprintf(stderr, "Warning: expected WGS_1984 spheroid in projection, not %s\n", spheroid->sublist[0].s.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void warn_epsg3857(FILE *f) {
|
||||
std::vector<wkt> w;
|
||||
parsewkt(f, w);
|
||||
}
|
||||
|
||||
struct projection projections[] = {
|
||||
{"EPSG:4326", lonlat2tile, tile2lonlat, "urn:ogc:def:crs:OGC:1.3:CRS84"},
|
||||
{"EPSG:3857", epsg3857totile, tiletoepsg3857, "urn:ogc:def:crs:EPSG::3857"},
|
||||
{"EPSG:4326", lonlat2tile, tile2lonlat, "urn:ogc:def:crs:OGC:1.3:CRS84", warn_wgs84},
|
||||
{"EPSG:3857", epsg3857totile, tiletoepsg3857, "urn:ogc:def:crs:EPSG::3857", warn_epsg3857},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef PROJECTION_HPP
|
||||
#define PROJECTION_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void lonlat2tile(double lon, double lat, int zoom, long long *x, long long *y);
|
||||
void epsg3857totile(double ix, double iy, int zoom, long long *x, long long *y);
|
||||
void tile2lonlat(long long x, long long y, int zoom, double *lon, double *lat);
|
||||
@ -14,6 +16,7 @@ struct projection {
|
||||
void (*project)(double ix, double iy, int zoom, long long *ox, long long *oy);
|
||||
void (*unproject)(long long ix, long long iy, int zoom, double *ox, double *oy);
|
||||
const char *alias;
|
||||
void (*warn)(FILE *prj);
|
||||
};
|
||||
|
||||
extern struct projection *projection;
|
||||
|
@ -198,6 +198,7 @@ drawvec decode_geometry(unsigned char *data, size_t len, int *type) {
|
||||
|
||||
void parse_shapefile(struct serialization_state *sst, std::string fname, int layer, std::string layername) {
|
||||
std::string dbfname = fname.substr(0, fname.size() - 3) + "dbf";
|
||||
std::string prjname = fname.substr(0, fname.size() - 3) + "prj";
|
||||
|
||||
FILE *shp = fopen(fname.c_str(), "rb");
|
||||
if (shp == NULL) {
|
||||
@ -209,6 +210,11 @@ void parse_shapefile(struct serialization_state *sst, std::string fname, int lay
|
||||
perror(dbfname.c_str());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
FILE *prj = fopen(prjname.c_str(), "r");
|
||||
if (prj != NULL) {
|
||||
projection->warn(prj);
|
||||
fclose(prj);
|
||||
}
|
||||
|
||||
unsigned char shpheader[100];
|
||||
if (fread(shpheader, 1, 100, shp) != 100) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user