From 0de5b7c6cd40b264994910ff0c60c3f0dcb8c3bf Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sat, 21 Aug 2021 23:05:15 +0300 Subject: [PATCH] precipitation generation - minor fix --- main.js | 59 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/main.js b/main.js index b7c797b8..eb47aadd 100644 --- a/main.js +++ b/main.js @@ -957,27 +957,32 @@ function calculateTemperatures() { function generatePrecipitation() { TIME && console.time("generatePrecipitation"); prec.selectAll("*").remove(); - const cells = grid.cells; + const {cells, cellsX, cellsY} = grid; cells.prec = new Uint8Array(cells.i.length); // precipitation array const modifier = precInput.value / 100; // user's input - const cellsX = grid.cellsX, - cellsY = grid.cellsY; + const {winds} = options; + + const MAX_PASSABLE_ELEVATION = 85; + let westerly = [], easterly = [], southerly = 0, northerly = 0; - { - // latitude bands - // x4 = 0-5 latitude: wet through the year (rising zone) - // x2 = 5-20 latitude: wet summer (rising zone), dry winter (sinking zone) - // x1 = 20-30 latitude: dry all year (sinking zone) - // x2 = 30-50 latitude: wet winter (rising zone), dry summer (sinking zone) - // x3 = 50-60 latitude: wet all year (rising zone) - // x2 = 60-70 latitude: wet summer (rising zone), dry winter (sinking zone) - // x1 = 70-90 latitude: dry all year (sinking zone) - } - const lalitudeModifier = [4, 2, 2, 2, 1, 1, 2, 2, 2, 2, 3, 3, 2, 2, 1, 1, 1, 0.5]; // by 5d step + const isWest = tier => winds[tier] > 40 && winds[tier] < 140; + const isEast = tier => winds[tier] > 220 && winds[tier] < 320; + const isSouth = tier => winds[tier] > 100 && winds[tier] < 260; + const isNorth = tier => winds[tier] > 280 && winds[tier] < 80; + + // latitude bands info + // x4 = 0-5 latitude: wet through the year (rising zone) + // x2 = 5-20 latitude: wet summer (rising zone), dry winter (sinking zone) + // x1 = 20-30 latitude: dry all year (sinking zone) + // x2 = 30-50 latitude: wet winter (rising zone), dry summer (sinking zone) + // x3 = 50-60 latitude: wet all year (rising zone) + // x2 = 60-70 latitude: wet summer (rising zone), dry winter (sinking zone) + // x1 = 70-90 latitude: dry all year (sinking zone) + const lalitudeModifier = [4, 2, 2, 2, 1, 1, 2, 2, 2, 2, 3, 3, 2, 2, 1, 1, 1, 0.5]; // difine wind directions based on cells latitude and prevailing winds there d3.range(0, cells.i.length, cellsX).forEach(function (c, i) { @@ -985,15 +990,17 @@ function generatePrecipitation() { const band = ((Math.abs(lat) - 1) / 5) | 0; const latMod = lalitudeModifier[band]; const tier = (Math.abs(lat - 89) / 30) | 0; // 30d tiers from 0 to 5 from N to S - if (options.winds[tier] > 40 && options.winds[tier] < 140) westerly.push([c, latMod, tier]); - else if (options.winds[tier] > 220 && options.winds[tier] < 320) easterly.push([c + cellsX - 1, latMod, tier]); - if (options.winds[tier] > 100 && options.winds[tier] < 260) northerly++; - else if (options.winds[tier] > 280 || options.winds[tier] < 80) southerly++; + + if (isWest(tier)) westerly.push([c, latMod, tier]); + else if (isEast(tier)) easterly.push([c + cellsX - 1, latMod, tier]); + if (isSouth(tier)) northerly++; + if (isNorth(tier)) southerly++; }); // distribute winds by direction if (westerly.length) passWind(westerly, 120 * modifier, 1, cellsX); if (easterly.length) passWind(easterly, 120 * modifier, -1, cellsX); + const vertT = southerly + northerly; if (northerly) { const bandN = ((Math.abs(mapCoordinates.latN) - 1) / 5) | 0; @@ -1001,6 +1008,7 @@ function generatePrecipitation() { const maxPrecN = (northerly / vertT) * 60 * modifier * latModN; passWind(d3.range(0, cellsX, 1), maxPrecN, cellsX, cellsY); } + if (southerly) { const bandS = ((Math.abs(mapCoordinates.latS) - 1) / 5) | 0; const latModS = mapCoordinates.latT > 60 ? d3.mean(lalitudeModifier) : lalitudeModifier[bandS]; @@ -1010,18 +1018,21 @@ function generatePrecipitation() { function passWind(source, maxPrec, next, steps) { const maxPrecInit = maxPrec; + for (let first of source) { if (first[0]) { maxPrec = Math.min(maxPrecInit * first[1], 255); first = first[0]; } + let humidity = maxPrec - cells.h[first]; // initial water amount if (humidity <= 0) continue; // if first cell in row is too elevated cosdired wind dry + for (let s = 0, current = first; s < steps; s++, current += next) { - // no flux on permafrost - if (cells.temp[current] < -5) continue; - // water cell + if (cells.temp[current] < -5) continue; // no flux in permafrost + if (cells.h[current] < 20) { + // water cell if (cells.h[current + next] >= 20) { cells.prec[current + next] += Math.max(humidity / rand(10, 20), 1); // coastal precipitation } else { @@ -1032,16 +1043,16 @@ function generatePrecipitation() { } // land cell - const precipitation = getPrecipitation(humidity, current, next); + const isPassable = cells.h[current + next] <= MAX_PASSABLE_ELEVATION; + const precipitation = isPassable ? getPrecipitation(humidity, current, next) : humidity; cells.prec[current] += precipitation; const evaporation = precipitation > 1.5 ? 1 : 0; // some humidity evaporates back to the atmosphere - humidity = Math.min(Math.max(humidity - precipitation + evaporation, 0), maxPrec); + humidity = isPassable ? Math.min(Math.max(humidity - precipitation + evaporation, 0), maxPrec) : 0; } } } function getPrecipitation(humidity, i, n) { - if (cells.h[i + n] > 85) return humidity; // 85 is max passable height const normalLoss = Math.max(humidity / (10 * modifier), 1); // precipitation in normal conditions const diff = Math.max(cells.h[i + n] - cells.h[i], 0); // difference in height const mod = (cells.h[i + n] / 70) ** 2; // 50 stands for hills, 70 for mountains