shithub: map

Download patch

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