1.说明
9月1日,水经注官网发布了离线影像缓存包读取控件,顾名思义,利用水经注地图下载器下载的.dat缓存文件,可以直接被该控件读取。这对于广大地图应用开发的工作者来说,无疑是个很方便的控件。笔者决定亲自尝试下该控件加载超大离线地图的快感。
源码下载地址: http://www.rivermap.cn/download/DatFileReader.rar
该DEMO下载之后包含三个文件夹,水经注离线影像地图缓存包读取控件,水经注离线影像地图缓存包读取控件_调用示例,水经注离线影像地图缓存包读取控件_调用示例源码。开发者需要的只是第一个:水经注离线影像地图缓存包读取控件。

2.离线地图读取实现
既然要读取离线地图,我们得先下载。再在开发平台中搭建好框架,利用离线地图读取控件,来调用我们的离线地图。

2.1下载离线地图包
    启动水经注万能地图下载器X2,这里我们下载成都1-15级的影像地图。

设置下载的级数为1-15级,勾选卫星地图和标签。请记录下新建任务时的最小坐标和最大坐标,有什么用后面再详细说明。

然后等待下载完成。在等待的时候我们是不是该做点什么?对了,刚刚不是记录了两个点吗,我们在进行地图开发的时候常常用到web墨卡托的坐标,这里我们演示一下,怎么得到这两个点的墨卡托坐标,来作为加载离线地图的开始范围。
用excel保存刚刚得到的最小坐标和最大坐标,如下:

启动arcmap,按照顺序分别点击【文件】-【添加数据】-【添加xy数据】,在弹出的对话框中选择我们保存的excel,x字段选择x,y字段选择y,编辑投影左边为web墨卡托投影,如下:

确定之后,我们就把两个点添加到了地图中,把他们转成shp文件之后,添加两个字段xM,yM,然后利用几何计算分别算出这两个点的墨卡托坐标,如下:

2.2 离线地图读取
    在看了水经注官网的DEMO实例源码之后,可以知道,该控件的原理很简单,利用读取控件将离线影像中的图片向外推出,再用地图显示控件显示出来。在这里,笔者使用的是ARCGIS_RUNTIME_SDK_forWPF开发包,并使用其map控件来显示离线影像。
启动vs2010,【文件】-【新建】-【WPF应用程序】,根据自己需要改变window的风格。在开始编写代码之前,我们将下载的离线地图缓存包读取控件和离线的.dat、.idx一并拷贝到解决方案的bin/Debug目录下:

向window控件中加入map控件,删除map的默认显示地图源,设置map的显示风格为stretch最大,这里我们将控件取名为Bmap:

在MainWindow.xaml.cs中写入我们的map加载事件,并在这里将我们刚刚下载的地图的墨卡托坐标范围作为map的显示范围。

为解决方案添加三个类,取名为TileLoader.cs、LabelLayer.cs、MapLayer.cs.

TileLoader.cs里面我们定义.dat的读取方法,在Debug根目录里面调用下载的.dat读取控件DatFileReader.dll,并通过LabelLayer.cs、MapLayer.cs这两个类中方法将图片显示到map控件中,其详细代码如下:

public class TileLoader
{
enum LayerType
{
TILE_LAYER = 0,
ROAD_LAYER,
DEM_LAYER
}
[DllImport("DatFileReader.dll",EntryPoint = "GetTile",CallingConvention = CallingConvention.Cdecl)]
private static extern ErrorCodeGetTile(int id, byte[]data, ref intlength, int level, introw, int col);
[DllImport("DatFileReader.dll",EntryPoint = "GetRoad",CallingConvention = CallingConvention.Cdecl)]
private static extern ErrorCodeGetRoad(int id, byte[]data, ref intlength, int level, introw, int col);
[DllImport("DatFileReader.dll",EntryPoint = "SetDataSource",CallingConvention = CallingConvention.Cdecl)]
private static extern ErrorCodeSetDataSource(int layerType, string path, ref int id);
enum ErrorCode
{
NO_ERROR = 0,//无错误
NOT_MATCH_RANGE = 1,//没在数据中找到相交的范围
DIR_NOT_EXIST = 2,//目录不存在
NO_DATA_AND_INDEX = 3,//没有dat根idx文件
L_OR_B_ERROR = 4,//经纬度错误
OUT_OF_MEMORY,//内存溢出
ANGE_ERROR//范围错误
}
static TileLoader()
{
int id1 = 0;
try
{
ErrorCode ec = SetDataSource(0, "dat/tile", refid1);
ec = SetDataSource(1, "dat/label",ref id1);
}
catch (System.Exceptionex)
{
MessageBox.Show((ex.ToString()));
}
}
public static byte[] getTile(int id,int level, introw, int col)
{
byte[] tmp = new byte[1024 * 1024];
int length = 1024 * 1024;
ErrorCode ec = GetTile(id, tmp, ref length, level, row, col);
if (ec == ErrorCode.NO_ERROR&& length > 0)
{
byte[] data = newbyte[length];
Buffer.BlockCopy(tmp, 0, data, 0,length);
tmp = null;
return data;
}
return null;
}
public static byte[] getLabel(intid, int level, introw, int col)
{
byte[] tmp = new byte[1024 * 1024];
int length = 1024 * 1024;
ErrorCode ec = GetRoad(id, tmp, ref length, level, row, col);
if (ec == ErrorCode.NO_ERROR&& length > 0)
{
byte[] data = newbyte[length];
Buffer.BlockCopy(tmp, 0, data, 0,length);
tmp = null;
return data;
}
return null;
}
}
LabelLayer.cs、MapLayer.cs这两个类,分别用来读取离线影像的标签和实际影像文件。标签的具体读取方法是:
class LabelLayer : TiledMapServiceLayer
{
private const double halfCircle = 20037508.342787;
public override void Initialize()
{
TileInfo = new TileInfo();
TileInfo.Width = 256;
TileInfo.Height = 256;
TileInfo.Origin = new MapPoint(-halfCircle, halfCircle);
TileInfo.SpatialReference = new SpatialReference(102113);//102100
TileInfo.Lods = new Lod[19];
double resolution = halfCircle * 2 / 256;
base.MaximumResolution = resolution;
for (int i = 0; i< TileInfo.Lods.Count(); i++)
{
TileInfo.Lods = new Lod();
               TileInfo.Lods.Resolution = resolution;
               resolution /= 2.0;
            }
            base.MinimumResolution = resolution * 2.0;
            base.SpatialReference = newSpatialReference(102113);
            base.FullExtent = newEnvelope(-halfCircle, -halfCircle,halfCircle, halfCircle);
            base.Initialize();
        }
        public override string GetTileUrl(intlevel, int row, intcol)
        {
            return string.Empty;
        }
        protected override void GetTileSource(intlevel, int row, intcol, Action<System.Windows.Media.ImageSource> onComplete)
        {
            byte[] data = TileLoader.getLabel(0,level + 1, row + 1, col + 1);
            if (data != null)
            {
               MemoryStream mstream = new MemoryStream(data);//File.ReadAllBytes(path)
               System.Windows.Media.ImageSourceConvertercconv = new System.Windows.Media.ImageSourceConverter();
               ImageSource source =cconv.ConvertFrom(mstream) as ImageSource;
               onComplete(source);
            }
        }
}
实际影像的读取方法是:
class MapLayer : TiledMapServiceLayer
    {
        private const double halfCircle = 20037508.342787;
        public override void Initialize()
        {
           TileInfo = new TileInfo();
           TileInfo.Width = 256;
           TileInfo.Height = 256;
           TileInfo.Origin = new MapPoint(-halfCircle, halfCircle);
           TileInfo.SpatialReference = new SpatialReference(102113);//102100
           TileInfo.Lods = new Lod[19];
            double resolution = halfCircle * 2 / 256;
            base.MaximumResolution = resolution;
            for (int i = 0; i< TileInfo.Lods.Count(); i++)
            {
               TileInfo.Lods = new Lod();
               TileInfo.Lods.Resolution = resolution;
               resolution /= 2.0;
            }
            base.MinimumResolution = resolution * 2.0;
            base.SpatialReference = newSpatialReference(102113);
            base.FullExtent = newEnvelope(-halfCircle, -halfCircle,halfCircle, halfCircle);
            base.Initialize();
        }
        public override string GetTileUrl(intlevel, int row, intcol)
        {
            return string.Empty;
        }
        protected override void GetTileSource(intlevel, int row, intcol, Action<System.Windows.Media.ImageSource> onComplete)
        {
            byte[] data = TileLoader.getTile(0,level + 1, row + 1, col + 1);
            if (data != null)
            {
               MemoryStream mstream = new MemoryStream(data);//File.ReadAllBytes(path)
               System.Windows.Media.ImageSourceConvertercconv = new System.Windows.Media.ImageSourceConverter();
               ImageSource source =cconv.ConvertFrom(mstream) as ImageSource;
               onComplete(source);
            }
        }
    }

到这里,代码编写工作基本完成,我们来编译运行一下:

2.3 总结
    成都1-15级的离线影像通过离线缓存包读取控件可以轻松的显示在前端,并且能流畅地放缩自如,相比在线地图,完全不用担心网速原因带来的卡顿。相信水经注离线地图缓存包读取控件会给地图开发者在今后的工作带来很大方便!
有任何疑问,请加 QQ4000280050

水经注离线影像地图读取控件的二次开发教程相关推荐

  1. 水经注离线三维地球触摸GIS系统

        前言 水经注离线三维地球触摸GIS系统(以下简称离线系统)是成都水经注软件研发的一款离线三维地球触摸GIS系统,该系统通过计算机图形技术.虚拟现实技术.混合现实技术等,结合多通道.综合高层次. ...

  2. Xamarin XAML语言教程构建ControlTemplate控件模板 (二)

    Xamarin XAML语言教程构建ControlTemplate控件模板 (二) (2)打开MainPage.xaml文件,编写代码,将构建的控件模板应用于ContentView中.代码如下: &l ...

  3. atitit. applet 浏览器插件 控件 的环境,开发,提示总结o9o

    atitit. applet 浏览器插件 控件 的环境,开发,提示总结o9o 1. 建立applet:: 1 2. Applet 码 1 3. Applet (awt)跟japplet (swing) ...

  4. java jp2launcher.exe_atitit. applet 浏览器插件 控件 的环境,开发,提示总结o9o

    atitit. applet 浏览器插件 控件 的环境,开发,提示总结o9o 1. 建立applet:: myclipse>>new>>applet,设置applet属性,设置 ...

  5. VisionPro控件的使用 C# 开发篇

    VisionPro 常用控件的说明 工具设置窗体 CogPMAlignEditV2  [ 模版匹配设置窗体控件 ] CogPMAlignEditV2.Subject : 工具关联对象  如:CogPM ...

  6. 【GIS开发】VB6.0下MO控件的安装:安装教程及MO破解教程(MapObjects2.x)

    [GIS开发]VB6.0下MO控件的安装:安装教程及MO破解教程(MapObjects2.x) 基于MO和VB的GIS开发过程中,普遍使用的还是2.0及以上版本,ESRI公司早已不再对MO组件进行更新 ...

  7. java ocx,Eclipse使用ActiveX控件(OCX)开发Java程序

    本范例以使用来电显示ActiveX控件JDComport.ocx为例,说明怎样在Java中集成ActiveX控件. 1.开发环境:Eclipse(Java主流开发工具) (1)需要用到SWT.Visu ...

  8. Android 原生控件之二 ImageView

    Android 原生控件之二 ImageView 相关 来源 开始 XML属性 1.android:adjustViewBounds 2.android:baseline 3.android:base ...

  9. android 控件上下排列_android 实现控件左右或上下抖动教程

    差不多一年前在自己的项目中用过这效果,虽然很简单,但还是写写. 1.首先在你的res目录下新建anim子目录,并在anim目录下新建两个文件: (1)shake.xml文件(位移/平移:transla ...

最新文章

  1. linux 12541 重启监听器,ORA-12541:ORA-12541:TNS:没有监听器 解决方法
  2. 清华大学计算机网络研究中心,清华大学信息网络工程研究中心简介
  3. 深入JavaScript与.NET Framework中的日期时间(1):基本概念与概述
  4. oModel.create will also send to backend directly
  5. java openSession和getCurrentSession的比较
  6. 常见在线射频电学计算公式
  7. html5好看的颜色代码,css好看的颜色配色.html
  8. 地籍测量类毕业论文文献有哪些?
  9. JAVA学习笔记——对象(一)
  10. xpath跨级定位(parent::,following-sibling::, preceding-sibling)
  11. 奇葩需求系列-距离明天十二点倒计时
  12. 快讯|腔家政服务商“懒猪到家”完成200万种子轮融资,卡伊妮洗衣连锁投资... 1
  13. 提高Java反射速度的方法以及对setAccessable的误解
  14. Linux命令行下使用飞信
  15. 我的Crystal xcelsius之旅
  16. Visual Studio 2015/2017 与ASP.NET CORE 联合创建具有SPA模式的Angular2模板
  17. 【Oracle数据库基础学习】
  18. Java代码混淆工具-ProGuard
  19. 依据imu姿态角计算z轴倾角_树莓派小车-07-IMU姿态解算 imu_complementray_filter
  20. centos7配置时间同步

热门文章

  1. 编码转换使用java_java编码转换的详细过程
  2. SpringBoot开发使用DevTools进行热部署
  3. 数据格式(计算机组成原理)
  4. 【NoteBook】吴晓波:《影响商业的50本书》——第一部分:当商业开始改变世界
  5. 2022-2028年中国人用狂犬病疫苗行业市场调查研究及投资策略研究报告
  6. 微信小程序地址选择wx.chooseLocation
  7. 高德地图-web端根据地理编码和逆地理编码
  8. Vue实现复制粘贴功能
  9. 电阻、电容、电感的实际等效模型
  10. ttest函数使用方法_用MATLAB做T检验(ttest)