Esempio n. 1
0
void RgShortestPathWidget::exportPath()
{
  RgExportDlg dlg( this );
  if ( !dlg.exec() )
    return;

  QgsVectorLayer *vl = dlg.mapLayer();
  if ( vl == NULL )
    return;

  QgsPoint p1, p2;
  QgsGraph *path = getPath( p1, p2 );
  if ( path == NULL )
    return;

  QgsCoordinateTransform ct( mPlugin->iface()->mapCanvas()->mapSettings().destinationCrs(),
                             vl->crs() );

  int startVertexIdx = path->findVertex( p1 );
  int stopVertexIdx  = path->findVertex( p2 );

  double time = 0.0;
  double cost = 0.0;

  Unit timeUnit = Unit::byName( mPlugin->timeUnitName() );
  Unit distanceUnit = Unit::byName( mPlugin->distanceUnitName() );

  QgsPolyline p;
  while ( startVertexIdx != stopVertexIdx )
  {
    if ( stopVertexIdx < 0 )
      break;

    QgsGraphArcIdList l = path->vertex( stopVertexIdx ).inArc();
    if ( l.empty() )
      break;
    const QgsGraphArc& e = path->arc( l.front() );

    cost += e.property( 0 ).toDouble();
    time += e.property( 1 ).toDouble();

    p.push_front( ct.transform( path->vertex( e.inVertex() ).point() ) );
    stopVertexIdx = e.outVertex();
  }
  p.push_front( ct.transform( p1 ) );

  QgsFeature f;
  f.initAttributes( vl->pendingFields().count() );
  f.setGeometry( QgsGeometry::fromPolyline( p ) );
  f.setAttribute( 0, cost / distanceUnit.multipler() );
  f.setAttribute( 1, time / timeUnit.multipler() );
  QgsFeatureList features;
  features << f;
  vl->dataProvider()->addFeatures( features );
  vl->updateExtents();

  mPlugin->iface()->mapCanvas()->update();
  delete path;
}
Esempio n. 2
0
void RgShortestPathWidget::findingPath()
{
  QgsPoint p1, p2;
  QgsGraph *path = getPath( p1, p2 );
  if ( path == NULL )
    return;

  mrbPath->reset( QGis::Line );
  double time = 0.0;
  double cost = 0.0;

  int startVertexIdx = path->findVertex( p1 );
  int stopVertexIdx  = path->findVertex( p2 );
  QList< QgsPoint > p;
  while ( startVertexIdx != stopVertexIdx )
  {
    if ( stopVertexIdx < 0 )
      break;

    QgsGraphArcIdList l = path->vertex( stopVertexIdx ).inArc();
    if ( l.empty() )
      break;
    const QgsGraphArc& e = path->arc( l.front() );

    cost += e.property( 0 ).toDouble();
    time += e.property( 1 ).toDouble();

    p.push_front( path->vertex( e.inVertex() ).point() );

    stopVertexIdx = e.outVertex();
  }
  p.push_front( p1 );
  QList< QgsPoint>::iterator it;
  for ( it = p.begin(); it != p.end(); ++it )
  {
    mrbPath->addPoint( *it );
  }

  Unit timeUnit = Unit::byName( mPlugin->timeUnitName() );
  Unit distanceUnit = Unit::byName( mPlugin->distanceUnitName() );

  mPathCostLineEdit->setText( QString().setNum( cost / distanceUnit.multipler() ) + distanceUnit.name() );
  mPathTimeLineEdit->setText( QString().setNum( time / timeUnit.multipler() ) + timeUnit.name() );

  mrbPath->setColor( Qt::red );

  delete path;
}
Esempio n. 3
0
void RgShortestPathWidget::exportPath()
{
  RgExportDlg dlg( this );
  if ( !dlg.exec() )
    return;

  QgsVectorLayer *vl = dlg.mapLayer();
  if ( vl == NULL )
    return;

  QgsPoint p1, p2;
  QgsGraph *path = getPath( p1, p2 );
  if ( path == NULL )
    return;

  QgsCoordinateTransform ct( mPlugin->iface()->mapCanvas()->mapRenderer()->destinationCrs(),
                             vl->crs() );

  int startVertexIdx = path->findVertex( p1 );
  int stopVertexIdx  = path->findVertex( p2 );

  QgsPolyline p;
  while ( startVertexIdx != stopVertexIdx )
  {
    QgsGraphArcIdList l = path->vertex( stopVertexIdx ).inArc();
    if ( l.empty() )
      break;
    const QgsGraphArc& e = path->arc( l.front() );
    p.push_front( ct.transform( path->vertex( e.inVertex() ).point() ) );
    stopVertexIdx = e.outVertex();
  }
  p.push_front( ct.transform( p1 ) );

  vl->startEditing();
  QgsFeature f;
  f.setGeometry( QgsGeometry::fromPolyline( p ) );
  vl->addFeature( f );
  vl->updateExtents();

  mPlugin->iface()->mapCanvas()->update();
  delete path;
}
QVariantMap QgsShortestPathPointToPointAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
  loadCommonParams( parameters, context, feedback );

  QgsFields fields;
  fields.append( QgsField( QStringLiteral( "start" ), QVariant::String ) );
  fields.append( QgsField( QStringLiteral( "end" ), QVariant::String ) );
  fields.append( QgsField( QStringLiteral( "cost" ), QVariant::Double ) );

  QString dest;
  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, QgsWkbTypes::LineString, mNetwork->sourceCrs() ) );
  if ( !sink )
    throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );

  QgsPointXY startPoint = parameterAsPoint( parameters, QStringLiteral( "START_POINT" ), context, mNetwork->sourceCrs() );
  QgsPointXY endPoint = parameterAsPoint( parameters, QStringLiteral( "END_POINT" ), context, mNetwork->sourceCrs() );

  feedback->pushInfo( QObject::tr( "Building graph…" ) );
  QVector< QgsPointXY > points;
  points << startPoint << endPoint;
  QVector< QgsPointXY > snappedPoints;
  mDirector->makeGraph( mBuilder.get(), points, snappedPoints, feedback );

  feedback->pushInfo( QObject::tr( "Calculating shortest path…" ) );
  QgsGraph *graph = mBuilder->graph();
  int idxStart = graph->findVertex( snappedPoints[0] );
  int idxEnd = graph->findVertex( snappedPoints[1] );

  QVector< int > tree;
  QVector< double > costs;
  QgsGraphAnalyzer::dijkstra( graph, idxStart, 0, &tree, &costs );

  if ( tree.at( idxEnd ) == -1 )
  {
    throw QgsProcessingException( QObject::tr( "There is no route from start point to end point." ) );
  }

  QVector<QgsPointXY> route;
  route.push_front( graph->vertex( idxEnd ).point() );
  double cost = costs.at( idxEnd );
  while ( idxEnd != idxStart )
  {
    idxEnd = graph->edge( tree.at( idxEnd ) ).fromVertex();
    route.push_front( graph->vertex( idxEnd ).point() );
  }

  feedback->pushInfo( QObject::tr( "Writing results…" ) );
  QgsGeometry geom = QgsGeometry::fromPolylineXY( route );
  QgsFeature feat;
  feat.setFields( fields );
  QgsAttributes attributes;
  attributes << startPoint.toString() << endPoint.toString() << cost / mMultiplier;
  feat.setGeometry( geom );
  feat.setAttributes( attributes );
  sink->addFeature( feat, QgsFeatureSink::FastInsert );

  QVariantMap outputs;
  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
  outputs.insert( QStringLiteral( "TRAVEL_COST" ), cost / mMultiplier );
  return outputs;
}
Esempio n. 5
0
QgsGraph* RgShortestPathWidget::getPath( 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 NULL;
  }

  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 NULL;
    }
    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 NULL;
  }
  if ( p2 == QgsPoint( 0.0, 0.0 ) )
  {
    QMessageBox::critical( this, tr( "Tie point failed" ), tr( "Stop point doesn't tie to the road!" ) );
    return NULL;
  }

  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;

  QgsGraph* shortestpathTree = QgsGraphAnalyzer::shortestTree( graph, startVertexIdx, criterionNum );

  delete graph;

  if ( shortestpathTree->findVertex( p2 ) == -1 )
  {
    QMessageBox::critical( this, tr( "Path not found" ), tr( "Path not found" ) );
    return NULL;
  }
  return shortestpathTree;
}
QVariantMap QgsShortestPathPointToLayerAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
  loadCommonParams( parameters, context, feedback );

  QgsPointXY startPoint = parameterAsPoint( parameters, QStringLiteral( "START_POINT" ), context, mNetwork->sourceCrs() );

  std::unique_ptr< QgsFeatureSource > endPoints( parameterAsSource( parameters, QStringLiteral( "END_POINTS" ), context ) );
  if ( !endPoints )
    throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "END_POINTS" ) ) );

  QgsFields fields = endPoints->fields();
  fields.append( QgsField( QStringLiteral( "start" ), QVariant::String ) );
  fields.append( QgsField( QStringLiteral( "end" ), QVariant::String ) );
  fields.append( QgsField( QStringLiteral( "cost" ), QVariant::Double ) );

  QString dest;
  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, QgsWkbTypes::LineString, mNetwork->sourceCrs() ) );
  if ( !sink )
    throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );

  QVector< QgsPointXY > points;
  points.push_front( startPoint );
  QHash< int, QgsAttributes > sourceAttributes;
  loadPoints( endPoints.get(), points, sourceAttributes, context, feedback );

  feedback->pushInfo( QObject::tr( "Building graph…" ) );
  QVector< QgsPointXY > snappedPoints;
  mDirector->makeGraph( mBuilder.get(), points, snappedPoints, feedback );

  feedback->pushInfo( QObject::tr( "Calculating shortest paths…" ) );
  QgsGraph *graph = mBuilder->graph();
  int idxStart = graph->findVertex( snappedPoints[0] );
  int idxEnd;

  QVector< int > tree;
  QVector< double > costs;
  QgsGraphAnalyzer::dijkstra( graph, idxStart, 0, &tree, &costs );

  QVector<QgsPointXY> route;
  double cost;

  QgsFeature feat;
  feat.setFields( fields );
  QgsAttributes attributes;

  int step =  points.size() > 0 ? 100.0 / points.size() : 1;
  for ( int i = 1; i < points.size(); i++ )
  {
    if ( feedback->isCanceled() )
    {
      break;
    }

    idxEnd = graph->findVertex( snappedPoints[i] );
    if ( tree.at( idxEnd ) == -1 )
    {
      feedback->reportError( QObject::tr( "There is no route from start point (%1) to end point (%2)." )
                             .arg( startPoint.toString(),
                                   points[i].toString() ) );
      feat.clearGeometry();
      attributes = sourceAttributes.value( i );
      attributes.append( QVariant() );
      attributes.append( points[i].toString() );
      feat.setAttributes( attributes );
      sink->addFeature( feat, QgsFeatureSink::FastInsert );
      continue;
    }

    route.clear();
    route.push_front( graph->vertex( idxEnd ).point() );
    cost = costs.at( idxEnd );
    while ( idxEnd != idxStart )
    {
      idxEnd = graph->edge( tree.at( idxEnd ) ).fromVertex();
      route.push_front( graph->vertex( idxEnd ).point() );
    }

    QgsGeometry geom = QgsGeometry::fromPolylineXY( route );
    QgsFeature feat;
    feat.setFields( fields );
    attributes = sourceAttributes.value( i );
    attributes.append( startPoint.toString() );
    attributes.append( points[i].toString() );
    attributes.append( cost / mMultiplier );
    feat.setAttributes( attributes );
    feat.setGeometry( geom );
    sink->addFeature( feat, QgsFeatureSink::FastInsert );

    feedback->setProgress( i * step );
  }

  QVariantMap outputs;
  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
  return outputs;
}
Esempio n. 7
0
QgsGraph* RgShortestPathWidget::getPath( 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 nullptr;
  }

  QgsGraphBuilder builder(
    mPlugin->iface()->mapCanvas()->mapSettings().destinationCrs(),
    mPlugin->iface()->mapCanvas()->mapSettings().hasCrsTransformEnabled(),
    mPlugin->topologyToleranceFactor() );
  {
    const QgsGraphDirector *director = mPlugin->director();
    if ( !director )
    {
      QMessageBox::critical( this, tr( "Plugin isn't configured" ), tr( "Plugin isn't configured! Please go to the Vector menu, Road Graph, Settings option to configure it." ) );
      return nullptr;
    }
    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 nullptr;
  }
  if ( p2 == QgsPoint( 0.0, 0.0 ) )
  {
    QMessageBox::critical( this, tr( "Tie point failed" ), tr( "Stop point doesn't tie to the road!" ) );
    return nullptr;
  }

  QgsGraph *graph = builder.graph();

  int startVertexIdx = graph->findVertex( p1 );
  if ( startVertexIdx < 0 )
  {
    mPlugin->iface()->messageBar()->pushMessage(
      tr( "Cannot calculate path" ),
      tr( "Could not find start vertex. Please check your input data." ),
      QgsMessageBar::WARNING,
      mPlugin->iface()->messageTimeout()
    );

    delete graph;
    return nullptr;
  }

  int criterionNum = 0;
  if ( mCriterionName->currentIndex() > 0 )
    criterionNum = 1;

  if ( graph->vertexCount() == 0 )
  {
    mPlugin->iface()->messageBar()->pushMessage(
      tr( "Cannot calculate path" ),
      tr( "The created graph is empty. Please check your input data." ),
      QgsMessageBar::WARNING,
      mPlugin->iface()->messageTimeout()
    );

    delete graph;
    return nullptr;
  }


  QgsGraph* shortestpathTree = QgsGraphAnalyzer::shortestTree( graph, startVertexIdx, criterionNum );
  delete graph;

  if ( shortestpathTree->findVertex( p2 ) == -1 )
  {
    delete shortestpathTree;
    QMessageBox::critical( this, tr( "Path not found" ), tr( "Path not found" ) );
    return nullptr;
  }
  return shortestpathTree;
}