显示标签为“GIS”的博文。显示所有博文
显示标签为“GIS”的博文。显示所有博文

2009年4月12日星期日

【原】SuperMapObjects中最短路径分析的bug

最近在对以前SuperMapObjects最短路径代码进行了改动,用了一个成员变量 CsoPoints m_objPoints保存了设施点,结果在测试中发现最短路径分析时,得到的结果老是错误,看起来貌似最后一个添加的设施点没有在分析中起作用。于是在函数内下断点跟踪,发现经过一次路径分析后,果然是少了一个点。但是第一次分析的结果都是正确的,如果再次进行分析,则结果就是错误的。当然解决办法也是有的,就是每次分析时,都构造一个临时的CsoPoints对象传进去,这样才能保证每次的结果都正确。

【原】如何给Facilities图层添加元素

这里所说的Facilities图层是指Closest Facility图层的子图层,就是设施点图层。我上次在做最短路径分析时,得到了Facilities图层的接口,但是不知道如何给它添加元素。因为ILayer实现了IFeatureClass的接口,所以很容易就获取到IFeatureClass接口,但是是不是直接就Create一个Feature然后添加、保存上去呢?打开ArcMap,先看看它的属性,有ObjectID、PosAlong、SourceID、SourceOID、SideOfEdge等等,在帮助文档里找到了注释:SourceID是网络数据集上所定位到的图元的源ID,可以从INetworkSource::ID获得此ID;SourceOID是定位到的图元的对象ID;SideOfEdge是指在边的左侧还是右侧;PosAlong是指定位到的图元沿边的距离。要是一个字段一个字段的去计算,然后再添加,累死你,所幸ArcEngine提供了一个方法QueryLocationByPoint,可以帮我们完成这件事。
它的接口如下:HRESULT QueryLocationByPoint(IPoint* point,INALocation** Location,IPoint** outPoint,double* distanceFromPoint);AE帮助上是这种说的,Using the input Point object, the method calls QueryLocationByPoint on each of its associated NALocatorAgent classes. The corresponding NALocation, the point where the location was found, and the distance from the input point to the source feature found are all returned.
下面是实现代码
ILayerPtr ipLayer = m_map.GetLayer(0);
INALayerPtr ipNaLayer = ipLayer;
INAContextPtr ipNaContext;
HRESULT hr = ipNaLayer->get_Context(&ipNaContext);
INAClassLoaderPtr ipNAClassLoader(CLSID_NAClassLoader);
INALocatorPtr ipNALocator = NULL;hr = ipNaContext->get_Locator(&ipNALocator);
hr = ipNAClassLoader->putref_Locator(ipNALocator);
IPointPtr ipPoint;INALocationPtr ipNALocation(CLSID_NALocation);
ipNAClassLoader->get_Locator(&ipNALocator);
IPointPtr ipOutPoint(CLSID_Point);
double dbLVal = 0.0;
ipNALocator->QueryLocationByPoint(ipPoint, &ipNALocation, &ipOutPoint, &dbLVal);

2009年3月29日星期日

【原】ArcGIS中最短路径的实现(二)

上次介绍了用几何网络实现的“最短路径”,姑且这么叫吧。这次我们用网络数据集实现真正的最短路径功能,跟上次一样,我们先准备数据。
  1. 先打开ArcCatalog,连接到目标文件夹,假定该文件下有一个名为road的道路图层。
  2. 在road图层上右键新建一个网络数据集,并按照其默认设置直至完成。
  3. 打开该地图的工作空间,把刚才新建的网络数据集添加工作空间中。
  4. 在网络分析菜单中选择新建最近设施点。

这时在工作空间里,可以看到多了一个名为“Closest Facility”的图层。它下面还有4个子图层,名字分别为“Facilities”,“Incidents”,“Barriers”,“Routes”。“Facilities”就是设施点图层,也就是目的点,“Incidents”的意思就是出发点,“Barriers”是障碍点,意思就是地图某条道路附近有一个障碍点,如果障碍点与道路距离在容限范围内,则表示此道路不通,“Routes”就是最终的结果。这样我们编程实现最短路径的思路就出现了:

  1. 添加出发点。
  2. 添加目的点。
  3. 生成最优路径,获取结果。

这里的添加出发点或者目的点,是往“Facilities”或“Incidents”图层上添加元素。获取结果也是从“Routes”中获取Polyline。往“Facilities”或“Incidents”图层上添加元素用到的主要方法是INALocator的QueryLocationByPoint函数,生成路径主要接口是INASolver和它的Solve方法。获取结果是按属性查找,因为“Routes”类其实就是一个图层类,只不过只是存在于内存,这个查找方法网上很多。

相关链接:ArcGIS中最短路径的实现(一)

2009年3月15日星期日

【原】ArcGIS中最短路径的实现(一)

最短路径分析属于ArcGIS的网络分析范畴。而ArcGIS的网络分析分为两类,分别是基于几何网络和网络数据集的网络分析。它们都可以实现最短路径功能。下面先介绍基于几何网络的最短路径分析的实现。以后会陆续介绍基于网络数据集的最短路径分析以及这两种方法的区别。

几何网络是一种特殊的特征要素类,由一系列不同类别的点要素和线要素(可以度量并能图形表达)组成的,可在FeatureDataset下面创建,可进行图形与属性的编辑。包括流向分析和追踪分析两大功能。主要接口是ITraceFlowSolver。我们先在一幅地图上做出一个几何网络才能进行最短路径分析。下面是主要的一些步骤(ArcMap帮助中琐碎的说明有三四十项,被我省略很多):



  1. 打开ArcCatalog,连接到包含地图的文件夹。

  2. 在空白处,右键新建一个“Personal GeoDatabase”。

  3. 在生成的Personal GeoDatabase上右键新建一个feature dataset。

  4. 双击Personal GeoDatabase进去,找到刚才new出的feature dataset,右键Import导入Feature Class(Single),选择要建立几何网络的图层或者shape文件。

  5. 然后再右键新建一个Geometric Network,选择从已存在的图元中建立几何网络。

  6. 打开ArcMap,把刚才建立的“Personal GeoDatabase Feature Class”添加到地图中,这样几何网络就建立好了。

这样我们就建立好一个几何网络了。我们现在要通过编程来实现最短路径,用到的接口主要有INetworkCollection,IGeometricNetwork,IPointToEID,ITraceFlowSolverGEN(它实现了ITraceFlowSolver的接口),INetSchema,IEIDHelper等。主要步骤如下:

  1. 获取几何网络工作空间
  2. 定义一个边线旗数组,把离点串最近的网络元素添加进数组
  3. 设置开始和结束边线的权重
  4. 进行路径分析
  5. 得到路径分析的结果

具体的程序太过繁琐、冗长了,这里不便贴出,可以打开这个链接查看源程序。http://www.cnblogs.com/3echo/archive/2008/01/24/865527.html

相关链接:ArcGIS中最短路径的实现(二)

2009年3月8日星期日

【原】AE之鹰眼的实现

大家都用过百度地图或者googole地图吧,在它们主地图的右下角,有个小地图窗口,这就是鹰眼窗口。用鼠标拖动鹰眼里的小窗口,则主地图便移动到相应的位置。下面就介绍鹰眼的实现。
鹰眼和主地图的互动,主要体现在两个方面:一是主地图的地图改变了,则鹰眼里的矩形框要移动到对应的位置,以指示当前地图在整个地图中的位置;二是鹰眼的矩形框移动了,则主地图中显示的地图要移动到相应的位置。
AE中显示地图的控件叫 ESRI MapControl,这里主要用到了它的OnAfterDraw事件。在主地图的OnAfterDraw事件中,根据当前地图的大小,改变鹰眼中矩形框的大小;在鹰眼的OnAfterDraw事件中,根据矩形框的位置,确定主地图中地图的位置。google地图的鹰眼还实现了矩形框的拖动,这个也很好实现,呵呵。在鼠标点击到鹰眼控件时,先判断是否在矩形框内,如果在的话,用一个状态量记住这个状态,此时如果鼠标移动,则矩形框跟着相应的移动;若不在矩形框内,则矩形框移动到鼠标点击的位置。