ref: f900d290324a70af335cfe62fec24af726851d35
parent: 7c38fba56a72242a218c259981c57b7e451ce6b3
author: sirjofri <sirjofri@sirjofri.de>
date: Sun Apr 6 11:41:14 EDT 2025
fixes polygon rendering
--- a/dat.h
+++ b/dat.h
@@ -2,8 +2,13 @@
typedef struct GBundle GBundle;
typedef struct GProvider GProvider;
typedef struct Point Point;
+typedef struct Image Image;
extern int debug;
+
+extern Image *cwhite;
+extern Image *cgreen;
+extern Image *cred;
struct GPos {
double lon;
--- a/geojson.c
+++ b/geojson.c
@@ -15,16 +15,27 @@
static char *Tlinestring = "LineString";
static char *Tpolygon = "Polygon";
+static char *Enumber = "expected number";
+static char *Earray = "expected array";
+static char *Ecoords = "expected coords";
+static char *Eobject = "expected object";
+static char *Estring = "expected string";
+
extern Image *mapimage;
extern int tilesize;
static JSON *geojson = nil;
+static GBundle jpos;
+static int renderjsontype(JSON*);
+
static int
jsonnum(JSON *j, double *n)
{
- if (!(j && j->t == JSONNumber))
+ if (!(j && j->t == JSONNumber)) {
+ werrstr(Enumber);
return 0;
+ }
*n = j->n;
return 1;
}
@@ -35,27 +46,80 @@
JSONEl *el;
assert(x && y);
- if (j->t != JSONArray)
+ if (j->t != JSONArray) {
+ werrstr(Earray);
return 0;
+ }
el = j->first;
if (el && el->val) {
if (!jsonnum(el->val, x))
return 0;
- } else
+ } else {
+ werrstr(Ecoords);
return 0;
+ }
el = el->next;
if (el && el->val) {
if (!jsonnum(el->val, y))
return 0;
- } else
+ } else {
+ werrstr(Ecoords);
return 0;
+ }
return 1;
}
-static GBundle jpos;
-static int renderjsontype(JSON*);
+static int
+coordspoint(JSON *j, Point *point)
+{
+ GPos p;
+ GBundle b;
+ Point o;
+
+ if (!jsoncoords(j, &p.lon, &p.lat))
+ return 0;
+
+ b = getbundle(p, jpos.z, &o);
+ b.x -= jpos.x;
+ b.y -= jpos.y;
+ o.x = b.x * tilesize + o.x;
+ o.y = b.y * tilesize + o.y;
+ *point = o;
+ return 1;
+}
+static int
+topointarray(JSON *j, Point **arr, int *np)
+{
+ JSONEl *el;
+ int n;
+ if (!(j && j->t == JSONArray)) {
+ werrstr(Earray);
+ return 0;
+ }
+
+ *np = 0;
+ for (el = j->first; el; el = el->next)
+ (*np)++;
+
+ if (!*np) {
+ *arr = nil;
+ return 1;
+ }
+
+ *arr = mallocz(*np * sizeof(Point), 1);
+ if (!*arr)
+ sysfatal("topointarray: %r");
+
+ n = 0;
+ for (el = j->first; el; el = el->next) {
+ if (!coordspoint(el->val, &(*arr)[n++]))
+ return 0;
+ }
+ return 1;
+}
+
static void
drawline(GPos f, GPos t)
{
@@ -93,8 +157,10 @@
JSONEl *el;
int ret;
- if (!(j && j->t == JSONArray))
+ if (!(j && j->t == JSONArray)) {
+ werrstr(Earray);
return 0;
+ }
ret = 1;
for (el = j->first; el; el = el->next)
@@ -109,8 +175,10 @@
GBundle b;
Point off;
- if (!(j && j->t == JSONArray))
+ if (!(j && j->t == JSONArray)) {
+ werrstr(Earray);
return 0;
+ }
if (!jsoncoords(j, &p.lon, &p.lat))
return 0;
@@ -135,7 +203,7 @@
}
static int
-renderlinestring(JSON *j, JSON **l)
+renderlinestring(JSON *j)
{
JSONEl *el;
JSON *last = nil;
@@ -142,8 +210,10 @@
double x1 = 0., y1 = 0., x2 = 0., y2 = 0.;
GPos f, t;
- if (!(j && j->t == JSONArray))
+ if (!(j && j->t == JSONArray)) {
+ werrstr(Earray);
return 0;
+ }
debugprint("LINESTRING\n");
for (el = j->first; el; el = el->next) {
@@ -165,9 +235,6 @@
t.lat = y2;
drawline(f, t);
}
-
- if (l)
- *l = last;
return 1;
}
@@ -174,33 +241,28 @@
static int
renderpolygon(JSON *j)
{
- JSON *last;
JSONEl *el;
- double x1, y1, x2, y2;
- GPos f, t;
+ Image *img;
+ Point *pts;
+ int np;
- if (!(j && j->t == JSONArray))
+ if (!(j && j->t == JSONArray)) {
+ werrstr(Earray);
return 0;
+ }
+ img = allocimage(display, mapimage->r, GREY1, 0, DBlack);
+ if (!img)
+ sysfatal("%r");
+
for (el = j->first; el; el = el->next) {
- if (!renderlinestring(el->val, &last))
+ if (!topointarray(el->val, &pts, &np))
return 0;
-
- if (!last)
- return 0;
-
- if (!jsoncoords(el->val->first->val, &x2, &y2))
- return 0;
- if (!jsoncoords(last, &x1, &y1))
- return 0;
-
- f.lon = x1;
- f.lat = y1;
- t.lon = x2;
- t.lat = y2;
- drawline(f, t);
+ fillpoly(img, pts, np, 1, cwhite, ZP);
+ free(pts);
+ pts = nil;
}
-
+ draw(mapimage, img->r, cgreen, img, ZP);
return 1;
}
@@ -210,22 +272,29 @@
char *s;
JSON *type;
- if (!(j && j->t == JSONObject))
+ if (!(j && j->t == JSONObject)) {
+ werrstr(Eobject);
return 0;
+ }
type = jsonbyname(j, Ttype);
- if (!(type && type->t == JSONString))
+ if (!(type && type->t == JSONString)) {
+ werrstr(Estring);
return 0;
+ }
s = jsonstr(type);
- if (!s)
+ if (!s) {
+ werrstr("empty type");
return 0;
+ }
if (strcmp(s, Tpoint) == 0)
return renderpoint(jsonbyname(j, Tcoords));
if (strcmp(s, Tlinestring) == 0)
- return renderlinestring(jsonbyname(j, Tcoords), nil);
+ return renderlinestring(jsonbyname(j, Tcoords));
if (strcmp(s, Tpolygon) == 0)
return renderpolygon(jsonbyname(j, Tcoords));
+ werrstr("invalid type: %s", s);
return 0;
}
@@ -236,16 +305,21 @@
char *s;
type = jsonbyname(j, Ttype);
- if (!(type && type->t == JSONString))
+ if (!(type && type->t == JSONString)) {
+ werrstr(Estring);
return 0;
+ }
s = jsonstr(type);
- if (!s)
+ if (!s) {
+ werrstr("empty string");
return 0;
+ }
if (strcmp(s, Tfeaturecollection) == 0)
return renderfeaturecollection(jsonbyname(j, Tfeatures));
if (strcmp(s, Tfeature) == 0)
return renderfeaturegeometry(jsonbyname(j, Tgeometry));
+ werrstr("invalid type: %s", s);
return 0;
}
@@ -265,6 +339,7 @@
jpos = pos;
if (!renderjsontype(geojson)) {
+ debugprint("invalid geojson: %r\n");
jsonfree(geojson);
geojson = nil;
}
--- a/map.c
+++ b/map.c
@@ -35,6 +35,18 @@
sysfatal("/mnt/map does not exist: %r");
}
+Image *cwhite;
+Image *cgreen;
+Image *cred;
+
+static void
+initcolors(void)
+{
+ cwhite = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, DWhite);
+ cgreen = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, DGreen);
+ cred = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, DRed);
+}
+
GPos gpsloc;
GBundle currentloc;
Point drawoffset;
@@ -436,6 +448,8 @@
if (initdraw(nil, nil, "map") < 0)
sysfatal("%r");
+
+ initcolors();
nateborders = 0;
natetracedraw = 0;
--- a/tile.c
+++ b/tile.c
@@ -63,7 +63,9 @@
ret.x = lon2tilex(pos.lon, z, &offset->x);
ret.y = lat2tiley(pos.lat, z, &offset->y);
ret.z = z;
+ /*
debugprint("bundle for %f,%f = %d, %d, %d\n",
pos.lon, pos.lat, ret.z, ret.x, ret.y);
+ */
return ret;
}
--
⑨