mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
allow to add river - fix
This commit is contained in:
parent
4523e90551
commit
76c787b6e9
2 changed files with 37 additions and 28 deletions
|
|
@ -245,19 +245,19 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
// add points at 1/3 and 2/3 of a line between adjacents river cells
|
// add points at 1/3 and 2/3 of a line between adjacents river cells
|
||||||
const addMeandering = function (cells, width = 1, meandering = 0.5) {
|
const addMeandering = function (riverCells, width = 1, meandering = 0.5) {
|
||||||
const meandered = [];
|
const meandered = [];
|
||||||
const {p, conf, h} = pack.cells;
|
const {p, conf} = pack.cells;
|
||||||
const lastCell = cells.length - 1;
|
const lastCell = riverCells.length - 1;
|
||||||
|
|
||||||
for (let i = 0; i <= lastCell; i++, width++) {
|
for (let i = 0; i <= lastCell; i++, width++) {
|
||||||
const cell = cells[i];
|
const cell = riverCells[i];
|
||||||
const [x1, y1] = p[cell];
|
const [x1, y1] = p[cell];
|
||||||
meandered.push([x1, y1, conf[cell]]);
|
meandered.push([x1, y1, conf[cell]]);
|
||||||
|
|
||||||
if (i === lastCell) break;
|
if (i === lastCell) break;
|
||||||
|
|
||||||
const nextCell = cells[i + 1];
|
const nextCell = riverCells[i + 1];
|
||||||
if (nextCell === -1) {
|
if (nextCell === -1) {
|
||||||
meandered.push(getBorderPoint(cell));
|
meandered.push(getBorderPoint(cell));
|
||||||
break;
|
break;
|
||||||
|
|
@ -271,14 +271,14 @@
|
||||||
const meander = meandering + 1 / width + Math.random() * Math.max(meandering - width / 100, 0);
|
const meander = meandering + 1 / width + Math.random() * Math.max(meandering - width / 100, 0);
|
||||||
const dist2 = (x2 - x1) ** 2 + (y2 - y1) ** 2; // square distance between cells
|
const dist2 = (x2 - x1) ** 2 + (y2 - y1) ** 2; // square distance between cells
|
||||||
|
|
||||||
if (width < 10 && (dist2 > 64 || (dist2 > 36 && cells.length < 5))) {
|
if (width < 10 && (dist2 > 64 || (dist2 > 36 && riverCells.length < 5))) {
|
||||||
// if dist2 is big or river is small add extra points at 1/3 and 2/3 of segment
|
// if dist2 is big or river is small add extra points at 1/3 and 2/3 of segment
|
||||||
const p1x = (x1 * 2 + x2) / 3 + -sin * meander;
|
const p1x = (x1 * 2 + x2) / 3 + -sin * meander;
|
||||||
const p1y = (y1 * 2 + y2) / 3 + cos * meander;
|
const p1y = (y1 * 2 + y2) / 3 + cos * meander;
|
||||||
const p2x = (x1 + x2 * 2) / 3 + sin * meander;
|
const p2x = (x1 + x2 * 2) / 3 + sin * meander;
|
||||||
const p2y = (y1 + y2 * 2) / 3 + cos * meander;
|
const p2y = (y1 + y2 * 2) / 3 + cos * meander;
|
||||||
meandered.push([p1x, p1y], [p2x, p2y]);
|
meandered.push([p1x, p1y], [p2x, p2y]);
|
||||||
} else if (dist2 > 25 || cells.length < 6) {
|
} else if (dist2 > 25 || riverCells.length < 6) {
|
||||||
// if dist is medium or river is small add 1 extra middlepoint
|
// if dist is medium or river is small add 1 extra middlepoint
|
||||||
const p1x = (x1 + x2) / 2 + -sin * meander;
|
const p1x = (x1 + x2) / 2 + -sin * meander;
|
||||||
const p1y = (y1 + y2) / 2 + cos * meander;
|
const p1y = (y1 + y2) / 2 + cos * meander;
|
||||||
|
|
|
||||||
|
|
@ -538,8 +538,9 @@ function addRiverOnClick() {
|
||||||
if (cells.h[i] < 20) return tip("Cannot create river in water cell", false, "error");
|
if (cells.h[i] < 20) return tip("Cannot create river in water cell", false, "error");
|
||||||
if (cells.b[i]) return;
|
if (cells.b[i]) return;
|
||||||
|
|
||||||
const riverPoints = [];
|
const riverCells = [];
|
||||||
let riverId = +getNextId("river").slice(5);
|
let riverId = +getNextId("river").slice(5);
|
||||||
|
let parent = 0;
|
||||||
|
|
||||||
const initialFlux = grid.cells.prec[cells.g[i]];
|
const initialFlux = grid.cells.prec[cells.g[i]];
|
||||||
cells.fl[i] = initialFlux;
|
cells.fl[i] = initialFlux;
|
||||||
|
|
@ -549,8 +550,7 @@ function addRiverOnClick() {
|
||||||
|
|
||||||
while (i) {
|
while (i) {
|
||||||
cells.r[i] = riverId;
|
cells.r[i] = riverId;
|
||||||
const [x, y] = cells.p[i];
|
riverCells.push(i);
|
||||||
riverPoints.push({x, y, cell: i});
|
|
||||||
|
|
||||||
const min = cells.c[i].sort((a, b) => h[a] - h[b])[0]; // downhill cell
|
const min = cells.c[i].sort((a, b) => h[a] - h[b])[0]; // downhill cell
|
||||||
if (h[i] <= h[min]) return tip(`Cell ${i} is depressed, river cannot flow further`, false, "error");
|
if (h[i] <= h[min]) return tip(`Cell ${i} is depressed, river cannot flow further`, false, "error");
|
||||||
|
|
@ -559,16 +559,23 @@ function addRiverOnClick() {
|
||||||
|
|
||||||
// pour to water body
|
// pour to water body
|
||||||
if (h[min] < 20) {
|
if (h[min] < 20) {
|
||||||
riverPoints.push({x: tx, y: ty, cell: i});
|
riverCells.push(min);
|
||||||
|
|
||||||
const feature = pack.features[cells.f[min]];
|
const feature = pack.features[cells.f[min]];
|
||||||
if (feature.type === "lake") {
|
if (feature.type === "lake") {
|
||||||
riverPoints[0].parent = feature.outlet || 0;
|
parent = feature.outlet || 0;
|
||||||
feature.inlets ? feature.inlets.push(riverId) : (feature.inlets = [riverId]);
|
feature.inlets ? feature.inlets.push(riverId) : (feature.inlets = [riverId]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pour outside of map from border cell
|
||||||
|
if (cells.b[min]) {
|
||||||
|
cells.fl[min] += cells.fl[i];
|
||||||
|
riverCells.push(-1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// continue propagation if min cell has no river
|
// continue propagation if min cell has no river
|
||||||
if (!cells.r[min]) {
|
if (!cells.r[min]) {
|
||||||
cells.fl[min] += cells.fl[i];
|
cells.fl[min] += cells.fl[i];
|
||||||
|
|
@ -578,24 +585,28 @@ function addRiverOnClick() {
|
||||||
|
|
||||||
// handle case when lowest cell already has a river
|
// handle case when lowest cell already has a river
|
||||||
const oldRiverId = cells.r[min];
|
const oldRiverId = cells.r[min];
|
||||||
const riverCells = cells.i.filter(i => cells.r[i] === oldRiverId);
|
const oldRiver = rivers.find(river => river.i === oldRiverId);
|
||||||
const riverCellsUpper = riverCells.filter(i => h[i] > h[min]);
|
const oldRiverCells = oldRiver?.cells || cells.i.filter(i => cells.r[i] === oldRiverId);
|
||||||
|
const oldRiverCellsUpper = oldRiverCells.filter(i => h[i] > h[min]);
|
||||||
|
|
||||||
// create new river as a tributary
|
// create new river as a tributary
|
||||||
if (riverPoints.length <= riverCellsUpper.length) {
|
if (riverCells.length <= oldRiverCellsUpper.length) {
|
||||||
cells.conf[min] += cells.fl[i];
|
cells.conf[min] += cells.fl[i];
|
||||||
riverPoints.push({x: tx, y: ty, cell: min});
|
riverCells.push(min);
|
||||||
riverPoints[0].parent = oldRiverId;
|
parent = oldRiverId;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// continue old river
|
// continue old river
|
||||||
document.getElementById("river" + oldRiverId)?.remove();
|
document.getElementById("river" + oldRiverId)?.remove();
|
||||||
cells.i.filter(i => cells.r[i] === riverId).forEach(i => (cells.r[i] = oldRiverId));
|
riverCells.forEach(i => (cells.r[i] = oldRiverId));
|
||||||
const oldRiver = rivers.find(river => river.i === oldRiverId);
|
oldRiverCells.forEach(cell => {
|
||||||
oldRiver?.points.forEach(([x, y, cell]) => {
|
if (h[cell] > h[min]) {
|
||||||
riverPoints.push({x, y, cell});
|
cells.r[cell] = 0;
|
||||||
cells.fl[cell] += cells.fl[i];
|
} else {
|
||||||
|
riverCells.push(cell);
|
||||||
|
cells.fl[cell] += cells.fl[i];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
riverId = oldRiverId;
|
riverId = oldRiverId;
|
||||||
|
|
||||||
|
|
@ -604,9 +615,8 @@ function addRiverOnClick() {
|
||||||
|
|
||||||
const river = rivers.find(r => r.i === riverId);
|
const river = rivers.find(r => r.i === riverId);
|
||||||
const sourceWidth = 0.1;
|
const sourceWidth = 0.1;
|
||||||
const widthFactor = river.widthFactor || rn(0.8 + Math.random() * 0.4, 1);
|
const widthFactor = river?.widthFactor || rn(0.8 + Math.random() * 0.4, 1);
|
||||||
|
|
||||||
const riverCells = riverPoints.map(point => point.cell);
|
|
||||||
const riverMeandered = Rivers.addMeandering(riverCells, sourceWidth * 10, 0.5);
|
const riverMeandered = Rivers.addMeandering(riverCells, sourceWidth * 10, 0.5);
|
||||||
const [path, length, offset] = Rivers.getPath(riverMeandered, widthFactor, sourceWidth);
|
const [path, length, offset] = Rivers.getPath(riverMeandered, widthFactor, sourceWidth);
|
||||||
viewbox
|
viewbox
|
||||||
|
|
@ -616,8 +626,8 @@ function addRiverOnClick() {
|
||||||
.attr("id", "river" + riverId);
|
.attr("id", "river" + riverId);
|
||||||
|
|
||||||
// add new river to data or change extended river attributes
|
// add new river to data or change extended river attributes
|
||||||
const source = riverPoints[0].cell;
|
const source = riverCells[0];
|
||||||
const mouth = last(riverPoints).cell;
|
const mouth = last(riverCells);
|
||||||
const discharge = cells.fl[mouth]; // in m3/s
|
const discharge = cells.fl[mouth]; // in m3/s
|
||||||
const width = rn(offset ** 2, 2); // mounth width in km
|
const width = rn(offset ** 2, 2); // mounth width in km
|
||||||
|
|
||||||
|
|
@ -626,9 +636,8 @@ function addRiverOnClick() {
|
||||||
river.length = length;
|
river.length = length;
|
||||||
river.discharge = discharge;
|
river.discharge = discharge;
|
||||||
river.width = width;
|
river.width = width;
|
||||||
river.points = points;
|
river.cells = riverCells;
|
||||||
} else {
|
} else {
|
||||||
const parent = riverPoints[0].parent || 0;
|
|
||||||
const basin = Rivers.getBasin(parent);
|
const basin = Rivers.getBasin(parent);
|
||||||
const name = Rivers.getName(mouth);
|
const name = Rivers.getName(mouth);
|
||||||
const smallLength = rivers.map(r => r.length || 0).sort((a, b) => a - b)[Math.ceil(pack.rivers.length * 0.15)];
|
const smallLength = rivers.map(r => r.length || 0).sort((a, b) => a - b)[Math.ceil(pack.rivers.length * 0.15)];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue