feat: highlight dwelling parcels
This commit is contained in:
@@ -2,6 +2,7 @@ const DEFAULT_CENTER = [-8.65, 39.55];
|
|||||||
const API_CAPABILITIES = "/api/capabilities";
|
const API_CAPABILITIES = "/api/capabilities";
|
||||||
const API_WMS = "/api/wms";
|
const API_WMS = "/api/wms";
|
||||||
const PARCEL_LAYER_NAME = "xpro:parcelas";
|
const PARCEL_LAYER_NAME = "xpro:parcelas";
|
||||||
|
const DWELLING_PARCEL_LAYER_NAME = "xpro:parcelas_habitacao";
|
||||||
const FEATURE_INFO_LAYER_NAMES = new Set(["parcelas", "predios"]);
|
const FEATURE_INFO_LAYER_NAMES = new Set(["parcelas", "predios"]);
|
||||||
const DEVICE_ORIENTATION_EVENTS = ["deviceorientationabsolute", "deviceorientation"];
|
const DEVICE_ORIENTATION_EVENTS = ["deviceorientationabsolute", "deviceorientation"];
|
||||||
const COMPASS_HEADING_DEADBAND = 2;
|
const COMPASS_HEADING_DEADBAND = 2;
|
||||||
@@ -67,6 +68,21 @@ const wmsLayer = new ol.layer.Image({
|
|||||||
source: wmsSource,
|
source: wmsSource,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const dwellingParcelSource = new ol.source.Vector();
|
||||||
|
const dwellingParcelLayer = new ol.layer.Vector({
|
||||||
|
source: dwellingParcelSource,
|
||||||
|
// The pale halo keeps the red dwelling boundary distinct over every
|
||||||
|
// supported basemap and the existing parcel fills.
|
||||||
|
style: [
|
||||||
|
new ol.style.Style({
|
||||||
|
stroke: new ol.style.Stroke({ color: "rgba(255, 255, 255, 0.9)", width: 6 }),
|
||||||
|
}),
|
||||||
|
new ol.style.Style({
|
||||||
|
stroke: new ol.style.Stroke({ color: "#d71920", width: 3.5 }),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
const parcelSearchSource = new ol.source.Vector();
|
const parcelSearchSource = new ol.source.Vector();
|
||||||
const parcelSearchLayer = new ol.layer.Vector({
|
const parcelSearchLayer = new ol.layer.Vector({
|
||||||
source: parcelSearchSource,
|
source: parcelSearchSource,
|
||||||
@@ -106,7 +122,14 @@ const map = new ol.Map({
|
|||||||
tipLabel: "Reset map orientation to north",
|
tipLabel: "Reset map orientation to north",
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
layers: [softBasemapLayer, openStreetMapLayer, satelliteLayer, wmsLayer, parcelSearchLayer],
|
layers: [
|
||||||
|
softBasemapLayer,
|
||||||
|
openStreetMapLayer,
|
||||||
|
satelliteLayer,
|
||||||
|
wmsLayer,
|
||||||
|
dwellingParcelLayer,
|
||||||
|
parcelSearchLayer,
|
||||||
|
],
|
||||||
view: new ol.View({
|
view: new ol.View({
|
||||||
center: ol.proj.fromLonLat(DEFAULT_CENTER),
|
center: ol.proj.fromLonLat(DEFAULT_CENTER),
|
||||||
zoom: 7,
|
zoom: 7,
|
||||||
@@ -494,6 +517,7 @@ async function loadLayers() {
|
|||||||
|
|
||||||
renderLayerList();
|
renderLayerList();
|
||||||
syncSelectedLayers();
|
syncSelectedLayers();
|
||||||
|
await loadDwellingParcels();
|
||||||
fitToLayerExtent(availableLayers[0]);
|
fitToLayerExtent(availableLayers[0]);
|
||||||
|
|
||||||
updateStatus(`Showing ${availableLayers.length} layer(s) from GeoServer.`, "success");
|
updateStatus(`Showing ${availableLayers.length} layer(s) from GeoServer.`, "success");
|
||||||
@@ -502,6 +526,8 @@ async function loadLayers() {
|
|||||||
updateStatus(error.message || "Unable to load the WMS service.", "error");
|
updateStatus(error.message || "Unable to load the WMS service.", "error");
|
||||||
availableLayers = [];
|
availableLayers = [];
|
||||||
selectedLayers = [];
|
selectedLayers = [];
|
||||||
|
dwellingParcelSource.clear();
|
||||||
|
dwellingParcelLayer.setVisible(false);
|
||||||
renderLayerList();
|
renderLayerList();
|
||||||
syncSelectedLayers();
|
syncSelectedLayers();
|
||||||
}
|
}
|
||||||
@@ -590,6 +616,50 @@ function syncSelectedLayers() {
|
|||||||
LAYERS: [...orderedSelectedLayers].reverse().join(","),
|
LAYERS: [...orderedSelectedLayers].reverse().join(","),
|
||||||
_: Date.now(),
|
_: Date.now(),
|
||||||
});
|
});
|
||||||
|
dwellingParcelLayer.setVisible(
|
||||||
|
selectedLayers.some((name) => {
|
||||||
|
const layerName = unqualifiedLayerName(name);
|
||||||
|
return layerName === "parcelas" || layerName === unqualifiedLayerName(DWELLING_PARCEL_LAYER_NAME);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadDwellingParcels() {
|
||||||
|
const publishedDwellingLayer = availableLayers.find(
|
||||||
|
(layer) => unqualifiedLayerName(layer.name) === unqualifiedLayerName(DWELLING_PARCEL_LAYER_NAME),
|
||||||
|
);
|
||||||
|
|
||||||
|
dwellingParcelSource.clear();
|
||||||
|
if (!publishedDwellingLayer) {
|
||||||
|
console.warn("The dwelling parcel layer is not published by GeoServer.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
service: "WFS",
|
||||||
|
version: "2.0.0",
|
||||||
|
request: "GetFeature",
|
||||||
|
typeNames: publishedDwellingLayer.name,
|
||||||
|
outputFormat: "application/json",
|
||||||
|
srsName: "EPSG:3857",
|
||||||
|
});
|
||||||
|
const response = await fetch(`${API_WMS}?${params}`);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Dwelling parcel request failed with status ${response.status}.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const featureCollection = await response.json();
|
||||||
|
const features = new ol.format.GeoJSON().readFeatures(featureCollection, {
|
||||||
|
featureProjection: "EPSG:3857",
|
||||||
|
});
|
||||||
|
dwellingParcelSource.addFeatures(features);
|
||||||
|
} catch (error) {
|
||||||
|
// Keep the normal map usable when a deployment has not yet published the
|
||||||
|
// optional layer; the error remains available for operational diagnosis.
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function showFeatureInformation(event) {
|
async function showFeatureInformation(event) {
|
||||||
|
|||||||
Reference in New Issue
Block a user