shithub: map

Download patch

ref: 726126c176ac091ac28a14ae5efcded255dac71b
parent: 426d4a16d137b3a6612a336c0f1259ad5c488ad1
author: sirjofri <sirjofri@sirjofri.de>
date: Sat Mar 29 08:41:35 EDT 2025

better center handling, better position handling

--- a/fns.h
+++ b/fns.h
@@ -1,5 +1,6 @@
 GBundle getbundle(GPos pos, int zoom, Point *offset);
 GPos getlocation(void);
+void tile2gps(double *x, double *y, int z);
 
 void lockmapimage(void);
 void unlockmapimage(void);
--- a/gps.c
+++ b/gps.c
@@ -14,8 +14,8 @@
 	int n, quality;
 	char *nop;
 	
-	ret.lon = 0.;
-	ret.lat = 0.;
+	ret.lon = 180.;
+	ret.lat = 90.;
 	
 	fd = open("/mnt/gps/position", OREAD);
 	if (fd < 0) {
--- a/map.c
+++ b/map.c
@@ -34,14 +34,6 @@
 		sysfatal("/mnt/map does not exist: %r");
 }
 
-NWindow *mainwindow;
-NImage *nimage;
-
-enum {
-	Cnil,
-	Credraw,
-};
-
 GPos gpsloc;
 GBundle currentloc;
 Point drawoffset;
@@ -50,9 +42,71 @@
 
 int tilesize = 256;
 
+Point mapimagesize;
 Image *mapimage;
 QLock mapimagelock;
 
+char statusline[512];
+
+static char*
+getstatusline(void)
+{
+	char ns;
+	char we;
+	
+	ns = gpsloc.lat > 90 ? 'N' : 'S';
+	we = gpsloc.lon > 360 ? 'W' : 'E';
+	
+	snprint(statusline, sizeof statusline, "Loc: %f %c %f %c Z: %d",
+		gpsloc.lon - 180, we,
+		gpsloc.lat - 90, ns,
+		currentloc.z);
+	return statusline;
+}
+
+ulong *zoomsquared;
+
+static void
+initmapfs(void)
+{
+	int fd, n;
+	char buf[32];
+	
+	fd = open("/mnt/map/ctl", OREAD);
+	if (fd < 0)
+		sysfatal("mapfs error: open ctl: %r");
+	
+	n = read(fd, buf, sizeof(buf) - 1);
+	if (n < 0)
+		sysfatal("mapfs error: read ctl: %r");
+	close(fd);
+	buf[n] = 0;
+	
+	maxzoom = atoi(buf);
+	
+	zoomsquared = mallocz(sizeof(ulong) * (maxzoom+1), 1);
+	
+	for (int i = 0; i <= maxzoom; i++) {
+		zoomsquared[i] = 1;
+		for (int j = 0; j <= i; j++)
+			zoomsquared[i] *= 2;
+	}
+}
+
+static double
+gettiledeg(void)
+{
+	return 360 / zoomsquared[currentloc.z];
+}
+
+NWindow *mainwindow;
+NImage *nimage;
+
+enum {
+	Cnil,
+	Credraw,
+};
+
 void
 lockmapimage(void)
 {
@@ -64,6 +118,28 @@
 	qunlock(&mapimagelock);
 }
 
+static GPos
+gpsoff(void)
+{
+	GPos p;
+	Point off;
+	double x, y;
+	
+	if (gpsloc.lat > 180)
+		gpsloc.lat = 180;
+	if (gpsloc.lat < 0)
+		gpsloc.lat = 0;
+	
+	off = divpt(mapimagesize, 2);
+	x = off.x / (double)tilesize;
+	y = off.y / (double)tilesize;
+	
+	tile2gps(&x, &y, currentloc.z);
+	p.lon = gpsloc.lon - x;
+	p.lat = gpsloc.lat - y;
+	return p;
+}
+
 int debug;
 
 int shouldredraw = 0;
@@ -111,29 +187,21 @@
 	ncallcalcrect(mainwindow, screen, screen->r);
 	r.max.x = Dx(nimage->slot.r);
 	r.max.y = Dy(nimage->slot.r);
+	mapimagesize = r.max;
 	
 	mapimage = allocimage(display, r, screen->chan, 0, DWhite);
 	nimage->image = mapimage;
+	
+	debugprint("initimage: %P\n", mapimagesize);
 }
 
 void
 eresized(int new)
 {
-	Point isize;
 	if (new && getwindow(display, Refnone) < 0)
 		sysfatal("%r");
 	
-	freeimage(mapimage);
-	nimage->image = nil;
-	ncallcalcrect(mainwindow, screen, screen->r);
-	isize.x = Dx(nimage->slot.r);
-	isize.y = Dy(nimage->slot.r);
-	
-	debugprint("resized image: %P\n", isize);
-	
-	mapimage = allocimage(display, Rect(0, 0, isize.x, isize.y), screen->chan, 0, DWhite);
-	nimage->image = mapimage;
-	
+	initimage();
 	redrawmap();
 	
 	nateredraw(0);
@@ -169,14 +237,29 @@
 	currentloc.z = cz;
 	cz = currentloc.z == zoom ? Cnil : Credraw;
 	zoom = currentloc.z;
-	currentloc = getbundle(gpsloc, currentloc.z, &drawoffset);
+	currentloc = getbundle(gpsoff(), currentloc.z, &drawoffset);
 	return cz;
 }
 
+static void
+calcoffset(double m, double *x, double *y)
+{
+	double v;
+	double deg = gettiledeg();
+	if (x) *x = deg * m;
+	if (y) {
+		v = 1. - fabs(gpsloc.lat - 90) / 90.;
+		if (v < 0.1)
+			v = 0.1;
+		*y = deg * m * v;
+	}
+}
+
 static int
 handlekeyboard(int kbdc)
 {
-	double off = 100./(currentloc.z <= 0 ? 1 : currentloc.z*tilesize);
+	double v;
+	double off = 0.5;
 	
 	switch (kbdc) {
 	case Kdel:
@@ -187,22 +270,26 @@
 	case ',':
 		return inczoom(-1);
 	case Kleft:
-		gpsloc.lon -= off;
+		calcoffset(off, &v, nil);
+		gpsloc.lon -= v;
 		goto Loc;
 	case Kright:
-		gpsloc.lon += off;
+		calcoffset(off, &v, nil);
+		gpsloc.lon += v;
 		goto Loc;
 	case Kup:
-		gpsloc.lat += off;
+		calcoffset(off, nil, &v);
+		gpsloc.lat += v;
 		goto Loc;
 	case Kdown:
-		gpsloc.lat -= off;
+		calcoffset(off, nil, &v);
+		gpsloc.lat -= v;
 		goto Loc;
 	}
 	return Cnil;
 
 Loc:
-	currentloc = getbundle(gpsloc, currentloc.z, &drawoffset);
+	currentloc = getbundle(gpsoff(), currentloc.z, &drawoffset);
 	return Credraw;
 }
 
@@ -219,25 +306,6 @@
 	}
 }
 
-static void
-initmapfs(void)
-{
-	int fd, n;
-	char buf[32];
-	
-	fd = open("/mnt/map/ctl", OREAD);
-	if (fd < 0)
-		sysfatal("mapfs error: open ctl: %r");
-	
-	n = read(fd, buf, sizeof(buf) - 1);
-	if (n < 0)
-		sysfatal("mapfs error: read ctl: %r");
-	close(fd);
-	buf[n] = 0;
-	
-	maxzoom = atoi(buf);
-}
-
 void
 main(int argc, char **argv)
 {
@@ -257,13 +325,12 @@
 
 	initmapfs();
 	gpsloc = getlocation();
-	currentloc = getbundle(gpsloc, zoom, &drawoffset);
 	
 	if (initdraw(nil, nil, "map") < 0)
 		sysfatal("%r");
 	
 	nateborders = 0;
-	natetracedraw = debug;
+	natetracedraw = 0;
 	if (debug)
 		natedebugfd = 2;
 	
@@ -303,7 +370,7 @@
 			->Padding(NMargin2(5, 5))
 			->Slot(NSlot(),
 				New_Label(nil)
-				->Label("Status Line")
+				->LabelFunc(getstatusline)
 				->Align(LEFT)
 			)
 		)
@@ -310,6 +377,7 @@
 	);
 	
 	initimage();
+	currentloc = getbundle(gpsoff(), zoom, &drawoffset);
 	redrawmap();
 	
 	for (;;) {
--- a/tile.c
+++ b/tile.c
@@ -30,15 +30,22 @@
 	return t;
 }
 
-double tilex2long(int x, int z)
+double tilex2lon(double x, int z)
 {
 	return x / (double)(1<<z) * 360.0 - 180.0;
 }
 
-double tiley2lat(int y, int z)
+double tiley2lat(double y, int z)
 {
 	double n = PI - 2.0 * PI * y / (double)(1<<z);
 	return 180.0 / PI * atan(0.5 * (exp(n) - exp(-n)));
+}
+
+void
+tile2gps(double *x, double *y, int z)
+{
+	if (x) *x = tilex2lon(*x, z);
+	if (y) *y = tiley2lat(*y, z);
 }
 
 GBundle