Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions public/modules/ui/units-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ function editUnits() {
ensureEl("distanceScaleInput").on("change", changeDistanceScale);
ensureEl("heightUnit").on("change", changeHeightUnit);
ensureEl("heightExponentInput").on("input", changeHeightExponent);
ensureEl("altitudeLegend").on("click", toggleLegend);
ensureEl("temperatureScale").on("change", changeTemperatureScale);

ensureEl("populationRateInput").on("change", changePopulationRate);
Expand Down Expand Up @@ -67,6 +68,7 @@ function editUnits() {
function changeHeightExponent() {
calculateTemperatures();
if (layerIsOn("toggleTemperature")) drawTemperature();
updateLegendIfVisible();
}
Comment on lines 68 to 72

function changeTemperatureScale() {
Expand Down Expand Up @@ -119,6 +121,79 @@ function editUnits() {
localStorage.removeItem("urbanDensity");
}

function toggleLegend() {
const isVisible = legend.selectAll("*").size() > 0;

if (isVisible) {
clearLegend();
} else {
updateAndDisplayLegend();
}
}

function updateAndDisplayLegend() {
const heights = pack.cells.h;
const countByHeight = new Map();
for (const h of heights) countByHeight.set(h, (countByHeight.get(h) || 0) + 1);

Comment on lines +134 to +138
const exponent = +heightExponentInput.value;
const scheme = getColorScheme();
Comment thread
Avengium marked this conversation as resolved.
Outdated

const heightUnitSelect = ensureEl("heightUnit");
const heightUnitName =
heightUnitSelect.value === "custom_name"
? heightUnitSelect.nextElementSibling?.value || ""
: (heightUnitSelect.selectedOptions[0]?.text.match(/\(([^)]+)\)/)?.[1] ?? "");
Comment on lines +147 to +150

const heightLevels = [];
countByHeight.forEach((count, height) => {
const v = 1 - (height < 20 ? height - 5 : height) / 100;
const sRGB = scheme(v);
const altitude = height < 20 ? 0 : Math.pow(height - 18, exponent);
heightLevels.push({height, count, altitude, color: sRGB});
Comment on lines +153 to +157
});

// Sort by height
heightLevels.sort((a, b) => a.height - b.height);

// Select a representative sample of heights across the range
const totalSamples = 10;
const step = Math.max(1, Math.floor(heightLevels.length / totalSamples));
const sampled = heightLevels.filter(
(_, index) => index % step === 0 || index === heightLevels.length - 1
);

const data = sampled.map(c => [rn(c.height, 0), c.color, rn(c.altitude, 1)]);

// Set the number of items per column
styleLegendColItems.value = data.length;

drawLegend(`Heights (in ${heightUnitName})`, data);

Comment on lines +170 to +176
Comment on lines +172 to +176
// Center the legend label
const legendLabel = legend.select("#legendLabel");
const bbox = legend.node().getBBox();
legendLabel.attr("x", bbox.width / 2);

// Adjust legend position to ensure it's fully visible
const legendBox = legend.select("#legendBox");
const legendWidth = +legendBox.attr("width");
const legendHeight = +legendBox.attr("height");
const svgWidth = +d3.select("svg").attr("width");
const svgHeight = +d3.select("svg").attr("height");

const x = Math.max(10, Math.min(svgWidth - legendWidth - 10, (+legend.attr("data-x") / 100) * svgWidth));
const y = Math.max(10, Math.min(svgHeight - legendHeight - 10, (+legend.attr("data-y") / 100) * svgHeight));
Comment on lines +188 to +190

legend.attr("transform", `translate(${x},${y})`);
}

function updateLegendIfVisible() {
if (legend.selectAll("*").size() > 0) {
updateAndDisplayLegend();
}
}

function addRuler() {
if (!layerIsOn("toggleRulers")) toggleRulers();

Expand Down
5 changes: 5 additions & 0 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5340,6 +5340,11 @@
</slider-input>
</div>

<div data-tip="Toggle altitude legend. Granularity affects the amount of heights shown">
<span>Height legend:</span>
<button id="altitudeLegend" data-tip="Click to show the altitude legend" class="icon-list-bullet"></button>
</div>

<div class="unitsHeader" data-tip="Select Temperature scale">
<span class="icon-temperature-high"></span>
<label>Temperature:</label>
Expand Down
Loading