static void Main(string[] args) { double minLon = -81.4822; double minLat = 27.4582; double maxLon = -81.3475; double maxLat = 27.5832; double[] wgs84Bounds = new double[4] { minLon, minLat, maxLon, maxLat }; string urlFormat = "http://a.tile.openstreetmap.org/{z}/{x}/{y}.png"; var ts = new BruTile.Web.HttpTileSource(new GlobalSphericalMercator(0, 18), urlFormat, null, "OpenStreetMap", null, null, null); TileDownloadOptions tdo = new TileDownloadOptions { DBFilename = "myDatabase.mbtiles", Level = 14, UriFormat = urlFormat, DBName = "Offline", DBDescription = "Offline", MaxAge = new TimeSpan(60, 0, 0, 0), }; MBTilesDownloader.TileCacher.Cache(tdo, wgs84Bounds, ts); }
public static void Cache(TileDownloadOptions options, double[] bounds, BruTile.Web.HttpTileSource tileSource) { List <double[]> list = new List <double[]>(); list.Add(bounds); Cache(options, list, tileSource); }
public static void Cache(TileDownloadOptions options, List <double[]> boundsList, BruTile.Web.HttpTileSource tileSource) { double[] originalBounds = new double[4] { double.MaxValue, double.MaxValue, double.MinValue, double.MinValue }; // In WGS1984, the total extent of all bounds List <TileInfo> tileInfos = new List <TileInfo>(); foreach (double[] xy in boundsList) { if (xy[0] < originalBounds[0]) { originalBounds[0] = xy[0]; } if (xy[1] < originalBounds[1]) { originalBounds[1] = xy[1]; } if (xy[2] > originalBounds[2]) { originalBounds[2] = xy[2]; } if (xy[3] > originalBounds[3]) { originalBounds[3] = xy[3]; } ToMercator(ref xy[0], ref xy[1]); ToMercator(ref xy[2], ref xy[3]); // xy is now in SphericalMercator projection BruTile.Extent extent = new BruTile.Extent(xy[0], xy[1], xy[2], xy[3]); var curTileInfos = tileSource.Schema.GetTileInfos(extent, options.Level.ToString()); foreach (var tileInfo in curTileInfos) { TileInfo ti = tileInfos.Where(x => x.Index.Col == tileInfo.Index.Col && x.Index.Row == tileInfo.Index.Row && x.Index.Level == tileInfo.Index.Level).FirstOrDefault(); if (ti != null) // This tile is already in the list { continue; } tileInfos.Add(tileInfo); } } if (options.MaxAge.HasValue) { using (var db = new SQLite.SQLiteConnection(options.DBFilename)) { // Create the tables, so at least they will exist db.CreateTable <MBTiles.Domain.metadata>(); db.CreateTable <MBTiles.Domain.tiles>(); for (int i = 0; i < tileInfos.Count; i++) { TileInfo tileInfo = tileInfos[i]; int tileLevel = int.Parse(tileInfo.Index.Level); int tileRow = OSMtoTMS(tileLevel, tileInfo.Index.Row); MBTiles.Domain.tiles oldTile = db.Table <MBTiles.Domain.tiles>().Where(x => x.zoom_level == tileLevel && x.tile_column == tileInfo.Index.Col && x.tile_row == tileRow).FirstOrDefault(); if (oldTile != null && (DateTime.Now - oldTile.createDate) <= options.MaxAge.Value) { // This tile hasn't expired yet, so don't download it. tileInfos.Remove(tileInfo); i--; } } } } // Make sure we have any tiles left to download. If not, we are done! if (tileInfos.Count == 0) { return; } ConcurrentBag <LoadedTile> bag = new ConcurrentBag <LoadedTile>(); using (System.Net.Http.HttpClient client = new System.Net.Http.HttpClient()) { List <Task> fetchTasks = new List <Task>(); foreach (var ti in tileInfos) { fetchTasks.Add(Task.Run(async() => await FetchTile(ti, client, bag, options.UriFormat))); if (fetchTasks.Count > 1) // Limit 2 to concurrent download threads { Task.WaitAll(fetchTasks.ToArray()); fetchTasks.Clear(); } } Task.WaitAll(fetchTasks.ToArray()); } using (var db = new SQLite.SQLiteConnection(options.DBFilename)) { db.CreateTable <MBTiles.Domain.metadata>(); db.CreateTable <MBTiles.Domain.tiles>(); var metaList = new List <MBTiles.Domain.metadata>(); metaList.Add(new MBTiles.Domain.metadata { name = "name", value = options.DBName }); metaList.Add(new MBTiles.Domain.metadata { name = "type", value = "baselayer" }); metaList.Add(new MBTiles.Domain.metadata { name = "version", value = "1" }); metaList.Add(new MBTiles.Domain.metadata { name = "description", value = options.DBDescription }); metaList.Add(new MBTiles.Domain.metadata { name = "format", value = bag.First().mimeType.Contains("/png") ? "png" : "jpg" }); foreach (var meta in metaList) { db.InsertOrReplace(meta); } // Expand the bounds var existingBounds = db.Table <MBTiles.Domain.metadata>().Where(x => x.name == "bounds").FirstOrDefault(); if (existingBounds != null) { var components = existingBounds.value.Split(','); var existingExtent = new double[4] { double.Parse(components[0], NumberFormatInfo.InvariantInfo), double.Parse(components[1], NumberFormatInfo.InvariantInfo), double.Parse(components[2], NumberFormatInfo.InvariantInfo), double.Parse(components[3], NumberFormatInfo.InvariantInfo) }; if (originalBounds[0] < existingExtent[0]) { existingExtent[0] = originalBounds[0]; } if (originalBounds[1] < existingExtent[1]) { existingExtent[1] = originalBounds[1]; } if (originalBounds[2] > existingExtent[2]) { existingExtent[2] = originalBounds[2]; } if (originalBounds[3] > existingExtent[3]) { existingExtent[3] = originalBounds[3]; } existingExtent.CopyTo(originalBounds, 0); } db.InsertOrReplace(new MBTiles.Domain.metadata { name = "bounds", value = String.Join(",", originalBounds) }); foreach (var lt in bag) { MBTiles.Domain.tiles tile = new MBTiles.Domain.tiles(); tile.zoom_level = int.Parse(lt.ti.Index.Level); tile.tile_column = lt.ti.Index.Col; tile.tile_row = lt.ti.Index.Row; tile.tile_data = lt.data; tile.createDate = DateTime.Now; tile.tile_row = OSMtoTMS(tile.zoom_level, tile.tile_row); MBTiles.Domain.tiles oldTile = db.Table <MBTiles.Domain.tiles>().Where(x => x.zoom_level == tile.zoom_level && x.tile_column == tile.tile_column && x.tile_row == tile.tile_row).FirstOrDefault(); if (oldTile != null) { tile.id = oldTile.id; db.Update(tile); } else { db.Insert(tile); } } } }