A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© aisini 金牌黑马   /  2014-7-29 19:50  /  1397 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

            导航路径的计算,一般用 Dijkstra 算法和 A* 算法。
            Dijkstra 算法是全局遍历,确保运算结果一定是最短路径。
            A* 算法是策略寻路,不保证一定是最短路径。
          Dijkstra 需要载入全部数据,遍历搜索。(也可以分层计算,分层载入)
          A* 算法可以根据需要,分部分块载入地图数据。
    本代码是基于 A* 算法搜索最短路径的一个演示程序。
  附件源码中的道路属性类参考了高德导航地图的数据结构。

  1. /// <summary>
  2. /// 搜索最短路径
  3. /// </summary>
  4. /// <param name="starts">起始节点描述序列</param>
  5. /// <param name="endPt">终止点坐标值</param>
  6. /// <param name="endsID">终止节点ID序列</param>
  7. /// <param name="avoidsID">避开节点ID序列</param>
  8. /// <returns></returns>
  9. public int[] CreateShortPath(ExtendLine startELine, ExtendLine endELine, int[] avoids)
  10. {
  11.     ExtendLine sl = startELine;
  12.     ExtendLine el = endELine;
  13.     // 检测入口参数的合法性
  14.     // ...

  15.     // 检查起始节点内是否包含终止节点,如果包含,直接返回此点
  16.     Debug.Assert( sl.IsOut == false && el.IsOut == true );
  17.     if (( sl.FLine != null && el.FLine != null && el.FLine.TNodeID == el.FLine.FNodeID ) ||
  18.         ( sl.FLine != null && el.TLine != null && sl.FLine.TNodeID == el.TLine.FNodeID ))
  19.         return new int[] { sl.FLine.TNodeID };

  20.     if (( sl.TLine != null && el.FLine != null && sl.TLine.TNodeID == el.FLine.FNodeID ) ||
  21.         ( sl.TLine != null && el.TLine != null && sl.TLine.TNodeID == el.TLine.FNodeID ))
  22.         return new int[] { sl.TLine.TNodeID };

  23.     // 初始化搜索队列
  24.     AStarQueue queue = this.InitSearchQueue( sl, el, avoids );

  25.     // 搜索最短路径
  26.     int pos = this.ShortSearch( queue, el.VLine.Points[1] );

  27.     // 返回路径信息
  28.     return this.TracePath( queue, pos );
  29. }

  30. /// <summary>
  31. /// 初始化搜索队列
  32. /// </summary>
  33. private AStarQueue InitSearchQueue(ExtendLine sl, ExtendLine el, int[] avoidsID)
  34. {
  35.     // 创建队列
  36.     AStarQueue queue = new AStarQueue( _gTab );

  37.     // 起始点加入开放列表
  38.     Debug.Assert( sl.FLine != null || sl.TLine != null );
  39.     if ( sl.FLine != null )
  40.     {
  41.         Debug.Assert( sl.FLine.TNodeID > 0 );
  42.         GraphNode gn = GraphNode.SearchByID( _gTab, sl.FLine.TNodeID );
  43.         float h = GeoMath.Distance( gn.Point, el.VLine.Points[1] );
  44.         queue.SetOpen( gn.NodePos, -1, sl.FLine.Length, h );
  45.     }
  46.     if ( sl.TLine != null )
  47.     {
  48.         Debug.Assert( sl.TLine.TNodeID > 0 );
  49.         GraphNode gn = GraphNode.SearchByID( _gTab, sl.TLine.TNodeID );
  50.         float h = GeoMath.Distance( gn.Point, el.VLine.Points[1] );
  51.         queue.SetOpen( gn.NodePos, -1, sl.TLine.Length, h );
  52.     }

  53.     // 终止点加入终止列表
  54.     if ( el.FLine != null )
  55.     {
  56.         Debug.Assert( el.FLine.FNodeID > 0 );
  57.         GraphNode gn = GraphNode.SearchByID( _gTab, el.FLine.FNodeID );
  58.         Debug.Assert( ! queue.IsOpen( gn.NodePos ) );   // 起始点不能与终止点重合
  59.         queue.SetEnd( gn.NodePos );
  60.     }
  61.     if ( el.TLine != null )
  62.     {
  63.         Debug.Assert( el.TLine.FNodeID > 0 );
  64.         GraphNode gn = GraphNode.SearchByID( _gTab, el.TLine.FNodeID );
  65.         Debug.Assert( ! queue.IsOpen( gn.NodePos ) );
  66.         queue.SetEnd( gn.NodePos );
  67.     }

  68.     // 避开点加入封闭列表
  69.     if ( avoidsID != null )
  70.     {
  71.         foreach ( int nid in avoidsID )
  72.         {
  73.             GraphNode gn = GraphNode.SearchByID( _gTab, nid );
  74.             if ( queue.IsOpen( gn.NodePos ) )
  75.                 continue;
  76.             else if ( queue.IsEnd( gn.NodePos ) )
  77.                 continue;
  78.             else
  79.                 queue.SetClose( gn.NodePos );
  80.         }
  81.     }

  82.     // 返回队列
  83.     return queue;
  84. }

  85. /// <summary>
  86. /// 在设置好的队列内搜索最短路径
  87. /// </summary>
  88. /// <param name="queue">已设置好起止节点的队列</param>
  89. /// <param name="endPoint">终止点坐标</param>
  90. /// <returns>终止节点的位置(Pos)</returns>
  91. private int ShortSearch(AStarQueue queue, FPoint endPt)
  92. {
  93.     // 开始搜索
  94.     while ( queue.Min >= 0 )
  95.     {
  96.         // 当前点加入封闭列表
  97.         int curPos = queue.Min;
  98.         queue.SetClose( curPos );

  99.         GraphNode gnCur = this._gTab[curPos] as GraphNode;
  100.         foreach ( GraphLink glnk in gnCur.Links )
  101.         {
  102.             // 获取连接点
  103.             int nextPos = glnk.NodePos;
  104.             GraphNode gnNext = this._gTab[nextPos] as GraphNode;
  105.             float g = queue.GValue( curPos ) + glnk.Length;
  106.             float h = GeoMath.Distance( gnNext.Point, endPt );
  107.          
  108.             if ( ! queue.IsEnd( gnNext.NodePos ) )  // 未达终点
  109.             {
  110.                 // 不在封闭列表
  111.                 if ( ! queue.IsClose( nextPos ) )
  112.                 {
  113.                     // 开放列表内
  114.                     if ( queue.IsOpen( nextPos ) )
  115.                     {
  116.                         if ( g < queue.GValue( nextPos ) )
  117.                         {
  118.                             queue.SetOpen( nextPos, curPos, g, h );
  119.                         }
  120.                     }
  121.                     else
  122.                     {
  123.                         queue.SetOpen( nextPos, curPos, g, h );
  124.                     }
  125.                 }
  126.             }
  127.             else    // 抵达终点
  128.             {
  129.                 queue.SetOpen( nextPos, curPos, g, h );
  130.                 queue.SetClose( nextPos );
  131.                 return nextPos;
  132.             }
  133.         }
  134.     }
  135.     return -1;  // 不可到达
  136. }

  137. /// <summary>
  138. /// 获取路径数据
  139. /// </summary>
  140. /// <param name="queue">已搜出路径的队列</param>
  141. /// <param name="pos">回溯操作的起始点</param>
  142. /// <returns>NodeID, RoadID, NodeID, RoadID, ... , NodeID</returns>
  143. private int[] TracePath(AStarQueue queue, int endPos)
  144. {
  145.     // 获取路径
  146.     ArrayList idls = new ArrayList();
  147.     for ( int pos = endPos; pos >= 0; pos = queue[pos].ParentPos )
  148.     {
  149.         GraphNode gn = _gTab[pos] as GraphNode;
  150.         idls.Add( gn.NodeID );

  151.         int parentPos = queue[pos].ParentPos;
  152.         if ( parentPos >= 0 )
  153.         {
  154.             GraphNode pn = _gTab[parentPos] as GraphNode;
  155.             foreach ( GraphLink glnk in pn.Links )
  156.             {
  157.                 if ( glnk.NodePos == pos )
  158.                 {
  159.                     idls.Add( glnk.RoadID );
  160.                     break;
  161.                 }
  162.             }
  163.         }
  164.     }

  165.     idls.Reverse();
  166.     int[] ids = new int[idls.Count];
  167.     idls.CopyTo( ids );

  168.     Debug.Assert( this.ValidResult( ids ) );
  169.     return ids;
  170. }
复制代码



1 个回复

倒序浏览
学习了  努力再努力
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马