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 ); }
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 ); }
void QgsVectorLayerFeatureIterator::prepareExpressions() { const QList<QgsExpressionFieldBuffer::ExpressionField> exps = mSource->mExpressionFieldBuffer->expressions(); for ( int i = 0; i < mSource->mFields.count(); i++ ) { if ( mSource->mFields.fieldOrigin( i ) == QgsFields::OriginExpression ) { // Only prepare if there is no subset defined or the subset contains this field if ( !( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) || mRequest.subsetOfAttributes().contains( i ) ) { int oi = mSource->mFields.fieldOriginIndex( i ); QgsExpression* exp = new QgsExpression( exps[oi].expression ); exp->prepare( mSource->mFields ); mExpressionFieldInfo.insert( i, exp ); if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { QgsAttributeList attrs; Q_FOREACH( const QString& col, exp->referencedColumns() ) { attrs.append( mSource->mFields.fieldNameIndex( col ) ); } mRequest.setSubsetOfAttributes( mRequest.subsetOfAttributes() + attrs ); } if ( exp->needsGeometry() ) { mRequest.setFlags( mRequest.flags() & ~QgsFeatureRequest::NoGeometry ); } } }
QgsAttributeList QgsFields::allAttributesList() const { QgsAttributeList lst; for ( int i = 0; i < d->fields.count(); ++i ) lst.append( i ); return lst; }
void QgsSearchQueryBuilder::getFieldValues( int limit ) { if ( !mLayer ) { return; } // clear the values list mModelValues->clear(); // determine the field type QString fieldName = mModelFields->data( lstFields->currentIndex() ).toString(); int fieldIndex = mFieldMap[fieldName]; QgsField field = mLayer->pendingFields()[fieldIndex];//provider->fields()[fieldIndex]; bool numeric = ( field.type() == QVariant::Int || field.type() == QVariant::Double ); QgsFeature feat; QString value; QgsAttributeList attrs; attrs.append( fieldIndex ); mLayer->select( attrs, QgsRectangle(), false ); lstValues->setCursor( Qt::WaitCursor ); // Block for better performance mModelValues->blockSignals( true ); lstValues->setUpdatesEnabled( false ); /**MH: keep already inserted values in a set. Querying is much faster compared to QStandardItemModel::findItems*/ QSet<QString> insertedValues; while ( mLayer->nextFeature( feat ) && ( limit == 0 || mModelValues->rowCount() != limit ) ) { const QgsAttributeMap& attributes = feat.attributeMap(); value = attributes[fieldIndex].toString(); if ( !numeric ) { // put string in single quotes and escape single quotes in the string value = "'" + value.replace( "'", "''" ) + "'"; } // add item only if it's not there already if ( !insertedValues.contains( value ) ) { QStandardItem *myItem = new QStandardItem( value ); myItem->setEditable( false ); mModelValues->insertRow( mModelValues->rowCount(), myItem ); insertedValues.insert( value ); } } // Unblock for normal use mModelValues->blockSignals( false ); lstValues->setUpdatesEnabled( true ); // TODO: already sorted, signal emit to refresh model mModelValues->sort( 0 ); lstValues->setCursor( Qt::ArrowCursor ); }
QgsAttributeList QgsVectorDataProvider::attributeIndexes() { uint count = fieldCount(); QgsAttributeList list; for ( uint i = 0; i < count; i++ ) list.append( i ); return list; }
void QgsLabel::addRequiredFields( QgsAttributeList& fields ) const { for ( uint i = 0; i < LabelFieldCount; i++ ) { if ( mLabelFieldIdx[i] == -1 ) continue; bool found = false; for ( QgsAttributeList::iterator it = fields.begin(); it != fields.end(); ++it ) { if ( *it == mLabelFieldIdx[i] ) { found = true; break; } } if ( !found ) { fields.append( mLabelFieldIdx[i] ); } } }
void QgsVectorDataProvider::uniqueValues( int index, QList<QVariant> &values, int limit ) { QgsFeature f; QgsAttributeList keys; keys.append( index ); QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) ); QSet<QString> set; values.clear(); while ( fi.nextFeature( f ) ) { if ( !set.contains( f.attribute( index ).toString() ) ) { values.append( f.attribute( index ) ); set.insert( f.attribute( index ).toString() ); } if ( limit >= 0 && values.size() >= limit ) break; } }
void QgsVectorDataProvider::uniqueValues( int index, QList<QVariant> &values, int limit ) { QgsFeature f; QgsAttributeList keys; keys.append( index ); select( keys, QgsRectangle(), false ); QSet<QString> set; values.clear(); while ( nextFeature( f ) ) { if ( !set.contains( f.attributeMap()[index].toString() ) ) { values.append( f.attributeMap()[index] ); set.insert( f.attributeMap()[index].toString() ); } if ( limit >= 0 && values.size() >= limit ) break; } }
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; }
// Slot called when the menu item is triggered // If you created more menu items / toolbar buttons in initiGui, you should // create a separate handler for each action - this single run() method will // not be enough void Heatmap::run() { HeatmapGui d( mQGisIface->mainWindow(), QgisGui::ModalDialogFlags, &mSessionSettings ); if ( d.exec() == QDialog::Accepted ) { // everything runs here // Get the required data from the dialog QgsRectangle myBBox = d.bbox(); int columns = d.columns(); int rows = d.rows(); double cellsize = d.cellSizeX(); // or d.cellSizeY(); both have the same value mDecay = d.decayRatio(); int kernelShape = d.kernelShape(); // Start working on the input vector QgsVectorLayer* inputLayer = d.inputVectorLayer(); // Getting the rasterdataset in place GDALAllRegister(); GDALDataset *emptyDataset; GDALDriver *myDriver; myDriver = GetGDALDriverManager()->GetDriverByName( d.outputFormat().toUtf8() ); if ( myDriver == NULL ) { QMessageBox::information( 0, tr( "GDAL driver error" ), tr( "Cannot open the driver for the specified format" ) ); return; } double geoTransform[6] = { myBBox.xMinimum(), cellsize, 0, myBBox.yMinimum(), 0, cellsize }; emptyDataset = myDriver->Create( d.outputFilename().toUtf8(), columns, rows, 1, GDT_Float32, NULL ); emptyDataset->SetGeoTransform( geoTransform ); // Set the projection on the raster destination to match the input layer emptyDataset->SetProjection( inputLayer->crs().toWkt().toLocal8Bit().data() ); GDALRasterBand *poBand; poBand = emptyDataset->GetRasterBand( 1 ); poBand->SetNoDataValue( NO_DATA ); float* line = ( float * ) CPLMalloc( sizeof( float ) * columns ); for ( int i = 0; i < columns ; i++ ) { line[i] = NO_DATA; } // Write the empty raster for ( int i = 0; i < rows ; i++ ) { poBand->RasterIO( GF_Write, 0, i, columns, 1, line, columns, 1, GDT_Float32, 0, 0 ); } CPLFree( line ); //close the dataset GDALClose(( GDALDatasetH ) emptyDataset ); // open the raster in GA_Update mode GDALDataset *heatmapDS; heatmapDS = ( GDALDataset * ) GDALOpen( d.outputFilename().toUtf8(), GA_Update ); if ( !heatmapDS ) { QMessageBox::information( 0, tr( "Raster update error" ), tr( "Could not open the created raster for updating. The heatmap was not generated." ) ); return; } poBand = heatmapDS->GetRasterBand( 1 ); QgsAttributeList myAttrList; int rField = 0; int wField = 0; // Handle different radius options double radius; double radiusToMapUnits = 1; int myBuffer = 0; if ( d.variableRadius() ) { rField = d.radiusField(); myAttrList.append( rField ); QgsDebugMsg( QString( "Radius Field index received: %1" ).arg( rField ) ); // If not using map units, then calculate a conversion factor to convert the radii to map units if ( d.radiusUnit() == HeatmapGui::Meters ) { radiusToMapUnits = mapUnitsOf( 1, inputLayer->crs() ); } } else { radius = d.radius(); // radius returned by d.radius() is already in map units myBuffer = bufferSize( radius, cellsize ); } if ( d.weighted() ) { wField = d.weightField(); myAttrList.append( wField ); } // This might have attributes or mightnot have attibutes at all // based on the variableRadius() and weighted() QgsFeatureIterator fit = inputLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( myAttrList ) ); int totalFeatures = inputLayer->featureCount(); int counter = 0; QProgressDialog p( tr( "Creating heatmap" ), tr( "Abort" ), 0, totalFeatures, mQGisIface->mainWindow() ); p.setWindowModality( Qt::ApplicationModal ); p.show(); QgsFeature myFeature; while ( fit.nextFeature( myFeature ) ) { counter++; p.setValue( counter ); QApplication::processEvents(); if ( p.wasCanceled() ) { QMessageBox::information( 0, tr( "Heatmap generation aborted" ), tr( "QGIS will now load the partially-computed raster." ) ); break; } QgsGeometry* myPointGeometry; myPointGeometry = myFeature.geometry(); // convert the geometry to point QgsPoint myPoint; myPoint = myPointGeometry->asPoint(); // avoiding any empty points or out of extent points if (( myPoint.x() < myBBox.xMinimum() ) || ( myPoint.y() < myBBox.yMinimum() ) || ( myPoint.x() > myBBox.xMaximum() ) || ( myPoint.y() > myBBox.yMaximum() ) ) { continue; } // If radius is variable then fetch it and calculate new pixel buffer size if ( d.variableRadius() ) { radius = myFeature.attribute( rField ).toDouble() * radiusToMapUnits; myBuffer = bufferSize( radius, cellsize ); } int blockSize = 2 * myBuffer + 1; //Block SIDE would be more appropriate // calculate the pixel position unsigned int xPosition, yPosition; xPosition = (( myPoint.x() - myBBox.xMinimum() ) / cellsize ) - myBuffer; yPosition = (( myPoint.y() - myBBox.yMinimum() ) / cellsize ) - myBuffer; // get the data float *dataBuffer = ( float * ) CPLMalloc( sizeof( float ) * blockSize * blockSize ); poBand->RasterIO( GF_Read, xPosition, yPosition, blockSize, blockSize, dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 ); double weight = 1.0; if ( d.weighted() ) { weight = myFeature.attribute( wField ).toDouble(); } for ( int xp = 0; xp <= myBuffer; xp++ ) { for ( int yp = 0; yp <= myBuffer; yp++ ) { double distance = sqrt( pow( xp, 2.0 ) + pow( yp, 2.0 ) ); // is pixel outside search bandwidth of feature? if ( distance > myBuffer ) { continue; } double pixelValue = weight * calculateKernelValue( distance, myBuffer, kernelShape ); // clearing anamolies along the axes if ( xp == 0 && yp == 0 ) { pixelValue /= 4; } else if ( xp == 0 || yp == 0 ) { pixelValue /= 2; } int pos[4]; pos[0] = ( myBuffer + xp ) * blockSize + ( myBuffer + yp ); pos[1] = ( myBuffer + xp ) * blockSize + ( myBuffer - yp ); pos[2] = ( myBuffer - xp ) * blockSize + ( myBuffer + yp ); pos[3] = ( myBuffer - xp ) * blockSize + ( myBuffer - yp ); for ( int p = 0; p < 4; p++ ) { if ( dataBuffer[ pos[p] ] == NO_DATA ) { dataBuffer[ pos[p] ] = 0; } dataBuffer[ pos[p] ] += pixelValue; } } } poBand->RasterIO( GF_Write, xPosition, yPosition, blockSize, blockSize, dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 ); CPLFree( dataBuffer ); } // Finally close the dataset GDALClose(( GDALDatasetH ) heatmapDS ); // Open the file in QGIS window mQGisIface->addRasterLayer( d.outputFilename(), QFileInfo( d.outputFilename() ).baseName() ); } }
QVariantMap QgsRemoveDuplicatesByAttributeAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) { std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) ); if ( !source ) throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) ); const QStringList fieldNames = parameterAsFields( parameters, QStringLiteral( "FIELDS" ), context ); QgsAttributeList attributes; for ( const QString &field : fieldNames ) { const int index = source->fields().lookupField( field ); if ( index < 0 ) feedback->reportError( QObject::tr( "Field %1 not found in INPUT layer, skipping" ).arg( field ) ); else attributes.append( index ); } if ( attributes.isEmpty() ) throw QgsProcessingException( QObject::tr( "No input fields found" ) ); QString noDupeSinkId; std::unique_ptr< QgsFeatureSink > noDupeSink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, noDupeSinkId, source->fields(), source->wkbType(), source->sourceCrs() ) ); if ( !noDupeSink ) throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) ); QString dupeSinkId; std::unique_ptr< QgsFeatureSink > dupesSink( parameterAsSink( parameters, QStringLiteral( "DUPLICATES" ), context, dupeSinkId, source->fields(), source->wkbType(), source->sourceCrs() ) ); const long count = source->featureCount(); double step = count > 0 ? 100.0 / count : 1; int current = 0; long long keptCount = 0; long long discardedCount = 0; QSet< QVariantList > matched; QgsFeatureIterator it = source->getFeatures( QgsFeatureRequest(), QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks ); QgsFeature f; QVariantList dupeKey; dupeKey.reserve( attributes.size() ); for ( int i : attributes ) { ( void )i; dupeKey.append( QVariant() ); } while ( it.nextFeature( f ) ) { if ( feedback->isCanceled() ) { break; } int i = 0; for ( int attr : attributes ) dupeKey[i++] = f.attribute( attr ); if ( matched.contains( dupeKey ) ) { // duplicate discardedCount++; if ( dupesSink ) dupesSink->addFeature( f, QgsFeatureSink::FastInsert ); } else { // not duplicate keptCount++; matched.insert( dupeKey ); noDupeSink->addFeature( f, QgsFeatureSink::FastInsert ); } feedback->setProgress( current * step ); current++; } QVariantMap outputs; outputs.insert( QStringLiteral( "RETAINED_COUNT" ), keptCount ); outputs.insert( QStringLiteral( "DUPLICATE_COUNT" ), discardedCount ); outputs.insert( QStringLiteral( "OUTPUT" ), noDupeSinkId ); if ( dupesSink ) outputs.insert( QStringLiteral( "DUPLICATES" ), dupeSinkId ); return outputs; }
void QgsAttributeTypeDialog::setIndex( int index, int editTypeInt ) { mIndex = index; //need to set index for combobox QgsVectorLayer::EditType editType; if ( editTypeInt > -1 ) { editType = QgsVectorLayer::EditType( editTypeInt ); } else { editType = mLayer->editType( index ); } setWindowTitle( defaultWindowTitle() + " \"" + mLayer->pendingFields()[index].name() + "\"" ); QgsAttributeList attributeList = QgsAttributeList(); attributeList.append( index ); mLayer->select( attributeList, QgsRectangle(), false ); QgsFeature f; QString text; //calculate min and max for range for this field if ( mLayer->pendingFields()[index].type() == QVariant::Int ) { rangeWidget->clear(); rangeWidget->addItems( QStringList() << tr( "Editable" ) << tr( "Slider" ) << tr( "Dial" ) ); int min = INT_MIN; int max = INT_MAX; while ( mLayer->nextFeature( f ) ) { QVariant val = f.attributeMap()[index]; if ( val.isValid() && !val.isNull() ) { int valInt = val.toInt(); if ( min > valInt ) min = valInt; if ( max < valInt ) max = valInt; } text = tr( "Current minimum for this value is %1 and current maximum is %2." ).arg( min ).arg( max ); } } else if ( mLayer->pendingFields()[index].type() == QVariant::Double ) { double dMin = -DBL_MAX; double dMax = DBL_MAX; rangeWidget->clear(); rangeWidget->addItems( QStringList() << tr( "Editable" ) << tr( "Slider" ) ); while ( mLayer->nextFeature( f ) ) { QVariant val = f.attributeMap()[index]; if ( val.isValid() && !val.isNull() ) { double dVal = val.toDouble(); if ( dMin > dVal ) dMin = dVal; if ( dMax < dVal ) dMax = dVal; } text = tr( "Current minimum for this value is %1 and current maximum is %2." ).arg( dMin ).arg( dMax ); } } else { text = tr( "Attribute has no integer or real type, therefore range is not usable." ); } valuesLabel->setText( text ); //setPageForIndex( index ); setPageForEditType( editType ); switch ( editType ) { case QgsVectorLayer::ValueMap: { tableWidget->clearContents(); for ( int i = tableWidget->rowCount() - 1; i > 0; i-- ) { tableWidget->removeRow( i ); } // if some value map already present use it QMap<QString, QVariant> map; if ( !mValueMap.empty() ) { map = mValueMap; } else { map = mLayer->valueMap( index ); } int row = 0; for ( QMap<QString, QVariant>::iterator mit = map.begin(); mit != map.end(); mit++, row++ ) { tableWidget->insertRow( row ); if ( mit.value().isNull() ) { tableWidget->setItem( row, 0, new QTableWidgetItem( mit.key() ) ); } else { tableWidget->setItem( row, 0, new QTableWidgetItem( mit.value().toString() ) ); tableWidget->setItem( row, 1, new QTableWidgetItem( mit.key() ) ); } } } break; case QgsVectorLayer::EditRange: case QgsVectorLayer::SliderRange: case QgsVectorLayer::DialRange: { if ( mLayer->pendingFields()[mIndex].type() != QVariant::Int ) { minimumSpinBox->setValue( mLayer->range( index ).mMin.toInt() ); maximumSpinBox->setValue( mLayer->range( index ).mMax.toInt() ); stepSpinBox->setValue( mLayer->range( index ).mStep.toInt() ); } else if ( mLayer->pendingFields()[mIndex].type() == QVariant::Double ) { minimumDoubleSpinBox->setValue( mLayer->range( index ).mMin.toDouble() ); maximumDoubleSpinBox->setValue( mLayer->range( index ).mMax.toDouble() ); stepDoubleSpinBox->setValue( mLayer->range( index ).mStep.toDouble() ); } if ( editType == QgsVectorLayer::EditRange ) { rangeWidget->setCurrentIndex( 0 ); } else if ( editType == QgsVectorLayer::SliderRange ) { rangeWidget->setCurrentIndex( 1 ); } else { rangeWidget->setCurrentIndex( 2 ); } } break; case QgsVectorLayer::UniqueValuesEditable: editableUniqueValues->setChecked( editType == QgsVectorLayer::UniqueValuesEditable ); break; default: break; } }
// Slot called when the menu item is triggered // If you created more menu items / toolbar buttons in initiGui, you should // create a separate handler for each action - this single run() method will // not be enough void Heatmap::run() { HeatmapGui d( mQGisIface->mainWindow(), QgisGui::ModalDialogFlags, &mSessionSettings ); //check that dialog found a suitable vector layer if ( !d.inputVectorLayer() ) { mQGisIface->messageBar()->pushMessage( tr( "Layer not found" ), tr( "The heatmap plugin requires at least one point vector layer" ), QgsMessageBar::INFO, mQGisIface->messageTimeout() ); return; } if ( d.exec() != QDialog::Accepted ) { return; } QgsVectorLayer* inputLayer = d.inputVectorLayer(); // Get the required data from the dialog QgsRectangle myBBox = d.bbox(); int columns = d.columns(); int rows = d.rows(); double cellsize = d.cellSizeX(); // or d.cellSizeY(); both have the same value mDecay = d.decayRatio(); KernelShape kernelShape = d.kernelShape(); OutputValues valueType = d.outputValues(); //is input layer multipoint? bool isMultiPoint = inputLayer->wkbType() == Qgis::WKBMultiPoint || inputLayer->wkbType() == Qgis::WKBMultiPoint25D; // Getting the rasterdataset in place GDALAllRegister(); GDALDriverH myDriver = GDALGetDriverByName( d.outputFormat().toUtf8() ); if ( !myDriver ) { mQGisIface->messageBar()->pushMessage( tr( "GDAL driver error" ), tr( "Cannot open the driver for the specified format" ), QgsMessageBar::WARNING, mQGisIface->messageTimeout() ); return; } double geoTransform[6] = { myBBox.xMinimum(), cellsize, 0, myBBox.yMinimum(), 0, cellsize }; GDALDatasetH emptyDataset = GDALCreate( myDriver, d.outputFilename().toUtf8(), columns, rows, 1, GDT_Float32, nullptr ); GDALSetGeoTransform( emptyDataset, geoTransform ); // Set the projection on the raster destination to match the input layer GDALSetProjection( emptyDataset, inputLayer->crs().toWkt().toLocal8Bit().data() ); GDALRasterBandH poBand = GDALGetRasterBand( emptyDataset, 1 ); GDALSetRasterNoDataValue( poBand, NO_DATA ); float* line = ( float * ) CPLMalloc( sizeof( float ) * columns ); for ( int i = 0; i < columns ; i++ ) { line[i] = NO_DATA; } // Write the empty raster for ( int i = 0; i < rows ; i++ ) { if ( GDALRasterIO( poBand, GF_Write, 0, i, columns, 1, line, columns, 1, GDT_Float32, 0, 0 ) != CE_None ) { QgsDebugMsg( "Raster IO Error" ); } } CPLFree( line ); //close the dataset GDALClose( emptyDataset ); // open the raster in GA_Update mode GDALDatasetH heatmapDS = GDALOpen( TO8F( d.outputFilename() ), GA_Update ); if ( !heatmapDS ) { mQGisIface->messageBar()->pushMessage( tr( "Raster update error" ), tr( "Could not open the created raster for updating. The heatmap was not generated." ), QgsMessageBar::WARNING ); return; } poBand = GDALGetRasterBand( heatmapDS, 1 ); QgsAttributeList myAttrList; int rField = 0; int wField = 0; // Handle different radius options double radius; double radiusToMapUnits = 1; int myBuffer = 0; if ( d.variableRadius() ) { rField = d.radiusField(); myAttrList.append( rField ); QgsDebugMsg( QString( "Radius Field index received: %1" ).arg( rField ) ); // If not using map units, then calculate a conversion factor to convert the radii to map units if ( d.radiusUnit() == HeatmapGui::LayerUnits ) { radiusToMapUnits = mapUnitsOf( 1, inputLayer->crs() ); } } else { radius = d.radius(); // radius returned by d.radius() is already in map units myBuffer = bufferSize( radius, cellsize ); } if ( d.weighted() ) { wField = d.weightField(); myAttrList.append( wField ); } // This might have attributes or mightnot have attibutes at all // based on the variableRadius() and weighted() QgsFeatureIterator fit = inputLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( myAttrList ) ); int totalFeatures = inputLayer->featureCount(); int counter = 0; QProgressDialog p( tr( "Rendering heatmap..." ), tr( "Abort" ), 0, totalFeatures, mQGisIface->mainWindow() ); p.setWindowTitle( tr( "QGIS" ) ); p.setWindowModality( Qt::ApplicationModal ); p.show(); QgsFeature myFeature; while ( fit.nextFeature( myFeature ) ) { counter++; p.setValue( counter ); QApplication::processEvents(); if ( p.wasCanceled() ) { mQGisIface->messageBar()->pushMessage( tr( "Heatmap generation aborted" ), tr( "QGIS will now load the partially-computed raster" ), QgsMessageBar::INFO, mQGisIface->messageTimeout() ); break; } const QgsGeometry* featureGeometry = myFeature.constGeometry(); if ( !featureGeometry ) { continue; } // convert the geometry to multipoint QgsMultiPoint multiPoints; if ( !isMultiPoint ) { QgsPoint myPoint = featureGeometry->asPoint(); // avoiding any empty points or out of extent points if (( myPoint.x() < myBBox.xMinimum() ) || ( myPoint.y() < myBBox.yMinimum() ) || ( myPoint.x() > myBBox.xMaximum() ) || ( myPoint.y() > myBBox.yMaximum() ) ) { continue; } multiPoints << myPoint; } else { multiPoints = featureGeometry->asMultiPoint(); } // If radius is variable then fetch it and calculate new pixel buffer size if ( d.variableRadius() ) { radius = myFeature.attribute( rField ).toDouble() * radiusToMapUnits; myBuffer = bufferSize( radius, cellsize ); } int blockSize = 2 * myBuffer + 1; //Block SIDE would be more appropriate double weight = 1.0; if ( d.weighted() ) { weight = myFeature.attribute( wField ).toDouble(); } //loop through all points in multipoint for ( QgsMultiPoint::const_iterator pointIt = multiPoints.constBegin(); pointIt != multiPoints.constEnd(); ++pointIt ) { // avoiding any empty points or out of extent points if ((( *pointIt ).x() < myBBox.xMinimum() ) || (( *pointIt ).y() < myBBox.yMinimum() ) || (( *pointIt ).x() > myBBox.xMaximum() ) || (( *pointIt ).y() > myBBox.yMaximum() ) ) { continue; } // calculate the pixel position unsigned int xPosition, yPosition; xPosition = ((( *pointIt ).x() - myBBox.xMinimum() ) / cellsize ) - myBuffer; yPosition = ((( *pointIt ).y() - myBBox.yMinimum() ) / cellsize ) - myBuffer; // get the data float *dataBuffer = ( float * ) CPLMalloc( sizeof( float ) * blockSize * blockSize ); if ( GDALRasterIO( poBand, GF_Read, xPosition, yPosition, blockSize, blockSize, dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 ) != CE_None ) { QgsDebugMsg( "Raster IO Error" ); } for ( int xp = 0; xp <= myBuffer; xp++ ) { for ( int yp = 0; yp <= myBuffer; yp++ ) { double distance = sqrt( pow( xp, 2.0 ) + pow( yp, 2.0 ) ); // is pixel outside search bandwidth of feature? if ( distance > myBuffer ) { continue; } double pixelValue = weight * calculateKernelValue( distance, myBuffer, kernelShape, valueType ); // clearing anamolies along the axes if ( xp == 0 && yp == 0 ) { pixelValue /= 4; } else if ( xp == 0 || yp == 0 ) { pixelValue /= 2; } int pos[4]; pos[0] = ( myBuffer + xp ) * blockSize + ( myBuffer + yp ); pos[1] = ( myBuffer + xp ) * blockSize + ( myBuffer - yp ); pos[2] = ( myBuffer - xp ) * blockSize + ( myBuffer + yp ); pos[3] = ( myBuffer - xp ) * blockSize + ( myBuffer - yp ); for ( int p = 0; p < 4; p++ ) { if ( dataBuffer[ pos[p] ] == NO_DATA ) { dataBuffer[ pos[p] ] = 0; } dataBuffer[ pos[p] ] += pixelValue; } } } if ( GDALRasterIO( poBand, GF_Write, xPosition, yPosition, blockSize, blockSize, dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 ) != CE_None ) { QgsDebugMsg( "Raster IO Error" ); } CPLFree( dataBuffer ); } } // Finally close the dataset GDALClose(( GDALDatasetH ) heatmapDS ); // Open the file in QGIS window if requested if ( d.addToCanvas() ) { mQGisIface->addRasterLayer( d.outputFilename(), QFileInfo( d.outputFilename() ).baseName() ); } }
QgsAttributeList QgsContinuousColorRenderer::classificationAttributes() const { QgsAttributeList list; list.append( mClassificationField ); return list; }