ThinkGeo.com    |     Blog    |     Wiki    |     Support

CurrentExtent changing when calling DrawStaticLayers

I have code I’m converting from Map Suite Services Edition version 6 to version 9.  In that code I have a MapEngine object (called mMapEngine) that I’m calling DrawStaticLayers on 



                                mMapEngine.DrawStaticLayers(mStaticBitMap, GeographyUnit.DecimalDegree)



Before the call to DrawStaticLayers, mMapEngine.CurrentExtent is the following.

{-37236.7404841679,866159.440251802,37236.7404841715,804532.410162199}



Somehow DrawStaticLayers is altering the mMapEngine.CurrentExtent as immediately upon returning from the call to DrawStaticLayers, mMapEngine.CurrentExtent is

{-582.890624998203,835828.268957001,582.890625001797,834863.581457001}



I do have a projection (a conic conformal projection) set on my map, but why is it possible for a call to DrawStaticLayers to alter the CurrentExtent of the map, especially by altering it to make it dramatically smaller in both width and height?  I could somewhat rationalize it making it smaller in either width or height to match some sort of aspect ratio, but to make it smaller in both makes absolutely no sense to me.



This same call to DrawStaticLayers in Map Suite 6 leaves the CurrentExtent completely unchanged.




Hi John, 
  
 The reason is that in our another products the extent for each zoom level is snapped, in order to make the MapEngine be compatible with our another products we did the same action when Draws layers in version 9. 
  
 Please let me know if this change has bad effects for your application. We’ll find out if there is a workaround for your scenario. 
  
 Thanks, 
 Peter

Yes, this has very bad effects for our application.  We give the user essentially an infinite number of zoom levels as opposed to a discrete set of zoom levels and we don’t work with tiles rather expect the map engine to generate exactly the map we specify.  Further exacerbating this issue is that we have a client-server application with ThinkGeo Map Suite being the map generation on the client and some layers generated server-side and returned as a basemap image on top of which we draw the client side layers.  We do this so that large, slow layers (such as raster imagery and streets) are generated server side and can be slow while the client-side map is very fast and therefore responsive.  When the user triggers a new map (pan, zoom in, zoom out) we 

1. change the map’s current extents

2. resample the previous server-side image that is held by the client to match that new extent

3. draw the client-side layers

4. request a new server-side map image be generated on a separate thread

5. when that server-generated map image is ready we use it as the new base image on top of which we draw our client-side layers and trigger another re-draw of the client-side layers on top of this server-side image.



Steps 1-4 take less than 1 second.  Generating that server-side image can take 2-30 seconds.  I’ve attached some maps that show how this looks.

Map1.jpg is the initial view.

Map2.jpg is after one second when the client-side layers have drawn over the resampled server-side image after a rubber-band zoom in.

Map3.jpg is after 20 seconds when the new server-generated basemap has arrived and the map has been redrawn.

Map4.jpg is after one second when the client-side layers have drawn over the resampled server-side image after a zoom out back to the original extent. (Our server-side image is a bit larger than the actual map so that we can support some panning without the user immediately running into an area without server-side map).

Map5.jpg is after 20 seconds when the new server-generated basemap has arrived and the map has been redrawn again.



Hopefully from the above it becomes apparent that telling Map Suite to generate a map and getting a different map in response is just outright not acceptable in our design.

Maps.zip (886 KB)

Hi John,



As I mentioned before, In order to make the MapEngine be compatible with another products we snap the extent. There is a workaround, please try calling the GeoImage DrawStaticLayers(GeoImage image, GeographyUnit mapUnit) method instead of DrawStaticLayers(Bitmap gdiPlusBitmap, GeographyUnit mapUnit) method.



then try following code to get the bitmap:

Bitmap bitmap = new Bitmap(image.GetImageStream(mapEngine.Canvas));



Hope it’s helpful.



Thanks,

Peter

Thanks for the quick response!  Yes, that worked very well.  A little bit of a learning curve to get it to work, but overall it seems to work very well.  Perhaps you can verify whether what I’ve done is appropriate.



For drawing the static layers and saving the resulting image in a BitMap called mStaticBitMap that I can reuse later when only needing to draw dynamic layers:

                                Dim image As GeoImage = New GeoImage(mMapControl.GetWidth, mMapControl.GetHeight)

                                mMapEngine.DrawStaticLayers(image, GeographyUnit.DecimalDegree)

                                mStaticBitMap = New Bitmap(image.GetImageStream(mMapEngine.Canvas))



For drawing the dynamic layers:

                                Dim stream As MemoryStream = New MemoryStream()

                                mStaticBitMap.Save(stream, System.Drawing.Imaging.ImageFormat.Tiff)

                                Dim image As GeoImage = New GeoImage(stream)

                                mMapEngine.DrawDynamicLayers(image, GeographyUnit.DecimalDegree)

                                mBitMap = New Bitmap(image.GetImageStream(mMapEngine.Canvas))



And now that mStaticBitMap isn’t being supplied to DrawStaticLayers, my handler which adds the underlying server-generated basemap before the first layer is drawn needed modified to not use mStaticBitmap and instead use the NativeImage property of the EventArgs like this:

        Public Sub LayersDrawingHandler(ByVal sender As Object, ByVal e As LayersDrawingEventArgs) Handles mMapEngine.LayersDrawing

            If mIsFirstLayer = False Then Return

            mIsFirstLayer = False

            'Dim g As Graphics = Graphics.FromImage(mStaticBitMap)

            Dim g As Graphics = Graphics.FromImage(e.NativeImage)

            DrawBackground(g, 0, 0)

        End Sub



Thanks very much for the workaround.  I think I’ve now run out of issues preventing me from moving to Map Suite 9.  Still a bit of regression testing that needs done, but the core functionality of my app is now running right.



Thanks!

John


Hi John, 
  
 I’m very glad to hear it worked.  
  
 Yes, the code for drawing dynamic layers you appended is appropriate. 
  
 Any questions please let me know. 
  
 Thanks, 
 Peter