ref: cfddbc180a20062d424149829cc64fbf858b0812
dir: /geojson.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <json.h> #include "dat.h" #include "fns.h" static char *Tcoords = "coordinates"; static char *Ttype = "type"; static char *Tfeature = "Feature"; static char *Tfeatures = "features"; static char *Tgeometry = "geometry"; static char *Tfeaturecollection = "FeatureCollection"; static char *Tpoint = "Point"; static char *Tlinestring = "LineString"; static char *Tpolygon = "Polygon"; extern Image *mapimage; static JSON *geojson = nil; static int jsonnum(JSON *j, double *n) { if (!(j && j->t == JSONNumber)) return 0; *n = j->n; return 1; } static int jsoncoords(JSON *j, double *x, double *y) { JSONEl *el; assert(x && y); if (j->t != JSONArray) return 0; el = j->first; if (el && el->val) { if (!jsonnum(el->val, x)) return 0; } else return 0; el = el->next; if (el && el->val) { if (!jsonnum(el->val, y)) return 0; } else return 0; return 1; } static GPos jpos; static int jzoom; static int renderjsontype(JSON*); static int renderfeaturecollection(JSON *j) { JSONEl *el; int ret; if (!(j && j->t == JSONArray)) return 0; ret = 1; for (el = j->first; el; el = el->next) ret &= renderjsontype(el->val); return ret; } static int renderpoint(JSON *j) { double x, y; int ret; if (!(j && j->t == JSONArray)) return 0; ret = jsoncoords(j, &x, &y); debugprint("POINT: %f, %f\n", x, y); return ret; } static int renderlinestring(JSON *j, JSON **l) { JSONEl *el; JSON *last = nil; double x1 = 0., y1 = 0., x2 = 0., y2 = 0.; if (!(j && j->t == JSONArray)) return 0; debugprint("LINESTRING\n"); for (el = j->first; el; el = el->next) { if (last) { x1 = x2; y1 = y2; } if (!jsoncoords(el->val, &x2, &y2)) return 0; if (!last) { last = el->val; continue; } last = el->val; debugprint("LINE: %f, %f - %f %f\n", x1, y1, x2, y2); } if (l) *l = last; return 1; } static int renderpolygon(JSON *j) { JSON *last; int ret; double x1, y1, x2, y2; if (!(j && j->t == JSONArray)) return 0; ret = renderlinestring(j, &last); if (!ret) return 0; if (!last) return 0; if (!jsoncoords(j->first->val, &x2, &y2)) return ret; if (!jsoncoords(last, &x1, &y1)) return ret; debugprint("LINE: %f, %f - %f, %f\n", x1, y1, x2, y2); return 1; } static int renderfeaturegeometry(JSON *j) { char *s; JSON *type; if (!(j && j->t == JSONObject)) return 0; type = jsonbyname(j, Ttype); if (!(type && type->t == JSONString)) return 0; s = jsonstr(type); debugprint("parsing geo %s\n", s); if (!s) return 0; if (strcmp(s, Tpoint) == 0) return renderpoint(jsonbyname(j, Tcoords)); if (strcmp(s, Tlinestring) == 0) return renderlinestring(jsonbyname(j, Tcoords), nil); if (strcmp(s, Tpolygon) == 0) return renderpolygon(jsonbyname(j, Tcoords)); return 0; } static int renderjsontype(JSON *j) { JSON *type; char *s; type = jsonbyname(j, Ttype); if (!(type && type->t == JSONString)) return 0; s = jsonstr(type); debugprint("parsing %s\n", s); if (!s) return 0; if (strcmp(s, Tfeaturecollection) == 0) return renderfeaturecollection(jsonbyname(j, Tfeatures)); if (strcmp(s, Tfeature) == 0) return renderfeaturegeometry(jsonbyname(j, Tgeometry)); return 0; } void rendergeojson(GPos pos, int zoom) { if (!geojson) return; if (geojson->t != JSONObject) { jsonfree(geojson); geojson = nil; return; } debugprint("rendering geojson\n"); jpos = pos; jzoom = zoom; if (!renderjsontype(geojson)) { jsonfree(geojson); geojson = nil; } } int handlegeojson(char *data, int ndata) { char *s; if (geojson) { jsonfree(geojson); geojson = nil; } s = mallocz(ndata + 1, 1); if (!s) sysfatal("%r"); memcpy(s, data, ndata); geojson = jsonparse(s); free(s); if (geojson) debugprint("got geojson data\n"); return !!geojson; } void cleargeojson() { jsonfree(geojson); geojson = nil; }