使用ArcGIS Mobile SDK 9.3 开发移动设备应用-中级篇

【概述】概述如何 通过ArcGIS Server 9.3提供的Mobile SDK开发移动设备应用。
【环境】Windows XP SP3,ArcGIS Server 9.3,Visual Studio 2008,Windows Mobile 6 Professional SDK

 

ScaleBar控件

ScaleBar兼有比例尺和进度条的功能。ScaleBar对象同时和Map和 MobileService对象关联,与Map的关联可以显示当前地图的比例大小,与MobileService的关联可以显示当前设备从服务器同步数据 的进程。当然,你也可以把ScaleBar与MobileService对象的关联去除掉,好让ScaleBar显得更加纯粹一点。

image

 

空间参考

空 间参考(Spatial Reference)是GIS的一个非常重要的组成部分,空间参考包括地理坐标系和投影坐标系。我们通过MobileService获得地图是有空间参考 的,但是,在移动设备上,有时候还需要将一些坐标点(比如GPS信息)标注到地图上,这时就还需要进行空间参考的处理。

以下代码表现的 是如何将一个GPS经纬度坐标(WGS84)转化为一个当前空间参考下的坐标值。是不是很简单?

double lat = 40.123456;
double lon = 116.123456;
ESRI.ArcGIS.Mobile.SpatialReferences.SpatialReference spatialReference = mobileService.SpatialReference;
ESRI.ArcGIS.Mobile.Geometries.Coordinate coordinate = spatialReference.FromWgs84(lon, lat);

 

GPS支持

ArcGIS Mobile提供了3个GPS相关的控件对GPS进行支持:

l FileGpsConnection
l SerialPortGpsConnection
l GpsDisplay

对 名称的第一印象我们就可以大概知道,FileGpsConnection可以提供文件GPS连接,在调试中可能使用比较 多;SerialPortGpsConnection则提供串口GPS连接,实际应用一般都会用到;GpsDisplay和上述两种 GpsConnection联动,实现GPS信息在地图上的表现。

在没有GPS设备的时候,我们先使用 FileGpsConnection进行调试。FileGpsConnection的原理就是从一个包含GPS数据的文本文件,模拟一个GPS连接。当 然,首先需要准备一个GPS文件,这个文件手写是写不出来的,获得的最便捷的方法是安装Windows Mobile 6 Professional SDK的FakeGPS工具(“%WINDOWS_MOBILE_6_SDK_HOME%/Tools/GPS”),其中包含有GPS数据文件。我把 “fakegpsdata.txt”文件复制到“/Storage Card”目录下,再给FileGpsConnection对象指定FileName属性为“/Storage Card/fakegpsdata.txt”。

我们在菜单上新建两个菜单项,用以打开关闭GPS连接:

        private void menuItemOpenGpsConn_Click(object sender, EventArgs e)
        {
            this .fileGpsConnection.Open();
        }  

        private void menuItemCloseGpsConn_Click(object sender, EventArgs e)
        {
            this .fileGpsConnection.Close();
        }

GpsDisplay有一个AutoPan属性默认设为了true,现在让我们打开GPS连接,看看我们的地图,是不是自动移动了?

其 实,这个时候我们完全可以不用GpsDisplay,而直接通过GpsConnection做任何事情。我们给FileGpsConnnection添加 一个消息响应函数,每次GPS位置点改变了就触发一次:

        private ESRI.ArcGIS.Mobile.Geometries.Point gpsLocation;  

       
private void fileGpsConnection_GpsChanged(object sender, EventArgs e)
        {
            double lat = this .fileGpsConnection.Latitude;
            double lon = this .fileGpsConnection.Longitude;
            if (!(lat >= -90 && lat <= 90)) return ;
            if (!(lon >= -180 && lon <= 180)) return ;

            ESRI.ArcGIS.Mobile.SpatialReferences.SpatialReference spatialReference = mobileService.SpatialReference;
            ESRI.ArcGIS.Mobile.Geometries.Coordinate coordinate = spatialReference.FromWgs84(lon, lat);

            gpsLocation = new ESRI.ArcGIS.Mobile.Geometries.Point (coordinate);
            this .map.CenterAt(coordinate);
        }

        private void map_Paint(object sender, ESRI.ArcGIS.Mobile.MapPaintEventArgs e)
        {
            if (gpsLocation == null || gpsLocation.IsEmpty) return ;
            e.Display.DrawPoint(new Pen (Color .Blue), new SolidBrush (Color .Red), 5, gpsLocation);
       }

看一下实际效果:

image

 

离线编辑功能

ArcGIS Mobile的编辑功能可以在离线状态下使用,当然,前提要有空间数据缓存。要使用ArcGIS Mobile的编辑功能,首先需要在Map对象中添加一个或者几个sketchGraphicLayer对象,我们的编辑将会在这些图层上进行。

image

如果有必要,我们还可以针对Map的其它设置作 一些改变,比如捕捉:

image

和地图浏览的Action类似,我们还需要给 Map添加一些编辑的Action:

image

好,下面我们试着在 sketchGraphicLayer上添加一个多边形:

        private void menuItemAdd_Click(object sender, EventArgs e)
      
{
            this .map.CurrentMapAction = this .map.MapActions[3];
            ESRI.ArcGIS.Mobile.Sketch.SketchGraphicLayer sketchGraphicLayer = (this .map.MapGraphicLayers[0]) as ESRI.ArcGIS.Mobile.Sketch.SketchGraphicLayer ;
            sketchGraphicLayer.Geometry = new ESRI.ArcGIS.Mobile.Geometries.Polygon ();
      
}

 

现在,当我们点击 了菜单中的“Add”菜单项以后,再在地图上点击就可以绘制一个多边形了。再尝试一下DeleteVetexSketchTool、 InsertVetexSketchTool、MoveVetexSketchTool(前提是先获得需要操作的Geometry对象),是不是发现对已 经画的对象进行修改也是很容易呢?

image

当然,接着马上要做的事情就是保存刚才所作的编 辑,写程序的大多都有Ctrl+S的好习惯。保存刚才的编辑到缓存图层是一件很容易的事情,看一下这段代码:

        private void menuItemSave_Click(object sender, EventArgs e)
        {
            ESRI.ArcGIS.Mobile.MobileServices.FeatureLayer featureLayer = this .mobileService.Layers[0 ] as ESRI.ArcGIS.Mobile.MobileServices.FeatureLayer ;
            if (featureLayer.AllowNew)
            {
                ESRI.ArcGIS.Mobile.Sketch.SketchGraphicLayer sketchGraphicLayer = (this .map.MapGraphicLayers[0]) as ESRI.ArcGIS.Mobile.Sketch.SketchGraphicLayer ;
                ESRI.ArcGIS.Mobile.MobileServices.FeatureDataTable featureDataTable = featureLayer.GetDataTable();
                ESRI.ArcGIS.Mobile.MobileServices.FeatureDataRow featureDataRow = featureDataTable.NewRow();
                featureDataRow[featureLayer.GeometryColumnIndex] = sketchGraphicLayer.Geometry;
                featureDataTable.Rows.Add(featureDataRow);
                featureDataTable.SaveInFeatureLayer();
                sketchGraphicLayer.Geometry = null ;
            }
        }

在这里还要废话几句,上面做的保存是将编辑保存在本地的缓存中,而不是保存到服务器。在保存之前,先使用了FeatureLayer对象的 AllowNew属性,这是一个GET访问器,可以获得图层是否允许保存编辑(添加要素)。如果你在调试程序的时候AllowNew是false,可能有 几种原因:

l 图层不是SDE图层
l 图层没有Global ID(这是Mobile应用一个特殊的地方)

这 个时候,你或许可以尝试这个方法:

image

 

在线上传编辑

在 线上传编辑可以把在本地缓存上进行的编辑操作提交到服务器,使用方法很简单:

mobileService.PostFeaturesAsync("Update" );

不过,由于SDE分别有针对不同数据库的版本,而各种不同的数据库也各自有很多不同版本,在这种对应关系下,出现各种诡异的问题都是有可能的。建 议:暂时慎用这个功能。

 

异步请求和响应

在ArcGIS Mobile中,我们可以看到很多以Async结尾的方法,比如常用的GetFeatureDataAsync ()方法等等。从名称就可以看出来,这些方法会向服务器发送一个异步的请求,但是,请求何时完成,请求的结果如何,并不是由这个方法及其后续来处理。

对 异步请求结果的处理,可以通过MobileService对象的几个消息响应函数实现,主要包括RequestCompleted、 RequestProgressChanged等。当MobileService接收到了服务器发来的消息,表示请求有了反馈了,这些消息响应函数则被调 用,来实现后续的处理。

有个很自然的问题,我可能向服务器发送了很多种的请求,MobileService对象怎么来分辨接收到的反馈 属于谁呢?我们回头看一下Async方法的参数会发现,Async方法的参数中都有一个名叫 userState的object对象,这个对象用来表示Async请求发生时候的用户状态,也就是对请求进行了标识。

 

CatalogService 控件

CatalogService控件用以发现某个服务器上的Mobile服务。在ArcGIS Server服务器上,一个服务器下可以有若干个文件夹,一个文件夹下可以有若干个地图服务对象,每个地图服务对象提供1种以上地图服务(Mobile Access、WFS……)。CatalogService对象就可以把这个层次结构挖掘出来,并获得详细的信息。

获得文件夹:

         catalogService.Url = http://wuyf-winxp/arcgis/services ;
            string [] folders = catalogService.GetFolders();

获得服务信息:

         catalogService.Url = http://wuyf-winxp/arcgis/services/folder ;
            ESRI.ArcGIS.Mobile.CatalogServices.ServiceDescription [] serviceDescriptions = catalogService.GetServiceDescriptions();

 

好了,今天就到这里吧,欢迎关注本文的后续。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值