aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2025-05-22 13:03:47 +0200
committerGuilhem Moulin <guilhem@fripost.org>2025-05-23 01:05:07 +0200
commitbcc503ee14503e9bea3228e8c4138ead423f0f48 (patch)
tree589324fc086b841a78b5e0397e88af20faa0581f
parent8ca0f1d492a25932d8d2405a03e3754ca9721b7f (diff)
Adjust to new MVT backend.
We now query a CGI to retrieve feature properties and full geometries (as GeoJSON). This partially reverts commit 1c0748176997d2e915faae3c6fcf5634f4fb0582.
-rw-r--r--main.js167
1 files changed, 69 insertions, 98 deletions
diff --git a/main.js b/main.js
index 4917e79..08b5e74 100644
--- a/main.js
+++ b/main.js
@@ -3215,78 +3215,56 @@ const styles = (function() {
}, {});
})();
-const vectorLayers = {};
-const tileGrid = createXYZ({
- extent: extent,
- tileSize: 1024,
- maxResolution: 1024, /* = 1048576/1024 */
- minZoom: 0,
- maxZoom: 9,
-});
-function readLayerMap() {
- fetch('/tiles/metadata.json', {
- signal: AbortSignal.timeout(30000)
- }).then((resp) => resp.json())
- .then((data) => {
- const xyz = '/{z}/{x}/{y}.pbf';
- Object.entries(data.layermap).forEach(function([k, baseurl]) {
- if (vectorLayers[k] !== undefined) {
- const l = vectorLayers[k];
- if (l.baseurl !== baseurl) {
- console.log(`Changing ${k}'s baseurl to ${baseurl} from ${l.baseurl}`);
- l.baseurl = baseurl;
- l.vectorLayer.getSource().setUrl(baseurl + xyz);
+const vectorLayers = (function() {
+ const xyz = '/{z}/{x}/{y}.pbf';
+ const tileGrid = createXYZ({
+ extent: extent,
+ tileSize: 1024,
+ maxResolution: 1024, /* = 1048576/1024 */
+ minZoom: 0,
+ maxZoom: 7,
+ });
+ return Object.fromEntries(
+ ['mrr', 'nvr', 'ren', 'ri', 'sks', 'svk', 'vbk', 'misc']
+ .map(function(k) {
+ let visible = false;
+ Object.keys(layers).forEach(function(lyr) {
+ if (lyr.startsWith(k + '_')) {
+ visible ||= styles[lyr] !== undefined;
}
- } else {
- let visible = false;
- Object.keys(layers).forEach(function(lyr) {
- if (lyr.startsWith(k + '_')) {
- visible ||= styles[lyr] !== undefined;
+ });
+ const vectorLayer = new VectorTileLayer({
+ source: new VectorTile({
+ url: '/tiles/' + k + xyz,
+ format: new MVT(),
+ projection: projection,
+ wrapX: false,
+ transition: 0,
+ tileGrid: tileGrid,
+ }),
+ /* XXX switch to 'hybrid' if there are perf issues; but that seems to
+ * put lines above points regardless of their respective z-index */
+ renderMode: 'hybrid',
+ declutter: false,
+ visible: visible,
+ style: function(feature, resolution) {
+ const style = styles[k + '_' + feature.getProperties().layer];
+ if (!Array.isArray(style)) {
+ return style;
+ } else {
+ const maxi = style.length - 1;
+ const z = 10 /* Math.log2(maxResolution) */ - Math.log2(resolution);
+ /* use Math.floor() as VectorTile.js calls getZForResolution(resolution, 1) */
+ const i = z <= 0 ? 0 : z >= maxi ? maxi : Math.floor(z);
+ // console.log(`resolution=${resolution}, z=${z}, i=${i}`);
+ return style[i];
}
- });
- const vectorLayer = new VectorTileLayer({
- source: new VectorTile({
- url: baseurl + xyz,
- format: new MVT(),
- projection: projection,
- wrapX: false,
- transition: 0,
- tileGrid: tileGrid,
- }),
- /* XXX switch to 'hybrid' if there are perf issues; but that seems to
- * put lines above points regardless of their respective z-index */
- renderMode: 'hybrid',
- declutter: false,
- visible: visible,
- style: function(feature, resolution) {
- const style = styles[k + '_' + feature.getProperties().layer];
- if (!Array.isArray(style)) {
- return style;
- } else {
- const maxi = style.length - 1;
- const z = 10 /* Math.log2(maxResolution) */ - Math.log2(resolution);
- /* use Math.floor() as VectorTile.js calls getZForResolution(resolution, 1) */
- const i = z <= 0 ? 0 : z >= maxi ? maxi : Math.floor(z);
- // console.log(`resolution=${resolution}, z=${z}, i=${i}`);
- return style[i];
- }
- },
- });
- vectorLayer.set('layerGroup', k, true);
- map.addLayer(vectorLayer);
- vectorLayers[k] = {
- baseurl: baseurl,
- vectorLayer: vectorLayer,
- };
- }
- });
- });
-};
-
-/* re-read after 6h so we don't miss updates; the interval should never
- * be higher than the Cache-Control value on the tiles and metadata */
-readLayerMap();
-setInterval(readLayerMap, 21600000);
+ }});
+ vectorLayer.set('layerGroup', k, true);
+ map.addLayer(vectorLayer);
+ return [k, vectorLayer];
+ }));
+})();
/* layer selection panel */
@@ -3350,7 +3328,7 @@ setInterval(readLayerMap, 21600000);
const v = vectorLayers[lyr];
if (v !== undefined) {
//console.log(lyr, visible);
- v.vectorLayer.setVisible(visible);
+ v.setVisible(visible);
}
});
};
@@ -3377,7 +3355,7 @@ setInterval(readLayerMap, 21600000);
layerList
.map((l) => l.split('_', 2)[0])
.filter((v, i, arr) => arr.indexOf(v) === i)
- .forEach((l) => vectorLayers[l].vectorLayer.getSource().changed());
+ .forEach((l) => vectorLayers[l].getSource().changed());
searchParams.set('layers', layersParams.join(' '));
location.hash = '#' + searchParams.toString();
@@ -3748,41 +3726,34 @@ setInterval(readLayerMap, 21600000);
map.forEachFeatureAtPixel(event.pixel, function(feature, layer) {
const layerGroup = layer.get('layerGroup');
- let properties = feature.getProperties();
- const def = layers[layerGroup + '_' + properties.layer];
+ const layerName = feature.getProperties().layer;
+ const def = layers[layerGroup + '_' + layerName];
if (def === undefined || def.popover === undefined) {
/* skip layers which didn't opt-in for popover */
return;
}
- /* get filename and index of the original feature from the FID */
- const fid_dv = new DataView(new ArrayBuffer(4), 0);
- fid_dv.setUint32(0, feature.getId(), false);
-
- const fid_idx = fid_dv.getUint16(2);
- const buf = new Uint8Array(fid_dv.buffer.slice(0,2))
- const fid_p = buf.reduce((t, x) => t + x.toString(16).padStart(2, '0'), '')
-
if (features.length === 0) {
document.body.classList.add('progress');
}
- const url = vectorLayers[layerGroup].baseurl + '/attr/' + fid_p + '.json';
- fetch(url)
- .then((resp) => resp.json())
+ // TODO batch requests and use
+ // https://github.com/uhop/stream-json/wiki/StreamArray
+ fetch('/q', {
+ method: 'POST',
+ body: JSON.stringify({
+ mvt: layerGroup,
+ layer: layerName,
+ fid: feature.getId()
+ }),
+ headers: {
+ 'Content-Type': 'application/json; charset=UTF-8'
+ }
+ }).then((resp) => resp.json())
.then((data) => {
document.body.classList.remove('progress');
- properties = data[fid_idx]
- //console.log(properties);
-
- /* build new feature from the metadata */
- const geojson = { id: feature.getId() }
- geojson.properties = properties
- const geom = properties['geom']
- delete properties['geom']
- geojson.geometry = geom
- geojson.type = 'Feature'
- const feature2 = new GeoJSON().readFeature(geojson);
+ const properties = data.properties || {};
+ const feature0 = new GeoJSON().readFeature(data);
/* turn the properties into a fine table */
const table = document.createElement('table');
@@ -3859,7 +3830,7 @@ setInterval(readLayerMap, 21600000);
}
content.appendChild(table);
- features.push({feature: feature2, formattedContent: content});
+ features.push({feature: feature0, formattedContent: content});
pageCount.innerHTML = features.length.toString();
if (features.length == 2) {
@@ -3890,7 +3861,7 @@ setInterval(readLayerMap, 21600000);
container: container0,
});
popover.show();
- featureOverlaySource.addFeature(feature2);
+ featureOverlaySource.addFeature(feature0);
}
else if (popover.tip.classList.contains('popover-detached')) {
refreshPopover();