ThinkGeo.com    |     Documentation    |     Premium Support

Switch between 2 layer without the OverlaySwitcher

Hello,


 


In my application, the user can export his map. For that, I have to use a GoogleMapsLayer in the StaticOverlay to have a background map but the loading is longer than a GoogleOverlay in the BackgroundOverlay.


To make it easier, I want to show to the user the GoogleOverlay but when he exports his map, I want to switch to the StaticOverlay to put a background in his bitmap.


I use this code to do it but it doesn't work:


Map1.BackgroundOverlay.IsVisible = false;

Map1.StaticOverlay.Layers["GoogleMapsLayer"].IsVisible = true;



ScreenPointF ul = Map1.ToScreenCoordinate(Map1.CurrentExtent.UpperLeftPoint);

ScreenPointF lr = Map1.ToScreenCoordinate(Map1.CurrentExtent.LowerRightPoint);

int width = Convert.ToInt32(lr.X - ul.X);

int height = Convert.ToInt32(lr.Y - ul.Y);



Bitmap bmp = Map1.GetBitmap(width, height);            

MemoryStream ms = new MemoryStream();

bmp.Save(ms, ImageFormat.Bmp);

byte[] myByte = ms.ToArray();



Map1.BackgroundOverlay.IsVisible = true;

Map1.StaticOverlay.Layers["GoogleMapsLayer"].IsVisible = false;




 


If I use the OverlaySwitcher, it works very well.


How can I switch between my 2 layers without the OverlaySwitcher.


 


The declaration of my 2 layers:


string sOverlayMapURL = "Google Key;



GoogleOverlay gOverlay = new GoogleOverlay();

gOverlay.Name = "Google Overlay";

gOverlay.GoogleMapType = GoogleMapType.Hybrid;



gOverlay.JavaScriptLibraryUri = new Uri(sOverlayMapURL);

Map1.BackgroundOverlay = gOverlay;





GoogleMapsLayer gLayer = new GoogleMapsLayer(sOverlayMapURL);

gLayer.Name = "GoogleMapsLayer";

gLayer.MapType = GoogleMapsMapType.Hybrid;

gLayer.PictureFormat = GoogleMapsPictureFormat.Jpeg;



Map1.StaticOverlay.Layers.Add("GoogleMapsLayer", gLayer);



Pierre, 
  
 GoogleMapsLayer is different from GoogleOverlay, GoogleOverlay sends requests directly to GoogleMap  while GoogleMapsLayer first sends requests to the web server which then forwarded them to GoogleMap, also, the required images will get to the web server first and then be transferred to your browser. That’s why GoogleMapsLayer is slower than GoogleOverlay.  
  
 To inactivate the GoogleMapLayer, your code should be “Map1.StaticOverlay.IsVisible = false” instead of “Map1.StaticOverlay.Layers[“GoogleMapsLayer”].IsVisible = false;”. Have a try and let me know if you have more issues. 
  
 Thanks, 
  
 Ben 


Hello, 
  
 I’ve tried your code but it doesn’t work. I still have no background map on the method getBitmap().




 


Pierre,


You can use Map1.ActiveBaseOverlay to switch the background overlay. Sorry I forgot to let you know last time. Here is a complete sample.


Thanks,


Ben




496-SwitchGoogleMaps.zip (10.5 KB)

Hello, 
  
 I had not had time to test this code but it works perfectly. 
 Thank you.

That’s great, let me know if you have more issues.

When I call Map1.GetBitmap(), the GoogleMapsLayer does not line up with the other layers. The GoogleMapsLayer aligns fine in the map itself, just not when you call GetBitmap().


Screenshot of Map:





GetBitMap() result:





See the difference in the blue boundary?

Rob, 
  
 We had a test and found GoogleMapLayer is 1~3 pixels off than GoogleOverlay, that’s a bug in GoogleMapLayer and we will work on it.   
 From your snapshots, seems the CurrentExtent is different, can you make it the same so we can see the real difference in your cases? Just let you know the method ExtentHelper.GetDrawingExtent will get the real drawing extent in case you want to use it. 
  
 Thanks, 
  
 Ben

That helps preserve the shape better, but its still shifted from where it should be.





Is this how I should be getting the Bitmap?


Map1.CurrentExtent = ExtentHelper.GetDrawingExtent(Map1.CurrentExtent, 576, 576);
Bitmap mapImage = Map1.GetBitmap(576, 576);





 


Rob,


That's strange. It's only 1~3 pixels off in my test. Please have a look at the attached test sample and check what's the difference to yours.


GoogleMapOverlay



GoogleMapLayer



Thanks,


Ben


 



582-SaveGoogleImageSample.zip (12.6 KB)

I think it might have something to do with using Callbacks. I modified your sample so it uses callbacks, and emulates how I setup the layers and overlays. It now gets the same problem as I am.



Also, in your sample, you seem to be talking about the difference between the maps when using different backgrounds. Both my google background types seem to line up fine, except when using Map1.GetBitmap(). Is it maybe something to do with client vs server CurrentExtent?


Here is the visual on the modified sample:




585-SaveGoogleImageCallback.zip (13.1 KB)

Rob,



Whenever you set the Current Extent, the map will snap to the closest ZoomLevel and the current extent will be changed a bit,  that means you need to pass the modified drawing extent back to the client by callback. Please have a look at the attached sample for detail. 



Thanks,



Ben



593-SaveGoogleImageSample.zip (21.5 KB)

That makes sense, but the problems come back as soon as I GetBitmap() with a width and height different than the maps width and height.



To see what I mean, add the following code to the sample

// add this in your Page_Load
Map1.Height = new Unit(600, UnitType.Pixel);
Map1.Width = new Unit(100, UnitType.Percentage);

// replace the GetBitmap().Save() line with
Map1.CurrentExtent = ExtentHelper.GetDrawingExtent(Map1.CurrentExtent, 576, 576);
Map1.GetBitmap(576, 576).Save("C:\GoogleMapsLayer.bmp");


Rob, 


That's because Google map has fixed scale which won’t be affected by map’s size, but the LayerOverlay will, it's why the image got by GetBitmap() function didn’t match perfectly. Another reason is that if you set map’s size by percentage like 100%, we can’t get the actual size in pixel on server side. In the attached sample, we passed the map's size back to server by callback to work it around. Please have a look.


Thanks


Ben



601-SaveGoogleImageSample.zip (9.61 KB)

That fixed it! Thanks for all the help. Hopefully I can leave you alone for a while 
  
 Do you expect the 1-3px offset bug to be fixed in the next release?

Rob, 
  
 It’s already on the schedule but I’m not sure if it can be solved in the coming release.  We will try our best anyway. 
  
 Thanks, 
  
 Ben

I’m trying to preserve the current extent when calling GetBitmaps().  I found ExtentHelper.ResizeExtent() which has an option MapResizeMode.PreserveExtent, but that seems to make the old lining up problems return.

If you change these 2 lines from the above SaveGoogleImageSample
double currentScale = ExtentHelper.GetScale(Map1.CurrentExtent, float.Parse(args[4]), GeographyUnit.Meter);
Map1.CurrentExtent = ExtentHelper.ZoomToScale(currentScale, Map1.CurrentExtent, GeographyUnit.Meter, 576, 576);

to this, you’ll see the problem 

Map1.CurrentExtent = ExtentHelper.ResizeExtent(Map1.CurrentExtent, float.Parse(args[4]), 576, 576, GeographyUnit.Meter, MapResizeMode.PreserveExtent);
Maybe it has something to do with going from a rectangle to a square extent. I’d like to get the largest square that fits within the rectangle (100% x 600px), use that extent, and shrink the image down to 576px x 576px.



Hi Rob, 



I think the lining up problem is raised by the different drawing logic between Google layer and Map Suite Feature Layer. When you call the GetBitmap method, you want to get a bitmap whose size could be not same as the current map control, so the current extent should be changed according to the bitmap size.


This is very like the resize operation on the map control. We can not control the draw logic (or the resize logic) of Google layer, which keeps the scale fixed and adjusts the extent no matter how you resize the map. So you need to keep the behavior of Map Suite Feature Layer to be same as Google layer to avoid the lining up problem.


The PreserveExtent mode is designed to keep the center point of current extent not change no matter how you resize the map, which may lead to the scale changed. So I think you need to keep the scale not change like before to make them match each other. 



Any more questions please let us know. 



Thanks, 



Sun 

 



I am trying to be able to export a smaller version of the same view. I don’t care about the scale(zoomlevel) being preserved. I want to preserve the center point, and (roughly) the extent that you are looking at. 
  
 I understand that Google static layers cannot be scaled. But how would I jump to the closest zoomlevel (that roughly preserves extent), then make sure the Map Suite Feature Layers get set to this same extent (so things line up)? 
  
 Thanks, 
 Rob

Rob,


We have a static API to be used to jump to the closest zoomlevel which called SnapToZoomLevel in the ExtentHelper class. So I think you could try to use this method to implement your requirement. The code could be like this in the RaiseCallbackEvent:


public void RaiseCallbackEvent(string eventArgument)
{
    string[] args = eventArgument.Split(',');
    Map1.CurrentExtent = new RectangleShape(double.Parse(args[0]), double.Parse(args[1]), double.Parse(args[2]), double.Parse(args[3]));
    ((LayerOverlay)Map1.CustomOverlays[1]).Layers[0].IsVisible = true;
    Map1.CurrentExtent = ExtentHelper.SnapToZoomLevel(Map1.CurrentExtent, GeographyUnit.Meter, 576, 576, new GoogleMapZoomLevelSet());
    Map1.GetBitmap(576, 576).Save("C:\\temp\\GoogleMapsLayer.bmp");

    callbackResult = "image saved";
}


Hope this helps.
Any more questions please let me know.
Thanks,
Sun