ArcGIS Engine空间分析之拓扑分析的实现

  • 2019 年 11 月 7 日
  • 筆記

简单介绍:

拓扑学是一门研究几何图形位置关系的科学。

GIS所关注的拓扑主要集中在拓扑关系——存在于地理实体间的拓扑关系

拓扑关系在GIS中起着描述两个地理实体的相对空间位置的重要作用。它是GIS空间实体之间最重要的关系之一,在GIS空间数据建模、空间查询、空间分析、空间推理、制图综合等过程中起着重要的作用。拓扑关系对GIS具有以下重要意义
(1)不需要利用坐标或者计算距离,能够清楚地反映某一要素与另一要素的空间位置关系。
(2)某些空间分析功能是基于拓扑关系而实现的。例如,要求某条河流的流域面积、流经的城市,查询有哪些国家与某个国家相邻等等。
(3)在进行某些空间分析之前必须检查数据的拓扑关系的合理性。这样的空间分析功能有计算最佳路径、缓冲分析、裁剪、建立封闭多边形等。

拓扑元素是拓扑关系的描述单元。

GeoDatabase数据模型包括一般性的常见3类要素类:点状要素类、线状要素类和面状要素类。

在二维空间中,它们分别对应的是3种拓扑元素,即结点、弧和面域(多边形)。

拓扑关系是不考虑度量和方向的空间实体之间的空间关系,它讲究的是拓扑元素彼此间的相对位置关系。

拓扑邻接、拓扑关联、拓扑包含是三种最基本的拓扑关系。

 

最终效果图:

 

对于拓扑分析,其思路可以概括如下:

①创建拓扑数据集

②设置拓扑参数(拓扑规则)

③检查拓扑错误

④显示拓扑结果

 

①创建拓扑数据集

/// <summary>  /// 创建拓扑数据集  /// </summary>  /// <param name="sender"></param>  /// <param name="e"></param>  private void btnCreateTopo_Click(object sender, EventArgs e)  {      //设置指针处于等待状      this.Cursor = Cursors.WaitCursor;      //创建拓扑数据集(前提是要素集内没有数据集)      Global.GlobalTopology = create_topology(Global.pWorkSpace, "Road_Analysis", "Topology_Dataset");      //如果Flag为true则打开      if (Flag)      {          //打开拓扑数据集          Global.GlobalTopology = OpenToplogyFromFeatureWorkspace((IFeatureWorkspace)Global.pWorkSpace, "Road_Analysis", "Topology_Dataset");          //Flag为true表示已经存在拓扑数据集          MessageBox.Show("已经存在拓扑数据集");          //设置指针为默认状态          this.Cursor = Cursors.Default;          //返回          return;      }      //创建要素类      IFeatureClass pTempFt = null;      //向拓扑数据集中添加拓扑元素,可以添加多个      AddSingleElement(Global.GlobalTopology, "Road_Analysis", "南宁路网", out pTempFt);      //添加单个要素的拓扑规则, 相同图层内的先不能相交      AddRuleToTopology(Global.GlobalTopology, esriTopologyRuleType.esriTRTLineNoIntersection, "NoIntersection", pTempFt);      //Global.GlobalTopology将强转为IGeoDataset获得Extent      IGeoDataset GDS = Global.GlobalTopology as IGeoDataset;      //调用自定义方法添加拓扑规则      ValidateTopology(Global.GlobalTopology, GDS.Extent);      MessageBox.Show("拓扑数据集创建成功!");      this.Cursor = Cursors.Default;  }

 一些参数:

/// <summary>  /// 判断拓扑数据集是否存在,true表示存在拓扑数据集,false表示拓扑数据集为空  /// </summary>  private bool Flag = false;

class Global  {      public static string GdbPath = Application.StartupPath + @"网络分析网络分析.mdb";      public static IWorkspace pWorkSpace;      public static ITopology GlobalTopology;  }

 

 

 

 

  如果要创建拓扑数据集,调用create_topology函数

/// <summary>  /// 创建拓扑数据集(前提是要素集内没有数据集)  /// </summary>  /// <param name="myWSp">工作空间</param>  /// <param name="FtDSName">要素集名称</param>  /// <param name="TopologyName">拓扑数据集名</param>  /// <returns></returns>  public ITopology create_topology(IWorkspace myWSp, string FtDSName, string TopologyName)  {      //实例化拓扑为null      ITopology myTopology = null;      try      {          //将工作空间强转成要素工作空间          IFeatureWorkspace pFtWsp = myWSp as IFeatureWorkspace;          //通过要素工作空间打开名字为"FtDSName"的要素数据集          IFeatureDataset myFDS = pFtWsp.OpenFeatureDataset(FtDSName);          //将要素数据集放在要素类容器中          IFeatureClassContainer myFCContainer = myFDS as IFeatureClassContainer;          //将要素类容器强转成拓扑容器          ITopologyContainer myTopologyContainer = myFDS as ITopologyContainer;          //通过拓扑容器创建一个新的拓扑          myTopology = myTopologyContainer.CreateTopology(TopologyName, myTopologyContainer.DefaultClusterTolerance, -1, "");      }      catch (Exception ee)      {          //MessageBox.Show(ee.Message);          //如果拓扑已经存在,则将Flag变为true          Flag = true;          //返回null          return null;      }      //返回创建的myTopology      return myTopology;    }

注:如果创建拓扑出现问题,请参考【已解决】ArcGIS Engine无法创建拓扑的问题(CreateTopology)

 如果拓扑数据集已经存在,调用OpenToplogyFromFeatureWorkspace函数

/// <summary>  /// 打开拓扑数据集(如果拓扑数据集已经创建)  /// </summary>  /// <param name="featureWorkspace">工作空间</param>  /// <param name="featureDatasetName">普通数据集</param>  /// <param name="topologyName">拓扑集名</param>  /// <returns>返回拓扑数据集</returns>  private ITopology OpenToplogyFromFeatureWorkspace(IFeatureWorkspace featureWorkspace, string featureDatasetName, string topologyName)  {      //打开特征数据集      IFeatureDataset featureDataset = featureWorkspace.OpenFeatureDataset(featureDatasetName);      //将featureDataset转换为ITopologyContainer      ITopologyContainer topologyContainer = (ITopologyContainer)featureDataset;      //ITopology get_TopologyByName(string Name);      //打开拓扑      ITopology topology = topologyContainer.get_TopologyByName(topologyName);      //返回拓扑      return topology;  }

 

②设置拓扑参数(拓扑规则)

 

//向拓扑数据集中添加拓扑元素,可以添加多个  AddSingleElement(Global.GlobalTopology, "Road_Analysis", "南宁路网", out pTempFt);

 

/// <summary>  /// 向拓扑数据集中添加拓扑元素  /// </summary>  /// <param name="myTopology">拓扑数据集</param>  /// <param name="DSName">数据集名</param>  /// <param name="FtName">要素名</param>  /// <param name="pFtClass">输出参与拓扑的单个元素</param>  private void AddSingleElement(ITopology myTopology, string DSName, string FtName, out IFeatureClass pFtClass)  {      //打开工作空间      IFeatureWorkspace pFtWsp = Global.pWorkSpace as IFeatureWorkspace;      //打开数据集      IFeatureDataset myFDS = pFtWsp.OpenFeatureDataset(DSName);      //在数据集中打开要素      IFeatureClassContainer myFCContainer = myFDS as IFeatureClassContainer;      IFeatureClass pTempFt = myFCContainer.get_ClassByName(FtName);      pFtClass = pTempFt;      //调用ITopology.AddClass方法添加要素      myTopology.AddClass(pTempFt, 5, 1, 1, false);  }

 

 

//添加单个要素的拓扑规则, 相同图层内的先不能相交  AddRuleToTopology(Global.GlobalTopology, esriTopologyRuleType.esriTRTLineNoIntersection, "NoIntersection", pTempFt);

 

/// <summary>  /// 添加单个要素的拓扑规则  /// </summary>  /// <param name="topology">拓扑数据集</param>  /// <param name="ruleType">拓扑规则</param>  /// <param name="ruleName">规则名称</param>  /// <param name="featureClass">参与制定规则的要素</param>  private void AddRuleToTopology(ITopology topology, esriTopologyRuleType ruleType, string ruleName, IFeatureClass featureClass)  {      //实例化拓扑规则      ITopologyRule topologyRule = new TopologyRuleClass();      //拓扑规则      topologyRule.TopologyRuleType = ruleType;      //规则名称      topologyRule.Name = ruleName;      //规则面向的要素类      topologyRule.OriginClassID = featureClass.FeatureClassID;      topologyRule.AllOriginSubtypes = true;      ITopologyRuleContainer topologyRuleContainer = (ITopologyRuleContainer)topology;      if (topologyRuleContainer.get_CanAddRule(topologyRule))      {          //调用.AddRule方法添加规则          topologyRuleContainer.AddRule(topologyRule);      }      else      {          MessageBox.Show("规则添加失败, 不适用于拓扑集");      }  }

 

③检查拓扑错误

 

//验证拓扑错误  ValidateTopology(Global.GlobalTopology, GDS.Extent);

 

/// <summary>  /// 验证拓扑错误  /// </summary>  /// <param name="topology">拓扑集</param>  /// <param name="envelope">t拓扑集的Extent</param>  private void ValidateTopology(ITopology topology, IEnvelope envelope)  {      //实例化一个Polygon存储Topology的Extent      IPolygon localPolygon = new PolygonClass();      //获取Topology的外接矩形      ISegmentCollection segmentCollection = (ISegmentCollection)localPolygon;      segmentCollection.SetRectangle(envelope);      //赋值Topology的阴影区域      IPolygon polygon = topology.get_DirtyArea(localPolygon);      if (!polygon.IsEmpty)      {          //赋值参数并Validate拓扑错误          IEnvelope areaToValidate = polygon.Envelope;          IEnvelope areaValidated = topology.ValidateTopology(areaToValidate);      }  }

 

④显示拓扑结果

 

 

/// <summary>  /// 显示拓扑结果  /// </summary>  /// <param name="sender"></param>  /// <param name="e"></param>  private void btnDisplayTopo_Click(object sender, EventArgs e)  {      //防止没有拓扑而创建图层对象      if(Flag)      {          //设置指针处于等待状          this.Cursor = Cursors.WaitCursor;          //新建一个拓扑图层          ITopologyLayer pTpLayer = new TopologyLayerClass();          //将Global.GlobalTopology赋值给当前的拓扑图层的拓扑          pTpLayer.Topology = Global.GlobalTopology;          //拓扑图层强转成图层          ILayer pLayer = (ILayer)pTpLayer;          //将图层名字命名为"Topology_Dataset"          pLayer.Name = "Topology_Dataset";          //将图层加到axMapControl1上          axMapControl1.AddLayer(pLayer);          //设置指针为默认状态          this.Cursor = Cursors.Default;      }    }

 

总结:

 

 

谢谢观看!本人初学GIS二次开发,如果有不对的地方,请多多包涵!