Spehio

我叫杜晓三 | Ecology | Urban | Landscape | GIS | IT
Options:

昨天下午下了课,老板给打电话来说帮师兄研究一下如何实现这样如题的功能,具体情境是拿C#用ArcEngine做二次开发的时候,他要开四个MapControl控件,分别显示大气、土壤等等的信息,在每个地图容器里面拖拽放大的时候,其他容器里面的地图联动,鼠标也要在四个窗口里面同步显示。
好的,分成三步来做。以两个MapControl联动为例,做窗口上放了两个ArcGIS Engine MapControl控件,分别命名Map1和Map2。
先实现地图联动,每当地图位置、比例尺发生变化的时候,会触发MapControl的OnExtentUpdated事件,在Map1的响应函数里面写:

Map2.Extent = (IEnvelope)e.newEnvelope;

Map2同理,这样就好了。之前有试过Map2.Extent = Map1.Extent.Envelope的用法,但是联动的时候慢半拍。
接着实现同步操作状态,即鼠标进入MapControl控件的时候,保持一致的漫游、放大、缩小等功能。再放两个ArcGIS Engine ToolBarControl控件,分别命名Bar1和Bar2,添加好漫游、放大、缩小、全图四个按钮,并绑定对应的MapControl控件。
实现的原理是当按下一个ToolBar上按钮的时候,让别的ToolBar的该按钮也处于按下状态。在ToolBar的OnItemClick事件里面写,这里有一点要注意的是ToolBar里面的全图按钮算Command不算Tool(AO里面的强行不合理分类,Command是按下就弹起的按钮,Tool是按下后保持状态的。),在代码里面利用e.index把他排除在同步操作的状态以外。关键代码如下

Bar2.CurrentTool = Bar2.GetItem(e.index).Command as ITool;

Bar1同理,这样效果就出来了。前面几次操作在显示上略有点小问题,我归结到AE的Bug里面,多点几次基本就是无缝同步了,最后出成品的时候,隐藏到其他的ToolBar就好了。
鼠标这个功能比较麻烦,我试过用PicureBox装在个鼠标图片然后用位置控制的方法,但是PictrueBox本身不透明,效果不好,况且暂时也不需要也没必要实现同时弹出右键菜单,跟师兄沟通了一下决定改用在其他地图容器里面画一个大的十字丝来作为鼠标的定位显示,这个功能用NewLineFeedbackClass来实现。
首先做定义两个接口。

private IDisplayFeedback pDisplayFeedback1 = null;
private IScreenDisplay pScreenDisplay1 = null;
在窗体的构造函数里面添加初始化的代码。

pDisplayFeedback1 = new NewLineFeedbackClass();
pScreenDisplay1 = Map1.ActiveView.ScreenDisplay;
pDisplayFeedback1.Display = pScreenDisplay1;
在Map2的OnMouseMove事件里面写响应代码。

((INewLineFeedback)pDisplayFeedback1).Stop(); //结束之前的绘制,DisplayFeedback在执行Start()方法之后开始画,Stop()之后就清掉了。
//下面是画十字丝的,因为没有NewMultiLineFeedbackClass,这个十字丝只能一笔画成,所以就只能在显示区域外面多画了一点。
((INewLineFeedback)pDisplayFeedback1).Start(Map1.ActiveView.ScreenDisplay.
DisplayTransformation.ToMapPoint(0, e.y));
((INewLineFeedback)pDisplayFeedback1).AddPoint(Map1.ActiveView.ScreenDisplay.
DisplayTransformation.ToMapPoint(Map1.Width + 1, e.y));
((INewLineFeedback)pDisplayFeedback1).AddPoint(Map1.ActiveView.ScreenDisplay.
DisplayTransformation.ToMapPoint(Map1.Width + 1, -1));
((INewLineFeedback)pDisplayFeedback1).AddPoint(Map1.ActiveView.ScreenDisplay.
DisplayTransformation.ToMapPoint(e.x, -1));
((INewLineFeedback)pDisplayFeedback1).AddPoint(Map1.ActiveView.ScreenDisplay.
DisplayTransformation.ToMapPoint(e.x, Map1.Height));
这样就在当鼠标在Map2上时,Map1上会同步打一个十字丝。画出来的是默认宽度为1的黑色线,正好符合我的要求。也可以自定义线形,关键代码如下,加在初始化代码里面。

IRgbColor fcolor = new RgbColorClass();
fcolor.RGB = 0;
ISimpleLineSymbol pSymbol = (ISimpleLineSymbol)pDisplayFeedback1.Symbol;
pSymbol.Color = fcolor;
pSymbol.Width = 1;
pSymbol.Style = esriSimpleLineStyle.esriSLSSolid;
//放在这句之前 pDisplayFeedback1.Display = [...]

来解析一下Geoprocessor类的Execute方法,他有两种重载,Execute(IGPProcess, ITrackCancel)和Execute(string, IVariantArray, ITrackCancel)。
Execute(IGPProcess, ITrackCancel)
IGProcess是所有Geoprocessor工具类都实现了的接口,通过ITrackCancel接口能够处理用户发出的取消指令并进一步处理,暂时用不上,一般都用null直接代替了。
因此这种方式的执行流程如下:
ESRI.ArcGIS.AnalysisTools.Buffer bufferTool = new ESRI.ArcGIS.AnalysisTools.Buffer();
GP.Execute(bufferTool, null);
Execute(string, IVariantArray, ITrackCancel)
string即是这个GP工具的名字了,IVariantArray是esriSystem命名空间下的一个接口,提供对esriSystem数组类VarArrayClass的访问功能,该类提供执行GP所需的参数,通过上文,大概也应该猜到了,这个参数数组类的成员应该也是字符串,方法如下:
GP.AddToolbox(@”C:\SanDiego\BestPath.tbx”);
IVariantArray parameters = new VarArrayClass();
parameters.Add(@”C:\SanDiego\source.shp”);
parameters.Add(@”C:\SanDiego\destination.shp”);
parameters.Add(@”C:\SanDiego\bestpath.shp”);
GP.Execute(”CalculateBestPath”, parameters, null);
好的,这两种方法该用在哪里这下都明白了,对于既有的Geopressing工具是第一种方法,对于自己制作的ArcToolBox则可以使用第二种方法来执行。(窃以为第二种方法的形式更为优雅一点。)
我们还有一种方法可以把自制的ArcToolBox在系统中声明为引用,从而以第一种方式执行。这种方法我目前想到的好处有一是保护了tbx文件(在发布的系统里面tbx文件会被编译成dll,从而保护了自定义模型的内部实现细节不被泄露),二是在不打开ArcGIS Desktop产品甚至不安装的情况就能了解该工具箱中包含哪些工具和模型,以及入参出参的情况。
添加的方法很简单,在Visual Studio集成开发环境菜单中,项目->Add ArcGIS ToolBox Reference,选中你需要的tbx文件,执行加载即可,然后的用法跟添加了既有的Geoprocessing Tools引用是一样的了。不过目前我遇到的问题是经常会出现加载不成功,提示有些工具不能加载,甚至是ArcGIS自带的那些tbx文件,但是还能用,这就比较诡异了,似乎是版本的问题,关于这个问题会继续追踪报道。

今天先写个开头,最近开始接触在开发中应用ArcToolBox中的工具箱。主要背景如下:
a. ArcGIS Desktop中的ArcToolBox提供了大量的工具用于地理数据的处理。(前两天ESRI中国用户大会中提到,9.4版本中将会有升级的功能替代ArcToolBox,大会上研发人员没有透露具体的细节。)
b. ArcGIS允许Desktop用户通过组合ArcToolBox自带的功能或是自己编写Python脚本创建自己的工具箱,通过Model Builder工具简单的拖拽这些工具箱中的工具完成空间分析建模的过程。
c. ArcEngine支持通过代码完成既有工具箱中工具的调用已经用户自定义工具箱和模型的调用。
项目里面有师兄是负责建立模型,另一个师兄负责在AE里面加载这些模型。地球人都知道的,AE的库不是太容易上手,开发参考资料也相对较少,鲜见好书,就着那个Engine Help for .NET就一招鲜吃遍天了。但是从头开始啃对初学者有点困难了(说着真别扭,其实自己也是个初学者),于是打算写点这方面东西的笔记,一方面找寻一些最佳实践,也方便将来自己复习。
软件平台基本情况如下,Windows XP SP3+Visual Studio 2005(C#语言)+ArcEngine 9.3+ArcInfo 9.3。
然后我目前的参考资料,即是上文中提到的Engine Help for .NET,装了ArcEngine就会自带的帮助系统,Building solutions with ArcGIS Engine using .NET总目录下三个地方有我们需要的相关内容,欢迎自行深入挖掘:
a. Working with ArcGIS componets->Geoprocessing
b. Tools->Overview of the ArcGIS Visual Studio Integration Framework->ArcGIS Toolbox Reference dialog box
c. ArcObjects library reference->Geoprocessor library and tool reference
OK,准备工作完成,先在Desktop里面找个ArcToolBox的工具练练手吧,比如说Data Mangement Tools -> Fields -> Add Field,给一个shp文件加个字段好了。然后来动手做第一个程序,理解一下执行的逻辑。
1 Geoprocessor [...]

RSS订阅

  •    Feedburner
  • feedsky   FeedSky

杜晓三,这是艺名儿。

厦门呆着,白石村村民。

觉着页面太窄了?上面有个Large可以点。


分类目录

所有文章

最新评论

  • 胸无大志 (4)
    • Spehio: @滚石头 研究所在厦门,第一年在北京是集中上课。
    • 滚石头: 来打声招呼~ 怎么去厦门了,工作了?
    • Spehio: @Noname 俄…这个怎么说,大学阶段小姑娘里面不是谈恋爱那种 的朋友里面最好的一个。
    • Noname: …怎么感觉你和这个人的关系很不一般…… 然后吧……你的右边这“北京呆着”……
  • 新上线维基小说和媒体库两个子站点 (4)
    • Spehio: @秦秦 那个主题就是那样的

我出没的地方

有来有往