void QgsNetworkAnalysisAlgorithmBase::loadCommonParams( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) { Q_UNUSED( feedback ); mNetwork.reset( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) ); if ( !mNetwork ) throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) ); int strategy = parameterAsInt( parameters, QStringLiteral( "STRATEGY" ), context ); QString directionFieldName = parameterAsString( parameters, QStringLiteral( "DIRECTION_FIELD" ), context ); QString forwardValue = parameterAsString( parameters, QStringLiteral( "VALUE_FORWARD" ), context ); QString backwardValue = parameterAsString( parameters, QStringLiteral( "VALUE_BACKWARD" ), context ); QString bothValue = parameterAsString( parameters, QStringLiteral( "VALUE_BOTH" ), context ); QgsVectorLayerDirector::Direction defaultDirection = static_cast< QgsVectorLayerDirector::Direction>( parameterAsInt( parameters, QStringLiteral( "DEFAULT_DIRECTION" ), context ) ); QString speedFieldName = parameterAsString( parameters, QStringLiteral( "SPEED_FIELD" ), context ); double defaultSpeed = parameterAsDouble( parameters, QStringLiteral( "DEFAULT_SPEED" ), context ); double tolerance = parameterAsDouble( parameters, QStringLiteral( "TOLERANCE" ), context ); int directionField = -1; if ( !directionFieldName.isEmpty() ) { directionField = mNetwork->fields().lookupField( directionFieldName ); } int speedField = -1; if ( !speedFieldName.isEmpty() ) { speedField = mNetwork->fields().lookupField( speedFieldName ); } mDirector = new QgsVectorLayerDirector( mNetwork.get(), directionField, forwardValue, backwardValue, bothValue, defaultDirection ); QgsUnitTypes::DistanceUnit distanceUnits = context.project()->crs().mapUnits(); mMultiplier = QgsUnitTypes::fromUnitToUnitFactor( distanceUnits, QgsUnitTypes::DistanceMeters ); if ( strategy ) { mDirector->addStrategy( new QgsNetworkSpeedStrategy( speedField, defaultSpeed, mMultiplier * 1000.0 / 3600.0 ) ); mMultiplier = 3600; } else { mDirector->addStrategy( new QgsNetworkDistanceStrategy() ); } mBuilder = qgis::make_unique< QgsGraphBuilder >( mNetwork->sourceCrs(), true, tolerance ); }
bool QgsReclassifyAlgorithmBase::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) { mDataType = QgsRasterAnalysisUtils::rasterTypeChoiceToDataType( parameterAsEnum( parameters, QStringLiteral( "DATA_TYPE" ), context ) ); QgsRasterLayer *layer = parameterAsRasterLayer( parameters, QStringLiteral( "INPUT_RASTER" ), context ); if ( !layer ) throw QgsProcessingException( invalidRasterError( parameters, QStringLiteral( "INPUT_RASTER" ) ) ); mBand = parameterAsInt( parameters, QStringLiteral( "RASTER_BAND" ), context ); if ( mBand < 1 || mBand > layer->bandCount() ) throw QgsProcessingException( QObject::tr( "Invalid band number for RASTER_BAND (%1): Valid values for input raster are 1 to %2" ).arg( mBand ) .arg( layer->bandCount() ) ); mInterface.reset( layer->dataProvider()->clone() ); mExtent = layer->extent(); mCrs = layer->crs(); mRasterUnitsPerPixelX = std::abs( layer->rasterUnitsPerPixelX() ); mRasterUnitsPerPixelY = std::abs( layer->rasterUnitsPerPixelY() ); mNbCellsXProvider = mInterface->xSize(); mNbCellsYProvider = mInterface->ySize(); mNoDataValue = parameterAsDouble( parameters, QStringLiteral( "NO_DATA" ), context ); mUseNoDataForMissingValues = parameterAsBool( parameters, QStringLiteral( "NODATA_FOR_MISSING" ), context ); int boundsType = parameterAsEnum( parameters, QStringLiteral( "RANGE_BOUNDARIES" ), context ); switch ( boundsType ) { case 0: mBoundsType = QgsReclassifyUtils::RasterClass::IncludeMax; break; case 1: mBoundsType = QgsReclassifyUtils::RasterClass::IncludeMin; break; case 2: mBoundsType = QgsReclassifyUtils::RasterClass::IncludeMinAndMax; break; case 3: mBoundsType = QgsReclassifyUtils::RasterClass::Exclusive; break; } return _prepareAlgorithm( parameters, context, feedback ); }
bool QgsZonalHistogramAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * ) { QgsRasterLayer *layer = parameterAsRasterLayer( parameters, QStringLiteral( "INPUT_RASTER" ), context ); if ( !layer ) throw QgsProcessingException( invalidRasterError( parameters, QStringLiteral( "INPUT_RASTER" ) ) ); mRasterBand = parameterAsInt( parameters, QStringLiteral( "RASTER_BAND" ), context ); mHasNoDataValue = layer->dataProvider()->sourceHasNoDataValue( mRasterBand ); mNodataValue = layer->dataProvider()->sourceNoDataValue( mRasterBand ); mRasterInterface.reset( layer->dataProvider()->clone() ); mRasterExtent = layer->extent(); mCrs = layer->crs(); mCellSizeX = std::abs( layer->rasterUnitsPerPixelX() ); mCellSizeY = std::abs( layer->rasterUnitsPerPixelX() ); mNbCellsXProvider = mRasterInterface->xSize(); mNbCellsYProvider = mRasterInterface->ySize(); return true; }
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; }
QVariantMap QgsTransectAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) { Side orientation = static_cast< QgsTransectAlgorithm::Side >( parameterAsInt( parameters, QStringLiteral( "SIDE" ), context ) ); double angle = fabs( parameterAsDouble( parameters, QStringLiteral( "ANGLE" ), context ) ); bool dynamicAngle = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "ANGLE" ) ); QgsProperty angleProperty; if ( dynamicAngle ) angleProperty = parameters.value( QStringLiteral( "ANGLE" ) ).value< QgsProperty >(); double length = parameterAsDouble( parameters, QStringLiteral( "LENGTH" ), context ); bool dynamicLength = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "LENGTH" ) ); QgsProperty lengthProperty; if ( dynamicLength ) lengthProperty = parameters.value( QStringLiteral( "LENGTH" ) ).value< QgsProperty >(); if ( orientation == QgsTransectAlgorithm::Both ) length /= 2.0; std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) ); if ( !source ) throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) ); QgsExpressionContext expressionContext = createExpressionContext( parameters, context, dynamic_cast< QgsProcessingFeatureSource * >( source.get() ) ); QgsFields fields = source->fields(); fields.append( QgsField( QStringLiteral( "TR_FID" ), QVariant::Int, QString(), 20 ) ); fields.append( QgsField( QStringLiteral( "TR_ID" ), QVariant::Int, QString(), 20 ) ); fields.append( QgsField( QStringLiteral( "TR_SEGMENT" ), QVariant::Int, QString(), 20 ) ); fields.append( QgsField( QStringLiteral( "TR_ANGLE" ), QVariant::Double, QString(), 5, 2 ) ); fields.append( QgsField( QStringLiteral( "TR_LENGTH" ), QVariant::Double, QString(), 20, 6 ) ); fields.append( QgsField( QStringLiteral( "TR_ORIENT" ), QVariant::Int, QString(), 1 ) ); QgsWkbTypes::Type outputWkb = QgsWkbTypes::LineString; if ( QgsWkbTypes::hasZ( source->wkbType() ) ) outputWkb = QgsWkbTypes::addZ( outputWkb ); if ( QgsWkbTypes::hasM( source->wkbType() ) ) outputWkb = QgsWkbTypes::addM( outputWkb ); QString dest; std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, outputWkb, source->sourceCrs(), QgsFeatureSink::RegeneratePrimaryKey ) ); if ( !sink ) throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) ); QgsFeatureIterator features = source->getFeatures( ); int current = -1; int number = 0; double step = source->featureCount() > 0 ? 100.0 / source->featureCount() : 1; QgsFeature feat; while ( features.nextFeature( feat ) ) { current++; if ( feedback->isCanceled() ) { break; } feedback->setProgress( current * step ); if ( !feat.hasGeometry() ) continue; QgsGeometry inputGeometry = feat.geometry(); if ( dynamicLength || dynamicAngle ) { expressionContext.setFeature( feat ); } double evaluatedLength = length; if ( dynamicLength ) evaluatedLength = lengthProperty.valueAsDouble( context.expressionContext(), length ); double evaluatedAngle = angle; if ( dynamicAngle ) evaluatedAngle = angleProperty.valueAsDouble( context.expressionContext(), angle ); inputGeometry.convertToMultiType(); const QgsMultiLineString *multiLine = static_cast< const QgsMultiLineString * >( inputGeometry.constGet() ); for ( int id = 0; id < multiLine->numGeometries(); ++id ) { const QgsLineString *line = static_cast< const QgsLineString * >( multiLine->geometryN( id ) ); QgsAbstractGeometry::vertex_iterator it = line->vertices_begin(); while ( it != line->vertices_end() ) { QgsVertexId vertexId = it.vertexId(); int i = vertexId.vertex; QgsFeature outFeat; QgsAttributes attrs = feat.attributes(); attrs << current << number << i + 1 << evaluatedAngle << ( ( orientation == QgsTransectAlgorithm::Both ) ? evaluatedLength * 2 : evaluatedLength ) << orientation; outFeat.setAttributes( attrs ); double angleAtVertex = line->vertexAngle( vertexId ); outFeat.setGeometry( calcTransect( *it, angleAtVertex, evaluatedLength, orientation, evaluatedAngle ) ); sink->addFeature( outFeat, QgsFeatureSink::FastInsert ); number++; it++; } } } QVariantMap outputs; outputs.insert( QStringLiteral( "OUTPUT" ), dest ); return outputs; }
bool QgsMinimumEnclosingCircleAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * ) { mSegments = parameterAsInt( parameters, QStringLiteral( "SEGMENTS" ), context ); return true; }
QVariantMap QgsBufferAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) { std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) ); if ( !source ) throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) ); QString dest; std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, source->fields(), QgsWkbTypes::Polygon, source->sourceCrs() ) ); if ( !sink ) throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) ); // 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( "MITER_LIMIT" ), context ); double bufferDistance = parameterAsDouble( parameters, QStringLiteral( "DISTANCE" ), context ); bool dynamicBuffer = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "DISTANCE" ) ); QgsExpressionContext expressionContext = createExpressionContext( parameters, context, dynamic_cast< QgsProcessingFeatureSource * >( source.get() ) ); QgsProperty bufferProperty; if ( dynamicBuffer ) { bufferProperty = parameters.value( QStringLiteral( "DISTANCE" ) ).value< QgsProperty >(); } long count = source->featureCount(); QgsFeature f; QgsFeatureIterator it = source->getFeatures(); double step = count > 0 ? 100.0 / count : 1; int current = 0; QVector< QgsGeometry > bufferedGeometriesForDissolve; QgsAttributes dissolveAttrs; while ( it.nextFeature( f ) ) { if ( feedback->isCanceled() ) { break; } if ( dissolveAttrs.isEmpty() ) dissolveAttrs = f.attributes(); QgsFeature out = f; if ( out.hasGeometry() ) { double distance = bufferDistance; if ( dynamicBuffer ) { expressionContext.setFeature( f ); distance = bufferProperty.valueAsDouble( expressionContext, bufferDistance ); } QgsGeometry outputGeometry = f.geometry().buffer( distance, segments, endCapStyle, joinStyle, miterLimit ); if ( !outputGeometry ) { QgsMessageLog::logMessage( QObject::tr( "Error calculating buffer for feature %1" ).arg( f.id() ), QObject::tr( "Processing" ), Qgis::Warning ); } if ( dissolve ) bufferedGeometriesForDissolve << outputGeometry; else out.setGeometry( outputGeometry ); } if ( !dissolve ) sink->addFeature( out, QgsFeatureSink::FastInsert ); feedback->setProgress( current * step ); current++; } if ( dissolve ) { QgsGeometry finalGeometry = QgsGeometry::unaryUnion( bufferedGeometriesForDissolve ); QgsFeature f; f.setGeometry( finalGeometry ); f.setAttributes( dissolveAttrs ); sink->addFeature( f, QgsFeatureSink::FastInsert ); } QVariantMap outputs; outputs.insert( QStringLiteral( "OUTPUT" ), dest ); return outputs; }
bool QgsSubdivideAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * ) { mMaxNodes = parameterAsInt( parameters, QStringLiteral( "MAX_NODES" ), context ); return true; }
QVariantMap QgsDbscanClusteringAlgorithm::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 std::size_t minSize = static_cast< std::size_t>( parameterAsInt( parameters, QStringLiteral( "MIN_SIZE" ), context ) ); const double eps = parameterAsDouble( parameters, QStringLiteral( "EPS" ), context ); const bool borderPointsAreNoise = parameterAsBoolean( parameters, QStringLiteral( "DBSCAN*" ), context ); QgsFields outputFields = source->fields(); const QString clusterFieldName = parameterAsString( parameters, QStringLiteral( "FIELD_NAME" ), context ); QgsFields newFields; newFields.append( QgsField( clusterFieldName, QVariant::Int ) ); outputFields = QgsProcessingUtils::combineFields( outputFields, newFields ); QString dest; std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, outputFields, source->wkbType(), source->sourceCrs() ) ); if ( !sink ) throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) ); // build spatial index feedback->pushInfo( QObject::tr( "Building spatial index" ) ); QgsSpatialIndexKDBush index( *source, feedback ); if ( feedback->isCanceled() ) return QVariantMap(); // dbscan! feedback->pushInfo( QObject::tr( "Analysing clusters" ) ); std::unordered_map< QgsFeatureId, int> idToCluster; idToCluster.reserve( index.size() ); QgsFeatureIterator features = source->getFeatures( QgsFeatureRequest().setNoAttributes() ); const long featureCount = source->featureCount(); int clusterCount = 0; dbscan( minSize, eps, borderPointsAreNoise, featureCount, features, index, idToCluster, clusterCount, feedback ); // write clusters const double writeStep = featureCount > 0 ? 10.0 / featureCount : 1; features = source->getFeatures(); int i = 0; QgsFeature feat; while ( features.nextFeature( feat ) ) { i++; if ( feedback->isCanceled() ) { break; } feedback->setProgress( 90 + i * writeStep ); QgsAttributes attr = feat.attributes(); auto cluster = idToCluster.find( feat.id() ); if ( cluster != idToCluster.end() ) { attr << cluster->second; } else { attr << QVariant(); } feat.setAttributes( attr ); sink->addFeature( feat, QgsFeatureSink::FastInsert ); } QVariantMap outputs; outputs.insert( QStringLiteral( "OUTPUT" ), dest ); outputs.insert( QStringLiteral( "NUM_CLUSTERS" ), clusterCount ); return outputs; }