diff --git a/modules/river-generator.js b/modules/river-generator.js index 6b7ca97b..852f315a 100644 --- a/modules/river-generator.js +++ b/modules/river-generator.js @@ -37,47 +37,68 @@ const land = cells.i.filter(i => h[i] >= 20).sort((a,b) => h[b] - h[a]); const lakes = features.filter(f => f.type === "lake" && f.group === "freshwater"); const lakeHeights = lakes.map(l => l.height).sort((a,b) => b - a); + const used = [0]; + + const flowDown = function(min, iFlux, ri, wetCB = (iFlux, ri, nx, ny) => {}){ + if (cells.r[min]) { // downhill cell already has river assigned + if (cells.fl[min] < iFlux) { + cells.conf[min] = cells.fl[min]; // mark confluence + if (h[min] >= 20) riversData.find(r => r.river === cells.r[min]).parent = ri; // min river is a tributary of current river + cells.r[min] = ri; // re-assign river if downhill part has less flux + } else { + cells.conf[min] += iFlux; // mark confluence + if (h[min] >= 20) riversData.find(r => r.river === ri).parent = cells.r[min]; // current river is a tributary of min river + } + } else cells.r[min] = ri; // assign the river to the downhill cell + + const nx = p[min][0], ny = p[min][1]; + if (h[min] < 20) { + wetCB(iFlux, ri, nx, ny); + } else { + cells.fl[min] += iFlux; // propagate flux + riversData.push({river: ri, cell: min, x: nx, y: ny}); // add next River segment + } + }; + land.forEach(function(i) { while (lakeHeights && h[i] <= lakeHeights[0]){ // drain lakes first const lh = lakeHeights.shift(); const l = lakes.find(lk => lk.height === lh); - let min = 0; + let outlet = 0; if (l.shoreline) { - min = l.shoreline[d3.scan(l.shoreline, (a,b) => h[a] - h[b])]; + outlet = l.shoreline[d3.scan(l.shoreline, (a,b) => h[a] - h[b])]; } else { WARN && console.warn('Re-scanning shoreline of a lake'); - const shallows = cells.i.filter(i => cells.t[i] === -1 && cells.f[i] === l.i); + const shallows = cells.i.filter(j => cells.t[j] === -1 && cells.f[j] === l.i); let shoreline = l.firstCell - 1; shallows.map(w => cells.c[w]).forEach(cList => shoreline += cList); - min = shoreline[d3.scan(shoreline, (a,b) => h[a] - h[b])]; + outlet = shoreline[d3.scan(shoreline, (a,b) => h[a] - h[b])]; } - min = min ? min : l.firstCell - 1; // existance guarentee + outlet = outlet ? outlet : l.firstCell - 1; // existance guarentee let ri = l.river - const i = cells.haven[min]; - if (l.totalFlux > l.flux * 2) { - ri = riverNext; - riverNext++; + if(l.cells > 1) { + const j = cells.haven[outlet]; + // if (features[cells.f[i]].totalFlux > l.flux * 2) { + ri = ++riverNext; + // } else { + //TODO String the river along to the exit + // } + // assign river to come out of the lake + cells.r[j] = ri; + riversData.push({river: ri, cell: j, x: p[j][0], y: p[j][1]}); } - // assign river to come out of the lake - cells.r[i] = ri; - riversData.push({river: ri, cell: i, x: p[i][0], y: p[i][1]}); + flowDown(outlet, features[l.i].totalFlux, ri); + // two segments, so it doesn't return-stub + // lowest land neighbour + let next = cells.c[outlet].filter(c => h[c] >= 20).sort((a,b) => h[a] - h[b])[0]; + flowDown(next, cells.fl[outlet], cells.r[outlet]); + used.push(outlet); // is already done - if (cells.r[min]) { // outlet cell already has river assigned - if (cells.fl[min] < l.totalFlux) { - cells.conf[min] = cells.fl[min]; // mark confluence - if (h[min] >= 20) riversData.find(r => r.river === cells.r[min]).parent = ri; // min river is a tributary of current river - cells.r[min] = ri; // re-assign river if downhill part has less flux - } else { - cells.conf[min] += l.totalFlux; // mark confluence - if (h[min] >= 20) riversData.find(r => r.river === ri).parent = cells.r[min]; // current river is a tributary of min river - } - } else cells.r[min] = ri; // assign the river to the downhill cell - cells.fl[min] += l.totalFlux; - riversData.push({river: ri, cell: min, x: p[min][0], y: p[min][1]}); - - lakes.forEach(l => delete l.shoreline); // cleanup temp passed data + delete l.shoreline; // cleanup temp passed data } + if (used.includes(i)) { return; } + cells.fl[i] += grid.cells.prec[cells.g[i]]; // flux from precipitation const x = p[i][0], y = p[i][1]; @@ -98,12 +119,6 @@ //const min = cells.c[i][d3.scan(cells.c[i], (a, b) => h[a] - h[b])]; // downhill cell let min = cells.c[i][d3.scan(cells.c[i], (a, b) => h[a] - h[b])]; // downhill cell - // allow only one river can flow through a lake - // const cf = features[cells.f[i]]; // current cell feature - // if (cf.river && cf.river !== cells.r[i]) { - // cells.fl[i] = 0; - // } - if (cells.fl[i] < 30) { if (h[min] >= 20) cells.fl[min] += cells.fl[i]; return; // flux is too small to operate as river @@ -116,33 +131,18 @@ riverNext++; } - if (cells.r[min]) { // downhill cell already has river assigned - if (cells.fl[min] < cells.fl[i]) { - cells.conf[min] = cells.fl[min]; // mark confluence - if (h[min] >= 20) riversData.find(r => r.river === cells.r[min]).parent = cells.r[i]; // min river is a tributary of current river - cells.r[min] = cells.r[i]; // re-assign river if downhill part has less flux - } else { - cells.conf[min] += cells.fl[i]; // mark confluence - if (h[min] >= 20) riversData.find(r => r.river === cells.r[i]).parent = cells.r[min]; // current river is a tributary of min river - } - } else cells.r[min] = cells.r[i]; // assign the river to the downhill cell - - const nx = p[min][0], ny = p[min][1]; - if (h[min] < 20) { + flowDown(min, cells.fl[i], cells.r[i], (iFlux, ri, nx, ny) => { // pour water to the sea haven - riversData.push({river: cells.r[i], cell: cells.haven[i], x: nx, y: ny}); + riversData.push({river: ri, cell: cells.haven[i], x: nx, y: ny}); const mf = features[cells.f[min]]; // feature of min cell if (mf.type === "lake") { - if (!mf.river || cells.fl[i] > mf.flux) { - mf.river = cells.r[i]; // pour water to temporaly elevated lake - mf.flux = cells.fl[i]; // entering flux + if (!mf.river || iFlux > mf.flux) { + mf.river = ri; // pour water to temporaly elevated lake + mf.flux = iFlux; // entering flux } - mf.totalFlux += cells.fl[i]; + mf.totalFlux += iFlux; } - } else { - cells.fl[min] += cells.fl[i]; // propagate flux - riversData.push({river: cells.r[i], cell: min, x: nx, y: ny}); // add next River segment - } + }); }); }()