When I run the following, the layer is still not open and results in an exception when I subsequently try to set the ActiveLayerName.
WmtsAsyncLayer lyr = new WmtsAsyncLayer(uri);
await lyr.OpenAsync();
When I run the following, the layer is still not open and results in an exception when I subsequently try to set the ActiveLayerName.
WmtsAsyncLayer lyr = new WmtsAsyncLayer(uri);
await lyr.OpenAsync();
ActiveLayerName is supposed to be set before opening the layer, otherwise the layer has no idea what specific data to fetch from the server. And updating ActiveLayerName after OpenAsync will not work until reopenning the layer.
If you do have issue when setting layer.ActiveLayerName == “layerName”, please let me know what the exception is.
The exception is that the layer must be opened first. This is the code I was using originally which is why I added the OpenAsync after defining the layer.
WmtsAsyncLayer lyr = new WmtsAsyncLayer(uri);
lyr.ActiveLayerName = lyr.GetServerTileMatrixSetNames().FirstOrDefault();
Hi @Damian_Hite,
You must set the TileMatrixSetName property first, and then call OpenAsync method.
You could check TileMatrixSetName on wmts_uri?Service=WMTS&Request=GetCapabilities or wmts_uri/WMTSCapabilities.xml.
var wmtsAsyncLayer = new WmtsAsyncLayer(new Uri("your_wmts_uri"));
wmtsAsyncLayer.TileMatrixSetName = "matrix_set_name";
await wmtsAsyncLayer.OpenAsync();
Regards,
Leo
Leo,
Sorry, I don’t get it. Why do you have functions such as GetServerTileMatrixSetNames() if you can’t use them upfront to set the values? This is how v10 worked…
At any rate, something else is wrong here. I manually set the TileMatrixSetName to one that I know is there and the OpenAsync generated the following errors and the layer was still not open afterwards.
Exception thrown: ‘System.NotImplementedException’ in SurveyDesign.dll
Exception thrown: ‘System.NotImplementedException’ in mscorlib.dll
Exception thrown: ‘System.NotImplementedException’ in SurveyDesign.dll
Exception thrown: ‘System.NotImplementedException’ in mscorlib.dll
Exception thrown: ‘System.Collections.Generic.KeyNotFoundException’ in mscorlib.dll
Exception thrown: ‘System.Collections.Generic.KeyNotFoundException’ in mscorlib.dll
Exception thrown: ‘System.InvalidOperationException’ in ThinkGeo.Core.dll
hi @Damian_Hite,
Could you let me know the wmts url? If you prefer not to post it here, please feel free to email to me: leoliu@thinkgeo.com.
Regards,
Leo
Sure. Here it is.
https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/WMTS
hi @Damian_Hite,
The following code worked for me, you could give it a try.
Here’s the complete sample.
WmtsAsyncLayerSample.zip (11.7 KB)
var layerOverlay = new LayerOverlay();
MapView.Overlays.Add(layerOverlay);
wmtsAsyncLayer = new WmtsAsyncLayer(new Uri("https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/WMTS"));
wmtsAsyncLayer.TileMatrixSetName = "default028mm";
await wmtsAsyncLayer.OpenAsync();
var layers= wmtsAsyncLayer.GetServerLayerNames();
var styles = wmtsAsyncLayer.GetServerLayerStyles();
var matrixSetName = wmtsAsyncLayer.GetServerTileMatrixSetNames();
var formats = wmtsAsyncLayer.GetLayerOutputFormats(layers[0]);
wmtsAsyncLayer.DrawingExceptionMode = DrawingExceptionMode.DrawException;
wmtsAsyncLayer.ActiveLayerName = layers[0];
wmtsAsyncLayer.ActiveStyleName = styles[0];
wmtsAsyncLayer.OutputFormat = formats[0];
layerOverlay.TileType = TileType.SingleTile;
layerOverlay.Layers.Add(wmtsAsyncLayer);
// Create a zoomlevelSet from the WMTS server
MapView.ZoomScales = GetZoomLevelSetFromWmtsServer().GetScales();
MapView.CurrentExtent = wmtsAsyncLayer.GetBoundingBox();
await MapView.RefreshAsync();
Regards,
Leo
Hi Leo,
In my code, I was adding some events for sending and receiving http responses before setting the TileMatrixSetName which appears to have been the issue.
However, I have a related issue. I use the following code to find a layer by name, but it seems that once I add a WmtsAsyncLayer to this overlay that it is not of type Layer and I get an exception. How can I get around this other than putting all of these layer types into an overlay that is not searched or is that the best way?
foreach (Layer fl in overlay.Layers)
{
if (fl.Name == name)
return fl;
}
hi @Damian_Hite,
WmtsAsyncLayer doesn’t inherit from Layer, that’s why the type cast error occurred. You could use LayerBase here.
foreach (LayerBase fl in overlay.Layers)
{
if (fl.Name == name)
return fl;
}
Regards,
Leo
Hi Leo,
Okay, we’re getting there. I am now able to display my layer.
Regarding the TileCache. Even when I set this, it doesn’t appear to be saving anything. Is it because it is in SingleTile mode?
I am starting to think that having a dedicated overlay for WMS and WMTS layers would be a good idea that way I can set MultiTile mode and get some speed advantage. Is there any documentation on optimizing layers for speed?
hi @Damian_Hite,
TileCache should work even it’s SingleTile. I just added the following code to WmtsAsyncLayerSample.zip, as you can see, D:\hey folder had the tile caches.
wmtsAsyncLayer.TileCache = new FileRasterTileCache(@“D:\hey”);
MultiTile mode does look more smooth than SingleTile, it’s a good choice.
Regarding the speed, You could use the fast mode of WmsAsyncLayer if you’re sure about the CRS, axis order and version. In the code below, the last parameter means fastMode. True means it won’t send http requst to fetch capability xml.
WmsAsyncLayer wmsAsyncLayer = new WmsAsyncLayer(new Uri(“your_wms_uri”), null, “EPSG:4326”, WmsAxisOrder.XY, “1.3.0”, true)
Regards,
Leo
Hi Leo,
I am setting both a TileCache and a ProjectedTileCache like so.
string cacheDir = MyParentForm.DataDirectory + @"\TileCache\WMTS";
string cacheProjDir = MyParentForm.DataDirectory + @"\TileCache\ProjectedWMTS";
lyr.TileCache = new FileRasterTileCache(cacheDir, wmsName);
lyr.ProjectedTileCache = new FileRasterTileCache(cacheProjDir, wmsName);
The regular TileCache seems to be working sometimes, but not the projected one at all. Is ProjectedTileCache useful in v14? Or do the two cancel each other out? Which one is best?
It would be great to have faster mode, but I think you have confused WMS with WMTS. There is no call for WMTS that has those parameters.
hi @Damian_Hite,
ProjectedTileCache only works when ProjectedTileCache of WmsAsyncLayer is not null. If ProjectionConverter is null, just use TileCache.
Regarding faster mode, it’s for WMS only, WMTS doesn’t support it yet. If you’d like to speed up WMTS, I think TileCache is the best way.
Regards,
Leo
Hi Leo,
My code has assigned a ProjectionConverter to the layer yet I don’t get anything in the projected tile cache.
Also the standard tile cache doesn’t always write things. What governs when tile cache is written to? I have seen it go for long periods of time and not write any files.
hi @Damian_Hite,
Do you use ProjectionConverter or GdalProjectionConverter? For raster layer, we should use GdalProjectionConverter(ThinkGeo.Gdal is required). ProjectedTileCache works with my sample, could you have a look? If the problem persists, could you update the sample and get back to me?
wmtsAsyncLayer.ProjectionConverter = new GdalProjectionConverter(3857, 4326);
WmtsAsyncLayerSample(Projection).zip (14.6 KB)
Regards,
Leo