-
Notifications
You must be signed in to change notification settings - Fork 405
[Proposal] WMS Tile Grid Settings
The goal of this improvement is to simplify the current MapStore project creation and update system.
- Lorenzo Natali (author and writer of the proposal)
The proposal is for 2023.02.00 or next
- Under Discussion
- In Progress
- Completed
- Rejected
- Deferred
MapStore, and in particular the Openlayers implementation of Tiled WMS, generates the a tile grid based to the map resolutions. This limits the possibility to use the tile caches from GeoWebCache when the map have custom resolutions. Also creating custom gridsets causes problems because the current implementation allows to define a fixed origin (top-left corner) for the layer, while GeoWebCache generates the tilegrid by starting from the bottom-left corner. In case the resolutions are not exponential (that generate tiles of power of 2, that are integer), this means that the top-left corner vary on every zoom level.
Moreover, in order to pass to a more modern web mapping (e.g. with fractional scales or ready for the 3D modes), we have to bind the tile grid system to detouch the tile grid generation strategy from the map resolutions and allow to configure them accordingly with the source.
Original issue proposed here:
https://github.com/geosolutions-it/MapStore2/issues/9025
We should implement some improvement to MapStore in order to:
- Use by default the exponential generation of tilegrid, that guarantees a better alignment to default gridsets generated by GeoWebCache
- Allow to define from UI and store in the Map JSON:
- default tilegrid settings for WMS source (advanced layer settings)
- layer tilegrid settings for WMS Layer (layer settings)
Here a sample about Tile grid settings button in WMS Source
The same will be present in layer settings.
Actually the 3D map relies on EPSG:4326. We can configure a proper custom TilingScheme but using the default for now is enough and it is not part of the estimation.
- Printing
- Properly define new defaults (while deveolping): 1pt
- Change WMSLayer in OpenLayers to use a
tileGrid
object: 2pt - Extract/export proper functionalities from MapUtils (e.g. get resolutions for map): 1pt
- UI to insert configurations in WMS source and WMS Layer tile grid configuration (near tile-sizes, a new button, should allow to completely customize tile grid in a dialog):
- allow to define origin(s), tileSize(s),resolutions (or scales) manually: 2-3pt
- Reuse the dialog in both layer properties and WMS source: 1pt
- Optional: retrieve them from WMTS (GeoServer only, helps to auto-load) 2-3pt
- Optional: In map settings, allow to configure the scales/resolutions of the map manually: 2-3pt
- Testing with various CRS/Tile grids: (also developer need to test) 3pt
This (missing export getResolutionsForProjection from MapUtils) seems to work, but generates some MISS for first testing, to verify
diff --git a/web/client/components/map/openlayers/plugins/WMSLayer.js b/web/client/components/map/openlayers/plugins/WMSLayer.js
index 87ad6931c..516b376dc 100644
--- a/web/client/components/map/openlayers/plugins/WMSLayer.js
+++ b/web/client/components/map/openlayers/plugins/WMSLayer.js
@@ -20,7 +20,7 @@ import { getConfigProp } from '../../../../utils/ConfigUtils';
import {optionsToVendorParams} from '../../../../utils/VendorParamsUtils';
import {addAuthenticationToSLD, addAuthenticationParameter, getAuthenticationHeaders} from '../../../../utils/SecurityUtils';
-import { creditsToAttribution, getWMSVendorParams } from '../../../../utils/LayersUtils';
+import { creditsToAttribution } from '../../../../utils/LayersUtils';
import MapUtils from '../../../../utils/MapUtils';
import {loadTile, getElevation as getElevationFunc} from '../../../../utils/ElevationUtils';
@@ -123,7 +123,7 @@ function wmsToOpenlayersOptions(options) {
TRANSPARENT: options.transparent !== undefined ? options.transparent : true,
SRS: CoordinatesUtils.normalizeSRS(options.srs || 'EPSG:3857', options.allowedSRS),
CRS: CoordinatesUtils.normalizeSRS(options.srs || 'EPSG:3857', options.allowedSRS),
- ...getWMSVendorParams(options),
+ TILED: options.singleTile ? false : (!isNil(options.tiled) ? options.tiled : true),
VERSION: options.version || "1.3.0"
}, assign(
{},
@@ -189,6 +189,64 @@ function getElevation(pos) {
}
const toOLAttributions = credits => credits && creditsToAttribution(credits) || undefined;
+/**
+ * Generates the tile grid for the layer based on the options.
+ * If the options contains a tileGridStrategy, it will be used to generate the tile grid.
+ * Otherwise, the default tile grid will be used.
+ * @param {object} options layer options. If it contains a `tileGridStrategy`, it will be used to generate the tile grid.
+ * @param {string} options.tileGridStrategy the tile grid strategy to use. Valid values are:
+ * - `default`: the tile grid will be generated by calculating the resolutions based on the current projection extent, exponentially increasing the resolution.
+ * - `map`: the tile grid will be generated using the current map resolutions.
+ * - `custom`: the tile grid will be generated using the resolutions provided in the `resolutions` option. Also `origin` or `origins` can be provided.
+ * @param {map} map the map object
+ * @returns {TileGrid} the tile grid for the layer
+ */
+const generateTileGrid = (options, map) => {
+
+ const strategy = options.tileGridStrategy // use a tileGrid object with strategy object, containing information about the tile grid (by crs)
+ || (options.resolutions && (options.origin || options.origins)
+ ? 'custom'
+ : 'default');
+ const mapSrs = map && map.getView() && map.getView().getProjection() && map.getView().getProjection().getCode() || 'EPSG:3857';
+ const normalizedSrs = CoordinatesUtils.normalizeSRS(options.srs || mapSrs, options.allowedSRS);
+ const tileSize = options.tileSize ? options.tileSize : 256; // TODO check tileSizes
+ // if tileSizes is defined, it overrides tileSize.
+ // tileSizes is an array of tile sizes for each resolution (array of same length of resolutions)
+ // other openlayers TileGrid arguments are
+ const extent = options.extent
+ || get(normalizedSrs).getExtent()
+ || CoordinatesUtils.getExtentForProjection(normalizedSrs).extent;
+ switch (strategy) {
+ case 'map':
+ return new TileGrid({
+ extent: extent,
+ tileSize,
+ resolutions: options.resolutions || MapUtils.getResolutions(),
+ origin: options.origin ? options.origin : [extent[0], extent[1]]
+ });
+ case 'custom':
+ return new TileGrid({
+ extent: extent,
+ // minZoom: options.minZoom, // TODO: check
+ origin: options.origin ? options.origin : [extent[0], extent[1]],
+ origins: options.origins,
+ resolutions: options.resolutions,
+ // sizes: options.sizes, // Number of tile rows and columns for each zoom level. // TODO: check
+ tileSize,
+ tileSizes: options.tileSizes
+
+ });
+ case 'default':
}
- const mapSrs = map && map.getView() && map.getView().getProjection() && map.getView().getProjection().getCode() || 'EPSG:3857';
- const normalizedSrs = CoordinatesUtils.normalizeSRS(options.srs || mapSrs, options.allowedSRS);
- const extent = get(normalizedSrs).getExtent() || CoordinatesUtils.getExtentForProjection(normalizedSrs).extent;
+
+ const tileGrid = generateTileGrid(options, map);
const sourceOptions = addTileLoadFunction({
attributions: toOLAttributions(options.credits),
urls: urls,
crossOrigin: options.crossOrigin,
params: queryParameters,
- tileGrid: new TileGrid({
- extent: extent,
- resolutions: options.resolutions || MapUtils.getResolutions(),
- tileSize: options.tileSize ? options.tileSize : 256,
- origin: options.origin ? options.origin : [extent[0], extent[1]]
- }),
+ tileGrid,
tileLoadFunction: loadFunction(options, headers)
}, options);
const wmsSource = new TileWMS({ ...sourceOptions });