//-----------------------------------------------------------------------
//
// Copyright (c) 2016 Mapbox. All rights reserved.
//
//-----------------------------------------------------------------------
namespace Mapbox.Map
{
using System;
using Mapbox.Utils;
///
/// Data type to store Web Mercator tile scheme.
/// See tile IDs in action.
///
public struct CanonicalTileId : IEquatable
{
/// The zoom level.
public readonly int Z;
/// The X coordinate in the tile grid.
public readonly int X;
/// The Y coordinate in the tile grid.
public readonly int Y;
///
/// Initializes a new instance of the struct,
/// representing a tile coordinate in a slippy map.
///
/// The z coordinate or the zoom level.
/// The x coordinate.
/// The y coordinate.
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);
}
///
/// Get the cordinate at the top left of corner of the tile.
///
/// The coordinate.
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);
}
///
/// Returns a that represents the current
/// .
///
///
/// A that represents the current
/// .
///
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
}
}