11import Alea from "alea" ;
2- import { curveBasis , curveCatmullRom , line , mean , min , sum } from "d3" ;
2+ import { curveBasis , curveCatmullRom , line , mean , sum } from "d3" ;
33import { each , rn , round , rw } from "../utils" ;
44
55declare global {
@@ -69,16 +69,21 @@ class RiverModule {
6969 . sort ( ( a : number , b : number ) => h [ b ] - h [ a ] ) ;
7070 const lakeOutCells = Lakes . defineClimateData ( h ) ;
7171
72+ // pre-compute map from outCell to qualifying lake features
73+ const outCellToLakes = new Map < number , any [ ] > ( ) ;
74+ for ( const feature of features ) {
75+ if ( feature . type !== "lake" || ! feature . outCell ) continue ;
76+ if ( ! ( feature . flux > feature . evaporation ) ) continue ;
77+ const list = outCellToLakes . get ( feature . outCell ) ;
78+ if ( list ) list . push ( feature ) ;
79+ else outCellToLakes . set ( feature . outCell , [ feature ] ) ;
80+ }
81+
7282 for ( const i of land ) {
7383 cells . fl [ i ] += prec [ cells . g [ i ] ] / cellsNumberModifier ; // add flux from precipitation
7484
7585 // create lake outlet if lake is not in deep depression and flux > evaporation
76- const lakes = lakeOutCells [ i ]
77- ? features . filter (
78- ( feature : any ) =>
79- i === feature . outCell && feature . flux > feature . evaporation ,
80- )
81- : [ ] ;
86+ const lakes = ( lakeOutCells [ i ] && outCellToLakes . get ( i ) ) || [ ] ;
8287 for ( const lake of lakes ) {
8388 const lakeCell = cells . c [ i ] . find (
8489 ( c : number ) => h [ c ] < 20 && cells . f [ c ] === lake . i ,
@@ -121,34 +126,29 @@ class RiverModule {
121126 }
122127
123128 // downhill cell (make sure it's not in the source lake)
124- let min = null ;
129+ let minCell = - 1 ;
125130 if ( lakeOutCells [ i ] ) {
126- const filtered = cells . c [ i ] . filter (
127- ( c : number ) =>
128- ! lakes . map ( ( lake : any ) => lake . i ) . includes ( cells . f [ c ] ) ,
129- ) ;
130- min = filtered . sort ( ( a : number , b : number ) => h [ a ] - h [ b ] ) [ 0 ] ;
131+ const lakeIds = new Set ( lakes . map ( ( lake : any ) => lake . i ) ) ;
132+ let minH = Infinity ;
133+ for ( const c of cells . c [ i ] ) {
134+ if ( lakeIds . has ( cells . f [ c ] ) ) continue ;
135+ if ( h [ c ] < minH ) { minH = h [ c ] ; minCell = c ; }
136+ }
131137 } else if ( cells . haven [ i ] ) {
132- min = cells . haven [ i ] ;
138+ minCell = cells . haven [ i ] ;
133139 } else {
134- min = cells . c [ i ] . sort ( ( a : number , b : number ) => h [ a ] - h [ b ] ) [ 0 ] ;
140+ let minH = Infinity ;
141+ for ( const c of cells . c [ i ] ) {
142+ if ( h [ c ] < minH ) { minH = h [ c ] ; minCell = c ; }
143+ }
135144 }
136145
137146 // cells is depressed
138- if ( h [ i ] <= h [ min ] ) continue ;
139-
140- // debug
141- // .append("line")
142- // .attr("x1", pack.cells.p[i][0])
143- // .attr("y1", pack.cells.p[i][1])
144- // .attr("x2", pack.cells.p[min][0])
145- // .attr("y2", pack.cells.p[min][1])
146- // .attr("stroke", "#333")
147- // .attr("stroke-width", 0.2);
147+ if ( minCell < 0 || h [ i ] <= h [ minCell ] ) continue ;
148148
149149 if ( cells . fl [ i ] < MIN_FLUX_TO_FORM_RIVER ) {
150150 // flux is too small to operate as a river
151- if ( h [ min ] >= 20 ) cells . fl [ min ] += cells . fl [ i ] ;
151+ if ( h [ minCell ] >= 20 ) cells . fl [ minCell ] += cells . fl [ i ] ;
152152 continue ;
153153 }
154154
@@ -159,7 +159,7 @@ class RiverModule {
159159 riverNext ++ ;
160160 }
161161
162- flowDown ( min , cells . fl [ i ] , cells . r [ i ] ) ;
162+ flowDown ( minCell , cells . fl [ i ] , cells . r [ i ] ) ;
163163 }
164164 } ;
165165
@@ -370,28 +370,39 @@ class RiverModule {
370370 if ( iteration < checkLakeMaxIteration ) {
371371 for ( const l of lakes ) {
372372 if ( l . closed ) continue ;
373- const minHeight = min ( l . shoreline . map ( ( s : number ) => h [ s ] ) ) as number ;
373+ let minHeight = Infinity ;
374+ for ( let si = 0 ; si < l . shoreline . length ; si ++ ) {
375+ const sh = h [ l . shoreline [ si ] ] ;
376+ if ( sh < minHeight ) minHeight = sh ;
377+ }
374378 if ( minHeight >= 100 || l . height > minHeight ) continue ;
375379
376380 if ( iteration > elevateLakeMaxIteration ) {
377381 l . shoreline . forEach ( ( i : number ) => {
378382 h [ i ] = cells . h [ i ] ;
379383 } ) ;
380- l . height =
381- ( min ( l . shoreline . map ( ( s : number ) => h [ s ] ) ) as number ) - 1 ;
384+ let resetMin = Infinity ;
385+ for ( let si = 0 ; si < l . shoreline . length ; si ++ ) {
386+ const sh = h [ l . shoreline [ si ] ] ;
387+ if ( sh < resetMin ) resetMin = sh ;
388+ }
389+ l . height = resetMin - 1 ;
382390 l . closed = true ;
383391 continue ;
384392 }
385393
386394 depressions ++ ;
387- l . height = ( minHeight as number ) + 0.2 ;
395+ l . height = minHeight + 0.2 ;
388396 }
389397 }
390398
391399 for ( const i of land ) {
392- const minHeight = min (
393- cells . c [ i ] . map ( ( c : number ) => height ( c ) ) ,
394- ) as number ;
400+ const neighbors = cells . c [ i ] ;
401+ let minHeight = Infinity ;
402+ for ( let ni = 0 ; ni < neighbors . length ; ni ++ ) {
403+ const nh = height ( neighbors [ ni ] ) ;
404+ if ( nh < minHeight ) minHeight = nh ;
405+ }
395406 if ( minHeight >= 100 || h [ i ] > minHeight ) continue ;
396407
397408 depressions ++ ;
0 commit comments