Untitled
unknown
plain_text
2 years ago
12 kB
7
Indexable
/****************************************************************************** Online C# Compiler. Code, Compile, Run and Debug C# program online. Write your code in this editor and press "Run" button to execute it. *******************************************************************************/ //------------------------------------------------------------------------------ // <copyright company="Microsoft"> // Copyright (c) 2006-2009 Microsoft Corporation. All rights reserved. // </copyright> //------------------------------------------------------------------------------ using System; using System.Text; static class TileSystem { private const double EarthRadius = 6378137; private const double MinLatitude = -85.05112878; private const double MaxLatitude = 85.05112878; private const double MinLongitude = -180; private const double MaxLongitude = 180; /// <summary> /// Clips a number to the specified minimum and maximum values. /// </summary> /// <param name="n">The number to clip.</param> /// <param name="minValue">Minimum allowable value.</param> /// <param name="maxValue">Maximum allowable value.</param> /// <returns>The clipped value.</returns> private static double Clip(double n, double minValue, double maxValue) { return Math.Min(Math.Max(n, minValue), maxValue); } /// <summary> /// Determines the map width and height (in pixels) at a specified level /// of detail. /// </summary> /// <param name="levelOfDetail">Level of detail, from 1 (lowest detail) /// to 23 (highest detail).</param> /// <returns>The map width and height in pixels.</returns> public static uint MapSize(int levelOfDetail) { return (uint) 256 << levelOfDetail; } public static ulong MapSizeNew(int levelOfDetail) { return (ulong) 256 << levelOfDetail; } /// <summary> /// Determines the ground resolution (in meters per pixel) at a specified /// latitude and level of detail. /// </summary> /// <param name="latitude">Latitude (in degrees) at which to measure the /// ground resolution.</param> /// <param name="levelOfDetail">Level of detail, from 1 (lowest detail) /// to 23 (highest detail).</param> /// <returns>The ground resolution, in meters per pixel.</returns> public static double GroundResolution(double latitude, int levelOfDetail) { latitude = Clip(latitude, MinLatitude, MaxLatitude); return Math.Cos(latitude * Math.PI / 180) * 2 * Math.PI * EarthRadius / MapSize(levelOfDetail); } /// <summary> /// Determines the map scale at a specified latitude, level of detail, /// and screen resolution. /// </summary> /// <param name="latitude">Latitude (in degrees) at which to measure the /// map scale.</param> /// <param name="levelOfDetail">Level of detail, from 1 (lowest detail) /// to 23 (highest detail).</param> /// <param name="screenDpi">Resolution of the screen, in dots per inch.</param> /// <returns>The map scale, expressed as the denominator N of the ratio 1 : N.</returns> public static double MapScale(double latitude, int levelOfDetail, int screenDpi) { return GroundResolution(latitude, levelOfDetail) * screenDpi / 0.0254; } /// <summary> /// Converts a point from latitude/longitude WGS-84 coordinates (in degrees) /// into pixel XY coordinates at a specified level of detail. /// </summary> /// <param name="latitude">Latitude of the point, in degrees.</param> /// <param name="longitude">Longitude of the point, in degrees.</param> /// <param name="levelOfDetail">Level of detail, from 1 (lowest detail) /// to 23 (highest detail).</param> /// <param name="pixelX">Output parameter receiving the X coordinate in pixels.</param> /// <param name="pixelY">Output parameter receiving the Y coordinate in pixels.</param> public static void LatLongToPixelXY(double latitude, double longitude, int levelOfDetail, out ulong pixelX, out ulong pixelY) { latitude = Clip(latitude, MinLatitude, MaxLatitude); longitude = Clip(longitude, MinLongitude, MaxLongitude); double x = (longitude + 180) / 360; double sinLatitude = Math.Sin(latitude * Math.PI / 180); double y = 0.5 - Math.Log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI); ulong mapSize = MapSizeNew(levelOfDetail); Console.WriteLine("QQQQ"); Console.WriteLine(mapSize); pixelX = (ulong) Clip(x * mapSize + 0.5, 0, mapSize - 1); pixelY = (ulong) Clip(y * mapSize + 0.5, 0, mapSize - 1); } /// <summary> /// Converts a pixel from pixel XY coordinates at a specified level of detail /// into latitude/longitude WGS-84 coordinates (in degrees). /// </summary> /// <param name="pixelX">X coordinate of the point, in pixels.</param> /// <param name="pixelY">Y coordinates of the point, in pixels.</param> /// <param name="levelOfDetail">Level of detail, from 1 (lowest detail) /// to 23 (highest detail).</param> /// <param name="latitude">Output parameter receiving the latitude in degrees.</param> /// <param name="longitude">Output parameter receiving the longitude in degrees.</param> public static void PixelXYToLatLong(ulong pixelX, ulong pixelY, int levelOfDetail, out double latitude, out double longitude) { double mapSize = MapSizeNew(levelOfDetail); double x = (Clip(pixelX, 0, mapSize - 1) / mapSize) - 0.5; double y = 0.5 - (Clip(pixelY, 0, mapSize - 1) / mapSize); Console.WriteLine("Reversed x&y:"); Console.WriteLine(x); Console.WriteLine(y); Console.WriteLine(); latitude = 90 - 360 * Math.Atan(Math.Exp(-y * 2 * Math.PI)) / Math.PI; longitude = 360 * x; } /// <summary> /// Converts pixel XY coordinates into tile XY coordinates of the tile containing /// the specified pixel. /// </summary> /// <param name="pixelX">Pixel X coordinate.</param> /// <param name="pixelY">Pixel Y coordinate.</param> /// <param name="tileX">Output parameter receiving the tile X coordinate.</param> /// <param name="tileY">Output parameter receiving the tile Y coordinate.</param> public static void PixelXYToTileXY(ulong pixelX, ulong pixelY, out ulong tileX, out ulong tileY) { tileX = pixelX / 256; tileY = pixelY / 256; } /// <summary> /// Converts tile XY coordinates into pixel XY coordinates of the upper-left pixel /// of the specified tile. /// </summary> /// <param name="tileX">Tile X coordinate.</param> /// <param name="tileY">Tile Y coordinate.</param> /// <param name="pixelX">Output parameter receiving the pixel X coordinate.</param> /// <param name="pixelY">Output parameter receiving the pixel Y coordinate.</param> public static void TileXYToPixelXY(ulong tileX, ulong tileY, out ulong pixelX, out ulong pixelY) { pixelX = tileX * 256; pixelY = tileY * 256; } /// <summary> /// Converts tile XY coordinates into a QuadKey at a specified level of detail. /// </summary> /// <param name="tileX">Tile X coordinate.</param> /// <param name="tileY">Tile Y coordinate.</param> /// <param name="levelOfDetail">Level of detail, from 1 (lowest detail) /// to 23 (highest detail).</param> /// <returns>A string containing the QuadKey.</returns> public static string TileXYToQuadKey(ulong tileX, ulong tileY, int levelOfDetail) { StringBuilder quadKey = new StringBuilder(); for (int i = levelOfDetail; i > 0; i--) { char digit = '0'; ulong mask = (ulong) 1 << (i - 1); if ((tileX & mask) != 0) { digit++; } if ((tileY & mask) != 0) { digit++; digit++; } quadKey.Append(digit); } return quadKey.ToString(); } /// <summary> /// Converts a QuadKey into tile XY coordinates. /// </summary> /// <param name="quadKey">QuadKey of the tile.</param> /// <param name="tileX">Output parameter receiving the tile X coordinate.</param> /// <param name="tileY">Output parameter receiving the tile Y coordinate.</param> /// <param name="levelOfDetail">Output parameter receiving the level of detail.</param> public static void QuadKeyToTileXY(string quadKey, out ulong tileX, out ulong tileY, out int levelOfDetail) { tileX = tileY = 0; levelOfDetail = quadKey.Length; for (int i = levelOfDetail; i > 0; i--) { ulong mask = (ulong) 1 << (i - 1); switch (quadKey[levelOfDetail - i]) { case '0': break; case '1': tileX |= mask; break; case '2': tileY |= mask; break; case '3': tileX |= mask; tileY |= mask; break; default: throw new ArgumentException("Invalid QuadKey digit sequence."); } } } } class HelloWorld { static void Main() { double lat = 55.7452461341856, lon = 37.6019472060954; int level = 32; Console.WriteLine("lat&lon:"); Console.WriteLine(lat); Console.WriteLine(lon); Console.WriteLine(); ulong pixelX = 0, pixelY = 0; TileSystem.LatLongToPixelXY(lat, lon, level, out pixelX, out pixelY); Console.WriteLine("Pixel x&y"); Console.WriteLine(pixelX); Console.WriteLine(pixelY); Console.WriteLine(); ulong tileX = 0, tileY = 0; TileSystem.PixelXYToTileXY(pixelX, pixelY, out tileX, out tileY); Console.WriteLine("Tile x&y"); Console.WriteLine(tileX); Console.WriteLine(tileY); Console.WriteLine(); string quadkey =TileSystem.TileXYToQuadKey(tileX, tileY, level); Console.WriteLine("Quadkey:"); Console.WriteLine(quadkey); Console.WriteLine(); ulong reverseTileX, reverseTileY; int tmp; TileSystem.QuadKeyToTileXY(quadkey, out reverseTileX, out reverseTileY, out tmp); Console.WriteLine("Reverse tile x&y:"); Console.WriteLine(reverseTileX); Console.WriteLine(reverseTileY); Console.WriteLine(); ulong reversePixelX, reversePixelY; TileSystem.TileXYToPixelXY(reverseTileX, reverseTileY, out reversePixelX, out reversePixelY); double reversedLat, reversedLon; TileSystem.PixelXYToLatLong(reversePixelX, reversePixelY, level, out reversedLat, out reversedLon); Console.WriteLine("Reversed lat&lon:"); Console.WriteLine(reversedLat); Console.WriteLine(reversedLon); Console.WriteLine(); // Console.WriteLine("Disance: "); // Console.WriteLine(Math.Sqrt(Math.Pow(lat - reversedLat, 2) + Math.Pow(lon - reversedLon, 2))); } }
Editor is loading...