using System; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Geometry; using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.NetworkAnalysis;
namespace GisEditor { /// <summary> /// 最短路徑分析 /// </summary> public class ClsPathFinder { private IGeometricNetwork m_ipGeometricNetwork; private IMap m_ipMap; private IPointCollection m_ipPoints; private IPointToEID m_ipPointToEID; private double m_dblPathCost =0; private IEnumNetEID m_ipEnumNetEID_Junctions; private IEnumNetEID m_ipEnumNetEID_Edges; private IPolyline m_ipPolyline;
#region Public Function //返回和設置當前地圖 public IMap SetOrGetMap { set{ m_ipMap = value;} get{return m_ipMap;} } //打開幾何數據集的網絡工作空間 public void OpenFeatureDatasetNetwork(IFeatureDataset FeatureDataset) { CloseWorkspace(); if (!InitializeNetworkAndMap(FeatureDataset)) Console.WriteLine( "打開network出錯"); } //輸入點的集合 public IPointCollection StopPoints { set{m_ipPoints= value;} get{return m_ipPoints;} } //路徑成本 public double PathCost { get {return m_dblPathCost;} } //返回路徑的幾何體 public IPolyline PathPolyLine() { IEIDInfo ipEIDInfo; IGeometry ipGeometry; if(m_ipPolyline!=null)return m_ipPolyline; m_ipPolyline = new PolylineClass(); IGeometryCollection ipNewGeometryColl = m_ipPolyline as IGeometryCollection; ISpatialReference ipSpatialReference = m_ipMap.SpatialReference; IEIDHelper ipEIDHelper = new EIDHelperClass(); ipEIDHelper.GeometricNetwork = m_ipGeometricNetwork; ipEIDHelper.OutputSpatialReference = ipSpatialReference; ipEIDHelper.ReturnGeometries = true;
IEnumEIDInfo ipEnumEIDInfo = ipEIDHelper.CreateEnumEIDInfo(m_ipEnumNetEID_Edges); int count = ipEnumEIDInfo.Count; ipEnumEIDInfo.Reset(); for(int i =0;i<count;i++) { ipEIDInfo = ipEnumEIDInfo.Next(); ipGeometry = ipEIDInfo.Geometry; ipNewGeometryColl.AddGeometryCollection( ipGeometry as IGeometryCollection); } return m_ipPolyline; } //解決路徑 public void SolvePath(string WeightName) { try { int intEdgeUserClassID; int intEdgeUserID; int intEdgeUserSubID; int intEdgeID; IPoint ipFoundEdgePoint; double dblEdgePercent; /*PutEdgeOrigins方法的第二個參數要求是IEdgeFlag類型的數組, * 在VB等其他語言的代碼中,只需傳人該類型數組的第一個元素即 * 可,但C#中的機制有所不同,需要作出如下修改:使用 * ITraceFlowSolverGEN替代ITraceFlowSolver */ ITraceFlowSolverGEN ipTraceFlowSolver = new TraceFlowSolverClass() as ITraceFlowSolverGEN; INetSolver ipNetSolver = ipTraceFlowSolver as INetSolver; INetwork ipNetwork = m_ipGeometricNetwork.Network; ipNetSolver.SourceNetwork = ipNetwork; INetElements ipNetElements = ipNetwork as INetElements; int intCount = m_ipPoints.PointCount; //定義一個邊線旗數組 IEdgeFlag[] pEdgeFlagList = new EdgeFlagClass[intCount]; for(int i = 0;i<intCount ;i++) { INetFlag ipNetFlag = new EdgeFlagClass()as INetFlag; IPoint ipEdgePoint = m_ipPoints.get_Point(i); //查找輸入點的最近的邊線 m_ipPointToEID.GetNearestEdge(ipEdgePoint, out intEdgeID,out ipFoundEdgePoint, out dblEdgePercent); ipNetElements.QueryIDs( intEdgeID, esriElementType.esriETEdge, out intEdgeUserClassID, out intEdgeUserID,out intEdgeUserSubID); ipNetFlag.UserClassID = intEdgeUserClassID; ipNetFlag.UserID = intEdgeUserID; ipNetFlag.UserSubID = intEdgeUserSubID; IEdgeFlag pTemp = (IEdgeFlag)(ipNetFlag as IEdgeFlag); pEdgeFlagList[i]=pTemp; } ipTraceFlowSolver.PutEdgeOrigins(ref pEdgeFlagList); INetSchema ipNetSchema = ipNetwork as INetSchema; INetWeight ipNetWeight = ipNetSchema.get_WeightByName(WeightName);
INetSolverWeights ipNetSolverWeights = ipTraceFlowSolver as INetSolverWeights; ipNetSolverWeights.FromToEdgeWeight = ipNetWeight;//開始邊線的權重 ipNetSolverWeights.ToFromEdgeWeight = ipNetWeight;//終止邊線的權重 object [] vaRes =new object[intCount-1]; //通過findpath得到邊線和交匯點的集合 ipTraceFlowSolver.FindPath(esriFlowMethod.esriFMConnected, esriShortestPathObjFn.esriSPObjFnMinSum, out m_ipEnumNetEID_Junctions,out m_ipEnumNetEID_Edges, intCount-1, ref vaRes); //計算元素成本 m_dblPathCost = 0; for (int i =0;i<vaRes.Length;i++) { double m_Va =(double) vaRes[i]; m_dblPathCost = m_dblPathCost + m_Va; } m_ipPolyline = null; } catch(Exception ex) { Console.WriteLine(ex.Message); } } #endregion
#region Private Function //初始化幾何網絡和地圖 private bool InitializeNetworkAndMap(IFeatureDataset FeatureDataset) { IFeatureClassContainer ipFeatureClassContainer; IFeatureClass ipFeatureClass ; IGeoDataset ipGeoDataset; ILayer ipLayer ; IFeatureLayer ipFeatureLayer; IEnvelope ipEnvelope, ipMaxEnvelope ; double dblSearchTol;
INetworkCollection ipNetworkCollection = FeatureDataset as INetworkCollection; int count = ipNetworkCollection.GeometricNetworkCount; //獲取第一個幾何網絡工作空間 m_ipGeometricNetwork = ipNetworkCollection.get_GeometricNetwork(0); INetwork ipNetwork = m_ipGeometricNetwork.Network;
if(m_ipMap!=null) { m_ipMap = new MapClass(); ipFeatureClassContainer = m_ipGeometricNetwork as IFeatureClassContainer; count = ipFeatureClassContainer.ClassCount; for(int i =0;i<count;i++) { ipFeatureClass = ipFeatureClassContainer.get_Class(i); ipFeatureLayer = new FeatureLayerClass(); ipFeatureLayer.FeatureClass = ipFeatureClass; m_ipMap.AddLayer( ipFeatureLayer); } } count = m_ipMap.LayerCount; ipMaxEnvelope = new EnvelopeClass(); for(int i =0;i<count;i++) { ipLayer = m_ipMap.get_Layer(i); ipFeatureLayer = ipLayer as IFeatureLayer; ipGeoDataset = ipFeatureLayer as IGeoDataset; ipEnvelope = ipGeoDataset.Extent; ipMaxEnvelope.Union( ipEnvelope); }
m_ipPointToEID = new PointToEIDClass(); m_ipPointToEID.SourceMap = m_ipMap; m_ipPointToEID.GeometricNetwork = m_ipGeometricNetwork;
double dblWidth = ipMaxEnvelope.Width; double dblHeight = ipMaxEnvelope.Height;
if( dblWidth > dblHeight) dblSearchTol = dblWidth / 100; else dblSearchTol = dblHeight / 100; m_ipPointToEID.SnapTolerance = dblSearchTol;
return true ;
} //關閉工作空間 private void CloseWorkspace() { m_ipGeometricNetwork = null; m_ipPoints = null; m_ipPointToEID = null; m_ipEnumNetEID_Junctions = null; m_ipEnumNetEID_Edges = null; m_ipPolyline = null; } #endregion } }
備註:
在調用該類時的次序:
ClsPathFinder m_ipPathFinder;
if(m_ipPathFinder==null)//打開幾何網絡工作空間 { m_ipPathFinder = new ClsPathFinder(); ipMap = this.m_ActiveView.FocusMap; ipLayer = ipMap.get_Layer(0); ipFeatureLayer = ipLayer as IFeatureLayer; ipFDB = ipFeatureLayer.FeatureClass.FeatureDataset; m_ipPathFinder.SetOrGetMap = ipMap; m_ipPathFinder.OpenFeatureDatasetNetwork(ipFDB); }
private void ViewMap_OnMouseDown(object sender, ESRI.ArcGIS.MapControl.IMapControlEvents2_OnMouseDownEvent e)//獲取地圖上鼠標輸入的點 { IPoint ipNew ; if( m_ipPoints==null) { m_ipPoints = new MultipointClass(); m_ipPathFinder.StopPoints = m_ipPoints; } ipNew = ViewMap.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x,e.y); object o = Type.Missing; m_ipPoints.AddPoint(ipNew,ref o,ref o); }
m_ipPathFinder.SolvePath("Weight");//先解析路徑
IPolyline ipPolyResult = m_ipPathFinder.PathPolyLine();//最後返回最短路徑
|