make depressions resolve elevation change not that big

This commit is contained in:
Azgaar 2021-06-06 01:29:58 +03:00
parent ab065da5d2
commit 67235bc41e
8 changed files with 1765 additions and 1264 deletions

View file

@ -1,90 +1,110 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Lakes = factory());
}(this, (function () {'use strict';
typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : (global.Lakes = factory());
})(this, function () {
"use strict";
const setClimateData = function(h) {
const cells = pack.cells;
const lakeOutCells = new Uint16Array(cells.i.length);
const setClimateData = function (h) {
const cells = pack.cells;
const lakeOutCells = new Uint16Array(cells.i.length);
pack.features.forEach(f => {
if (f.type !== "lake") return;
pack.features.forEach(f => {
if (f.type !== "lake") return;
// default flux: sum of precipition around lake first cell
f.flux = rn(d3.sum(f.shoreline.map(c => grid.cells.prec[cells.g[c]])) / 2);
// temperature and evaporation to detect closed lakes
f.temp = f.cells < 6 ? grid.cells.temp[cells.g[f.firstCell]] : rn(d3.mean(f.shoreline.map(c => grid.cells.temp[cells.g[c]])), 1);
const height = (f.height - 18) ** heightExponentInput.value; // height in meters
const evaporation = (700 * (f.temp + .006 * height) / 50 + 75) / (80 - f.temp); // based on Penman formula, [1-11]
f.evaporation = rn(evaporation * f.cells);
// default flux: sum of precipition around lake first cell
f.flux = rn(d3.sum(f.shoreline.map(c => grid.cells.prec[cells.g[c]])) / 2);
// lake outlet cell
f.outCell = f.shoreline[d3.scan(f.shoreline, (a,b) => h[a] - h[b])];
lakeOutCells[f.outCell] = f.i;
});
// temperature and evaporation to detect closed lakes
f.temp = f.cells < 6 ? grid.cells.temp[cells.g[f.firstCell]] : rn(d3.mean(f.shoreline.map(c => grid.cells.temp[cells.g[c]])), 1);
const height = (f.height - 18) ** heightExponentInput.value; // height in meters
const evaporation = ((700 * (f.temp + 0.006 * height)) / 50 + 75) / (80 - f.temp); // based on Penman formula, [1-11]
f.evaporation = rn(evaporation * f.cells);
return lakeOutCells;
}
// no outlet for lakes in depressed areas
if (f.closed) return;
const cleanupLakeData = function() {
for (const feature of pack.features) {
if (feature.type !== "lake") continue;
delete feature.river;
delete feature.enteringFlux;
delete feature.shoreline;
delete feature.outCell;
feature.height = rn(feature.height);
// lake outlet cell
f.outCell = f.shoreline[d3.scan(f.shoreline, (a, b) => h[a] - h[b])];
lakeOutCells[f.outCell] = f.i;
});
const inlets = feature.inlets?.filter(r => pack.rivers.find(river => river.i === r));
if (!inlets || !inlets.length) delete feature.inlets;
else feature.inlets = inlets;
return lakeOutCells;
};
const outlet = feature.outlet && pack.rivers.find(river => river.i === feature.outlet);
if (!outlet) delete feature.outlet;
}
}
// get array of land cells aroound lake
const getShoreline = function (lake) {
const queue = [lake.firstCell];
const used = [queue[0]];
const landCellsAround = [];
while (queue.length) {
const q = queue.pop();
for (const c of pack.cells.c[q]) {
if (used[c]) continue;
used[c] = true;
if (pack.cells.f[c] === lake.i) queue.push(c);
if (pack.cells.h[c] >= 20) landCellsAround.push(c);
}
}
const defineGroup = function() {
for (const feature of pack.features) {
if (feature.type !== "lake") continue;
const lakeEl = lakes.select(`[data-f="${feature.i}"]`).node();
if (!lakeEl) continue;
lake.shoreline = landCellsAround;
};
feature.group = getGroup(feature);
document.getElementById(feature.group).appendChild(lakeEl);
}
}
const cleanupLakeData = function () {
for (const feature of pack.features) {
if (feature.type !== "lake") continue;
delete feature.river;
delete feature.enteringFlux;
delete feature.shoreline;
delete feature.outCell;
delete feature.closed;
feature.height = rn(feature.height);
const generateName = function() {
Math.random = aleaPRNG(seed);
for (const feature of pack.features) {
if (feature.type !== "lake") continue;
feature.name = getName(feature);
}
}
const inlets = feature.inlets?.filter(r => pack.rivers.find(river => river.i === r));
if (!inlets || !inlets.length) delete feature.inlets;
else feature.inlets = inlets;
const getName = function(feature) {
const landCell = pack.cells.c[feature.firstCell].find(c => pack.cells.h[c] >= 20);
const culture = pack.cells.culture[landCell];
return Names.getCulture(culture);
}
const outlet = feature.outlet && pack.rivers.find(river => river.i === feature.outlet);
if (!outlet) delete feature.outlet;
}
};
function getGroup(feature) {
if (feature.temp < -3) return "frozen";
if (feature.height > 60 && feature.cells < 10 && feature.firstCell % 5 === 0) return "lava";
const defineGroup = function () {
for (const feature of pack.features) {
if (feature.type !== "lake") continue;
const lakeEl = lakes.select(`[data-f="${feature.i}"]`).node();
if (!lakeEl) continue;
if (!feature.inlets && !feature.outlet) {
if (feature.evaporation / 2 > feature.flux) return "dry";
if (feature.cells < 3 && feature.firstCell % 5 === 0) return "sinkhole";
feature.group = getGroup(feature);
document.getElementById(feature.group).appendChild(lakeEl);
}
};
const generateName = function () {
Math.random = aleaPRNG(seed);
for (const feature of pack.features) {
if (feature.type !== "lake") continue;
feature.name = getName(feature);
}
};
const getName = function (feature) {
const landCell = pack.cells.c[feature.firstCell].find(c => pack.cells.h[c] >= 20);
const culture = pack.cells.culture[landCell];
return Names.getCulture(culture);
};
function getGroup(feature) {
if (feature.temp < -3) return "frozen";
if (feature.height > 60 && feature.cells < 10 && feature.firstCell % 5 === 0) return "lava";
if (!feature.inlets && !feature.outlet) {
if (feature.evaporation / 2 > feature.flux) return "dry";
if (feature.cells < 3 && feature.firstCell % 5 === 0) return "sinkhole";
}
if (!feature.outlet && feature.evaporation > feature.flux) return "salt";
return "freshwater";
}
if (!feature.outlet && feature.evaporation > feature.flux) return "salt";
return "freshwater";
}
return {setClimateData, cleanupLakeData, defineGroup, generateName, getName};
})));
return {setClimateData, cleanupLakeData, defineGroup, generateName, getName, getShoreline};
});