zoukankan      html  css  js  c++  java
  • ArcGIS Engine空间分析之拓扑分析的实现

    简单介绍:

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

    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二次开发,如果有不对的地方,请多多包涵!

     

  • 相关阅读:
    C#通过“委托和事件”的方式实现进程监控并与“普通方式”对比
    SharePoint自动化系列——通过PowerShell创建SharePoint Web
    SharePoint自动化系列——通过PowerShell创建SharePoint Site Collection
    IE11不支持Selenium 2.0的解决方法
    C#中WebBrowser控件的使用
    SharePoint自动化系列——Solution auto-redeploy using Selenium(C#)
    多进程监控自动关机工具升级远程关闭多台server——C# works with PowerShell
    通过Windows PowerShell远程管理计算机(精简版)
    .NET项目web自动化测试实战——Selenium 2.0
    HP LoadRunner 12.02 Tutorial T7177-88037教程独家中文版
  • 原文地址:https://www.cnblogs.com/edcoder/p/11808555.html
Copyright © 2011-2022 走看看