rotate the offscreen map

this takes us from 60% cpu to about 20% (on my laptop, your hardware
may vary) when we're travelling in a straight line, as we render the
offscreen map only when the bounds change or the target orientation
changes, not every time we move
This commit is contained in:
Daniel Barlow 2025-06-15 17:52:06 +01:00
parent 6b921e2c25
commit 173a440bd6

View File

@ -134,17 +134,23 @@ label.readout {
:x (* tile-size num-tiles-x) :x (* tile-size num-tiles-x)
:y (* tile-size num-tiles-y) :y (* tile-size num-tiles-y)
} }
:centre {
:x (/ (+ min-tile-x max-tile-x 1) 2)
:y (/ (+ min-tile-y max-tile-y 1) 2)
}
})) }))
;; diagonal radius is 538 pixels, 2.1 tiles ;; diagonal radius is 538 pixels, 2.1 tiles
(let [bounds (map-bounds-tile 65539.5 45014.5)] (let [bounds (map-bounds-tile 65539.5 45014.5)]
(expect= bounds.min {:x 65537 :y 45012}) (expect= bounds.min {:x 65537 :y 45012})
(expect= bounds.max {:x 65541 :y 45016})) (expect= bounds.max {:x 65541 :y 45016})
(expect= bounds.centre {:x 65539.5 :y 45014.5}))
(let [bounds (map-bounds-tile 65539.0 45014.0)] (let [bounds (map-bounds-tile 65539.0 45014.0)]
(expect= bounds.min {:x 65536 :y 45011}) (expect= bounds.min {:x 65536 :y 45011})
(expect= bounds.max {:x 65541 :y 45016}) (expect= bounds.max {:x 65541 :y 45016})
(expect= bounds.centre {:x 65539 :y 45014})
) )
(fn map-bounds [lat lon zoom] (fn map-bounds [lat lon zoom]
@ -217,6 +223,10 @@ label.readout {
(g:rectangle 0 0 bounds.pixels.x bounds.pixels.y) (g:rectangle 0 0 bounds.pixels.x bounds.pixels.y)
(g:fill) (g:fill)
(g:translate (+ (// bounds.pixels.x 2)) (+ (// bounds.pixels.y 2)))
(g:rotate (* (/ (- app-state.orientation-target) 180) math.pi))
(g:translate (- (// bounds.pixels.x 2)) (- (// bounds.pixels.y 2)))
(cairo-roads g lines bounds) (cairo-roads g lines bounds)
(g:set_source_rgb 0.2 0.2 0.2) (g:set_source_rgb 0.2 0.2 0.2)
@ -246,8 +256,16 @@ label.readout {
(fn on-osm-draw [widget g] (fn on-osm-draw [widget g]
(let [(tile-x tile-y) (tiles.latlon->tile app-state.lat app-state.lon app-state.zoom) (let [(tile-x tile-y) (tiles.latlon->tile app-state.lat app-state.lon app-state.zoom)
bounds (map-bounds-tile tile-x tile-y) bounds (map-bounds-tile tile-x tile-y)
offset-x (- (* tile-size (- tile-x bounds.min.x)) (/ viewport-width 2)) offset-x (/ (- viewport-width bounds.pixels.x) 2)
offset-y (- (* tile-size (- tile-y bounds.min.y)) (/ viewport-height 2))] offset-y (/ (- viewport-height bounds.pixels.y) 2)
x-to-centre (- tile-x bounds.centre.x)
y-to-centre (- tile-y bounds.centre.y)
angle (- (/ (* math.pi app-state.orientation-target) 180))
x-to-centre-rot (- (* x-to-centre (math.cos angle))
(* y-to-centre (math.sin angle)))
y-to-centre-rot (+ (* x-to-centre (math.sin angle))
(* y-to-centre (math.cos angle)))
]
(when (not map-surface) (when (not map-surface)
(let [window (widget:get_window)] (let [window (widget:get_window)]
@ -259,11 +277,16 @@ label.readout {
bounds.pixels.y) bounds.pixels.y)
(draw-onto-map-surface bounds app-state.zoom))))) (draw-onto-map-surface bounds app-state.zoom)))))
(g:translate (+ (/ viewport-width 2)) (+ (/ viewport-height 2)))
(g:rotate (* (/ (- 360 app-state.orientation-actual) 180) math.pi))
(g:translate (- (/ viewport-width 2)) (- (/ viewport-height 2)))
(g:set_source_surface map-surface (- offset-x) (- offset-y)) (when (not (= app-state.orientation-actual app-state.orientation-target))
(print (- app-state.orientation-actual app-state.orientation-target))
(g:translate (+ (/ viewport-width 2)) (+ (/ viewport-height 2)))
(g:rotate (* (/ (- 360 (- app-state.orientation-actual app-state.orientation-target)) 180) math.pi))
(g:translate (- (/ viewport-width 2)) (- (/ viewport-height 2))))
(g:set_source_surface map-surface
(- offset-x (* tile-size x-to-centre-rot))
(- offset-y (* tile-size y-to-centre-rot)))
(g:set_operator cairo.Operator.SOURCE) (g:set_operator cairo.Operator.SOURCE)
(g:paint))) (g:paint)))