ArcGIS Engine空間分析之拓撲分析的實現

簡單介紹:html

拓撲學是一門研究幾何圖形位置關係的科學。網絡

GIS所關注的拓撲主要集中在拓撲關係——存在於地理實體間的拓撲關係函數

拓撲關係在GIS中起着描述兩個地理實體的相對空間位置的重要做用。它是GIS空間實體之間最重要的關係之一,在GIS空間數據建模、空間查詢、空間分析、空間推理、製圖綜合等過程當中起着重要的做用。拓撲關係對GIS具備如下重要意義
(1)不須要利用座標或者計算距離,可以清楚地反映某一要素與另外一要素的空間位置關係。
(2)某些空間分析功能是基於拓撲關係而實現的。例如,要求某條河流的流域面積、流經的城市,查詢有哪些國家與某個國家相鄰等等。
(3)在進行某些空間分析以前必須檢查數據的拓撲關係的合理性。這樣的空間分析功能有計算最佳路徑、緩衝分析、裁剪、創建封閉多邊形等。post

拓撲元素是拓撲關係的描述單元。this

GeoDatabase數據模型包括通常性的常見3類要素類:點狀要素類、線狀要素類和麪狀要素類。url

在二維空間中,它們分別對應的是3種拓撲元素,即結點、弧和麪域(多邊形)。spa

拓撲關係是不考慮度量和方向的空間實體之間的空間關係,它講究的是拓撲元素彼此間的相對位置關係。3d

拓撲鄰接、拓撲關聯、拓撲包含是三種最基本的拓撲關係。指針

 

最終效果圖:code

 

對於拓撲分析,其思路能夠歸納以下:

①建立拓撲數據集

②設置拓撲參數(拓撲規則)

③檢查拓撲錯誤

④顯示拓撲結果

 

①建立拓撲數據集

/// <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二次開發,若是有不對的地方,請多多包涵!

相關文章
相關標籤/搜索