commit ff0e5fe75c20801f7aabb3209bba8f9d22127a19
parent c81b37a65ed2c5e0613ba52825b314bbf80849b0
Author: Daniel Barlow <dan@telent.net>
Date: Fri, 22 Nov 2024 23:39:30 +0000
extract TileMap and Pos modules
Diffstat:
6 files changed, 121 insertions(+), 95 deletions(-)
diff --git a/Makefile b/Makefile
@@ -3,6 +3,7 @@ default: frontend/frontend.js dist-newstyle/build/x86_64-linux/ghc-9.6.5/souples
dist-newstyle/build/x86_64-linux/ghc-9.6.5/souplesse-0.1.0.0/x/souplesse/build/souplesse/souplesse: app/*.hs lib/*.hs
cabal build
-frontend/frontend.js: frontend/src/Main.elm frontend/src/Lib.elm frontend/src/Point.elm
+FRONTEND=Main.elm Lib.elm Point.elm Pos.elm TileMap.elm
+frontend/frontend.js: $(patsubst %,frontend/src/%,$(FRONTEND))
elm-test frontend/tests/
elm make --output=$@ $<
diff --git a/frontend/src/Main.elm b/frontend/src/Main.elm
@@ -11,7 +11,8 @@ import Lib exposing(..)
import List.Extra exposing(find)
import Json.Decode as D
import Http
-import Point exposing(Point, Pos ,decoder)
+import Point exposing (Point, decoder)
+import Pos exposing (Pos)
import Svg exposing (Svg, svg, rect, g, polyline, line)
import Svg.Attributes as S exposing
( viewBox
@@ -22,6 +23,7 @@ import Svg.Attributes as S exposing
, fill
, stroke, strokeWidth, strokeOpacity)
import Time
+import TileMap exposing (..) -- (tiles, FineZoomLevel, toZoomCoord, toCoord)
import Url.Parser exposing (Parser, (<?>), int, map, s, string)
import Url.Parser.Query as Query
import Url exposing (Url)
@@ -47,73 +49,6 @@ main =
-- MATHS
--- Coordinates in a Mercator projection
-type alias Coord = { x: Float, y: Float }
-
--- zoom level
-type alias ZoomLevel = Int
-type FineZoomLevel = FineZoomLevel Int
-
-zoomStep = 8
-
-toZoom : FineZoomLevel -> ZoomLevel
-toZoom (FineZoomLevel f) = f // zoomStep
-
-
-incZoom : FineZoomLevel -> Int -> FineZoomLevel
-incZoom (FineZoomLevel z) delta =
- FineZoomLevel (clamp 0 (20 * zoomStep) (z + delta))
-
-type alias TileNumber = { x: Int, y: Int }
-
--- project lat/long to co-ordinates based on pseudocode at
--- https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Zoom_levels
-
-sec x = 1 / (cos x)
-
-toCoord : Pos -> Coord
-toCoord pos =
- let
- lat_rad = pos.lat * pi / 180
- x = (pos.lon + 180) / 360
- y = (1 - (logBase e ((tan lat_rad) + (sec lat_rad))) / pi) / 2
- in
- Coord x y
-
-pixelsToCoord z (x,y) =
- let x_float = toFloat x / toFloat ( 2 ^ (z + 8))
- y_float = toFloat y / toFloat ( 2 ^ (z + 8))
- in Coord x_float y_float
-
-reflect : Coord -> Coord
-reflect c = Coord -c.x -c.y
-
--- translate : a -> a -> a
-translate base offset =
- { base | x = (base.x + offset.x), y = (base.y + offset.y) }
-
-translatePixels : Coord -> ZoomLevel -> (Int, Int) -> Coord
-translatePixels old z (x, y) = translate old (pixelsToCoord z (x, y))
-
-
-tileCovering : Coord -> ZoomLevel -> TileNumber
-tileCovering c z =
- TileNumber (truncate (toFloat (2 ^ z) * c.x)) (truncate (toFloat (2 ^ z) * c.y))
-
-pixelFromCoord : Coord -> ZoomLevel -> (Int, Int)
-pixelFromCoord c z =
- let {x,y} = tileCovering c (z + 8)
- in (x,y)
-
-boundingTiles : Coord -> ZoomLevel -> Int -> Int -> (TileNumber, TileNumber)
-boundingTiles centre z width height =
- -- find the tiles needed to cover the area (`width` x `height`)
- -- about the point at `centre`
- let delta = pixelsToCoord z ((width // 2), (height // 2))
- minCoord = translate centre (reflect delta)
- maxCoord = translate centre delta
- in ((tileCovering minCoord z),
- (translate (tileCovering maxCoord z) (TileNumber 1 1)))
-- MODEL
@@ -314,18 +249,6 @@ timeTick duration =
Just n -> n
Nothing -> width
-tileUrl : TileNumber -> ZoomLevel -> String
-tileUrl {x,y} z =
- String.concat ["https://a.tile.openstreetmap.org",
- "/", String.fromInt z,
- "/", String.fromInt x,
- "/", String.fromInt y,
- ".png" ]
-
-tileImg zoom tilenumber = img [ width 256,
- height 256,
- src (tileUrl tilenumber zoom) ] []
-
type alias Colour = String
measureView : String -> Colour -> (Point -> Maybe Float) -> List Point -> Svg Msg
@@ -578,12 +501,6 @@ trackView leftedge topedge zoom points =
px x = String.fromInt x ++ "px"
-tiles xs ys zoom =
- List.map
- (\ y -> div []
- (List.map (\ x -> tileImg zoom (TileNumber x y)) xs))
- ys
-
ifTrack : Model -> (List Point -> Html msg) -> Html msg
ifTrack model content =
case model.track of
diff --git a/frontend/src/Point.elm b/frontend/src/Point.elm
@@ -1,12 +1,7 @@
-module Point exposing(Pos, Point, decoder, downsample, duration, subseq, startTime, centre)
+module Point exposing(Point, decoder, downsample, duration, subseq, startTime, centre)
import Json.Decode as D
-
-type alias Pos =
- { lat : Float
- , lon : Float
- , ele : Maybe Float
- }
+import Pos exposing (Pos)
type alias Point =
diff --git a/frontend/src/Pos.elm b/frontend/src/Pos.elm
@@ -0,0 +1,7 @@
+module Pos exposing (Pos)
+
+type alias Pos =
+ { lat : Float
+ , lon : Float
+ , ele : Maybe Float
+ }
diff --git a/frontend/src/TileMap.elm b/frontend/src/TileMap.elm
@@ -0,0 +1,105 @@
+module TileMap exposing (tiles
+ , FineZoomLevel(..)
+ , ZoomLevel
+ , Coord
+ , toCoord
+ , toZoom
+ , translate
+ , translatePixels
+ , incZoom
+ , boundingTiles
+ , pixelsToCoord
+ , pixelFromCoord
+ , zoomStep)
+
+import Html exposing (img, div)
+import Html.Attributes as H exposing (src, style, width, height)
+
+import Pos exposing (Pos)
+
+type alias TileNumber = { x: Int, y: Int }
+
+-- Coordinates in a Mercator projection
+type alias Coord = { x: Float, y: Float }
+
+-- zoom level
+type alias ZoomLevel = Int
+type FineZoomLevel = FineZoomLevel Int
+
+zoomStep = 8
+
+toZoom : FineZoomLevel -> ZoomLevel
+toZoom (FineZoomLevel f) = f // zoomStep
+
+
+incZoom : FineZoomLevel -> Int -> FineZoomLevel
+incZoom (FineZoomLevel z) delta =
+ FineZoomLevel (clamp 0 (20 * zoomStep) (z + delta))
+
+
+-- project lat/long to co-ordinates based on pseudocode at
+-- https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Zoom_levels
+
+sec x = 1 / (cos x)
+
+toCoord : Pos -> Coord
+toCoord pos =
+ let
+ lat_rad = pos.lat * pi / 180
+ x = (pos.lon + 180) / 360
+ y = (1 - (logBase e ((tan lat_rad) + (sec lat_rad))) / pi) / 2
+ in
+ Coord x y
+
+pixelsToCoord z (x,y) =
+ let x_float = toFloat x / toFloat ( 2 ^ (z + 8))
+ y_float = toFloat y / toFloat ( 2 ^ (z + 8))
+ in Coord x_float y_float
+
+reflect : Coord -> Coord
+reflect c = Coord -c.x -c.y
+
+-- translate : a -> a -> a
+translate base offset =
+ { base | x = (base.x + offset.x), y = (base.y + offset.y) }
+
+translatePixels : Coord -> ZoomLevel -> (Int, Int) -> Coord
+translatePixels old z (x, y) = translate old (pixelsToCoord z (x, y))
+
+
+tileCovering : Coord -> ZoomLevel -> TileNumber
+tileCovering c z =
+ TileNumber (truncate (toFloat (2 ^ z) * c.x)) (truncate (toFloat (2 ^ z) * c.y))
+
+pixelFromCoord : Coord -> ZoomLevel -> (Int, Int)
+pixelFromCoord c z =
+ let {x,y} = tileCovering c (z + 8)
+ in (x,y)
+
+boundingTiles : Coord -> ZoomLevel -> Int -> Int -> (TileNumber, TileNumber)
+boundingTiles centre z width height =
+ -- find the tiles needed to cover the area (`width` x `height`)
+ -- about the point at `centre`
+ let delta = pixelsToCoord z ((width // 2), (height // 2))
+ minCoord = translate centre (reflect delta)
+ maxCoord = translate centre delta
+ in ((tileCovering minCoord z),
+ (translate (tileCovering maxCoord z) (TileNumber 1 1)))
+
+tileUrl : TileNumber -> ZoomLevel -> String
+tileUrl {x,y} z =
+ String.concat ["https://a.tile.openstreetmap.org",
+ "/", String.fromInt z,
+ "/", String.fromInt x,
+ "/", String.fromInt y,
+ ".png" ]
+
+tileImg zoom tilenumber = img [ width 256,
+ height 256,
+ src (tileUrl tilenumber zoom) ] []
+
+tiles xs ys zoom =
+ List.map
+ (\ y -> div []
+ (List.map (\ x -> tileImg zoom (TileNumber x y)) xs))
+ ys
diff --git a/frontend/tests/PointTest.elm b/frontend/tests/PointTest.elm
@@ -1,6 +1,7 @@
module PointTest exposing (specs)
-import Point exposing (Point, Pos, downsample, subseq)
+import Point exposing (Point, downsample, subseq)
+import Pos exposing (Pos)
import Test exposing (..)
import Expect exposing (Expectation)