using System; using System.Collections.Generic; using System.IO; using System.Text; using OnlineMaps; using UnityEngine; public class TileDownloader4: MonoBehaviour { private string folder; private double leftLongitude; private double topLatitude; private double rightLongitude; private double bottomLatitude; private int minZoom = 3; private int maxZoom = 20; private const int averageSize = 30000; private long countTiles = 0; private long totalSize = 0; private static Map map; private Rectangle rect; private List downloadTiles; private void Calculate() { countTiles = 0; GeoRect geoRect = new GeoRect(leftLongitude, topLatitude, rightLongitude, bottomLatitude); for (int z = minZoom; z <= maxZoom; z++) { TileRect r = geoRect.ToTileRect(map, z); r.FixWrap(); int itlx = (int) r.left; int itly = (int) r.top; int ibrx = (int)Math.Ceiling(r.right); int ibry = (int)Math.Ceiling(r.bottom); countTiles += (ibrx - itlx) * (ibry - itly); } totalSize = countTiles * averageSize; } private double DoubleField(string label, double value) { GUILayout.BeginHorizontal(); GUILayout.Label(label, GUILayout.Width(150)); string strVal = GUILayout.TextField(value.ToString()); GUILayout.EndHorizontal(); double newValue; if (double.TryParse(strVal, out newValue)) return newValue; return value; } private void Download() { downloadTiles = new List(); GeoRect geoRect = new GeoRect(leftLongitude, topLatitude, rightLongitude, bottomLatitude); for (int z = minZoom; z <= maxZoom; z++) { TileRect r = geoRect.ToTileRect(map, z); r.FixWrap(); int itlx = (int)r.left; int itly = (int)r.top; int ibrx = (int)Math.Ceiling(r.right); int ibry = (int)Math.Ceiling(r.bottom); for (int x = itlx; x < ibrx; x++) { for (int y = itly; y < ibry; y++) { downloadTiles.Add(new Tile { x = x, y = y, zoom = z }); } } countTiles += (ibrx - itlx) * (ibry - itly); } StartNextDownload(); } private string GetTilePath(Tile tile) { return GetTilePath(tile.zoom, tile.x, tile.y); } private string GetTilePath(int zoom, int x, int y) { StringBuilder builder = new StringBuilder(folder); builder.Append(map.activeType.fullID).Append("/"); builder.Append(zoom).Append("/"); builder.Append(x).Append("/"); builder.Append(y).Append(".png"); return builder.ToString(); } private int IntField(string label, int value) { GUILayout.BeginHorizontal(); GUILayout.Label(label, GUILayout.Width(150)); string strVal = GUILayout.TextField(value.ToString()); GUILayout.EndHorizontal(); int newValue; if (int.TryParse(strVal, out newValue)) return newValue; return value; } private void OnGUI() { GUILayout.BeginArea(new Rect(10, 10, 300, Screen.height - 20)); double newLeftLongitude = DoubleField("Left Longitude", leftLongitude); double newTopLatitude = DoubleField("Top Latitude", topLatitude); double newRightLongitude = DoubleField("Right Longitude", rightLongitude); double newBottomLatitude = DoubleField("Bottom Latitude", bottomLatitude); bool updateRect = false; if (Math.Abs(newLeftLongitude - leftLongitude) > double.Epsilon) { leftLongitude = newLeftLongitude; updateRect = true; } if (Math.Abs(newRightLongitude - rightLongitude) > double.Epsilon) { rightLongitude = newRightLongitude; updateRect = true; } if (Math.Abs(newBottomLatitude - bottomLatitude) > double.Epsilon) { bottomLatitude = newBottomLatitude; updateRect = true; } if (Math.Abs(newTopLatitude - topLatitude) > double.Epsilon) { topLatitude = newTopLatitude; updateRect = true; } if (updateRect) UpdateRect(); minZoom = IntField("Min Zoom", minZoom); maxZoom = IntField("Max Zoom", maxZoom); if (GUILayout.Button("Place")) PlaceRect(); if (GUILayout.Button("Calculate")) Calculate(); GUILayout.Label("Count Tiles: " + countTiles); GUILayout.Label("Total Size: " + totalSize); if (GUILayout.Button("Download")) Download(); GUILayout.EndArea(); } private void OnStartDownloadTile(OnlineMaps.Tile tile) { string tilePath = GetTilePath(tile.zoom, tile.x, tile.y); if (!File.Exists(tilePath)) { TileManager.StartDownloadTile(tile); return; } byte[] bytes = File.ReadAllBytes(tilePath); Texture2D tileTexture = new Texture2D(256, 256); tileTexture.LoadImage(bytes); tileTexture.wrapMode = TextureWrapMode.Clamp; if (map.control.resultIsTexture) { (tile as RasterTile).ApplyTexture(tileTexture); map.buffer.ApplyTile(tile); Utils.Destroy(tileTexture); } else { tile.texture = tileTexture; tile.status = TileStatus.loaded; } tile.MarkLoaded(); map.Redraw(); } private void OnTileDownloaded(WebRequest www) { string tilePath = www["path"] as string; if (!www.hasError) { FileInfo fileInfo = new FileInfo(tilePath); DirectoryInfo directoryInfo = fileInfo.Directory; if (!directoryInfo.Exists) directoryInfo.Create(); File.WriteAllBytes(tilePath, www.bytes); } StartNextDownload(); } private void PlaceRect() { MercatorRect r = map.view.GetMercatorRect(); MercatorPoint center = r.center; Vector2d offset = r.size / 2 * 0.8; r.left = center.x - offset.x; r.right = center.x + offset.x; r.top = center.y - offset.y; r.bottom = center.y + offset.y; GeoRect geoRect = r.ToGeoRect(map); leftLongitude = geoRect.left; rightLongitude = geoRect.right; topLatitude = geoRect.top; bottomLatitude = geoRect.bottom; UpdateRect(); map.Redraw(); } private void Start() { map = Map.instance; folder = Application.persistentDataPath + "/Tiles/"; TileManager.OnStartDownloadTile += OnStartDownloadTile; } private void StartNextDownload() { if (downloadTiles == null) return; while (downloadTiles.Count > 0) { Tile tile = downloadTiles[0]; downloadTiles.RemoveAt(0); string tilePath = GetTilePath(tile); if (File.Exists(tilePath)) continue; string url = tile.url; Debug.Log(url + " " + tilePath); WebRequest www = new WebRequest(url); www["path"] = tilePath; www.OnComplete += OnTileDownloaded; return; } } private void UpdateRect() { if (rect == null) { rect = new Rectangle( leftLongitude, bottomLatitude, rightLongitude - leftLongitude, topLatitude - bottomLatitude, Color.blue, 5, new Color(1, 1, 1, 0.1f) ); DrawingElementManager.AddItem(rect); } else { rect.x = leftLongitude; rect.y = bottomLatitude; rect.width = rightLongitude - leftLongitude; rect.height = topLatitude - bottomLatitude; } } private struct Tile { public int x, y, zoom; public string url { get { RasterTile tile = new RasterTile(x, y, zoom, map, false); string tileURL = tile.url; tile.Dispose(); return tileURL; } } } }