Arcgis API for Silverlight如何加载天地图底图以及地方坐标系的偏门底图

转载地址:http://blog.csdn.net/yanglang1987500/article/details/42423309

上回答应大家,说一下怎么用Silverlight的Arcgis地图来加载各种第三方底图服务,这里我就贴贴代码做下讲解,希望能帮到有需要的童鞋。
首先贴上天地图底图的扩展类如下所示:
[csharp] view plain copy
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ESRI.ArcGIS.Client.Geometry;
using ESRI.ArcGIS.Client;
using JIUQI.BI.DataMap.Core.Commons;

namespace JIUQI.BI.DataMap
{
public class TDTTileLayer : TiledMapServiceLayer
{
public override void Initialize()
{

        this.FullExtent = new  
        ESRI.ArcGIS.Client.Geometry.Envelope(-20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892);  
        {  
            SpatialReference = new ESRI.ArcGIS.Client.Geometry.SpatialReference(3857);  
        };  

        this.SpatialReference = new ESRI.ArcGIS.Client.Geometry.SpatialReference(3857);  

        this.TileInfo = new TileInfo()  
        {  
            Height = 256,  
            Width = 256,  
            Origin = new ESRI.ArcGIS.Client.Geometry.MapPoint(-20037508.3427892, 20037508.3427892)  
            {  
                SpatialReference = new ESRI.ArcGIS.Client.Geometry.SpatialReference(3857)  
            },  
            Lods = new Lod[18]  
        };  
        TileInfo.Lods[0] = new Lod() { Resolution = 156543.033928 };  
        TileInfo.Lods[1] = new Lod() { Resolution = 78271.51696402048 };  
        TileInfo.Lods[2] = new Lod() { Resolution = 39135.75848201024 };  
        TileInfo.Lods[3] = new Lod() { Resolution = 19567.87924100512 };  
        TileInfo.Lods[4] = new Lod() { Resolution = 9783.93962050256 };  
        TileInfo.Lods[5] = new Lod() { Resolution = 4891.96981025128 };  
        TileInfo.Lods[6] = new Lod() { Resolution = 2445.98490512564 };  
        TileInfo.Lods[7] = new Lod() { Resolution = 1222.99245256282 };  
        TileInfo.Lods[8] = new Lod() { Resolution = 611.49622628141 };  
        TileInfo.Lods[9] = new Lod() { Resolution = 305.748113140705 };  
        TileInfo.Lods[10] = new Lod() { Resolution = 152.8740565703525 };  
        TileInfo.Lods[11] = new Lod() { Resolution = 76.43702828517625 };  
        TileInfo.Lods[12] = new Lod() { Resolution = 38.21851414258813 };  
        TileInfo.Lods[13] = new Lod() { Resolution = 19.109257071294063 };  
        TileInfo.Lods[14] = new Lod() { Resolution = 9.554628535647032 };  
        TileInfo.Lods[15] = new Lod() { Resolution = 4.777314267823516 };  
        TileInfo.Lods[16] = new Lod() { Resolution = 2.388657133911758 };  
        TileInfo.Lods[17] = new Lod() { Resolution = 1.194328566955879 };  

        base.Initialize();  

    }  
    private string _url = "";  
    public override string GetTileUrl(int level, int row, int col)  
    {  
        return _url + "/" + level + "/" + row + "/" + col + "";  
    }  
    public string Url  
    {  
        get  
        {  
            return _url;  
        }  
        set  
        {  
            _url = value;  
        }  
    }  
}  

}

该类继承自API中的TiledMapServiceLayer类,实现了GetTileUrl方法。首先需要在初始化函数中,实例化FullExtent属性、SpatialReference属性以及TileInfo属性,这三个属性一般底图服务商都会提供过来,特别是第三个,如果对方只提供了Scale而未提供Resolution的话还需要通过一个公式进行换算。

至于这个公式是什么意思,我就不在这里缀述了,因为讲起来篇幅太大,不在本文讨论范围内,小伙伴们可以参考其它资料,总之就是涉及到屏幕分辨率与地图缩放级别单位之间的转换。
天地图底图这个扩展我研究了两天时间才解决,真正麻烦的问题在于如何扩展支持地方坐标系的底图服务!
由于地方坐标系的底图服务与墨卡托坐标系的投影不一致,初始缩放级别不一致(地方坐标系的底图往往是从省或市一级开始,国家级别直接没有),所以折腾了将近一周时间(利用的闲暇时间,平时有别的工作,但因为问题没解决心里总是有块阴影,难受。。)
下面贴代码:
[csharp] view plain copy
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ESRI.ArcGIS.Client.Geometry;
using ESRI.ArcGIS.Client;
using JIUQI.BI.DataMap.Core.Commons;

namespace JIUQI.BI.DataMap
{
public class JXWTileLayer : TiledMapServiceLayer
{
public override void Initialize()
{
SpatialReference sr = new ESRI.ArcGIS.Client.Geometry.SpatialReference(“PROJCS[\”Beijing_1954_GK_Zone_Custom\”,GEOGCS[\”GCS_Beijing_1954\”,DATUM[\”D_Beijing_1954\”,SPHEROID[\”Krasovsky_1940\”,6378245.0,298.3]],PRIMEM[\”Greenwich\”,0.0],UNIT[\”Degree\”,0.0174532925199433]],PROJECTION[\”Gauss_Kruger\”],PARAMETER[\”False_Easting\”,500000.0],PARAMETER[\”False_Northing\”,-4114707.712],PARAMETER[\”Central_Meridian\”,116.3510110655],PARAMETER[\”Scale_Factor\”,1.0],PARAMETER[\”Latitude_Of_Origin\”,0.0003],UNIT[\”Meter\”,1.0]]”);

        this.FullExtent = new  
        ESRI.ArcGIS.Client.Geometry.Envelope(371987.18334, 252920.58593, 624459.12036, 423400.07714);  
        {  
            SpatialReference = sr;  
        };  

        this.SpatialReference = sr;  

        this.TileInfo = new TileInfo()  
        {  
            Height = 256,  
            Width = 256,  

            Origin = new ESRI.ArcGIS.Client.Geometry.MapPoint(0, 688194)  
            {  
                SpatialReference = sr  
            },  
            Lods = new Lod[13]  
        };  
        TileInfo.Lods[0] = new Lod() { Resolution = 896.0859375 };  
        TileInfo.Lods[1] = new Lod() { Resolution = 448.04296875 };  
        TileInfo.Lods[2] = new Lod() { Resolution = 224.021484375 };  
        TileInfo.Lods[3] = new Lod() { Resolution = 112.0107421875 };  
        TileInfo.Lods[4] = new Lod() { Resolution = 56.00537109375 };  
        TileInfo.Lods[5] = new Lod() { Resolution = 28.002685546875 };  
        TileInfo.Lods[6] = new Lod() { Resolution = 14.0013427734375 };  
        TileInfo.Lods[7] = new Lod() { Resolution = 7.00067138671875 };  
        TileInfo.Lods[8] = new Lod() { Resolution = 3.50033569335937 };  
        TileInfo.Lods[9] = new Lod() { Resolution = 1.75016784667968 };  
        TileInfo.Lods[10] = new Lod() { Resolution = 0.875083923339843 };  
        TileInfo.Lods[11] = new Lod() { Resolution = 0.4375419616699215 };  
        TileInfo.Lods[12] = new Lod() { Resolution = 0.2187709808349608 };  

        base.Initialize();  

    }  
    private string _url = "";  
    public override string GetTileUrl(int level, int row, int col)  
    {  
        return _url + "/" + level + "/" + (row + 1) + "/" + col + "";  
    }  
    public string Url  
    {  
        get  
        {  
            return _url;  
        }  
        set  
        {  
            _url = value;  
        }  
    }  
}  

}

有小伙伴肯定会说啦,代码量也不多啊,就这么十来行……但是真正折腾人的在于row+1这个地方。
首先,同样的,依照从服务提供商处得到的参数,填充FullExtent属性,但问题来了,这个坐标系是北京地方坐标系,Arcgis并未内置,所以我们无法使用像102100 4326一类的代码来初始空间参考对象,只能通过WKID的字符串来初始化。并且这里同样有一个坑容易掉进去:此字符串内千万不能多出空格来,哪怕是一个也不行,直接与图层服务匹配不上,导致图层加载不上来。我猜这个字符串并未解析成对象来匹配图层坐标系,而是直接通过字符串是否相等进行匹配的!
之后呢,这个TileInfo数组也明显的减少至了13级,最麻烦的地方在于row+1这里!这个底图瓦片结构的左上角初始区域向下偏了一行图块!导致浏览地图的时候总是出现编移,而且是一边缩放一边偏移~结果加个1好了。。。
当然,对于这种地方坐标系,在初始地图图层的时候也必须将空间参考设置成和上面代码中一样的WKID字符串才行哦!
好了,有了这两个类的示例,大家以后扩展任何第三方底图哪怕是地方坐标系的都没有问题了!
该说的都说完啦,转载还请注明出处哦,谢谢各位!^_^~

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页