arcgis for silverlight 加载GoogleMap 或 BingMap

arcgis for silverlight 加载GoogleMap 或 BingMap  可以使用重载 TiledMapServiceLayer

对于silverlight内的地图进行截屏操作时,会出现跨域问题,目前我的解决方式就是,将加载切片

数据交给本地服务端,本地服务端加载后的图片再给silverlight,这样就不会出现跨域问题,而无法截屏了

GoogleMap:

/// <summary>
    /// Google Title System layer (Google 地图切片系统图层)
    /// </summary>
    public class GoogleMapTileLayer : TiledMapServiceLayer
    {
        /// <summary>
        /// 初始化
        /// </summary>
        public override void Initialize()
        {
            //全图范围
            this.FullExtent = new Envelope(-20037508.342787, -20037508.342787, 20037508.342787, 20037508.342787);
            {
                SpatialReference = new SpatialReference(102113);
            };
            //空间投影
            this.SpatialReference = new SpatialReference(102113);
            //切片信息
            this.TileInfo = new TileInfo()
            {
                Height = 256,
                Width = 256,
                Origin = new MapPoint(-20037508.342787, 20037508.342787)
                {
                    SpatialReference = new SpatialReference(102113)
                },
                Lods = new Lod[20]
            };
            double resolution = 156543.033928;
            for (int i = 0; i < TileInfo.Lods.Length; i++)
            {
                TileInfo.Lods[i] = new Lod() { Resolution = resolution };
                resolution /= 2;
            }
            //加载
            base.Initialize();
        }
        /// <summary>
        /// Google 切片地址
        /// </summary>
        private static string basicGoogleTitleUrl = "http://mt{0}.google.cn/vt/lyrs=m@156000000&hl=zh-CN&x=";

        /// <summary>
        /// 服务器随机数
        /// </summary>
        private static Random RandomTitle = new Random(DateTime.Now.Second);

        /// <summary>
        /// 获取切片地址
        /// </summary>
        /// <param name="level"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <returns></returns>
        public override string GetTileUrl(int level, int row, int col)
        {
            int Server = RandomTitle.Next(0, 4);
            string url = string.Format(basicGoogleTitleUrl, Server);
            url = url + col.ToString() + "&y=" + row.ToString() + "&z=" + level.ToString() + "&s=";
            return url;
        }
    }

BingMap:

/// <summary>
    /// BingMap Title System layer (Google 地图切片系统图层)
    /// </summary>
    public class BingMapTileLayer : TiledMapServiceLayer
    {

        /// <summary>
        /// 经纬度转墨卡托
        /// </summary>
        /// <param name="lonLat"></param>
        /// <returns></returns>
        public MapPoint lonLat2Mercator(MapPoint lonLat)
        {
            MapPoint mercator = new MapPoint();
            double x = lonLat.X * 20037508.34 / 180;
            double y = Math.Log(Math.Tan((90 + lonLat.Y) * Math.PI / 360)) / (Math.PI / 180);
            y = y * 20037508.34 / 180;
            mercator.X = x;
            mercator.Y = y;
            return mercator;
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public override void Initialize()
        {

            MapPoint minPoint = new MapPoint(TileSystem.MinLongitude, TileSystem.MinLatitude);

            minPoint = lonLat2Mercator(minPoint);

            minPoint.SpatialReference = new ESRI.ArcGIS.Client.Geometry.SpatialReference(102113);

            MapPoint maxPoint = new MapPoint(TileSystem.MaxLongitude, TileSystem.MaxLatitude);

            maxPoint = lonLat2Mercator(maxPoint);
            maxPoint.SpatialReference = new ESRI.ArcGIS.Client.Geometry.SpatialReference(102113);

            //全图范围
            this.FullExtent = new Envelope(minPoint, maxPoint);
            {
                SpatialReference = new SpatialReference(102113);
            };
            //空间投影
            this.SpatialReference = new SpatialReference(102113);
            //切片信息
            this.TileInfo = new TileInfo()
            {
                Height = 256,
                Width = 256,
                Origin = new MapPoint(-20037508.342787, 20037508.342787)
                {
                    SpatialReference = new SpatialReference(102113)
                },
                Lods = new Lod[23]
            };
            double resolution = 39135.7585 * 4;
            for (int i = 0; i < TileInfo.Lods.Length; i++)
            {
                TileInfo.Lods[i] = new Lod() { Resolution = resolution };
                resolution /= 2;
            }
            //加载
            base.Initialize();
        }
        /// <summary>
        /// BingMap 切片地址(由本地页面加载切片,可以使用silverlight的截屏功能,而不会出现权限错误)
        /// </summary>
        private static string basicbingTitleUrl = "http://localhost:18839/BingMapUrl.aspx?r{1}.png?g=94&mkt=zh-cn&b={0}";

        /// <summary>
        /// 服务器随机数
        /// </summary>
        private static Random RandomTitle = new Random(DateTime.Now.Second);

        /// <summary>
        /// 获取切片地址
        /// </summary>
        /// <param name="level"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <returns></returns>
        public override string GetTileUrl(int level, int row, int col)
        {
            return GetUri(level, col, row);
        }



        public string GetUri(int tileLevel, int tilePositionX, int tilePositionY)
        {
            var quadKey = TileSystem.TileXYToQuadKey(tilePositionX, tilePositionY, tileLevel);
            if (string.IsNullOrEmpty(quadKey))
                quadKey = "0";
            return string.Format(basicbingTitleUrl, RandomTitle.Next(0, 3), quadKey);
        }
    }

TileSystem:

/// <summary>
    /// 切片系统
    /// </summary>
    static class TileSystem
    {
        public const double EarthRadius = 6378137;
        public const double MinLatitude = -85.05112878;
        public const double MaxLatitude = 85.05112878;
        public const double MinLongitude = -180;
        public 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;
        }



        /// <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 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>
        /// 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(int pixelX, int pixelY, int levelOfDetail, out double latitude, out double longitude)
        {
            double mapSize = MapSize(levelOfDetail);
            double x = (Clip(pixelX, 0, mapSize - 1) / mapSize) - 0.5;
            double y = 0.5 - (Clip(pixelY, 0, mapSize - 1) / mapSize);

            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(int pixelX, int pixelY, out int tileX, out int 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(int tileX, int tileY, out int pixelX, out int 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(int tileX, int tileY, int levelOfDetail)
        {
            StringBuilder quadKey = new StringBuilder();
            for (int i = levelOfDetail; i > 0; i--)
            {
                char digit = '0';
                int mask = 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 int tileX, out int tileY, out int levelOfDetail)
        {
            tileX = tileY = 0;
            levelOfDetail = quadKey.Length;
            for (int i = levelOfDetail; i > 0; i--)
            {
                int mask = 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.");
                }
            }
        }
    }

BingMapUrl.aspx.cs:

public partial class BingMapUrl : System.Web.UI.Page
    {

        public Random random = new Random(DateTime.Now.Second);

        private const string BingMapHostUrl = "http://r{0}.tiles.ditu.live.com/tiles/";

        private const int BUFFERSIZE = 1048576;

        /// <summary>
        /// 页面加载
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                try
                {
                    this.HandleMapPic();
                }
                catch (Exception ex)
                {
                    Response.Write(ex.Message);
                }
            }
        }

        /// <summary>
        /// 加载图片
        /// </summary>
        private void HandleMapPic()
        {
            string queryParams = Request.Url.Query;

            if (string.IsNullOrWhiteSpace(queryParams))
                return;
            queryParams = queryParams.Substring(1, queryParams.Length - 1);
            string bingMapUrl = string.Format(BingMapHostUrl, random.Next(0, 3));
            string requestUrl = string.Concat(bingMapUrl, queryParams);

            HttpWebRequest webRequest = null;

            #region Prepare the request object
            webRequest = (HttpWebRequest)WebRequest.Create(Server.UrlDecode(requestUrl));
            webRequest.Method = Request.HttpMethod;
            webRequest.ContentType = Request.ContentType;
            #endregion Prepare the request object

            #region Cycle through and return output
            HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
            System.IO.Stream fileStream = webResponse.GetResponseStream();
            Byte[] buffer = new byte[1048576];
            int bytesRead = 1;
            while (bytesRead > 0)
            {
                bytesRead = fileStream.Read(buffer, 0, BUFFERSIZE);
                if (bytesRead == BUFFERSIZE)
                    Response.BinaryWrite(buffer);
                else if (bytesRead > 0)
                {
                    byte[] endBuffer = new byte[bytesRead];
                    Array.Copy(buffer, endBuffer, bytesRead);
                    Response.BinaryWrite(endBuffer);
                }
            }

            fileStream.Dispose();
            webResponse.Close();
            #endregion Cycle through and return output
        }
    }
原文地址:https://www.cnblogs.com/zhangbingCoder/p/3387289.html