mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
riversData: use object to avoid filtering data
This commit is contained in:
parent
f932fb8906
commit
27d460ce2f
1 changed files with 39 additions and 41 deletions
|
|
@ -7,9 +7,14 @@
|
||||||
TIME && console.time("generateRivers");
|
TIME && console.time("generateRivers");
|
||||||
Math.random = aleaPRNG(seed);
|
Math.random = aleaPRNG(seed);
|
||||||
const {cells, features} = pack;
|
const {cells, features} = pack;
|
||||||
const p = cells.p;
|
|
||||||
|
|
||||||
const riversData = []; // rivers data
|
const riversData = {}; // rivers data
|
||||||
|
const riverParents = {};
|
||||||
|
const addCellToRiver = function (cell, river) {
|
||||||
|
if (!riversData[river]) riversData[river] = [cell];
|
||||||
|
else riversData[river].push(cell);
|
||||||
|
};
|
||||||
|
|
||||||
cells.fl = new Uint16Array(cells.i.length); // water flux array
|
cells.fl = new Uint16Array(cells.i.length); // water flux array
|
||||||
cells.r = new Uint16Array(cells.i.length); // rivers array
|
cells.r = new Uint16Array(cells.i.length); // rivers array
|
||||||
cells.conf = new Uint8Array(cells.i.length); // confluences array
|
cells.conf = new Uint8Array(cells.i.length); // confluences array
|
||||||
|
|
@ -49,10 +54,10 @@
|
||||||
|
|
||||||
if (sameRiver) {
|
if (sameRiver) {
|
||||||
cells.r[lakeCell] = lake.river;
|
cells.r[lakeCell] = lake.river;
|
||||||
riversData.push({river: lake.river, cell: lakeCell});
|
addCellToRiver(lakeCell, lake.river);
|
||||||
} else {
|
} else {
|
||||||
cells.r[lakeCell] = riverNext;
|
cells.r[lakeCell] = riverNext;
|
||||||
riversData.push({river: riverNext, cell: lakeCell});
|
addCellToRiver(lakeCell, riverNext);
|
||||||
riverNext++;
|
riverNext++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -62,15 +67,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign all tributary rivers to outlet basin
|
// assign all tributary rivers to outlet basin
|
||||||
for (let outlet = lakes[0]?.outlet, l = 0; l < lakes.length; l++) {
|
const outlet = lakes[0]?.outlet;
|
||||||
lakes[l].inlets?.forEach(fork => (riversData.find(r => r.river === fork).parent = outlet));
|
for (const lake of lakes) {
|
||||||
|
if (!Array.isArray(lake.inlets)) continue;
|
||||||
|
for (const inlet of lake.inlets) {
|
||||||
|
riverParents[inlet] = outlet;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// near-border cell: pour water out of the screen
|
// near-border cell: pour water out of the screen
|
||||||
if (cells.b[i] && cells.r[i]) {
|
if (cells.b[i] && cells.r[i]) return addCellToRiver(-1, cells.r[i]);
|
||||||
riversData.push({river: cells.r[i], cell: -1});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// downhill cell (make sure it's not in the source lake)
|
// downhill cell (make sure it's not in the source lake)
|
||||||
let min = null;
|
let min = null;
|
||||||
|
|
@ -95,7 +101,7 @@
|
||||||
// proclaim a new river
|
// proclaim a new river
|
||||||
if (!cells.r[i]) {
|
if (!cells.r[i]) {
|
||||||
cells.r[i] = riverNext;
|
cells.r[i] = riverNext;
|
||||||
riversData.push({river: riverNext, cell: i});
|
addCellToRiver(i, riverNext);
|
||||||
riverNext++;
|
riverNext++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,24 +111,17 @@
|
||||||
|
|
||||||
function flowDown(toCell, fromFlux, river) {
|
function flowDown(toCell, fromFlux, river) {
|
||||||
const toFlux = cells.fl[toCell] - cells.conf[toCell];
|
const toFlux = cells.fl[toCell] - cells.conf[toCell];
|
||||||
|
const toRiver = cells.r[toCell];
|
||||||
|
|
||||||
if (cells.r[toCell]) {
|
if (toRiver) {
|
||||||
// downhill cell already has river assigned
|
// downhill cell already has river assigned
|
||||||
if (fromFlux > toFlux) {
|
if (fromFlux > toFlux) {
|
||||||
cells.conf[toCell] += cells.fl[toCell]; // mark confluence
|
cells.conf[toCell] += cells.fl[toCell]; // mark confluence
|
||||||
if (h[toCell] >= 20) {
|
if (h[toCell] >= 20) riverParents[toRiver] = river; // min river is a tributary of current river
|
||||||
// min river is a tributary of current river
|
|
||||||
const toRiver = riversData.find(r => r.river === cells.r[toCell]);
|
|
||||||
if (toRiver) toRiver.parent = river;
|
|
||||||
}
|
|
||||||
cells.r[toCell] = river; // re-assign river if downhill part has less flux
|
cells.r[toCell] = river; // re-assign river if downhill part has less flux
|
||||||
} else {
|
} else {
|
||||||
cells.conf[toCell] += fromFlux; // mark confluence
|
cells.conf[toCell] += fromFlux; // mark confluence
|
||||||
if (h[toCell] >= 20) {
|
if (h[toCell] >= 20) riverParents[river] = toRiver; // current river is a tributary of min river
|
||||||
// current river is a tributary of min river
|
|
||||||
const thisRiver = riversData.find(r => r.river === river);
|
|
||||||
if (thisRiver) thisRiver.parent = cells.r[toCell];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else cells.r[toCell] = river; // assign the river to the downhill cell
|
} else cells.r[toCell] = river; // assign the river to the downhill cell
|
||||||
|
|
||||||
|
|
@ -143,7 +142,7 @@
|
||||||
cells.fl[toCell] += fromFlux;
|
cells.fl[toCell] += fromFlux;
|
||||||
}
|
}
|
||||||
|
|
||||||
riversData.push({river, cell: toCell});
|
addCellToRiver(toCell, river);
|
||||||
}
|
}
|
||||||
|
|
||||||
function defineRivers() {
|
function defineRivers() {
|
||||||
|
|
@ -153,36 +152,35 @@
|
||||||
pack.rivers = [];
|
pack.rivers = [];
|
||||||
const riverPaths = [];
|
const riverPaths = [];
|
||||||
|
|
||||||
for (let r = 1; r <= riverNext; r++) {
|
for (const key in riversData) {
|
||||||
const riverData = riversData.filter(d => d.river === r);
|
const riverCells = riversData[key];
|
||||||
if (riverData.length < 3) continue; // exclude tiny rivers
|
if (riverCells.length < 3) continue; // exclude tiny rivers
|
||||||
|
|
||||||
for (const segment of riverData) {
|
const riverId = +key;
|
||||||
const i = segment.cell;
|
for (const cell of riverCells) {
|
||||||
if (i < 0 || cells.h[i] < 20) continue;
|
if (cell < 0 || cells.h[cell] < 20) continue;
|
||||||
|
|
||||||
// mark real confluences and assign river to cells
|
// mark real confluences and assign river to cells
|
||||||
if (cells.r[i]) cells.conf[i] = 1;
|
if (cells.r[cell]) cells.conf[cell] = 1;
|
||||||
else cells.r[i] = r;
|
else cells.r[cell] = riverId;
|
||||||
}
|
}
|
||||||
|
|
||||||
const source = riverData[0].cell;
|
const source = riverCells[0];
|
||||||
const mouth = riverData[riverData.length - 2].cell;
|
const mouth = riverCells[riverCells.length - 2];
|
||||||
const parent = riverData[0].parent || 0;
|
const parent = riverParents[key] || 0;
|
||||||
|
|
||||||
const riverCells = riverData.map(point => point.cell);
|
const widthFactor = !parent || parent === riverId ? 1.2 : 1;
|
||||||
const widthFactor = !parent || parent === r ? 1.2 : 1;
|
|
||||||
const initStep = cells.h[source] >= 20 ? 1 : 10;
|
const initStep = cells.h[source] >= 20 ? 1 : 10;
|
||||||
const riverMeandered = addMeandering(riverCells, initStep, 0.5);
|
const riverMeandered = addMeandering(riverCells, initStep, 0.5);
|
||||||
const [path, length, offset] = getRiverPath(riverMeandered, widthFactor);
|
const [path, length, offset] = getRiverPath(riverMeandered, widthFactor);
|
||||||
riverPaths.push([path, r]);
|
riverPaths.push([path, riverId]);
|
||||||
|
|
||||||
// Real mounth width examples: Amazon 6000m, Volga 6000m, Dniepr 3000m, Mississippi 1300m, Themes 900m,
|
// Real mouth width examples: Amazon 6000m, Volga 6000m, Dniepr 3000m, Mississippi 1300m, Themes 900m,
|
||||||
// Danube 800m, Daugava 600m, Neva 500m, Nile 450m, Don 400m, Wisla 300m, Pripyat 150m, Bug 140m, Muchavets 40m
|
// Danube 800m, Daugava 600m, Neva 500m, Nile 450m, Don 400m, Wisla 300m, Pripyat 150m, Bug 140m, Muchavets 40m
|
||||||
const width = rn((offset / 1.4) ** 2, 2); // mounth width in km
|
const width = rn((offset / 1.4) ** 2, 2); // mouth width in km
|
||||||
const discharge = last(riverData).flux; // in m3/s
|
const discharge = cells.fl[mouth]; // in m3/s
|
||||||
|
|
||||||
pack.rivers.push({i: r, source, mouth, discharge, length, width, widthFactor, sourceWidth: 0, parent, cells: riverCells});
|
pack.rivers.push({i: riverId, source, mouth, discharge, length, width, widthFactor, sourceWidth: 0, parent, cells: riverCells});
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw rivers
|
// draw rivers
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue