bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature ) const { feature.setFeatureId( OGR_F_GetFID( fet ) ); feature.initAttributes( mSource->mFields.count() ); feature.setFields( mSource->mFields ); // allow name-based attribute lookups bool useIntersect = mRequest.flags() & QgsFeatureRequest::ExactIntersect; bool geometryTypeFilter = mSource->mOgrGeometryTypeFilter != wkbUnknown; if ( mFetchGeometry || useIntersect || geometryTypeFilter ) { OGRGeometryH geom = OGR_F_GetGeometryRef( fet ); if ( geom ) { feature.setGeometry( QgsOgrUtils::ogrGeometryToQgsGeometry( geom ) ); } else feature.clearGeometry(); if ( mSource->mOgrGeometryTypeFilter == wkbGeometryCollection && geom && wkbFlatten( OGR_G_GetGeometryType( geom ) ) == wkbGeometryCollection ) { // OK } else if (( useIntersect && ( !feature.hasGeometry() || !feature.geometry().intersects( mRequest.filterRect() ) ) ) || ( geometryTypeFilter && ( !feature.hasGeometry() || QgsOgrProvider::ogrWkbSingleFlatten(( OGRwkbGeometryType )feature.geometry().wkbType() ) != mSource->mOgrGeometryTypeFilter ) ) ) { OGR_F_Destroy( fet ); return false; } } if ( !mFetchGeometry ) { feature.clearGeometry(); } // fetch attributes if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { QgsAttributeList attrs = mRequest.subsetOfAttributes(); for ( QgsAttributeList::const_iterator it = attrs.begin(); it != attrs.end(); ++it ) { getFeatureAttribute( fet, feature, *it ); } } else { // all attributes for ( int idx = 0; idx < mSource->mFields.count(); ++idx ) { getFeatureAttribute( fet, feature, idx ); } } return true; }
QgsFeatureList QgsConvexHullAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback ) { QgsFeature f = feature; if ( f.hasGeometry() ) { QgsGeometry outputGeometry; if ( QgsWkbTypes::flatType( f.geometry().wkbType() ) == QgsWkbTypes::Point ) { feedback->reportError( QObject::tr( "Cannot calculate convex hull for a single Point feature (try 'Minimum bounding geometry' algorithm instead)." ) ); f.clearGeometry(); } else { outputGeometry = f.geometry().convexHull(); if ( outputGeometry.isNull() ) feedback->reportError( outputGeometry.lastError() ); f.setGeometry( outputGeometry ); } if ( !outputGeometry.isNull() ) { QgsAttributes attrs = f.attributes(); attrs << outputGeometry.constGet()->area() << outputGeometry.constGet()->perimeter(); f.setAttributes( attrs ); } else { QgsAttributes attrs = f.attributes(); attrs << QVariant() << QVariant(); f.setAttributes( attrs ); } } return QgsFeatureList() << f; }
bool QgsOgrUtils::readOgrFeatureGeometry( OGRFeatureH ogrFet, QgsFeature& feature ) { if ( !ogrFet ) return false; OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet ); if ( !geom ) feature.clearGeometry(); else feature.setGeometry( ogrGeometryToQgsGeometry( geom ) ); return true; }
QgsFeatureList QgsBoundaryAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback ) { QgsFeature outFeature = feature; if ( feature.hasGeometry() ) { QgsGeometry inputGeometry = feature.geometry(); QgsGeometry outputGeometry = QgsGeometry( inputGeometry.constGet()->boundary() ); if ( !outputGeometry ) { feedback->reportError( QObject::tr( "No boundary for feature %1 (possibly a closed linestring?)'" ).arg( feature.id() ) ); outFeature.clearGeometry(); } else { outFeature.setGeometry( outputGeometry ); } } return QgsFeatureList() << outFeature; }
QgsFeatureList QgsLineSubstringAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback * ) { QgsFeature f = feature; if ( f.hasGeometry() ) { const QgsGeometry geometry = f.geometry(); double startDistance = mStartDistance; if ( mDynamicStartDistance ) startDistance = mStartDistanceProperty.valueAsDouble( context.expressionContext(), startDistance ); double endDistance = mEndDistance; if ( mDynamicEndDistance ) endDistance = mEndDistanceProperty.valueAsDouble( context.expressionContext(), endDistance ); const QgsCurve *curve = nullptr; if ( !geometry.isMultipart() ) curve = qgsgeometry_cast< const QgsCurve * >( geometry.constGet() ); else { if ( const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( geometry.constGet() ) ) { if ( collection->numGeometries() > 0 ) { curve = qgsgeometry_cast< const QgsCurve * >( collection->geometryN( 0 ) ); } } } if ( curve ) { std::unique_ptr< QgsCurve > substring( curve->curveSubstring( startDistance, endDistance ) ); QgsGeometry result( std::move( substring ) ); f.setGeometry( result ); } else { f.clearGeometry(); } } return QgsFeatureList() << f; }
void QgsAbstractFeatureIterator::geometryToDestinationCrs( QgsFeature &feature, const QgsCoordinateTransform &transform ) const { if ( transform.isValid() && feature.hasGeometry() ) { try { QgsGeometry g = feature.geometry(); g.transform( transform ); feature.setGeometry( g ); } catch ( QgsCsException & ) { // transform error if ( mRequest.transformErrorCallback() ) { mRequest.transformErrorCallback()( feature ); } // remove geometry - we can't reproject so better not return a geometry in a different crs feature.clearGeometry(); } } }
QgsFeature QgsTransformAlgorithm::processFeature( const QgsFeature &f, QgsProcessingContext &, QgsProcessingFeedback * ) { QgsFeature feature = f; if ( !mCreatedTransform ) { mCreatedTransform = true; mTransform = QgsCoordinateTransform( sourceCrs(), mDestCrs, mTransformContext ); } if ( feature.hasGeometry() ) { QgsGeometry g = feature.geometry(); if ( g.transform( mTransform ) == 0 ) { feature.setGeometry( g ); } else { feature.clearGeometry(); } } return feature; }
QgsFeature QgsFixGeometriesAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingFeedback *feedback ) { if ( !feature.hasGeometry() ) return feature; QgsFeature outputFeature = feature; QgsGeometry outputGeometry = outputFeature.geometry().makeValid(); if ( !outputGeometry ) { feedback->pushInfo( QObject::tr( "makeValid failed for feature %1 " ).arg( feature.id() ) ); outputFeature.clearGeometry(); return outputFeature; } if ( outputGeometry.wkbType() == QgsWkbTypes::Unknown || QgsWkbTypes::flatType( outputGeometry.wkbType() ) == QgsWkbTypes::GeometryCollection ) { // keep only the parts of the geometry collection with correct type const QVector< QgsGeometry > tmpGeometries = outputGeometry.asGeometryCollection(); QVector< QgsGeometry > matchingParts; for ( const QgsGeometry &g : tmpGeometries ) { if ( g.type() == feature.geometry().type() ) matchingParts << g; } if ( !matchingParts.empty() ) outputGeometry = QgsGeometry::collectGeometry( matchingParts ); else outputGeometry = QgsGeometry(); } outputGeometry.convertToMultiType(); outputFeature.setGeometry( outputGeometry ); return outputFeature; }
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; }
QgsFeature QgsDropGeometryAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingFeedback * ) { QgsFeature f = feature; f.clearGeometry(); return f; }
bool QgsVirtualLayerFeatureIterator::fetchFeature( QgsFeature &feature ) { feature.setValid( false ); if ( mClosed ) { return false; } bool skipFeature = false; do { if ( mQuery->step() != SQLITE_ROW ) { return false; } feature.setFields( mSource->mFields, /* init */ true ); if ( mSource->mDefinition.uid().isNull() && mRequest.filterType() != QgsFeatureRequest::FilterFid ) { // no id column => autoincrement feature.setId( mFid++ ); } else { // first column: uid feature.setId( mQuery->columnInt64( 0 ) ); } int n = mQuery->columnCount(); int i = 0; const auto constMAttributes = mAttributes; for ( int idx : constMAttributes ) { int type = mQuery->columnType( i + 1 ); switch ( type ) { case SQLITE_INTEGER: feature.setAttribute( idx, mQuery->columnInt64( i + 1 ) ); break; case SQLITE_FLOAT: feature.setAttribute( idx, mQuery->columnDouble( i + 1 ) ); break; case SQLITE_TEXT: default: feature.setAttribute( idx, mQuery->columnText( i + 1 ) ); break; }; i++; } if ( n > mAttributes.size() + 1 ) { // geometry field QByteArray blob( mQuery->columnBlob( n - 1 ) ); if ( blob.size() > 0 ) { feature.setGeometry( spatialiteBlobToQgsGeometry( blob.constData(), blob.size() ) ); } else { feature.clearGeometry(); } } feature.setValid( true ); geometryToDestinationCrs( feature, mTransform ); // if the FilterRect has not been applied on the query // apply it here by skipping features until they intersect if ( mSource->mDefinition.uid().isNull() && feature.hasGeometry() && mSource->mDefinition.hasDefinedGeometry() && !mFilterRect.isNull() ) { if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) { // using exact test when checking for intersection skipFeature = !mRectEngine->intersects( feature.geometry().constGet() ); } else { // check just bounding box against rect when not using intersection skipFeature = !feature.geometry().boundingBox().intersects( mFilterRect ); } } } while ( skipFeature ); return true; }
QgsFeatureList QgsDropGeometryAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * ) { QgsFeature f = feature; f.clearGeometry(); return QgsFeatureList() << f; }
bool QgsOgrFeatureIterator::readFeature( gdal::ogr_feature_unique_ptr fet, QgsFeature &feature ) const { feature.setId( OGR_F_GetFID( fet.get() ) ); feature.initAttributes( mSource->mFields.count() ); feature.setFields( mSource->mFields ); // allow name-based attribute lookups bool useIntersect = !mRequest.filterRect().isNull(); bool geometryTypeFilter = mSource->mOgrGeometryTypeFilter != wkbUnknown; if ( mFetchGeometry || useIntersect || geometryTypeFilter ) { OGRGeometryH geom = OGR_F_GetGeometryRef( fet.get() ); if ( geom ) { QgsGeometry g = QgsOgrUtils::ogrGeometryToQgsGeometry( geom ); // Insure that multipart datasets return multipart geometry if ( QgsWkbTypes::isMultiType( mSource->mWkbType ) && !g.isMultipart() ) { g.convertToMultiType(); } feature.setGeometry( g ); } else feature.clearGeometry(); if ( mSource->mOgrGeometryTypeFilter == wkbGeometryCollection && geom && wkbFlatten( OGR_G_GetGeometryType( geom ) ) == wkbGeometryCollection ) { // OK } else if ( ( useIntersect && ( !feature.hasGeometry() || ( mRequest.flags() & QgsFeatureRequest::ExactIntersect && !feature.geometry().intersects( mFilterRect ) ) || ( !( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) && !feature.geometry().boundingBoxIntersects( mFilterRect ) ) ) ) || ( geometryTypeFilter && ( !feature.hasGeometry() || QgsOgrProvider::ogrWkbSingleFlatten( ( OGRwkbGeometryType )feature.geometry().wkbType() ) != mSource->mOgrGeometryTypeFilter ) ) ) { return false; } } if ( !mFetchGeometry ) { feature.clearGeometry(); } // fetch attributes if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) { QgsAttributeList attrs = mRequest.subsetOfAttributes(); for ( QgsAttributeList::const_iterator it = attrs.constBegin(); it != attrs.constEnd(); ++it ) { getFeatureAttribute( fet.get(), feature, *it ); } } else { // all attributes const auto fieldCount = mSource->mFields.count(); for ( int idx = 0; idx < fieldCount; ++idx ) { getFeatureAttribute( fet.get(), feature, idx ); } } return true; }