refactor: markupPackFeatures

This commit is contained in:
Azgaar 2022-07-14 01:38:45 +03:00
parent 87d8c1024d
commit f82fcbae0f
8 changed files with 271 additions and 178 deletions

View file

@ -3,10 +3,9 @@ import * as d3 from "d3";
import {ERROR, INFO, WARN} from "config/logging";
import {closeDialogs} from "dialogs/utils";
import {openDialog} from "dialogs";
import {initLayers, renderLayer, restoreLayers} from "layers";
import {initLayers, restoreLayers} from "layers";
// @ts-expect-error js module
import {drawCoastline} from "modules/coastline";
import {reMarkFeatures} from "modules/markup";
// @ts-expect-error js module
import {drawScaleBar, Rulers} from "modules/measurers";
// @ts-expect-error js module
@ -26,26 +25,12 @@ import {debounce} from "utils/functionUtils";
import {rn} from "utils/numberUtils";
import {generateSeed} from "utils/probabilityUtils";
import {byId} from "utils/shorthands";
import {rankCells} from "../rankCells";
import {showStatistics} from "../statistics";
import {createGrid} from "./grid";
import {reGraph} from "./reGraph";
import {createPack} from "./pack";
import {getInputValue, setInputValue} from "utils/nodeUtils";
const {
Zoom,
Lakes,
OceanLayers,
Rivers,
Biomes,
Cultures,
BurgsAndStates,
Religions,
Military,
Markers,
Names,
ThreeD
} = window;
const {Zoom, ThreeD} = window;
interface IGenerationOptions {
seed: string;
@ -66,42 +51,10 @@ async function generate(options?: IGenerationOptions) {
randomizeOptions();
const newGrid = await createGrid(grid, precreatedGraph);
const newPack = reGraph(newGrid);
const newPack = createPack(newGrid);
reMarkFeatures(newPack, newGrid);
drawCoastline(newPack);
Rivers.generate(newPack, newGrid);
renderLayer("rivers", newPack);
Lakes.defineGroup(newPack);
Biomes.define(newPack, newGrid);
rankCells(newPack);
Cultures.generate();
Cultures.expand();
BurgsAndStates.generate();
Religions.generate();
BurgsAndStates.defineStateForms();
BurgsAndStates.generateProvinces();
BurgsAndStates.defineBurgFeatures();
renderLayer("states");
renderLayer("borders");
BurgsAndStates.drawStateLabels();
Rivers.specify();
Lakes.generateName();
Military.generate();
Markers.generate();
addZones();
OceanLayers(newGrid);
drawScaleBar(window.scale);
Names.getMapName();
// @ts-expect-error redefine global
// redefine global grid and pack
grid = newGrid;
pack = newPack;
WARN && console.warn(`TOTAL: ${rn((performance.now() - timeStart) / 1000, 2)}s`);

View file

@ -1,17 +1,75 @@
import * as d3 from "d3";
import {renderLayer} from "layers";
// @ts-expect-error js module
import {drawCoastline} from "modules/coastline";
import {markupPackFeatures} from "modules/markup";
// @ts-expect-error js module
import {drawScaleBar} from "modules/measurers";
// @ts-expect-error js module
import {addZones} from "modules/zones";
import {DISTANCE_FIELD, MIN_LAND_HEIGHT} from "config/generation";
import {TIME} from "config/logging";
import {UINT16_MAX} from "constants";
import {createTypedArray} from "utils/arrayUtils";
import {calculateVoronoi} from "scripts/generation/graph";
import {createTypedArray} from "utils/arrayUtils";
import {pick} from "utils/functionUtils";
import {rn} from "utils/numberUtils";
import {DISTANCE_FIELD, MIN_LAND_HEIGHT} from "config/generation";
import {rankCells} from "../rankCells";
const {LAND_COAST, WATER_COAST, DEEPER_WATER} = DISTANCE_FIELD;
const {Lakes, OceanLayers, Rivers, Biomes, Cultures, BurgsAndStates, Religions, Military, Markers, Names} = window;
// recalculate Voronoi Graph to pack cells
export function reGraph(grid: IGrid): IPackBase {
TIME && console.time("reGraph");
export function createPack(grid: IGrid): IPack {
const {vertices, cells} = repackGrid(grid);
const markup = markupPackFeatures(grid, pick(cells, "c", "b", "p", "h"));
drawCoastline({vertices, cells}); // split into vertices definition and rendering
// Rivers.generate(newPack, grid);
// renderLayer("rivers", newPack);
// Lakes.defineGroup(newPack);
// Biomes.define(newPack, grid);
// const rankCellsData = pick(newPack.cells, "i", "f", "fl", "conf", "r", "h", "area", "biome", "haven", "harbor");
// rankCells(newPack.features!, rankCellsData);
Cultures.generate();
Cultures.expand();
BurgsAndStates.generate();
Religions.generate();
BurgsAndStates.defineStateForms();
BurgsAndStates.generateProvinces();
BurgsAndStates.defineBurgFeatures();
renderLayer("states");
renderLayer("borders");
BurgsAndStates.drawStateLabels();
Rivers.specify();
Lakes.generateName();
Military.generate();
Markers.generate();
addZones();
OceanLayers(newGrid);
drawScaleBar(window.scale);
Names.getMapName();
const pack = {
vertices,
cells
};
return pack as IPack;
}
// repack grid cells: discart deep water cells, add land cells along the coast
function repackGrid(grid: IGrid) {
TIME && console.time("repackGrid");
const {cells: gridCells, points, features} = grid;
const newCells: {p: TPoints; g: number[]; h: number[]} = {p: [], g: [], h: []}; // store new data
const spacing2 = grid.spacing ** 2;
@ -59,7 +117,7 @@ export function reGraph(grid: IGrid): IPackBase {
return Math.min(area, UINT16_MAX);
}
const pack: IPackBase = {
const pack = {
vertices,
cells: {
...cells,
@ -71,6 +129,6 @@ export function reGraph(grid: IGrid): IPackBase {
}
};
TIME && console.timeEnd("reGraph");
TIME && console.timeEnd("repackGrid");
return pack;
}

View file

@ -8,12 +8,14 @@ const FLUX_MAX_BONUS = 250;
const SUITABILITY_FACTOR = 5;
// assess cells suitability for population and rank cells for culture centers and burgs placement
export function rankCells(pack: IPack) {
export function rankCells(
features: TPackFeatures,
cells: Pick<IPack["cells"], "i" | "f" | "fl" | "conf" | "r" | "h" | "area" | "biome" | "haven" | "harbor">
) {
TIME && console.time("rankCells");
const {cells, features} = pack;
cells.s = new Int16Array(cells.i.length); // cell suitability array
cells.pop = new Float32Array(cells.i.length); // cell population array
const suitability = new Int16Array(cells.i.length); // cell suitability array
const population = new Float32Array(cells.i.length); // cell population array
const meanFlux = d3.median(cells.fl.filter(f => f)) || 0;
const maxFlux = (d3.max(cells.fl) || 0) + (d3.max(cells.conf) || 0); // to normalize flux
@ -30,14 +32,12 @@ export function rankCells(pack: IPack) {
const coastBonus = getCoastBonus(cellId); // [-30, 30]
const estuaryBonus = getEstuaryBonus(cellId); // [0, 15]
const suitability =
(habitabilityBonus + riverBonus + elevationBonus + coastBonus + estuaryBonus) / SUITABILITY_FACTOR; // [-30, 311]
const bonuses = [habitabilityBonus, riverBonus, elevationBonus, coastBonus, estuaryBonus];
const total = d3.sum(bonuses) / SUITABILITY_FACTOR; // [-30, 311]
suitability[cellId] = total;
// cell rural population is suitability adjusted by cell area
const population = suitability > 0 ? suitability * (cells.area[cellId] / meanArea) : 0;
cells.pop[cellId] = population;
cells.s[cellId] = suitability;
population[cellId] = total > 0 ? total * (cells.area[cellId] / meanArea) : 0;
}
function getHabitabilityBonus(cellId: number) {
@ -57,7 +57,10 @@ export function rankCells(pack: IPack) {
if (!isCoastal(cellId)) return 0;
const havenCell = cells.haven[cellId];
const {group} = features[cells.f[havenCell]];
const feature = features[cells.f[havenCell]];
if (!feature) return 0;
const {group} = feature;
// lake coast
if (group === "freshwater") return 30;
@ -78,4 +81,6 @@ export function rankCells(pack: IPack) {
}
TIME && console.timeEnd("rankCells");
return {s: suitability, pop: population};
}