public static void saveMaps(Extent extent, double resolution) { //Get the online layers var layers = GetLayersForMap(App.CurrentProjectId); //Create an array for adding the layers into in an ordered fashion var mapLayersTemp = new MapLayer[layers.Count]; //Add online wms layers var layerStack = layers.OrderBy(o => o.order).ToList(); foreach (var layer in layerStack) { string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), ""); var files = Directory.GetFiles(filePath); FileStream destination = File.Create(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "mbtiles/new.mbtiles")); using (var sourceStream = File.Open(filePath, FileMode.Open, FileAccess.Read)) { sourceStream.CopyTo(destination); } //Now add the layers in their correct order var layerNo = Math.Max(layers.Count - layer.order, 0); var tileSource = WMSLayer.CreateTileSource(layer.url, layer.wmsLayer, "EPSG:3857"); var tileInfos = tileSource.Schema.GetTileInfos(extent, resolution); // 3) Fetch the tiles from the service Console.WriteLine("Show tile info"); foreach (var tileInfo in tileInfos) { var tile = tileSource.GetTile(tileInfo); Console.WriteLine( $"Layer: {layer.title}, " + $"tile col: {tileInfo.Index.Col}, " + $"tile row: {tileInfo.Index.Row}, " + $"tile level: {tileInfo.Index.Level} , " + $"tile size {tile.Length}"); } } }
/// <summary> /// Save each of the map layers on-screen (the extent is provided by the screen edges) to an mbtiles file /// </summary> /// <param name="extent"></param> public static async void saveMaps(Extent extent) { var basemap = Preferences.Get("BaseLayer", "swisstopo_pixelkarte"); //Check which basemap var cancel = false; MessagingCenter.Subscribe <Application>(App.Current, "CancelMapSave", (sender) => { //Listen for tile save updates and update the count cancel = true; }); //Get the online layers var layers = GetLayersForMap(App.CurrentProjectId); //Create an array for adding the layers into in an ordered fashion var mapLayersTemp = new MapLayer[layers.Count]; //Add online wms layers var layerStack = layers.OrderBy(o => o.order).ToList(); //Calculate number of tiles var noOfLayers = 0; //Calculate number of tiles long noOfTiles = 0; foreach (var layer in layerStack) { if (layer.visible) { var tileSource = WMSLayer.CreateTileSource(layer.url, layer.wmsLayer, "EPSG:3857"); foreach (var zoomScale in tileSource.Schema.Resolutions) { var tileInfos = tileSource.Schema.GetTileInfos(extent, zoomScale.Value.UnitsPerPixel); noOfTiles = noOfTiles + tileInfos.Count(); } noOfLayers++; } } if (basemap == "swisstopo_pixelkarte") { string swisstopoDbpath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "mbtiles/swisstopo.mbtiles"); TileLayer swisstopo = WMSLayer.CreatePixelkarteWMTSTileLayer(); foreach (var zoomScale in swisstopo.TileSource.Schema.Resolutions) { var stTileInfos = swisstopo.TileSource.Schema.GetTileInfos(extent, zoomScale.Value.UnitsPerPixel); noOfTiles = noOfTiles + stTileInfos.Count(); } } else if (basemap == "swissimage") { string swisstopoDbpath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "mbtiles/swissimage.mbtiles"); TileLayer swisstopo = WMSLayer.CreateSwissimageWMTSTileLayer(); foreach (var zoomScale in swisstopo.TileSource.Schema.Resolutions) { var stTileInfos = swisstopo.TileSource.Schema.GetTileInfos(extent, zoomScale.Value.UnitsPerPixel); noOfTiles = noOfTiles + stTileInfos.Count(); } } else { string osmDbpath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "mbtiles/osm.mbtiles"); TileLayer osm = OpenStreetMap.CreateTileLayer(); foreach (var zoomScale in osm.TileSource.Schema.Resolutions) { var osmTileInfos = osm.TileSource.Schema.GetTileInfos(extent, zoomScale.Value.UnitsPerPixel); noOfTiles = noOfTiles + osmTileInfos.Count(); } } Console.WriteLine(noOfTiles + " tiles in " + (noOfLayers + 1) + " layers"); //Save tiles long tilesSaved = 0; MessagingCenter.Subscribe <Application>(App.Current, "TileSavedInternal", (sender) => { //Listen for tile save updates and update the count var message = tilesSaved + " von " + noOfTiles + " Kacheln aus " + (noOfLayers + 1) + " Ebenen gespeichert"; if (noOfLayers == 0) { message = tilesSaved + " von " + noOfTiles + " Kacheln aus " + (noOfLayers + 1) + " Ebene gespeichert"; } Console.WriteLine(message); MessagingCenter.Send <Application, string>(App.Current, "TileSaved", message); if (tilesSaved >= noOfTiles - 5 || cancel) { MessagingCenter.Send <Application, string>(App.Current, "TileSaved", String.Empty); MessagingCenter.Unsubscribe <Application>(App.Current, "TileSavedInternal"); MapModel.MakeArrayOfLayers(); } }); var tasks = new List <Task>(); // Each layer has to be saved in a single thread due to database access, but we can save layers concurrently foreach (var layer in layerStack) { if (cancel) { break; } if (layer.visible) { var layerNo = Math.Max(layers.Count - layer.order, 0); var tileSource = WMSLayer.CreateTileSource(layer.url, layer.wmsLayer, "EPSG:3857"); string dbpath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "mbtiles/" + layer.title + ".mbtiles"); //extent = tileSource.Schema.Extent; var layerTask = Task.Run(async() => { //Create the database Mbtiles.CreateMbTiles(dbpath, layer, tileSource); //Populate the database foreach (var zoomScale in tileSource.Schema.Resolutions) { if (cancel) { break; } await Task.Run(async() => { var tileInfos = tileSource.Schema.GetTileInfos(extent, zoomScale.Value.UnitsPerPixel); foreach (var tileInfo in tileInfos) { if (cancel) { break; } await Task.Run(() => { tilesSaved++; saveTile(tileSource, tileInfo, dbpath, layer); }); } }); } Console.WriteLine("Saving of 1 layer complete"); }); tasks.Add(layerTask); } } //Swisstopo layer var task = Task.Run(async() => { string baselayerDbsavepath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "mbtiles/swisstopo_pixelkarte.mbtiles"); TileLayer baselayer = WMSLayer.CreatePixelkarteWMTSTileLayer(); //Create the database var baseLayer = new BioDivCollectorXamarin.Models.DatabaseModel.Layer(); baseLayer.title = "swisstopo pixelkarte"; if (basemap == "osm") //OSM case { baselayerDbsavepath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "mbtiles/osm.mbtiles"); baselayer = OpenStreetMap.CreateTileLayer(); //Create the database baseLayer = new BioDivCollectorXamarin.Models.DatabaseModel.Layer(); baseLayer.title = "osm"; } else if (basemap == "swissimage") //Swissimage case { baselayerDbsavepath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "mbtiles/swissimage.mbtiles"); baselayer = WMSLayer.CreateSwissimageWMTSTileLayer(); //Create the database baseLayer = new BioDivCollectorXamarin.Models.DatabaseModel.Layer(); baseLayer.title = "swissimage"; } Mbtiles.CreateMbTiles(baselayerDbsavepath, baseLayer, baselayer.TileSource); //Populate the database foreach (var zoomScale in baselayer.TileSource.Schema.Resolutions) { if (cancel) { break; } await Task.Run(async() => { var baseLayerTileInfos = baselayer.TileSource.Schema.GetTileInfos(extent, zoomScale.Value.UnitsPerPixel); foreach (var tileInfo in baseLayerTileInfos) { if (cancel) { break; } await Task.Run(() => { tilesSaved++; saveTile(baselayer.TileSource, tileInfo, baselayerDbsavepath, baseLayer); }); } }); } Console.WriteLine("Baselayer saved"); }); tasks.Add(task); await Task.WhenAll(tasks); }