1. 程式人生 > >關於如何根據幾何網路進行爆管分析

關於如何根據幾何網路進行爆管分析

我的QQ是:732344647,加我記得寫備註~

之前寫過一篇關於如何建立集合網路流向的文章:如何建立幾何網路流向,在這篇文章之中只是介紹如何建立流向,並沒有介紹如何實現爆管分析的功能,我在網上也沒百度谷歌出相關程式碼(應該有我沒有找到吧),所以自己研究出來了,今天就分享給大家,並感謝給我找相關文獻的同門們以及那些分享經驗的大神們(本文實現程式碼並沒有根據流向來找到閥門,而是找到所有的相連,但是整體的實現思路不會錯,如果你需要根據流向來實現搜尋,還需要將流向設定好了以後進一步判斷,參考API以後相信根據本文你可以進一步完善)。

———————————————————————————————————————-


首先,我並不會將所有的程式碼都寫出來,但是會介紹最關鍵的流程與主要程式碼。
1–找到目標資料的幾何網路。因為我們是在這個資料基礎上進行分析的,就是QI到這個介面INetworkCollection,通過ArcGIS API的幫助文件,我們可以發現類FeatureDataset實現了這個介面,所以思路就是從操作的圖層之中盡享QI轉換過去就可以了;

iFeatureLayer = iLayer as IFeatureLayer;
iFeatureDataset = iFeaLayer.FeatureClass.FeatureDataset;
iNetCollec = iDataset as INetworkCollection;

2-找到Edge邊。因為爆管分析是我們需要先選中我們確定的已經的爆管的管道,所以需要根據滑鼠點選資料找到那條邊;這裡主要用到了IPointToEID介面的GetNearestEdge方法獲取到當前的爆管位置
3-找到Edge首末節點。根據第二步找到Edge以後得到的是該邊的EID,在幾何網路之中會根據Feature重新生成一個EID對應每個要素;所以我們可以使用INetTopologyEditGEN介面的GetFromToJunctionEIDs方法找到首末節點的EID
4–判斷首末節點是否為閥門(爆管分析就是要關閉連通的閥門),如果是閥門,那麼這個節點相連的邊線就不用繼續搜尋了,否則根據該節點的EID繼續往下搜尋所有相連的邊線Edges;這裡我們使用佇列Enqueue資料結構來處理節點EID,所有檢索到的非節點的EID全部儲存在佇列之中,因為佇列是先進先出的,而且出列的同時會返回該出列值,適用於當前的資料結構,而檢索到的所有Edges全部儲存在字典Dictionary之中,其中Key是連線節點,而Value是與該點連線Edges;這樣,當我們從佇列中取出非閥門節點的EID的時候就可以去字典中找到相連的Edge,然後根據這條連線邊繼續尋找節點,直到佇列為空為止。
這一步相對較為複雜,所以會將所有程式碼全部貢獻出來

while (true)
                {
                    dictionary.Clear();
                    //判斷2個起始節點是否為閥門
                    if (IsWaterValue(fromFuncEID, iGeoNetwork) && IsWaterValue(toFuncEID, iGeoNetwork))//首尾皆為閥門
                    {
g_WaterValues.Add(GetFeatureByEID(fromFuncEID, iGeoNetwork));                    g_WaterValues.Add(GetFeatureByEID(toFuncEID, iGeoNetwork));
                        break;//跳出
                    }
                    else if (IsWaterValue(fromFuncEID, iGeoNetwork) && !IsWaterValue(toFuncEID, iGeoNetwork))//起點是閥門
                    {
                        g_WaterValues.Add(GetFeatureByEID(fromFuncEID, iGeoNetwork));
                        juncQueue.Enqueue(toFuncEID);
                        dictionary.Add(toFuncEID, nearestEdgeEID);
                    }
                    else if (!IsWaterValue(fromFuncEID, iGeoNetwork) && IsWaterValue(toFuncEID, iGeoNetwork))//終點是閥門
                    {
                        g_WaterValues.Add(GetFeatureByEID(toFuncEID, iGeoNetwork));
                        juncQueue.Enqueue(fromFuncEID);
                        dictionary.Add(fromFuncEID, nearestEdgeEID);
                    }
                    else//都不是閥門
                    {
                        juncQueue.Enqueue(fromFuncEID);
                        juncQueue.Enqueue(toFuncEID);
                        dictionary.Add(fromFuncEID, nearestEdgeEID);
                        dictionary.Add(toFuncEID, nearestEdgeEID);
                    }

                    IForwardStarGEN iForwardStarGEN = iGeoNetwork.Network.CreateForwardStar(true, null, null, null, null) as IForwardStarGEN;//這個介面主要負責根據EID查詢連通的要素EID
                    while (juncQueue.Count != 0)//判斷佇列是否為空,遞迴...
                    {
                        int adgacentEdgesCount = 0;//指定的搜尋節點連線的除源edge以外的鄰接邊線個數
                        int eid = (int)juncQueue.Dequeue();//佇列移除eid並獲取eid

                        iForwardStarGEN.FindAdjacent(dictionary[eid], eid, out adgacentEdgesCount);//首次判斷使用起始邊線作為輸入引數
                        if (adgacentEdgesCount != 0)//如果鄰接線為0
                        {
                            int[] refEdgesEIDs = new int[adgacentEdgesCount];//查詢到的邊線集合
                            bool[] refReverseOrirntation = new bool[adgacentEdgesCount];//預設為false
                            object[] refWeightValue = new object[adgacentEdgesCount];
                            iForwardStarGEN.QueryAdjacentEdges(ref refEdgesEIDs, ref refReverseOrirntation, ref refWeightValue);//獲得與指定節點的邊線EID集合
                            //遍歷邊線集合
                            for (int i = 0; i < refEdgesEIDs.Length; i++)
                            {
                                int adgacentJunc;
                                object weight;
                                iForwardStarGEN.QueryAdjacentJunction(i, out adgacentJunc, out weight);
                                //判斷這個輸出的節點EID是否為閥門
                                if (IsWaterValue(adgacentJunc, iGeoNetwork))
                                {//如果是閥門加入到集合中
                                    g_WaterValues.Add(GetFeatureByEID(adgacentJunc, iGeoNetwork));
                                }
                                else
                                {
                                    if (!dictionary.ContainsKey(adgacentJunc))//因為沒有設定流向,所以是雙向查詢,所以要判斷是否已經查過了
                                    {
                                        dictionary.Add(adgacentJunc, refEdgesEIDs[i]); //成對新增到字典中去
                                        juncQueue.Enqueue(adgacentJunc);//如果不是閥門,那麼將該節點加入到佇列中去
                                    }
                                }
                            }
                        }
                    }
                    //最後需要break
                    break;
                }

———————————————————————————————————————-
這就是主要的流程邏輯與程式碼了,希望可以幫到大家,另外有什麼不足之處請大家不吝指教!