Skip to content


Subversion checkout URL

You can clone with
Download ZIP


Computation of resolution hint was incorrect #83

wants to merge 1 commit into from

3 participants


We use resolutionHint (generally best known as scaleHint) to check if a layer is visible at current resolution and to zoom to the "next visible scale".

To do so we used to compare minResolutionHint and maxResolutionHint (available as min/max values of layer's ScaleHint in WMS GetCapabilities response). This comparison was incorrect.

Mapserver computes max scaleHint as:
scalehintmax = diag*(maxscaledenom/resolution)/msInchesPerUnit(MS_METERS,0);
diag = sqrt(2.0);

On the other hand OpenLayers.Utils.getResolutionFromScale() returns:
resolution = 1 / (normScale * OpenLayers.INCHES_PER_UNIT[units] * OpenLayers.DOTS_PER_INCH);

There is a sqrt(2.0) ratio between those two values. That's because the scaleHint is based on the diagonal length of a pixel which is sqrt(2.0) longer than its side. See for instance :

This pull request simply reintroduces the missing sqrt(2.0) ratio in scaleHint/resolution comparisons.


Many thanks @asaunier for your investigation, but I think that it should be correcter on the server side, because the correction should be done only when we get the scale hint from the WMS server, not when we directly specify in the admin interface.



Thanks @sbrunner for the feedback. Your arguments make sense.

On the other hand, should we really take into account c2cgeoportal-related considerations? Isn't CGXP supposed to be a standalone library that could be use with whatever server part? What if we would like in the future to add direct WMS GetCapabilities support without an intermediary server processing?

The OGC standards have chosen to use pixel diagonal length as resolution hint. Shouldn't we stick to this choice as well when comparing resolution hints?


With tilecache we use resolution base on the edge, OpenLayers do the same, for WMTS it difficult to say but it's base on a pixel of 0.28x0.28mm and they don't speak about diagonal.

For me WMS use the diagonal of a pixel only because the pixels can be not squared !

And it shouldn't be linked directly to WMST near future it can be used fot WMTS.

@elemoine what do you think about this ?


To make the work the integrator and administrator easier I'd do it as @sbrunner suggested.

Setting the minResolution and maxResolution values in the admin interface is indeed easier if these values are directly related to the OpenLayers map resolutions. The integrator can provide the administrator with the list of resolutions the map works with, and the administrator can set the minResolution and maxResolution values based on this list, without extra calculation.

If we add "direct WMS GetCapabilities support" later we will rely on OpenLayers' GetCapabilities format, which does the right thing when setting minScale and maxScale (and therefore minResolution and maxResolution) in the layer object.

I hope this makes sense.


OK thanks. I will then make the change server side and close this pull request.


@asaunier in any way thanks a lot for the investigation and work on that, this is important knowledge to have. I can imagine that pinpointing the source of the issue hasn't been easy.


This pull request is replaced by camptocamp/c2cgeoportal#176

@asaunier asaunier closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 27, 2012
  1. @asaunier
This page is out of date. Refresh to see the latest.
Showing with 10 additions and 7 deletions.
  1. +10 −7 core/src/script/CGXP/widgets/tree/LayerTree.js
17 core/src/script/CGXP/widgets/tree/LayerTree.js
@@ -580,15 +580,16 @@ cgxp.tree.LayerTree = Ext.extend(Ext.tree.TreePanel, {
case 'zoomtoscale':
var n = node,
map =,
- res = map.getResolution(),
+ pixelDiagonal = Math.sqrt(2),
+ resolutionHint = pixelDiagonal * map.getResolution(),
center = map.getCenter(),
minResolutionHint = n.attributes.minResolutionHint,
maxResolutionHint = n.attributes.maxResolutionHint;
- if (maxResolutionHint && maxResolutionHint < res) {
- zoom = map.getZoomForResolution(maxResolutionHint) + 1;
- } else if (minResolutionHint && minResolutionHint > res) {
- zoom = map.getZoomForResolution(minResolutionHint);
+ if (maxResolutionHint && maxResolutionHint < resolutionHint) {
+ zoom = map.getZoomForResolution(maxResolutionHint / pixelDiagonal) + 1;
+ } else if (minResolutionHint && minResolutionHint > resolutionHint) {
+ zoom = map.getZoomForResolution(minResolutionHint / pixelDiagonal);
map.setCenter(center, zoom);
@@ -875,7 +876,8 @@ cgxp.tree.LayerTree = Ext.extend(Ext.tree.TreePanel, {
var n = node,
map =,
- resolution = map.getResolution(),
+ pixelDiagonal = Math.sqrt(2),
+ resolutionHint = pixelDiagonal * map.getResolution(),
minResolutionHint = n.attributes.minResolutionHint,
maxResolutionHint = n.attributes.maxResolutionHint;
if (n.getUI().rendered) {
@@ -884,7 +886,8 @@ cgxp.tree.LayerTree = Ext.extend(Ext.tree.TreePanel, {
var zoomToScale =".gx-tree-layer-actions img.zoomtoscale", true, n.getUI().elNode);
- if ((minResolutionHint && minResolutionHint > resolution) || (maxResolutionHint && maxResolutionHint < resolution)) {
+ if ((minResolutionHint && minResolutionHint > resolutionHint) ||
+ (maxResolutionHint && maxResolutionHint < resolutionHint)) {
Something went wrong with that request. Please try again.