Opened 17 years ago

Last modified 16 years ago

#2166 reopened defect

MAXSCALE bug

Reported by: woodbri Owned by: sdlime
Priority: normal Milestone: 5.0 release
Component: MapServer C Library Version: 5.0
Severity: normal Keywords:
Cc: woodbri@…, dmorissette

Description

I have found a problem with the MAXSCALE computation in mapserver. This showed up while looking at the AGG code, but might not have anything to do with that per say.

The layer (see below) has the MAXSCALE 4000100.0 but when I request a map at scale=4000000 the cities do not show up.

http://imaptools.com/cgi-bin/mapserv-4.99?mode=map&layers=all&scale=4000000&map=/u/data/maps/google-agg.map&mapxy=-87.65+41.85&map_size=450+350 http://imaptools.com/cgi-bin/mapserv-4.99?mode=map&layers=all&scale=3997555&map=/u/data/maps/google-agg.map&mapxy=-87.65+41.85&map_size=450+350

this one finally works:

http://imaptools.com/cgi-bin/mapserv-4.99?mode=map&layers=all&scale=3997554&map=/u/data/maps/google-agg.map&mapxy=-87.65+41.85&map_size=450+350

This mapfile works fine in 4.10, here is a comparison of 4.10 and trunk with AGG.

http://imaptools.com/maps/compare-maps2.php?loc=2&ll=41.85+-87.65&address=&city=boston&state=ma&zipcode=&country=&asrv=1&amf=%2Fu%2Fdata%2Fmaps%2Fgoogle-aa2.map&msa=mapserv-4.10&bsrv=1&bmf=%2Fu%2Fdata%2Fmaps%2Fgoogle-agg.map&msb=mapserv-4.99&submit=Show

Here is the layer in question:

  LAYER
    NAME "US_Places"
    STATUS DEFAULT
    DATA "us/placenames2"
    TYPE ANNOTATION
    FILTER ([POP] >= 5000)
    MAXSCALE 4000100.0
    CLASSITEM "POP"
    LABELITEM "NAME"
    CLASS
      NAME "Mega Cities"
      EXPRESSION ([POP] > 100000)
      SYMBOL "target-1"
      COLOR 0 0 0
      LABEL
        TYPE TRUETYPE
        FONT "arial-bold"
        SIZE 9
        POSITION AUTO
        BUFFER 5
        COLOR 0 0 0
        OUTLINECOLOR 245 245 231
        #ANTIALIAS TRUE
        PARTIALS FALSE
      END
    END
    CLASS
      NAME "Major Cities"
      EXPRESSION ([POP] >= 25000 && [POP] < 99999)
      SYMBOL "target-2"
      COLOR 0 0 0
      LABEL
        TYPE TRUETYPE
        FONT "arial-bold"
        SIZE 8
        POSITION AUTO
        BUFFER 5
        COLOR 0 0 0
        OUTLINECOLOR 245 245 231
        #ANTIALIAS TRUE
        PARTIALS FALSE
      END
    END
    CLASS
      NAME "Cities"
      EXPRESSION ([POP] >= 5000 && [POP] < 24999)
      SYMBOL "circle"
      COLOR 255 255 255
      OUTLINECOLOR 0 0 0
      SIZE 5
      LABEL
        TYPE TRUETYPE
        FONT "arial-bold"
        SIZE 7
        POSITION AUTO
        BUFFER 5
        COLOR 0 0 0
        OUTLINECOLOR 245 245 231
        #ANTIALIAS TRUE
        PARTIALS FALSE
      END
    END
  END

Change History (24)

comment:1 by sdlime, 17 years ago

Status: newassigned

Do AGG and GD behave the same or not? If not I can't see how this is a scale bug... Hard to debug otherwise.

Steve

comment:3 by woodbri, 17 years ago

Cc: woodbri@… added

comment:4 by sdlime, 17 years ago

Note that #2193 is a duplicate of this, there's some discussion there.

Steve

comment:5 by sdlime, 17 years ago

Steve: Can you share the US_Places, or at least a small subset? I want to be able to test that layer snippet and your URLs to see what the computations (in mapserv.c) really are. I think it's likely that's where the problem is.

Steve

comment:6 by sdlime, 17 years ago

Cc: morissette added

Steve: I believe I fixed it. The inconsistency in extent models caused this problem. The code in maptemplate.c should be using width/height minus 1 when building the extent from a point and a scale value, and then msCalculateScale should also use width-1 when figuring the map distance. When I made those changes the scale and cellsize were identical before and after msAdjustExtent as I would expect.

cc'ing Dan...

Dan: Does this have any impact on the MapScript zoomScale method? I admit I don't quite get that method mostly because it requires a current extent and I don't know why that is necessary. The code in maptemplate.c (used by mapserv.c) just uses a point and a scale value and doesn't need the existing extent. (as an aside I'd like to get all the zoom code for both the CGI and MapScript ported to C and popped in a mapzoom.c)

An easy test would be to zoom to a scale in PHP/MapScript and have MapServer compute the scale. If they aren't the same then I suspect the off by 1 error.

Changes are in r6529 if anyone'd care to test and report back.

Steve

comment:7 by sdlime, 17 years ago

Oh, I see that zoomScale uses a image coordinate for point input so that's why you need the existing extent, to do the conversion to map units. Still should test scale before and after, they should be the same. Again, check the change set...

Steve

comment:9 by hobu, 17 years ago

Python MapScript tests now reporting this failure:

======================================================================
FAIL: MapExtentTestCase.testSetExtent: test the setting of a mapObj's extent
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/hobu/svn/mapserver/mapscript/python/tests/cases/maptest.py", line 73, in testSetExtent
    self.assertAlmostEqual(test_map.scaledenom, 14.173236)
  File "/Users/hobu/svn/mapserver/mapscript/python/tests/cases/testing.py", line 71, in assertAlmostEqual
    raise AssertionError, \
AssertionError: 14.244458291457285 != 14.173235999999999 within 7 places

comment:10 by sdlime, 17 years ago

Howard: I guess that confirms my worry. At lines 423 and 424 in mapscript/swiginc/mapzoom.i can you try changing width and height to (width-1) and (height-1) and re-run the test?

Steve

comment:11 by hobu, 17 years ago

I guess my question is does the test need to be updated because we were wrong all that time before, or does the test demonstrate we broke something?

Changing that to (width-1) results in three failures:

======================================================================
FAIL: ZoomScaleTestCase.testRecenter: recentering map returns proper extent
----------------------------------------------------------------------
Traceback (most recent call last):
  File "zoomtest.py", line 137, in testRecenter
    self.assertRectsEqual(new_extent, mapscript.rectObj(-50,-50,50,50))
  File "/Users/hobu/svn/mapserver/mapscript/python/tests/cases/testing.py", line 137, in assertRectsEqual
    self.assertAlmostEqual(first.minx, second.minx)
  File "/Users/hobu/svn/mapserver/mapscript/python/tests/cases/testing.py", line 71, in assertAlmostEqual
    raise AssertionError, \
AssertionError: -49.494949494949495 != -50.0 within 7 places

======================================================================
FAIL: ZoomScaleTestCase.testZoomInScale: zooming in to a specified scale returns proper extent
----------------------------------------------------------------------
Traceback (most recent call last):
  File "zoomtest.py", line 147, in testZoomInScale
    self.assertRectsEqual(new_extent, mapscript.rectObj(-25,-25,25,25))
  File "/Users/hobu/svn/mapserver/mapscript/python/tests/cases/testing.py", line 137, in assertRectsEqual
    self.assertAlmostEqual(first.minx, second.minx)
  File "/Users/hobu/svn/mapserver/mapscript/python/tests/cases/testing.py", line 71, in assertAlmostEqual
    raise AssertionError, \
AssertionError: -24.494949494949495 != -25.0 within 7 places

======================================================================
FAIL: ZoomScaleTestCase.testZoomOutScale: zooming out to a specified scale returns proper extent
----------------------------------------------------------------------
Traceback (most recent call last):
  File "zoomtest.py", line 157, in testZoomOutScale
    self.assertRectsEqual(new_extent, mapscript.rectObj(-100,-100,100,100))
  File "/Users/hobu/svn/mapserver/mapscript/python/tests/cases/testing.py", line 137, in assertRectsEqual
    self.assertAlmostEqual(first.minx, second.minx)
  File "/Users/hobu/svn/mapserver/mapscript/python/tests/cases/testing.py", line 71, in assertAlmostEqual
    raise AssertionError, \
AssertionError: -99.494949494949495 != -100.0 within 7 places

----------------------------------------------------------------------

comment:12 by sdlime, 17 years ago

You did hight-1 too correct? What does 4.10 output, nothing I assume.

Steve

comment:13 by hobu, 17 years ago

It looks like:

        dX = dfDeltaX/((double)width-1);
        dY = dfDeltaY/((double)height-1);

There were no failures in mapzoom in 4.10 AFAIK

comment:14 by sdlime, 17 years ago

I don't understand that code very well (zoomScale) do there may be another place to change. The code at lines 423/4 is only for converting from image to map coordinates. At line 437 there is another block using width/height for actually doing the extent computation. Try changing width/height there too.

Steve

comment:15 by hobu, 17 years ago

r6568 causes the tests to all pass... weird though

comment:16 by sdlime, 17 years ago

I don't see how that could affect things, so yes, wierd. I also see that the test isn't testing what I'd thought. I think we need a test of the scale before and after zooming. For example, if the requested scale is 50,000 in the call to zoomScale then that's what the computed scale should be after an extent is computed.

Testing the extent just tells us if things are consistent (e.g. I bet it works with width/height minus one in those couple of places), but not if they are correct.

Steve

comment:17 by hobu, 17 years ago

I have updated one mapscript test that was complaining about a different scaledenom

======================================================================
FAIL: MapExtentTestCase.testSetExtent: test the setting of a mapObj's extent
----------------------------------------------------------------------
Traceback (most recent call last):
  File "maptest.py", line 73, in testSetExtent
    self.assertAlmostEqual(test_map.scaledenom, 14.244458)
  File "/Users/hobu/svn/mapserver/mapscript/python/tests/cases/testing.py", line 71, in assertAlmostEqual
    raise AssertionError, \
AssertionError: 14.244458291457285 != 14.244458 within 7 places

Updated in r6726.

comment:18 by hobu, 17 years ago

Actually, the old failure was:

======================================================================
FAIL: MapExtentTestCase.testSetExtent: test the setting of a mapObj's extent
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/hobu/svn/mapserver/mapscript/python/tests/cases/maptest.py", line 73, in testSetExtent
    self.assertAlmostEqual(test_map.scaledenom, 14.173236)
  File "/Users/hobu/svn/mapserver/mapscript/python/tests/cases/testing.py", line 71, in assertAlmostEqual
    raise AssertionError, \
AssertionError: 14.244458291457285 != 14.173235999999999 within 7 places

comment:19 by hobu, 17 years ago

Are we done with this bug? I haven't noticed any issues anymore.

comment:20 by woodbri, 17 years ago

I'm good with this one. So close it if everyone else is ok with it.

comment:21 by hobu, 17 years ago

Resolution: fixed
Status: assignedclosed

Declaring it dead (for now :)

comment:22 by dmorissette, 17 years ago

Cc: dmorissette added; morissette removed

comment:23 by gisrob, 16 years ago

Resolution: fixed
Status: closedreopened

comment:24 by gisrob, 16 years ago

I've recently updated from 4.8.6 to 5.0.2 and fallen foul of this defect, where layers are not visible when I would expect them to be.

I'm in OSGB Projection (epsg:27700) but I didn't include this information in my sample mapfiles, in case it was a projection related issue. My implementation uses mapscript rather than the cgi mapserv process, but I have been testing using shp2img.

4.8.3 Mapfile

MAP
  EXTENT 200000 200000 266145 266145
  IMAGECOLOR 255 255 255
  IMAGETYPE png
  RESOLUTION 96.000000
  SIZE 500 500
  STATUS ON
  TRANSPARENT TRUE
  UNITS METERS
  NAME "Base"
  IMAGEQUALITY 75

  LEGEND
    IMAGECOLOR 255 255 255
    KEYSIZE 20 10
    KEYSPACING 5 5
    LABEL
      SIZE MEDIUM
      TYPE BITMAP
      BUFFER 0
      COLOR 0 0 0
      FORCE FALSE
      MINDISTANCE -1
      MINFEATURESIZE -1
      OFFSET 0 0
      PARTIALS TRUE
    END
    POSITION LL
    STATUS OFF
  END
  WEB
    IMAGEPATH "c:\tmp\"
    IMAGEURL "/"
    QUERYFORMAT text/html
    LEGENDFORMAT text/html
    BROWSEFORMAT text/html
  END
  LAYER
    MAXSCALE 500000
    MINSCALE 0
    NAME "Land"
    STATUS ON
    TRANSPARENCY 100
    TYPE RASTER
    UNITS METERS
    DATA "C:\Documents and Settings\Administrator\Desktop\gb\gbpng.tif"
  END
END

5.0.2 Mapfile

MAP
  EXTENT 200000 200000 266145 266145
  IMAGECOLOR 255 255 255
  IMAGETYPE png
  RESOLUTION 96.000000
  SIZE 500 500
  STATUS ON
  TRANSPARENT TRUE
  UNITS METERS
  NAME "Base"
  OUTPUTFORMAT
    NAME "png"
    MIMETYPE "image/png"
    DRIVER "GD/PNG"
    EXTENSION "png"
    IMAGEMODE "PC256"
    TRANSPARENT TRUE
  END
  PROJECTION
    "init=epsg:27700"
  END
  LEGEND
    IMAGECOLOR 255 255 255
    KEYSIZE 20 10
    KEYSPACING 5 5
    LABEL
      SIZE MEDIUM
      TYPE BITMAP
      BUFFER 0
      COLOR 0 0 0
      FORCE FALSE
      MINDISTANCE -1
      MINFEATURESIZE -1
      OFFSET 0 0
      PARTIALS TRUE
    END
    POSITION LL
    STATUS OFF
  END
  WEB
    IMAGEPATH "c:\tmp\"
    IMAGEURL "/"
    QUERYFORMAT text/html
    LEGENDFORMAT text/html
    BROWSEFORMAT text/html
  END
  LAYER
    DEBUG 5
    MAXSCALEDENOM 500000
    MINSCALEDENOM 0
    NAME "Land"
    STATUS ON
    TRANSPARENCY 100
    TYPE RASTER
    UNITS METERS
    DATA "C:\Documents and Settings\Administrator\Desktop\gb\gbpng.tif"
  END
END

GBPNG.TFW

333.333333333
0.000
0.000
-333.333333333
166.66666666
649833.33333333

Any 1000x1000 image should work.

Running shp2img against 4.8.3 will produce a valid image. Running shp2img against 5.0.2 does not.

Code is currently

center_y = (extent.miny+extent.maxy)/2.0;
   md = (width-1)/(resolution*msInchesPerUnit(units, center_y)); /* remember, we use a pixel-center to pixel-center extent, hence the width-1 */
   gd = extent.maxx - extent.minx;
   *scale = gd/md;

For the extents in the mapfiles, this gives a scale of 500997

Previously, using (width) instead of (width-1), we would have had 499993

My desktop GIS product seems to agree with the calculation to result in 499993, judging by the bbox it requests when zooming to 1:500,000

Full mapserver-users conversation is here - http://www.nabble.com/Problems-calculating-MAXSCALES-td18926188.html

Note: See TracTickets for help on using tickets.