bool QgsVectorLayerImport::addFeature( QgsFeature& feat ) { QgsAttributes attrs = feat.attributes(); QgsFeature newFeat; if ( feat.constGeometry() ) newFeat.setGeometry( *feat.constGeometry() ); newFeat.initAttributes( mAttributeCount ); for ( int i = 0; i < attrs.count(); ++i ) { // add only mapped attributes (un-mapped ones will not be present in the // destination layer) int dstIdx = mOldToNewAttrIdx.value( i, -1 ); if ( dstIdx < 0 ) continue; QgsDebugMsgLevel( QString( "moving field from pos %1 to %2" ).arg( i ).arg( dstIdx ), 3 ); newFeat.setAttribute( dstIdx, attrs.at( i ) ); } mFeatureBuffer.append( newFeat ); if ( mFeatureBuffer.count() >= FEATURE_BUFFER_SIZE ) { return flushBuffer(); } return true; }
void QgsFeatureAction::onFeatureSaved( const QgsFeature& feature ) { QgsAttributeForm* form = qobject_cast<QgsAttributeForm*>( sender() ); Q_UNUSED( form ) // only used for Q_ASSERT Q_ASSERT( form ); // Assign provider generated values if ( mFeature ) *mFeature = feature; mFeatureSaved = true; QSettings settings; bool reuseLastValues = settings.value( "/qgis/digitizing/reuseLastValues", false ).toBool(); QgsDebugMsg( QString( "reuseLastValues: %1" ).arg( reuseLastValues ) ); if ( reuseLastValues ) { QgsFields fields = mLayer->fields(); for ( int idx = 0; idx < fields.count(); ++idx ) { QgsAttributes newValues = feature.attributes(); QgsAttributeMap origValues = sLastUsedValues[ mLayer ]; if ( origValues[idx] != newValues.at( idx ) ) { QgsDebugMsg( QString( "saving %1 for %2" ).arg( sLastUsedValues[ mLayer ][idx].toString() ).arg( idx ) ); sLastUsedValues[ mLayer ][idx] = newValues.at( idx ); } } } }
bool QgsMemoryProvider::addAttributes( const QList<QgsField> &attributes ) { for ( QList<QgsField>::const_iterator it = attributes.begin(); it != attributes.end(); ++it ) { switch ( it->type() ) { case QVariant::Int: case QVariant::Double: case QVariant::String: case QVariant::Date: case QVariant::Time: case QVariant::DateTime: case QVariant::LongLong: break; default: QgsDebugMsg( "Field type not supported: " + it->typeName() ); continue; } // add new field as a last one mFields.append( *it ); for ( QgsFeatureMap::iterator fit = mFeatures.begin(); fit != mFeatures.end(); ++fit ) { QgsFeature& f = fit.value(); QgsAttributes attr = f.attributes(); attr.append( QVariant() ); f.setAttributes( attr ); } } return true; }
QSizeF QgsHistogramDiagram::diagramSize( const QgsAttributes& attributes, const QgsRenderContext& c, const QgsDiagramSettings& s ) { Q_UNUSED( c ); QSizeF size; if ( attributes.isEmpty() ) { return QSizeF(); //zero size if no attributes } double maxValue = attributes.at( 0 ).toDouble(); for ( int i = 0; i < attributes.count(); ++i ) { maxValue = qMax( attributes.at( i ).toDouble(), maxValue ); } switch ( s.diagramOrientation ) { case QgsDiagramSettings::Up: case QgsDiagramSettings::Down: mScaleFactor = maxValue / s.size.height(); size.scale( s.barWidth * s.categoryColors.size(), s.size.height(), Qt::IgnoreAspectRatio ); break; case QgsDiagramSettings::Right: case QgsDiagramSettings::Left: default: // just in case... mScaleFactor = maxValue / s.size.width(); size.scale( s.size.width(), s.barWidth * s.categoryColors.size(), Qt::IgnoreAspectRatio ); break; } return size; }
QgsSymbolV2* QgsCategorizedSymbolRendererV2::originalSymbolForFeature( QgsFeature& feature ) { QgsAttributes attrs = feature.attributes(); QVariant value; if ( mAttrNum == -1 ) { Q_ASSERT( mExpression.data() ); value = mExpression->evaluate( &feature ); } else { value = attrs.value( mAttrNum ); } // find the right symbol for the category QgsSymbolV2 *symbol = symbolForValue( value ); if ( symbol == &sSkipRender ) return 0; if ( !symbol ) { // if no symbol found use default one return symbolForValue( QVariant( "" ) ); } return symbol; }
QgsVectorLayer *QgsFeatureSource::materialize( const QgsFeatureRequest &request, QgsFeedback *feedback ) { QgsWkbTypes::Type outWkbType = request.flags() & QgsFeatureRequest::NoGeometry ? QgsWkbTypes::NoGeometry : wkbType(); QgsCoordinateReferenceSystem crs = request.destinationCrs().isValid() ? request.destinationCrs() : sourceCrs(); QgsAttributeList requestedAttrs = request.subsetOfAttributes(); QgsFields outFields; if ( request.flags() & QgsFeatureRequest::SubsetOfAttributes ) { int i = 0; const QgsFields sourceFields = fields(); for ( const QgsField &field : sourceFields ) { if ( requestedAttrs.contains( i ) ) outFields.append( field ); i++; } } else { outFields = fields(); } std::unique_ptr< QgsVectorLayer > layer( QgsMemoryProviderUtils::createMemoryLayer( sourceName(), outFields, outWkbType, crs ) ); QgsFeature f; QgsFeatureIterator it = getFeatures( request ); int fieldCount = fields().count(); while ( it.nextFeature( f ) ) { if ( feedback && feedback->isCanceled() ) break; if ( request.flags() & QgsFeatureRequest::SubsetOfAttributes ) { // remove unused attributes QgsAttributes attrs; for ( int i = 0; i < fieldCount; ++i ) { if ( requestedAttrs.contains( i ) ) { attrs.append( f.attributes().at( i ) ); } } f.setAttributes( attrs ); } layer->dataProvider()->addFeature( f, QgsFeatureSink::FastInsert ); } return layer.release(); }
QString QgsPointDisplacementRenderer::getLabel( const QgsFeature& f ) { QString attribute; QgsAttributes attrs = f.attributes(); if ( mLabelIndex >= 0 && mLabelIndex < attrs.count() ) { attribute = attrs[mLabelIndex].toString(); } return attribute; }
QVariant RgSpeedProperter::property( double distance, const QgsFeature& f ) const { QgsAttributes attrs = f.attributes(); if ( mAttributeId < 0 || mAttributeId >= attrs.count() ) return QVariant( distance / ( mDefaultValue*mToMetricFactor ) ); double val = distance / ( attrs.at( mAttributeId ).toDouble() * mToMetricFactor ); if ( val <= 0.0 ) return QVariant( distance / ( mDefaultValue / mToMetricFactor ) ); return QVariant( val ); }
QVariant QgsGraduatedSymbolRenderer::valueForFeature( QgsFeature &feature, QgsRenderContext &context ) const { QgsAttributes attrs = feature.attributes(); QVariant value; if ( mAttrNum < 0 || mAttrNum >= attrs.count() ) { value = mExpression->evaluate( &context.expressionContext() ); } else { value = attrs.at( mAttrNum ); } return value; }
QVariant QgsCategorizedSymbolRendererV2::valueForFeature( QgsFeature& feature, QgsRenderContext &context ) const { QgsAttributes attrs = feature.attributes(); QVariant value; if ( mAttrNum == -1 ) { Q_ASSERT( mExpression.data() ); value = mExpression->evaluate( &context.expressionContext() ); } else { value = attrs.value( mAttrNum ); } return value; }
QgsSymbolV2* QgsGraduatedSymbolRendererV2::originalSymbolForFeature( QgsFeature& feature ) { QgsAttributes attrs = feature.attributes(); QVariant value; if ( mAttrNum < 0 || mAttrNum >= attrs.count() ) { value = mExpression->evaluate( &feature ); } else { value = attrs[mAttrNum]; } // Null values should not be categorized if ( value.isNull() ) return NULL; // find the right category return symbolForValue( value.toDouble() ); }
void QgsOfflineEditing::applyFeaturesAdded( QgsVectorLayer* offlineLayer, QgsVectorLayer* remoteLayer, sqlite3* db, int layerId ) { QString sql = QString( "SELECT \"fid\" FROM 'log_added_features' WHERE \"layer_id\" = %1" ).arg( layerId ); QList<int> newFeatureIds = sqlQueryInts( db, sql ); // get new features from offline layer QgsFeatureList features; for ( int i = 0; i < newFeatureIds.size(); i++ ) { QgsFeature feature; if ( offlineLayer->getFeatures( QgsFeatureRequest().setFilterFid( newFeatureIds.at( i ) ) ).nextFeature( feature ) ) { features << feature; } } // copy features to remote layer emit progressModeSet( QgsOfflineEditing::AddFeatures, features.size() ); int i = 1; int newAttrsCount = remoteLayer->pendingFields().count(); for ( QgsFeatureList::iterator it = features.begin(); it != features.end(); ++it ) { QgsFeature f = *it; // NOTE: Spatialite provider ignores position of geometry column // restore gap in QgsAttributeMap if geometry column is not last (WORKAROUND) QMap<int, int> attrLookup = attributeLookup( offlineLayer, remoteLayer ); QgsAttributes newAttrs( newAttrsCount ); QgsAttributes attrs = f.attributes(); for ( int it = 0; it < attrs.count(); ++it ) { newAttrs[ attrLookup[ it ] ] = attrs[ it ]; } f.setAttributes( newAttrs ); remoteLayer->addFeature( f, false ); emit progressUpdated( i++ ); } }
bool QgsMemoryProvider::deleteAttributes( const QgsAttributeIds& attributes ) { QList<int> attrIdx = attributes.toList(); qSort( attrIdx.begin(), attrIdx.end(), qGreater<int>() ); // delete attributes one-by-one with decreasing index for ( QList<int>::const_iterator it = attrIdx.constBegin(); it != attrIdx.constEnd(); ++it ) { int idx = *it; mFields.remove( idx ); for ( QgsFeatureMap::iterator fit = mFeatures.begin(); fit != mFeatures.end(); ++fit ) { QgsFeature& f = fit.value(); QgsAttributes attr = f.attributes(); attr.remove( idx ); f.setAttributes( attr ); } } return true; }
bool QgsMapToolLabel::currentLabelDataDefinedPosition( double &x, bool &xSuccess, double &y, bool &ySuccess, int &xCol, int &yCol ) const { QgsVectorLayer *vlayer = mCurrentLabel.layer; QgsFeatureId featureId = mCurrentLabel.pos.featureId; xSuccess = false; ySuccess = false; if ( !vlayer ) { return false; } if ( mCurrentLabel.pos.isDiagram ) { if ( !diagramMoveable( vlayer, xCol, yCol ) ) { return false; } } else if ( !labelMoveable( vlayer, mCurrentLabel.settings, xCol, yCol ) ) { return false; } QgsFeature f; if ( !vlayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setFlags( QgsFeatureRequest::NoGeometry ) ).nextFeature( f ) ) { return false; } QgsAttributes attributes = f.attributes(); if ( !attributes.at( xCol ).isNull() ) x = attributes.at( xCol ).toDouble( &xSuccess ); if ( !attributes.at( yCol ).isNull() ) y = attributes.at( yCol ).toDouble( &ySuccess ); return true; }
QWidget *QgsFormAnnotation::createDesignerWidget( const QString &filePath ) { QFile file( filePath ); if ( !file.open( QFile::ReadOnly ) ) { return nullptr; } QUiLoader loader; QFileInfo fi( file ); loader.setWorkingDirectory( fi.dir() ); QWidget *widget = loader.load( &file, nullptr ); file.close(); //get feature and set attribute information QgsAttributeEditorContext context; QgsVectorLayer *vectorLayer = qobject_cast< QgsVectorLayer * >( mapLayer() ); if ( vectorLayer && associatedFeature().isValid() ) { QgsFields fields = vectorLayer->fields(); QgsAttributes attrs = associatedFeature().attributes(); for ( int i = 0; i < attrs.count(); ++i ) { if ( i < fields.count() ) { QWidget *attWidget = widget->findChild<QWidget *>( fields.at( i ).name() ); if ( attWidget ) { QgsEditorWidgetWrapper *eww = QgsGui::editorWidgetRegistry()->create( vectorLayer, i, attWidget, widget, context ); if ( eww ) { eww->setValue( attrs.at( i ) ); } } } } } return widget; }
/** * Slot called when the index changes for the cboxCompassBearingField combo box. * @param theIndex - The index of the new selected item */ void eVisGenericEventBrowserGui::on_cboxCompassOffsetField_currentIndexChanged( int theIndex ) { Q_UNUSED( theIndex ); if ( !mIgnoreEvent ) { mConfiguration.setCompassOffsetField( cboxCompassOffsetField->currentText() ); QgsFields myFields = mDataProvider->fields(); QgsFeature* myFeature = featureAtId( mFeatureIds.at( mCurrentFeatureIndex ) ); if ( !myFeature ) return; QgsAttributes myAttrs = myFeature->attributes(); for ( int i = 0; i < myAttrs.count(); ++i ) { if ( myFields.at( i ).name() == cboxCompassOffsetField->currentText() ) { mCompassOffset = myAttrs.at( i ).toDouble(); } } } }
/** * Slot called when the index changes for the cboxEventImagePathField combo box. * \param index - The index of the new selected item */ void eVisGenericEventBrowserGui::cboxEventImagePathField_currentIndexChanged( int index ) { Q_UNUSED( index ); if ( !mIgnoreEvent ) { mConfiguration.setEventImagePathField( cboxEventImagePathField->currentText() ); QgsFields myFields = mVectorLayer->fields(); QgsFeature *myFeature = featureAtId( mFeatureIds.at( mCurrentFeatureIndex ) ); if ( !myFeature ) return; QgsAttributes myAttrs = myFeature->attributes(); for ( int i = 0; i < myAttrs.count(); ++i ) { if ( myFields.at( i ).name() == cboxEventImagePathField->currentText() ) { mEventImagePath = myAttrs.at( i ).toString(); } } } }
void QgsVectorLayerEditBuffer::updateChangedAttributes( QgsFeature &f ) { QgsAttributes attrs = f.attributes(); // remove all attributes that will disappear - from higher indices to lower for ( int idx = mDeletedAttributeIds.count() - 1; idx >= 0; --idx ) { attrs.remove( mDeletedAttributeIds[idx] ); } // adjust size to accommodate added attributes attrs.resize( attrs.count() + mAddedAttributes.count() ); // update changed attributes if ( mChangedAttributeValues.contains( f.id() ) ) { const QgsAttributeMap &map = mChangedAttributeValues[f.id()]; for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); ++it ) attrs[it.key()] = it.value(); } f.setAttributes( attrs ); }
QVariantMap QgsLineIntersectionAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) { std::unique_ptr< QgsFeatureSource > sourceA( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) ); if ( !sourceA ) throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) ); std::unique_ptr< QgsFeatureSource > sourceB( parameterAsSource( parameters, QStringLiteral( "INTERSECT" ), context ) ); if ( !sourceB ) throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INTERSECT" ) ) ); const QStringList fieldsA = parameterAsFields( parameters, QStringLiteral( "INPUT_FIELDS" ), context ); const QStringList fieldsB = parameterAsFields( parameters, QStringLiteral( "INTERSECT_FIELDS" ), context ); QgsAttributeList fieldIndicesA = QgsProcessingUtils::fieldNamesToIndices( fieldsA, sourceA->fields() ); QgsAttributeList fieldIndicesB = QgsProcessingUtils::fieldNamesToIndices( fieldsB, sourceB->fields() ); QString intersectFieldsPrefix = parameterAsString( parameters, QStringLiteral( "INTERSECT_FIELDS_PREFIX" ), context ); QgsFields outFields = QgsProcessingUtils::combineFields( QgsProcessingUtils::indicesToFields( fieldIndicesA, sourceA->fields() ), QgsProcessingUtils::indicesToFields( fieldIndicesB, sourceB->fields() ), intersectFieldsPrefix ); QString dest; std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, outFields, QgsWkbTypes::Point, sourceA->sourceCrs(), QgsFeatureSink::RegeneratePrimaryKey ) ); if ( !sink ) throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) ); QgsSpatialIndex spatialIndex( sourceB->getFeatures( QgsFeatureRequest().setNoAttributes().setDestinationCrs( sourceA->sourceCrs(), context.transformContext() ) ), feedback ); QgsFeature outFeature; QgsFeatureIterator features = sourceA->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( fieldIndicesA ) ); double step = sourceA->featureCount() > 0 ? 100.0 / sourceA->featureCount() : 1; int i = 0; QgsFeature inFeatureA; while ( features.nextFeature( inFeatureA ) ) { i++; if ( feedback->isCanceled() ) { break; } if ( !inFeatureA.hasGeometry() ) continue; QgsGeometry inGeom = inFeatureA.geometry(); QgsFeatureIds lines = spatialIndex.intersects( inGeom.boundingBox() ).toSet(); if ( !lines.empty() ) { // use prepared geometries for faster intersection tests std::unique_ptr< QgsGeometryEngine > engine( QgsGeometry::createGeometryEngine( inGeom.constGet() ) ); engine->prepareGeometry(); QgsFeatureRequest request = QgsFeatureRequest().setFilterFids( lines ); request.setDestinationCrs( sourceA->sourceCrs(), context.transformContext() ); request.setSubsetOfAttributes( fieldIndicesB ); QgsFeature inFeatureB; QgsFeatureIterator featuresB = sourceB->getFeatures( request ); while ( featuresB.nextFeature( inFeatureB ) ) { if ( feedback->isCanceled() ) { break; } QgsGeometry tmpGeom = inFeatureB.geometry(); if ( engine->intersects( tmpGeom.constGet() ) ) { QgsMultiPointXY points; QgsGeometry intersectGeom = inGeom.intersection( tmpGeom ); QgsAttributes outAttributes; for ( int a : qgis::as_const( fieldIndicesA ) ) { outAttributes.append( inFeatureA.attribute( a ) ); } for ( int b : qgis::as_const( fieldIndicesB ) ) { outAttributes.append( inFeatureB.attribute( b ) ); } if ( QgsWkbTypes::flatType( intersectGeom.wkbType() ) == QgsWkbTypes::GeometryCollection ) { const QVector<QgsGeometry> geomCollection = intersectGeom.asGeometryCollection(); for ( const QgsGeometry &part : geomCollection ) { if ( part.type() == QgsWkbTypes::PointGeometry ) { if ( part.isMultipart() ) { points = part.asMultiPoint(); } else { points.append( part.asPoint() ); } } } } else if ( intersectGeom.type() == QgsWkbTypes::PointGeometry ) { if ( intersectGeom.isMultipart() ) { points = intersectGeom.asMultiPoint(); } else { points.append( intersectGeom.asPoint() ); } } for ( const QgsPointXY &j : qgis::as_const( points ) ) { outFeature.setGeometry( QgsGeometry::fromPointXY( j ) ); outFeature.setAttributes( outAttributes ); sink->addFeature( outFeature, QgsFeatureSink::FastInsert ); } } } } feedback->setProgress( i * step ); } QVariantMap outputs; outputs.insert( QStringLiteral( "OUTPUT" ), dest ); return outputs; }
bool QgsWFSProvider::addFeatures( QgsFeatureList &flist ) { //create <Transaction> xml QDomDocument transactionDoc; QDomElement transactionElem = createTransactionElement( transactionDoc ); transactionDoc.appendChild( transactionElem ); //find out typename from uri and strip namespace prefix QString tname = mShared->mURI.typeName(); if ( tname.isNull() ) { return false; } removeNamespacePrefix( tname ); //Add the features QgsFeatureList::iterator featureIt = flist.begin(); for ( ; featureIt != flist.end(); ++featureIt ) { //Insert element QDomElement insertElem = transactionDoc.createElementNS( QgsWFSConstants::WFS_NAMESPACE, "Insert" ); transactionElem.appendChild( insertElem ); QDomElement featureElem = transactionDoc.createElementNS( mApplicationNamespace, tname ); QgsAttributes featureAttributes = featureIt->attributes(); int nAttrs = featureAttributes.size(); for ( int i = 0; i < nAttrs; ++i ) { const QVariant& value = featureAttributes.at( i ); if ( value.isValid() && !value.isNull() ) { QDomElement fieldElem = transactionDoc.createElementNS( mApplicationNamespace, mShared->mFields.at( i ).name() ); QDomText fieldText = transactionDoc.createTextNode( value.toString() ); fieldElem.appendChild( fieldText ); featureElem.appendChild( fieldElem ); } } //add geometry column (as gml) const QgsGeometry* geometry = featureIt->constGeometry(); if ( geometry != nullptr ) { QDomElement geomElem = transactionDoc.createElementNS( mApplicationNamespace, mShared->mGeometryAttribute ); QgsGeometry the_geom( *geometry ); // convert to multi if the layer geom type is multi and the geom is not if ( QGis::isMultiType( this->geometryType( ) ) && ! the_geom.isMultipart( ) ) { the_geom.convertToMultiType(); } QDomElement gmlElem = QgsOgcUtils::geometryToGML( &the_geom, transactionDoc ); if ( !gmlElem.isNull() ) { gmlElem.setAttribute( "srsName", crs().authid() ); geomElem.appendChild( gmlElem ); featureElem.appendChild( geomElem ); } } insertElem.appendChild( featureElem ); } QDomDocument serverResponse; bool success = sendTransactionDocument( transactionDoc, serverResponse ); if ( !success ) { return false; } if ( transactionSuccess( serverResponse ) ) { //transaction successful. Add the features to the cache QStringList idList = insertedFeatureIds( serverResponse ); QStringList::const_iterator idIt = idList.constBegin(); featureIt = flist.begin(); QVector<QgsWFSFeatureGmlIdPair> serializedFeatureList; for ( ; idIt != idList.constEnd() && featureIt != flist.end(); ++idIt, ++featureIt ) { serializedFeatureList.push_back( QgsWFSFeatureGmlIdPair( *featureIt, *idIt ) ); } mShared->serializeFeatures( serializedFeatureList ); // And now set the feature id from the one got from the database QMap< QString, QgsFeatureId > map; for ( int idx = 0; idx < serializedFeatureList.size(); idx++ ) map[ serializedFeatureList[idx].second ] = serializedFeatureList[idx].first.id(); idIt = idList.constBegin(); featureIt = flist.begin(); for ( ; idIt != idList.constEnd() && featureIt != flist.end(); ++idIt, ++featureIt ) { if ( map.find( *idIt ) != map.end() ) featureIt->setFeatureId( map[*idIt] ); } return true; } else { handleException( serverResponse ); return false; } }
bool QgsHeatmapRenderer::renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker ) { Q_UNUSED( layer ); Q_UNUSED( selected ); Q_UNUSED( drawVertexMarker ); if ( !context.painter() ) { return false; } if ( !feature.constGeometry() || feature.constGeometry()->type() != QGis::Point ) { //can only render point type return false; } double weight = 1.0; if ( !mWeightExpressionString.isEmpty() ) { QVariant value; if ( mWeightAttrNum == -1 ) { Q_ASSERT( mWeightExpression.data() ); value = mWeightExpression->evaluate( &feature ); } else { QgsAttributes attrs = feature.attributes(); value = attrs.value( mWeightAttrNum ); } bool ok = false; double evalWeight = value.toDouble( &ok ); if ( ok ) { weight = evalWeight; } } int width = context.painter()->device()->width() / mRenderQuality; int height = context.painter()->device()->height() / mRenderQuality; //transform geometry if required QgsGeometry* transformedGeom = 0; const QgsCoordinateTransform* xform = context.coordinateTransform(); if ( xform ) { transformedGeom = new QgsGeometry( *feature.constGeometry() ); transformedGeom->transform( *xform ); } //convert point to multipoint QgsMultiPoint multiPoint = convertToMultipoint( transformedGeom ? transformedGeom : feature.constGeometry() ); delete transformedGeom; transformedGeom = 0; //loop through all points in multipoint for ( QgsMultiPoint::const_iterator pointIt = multiPoint.constBegin(); pointIt != multiPoint.constEnd(); ++pointIt ) { QgsPoint pixel = context.mapToPixel().transform( *pointIt ); int pointX = pixel.x() / mRenderQuality; int pointY = pixel.y() / mRenderQuality; for ( int x = qMax( pointX - mRadiusPixels, 0 ); x < qMin( pointX + mRadiusPixels, width ); ++x ) { for ( int y = qMax( pointY - mRadiusPixels, 0 ); y < qMin( pointY + mRadiusPixels, height ); ++y ) { int index = y * width + x; if ( index >= mValues.count( ) ) { continue; } double distanceSquared = pow( pointX - x, 2.0 ) + pow( pointY - y, 2.0 ); if ( distanceSquared > mRadiusSquared ) { continue; } double score = weight * quarticKernel( sqrt( distanceSquared ), mRadiusPixels ); double value = mValues[ index ] + score; if ( value > mCalculatedMaxValue ) { mCalculatedMaxValue = value; } mValues[ index ] = value; } } } mFeaturesRendered++; #if 0 //TODO - enable progressive rendering if ( mFeaturesRendered % 200 == 0 ) { renderImage( context ); } #endif return true; }
QString QgsClipboard::generateClipboardText() const { QgsSettings settings; CopyFormat format = AttributesWithWKT; if ( settings.contains( QStringLiteral( "/qgis/copyFeatureFormat" ) ) ) format = static_cast< CopyFormat >( settings.value( QStringLiteral( "qgis/copyFeatureFormat" ), true ).toInt() ); else { //old format setting format = settings.value( QStringLiteral( "qgis/copyGeometryAsWKT" ), true ).toBool() ? AttributesWithWKT : AttributesOnly; } switch ( format ) { case AttributesOnly: case AttributesWithWKT: { QStringList textLines; QStringList textFields; // first do the field names if ( format == AttributesWithWKT ) { textFields += QStringLiteral( "wkt_geom" ); } Q_FOREACH ( const QgsField &field, mFeatureFields ) { textFields += field.name(); } textLines += textFields.join( QStringLiteral( "\t" ) ); textFields.clear(); // then the field contents for ( QgsFeatureList::const_iterator it = mFeatureClipboard.constBegin(); it != mFeatureClipboard.constEnd(); ++it ) { QgsAttributes attributes = it->attributes(); // TODO: Set up Paste Transformations to specify the order in which fields are added. if ( format == AttributesWithWKT ) { if ( it->hasGeometry() ) textFields += it->geometry().exportToWkt(); else { textFields += QgsApplication::nullRepresentation(); } } // QgsDebugMsg("about to traverse fields."); for ( int idx = 0; idx < attributes.count(); ++idx ) { // QgsDebugMsg(QString("inspecting field '%1'.").arg(it2->toString())); textFields += attributes.at( idx ).toString(); } textLines += textFields.join( QStringLiteral( "\t" ) ); textFields.clear(); } return textLines.join( QStringLiteral( "\n" ) ); } case GeoJSON: { QgsJSONExporter exporter; exporter.setSourceCrs( mCRS ); return exporter.exportFeatures( mFeatureClipboard ); } } return QString(); }
void QgsMergeAttributesDialog::createTableWidgetContents() { //get information about attributes from vector layer if ( !mVectorLayer ) { return; } //combo box row, attributes titles, feature values and current merge results mTableWidget->setRowCount( mFeatureList.size() + 2 ); //create combo boxes and insert attribute names mFields = mVectorLayer->fields(); int col = 0; mHiddenAttributes.clear(); for ( int idx = 0; idx < mFields.count(); ++idx ) { const QgsEditorWidgetSetup setup = QgsGui::editorWidgetRegistry()->findBest( mVectorLayer, mFields.at( idx ).name() ); if ( setup.type() == QLatin1String( "Hidden" ) || setup.type() == QLatin1String( "Immutable" ) ) { mHiddenAttributes.insert( idx ); continue; } mTableWidget->setColumnCount( col + 1 ); QComboBox *cb = createMergeComboBox( mFields.at( idx ).type() ); if ( mFields.at( idx ).constraints().constraints() & QgsFieldConstraints::ConstraintUnique ) { cb->setCurrentIndex( cb->findData( "skip" ) ); } mTableWidget->setCellWidget( 0, col, cb ); QTableWidgetItem *item = new QTableWidgetItem( mFields.at( idx ).name() ); item->setData( FieldIndex, idx ); mTableWidget->setHorizontalHeaderItem( col++, item ); } //insert the attribute values QStringList verticalHeaderLabels; //the id column is in the verticalHeaderLabels << tr( "Id" ); for ( int i = 0; i < mFeatureList.size(); ++i ) { verticalHeaderLabels << FID_TO_STRING( mFeatureList[i].id() ); QgsAttributes attrs = mFeatureList.at( i ).attributes(); for ( int j = 0; j < mTableWidget->columnCount(); j++ ) { int idx = mTableWidget->horizontalHeaderItem( j )->data( FieldIndex ).toInt(); const QgsEditorWidgetSetup setup = mFields.at( idx ).editorWidgetSetup(); const QgsFieldFormatter *formatter = QgsApplication::fieldFormatterRegistry()->fieldFormatter( setup.type() ); QString stringVal = formatter->representValue( mVectorLayer, idx, setup.config(), QVariant(), attrs.at( idx ) ); QTableWidgetItem *attributeValItem = new QTableWidgetItem( stringVal ); attributeValItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable ); mTableWidget->setItem( i + 1, j, attributeValItem ); } } //merge verticalHeaderLabels << tr( "Merge" ); mTableWidget->setVerticalHeaderLabels( verticalHeaderLabels ); for ( int j = 0; j < mTableWidget->columnCount(); j++ ) { QTableWidgetItem *mergedItem = new QTableWidgetItem(); mergedItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable ); mTableWidget->setItem( mTableWidget->rowCount() - 1, j, mergedItem ); } //insert currently merged values for ( int i = 0; i < mTableWidget->columnCount(); ++i ) { refreshMergedValue( i ); } //initially set any fields with default values/default value clauses to that value for ( int j = 0; j < mTableWidget->columnCount(); j++ ) { int idx = mTableWidget->horizontalHeaderItem( j )->data( FieldIndex ).toInt(); bool setToManual = false; if ( !mVectorLayer->dataProvider()->defaultValueClause( idx ).isEmpty() ) { mTableWidget->item( mTableWidget->rowCount() - 1, j )->setData( Qt::DisplayRole, mVectorLayer->dataProvider()->defaultValueClause( idx ) ); setToManual = true; } else { QVariant v = mVectorLayer->dataProvider()->defaultValue( idx ); if ( v.isValid() ) { mTableWidget->item( mTableWidget->rowCount() - 1, j )->setData( Qt::DisplayRole, v ); setToManual = true; } } if ( setToManual ) { QComboBox *currentComboBox = qobject_cast<QComboBox *>( mTableWidget->cellWidget( 0, j ) ); if ( currentComboBox ) { currentComboBox->blockSignals( true ); currentComboBox->setCurrentIndex( currentComboBox->findData( "manual" ) ); currentComboBox->blockSignals( false ); } } } }
QVariantMap QgsShortestPathPointToLayerAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) { loadCommonParams( parameters, context, feedback ); QgsPointXY startPoint = parameterAsPoint( parameters, QStringLiteral( "START_POINT" ), context, mNetwork->sourceCrs() ); std::unique_ptr< QgsFeatureSource > endPoints( parameterAsSource( parameters, QStringLiteral( "END_POINTS" ), context ) ); if ( !endPoints ) throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "END_POINTS" ) ) ); QgsFields fields = endPoints->fields(); fields.append( QgsField( QStringLiteral( "start" ), QVariant::String ) ); fields.append( QgsField( QStringLiteral( "end" ), QVariant::String ) ); fields.append( QgsField( QStringLiteral( "cost" ), QVariant::Double ) ); QString dest; std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, QgsWkbTypes::LineString, mNetwork->sourceCrs() ) ); if ( !sink ) throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) ); QVector< QgsPointXY > points; points.push_front( startPoint ); QHash< int, QgsAttributes > sourceAttributes; loadPoints( endPoints.get(), points, sourceAttributes, context, feedback ); feedback->pushInfo( QObject::tr( "Building graph…" ) ); QVector< QgsPointXY > snappedPoints; mDirector->makeGraph( mBuilder.get(), points, snappedPoints, feedback ); feedback->pushInfo( QObject::tr( "Calculating shortest paths…" ) ); QgsGraph *graph = mBuilder->graph(); int idxStart = graph->findVertex( snappedPoints[0] ); int idxEnd; QVector< int > tree; QVector< double > costs; QgsGraphAnalyzer::dijkstra( graph, idxStart, 0, &tree, &costs ); QVector<QgsPointXY> route; double cost; QgsFeature feat; feat.setFields( fields ); QgsAttributes attributes; int step = points.size() > 0 ? 100.0 / points.size() : 1; for ( int i = 1; i < points.size(); i++ ) { if ( feedback->isCanceled() ) { break; } idxEnd = graph->findVertex( snappedPoints[i] ); if ( tree.at( idxEnd ) == -1 ) { feedback->reportError( QObject::tr( "There is no route from start point (%1) to end point (%2)." ) .arg( startPoint.toString(), points[i].toString() ) ); feat.clearGeometry(); attributes = sourceAttributes.value( i ); attributes.append( QVariant() ); attributes.append( points[i].toString() ); feat.setAttributes( attributes ); sink->addFeature( feat, QgsFeatureSink::FastInsert ); continue; } route.clear(); route.push_front( graph->vertex( idxEnd ).point() ); cost = costs.at( idxEnd ); while ( idxEnd != idxStart ) { idxEnd = graph->edge( tree.at( idxEnd ) ).fromVertex(); route.push_front( graph->vertex( idxEnd ).point() ); } QgsGeometry geom = QgsGeometry::fromPolylineXY( route ); QgsFeature feat; feat.setFields( fields ); attributes = sourceAttributes.value( i ); attributes.append( startPoint.toString() ); attributes.append( points[i].toString() ); attributes.append( cost / mMultiplier ); feat.setAttributes( attributes ); feat.setGeometry( geom ); sink->addFeature( feat, QgsFeatureSink::FastInsert ); feedback->setProgress( i * step ); } QVariantMap outputs; outputs.insert( QStringLiteral( "OUTPUT" ), dest ); return outputs; }
/** * Display the attrbiutes for the current feature and load the image */ void eVisGenericEventBrowserGui::loadRecord() { treeEventData->clear(); //Get a pointer to the current feature QgsFeature* myFeature; myFeature = featureAtId( mFeatureIds.at( mCurrentFeatureIndex ) ); if ( !myFeature ) return; QString myCompassBearingField = cboxCompassBearingField->currentText(); QString myCompassOffsetField = cboxCompassOffsetField->currentText(); QString myEventImagePathField = cboxEventImagePathField->currentText(); QgsFields myFields = mDataProvider->fields(); QgsAttributes myAttrs = myFeature->attributes(); //loop through the attributes and display their contents for ( int i = 0; i < myAttrs.count(); ++i ) { QStringList myValues; QString fieldName = myFields.at( i ).name(); myValues << fieldName << myAttrs.at( i ).toString(); QTreeWidgetItem* myItem = new QTreeWidgetItem( myValues ); if ( fieldName == myEventImagePathField ) { mEventImagePath = myAttrs.at( i ).toString(); } if ( fieldName == myCompassBearingField ) { mCompassBearing = myAttrs.at( i ).toDouble(); } if ( mConfiguration.isAttributeCompassOffsetSet() ) { if ( fieldName == myCompassOffsetField ) { mCompassOffset = myAttrs.at( i ).toDouble(); } } else { mCompassOffset = 0.0; } //Check to see if the attribute is a know file type int myIterator = 0; while ( myIterator < tableFileTypeAssociations->rowCount() ) { if ( tableFileTypeAssociations->item( myIterator, 0 ) && ( myAttrs.at( i ).toString().startsWith( tableFileTypeAssociations->item( myIterator, 0 )->text() + ':', Qt::CaseInsensitive ) || myAttrs.at( i ).toString().endsWith( tableFileTypeAssociations->item( myIterator, 0 )->text(), Qt::CaseInsensitive ) ) ) { myItem->setBackground( 1, QBrush( QColor( 183, 216, 125, 255 ) ) ); break; } else myIterator++; } treeEventData->addTopLevelItem( myItem ); } //Modify EventImagePath as needed buildEventImagePath(); //Request the image to be displayed in the browser displayImage(); }
QVariantMap QgsJoinWithLinesAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) { if ( parameters.value( QStringLiteral( "SPOKES" ) ) == parameters.value( QStringLiteral( "HUBS" ) ) ) throw QgsProcessingException( QObject::tr( "Same layer given for both hubs and spokes" ) ); std::unique_ptr< QgsProcessingFeatureSource > hubSource( parameterAsSource( parameters, QStringLiteral( "HUBS" ), context ) ); if ( !hubSource ) throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "HUBS" ) ) ); std::unique_ptr< QgsProcessingFeatureSource > spokeSource( parameterAsSource( parameters, QStringLiteral( "SPOKES" ), context ) ); if ( !hubSource || !spokeSource ) throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "SPOKES" ) ) ); QString fieldHubName = parameterAsString( parameters, QStringLiteral( "HUB_FIELD" ), context ); int fieldHubIndex = hubSource->fields().lookupField( fieldHubName ); const QStringList hubFieldsToCopy = parameterAsFields( parameters, QStringLiteral( "HUB_FIELDS" ), context ); QString fieldSpokeName = parameterAsString( parameters, QStringLiteral( "SPOKE_FIELD" ), context ); int fieldSpokeIndex = spokeSource->fields().lookupField( fieldSpokeName ); const QStringList spokeFieldsToCopy = parameterAsFields( parameters, QStringLiteral( "SPOKE_FIELDS" ), context ); if ( fieldHubIndex < 0 || fieldSpokeIndex < 0 ) throw QgsProcessingException( QObject::tr( "Invalid ID field" ) ); const bool geodesic = parameterAsBool( parameters, QStringLiteral( "GEODESIC" ), context ); const double geodesicDistance = parameterAsDouble( parameters, QStringLiteral( "GEODESIC_DISTANCE" ), context ) * 1000; bool dynamicGeodesicDistance = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "GEODESIC_DISTANCE" ) ); QgsExpressionContext expressionContext = createExpressionContext( parameters, context, hubSource.get() ); QgsProperty geodesicDistanceProperty; if ( dynamicGeodesicDistance ) { geodesicDistanceProperty = parameters.value( QStringLiteral( "GEODESIC_DISTANCE" ) ).value< QgsProperty >(); } const bool splitAntimeridian = parameterAsBool( parameters, QStringLiteral( "ANTIMERIDIAN_SPLIT" ), context ); QgsDistanceArea da; da.setSourceCrs( hubSource->sourceCrs(), context.transformContext() ); da.setEllipsoid( context.project()->ellipsoid() ); QgsFields hubOutFields; QgsAttributeList hubFieldIndices; if ( hubFieldsToCopy.empty() ) { hubOutFields = hubSource->fields(); hubFieldIndices.reserve( hubOutFields.count() ); for ( int i = 0; i < hubOutFields.count(); ++i ) { hubFieldIndices << i; } } else { hubFieldIndices.reserve( hubOutFields.count() ); for ( const QString &field : hubFieldsToCopy ) { int index = hubSource->fields().lookupField( field ); if ( index >= 0 ) { hubFieldIndices << index; hubOutFields.append( hubSource->fields().at( index ) ); } } } QgsAttributeList hubFields2Fetch = hubFieldIndices; hubFields2Fetch << fieldHubIndex; QgsFields spokeOutFields; QgsAttributeList spokeFieldIndices; if ( spokeFieldsToCopy.empty() ) { spokeOutFields = spokeSource->fields(); spokeFieldIndices.reserve( spokeOutFields.count() ); for ( int i = 0; i < spokeOutFields.count(); ++i ) { spokeFieldIndices << i; } } else { for ( const QString &field : spokeFieldsToCopy ) { int index = spokeSource->fields().lookupField( field ); if ( index >= 0 ) { spokeFieldIndices << index; spokeOutFields.append( spokeSource->fields().at( index ) ); } } } QgsAttributeList spokeFields2Fetch = spokeFieldIndices; spokeFields2Fetch << fieldSpokeIndex; QgsFields fields = QgsProcessingUtils::combineFields( hubOutFields, spokeOutFields ); QgsWkbTypes::Type outType = geodesic ? QgsWkbTypes::MultiLineString : QgsWkbTypes::LineString; bool hasZ = false; if ( QgsWkbTypes::hasZ( hubSource->wkbType() ) || QgsWkbTypes::hasZ( spokeSource->wkbType() ) ) { outType = QgsWkbTypes::addZ( outType ); hasZ = true; } bool hasM = false; if ( QgsWkbTypes::hasM( hubSource->wkbType() ) || QgsWkbTypes::hasM( spokeSource->wkbType() ) ) { outType = QgsWkbTypes::addM( outType ); hasM = true; } QString dest; std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, outType, hubSource->sourceCrs(), QgsFeatureSink::RegeneratePrimaryKey ) ); if ( !sink ) throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) ); auto getPointFromFeature = [hasZ, hasM]( const QgsFeature & feature )->QgsPoint { QgsPoint p; if ( feature.geometry().type() == QgsWkbTypes::PointGeometry && !feature.geometry().isMultipart() ) p = *static_cast< const QgsPoint *>( feature.geometry().constGet() ); else p = *static_cast< const QgsPoint *>( feature.geometry().pointOnSurface().constGet() ); if ( hasZ && !p.is3D() ) p.addZValue( 0 ); if ( hasM && !p.isMeasure() ) p.addMValue( 0 ); return p; }; QgsFeatureIterator hubFeatures = hubSource->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( hubFields2Fetch ), QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks ); double step = hubSource->featureCount() > 0 ? 100.0 / hubSource->featureCount() : 1; int i = 0; QgsFeature hubFeature; while ( hubFeatures.nextFeature( hubFeature ) ) { i++; if ( feedback->isCanceled() ) { break; } feedback->setProgress( i * step ); if ( !hubFeature.hasGeometry() ) continue; QgsPoint hubPoint = getPointFromFeature( hubFeature ); // only keep selected attributes QgsAttributes hubAttributes; for ( int j = 0; j < hubFeature.attributes().count(); ++j ) { if ( !hubFieldIndices.contains( j ) ) continue; hubAttributes << hubFeature.attribute( j ); } QgsFeatureRequest spokeRequest = QgsFeatureRequest().setDestinationCrs( hubSource->sourceCrs(), context.transformContext() ); spokeRequest.setSubsetOfAttributes( spokeFields2Fetch ); spokeRequest.setFilterExpression( QgsExpression::createFieldEqualityExpression( fieldSpokeName, hubFeature.attribute( fieldHubIndex ) ) ); QgsFeatureIterator spokeFeatures = spokeSource->getFeatures( spokeRequest, QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks ); QgsFeature spokeFeature; while ( spokeFeatures.nextFeature( spokeFeature ) ) { if ( feedback->isCanceled() ) { break; } if ( !spokeFeature.hasGeometry() ) continue; QgsPoint spokePoint = getPointFromFeature( spokeFeature ); QgsGeometry line; if ( !geodesic ) { line = QgsGeometry( new QgsLineString( QVector< QgsPoint >() << hubPoint << spokePoint ) ); if ( splitAntimeridian ) line = da.splitGeometryAtAntimeridian( line ); } else { double distance = geodesicDistance; if ( dynamicGeodesicDistance ) { expressionContext.setFeature( hubFeature ); distance = geodesicDistanceProperty.valueAsDouble( expressionContext, distance ); } std::unique_ptr< QgsMultiLineString > ml = qgis::make_unique< QgsMultiLineString >(); std::unique_ptr< QgsLineString > l = qgis::make_unique< QgsLineString >( QVector< QgsPoint >() << hubPoint ); QVector< QVector< QgsPointXY > > points = da.geodesicLine( QgsPointXY( hubPoint ), QgsPointXY( spokePoint ), distance, splitAntimeridian ); QVector< QgsPointXY > points1 = points.at( 0 ); points1.pop_front(); if ( points.count() == 1 ) points1.pop_back(); QgsLineString geodesicPoints( points1 ); l->append( &geodesicPoints ); if ( points.count() == 1 ) l->addVertex( spokePoint ); ml->addGeometry( l.release() ); if ( points.count() > 1 ) { QVector< QgsPointXY > points2 = points.at( 1 ); points2.pop_back(); l = qgis::make_unique< QgsLineString >( points2 ); if ( hasZ ) l->addZValue( std::numeric_limits<double>::quiet_NaN() ); if ( hasM ) l->addMValue( std::numeric_limits<double>::quiet_NaN() ); l->addVertex( spokePoint ); ml->addGeometry( l.release() ); } line = QgsGeometry( std::move( ml ) ); } QgsFeature outFeature; QgsAttributes outAttributes = hubAttributes; // only keep selected attributes QgsAttributes spokeAttributes; for ( int j = 0; j < spokeFeature.attributes().count(); ++j ) { if ( !spokeFieldIndices.contains( j ) ) continue; spokeAttributes << spokeFeature.attribute( j ); } outAttributes.append( spokeAttributes ); outFeature.setAttributes( outAttributes ); outFeature.setGeometry( line ); sink->addFeature( outFeature, QgsFeatureSink::FastInsert ); } } QVariantMap outputs; outputs.insert( QStringLiteral( "OUTPUT" ), dest ); return outputs; }
void QgsOverlayUtils::difference( const QgsFeatureSource &sourceA, const QgsFeatureSource &sourceB, QgsFeatureSink &sink, QgsProcessingContext &context, QgsProcessingFeedback *feedback, int &count, int totalCount, QgsOverlayUtils::DifferenceOutput outputAttrs ) { QgsFeatureRequest requestB; requestB.setSubsetOfAttributes( QgsAttributeList() ); if ( outputAttrs != OutputBA ) requestB.setDestinationCrs( sourceA.sourceCrs(), context.transformContext() ); QgsSpatialIndex indexB( sourceB.getFeatures( requestB ), feedback ); int fieldsCountA = sourceA.fields().count(); int fieldsCountB = sourceB.fields().count(); QgsAttributes attrs; attrs.resize( outputAttrs == OutputA ? fieldsCountA : ( fieldsCountA + fieldsCountB ) ); if ( totalCount == 0 ) totalCount = 1; // avoid division by zero QgsFeature featA; QgsFeatureRequest requestA; if ( outputAttrs == OutputBA ) requestA.setDestinationCrs( sourceB.sourceCrs(), context.transformContext() ); QgsFeatureIterator fitA = sourceA.getFeatures( requestA ); while ( fitA.nextFeature( featA ) ) { if ( feedback->isCanceled() ) break; if ( featA.hasGeometry() ) { QgsGeometry geom( featA.geometry() ); QgsFeatureIds intersects = indexB.intersects( geom.boundingBox() ).toSet(); QgsFeatureRequest request; request.setFilterFids( intersects ); request.setSubsetOfAttributes( QgsAttributeList() ); if ( outputAttrs != OutputBA ) request.setDestinationCrs( sourceA.sourceCrs(), context.transformContext() ); std::unique_ptr< QgsGeometryEngine > engine; if ( !intersects.isEmpty() ) { // use prepared geometries for faster intersection tests engine.reset( QgsGeometry::createGeometryEngine( geom.constGet() ) ); engine->prepareGeometry(); } QVector<QgsGeometry> geometriesB; QgsFeature featB; QgsFeatureIterator fitB = sourceB.getFeatures( request ); while ( fitB.nextFeature( featB ) ) { if ( feedback->isCanceled() ) break; if ( engine->intersects( featB.geometry().constGet() ) ) geometriesB << featB.geometry(); } if ( !geometriesB.isEmpty() ) { QgsGeometry geomB = QgsGeometry::unaryUnion( geometriesB ); geom = geom.difference( geomB ); } if ( !sanitizeDifferenceResult( geom ) ) continue; const QgsAttributes attrsA( featA.attributes() ); switch ( outputAttrs ) { case OutputA: attrs = attrsA; break; case OutputAB: for ( int i = 0; i < fieldsCountA; ++i ) attrs[i] = attrsA[i]; break; case OutputBA: for ( int i = 0; i < fieldsCountA; ++i ) attrs[i + fieldsCountB] = attrsA[i]; break; } QgsFeature outFeat; outFeat.setGeometry( geom ); outFeat.setAttributes( attrs ); sink.addFeature( outFeat, QgsFeatureSink::FastInsert ); } else { // TODO: should we write out features that do not have geometry? sink.addFeature( featA, QgsFeatureSink::FastInsert ); } ++count; feedback->setProgress( count / ( double ) totalCount * 100. ); } }
QVariantMap QgsBufferAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const { std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) ); if ( !source ) return QVariantMap(); QString dest; std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT_LAYER" ), context, source->fields(), QgsWkbTypes::Polygon, source->sourceCrs(), dest ) ); if ( !sink ) return QVariantMap(); // fixed parameters bool dissolve = parameterAsBool( parameters, QStringLiteral( "DISSOLVE" ), context ); int segments = parameterAsInt( parameters, QStringLiteral( "SEGMENTS" ), context ); QgsGeometry::EndCapStyle endCapStyle = static_cast< QgsGeometry::EndCapStyle >( 1 + parameterAsInt( parameters, QStringLiteral( "END_CAP_STYLE" ), context ) ); QgsGeometry::JoinStyle joinStyle = static_cast< QgsGeometry::JoinStyle>( 1 + parameterAsInt( parameters, QStringLiteral( "JOIN_STYLE" ), context ) ); double miterLimit = parameterAsDouble( parameters, QStringLiteral( "MITRE_LIMIT" ), context ); double bufferDistance = parameterAsDouble( parameters, QStringLiteral( "DISTANCE" ), context ); bool dynamicBuffer = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "DISTANCE" ) ); const QgsProcessingParameterDefinition *distanceParamDef = parameterDefinition( QStringLiteral( "DISTANCE" ) ); long count = source->featureCount(); if ( count <= 0 ) return QVariantMap(); QgsFeature f; QgsFeatureIterator it = source->getFeatures(); double step = 100.0 / count; int current = 0; QList< QgsGeometry > bufferedGeometriesForDissolve; QgsAttributes dissolveAttrs; while ( it.nextFeature( f ) ) { if ( feedback->isCanceled() ) { break; } if ( dissolveAttrs.isEmpty() ) dissolveAttrs = f.attributes(); QgsFeature out = f; if ( out.hasGeometry() ) { if ( dynamicBuffer ) { context.expressionContext().setFeature( f ); bufferDistance = QgsProcessingParameters::parameterAsDouble( distanceParamDef, parameters, context ); } QgsGeometry outputGeometry = f.geometry().buffer( bufferDistance, segments, endCapStyle, joinStyle, miterLimit ); if ( !outputGeometry ) { QgsMessageLog::logMessage( QObject::tr( "Error calculating buffer for feature %1" ).arg( f.id() ), QObject::tr( "Processing" ), QgsMessageLog::WARNING ); } if ( dissolve ) bufferedGeometriesForDissolve << outputGeometry; else out.setGeometry( outputGeometry ); } if ( !dissolve ) sink->addFeature( out ); feedback->setProgress( current * step ); current++; } if ( dissolve ) { QgsGeometry finalGeometry = QgsGeometry::unaryUnion( bufferedGeometriesForDissolve ); QgsFeature f; f.setGeometry( finalGeometry ); f.setAttributes( dissolveAttrs ); sink->addFeature( f ); } QVariantMap outputs; outputs.insert( QStringLiteral( "OUTPUT_LAYER" ), dest ); return outputs; }
void QgsVectorDataProvider::fillMinMaxCache() { if ( !mCacheMinMaxDirty ) return; const QgsFields& flds = fields(); for ( int i = 0; i < flds.count(); ++i ) { if ( flds[i].type() == QVariant::Int ) { mCacheMinValues[i] = QVariant( INT_MAX ); mCacheMaxValues[i] = QVariant( INT_MIN ); } else if ( flds[i].type() == QVariant::LongLong ) { mCacheMinValues[i] = QVariant( std::numeric_limits<qlonglong>::max() ); mCacheMaxValues[i] = QVariant( std::numeric_limits<qlonglong>::min() ); } else if ( flds[i].type() == QVariant::Double ) { mCacheMinValues[i] = QVariant( DBL_MAX ); mCacheMaxValues[i] = QVariant( -DBL_MAX ); } else { mCacheMinValues[i] = QVariant(); mCacheMaxValues[i] = QVariant(); } } QgsFeature f; QgsAttributeList keys = mCacheMinValues.keys(); QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) ); while ( fi.nextFeature( f ) ) { QgsAttributes attrs = f.attributes(); for ( QgsAttributeList::const_iterator it = keys.begin(); it != keys.end(); ++it ) { const QVariant& varValue = attrs.at( *it ); if ( varValue.isNull() ) continue; if ( flds[*it].type() == QVariant::Int ) { int value = varValue.toInt(); if ( value < mCacheMinValues[*it].toInt() ) mCacheMinValues[*it] = value; if ( value > mCacheMaxValues[*it].toInt() ) mCacheMaxValues[*it] = value; } else if ( flds[*it].type() == QVariant::LongLong ) { qlonglong value = varValue.toLongLong(); if ( value < mCacheMinValues[*it].toLongLong() ) mCacheMinValues[*it] = value; if ( value > mCacheMaxValues[*it].toLongLong() ) mCacheMaxValues[*it] = value; } else if ( flds[*it].type() == QVariant::Double ) { double value = varValue.toDouble(); if ( value < mCacheMinValues[*it].toDouble() ) mCacheMinValues[*it] = value; if ( value > mCacheMaxValues[*it].toDouble() ) mCacheMaxValues[*it] = value; } else { QString value = varValue.toString(); if ( mCacheMinValues[*it].isNull() || value < mCacheMinValues[*it].toString() ) { mCacheMinValues[*it] = value; } if ( mCacheMaxValues[*it].isNull() || value > mCacheMaxValues[*it].toString() ) { mCacheMaxValues[*it] = value; } } } } mCacheMinMaxDirty = false; }
void QgsMergeAttributesDialog::createTableWidgetContents() { //get information about attributes from vector layer if ( !mVectorLayer ) { return; } //combo box row, attributes titles, feature values and current merge results mTableWidget->setRowCount( mFeatureList.size() + 2 ); //create combo boxes and insert attribute names mFields = mVectorLayer->fields(); QSet<int> pkAttrList = mVectorLayer->pkAttributeList().toSet(); int col = 0; mHiddenAttributes.clear(); for ( int idx = 0; idx < mFields.count(); ++idx ) { const QgsEditorWidgetSetup setup = QgsEditorWidgetRegistry::instance()->findBest( mVectorLayer, mFields.at( idx ).name() ); if ( setup.type() == "Hidden" || setup.type() == "Immutable" ) { mHiddenAttributes.insert( idx ); continue; } mTableWidget->setColumnCount( col + 1 ); QComboBox *cb = createMergeComboBox( mFields.at( idx ).type() ); if ( pkAttrList.contains( idx ) ) { cb->setCurrentIndex( cb->findData( "skip" ) ); } mTableWidget->setCellWidget( 0, col, cb ); QTableWidgetItem *item = new QTableWidgetItem( mFields.at( idx ).name() ); item->setData( FieldIndex, idx ); mTableWidget->setHorizontalHeaderItem( col++, item ); } //insert the attribute values QStringList verticalHeaderLabels; //the id column is in the verticalHeaderLabels << tr( "Id" ); QgsAttributeEditorContext context; for ( int i = 0; i < mFeatureList.size(); ++i ) { verticalHeaderLabels << FID_TO_STRING( mFeatureList[i].id() ); QgsAttributes attrs = mFeatureList.at( i ).attributes(); for ( int j = 0; j < mTableWidget->columnCount(); j++ ) { int idx = mTableWidget->horizontalHeaderItem( j )->data( FieldIndex ).toInt(); QTableWidgetItem* attributeValItem = new QTableWidgetItem( attrs.at( idx ).toString() ); attributeValItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable ); mTableWidget->setItem( i + 1, j, attributeValItem ); QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( mVectorLayer, idx, nullptr, mTableWidget, context ); if ( eww ) { eww->setValue( attrs.at( idx ) ); } mTableWidget->setCellWidget( i + 1, j, eww->widget() ); } } //merge verticalHeaderLabels << tr( "Merge" ); mTableWidget->setVerticalHeaderLabels( verticalHeaderLabels ); //insert currently merged values for ( int i = 0; i < mTableWidget->columnCount(); ++i ) { refreshMergedValue( i ); } }