You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							159 lines
						
					
					
						
							5.4 KiB
						
					
					
				
			
		
		
	
	
							159 lines
						
					
					
						
							5.4 KiB
						
					
					
				| //-----------------------------------------------------------------------
 | |
| // <copyright file="TileCover.cs" company="Mapbox">
 | |
| //     Copyright (c) 2016 Mapbox. All rights reserved.
 | |
| // </copyright>
 | |
| //-----------------------------------------------------------------------
 | |
| 
 | |
| namespace Mapbox.Map
 | |
| {
 | |
| 	using System;
 | |
| 	using System.Collections.Generic;
 | |
| 	using Mapbox.Utils;
 | |
| 	using UnityEngine;
 | |
| 
 | |
| 	/// <summary>
 | |
| 	///     Helper funtions to get a tile cover, i.e. a set of tiles needed for
 | |
| 	///     covering a bounding box.
 | |
| 	/// </summary>
 | |
| 	public static class TileCover
 | |
| 	{
 | |
| 		/// <summary> Get a tile cover for the specified bounds and zoom. </summary>
 | |
| 		/// <param name="bounds"> Geographic bounding box.</param>
 | |
| 		/// <param name="zoom"> Zoom level. </param>
 | |
| 		/// <returns> The tile cover set. </returns>
 | |
| 		/// <example>
 | |
| 		/// Build a map of Colorado using TileCover:
 | |
| 		/// <code>
 | |
| 		/// var sw = new Vector2d(36.997749, -109.0524961);
 | |
| 		/// var ne = new Vector2d(41.0002612, -102.0609668);
 | |
| 		/// var coloradoBounds = new Vector2dBounds(sw, ne);
 | |
| 		/// var tileCover = TileCover.Get(coloradoBounds, 8);
 | |
| 		/// Console.Write("Tiles Needed: " + tileCover.Count);
 | |
| 		/// foreach (var id in tileCover)
 | |
| 		/// {
 | |
| 		/// 	var tile = new RasterTile();
 | |
| 		/// 	var parameters = new Tile.Parameters();
 | |
| 		/// 	parameters.Id = id;
 | |
| 		///		parameters.Fs = MapboxAccess.Instance;
 | |
| 		///		parameters.TilesetId = "mapbox://styles/mapbox/outdoors-v10";
 | |
| 		///		tile.Initialize(parameters, (Action)(() =>
 | |
| 		///		{
 | |
| 		///			// Place tiles and load textures.
 | |
| 		///		}));
 | |
| 		///	}
 | |
| 		/// </code>
 | |
| 		/// </example>
 | |
| 		public static HashSet<CanonicalTileId> Get(Vector2dBounds bounds, int zoom)
 | |
| 		{
 | |
| 			var tiles = new HashSet<CanonicalTileId>();
 | |
| 
 | |
| 			if (bounds.IsEmpty() ||
 | |
| 				bounds.South > Constants.LatitudeMax ||
 | |
| 				bounds.North < -Constants.LatitudeMax)
 | |
| 			{
 | |
| 				return tiles;
 | |
| 			}
 | |
| 
 | |
| 			var hull = Vector2dBounds.FromCoordinates(
 | |
| 				new Vector2d(Math.Max(bounds.South, -Constants.LatitudeMax), bounds.West),
 | |
| 				new Vector2d(Math.Min(bounds.North, Constants.LatitudeMax), bounds.East));
 | |
| 
 | |
| 			var sw = CoordinateToTileId(hull.SouthWest, zoom);
 | |
| 			var ne = CoordinateToTileId(hull.NorthEast, zoom);
 | |
| 
 | |
| 			// Scanlines.
 | |
| 			for (var x = sw.X; x <= ne.X; ++x)
 | |
| 			{
 | |
| 				for (var y = ne.Y; y <= sw.Y; ++y)
 | |
| 				{
 | |
| 					tiles.Add(new UnwrappedTileId(zoom, x, y).Canonical);
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			return tiles;
 | |
| 		}
 | |
| 
 | |
| 
 | |
| 		public static HashSet<UnwrappedTileId> GetWithWebMerc(Vector2dBounds bounds, int zoom)
 | |
| 		{
 | |
| 			HashSet<UnwrappedTileId> tiles = new HashSet<UnwrappedTileId>();
 | |
| 			HashSet<CanonicalTileId> canonicalTiles = new HashSet<CanonicalTileId>();
 | |
| 
 | |
| 			if (bounds.IsEmpty()) { return tiles; }
 | |
| 
 | |
| 			//stay within WebMerc bounds
 | |
| 			Vector2d swWebMerc = new Vector2d(Math.Max(bounds.SouthWest.x, -Constants.WebMercMax), Math.Max(bounds.SouthWest.y, -Constants.WebMercMax));
 | |
| 			Vector2d neWebMerc = new Vector2d(Math.Min(bounds.NorthEast.x, Constants.WebMercMax), Math.Min(bounds.NorthEast.y, Constants.WebMercMax));
 | |
| 
 | |
| 			UnwrappedTileId swTile = WebMercatorToTileId(swWebMerc, zoom);
 | |
| 			UnwrappedTileId neTile = WebMercatorToTileId(neWebMerc, zoom);
 | |
| 
 | |
| 			for (int x = swTile.X; x <= neTile.X; x++)
 | |
| 			{
 | |
| 				for (int y = neTile.Y; y <= swTile.Y; y++)
 | |
| 				{
 | |
| 					UnwrappedTileId uwtid = new UnwrappedTileId(zoom, x, y);
 | |
| 					//hack: currently too many tiles are created at lower zoom levels
 | |
| 					//investigate formulas, this worked before
 | |
| 					if (!canonicalTiles.Contains(uwtid.Canonical))
 | |
| 					{
 | |
| 						tiles.Add(uwtid);
 | |
| 						canonicalTiles.Add(uwtid.Canonical);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			return tiles;
 | |
| 		}
 | |
| 
 | |
| 
 | |
| 		/// <summary> Converts a coordinate to a tile identifier. </summary>
 | |
| 		/// <param name="coord"> Geographic coordinate. </param>
 | |
| 		/// <param name="zoom"> Zoom level. </param>
 | |
| 		/// <returns>The to tile identifier.</returns>
 | |
| 		/// <example>
 | |
| 		/// Convert a geocoordinate to a TileId:
 | |
| 		/// <code>
 | |
| 		/// var unwrappedTileId = TileCover.CoordinateToTileId(new Vector2d(40.015, -105.2705), 18);
 | |
| 		/// Console.Write("UnwrappedTileId: " + unwrappedTileId.ToString());
 | |
| 		/// </code>
 | |
| 		/// </example>
 | |
| 		public static UnwrappedTileId CoordinateToTileId(Vector2d coord, int zoom)
 | |
| 		{
 | |
| 			var lat = coord.x;
 | |
| 			var lng = coord.y;
 | |
| 
 | |
| 			// See: http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
 | |
| 			var x = (int)Math.Floor((lng + 180.0) / 360.0 * Math.Pow(2.0, zoom));
 | |
| 			var y = (int)Math.Floor((1.0 - Math.Log(Math.Tan(lat * Math.PI / 180.0)
 | |
| 					+ 1.0 / Math.Cos(lat * Math.PI / 180.0)) / Math.PI) / 2.0 * Math.Pow(2.0, zoom));
 | |
| 
 | |
| 			return new UnwrappedTileId(zoom, x, y);
 | |
| 		}
 | |
| 
 | |
| 
 | |
| 
 | |
| 		/// <summary>
 | |
| 		///  Converts a Web Mercator coordinate to a tile identifier. https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Derivation_of_tile_names
 | |
| 		/// </summary>
 | |
| 		/// <param name="webMerc">Web Mercator coordinate</param>
 | |
| 		/// <param name="zoom">Zoom level</param>
 | |
| 		/// <returns>The to tile identifier.</returns>
 | |
| 		public static UnwrappedTileId WebMercatorToTileId(Vector2d webMerc, int zoom)
 | |
| 		{
 | |
| 			// See:  https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Derivation_of_tile_names
 | |
| 			double tileCount = Math.Pow(2, zoom);
 | |
| 
 | |
| 			//this SDK defines Vector2d.x as latitude and Vector2d.y as longitude
 | |
| 			//same for WebMerc, so we have to flip x/y to make this formula work
 | |
| 			double dblX = webMerc.x / Constants.WebMercMax;
 | |
| 			double dblY = webMerc.y / Constants.WebMercMax;
 | |
| 
 | |
| 			int x = (int)Math.Floor((1 + dblX) / 2 * tileCount);
 | |
| 			int y = (int)Math.Floor((1 - dblY) / 2 * tileCount);
 | |
| 			return new UnwrappedTileId(zoom, x, y);
 | |
| 		}
 | |
| 
 | |
| 
 | |
| 	}
 | |
| }
 | |
| 
 |