mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 01:41:22 +01:00
v1.5.86 - separate lakes object
This commit is contained in:
parent
cb88ab9229
commit
5f5a67d436
11 changed files with 175 additions and 109 deletions
|
|
@ -1441,7 +1441,10 @@ div.states > .coaIcon > use {
|
||||||
|
|
||||||
#riverBody div.label,
|
#riverBody div.label,
|
||||||
#riverBody input,
|
#riverBody input,
|
||||||
#riverBody select {
|
#riverBody select,
|
||||||
|
#lakeBody div.label,
|
||||||
|
#lakeBody input,
|
||||||
|
#lakeBody select {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 7em;
|
width: 7em;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
47
index.html
47
index.html
|
|
@ -1624,6 +1624,37 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="lakeEditor" class="dialog" style="display: none">
|
||||||
|
<div id="lakeBody" style="padding-bottom: .3em">
|
||||||
|
<div style="padding: .1em">
|
||||||
|
<div class="label" style="width: 4.8em">Name:</div>
|
||||||
|
<span id="lakeNameCulture" data-tip="Generate culture-specific name for the lake" class="icon-book pointer"></span>
|
||||||
|
<span id="lakeNameRandom" data-tip="Generate random name for the lake" class="icon-globe pointer"></span>
|
||||||
|
<input id="lakeName" data-tip="Type to rename the lake" autocorrect="off" spellcheck="false">
|
||||||
|
<span data-tip="Speak the name. You can change voice and language in options" class="speaker">🔊</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="padding: .1em" data-tip="Type to change lake type (group)">
|
||||||
|
<div class="label">Type:</div>
|
||||||
|
|
||||||
|
<select id="lakeGroup" data-tip="Select lake type (group)" style="width:9em"></select>
|
||||||
|
<input id="lakeGroupName" placeholder="new group name" data-tip="Provide a name for the new group" style="display:none; width:9em"/>
|
||||||
|
<span id="lakeGroupAdd" data-tip="Create new type (group) for the lake" class="icon-plus pointer"></span>
|
||||||
|
<span id="lakeGroupRemove" data-tip="Remove the group" class="icon-trash-empty pointer"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="padding: .1em" data-tip="Lake area in selected units">
|
||||||
|
<div class="label">Area:</div>
|
||||||
|
<input id="lakeArea" disabled/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="lakeBottom">
|
||||||
|
<button id="lakeEditStyle" data-tip="Edit lake group style in Style Editor" class="icon-brush"></button>
|
||||||
|
<button id="lakeLegend" data-tip="Edit free text notes (legend) for the lake" class="icon-edit"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="elevationProfile" class="dialog" style="display: none" width="100%">
|
<div id="elevationProfile" class="dialog" style="display: none" width="100%">
|
||||||
<div id="elevationGraph" data-tip="Elevation profile"></div>
|
<div id="elevationGraph" data-tip="Elevation profile"></div>
|
||||||
<div style="text-align: center">
|
<div style="text-align: center">
|
||||||
|
|
@ -1663,21 +1694,6 @@
|
||||||
<button id="routeRemove" data-tip="Remove route. Shortcut: Delete" class="icon-trash fastDelete"></button>
|
<button id="routeRemove" data-tip="Remove route. Shortcut: Delete" class="icon-trash fastDelete"></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="lakeEditor" class="dialog" style="display: none">
|
|
||||||
<button id="lakeGroupsShow" data-tip="Show the group selection" class="icon-tags"></button>
|
|
||||||
<div id="lakeGroupsSelection" style="display: none">
|
|
||||||
<button id="lakeGroupsHide" data-tip="Hide the group section" class="icon-tags"></button>
|
|
||||||
<select id="lakeGroup" data-tip="Select a group for this lake" style="width:9em"></select>
|
|
||||||
<input id="lakeGroupName" placeholder="new group name" data-tip="Provide a name for the new group" style="display:none; width:9em"/>
|
|
||||||
<span id="lakeGroupAdd" data-tip="Create new group for this lake" class="icon-plus pointer"></span>
|
|
||||||
<span id="lakeGroupRemove" data-tip="Remove the group" class="icon-trash-empty pointer"></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button id="lakeEditStyle" data-tip="Edit lake group style in Style Editor" class="icon-brush"></button>
|
|
||||||
<button id="lakeArea" data-tip="Lake area in selected units">0</button>
|
|
||||||
<button id="lakeLegend" data-tip="Edit free text notes (legend) for the lake" class="icon-edit"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="iceEditor" class="dialog" style="display: none">
|
<div id="iceEditor" class="dialog" style="display: none">
|
||||||
<button id="iceEditStyle" data-tip="Edit style in Style Editor" class="icon-brush"></button>
|
<button id="iceEditStyle" data-tip="Edit style in Style Editor" class="icon-brush"></button>
|
||||||
<button id="iceRandomize" data-tip="Randomize Iceberd shape" class="icon-shuffle"></button>
|
<button id="iceRandomize" data-tip="Randomize Iceberd shape" class="icon-shuffle"></button>
|
||||||
|
|
@ -4037,6 +4053,7 @@
|
||||||
<script src="modules/heightmap-generator.js"></script>
|
<script src="modules/heightmap-generator.js"></script>
|
||||||
<script src="modules/ocean-layers.js"></script>
|
<script src="modules/ocean-layers.js"></script>
|
||||||
<script src="modules/river-generator.js"></script>
|
<script src="modules/river-generator.js"></script>
|
||||||
|
<script src="modules/lakes.js"></script>
|
||||||
<script src="modules/names-generator.js"></script>
|
<script src="modules/names-generator.js"></script>
|
||||||
<script src="modules/cultures-generator.js"></script>
|
<script src="modules/cultures-generator.js"></script>
|
||||||
<script src="modules/burgs-and-states.js"></script>
|
<script src="modules/burgs-and-states.js"></script>
|
||||||
|
|
|
||||||
28
main.js
28
main.js
|
|
@ -547,7 +547,7 @@ function generate() {
|
||||||
drawCoastline();
|
drawCoastline();
|
||||||
|
|
||||||
Rivers.generate();
|
Rivers.generate();
|
||||||
defineLakesGroup();
|
Lakes.defineGroup();
|
||||||
defineBiomes();
|
defineBiomes();
|
||||||
|
|
||||||
rankCells();
|
rankCells();
|
||||||
|
|
@ -564,6 +564,7 @@ function generate() {
|
||||||
BurgsAndStates.drawStateLabels();
|
BurgsAndStates.drawStateLabels();
|
||||||
|
|
||||||
Rivers.specify();
|
Rivers.specify();
|
||||||
|
Lakes.generateName();
|
||||||
|
|
||||||
Military.generate();
|
Military.generate();
|
||||||
addMarkers();
|
addMarkers();
|
||||||
|
|
@ -1120,31 +1121,6 @@ function reMarkFeatures() {
|
||||||
TIME && console.timeEnd("reMarkFeatures");
|
TIME && console.timeEnd("reMarkFeatures");
|
||||||
}
|
}
|
||||||
|
|
||||||
function defineLakesGroup() {
|
|
||||||
for (const feature of pack.features) {
|
|
||||||
if (feature.type !== "lake") continue;
|
|
||||||
const lakeEl = lakes.select(`[data-f="${feature.i}"]`).node();
|
|
||||||
if (!lakeEl) continue;
|
|
||||||
|
|
||||||
feature.group = defineGroup(feature);
|
|
||||||
document.getElementById(feature.group).appendChild(lakeEl);
|
|
||||||
}
|
|
||||||
|
|
||||||
function defineGroup(feature) {
|
|
||||||
if (feature.temp < -3) return "frozen";
|
|
||||||
if (feature.height > 60 && feature.cells < 10 && feature.firstCell % 5 === 0) return "lava";
|
|
||||||
|
|
||||||
if (!feature.inlets && !feature.outlet) {
|
|
||||||
if (feature.evaporation / 2 > feature.flux) return "dry";
|
|
||||||
if (feature.cells < 3 && feature.firstCell % 5 === 0) return "sinkhole";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!feature.outlet && feature.evaporation > feature.flux) return "salt";
|
|
||||||
|
|
||||||
return "freshwater";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// assign biome id for each cell
|
// assign biome id for each cell
|
||||||
function defineBiomes() {
|
function defineBiomes() {
|
||||||
TIME && console.time("defineBiomes");
|
TIME && console.time("defineBiomes");
|
||||||
|
|
|
||||||
89
modules/lakes.js
Normal file
89
modules/lakes.js
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
(function (global, factory) {
|
||||||
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
||||||
|
typeof define === 'function' && define.amd ? define(factory) :
|
||||||
|
(global.Lakes = factory());
|
||||||
|
}(this, (function () {'use strict';
|
||||||
|
|
||||||
|
const setClimateData = function(h) {
|
||||||
|
const cells = pack.cells;
|
||||||
|
const lakeOutCells = new Uint16Array(cells.i.length);
|
||||||
|
|
||||||
|
pack.features.forEach(f => {
|
||||||
|
if (f.type !== "lake") return;
|
||||||
|
|
||||||
|
// default flux: sum of precipition around lake first cell
|
||||||
|
f.flux = rn(d3.sum(f.shoreline.map(c => grid.cells.prec[cells.g[c]])) / 2);
|
||||||
|
|
||||||
|
// temperature and evaporation to detect closed lakes
|
||||||
|
f.temp = f.cells < 6 ? grid.cells.temp[cells.g[f.firstCell]] : rn(d3.mean(f.shoreline.map(c => grid.cells.temp[cells.g[c]])), 1);
|
||||||
|
const height = (f.height - 18) ** heightExponentInput.value; // height in meters
|
||||||
|
const evaporation = (700 * (f.temp + .006 * height) / 50 + 75) / (80 - f.temp); // based on Penman formula, [1-11]
|
||||||
|
f.evaporation = rn(evaporation * f.cells);
|
||||||
|
|
||||||
|
// lake outlet cell
|
||||||
|
f.outCell = f.shoreline[d3.scan(f.shoreline, (a,b) => h[a] - h[b])];
|
||||||
|
lakeOutCells[f.outCell] = f.i;
|
||||||
|
});
|
||||||
|
|
||||||
|
return lakeOutCells;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cleanupLakeData = function() {
|
||||||
|
for (const feature of pack.features) {
|
||||||
|
if (feature.type !== "lake") continue;
|
||||||
|
delete feature.river;
|
||||||
|
delete feature.enteringFlux;
|
||||||
|
delete feature.shoreline;
|
||||||
|
delete feature.outCell;
|
||||||
|
feature.height = rn(feature.height);
|
||||||
|
|
||||||
|
const inlets = feature.inlets?.filter(r => pack.rivers.find(river => river.i === r));
|
||||||
|
if (!inlets || !inlets.length) delete feature.inlets;
|
||||||
|
else feature.inlets = inlets;
|
||||||
|
|
||||||
|
const outlet = feature.outlet && pack.rivers.find(river => river.i === feature.outlet);
|
||||||
|
if (!outlet) delete feature.outlet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const defineGroup = function() {
|
||||||
|
for (const feature of pack.features) {
|
||||||
|
if (feature.type !== "lake") continue;
|
||||||
|
const lakeEl = lakes.select(`[data-f="${feature.i}"]`).node();
|
||||||
|
if (!lakeEl) continue;
|
||||||
|
|
||||||
|
feature.group = getGroup(feature);
|
||||||
|
document.getElementById(feature.group).appendChild(lakeEl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateName = function() {
|
||||||
|
for (const feature of pack.features) {
|
||||||
|
if (feature.type !== "lake") continue;
|
||||||
|
feature.name = getName(feature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getName = function(feature) {
|
||||||
|
const landCell = pack.cells.c[feature.firstCell].find(c => pack.cells.h[c] >= 20);
|
||||||
|
const culture = pack.cells.culture[landCell];
|
||||||
|
return Names.getCulture(culture);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGroup(feature) {
|
||||||
|
if (feature.temp < -3) return "frozen";
|
||||||
|
if (feature.height > 60 && feature.cells < 10 && feature.firstCell % 5 === 0) return "lava";
|
||||||
|
|
||||||
|
if (!feature.inlets && !feature.outlet) {
|
||||||
|
if (feature.evaporation / 2 > feature.flux) return "dry";
|
||||||
|
if (feature.cells < 3 && feature.firstCell % 5 === 0) return "sinkhole";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!feature.outlet && feature.evaporation > feature.flux) return "salt";
|
||||||
|
|
||||||
|
return "freshwater";
|
||||||
|
}
|
||||||
|
|
||||||
|
return {setClimateData, cleanupLakeData, defineGroup, generateName, getName};
|
||||||
|
|
||||||
|
})));
|
||||||
|
|
@ -21,7 +21,7 @@ const generate = function(changeHeights = true) {
|
||||||
resolveDepressions(h);
|
resolveDepressions(h);
|
||||||
drainWater();
|
drainWater();
|
||||||
defineRivers();
|
defineRivers();
|
||||||
cleanupLakeData();
|
Lakes.cleanupLakeData();
|
||||||
|
|
||||||
if (changeHeights) cells.h = Uint8Array.from(h); // apply changed heights as basic one
|
if (changeHeights) cells.h = Uint8Array.from(h); // apply changed heights as basic one
|
||||||
|
|
||||||
|
|
@ -57,25 +57,7 @@ const generate = function(changeHeights = true) {
|
||||||
function drainWater() {
|
function drainWater() {
|
||||||
const MIN_FLUX_TO_FORM_RIVER = 30;
|
const MIN_FLUX_TO_FORM_RIVER = 30;
|
||||||
const land = cells.i.filter(i => h[i] >= 20).sort((a,b) => h[b] - h[a]);
|
const land = cells.i.filter(i => h[i] >= 20).sort((a,b) => h[b] - h[a]);
|
||||||
|
const lakeOutCells = Lakes.setClimateData(h);
|
||||||
const lakeOutCells = new Uint16Array(cells.i.length); // to enumerate lake outlet positions
|
|
||||||
features.forEach(f => {
|
|
||||||
if (f.type !== "lake") return;
|
|
||||||
const gridCell = cells.g[f.firstCell];
|
|
||||||
|
|
||||||
// lake possible outlet: cell around with min height
|
|
||||||
f.outCell = f.shoreline[d3.scan(f.shoreline, (a,b) => h[a] - h[b])];
|
|
||||||
lakeOutCells[f.outCell] = f.i;
|
|
||||||
|
|
||||||
// default flux: sum of precipition around lake first cell
|
|
||||||
f.flux = rn(d3.sum(f.shoreline.map(c => grid.cells.prec[cells.g[c]])) / 2);
|
|
||||||
|
|
||||||
// temperature and evaporation to detect closed lakes
|
|
||||||
f.temp = f.cells < 6 ? grid.cells.temp[gridCell] : rn(d3.mean(f.shoreline.map(c => grid.cells.temp[cells.g[c]])), 1);
|
|
||||||
const height = (f.height - 18) ** heightExponentInput.value; // height in meters
|
|
||||||
const evaporation = (700 * (f.temp + .006 * height) / 50 + 75) / (80 - f.temp); // based on Penman formula, [1-11]
|
|
||||||
f.evaporation = rn(evaporation * f.cells);
|
|
||||||
});
|
|
||||||
|
|
||||||
land.forEach(function(i) {
|
land.forEach(function(i) {
|
||||||
cells.fl[i] += grid.cells.prec[cells.g[i]]; // flux from precipitation
|
cells.fl[i] += grid.cells.prec[cells.g[i]]; // flux from precipitation
|
||||||
|
|
@ -208,24 +190,6 @@ const generate = function(changeHeights = true) {
|
||||||
// draw rivers
|
// draw rivers
|
||||||
rivers.html(riverPaths.map(d => `<path id="river${d[1]}" d="${d[0]}"/>`).join(""));
|
rivers.html(riverPaths.map(d => `<path id="river${d[1]}" d="${d[0]}"/>`).join(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanupLakeData() {
|
|
||||||
for (const feature of features) {
|
|
||||||
if (feature.type !== "lake") continue;
|
|
||||||
delete feature.river;
|
|
||||||
delete feature.enteringFlux;
|
|
||||||
delete feature.shoreline;
|
|
||||||
delete feature.outCell;
|
|
||||||
feature.height = rn(feature.height);
|
|
||||||
|
|
||||||
const inlets = feature.inlets?.filter(r => pack.rivers.find(river => river.i === r));
|
|
||||||
if (!inlets || !inlets.length) delete feature.inlets;
|
|
||||||
else feature.inlets = inlets;
|
|
||||||
|
|
||||||
const outlet = feature.outlet && pack.rivers.find(river => river.i === feature.outlet);
|
|
||||||
if (!outlet) delete feature.outlet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// depression filling algorithm (for a correct water flux modeling)
|
// depression filling algorithm (for a correct water flux modeling)
|
||||||
|
|
@ -238,7 +202,6 @@ const resolveDepressions = function(h) {
|
||||||
const uniqueCells = new Set();
|
const uniqueCells = new Set();
|
||||||
l.vertices.forEach(v => pack.vertices.c[v].forEach(c => cells.h[c] >= 20 && uniqueCells.add(c)));
|
l.vertices.forEach(v => pack.vertices.c[v].forEach(c => cells.h[c] >= 20 && uniqueCells.add(c)));
|
||||||
l.shoreline = [...uniqueCells];
|
l.shoreline = [...uniqueCells];
|
||||||
l.height = 21;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const land = cells.i.filter(i => h[i] >= 20 && !cells.b[i]); // exclude near-border cells
|
const land = cells.i.filter(i => h[i] >= 20 && !cells.b[i]); // exclude near-border cells
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,12 @@ function showMapTooltip(point, e, i, g) {
|
||||||
}
|
}
|
||||||
if (subgroup === "burgIcons") {tip("Click to edit the Burg"); return;}
|
if (subgroup === "burgIcons") {tip("Click to edit the Burg"); return;}
|
||||||
if (subgroup === "burgLabels") {tip("Click to edit the Burg"); return;}
|
if (subgroup === "burgLabels") {tip("Click to edit the Burg"); return;}
|
||||||
if (group === "lakes" && !land) {tip(`${capitalize(subgroup)} lake. Click to edit`); return;}
|
if (group === "lakes" && !land) {
|
||||||
|
const lakeId = +e.target.dataset.f;
|
||||||
|
const name = pack.features[lakeId]?.name;
|
||||||
|
const fullName = subgroup === "freshwater" ? name : name + " " + subgroup;
|
||||||
|
tip(`${fullName} lake. Click to edit`); return;
|
||||||
|
}
|
||||||
if (group === "coastline") {tip("Click to edit the coastline"); return;}
|
if (group === "coastline") {tip("Click to edit the coastline"); return;}
|
||||||
if (group === "zones") {
|
if (group === "zones") {
|
||||||
const zone = path[path.length-8];
|
const zone = path[path.length-8];
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@ function editHeightmap() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defineLakesGroup();
|
Lakes.defineGroup();
|
||||||
defineBiomes();
|
defineBiomes();
|
||||||
rankCells();
|
rankCells();
|
||||||
Cultures.generate();
|
Cultures.generate();
|
||||||
|
|
@ -201,6 +201,8 @@ function editHeightmap() {
|
||||||
BurgsAndStates.drawStateLabels();
|
BurgsAndStates.drawStateLabels();
|
||||||
|
|
||||||
Rivers.specify();
|
Rivers.specify();
|
||||||
|
Lakes.generateName();
|
||||||
|
|
||||||
Military.generate();
|
Military.generate();
|
||||||
addMarkers();
|
addMarkers();
|
||||||
addZones();
|
addZones();
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ function editLake() {
|
||||||
const node = d3.event.target;
|
const node = d3.event.target;
|
||||||
debug.append("g").attr("id", "vertices");
|
debug.append("g").attr("id", "vertices");
|
||||||
elSelected = d3.select(node);
|
elSelected = d3.select(node);
|
||||||
|
updateLakeValues();
|
||||||
selectLakeGroup(node);
|
selectLakeGroup(node);
|
||||||
drawLakeVertices();
|
drawLakeVertices();
|
||||||
viewbox.on("touchmove mousemove", null);
|
viewbox.on("touchmove mousemove", null);
|
||||||
|
|
@ -21,19 +22,34 @@ function editLake() {
|
||||||
modules.editLake = true;
|
modules.editLake = true;
|
||||||
|
|
||||||
// add listeners
|
// add listeners
|
||||||
document.getElementById("lakeGroupsShow").addEventListener("click", showGroupSection);
|
document.getElementById("lakeName").addEventListener("input", changeName);
|
||||||
|
document.getElementById("lakeNameCulture").addEventListener("click", generateNameCulture);
|
||||||
|
document.getElementById("lakeNameRandom").addEventListener("click", generateNameRandom);
|
||||||
|
|
||||||
document.getElementById("lakeGroup").addEventListener("change", changeLakeGroup);
|
document.getElementById("lakeGroup").addEventListener("change", changeLakeGroup);
|
||||||
document.getElementById("lakeGroupAdd").addEventListener("click", toggleNewGroupInput);
|
document.getElementById("lakeGroupAdd").addEventListener("click", toggleNewGroupInput);
|
||||||
document.getElementById("lakeGroupName").addEventListener("change", createNewGroup);
|
document.getElementById("lakeGroupName").addEventListener("change", createNewGroup);
|
||||||
document.getElementById("lakeGroupRemove").addEventListener("click", removeLakeGroup);
|
document.getElementById("lakeGroupRemove").addEventListener("click", removeLakeGroup);
|
||||||
document.getElementById("lakeGroupsHide").addEventListener("click", hideGroupSection);
|
|
||||||
|
|
||||||
document.getElementById("lakeEditStyle").addEventListener("click", editGroupStyle);
|
document.getElementById("lakeEditStyle").addEventListener("click", editGroupStyle);
|
||||||
document.getElementById("lakeLegend").addEventListener("click", editLakeLegend);
|
document.getElementById("lakeLegend").addEventListener("click", editLakeLegend);
|
||||||
|
|
||||||
|
function getLake() {
|
||||||
|
const lakeId = +elSelected.attr("data-f");
|
||||||
|
return pack.features.find(feature => feature.i === lakeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateLakeValues() {
|
||||||
|
const l = getLake();
|
||||||
|
document.getElementById("lakeName").value = l.name;
|
||||||
|
document.getElementById("lakeGroup").value = l.type;
|
||||||
|
|
||||||
|
const unit = areaUnit.value === "square" ? " " + distanceUnitInput.value + "²" : " " + areaUnit.value;
|
||||||
|
document.getElementById("lakeArea").value = si(l.area * distanceScaleInput.value ** 2) + unit;
|
||||||
|
}
|
||||||
|
|
||||||
function drawLakeVertices() {
|
function drawLakeVertices() {
|
||||||
const f = +elSelected.attr("data-f"); // feature id
|
const v = getLake().vertices; // lake outer vertices
|
||||||
const v = pack.features[f].vertices; // lake outer vertices
|
|
||||||
|
|
||||||
const c = [... new Set(v.map(v => pack.vertices.c[v]).flat())];
|
const c = [... new Set(v.map(v => pack.vertices.c[v]).flat())];
|
||||||
debug.select("#vertices").selectAll("polygon").data(c).enter().append("polygon")
|
debug.select("#vertices").selectAll("polygon").data(c).enter().append("polygon")
|
||||||
|
|
@ -43,10 +59,6 @@ function editLake() {
|
||||||
.attr("cx", d => pack.vertices.p[d][0]).attr("cy", d => pack.vertices.p[d][1])
|
.attr("cx", d => pack.vertices.p[d][0]).attr("cy", d => pack.vertices.p[d][1])
|
||||||
.attr("r", .4).attr("data-v", d => d).call(d3.drag().on("drag", dragVertex))
|
.attr("r", .4).attr("data-v", d => d).call(d3.drag().on("drag", dragVertex))
|
||||||
.on("mousemove", () => tip("Drag to move the vertex, please use for fine-tuning only. Edit heightmap to change actual cell heights"));
|
.on("mousemove", () => tip("Drag to move the vertex, please use for fine-tuning only. Edit heightmap to change actual cell heights"));
|
||||||
|
|
||||||
const unit = areaUnit.value === "square" ? " " + distanceUnitInput.value + "²" : " " + areaUnit.value;
|
|
||||||
const area = pack.features[f].area;
|
|
||||||
lakeArea.innerHTML = si(area * distanceScaleInput.value ** 2) + unit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function dragVertex() {
|
function dragVertex() {
|
||||||
|
|
@ -61,29 +73,29 @@ function editLake() {
|
||||||
|
|
||||||
function redrawLake() {
|
function redrawLake() {
|
||||||
lineGen.curve(d3.curveBasisClosed);
|
lineGen.curve(d3.curveBasisClosed);
|
||||||
const f = +elSelected.attr("data-f");
|
const feature = getLake();
|
||||||
const vertices = pack.features[f].vertices;
|
const points = feature.vertices.map(v => pack.vertices.p[v]);
|
||||||
const points = vertices.map(v => pack.vertices.p[v]);
|
|
||||||
const d = round(lineGen(points));
|
const d = round(lineGen(points));
|
||||||
elSelected.attr("d", d);
|
elSelected.attr("d", d);
|
||||||
defs.select("mask#land > path#land_"+f).attr("d", d); // update land mask
|
defs.select("mask#land > path#land_"+feature.i).attr("d", d); // update land mask
|
||||||
|
|
||||||
const unit = areaUnit.value === "square" ? " " + distanceUnitInput.value + "²" : " " + areaUnit.value;
|
const unit = areaUnit.value === "square" ? " " + distanceUnitInput.value + "²" : " " + areaUnit.value;
|
||||||
const area = Math.abs(d3.polygonArea(points));
|
feature.area = Math.abs(d3.polygonArea(points));
|
||||||
lakeArea.innerHTML = si(area * distanceScaleInput.value ** 2) + unit;
|
document.getElementById("lakeArea").value = si(feature.area * distanceScaleInput.value ** 2) + unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showGroupSection() {
|
function changeName() {
|
||||||
document.querySelectorAll("#lakeEditor > button").forEach(el => el.style.display = "none");
|
getLake().name = this.value;
|
||||||
document.getElementById("lakeGroupsSelection").style.display = "inline-block";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideGroupSection() {
|
function generateNameCulture() {
|
||||||
document.querySelectorAll("#lakeEditor > button").forEach(el => el.style.display = "inline-block");
|
const lake = getLake();
|
||||||
document.getElementById("lakeGroupsSelection").style.display = "none";
|
lake.name = lakeName.value = Lakes.getName(lake);
|
||||||
document.getElementById("lakeGroupName").style.display = "none";
|
}
|
||||||
document.getElementById("lakeGroupName").value = "";
|
|
||||||
document.getElementById("lakeGroup").style.display = "inline-block";
|
function generateNameRandom() {
|
||||||
|
const lake = getLake();
|
||||||
|
lake.name = lakeName.value = Names.getBase(rand(nameBases.length-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectLakeGroup(node) {
|
function selectLakeGroup(node) {
|
||||||
|
|
|
||||||
|
|
@ -421,7 +421,6 @@ function applyStoredOptions() {
|
||||||
const height = +params.get("height");
|
const height = +params.get("height");
|
||||||
if (width) mapWidthInput.value = width;
|
if (width) mapWidthInput.value = width;
|
||||||
if (height) mapHeightInput.value = height;
|
if (height) mapHeightInput.value = height;
|
||||||
//window.history.pushState({}, null, "?");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// randomize options if randomization is allowed (not locked or options='default')
|
// randomize options if randomization is allowed (not locked or options='default')
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ async function openEmblemEditor() {
|
||||||
|
|
||||||
function regenerateRivers() {
|
function regenerateRivers() {
|
||||||
Rivers.generate();
|
Rivers.generate();
|
||||||
defineLakesGroup();
|
Lakes.defineGroup();
|
||||||
Rivers.specify();
|
Rivers.specify();
|
||||||
if (!layerIsOn("toggleRivers")) toggleRivers();
|
if (!layerIsOn("toggleRivers")) toggleRivers();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ function editWorld() {
|
||||||
generatePrecipitation();
|
generatePrecipitation();
|
||||||
const heights = new Uint8Array(pack.cells.h);
|
const heights = new Uint8Array(pack.cells.h);
|
||||||
Rivers.generate();
|
Rivers.generate();
|
||||||
defineLakesGroup();
|
Lakes.defineGroup();
|
||||||
Rivers.specify();
|
Rivers.specify();
|
||||||
pack.cells.h = new Float32Array(heights);
|
pack.cells.h = new Float32Array(heights);
|
||||||
defineBiomes();
|
defineBiomes();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue