widen map obunds so that rotation works

...without showing missing white bits in the corners when moving
diagonally
This commit is contained in:
Daniel Barlow 2025-06-08 19:10:11 +01:00
parent 56f070ceee
commit 53e377cabd

View File

@ -77,13 +77,32 @@ label.readout {
(fn map-bounds-tile [tile-x tile-y] (fn map-bounds-tile [tile-x tile-y]
(let [min-tile-x (math.floor (- tile-x (/ viewport-width tile-size 2))) ;; we fetch enough tiles around the current location that the screen
max-tile-x (math.floor (+ tile-x (/ viewport-width tile-size 2))) ;; can be freely rotated without needing to fetch more.
min-tile-y (math.floor (- tile-y (/ viewport-height tile-size 2)))
max-tile-y (math.floor (+ tile-y (/ viewport-height tile-size 2))) ;; 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-x (+ 1 (- max-tile-x min-tile-x))
num-tiles-y (+ 1 (- max-tile-y min-tile-y))] num-tiles-y (+ 1 (- max-tile-y min-tile-y))]
{ {
:min { :x min-tile-x :y min-tile-y } :min { :x min-tile-x :y min-tile-y }
:max { :x max-tile-x :y max-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 ;; diagonal radius is 538 pixels, 2.1 tiles
;; 800 height is 3.125 tiles
(let [bounds (map-bounds-tile 65539.5 45014.5)] (let [bounds (map-bounds-tile 65539.5 45014.5)]
;; tile 65539, 45014 is centred on screen. left of it there is space (expect= bounds.min {:x 65537 :y 45012})
;; for one tile and right of it likewise. (expect= bounds.max {:x 65541 :y 45016}))
;; 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}))
(let [bounds (map-bounds-tile 65539.0 45014.0)] (let [bounds (map-bounds-tile 65539.0 45014.0)]
;; top left corner of tile 65539, 45014 is centred on screen. (expect= bounds.min {:x 65536 :y 45011})
;; to its left there are 360 pixels, so we need two tiles (expect= bounds.max {:x 65541 :y 45016})
;; 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})
) )
(fn map-bounds [lat lon zoom] (fn map-bounds [lat lon zoom]
@ -260,8 +266,7 @@ label.readout {
(g:set_source_surface map-surface (- offset-x) (- offset-y)) (g:set_source_surface map-surface (- offset-x) (- offset-y))
(g:set_operator cairo.Operator.SOURCE) (g:set_operator cairo.Operator.SOURCE)
(g:rectangle 0 0 viewport-width viewport-height) (g:paint)))
(g:fill)))