(Arne Babenhauserheide)
2016-06-08: can calculate the cell-idx for each lat-lon combination. can calculate the cell-idx for each lat-lon combination.
diff --git a/examples/d20world.w b/examples/d20world.w
--- a/examples/d20world.w
+++ b/examples/d20world.w
@@ -19,6 +19,7 @@ define-module : examples d20world
. #:export : world neighbors d20-as-text d20-diffuse
use-modules : ice-9 format
+use-modules : srfi srfi-1
use-modules
: ice-9 popen
. #:select : open-output-pipe close-pipe
@@ -190,46 +191,89 @@ define : d20-advect world advection-dire
loop : cdr neighbors-to-advect
-define φ : * (/ 1 2) : 1+ : sqrt 5
+define d20numbers '(1 14 10 6
+ 19 18 4 8 9 16
+ 2 3 17 13 12 5
+ 11 15 7 20)
+
+define : cellidx->dienumber idx
+ list-ref d20numbers idx
+
+define : dienumber->cellidx number
+ list-index (λ(x)(= x number)) d20numbers
+
+
+define : latlonsixthslabidx latfromtop lonfrac
+ . "calculate the index in a sixth longitude slab of the icosaeder"
+ let*
+ : triangleheight : / (sqrt 3) 2
+ length-top-to-bottom-at-lon0 : + 1 (* 2 triangleheight)
+ height-deg : * 180 : / triangleheight length-top-to-bottom-at-lon0
+ side-deg : * 180 : / 1 length-top-to-bottom-at-lon0
+ ; in one sixth of the icosaeder, there are 6 reachable
+ ; fields. I am indexing them from top to bottom.
+ format #t "latfromtop: ~a, lonfrac: ~a, height-deg/3: ~a, side-deg: ~a\n" latfromtop lonfrac (/ height-deg 3) side-deg
+ cond
+ : < latfromtop : / height-deg 3
+ . 0
+ : < latfromtop : - (* 2 (/ height-deg 3)) (* lonfrac (/ height-deg 3))
+ . 0
+ : < latfromtop : * 2 : / height-deg 3
+ . 1
+ : < latfromtop : + (* 2 (/ height-deg 3)) (* lonfrac (* 2 (/ height-deg 3)))
+ . 1
+ : < latfromtop : * 4 : / height-deg 3
+ . 2
+ : < latfromtop : - (+ side-deg (* 2 (/ height-deg 3))) (* lonfrac (- (+ side-deg (* 2 (/ height-deg 3))) (* 4 (/ height-deg 3))))
+ . 2
+ : < latfromtop : + side-deg : * 2 : / height-deg 3
+ . 3
+ : < latfromtop : + (+ side-deg (* 2 (/ height-deg 3))) (* lonfrac (- (+ side-deg (* 4 (/ height-deg 3))) (+ side-deg (* 2 (/ height-deg 3)))))
+ . 3
+ : < latfromtop : - (+ side-deg (* 5 (/ height-deg 3))) (* lonfrac (- (+ side-deg (* 5 (/ height-deg 3))) (+ side-deg (* 4 (/ height-deg 3)))))
+ . 4
+ else
+ . 5
+
define : latlon2cellidx lat lon
- . "Convert a position given as latitude and longitude into the correct cell index."
- ; cell 1 (index 0) is on top, cell 20 at the bottom. The right
- ; border of cell 2 is situated at longitude 0. With that, the
- ; left corner of cell 19 is at longitude 180. Top and bottom
- ; are point-symmetric. We can cleanly divide the upper part of
- ; the icosaeder into 3 regions by longitude. Let's do that.
- let*
- : upper : > lat 0
- ; we start by switching to a symmetric longitude
- slon : if upper lon : + lon 180
- ; the sector number is defined by the uppermost triangle
- ; in it.
- sector : if (< slon 120) 4 (if (< slon 270) 3 2)
+ . "Convert a position given as latitude (-90 .. 90) and
+longitude (0 .. 360) into the correct cell index."
+ ; cell 1 (index 0) is on top, cell 20 at the bottom. The left
+ ; border of cell 2 is situated at longitude 0. We can cleanly
+ ; divide the upper part of the icosaeder into 3 regions by
+ ; longitude. Let's do that.
+ let* ; the sector number is defined by the uppermost triangle
+ : sector : if (< lon 120) 2 (if (< lon 270) 4 3)
; we start by calculating the fraction inside the sector
- lonsectorfraction : modulo slon 120
+ lonsectorfraction : modulo lon 120
; we can further subdivide the sector by longitude into two subsectors
- subsec : if (< lonsectorfraction 60) 0 1
- subseclon : if (= subsec 0) lonsectorfraction (- 120 lonsectorfraction)
- ; TODO find some more symmetry or start nontrivial geometry.
- . #t
-
-define : cellidx->dienumber idx
- let
- : numbers '(1 14 10 6
- 19 18 4 8 9 16
- 2 3 17 13 12 5
- 11 15 7 20)
- list-ref numbers (- idx 1)
+ subsector : if (< lonsectorfraction 60) 0 1
+ subseclon : if (= subsector 0) lonsectorfraction (- 120 lonsectorfraction)
+ lonfrac : / subseclon 60
+ latfromtop : - 90 lat
+ sixthslab : latlonsixthslabidx latfromtop lonfrac
+ ; for each sector and subsector, set the dienumber
+ slabsec->index '((2 . ((1 14 19 13 15 20) (1 14 16 17 11 20)))
+ (4 . ((1 6 9 3 11 20) (1 6 8 2 7 20)))
+ (3 . ((1 10 4 5 7 20) (1 10 18 12 15 20))))
+ dienumber->cellidx
+ list-ref
+ list-ref
+ assoc-ref slabsec->index sector
+ . subsector
+ . sixthslab
define : main args
. "Test the code"
- ; display : cellidx->dienumber 5
- ; newline
- ; display : latlon2cellidx 5 3
- ; newline
- ; exit 0
+ if : > 2 (length args)
+ set! args : append args '("88") ; lat
+ if : > 3 (length args)
+ set! args : append args '("45") ; lon
+ display : latlon2cellidx (string->number (first (take-right args 2))) (string->number (last args))
+ newline
+ exit 0
display : d20-as-text world
newline