names
This commit is contained in:
parent
e1bb10ff8a
commit
4bf36b1f59
6 changed files with 157 additions and 43 deletions
|
|
@ -25,7 +25,7 @@ function neighbors4(x, y) {
|
|||
return out;
|
||||
}
|
||||
|
||||
export function generateAdminRegions(centers, prefectureMask, sea, elevation, slope, river, ridgeField, valleyField, populationDensity, landuse) {
|
||||
export function generateAdminRegions(centers, prefectureMask, sea, elevation, slope, river, ridgeField, valleyField, crestCrossingScore, populationDensity, landuse) {
|
||||
const adminId = new Int16Array(SIZE);
|
||||
adminId.fill(-1);
|
||||
const dist = new Float32Array(SIZE);
|
||||
|
|
@ -55,14 +55,16 @@ export function generateAdminRegions(centers, prefectureMask, sea, elevation, sl
|
|||
const ridgeBarrier = Math.max(ridgeField[ni], ridgeField[curIndex]);
|
||||
const riverBarrier = Math.max(river[ni], river[curIndex]);
|
||||
const highDivide = Math.max(elevation[ni], elevation[curIndex]);
|
||||
const crest = Math.max(crestCrossingScore?.[ni] || 0, crestCrossingScore?.[curIndex] || 0);
|
||||
const watershedBarrier = ridgeBarrier * (27.0 + Math.max(0, highDivide - 0.46) * 46.0);
|
||||
const crestPenalty = crest * (18.0 + Math.max(0, highDivide - 0.48) * 38.0) * (1 + Math.max(0, highDivide - 0.56) * 1.9);
|
||||
const ridgePenalty = Math.max(0, highDivide - 0.36) * 16.0 + Math.abs(elevation[ni] - elevation[curIndex]) * 12.4 + watershedBarrier;
|
||||
const slopePenalty = slope[ni] * 10.6;
|
||||
const valleyBarrier = valleyField[ni] > 0.50 ? valleyField[ni] * (riverBarrier > 0.16 ? 7.2 : 2.6) : 0;
|
||||
const riverPenalty = riverBarrier > 0.7 ? 22.0 : riverBarrier > 0.42 ? 14.8 : riverBarrier > 0.22 ? 7.4 : riverBarrier > 0.12 ? 2.2 : 0;
|
||||
const urbanContinuityBonus = (landuse[ni] >= 2 && landuse[ni] <= 4 && populationDensity[ni] > 0.20) ? 1.65 : 0;
|
||||
const valleyLocalityBonus = valleyField[ni] * 0.16;
|
||||
const stepCost = Math.max(0.25, 0.72 + ridgePenalty + slopePenalty + riverPenalty + valleyBarrier - valleyLocalityBonus - urbanContinuityBonus) * step;
|
||||
const stepCost = Math.max(0.25, 0.72 + ridgePenalty + crestPenalty + slopePenalty + riverPenalty + valleyBarrier - valleyLocalityBonus - urbanContinuityBonus) * step;
|
||||
const nextDist = dist[curIndex] + stepCost;
|
||||
|
||||
if (nextDist < dist[ni]) {
|
||||
|
|
@ -266,15 +268,16 @@ export function removeMunicipalExclaves(adminId, prefectureMask, sea, adminCente
|
|||
}
|
||||
}
|
||||
|
||||
export function terrainBoundaryTargetScore(i, elevation, slope, river, ridgeField, valleyField, flowAccum, populationDensity, landuse) {
|
||||
export function terrainBoundaryTargetScore(i, elevation, slope, river, ridgeField, valleyField, flowAccum, crestCrossingScore, populationDensity, landuse) {
|
||||
const urbanPenalty = urbanBoundaryPenalty(i, populationDensity, landuse);
|
||||
const crest = crestCrossingScore?.[i] || 0;
|
||||
const majorRiver = clamp(Math.max(river[i] - 0.32, 0) * 1.9 + Math.max(flowAccum[i] - 0.38, 0) * 0.75);
|
||||
const minorStream = clamp(river[i] * 0.34 + flowAccum[i] * 0.18);
|
||||
const ridgeDivide = clamp(ridgeField[i] * 1.55 + Math.max(0, elevation[i] - 0.54) * ridgeField[i] * 0.95);
|
||||
const slopeBreak = clamp(slope[i] * 0.58 + Math.max(0, slope[i] - 0.32) * 0.68);
|
||||
const highGround = Math.max(0, elevation[i] - 0.56) * 0.22;
|
||||
const valleyFloorPenalty = valleyField[i] * (majorRiver > 0.34 ? -0.10 : -0.62);
|
||||
return clamp(ridgeDivide + majorRiver * 0.88 + minorStream * 0.22 + slopeBreak + highGround + valleyFloorPenalty - urbanPenalty * 0.72);
|
||||
return clamp(ridgeDivide + crest * 1.38 + majorRiver * 0.88 + minorStream * 0.22 + slopeBreak + highGround + valleyFloorPenalty - urbanPenalty * 0.72);
|
||||
}
|
||||
|
||||
function urbanBoundaryPenalty(i, populationDensity, landuse) {
|
||||
|
|
@ -344,7 +347,7 @@ function buildAdminProtectedMask(adminId, prefectureMask, sea, adminCenters = []
|
|||
function localBoundaryEnergy(labels, i, candidateId, targetScore, centerDist, populationDensity, landuse, river, valleyField) {
|
||||
const [x, y] = xyOf(i);
|
||||
const oldId = labels[i];
|
||||
let energy = centerDist[candidateId]?.[i] ?? 0;
|
||||
let energy = (centerDist[candidateId]?.[i] ?? 0) * 0.035;
|
||||
let same4 = 0;
|
||||
let diff4 = 0;
|
||||
let diagDiff = 0;
|
||||
|
|
@ -375,7 +378,7 @@ function localBoundaryEnergy(labels, i, candidateId, targetScore, centerDist, po
|
|||
if (diagDiff >= 3 && diff4 >= 2 && targetScore[i] < 0.50) energy += 0.42;
|
||||
if (candidateId !== oldId && centerDist[candidateId] && centerDist[oldId]) {
|
||||
const drift = centerDist[candidateId][i] - centerDist[oldId][i];
|
||||
if (drift > 0) energy += Math.min(0.9, drift * 0.012);
|
||||
if (drift > 0) energy += Math.min(0.55, drift * 0.006);
|
||||
}
|
||||
return energy;
|
||||
}
|
||||
|
|
@ -467,7 +470,7 @@ function classifyLandscapeCell(i, elevation, slope, river, ridgeField, valleyFie
|
|||
return 11;
|
||||
}
|
||||
|
||||
function buildLandscapeUnits(prefectureMask, sea, elevation, slope, river, ridgeField, valleyField, basinField, coastalLowland, flowAccum, plain, agriculture, populationDensity, landuse) {
|
||||
function buildLandscapeUnits(prefectureMask, sea, elevation, slope, river, ridgeField, valleyField, basinField, coastalLowland, flowAccum, crestCrossingScore, plain, agriculture, populationDensity, landuse) {
|
||||
const unitId = new Int32Array(SIZE);
|
||||
unitId.fill(-1);
|
||||
const cellClass = new Int16Array(SIZE);
|
||||
|
|
@ -504,7 +507,7 @@ function buildLandscapeUnits(prefectureMask, sea, elevation, slope, river, ridge
|
|||
}
|
||||
|
||||
const targetScore = new Float32Array(SIZE);
|
||||
for (let i = 0; i < SIZE; i++) if (cellClass[i] >= 0) targetScore[i] = terrainBoundaryTargetScore(i, elevation, slope, river, ridgeField, valleyField, flowAccum, populationDensity, landuse);
|
||||
for (let i = 0; i < SIZE; i++) if (cellClass[i] >= 0) targetScore[i] = terrainBoundaryTargetScore(i, elevation, slope, river, ridgeField, valleyField, flowAccum, crestCrossingScore, populationDensity, landuse);
|
||||
rebuildLandscapeUnitAdjacency(unitId, units, targetScore, prefectureMask, sea);
|
||||
mergeTinyLandscapeUnits(unitId, units, 10);
|
||||
rebuildLandscapeUnitAdjacency(unitId, units, targetScore, prefectureMask, sea);
|
||||
|
|
@ -569,8 +572,8 @@ function landscapeTransitionCost(a, b, edge) {
|
|||
return Math.max(0.18, 0.70 + boundaryTarget * 4.2 + (a.classId === b.classId ? 0 : 0.75) + ((a.classId === 8 || b.classId === 8) ? 1.2 : 0) - urbanContinuity - (bothCorridor ? 0.55 : 0));
|
||||
}
|
||||
|
||||
export function applyLandscapeUnitAdminPartition(adminId, prefectureMask, sea, elevation, slope, river, ridgeField, valleyField, basinField, coastalLowland, flowAccum, plain, agriculture, populationDensity, landuse, adminCenters = []) {
|
||||
const { unitId, units, targetScore } = buildLandscapeUnits(prefectureMask, sea, elevation, slope, river, ridgeField, valleyField, basinField, coastalLowland, flowAccum, plain, agriculture, populationDensity, landuse);
|
||||
export function applyLandscapeUnitAdminPartition(adminId, prefectureMask, sea, elevation, slope, river, ridgeField, valleyField, basinField, coastalLowland, flowAccum, crestCrossingScore, plain, agriculture, populationDensity, landuse, adminCenters = []) {
|
||||
const { unitId, units, targetScore } = buildLandscapeUnits(prefectureMask, sea, elevation, slope, river, ridgeField, valleyField, basinField, coastalLowland, flowAccum, crestCrossingScore, plain, agriculture, populationDensity, landuse);
|
||||
if (units.length === 0) return;
|
||||
for (let id = 0; id < adminCenters.length; id++) {
|
||||
const center = adminCenters[id];
|
||||
|
|
@ -621,11 +624,11 @@ export function applyLandscapeUnitAdminPartition(adminId, prefectureMask, sea, e
|
|||
repairAdminTopology(adminId, prefectureMask, sea, adminCenters, targetScore, populationDensity, landuse);
|
||||
}
|
||||
|
||||
export function snapAdminBoundariesToTerrain(adminId, prefectureMask, sea, elevation, slope, river, ridgeField, valleyField, flowAccum, populationDensity, landuse, adminCenters = [], protectedPoints = [], passes = 6) {
|
||||
export function snapAdminBoundariesToTerrain(adminId, prefectureMask, sea, elevation, slope, river, ridgeField, valleyField, flowAccum, crestCrossingScore, populationDensity, landuse, adminCenters = [], protectedPoints = [], passes = 6) {
|
||||
const targetScore = new Float32Array(SIZE);
|
||||
for (let i = 0; i < SIZE; i++) if (prefectureMask[i] && !sea[i]) targetScore[i] = terrainBoundaryTargetScore(i, elevation, slope, river, ridgeField, valleyField, flowAccum, populationDensity, landuse);
|
||||
for (let i = 0; i < SIZE; i++) if (prefectureMask[i] && !sea[i]) targetScore[i] = terrainBoundaryTargetScore(i, elevation, slope, river, ridgeField, valleyField, flowAccum, crestCrossingScore, populationDensity, landuse);
|
||||
const protectedMask = buildAdminProtectedMask(adminId, prefectureMask, sea, adminCenters, protectedPoints, populationDensity, landuse);
|
||||
const band = buildBoundaryBand(adminId, prefectureMask, sea, 5);
|
||||
const band = buildBoundaryBand(adminId, prefectureMask, sea, 8);
|
||||
const adminIds = [...new Set([...adminId].filter((id) => id >= 0))];
|
||||
const centerDist = buildCenterDistanceFields(adminIds, adminCenters, prefectureMask, sea);
|
||||
let current = new Int16Array(adminId);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue