commit dc95c2252ee3b5107cebf5eeee44afedac10a67e
parent 1deaea2948b0aceda639714c224c4b754c52ef38
Author: Daniel Barlow <dan@telent.net>
Date: Tue, 27 May 2025 23:48:32 +0100
convert lat/lon to tile x/y and back
Diffstat:
2 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/pkgs/maps/assert.fnl b/pkgs/maps/assert.fnl
@@ -17,8 +17,16 @@
(.. "\nexpected " ve# "\ngot " va#)
))))
+(fn expect-near [actual expected]
+ `(let [delta# (math.abs (- ,actual ,expected))
+ e# ,expected
+ a# ,actual]
+ (assert (< delta# 0.00000001)
+ (.. "expected " e# " to be approximately " a#))))
+
+
(fn define-tests [& body]
(when _G.RUNNING_TESTS
`(do ,(unpack body))))
-{ : define-tests : expect : expect= }
+{ : define-tests : expect : expect= : expect-near }
diff --git a/pkgs/maps/tiles.fnl b/pkgs/maps/tiles.fnl
@@ -2,6 +2,7 @@
(local { : dict_to_query } (require :http.util))
(local json (require :json))
+(import-macros { : define-tests : expect : expect= : expect-near } :assert)
(local { : view } (require :fennel))
@@ -33,3 +34,38 @@
(print (view headers))
(print (view (json.decode (stream:get_body_as_string))))))
+(fn sinh [x] (/ (- 1 (math.exp (* -2 x))) (* 2 (math.exp (- x)))))
+
+(expect (< (math.abs (- (sinh 2) 3.626860407847)) 0.001))
+
+(fn tile->latlon [xtile ytile zoom]
+ (let [n (^ 2 zoom)
+ lon-deg (- (/ (* xtile 360) n) 180.0)
+ lat-rad (math.atan
+ (sinh (* math.pi (- 1 (/ (* 2 ytile) n))))
+ )]
+
+ (values (/ (* lat-rad 180) math.pi) lon-deg)))
+
+(let [(lat lon) (tile->latlon 0 0 0)]
+ (expect= lon -180)
+ (expect-near lat 85.05112877)
+ )
+
+(let [(lat lon) (tile->latlon 232798 103246 18)]
+ (expect-near lon 139.699401855)
+ (expect-near lat 35.6595278648)
+ )
+
+(fn latlon->tile [lat lon zoom]
+ (let [n (^ 2 zoom)
+ x (* n (/ (+ lon 180) 360))
+ t1 (/ (* lat math.pi) 180)
+ t (math.log (+ (math.tan t1) (/ 1 (math.cos t1))))
+ y (* (- 1 (/ t math.pi)) (/ n 2))]
+ (values x y)))
+
+(let [(x y) (latlon->tile 52.1234 -0.53 17)]
+ (expect= (math.floor x) 65343)
+ (expect= (math.floor y) 43221))
+