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;
}