diff --git a/modules/ui/elevation-profile.js b/modules/ui/elevation-profile.js index 7c180d37..b791e99b 100644 --- a/modules/ui/elevation-profile.js +++ b/modules/ui/elevation-profile.js @@ -1,43 +1,14 @@ "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); -} - +// data is an array of cell indexes, routeLen is the distance (in actual metres/feet), isRiver should be true for rivers, false otherwise 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 - document.getElementById("epScaleRange").addEventListener("change", draw); - document.getElementById("epCurve").addEventListener("change", draw); - document.getElementById("epSave").addEventListener("click", downloadCSV); + byId("epScaleRange").on("change", draw); + byId("epCurve").on("change", draw); + byId("epSave").on("click", downloadCSV); $("#elevationProfile").dialog({ title: "Elevation profile", resizable: false, - width: window.width, close: closeElevationProfile, 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 let slope = 0; 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 - } else if (pack.cells.h[data[0]] > pack.cells.h[data[data.length - 1]]) { + } else if (firstCellHeight > lastCellHeight) { slope = -1; // down-hill } } - const chartWidth = window.innerWidth - 180, - chartHeight = 300; // height of our land/sea profile, excluding the biomes data below - const xOffset = 80, - yOffset = 80; // this is our drawing starting point from top-left (y = 0) of SVG - const biomesHeight = 40; + const chartWidth = window.innerWidth - 200; + const chartHeight = 300; + const xOffset = 80; + const yOffset = 80; + const biomesHeight = 10; let lastBurgIndex = 0; let lastBurgCell = 0; @@ -170,7 +143,7 @@ function showElevationProfile(data, routeLen, isRiver) { chartData.points.push([xscale(i) + xOffset, yscale(chartData.height[i]) + yOffset]); } - document.getElementById("elevationGraph").innerHTML = ""; + byId("elevationGraph").innerHTML = ""; const chart = d3 .select("#elevationGraph") @@ -309,7 +282,7 @@ function showElevationProfile(data, routeLen, isRiver) { .attr("x", x) .attr("y", y) .attr("width", xscale(1)) - .attr("height", 15) + .attr("height", biomesHeight) .attr("data-tip", dataTip); } @@ -387,7 +360,7 @@ function showElevationProfile(data, routeLen, isRiver) { .attr("x", x1) .attr("y", y1) .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 g.append("path") @@ -412,10 +385,10 @@ function showElevationProfile(data, routeLen, isRiver) { } function closeElevationProfile() { - document.getElementById("epScaleRange").removeEventListener("change", draw); - document.getElementById("epCurve").removeEventListener("change", draw); - document.getElementById("epSave").removeEventListener("click", downloadCSV); - document.getElementById("elevationGraph").innerHTML = ""; + byId("epScaleRange").removeEventListener("change", draw); + byId("epCurve").removeEventListener("change", draw); + byId("epSave").removeEventListener("click", downloadCSV); + byId("elevationGraph").innerHTML = ""; modules.elevation = false; } } diff --git a/modules/ui/rivers-editor.js b/modules/ui/rivers-editor.js index 499d8f31..95f7593e 100644 --- a/modules/ui/rivers-editor.js +++ b/modules/ui/rivers-editor.js @@ -5,7 +5,7 @@ function editRiver(id) { closeDialogs(".stable"); if (!layerIsOn("toggleRivers")) toggleRivers(); - document.getElementById("toggleCells").dataset.forced = +!layerIsOn("toggleCells"); + byId("toggleCells").dataset.forced = +!layerIsOn("toggleCells"); if (!layerIsOn("toggleCells")) toggleCells(); elSelected = d3.select("#" + id).on("click", addControlPoint); @@ -36,18 +36,18 @@ function editRiver(id) { modules.editRiver = true; // add listeners - document.getElementById("riverCreateSelectingCells").addEventListener("click", createRiver); - document.getElementById("riverEditStyle").addEventListener("click", () => editStyle("rivers")); - document.getElementById("riverElevationProfile").addEventListener("click", showElevationProfile); - document.getElementById("riverLegend").addEventListener("click", editRiverLegend); - document.getElementById("riverRemove").addEventListener("click", removeRiver); - document.getElementById("riverName").addEventListener("input", changeName); - document.getElementById("riverType").addEventListener("input", changeType); - document.getElementById("riverNameCulture").addEventListener("click", generateNameCulture); - document.getElementById("riverNameRandom").addEventListener("click", generateNameRandom); - document.getElementById("riverMainstem").addEventListener("change", changeParent); - document.getElementById("riverSourceWidth").addEventListener("input", changeSourceWidth); - document.getElementById("riverWidthFactor").addEventListener("input", changeWidthFactor); + byId("riverCreateSelectingCells").on("click", createRiver); + byId("riverEditStyle").on("click", () => editStyle("rivers")); + byId("riverElevationProfile").on("click", showRiverElevationProfile); + byId("riverLegend").on("click", editRiverLegend); + byId("riverRemove").on("click", removeRiver); + byId("riverName").on("input", changeName); + byId("riverType").on("input", changeType); + byId("riverNameCulture").on("click", generateNameCulture); + byId("riverNameRandom").on("click", generateNameRandom); + byId("riverMainstem").on("change", changeParent); + byId("riverSourceWidth").on("input", changeSourceWidth); + byId("riverWidthFactor").on("input", changeWidthFactor); function getRiver() { const riverId = +elSelected.attr("id").slice(5); @@ -58,10 +58,10 @@ function editRiver(id) { function updateRiverData() { const r = getRiver(); - document.getElementById("riverName").value = r.name; - document.getElementById("riverType").value = r.type; + byId("riverName").value = r.name; + byId("riverType").value = r.type; - const parentSelect = document.getElementById("riverMainstem"); + const parentSelect = byId("riverMainstem"); parentSelect.options.length = 0; const parent = r.parent || r.i; 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); 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"; - document.getElementById("riverSourceWidth").value = r.sourceWidth; - document.getElementById("riverWidthFactor").value = r.widthFactor; + byId("riverDischarge").value = r.discharge + " m³/s"; + byId("riverSourceWidth").value = r.sourceWidth; + byId("riverWidthFactor").value = r.widthFactor; updateRiverLength(r); updateRiverWidth(r); @@ -82,7 +82,7 @@ function editRiver(id) { function updateRiverLength(river) { river.length = rn(elSelected.node().getTotalLength() / 2, 2); const lengthUI = `${rn(river.length * distanceScaleInput.value)} ${distanceUnitInput.value}`; - document.getElementById("riverLength").value = lengthUI; + byId("riverLength").value = lengthUI; } function updateRiverWidth(river) { @@ -92,7 +92,7 @@ function editRiver(id) { river.width = getWidth(getOffset(discharge, meanderedPoints.length, widthFactor, sourceWidth)); const width = `${rn(river.width * distanceScaleInput.value, 3)} ${distanceUnitInput.value}`; - document.getElementById("riverWidth").value = width; + byId("riverWidth").value = width; } function drawControlPoints(points) { @@ -166,7 +166,7 @@ function editRiver(id) { elSelected.attr("d", path); updateRiverLength(river); - if (modules.elevation) showEPForRiver(elSelected.node()); + if (byId("elevationProfile").offsetParent) showRiverElevationProfile(); } function addControlPoint() { @@ -212,7 +212,7 @@ function editRiver(id) { const r = getRiver(); r.parent = +this.value; 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() { @@ -229,9 +229,14 @@ function editRiver(id) { redrawRiver(); } - function showElevationProfile() { - modules.elevation = true; - showEPForRiver(elSelected.node()); + function showRiverElevationProfile() { + const points = debug + .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() { @@ -269,8 +274,8 @@ function editRiver(id) { unselect(); clearMainTip(); - const forced = +document.getElementById("toggleCells").dataset.forced; - document.getElementById("toggleCells").dataset.forced = 0; + const forced = +byId("toggleCells").dataset.forced; + byId("toggleCells").dataset.forced = 0; if (forced && layerIsOn("toggleCells")) toggleCells(); } } diff --git a/modules/ui/routes-editor.js b/modules/ui/routes-editor.js index 786a7fd1..bb91d455 100644 --- a/modules/ui/routes-editor.js +++ b/modules/ui/routes-editor.js @@ -35,8 +35,8 @@ function editRoute(id) { // add listeners byId("routeCreateSelectingCells").on("click", createRoute); - byId("routeEditStyle").on("click", () => editStyle("routes")); - byId("routeElevationProfile").on("click", showElevationProfile); + byId("routeEditStyle").on("click", editRouteGroupStyle); + byId("routeElevationProfile").on("click", showRouteElevationProfile); byId("routeLegend").on("click", editRouteLegend); byId("routeRemove").on("click", removeRoute); byId("routeName").on("input", changeName); @@ -63,6 +63,9 @@ function editRoute(id) { }); updateRouteLength(route); + + const isWater = route.cells.some(cell => pack.cells.h[cell] < 20); + byId("routeElevationProfile").style.display = isWater ? "none" : "inline-block"; } function generateRouteName(route) { @@ -153,7 +156,7 @@ function editRoute(id) { elSelected.attr("d", path); updateRouteLength(route); - if (modules.elevation) showEPForRoute(elSelected.node()); + if (byId("elevationProfile").offsetParent) showRouteElevationProfile(); } function addControlPoint() { @@ -248,9 +251,10 @@ function editRoute(id) { route.name = routeName.value = Names.getBase(rand(nameBases.length - 1)); } - function showElevationProfile() { - modules.elevation = true; - showEPForRoute(elSelected.node()); + function showRouteElevationProfile() { + const route = getRoute(); + const routeLen = rn(route.length * distanceScaleInput.value); + showElevationProfile(route.cells, routeLen, false); } function editRouteLegend() { @@ -259,6 +263,11 @@ function editRoute(id) { editNotes(id, route.name); } + function editRouteGroupStyle() { + const {group} = getRoute(); + editStyle("routes", group); + } + function createRoute() { // TODO: white the code :) }