void topolTest::fillFeatureList( QgsVectorLayer *layer, const QgsRectangle &extent ) { QgsFeatureIterator fit; if ( extent.isEmpty() ) { fit = layer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) ); } else { fit = layer->getFeatures( QgsFeatureRequest() .setFilterRect( extent ) .setFlags( QgsFeatureRequest::ExactIntersect ) .setSubsetOfAttributes( QgsAttributeList() ) ); } QgsFeature f; while ( fit.nextFeature( f ) ) { if ( f.hasGeometry() ) { mFeatureList1 << FeatureLayer( layer, f ); } } }
bool QgsReclassifyByLayerAlgorithm::_prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * ) { std::unique_ptr< QgsFeatureSource >tableSource( parameterAsSource( parameters, QStringLiteral( "INPUT_TABLE" ), context ) ); if ( !tableSource ) throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT_TABLE" ) ) ); QString fieldMin = parameterAsString( parameters, QStringLiteral( "MIN_FIELD" ), context ); mMinFieldIdx = tableSource->fields().lookupField( fieldMin ); if ( mMinFieldIdx < 0 ) throw QgsProcessingException( QObject::tr( "Invalid field specified for MIN_FIELD: %1" ).arg( fieldMin ) ); QString fieldMax = parameterAsString( parameters, QStringLiteral( "MAX_FIELD" ), context ); mMaxFieldIdx = tableSource->fields().lookupField( fieldMax ); if ( mMaxFieldIdx < 0 ) throw QgsProcessingException( QObject::tr( "Invalid field specified for MAX_FIELD: %1" ).arg( fieldMax ) ); QString fieldValue = parameterAsString( parameters, QStringLiteral( "VALUE_FIELD" ), context ); mValueFieldIdx = tableSource->fields().lookupField( fieldValue ); if ( mValueFieldIdx < 0 ) throw QgsProcessingException( QObject::tr( "Invalid field specified for VALUE_FIELD: %1" ).arg( fieldValue ) ); QgsFeatureRequest request; request.setFlags( QgsFeatureRequest::NoGeometry ); request.setSubsetOfAttributes( QgsAttributeList() << mMinFieldIdx << mMaxFieldIdx << mValueFieldIdx ); mTableIterator = tableSource->getFeatures( request ); return true; }
QgsFeaturePool::QgsFeaturePool( QgsVectorLayer *layer, double layerToMapUnits, const QgsCoordinateTransform &layerToMapTransform, bool selectedOnly ) : mFeatureCache( CACHE_SIZE ) , mLayer( layer ) , mLayerToMapUnits( layerToMapUnits ) , mLayerToMapTransform( layerToMapTransform ) , mSelectedOnly( selectedOnly ) { if ( selectedOnly ) { mFeatureIds = layer->selectedFeatureIds(); } else { mFeatureIds = layer->allFeatureIds(); } // Build spatial index QgsFeature feature; QgsFeatureRequest req; req.setSubsetOfAttributes( QgsAttributeList() ); QgsFeatureIterator it = layer->getFeatures( req ); while ( it.nextFeature( feature ) ) { if ( mFeatureIds.contains( feature.id() ) && feature.geometry() ) { mIndex.insertFeature( feature ); } else { mFeatureIds.remove( feature.id() ); } } }
void QgsAttributeTableDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const { QgsVectorLayer *vl = layer( model ); if ( !vl ) return; int fieldIdx = model->data( index, QgsAttributeTableModel::FieldIndexRole ).toInt(); QgsFeatureId fid = model->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong(); QVariant oldValue = model->data( index, Qt::EditRole ); QVariant newValue; QgsEditorWidgetWrapper *eww = QgsEditorWidgetWrapper::fromWidget( editor ); if ( !eww ) return; newValue = eww->value(); if ( ( oldValue != newValue && newValue.isValid() ) || oldValue.isNull() != newValue.isNull() ) { // This fixes https://issues.qgis.org/issues/16492 QgsFeatureRequest request( fid ); request.setFlags( QgsFeatureRequest::NoGeometry ); request.setSubsetOfAttributes( QgsAttributeList() ); QgsFeature feature; vl->getFeatures( request ).nextFeature( feature ); if ( feature.isValid() ) { vl->beginEditCommand( tr( "Attribute changed" ) ); vl->changeAttributeValue( fid, fieldIdx, newValue, oldValue ); vl->endEditCommand(); } } }
void QgsAttributeTypeLoadDialog::loadDataToValueMap() { mValueMap.clear(); int idx = keyComboBox->itemData( keyComboBox->currentIndex() ).toInt(); int idx2 = valueComboBox->itemData( valueComboBox->currentIndex() ).toInt(); QgsMapLayer* dataLayer = QgsMapLayerRegistry::instance()->mapLayer( layerComboBox->currentText() ); QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer *>( dataLayer ); if ( vLayer == NULL ) { return; } QgsVectorDataProvider* dataProvider = vLayer->dataProvider(); dataProvider->enableGeometrylessFeatures( true ); QgsAttributeList attributeList = QgsAttributeList(); attributeList.append( idx ); attributeList.append( idx2 ); vLayer->select( attributeList, QgsRectangle(), false ); QgsFeature f; while ( vLayer->nextFeature( f ) ) { QVariant val = f.attributeMap()[idx]; if ( val.isValid() && !val.isNull() && !val.toString().isEmpty() ) { mValueMap.insert( f.attributeMap()[idx2].toString(), val ); } } dataProvider->enableGeometrylessFeatures( false ); }
QgsVectorLayerFeatureSource::QgsVectorLayerFeatureSource( const QgsVectorLayer *layer ) { QMutexLocker locker( &layer->mFeatureSourceConstructorMutex ); mProviderFeatureSource = layer->dataProvider()->featureSource(); mFields = layer->fields(); mId = layer->id(); // update layer's join caches if necessary if ( layer->mJoinBuffer->containsJoins() ) layer->mJoinBuffer->createJoinCaches(); mJoinBuffer = layer->mJoinBuffer->clone(); mExpressionFieldBuffer = new QgsExpressionFieldBuffer( *layer->mExpressionFieldBuffer ); mCrs = layer->crs(); mHasEditBuffer = layer->editBuffer(); if ( mHasEditBuffer ) { #if 0 // TODO[MD]: after merge if ( request.filterType() == QgsFeatureRequest::FilterFid ) { // only copy relevant parts if ( L->editBuffer()->addedFeatures().contains( request.filterFid() ) ) mAddedFeatures.insert( request.filterFid(), L->editBuffer()->addedFeatures()[ request.filterFid()] ); if ( L->editBuffer()->changedGeometries().contains( request.filterFid() ) ) mChangedGeometries.insert( request.filterFid(), L->editBuffer()->changedGeometries()[ request.filterFid()] ); if ( L->editBuffer()->deletedFeatureIds().contains( request.filterFid() ) ) mDeletedFeatureIds.insert( request.filterFid() ); if ( L->editBuffer()->changedAttributeValues().contains( request.filterFid() ) ) mChangedAttributeValues.insert( request.filterFid(), L->editBuffer()->changedAttributeValues()[ request.filterFid()] ); if ( L->editBuffer()->changedAttributeValues().contains( request.filterFid() ) ) mChangedFeaturesRequest.setFilterFids( QgsFeatureIds() << request.filterFid() ); } else { #endif mAddedFeatures = QgsFeatureMap( layer->editBuffer()->addedFeatures() ); mChangedGeometries = QgsGeometryMap( layer->editBuffer()->changedGeometries() ); mDeletedFeatureIds = QgsFeatureIds( layer->editBuffer()->deletedFeatureIds() ); mChangedAttributeValues = QgsChangedAttributesMap( layer->editBuffer()->changedAttributeValues() ); mAddedAttributes = QList<QgsField>( layer->editBuffer()->addedAttributes() ); mDeletedAttributeIds = QgsAttributeList( layer->editBuffer()->deletedAttributeIds() ); #if 0 } #endif } std::unique_ptr< QgsExpressionContextScope > layerScope( QgsExpressionContextUtils::layerScope( layer ) ); mLayerScope = *layerScope; }
void QgsVectorLayerRenderer::prepareLabeling( QgsVectorLayer* layer, QStringList& attributeNames ) { if ( !mContext.labelingEngine() ) { if ( QgsLabelingEngineV2* engine2 = mContext.labelingEngineV2() ) { if ( layer->labeling() ) { mLabelProvider = layer->labeling()->provider( layer ); if ( mLabelProvider ) { engine2->addProvider( mLabelProvider ); if ( !mLabelProvider->prepare( mContext, attributeNames ) ) { engine2->removeProvider( mLabelProvider ); mLabelProvider = nullptr; // deleted by engine } } } } return; } if ( mContext.labelingEngine()->prepareLayer( layer, attributeNames, mContext ) ) { mLabeling = true; #if 0 // TODO: limit of labels, font not found QgsPalLayerSettings& palyr = mContext.labelingEngine()->layer( mLayerID ); // see if feature count limit is set for labeling if ( palyr.limitNumLabels && palyr.maxNumLabels > 0 ) { QgsFeatureIterator fit = getFeatures( QgsFeatureRequest() .setFilterRect( mContext.extent() ) .setSubsetOfAttributes( QgsAttributeList() ) ); // total number of features that may be labeled QgsFeature f; int nFeatsToLabel = 0; while ( fit.nextFeature( f ) ) { nFeatsToLabel++; } palyr.mFeaturesToLabel = nFeatsToLabel; } // notify user about any font substitution if ( !palyr.mTextFontFound && !mLabelFontNotFoundNotified ) { emit labelingFontNotFound( this, palyr.mTextFontFamily ); mLabelFontNotFoundNotified = true; } #endif } }
void QgsMapToolSimplify::canvasPressEvent( QMouseEvent * e ) { QgsVectorLayer * vlayer = currentVectorLayer(); QgsPoint layerCoords = mCanvas->getCoordinateTransform()->toMapPoint( e->pos().x(), e->pos().y() ); double r = QgsTolerance::vertexSearchRadius( vlayer, mCanvas->mapRenderer() ); QgsRectangle selectRect = QgsRectangle( layerCoords.x() - r, layerCoords.y() - r, layerCoords.x() + r, layerCoords.y() + r ); vlayer->select( QgsAttributeList(), selectRect, true ); QgsGeometry* geometry = QgsGeometry::fromPoint( layerCoords ); double minDistance = DBL_MAX; double currentDistance; QgsFeature f; mSelectedFeature.setValid( false ); while ( vlayer->nextFeature( f ) ) { currentDistance = geometry->distance( *( f.geometry() ) ); if ( currentDistance < minDistance ) { minDistance = currentDistance; mSelectedFeature = f; } } // delete previous rubberband (if any) removeRubberBand(); if ( mSelectedFeature.isValid() ) { if ( mSelectedFeature.geometry()->isMultipart() ) { QMessageBox::critical( 0, tr( "Unsupported operation" ), tr( "Multipart features are not supported for simplification." ) ); return; } mRubberBand = new QgsRubberBand( mCanvas ); mRubberBand->setToGeometry( mSelectedFeature.geometry(), 0 ); mRubberBand->setColor( Qt::red ); mRubberBand->setWidth( 2 ); mRubberBand->show(); //calculate boudaries for slidebar if ( calculateSliderBoudaries() ) { // show dialog as a non-modal window mSimplifyDialog->show(); } else { QMessageBox::warning( 0, tr( "Unsupported operation" ), tr( "This feature cannot be simplified. Check if feature has enough vertices to be simplified." ) ); } } }
void QgsAttributeTypeLoadDialog::createPreview( int fieldIndex, bool full ) { previewTableWidget->clearContents(); for ( int i = previewTableWidget->rowCount() - 1; i > 0; i-- ) { previewTableWidget->removeRow( i ); } if ( layerComboBox->currentIndex() < 0 || fieldIndex < 0 ) { //when nothing is selected there is no reason for preview return; } int idx = keyComboBox->itemData( keyComboBox->currentIndex() ).toInt(); int idx2 = valueComboBox->itemData( valueComboBox->currentIndex() ).toInt(); QgsMapLayer* dataLayer = QgsMapLayerRegistry::instance()->mapLayer( layerComboBox->currentText() ); QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer *>( dataLayer ); if ( vLayer == NULL ) { return; } QgsVectorDataProvider* dataProvider = vLayer->dataProvider(); dataProvider->enableGeometrylessFeatures( true ); QgsAttributeList attributeList = QgsAttributeList(); attributeList.append( idx ); attributeList.append( idx2 ); vLayer->select( attributeList, QgsRectangle(), false ); QgsFeature f; QMap<QString, QVariant> valueMap; while ( vLayer->nextFeature( f ) ) { QVariant val1 = f.attributeMap()[idx]; QVariant val2 = f.attributeMap()[idx2]; if ( val1.isValid() && !val1.isNull() && !val1.toString().isEmpty() && val2.isValid() && !val2.isNull() && !val2.toString().isEmpty() ) { valueMap.insert( val1.toString(), val2.toString() ); } if ( !full && valueMap.size() > 8 ) break; //just first entries all on button } int row = 0; for ( QMap<QString, QVariant>::iterator mit = valueMap.begin(); mit != valueMap.end(); mit++, row++ ) { previewTableWidget->insertRow( row ); previewTableWidget->setItem( row, 0, new QTableWidgetItem( mit.value().toString() ) ); previewTableWidget->setItem( row, 1, new QTableWidgetItem( mit.key() ) ); } dataProvider->enableGeometrylessFeatures( false ); }
int QgsGeometrySnapperSingleSource::run( const QgsFeatureSource &source, QgsFeatureSink &sink, double thresh, QgsFeedback *feedback ) { // the logic here comes from GRASS implementation of Vect_snap_lines_list() int count = 0; int totalCount = source.featureCount() * 2; // step 1: record all point locations in a spatial index + extra data structure to keep // reference to which other point they have been snapped to (in the next phase). QgsSpatialIndex index; QVector<AnchorPoint> pnts; QgsFeatureRequest request; request.setSubsetOfAttributes( QgsAttributeList() ); QgsFeatureIterator fi = source.getFeatures( request ); buildSnapIndex( fi, index, pnts, feedback, count, totalCount ); if ( feedback->isCanceled() ) return 0; // step 2: go through all registered points and if not yet marked mark it as anchor and // assign this anchor to all not yet marked points in threshold assignAnchors( index, pnts, thresh ); // step 3: alignment of vertices and segments to the anchors // Go through all lines and: // 1) for all vertices: if not anchor snap it to its anchor // 2) for all segments: snap it to all anchors in threshold (except anchors of vertices of course) int modified = 0; QgsFeature f; fi = source.getFeatures(); while ( fi.nextFeature( f ) ) { if ( feedback->isCanceled() ) break; QgsGeometry geom = f.geometry(); if ( snapGeometry( geom.get(), index, pnts, thresh ) ) { f.setGeometry( geom ); ++modified; } sink.addFeature( f, QgsFeatureSink::FastInsert ); ++count; feedback->setProgress( 100. * count / totalCount ); } return modified; }
QgsSpatialIndex *topolTest::createIndex( QgsVectorLayer *layer, const QgsRectangle &extent ) { QgsSpatialIndex *index = new QgsSpatialIndex(); QgsFeatureIterator fit; if ( extent.isEmpty() ) { fit = layer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) ); } else { fit = layer->getFeatures( QgsFeatureRequest() .setFilterRect( extent ) .setFlags( QgsFeatureRequest::ExactIntersect ) .setSubsetOfAttributes( QgsAttributeList() ) ); } int i = 0; QgsFeature f; while ( fit.nextFeature( f ) ) { if ( !( ++i % 100 ) ) emit progress( i ); if ( testCanceled() ) { delete index; return nullptr; } if ( f.hasGeometry() ) { index->addFeature( f ); mFeatureMap2[f.id()] = FeatureLayer( layer, f ); } } return index; }
void QgsExpressionSelectionDialog::mButtonZoomToFeatures_clicked() { if ( mExpressionBuilder->expressionText().isEmpty() || !mMapCanvas ) return; QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( mLayer ) ); QgsFeatureRequest request = QgsFeatureRequest().setFilterExpression( mExpressionBuilder->expressionText() ) .setExpressionContext( context ) .setSubsetOfAttributes( QgsAttributeList() ); QgsFeatureIterator features = mLayer->getFeatures( request ); QgsRectangle bbox; bbox.setMinimal(); QgsFeature feat; int featureCount = 0; while ( features.nextFeature( feat ) ) { QgsGeometry geom = feat.geometry(); if ( geom.isNull() || geom.constGet()->isEmpty() ) continue; QgsRectangle r = mMapCanvas->mapSettings().layerExtentToOutputExtent( mLayer, geom.boundingBox() ); bbox.combineExtentWith( r ); featureCount++; } features.close(); QgsSettings settings; int timeout = settings.value( QStringLiteral( "qgis/messageTimeout" ), 5 ).toInt(); if ( featureCount > 0 ) { mMapCanvas->zoomToFeatureExtent( bbox ); if ( mMessageBar ) { mMessageBar->pushMessage( QString(), tr( "Zoomed to %n matching feature(s)", "number of matching features", featureCount ), Qgis::Info, timeout ); } } else if ( mMessageBar ) { mMessageBar->pushMessage( QString(), tr( "No matching features found" ), Qgis::Info, timeout ); } saveRecent(); }
bool QgsMapToolShowHideLabels::selectedFeatures( QgsVectorLayer* vlayer, QgsFeatureIds& selectedFeatIds ) { // culled from QgsMapToolSelectUtils::setSelectFeatures() QgsGeometry* selectGeometry = mRubberBand->asGeometry(); // 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 ( mCanvas->hasCrsTransformEnabled() ) { try { QgsCoordinateTransform ct( mCanvas->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__ ) ); emit messageEmitted( tr( "CRS Exception: selection extends beyond layer's coordinate system." ), QgsMessageBar::WARNING ); return false; } } QApplication::setOverrideCursor( Qt::WaitCursor ); QgsDebugMsg( "Selection layer: " + vlayer->name() ); QgsDebugMsg( "Selection polygon: " + selectGeomTrans.exportToWkt() ); QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest() .setFilterRect( selectGeomTrans.boundingBox() ) .setFlags( QgsFeatureRequest::NoGeometry | QgsFeatureRequest::ExactIntersect ) .setSubsetOfAttributes( QgsAttributeList() ) ); QgsFeature f; while ( fit.nextFeature( f ) ) { selectedFeatIds.insert( f.id() ); } QApplication::restoreOverrideCursor(); return true; }
QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* layer, const QgsFeatureRequest& request ) : QgsAbstractFeatureIterator( request ), L( layer ) { QgsVectorLayerJoinBuffer* joinBuffer = L->mJoinBuffer; if ( L->editBuffer() ) { mAddedFeatures = QgsFeatureMap( L->editBuffer()->addedFeatures() ); mChangedGeometries = QgsGeometryMap( L->editBuffer()->changedGeometries() ); mDeletedFeatureIds = QgsFeatureIds( L->editBuffer()->deletedFeatureIds() ); mChangedAttributeValues = QgsChangedAttributesMap( L->editBuffer()->changedAttributeValues() ); mAddedAttributes = QList<QgsField>( L->editBuffer()->addedAttributes() ); mDeletedAttributeIds = QgsAttributeList( L->editBuffer()->deletedAttributeIds() ); } // prepare joins: may add more attributes to fetch (in order to allow join) if ( joinBuffer->containsJoins() ) prepareJoins(); // by default provider's request is the same mProviderRequest = mRequest; if ( mProviderRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { // prepare list of attributes to match provider fields QgsAttributeList providerSubset; QgsAttributeList subset = mProviderRequest.subsetOfAttributes(); const QgsFields &pendingFields = L->pendingFields(); int nPendingFields = pendingFields.count(); for ( int i = 0; i < subset.count(); ++i ) { int attrIndex = subset[i]; if ( attrIndex < 0 || attrIndex >= nPendingFields ) continue; if ( L->pendingFields().fieldOrigin( attrIndex ) == QgsFields::OriginProvider ) providerSubset << L->pendingFields().fieldOriginIndex( attrIndex ); } mProviderRequest.setSubsetOfAttributes( providerSubset ); } if ( request.filterType() == QgsFeatureRequest::FilterFid ) { mFetchedFid = false; } else // no filter or filter by rect { mProviderIterator = L->dataProvider()->getFeatures( mProviderRequest ); rewindEditBuffer(); } }
QgsVectorLayerFeatureSource::QgsVectorLayerFeatureSource( QgsVectorLayer *layer ) : mCrsId( 0 ) { mProviderFeatureSource = layer->dataProvider()->featureSource(); mFields = layer->fields(); mJoinBuffer = layer->mJoinBuffer->clone(); mExpressionFieldBuffer = new QgsExpressionFieldBuffer( *layer->mExpressionFieldBuffer ); mCrsId = layer->crs().srsid(); mCanBeSimplified = layer->hasGeometryType() && layer->geometryType() != QGis::Point; mHasEditBuffer = layer->editBuffer(); if ( mHasEditBuffer ) { #if 0 // TODO[MD]: after merge if ( request.filterType() == QgsFeatureRequest::FilterFid ) { // only copy relevant parts if ( L->editBuffer()->addedFeatures().contains( request.filterFid() ) ) mAddedFeatures.insert( request.filterFid(), L->editBuffer()->addedFeatures()[ request.filterFid()] ); if ( L->editBuffer()->changedGeometries().contains( request.filterFid() ) ) mChangedGeometries.insert( request.filterFid(), L->editBuffer()->changedGeometries()[ request.filterFid()] ); if ( L->editBuffer()->deletedFeatureIds().contains( request.filterFid() ) ) mDeletedFeatureIds.insert( request.filterFid() ); if ( L->editBuffer()->changedAttributeValues().contains( request.filterFid() ) ) mChangedAttributeValues.insert( request.filterFid(), L->editBuffer()->changedAttributeValues()[ request.filterFid()] ); if ( L->editBuffer()->changedAttributeValues().contains( request.filterFid() ) ) mChangedFeaturesRequest.setFilterFids( QgsFeatureIds() << request.filterFid() ); } else { #endif mAddedFeatures = QgsFeatureMap( layer->editBuffer()->addedFeatures() ); mChangedGeometries = QgsGeometryMap( layer->editBuffer()->changedGeometries() ); mDeletedFeatureIds = QgsFeatureIds( layer->editBuffer()->deletedFeatureIds() ); mChangedAttributeValues = QgsChangedAttributesMap( layer->editBuffer()->changedAttributeValues() ); mAddedAttributes = QList<QgsField>( layer->editBuffer()->addedAttributes() ); mDeletedAttributeIds = QgsAttributeList( layer->editBuffer()->deletedAttributeIds() ); #if 0 } #endif } }
void QgsReaderFeatures::initReader( bool useSelection ) { if ( useSelection ) { mListSelectedFeature = mLayer->selectedFeatures(); mIterSelectedFeature = mListSelectedFeature.begin(); mFuncNextFeature = &QgsReaderFeatures::nextFeatureSelected; } else { mLayer->select( QgsAttributeList() ); mFuncNextFeature = &QgsReaderFeatures::nextFeatureTotal; } } // void QgsReaderFeatures::initReader()
QgsFeatureIds QgsFeatureSource::allFeatureIds() const { QgsFeatureIterator fit = getFeatures( QgsFeatureRequest() .setFlags( QgsFeatureRequest::NoGeometry ) .setSubsetOfAttributes( QgsAttributeList() ) ); QgsFeatureIds ids; QgsFeature fet; while ( fit.nextFeature( fet ) ) { ids << fet.id(); } return ids; }
QgsRectangle QgsFeatureSource::sourceExtent() const { QgsRectangle r; QgsFeatureRequest req; req.setSubsetOfAttributes( QgsAttributeList() ); QgsFeatureIterator it = getFeatures( req ); QgsFeature f; while ( it.nextFeature( f ) ) { if ( f.hasGeometry() ) r.combineExtentWith( f.geometry().boundingBox() ); } return r; }
void QgsOfflineEditing::updateFidLookup( QgsVectorLayer* remoteLayer, sqlite3* db, int layerId ) { // update fid lookup for added features // get remote added fids // NOTE: use QMap for sorted fids QMap < int, bool /*dummy*/ > newRemoteFids; QgsFeature f; remoteLayer->select( QgsAttributeList(), QgsRectangle(), false, false ); mProgressDialog->setupProgressBar( tr( "%v / %m features processed" ), remoteLayer->featureCount() ); int i = 1; while ( remoteLayer->nextFeature( f ) ) { if ( offlineFid( db, layerId, f.id() ) == -1 ) { newRemoteFids[ f.id()] = true; } mProgressDialog->setProgressValue( i++ ); } // get local added fids // NOTE: fids are sorted QString sql = QString( "SELECT \"fid\" FROM 'log_added_features' WHERE \"layer_id\" = %1" ).arg( layerId ); QList<int> newOfflineFids = sqlQueryInts( db, sql ); if ( newRemoteFids.size() != newOfflineFids.size() ) { //showWarning( QString( "Different number of new features on offline layer (%1) and remote layer (%2)" ).arg(newOfflineFids.size()).arg(newRemoteFids.size()) ); } else { // add new fid lookups i = 0; sqlExec( db, "BEGIN" ); for ( QMap<int, bool>::const_iterator it = newRemoteFids.begin(); it != newRemoteFids.end(); ++it ) { addFidLookup( db, layerId, newOfflineFids.at( i++ ), it.key() ); } sqlExec( db, "COMMIT" ); } }
QSet<QVariant> QgsFeatureSource::uniqueValues( int fieldIndex, int limit ) const { if ( fieldIndex < 0 || fieldIndex >= fields().count() ) return QSet<QVariant>(); QgsFeatureRequest req; req.setFlags( QgsFeatureRequest::NoGeometry ); req.setSubsetOfAttributes( QgsAttributeList() << fieldIndex ); QSet<QVariant> values; QgsFeatureIterator it = getFeatures( req ); QgsFeature f; while ( it.nextFeature( f ) ) { values.insert( f.attribute( fieldIndex ) ); if ( limit > 0 && values.size() >= limit ) return values; } return values; }
QVariant QgsFeatureSource::minimumValue( int fieldIndex ) const { if ( fieldIndex < 0 || fieldIndex >= fields().count() ) return QVariant(); QgsFeatureRequest req; req.setFlags( QgsFeatureRequest::NoGeometry ); req.setSubsetOfAttributes( QgsAttributeList() << fieldIndex ); QVariant min; QgsFeatureIterator it = getFeatures( req ); QgsFeature f; while ( it.nextFeature( f ) ) { QVariant v = f.attribute( fieldIndex ); if ( v.isValid() && qgsVariantLessThan( v, min ) ) { min = v; } } return min; }
QVariant QgsFeatureSource::maximumValue( int fieldIndex ) const { if ( fieldIndex < 0 || fieldIndex >= fields().count() ) return QVariant(); QgsFeatureRequest req; req.setFlags( QgsFeatureRequest::NoGeometry ); req.setSubsetOfAttributes( QgsAttributeList() << fieldIndex ); QVariant max; QgsFeatureIterator it = getFeatures( req ); QgsFeature f; while ( it.nextFeature( f ) ) { QVariant v = f.attribute( fieldIndex ); if ( !v.isNull() && ( qgsVariantGreaterThan( v, max ) || max.isNull() ) ) { max = v; } } return max; }
QgsFeaturePool::QgsFeaturePool( QgsVectorLayer *layer, bool selectedOnly ) : mFeatureCache( sCacheSize ), mLayer( layer ), mSelectedOnly( selectedOnly ) { if ( selectedOnly ) { mFeatureIds = layer->selectedFeaturesIds(); } else { mFeatureIds = layer->allFeatureIds(); } // Build spatial index QgsFeature feature; QgsFeatureRequest req; req.setSubsetOfAttributes( QgsAttributeList() ); QgsFeatureIterator it = layer->getFeatures( req ); while ( it.nextFeature( feature ) ) { mIndex.insertFeature( feature ); } }
void QgsVectorLayerUndoCommandChangeAttribute::undo() { QVariant original = mOldValue; if ( FID_IS_NEW( mFid ) ) { // added feature QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.find( mFid ); Q_ASSERT( it != mBuffer->mAddedFeatures.end() ); it.value().setAttribute( mFieldIndex, mOldValue ); } else if ( mFirstChange ) { // existing feature mBuffer->mChangedAttributeValues[mFid].remove( mFieldIndex ); if ( mBuffer->mChangedAttributeValues[mFid].isEmpty() ) mBuffer->mChangedAttributeValues.remove( mFid ); if ( !mOldValue.isValid() ) { // get old value from provider QgsFeature tmp; QgsFeatureRequest request; request.setFilterFid( mFid ); request.setFlags( QgsFeatureRequest::NoGeometry ); request.setSubsetOfAttributes( QgsAttributeList() << mFieldIndex ); QgsFeatureIterator fi = layer()->getFeatures( request ); if ( fi.nextFeature( tmp ) ) original = tmp.attribute( mFieldIndex ); } } else { mBuffer->mChangedAttributeValues[mFid][mFieldIndex] = mOldValue; } emit mBuffer->attributeValueChanged( mFid, mFieldIndex, original ); }
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 ) { QgsWkbTypes::Type memoryProviderType = QgsWkbTypes::MultiLineString; if ( locationField2 == -1 ) { memoryProviderType = forceSingleGeometry ? QgsWkbTypes::Point : QgsWkbTypes::MultiPoint; } else { memoryProviderType = forceSingleGeometry ? QgsWkbTypes::LineString : QgsWkbTypes::MultiLineString; } 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; 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->geometry() ); } else { lrsGeom = locateBetweenMeasures( measure1, measure2, featureIdIt->geometry() ); } if ( !lrsGeom.isEmpty() ) { ++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; }
bool QgsGeometryAnalyzer::centroids( QgsVectorLayer* layer, const QString& shapefileName, bool onlySelectedFeatures, QProgressDialog* p ) { if ( !layer ) { QgsDebugMsg( "No layer passed to centroids" ); return false; } QgsVectorDataProvider* dp = layer->dataProvider(); if ( !dp ) { QgsDebugMsg( "No data provider for layer passed to centroids" ); return false; } QgsWkbTypes::Type outputType = QgsWkbTypes::Point; 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; } centroidFeature( currentFeature, &vWriter ); ++processedFeatures; } if ( p ) { p->setValue( selection.size() ); } } //take all features else { QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) ); 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; } centroidFeature( currentFeature, &vWriter ); ++processedFeatures; } if ( p ) { p->setValue( featureCount ); } } return true; }
void QgsVectorLayerUndoCommandChangeGeometry::undo() { if ( FID_IS_NEW( mFid ) ) { // modify added features QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.find( mFid ); Q_ASSERT( it != mBuffer->mAddedFeatures.end() ); it.value().setGeometry( mOldGeom ); cache()->cacheGeometry( mFid, mOldGeom ); emit mBuffer->geometryChanged( mFid, mOldGeom ); } else { // existing feature if ( mOldGeom.isEmpty() ) { mBuffer->mChangedGeometries.remove( mFid ); QgsFeature f; if ( layer()->getFeatures( QgsFeatureRequest().setFilterFid( mFid ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) && f.hasGeometry() ) { cache()->cacheGeometry( mFid, f.geometry() ); emit mBuffer->geometryChanged( mFid, f.geometry() ); } } else { mBuffer->mChangedGeometries[mFid] = mOldGeom; cache()->cacheGeometry( mFid, mOldGeom ); emit mBuffer->geometryChanged( mFid, mOldGeom ); } } }
QgsAbstractGeometryV2* QgsGeometryEditUtils::avoidIntersections( const QgsAbstractGeometryV2& geom, QMap<QgsVectorLayer*, QSet<QgsFeatureId> > ignoreFeatures ) { QScopedPointer<QgsGeometryEngine> geomEngine( QgsGeometry::createGeometryEngine( &geom ) ); if ( geomEngine.isNull() ) { return nullptr; } QgsWKBTypes::Type geomTypeBeforeModification = geom.wkbType(); //check if g has polygon type if ( QgsWKBTypes::geometryType( geomTypeBeforeModification ) != QgsWKBTypes::PolygonGeometry ) { return nullptr; } //read avoid intersections list from project properties bool listReadOk; QStringList avoidIntersectionsList = QgsProject::instance()->readListEntry( "Digitizing", "/AvoidIntersectionsList", QStringList(), &listReadOk ); if ( !listReadOk ) return nullptr; //no intersections stored in project does not mean error QList< QgsAbstractGeometryV2* > nearGeometries; //go through list, convert each layer to vector layer and call QgsVectorLayer::removePolygonIntersections for each QgsVectorLayer* currentLayer = nullptr; QStringList::const_iterator aIt = avoidIntersectionsList.constBegin(); for ( ; aIt != avoidIntersectionsList.constEnd(); ++aIt ) { currentLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( *aIt ) ); if ( currentLayer ) { QgsFeatureIds ignoreIds; QMap<QgsVectorLayer*, QSet<qint64> >::const_iterator ignoreIt = ignoreFeatures.find( currentLayer ); if ( ignoreIt != ignoreFeatures.constEnd() ) ignoreIds = ignoreIt.value(); QgsFeatureIterator fi = currentLayer->getFeatures( QgsFeatureRequest( geom.boundingBox() ) .setFlags( QgsFeatureRequest::ExactIntersect ) .setSubsetOfAttributes( QgsAttributeList() ) ); QgsFeature f; while ( fi.nextFeature( f ) ) { if ( ignoreIds.contains( f.id() ) ) continue; if ( !f.hasGeometry() ) continue; nearGeometries << f.geometry().geometry()->clone(); } } } if ( nearGeometries.isEmpty() ) { return nullptr; } QgsAbstractGeometryV2* combinedGeometries = geomEngine.data()->combine( nearGeometries ); qDeleteAll( nearGeometries ); if ( !combinedGeometries ) { return nullptr; } QgsAbstractGeometryV2* diffGeom = geomEngine.data()->difference( *combinedGeometries ); delete combinedGeometries; return diffGeom; }
int QgsZonalStatistics::calculateStatistics( QgsFeedback *feedback ) { if ( !mPolygonLayer || mPolygonLayer->geometryType() != QgsWkbTypes::PolygonGeometry ) { return 1; } QgsVectorDataProvider *vectorProvider = mPolygonLayer->dataProvider(); if ( !vectorProvider ) { return 2; } if ( !mRasterLayer ) { return 3; } if ( mRasterLayer->bandCount() < mRasterBand ) { return 4; } mRasterProvider = mRasterLayer->dataProvider(); mInputNodataValue = mRasterProvider->sourceNoDataValue( mRasterBand ); //get geometry info about raster layer int nCellsXProvider = mRasterProvider->xSize(); int nCellsYProvider = mRasterProvider->ySize(); double cellsizeX = mRasterLayer->rasterUnitsPerPixelX(); if ( cellsizeX < 0 ) { cellsizeX = -cellsizeX; } double cellsizeY = mRasterLayer->rasterUnitsPerPixelY(); if ( cellsizeY < 0 ) { cellsizeY = -cellsizeY; } QgsRectangle rasterBBox = mRasterProvider->extent(); //add the new fields to the provider QList<QgsField> newFieldList; QString countFieldName; if ( mStatistics & QgsZonalStatistics::Count ) { countFieldName = getUniqueFieldName( mAttributePrefix + "count", newFieldList ); QgsField countField( countFieldName, QVariant::Double, QStringLiteral( "double precision" ) ); newFieldList.push_back( countField ); } QString sumFieldName; if ( mStatistics & QgsZonalStatistics::Sum ) { sumFieldName = getUniqueFieldName( mAttributePrefix + "sum", newFieldList ); QgsField sumField( sumFieldName, QVariant::Double, QStringLiteral( "double precision" ) ); newFieldList.push_back( sumField ); } QString meanFieldName; if ( mStatistics & QgsZonalStatistics::Mean ) { meanFieldName = getUniqueFieldName( mAttributePrefix + "mean", newFieldList ); QgsField meanField( meanFieldName, QVariant::Double, QStringLiteral( "double precision" ) ); newFieldList.push_back( meanField ); } QString medianFieldName; if ( mStatistics & QgsZonalStatistics::Median ) { medianFieldName = getUniqueFieldName( mAttributePrefix + "median", newFieldList ); QgsField medianField( medianFieldName, QVariant::Double, QStringLiteral( "double precision" ) ); newFieldList.push_back( medianField ); } QString stdevFieldName; if ( mStatistics & QgsZonalStatistics::StDev ) { stdevFieldName = getUniqueFieldName( mAttributePrefix + "stdev", newFieldList ); QgsField stdField( stdevFieldName, QVariant::Double, QStringLiteral( "double precision" ) ); newFieldList.push_back( stdField ); } QString minFieldName; if ( mStatistics & QgsZonalStatistics::Min ) { minFieldName = getUniqueFieldName( mAttributePrefix + "min", newFieldList ); QgsField minField( minFieldName, QVariant::Double, QStringLiteral( "double precision" ) ); newFieldList.push_back( minField ); } QString maxFieldName; if ( mStatistics & QgsZonalStatistics::Max ) { maxFieldName = getUniqueFieldName( mAttributePrefix + "max", newFieldList ); QgsField maxField( maxFieldName, QVariant::Double, QStringLiteral( "double precision" ) ); newFieldList.push_back( maxField ); } QString rangeFieldName; if ( mStatistics & QgsZonalStatistics::Range ) { rangeFieldName = getUniqueFieldName( mAttributePrefix + "range", newFieldList ); QgsField rangeField( rangeFieldName, QVariant::Double, QStringLiteral( "double precision" ) ); newFieldList.push_back( rangeField ); } QString minorityFieldName; if ( mStatistics & QgsZonalStatistics::Minority ) { minorityFieldName = getUniqueFieldName( mAttributePrefix + "minority", newFieldList ); QgsField minorityField( minorityFieldName, QVariant::Double, QStringLiteral( "double precision" ) ); newFieldList.push_back( minorityField ); } QString majorityFieldName; if ( mStatistics & QgsZonalStatistics::Majority ) { majorityFieldName = getUniqueFieldName( mAttributePrefix + "majority", newFieldList ); QgsField majField( majorityFieldName, QVariant::Double, QStringLiteral( "double precision" ) ); newFieldList.push_back( majField ); } QString varietyFieldName; if ( mStatistics & QgsZonalStatistics::Variety ) { varietyFieldName = getUniqueFieldName( mAttributePrefix + "variety", newFieldList ); QgsField varietyField( varietyFieldName, QVariant::Int, QStringLiteral( "int" ) ); newFieldList.push_back( varietyField ); } QString varianceFieldName; if ( mStatistics & QgsZonalStatistics::Variance ) { varianceFieldName = getUniqueFieldName( mAttributePrefix + "variance", newFieldList ); QgsField varianceField( varianceFieldName, QVariant::Double, QStringLiteral( "double precision" ) ); newFieldList.push_back( varianceField ); } vectorProvider->addAttributes( newFieldList ); //index of the new fields int countIndex = mStatistics & QgsZonalStatistics::Count ? vectorProvider->fieldNameIndex( countFieldName ) : -1; int sumIndex = mStatistics & QgsZonalStatistics::Sum ? vectorProvider->fieldNameIndex( sumFieldName ) : -1; int meanIndex = mStatistics & QgsZonalStatistics::Mean ? vectorProvider->fieldNameIndex( meanFieldName ) : -1; int medianIndex = mStatistics & QgsZonalStatistics::Median ? vectorProvider->fieldNameIndex( medianFieldName ) : -1; int stdevIndex = mStatistics & QgsZonalStatistics::StDev ? vectorProvider->fieldNameIndex( stdevFieldName ) : -1; int minIndex = mStatistics & QgsZonalStatistics::Min ? vectorProvider->fieldNameIndex( minFieldName ) : -1; int maxIndex = mStatistics & QgsZonalStatistics::Max ? vectorProvider->fieldNameIndex( maxFieldName ) : -1; int rangeIndex = mStatistics & QgsZonalStatistics::Range ? vectorProvider->fieldNameIndex( rangeFieldName ) : -1; int minorityIndex = mStatistics & QgsZonalStatistics::Minority ? vectorProvider->fieldNameIndex( minorityFieldName ) : -1; int majorityIndex = mStatistics & QgsZonalStatistics::Majority ? vectorProvider->fieldNameIndex( majorityFieldName ) : -1; int varietyIndex = mStatistics & QgsZonalStatistics::Variety ? vectorProvider->fieldNameIndex( varietyFieldName ) : -1; int varianceIndex = mStatistics & QgsZonalStatistics::Variance ? vectorProvider->fieldNameIndex( varianceFieldName ) : -1; if ( ( mStatistics & QgsZonalStatistics::Count && countIndex == -1 ) || ( mStatistics & QgsZonalStatistics::Sum && sumIndex == -1 ) || ( mStatistics & QgsZonalStatistics::Mean && meanIndex == -1 ) || ( mStatistics & QgsZonalStatistics::Median && medianIndex == -1 ) || ( mStatistics & QgsZonalStatistics::StDev && stdevIndex == -1 ) || ( mStatistics & QgsZonalStatistics::Min && minIndex == -1 ) || ( mStatistics & QgsZonalStatistics::Max && maxIndex == -1 ) || ( mStatistics & QgsZonalStatistics::Range && rangeIndex == -1 ) || ( mStatistics & QgsZonalStatistics::Minority && minorityIndex == -1 ) || ( mStatistics & QgsZonalStatistics::Majority && majorityIndex == -1 ) || ( mStatistics & QgsZonalStatistics::Variety && varietyIndex == -1 ) || ( mStatistics & QgsZonalStatistics::Variance && varianceIndex == -1 ) ) { //failed to create a required field return 8; } //progress dialog long featureCount = vectorProvider->featureCount(); //iterate over each polygon QgsFeatureRequest request; request.setSubsetOfAttributes( QgsAttributeList() ); QgsFeatureIterator fi = vectorProvider->getFeatures( request ); QgsFeature f; bool statsStoreValues = ( mStatistics & QgsZonalStatistics::Median ) || ( mStatistics & QgsZonalStatistics::StDev ) || ( mStatistics & QgsZonalStatistics::Variance ); bool statsStoreValueCount = ( mStatistics & QgsZonalStatistics::Minority ) || ( mStatistics & QgsZonalStatistics::Majority ); FeatureStats featureStats( statsStoreValues, statsStoreValueCount ); int featureCounter = 0; QgsChangedAttributesMap changeMap; while ( fi.nextFeature( f ) ) { if ( feedback && feedback->isCanceled() ) { break; } if ( feedback ) { feedback->setProgress( 100.0 * static_cast< double >( featureCounter ) / featureCount ); } if ( !f.hasGeometry() ) { ++featureCounter; continue; } QgsGeometry featureGeometry = f.geometry(); QgsRectangle featureRect = featureGeometry.boundingBox().intersect( &rasterBBox ); if ( featureRect.isEmpty() ) { ++featureCounter; continue; } int offsetX, offsetY, nCellsX, nCellsY; if ( cellInfoForBBox( rasterBBox, featureRect, cellsizeX, cellsizeY, offsetX, offsetY, nCellsX, nCellsY ) != 0 ) { ++featureCounter; continue; } //avoid access to cells outside of the raster (may occur because of rounding) if ( ( offsetX + nCellsX ) > nCellsXProvider ) { nCellsX = nCellsXProvider - offsetX; } if ( ( offsetY + nCellsY ) > nCellsYProvider ) { nCellsY = nCellsYProvider - offsetY; } statisticsFromMiddlePointTest( featureGeometry, offsetX, offsetY, nCellsX, nCellsY, cellsizeX, cellsizeY, rasterBBox, featureStats ); if ( featureStats.count <= 1 ) { //the cell resolution is probably larger than the polygon area. We switch to precise pixel - polygon intersection in this case statisticsFromPreciseIntersection( featureGeometry, offsetX, offsetY, nCellsX, nCellsY, cellsizeX, cellsizeY, rasterBBox, featureStats ); } //write the statistics value to the vector data provider QgsAttributeMap changeAttributeMap; if ( mStatistics & QgsZonalStatistics::Count ) changeAttributeMap.insert( countIndex, QVariant( featureStats.count ) ); if ( mStatistics & QgsZonalStatistics::Sum ) changeAttributeMap.insert( sumIndex, QVariant( featureStats.sum ) ); if ( featureStats.count > 0 ) { double mean = featureStats.sum / featureStats.count; if ( mStatistics & QgsZonalStatistics::Mean ) changeAttributeMap.insert( meanIndex, QVariant( mean ) ); if ( mStatistics & QgsZonalStatistics::Median ) { std::sort( featureStats.values.begin(), featureStats.values.end() ); int size = featureStats.values.count(); bool even = ( size % 2 ) < 1; double medianValue; if ( even ) { medianValue = ( featureStats.values.at( size / 2 - 1 ) + featureStats.values.at( size / 2 ) ) / 2; } else //odd { medianValue = featureStats.values.at( ( size + 1 ) / 2 - 1 ); } changeAttributeMap.insert( medianIndex, QVariant( medianValue ) ); } if ( mStatistics & QgsZonalStatistics::StDev || mStatistics & QgsZonalStatistics::Variance ) { double sumSquared = 0; for ( int i = 0; i < featureStats.values.count(); ++i ) { double diff = featureStats.values.at( i ) - mean; sumSquared += diff * diff; } double variance = sumSquared / featureStats.values.count(); if ( mStatistics & QgsZonalStatistics::StDev ) { double stdev = std::pow( variance, 0.5 ); changeAttributeMap.insert( stdevIndex, QVariant( stdev ) ); } if ( mStatistics & QgsZonalStatistics::Variance ) changeAttributeMap.insert( varianceIndex, QVariant( variance ) ); } if ( mStatistics & QgsZonalStatistics::Min ) changeAttributeMap.insert( minIndex, QVariant( featureStats.min ) ); if ( mStatistics & QgsZonalStatistics::Max ) changeAttributeMap.insert( maxIndex, QVariant( featureStats.max ) ); if ( mStatistics & QgsZonalStatistics::Range ) changeAttributeMap.insert( rangeIndex, QVariant( featureStats.max - featureStats.min ) ); if ( mStatistics & QgsZonalStatistics::Minority || mStatistics & QgsZonalStatistics::Majority ) { QList<int> vals = featureStats.valueCount.values(); std::sort( vals.begin(), vals.end() ); if ( mStatistics & QgsZonalStatistics::Minority ) { float minorityKey = featureStats.valueCount.key( vals.first() ); changeAttributeMap.insert( minorityIndex, QVariant( minorityKey ) ); } if ( mStatistics & QgsZonalStatistics::Majority ) { float majKey = featureStats.valueCount.key( vals.last() ); changeAttributeMap.insert( majorityIndex, QVariant( majKey ) ); } } if ( mStatistics & QgsZonalStatistics::Variety ) changeAttributeMap.insert( varietyIndex, QVariant( featureStats.valueCount.count() ) ); } changeMap.insert( f.id(), changeAttributeMap ); ++featureCounter; } vectorProvider->changeAttributeValues( changeMap ); if ( feedback ) { feedback->setProgress( 100 ); } mPolygonLayer->updateFields(); if ( feedback && feedback->isCanceled() ) { return 9; } return 0; }
int QgsZonalStatistics::calculateStatistics( QProgressDialog* p ) { if ( !mPolygonLayer || mPolygonLayer->geometryType() != QGis::Polygon ) { return 1; } QgsVectorDataProvider* vectorProvider = mPolygonLayer->dataProvider(); if ( !vectorProvider ) { return 2; } //open the raster layer and the raster band GDALAllRegister(); GDALDatasetH inputDataset = GDALOpen( mRasterFilePath.toLocal8Bit().data(), GA_ReadOnly ); if ( inputDataset == NULL ) { return 3; } if ( GDALGetRasterCount( inputDataset ) < ( mRasterBand - 1 ) ) { GDALClose( inputDataset ); return 4; } GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset, mRasterBand ); if ( rasterBand == NULL ) { GDALClose( inputDataset ); return 5; } mInputNodataValue = GDALGetRasterNoDataValue( rasterBand, NULL ); //get geometry info about raster layer int nCellsX = GDALGetRasterXSize( inputDataset ); int nCellsY = GDALGetRasterYSize( inputDataset ); double geoTransform[6]; if ( GDALGetGeoTransform( inputDataset, geoTransform ) != CE_None ) { GDALClose( inputDataset ); return 6; } double cellsizeX = geoTransform[1]; if ( cellsizeX < 0 ) { cellsizeX = -cellsizeX; } double cellsizeY = geoTransform[5]; if ( cellsizeY < 0 ) { cellsizeY = -cellsizeY; } QgsRectangle rasterBBox( geoTransform[0], geoTransform[3] - ( nCellsY * cellsizeY ), geoTransform[0] + ( nCellsX * cellsizeX ), geoTransform[3] ); //add the new count, sum, mean fields to the provider QList<QgsField> newFieldList; QgsField countField( mAttributePrefix + "count", QVariant::Double ); QgsField sumField( mAttributePrefix + "sum", QVariant::Double ); QgsField meanField( mAttributePrefix + "mean", QVariant::Double ); newFieldList.push_back( countField ); newFieldList.push_back( sumField ); newFieldList.push_back( meanField ); if ( !vectorProvider->addAttributes( newFieldList ) ) { return 7; } //index of the new fields int countIndex = vectorProvider->fieldNameIndex( mAttributePrefix + "count" ); int sumIndex = vectorProvider->fieldNameIndex( mAttributePrefix + "sum" ); int meanIndex = vectorProvider->fieldNameIndex( mAttributePrefix + "mean" ); if ( countIndex == -1 || sumIndex == -1 || meanIndex == -1 ) { return 8; } //progress dialog long featureCount = vectorProvider->featureCount(); if ( p ) { p->setMaximum( featureCount ); } //iterate over each polygon vectorProvider->select( QgsAttributeList(), QgsRectangle(), true, false ); vectorProvider->rewind(); QgsFeature f; double count = 0; double sum = 0; double mean = 0; int featureCounter = 0; while ( vectorProvider->nextFeature( f ) ) { qWarning( "%d", featureCounter ); if ( p ) { p->setValue( featureCounter ); } if ( p && p->wasCanceled() ) { break; } QgsGeometry* featureGeometry = f.geometry(); if ( !featureGeometry ) { ++featureCounter; continue; } int offsetX, offsetY, nCellsX, nCellsY; if ( cellInfoForBBox( rasterBBox, featureGeometry->boundingBox(), cellsizeX, cellsizeY, offsetX, offsetY, nCellsX, nCellsY ) != 0 ) { ++featureCounter; continue; } statisticsFromMiddlePointTest_improved( rasterBand, featureGeometry, offsetX, offsetY, nCellsX, nCellsY, cellsizeX, cellsizeY, rasterBBox, sum, count ); if ( count <= 1 ) { //the cell resolution is probably larger than the polygon area. We switch to precise pixel - polygon intersection in this case statisticsFromPreciseIntersection( rasterBand, featureGeometry, offsetX, offsetY, nCellsX, nCellsY, cellsizeX, cellsizeY, rasterBBox, sum, count ); } if ( count == 0 ) { mean = 0; } else { mean = sum / count; } //write the statistics value to the vector data provider QgsChangedAttributesMap changeMap; QgsAttributeMap changeAttributeMap; changeAttributeMap.insert( countIndex, QVariant( count ) ); changeAttributeMap.insert( sumIndex, QVariant( sum ) ); changeAttributeMap.insert( meanIndex, QVariant( mean ) ); changeMap.insert( f.id(), changeAttributeMap ); vectorProvider->changeAttributeValues( changeMap ); ++featureCounter; } if ( p ) { p->setValue( featureCount ); } GDALClose( inputDataset ); return 0; }