[GIS] MapServer computes wrong map scales — off by factor 0.77. Or is it just me

mapserverresolutionscale

I've noticed in a current project that MapServer seems to get the map scale wrong, or then I'm wrong, but don't see how.

My mapfile contains the following definitions:

RESOLUTION 72   # this is the default, but I set it explicitly, just to make sure

PROJECTION
    "init=epsg:21781"  # = CH1903 LV 03, which uses meters as coordinate units
END

LAYER
    NAME "one"
    MAXSCALEDENOM 7500
    ...
END

LAYER
    NAME "two"
    MINSCALEDENOM 7502
    ...
END

If I only display these two layers, I should definitely be able to get an empty map at scale 1:7,501.

I have written a simple map viewer application to verify this. My viewer also assumes a screen resolution of 72 DPI, just like MapServer. However, it turns out that both layers are invisible around map scale 1:5,803. I would have to adjust my viewer to 93.062 DPI to get the empty map at 1:7,501. Why is this?

Just for reference, this is how I calculate the map scale in my viewer:

double imageWidthInPixels = ...;   // passed to mapserv.exe (via 'map_size' arg.)
double extentWidthInMeters = ...;  // = extent's xmax-xmin (via 'mapext' arg.)

// constants:
const double dpi = 72.0;
const double inchesPerPixel = 1.0 / dpi;
const double inchesPerMeter = 1.0 / 0.0254;

double inchesOnScreen = inchesPerPixel * imageWidthInPixels;
double inchesInReality = inchesPerMeter * extentWidthInMeters;

double scaleDenominator = 1 / (inchesOnScreen / inchesInReality);

How could this go wrong?

P.S.: I am quite certain that I have the right extentWidthInMeters since I can easily derive it from the extent. (I'm using the Swiss projected coordinate system CH1903 LV03, which already uses meters as coordinate units.)


UPDATE: It seems as if the inaccuracy was partly caused by differing aspect ratios of the map image control in my viewer and the extent sent to MapServer. I've now made sure that only map extents are passed to MapServer that have the same aspect ratio as my map image control. But some small error still remains: The map is now empty around scale 1:7'489 instead of 1:7'501.

Best Answer

Your screen is probably running at 96 DPI, not 72.

Computing scale as a ratio of 1:n is a risky business at best with a web map. If your map is being displayed on an average monitor, you can assume 96DPI. But that will be wrong on (say) a mobile device, or a projector, or a 19" LCD running at 640x480 resolution, etc.

It is better to produce a scale bar of a known width and then label its width.

Your loss of precision is likely due to the conversion factor - try:

const double inchesPerMeter = 1.0 / 0.0254000508;
Related Question