最短路径分析算法in QGIS

                                                                          最短路径分析算法in QGIS

                                                                                                                                  wangsh 2011-11-20

 

       qgis是一款稳定高效的gis桌面产品(参考1),而开发者提供了最短路径功能(参考2),其主要功能为:

两点间的最短路径;

最短路径Tree。

 
    首先编译qgis(参考链接)
     最短路径核心代码:代码位置:QGIS\src\analysis\network\qgsgraphanalyzer.cpp
     

void QgsGraphAnalyzer::shortestpath( const QgsGraph* source, int startPointIdx, int criterionNum, const QVector<int>& destPointCost, QVector<double>& cost, QgsGraph* treeResult )

{

 

  // QMap< cost, vertexIdx > not_begin

  // I use it and not create any struct or class.

  QMap< double, int > not_begin;

  QMap< double, int >::iterator it;

 

  // QVector< QPair< cost, arc id > result

  QVector< QPair< double, int > > result;

 

  result.reserve( source->vertexCount() );

  int i;

  for ( i = 0; i < source->vertexCount(); ++i )

  {

    result.push_back( QPair<double, int> ( std::numeric_limits<double>::infinity() , i ) );

  }

  result[ startPointIdx ] = QPair<double, int> ( 0.0, -1 );

 

  not_begin.insert( 0.0, startPointIdx );

 

  // begin Dijkstra algorithm

  while ( !not_begin.empty() )

  {

    it = not_begin.begin();

    double curCost = it.key();

    int curVertex = it.value();

    not_begin.erase( it );

 

    // edge index list

    QgsGraphArcIdList l = source->vertex( curVertex ).outArc();

    QgsGraphArcIdList::iterator arcIt;

    for ( arcIt = l.begin(); arcIt != l.end(); ++arcIt )

    {

      const QgsGraphArc& arc = source->arc( *arcIt );

      double cost = arc.property( criterionNum ).toDouble() + curCost;

 

      if ( cost < result[ arc.inVertex()].first )

      {

        result[ arc.inVertex()] = QPair< double, int >( cost, *arcIt );

        not_begin.insert( cost, arc.inVertex() );

      }

    }

  }

 

  // fill shortestpath tree

  if ( treeResult != NULL )

  {

    // sourceVertexIdx2resultVertexIdx

    QVector<int> source2result( result.size(), -1 );

 

    for ( i = 0; i < source->vertexCount(); ++i )

    {

      if ( result[ i ].first < std::numeric_limits<double>::infinity() )

      {

        source2result[ i ] = treeResult->addVertex( source->vertex( i ).point() );

      }

    }

    for ( i = 0; i < source->vertexCount(); ++i )

    {

      if ( result[ i ].first < std::numeric_limits<double>::infinity() && result[i].second != -1 )

      {

        const QgsGraphArc& arc = source->arc( result[i].second );

 

        treeResult->addArc( source2result[ arc.outVertex()], source2result[ i ],

                            arc.properties() );

      }

    }

  }

 

  // fill shortestpath's costs

  for ( i = 0; i < destPointCost.size(); ++i )

  {

    cost[i] = result[ destPointCost[i] ].first;

  }

}

 

QgsGraph* QgsGraphAnalyzer::shortestTree( const QgsGraph* source, int startVertexIdx, int criterionNum )

{

  QgsGraph *g = new QgsGraph;

  QVector<int> v;

  QVector<double> vv;

  QgsGraphAnalyzer::shortestpath( source, startVertexIdx, criterionNum, v, vv, g );

 

  return g;

}
     调用最短路径:
位置:QGIS\src\plugins\roadgraph\shortestpathwidget.cpp
 

bool RgShortestPathWidget::getPath( QgsGraph* shortestTree, QgsPoint& p1, QgsPoint& p2 )

{

  if ( mFrontPointLineEdit->text().isNull() || mBackPointLineEdit->text().isNull() )

  {

    QMessageBox::critical( this, tr( "Point not selected" ), tr( "First, select start and stop points." ) );

    return false;

  }

 

  QgsGraphBuilder builder(

    mPlugin->iface()->mapCanvas()->mapRenderer()->destinationCrs(),

    mPlugin->iface()->mapCanvas()->mapRenderer()->hasCrsTransformEnabled(),

    mPlugin->topologyToleranceFactor() );

  {

    const QgsGraphDirector *director = mPlugin->director();

    if ( director == NULL )

    {

      QMessageBox::critical( this, tr( "Plugin isn't configured" ), tr( "Plugin isn't configured!" ) );

      return false;

    }

    connect( director, SIGNAL( buildProgress( int, int ) ), mPlugin->iface()->mainWindow(), SLOT( showProgress( int, int ) ) );

    connect( director, SIGNAL( buildMessage( QString ) ), mPlugin->iface()->mainWindow(), SLOT( showStatusMessage( QString ) ) );

 

    QVector< QgsPoint > points;

    QVector< QgsPoint > tiedPoint;

 

    points.push_back( mFrontPoint );

    points.push_back( mBackPoint );

    director->makeGraph( &builder, points, tiedPoint );

 

    p1 = tiedPoint[ 0 ];

    p2 = tiedPoint[ 1 ];

    // not need

    delete director;

  }

 

  if ( p1 == QgsPoint( 0.0, 0.0 ) )

  {

    QMessageBox::critical( this, tr( "Tie point failed" ), tr( "Start point doesn't tie to the road!" ) );

    return false;

  }

  if ( p2 == QgsPoint( 0.0, 0.0 ) )

  {

    QMessageBox::critical( this, tr( "Tie point failed" ), tr( "Stop point doesn't tie to the road!" ) );

    return false;

  }

 

  QgsGraph *graph = builder.graph();

 

  QVector< int > pointIdx( 0, 0 );

  QVector< double > pointCost( 0, 0.0 );

 

  int startVertexIdx = graph->findVertex( p1 );

 

  int criterionNum = 0;

  if ( mCriterionName->currentIndex() > 0 )

    criterionNum = 1;

 

  QgsGraphAnalyzer::shortestpath( graph, startVertexIdx, criterionNum, pointIdx, pointCost, shortestTree );

 

  delete graph;

 

  if ( shortestTree->findVertex( p2 ) == -1 )

  {

    QMessageBox::critical( this, tr( "Path not found" ), tr( "Path not found" ) );

    return false;

  }

  return true;

}

 

参考资料

1.     Qgis主页 http://www.qgis.org/     

2.     RoadGraph开发介绍 http://gis-lab.info/qa/road-graph-eng.html   

3.     Qgis编译 http://blog.csdn.net/wsh6759/article/details/6894073

4.     测试数据地址:http://svn.gis-lab.info/road-graph/  

5.     源码:http://svn.gis-lab.info/road-graph/  

 

 

 

 

你可能感兴趣的:(Algorithm,算法,delete,iterator,Graph,Signal)