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