MSCBSC 移动通信论坛
搜索
登录注册
网络优化工程师招聘专栏 4G/LTE通信工程师最新职位列表 通信实习生/应届生招聘职位

  • 阅读:2227
  • 回复:2
[经验] 水经注离线影像地图读取控件的二次开发教程
诺一小宝贝
初级会员
鎵嬫満鍙风爜宸查獙璇


 发短消息    关注Ta 

积分 140
帖子 28
威望 12003 个
礼品券 0 个
专家指数 0
注册 2015-11-5
专业方向  工程测量
回答问题数 0
回答被采纳数 0
回答采纳率 0%
 
发表于 2016-01-14 10:59:07  只看楼主 
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


扫码关注5G通信官方公众号,免费领取以下5G精品资料
  • 1、回复“YD5GAI”免费领取《中国移动:5G网络AI应用典型场景技术解决方案白皮书
  • 2、回复“5G6G”免费领取《5G_6G毫米波测试技术白皮书-2022_03-21
  • 3、回复“YD6G”免费领取《中国移动:6G至简无线接入网白皮书
  • 4、回复“LTBPS”免费领取《《中国联通5G终端白皮书》
  • 5、回复“ZGDX”免费领取《中国电信5G NTN技术白皮书
  • 6、回复“TXSB”免费领取《通信设备安装工程施工工艺图解
  • 7、回复“YDSL”免费领取《中国移动算力并网白皮书
  • 8、回复“5GX3”免费领取《 R16 23501-g60 5G的系统架构1
  • 对本帖内容的看法? 我要点评

     
    [充值威望,立即自动到帐] [VIP贵宾权限+威望套餐] 另有大量优惠赠送活动,请光临充值中心
    充值拥有大量的威望和最高的下载权限,下载站内资料无忧
    相思雨312
    初级会员
    鎵嬫満鍙风爜宸查獙璇


     发短消息    关注Ta 

    积分 325
    帖子 65
    威望 73889 个
    礼品券 0 个
    专家指数 0
    注册 2014-7-10
    专业方向  通信
    回答问题数 0
    回答被采纳数 0
    回答采纳率 0%
     
    发表于 2016-01-18 13:40:45 
    技术问题,回答得专家指数,快速升级
    大赞,谢谢lz分享,我也下下来研究一下

    对本帖内容的看法? 我要点评

     
    [立即成为VIP会员,百万通信专业资料立即下载,支付宝、微信付款,简单、快速!]
    诺一小宝贝
    初级会员
    鎵嬫満鍙风爜宸查獙璇


     发短消息    关注Ta 

    积分 140
    帖子 28
    威望 12003 个
    礼品券 0 个
    专家指数 0
    注册 2015-11-5
    专业方向  工程测量
    回答问题数 0
    回答被采纳数 0
    回答采纳率 0%
     
    发表于 2016-01-19 15:43:28  只看楼主 
    最近万能下载器有免费授权活动哈 详情咨询QQ 4000280050

    对本帖内容的看法? 我要点评

     
    最新通信职位:广东通信人才网 | 北京通信人才网 | 上海通信人才网 | 南京通信人才网 | 西安通信人才网 | 重庆通信人才网 | 中国通信人才网

    快速回复主题    
    标题 [经验] 水经注离线影像地图读取控件的二次开发教程" tabindex="1">
    内容
     上传资料请点左侧【添加附件】

    当前时区 GMT+8, 现在时间是 2026-07-20 09:28:46
    渝ICP备11001752号  Copyright @ 2006-2016 mscbsc.com  本站统一服务邮箱:mscbsc@163.com

    Processed in 0.852289 second(s), 20 queries , Gzip enabled
    TOP
    清除 Cookies - 联系我们 - 移动通信网 - 移动通信论坛 - 通信招聘网 - Archiver