This commit is contained in:
runette committed 2024-04-22 15:52:51 +01:00
commit e0afef912e
1285 files changed
+83219

No files matched your search

+117
View File
@@ -0,0 +1,117 @@
//-----------------------------------------------------------------------
// <copyright file="CanonicalTileId.cs" company="Mapbox">
// Copyright (c) 2016 Mapbox. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Mapbox.Map
{
using System;
using Mapbox.Utils;
/// <summary>
/// Data type to store <see href="https://en.wikipedia.org/wiki/Web_Mercator"> Web Mercator</see> tile scheme.
/// <see href="http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/"> See tile IDs in action. </see>
/// </summary>
public struct CanonicalTileId : IEquatable<CanonicalTileId>
{
/// <summary> The zoom level. </summary>
public readonly int Z;
/// <summary> The X coordinate in the tile grid. </summary>
public readonly int X;
/// <summary> The Y coordinate in the tile grid. </summary>
public readonly int Y;
/// <summary>
/// Initializes a new instance of the <see cref="CanonicalTileId"/> struct,
/// representing a tile coordinate in a slippy map.
/// </summary>
/// <param name="z"> The z coordinate or the zoom level. </param>
/// <param name="x"> The x coordinate. </param>
/// <param name="y"> The y coordinate. </param>
public CanonicalTileId(int z, int x, int y)
{
this.Z = z;
this.X = x;
this.Y = y;
}
internal CanonicalTileId(UnwrappedTileId unwrapped)
{
var z = unwrapped.Z;
var x = unwrapped.X;
var y = unwrapped.Y;
var wrap = (x < 0 ? x - (1 << z) + 1 : x) / (1 << z);
this.Z = z;
this.X = x - wrap * (1 << z);
this.Y = y < 0 ? 0 : Math.Min(y, (1 << z) - 1);
}
/// <summary>
/// Get the cordinate at the top left of corner of the tile.
/// </summary>
/// <returns> The coordinate. </returns>
public Vector2d ToVector2d()
{
double n = Math.PI - ((2.0 * Math.PI * this.Y) / Math.Pow(2.0, this.Z));
double lat = 180.0 / Math.PI * Math.Atan(Math.Sinh(n));
double lng = (this.X / Math.Pow(2.0, this.Z) * 360.0) - 180.0;
// FIXME: Super hack because of rounding issues.
return new Vector2d(lat - 0.0001, lng + 0.0001);
}
/// <summary>
/// Returns a <see cref="T:System.String"/> that represents the current
/// <see cref="T:Mapbox.Map.CanonicalTileId"/>.
/// </summary>
/// <returns>
/// A <see cref="T:System.String"/> that represents the current
/// <see cref="T:Mapbox.Map.CanonicalTileId"/>.
/// </returns>
public override string ToString()
{
return this.Z + "/" + this.X + "/" + this.Y;
}
#region Equality
public bool Equals(CanonicalTileId other)
{
return this.X == other.X && this.Y == other.Y && this.Z == other.Z;
}
public override int GetHashCode()
{
return X ^ Y ^ Z;
}
public static bool operator ==(CanonicalTileId a, CanonicalTileId b)
{
return a.X == b.X && a.Y == b.Y && a.Z == b.Z;
}
public static bool operator !=(CanonicalTileId a, CanonicalTileId b)
{
return !(a == b);
}
public override bool Equals(object obj)
{
if (obj is CanonicalTileId)
{
return this.Equals((CanonicalTileId)obj);
}
else
{
return false;
}
}
#endregion
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b032ac6adcdd94a899ef544e06b9e828
timeCreated: 1493952209
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,22 @@
//-----------------------------------------------------------------------
// <copyright file="ClassicRasterTile.cs" company="Mapbox">
// Copyright (c) 2016 Mapbox. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Mapbox.Map
{
/// <summary>
/// A raster tile from the Mapbox Map API, a encoded image representing a geographic
/// bounding box. Usually JPEG or PNG encoded.
/// See <see cref="T:Mapbox.Map.RasterTile"/> for usage.
/// Read more about <see href="https://www.mapbox.com/api-documentation/legacy/static-classic/"> static classic maps </see>.
/// </summary>
public class ClassicRasterTile : RasterTile
{
internal override TileResource MakeTileResource(string tilesetId)
{
return TileResource.MakeClassicRaster(Id, tilesetId);
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 26ff02ff702b3417b9d4514af452c64f
timeCreated: 1494603018
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,22 @@
//-----------------------------------------------------------------------
// <copyright file="ClassicRetinaRasterTile.cs" company="Mapbox">
// Copyright (c) 2016 Mapbox. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Mapbox.Map
{
/// <summary>
/// A retina-resolution raster tile from the Mapbox Map API, a encoded image representing a geographic
/// bounding box. Usually JPEG or PNG encoded.
/// Like <see cref="T:Mapbox.Map.ClassicRasterTile"/>, but higher resolution.
/// See <see href="https://www.mapbox.com/api-documentation/#high-dpi-images"> retina documentation </see>.
/// </summary>
public class ClassicRetinaRasterTile : ClassicRasterTile
{
internal override TileResource MakeTileResource(string tilesetId)
{
return TileResource.MakeClassicRetinaRaster(Id, tilesetId);
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 83237273afa4e4a8a9a0600d8c694e38
timeCreated: 1494603018
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+236
View File
@@ -0,0 +1,236 @@
//-----------------------------------------------------------------------
// <copyright file="Map.cs" company="Mapbox">
// Copyright (c) 2016 Mapbox. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Mapbox.Map
{
using System;
using System.Collections.Generic;
using Mapbox.Platform;
using Mapbox.Utils;
/// <summary>
/// The Mapbox Map abstraction will take care of fetching and decoding
/// data for a geographic bounding box at a certain zoom level.
/// </summary>
/// <typeparam name="T">
/// The tile type, currently <see cref="T:Mapbox.Map.Vector"/> or
/// <see cref="T:Mapbox.Map.Raster"/>.
/// </typeparam>
/// <example>
/// Request a map of the whole world:
/// <code>
/// var map = new Map&lt;RasterTile&gt;(MapboxAccess.Instance);
/// map.Zoom = 2
/// map.Vector2dBounds = Vector2dBounds.World();
/// map.TilesetId = "mapbox://styles/mapbox/streets-v10
///
/// // Register for tile updates.
/// map.Subscribe(this);
///
/// // Trigger the request.
/// map.Update();
/// </code>
/// </example>
public sealed class Map<T> : Mapbox.Utils.IObservable<T> where T : Tile, new()
{
/// <summary>
/// Arbitrary limit of tiles this class will handle simultaneously.
/// </summary>
public const int TileMax = 256;
private readonly IFileSource fs;
private Vector2dBounds latLngBounds;
private int zoom;
private string tilesetId;
private HashSet<T> tiles = new HashSet<T>();
private List<Mapbox.Utils.IObserver<T>> observers = new List<Mapbox.Utils.IObserver<T>>();
/// <summary>
/// Initializes a new instance of the <see cref="T:Mapbox.Map.Map`1"/> class.
/// </summary>
/// <param name="fs"> The data source abstraction. </param>
public Map(IFileSource fs)
{
this.fs = fs;
this.latLngBounds = new Vector2dBounds();
this.zoom = 0;
}
/// <summary>
/// Gets or sets the tileset ID. If not set, it will use the default
/// tileset ID for the tile type. I.e. "mapbox.satellite" for raster tiles
/// and "mapbox.mapbox-streets-v7" for vector tiles.
/// </summary>
/// <value>
/// The tileset ID, usually in the format "user.mapid". Exceptionally,
/// <see cref="T:Mapbox.Map.RasterTile"/> will take the full style URL
/// from where the tile is composited from, like "mapbox://styles/mapbox/streets-v9".
/// </value>
public string TilesetId
{
get
{
return this.tilesetId;
}
set
{
if (this.tilesetId == value)
{
return;
}
this.tilesetId = value;
foreach (Tile tile in this.tiles)
{
tile.Cancel();
}
this.tiles.Clear();
}
}
/// <summary>
/// Gets the tiles, vector or raster. Tiles might be
/// in a incomplete state.
/// </summary>
/// <value> The tiles. </value>
public HashSet<T> Tiles
{
get
{
return this.tiles;
}
}
/// <summary>Gets or sets a geographic bounding box.</summary>
/// <value>New geographic bounding box.</value>
public Vector2dBounds Vector2dBounds
{
get
{
return this.latLngBounds;
}
set
{
this.latLngBounds = value;
}
}
/// <summary>Gets or sets the central coordinate of the map.</summary>
/// <value>The central coordinate.</value>
public Vector2d Center
{
get
{
return this.latLngBounds.Center;
}
set
{
this.latLngBounds.Center = value;
}
}
/// <summary>Gets or sets the map zoom level.</summary>
/// <value>The new zoom level.</value>
public int Zoom
{
get
{
return this.zoom;
}
set
{
this.zoom = Math.Max(0, Math.Min(20, value));
}
}
/// <summary>
/// Sets the coordinates bounds and zoom at once.
/// </summary>
/// <param name="bounds"> Coordinates bounds. </param>
/// <param name="zoom"> Zoom level. </param>
public void SetVector2dBoundsZoom(Vector2dBounds bounds, int zoom)
{
this.latLngBounds = bounds;
this.zoom = zoom;
}
/// <summary> Add an <see cref="T:IObserver" /> to the observer list. </summary>
/// <param name="observer"> The object subscribing to events. </param>
public void Subscribe(Mapbox.Utils.IObserver<T> observer)
{
this.observers.Add(observer);
}
/// <summary> Remove an <see cref="T:IObserver" /> to the observer list. </summary>
/// <param name="observer"> The object unsubscribing to events. </param>
public void Unsubscribe(Mapbox.Utils.IObserver<T> observer)
{
this.observers.Remove(observer);
}
private void NotifyNext(T next)
{
var copy = new List<Mapbox.Utils.IObserver<T>>(this.observers);
foreach (Mapbox.Utils.IObserver<T> observer in copy)
{
observer.OnNext(next);
}
}
/// <summary>
/// Request tiles after changing map properties.
/// </summary>
public void Update()
{
var cover = TileCover.Get(this.latLngBounds, this.zoom);
if (cover.Count > TileMax)
{
return;
}
// Do not request tiles that we are already requesting
// but at the same time exclude the ones we don't need
// anymore, cancelling the network request.
this.tiles.RemoveWhere((T tile) =>
{
if (cover.Remove(tile.Id))
{
return false;
}
else
{
tile.Cancel();
this.NotifyNext(tile);
return true;
}
});
foreach (CanonicalTileId id in cover)
{
var tile = new T();
Tile.Parameters param;
param.Id = id;
param.TilesetId = this.tilesetId;
param.Fs = this.fs;
tile.Initialize(param, () => { this.NotifyNext(tile); });
this.tiles.Add(tile);
}
}
}
}
+12
View File
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 24bb3ef727dad4e1385a77beef324ff0
timeCreated: 1494441866
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+58
View File
@@ -0,0 +1,58 @@
//-----------------------------------------------------------------------
// <copyright file="MapUtils.cs" company="Mapbox">
// Copyright (c) 2016 Mapbox. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Mapbox.Map
{
using System;
using Mapbox.Utils;
/// <summary>
/// Utilities for working with Map APIs.
/// </summary>
public static class MapUtils
{
/// <summary>
/// Normalizes a static style URL.
/// </summary>
/// <returns>The static style URL.</returns>
/// <param name="url">A url, either a Mapbox URI (mapbox://{username}/{styleid}) or a full url to a map.</param>
public static string NormalizeStaticStyleURL(string url)
{
bool isMapboxUrl = url.StartsWith("mapbox://", StringComparison.Ordinal);
// Support full Mapbox URLs by returning here if a mapbox URL is not detected.
if (!isMapboxUrl)
{
return url;
}
string[] split = url.Split('/');
var user = split[3];
var style = split[4];
var draft = string.Empty;
if (split.Length > 5)
{
draft = "/draft";
}
return Constants.BaseAPI + "styles/v1/" + user + "/" + style + draft + "/tiles";
}
/// <summary>
/// Converts a TilesetId to a URL.
/// </summary>
/// <returns>The identifier to URL.</returns>
/// <param name="id">The style id.</param>
public static string TilesetIdToUrl(string id)
{
// TODO: Validate that id is a real id
const string MapBaseApi = Constants.BaseAPI + "v4/";
return MapBaseApi + id;
}
}
}
+12
View File
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a237cc1b965e34670a7c74ecf2bdbee3
timeCreated: 1491243034
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+69
View File
@@ -0,0 +1,69 @@
//-----------------------------------------------------------------------
// <copyright file="RasterTile.cs" company="Mapbox">
// Copyright (c) 2016 Mapbox. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Mapbox.Map
{
/// <summary>
/// A raster tile from the Mapbox Style API, an encoded image representing a geographic
/// bounding box. Usually JPEG or PNG encoded.
/// </summary>
/// <example>
/// Making a RasterTile request:
/// <code>
/// var parameters = new Tile.Parameters();
/// parameters.Fs = MapboxAccess.Instance;
/// parameters.Id = new CanonicalTileId(_zoom, _tileCoorindateX, _tileCoordinateY);
/// parameters.TilesetId = "mapbox://styles/mapbox/satellite-v9";
/// var rasterTile = new RasterTile();
///
/// // Make the request.
/// rasterTile.Initialize(parameters, (Action)(() =>
/// {
/// if (!string.IsNullOrEmpty(rasterTile.Error))
/// {
/// // Handle the error.
/// }
///
/// // Consume the <see cref="Data"/>.
/// }));
/// </code>
/// </example>
public class RasterTile : Tile
{
private byte[] data;
/// <summary> Gets the raster tile raw data. </summary>
/// <value> The raw data, usually an encoded JPEG or PNG. </value>
/// <example>
/// Consuming data in Unity to create a Texture2D:
/// <code>
/// var texture = new Texture2D(0, 0);
/// texture.LoadImage(rasterTile.Data);
/// _sampleMaterial.mainTexture = texture;
/// </code>
/// </example>
public byte[] Data
{
get
{
return this.data;
}
}
internal override TileResource MakeTileResource(string tilesetId)
{
return TileResource.MakeRaster(Id, tilesetId);
}
internal override bool ParseTileData(byte[] data)
{
// We do not parse raster tiles as they are
this.data = data;
return true;
}
}
}
+12
View File
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 01d65e8417e21498f88939119e4fe3ab
timeCreated: 1493756686
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,36 @@
//-----------------------------------------------------------------------
// <copyright file="RawPngRasterTile.cs" company="Mapbox">
// Copyright (c) 2016 Mapbox. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Mapbox.Map
{
/// <summary>
/// A raster tile containing an encoded RGBA PNG.
/// <see href="https://www.mapbox.com/blog/terrain-rgb/"> Read about global elevation data. </see>
/// </summary>
/// <example>
/// Print the real world height, in meters, for each pixel:
/// <code>
/// var texture = new Texture2D(0, 0);
/// texture.LoadImage(tile.Data);
/// for (int i = 0; i &lt; texture.width; i++)
/// {
/// for (int j = 0; j &lt; texture.height; j++)
/// {
/// var color = texture.GetPixel(i, j);
/// var height = Conversions.GetAbsoluteHeightFromColor(color);
/// Console.Write("Height: " + height);
/// }
/// }
/// </code>
/// </example>
public sealed class RawPngRasterTile : RasterTile
{
internal override TileResource MakeTileResource(string tilesetId)
{
return TileResource.MakeRawPngRaster(Id, tilesetId);
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ab4a5e34c15df42b3b4d5bf5c9b6b9b1
timeCreated: 1493952209
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,22 @@
//-----------------------------------------------------------------------
// <copyright file="RetinaClassicRasterTile.cs" company="Mapbox">
// Copyright (c) 2016 Mapbox. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Mapbox.Map
{
/// <summary>
/// A retin-resolution raster tile from the Mapbox Style API, an encoded image representing a geographic
/// bounding box. Usually JPEG or PNG encoded.
/// Like <see cref="T:Mapbox.Map.RasterTile"/>, but higher resolution.
/// See <see href="https://www.mapbox.com/api-documentation/#high-dpi-images"> retina documentation </see>.
/// </summary>
public class RetinaRasterTile : RasterTile
{
internal override TileResource MakeTileResource(string tilesetId)
{
return TileResource.MakeRetinaRaster(Id, tilesetId);
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9cd3514d26c4b4c7685f804af02d388b
timeCreated: 1494603018
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+277
View File
@@ -0,0 +1,277 @@
//-----------------------------------------------------------------------
// <copyright file="Tile.cs" company="Mapbox">
// Copyright (c) 2016 Mapbox. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Mapbox.Map
{
using System;
using Mapbox.Platform;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Mapbox.Unity.Utilities;
/// <summary>
/// A Map tile, a square with vector or raster data representing a geographic
/// bounding box. More info <see href="https://en.wikipedia.org/wiki/Tiled_web_map">
/// here </see>.
/// </summary>
public abstract class Tile : IAsyncRequest
{
private CanonicalTileId _id;
private List<Exception> _exceptions;
private State _state = State.New;
private IAsyncRequest _request;
private Action _callback;
/// <summary> Tile state. </summary>
public enum State
{
/// <summary> New tile, not yet initialized. </summary>
New,
/// <summary> Loading data. </summary>
Loading,
/// <summary> Data loaded and parsed. </summary>
Loaded,
/// <summary> Data loading cancelled. </summary>
Canceled,
/// <summary> Data has been loaded before and got updated. </summary>
Updated
}
/// <summary> Gets the <see cref="T:Mapbox.Map.CanonicalTileId"/> identifier. </summary>
/// <value> The canonical tile identifier. </value>
public CanonicalTileId Id
{
get { return _id; }
set { _id = value; }
}
/// <summary>Flag to indicate if the request was successful</summary>
public bool HasError
{
get
{
return _exceptions == null ? false : _exceptions.Count > 0;
}
}
/// <summary> Exceptions that might have occured during creation of the tile. </summary>
public ReadOnlyCollection<Exception> Exceptions
{
get { return null == _exceptions ? null : _exceptions.AsReadOnly(); }
}
/// <summary> Messages of exceptions otherwise empty string. </summary>
public string ExceptionsAsString
{
get
{
if (null == _exceptions || _exceptions.Count == 0) { return string.Empty; }
return string.Join(Environment.NewLine, _exceptions.Select(e => e.Message).ToArray());
}
}
/// <summary>
/// Sets the error message.
/// </summary>
/// <param name="errorMessage"></param>
internal void AddException(Exception ex)
{
if (null == _exceptions) { _exceptions = new List<Exception>(); }
_exceptions.Add(ex);
}
/// <summary>
/// Gets the current state. When fully loaded, you must
/// check if the data actually arrived and if the tile
/// is accusing any error.
/// </summary>
/// <value> The tile state. </value>
public State CurrentState
{
get
{
return _state;
}
}
public HttpRequestType RequestType { get { return _request.RequestType; } }
public bool IsCompleted
{
get
{
return _state == State.Loaded;
}
}
/// <summary>
/// Initializes the <see cref="T:Mapbox.Map.Tile"/> object. It will
/// start a network request and fire the callback when completed.
/// </summary>
/// <param name="param"> Initialization parameters. </param>
/// <param name="callback"> The completion callback. </param>
public void Initialize(Parameters param, Action callback)
{
Cancel();
_state = State.Loading;
_id = param.Id;
_callback = callback;
_request = param.Fs.Request(MakeTileResource(param.TilesetId).GetUrl(), HandleTileResponse, tileId: _id, tilesetId: param.TilesetId);
}
internal void Initialize(IFileSource fileSource, CanonicalTileId canonicalTileId, string tilesetId, Action p)
{
Cancel();
_state = State.Loading;
_id = canonicalTileId;
_callback = p;
_request = fileSource.Request(MakeTileResource(tilesetId).GetUrl(), HandleTileResponse, tileId: _id, tilesetId: tilesetId);
}
/// <summary>
/// Returns a <see cref="T:System.String"/> that represents the current
/// <see cref="T:Mapbox.Map.Tile"/>.
/// </summary>
/// <returns>
/// A <see cref="T:System.String"/> that represents the current
/// <see cref="T:Mapbox.Map.Tile"/>.
/// </returns>
public override string ToString()
{
return Id.ToString();
}
/// <summary>
/// Cancels the request for the <see cref="T:Mapbox.Map.Tile"/> object.
/// It will stop a network request and set the tile's state to Canceled.
/// </summary>
/// <example>
/// <code>
/// // Do not request tiles that we are already requesting
/// // but at the same time exclude the ones we don't need
/// // anymore, cancelling the network request.
/// tiles.RemoveWhere((T tile) =>
/// {
/// if (cover.Remove(tile.Id))
/// {
/// return false;
/// }
/// else
/// {
/// tile.Cancel();
/// NotifyNext(tile);
/// return true;
/// }
/// });
/// </code>
/// </example>
public void Cancel()
{
if (_request != null)
{
_request.Cancel();
_request = null;
}
_state = State.Canceled;
}
// Get the tile resource (raster/vector/etc).
internal abstract TileResource MakeTileResource(string tilesetId);
// Decode the tile.
internal abstract bool ParseTileData(byte[] data);
// TODO: Currently the tile decoding is done on the main thread. We must implement
// a Worker class to abstract this, so on platforms that support threads (like Unity
// on the desktop, Android, etc) we can use worker threads and when building for
// the browser, we keep it single-threaded.
List<string> ids = new List<string>();
private void HandleTileResponse(Response response)
{
if (response.HasError)
{
if (!ids.Contains(_id.ToString()))
ids.Add(_id.ToString());
else
return;
response.Exceptions.ToList().ForEach(e => AddException(e));
}
else
{
// only try to parse if request was successful
// current implementation doesn't need to check if parsing is successful:
// * Mapbox.Map.VectorTile.ParseTileData() already adds any exception to the list
// * Mapbox.Map.RasterTile.ParseTileData() doesn't do any parsing
ParseTileData(response.Data);
}
// Cancelled is not the same as loaded!
if (_state != State.Canceled)
{
if (response.IsUpdate)
{
_state = State.Updated;
}
else
{
_state = State.Loaded;
}
}
_callback();
}
/// <summary>
/// Parameters for initializing a Tile object.
/// </summary>
/// <example>
/// <code>
/// var parameters = new Tile.Parameters();
/// parameters.Fs = MapboxAccess.Instance;
/// parameters.Id = new CanonicalTileId(_zoom, _tileCoorindateX, _tileCoordinateY);
/// parameters.TilesetId = "mapbox.mapbox-streets-v7";
/// </code>
/// </example>
public struct Parameters
{
/// <summary> The tile id. </summary>
public CanonicalTileId Id;
/// <summary>
/// The tileset ID, usually in the format "user.mapid". Exceptionally,
/// <see cref="T:Mapbox.Map.RasterTile"/> will take the full style URL
/// from where the tile is composited from, like mapbox://styles/mapbox/streets-v9.
/// </summary>
public string TilesetId;
/// <summary> The data source abstraction. </summary>
public IFileSource Fs;
}
}
}
+12
View File
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8010c0fffeba24190a0e4a5a5f4317c6
timeCreated: 1494951007
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+159
View File
@@ -0,0 +1,159 @@
//-----------------------------------------------------------------------
// <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)(() =&gt;
/// {
/// // 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);
}
}
}
+12
View File
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: fc67290bfffab4457b83802ef2f4c824
timeCreated: 1494945808
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,63 @@
namespace Mapbox.Map
{
using System;
using Mapbox.Unity.MeshGeneration.Data;
using System.Collections.Generic;
using System.Collections.ObjectModel;
public class TileErrorEventArgs : EventArgs
{
/// <summary>
/// The tile identifier.
/// </summary>
public CanonicalTileId TileId;
/// <summary>
/// The exceptions.
/// </summary>
public List<Exception> Exceptions;
/// <summary>
/// The unity tile instance.
/// </summary>
public UnityTile UnityTileInstance;
/// <summary>
/// The type of the tile.
/// </summary>
public Type TileType;
/// <summary>
/// Initializes a new instance of the <see cref="T:Mapbox.Map.TileErrorEventArgs"/> class.
/// </summary>
/// <param name="TileId">Tile identifier.</param>
/// <param name="TileType">Tile type.</param>
/// <param name="UnityTileInstance">Unity tile instance.</param>
/// <param name="Exceptions">Exceptions as a List</param>
public TileErrorEventArgs(CanonicalTileId TileId, Type TileType, UnityTile UnityTileInstance, List<System.Exception> Exceptions)
{
this.TileId = TileId;
this.Exceptions = Exceptions;
this.UnityTileInstance = UnityTileInstance;
this.TileType = TileType;
}
/// <summary>
/// Initializes a new instance of the <see cref="T:Mapbox.Map.TileErrorEventArgs"/> class.
/// </summary>
/// <param name="TileId">Tile identifier.</param>
/// <param name="TileType">Tile type.</param>
/// <param name="UnityTileInstance">Unity tile instance.</param>
/// <param name="Exceptions">Exceptions as a ReadOnlyCollection</param>
public TileErrorEventArgs(CanonicalTileId TileId, Type TileType, UnityTile UnityTileInstance, ReadOnlyCollection<Exception> Exceptions)
{
this.TileId = TileId;
List<Exception> _exceptions = new List<Exception>();
foreach (var exception in Exceptions)
{
_exceptions.Add(exception);
}
this.Exceptions = _exceptions;
this.UnityTileInstance = UnityTileInstance;
this.TileType = TileType;
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 59c42a951767c4031966d5ae5c20a47a
timeCreated: 1509068021
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+67
View File
@@ -0,0 +1,67 @@
//-----------------------------------------------------------------------
// <copyright file="TileResource.cs" company="Mapbox">
// Copyright (c) 2016 Mapbox. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Mapbox.Map
{
using Platform;
using System;
using Mapbox.Unity.Telemetry;
public sealed class TileResource : IResource
{
readonly string _query;
internal TileResource(string query)
{
_query = query;
}
public static TileResource MakeRaster(CanonicalTileId id, string styleUrl)
{
return new TileResource(string.Format("{0}/{1}", MapUtils.NormalizeStaticStyleURL(styleUrl ?? "mapbox://styles/mapbox/satellite-v9"), id));
}
internal static TileResource MakeRetinaRaster(CanonicalTileId id, string styleUrl)
{
return new TileResource(string.Format("{0}/{1}@2x", MapUtils.NormalizeStaticStyleURL(styleUrl ?? "mapbox://styles/mapbox/satellite-v9"), id));
}
public static TileResource MakeClassicRaster(CanonicalTileId id, string tilesetId)
{
return new TileResource(string.Format("{0}/{1}.png", MapUtils.TilesetIdToUrl(tilesetId ?? "mapbox.satellite"), id));
}
internal static TileResource MakeClassicRetinaRaster(CanonicalTileId id, string tilesetId)
{
return new TileResource(string.Format("{0}/{1}@2x.png", MapUtils.TilesetIdToUrl(tilesetId ?? "mapbox.satellite"), id));
}
public static TileResource MakeRawPngRaster(CanonicalTileId id, string tilesetId)
{
return new TileResource(string.Format("{0}/{1}.pngraw", MapUtils.TilesetIdToUrl(tilesetId ?? "mapbox.terrain-rgb"), id));
}
public static TileResource MakeVector(CanonicalTileId id, string tilesetId)
{
return new TileResource(string.Format("{0}/{1}.vector.pbf", MapUtils.TilesetIdToUrl(tilesetId ?? "mapbox.mapbox-streets-v7"), id));
}
internal static TileResource MakeStyleOptimizedVector(CanonicalTileId id, string tilesetId, string optimizedStyleId, string modifiedDate)
{
return new TileResource(string.Format("{0}/{1}.vector.pbf?style={2}@{3}", MapUtils.TilesetIdToUrl(tilesetId ?? "mapbox.mapbox-streets-v7"), id, optimizedStyleId, modifiedDate));
}
public string GetUrl()
{
var uriBuilder = new UriBuilder(_query);
if (uriBuilder.Query != null && uriBuilder.Query.Length > 1)
{
uriBuilder.Query = uriBuilder.Query.Substring(1);
}
//return uriBuilder.ToString();
return uriBuilder.Uri.ToString();
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b56f5c7f0b51844c19d1267530b5acb1
timeCreated: 1494603018
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+147
View File
@@ -0,0 +1,147 @@
using System;
namespace Mapbox.Map
{
/// <summary>
/// Unwrapped tile identifier in a slippy map. Similar to <see cref="CanonicalTileId"/>,
/// but might go around the globe.
/// </summary>
public struct UnwrappedTileId : IEquatable<UnwrappedTileId>
{
/// <summary> The zoom level. </summary>
public readonly int Z;
/// <summary> The X coordinate in the tile grid. </summary>
public readonly int X;
/// <summary> The Y coordinate in the tile grid. </summary>
public readonly int Y;
/// <summary>
/// Initializes a new instance of the <see cref="UnwrappedTileId"/> struct,
/// representing a tile coordinate in a slippy map that might go around the
/// globe.
/// </summary>
/// <param name="z">The z coordinate.</param>
/// <param name="x">The x coordinate.</param>
/// <param name="y">The y coordinate.</param>
public UnwrappedTileId(int z, int x, int y)
{
this.Z = z;
this.X = x;
this.Y = y;
}
/// <summary> Gets the canonical tile identifier. </summary>
/// <value> The canonical tile identifier. </value>
public CanonicalTileId Canonical
{
get
{
return new CanonicalTileId(this);
}
}
/// <summary>
/// Returns a <see cref="T:System.String"/> that represents the current
/// <see cref="T:Mapbox.Map.UnwrappedTileId"/>.
/// </summary>
/// <returns>
/// A <see cref="T:System.String"/> that represents the current
/// <see cref="T:Mapbox.Map.UnwrappedTileId"/>.
/// </returns>
public override string ToString()
{
return this.Z + "/" + this.X + "/" + this.Y;
}
public bool Equals(UnwrappedTileId other)
{
return this.X == other.X && this.Y == other.Y && this.Z == other.Z;
}
public override int GetHashCode()
{
return (X << 6) ^ (Y << 16) ^ (Z << 8);
}
public override bool Equals(object obj)
{
return this.X == ((UnwrappedTileId)obj).X && this.Y == ((UnwrappedTileId)obj).Y && this.Z == ((UnwrappedTileId)obj).Z;
}
public static bool operator ==(UnwrappedTileId a, UnwrappedTileId b)
{
return a.X == b.X && a.Y == b.Y && a.Z == b.Z;
}
public static bool operator !=(UnwrappedTileId a, UnwrappedTileId b)
{
return !(a == b);
}
public UnwrappedTileId North
{
get
{
return new UnwrappedTileId(Z, X, Y - 1);
}
}
public UnwrappedTileId East
{
get
{
return new UnwrappedTileId(Z, X + 1, Y);
}
}
public UnwrappedTileId South
{
get
{
return new UnwrappedTileId(Z, X, Y + 1);
}
}
public UnwrappedTileId West
{
get
{
return new UnwrappedTileId(Z, X - 1, Y);
}
}
public UnwrappedTileId NorthEast
{
get
{
return new UnwrappedTileId(Z, X + 1, Y - 1);
}
}
public UnwrappedTileId SouthEast
{
get
{
return new UnwrappedTileId(Z, X + 1, Y + 1);
}
}
public UnwrappedTileId NorthWest
{
get
{
return new UnwrappedTileId(Z, X - 1, Y - 1);
}
}
public UnwrappedTileId SouthWest
{
get
{
return new UnwrappedTileId(Z, X - 1, Y + 1);
}
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b05b9f9c791be434db474b25089ff310
timeCreated: 1494945808
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+211
View File
@@ -0,0 +1,211 @@
//-----------------------------------------------------------------------
// <copyright file="VectorTile.cs" company="Mapbox">
// Copyright (c) 2016 Mapbox. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace Mapbox.Map
{
using System.Collections.ObjectModel;
using Mapbox.Utils;
using Mapbox.VectorTile;
using Mapbox.VectorTile.ExtensionMethods;
using System;
/// <summary>
/// A decoded vector tile, as specified by the
/// <see href="https://www.mapbox.com/vector-tiles/specification/">
/// Mapbox Vector Tile specification</see>.
/// See available layers and features <see href="https://www.mapbox.com/vector-tiles/mapbox-streets-v7/">here</see>.
/// The tile might be incomplete if the network request and parsing are still pending.
/// </summary>
/// <example>
/// Making a VectorTile request:
/// <code>
/// var parameters = new Tile.Parameters();
/// parameters.Fs = MapboxAccess.Instance;
/// parameters.Id = new CanonicalTileId(_zoom, _tileCoorindateX, _tileCoordinateY);
/// parameters.TilesetId = "mapbox.mapbox-streets-v7";
/// var vectorTile = new VectorTile();
///
/// // Make the request.
/// vectorTile.Initialize(parameters, (Action)(() =>
/// {
/// if (!string.IsNullOrEmpty(vectorTile.Error))
/// {
/// // Handle the error.
/// }
///
/// // Consume the <see cref="Data"/>.
/// }));
/// </code>
/// </example>
public sealed class VectorTile : Tile, IDisposable
{
// FIXME: Namespace here is very confusing and conflicts (sematically)
// with his class. Something has to be renamed here.
private Mapbox.VectorTile.VectorTile data;
bool _isStyleOptimized = false;
string _optimizedStyleId;
string _modifiedDate;
private bool isDisposed = false;
/// <summary> Gets the vector decoded using Mapbox.VectorTile library. </summary>
/// <value> The GeoJson data. </value>
public Mapbox.VectorTile.VectorTile Data
{
get
{
return this.data;
}
}
public VectorTile()
{
_isStyleOptimized = false;
}
public VectorTile(string styleId, string modifiedDate)
{
if (string.IsNullOrEmpty(styleId) || string.IsNullOrEmpty(modifiedDate))
{
UnityEngine.Debug.LogWarning("Style Id or Modified Time cannot be empty for style optimized tilesets. Switching to regular tilesets!");
_isStyleOptimized = false;
}
else
{
_isStyleOptimized = true;
_optimizedStyleId = styleId;
_modifiedDate = modifiedDate;
}
}
//TODO: uncomment if 'VectorTile' class changes from 'sealed'
//protected override void Dispose(bool disposeManagedResources)
//~VectorTile()
//{
// Dispose(false);
//}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
//TODO: change signature if 'VectorTile' class changes from 'sealed'
//protected override void Dispose(bool disposeManagedResources)
public void Dispose(bool disposeManagedResources)
{
if (!isDisposed)
{
if (disposeManagedResources)
{
//TODO implement IDisposable with Mapbox.VectorTile.VectorTile
if (null != data)
{
data = null;
}
}
}
}
/// <summary>
/// <para>Gets the vector in a GeoJson format.</para>
/// <para>
/// This method should be avoided as it fully decodes the whole tile and might pose performance and memory bottle necks.
/// </para>
/// </summary>
/// <value> The GeoJson data. </value>
/// <example>
/// Inspect the GeoJson.
/// <code>
/// var json = VectorTile.GeoJson;
/// Console.Write("GeoJson: " + json);
/// </code>
/// </example>
public string GeoJson
{
get
{
return this.data.ToGeoJson((ulong)Id.Z, (ulong)Id.X, (ulong)Id.Y, 0);
}
}
/// <summary>
/// Gets all availble layer names.
/// See available layers and features <see href="https://www.mapbox.com/vector-tiles/mapbox-streets-v7/">here</see>.
/// </summary>
/// <returns>Collection of availble layers.</returns>
/// <example>
/// Inspect the LayerNames.
/// <code>
/// var layerNames = vectorTile.LayerNames();
/// foreach (var layer in layerNames)
/// {
/// Console.Write("Layer: " + layer);
/// }
/// </code>
/// </example>
public ReadOnlyCollection<string> LayerNames()
{
return this.data.LayerNames();
}
// FIXME: Why don't these work?
/// <summary>
/// Decodes the requested layer.
/// </summary>
/// <param name="layerName">Name of the layer to decode.</param>
/// <returns>Decoded VectorTileLayer or 'null' if an invalid layer name was specified.</returns>
/// <example>
/// Inspect a layer of the vector tile.
/// <code>
/// var countryLabelLayer = vectorTile.GetLayer("country_label");
/// var count = countryLabelLayer.Keys.Count;
/// for (int i = 0; i &lt; count; i++)
/// {
/// Console.Write(string.Format("{0}:{1}", countryLabelLayer.Keys[i], countryLabelLayer.Values[i]));
/// }
/// </code>
/// </example>
public VectorTileLayer GetLayer(string layerName)
{
return this.data.GetLayer(layerName);
}
internal override TileResource MakeTileResource(string tilesetId)
{
return (_isStyleOptimized) ?
TileResource.MakeStyleOptimizedVector(Id, tilesetId, _optimizedStyleId, _modifiedDate)
: TileResource.MakeVector(Id, tilesetId);
}
internal override bool ParseTileData(byte[] data)
{
try
{
var decompressed = Compression.Decompress(data);
this.data = new Mapbox.VectorTile.VectorTile(decompressed);
return true;
}
catch (Exception ex)
{
AddException(ex);
return false;
}
}
}
}
+12
View File
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: bfd8ce307104a47389d62ff6cd67802c
timeCreated: 1494951007
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: