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

 

posted @ 2019-11-07 09:38  the_path_of_grace  阅读(...)  评论(...编辑  收藏