/// <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); }
public static ILayer CreateTempLayer(List <Mapsui.Geometries.Point> pointList) { var layerDic = new Dictionary <string, ILayer>(); var points = new List <Feature>(); var polygons = new List <Feature>(); var lines = new List <Feature>(); var allShapes = new List <Feature>(); var coords = pointList; var coordCount = pointList.Count; if (coordCount > 0) { if (coordCount == 1) { //Point var coord = coords[0]; var point = SphericalMercator.FromLonLat(coord.X, coord.Y); var feature = new Feature { Geometry = point, ["Name"] = Guid.NewGuid().ToString(), ["Label"] = "" }; feature.Styles.Add(new LabelStyle { Text = "", BackColor = new Mapsui.Styles.Brush(Mapsui.Styles.Color.White), HorizontalAlignment = LabelStyle.HorizontalAlignmentEnum.Left, Offset = new Offset(20, 0, false) }); points.Add(feature); ILayer pointLayer = MapModel.CreateTempPointLayer(points); return(pointLayer); } else { var coord0 = coords[0]; var coordx = coords[coordCount - 1]; if (coord0.X == coordx.X && coord0.Y == coordx.Y) { //Polygon var polygon = new Polygon(); var localCoords = coords; foreach (var coord in pointList) { var pt = SphericalMercator.FromLonLat(coord.X, coord.Y); polygon.ExteriorRing.Vertices.Add(new Mapsui.Geometries.Point(pt.X, pt.Y)); } var feature = new Feature { Geometry = polygon, ["Name"] = Guid.NewGuid().ToString(), ["Label"] = "" }; feature.Styles.Add(new LabelStyle { Text = "", BackColor = new Mapsui.Styles.Brush(Mapsui.Styles.Color.White), HorizontalAlignment = LabelStyle.HorizontalAlignmentEnum.Center }); polygons.Add(feature); ILayer polygonLayer = MapModel.CreatePolygonLayer(polygons, new Mapsui.Styles.Color(59, 181, 11, 255), new Mapsui.Styles.Color(59, 181, 11, 32)); return(polygonLayer); } else { //Line var line = new LineString(); var localCoords = coords; foreach (var coord in localCoords) { var pt = SphericalMercator.FromLonLat(coord.X, coord.Y); line.Vertices.Add(new Mapsui.Geometries.Point(pt.X, pt.Y)); } var feature = new Feature { Geometry = line, ["Name"] = Guid.NewGuid().ToString(), ["Label"] = "" }; feature.Styles.Add(new LabelStyle { Text = "", BackColor = new Mapsui.Styles.Brush(Mapsui.Styles.Color.White), HorizontalAlignment = LabelStyle.HorizontalAlignmentEnum.Center }); lines.Add(feature); ILayer lineLayer = MapModel.CreateLineLayer(lines, new Mapsui.Styles.Color(59, 181, 11, 255)); return(lineLayer); } } } return(null); }
/// <summary> /// Create an array of map layers: either mbtiles layers if offline and the mbtiles file exists, or direct links to the map servers /// </summary> /// <returns>An observable collection of map layers</returns> public static ObservableCollection <MapLayer> MakeArrayOfLayers() { int i = 0; //Add mbtiles layers var dirPath = Path.Combine(App.TileLocation, "mbtiles"); //Create directory if it doesn't exist if (!File.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } //Get the offline layers var offlineLayers = GetOfflineLayers(dirPath); //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(); bool noInternet = MapModel.IsAppDisconnected(); foreach (var layer in layerStack) { //Now add the layers in their correct order try { var layerNo = Math.Max(layers.Count - layer.order, 0); bool offlineLayerExists = offlineLayers.Keys.Contains(layer.title); if (noInternet && offlineLayerExists) { //If no internet, check for saved tiles ILayer offlineLayer; offlineLayers.TryGetValue(layer.title, out offlineLayer); if (offlineLayer != null) { offlineLayer.Opacity = layer.opacity; offlineLayer.Enabled = layer.visible; var WmsLayer = new MapLayer(true, 0, offlineLayer); WmsLayer.Opacity = layer.opacity; WmsLayer.Enabled = layer.visible; WmsLayer.LayerZ = layer.order; WmsLayer.Name = layer.title; mapLayersTemp.SetValue(WmsLayer, layerNo); var path = dirPath + "/" + layer.title; FileInfo fi = new FileInfo(dirPath + "/" + layer.title + ".mbtiles"); if (fi != null) { WmsLayer.LocalStorage = fi.Length; } else { WmsLayer.LocalStorage = 0; } i++; } } else { //If internet, read directly from WMS var layerWms = WMSLayer.CreateWMSLayer(layer.url, layer.wmsLayer, "EPSG:3857", layer.title); layerWms.Opacity = layer.opacity; layerWms.Enabled = layer.visible; if (layerWms != null) { var WmsLayer = new MapLayer(true, 0, layerWms); WmsLayer.Opacity = layer.opacity; WmsLayer.Enabled = layer.visible; WmsLayer.LayerZ = layer.order; WmsLayer.Name = layer.title; mapLayersTemp.SetValue(WmsLayer, layerNo); if (offlineLayerExists) { var path = dirPath + "/" + layer.title; FileInfo fi = new FileInfo(dirPath + "/" + layer.title + ".mbtiles"); if (fi != null) { WmsLayer.LocalStorage = fi.Length; } else { WmsLayer.LocalStorage = 0; } } i++; } } } catch (Exception e) { Console.WriteLine(e); } } var mapLayersTempList = mapLayersTemp.ToList().GetRange(0, i); return(new ObservableCollection <MapLayer>(mapLayersTempList as List <MapLayer>)); }