Skip to content

Add minmax_resolution field and deprecate minmax_zoom - #27

Open
emmanuelmathot wants to merge 3 commits into
mainfrom
fix/issue-16-resolution-vs-zoom
Open

emmanuelmathot wants to merge 3 commits into
mainfrom
fix/issue-16-resolution-vs-zoom

Conversation

@emmanuelmathot

Copy link
Copy Markdown
Member

Introduce the minmax_resolution field to specify the visible resolution range in meters per pixel, replacing the ambiguous minmax_zoom. Deprecate minmax_zoom due to its dependency on varying tile size conventions across mapping libraries. Update documentation to clarify the transition and provide guidance on the new resolution-based approach.

fixes #16

Comment thread json-schema/schema.json
Comment thread README.md Outdated
| expression | string, object, array | Band arithmetic formula to apply to the referenced assets. The format is defined by the rendering application, e.g. a [TiTiler](https://developmentseed.org/titiler/) band math string or a [MapLibre](https://maplibre.org/maplibre-style-spec/expressions/) style expression array. |
| minmax_zoom | \[int] | Zoom levels range applicable for the visualization |
| minmax_zoom | \[int] | **Deprecated**, use `minmax_resolution` instead. Zoom levels range applicable for the visualization. Ambiguous across mapping libraries, see [Resolution vs. zoom levels](#resolution-vs-zoom-levels). |
| minmax_resolution | \[float] | Min/max ground sample distance (resolution), in the same unit as [`gsd`](https://github.com/radiantearth/stac-spec/blob/master/item-spec/common-metadata.md#instrument), applicable for the visualization. Preferred over `minmax_zoom` since it is independent of any tiling scheme or library convention. |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no way to define just minimum or maximum, is there? Woult it make sense?

Thus was wondering whether it would make sense to split into two properties then:

  • min_resolution
  • max_resolution

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dont know. @vincentsarago can we?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure OpenLayers supports it. Technically there probably always a min and max, but it could make sense to keep it open for the renderer to decide what it can do...

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally don't like minmax_resolution because it means nothing without a bbox and projection.

Same for minmax_zoom because it needs to be linked to a tilematrixset.

in titiler-stacapi we moved to tilematrixset: dict[str, tuple[int, int] | None] which enable users to pass per TMS zoom range.

IMO we could remove this and let the proj extension drive the min/max zoom decision.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for minmax_zoom because it needs to be linked to a tilematrixset.

ok, lets take some time to find alternatives

IMO we could remove this and let the proj extension drive the min/max zoom decision.

We need a min max scoped to the render. This is a way to inform the client about this specific view, not the item or the asset.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, if proj is part of the render extension, it would describe the actual intended projection of the rendering/map.

I don't get why proj. would be part of the render extension. I was just saying that if an item has the proj extension, the client can easily define the min/max zoom theoretically available (max-zoom = resolution x projection)

Fine to describe the TMS in addition, but if a simple intended min_resolution: 10, proj:code: "EPSG:1234" means I need to create a separate TMS file for this and host it separately, I'm not sure I'd adopt this extension at all.

no one proposed this 🤷

The previous minmax_zoom property was used to tell the client that the render could only be rendered between those zoom level. The issue is that no TMS was associated but WebMercatorQuad was assumed.

See above, I indicated some usecases that I've had. WMTS only giving results in a certain zoom range for example. We also recently had a PMTiles that only contained (useful) information for certain levels. There could be a difference between projection and data.

I don't understand why you would need to have min/max zoom within a render object for PMTiles which has the information internally 🤷

I feel there are some mis-understanding about why and how the render extension should be used.

I personally see the render extension as a way to tell the client (OpenLayer or TiTiler) how to create a visual representation of an asset (or a set of assets). min/max zoom is not about how you create this representation but more about what is possible or not. min/max zoom will tell the application it should not create tiles outside the zoom range. If we persist with this, what would restrict other people to ask for fields like CRS or bbox to tell the client to use a specific projection and/or a specific bounding box?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends which path OpenLayers is on.

Consuming pre-tiled server output (WMTS/XYZ, what tilematrixsets targets): a CRS code isn't enough. ol/tilegrid/TileGrid's constructor requires an explicit resolutions array plus an origin/extent. proj:code says which CRS, not where the grid starts or how zoom levels progress. That's the gap TMS closes.

Reading source data directly (ol/source/GeoTIFF): none of this applies, OpenLayers builds its own grid from the file's native resolution on the fly. No TMS needed there. Is that your use case @m-mohr ?
If so proj:code + min/max_resolution is enough for direct rendering, not for server-tiled. Argument for having both then.

@m-mohr m-mohr Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get why proj. would be part of the render extension [...]
I don't understand why you would need to have min/max zoom within a render object

To provide a good default visualization. if this extension is only about actually providing default for the actual asset, not the map visualization, we may then need a new extension. But as it's closely related I feel like it should be combined and not separated.

Depending on the decision, the minmax_zoom and title should probably be removed as it's not related to visualizing the asset independantly of the map. If we keep map related stuff in, it would include min/max resolution, map projection, etc.

no one proposed this 🤷

Emmanuel did! Quote:

self-host your own TMS JSON for a regional CRS and reference it by URI, no central registry entry required.


If we persist with this, what would restrict other people to ask for fields like CRS or bbox to tell the client to use a specific projection and/or a specific bounding box?

Yeah, bbox and CRS would be useful for good default visualization.

But maybe we stick to just fixing #16 for now and open an issue for the other usecases? Or restrict the extension to pure asset-related visualization capabilites and create a new extension for map visualization, but that would make things obviously more complex as then two extensions needs to communicate their relationships. I'm probably fine either way as long as I have a path forward, although I feel all this could be bundled well into render.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that your use case @m-mohr ?

One of many, yes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stepping back a bit, since I think this thread is actually circling a scope question that is worth describing

render started from a different problem: the idea of being able to describe a composite derived from existing assets (composite). That overlapped confusingly with virtual-assets' cross-reference/repositioning model. two extensions reaching for the same thing from different angles. What we settled on was narrowing render's scope specifically to rendering: visualization, meaning how to combine assets (or bands within assets) with a small set of usual display parameters (rescale, colormap, resampling, expression, and so on.)

@vincentsarago's point about minmax_zoom/tilematrixsets is fair by that same logic: zoom levels and tile matrix sets are web-mapping concepts, not properties of how pixel values get transformed. But rendering isn't only a web-mapping activity. The same render object could just as well inform a GIS desktop template (QGIS layer styling, a print layout) where "zoom level" isn't a meaningful concept at all.

So maybe the actual question is narrower scope, not a better field: should render stay limited to how pixels are rendered (rescale, color, resampling, expression, band selection; the transformation itself), and push web-mapping-specific hints (tiling/zoom/resolution limits) out to a separate mechanism, either extending web-map-links (which already exists to cross-reference tile server endpoints) or a dedicated extension for map-display hints? That would keep render usable outside a tiling context at all, and let the tiling-specific debate (TMS vs. resolution vs. proj) happen in a place whose scope is actually about web mapping. It would then also reduce complexity of this extension.

Curious what you all think? Not proposing an answer here, just think it's worth deciding the boundary before we keep iterating on a field inside it.

Comment thread README.md Outdated
Comment thread README.md
Comment on lines +110 to +113
`minmax_resolution` avoids this by expressing the range directly in ground resolution (the same unit as
[`gsd`](https://github.com/radiantearth/stac-spec/blob/master/item-spec/common-metadata.md#instrument), meters
per pixel), independent of any tiling scheme. A client can derive the zoom level for its own tile size with the
inverse formula:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reference to gsd is confusing. The gsd defintion in STAC says: "Ground Sample Distance at the sensor, in meters (m)".

If it just meant to communicate the unit, then we can just say meter. But mixing sensor and on the ground here I think doesn't help with understanding.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the usual gsd / resolution dilemma... Should we refer to the raster extension resolution field? We need a proper value to compute the min and max in the renderer

@m-mohr m-mohr Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

raster:resolution is probably better suited than gsd, but not always present. We could recommend its usage here though. So an equivalent to maxResolution, minResolution in OpenLayers for example. https://openlayers.org/en/latest/apidoc/module-ol_View-View.html

emmanuelmathot and others added 2 commits September 22, 2026 13:04
Co-authored-by: Matthias Mohr <m.mohr@moregeo.it>
Co-authored-by: Matthias Mohr <m.mohr@moregeo.it>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

minmax_zoom leads to different results for mapping libraries

3 participants