ThinkGeo.com    |     Documentation    |     Premium Support

Printing WmsAsyncLayer

Hi,

We have a project that allows maps to be printed. It builds up the layers by using MapPrinterLayer.Layers.Add(layer). However we would like to include one or more WmsAsyncLayers on the print but these are not of type Layer but rather LayerBase so we cannot add them.

Could you help understand how to include wms layers on a printout?

Thanks,
Jonathan

Hi Jonathan,

LayerBase is the base class of Layer and AsyncLayer, meaning you can add a WmsAsyncLayer into MapPrinterLayer.Layers (which is a collection of LayerBase) without any issues.

If you are not using the latest version, chances are the Layers are a collection of Layers instead of a collection of LayerBases and you will have an issue adding an AsyncLayer. Just upgrade it to the latest version would be fine.

Thanks,
Ben

Hi Ben,
Thanks for the suggestion. I updated .Printers and .Core to 4.3.0-beta064 from -beta012 and that did make a significant difference however it also appeared to introduce a different problem with WMTS layers that were working before the update. What looks to be happening is that in the previous version the WMTS sourced tiles all fitted together correctly on -beta064 they either misalign or have huge gaps depending on zoom level.

Should I raise a ticket and send some screen shots.

Kind Regards,
Jonathan

Hi Jonathan,

We recently made lots of improvements on WMTS. In the latest HowDoI sample (beta branch: samples/wpf/HowDoISample · master · ThinkGeo / Public / Desktop Maps · GitLab), you can find 2 WMTS Samples (“WMTS” is using WmtsOverlay while “Display Raster from WMTS Server” is using the WmtsAsyncLayer), in the sample we fetched the zooms from the WMTS server instead of using the 20 default zooms, we enabled client projection, support rendering lower zooms by stretching the tiles from upper zooms, and displayed debug info to help you understand where the tiles from. I’d suggest you check out that sample first, and if you still have issues, feel free to create a ticket and share some code to us and we can dive in.

Thanks,
Ben

Hi Ben,
I downloaded the sample project but cannot see the XYZ Based Layers node in the sample application tree and searching for WmtsOverlay in the code found no instances. So I am having trouble finding the relevant example.

Thanks,
Jonathan

Sorry, my bad. I told you beta branch but the link I sent is for master, here it is the right one: samples/wpf/HowDoISample · develop · ThinkGeo / Public / Desktop Maps · GitLab

Just FYI we just released v14.2.2 and we are in the middle of updating all the HowDoI samples, you will see the update samples in master branch in a couple days.

Hi Ben,
I am slowly getting there and have found that WmtsAsyncLayer works better than WmtsServer for resizing tiles and getting them in the right places. However still having problems with one source, MapBox, that needs to be reprojected, I had set this up as

myWmtsAsyncLayer.ProjectionConverter = new GdalProjectionConverter(3857, 27700);

But that is giving strange results with tiles looking to be in the wrong places, like a badly finished jigsaw, and maybe other inaccuracies.

I see that the example does have some reprojection information so will look into that next…

Jonathan

HI Jonathan,

The reprojection should have been taken care of. Take a look at the example and please send me your code snippet if you still see the issues.

Thanks,
Ben

Hi Ben,
Unfortunately we are still having a variety of issues including:

  • Tiles look muddled up. I think they are the correct tiles but definitely in the wrong order and I have not picked up a pattern for how they are disarranged.

  • As you zoom in the tiles have gaps between

  • Adding a projected tile cache causes an error that shows as the message ‘Arithmetic operation resulted in an overflow’ instead of actual tiles.

The code looks like this:

        private static void InitialiseBackgrounds(MapView mapControl)
    {
        // If the setting exists in the setting file, then osMapsAPIKey will come out with its corresponding value and it returns true
        // Otherwise it returns false (meaning the osMapsAPIKey will contain an empty value) and we set it to the default key
        // To add a user key use a line like this in the setting file:
        // <OSMapsAPIKey>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</OSMapsAPIKey>

        Setting settings = new Setting(Setting.Usage.DEFAULT, Setting.Areas.GENERAL);

        if (!settings.GetSettingsValues().TryGetValue(Setting.GeneralKeys.OSMAPS_API_KEY, out _osMapsAPIKey))
            SetStandardOSKey();

        if (!settings.GetSettingsValues().TryGetValue(Setting.GeneralKeys.MAPBOX_API_KEY, out _mapboxAPIKey))
            SetStandardMapBoxKey();

        osMapLayer = new WmtsAsyncLayer(new Uri("https://api.os.uk/maps/raster/v1/wmts"))
        {
            Name = OS_BACKGROUND,
            AxisOrder = WmtsAxisOrder.XY,
            DrawingExceptionMode = DrawingExceptionMode.DrawException,
            WebProxy = null,
            ActiveLayerName = "Road_27700",
            ActiveStyleName = "Road",
            TileMatrixSetName = "EPSG:27700",
            IsVisible = true,
            OutputFormat = "image/png",
        };

        osMapLayer.TileCache = CreateCacheForLayer(osMapLayer.ActiveLayerName, MapBackgroundLayerStyle.OSAPI);
        osMapLayer.SendingHttpRequest += OsMapLayer_SendingHttpRequest;

        mapBoxLayer = new WmtsAsyncLayer(new Uri("https://api.mapbox.com/styles/v1/lukeor/ckfy0j3ye01d019pfob9re2zi/wmts"))
        {
            Name = MAPBOX_BACKGROUND,
            AxisOrder = WmtsAxisOrder.XY,
            DrawingExceptionMode = DrawingExceptionMode.DrawException,
            WebProxy = null,
            ActiveLayerName = "ckfy0j3ye01d019pfob9re2zi",
            ActiveStyleName = "default",
            TileMatrixSetName = "GoogleMapsCompatible",
            ProjectionConverter = new GdalProjectionConverter(3857, 27700),
            IsVisible = true,
        };

        mapBoxLayer.TileCache = CreateCacheForLayer(mapBoxLayer.ActiveLayerName, MapBackgroundLayerStyle.SATELLITE);
        mapBoxLayer.ProjectedTileCache = CreateCacheForLayer(mapBoxLayer.ActiveLayerName, MapBackgroundLayerStyle.SATELLITE_PROJECTED);

        // Include the key as a parameter
        mapBoxLayer.Parameters.Add("access_token", _mapboxAPIKey);

        wmtsBackgrounds.Name = WMTS_OVERLAY_NAME;
        wmtsBackgrounds.Layers.Add(MAPBOX_BACKGROUND, mapBoxLayer);
        wmtsBackgrounds.Layers.Add(OS_BACKGROUND, osMapLayer);            
        mapControl.Overlays.Add(WMTS_OVERLAY_NAME, wmtsBackgrounds);
        mapControl.Overlays.MoveToBottom(wmtsBackgrounds);
    }

Hi Jonathan,

Thanks for reporting. It does have some issues projecting from 27700 to 3857, and it’s been fixed in the latest beta074. Please have another try. Here below is how I tested:

1, I signed up an account at https://api.os.uk, get a key
2. I modified the WMTS HowDoI sample as following:

  wmtsAsyncLayer = new WmtsAsyncLayer(new Uri("https://api.os.uk/maps/raster/v1/wmts"))
  {
  Name = "OS_BACKGROUND",
  AxisOrder = WmtsAxisOrder.XY,
  DrawingExceptionMode = DrawingExceptionMode.DrawException,
  WebProxy = null,
  ActiveLayerName = "Road_27700",
  ActiveStyleName = "Road",
  TileMatrixSetName = "EPSG:27700",
  IsVisible = true,
  OutputFormat = "image/png",
  };
  
  //wmtsAsyncLayer.SendingHttpRequest += WmtsAsyncLayer_SendingHttpRequest;
  wmtsAsyncLayer.Parameters.Add("key", "GHA684whwoGwDnKtFHUB2dPqp6sr6Bdy");

  layerOverlay.TileType = TileType.SingleTile;
  layerOverlay.Layers.Add(wmtsAsyncLayer);
  1. Here is what it looks like:

reprojected to 3857 (there are 2 sets of tile ids, one is from the original cache tiles and the other is from the projected cache tiles)

Thanks,
Ben

Hi Ben,

Nice work on projecting 27700 to 3857, looked like the .SingleTile was the key bit?

I have updated the nuget packages but still have some problems with tile ordering, however I am going to have to shelf this one for a little while as need to work on some other things. There was also a problem with updating the packages. I updated ThinkGeo.Gdal OK, but if I tried to update ThinkGeo.Gdal.Dependancy.Windows to 14.0.1 that introduced a runtime error about no entry point for DLL. Also still get the same error as before when using the projected tile cache.

Thanks,
Jonathan

Hi Jonathan,

MultiTile will bring you some performance penalty as it will do a reprojection for each tile, so yes, I would suggest you using singleTile for this case.

“no entry point for DLL” errors means your gdal dependency doesn’t match the callers in ThinkGeo.Gdal package. Please avoid updating ThinkGeo.Gdal.Dependancy.Windows yourself, just update ThinkGeo.Gdal if needed which will update ThinkGeo.Gdal.Dependancy.Windows if necessary.

Thanks,
Ben

OK, thanks. We found the tile ordering problem was due to using the wrong tile size and changing to 512x512 fixed that.

All the best,
Jonathan

Glad to hear that! :+1: