mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 01:41:22 +01:00
[Draft] Submap refactoring (#1153)
* refactor: submap - start * refactor: submap - continue * Merge branch 'master' of https://github.com/Azgaar/Fantasy-Map-Generator into submap-refactoring * refactor: submap - relocate burgs * refactor: submap - restore routes * refactor: submap - restore lake names * refactor: submap - UI update * refactor: submap - restore river and biome data * refactor: submap - simplify options * refactor: submap - restore rivers * refactor: submap - recalculateMapSize * refactor: submap - add middle points * refactor: submap - don't add middle points, unified findPath fn * chore: update version * feat: submap - relocate out of map regiments * feat: submap - fix route gen * feat: submap - allow custom number of cells * feat: submap - add checkbox submapRescaleBurgStyles * feat: submap - update version hash * chore: supporters update --------- Co-authored-by: Azgaar <azgaar.fmg@yandex.com>
This commit is contained in:
parent
23f36c3210
commit
66d22f26c0
18 changed files with 1043 additions and 745 deletions
|
|
@ -190,7 +190,15 @@ window.Rivers = (function () {
|
|||
const meanderedPoints = addMeandering(riverCells);
|
||||
const discharge = cells.fl[mouth]; // m3 in second
|
||||
const length = getApproximateLength(meanderedPoints);
|
||||
const width = getWidth(getOffset(discharge, meanderedPoints.length, widthFactor, 0));
|
||||
const sourceWidth = getSourceWidth(cells.fl[source]);
|
||||
const width = getWidth(
|
||||
getOffset({
|
||||
flux: discharge,
|
||||
pointIndex: meanderedPoints.length,
|
||||
widthFactor,
|
||||
sourceWidth
|
||||
})
|
||||
);
|
||||
|
||||
pack.rivers.push({
|
||||
i: riverId,
|
||||
|
|
@ -200,7 +208,7 @@ window.Rivers = (function () {
|
|||
length,
|
||||
width,
|
||||
widthFactor,
|
||||
sourceWidth: 0,
|
||||
sourceWidth,
|
||||
parent,
|
||||
cells: riverCells
|
||||
});
|
||||
|
|
@ -306,59 +314,49 @@ window.Rivers = (function () {
|
|||
|
||||
// add points at 1/3 and 2/3 of a line between adjacents river cells
|
||||
const addMeandering = function (riverCells, riverPoints = null, meandering = 0.5) {
|
||||
const {fl, conf, h} = pack.cells;
|
||||
const {fl, h} = pack.cells;
|
||||
const meandered = [];
|
||||
const lastStep = riverCells.length - 1;
|
||||
const points = getRiverPoints(riverCells, riverPoints);
|
||||
let step = h[riverCells[0]] < 20 ? 1 : 10;
|
||||
|
||||
let fluxPrev = 0;
|
||||
const getFlux = (step, flux) => (step === lastStep ? fluxPrev : flux);
|
||||
|
||||
for (let i = 0; i <= lastStep; i++, step++) {
|
||||
const cell = riverCells[i];
|
||||
const isLastCell = i === lastStep;
|
||||
|
||||
const [x1, y1] = points[i];
|
||||
const flux1 = getFlux(i, fl[cell]);
|
||||
fluxPrev = flux1;
|
||||
|
||||
meandered.push([x1, y1, flux1]);
|
||||
meandered.push([x1, y1, fl[cell]]);
|
||||
if (isLastCell) break;
|
||||
|
||||
const nextCell = riverCells[i + 1];
|
||||
const [x2, y2] = points[i + 1];
|
||||
|
||||
if (nextCell === -1) {
|
||||
meandered.push([x2, y2, fluxPrev]);
|
||||
meandered.push([x2, y2, fl[cell]]);
|
||||
break;
|
||||
}
|
||||
|
||||
const dist2 = (x2 - x1) ** 2 + (y2 - y1) ** 2; // square distance between cells
|
||||
if (dist2 <= 25 && riverCells.length >= 6) continue;
|
||||
|
||||
const flux2 = getFlux(i + 1, fl[nextCell]);
|
||||
const keepInitialFlux = conf[nextCell] || flux1 === flux2;
|
||||
|
||||
const meander = meandering + 1 / step + Math.max(meandering - step / 100, 0);
|
||||
const angle = Math.atan2(y2 - y1, x2 - x1);
|
||||
const sinMeander = Math.sin(angle) * meander;
|
||||
const cosMeander = Math.cos(angle) * meander;
|
||||
|
||||
if (step < 10 && (dist2 > 64 || (dist2 > 36 && riverCells.length < 5))) {
|
||||
if (step < 20 && (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
|
||||
const p1x = (x1 * 2 + x2) / 3 + -sinMeander;
|
||||
const p1y = (y1 * 2 + y2) / 3 + cosMeander;
|
||||
const p2x = (x1 + x2 * 2) / 3 + sinMeander / 2;
|
||||
const p2y = (y1 + y2 * 2) / 3 - cosMeander / 2;
|
||||
const [p1fl, p2fl] = keepInitialFlux ? [flux1, flux1] : [(flux1 * 2 + flux2) / 3, (flux1 + flux2 * 2) / 3];
|
||||
meandered.push([p1x, p1y, p1fl], [p2x, p2y, p2fl]);
|
||||
meandered.push([p1x, p1y, 0], [p2x, p2y, 0]);
|
||||
} else if (dist2 > 25 || riverCells.length < 6) {
|
||||
// if dist is medium or river is small add 1 extra middlepoint
|
||||
const p1x = (x1 + x2) / 2 + -sinMeander;
|
||||
const p1y = (y1 + y2) / 2 + cosMeander;
|
||||
const p1fl = keepInitialFlux ? flux1 : (flux1 + flux2) / 2;
|
||||
meandered.push([p1x, p1y, p1fl]);
|
||||
meandered.push([p1x, p1y, 0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -385,29 +383,36 @@ window.Rivers = (function () {
|
|||
};
|
||||
|
||||
const FLUX_FACTOR = 500;
|
||||
const MAX_FLUX_WIDTH = 2;
|
||||
const MAX_FLUX_WIDTH = 1;
|
||||
const LENGTH_FACTOR = 200;
|
||||
const STEP_WIDTH = 1 / LENGTH_FACTOR;
|
||||
const LENGTH_STEP_WIDTH = 1 / LENGTH_FACTOR;
|
||||
const LENGTH_PROGRESSION = [1, 1, 2, 3, 5, 8, 13, 21, 34].map(n => n / LENGTH_FACTOR);
|
||||
const MAX_PROGRESSION = last(LENGTH_PROGRESSION);
|
||||
|
||||
const getOffset = (flux, pointNumber, widthFactor, startingWidth = 0) => {
|
||||
const fluxWidth = Math.min(flux ** 0.9 / FLUX_FACTOR, MAX_FLUX_WIDTH);
|
||||
const lengthWidth = pointNumber * STEP_WIDTH + (LENGTH_PROGRESSION[pointNumber] || MAX_PROGRESSION);
|
||||
const getOffset = ({flux, pointIndex, widthFactor, startingWidth}) => {
|
||||
if (pointIndex === 0) return startingWidth;
|
||||
|
||||
const fluxWidth = Math.min(flux ** 0.7 / FLUX_FACTOR, MAX_FLUX_WIDTH);
|
||||
const lengthWidth = pointIndex * LENGTH_STEP_WIDTH + (LENGTH_PROGRESSION[pointIndex] || MAX_PROGRESSION);
|
||||
return widthFactor * (lengthWidth + fluxWidth) + startingWidth;
|
||||
};
|
||||
|
||||
const getSourceWidth = flux => rn(Math.min(flux ** 0.9 / FLUX_FACTOR, MAX_FLUX_WIDTH), 2);
|
||||
|
||||
// build polygon from a list of points and calculated offset (width)
|
||||
const getRiverPath = function (points, widthFactor, startingWidth = 0) {
|
||||
const getRiverPath = (points, widthFactor, startingWidth) => {
|
||||
lineGen.curve(d3.curveCatmullRom.alpha(0.1));
|
||||
const riverPointsLeft = [];
|
||||
const riverPointsRight = [];
|
||||
let flux = 0;
|
||||
|
||||
for (let p = 0; p < points.length; p++) {
|
||||
const [x0, y0] = points[p - 1] || points[p];
|
||||
const [x1, y1, flux] = points[p];
|
||||
const [x2, y2] = points[p + 1] || points[p];
|
||||
for (let pointIndex = 0; pointIndex < points.length; pointIndex++) {
|
||||
const [x0, y0] = points[pointIndex - 1] || points[pointIndex];
|
||||
const [x1, y1, pointFlux] = points[pointIndex];
|
||||
const [x2, y2] = points[pointIndex + 1] || points[pointIndex];
|
||||
if (pointFlux > flux) flux = pointFlux;
|
||||
|
||||
const offset = getOffset(flux, p, widthFactor, startingWidth);
|
||||
const offset = getOffset({flux, pointIndex, widthFactor, startingWidth});
|
||||
const angle = Math.atan2(y0 - y2, x0 - x2);
|
||||
const sinOffset = Math.sin(angle) * offset;
|
||||
const cosOffset = Math.cos(angle) * offset;
|
||||
|
|
@ -507,6 +512,7 @@ window.Rivers = (function () {
|
|||
getBasin,
|
||||
getWidth,
|
||||
getOffset,
|
||||
getSourceWidth,
|
||||
getApproximateLength,
|
||||
getRiverPoints,
|
||||
remove,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue