mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
v1.5.79 - river overview update
This commit is contained in:
parent
41d03e8039
commit
fbec08f982
7 changed files with 104 additions and 100 deletions
|
|
@ -1383,7 +1383,11 @@ div.states span.inactive:hover {
|
||||||
color: #abaaaa;
|
color: #abaaaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.states>input.riverType {
|
div.states > .riverName {
|
||||||
|
width: 7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.states > .riverType {
|
||||||
width: 5em;
|
width: 5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
18
index.html
18
index.html
|
|
@ -1611,7 +1611,7 @@
|
||||||
|
|
||||||
<div style="padding: .1em" data-tip="River width multiplier">
|
<div style="padding: .1em" data-tip="River width multiplier">
|
||||||
<div class="label">Width modifier:</div>
|
<div class="label">Width modifier:</div>
|
||||||
<input id="riverWidthFactor" type="number" min=.2 max=4 step=.1 />
|
<input id="riverWidthFactor" type="number" min=.1 max=4 step=.1 />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -3088,19 +3088,21 @@
|
||||||
|
|
||||||
<div id="riversOverview" class="dialog stable" style="display: none">
|
<div id="riversOverview" class="dialog stable" style="display: none">
|
||||||
<div id="riversHeader" class="header">
|
<div id="riversHeader" class="header">
|
||||||
<div style="left:1.7em" data-tip="Click to sort by river name" class="sortable alphabetically" data-sortby="name">River </div>
|
<div style="left:1.3em" data-tip="Click to sort by river name" class="sortable alphabetically" data-sortby="name">River </div>
|
||||||
<div style="left:7.9em" data-tip="Click to sort by river type name" class="sortable alphabetically" data-sortby="type">Type </div>
|
<div style="left:8.6em" data-tip="Click to sort by river type name" class="sortable alphabetically" data-sortby="type">Type </div>
|
||||||
<div style="left:11.9em" data-tip="Click to sort by discharge (flux in m3/s)" class="sortable icon-sort-number-down" data-sortby="discharge">Discharge </div>
|
<div style="left:13em" data-tip="Click to sort by discharge (flux in m3/s)" class="sortable icon-sort-number-down" data-sortby="discharge">Discharge </div>
|
||||||
<div style="left:18.2em" data-tip="Click to sort by river length" class="sortable" data-sortby="length">Length </div>
|
<div style="left:19.3em" data-tip="Click to sort by river length" class="sortable" data-sortby="length">Length </div>
|
||||||
<div style="left:23.4em" data-tip="Click to sort by river mouth width" class="sortable" data-sortby="width">Width </div>
|
<div style="left:24.4em" data-tip="Click to sort by river mouth width" class="sortable" data-sortby="width">Width </div>
|
||||||
<div style="left:29em" data-tip="Click to sort by river basin" class="sortable alphabetically" data-sortby="basin">Basin </div>
|
<div style="left:30em" data-tip="Click to sort by river basin" class="sortable alphabetically" data-sortby="basin">Basin </div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="riversBody" class="burgs-table"></div>
|
<div id="riversBody" class="burgs-table"></div>
|
||||||
|
|
||||||
<div id="riversFooter" class="totalLine">
|
<div id="riversFooter" class="totalLine">
|
||||||
<div data-tip="Rivers number" style="margin-left: 4px">Rivers: <span id="riversFooterNumber">0</span></div>
|
<div data-tip="Rivers number" style="margin-left: 4px">Rivers: <span id="riversFooterNumber">0</span></div>
|
||||||
<div data-tip="Average length" style="margin-left: 14px">Average length: <span id="riversFooterLength">0</span></div>
|
<div data-tip="Average discharge" style="margin-left: 12px">Average discharge: <span id="riversFooterDischarge">0</span></div>
|
||||||
|
<div data-tip="Average length" style="margin-left: 12px">Length: <span id="riversFooterLength">0</span></div>
|
||||||
|
<div data-tip="Average mouth width" style="margin-left: 12px">Width: <span id="riversFooterWidth">0</span></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="riversBottom">
|
<div id="riversBottom">
|
||||||
|
|
|
||||||
|
|
@ -607,7 +607,7 @@ function highlightElement(element) {
|
||||||
if (tr[0]) x += tr[0];
|
if (tr[0]) x += tr[0];
|
||||||
let y = box.y + box.height / 2;
|
let y = box.y + box.height / 2;
|
||||||
if (tr[1]) y += tr[1];
|
if (tr[1]) y += tr[1];
|
||||||
if (scale >= 2) zoomTo(x, y, scale, 1600);
|
zoomTo(x, y, scale > 2 ? scale : 3, 1600);
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectIcon(initial, callback) {
|
function selectIcon(initial, callback) {
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,10 @@ function showElevationProfile(data, routeLen, isRiver) {
|
||||||
for (let i = 0, prevB = 0, prevH = -1; i < data.length; i++) {
|
for (let i = 0, prevB = 0, prevH = -1; i < data.length; i++) {
|
||||||
let cell = data[i];
|
let cell = data[i];
|
||||||
let h = pack.cells.h[cell];
|
let h = pack.cells.h[cell];
|
||||||
if (h < 20) h = 20;
|
if (h < 20) {
|
||||||
|
const f = pack.features[pack.cells.f[cell]];
|
||||||
|
if (f.type === "lake") h = f.height; else h = 20;
|
||||||
|
}
|
||||||
|
|
||||||
// check for river up-hill
|
// check for river up-hill
|
||||||
if (prevH != -1) {
|
if (prevH != -1) {
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ function editRiver(id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRiver() {
|
function getRiver() {
|
||||||
const riverId = +node.id.slice(5);
|
const riverId = +elSelected.attr("id").slice(5);
|
||||||
const river = pack.rivers.find(r => r.i === riverId);
|
const river = pack.rivers.find(r => r.i === riverId);
|
||||||
return river;
|
return river;
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +78,7 @@ function editRiver(id) {
|
||||||
|
|
||||||
function drawControlPoints(node) {
|
function drawControlPoints(node) {
|
||||||
const length = getRiver().length;
|
const length = getRiver().length;
|
||||||
const segments = Math.ceil(length / 5);
|
const segments = Math.ceil(length / 4);
|
||||||
const increment = rn(length / segments * 1e5);
|
const increment = rn(length / segments * 1e5);
|
||||||
for (let i = increment * segments, c = i; i >= 0; i -= increment, c += increment) {
|
for (let i = increment * segments, c = i; i >= 0; i -= increment, c += increment) {
|
||||||
const p1 = node.getPointAtLength(i / 1e5);
|
const p1 = node.getPointAtLength(i / 1e5);
|
||||||
|
|
@ -89,7 +89,7 @@ function editRiver(id) {
|
||||||
|
|
||||||
function addControlPoint(point) {
|
function addControlPoint(point) {
|
||||||
debug.select("#controlPoints").append("circle")
|
debug.select("#controlPoints").append("circle")
|
||||||
.attr("cx", point[0]).attr("cy", point[1]).attr("r", .8)
|
.attr("cx", point[0]).attr("cy", point[1]).attr("r", .6)
|
||||||
.call(d3.drag().on("drag", dragControlPoint))
|
.call(d3.drag().on("drag", dragControlPoint))
|
||||||
.on("click", clickControlPoint);
|
.on("click", clickControlPoint);
|
||||||
}
|
}
|
||||||
|
|
@ -106,7 +106,7 @@ function editRiver(id) {
|
||||||
points.push([+this.getAttribute("cx"), +this.getAttribute("cy")]);
|
points.push([+this.getAttribute("cx"), +this.getAttribute("cy")]);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (points.length === 1) return;
|
if (points.length < 2) return;
|
||||||
if (points.length === 2) {
|
if (points.length === 2) {
|
||||||
const p0 = points[0], p1 = points[1];
|
const p0 = points[0], p1 = points[1];
|
||||||
const angle = Math.atan2(p1[1] - p0[1], p1[0] - p0[0]);
|
const angle = Math.atan2(p1[1] - p0[1], p1[0] - p0[0]);
|
||||||
|
|
@ -114,13 +114,20 @@ function editRiver(id) {
|
||||||
elSelected.attr("d", `M${p0[0]},${p0[1]} L${p1[0]},${p1[1]} l${-sin/2},${cos/2} Z`);
|
elSelected.attr("d", `M${p0[0]},${p0[1]} L${p1[0]},${p1[1]} l${-sin/2},${cos/2} Z`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const [d, length] = Rivers.getPath(points, +riverWidthInput.value, +riverIncrement.value);
|
|
||||||
elSelected.attr("d", d);
|
|
||||||
//updateRiverLength(length);
|
|
||||||
|
|
||||||
if (modules.elevation) {
|
const widthFactor = +document.getElementById("riverWidthFactor").value;
|
||||||
showEPForRiver(elSelected.node());
|
const sourceWidth = +document.getElementById("riverSourceWidth").value;
|
||||||
|
const [path, length, offset] = Rivers.getPath(points, widthFactor, sourceWidth);
|
||||||
|
elSelected.attr("d", path);
|
||||||
|
|
||||||
|
const r = getRiver();
|
||||||
|
if (r) {
|
||||||
|
r.width = rn(offset ** 2, 2);
|
||||||
|
r.length = length;
|
||||||
|
updateRiverData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (modules.elevation) showEPForRiver(elSelected.node());
|
||||||
}
|
}
|
||||||
|
|
||||||
function clickControlPoint() {
|
function clickControlPoint() {
|
||||||
|
|
@ -181,21 +188,25 @@ function editRiver(id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeSourceWidth() {
|
function changeSourceWidth() {
|
||||||
getRiver().sourceWidth = this.value;
|
getRiver().sourceWidth = +this.value;
|
||||||
redrawRiver();
|
redrawRiver();
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeWidthFactor() {
|
function changeWidthFactor() {
|
||||||
getRiver().widthFactor = this.value;
|
getRiver().widthFactor = +this.value;
|
||||||
redrawRiver();
|
redrawRiver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function showElevationProfile() {
|
function showElevationProfile() {
|
||||||
modules.elevation = true;
|
modules.elevation = true;
|
||||||
showEPForRiver(elSelected.node());
|
showEPForRiver(elSelected.node());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function editRiverLegend() {
|
||||||
|
const id = elSelected.attr("id");
|
||||||
|
editNotes(id, id);
|
||||||
|
}
|
||||||
|
|
||||||
function toggleRiverCreationMode() {
|
function toggleRiverCreationMode() {
|
||||||
if (document.getElementById("riverNew").classList.contains("pressed")) exitRiverCreationMode();
|
if (document.getElementById("riverNew").classList.contains("pressed")) exitRiverCreationMode();
|
||||||
else {
|
else {
|
||||||
|
|
@ -210,8 +221,7 @@ function editRiver(id) {
|
||||||
if (!elSelected.attr("data-new")) {
|
if (!elSelected.attr("data-new")) {
|
||||||
debug.select("#controlPoints").selectAll("circle").remove();
|
debug.select("#controlPoints").selectAll("circle").remove();
|
||||||
const id = getNextId("river");
|
const id = getNextId("river");
|
||||||
elSelected = d3.select(elSelected.node().parentNode).append("path").attr("id", id)
|
elSelected = d3.select(elSelected.node().parentNode).append("path").attr("id", id).attr("data-new", 1);
|
||||||
.attr("data-new", 1).attr("data-width", 1).attr("data-increment", .5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add control point
|
// add control point
|
||||||
|
|
@ -220,9 +230,38 @@ function editRiver(id) {
|
||||||
redrawRiver();
|
redrawRiver();
|
||||||
}
|
}
|
||||||
|
|
||||||
function editRiverLegend() {
|
function exitRiverCreationMode() {
|
||||||
const id = elSelected.attr("id");
|
riverNew.classList.remove("pressed");
|
||||||
editNotes(id, id);
|
clearMainTip();
|
||||||
|
viewbox.on("click", clicked).style("cursor", "default");
|
||||||
|
elSelected.on("click", addInterimControlPoint);
|
||||||
|
|
||||||
|
if (!elSelected.attr("data-new")) return; // no need to create a new river
|
||||||
|
elSelected.attr("data-new", null);
|
||||||
|
|
||||||
|
// add a river
|
||||||
|
const r = +elSelected.attr("id").slice(5);
|
||||||
|
const node = elSelected.node(), length = node.getTotalLength() / 2;
|
||||||
|
|
||||||
|
const cells = [];
|
||||||
|
const segments = Math.ceil(length / 4), increment = rn(length / segments * 1e5);
|
||||||
|
for (let i = increment * segments, c = i; i >= 0; i -= increment, c += increment) {
|
||||||
|
const p = node.getPointAtLength(i / 1e5);
|
||||||
|
const cell = findCell(p.x, p.y);
|
||||||
|
if (!pack.cells.r[cell]) pack.cells.r[cell] = r;
|
||||||
|
cells.push(cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
const source = cells[0], mouth = last(cells);
|
||||||
|
const name = Rivers.getName(mouth);
|
||||||
|
const smallLength = pack.rivers.map(r => r.length||0).sort((a,b) => a-b)[Math.ceil(pack.rivers.length * .15)];
|
||||||
|
const type = length < smallLength ? rw({"Creek":9, "River":3, "Brook":3, "Stream":1}) : "River";
|
||||||
|
|
||||||
|
const discharge = rn(cells.length * 20 * Math.random());
|
||||||
|
const widthFactor = +document.getElementById("riverWidthFactor").value;
|
||||||
|
const sourceWidth = +document.getElementById("riverSourceWidth").value;
|
||||||
|
|
||||||
|
pack.rivers.push({i:r, source, mouth, discharge, length, width: sourceWidth, widthFactor, sourceWidth, parent:0, name, type, basin:r});
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeRiver() {
|
function removeRiver() {
|
||||||
|
|
@ -240,40 +279,10 @@ function editRiver(id) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function exitRiverCreationMode() {
|
|
||||||
riverNew.classList.remove("pressed");
|
|
||||||
clearMainTip();
|
|
||||||
viewbox.on("click", clicked).style("cursor", "default");
|
|
||||||
elSelected.on("click", addInterimControlPoint);
|
|
||||||
|
|
||||||
if (!elSelected.attr("data-new")) return; // no need to create a new river
|
|
||||||
elSelected.attr("data-new", null);
|
|
||||||
|
|
||||||
// add a river
|
|
||||||
const r = +elSelected.attr("id").slice(5);
|
|
||||||
const node = elSelected.node(), length = node.getTotalLength() / 2;
|
|
||||||
|
|
||||||
const cells = [];
|
|
||||||
const segments = Math.ceil(length / 8), increment = rn(length / segments * 1e5);
|
|
||||||
for (let i=increment*segments, c=i; i >= 0; i -= increment, c += increment) {
|
|
||||||
const p = node.getPointAtLength(i / 1e5);
|
|
||||||
const cell = findCell(p.x, p.y);
|
|
||||||
if (!pack.cells.r[cell]) pack.cells.r[cell] = r;
|
|
||||||
cells.push(cell);
|
|
||||||
}
|
|
||||||
|
|
||||||
const source = cells[0], mouth = last(cells);
|
|
||||||
const name = Rivers.getName(mouth);
|
|
||||||
const smallLength = pack.rivers.map(r => r.length||0).sort((a,b) => a-b)[Math.ceil(pack.rivers.length * .15)];
|
|
||||||
const type = length < smallLength ? rw({"Creek":9, "River":3, "Brook":3, "Stream":1}) : "River";
|
|
||||||
pack.rivers.push({i:r, parent:0, length, source, mouth, basin:r, name, type});
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeRiverEditor() {
|
function closeRiverEditor() {
|
||||||
exitRiverCreationMode();
|
exitRiverCreationMode();
|
||||||
elSelected.on("click", null);
|
elSelected.on("click", null);
|
||||||
debug.select("#controlPoints").remove();
|
debug.select("#controlPoints").remove();
|
||||||
unselect();
|
unselect();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,17 +27,18 @@ function overviewRivers() {
|
||||||
function riversOverviewAddLines() {
|
function riversOverviewAddLines() {
|
||||||
body.innerHTML = "";
|
body.innerHTML = "";
|
||||||
let lines = "";
|
let lines = "";
|
||||||
|
const unit = distanceUnitInput.value;
|
||||||
|
|
||||||
for (const r of pack.rivers) {
|
for (const r of pack.rivers) {
|
||||||
const discharge = r.discharge + " m³/s";
|
const discharge = r.discharge + " m³/s";
|
||||||
const length = rn(r.length * distanceScaleInput.value) + " " + distanceUnitInput.value;
|
const length = rn(r.length * distanceScaleInput.value) + " " + unit;
|
||||||
const width = rn(r.width * distanceScaleInput.value, 3) + " " + distanceUnitInput.value;
|
const width = rn(r.width * distanceScaleInput.value, 3) + " " + unit;
|
||||||
const basin = pack.rivers.find(river => river.i === r.basin).name;
|
const basin = pack.rivers.find(river => river.i === r.basin).name;
|
||||||
|
|
||||||
lines += `<div class="states" data-id=${r.i} data-name="${r.name}" data-type="${r.type}" data-discharge="${r.discharge}" data-length="${r.length}" data-width="${r.width}" data-basin="${basin}">
|
lines += `<div class="states" data-id=${r.i} data-name="${r.name}" data-type="${r.type}" data-discharge="${r.discharge}" data-length="${r.length}" data-width="${r.width}" data-basin="${basin}">
|
||||||
<span data-tip="Click to focus on river" class="icon-dot-circled pointer"></span>
|
<span data-tip="Click to focus on river" class="icon-dot-circled pointer"></span>
|
||||||
<input data-tip="River proper name. Click to change. Ctrl + click to regenerate" class="riverName" value="${r.name}" autocorrect="off" spellcheck="false">
|
<div data-tip="River name" class="riverName">${r.name}</div>
|
||||||
<input data-tip="River type name. Click to change" class="riverType" value="${r.type}">
|
<div data-tip="River type name" class="riverType">${r.type}</div>
|
||||||
<div data-tip="River discharge (flux power)" class="biomeArea">${discharge}</div>
|
<div data-tip="River discharge (flux power)" class="biomeArea">${discharge}</div>
|
||||||
<div data-tip="River length from source to mouth" class="biomeArea">${length}</div>
|
<div data-tip="River length from source to mouth" class="biomeArea">${length}</div>
|
||||||
<div data-tip="River mouth width" class="biomeArea">${width}</div>
|
<div data-tip="River mouth width" class="biomeArea">${width}</div>
|
||||||
|
|
@ -50,15 +51,16 @@ function overviewRivers() {
|
||||||
|
|
||||||
// update footer
|
// update footer
|
||||||
riversFooterNumber.innerHTML = pack.rivers.length;
|
riversFooterNumber.innerHTML = pack.rivers.length;
|
||||||
const averageLength = rn(d3.sum(pack.rivers.map(r => r.length)) / pack.rivers.length);
|
const averageDischarge = rn(d3.mean(pack.rivers.map(r => r.discharge)));
|
||||||
riversFooterLength.innerHTML = (averageLength * distanceScaleInput.value) + " " + distanceUnitInput.value;
|
riversFooterDischarge.innerHTML = averageDischarge + " m³/s";
|
||||||
|
const averageLength = rn(d3.mean(pack.rivers.map(r => r.length)) );
|
||||||
|
riversFooterLength.innerHTML = (averageLength * distanceScaleInput.value) + " " + unit;
|
||||||
|
const averageWidth = rn(d3.mean(pack.rivers.map(r => r.width)), 3);
|
||||||
|
riversFooterWidth.innerHTML = rn(averageWidth * distanceScaleInput.value, 3) + " " + unit;
|
||||||
|
|
||||||
// add listeners
|
// add listeners
|
||||||
body.querySelectorAll("div.states").forEach(el => el.addEventListener("mouseenter", ev => riverHighlightOn(ev)));
|
body.querySelectorAll("div.states").forEach(el => el.addEventListener("mouseenter", ev => riverHighlightOn(ev)));
|
||||||
body.querySelectorAll("div.states").forEach(el => el.addEventListener("mouseleave", ev => riverHighlightOff(ev)));
|
body.querySelectorAll("div.states").forEach(el => el.addEventListener("mouseleave", ev => riverHighlightOff(ev)));
|
||||||
body.querySelectorAll("div > input.riverName").forEach(el => el.addEventListener("input", changeRiverName));
|
|
||||||
body.querySelectorAll("div > input.riverName").forEach(el => el.addEventListener("click", regenerateRiverName));
|
|
||||||
body.querySelectorAll("div > input.riverType").forEach(el => el.addEventListener("input", changeRiverType));
|
|
||||||
body.querySelectorAll("div > span.icon-dot-circled").forEach(el => el.addEventListener("click", zoomToRiver));
|
body.querySelectorAll("div > span.icon-dot-circled").forEach(el => el.addEventListener("click", zoomToRiver));
|
||||||
body.querySelectorAll("div > span.icon-pencil").forEach(el => el.addEventListener("click", openRiverEditor));
|
body.querySelectorAll("div > span.icon-pencil").forEach(el => el.addEventListener("click", openRiverEditor));
|
||||||
body.querySelectorAll("div > span.icon-trash-empty").forEach(el => el.addEventListener("click", triggerRiverRemove));
|
body.querySelectorAll("div > span.icon-trash-empty").forEach(el => el.addEventListener("click", triggerRiverRemove));
|
||||||
|
|
@ -72,32 +74,11 @@ function overviewRivers() {
|
||||||
rivers.select("#river"+r).attr("stroke", "red").attr("stroke-width", 1);
|
rivers.select("#river"+r).attr("stroke", "red").attr("stroke-width", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function riverHighlightOff() {
|
function riverHighlightOff(e) {
|
||||||
const r = +event.target.dataset.id;
|
const r = +e.target.dataset.id;
|
||||||
rivers.select("#river"+r).attr("stroke", null).attr("stroke-width", null);
|
rivers.select("#river"+r).attr("stroke", null).attr("stroke-width", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeRiverName() {
|
|
||||||
if (this.value == "") tip("Please provide a proper name", false, "error");
|
|
||||||
const river = +this.parentNode.dataset.id;
|
|
||||||
pack.rivers.find(r => r.i === river).name = this.value;
|
|
||||||
this.parentNode.dataset.name = this.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function regenerateRiverName(event) {
|
|
||||||
if (!isCtrlClick(event)) return;
|
|
||||||
const river = +this.parentNode.dataset.id;
|
|
||||||
const r = pack.rivers.find(r => r.i === river);
|
|
||||||
r.name = this.value = this.parentNode.dataset.name = Rivers.getName(r.mouth);
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeRiverType() {
|
|
||||||
if (this.value == "") tip("Please provide a type name", false, "error");
|
|
||||||
const river = +this.parentNode.dataset.id;
|
|
||||||
pack.rivers.find(r => r.i === river).type = this.value;
|
|
||||||
this.parentNode.dataset.type = this.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function zoomToRiver() {
|
function zoomToRiver() {
|
||||||
const r = +this.parentNode.dataset.id;
|
const r = +this.parentNode.dataset.id;
|
||||||
const river = rivers.select("#river"+r).node();
|
const river = rivers.select("#river"+r).node();
|
||||||
|
|
|
||||||
|
|
@ -522,25 +522,30 @@ function addRiverOnClick() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const points = Rivers.addMeandering(dataRiver, 1, .5);
|
const points = Rivers.addMeandering(dataRiver, 1, .5);
|
||||||
const width = Math.random() * .5 + .9;
|
const widthFactor = rn(.8 + Math.random() * .4, 1); // river width modifier [.8, 1.2]
|
||||||
const increment = Math.random() * .4 + .8;
|
const sourceWidth = .1;
|
||||||
const [path, length] = Rivers.getPath(points, width, increment);
|
const [path, length, offset] = Rivers.getPath(points, widthFactor, sourceWidth);
|
||||||
rivers.append("path").attr("d", path).attr("id", "river"+river).attr("data-width", width).attr("data-increment", increment);
|
rivers.append("path").attr("d", path).attr("id", "river"+river);
|
||||||
|
|
||||||
// add new river to data or change extended river attributes
|
// add new river to data or change extended river attributes
|
||||||
const r = pack.rivers.find(r => r.i === river);
|
const r = pack.rivers.find(r => r.i === river);
|
||||||
|
const mouth = last(dataRiver).cell;
|
||||||
|
const discharge = cells.fl[mouth]; // in m3/s
|
||||||
|
|
||||||
if (r) {
|
if (r) {
|
||||||
r.source = dataRiver[0].cell;
|
r.source = dataRiver[0].cell;
|
||||||
r.length = length;
|
r.length = length;
|
||||||
|
r.discharge = discharge;
|
||||||
} else {
|
} else {
|
||||||
const parent = dataRiver[0].parent || 0;
|
const parent = dataRiver[0].parent || 0;
|
||||||
const basin = Rivers.getBasin(river);
|
const basin = Rivers.getBasin(river);
|
||||||
const source = dataRiver[0].cell;
|
const source = dataRiver[0].cell;
|
||||||
const mouth = last(dataRiver).cell;
|
const width = rn(offset ** 2, 2); // mounth width in km
|
||||||
const name = Rivers.getName(mouth);
|
const name = Rivers.getName(mouth);
|
||||||
const smallLength = pack.rivers.map(r => r.length||0).sort((a,b) => a-b)[Math.ceil(pack.rivers.length * .15)];
|
const smallLength = pack.rivers.map(r => r.length||0).sort((a,b) => a-b)[Math.ceil(pack.rivers.length * .15)];
|
||||||
const type = length < smallLength ? rw({"Creek":9, "River":3, "Brook":3, "Stream":1}) : "River";
|
const type = length < smallLength ? rw({"Creek":9, "River":3, "Brook":3, "Stream":1}) : "River";
|
||||||
pack.rivers.push({i:river, parent, length, source, mouth, basin, name, type});
|
|
||||||
|
pack.rivers.push({i:river, source, mouth, discharge, length, width, widthFactor, sourceWidth, parent, basin, name, type});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d3.event.shiftKey === false) {
|
if (d3.event.shiftKey === false) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue