Exemplo n.º 1
0
int QgsAtlasComposition::updateFeatures()
{
  //needs to be called when layer, filter, sort changes

  if ( !mCoverageLayer )
  {
    return 0;
  }

  updateFilenameExpression();

  // select all features with all attributes
  QgsFeatureIterator fit = mCoverageLayer->getFeatures();

  std::auto_ptr<QgsExpression> filterExpression;
  if ( mFilterFeatures && !mFeatureFilter.isEmpty() )
  {
    filterExpression = std::auto_ptr<QgsExpression>( new QgsExpression( mFeatureFilter ) );
    if ( filterExpression->hasParserError() )
    {
      mFilterParserError = filterExpression->parserErrorString();
      return 0;
    }
  }
  mFilterParserError = QString();

  // We cannot use nextFeature() directly since the feature pointer is rewinded by the rendering process
  // We thus store the feature ids for future extraction
  QgsFeature feat;
  mFeatureIds.clear();
  mFeatureKeys.clear();
  int sortIdx = mCoverageLayer->fieldNameIndex( mSortKeyAttributeName );
  while ( fit.nextFeature( feat ) )
  {
    if ( mFilterFeatures && !mFeatureFilter.isEmpty() )
    {
      QVariant result = filterExpression->evaluate( &feat, mCoverageLayer->pendingFields() );
      if ( filterExpression->hasEvalError() )
      {
        QgsMessageLog::logMessage( tr( "Atlas filter eval error: %1" ).arg( filterExpression->evalErrorString() ), tr( "Composer" ) );
      }

      // skip this feature if the filter evaluation if false
      if ( !result.toBool() )
      {
        continue;
      }
    }
    mFeatureIds.push_back( feat.id() );

    if ( mSortFeatures && sortIdx != -1 )
    {
      mFeatureKeys.insert( feat.id(), feat.attributes()[ sortIdx ] );
    }
  }

  // sort features, if asked for
  if ( mFeatureKeys.count() )
  {
    FieldSorter sorter( mFeatureKeys, mSortAscending );
    qSort( mFeatureIds.begin(), mFeatureIds.end(), sorter );
  }

  QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )mFeatureIds.size() ) );

  //jump to first feature if currently using an atlas preview
  //need to do this in case filtering/layer change has altered matching features
  if ( mComposition->atlasMode() == QgsComposition::PreviewAtlas )
  {
    firstFeature();
  }

  return mFeatureIds.size();
}
Exemplo n.º 2
0
QgsFeatureList QgsQuickIdentifyKit::identifyVectorLayer( QgsVectorLayer *layer, const QgsPointXY &point ) const
{
  QgsFeatureList results;

  if ( !layer || !layer->isSpatial() )
    return results;

  if ( !layer->isInScaleRange( mMapSettings->mapSettings().scale() ) )
    return results;

  QgsFeatureList featureList;

  // toLayerCoordinates will throw an exception for an 'invalid' point.
  // For example, if you project a world map onto a globe using EPSG 2163
  // and then click somewhere off the globe, an exception will be thrown.
  try
  {
    // create the search rectangle
    double searchRadius = searchRadiusMU();

    QgsRectangle r;
    r.setXMinimum( point.x() - searchRadius );
    r.setXMaximum( point.x() + searchRadius );
    r.setYMinimum( point.y() - searchRadius );
    r.setYMaximum( point.y() + searchRadius );

    r = toLayerCoordinates( layer, r );

    QgsFeatureRequest req;
    req.setFilterRect( r );
    req.setLimit( mFeaturesLimit );
    req.setFlags( QgsFeatureRequest::ExactIntersect );

    QgsFeatureIterator fit = layer->getFeatures( req );
    QgsFeature f;
    while ( fit.nextFeature( f ) )
      featureList << QgsFeature( f );
  }
  catch ( QgsCsException &cse )
  {
    QgsDebugMsg( QStringLiteral( "Invalid point, proceed without a found features." ) );
    Q_UNUSED( cse );
  }

  bool filter = false;

  QgsRenderContext context( QgsRenderContext::fromMapSettings( mMapSettings->mapSettings() ) );
  context.expressionContext() << QgsExpressionContextUtils::layerScope( layer );
  QgsFeatureRenderer *renderer = layer->renderer();
  if ( renderer && renderer->capabilities() & QgsFeatureRenderer::ScaleDependent )
  {
    // setup scale for scale dependent visibility (rule based)
    renderer->startRender( context, layer->fields() );
    filter = renderer->capabilities() & QgsFeatureRenderer::Filter;
  }

  for ( const QgsFeature &feature : featureList )
  {
    context.expressionContext().setFeature( feature );

    if ( filter && !renderer->willRenderFeature( const_cast<QgsFeature &>( feature ), context ) )
      continue;

    results.append( feature );
  }

  if ( renderer && renderer->capabilities() & QgsFeatureRenderer::ScaleDependent )
  {
    renderer->stopRender( context );
  }

  return results;
}
Exemplo n.º 3
0
bool QgsMapToolIdentify::identifyVectorLayer( QList<IdentifyResult> *results, QgsVectorLayer *layer, QgsPoint point )
{
  if ( !layer || !layer->hasGeometryType() )
    return false;

  if ( layer->hasScaleBasedVisibility() &&
       ( layer->minimumScale() > mCanvas->mapSettings().scale() ||
         layer->maximumScale() <= mCanvas->mapSettings().scale() ) )
  {
    QgsDebugMsg( "Out of scale limits" );
    return false;
  }

  QApplication::setOverrideCursor( Qt::WaitCursor );

  QMap< QString, QString > commonDerivedAttributes;

  commonDerivedAttributes.insert( tr( "(clicked coordinate)" ), point.toString() );

  int featureCount = 0;

  QgsFeatureList featureList;

  // toLayerCoordinates will throw an exception for an 'invalid' point.
  // For example, if you project a world map onto a globe using EPSG 2163
  // and then click somewhere off the globe, an exception will be thrown.
  try
  {
    // create the search rectangle
    double searchRadius = searchRadiusMU( mCanvas );

    QgsRectangle r;
    r.setXMinimum( point.x() - searchRadius );
    r.setXMaximum( point.x() + searchRadius );
    r.setYMinimum( point.y() - searchRadius );
    r.setYMaximum( point.y() + searchRadius );

    r = toLayerCoordinates( layer, r );

    QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterRect( r ).setFlags( QgsFeatureRequest::ExactIntersect ) );
    QgsFeature f;
    while ( fit.nextFeature( f ) )
      featureList << QgsFeature( f );
  }
  catch ( QgsCsException & cse )
  {
    Q_UNUSED( cse );
    // catch exception for 'invalid' point and proceed with no features found
    QgsDebugMsg( QString( "Caught CRS exception %1" ).arg( cse.what() ) );
  }

  QgsFeatureList::iterator f_it = featureList.begin();

  bool filter = false;

  QgsRenderContext context( QgsRenderContext::fromMapSettings( mCanvas->mapSettings() ) );
  context.expressionContext() << QgsExpressionContextUtils::layerScope( layer );
  QgsFeatureRendererV2* renderer = layer->rendererV2();
  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
  {
    // setup scale for scale dependent visibility (rule based)
    renderer->startRender( context, layer->fields() );
    filter = renderer->capabilities() & QgsFeatureRendererV2::Filter;
  }

  for ( ; f_it != featureList.end(); ++f_it )
  {
    QMap< QString, QString > derivedAttributes = commonDerivedAttributes;

    QgsFeatureId fid = f_it->id();
    context.expressionContext().setFeature( *f_it );

    if ( filter && !renderer->willRenderFeature( *f_it, context ) )
      continue;

    featureCount++;

    derivedAttributes.unite( featureDerivedAttributes( &( *f_it ), layer ) );

    derivedAttributes.insert( tr( "feature id" ), fid < 0 ? tr( "new feature" ) : FID_TO_STRING( fid ) );

    results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), *f_it, derivedAttributes ) );
  }

  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
  {
    renderer->stopRender( context );
  }

  QgsDebugMsg( "Feature count on identify: " + QString::number( featureCount ) );

  QApplication::restoreOverrideCursor();
  return featureCount > 0;
}
Exemplo n.º 4
0
bool QgsGeometryAnalyzer::eventLayer( QgsVectorLayer* lineLayer, QgsVectorLayer* eventLayer, int lineField, int eventField, QgsFeatureIds &unlocatedFeatureIds, const QString& outputLayer,
                                      const QString& outputFormat, int locationField1, int locationField2, int offsetField, double offsetScale,
                                      bool forceSingleGeometry, QgsVectorDataProvider* memoryProvider, QProgressDialog* p )
{
    if ( !lineLayer || !eventLayer || !lineLayer->isValid() || !eventLayer->isValid() )
    {
        return false;
    }

    //create line field / id map for line layer
    QMultiHash< QString, QgsFeature > lineLayerIdMap; //1:n possible (e.g. several linear reference geometries for one feature in the event layer)
    QgsFeatureIterator fit = lineLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() << lineField ) );
    QgsFeature fet;
    while ( fit.nextFeature( fet ) )
    {
        lineLayerIdMap.insert( fet.attribute( lineField ).toString(), fet );
    }

    //create output datasource or attributes in memory provider
    QgsVectorFileWriter* fileWriter = nullptr;
    QgsFeatureList memoryProviderFeatures;
    if ( !memoryProvider )
    {
        QGis::WkbType memoryProviderType = QGis::WKBMultiLineString;
        if ( locationField2 == -1 )
        {
            memoryProviderType = forceSingleGeometry ? QGis::WKBPoint : QGis::WKBMultiPoint;
        }
        else
        {
            memoryProviderType = forceSingleGeometry ? QGis::WKBLineString : QGis::WKBMultiLineString;
        }
        fileWriter = new QgsVectorFileWriter( outputLayer,
                                              eventLayer->dataProvider()->encoding(),
                                              eventLayer->fields(),
                                              memoryProviderType,
                                              &( lineLayer->crs() ),
                                              outputFormat );
    }
    else
    {
        memoryProvider->addAttributes( eventLayer->fields().toList() );
    }

    //iterate over eventLayer and write new features to output file or layer
    fit = eventLayer->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ) );
    QgsGeometry* lrsGeom = nullptr;
    double measure1, measure2 = 0.0;

    int nEventFeatures = eventLayer->featureCount();
    int featureCounter = 0;
    int nOutputFeatures = 0; //number of output features for the current event feature
    if ( p )
    {
        p->setWindowModality( Qt::WindowModal );
        p->setMinimum( 0 );
        p->setMaximum( nEventFeatures );
        p->show();
    }

    while ( fit.nextFeature( fet ) )
    {
        nOutputFeatures = 0;

        //update progress dialog
        if ( p )
        {
            if ( p->wasCanceled() )
            {
                break;
            }
            p->setValue( featureCounter );
            ++featureCounter;
        }

        measure1 = fet.attribute( locationField1 ).toDouble();
        if ( locationField2 != -1 )
        {
            measure2 = fet.attribute( locationField2 ).toDouble();
            if ( qgsDoubleNear(( measure2 - measure1 ), 0.0 ) )
            {
                continue;
            }
        }

        QList<QgsFeature> featureIdList = lineLayerIdMap.values( fet.attribute( eventField ).toString() );
        QList<QgsFeature>::iterator featureIdIt = featureIdList.begin();
        for ( ; featureIdIt != featureIdList.end(); ++featureIdIt )
        {
            if ( locationField2 == -1 )
            {
                lrsGeom = locateAlongMeasure( measure1, featureIdIt->constGeometry() );
            }
            else
            {
                lrsGeom = locateBetweenMeasures( measure1, measure2, featureIdIt->constGeometry() );
            }

            if ( lrsGeom )
            {
                ++nOutputFeatures;
                addEventLayerFeature( fet, lrsGeom, featureIdIt->geometry(), fileWriter, memoryProviderFeatures, offsetField, offsetScale, forceSingleGeometry );
            }
        }
        if ( nOutputFeatures < 1 )
        {
            unlocatedFeatureIds.insert( fet.id() );
        }
    }

    if ( p )
    {
        p->setValue( nEventFeatures );
    }

    if ( memoryProvider )
    {
        memoryProvider->addFeatures( memoryProviderFeatures );
    }
    delete fileWriter;
    return true;
}
Exemplo n.º 5
0
void QgsGeometryCheckerSetupTab::runChecks()
{
  // Get selected layer
  const QList<QgsVectorLayer *> layers = getSelectedLayers();
  if ( layers.isEmpty() )
    return;

  if ( ui.radioButtonOutputNew->isChecked() )
  {
    for ( QgsVectorLayer *layer : layers )
    {
      if ( layer->dataProvider()->dataSourceUri().startsWith( ui.lineEditOutputDirectory->text() ) )
      {
        QMessageBox::critical( this, tr( "Check Geometries" ), tr( "The chosen output directory contains one or more input layers." ) );
        return;
      }
    }
  }
  QgsVectorLayer *lineLayerCheckLayer = ui.comboLineLayerIntersection->isEnabled() ? QgsProject::instance()->mapLayer<QgsVectorLayer *>( ui.comboLineLayerIntersection->currentData().toString() ) : nullptr;
  QgsVectorLayer *followBoundaryCheckLayer = ui.comboBoxFollowBoundaries->isEnabled() ? QgsProject::instance()->mapLayer<QgsVectorLayer *>( ui.comboBoxFollowBoundaries->currentData().toString() ) : nullptr;
  if ( layers.contains( lineLayerCheckLayer ) || layers.contains( followBoundaryCheckLayer ) )
  {
    QMessageBox::critical( this, tr( "Check Geometries" ), tr( "The selected input layers cannot contain a layer also selected for a topology check." ) );
    return;
  }

  for ( QgsVectorLayer *layer : layers )
  {
    if ( layer->isEditable() )
    {
      QMessageBox::critical( this, tr( "Check Geometries" ), tr( "Input layer '%1' is not allowed to be in editing mode." ).arg( layer->name() ) );
      return;
    }
  }
  bool selectedOnly = ui.checkBoxInputSelectedOnly->isChecked();

  // Set window busy
  setCursor( Qt::WaitCursor );
  mRunButton->setEnabled( false );
  ui.labelStatus->setText( tr( "<b>Preparing output…</b>" ) );
  ui.labelStatus->show();
  QApplication::processEvents( QEventLoop::ExcludeUserInputEvents );

  QList<QgsVectorLayer *> processLayers;
  if ( ui.radioButtonOutputNew->isChecked() )
  {
    // Get output directory and file extension
    QDir outputDir = QDir( ui.lineEditOutputDirectory->text() );
    QString outputDriverName = ui.comboBoxOutputFormat->currentData().toString();
    QgsVectorFileWriter::MetaData metadata;
    if ( !QgsVectorFileWriter::driverMetadata( outputDriverName, metadata ) )
    {
      QMessageBox::critical( this, tr( "Check Geometries" ), tr( "The specified output format cannot be recognized." ) );
      mRunButton->setEnabled( true );
      ui.labelStatus->hide();
      unsetCursor();
      return;
    }
    QString outputExtension = metadata.ext;

    // List over input layers, check which existing project layers need to be removed and create output layers
    QString filenamePrefix = ui.lineEditFilenamePrefix->text();
    QSettings().setValue( "/geometry_checker/previous_values/filename_prefix", filenamePrefix );
    QStringList toRemove;
    QStringList createErrors;
    for ( QgsVectorLayer *layer : layers )
    {
      QString outputPath = outputDir.absoluteFilePath( filenamePrefix + layer->name() + "." + outputExtension );

      // Remove existing layer with same uri from project
      for ( QgsVectorLayer *projectLayer : QgsProject::instance()->layers<QgsVectorLayer *>() )
      {
        if ( projectLayer->dataProvider()->dataSourceUri().startsWith( outputPath ) )
        {
          toRemove.append( projectLayer->id() );
        }
      }

      // Create output layer
      QString errMsg;
      QgsVectorFileWriter::WriterError err =  QgsVectorFileWriter::writeAsVectorFormat( layer, outputPath, layer->dataProvider()->encoding(), layer->crs(), outputDriverName, selectedOnly, &errMsg );
      if ( err != QgsVectorFileWriter::NoError )
      {
        createErrors.append( errMsg );
        continue;
      }
      const QgsVectorLayer::LayerOptions options { QgsProject::instance()->transformContext() };
      QgsVectorLayer *newlayer = new QgsVectorLayer( outputPath, QFileInfo( outputPath ).completeBaseName(), QStringLiteral( "ogr" ), options );
      if ( selectedOnly )
      {
        QgsFeature feature;

        // Get features to select (only selected features were written up to this point)
        QgsFeatureIds selectedFeatures = newlayer->allFeatureIds();

        // Write non-selected feature ids
        QgsFeatureList features;
        QgsFeatureIterator it = layer->getFeatures();
        while ( it.nextFeature( feature ) )
        {
          if ( !layer->selectedFeatureIds().contains( feature.id() ) )
          {
            features.append( feature );
          }
        }
        newlayer->dataProvider()->addFeatures( features );

        // Set selected features
        newlayer->selectByIds( selectedFeatures );
      }
      processLayers.append( newlayer );
    }

    //  Remove layers from project
    if ( !toRemove.isEmpty() )
    {
      QgsProject::instance()->removeMapLayers( toRemove );
    }

    // Error if an output layer could not be created
    if ( !createErrors.isEmpty() )
    {
      QMessageBox::critical( this, tr( "Check Geometries" ), tr( "Failed to create one or more output layers:\n%1" ).arg( createErrors.join( "\n" ) ) );
      mRunButton->setEnabled( true );
      ui.labelStatus->hide();
      unsetCursor();
      return;
    }
  }
  else
  {
    processLayers = layers;
  }

  // Check if output layers are editable
  QList<QgsVectorLayer *> nonEditableLayers;
  for ( QgsVectorLayer *layer : qgis::as_const( processLayers ) )
  {
    if ( ( layer->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeGeometries ) == 0 )
    {
      nonEditableLayers.append( layer );
    }
  }
  if ( !nonEditableLayers.isEmpty() )
  {
    QStringList nonEditableLayerNames;
    for ( QgsVectorLayer *layer : nonEditableLayers )
    {
      nonEditableLayerNames.append( layer->name() );
    }
    if ( QMessageBox::Yes != QMessageBox::question( this, tr( "Check Geometries" ), tr( "The following output layers are in a format that does not support editing features:\n%1\n\nThe geometry check can be performed, but it will not be possible to fix any errors. Do you want to continue?" ).arg( nonEditableLayerNames.join( "\n" ) ), QMessageBox::Yes, QMessageBox::No ) )
    {
      if ( ui.radioButtonOutputNew->isChecked() )
      {
        for ( QgsVectorLayer *layer : qgis::as_const( processLayers ) )
        {
          QString layerPath = layer->dataProvider()->dataSourceUri();
          delete layer;
          if ( ui.comboBoxOutputFormat->currentText() == QLatin1String( "ESRI Shapefile" ) )
          {
            QgsVectorFileWriter::deleteShapeFile( layerPath );
          }
          else
          {
            QFile( layerPath ).remove();
          }
        }
        mRunButton->setEnabled( true );
        ui.labelStatus->hide();
        unsetCursor();
      }
      return;
    }
  }

  // Setup checker
  ui.labelStatus->setText( tr( "<b>Building spatial index…</b>" ) );
  QApplication::processEvents( QEventLoop::ExcludeUserInputEvents );
  QMap<QString, QgsFeaturePool *> featurePools;
  for ( QgsVectorLayer *layer : qgis::as_const( processLayers ) )
  {
    featurePools.insert( layer->id(), new QgsVectorDataProviderFeaturePool( layer, selectedOnly ) );
  }
  // LineLayerIntersection check is enabled, make sure there is also a feature pool for that layer
  if ( ui.checkLineLayerIntersection->isChecked() && !featurePools.keys().contains( ui.comboLineLayerIntersection->currentData().toString() ) )
  {
    QgsVectorLayer *layer = QgsProject::instance()->mapLayer<QgsVectorLayer *>( ui.comboLineLayerIntersection->currentData().toString() );
    Q_ASSERT( layer );
    featurePools.insert( layer->id(), new QgsVectorDataProviderFeaturePool( layer, selectedOnly ) );
  }

  QgsGeometryCheckContext *context = new QgsGeometryCheckContext( ui.spinBoxTolerance->value(), QgsProject::instance()->crs(), QgsProject::instance()->transformContext() );

  QList<QgsGeometryCheck *> checks;
  for ( const QgsGeometryCheckFactory *factory : QgsGeometryCheckFactoryRegistry::getCheckFactories() )
  {
    QgsGeometryCheck *check = factory->createInstance( context, ui );
    if ( check )
    {
      checks.append( check );
    }
  }
  QgsGeometryChecker *checker = new QgsGeometryChecker( checks, context, featurePools );

  emit checkerStarted( checker );

  if ( ui.radioButtonOutputNew->isChecked() )
  {
    QList<QgsMapLayer *> addLayers;
    for ( QgsVectorLayer *layer : qgis::as_const( processLayers ) )
    {
      addLayers.append( layer );
    }
    QgsProject::instance()->addMapLayers( addLayers );
  }

  // Run
  ui.buttonBox->addButton( mAbortButton, QDialogButtonBox::ActionRole );
  mRunButton->hide();
  ui.progressBar->setRange( 0, 0 );
  ui.labelStatus->hide();
  ui.progressBar->show();
  ui.widgetInputs->setEnabled( false );
  QEventLoop evLoop;
  QFutureWatcher<void> futureWatcher;
  connect( checker, &QgsGeometryChecker::progressValue, ui.progressBar, &QProgressBar::setValue );
  connect( &futureWatcher, &QFutureWatcherBase::finished, &evLoop, &QEventLoop::quit );
  connect( mAbortButton, &QAbstractButton::clicked, &futureWatcher, &QFutureWatcherBase::cancel );
  connect( mAbortButton, &QAbstractButton::clicked, this, &QgsGeometryCheckerSetupTab::showCancelFeedback );

  mIsRunningInBackground = true;

  int maxSteps = 0;
  futureWatcher.setFuture( checker->execute( &maxSteps ) );
  ui.progressBar->setRange( 0, maxSteps );
  evLoop.exec();

  mIsRunningInBackground = false;

  // Restore window
  unsetCursor();
  mAbortButton->setEnabled( true );
  ui.buttonBox->removeButton( mAbortButton );
  mRunButton->setEnabled( true );
  mRunButton->show();
  ui.progressBar->hide();
  ui.labelStatus->hide();
  ui.widgetInputs->setEnabled( true );

  // Show result
  emit checkerFinished( !futureWatcher.isCanceled() );
}
Exemplo n.º 6
0
bool QgsGeometryAnalyzer::dissolve( QgsVectorLayer* layer, const QString& shapefileName,
                                    bool onlySelectedFeatures, int uniqueIdField, QProgressDialog* p )
{
    if ( !layer )
    {
        return false;
    }
    QgsVectorDataProvider* dp = layer->dataProvider();
    if ( !dp )
    {
        return false;
    }
    bool useField = false;
    if ( uniqueIdField == -1 )
    {
        uniqueIdField = 0;
    }
    else
    {
        useField = true;
    }

    QGis::WkbType outputType = dp->geometryType();
    QgsCoordinateReferenceSystem crs = layer->crs();

    QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), layer->fields(), outputType, &crs );
    QgsFeature currentFeature;
    QMultiMap<QString, QgsFeatureId> map;

    if ( onlySelectedFeatures )
    {
        //use QgsVectorLayer::featureAtId
        const QgsFeatureIds selection = layer->selectedFeaturesIds();
        QgsFeatureIds::const_iterator it = selection.constBegin();
        for ( ; it != selection.constEnd(); ++it )
        {
            if ( !layer->getFeatures( QgsFeatureRequest().setFilterFid( *it ) ).nextFeature( currentFeature ) )
            {
                continue;
            }
            map.insert( currentFeature.attribute( uniqueIdField ).toString(), currentFeature.id() );
        }
    }
    else
    {
        QgsFeatureIterator fit = layer->getFeatures();
        while ( fit.nextFeature( currentFeature ) )
        {
            map.insert( currentFeature.attribute( uniqueIdField ).toString(), currentFeature.id() );
        }
    }

    QgsGeometry *dissolveGeometry = nullptr; //dissolve geometry
    QMultiMap<QString, QgsFeatureId>::const_iterator jt = map.constBegin();
    QgsFeature outputFeature;
    while ( jt != map.constEnd() )
    {
        QString currentKey = jt.key();
        int processedFeatures = 0;
        bool first = true;
        //take only selection
        if ( onlySelectedFeatures )
        {
            //use QgsVectorLayer::featureAtId
            const QgsFeatureIds selection = layer->selectedFeaturesIds();
            if ( p )
            {
                p->setMaximum( selection.size() );
            }
            while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
            {
                if ( p && p->wasCanceled() )
                {
                    break;
                }
                if ( selection.contains( jt.value() ) )
                {
                    if ( p )
                    {
                        p->setValue( processedFeatures );
                    }
                    if ( !layer->getFeatures( QgsFeatureRequest().setFilterFid( jt.value() ) ).nextFeature( currentFeature ) )
                    {
                        continue;
                    }
                    if ( first )
                    {
                        outputFeature.setAttributes( currentFeature.attributes() );
                        first = false;
                    }
                    dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry );
                    ++processedFeatures;
                }
                ++jt;
            }
        }
        //take all features
        else
        {
            int featureCount = layer->featureCount();
            if ( p )
            {
                p->setMaximum( featureCount );
            }
            while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
            {
                if ( p )
                {
                    p->setValue( processedFeatures );
                }

                if ( p && p->wasCanceled() )
                {
                    break;
                }
                if ( !layer->getFeatures( QgsFeatureRequest().setFilterFid( jt.value() ) ).nextFeature( currentFeature ) )
                {
                    continue;
                }
                {
                    outputFeature.setAttributes( currentFeature.attributes() );
                    first = false;
                }
                dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry );
                ++processedFeatures;
                ++jt;
            }
        }
        outputFeature.setGeometry( dissolveGeometry );
        vWriter.addFeature( outputFeature );
    }
    return true;
}
Exemplo n.º 7
0
bool QgsGeometryAnalyzer::buffer( QgsVectorLayer* layer, const QString& shapefileName, double bufferDistance,
                                  bool onlySelectedFeatures, bool dissolve, int bufferDistanceField, QProgressDialog* p )
{
    if ( !layer )
    {
        return false;
    }

    QgsVectorDataProvider* dp = layer->dataProvider();
    if ( !dp )
    {
        return false;
    }

    QGis::WkbType outputType = QGis::WKBPolygon;
    if ( dissolve )
    {
        outputType = QGis::WKBMultiPolygon;
    }
    QgsCoordinateReferenceSystem crs = layer->crs();

    QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), layer->fields(), outputType, &crs );
    QgsFeature currentFeature;
    QgsGeometry *dissolveGeometry = nullptr; //dissolve geometry (if dissolve enabled)

    //take only selection
    if ( onlySelectedFeatures )
    {
        //use QgsVectorLayer::featureAtId
        const QgsFeatureIds selection = layer->selectedFeaturesIds();
        if ( p )
        {
            p->setMaximum( selection.size() );
        }

        int processedFeatures = 0;
        QgsFeatureIds::const_iterator it = selection.constBegin();
        for ( ; it != selection.constEnd(); ++it )
        {
            if ( p )
            {
                p->setValue( processedFeatures );
            }

            if ( p && p->wasCanceled() )
            {
                break;
            }
            if ( !layer->getFeatures( QgsFeatureRequest().setFilterFid( *it ) ).nextFeature( currentFeature ) )
            {
                continue;
            }
            bufferFeature( currentFeature, processedFeatures, &vWriter, dissolve, &dissolveGeometry, bufferDistance, bufferDistanceField );
            ++processedFeatures;
        }

        if ( p )
        {
            p->setValue( selection.size() );
        }
    }
    //take all features
    else
    {
        QgsFeatureIterator fit = layer->getFeatures();

        int featureCount = layer->featureCount();
        if ( p )
        {
            p->setMaximum( featureCount );
        }
        int processedFeatures = 0;

        while ( fit.nextFeature( currentFeature ) )
        {
            if ( p )
            {
                p->setValue( processedFeatures );
            }
            if ( p && p->wasCanceled() )
            {
                break;
            }
            bufferFeature( currentFeature, processedFeatures, &vWriter, dissolve, &dissolveGeometry, bufferDistance, bufferDistanceField );
            ++processedFeatures;
        }
        if ( p )
        {
            p->setValue( featureCount );
        }
    }

    if ( dissolve )
    {
        QgsFeature dissolveFeature;
        if ( !dissolveGeometry )
        {
            QgsDebugMsg( "no dissolved geometry - should not happen" );
            return false;
        }
        dissolveFeature.setGeometry( dissolveGeometry );
        vWriter.addFeature( dissolveFeature );
    }
    return true;
}
Exemplo n.º 8
0
bool QgsGeometryAnalyzer::simplify( QgsVectorLayer* layer,
                                    const QString& shapefileName,
                                    double tolerance,
                                    bool onlySelectedFeatures,
                                    QProgressDialog *p )
{
    if ( !layer )
    {
        return false;
    }

    QgsVectorDataProvider* dp = layer->dataProvider();
    if ( !dp )
    {
        return false;
    }

    QGis::WkbType outputType = dp->geometryType();
    QgsCoordinateReferenceSystem crs = layer->crs();

    QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), layer->fields(), outputType, &crs );
    QgsFeature currentFeature;

    //take only selection
    if ( onlySelectedFeatures )
    {
        //use QgsVectorLayer::featureAtId
        const QgsFeatureIds selection = layer->selectedFeaturesIds();
        if ( p )
        {
            p->setMaximum( selection.size() );
        }

        int processedFeatures = 0;
        QgsFeatureIds::const_iterator it = selection.constBegin();
        for ( ; it != selection.constEnd(); ++it )
        {
            if ( p )
            {
                p->setValue( processedFeatures );
            }

            if ( p && p->wasCanceled() )
            {
                break;
            }
            if ( !layer->getFeatures( QgsFeatureRequest().setFilterFid( *it ) ).nextFeature( currentFeature ) )
            {
                continue;
            }
            simplifyFeature( currentFeature, &vWriter, tolerance );
            ++processedFeatures;
        }

        if ( p )
        {
            p->setValue( selection.size() );
        }
    }
    //take all features
    else
    {
        QgsFeatureIterator fit = layer->getFeatures();

        int featureCount = layer->featureCount();
        if ( p )
        {
            p->setMaximum( featureCount );
        }
        int processedFeatures = 0;

        while ( fit.nextFeature( currentFeature ) )
        {
            if ( p )
            {
                p->setValue( processedFeatures );
            }
            if ( p && p->wasCanceled() )
            {
                break;
            }
            simplifyFeature( currentFeature, &vWriter, tolerance );
            ++processedFeatures;
        }
        if ( p )
        {
            p->setValue( featureCount );
        }
    }

    return true;
}
Exemplo n.º 9
0
bool QgsGeometryAnalyzer::convexHull( QgsVectorLayer* layer, const QString& shapefileName,
                                      bool onlySelectedFeatures, int uniqueIdField, QProgressDialog* p )
{
    if ( !layer )
    {
        return false;
    }
    QgsVectorDataProvider* dp = layer->dataProvider();
    if ( !dp )
    {
        return false;
    }
    bool useField = false;
    if ( uniqueIdField == -1 )
    {
        uniqueIdField = 0;
    }
    else
    {
        useField = true;
    }
    QgsFields fields;
    fields.append( QgsField( QString( "UID" ), QVariant::String ) );
    fields.append( QgsField( QString( "AREA" ), QVariant::Double ) );
    fields.append( QgsField( QString( "PERIM" ), QVariant::Double ) );

    QGis::WkbType outputType = QGis::WKBPolygon;
    QgsCoordinateReferenceSystem crs = layer->crs();

    QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), fields, outputType, &crs );
    QgsFeature currentFeature;
    QgsGeometry* dissolveGeometry = nullptr; //dissolve geometry
    QMultiMap<QString, QgsFeatureId> map;

    if ( onlySelectedFeatures )
    {
        //use QgsVectorLayer::featureAtId
        const QgsFeatureIds selection = layer->selectedFeaturesIds();
        QgsFeatureIds::const_iterator it = selection.constBegin();
        for ( ; it != selection.constEnd(); ++it )
        {
#if 0
            if ( p )
            {
                p->setValue( processedFeatures );
            }
            if ( p && p->wasCanceled() )
            {
                // break; // it may be better to do something else here?
                return false;
            }
#endif
            if ( !layer->getFeatures( QgsFeatureRequest().setFilterFid( *it ) ).nextFeature( currentFeature ) )
            {
                continue;
            }
            map.insert( currentFeature.attribute( uniqueIdField ).toString(), currentFeature.id() );
        }
    }
    else
    {
        QgsFeatureIterator fit = layer->getFeatures();
        while ( fit.nextFeature( currentFeature ) )
        {
#if 0
            if ( p )
            {
                p->setValue( processedFeatures );
            }
            if ( p && p->wasCanceled() )
            {
                // break; // it may be better to do something else here?
                return false;
            }
#endif
            map.insert( currentFeature.attribute( uniqueIdField ).toString(), currentFeature.id() );
        }
    }

    QMultiMap<QString, QgsFeatureId>::const_iterator jt = map.constBegin();
    while ( jt != map.constEnd() )
    {
        QString currentKey = jt.key();
        int processedFeatures = 0;
        //take only selection
        if ( onlySelectedFeatures )
        {
            //use QgsVectorLayer::featureAtId
            const QgsFeatureIds selection = layer->selectedFeaturesIds();
            if ( p )
            {
                p->setMaximum( selection.size() );
            }
            processedFeatures = 0;
            while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
            {
                if ( p && p->wasCanceled() )
                {
                    break;
                }
                if ( selection.contains( jt.value() ) )
                {
                    if ( p )
                    {
                        p->setValue( processedFeatures );
                    }
                    if ( !layer->getFeatures( QgsFeatureRequest().setFilterFid( jt.value() ) ).nextFeature( currentFeature ) )
                    {
                        continue;
                    }
                    convexFeature( currentFeature, processedFeatures, &dissolveGeometry );
                    ++processedFeatures;
                }
                ++jt;
            }
            QList<double> values;
            if ( !dissolveGeometry )
            {
                QgsDebugMsg( "no dissolved geometry - should not happen" );
                return false;
            }
            dissolveGeometry = dissolveGeometry->convexHull();
            values = simpleMeasure( dissolveGeometry );
            QgsAttributes attributes( 3 );
            attributes[0] = QVariant( currentKey );
            attributes[1] = values.at( 0 );
            attributes[2] = values.at( 1 );
            QgsFeature dissolveFeature;
            dissolveFeature.setAttributes( attributes );
            dissolveFeature.setGeometry( dissolveGeometry );
            vWriter.addFeature( dissolveFeature );
        }
        //take all features
        else
        {
            int featureCount = layer->featureCount();
            if ( p )
            {
                p->setMaximum( featureCount );
            }
            processedFeatures = 0;
            while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
            {
                if ( p )
                {
                    p->setValue( processedFeatures );
                }

                if ( p && p->wasCanceled() )
                {
                    break;
                }
                if ( !layer->getFeatures( QgsFeatureRequest().setFilterFid( jt.value() ) ).nextFeature( currentFeature ) )
                {
                    continue;
                }
                convexFeature( currentFeature, processedFeatures, &dissolveGeometry );
                ++processedFeatures;
                ++jt;
            }
            QList<double> values;
            // QgsGeometry* tmpGeometry = 0;
            if ( !dissolveGeometry )
            {
                QgsDebugMsg( "no dissolved geometry - should not happen" );
                return false;
            }
            dissolveGeometry = dissolveGeometry->convexHull();
            // values = simpleMeasure( tmpGeometry );
            values = simpleMeasure( dissolveGeometry );
            QgsAttributes attributes;
            attributes[0] = QVariant( currentKey );
            attributes[1] = QVariant( values[ 0 ] );
            attributes[2] = QVariant( values[ 1 ] );
            QgsFeature dissolveFeature;
            dissolveFeature.setAttributes( attributes );
            dissolveFeature.setGeometry( dissolveGeometry );
            vWriter.addFeature( dissolveFeature );
        }
    }
    return true;
}
Exemplo n.º 10
0
void QgsDelimitedTextProvider::rescanFile() const
{
  mRescanRequired = false;
  resetIndexes();

  bool buildSpatialIndex = nullptr != mSpatialIndex;
  bool buildSubsetIndex = mBuildSubsetIndex && ( mSubsetExpression || mGeomRep != GeomNone );

  // In case file has been rewritten check that it is still valid

  mValid = mLayerValid && mFile->isValid();
  if ( ! mValid )
    return;

  // Open the file and get number of rows, etc. We assume that the
  // file has a header row and process accordingly. Caller should make
  // sure that the delimited file is properly formed.

  QStringList messages;

  if ( mGeomRep == GeomAsWkt )
  {
    mWktFieldIndex = mFile->fieldIndex( mWktFieldName );
    if ( mWktFieldIndex < 0 )
    {
      messages.append( tr( "%0 field %1 is not defined in delimited text file" ).arg( QStringLiteral( "Wkt" ), mWktFieldName ) );
    }
  }
  else if ( mGeomRep == GeomAsXy )
  {
    mXFieldIndex = mFile->fieldIndex( mXFieldName );
    mYFieldIndex = mFile->fieldIndex( mYFieldName );
    if ( mXFieldIndex < 0 )
    {
      messages.append( tr( "%0 field %1 is not defined in delimited text file" ).arg( QStringLiteral( "X" ), mWktFieldName ) );
    }
    if ( mYFieldIndex < 0 )
    {
      messages.append( tr( "%0 field %1 is not defined in delimited text file" ).arg( QStringLiteral( "Y" ), mWktFieldName ) );
    }
  }
  if ( !messages.isEmpty() )
  {
    reportErrors( messages );
    QgsDebugMsg( "Delimited text source invalid on rescan - missing geometry fields" );
    mValid = false;
    return;
  }

  // Reset the field columns

  for ( int i = 0; i < attributeFields.size(); i++ )
  {
    attributeColumns[i] = mFile->fieldIndex( attributeFields.at( i ).name() );
  }

  // Scan through the features in the file

  mSubsetIndex.clear();
  mUseSubsetIndex = false;
  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest() );
  mNumberFeatures = 0;
  mExtent = QgsRectangle();
  QgsFeature f;
  bool foundFirstGeometry = false;
  while ( fi.nextFeature( f ) )
  {
    if ( mGeometryType != QgsWkbTypes::NullGeometry && f.hasGeometry() )
    {
      if ( !foundFirstGeometry )
      {
        mExtent = f.geometry().boundingBox();
        foundFirstGeometry = true;
      }
      else
      {
        QgsRectangle bbox( f.geometry().boundingBox() );
        mExtent.combineExtentWith( bbox );
      }
      if ( buildSpatialIndex )
        mSpatialIndex->insertFeature( f );
    }
    if ( buildSubsetIndex )
      mSubsetIndex.append( ( quintptr ) f.id() );
    mNumberFeatures++;
  }
  if ( buildSubsetIndex )
  {
    long recordCount = mFile->recordCount();
    recordCount -= recordCount / SUBSET_ID_THRESHOLD_FACTOR;
    mUseSubsetIndex = recordCount < mSubsetIndex.size();
    if ( ! mUseSubsetIndex )
      mSubsetIndex.clear();
  }

  mUseSpatialIndex = buildSpatialIndex;
}
Exemplo n.º 11
0
void QgsTINInterpolator::initialize()
{
    DualEdgeTriangulation* theDualEdgeTriangulation = new DualEdgeTriangulation( 100000, 0 );
    if ( mInterpolation == CloughTocher )
    {
        NormVecDecorator* dec = new NormVecDecorator();
        dec->addTriangulation( theDualEdgeTriangulation );
        mTriangulation = dec;
    }
    else
    {
        mTriangulation = theDualEdgeTriangulation;
    }

    //get number of features if we use a progress bar
    int nFeatures = 0;
    int nProcessedFeatures = 0;
    if ( mShowProgressDialog )
    {
        QList<LayerData>::iterator layerDataIt = mLayerData.begin();
        for ( ; layerDataIt != mLayerData.end(); ++layerDataIt )
        {
            if ( layerDataIt->vectorLayer )
            {
                nFeatures += layerDataIt->vectorLayer->featureCount();
            }
        }
    }

    QProgressDialog* theProgressDialog = 0;
    if ( mShowProgressDialog )
    {
        theProgressDialog = new QProgressDialog( QObject::tr( "Building triangulation..." ), QObject::tr( "Abort" ), 0, nFeatures, 0 );
        theProgressDialog->setWindowModality( Qt::WindowModal );
    }


    QgsFeature f;
    QList<LayerData>::iterator layerDataIt = mLayerData.begin();
    for ( ; layerDataIt != mLayerData.end(); ++layerDataIt )
    {
        if ( layerDataIt->vectorLayer )
        {
            QgsAttributeList attList;
            if ( !layerDataIt->zCoordInterpolation )
            {
                attList.push_back( layerDataIt->interpolationAttribute );
            }

            QgsFeatureIterator fit = layerDataIt->vectorLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( attList ) );

            while ( fit.nextFeature( f ) )
            {
                if ( mShowProgressDialog )
                {
                    if ( theProgressDialog->wasCanceled() )
                    {
                        break;
                    }
                    theProgressDialog->setValue( nProcessedFeatures );
                }
                insertData( &f, layerDataIt->zCoordInterpolation, layerDataIt->interpolationAttribute, layerDataIt->mInputType );
                ++nProcessedFeatures;
            }
        }
    }

    delete theProgressDialog;

    if ( mInterpolation == CloughTocher )
    {
        CloughTocherInterpolator* ctInterpolator = new CloughTocherInterpolator();
        NormVecDecorator* dec = dynamic_cast<NormVecDecorator*>( mTriangulation );
        if ( dec )
        {
            QProgressDialog* progressDialog = 0;
            if ( mShowProgressDialog ) //show a progress dialog because it can take a long time...
            {
                progressDialog = new QProgressDialog();
                progressDialog->setLabelText( QObject::tr( "Estimating normal derivatives..." ) );
            }
            dec->estimateFirstDerivatives( progressDialog );
            delete progressDialog;
            ctInterpolator->setTriangulation( dec );
            dec->setTriangleInterpolator( ctInterpolator );
            mTriangleInterpolator = ctInterpolator;
        }
    }
    else //linear
    {
        mTriangleInterpolator = new LinTriangleInterpolator( theDualEdgeTriangulation );
    }
    mIsInitialized = true;

    //debug
    if ( mExportTriangulationToFile )
    {
        theDualEdgeTriangulation->saveAsShapefile( mTriangulationFilePath );
    }
}
Exemplo n.º 12
0
void QgsMapToolRotateFeature::canvasReleaseEvent( QgsMapMouseEvent *e )
{
  deleteRotationWidget();

  if ( !mCanvas )
  {
    return;
  }

  QgsVectorLayer *vlayer = currentVectorLayer();
  if ( !vlayer )
  {
    deleteRubberband();
    notifyNotVectorLayer();
    return;
  }

  if ( e->button() == Qt::RightButton )
  {
    deleteRubberband();
    mRotationActive = false;
    return;
  }

  // place anchor point on CTRL + click
  if ( e->modifiers() & Qt::ControlModifier )
  {
    if ( !mAnchorPoint )
    {
      return;
    }
    mAnchorPoint->setCenter( toMapCoordinates( e->pos() ) );
    mStartPointMapCoords = toMapCoordinates( e->pos() );
    mStPoint = e->pos();
    return;
  }

  // Initialize rotation if not yet active
  if ( !mRotationActive )
  {
    mRotation = 0;
    mRotationOffset = 0;

    deleteRubberband();

    mInitialPos = e->pos();

    if ( !vlayer->isEditable() )
    {
      notifyNotEditableLayer();
      return;
    }

    QgsPointXY layerCoords = toLayerCoordinates( vlayer, e->pos() );
    double searchRadius = QgsTolerance::vertexSearchRadius( mCanvas->currentLayer(), mCanvas->mapSettings() );
    QgsRectangle selectRect( layerCoords.x() - searchRadius, layerCoords.y() - searchRadius,
                             layerCoords.x() + searchRadius, layerCoords.y() + searchRadius );

    if ( vlayer->selectedFeatureCount() == 0 )
    {
      QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( selectRect ).setSubsetOfAttributes( QgsAttributeList() ) );

      //find the closest feature
      QgsGeometry pointGeometry = QgsGeometry::fromPoint( layerCoords );
      if ( pointGeometry.isNull() )
      {
        return;
      }

      double minDistance = std::numeric_limits<double>::max();

      QgsFeature cf;
      QgsFeature f;
      while ( fit.nextFeature( f ) )
      {
        if ( f.hasGeometry() )
        {
          double currentDistance = pointGeometry.distance( f.geometry() );
          if ( currentDistance < minDistance )
          {
            minDistance = currentDistance;
            cf = f;
          }
        }
      }

      if ( minDistance == std::numeric_limits<double>::max() )
      {
        emit messageEmitted( tr( "Could not find a nearby feature in the current layer." ) );
        return;
      }

      QgsRectangle bound = cf.geometry().boundingBox();
      mStartPointMapCoords = toMapCoordinates( vlayer, bound.center() );

      if ( !mAnchorPoint )
      {
        mAnchorPoint = new QgsVertexMarker( mCanvas );
      }
      mAnchorPoint->setIconType( QgsVertexMarker::ICON_CROSS );
      mAnchorPoint->setCenter( mStartPointMapCoords );

      mStPoint = toCanvasCoordinates( mStartPointMapCoords );

      mRotatedFeatures.clear();
      mRotatedFeatures << cf.id(); //todo: take the closest feature, not the first one...

      mRubberBand = createRubberBand( vlayer->geometryType() );
      mRubberBand->setToGeometry( cf.geometry(), vlayer );
    }
    else
    {
      mRotatedFeatures = vlayer->selectedFeatureIds();

      mRubberBand = createRubberBand( vlayer->geometryType() ) ;

      QgsFeature feat;
      QgsFeatureIterator it = vlayer->getSelectedFeatures();
      while ( it.nextFeature( feat ) )
      {
        mRubberBand->addGeometry( feat.geometry(), vlayer );
      }
    }

    mRubberBand->setColor( QColor( 255, 0, 0, 65 ) );
    mRubberBand->setWidth( 2 );
    mRubberBand->show();

    double XDistance = mInitialPos.x() - mAnchorPoint->x();
    double YDistance = mInitialPos.y() - mAnchorPoint->y() ;
    mRotationOffset = std::atan2( YDistance, XDistance ) * ( 180 / M_PI );

    createRotationWidget();
    if ( e->modifiers() & Qt::ShiftModifier )
    {
      if ( mRotationWidget )
      {
        mRotationWidget->setMagnet( 45 );
      }
    }

    mRotationActive = true;

    return;
  }

  applyRotation( mRotation );
}
QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::createRenderer(
  QgsVectorLayer* vlayer,
  QString attrName,
  int classes,
  Mode mode,
  QgsSymbolV2* symbol,
  QgsVectorColorRampV2* ramp )
{
  if ( classes < 1 )
    return NULL;

  int attrNum = vlayer->fieldNameIndex( attrName );

  double minimum = vlayer->minimumValue( attrNum ).toDouble();
  double maximum = vlayer->maximumValue( attrNum ).toDouble();
  QgsDebugMsg( QString( "min %1 // max %2" ).arg( minimum ).arg( maximum ) );

  QList<double> breaks;
  QList<int> labels;
  if ( mode == EqualInterval )
  {
    breaks = _calcEqualIntervalBreaks( minimum, maximum, classes );
  }
  else if ( mode == Pretty )
  {
    breaks = _calcPrettyBreaks( minimum, maximum, classes );
  }
  else if ( mode == Quantile || mode == Jenks || mode == StdDev )
  {
    // get values from layer
    QList<double> values;
    QgsFeature f;
    QgsAttributeList lst;
    lst.append( attrNum );

    QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ).setSubsetOfAttributes( lst ) );

    // create list of non-null attribute values
    while ( fit.nextFeature( f ) )
      if ( !f.attribute( attrNum ).isNull() )
        values.append( f.attribute( attrNum ).toDouble() );

    // calculate the breaks
    if ( mode == Quantile )
    {
      breaks = _calcQuantileBreaks( values, classes );
    }
    else if ( mode == Jenks )
    {
      breaks = _calcJenksBreaks( values, classes, minimum, maximum );
    }
    else if ( mode == StdDev )
    {
      breaks = _calcStdDevBreaks( values, classes, labels );
    }
  }
  else
  {
    Q_ASSERT( false );
  }

  QgsRangeList ranges;
  double lower, upper = minimum;
  QString label;

  // "breaks" list contains all values at class breaks plus maximum as last break
  int i = 0;
  for ( QList<double>::iterator it = breaks.begin(); it != breaks.end(); ++it, ++i )
  {
    lower = upper; // upper border from last interval
    upper = *it;
    if ( mode == StdDev )
    {
      if ( i == 0 )
      {
        label = "< " + QString::number( labels[i], 'i', 0 ) + " Std Dev";
      }
      else if ( i == labels.count() - 1 )
      {
        label = ">= " + QString::number( labels[i-1], 'i', 0 ) + " Std Dev";
      }
      else
      {
        label = QString::number( labels[i-1], 'i', 0 ) + " Std Dev" + " - " + QString::number( labels[i], 'i', 0 ) + " Std Dev";
      }
    }
    else
    {
      label = QString::number( lower, 'f', 4 ) + " - " + QString::number( upper, 'f', 4 );
    }

    QgsSymbolV2* newSymbol = symbol->clone();
    double colorValue = ( breaks.count() > 1 ? ( double ) i / ( breaks.count() - 1 ) : 0 );
    newSymbol->setColor( ramp->color( colorValue ) ); // color from (0 / cl-1) to (cl-1 / cl-1)

    ranges.append( QgsRendererRangeV2( lower, upper, newSymbol, label ) );
  }

  QgsGraduatedSymbolRendererV2* r = new QgsGraduatedSymbolRendererV2( attrName, ranges );
  r->setSourceSymbol( symbol->clone() );
  r->setSourceColorRamp( ramp->clone() );
  r->setMode( mode );
  return r;
}
Exemplo n.º 14
0
void QgsMapToolSelectUtils::setSelectFeatures( QgsMapCanvas* canvas,
    QgsGeometry* selectGeometry,
    bool doContains,
    bool doDifference,
    bool singleSelect )
{
  if ( selectGeometry->type() != QGis::Polygon )
  {
    return;
  }
  QgsVectorLayer* vlayer = QgsMapToolSelectUtils::getCurrentVectorLayer( canvas );
  if ( vlayer == NULL )
  {
    return;
  }

  // toLayerCoordinates will throw an exception for any 'invalid' points in
  // the rubber band.
  // For example, if you project a world map onto a globe using EPSG 2163
  // and then click somewhere off the globe, an exception will be thrown.
  QgsGeometry selectGeomTrans( *selectGeometry );

  if ( canvas->mapSettings().hasCrsTransformEnabled() )
  {
    try
    {
      QgsCoordinateTransform ct( canvas->mapSettings().destinationCrs(), vlayer->crs() );
      selectGeomTrans.transform( ct );
    }
    catch ( QgsCsException &cse )
    {
      Q_UNUSED( cse );
      // catch exception for 'invalid' point and leave existing selection unchanged
      QgsLogger::warning( "Caught CRS exception " + QString( __FILE__ ) + ": " + QString::number( __LINE__ ) );
      QgisApp::instance()->messageBar()->pushMessage(
        QObject::tr( "CRS Exception" ),
        QObject::tr( "Selection extends beyond layer's coordinate system" ),
        QgsMessageBar::WARNING,
        QgisApp::instance()->messageTimeout() );
      return;
    }
  }

  QApplication::setOverrideCursor( Qt::WaitCursor );

  QgsDebugMsg( "Selection layer: " + vlayer->name() );
  QgsDebugMsg( "Selection polygon: " + selectGeomTrans.exportToWkt() );
  QgsDebugMsg( "doContains: " + QString( doContains ? "T" : "F" ) );
  QgsDebugMsg( "doDifference: " + QString( doDifference ? "T" : "F" ) );

  QgsRenderContext context = QgsRenderContext::fromMapSettings( canvas->mapSettings() );
  QgsFeatureRendererV2* r = vlayer->rendererV2();
  if ( r )
    r->startRender( context, vlayer->fields() );

  QgsFeatureRequest request;
  request.setFilterRect( selectGeomTrans.boundingBox() );
  request.setFlags( QgsFeatureRequest::ExactIntersect );
  if ( r )
    request.setSubsetOfAttributes( r->usedAttributes(), vlayer->fields() );
  else
    request.setSubsetOfAttributes( QgsAttributeList() );

  QgsFeatureIterator fit = vlayer->getFeatures( request );

  QgsFeatureIds newSelectedFeatures;
  QgsFeature f;
  QgsFeatureId closestFeatureId = 0;
  bool foundSingleFeature = false;
  double closestFeatureDist = std::numeric_limits<double>::max();
  while ( fit.nextFeature( f ) )
  {
    // make sure to only use features that are visible
    if ( r && !r->willRenderFeature( f ) )
      continue;

    const QgsGeometry* g = f.constGeometry();
    if ( doContains )
    {
      if ( !selectGeomTrans.contains( g ) )
        continue;
    }
    else
    {
      if ( !selectGeomTrans.intersects( g ) )
        continue;
    }
    if ( singleSelect )
    {
      foundSingleFeature = true;
      double distance = g->distance( selectGeomTrans );
      if ( distance <= closestFeatureDist )
      {
        closestFeatureDist = distance;
        closestFeatureId = f.id();
      }
    }
    else
    {
      newSelectedFeatures.insert( f.id() );
    }
  }
  if ( singleSelect && foundSingleFeature )
  {
    newSelectedFeatures.insert( closestFeatureId );
  }

  if ( r )
    r->stopRender( context );

  QgsDebugMsg( "Number of new selected features: " + QString::number( newSelectedFeatures.size() ) );

  if ( doDifference )
  {
    QgsFeatureIds layerSelectedFeatures = vlayer->selectedFeaturesIds();

    QgsFeatureIds selectedFeatures;
    QgsFeatureIds deselectedFeatures;

    QgsFeatureIds::const_iterator i = newSelectedFeatures.constEnd();
    while ( i != newSelectedFeatures.constBegin() )
    {
      --i;
      if ( layerSelectedFeatures.contains( *i ) )
      {
        deselectedFeatures.insert( *i );
      }
      else
      {
        selectedFeatures.insert( *i );
      }
    }

    vlayer->modifySelection( selectedFeatures, deselectedFeatures );
  }
  else
  {
    vlayer->setSelectedFeatures( newSelectedFeatures );
  }

  QApplication::restoreOverrideCursor();
}
void QgsAttributeTableFilterModel::generateListOfVisibleFeatures()
{
  if ( !layer() )
    return;

  bool filter = false;
  QgsRectangle rect = mCanvas->mapSettings().mapToLayerCoordinates( layer(), mCanvas->extent() );
  QgsRenderContext renderContext;
  renderContext.expressionContext() << QgsExpressionContextUtils::globalScope()
  << QgsExpressionContextUtils::projectScope()
  << QgsExpressionContextUtils::layerScope( layer() );
  QgsFeatureRendererV2* renderer = layer()->rendererV2();

  mFilteredFeatures.clear();

  if ( !renderer )
  {
    QgsDebugMsg( "Cannot get renderer" );
    return;
  }

  const QgsMapSettings& ms = mCanvas->mapSettings();
  if ( layer()->hasScaleBasedVisibility() &&
       ( layer()->minimumScale() > ms.scale() ||
         layer()->maximumScale() <= ms.scale() ) )
  {
    QgsDebugMsg( "Out of scale limits" );
  }
  else
  {
    if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
    {
      // setup scale
      // mapRenderer()->renderContext()->scale is not automaticaly updated when
      // render extent changes (because it's scale is used to identify if changed
      // since last render) -> use local context
      renderContext.setExtent( ms.visibleExtent() );
      renderContext.setMapToPixel( ms.mapToPixel() );
      renderContext.setRendererScale( ms.scale() );
    }

    filter = renderer && renderer->capabilities() & QgsFeatureRendererV2::Filter;
  }

  renderer->startRender( renderContext, layer()->fields() );

  QgsFeatureRequest r( masterModel()->request() );
  if ( !r.filterRect().isNull() )
  {
    r.setFilterRect( r.filterRect().intersect( &rect ) );
  }
  else
  {
    r.setFilterRect( rect );
  }
  QgsFeatureIterator features = masterModel()->layerCache()->getFeatures( r );

  QgsFeature f;

  while ( features.nextFeature( f ) )
  {
    renderContext.expressionContext().setFeature( f );
    if ( !filter || renderer->willRenderFeature( f, renderContext ) )
    {
      mFilteredFeatures << f.id();
    }
#if 0
    if ( t.elapsed() > 5000 )
    {
      bool cancel = false;
      emit progress( i, cancel );
      if ( cancel )
        break;

      t.restart();
    }
#endif
  }

  features.close();

  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
  {
    renderer->stopRender( renderContext );
  }
}
Exemplo n.º 16
0
void QgsLineVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, const QVector< QgsPoint >& additionalPoints,
    QVector< QgsPoint >& tiedPoint ) const
{
  QgsVectorLayer *vl = mVectorLayer;

  if ( !vl )
    return;

  int featureCount = ( int ) vl->featureCount() * 2;
  int step = 0;

  QgsCoordinateTransform ct;
  ct.setSourceCrs( vl->crs() );
  if ( builder->coordinateTransformationEnabled() )
  {
    ct.setDestinationCrs( builder->destinationCrs() );
  }
  else
  {
    ct.setDestinationCrs( vl->crs() );
  }

  tiedPoint = QVector< QgsPoint >( additionalPoints.size(), QgsPoint( 0.0, 0.0 ) );

  TiePointInfo tmpInfo;
  tmpInfo.mLength = std::numeric_limits<double>::infinity();

  QVector< TiePointInfo > pointLengthMap( additionalPoints.size(), tmpInfo );
  QVector< TiePointInfo >::iterator pointLengthIt;

  //Graph's points;
  QVector< QgsPoint > points;

  QgsFeatureIterator fit = vl->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) );

  // begin: tie points to the graph
  QgsAttributeList la;
  QgsFeature feature;
  while ( fit.nextFeature( feature ) )
  {
    QgsMultiPolyline mpl;
    if ( QgsWkbTypes::flatType( feature.geometry().geometry()->wkbType() ) == QgsWkbTypes::MultiLineString )
      mpl = feature.geometry().asMultiPolyline();
    else if ( QgsWkbTypes::flatType( feature.geometry().geometry()->wkbType() ) == QgsWkbTypes::LineString )
      mpl.push_back( feature.geometry().asPolyline() );

    QgsMultiPolyline::iterator mplIt;
    for ( mplIt = mpl.begin(); mplIt != mpl.end(); ++mplIt )
    {
      QgsPoint pt1, pt2;
      bool isFirstPoint = true;
      QgsPolyline::iterator pointIt;
      for ( pointIt = mplIt->begin(); pointIt != mplIt->end(); ++pointIt )
      {
        pt2 = ct.transform( *pointIt );
        points.push_back( pt2 );

        if ( !isFirstPoint )
        {
          int i = 0;
          for ( i = 0; i != additionalPoints.size(); ++i )
          {
            TiePointInfo info;
            if ( pt1 == pt2 )
            {
              info.mLength = additionalPoints[ i ].sqrDist( pt1 );
              info.mTiedPoint = pt1;
            }
            else
            {
              info.mLength = additionalPoints[ i ].sqrDistToSegment( pt1.x(), pt1.y(),
                             pt2.x(), pt2.y(), info.mTiedPoint );
            }

            if ( pointLengthMap[ i ].mLength > info.mLength )
            {
              Q_UNUSED( info.mTiedPoint );
              info.mFirstPoint = pt1;
              info.mLastPoint = pt2;

              pointLengthMap[ i ] = info;
              tiedPoint[ i ] = info.mTiedPoint;
            }
          }
        }
        pt1 = pt2;
        isFirstPoint = false;
      }
    }
    emit buildProgress( ++step, featureCount );
  }
  // end: tie points to graph

  // add tied point to graph
  int i = 0;
  for ( i = 0; i < tiedPoint.size(); ++i )
  {
    if ( tiedPoint[ i ] != QgsPoint( 0.0, 0.0 ) )
    {
      points.push_back( tiedPoint [ i ] );
    }
  }

  QgsPointCompare pointCompare( builder->topologyTolerance() );

  qSort( points.begin(), points.end(), pointCompare );
  QVector< QgsPoint >::iterator tmp = std::unique( points.begin(), points.end() );
  points.resize( tmp - points.begin() );

  for ( i = 0;i < points.size();++i )
    builder->addVertex( i, points[ i ] );

  for ( i = 0; i < tiedPoint.size() ; ++i )
    tiedPoint[ i ] = *( my_binary_search( points.begin(), points.end(), tiedPoint[ i ], pointCompare ) );

  qSort( pointLengthMap.begin(), pointLengthMap.end(), TiePointInfoCompare );

  {
    // fill attribute list 'la'
    QgsAttributeList tmpAttr;
    if ( mDirectionFieldId != -1 )
    {
      tmpAttr.push_back( mDirectionFieldId );
    }

    QList< QgsArcProperter* >::const_iterator it;
    QgsAttributeList::const_iterator it2;

    for ( it = mProperterList.begin(); it != mProperterList.end(); ++it )
    {
      QgsAttributeList tmp = ( *it )->requiredAttributes();
      for ( it2 = tmp.begin(); it2 != tmp.end(); ++it2 )
      {
        tmpAttr.push_back( *it2 );
      }
    }
    qSort( tmpAttr.begin(), tmpAttr.end() );

    int lastAttrId = -1;
    for ( it2 = tmpAttr.begin(); it2 != tmpAttr.end(); ++it2 )
    {
      if ( *it2 == lastAttrId )
      {
        continue;
      }

      la.push_back( *it2 );

      lastAttrId = *it2;
    }
  } // end fill attribute list 'la'

  // begin graph construction
  fit = vl->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( la ) );
  while ( fit.nextFeature( feature ) )
  {
    int directionType = mDefaultDirection;

    // What direction have feature?
    QString str = feature.attribute( mDirectionFieldId ).toString();
    if ( str == mBothDirectionValue )
    {
      directionType = 3;
    }
    else if ( str == mDirectDirectionValue )
    {
      directionType = 1;
    }
    else if ( str == mReverseDirectionValue )
    {
      directionType = 2;
    }

    // begin features segments and add arc to the Graph;
    QgsMultiPolyline mpl;
    if ( QgsWkbTypes::flatType( feature.geometry().geometry()->wkbType() ) == QgsWkbTypes::MultiLineString )
      mpl = feature.geometry().asMultiPolyline();
    else if ( QgsWkbTypes::flatType( feature.geometry().geometry()->wkbType() ) == QgsWkbTypes::LineString )
      mpl.push_back( feature.geometry().asPolyline() );

    QgsMultiPolyline::iterator mplIt;
    for ( mplIt = mpl.begin(); mplIt != mpl.end(); ++mplIt )
    {
      QgsPoint pt1, pt2;

      bool isFirstPoint = true;
      QgsPolyline::iterator pointIt;
      for ( pointIt = mplIt->begin(); pointIt != mplIt->end(); ++pointIt )
      {
        pt2 = ct.transform( *pointIt );

        if ( !isFirstPoint )
        {
          QMap< double, QgsPoint > pointsOnArc;
          pointsOnArc[ 0.0 ] = pt1;
          pointsOnArc[ pt1.sqrDist( pt2 )] = pt2;

          TiePointInfo t;
          t.mFirstPoint = pt1;
          t.mLastPoint  = pt2;
          t.mLength = 0.0;
          pointLengthIt = my_binary_search( pointLengthMap.begin(), pointLengthMap.end(), t, TiePointInfoCompare );

          if ( pointLengthIt != pointLengthMap.end() )
          {
            QVector< TiePointInfo >::iterator it;
            for ( it = pointLengthIt; it - pointLengthMap.begin() >= 0; --it )
            {
              if ( it->mFirstPoint == pt1 && it->mLastPoint == pt2 )
              {
                pointsOnArc[ pt1.sqrDist( it->mTiedPoint )] = it->mTiedPoint;
              }
            }
            for ( it = pointLengthIt + 1; it != pointLengthMap.end(); ++it )
            {
              if ( it->mFirstPoint == pt1 && it->mLastPoint == pt2 )
              {
                pointsOnArc[ pt1.sqrDist( it->mTiedPoint )] = it->mTiedPoint;
              }
            }
          }

          QMap< double, QgsPoint >::iterator pointsIt;
          QgsPoint pt1;
          QgsPoint pt2;
          int pt1idx = -1, pt2idx = -1;
          bool isFirstPoint = true;
          for ( pointsIt = pointsOnArc.begin(); pointsIt != pointsOnArc.end(); ++pointsIt )
          {
            pt2 = *pointsIt;
            tmp = my_binary_search( points.begin(), points.end(), pt2, pointCompare );
            pt2 = *tmp;
            pt2idx = tmp - points.begin();

            if ( !isFirstPoint && pt1 != pt2 )
            {
              double distance = builder->distanceArea()->measureLine( pt1, pt2 );
              QVector< QVariant > prop;
              QList< QgsArcProperter* >::const_iterator it;
              for ( it = mProperterList.begin(); it != mProperterList.end(); ++it )
              {
                prop.push_back(( *it )->property( distance, feature ) );
              }

              if ( directionType == 1 ||
                   directionType == 3 )
              {
                builder->addArc( pt1idx, pt1, pt2idx, pt2, prop );
              }
              if ( directionType == 2 ||
                   directionType == 3 )
              {
                builder->addArc( pt2idx, pt2, pt1idx, pt1, prop );
              }
            }
            pt1idx = pt2idx;
            pt1 = pt2;
            isFirstPoint = false;
          }
        } // if ( !isFirstPoint )
        pt1 = pt2;
        isFirstPoint = false;
      } // for (it = pl.begin(); it != pl.end(); ++it)
    }
    emit buildProgress( ++step, featureCount );
  } // while( vl->nextFeature(feature) )
} // makeGraph( QgsGraphBuilderInterface *builder, const QVector< QgsPoint >& additionalPoints, QVector< QgsPoint >& tiedPoint )