id | follows |
---|---|
litvis |
data/d02Data |
@import "css/litvis.less"
This document best viewed in litvis
Peter Saville's Unknown Pleasures design. Iconic use of lines. But what to show and how would it be a map? Britain has approximately similar aspect ratio. Could show distance from coastline as this will increase towards centre.
Unknown pleasures of the seaside?
How best to calculate distance? Does not have to be accurate at this scale so could just treat boundary vertices as points. No need to calculate distances within line segments.
-
Use ukConstituencies.json, which itself was based on ONS boundary data simplified in mapshaper.
-
Create a coastline file with mapshaper by dissolving internal polygon boundaries and reprojecting to OSGB National Grid coordinates:
mapshaper ukConstituencies.json -dissolve2 name=coastline \ -proj +init=EPSG:27700 \ -o format=topojson ukCoastline.json
-
Create a coastal vertex file from
ukCoastline.json
:mapshaper ukCoastline.json -points vertices \ -o precision=0.1 format=geojson ukCoastVertices.json
-
Create a grid of 1000x90 points over entire region with mapshaper
mapshaper ukCoastline.json -point-grid 1000,90 \ -o precision=0.00001 format=geojson ukGrid.json
-
Filter grid to create a second grid of points only within land polygons:
mapshaper ukGrid.json -clip ukCoastline.json \ -o format=geojson ukLandGrid.json
-
Extract coordinates from
ukCoastVertices.json
andukLandGrid.json
and place in d02Data.md. Add missing rows to ukLandGrid.json (where no land in transact. Missing rows at the following northings: 983918, 1037568, 1050981, 1064394, 1077806, 1091219, 1104631.
Coastal vertices:
coastMap : Spec
coastMap =
let
data =
dataFromColumns []
<< dataColumn "easting" (List.map Tuple.first coastalVertices |> nums)
<< dataColumn "northing" (List.map Tuple.second coastalVertices |> nums)
enc =
encoding
<< position X [ pName "easting", pQuant ]
<< position Y [ pName "northing", pQuant ]
in
toVegaLite [ width 200, height 400, data [], enc [], circle [ maSize 4 ] ]
Each row of points along an east-west line is referenced by its northing and contains a sequence of eastings. Add a vertex at eastings of 0 and 700000 in order to use full width of line chart space.
addToStrip : ( Float, Float ) -> Dict Float (List Float) -> Dict Float (List Float)
addToStrip ( easting, northing ) dict =
if Dict.member northing dict then
Dict.update northing
(\maybeEastings ->
case maybeEastings of
Nothing ->
Just [ easting ]
Just eastings ->
Just (eastings ++ [ easting ])
)
dict
else
Dict.insert northing [ easting ] dict
strips : List ( Float, List Float )
strips =
List.foldl addToStrip Dict.empty gridPointsLand
|> Dict.toList
toPairs : ( Float, List Float ) -> List ( Float, Float )
toPairs ( y, xs ) =
[ ( 0, y ) ] ++ List.map (\x -> ( x, y )) xs ++ [ ( 700000, y ) ]
Add the distance to nearest coastal vertex to the northing of each grid point.
gridMap : Spec
gridMap =
let
cfg =
configure
<< configuration (coView [ vicoStroke Nothing ])
points =
List.concatMap toPairs strips
sqDistToCoast ( x0, y0 ) =
List.foldl (\( x1, y1 ) dMin -> min dMin ((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1))) (10 ^ 50)
pHeight ( easting, northing ) =
if easting == 0 || easting == 700000 then
northing
else
northing + sqrt (sqDistToCoast ( easting, northing ) coastalVertices)
data =
dataFromColumns []
<< dataColumn "row" (List.map Tuple.second points |> nums)
<< dataColumn "easting" (List.map Tuple.first points |> nums)
<< dataColumn "northing" (List.map pHeight points |> nums)
enc =
encoding
<< position X [ pName "easting", pQuant, pAxis [] ]
<< position Y [ pName "northing", pQuant, pAxis [] ]
<< detail [ dName "row" ]
in
toVegaLite
[ cfg []
, background "black"
, title "UNKNOWN PLEASURES OF A TRIP TO THE SEASIDE"
[ tiColor "#eee"
, tiOrient siBottom
, tiFontSize 27.9
, tiFontWeight (fwValue 400)
, tiOffset -5
]
, padding (paSize 300)
, width 700
, height 1200
, data []
, enc []
, line [ maStrokeWidth 1, maStroke "#f0f0f0" ]
]