ThinkGeo.com    |     Documentation    |     Premium Support

Issue Drawing ThinkGeo.Core.Async.GoogleMapsLayer to GeoCanvas

Can you please assist or point me to any documentation for using ThinkGeo.Core.Async.GoogleMapsLayer that is replacing ThinkGeo.Core.GoogleMapsLayer? We include this layer to generate images for reports combined with other layers (i.e. InMemoryFeatureLayer, ShapeFileFeatureLayer, etc) using LayerOverlays and drawing them to a GeoImage using GeoCanvas. When I swtiched ThinkGeo.Core.GoogleMapsLayer to ThinkGeo.Core.Async.GoogleMapsLayer it is no longer drawing the Google imagery onto the GeoImage. We are using ThinkGeo version 13.3.0. The following error is thrown behind the scenes

System.Exception: Please call OpenAsync() instead of Open() 
   at ThinkGeo.Core.Async.LayerAsync.OpenCore()
   at ThinkGeo.Core.Layer.Open()
   at ThinkGeo.UI.WebApi.LayerOverlay.Dkc=(GeoCanvas geoCanvas)
   at ThinkGeo.UI.WebApi.LayerOverlay.DrawCore(GeoCanvas geoCanvas)
   at ThinkGeo.UI.WebApi.Overlay.Draw(GeoCanvas geoCanvas)

Here is a dumbed down version of our code that generates the image and and errors on layerOverlay.Draw(geoCanvas).

try
{
    var extent = new RectangleShape(-10576465.08714375, 4824786.890078585, -10570683.571714485, 4819005.374649317);
    var layerOverlay = new LayerOverlay();
    var googleLayer = new ThinkGeo.Core.Async.GoogleMapsLayer("apikey", "signingsecret")
    {
        MapType = GoogleMapsMapType.Hybrid,
        PictureFormat = GoogleMapsPictureFormat.Jpeg,
        Name = "Google",
        DrawingExceptionMode = DrawingExceptionMode.ThrowException
    };

    layerOverlay.Layers.Add(googleLayer);

    using (var image = new GeoImage(400, 400))
    {
        var geoCanvas = GeoCanvas.CreateDefaultGeoCanvas();
        geoCanvas.BeginDrawing(image, extent, GeographyUnit.Meter);
        layerOverlay.Draw(geoCanvas);

        geoCanvas.EndDrawing();

        // output image to temp file
        var guid = Guid.NewGuid();
        var fs = new System.IO.FileStream($@"C:\\temp\{guid}.jpg", System.IO.FileMode.Create);
        image.Save(fs, GeoImageFormat.Jpeg);
        fs.Close();
    }
}
catch (Exception ex)
{
    System.Diagnostics.Debug.WriteLine(ex.Message);
}

Hi Greg,

Sure, here it is:

  1. We suggest you direct request Google background from the client, instead of sending the request to webApi Server, which then forward the request to Google Server. Sending directly from the client would be much more efficient.

  2. If for some reason you want to keep the current way, you can do something like following:
    2.1 change the entry api to Async, so instead of

    [Route("{z}/{x}/{y}/")]
    [HttpGet]
    public IActionResult GetDynamicLayerTile(int z, int x, int y)
    

Use the following:

     [Route("{z}/{x}/{y}/")]
     [HttpGet]
     public async Task<IActionResult> GetDynamicLayerTile(int z, int x, int y)

2.2, Instead of calling layerOverlay.Draw(geoCanvas), directly use layer.DrawAsync

// ......
using (var image = new GeoImage(400, 400))
{
    var geoCanvas = GeoCanvas.CreateDefaultGeoCanvas();
    geoCanvas.BeginDrawing(image, extent, GeographyUnit.Meter);
   
    await googleLayer.OpenAsync();
    await googleLayer.DrawAsync(canvas, new Collection<SimpleCandidate>());

    // you can also call otherLayer.Draw() if otherLayer is not a web based layer, 
    await otherLayer.OpenAsync();
    await otherLayer.DrawAsync(canvas, new Collection<SimpleCandidate>());

    geoCanvas.EndDrawing();
   ....
  }
  1. More explanation:
    We suggest using DrawAsync for all the Web Based Layers, which is more efficient and makes the map more responsive. Also for WebAPI project, we suggest the users directly sending the request to the 3rd party server (mentioned in #1) to improve the performance. That’s why by default the LayerOverlay doesn’t handle those web based layers.

I hope that makes sense. Let us know if you have more questions.

Thanks,
Ben

Thanks Ben! This helps and I got it working.

Question and just making sure I’m not missing something on this snippet of code

// you can also call otherLayer.Draw() if otherLayer is not a web based layer, 
await otherLayer.OpenAsync();
await otherLayer.DrawAsync(canvas, new Collection<SimpleCandidate>());

Are you saying layers like ShapeFileFeatureLayer and InMemoryFeatureLayer have asynchronous versions? I only see these in the ThinkGeo.Core namespace and they do not have async methods. I was able to combine drawing them to the GeoCanvas but using the Open() and Draw() methods.

Hi Greg,

You can use DrawAsync if OtherLayers are web-based layers; and use Draw() if other layers are non-web-based layers (such as ShapeFileFeatureLayer of InMemoryFeatureLayer ). You are right there’s no async versions for those non-web based layers.

Thanks,
Ben