- #region A_STAR
- public IRgbColor getRGB(int r,int g,int b)//用于获取颜色
- {
- IRgbColor pColor;
- pColor = new RgbColorClass();
- pColor.Red = r;
- pColor.Green = g;
- pColor.Blue = b;
- return pColor;
- }
- //定义路网中的边信息
- public class Edge
- {
- public string EdgeFID;
- public string StartNodeID;
- public string EndNodeID;
- public double Weight; //权值,代价
- }
- //定义路网中的点信息
- public class NETA_Point
- {
- private string pointID;
- private double fn;
- private double gn;
- private double hn;
- private bool isEnabled;
- private PointAnalyseState analyseState;
- private double x;
- private double y;
- //定义父结点
- private NETA_Point parentPoint;
- private ArrayList edgeList;//Edge的集合--出边表
- public NETA_Point()
- {
- }
- //构造函数初始化
- public NETA_Point(string id)
- {
- this.pointID = id;
- this.fn = 0;
- this.gn = 0;
- this.hn = 0;
- this.isEnabled = true;
- this.analyseState = PointAnalyseState.Undisposed;
- this.x = 0;
- this.y = 0;
- this.parentPoint = new NETA_Point();
- this.edgeList = new ArrayList();
- }
- #region property
- public string PointID
- {
- get
- {
- return this.pointID;
- }
- }
- public double Fn
- {
- get
- {
- return this.fn;
- }
- set
- {
- this.fn = value;
- }
- }
- public double Gn
- {
- get
- {
- return this.gn;
- }
- set
- {
- this.gn = value;
- }
- }
- public double Hn
- {
- get
- {
- return this.hn;
- }
- set
- {
- this.hn = value;
- }
- }
- public double X
- {
- get
- {
- return this.x;
- }
- set
- {
- this.x = value;
- }
- }
- public double Y
- {
- get
- {
- return this.y;
- }
- set
- {
- this.y = value;
- }
- }
- public PointAnalyseState AnalyseState
- {
- get
- {
- return this.analyseState;
- }
- set
- {
- this.analyseState = value;
- }
- }
- public bool IsEnabled
- {
- get
- {
- return this.isEnabled;
- }
- }
- public NETA_Point ParentPoint
- {
- get
- {
- return this.parentPoint;
- }
- set
- {
- this.parentPoint = value;
- }
- }
- public ArrayList EdgeList
- {
- get
- {
- return this.edgeList;
- }
- }
- #endregion
- }
- public enum PointAnalyseState
- {
- InOpenList,
- InCloseList,
- Undisposed
- }
- private void printPath(ArrayList strPath) //显示线路
- {
- IMap pMap = axMapControl1.Map;
- IActiveView pActiveView = pMap as IActiveView;
- IFeatureLayer pFeatureLayer = pMap.get_Layer(1) as IFeatureLayer;
- IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass;
- IQueryFilter pQueryFilter = new QueryFilterClass();
- ISimpleLineSymbol pLineSymbol = new SimpleLineSymbolClass();
- pLineSymbol.Color = getRGB(100, 100, 255);
- pLineSymbol.Style = esriSimpleLineStyle.esriSLSSolid;
- pLineSymbol.Width = 3;
- foreach (string s in strPath)
- {
- pQueryFilter.WhereClause = "FID_1=" + s + "";
- IFeatureCursor pCursor = pFeatureClass.Search(pQueryFilter, false);
- IFeature pFeature = pCursor.NextFeature();
- IPolyline pPolyline = pFeature.Shape as IPolyline;
- ILineElement pLineElement = new LineElementClass();
- IElement m_Element;
- m_Element = pLineElement as IElement;
- m_Element.Geometry = pPolyline;
- pLineElement.Symbol = pLineSymbol;
- IGraphicsContainer pgc = pMap as IGraphicsContainer;
- pgc.AddElement(pLineElement as IElement, 0);
- }
- pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
- }
- private void printPath2(ArrayList strPath)//利用选择集
- {
- IMap pMap = axMapControl1.Map;
- IActiveView pActiveView = pMap as IActiveView;
- IFeatureLayer pFeatLayer = pMap.get_Layer(1) as IFeatureLayer;
- IQueryFilter pQueryFilter = new QueryFilterClass();
- IFeatureClass pFeatClass = pFeatLayer.FeatureClass;
- foreach (string pathName in strPath)
- {
- pQueryFilter.WhereClause = "FID_1 =" + pathName + "";
- IFeatureCursor pFeatCursor = pFeatClass.Search(pQueryFilter, false);
- IFeature pFeat = pFeatCursor.NextFeature();
- pMap.SelectFeature(pFeatLayer, pFeat);
- }
- pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, null, null);
- }
- #region 二叉堆数据结构,用于OpenList结构
- //针对A*算法设计的二叉堆结构,用于OpenList结构
- //KeyID对应PtID,所以唯一
- //Fn可能重复
- //按Fn维护堆结构
- //zhb 2008.11.4
- public class BinaryHeapItem
- {
- public Double Fn;
- public string KeyID;
- }
- //二叉堆接口定义
- public interface iNETA_BinaryHeapM
- {
- bool AddItem(BinaryHeapItem Item);
- bool MinishItemFnValue(string KeyID, Double NewFn);//A*应用中只会减小Fn
- BinaryHeapItem GetAndRemoveMinFnItem();
- void Clear();
- int ItemCount { get;}
- }
- //Singleton二叉堆接口的函数实现
- public class NETA_BinaryHeap : iNETA_BinaryHeapM
- {
- public static readonly NETA_BinaryHeap NETA_BinaryHeapInstance = new NETA_BinaryHeap();
- private System.Collections.Hashtable BinaryHeap = new System.Collections.Hashtable();
- private NETA_BinaryHeap() { }
- #region iNETA_BinaryHeapM 成员
- #region AddItem增加新成员
- public bool AddItem(BinaryHeapItem Item)
- {
- try
- {
- if (BinaryHeap.Count == 0)
- BinaryHeap.Add(1, Item);
- else
- {
- BinaryHeap.Add(BinaryHeap.Count + 1, Item);
- int index = BinaryHeap.Count;
- int temp;
- double temp1;
- BinaryHeapItem tempItem;
- bool isOK = false;
- while (!isOK)
- {
- temp1 = index / 2;
- temp = (int)System.Math.Floor(temp1);
- if (temp <= 0) break;
- if (((BinaryHeapItem)BinaryHeap[temp]).Fn > ((BinaryHeapItem)BinaryHeap[index]).Fn)
- {
- tempItem = (BinaryHeapItem)BinaryHeap[temp];
- BinaryHeap[temp] = (BinaryHeapItem)BinaryHeap[index];
- BinaryHeap[index] = tempItem;
- index = temp;
- }
- else
- isOK = true;
- }
- }
- return true;
- }
- catch (Exception e)
- {
- MessageBox.Show("NETA_BinaryHeap.AddItem错误" + e.Message);
- return false;
- }
- }
- #endregion
- //删除成员,并返回最小值
- public BinaryHeapItem GetAndRemoveMinFnItem()
- {
- try
- {
- if (BinaryHeap.ContainsKey(1))
- {
- BinaryHeapItem ResultItem = (BinaryHeapItem)BinaryHeap[1];
- BinaryHeapItem ChangeItem = (BinaryHeapItem)BinaryHeap[BinaryHeap.Count];
- BinaryHeap.Remove(BinaryHeap.Count);
- if (BinaryHeap.Count == 0) return ResultItem;
- BinaryHeap[1] = ChangeItem;
- int index = 1;
- int temp;
- BinaryHeapItem tempItem;
- bool isOK = false;
- while (!isOK)
- {
- temp = index * 2;
- if (temp + 1 <= BinaryHeap.Count)
- {
- if ((((BinaryHeapItem)BinaryHeap[index]).Fn > ((BinaryHeapItem)BinaryHeap[temp]).Fn) && (((BinaryHeapItem)BinaryHeap[index]).Fn > ((BinaryHeapItem)BinaryHeap[temp + 1]).Fn))
- {
- if (((BinaryHeapItem)BinaryHeap[temp]).Fn <= ((BinaryHeapItem)BinaryHeap[temp + 1]).Fn)
- {
- tempItem = (BinaryHeapItem)BinaryHeap[temp];
- BinaryHeap[temp] = (BinaryHeapItem)BinaryHeap[index];
- BinaryHeap[index] = tempItem;
- index = temp;
- }
- else
- {
- tempItem = (BinaryHeapItem)BinaryHeap[temp + 1];
- BinaryHeap[temp + 1] = (BinaryHeapItem)BinaryHeap[index];
- BinaryHeap[index] = tempItem;
- index = temp + 1;
- }
- }
- else if (((BinaryHeapItem)BinaryHeap[index]).Fn > ((BinaryHeapItem)BinaryHeap[temp]).Fn)
- {
- tempItem = (BinaryHeapItem)BinaryHeap[temp];
- BinaryHeap[temp] = (BinaryHeapItem)BinaryHeap[index];
- BinaryHeap[index] = tempItem;
- index = temp;
- }
- else if (((BinaryHeapItem)BinaryHeap[index]).Fn > ((BinaryHeapItem)BinaryHeap[temp + 1]).Fn)
- {
- tempItem = (BinaryHeapItem)BinaryHeap[temp + 1];
- BinaryHeap[temp + 1] = (BinaryHeapItem)BinaryHeap[index];
- BinaryHeap[index] = tempItem;
- index = temp + 1;
- }
- else
- isOK = true;
- }
- else if ((temp == BinaryHeap.Count) && (((BinaryHeapItem)BinaryHeap[index]).Fn > ((BinaryHeapItem)BinaryHeap[temp]).Fn))
- {
- tempItem = (BinaryHeapItem)BinaryHeap[temp];
- BinaryHeap[temp] = (BinaryHeapItem)BinaryHeap[index];
- BinaryHeap[index] = tempItem;
- index = temp;
- }
- else
- break;
- }
- return ResultItem;
- }
- else
- return null;
- }
- catch (Exception e)
- {
- MessageBox.Show("NETA_BinaryHeap.GetMinFnItem错误" + e.Message);
- return null;
- }
- }
- //更新Openlist中的Fn值。
- public bool MinishItemFnValue(string KeyID, double NewFn)
- {
- try
- {
- int index = -1;
- int temp;
- Double temp1;
- BinaryHeapItem tempItem;
- bool isOK = false;
- foreach (DictionaryEntry myDE in BinaryHeap)
- {
- if (((BinaryHeapItem)myDE.Value).KeyID == KeyID)
- {
- //A*应用中只能减小Fn
- if (((BinaryHeapItem)myDE.Value).Fn <= NewFn) return false;//非法Fn
- ((BinaryHeapItem)myDE.Value).Fn = NewFn;
- index = (int)(myDE.Key);
- break;
- }
- }
- if (index == -1) return false;
- while (!isOK)
- {
- temp1 = index / 2;
- temp = (int)System.Math.Floor(temp1);
- if (temp <= 0) break;
- if (((BinaryHeapItem)BinaryHeap[temp]).Fn > ((BinaryHeapItem)BinaryHeap[index]).Fn)
- {
- tempItem = (BinaryHeapItem)BinaryHeap[temp];
- BinaryHeap[temp] = (BinaryHeapItem)BinaryHeap[index];
- BinaryHeap[index] = tempItem;
- index = temp;
- }
- else
- isOK = true;
- }
- return true;
- }
- catch (Exception e)
- {
- MessageBox.Show("NETA_BinaryHeap.MinishItemFnValue错误" + e.Message);
- return false;
- }
- }
- public int ItemCount
- {
- get { return BinaryHeap.Count; }
- }
- public void Clear()
- {
- BinaryHeap.Clear();
- }
- #endregion
- }
- #endregion
- #region 辅助类的定义
- //接口,对查找最短路径的功能进行定义
- public interface iNetShortPathAnalyse
- {
- NETA_Point NetShortPathAnalyse(string StartID, string EndID);
- ArrayList resultPointLine(string start, string end);
- double ComputeTheHnValue(NETA_Point currPt, NETA_Point EndPt);
- double doCompute(NETA_Point currPt, NETA_Point EndPt);
- }
- public class NETA_NET
- {
- public ArrayList pArraylistRoad = new ArrayList();
- public NETA_NET()
- {
- pArraylistRoad = pArrayList;
- }
- public NETA_Point GetPoint(string PointID)//在路网中获取指定点。
- {
- //在路网中获取指定点。
- NETA_Point tempPoint = new NETA_Point();
- int tag=0;
- bool getOK = false;
- for (int i = 0; i < pArraylistRoad.Count; i++)
- {
- if (((NETA_Point)pArraylistRoad[i]).PointID == PointID)
- {
- tag = i;
- getOK = true;
- }
- }
- if (getOK)
- {
- tempPoint = (NETA_Point)pArraylistRoad[tag];
- }
- else
- {
- return null;
- }
- return tempPoint;
- }
- public ArrayList GetChildrenPoints(NETA_Point currPt)//找出当前点的子点。
- {
- //找出当前点的子点。
- ArrayList tempArraylist = new ArrayList();
- NETA_Point tempPoint = new NETA_Point();
- foreach (Edge temp in currPt.EdgeList)
- {
- if (GetPoint(temp.EndNodeID) != null)
- {
- tempPoint = GetPoint(temp.EndNodeID);
- tempPoint.Hn = temp.Weight;
- tempArraylist.Add(tempPoint);
- }
- else
- {
- continue;
- }
- }
- return tempArraylist;
- }
- public void ResetPointState()//将程序恢复到初始状态
- {
- }
- }
- #endregion
- #region NetShortPathAnalyse
- //对接口的实现
- public class BLL_NetShortPathAnalyse : iNetShortPathAnalyse//对接口 iNetShortPathAnalyse的实现
- {
- private NETA_NET TheAnalyseNET;
- private NETA_BinaryHeap NetShortPathAnalyseBinaryHeap = NETA_BinaryHeap.NETA_BinaryHeapInstance;
- public BLL_NetShortPathAnalyse()
- {
- TheAnalyseNET = new NETA_NET();
- }
- #region iNetShortPathAnalyse 成员
- public NETA_Point NetShortPathAnalyse(string StartID, string EndID)
- {
- try
- {
- if (TheAnalyseNET.pArraylistRoad == null)
- {
- MessageBox.Show("请先初始化网络");
- return null;
- }
- NETA_Point StartPt = TheAnalyseNET.GetPoint(StartID);
- NETA_Point EndPt = TheAnalyseNET.GetPoint(EndID);
- if (StartPt == null)
- {
- MessageBox.Show("起点在网络中不存在,请重新选择!");
- return null;
- }
- if (EndPt == null)
- {
- MessageBox.Show("终点在网络中不存在,请重新选择!");
- return null;
- }
- if (StartPt.IsEnabled == false || EndPt.IsEnabled == false)
- {
- MessageBox.Show("起点或终点被设置为障碍点,请重新选择!");
- return null;
- }
- //开始处理。
- TheAnalyseNET.ResetPointState();
- NetShortPathAnalyseBinaryHeap.Clear();
- StartPt.Fn = 0;
- StartPt.Gn = 0;
- StartPt.AnalyseState = PointAnalyseState.InOpenList;
- BinaryHeapItem MyItem = new BinaryHeapItem();
- MyItem.Fn = StartPt.Fn;
- MyItem.KeyID = StartPt.PointID;
- NetShortPathAnalyseBinaryHeap.AddItem(MyItem);
- NETA_Point CurrPt;
- BinaryHeapItem CurrItem;
- while (NetShortPathAnalyseBinaryHeap.ItemCount > 0)//openList为空程序结束
- {
- CurrItem = NetShortPathAnalyseBinaryHeap.GetAndRemoveMinFnItem();
- //获取当前点。
- CurrPt = TheAnalyseNET.GetPoint(CurrItem.KeyID);
- if (CurrPt.PointID == EndPt.PointID) return CurrPt;//找到了终点,程序结束
- CurrPt.AnalyseState = PointAnalyseState.InCloseList;
- System.Collections.ArrayList ChildrenPt = TheAnalyseNET.GetChildrenPoints(CurrPt);
- foreach (NETA_Point ChildPt in ChildrenPt)
- {
- if (ChildPt.IsEnabled == false || ChildPt.AnalyseState == PointAnalyseState.InCloseList)
- { }
- else if (ChildPt.AnalyseState != PointAnalyseState.InOpenList)
- {
- ChildPt.AnalyseState = PointAnalyseState.InOpenList;
- ChildPt.ParentPoint = CurrPt;
- // MessageBox.Show(ChildPt.PointID+"/n"+ChildPt.Hn.ToString());
- ChildPt.Gn = CurrPt.Gn + ChildPt.Hn;//Hn起临时储存本次Weight作用
- ChildPt.Hn = ComputeTheHnValue(ChildPt, EndPt);
- ChildPt.Fn = ChildPt.Gn + ChildPt.Hn;
- CurrItem = new BinaryHeapItem();
- CurrItem.KeyID = ChildPt.PointID;
- CurrItem.Fn = ChildPt.Fn;
- NetShortPathAnalyseBinaryHeap.AddItem(CurrItem);
- }
- else if (ChildPt.AnalyseState == PointAnalyseState.InOpenList)
- {
- if (CurrPt.Gn + ChildPt.Hn < ChildPt.Gn)
- {
- ChildPt.ParentPoint = CurrPt;
- ChildPt.Gn = CurrPt.Gn + ChildPt.Hn;
- ChildPt.Hn = ComputeTheHnValue(ChildPt, EndPt);
- ChildPt.Fn = ChildPt.Gn + ChildPt.Hn;
- NetShortPathAnalyseBinaryHeap.MinishItemFnValue(ChildPt.PointID, ChildPt.Fn);
- }
- }
- }
- }
- //if (NetShortPathAnalyseBinaryHeap.ItemCount == 0)
- MessageBox.Show("未找到连通路径!");
- return null;
- }
- catch (Exception e)
- {
- MessageBox.Show("BLL_NetShortPathAnalyse.NetShortPathAnalyse错误" + e.Message);
- return null;
- }
- }
- public ArrayList resultPointLine(string start, string end)//获取路径点ID
- {
- ArrayList temparr = new ArrayList();
- NETA_Point tempnode = TheAnalyseNET.GetPoint(end);
- while (start != tempnode.PointID)
- {
- if (tempnode.ParentPoint != null)
- {
- foreach (Edge temEdge in tempnode.ParentPoint.EdgeList)
- {
- if (temEdge.EndNodeID == tempnode.PointID)
- {
- temparr.Add(temEdge.EdgeFID);
- }
- }
- tempnode = tempnode.ParentPoint;
- }
- else
- {
- return null;
- }
- }
- return temparr;
- }
- public double ComputeTheHnValue(NETA_Point currPt, NETA_Point EndPt)
- {
- try
- {
- return doCompute(currPt, EndPt);
- }
- catch (Exception e)
- {
- MessageBox.Show("计算因子错误," + e.Message);
- return 0;
- }
- }
- public double doCompute(NETA_Point currPt, NETA_Point EndPt)
- {
- double radLat1 = Rad(currPt.X);
- double radLat2 = Rad(EndPt.X);
- double a = radLat1 - radLat2;
- double b = Rad(currPt.Y) - Rad(EndPt.Y);
- double s = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2)));
- s = s * 6378137.0; //(gs == GaussSphere.WGS84 ? 6378137.0 : (gs == GaussSphere.Xian80 ? 6378140.0 : 6378245.0));
- s = Math.Round(s * 10000) / 10000;
- return s;
- }
- public static double Rad(double d)
- {
- return d * Math.PI / 180.0;
- }
- //GaussSphere 为自定义枚举类型
- /// <summary>
- /// 高斯投影中所选用的参考椭球
- /// </summary>
- public enum GaussSphere
- {
- Beijing54,
- Xian80,
- WGS84,
- }
- #endregion
- }
- #endregion
- #endregion
A*算法的最短路径实现!
最新推荐文章于 2024-07-14 12:25:25 发布