feat: edit routes - EP

This commit is contained in:
Azgaar 2024-05-04 12:44:08 +02:00
parent 68b4cfd370
commit 9b46e7b877
3 changed files with 69 additions and 82 deletions

View file

@ -1,43 +1,14 @@
"use strict"; "use strict";
function showEPForRoute(node) {
const points = [];
debug
.select("#controlPoints")
.selectAll("circle")
.each(function () {
const i = findCell(this.getAttribute("cx"), this.getAttribute("cy"));
points.push(i);
});
const routeLen = node.getTotalLength() * distanceScaleInput.value;
showElevationProfile(points, routeLen, false);
}
function showEPForRiver(node) {
const points = [];
debug
.select("#controlPoints")
.selectAll("circle")
.each(function () {
const i = findCell(this.getAttribute("cx"), this.getAttribute("cy"));
points.push(i);
});
const riverLen = (node.getTotalLength() / 2) * distanceScaleInput.value;
showElevationProfile(points, riverLen, true);
}
function showElevationProfile(data, routeLen, isRiver) {
// data is an array of cell indexes, routeLen is the distance (in actual metres/feet), isRiver should be true for rivers, false otherwise // data is an array of cell indexes, routeLen is the distance (in actual metres/feet), isRiver should be true for rivers, false otherwise
document.getElementById("epScaleRange").addEventListener("change", draw); function showElevationProfile(data, routeLen, isRiver) {
document.getElementById("epCurve").addEventListener("change", draw); byId("epScaleRange").on("change", draw);
document.getElementById("epSave").addEventListener("click", downloadCSV); byId("epCurve").on("change", draw);
byId("epSave").on("click", downloadCSV);
$("#elevationProfile").dialog({ $("#elevationProfile").dialog({
title: "Elevation profile", title: "Elevation profile",
resizable: false, resizable: false,
width: window.width,
close: closeElevationProfile, close: closeElevationProfile,
position: {my: "left top", at: "left+20 bottom-500", of: window, collision: "fit"} position: {my: "left top", at: "left+20 bottom-500", of: window, collision: "fit"}
}); });
@ -45,18 +16,20 @@ function showElevationProfile(data, routeLen, isRiver) {
// prevent river graphs from showing rivers as flowing uphill - remember the general slope // prevent river graphs from showing rivers as flowing uphill - remember the general slope
let slope = 0; let slope = 0;
if (isRiver) { if (isRiver) {
if (pack.cells.h[data[0]] < pack.cells.h[data[data.length - 1]]) { const firstCellHeight = pack.cells.h[data.at(0)];
const lastCellHeight = pack.cells.h[data.at(-1)];
if (firstCellHeight < lastCellHeight) {
slope = 1; // up-hill slope = 1; // up-hill
} else if (pack.cells.h[data[0]] > pack.cells.h[data[data.length - 1]]) { } else if (firstCellHeight > lastCellHeight) {
slope = -1; // down-hill slope = -1; // down-hill
} }
} }
const chartWidth = window.innerWidth - 180, const chartWidth = window.innerWidth - 200;
chartHeight = 300; // height of our land/sea profile, excluding the biomes data below const chartHeight = 300;
const xOffset = 80, const xOffset = 80;
yOffset = 80; // this is our drawing starting point from top-left (y = 0) of SVG const yOffset = 80;
const biomesHeight = 40; const biomesHeight = 10;
let lastBurgIndex = 0; let lastBurgIndex = 0;
let lastBurgCell = 0; let lastBurgCell = 0;
@ -170,7 +143,7 @@ function showElevationProfile(data, routeLen, isRiver) {
chartData.points.push([xscale(i) + xOffset, yscale(chartData.height[i]) + yOffset]); chartData.points.push([xscale(i) + xOffset, yscale(chartData.height[i]) + yOffset]);
} }
document.getElementById("elevationGraph").innerHTML = ""; byId("elevationGraph").innerHTML = "";
const chart = d3 const chart = d3
.select("#elevationGraph") .select("#elevationGraph")
@ -309,7 +282,7 @@ function showElevationProfile(data, routeLen, isRiver) {
.attr("x", x) .attr("x", x)
.attr("y", y) .attr("y", y)
.attr("width", xscale(1)) .attr("width", xscale(1))
.attr("height", 15) .attr("height", biomesHeight)
.attr("data-tip", dataTip); .attr("data-tip", dataTip);
} }
@ -387,7 +360,7 @@ function showElevationProfile(data, routeLen, isRiver) {
.attr("x", x1) .attr("x", x1)
.attr("y", y1) .attr("y", y1)
.attr("text-anchor", "middle"); .attr("text-anchor", "middle");
document.getElementById("ep" + b).innerHTML = pack.burgs[b].name; byId("ep" + b).innerHTML = pack.burgs[b].name;
// arrow from burg name to graph line // arrow from burg name to graph line
g.append("path") g.append("path")
@ -412,10 +385,10 @@ function showElevationProfile(data, routeLen, isRiver) {
} }
function closeElevationProfile() { function closeElevationProfile() {
document.getElementById("epScaleRange").removeEventListener("change", draw); byId("epScaleRange").removeEventListener("change", draw);
document.getElementById("epCurve").removeEventListener("change", draw); byId("epCurve").removeEventListener("change", draw);
document.getElementById("epSave").removeEventListener("click", downloadCSV); byId("epSave").removeEventListener("click", downloadCSV);
document.getElementById("elevationGraph").innerHTML = ""; byId("elevationGraph").innerHTML = "";
modules.elevation = false; modules.elevation = false;
} }
} }

View file

@ -5,7 +5,7 @@ function editRiver(id) {
closeDialogs(".stable"); closeDialogs(".stable");
if (!layerIsOn("toggleRivers")) toggleRivers(); if (!layerIsOn("toggleRivers")) toggleRivers();
document.getElementById("toggleCells").dataset.forced = +!layerIsOn("toggleCells"); byId("toggleCells").dataset.forced = +!layerIsOn("toggleCells");
if (!layerIsOn("toggleCells")) toggleCells(); if (!layerIsOn("toggleCells")) toggleCells();
elSelected = d3.select("#" + id).on("click", addControlPoint); elSelected = d3.select("#" + id).on("click", addControlPoint);
@ -36,18 +36,18 @@ function editRiver(id) {
modules.editRiver = true; modules.editRiver = true;
// add listeners // add listeners
document.getElementById("riverCreateSelectingCells").addEventListener("click", createRiver); byId("riverCreateSelectingCells").on("click", createRiver);
document.getElementById("riverEditStyle").addEventListener("click", () => editStyle("rivers")); byId("riverEditStyle").on("click", () => editStyle("rivers"));
document.getElementById("riverElevationProfile").addEventListener("click", showElevationProfile); byId("riverElevationProfile").on("click", showRiverElevationProfile);
document.getElementById("riverLegend").addEventListener("click", editRiverLegend); byId("riverLegend").on("click", editRiverLegend);
document.getElementById("riverRemove").addEventListener("click", removeRiver); byId("riverRemove").on("click", removeRiver);
document.getElementById("riverName").addEventListener("input", changeName); byId("riverName").on("input", changeName);
document.getElementById("riverType").addEventListener("input", changeType); byId("riverType").on("input", changeType);
document.getElementById("riverNameCulture").addEventListener("click", generateNameCulture); byId("riverNameCulture").on("click", generateNameCulture);
document.getElementById("riverNameRandom").addEventListener("click", generateNameRandom); byId("riverNameRandom").on("click", generateNameRandom);
document.getElementById("riverMainstem").addEventListener("change", changeParent); byId("riverMainstem").on("change", changeParent);
document.getElementById("riverSourceWidth").addEventListener("input", changeSourceWidth); byId("riverSourceWidth").on("input", changeSourceWidth);
document.getElementById("riverWidthFactor").addEventListener("input", changeWidthFactor); byId("riverWidthFactor").on("input", changeWidthFactor);
function getRiver() { function getRiver() {
const riverId = +elSelected.attr("id").slice(5); const riverId = +elSelected.attr("id").slice(5);
@ -58,10 +58,10 @@ function editRiver(id) {
function updateRiverData() { function updateRiverData() {
const r = getRiver(); const r = getRiver();
document.getElementById("riverName").value = r.name; byId("riverName").value = r.name;
document.getElementById("riverType").value = r.type; byId("riverType").value = r.type;
const parentSelect = document.getElementById("riverMainstem"); const parentSelect = byId("riverMainstem");
parentSelect.options.length = 0; parentSelect.options.length = 0;
const parent = r.parent || r.i; const parent = r.parent || r.i;
const sortedRivers = pack.rivers.slice().sort((a, b) => (a.name > b.name ? 1 : -1)); const sortedRivers = pack.rivers.slice().sort((a, b) => (a.name > b.name ? 1 : -1));
@ -69,11 +69,11 @@ function editRiver(id) {
const opt = new Option(river.name, river.i, false, river.i === parent); const opt = new Option(river.name, river.i, false, river.i === parent);
parentSelect.options.add(opt); parentSelect.options.add(opt);
}); });
document.getElementById("riverBasin").value = pack.rivers.find(river => river.i === r.basin).name; byId("riverBasin").value = pack.rivers.find(river => river.i === r.basin).name;
document.getElementById("riverDischarge").value = r.discharge + " m³/s"; byId("riverDischarge").value = r.discharge + " m³/s";
document.getElementById("riverSourceWidth").value = r.sourceWidth; byId("riverSourceWidth").value = r.sourceWidth;
document.getElementById("riverWidthFactor").value = r.widthFactor; byId("riverWidthFactor").value = r.widthFactor;
updateRiverLength(r); updateRiverLength(r);
updateRiverWidth(r); updateRiverWidth(r);
@ -82,7 +82,7 @@ function editRiver(id) {
function updateRiverLength(river) { function updateRiverLength(river) {
river.length = rn(elSelected.node().getTotalLength() / 2, 2); river.length = rn(elSelected.node().getTotalLength() / 2, 2);
const lengthUI = `${rn(river.length * distanceScaleInput.value)} ${distanceUnitInput.value}`; const lengthUI = `${rn(river.length * distanceScaleInput.value)} ${distanceUnitInput.value}`;
document.getElementById("riverLength").value = lengthUI; byId("riverLength").value = lengthUI;
} }
function updateRiverWidth(river) { function updateRiverWidth(river) {
@ -92,7 +92,7 @@ function editRiver(id) {
river.width = getWidth(getOffset(discharge, meanderedPoints.length, widthFactor, sourceWidth)); river.width = getWidth(getOffset(discharge, meanderedPoints.length, widthFactor, sourceWidth));
const width = `${rn(river.width * distanceScaleInput.value, 3)} ${distanceUnitInput.value}`; const width = `${rn(river.width * distanceScaleInput.value, 3)} ${distanceUnitInput.value}`;
document.getElementById("riverWidth").value = width; byId("riverWidth").value = width;
} }
function drawControlPoints(points) { function drawControlPoints(points) {
@ -166,7 +166,7 @@ function editRiver(id) {
elSelected.attr("d", path); elSelected.attr("d", path);
updateRiverLength(river); updateRiverLength(river);
if (modules.elevation) showEPForRiver(elSelected.node()); if (byId("elevationProfile").offsetParent) showRiverElevationProfile();
} }
function addControlPoint() { function addControlPoint() {
@ -212,7 +212,7 @@ function editRiver(id) {
const r = getRiver(); const r = getRiver();
r.parent = +this.value; r.parent = +this.value;
r.basin = pack.rivers.find(river => river.i === r.parent).basin; r.basin = pack.rivers.find(river => river.i === r.parent).basin;
document.getElementById("riverBasin").value = pack.rivers.find(river => river.i === r.basin).name; byId("riverBasin").value = pack.rivers.find(river => river.i === r.basin).name;
} }
function changeSourceWidth() { function changeSourceWidth() {
@ -229,9 +229,14 @@ function editRiver(id) {
redrawRiver(); redrawRiver();
} }
function showElevationProfile() { function showRiverElevationProfile() {
modules.elevation = true; const points = debug
showEPForRiver(elSelected.node()); .selectAll("#controlPoints > *")
.data()
.map(([x, y]) => findCell(x, y));
const river = getRiver();
const riverLen = rn(river.length * distanceScaleInput.value);
showElevationProfile(points, riverLen, true);
} }
function editRiverLegend() { function editRiverLegend() {
@ -269,8 +274,8 @@ function editRiver(id) {
unselect(); unselect();
clearMainTip(); clearMainTip();
const forced = +document.getElementById("toggleCells").dataset.forced; const forced = +byId("toggleCells").dataset.forced;
document.getElementById("toggleCells").dataset.forced = 0; byId("toggleCells").dataset.forced = 0;
if (forced && layerIsOn("toggleCells")) toggleCells(); if (forced && layerIsOn("toggleCells")) toggleCells();
} }
} }

View file

@ -35,8 +35,8 @@ function editRoute(id) {
// add listeners // add listeners
byId("routeCreateSelectingCells").on("click", createRoute); byId("routeCreateSelectingCells").on("click", createRoute);
byId("routeEditStyle").on("click", () => editStyle("routes")); byId("routeEditStyle").on("click", editRouteGroupStyle);
byId("routeElevationProfile").on("click", showElevationProfile); byId("routeElevationProfile").on("click", showRouteElevationProfile);
byId("routeLegend").on("click", editRouteLegend); byId("routeLegend").on("click", editRouteLegend);
byId("routeRemove").on("click", removeRoute); byId("routeRemove").on("click", removeRoute);
byId("routeName").on("input", changeName); byId("routeName").on("input", changeName);
@ -63,6 +63,9 @@ function editRoute(id) {
}); });
updateRouteLength(route); updateRouteLength(route);
const isWater = route.cells.some(cell => pack.cells.h[cell] < 20);
byId("routeElevationProfile").style.display = isWater ? "none" : "inline-block";
} }
function generateRouteName(route) { function generateRouteName(route) {
@ -153,7 +156,7 @@ function editRoute(id) {
elSelected.attr("d", path); elSelected.attr("d", path);
updateRouteLength(route); updateRouteLength(route);
if (modules.elevation) showEPForRoute(elSelected.node()); if (byId("elevationProfile").offsetParent) showRouteElevationProfile();
} }
function addControlPoint() { function addControlPoint() {
@ -248,9 +251,10 @@ function editRoute(id) {
route.name = routeName.value = Names.getBase(rand(nameBases.length - 1)); route.name = routeName.value = Names.getBase(rand(nameBases.length - 1));
} }
function showElevationProfile() { function showRouteElevationProfile() {
modules.elevation = true; const route = getRoute();
showEPForRoute(elSelected.node()); const routeLen = rn(route.length * distanceScaleInput.value);
showElevationProfile(route.cells, routeLen, false);
} }
function editRouteLegend() { function editRouteLegend() {
@ -259,6 +263,11 @@ function editRoute(id) {
editNotes(id, route.name); editNotes(id, route.name);
} }
function editRouteGroupStyle() {
const {group} = getRoute();
editStyle("routes", group);
}
function createRoute() { function createRoute() {
// TODO: white the code :) // TODO: white the code :)
} }