随笔 - 15  文章 - 0 评论 - 20 trackbacks - 0

  在上一篇中,地图使用的本地缓存是通过Create Mobile Map这个GP工具生成(放在文件夹XYZ中),然后把文件夹拷贝到移动设备的My Documents文件夹下的。这里我们介绍通过访问“Mobile Data Access”类型的服务,直接创建缓存的方法(可以先删除设备上My Documents\XYZ\MobileCache下的所有本地缓存文件) 在Form1的Load事件处理函数中添加如下代码:

Form1_Load
 1         private void Form1_Load(object sender, EventArgs e)
 2         {
 3             this.mobileCache1.StoragePath = @"\My Documents\GlobeMapCache\MobileCache";
 4             if (!this.mobileCache1.IsValid)
 5             {
 6                 MessageBox.Show("Map Cache is not valid!");
 7                 return;
 8             }
 9             if (this.mobileCache1 != null && this.mobileCache1.IsOpen)
10             { this.mobileCache1.Close(); }
11             if (mobileCache1.IsEmpty)
12             {
13                 mobileCache1.DeleteCache();//删除现有缓存,试验结果是删除My Documents\XYZ 下的MobileCache文件夹
14                 mobileServiceConnection1.Url = @"http://vmserver/arcgis/services/MobileGlobe/MobileServer";
15                 mobileServiceConnection1.WebClientProtocolType = WebClientProtocolType.BinaryWebService;
16                 MobileCacheSyncAgent mobilesync = new MobileCacheSyncAgent(mobileCache1, mobileServiceConnection1);
17                 
18                 mobileServiceConnection1.CreateCache(mobileCache1);//新建缓存
19                 mobileCache1.Open();//试验结果是此行先于下一行,文档Ya稳定。。。
20                 mobilesync.Synchronize();
21                 //map1.DataSources.Add(mobileCache1);//此行作用等同于上篇中:在Map控件的DataSources属性中添加MobileCache1
22             }
23         }

       到目前为止,说得都是从服务器上获取数据然后在设备上显示,但用移动设备的目的之一是采集数据,然后同步到服务器。下面我们先讲如何在移动设备上实现离线数据编辑,数据同步到服务器上的问题就留到下篇(也可能是下。。。下篇~)

一、创建新要素

A 添加一个ESRI.ArcGIS.Mobile.Geometries.CoordinateCollection类型的全局变量m_coordinateCollection,为Map控件的MouseUp事件添加处理函数,每次点击地图为m_coordinateCollection添加一个新的节点:

map1_MouseUp
 1         private ESRI.ArcGIS.Mobile.Geometries.CoordinateCollection m_coordinateCollection;
 2 
 3         private void map1_MouseUp(object sender, ESRI.ArcGIS.Mobile.MapMouseEventArgs e)
 4         {
 5             // Creates a new instance of a coordinate collection, if needed
 6             if (m_coordinateCollection == null)
 7             { m_coordinateCollection = new ESRI.ArcGIS.Mobile.Geometries.CoordinateCollection(); }
 8             // Adds the mouse up map coordinate to the collection e.MapCoordinate
 9             m_coordinateCollection.Add(e.MapCoordinate);
10             // Refreshes the client area
11             map1.Invalidate();
12         }

 B 为Map控件的Paint事件添加处理函数,相应上面的map1.Invalidate(),注意下面的DrawPolygon方法,我们也可以用各种Draw方法,具体参考ESRI.ArcGIS.Mobile.Display类的方法。

map1_Paint
1         private void map1_Paint(object sender, ESRI.ArcGIS.Mobile.MapPaintEventArgs e)
2         {
3             // Checks the coordinate collection feedback
4             if (m_coordinateCollection != null && m_coordinateCollection.Count != 0)
5             {
6                 // Draws the coordinate collection as a polygon
7                 e.Display.DrawPolygon(new Pen(Color.Red), new SolidBrush(Color.Red), m_coordinateCollection);
8             }
9         }

 C 保存绘制的要素,添加一个名为Save的Button,添加单击响应函数实现保存:

buttonSaveEdit_Click
 1         private void buttonSaveEdit_Click(object sender, EventArgs e)
 2         {
 3             // Selects a specific cache layer
 4             FeatureLayer featureLayer = this.mobileCache1.Layers[0as FeatureLayer;
 5 
 6             // Checks if geometry is editable
 7             if (!featureLayer.AllowNew)
 8                 return;
 9 
10             // Gets the schema of the feture layer
11             FeatureDataTable featureDataTable = featureLayer.GetDataTable();
12 
13             // Gets the feature layer's geometry column index
14             int geometryIndex = featureLayer.GeometryColumnIndex;
15 
16             // If feature is a NEW feature
17             // Creates a new row
18             FeatureDataRow featureDataRow = featureDataTable.NewRow();
19 
20             // Sets the new geometry to the geometry field
21             featureDataRow[geometryIndex] = new Polygon(m_coordinateCollection);
22 
23             // Adds the new row to the feature layer data table
24             featureDataTable.Rows.Add(featureDataRow);
25 
26             // Updates the feature layer data table
27             featureDataTable.SaveInFeatureLayer();
28         }

   上面做的保存是将编辑保存在本地的缓存中,这里重点要讲的是在保存之前,先使用了FeatureLayer对象的AllowNew属性。这是一个GET访问器,可以获得图层是否允许保存编辑(添加要素)。如果你在调试程序的时候AllowNew是false,那么可能有以下两个原因:1、图层不是SDE图层(实验的结果是你也可以使用Personal Geodatabase的图层) 2、图层没有Global ID(这是Mobile应用一个特殊的地方,给图层创建Global ID的方法很简单,在ArcCatalog中右击图层点击Add Global IDs...既可)

 

  既然说到SDE和Personal Geodatabase,我最近看到一份比较早的关于ArcGIS和SuperMap的比较报告,其中比较好玩的是说到ArcGIS的SDE不支持空间拓扑,而Geodatabase支持。其实熟悉Geodatabase的都知道,Geodatabase分为Personal Geodatabase(物理存储为Access数据库)、File Geodatabase(物理存诸为文件夹)、SDE Geodatabase(物理存储为大型RDBMS数据库),ArcSDE是ESRI公司实现Geodatabase数据模型的一个服务器软件产品,如果把抽象的Geodatabase当作逻辑模型的话,ArcSDE产品则是对Geodatabase的一个物理实现。通过ArcSDE,GIS管理员能够以面向对象的方式在关系型数据库中存储空间数据,也就能够实现所有Geodatabase数据模型所支持的数据对象和功能。

 

    偶のSuperStar宋关福认为GIS研发人员应该长三只眼睛:第一只眼盯用户需求,要随需而变,这是根本;第二只眼盯着IT变化,不管GIS软件中蕴含多专业的地学知识,但它首先是软件,IT的所有新的变化都可能给GIS软件带来不可低估的影响;第三只眼留意同行举动,此举不是为了要跟着先行者走,那是追星族,没有战略的表现,而是留意同行举动背后蕴藏着什么样的用户需求,以便采取更有效的途径去满足。前两只眼是预见性的,最为重要,第三只眼用于亡羊补牢,要尽量争取用前两只眼发现问题和机会。(好像SuperMap盯梢的没盯好啊~咳咳~扯远了~刹车~)

 

二、利用草图工具创建图形

  要使用ArcGIS Mobile的编辑功能,首先需要在Map控件的MapGraphicLayer属性中添加一个或者几个sketchGraphicLayer对象,我们的编辑将会在这些图层上进行。然后为MapAction属性添加以下工具,这里我们先已AddVertexSketchTool为例,为MapAction属性添加工具的详细图片看上篇。

AddVertexSketchTool(used to create a new geometry )

DeleteVertexSketchTool( used to delete vertices in an existing geometry)
InsertVertexSketchTool (used to insert/move new vertices in an existing geometry)

MoveVertexSketchTool(used to move vertices in an existing geometry)

添加一个menuItem(menuItemAdd)并加入单击响应函数实现绘制图形,然后再添加一个menuItem(menuItemSave)用来保存图形:

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

  

menuItemSave_Click
         private void menuItemSave_Click(object sender, EventArgs e)
         {
             ESRI.ArcGIS.Mobile.MobileServices.FeatureLayer featureLayer 
= this.mobileCache1.Layers[0as ESRI.ArcGIS.Mobile.MobileServices.FeatureLayer;
             
if (featureLayer.AllowNew)
             {
                 ESRI.ArcGIS.Mobile.Sketch.SketchGraphicLayer sketchGraphicLayer 
= (this.map1.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;
             }
             
this.map1.CurrentMapAction = this.map1.MapActions[0];//回复Pan的状态
         }

 

更多关于ArcGIS Mobile的开发:http://www.cnblogs.com/ECNU-GIS-LIUJIE

posted @ 2010-03-04 17:18 JayLiu 阅读(1331) 评论(1) 编辑

  在上篇中我们可以看到,利用Mobile Project Center可以方便的创建直接可用的ArcGIS Mobile应用程序,这里我们介绍如何利用ArcGIS Mobile SDK把GIS功能嵌入到已有的移动设备应用程序中。首先利用Visual Studio创建一个智能设备项目,在VS2005新建项目对话框的左侧点击智能设备,在下面的子节点中选择项目平台(如Windows Mobile 6 Professional), 在VS2008新建项目对话框中,先在右上角选择.NET Framework 2.0,按确定按钮在随后出现的对话框中选择目标平台(如下左图),把一个Map控件拖到界面中,我们会发现一个MobileCache1控件自动添加到下面,项目的引用中也会自动添加程序集ESRI.ArcGIS.Mobile(如下右图)

Tips:如果一开始选错了目标平台也没关系,在解决方案资源管理器的项目上右击,然后选择“更改目标平台”命令,就可以修改到你期望的目标平台。

查看Map控件的DataSources属性,我们会发现MobileCache1 自动列在那里,如果没有列出,请自己添加(一般都是自动添加,除非你的RP。。。)

 

   在笔记二的最后一段我们通过属性对话框来进行参数设置,现在我们通过代码来进行同样的设置,为Form1添加Load事件,在其中添加如下代码:

Form1_Load相应函数
 1         private void Form1_Load(object sender, EventArgs e)
 2         {
 3             //Environment.GetFolderPath(Environment.SpecialFolder.Personal) ==  "\My Documents"
 4             this.mobileCache1.StoragePath = @"\My Documents\XYZ\MobileCache";
 5             if (!this.mobileCache1.IsValid)
 6             {
 7                 MessageBox.Show("Map Cache is not valid!");
 8                 return;
 9             }
10             if (this.mobileCache1 != null && this.mobileCache1.IsOpen)
11             { this.mobileCache1.Close(); }
12             try
13             {
14                 this.mobileCache1.Open();//原来9.3中CacheOpenMode枚举类型的参数取消了=。=
15             }
16             catch
17             {
18                 MessageBox.Show("Cannot open map cache");
19             }
20         }

       因为地图缓存是事先通过笔记一中介绍的Create Mobile Map这个GP工具生成(放在文件夹XYZ中),然后把文件夹拷贝到移动设备的My Documents文件夹下的,还有一种通过访问地图服务直接创建缓存的方法在下一篇介绍。既然说到文件拷贝,那就具体介绍下模拟器配置,点击VS“工具”菜单下的“设备仿真器模拟器”,在你期待的目标平台上右击,连接后插入底座(Cradle如下左图),就可以同步了,前提是你打开了ActiveSync的wcescomm.exe程序。现在在“我的电脑”目录下,打开“移动设备”,就可以把文件拷贝到你想要的位置。

Tips:要运用ArcGIS Mobile应用程序,需要把C:\Program Files\ArcGIS\Mobile9.4\Install下的ArcGISMobile.CAB或AGMRuntime.CAB拷贝到移动设备上并安装 

        现在实现地图的移动、放大、缩小等基本功能,点击Map控件的MapAction属性,弹出如上右图的编辑框,加入你想要的操作,如PanMapAction, ZoomInMapAction、ZoomOutMapAction等,为3个menuItem添加相应函数:

地图操作
 1         private void menuItemPan_Click(object sender, EventArgs e)
 2         {
 3             this.map1.CurrentMapAction = this.map1.MapActions[0];
 4         }
 5 
 6         private void menuItemIn_Click(object sender, EventArgs e)
 7         {
 8             this.map1.CurrentMapAction = this.map1.MapActions[1];
 9         }
10 
11         private void menuItemOut_Click(object sender, EventArgs e)
12         {
13             this.map1.CurrentMapAction = this.map1.MapActions[2];
14         }

   最后,我们再实现一个Identify的功能,添加一个menuItem( menuItemIdentify),为其添加处理函数,并且为Map控件添加MouseDown的相应函数,代码如下:

Identify
 1         private void menuItemIdentify_Click(object sender, EventArgs e)
 2         {
 3             this.map1.CurrentMapAction = null;
 4         }
 5 
 6         private void map1_MouseDown(object sender, ESRI.ArcGIS.Mobile.MapMouseEventArgs e)
 7         {
 8             if (map1.CurrentMapAction != null)
 9             { return; }
10 
11             Cursor.Current = Cursors.WaitCursor;
12             MapMouseEventArgs me = e as MapMouseEventArgs;
13             Envelope qEnv = new Envelope(me.MapCoordinate, me.MapCoordinate);
14 
15             double mapTolerance = map1.ToMap(3);
16             qEnv.Resize(mapTolerance, mapTolerance);
17 
18             QueryFilter qFilter = new QueryFilter(qEnv, GeometricRelationshipType.Intersect);
19 
20             string txtResult = "Identify Results: ";
21             int intFields;
22                 foreach (MobileCacheLayer MCLayer in mobileCache1.Layers)
23                 {
24                     if (MCLayer is FeatureLayer)
25                     {
26                         txtResult += "\r\n Layer " + MCLayer.Name;
27                         FeatureLayer FLayer;
28                         FLayer = (FeatureLayer)MCLayer;
29                         using (FeatureDataReader featReader = FLayer.GetDataReader(qFilter))
30                         {
31                             intFields = featReader.FieldCount;
32                             while (featReader.Read())
33                             {
34                                 for (int i = 0; i < intFields; i++)
35                                 { txtResult += "\r\n" + featReader.GetName(i) + "" + featReader.GetValue(i).ToString(); }
36                             }
37                         }
38                     }
39                 }
40             Cursor.Current = Cursors.Default;
41             MessageBox.Show(txtResult.ToString());
42         }

 

 代码执行到32行的while (featReader.Read())时,此处耗费很多时间,本人开发环境是虚拟机+模拟器,所以显得更慢(Oh~,my bloom) 如果不报错,建议耐心等待,最终结果如下图:

  

更多关于ArcGIS Mobile的开发:http://www.cnblogs.com/ECNU-GIS-LIUJIE

posted @ 2010-03-04 11:30 JayLiu 阅读(1912) 评论(0) 编辑