From 53e377cabdc3856c9b5fbf851b4b0e64bc8b5dde Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Sun, 8 Jun 2025 19:10:11 +0100 Subject: [PATCH] widen map obunds so that rotation works ...without showing missing white bits in the corners when moving diagonally --- pkgs/maps/main.fnl | 55 +++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/pkgs/maps/main.fnl b/pkgs/maps/main.fnl index 32b0a5a..c1c8f66 100644 --- a/pkgs/maps/main.fnl +++ b/pkgs/maps/main.fnl @@ -77,13 +77,32 @@ label.readout { (fn map-bounds-tile [tile-x tile-y] - (let [min-tile-x (math.floor (- tile-x (/ viewport-width tile-size 2))) - max-tile-x (math.floor (+ tile-x (/ viewport-width tile-size 2))) - min-tile-y (math.floor (- tile-y (/ viewport-height tile-size 2))) - max-tile-y (math.floor (+ tile-y (/ viewport-height tile-size 2))) + ;; we fetch enough tiles around the current location that the screen + ;; can be freely rotated without needing to fetch more. + + ;; when facing north, we have e.g. + ;; 720 width is 2.8 * 256 pixel tiles + ;; 800 height is 3.125 tiles + ;; + ;; however: + ;; - when the map is rotated 90 degrees we instead have + ;; 3.125 tiles horizontally and 2.8 vertically + ;; - at e.g a 45 degree angle ... something else? + ;; + ;; the furthest points visible from the centre of the screen are the + ;; corners. So, we draw a circle about the centre which goes + ;; through those points. To ensure we have enough tiles to fill the + ;; screen at any angle, we fetch every tile that's (partly + ;; or entirely) inside that circle + + (let [radius (/ (math.sqrt (+ (^ viewport-width 2) (^ viewport-height 2))) + tile-size 2) + min-tile-x (math.floor (- tile-x radius)) + max-tile-x (math.floor (+ tile-x radius)) + min-tile-y (math.floor (- tile-y radius)) + max-tile-y (math.floor (+ tile-y radius)) num-tiles-x (+ 1 (- max-tile-x min-tile-x)) num-tiles-y (+ 1 (- max-tile-y min-tile-y))] - { :min { :x min-tile-x :y min-tile-y } :max { :x max-tile-x :y max-tile-y } @@ -95,28 +114,15 @@ label.readout { } })) -;; 720 width is 2.8 * 256 pixel tiles -;; 800 height is 3.125 tiles +;; diagonal radius is 538 pixels, 2.1 tiles (let [bounds (map-bounds-tile 65539.5 45014.5)] - ;; tile 65539, 45014 is centred on screen. left of it there is space - ;; for one tile and right of it likewise. - ;; vertical space for other tiles is (/ (- viewport-height tile-size) 256) - ;; => 2.125 tiles, shared equally to top and bottom therefore - ;; 1.0625 tiles above and 1.0625 tiles below - - (expect= bounds.min {:x 65538 :y 45012}) - (expect= bounds.max {:x 65540 :y 45016})) + (expect= bounds.min {:x 65537 :y 45012}) + (expect= bounds.max {:x 65541 :y 45016})) (let [bounds (map-bounds-tile 65539.0 45014.0)] - ;; top left corner of tile 65539, 45014 is centred on screen. - ;; to its left there are 360 pixels, so we need two tiles - ;; to its right there are 104 pixels, so one tile - ;; above there are 400 pixels: two tiles - ;; below are 144 pixels: one tile - - (expect= bounds.min {:x 65537 :y 45012}) - (expect= bounds.max {:x 65540 :y 45015}) + (expect= bounds.min {:x 65536 :y 45011}) + (expect= bounds.max {:x 65541 :y 45016}) ) (fn map-bounds [lat lon zoom] @@ -260,8 +266,7 @@ label.readout { (g:set_source_surface map-surface (- offset-x) (- offset-y)) (g:set_operator cairo.Operator.SOURCE) - (g:rectangle 0 0 viewport-width viewport-height) - (g:fill))) + (g:paint)))