rivers editor - optimize

This commit is contained in:
Azgaar 2021-07-25 13:52:10 +03:00
parent a1425bcb54
commit c5698c5a11
3 changed files with 15 additions and 106 deletions

View file

@ -991,12 +991,6 @@ body button.noicon {
stroke-width: 0.4; stroke-width: 0.4;
} }
#controlCells > .available {
fill: #82ff9b40;
stroke: #82ff9b;
stroke-width: 0.4;
}
#controlCells > .occupied { #controlCells > .occupied {
fill: #ff828240; fill: #ff828240;
stroke: #ff8282; stroke: #ff8282;

View file

@ -1656,7 +1656,6 @@
</div> </div>
<div id="riverBottom"> <div id="riverBottom">
<button id="riverNew" data-tip="Create new river clicking on map" class="icon-map-pin"></button>
<button id="riverEditStyle" data-tip="Edit style for all rivers in Style Editor" class="icon-brush"></button> <button id="riverEditStyle" data-tip="Edit style for all rivers in Style Editor" class="icon-brush"></button>
<button id="riverElevationProfile" data-tip="Show the elevation profile for the river" class="icon-chart-area"></button> <button id="riverElevationProfile" data-tip="Show the elevation profile for the river" class="icon-chart-area"></button>
<button id="riverLegend" data-tip="Edit free text notes (legend) for the river" class="icon-edit"></button> <button id="riverLegend" data-tip="Edit free text notes (legend) for the river" class="icon-edit"></button>

View file

@ -10,7 +10,7 @@ function editRiver(id) {
elSelected = d3.select("#" + id); elSelected = d3.select("#" + id);
viewbox.on("touchmove mousemove", showEditorTips); tip("Drag control points to change the river course. For major changes please create a new river instead", true);
debug.append("g").attr("id", "controlCells"); debug.append("g").attr("id", "controlCells");
debug.append("g").attr("id", "controlPoints"); debug.append("g").attr("id", "controlPoints");
@ -20,7 +20,7 @@ function editRiver(id) {
const {cells, points} = river; const {cells, points} = river;
const riverPoints = Rivers.getRiverPoints(cells, points); const riverPoints = Rivers.getRiverPoints(cells, points);
drawControlPoints(riverPoints, cells); drawControlPoints(riverPoints, cells);
drawRiverCells(cells); drawCells(cells, "current");
$("#riverEditor").dialog({ $("#riverEditor").dialog({
title: "Edit River", title: "Edit River",
@ -40,17 +40,11 @@ function editRiver(id) {
document.getElementById("riverMainstem").addEventListener("change", changeParent); document.getElementById("riverMainstem").addEventListener("change", changeParent);
document.getElementById("riverSourceWidth").addEventListener("input", changeSourceWidth); document.getElementById("riverSourceWidth").addEventListener("input", changeSourceWidth);
document.getElementById("riverWidthFactor").addEventListener("input", changeWidthFactor); document.getElementById("riverWidthFactor").addEventListener("input", changeWidthFactor);
document.getElementById("riverNew").addEventListener("click", toggleRiverCreationMode);
document.getElementById("riverEditStyle").addEventListener("click", () => editStyle("rivers")); document.getElementById("riverEditStyle").addEventListener("click", () => editStyle("rivers"));
document.getElementById("riverElevationProfile").addEventListener("click", showElevationProfile); document.getElementById("riverElevationProfile").addEventListener("click", showElevationProfile);
document.getElementById("riverLegend").addEventListener("click", editRiverLegend); document.getElementById("riverLegend").addEventListener("click", editRiverLegend);
document.getElementById("riverRemove").addEventListener("click", removeRiver); document.getElementById("riverRemove").addEventListener("click", removeRiver);
function showEditorTips() {
tip("Drag control points for minor change, to change cells add a new river", true);
showMainTip();
}
function getRiver() { function getRiver() {
const riverId = +elSelected.attr("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);
@ -112,52 +106,34 @@ function editRiver(id) {
.call(d3.drag().on("start", dragControlPoint)); .call(d3.drag().on("start", dragControlPoint));
} }
function drawRiverCells(cells) { function drawCells(cells, type) {
debug debug
.select("#controlCells") .select("#controlCells")
.selectAll("polygon.current") .selectAll(`polygon.${type}`)
.data(cells) .data(cells)
.join("polygon") .join("polygon")
.attr("points", d => getPackPolygon(d)) .attr("points", d => getPackPolygon(d))
.attr("class", "current"); .attr("class", type);
}
function drawAvailableCells(cells) {
debug
.select("#controlCells")
.selectAll("polygon.available")
.data(cells)
.join("polygon")
.attr("points", d => getPackPolygon(d))
.attr("class", "available");
} }
function dragControlPoint() { function dragControlPoint() {
const {c, r, fl, conf} = pack.cells; const {i, r, fl} = pack.cells;
const river = getRiver(); const river = getRiver();
const {cells} = river;
const initCell = +this.dataset.cell; const initCell = +this.dataset.cell;
const index = +this.dataset.i; const index = +this.dataset.i;
const prev = cells[index - 1];
const next = cells[index + 1];
const availableCells = conf[initCell]
? []
: c[initCell]
.filter(neib => !r[neib])
.filter(neib => !prev || c[neib].includes(prev))
.filter(neib => !next || c[neib].includes(next));
const occupiedCells = i.filter(i => r[i] && !river.cells.includes(i));
drawCells(occupiedCells, "occupied");
let movedToCell = null; let movedToCell = null;
drawAvailableCells(availableCells);
d3.event.on("drag", function () { d3.event.on("drag", function () {
const {x, y} = d3.event; const {x, y} = d3.event;
const currentCell = findCell(x, y); const currentCell = findCell(x, y);
if (initCell !== currentCell) { if (initCell !== currentCell) {
if (availableCells.includes(currentCell)) movedToCell = currentCell; if (occupiedCells.includes(currentCell)) return;
else return; movedToCell = currentCell;
} else movedToCell = null; } else movedToCell = null;
this.setAttribute("cx", x); this.setAttribute("cx", x);
@ -170,16 +146,17 @@ function editRiver(id) {
if (movedToCell) { if (movedToCell) {
this.dataset.cell = movedToCell; this.dataset.cell = movedToCell;
river.cells[index] = movedToCell; river.cells[index] = movedToCell;
drawCells(river.cells, "current");
// swap river data
r[initCell] = 0; r[initCell] = 0;
r[movedToCell] = river.i; r[movedToCell] = river.i;
const sourceFlux = fl[initCell]; const sourceFlux = fl[initCell];
fl[initCell] = fl[movedToCell]; fl[initCell] = fl[movedToCell];
fl[movedToCell] = sourceFlux; fl[movedToCell] = sourceFlux;
drawRiverCells(river.cells);
} }
debug.select("#controlCells").selectAll("polygon.available").remove(); debug.select("#controlCells").selectAll("polygon.available, polygon.occupied").remove();
}); });
} }
@ -247,66 +224,6 @@ function editRiver(id) {
editNotes(id, river.name + " " + river.type); editNotes(id, river.name + " " + river.type);
} }
function toggleRiverCreationMode() {
if (document.getElementById("riverNew").classList.contains("pressed")) exitRiverCreationMode();
else {
document.getElementById("riverNew").classList.add("pressed");
tip("Click on map to add control points", true, "warn");
viewbox.on("click", addPointOnClick).style("cursor", "crosshair");
elSelected.on("click", null);
}
}
function addPointOnClick() {
if (!elSelected.attr("data-new")) {
debug.select("#controlPoints").selectAll("circle").remove();
const id = getNextId("river");
elSelected = d3.select(elSelected.node().parentNode).append("path").attr("id", id).attr("data-new", 1);
}
// add control point
const point = d3.mouse(this);
// addControlPoint([point[0], point[1]]);
redrawRiver();
}
function exitRiverCreationMode() {
riverNew.classList.remove("pressed");
clearMainTip();
viewbox.on("click", clicked).style("cursor", "default");
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();
const length = node.getTotalLength() / 2;
const cells = [];
const segments = Math.ceil(length / 4);
const 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];
const 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 * 0.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() {
alertMessage.innerHTML = "Are you sure you want to remove the river and all its tributaries"; alertMessage.innerHTML = "Are you sure you want to remove the river and all its tributaries";
$("#alert").dialog({ $("#alert").dialog({
@ -318,7 +235,7 @@ function editRiver(id) {
$(this).dialog("close"); $(this).dialog("close");
const river = +elSelected.attr("id").slice(5); const river = +elSelected.attr("id").slice(5);
Rivers.remove(river); Rivers.remove(river);
elSelected.remove(); // keep if river if missed in pack.rivers elSelected.remove();
$("#riverEditor").dialog("close"); $("#riverEditor").dialog("close");
}, },
Cancel: function () { Cancel: function () {
@ -329,11 +246,10 @@ function editRiver(id) {
} }
function closeRiverEditor() { function closeRiverEditor() {
exitRiverCreationMode();
elSelected.on("click", null);
debug.select("#controlPoints").remove(); debug.select("#controlPoints").remove();
debug.select("#controlCells").remove(); debug.select("#controlCells").remove();
unselect(); unselect();
clearMainTip();
const forced = +document.getElementById("toggleCells").dataset.forced; const forced = +document.getElementById("toggleCells").dataset.forced;
document.getElementById("toggleCells").dataset.forced = 0; document.getElementById("toggleCells").dataset.forced = 0;