diff --git a/modules/ui/layers.js b/modules/ui/layers.js
index a4801b35..a921c36f 100644
--- a/modules/ui/layers.js
+++ b/modules/ui/layers.js
@@ -1885,13 +1885,45 @@ function drawZones() {
const filterBy = byId("zonesFilterType").value;
const isFiltered = filterBy && filterBy !== "all";
- const zonesHtml = pack.zones.filter(zone => !zone.hidden && (!isFiltered || zone.type === filterBy)).map(drawZone);
- zones.html(zonesHtml.join(""));
+ const visibleZones = pack.zones.filter(
+ zone => !zone.hidden && zone.cells.length && (!isFiltered || zone.type === filterBy)
+ );
+ zones.html(visibleZones.map(drawZone).join(""));
}
function drawZone({i, cells, type, color}) {
- const cellsPath = cells.map(cell => "M" + getPackPolygon(cell).join(" ")).join(" ");
- return ``;
+ // find a path connecting all cells of zone
+ const path = getZonePath(cells);
+ if (!path) return;
+
+ function getZonePath(cells) {
+ const used = new Set();
+ const vertices = cells.map(c => pack.cells.v[c]).flat();
+ const points = vertices.map(v => pack.vertices.p[v]);
+ const boundary = getBoundaryPoints(points, used);
+ return boundary.length > 2 ? "M" + boundary.join("L") + "Z" : null;
+ }
+
+ function getBoundaryPoints(points, used) {
+ const boundary = [];
+ let currentPoint = points[0];
+
+ while (true) {
+ boundary.push(currentPoint);
+ used.add(currentPoint.toString());
+ let nextPoint = findNextPoint(currentPoint, points, used);
+ if (!nextPoint || nextPoint === boundary[0]) break;
+ currentPoint = nextPoint;
+ }
+
+ return boundary;
+ }
+
+ function findNextPoint(current, points, used) {
+ return points.find(p => !used.has(p.toString()) && Math.hypot(p[0] - current[0], p[1] - current[1]) < 20);
+ }
+
+ return ``;
}
function toggleEmblems(event) {
diff --git a/modules/ui/tools.js b/modules/ui/tools.js
index 7d2a0e1f..9dce15c5 100644
--- a/modules/ui/tools.js
+++ b/modules/ui/tools.js
@@ -167,9 +167,9 @@ function regenerateStates() {
Military.generate();
if (layerIsOn("toggleEmblems")) drawEmblems();
- if (document.getElementById("burgsOverviewRefresh")?.offsetParent) burgsOverviewRefresh.click();
- if (document.getElementById("statesEditorRefresh")?.offsetParent) statesEditorRefresh.click();
- if (document.getElementById("militaryOverviewRefresh")?.offsetParent) militaryOverviewRefresh.click();
+ if (byId("burgsOverviewRefresh")?.offsetParent) burgsOverviewRefresh.click();
+ if (byId("statesEditorRefresh")?.offsetParent) statesEditorRefresh.click();
+ if (byId("militaryOverviewRefresh")?.offsetParent) militaryOverviewRefresh.click();
}
function recreateStates() {
@@ -445,8 +445,8 @@ function regenerateBurgs() {
emblems.selectAll("use").remove();
if (layerIsOn("toggleEmblems")) drawEmblems();
- if (document.getElementById("burgsOverviewRefresh")?.offsetParent) burgsOverviewRefresh.click();
- if (document.getElementById("statesEditorRefresh")?.offsetParent) statesEditorRefresh.click();
+ if (byId("burgsOverviewRefresh")?.offsetParent) burgsOverviewRefresh.click();
+ if (byId("statesEditorRefresh")?.offsetParent) statesEditorRefresh.click();
}
function regenerateEmblems() {
@@ -521,7 +521,7 @@ function regenerateCultures() {
function regenerateMilitary() {
Military.generate();
if (!layerIsOn("toggleMilitary")) toggleMilitary();
- if (document.getElementById("militaryOverviewRefresh").offsetParent) militaryOverviewRefresh.click();
+ if (byId("militaryOverviewRefresh").offsetParent) militaryOverviewRefresh.click();
}
function regenerateIce() {
@@ -534,7 +534,7 @@ function regenerateMarkers() {
Markers.regenerate();
turnButtonOn("toggleMarkers");
drawMarkers();
- if (document.getElementById("markersOverviewRefresh").offsetParent) markersOverviewRefresh.click();
+ if (byId("markersOverviewRefresh").offsetParent) markersOverviewRefresh.click();
}
function regenerateZones(event) {
@@ -545,10 +545,9 @@ function regenerateZones(event) {
else addNumberOfZones(gauss(1, 0.5, 0.6, 5, 2));
function addNumberOfZones(number) {
- zones.selectAll("g").remove(); // remove existing zones
Zones.generate(number);
- if (document.getElementById("zonesEditorRefresh").offsetParent) zonesEditorRefresh.click();
- if (!layerIsOn("toggleZones")) toggleZones();
+ if (byId("zonesEditorRefresh").offsetParent) zonesEditorRefresh.click();
+ if (layerIsOn("toggleZones")) drawZones();
}
}
@@ -559,7 +558,7 @@ function unpressClickToAddButton() {
}
function toggleAddLabel() {
- const pressed = document.getElementById("addLabel").classList.contains("pressed");
+ const pressed = byId("addLabel").classList.contains("pressed");
if (pressed) {
unpressClickToAddButton();
return;
@@ -627,22 +626,22 @@ function addLabelOnClick() {
function toggleAddBurg() {
unpressClickToAddButton();
- document.getElementById("addBurgTool").classList.add("pressed");
+ byId("addBurgTool").classList.add("pressed");
overviewBurgs();
- document.getElementById("addNewBurg").click();
+ byId("addNewBurg").click();
}
function toggleAddRiver() {
- const pressed = document.getElementById("addRiver").classList.contains("pressed");
+ const pressed = byId("addRiver").classList.contains("pressed");
if (pressed) {
unpressClickToAddButton();
- document.getElementById("addNewRiver").classList.remove("pressed");
+ byId("addNewRiver").classList.remove("pressed");
return;
}
addFeature.querySelectorAll("button.pressed").forEach(b => b.classList.remove("pressed"));
addRiver.classList.add("pressed");
- document.getElementById("addNewRiver").classList.add("pressed");
+ byId("addNewRiver").classList.add("pressed");
closeDialogs(".stable");
viewbox.style("cursor", "crosshair").on("click", addRiverOnClick);
tip("Click on map to place new river or extend an existing one. Hold Shift to place multiple rivers", true, "warn");
@@ -728,7 +727,7 @@ function addRiverOnClick() {
}
// continue old river
- document.getElementById("river" + oldRiverId)?.remove();
+ byId("river" + oldRiverId)?.remove();
riverCells.forEach(i => (cells.r[i] = oldRiverId));
oldRiverCells.forEach(cell => {
if (h[cell] > h[min]) {
@@ -796,13 +795,13 @@ function addRiverOnClick() {
if (d3.event.shiftKey === false) {
Lakes.cleanupLakeData();
unpressClickToAddButton();
- document.getElementById("addNewRiver").classList.remove("pressed");
+ byId("addNewRiver").classList.remove("pressed");
if (addNewRiver.offsetParent) riversOverviewRefresh.click();
}
}
function toggleAddMarker() {
- const pressed = document.getElementById("addMarker")?.classList.contains("pressed");
+ const pressed = byId("addMarker")?.classList.contains("pressed");
if (pressed) {
unpressClickToAddButton();
return;
@@ -830,7 +829,7 @@ function addMarkerOnClick() {
const isMarkerSelected = markers.length && elSelected?.node()?.parentElement?.id === "markers";
const selectedMarker = isMarkerSelected ? markers.find(marker => marker.i === +elSelected.attr("id").slice(6)) : null;
- const selectedType = document.getElementById("addedMarkerType").value;
+ const selectedType = byId("addedMarkerType").value;
const selectedConfig = Markers.getConfig().find(({type}) => type === selectedType);
const baseMarker = selectedMarker || selectedConfig || {icon: "❓"};
@@ -840,13 +839,13 @@ function addMarkerOnClick() {
selectedConfig.add("marker" + marker.i, cell);
}
- const markersElement = document.getElementById("markers");
+ const markersElement = byId("markers");
const rescale = +markersElement.getAttribute("rescale");
markersElement.insertAdjacentHTML("beforeend", drawMarker(marker, rescale));
if (d3.event.shiftKey === false) {
- document.getElementById("markerAdd").classList.remove("pressed");
- document.getElementById("markersAddFromOverview").classList.remove("pressed");
+ byId("markerAdd").classList.remove("pressed");
+ byId("markersAddFromOverview").classList.remove("pressed");
unpressClickToAddButton();
}
}