1- "use strict" ;
2-
3- // Ice layer data model - separates ice data from SVG rendering
4- window . Ice = ( function ( ) {
5-
1+ import Alea from "alea" ;
2+ import { min } from "d3" ;
3+ import {
4+ clipPoly ,
5+ getGridPolygon ,
6+ getIsolines ,
7+ lerp ,
8+ minmax ,
9+ normalize ,
10+ P ,
11+ ra ,
12+ rand ,
13+ rn ,
14+ } from "../utils" ;
15+ import type { Point } from "./voronoi" ;
16+
17+ declare global {
18+ var Ice : IceModule ;
19+ }
20+
21+ class IceModule {
622 // Find next available id for new ice element idealy filling gaps
7- function getNextId ( ) {
23+ private getNextId ( ) {
824 if ( pack . ice . length === 0 ) return 0 ;
925 // find gaps in existing ids
10- const existingIds = pack . ice . map ( e => e . i ) . sort ( ( a , b ) => a - b ) ;
26+ const existingIds = pack . ice . map ( ( e ) => e . i ) . sort ( ( a , b ) => a - b ) ;
1127 for ( let id = 0 ; id < existingIds [ existingIds . length - 1 ] ; id ++ ) {
1228 if ( ! existingIds . includes ( id ) ) return id ;
1329 }
1430 return existingIds [ existingIds . length - 1 ] + 1 ;
1531 }
1632
33+ // Clear all ice
34+ private clear ( ) {
35+ pack . ice = [ ] ;
36+ }
37+
1738 // Generate glaciers and icebergs based on temperature and height
18- function generate ( ) {
19- clear ( ) ;
39+ public generate ( ) {
40+ this . clear ( ) ;
2041 const { cells, features } = grid ;
2142 const { temp, h } = cells ;
22- Math . random = aleaPRNG ( seed ) ;
43+ Math . random = Alea ( seed ) ;
2344
2445 const ICEBERG_MAX_TEMP = 0 ;
2546 const GLACIER_MAX_TEMP = - 8 ;
26- const minMaxTemp = d3 . min ( temp ) ;
47+ const minMaxTemp = min < number > ( temp ) ! ;
2748
2849 // Generate glaciers on cold land
2950 {
3051 const type = "iceShield" ;
31- const getType = cellId =>
52+ const getType = ( cellId : number ) =>
3253 h [ cellId ] >= 20 && temp [ cellId ] <= GLACIER_MAX_TEMP ? type : null ;
3354 const isolines = getIsolines ( grid , getType , { polygons : true } ) ;
3455
3556 if ( isolines [ type ] ?. polygons ) {
36- isolines [ type ] . polygons . forEach ( points => {
37- const clipped = clipPoly ( points ) ;
57+ isolines [ type ] . polygons . forEach ( ( points : Point [ ] ) => {
58+ const clipped = clipPoly ( points , graphWidth , graphHeight ) ;
3859 pack . ice . push ( {
39- i : getNextId ( ) ,
60+ i : this . getNextId ( ) ,
4061 points : clipped ,
41- type : "glacier"
62+ type : "glacier" ,
4263 } ) ;
4364 } ) ;
4465 }
@@ -58,62 +79,53 @@ window.Ice = (function () {
5879 const size = minmax ( rn ( baseSize * randomFactor , 2 ) , 0.1 , 1 ) ;
5980
6081 const [ cx , cy ] = grid . points [ cellId ] ;
61- const points = getGridPolygon ( cellId ) . map ( ( [ x , y ] ) => [
82+ const points = getGridPolygon ( cellId , grid ) . map ( ( [ x , y ] : Point ) => [
6283 rn ( lerp ( cx , x , size ) , 2 ) ,
63- rn ( lerp ( cy , y , size ) , 2 )
84+ rn ( lerp ( cy , y , size ) , 2 ) ,
6485 ] ) ;
6586
6687 pack . ice . push ( {
67- i : getNextId ( ) ,
88+ i : this . getNextId ( ) ,
6889 points,
6990 type : "iceberg" ,
7091 cellId,
71- size
92+ size,
7293 } ) ;
7394 }
7495 }
7596
76- function addIceberg ( cellId , size ) {
97+ addIceberg ( cellId : number , size : number ) {
7798 const [ cx , cy ] = grid . points [ cellId ] ;
78- const points = getGridPolygon ( cellId ) . map ( ( [ x , y ] ) => [
99+ const points = getGridPolygon ( cellId , grid ) . map ( ( [ x , y ] : Point ) => [
79100 rn ( lerp ( cx , x , size ) , 2 ) ,
80- rn ( lerp ( cy , y , size ) , 2 )
101+ rn ( lerp ( cy , y , size ) , 2 ) ,
81102 ] ) ;
82- const id = getNextId ( ) ;
103+ const id = this . getNextId ( ) ;
83104 pack . ice . push ( {
84105 i : id ,
85106 points,
86107 type : "iceberg" ,
87108 cellId,
88- size
109+ size,
89110 } ) ;
90111 redrawIceberg ( id ) ;
91112 }
92113
93- function removeIce ( id ) {
94- const index = pack . ice . findIndex ( element => element . i === id ) ;
114+ removeIce ( id : number ) {
115+ const index = pack . ice . findIndex ( ( element ) => element . i === id ) ;
95116 if ( index !== - 1 ) {
96- const type = pack . ice . find ( element => element . i === id ) . type ;
117+ const type = pack . ice . find ( ( element ) => element . i === id ) . type ;
97118 pack . ice . splice ( index , 1 ) ;
98119 if ( type === "glacier" ) {
99120 redrawGlacier ( id ) ;
100121 } else {
101122 redrawIceberg ( id ) ;
102123 }
103-
104124 }
105125 }
106126
107- function updateIceberg ( id , points , size ) {
108- const iceberg = pack . ice . find ( element => element . i === id ) ;
109- if ( iceberg ) {
110- iceberg . points = points ;
111- iceberg . size = size ;
112- }
113- }
114-
115- function randomizeIcebergShape ( id ) {
116- const iceberg = pack . ice . find ( element => element . i === id ) ;
127+ randomizeIcebergShape ( id : number ) {
128+ const iceberg = pack . ice . find ( ( element ) => element . i === id ) ;
117129 if ( ! iceberg ) return ;
118130
119131 const cellId = iceberg . cellId ;
@@ -123,17 +135,20 @@ window.Ice = (function () {
123135 // Get a different random cell for the polygon template
124136 const i = ra ( grid . cells . i ) ;
125137 const cn = grid . points [ i ] ;
126- const poly = getGridPolygon ( i ) . map ( p => [ p [ 0 ] - cn [ 0 ] , p [ 1 ] - cn [ 1 ] ] ) ;
127- const points = poly . map ( p => [
138+ const poly = getGridPolygon ( i , grid ) . map ( ( p : Point ) => [
139+ p [ 0 ] - cn [ 0 ] ,
140+ p [ 1 ] - cn [ 1 ] ,
141+ ] ) ;
142+ const points = poly . map ( ( p : Point ) => [
128143 rn ( cx + p [ 0 ] * size , 2 ) ,
129- rn ( cy + p [ 1 ] * size , 2 )
144+ rn ( cy + p [ 1 ] * size , 2 ) ,
130145 ] ) ;
131146
132147 iceberg . points = points ;
133148 }
134149
135- function changeIcebergSize ( id , newSize ) {
136- const iceberg = pack . ice . find ( element => element . i === id ) ;
150+ changeIcebergSize ( id : number , newSize : number ) {
151+ const iceberg = pack . ice . find ( ( element ) => element . i === id ) ;
137152 if ( ! iceberg ) return ;
138153
139154 const cellId = iceberg . cellId ;
@@ -143,28 +158,18 @@ window.Ice = (function () {
143158 const flat = iceberg . points . flat ( ) ;
144159 const pairs = [ ] ;
145160 while ( flat . length ) pairs . push ( flat . splice ( 0 , 2 ) ) ;
146- const poly = pairs . map ( p => [ ( p [ 0 ] - cx ) / oldSize , ( p [ 1 ] - cy ) / oldSize ] ) ;
147- const points = poly . map ( p => [
161+ const poly = pairs . map ( ( p ) => [
162+ ( p [ 0 ] - cx ) / oldSize ,
163+ ( p [ 1 ] - cy ) / oldSize ,
164+ ] ) ;
165+ const points = poly . map ( ( p ) => [
148166 rn ( cx + p [ 0 ] * newSize , 2 ) ,
149- rn ( cy + p [ 1 ] * newSize , 2 )
167+ rn ( cy + p [ 1 ] * newSize , 2 ) ,
150168 ] ) ;
151169
152170 iceberg . points = points ;
153171 iceberg . size = newSize ;
154172 }
173+ }
155174
156- // Clear all ice
157- function clear ( ) {
158- pack . ice = [ ] ;
159- }
160-
161- return {
162- generate,
163- addIceberg,
164- removeIce,
165- updateIceberg,
166- randomizeIcebergShape,
167- changeIcebergSize,
168- clear
169- } ;
170- } ) ( ) ;
175+ window . Ice = new IceModule ( ) ;
0 commit comments