前一段时间 ,在做一个GPS平台的项目 ,虽然不是很大
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace WSGPSGateway.BLL { public enum MapStyle { Road, Aerial, Hybrid } public enum MapLanguageVersion { Chinese, UnitedStates } /// <summary> /// A map displayed on the screen. /// </summary> public class Map { private int width, height; private int zoomLevel; /// <summary> /// The X-coordinate of the center of the map, in pixels, in world coordinates (at the current zoom level). /// </summary> private int x; /// <summary> /// The Y-coordinate of the center of the map, in pixels, in world coordinates (at the current zoom level). /// </summary> private int y; /// <summary> /// The latitude of the center of the map. /// </summary> private double latitude; /// <summary> /// The longitude of the center of the map. /// </summary> private double longitude; private MapStyle mapStyle; private const int earthRadius = 6378137; private const int buffer = 0/*100*/; private const double offsetMeters = 20971520; private const double baseMetersPerPixel = 163840; private const double MinLatitude = -85.05112878; private const double MaxLatitude = 85.05112878; private const double MinLongitude = -180; private const double MaxLongitude = 180; public Map() { } /// <summary> /// Minimum allowed zoom level /// </summary> public int MinimumZoom { get { return 3; } } /// <summary> /// Maximum allowed zoom level /// </summary> public int MaximumZoom { get { return 19; } } /// <summary> /// Gets or sets the latitude. /// </summary> /// <value>The latitude.</value> public double Latitude { get { if (double.IsNaN(latitude)) { // We have panned, so we must recalculate the latitude. latitude = YToLatitudeAtZoom(Y, zoomLevel); } return latitude; } set { latitude = value; y = LatitudeToYAtZoom(latitude, zoomLevel); } } /// <summary> /// Gets or sets the longitude. /// </summary> /// <value>The longitude.</value> public double Longitude { get { if (double.IsNaN(longitude)) { // We have panned, so we must recalculate the longitude. longitude = XToLongitudeAtZoom(X, zoomLevel); } return longitude; } set { longitude = value; x = LongitudeToXAtZoom(longitude, zoomLevel); } } /// <summary> /// The X-coordinate of the center of the map, in pixels, /// in world coordinates (at the current zoom level). /// </summary> public int X { get { return x; } set { x = value; // We don't bother recalculating the longitude until asked for. // So right now, we just invalidate it. longitude = double.NaN; } } /// <summary> /// The Y-coordinate of the center of the map, in pixels, /// in world coordinates (at the current zoom level). /// </summary> public int Y { get { return y; } set { y = value; // We don't bother recalculating the latitude until asked for. // So right now, we just invalidate it. latitude = double.NaN; } } /// <summary> /// The style of map (road, aerial, or hybrid). /// </summary> public MapStyle MapStyle { get { return mapStyle; } set { mapStyle = value; } } private MapLanguageVersion languageVersion; /// <summary> /// The version of map (chinese,us). /// </summary> public MapLanguageVersion LanguageVersion { get { return languageVersion; } set { languageVersion = value; } } /// <summary> /// The current zoom level. /// </summary> public int ZoomLevel { get { return zoomLevel; } set { // Make sure we have a valid lat/long at the old zoom level // before we change the zoom level. double lon = Longitude; double lat = Latitude; zoomLevel = value; //x = LongitudeToXAtZoom(lon, zoomLevel); //y = LatitudeToYAtZoom(lat, zoomLevel); } } /// <summary> /// Zooms the in. /// </summary> public void ZoomIn() { if (ZoomLevel < MaximumZoom) { ZoomLevel = ZoomLevel + 1; x = 2 * X; y = 2 * Y; } } /// <summary> /// Zooms the out. /// </summary> public void ZoomOut() { if (ZoomLevel > MinimumZoom) { ZoomLevel = ZoomLevel - 1; x = X / 2; y = Y / 2; } } /// <summary> /// Initializes a new instance of the <see cref="Map"/> class. /// </summary> /// <param name="width">The width.</param> /// <param name="height">The height.</param> /// <param name="latitude">The latitude.</param> /// <param name="longitude">The longitude.</param> /// <param name="zoomLevel">The zoom level.</param> /// <param name="mapStyle">The map style.</param> /// <param name="mlv">The MLV.</param> public Map( int width, int height, double latitude, double longitude, int zoomLevel, MapStyle mapStyle, MapLanguageVersion mlv) { this.width = width; this.height = height; this.zoomLevel = zoomLevel; this.Latitude = latitude; this.Longitude = longitude; this.MapStyle = mapStyle; this.LanguageVersion = mlv; } /// <summary> /// Lats the long to pixel XY. /// </summary> /// <param name="latitude">The latitude.</param> /// <param name="longitude">The longitude.</param> /// <param name="levelOfDetail">The level of detail.</param> /// <param name="pixelX">The pixel X.</param> /// <param name="pixelY">The pixel Y.</param> public static void LatLongToPixelXY(double latitude, double longitude, int levelOfDetail, out int pixelX, out int 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); uint mapSize = MapSize(levelOfDetail); pixelX = (int)Clip(x * mapSize + 0.5, 0, mapSize - 1); pixelY = (int)Clip(y * mapSize + 0.5, 0, mapSize - 1); } /// <summary> /// Lats the long to tile XY. /// </summary> /// <param name="latitude">The latitude.</param> /// <param name="longitude">The longitude.</param> /// <param name="levelOfDetail">The level of detail.</param> /// <param name="tileX">The tile X.</param> /// <param name="tileY">The tile Y.</param> public static void LatLongToTileXY(double latitude, double longitude, int levelOfDetail, out int tileX, out int tileY) { int pixelX = 0; int pixelY = 0; LatLongToPixelXY(latitude, longitude, levelOfDetail, out pixelX, out pixelY); PixelXYToTileXY(pixelX, pixelY, out tileX, out tileY); } /// <summary> /// Pixels the XY to tile XY. /// </summary> /// <param name="pixelX">The pixel X.</param> /// <param name="pixelY">The pixel Y.</param> /// <param name="tileX">The tile X.</param> /// <param name="tileY">The tile Y.</param> public static void PixelXYToTileXY(int pixelX, int pixelY, out int tileX, out int tileY) { tileX = pixelX / 256; tileY = pixelY / 256; } /// <summary> /// Maps the size. /// </summary> /// <param name="levelOfDetail">The level of detail.</param> /// <returns></returns> public static uint MapSize(int levelOfDetail) { return (uint)256 << levelOfDetail; } /// <summary> /// Clips the specified n. /// </summary> /// <param name="n">The n.</param> /// <param name="minValue">The min value.</param> /// <param name="maxValue">The max value.</param> /// <returns></returns> private static double Clip(double n, double minValue, double maxValue) { return Math.Min(Math.Max(n, minValue), maxValue); } /// <summary> /// Meterses the per pixel. /// </summary> /// <param name="zl">The zl.</param> /// <returns></returns> private static double MetersPerPixel(int zl) { return baseMetersPerPixel / (1 << zl); } /// <summary> /// Ys to latitude at zoom. /// </summary> /// <param name="y">The y.</param> /// <param name="zl">The zl.</param> /// <returns></returns> private double YToLatitudeAtZoom(int y, int zl) { double metersY = Map.offsetMeters - y * MetersPerPixel(zl); return RadToDeg(Math.PI / 2 - 2 * Math.Atan(Math.Exp(-metersY / earthRadius))); } /// <summary> /// Xs to longitude at zoom. /// </summary> /// <param name="x">The x.</param> /// <param name="zl">The zl.</param> /// <returns></returns> private double XToLongitudeAtZoom(int x, int zl) { double metersX = x * MetersPerPixel(zl) - offsetMeters; return RadToDeg(metersX / earthRadius); } /// <summary> /// Longitudes to X at zoom. /// </summary> /// <param name="longitude">The longitude.</param> /// <param name="zl">The zl.</param> /// <returns></returns> private int LongitudeToXAtZoom(double longitude, int zl) { longitude = Clip(longitude, MinLongitude, MaxLongitude); double x = (longitude + 180) / 360; uint mapSize = MapSize(zl); return (int)Clip(x * mapSize + 0.5, 0, mapSize - 1); } /// <summary> /// Latitudes to Y at zoom. /// </summary> /// <param name="latitude">The latitude.</param> /// <param name="zl">The zl.</param> /// <returns></returns> private int LatitudeToYAtZoom(double latitude, int zl) { double sinLatitude = Math.Sin(latitude * Math.PI / 180); double y = 0.5 - Math.Log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI); uint mapSize = MapSize(zl); return (int)Clip(y * mapSize + 0.5, 0, mapSize - 1); } /// <summary> /// Degs to RAD. /// </summary> /// <param name="d">The d.</param> /// <returns></returns> private static double DegToRad(double d) { return d * Math.PI / 180.0; } /// <summary> /// RADs to deg. /// </summary> /// <param name="r">The r.</param> /// <returns></returns> private static double RadToDeg(double r) { return r * 180.0 / Math.PI; } public static double PixelXToLng(double pixelX, int zoom) { return pixelX * 360 / (256L << zoom) - 180; } public static double PixelYToLat(double pixelY, int zoom) { double y = 2 * Math.PI * (1 - pixelY / (128 << zoom)); double z = Math.Pow(Math.E, y); double siny = (z - 1) / (z + 1); return Math.Asin(siny) * 180 / Math.PI; } } }
。我是第一次做 ,所以为了给自己增加经验和多多总结的机会 ,所以将自己写的代码部分贴出来 。