20240422
This commit is contained in:
commit
e0afef912e
1285 files changed
+83219
No files matched your search
@@ -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:
|
||||
@@ -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<RasterTile>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24bb3ef727dad4e1385a77beef324ff0
|
||||
timeCreated: 1494441866
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a237cc1b965e34670a7c74ecf2bdbee3
|
||||
timeCreated: 1491243034
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 < texture.width; i++)
|
||||
/// {
|
||||
/// for (int j = 0; j < 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:
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8010c0fffeba24190a0e4a5a5f4317c6
|
||||
timeCreated: 1494951007
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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)(() =>
|
||||
/// {
|
||||
/// // 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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:
|
||||
@@ -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:
|
||||
@@ -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 < 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bfd8ce307104a47389d62ff6cd67802c
|
||||
timeCreated: 1494951007
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in new issue
Block a user