feat: draw WMS tiles from servers without EPSG:3857 in the desktop app (#2562)

* feat(desktop): draw WMS tiles from servers without EPSG:3857

When a WMS tile template names a geographic CRS (EPSG:4326, EPSG:4258,
EPSG:6706, CRS:84), the desktop geolibre-wms protocol requests the tile's
lon/lat extent in that CRS and redraws the latitude-linear image into Web
Mercator in horizontal strips, as the KML Super-Overlay protocol does.
Requests in EPSG:3857 are fetched unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(python): crs option for WMS layers

wms_layer, Map.add_wms and the add_ogc_layer MCP tool accept crs, written
into the GetMap template in place of EPSG:3857 while the bbox placeholder
stays. Only Web Mercator and the geographic CRSs the desktop can redraw are
accepted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(python): reject crs for WMTS; cross-reference the CRS allowlists

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(desktop): clamp latitude in the WMS strip redraw

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(desktop): skip degenerate extents in the WMS strip redraw

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(desktop): read any WMS 1.3.x as latitude first; name the server error when a geographic tile is not an image

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(python): replace a CRS already in the WMS endpoint; document desktop-only geographic CRS

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(desktop): cover the non-image path of the geographic WMS redraw

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(python): replace every GetMap key already in a WMS endpoint

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(python): require WMS 1.3.0 for crs='CRS:84'

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix: decode endpoint key names before replacing them; trim the tile CRS

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test: keep the desktop and Python WMS CRS allowlists equal

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Andrea BorrusoandClaude Opus 5.5 authored and GitHub committed 2026-09-22 17:24:57 -04:00
1 parent 7c19bf803f
commit bf47a7a766
11 files changed
+584 -11

No files matched your search

+1 -1
View File
@@ -289,7 +289,7 @@ m.on_layer_change(lambda e: print("layers", e["layerIds"]))
| `add_pmtiles(url, name=, tile_type=, source_layers=, **style)` | Add a PMTiles archive (vector or raster). |
| `add_tile_layer(url, name=, tile_size=, attribution=)` | Add a raster XYZ tile layer. |
| `add_ee_layer(ee_object, vis_params=, name=, shown=, opacity=)` | Add an authenticated Google Earth Engine object as raster tiles (needs `earthengine-api`). |
| `add_wms(endpoint, layers, name=, styles=, image_format=, transparent=, tile_size=, version=, bounds=, **style)` | Add a WMS layer (GetMap, tiled raster). `bounds` is `[west, south, east, north]`, needed for zoom-to-layer. |
| `add_wms(endpoint, layers, name=, styles=, image_format=, transparent=, tile_size=, version=, crs=, bounds=, **style)` | Add a WMS layer (GetMap, tiled raster). `bounds` is `[west, south, east, north]`, needed for zoom-to-layer. `crs` defaults to `EPSG:3857`; for a server without Web Mercator pass a geographic CRS it lists (`EPSG:4326`, `EPSG:4258`, `EPSG:6706`, or `CRS:84` with `version="1.3.0"`; no others). Only the desktop app redraws those tiles into Web Mercator: the web build and `export_html` pages still send the Web Mercator BBOX, so such a layer stays blank there. |
| `add_wmts(url, name=, tile_size=, bounds=, **style)` | Add a WMTS layer from a tile URL template. |
| `add_wfs(endpoint, type_name, name=, version=, output_format=, srs_name=, max_features=, **style)` | Add a WFS layer (GetFeature GeoJSON, fetched and inlined). |
| `add_cog(url, name=, bands=, colormap=, rescale=, **style)` | Add a Cloud Optimized GeoTIFF (URL or a kernel-side local GeoTIFF path). |