25 QString QgsLineDensityAlgorithm::name()
const
27 return QStringLiteral(
"linedensity" );
30 QString QgsLineDensityAlgorithm::displayName()
const
32 return QObject::tr(
"Line density" );
35 QStringList QgsLineDensityAlgorithm::tags()
const
37 return QObject::tr(
"density,kernel,line,line density,interpolation,weight" ).split(
',' );
40 QString QgsLineDensityAlgorithm::group()
const
42 return QObject::tr(
"Interpolation" );
45 QString QgsLineDensityAlgorithm::groupId()
const
47 return QStringLiteral(
"interpolation" );
50 void QgsLineDensityAlgorithm::initAlgorithm(
const QVariantMap & )
54 addParameter(
new QgsProcessingParameterDistance( QStringLiteral(
"RADIUS" ), QObject::tr(
"Search radius" ), 10, QStringLiteral(
"INPUT" ),
false, 0 ) );
55 addParameter(
new QgsProcessingParameterDistance( QStringLiteral(
"PIXEL_SIZE" ), QObject::tr(
"Pixel size" ), 10, QStringLiteral(
"INPUT" ),
false ) );
60 QString QgsLineDensityAlgorithm::shortHelpString()
const
62 return QObject::tr(
"The line density interpolation algorithm calculates a density measure of linear features "
63 "which is obtained in a circular neighborhood within each raster cell. "
64 "First, the length of the segment of each line that is intersected by the circular neighborhood "
65 "is multiplied with the lines weight factor. In a second step, all length values are summed and "
66 "divided by the area of the circular neighborhood. This process is repeated for all raster cells."
70 QgsLineDensityAlgorithm *QgsLineDensityAlgorithm::createInstance()
const
72 return new QgsLineDensityAlgorithm();
78 mSource.reset( parameterAsSource( parameters, QStringLiteral(
"INPUT" ), context ) );
82 mWeightField = parameterAsString( parameters, QStringLiteral(
"WEIGHT" ), context );
84 mPixelSize = parameterAsDouble( parameters, QStringLiteral(
"PIXEL_SIZE" ), context );
86 mSearchRadius = parameterAsDouble( parameters, QStringLiteral(
"RADIUS" ), context );
87 if ( mSearchRadius < 0.5 * mPixelSize * std::sqrt( 2 ) )
88 throw QgsProcessingException( QObject::tr(
"Raster cells must be fully contained by the search circle. Therefore, "
89 "the search radius must not be smaller than half of the pixel diagonal." ) );
91 mExtent = mSource->sourceExtent();
92 mCrs = mSource->sourceCrs();
98 const QgsPoint firstCellMidpoint =
QgsPoint( mExtent.xMinimum() + ( mPixelSize / 2 ), mExtent.yMaximum() - ( mPixelSize / 2 ) );
109 const QStringList weightName = QStringList( mWeightField );
110 const QgsFields attrFields = mSource->fields();
122 if ( !mWeightField.isEmpty() )
124 const double analysisWeight = f.
attribute( mWeightField ).toDouble();
125 mFeatureWeights.insert( f.
id(), analysisWeight );
129 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral(
"OUTPUT" ), context );
130 const QFileInfo fi( outputFile );
133 const int rows = std::max( std::ceil( mExtent.height() / mPixelSize ), 1.0 );
134 const int cols = std::max( std::ceil( mExtent.width() / mPixelSize ), 1.0 );
138 const QgsRectangle rasterExtent =
QgsRectangle( mExtent.xMinimum(), mExtent.yMaximum() - ( rows * mPixelSize ), mExtent.xMinimum() + ( cols * mPixelSize ), mExtent.yMaximum() );
146 if ( !provider->isValid() )
149 provider->setNoDataValue( 1, -9999 );
154 std::unique_ptr< QgsRasterBlock > rasterDataLine = std::make_unique< QgsRasterBlock >(
Qgis::DataType::Float32, cols, 1 );
156 for (
int row = 0; row < rows; row++ )
158 for (
int col = 0; col < cols; col++ )
166 mSearchGeometry.translate( mPixelSize, 0 );
168 const QList<QgsFeatureId> fids = mIndex.intersects( mSearchGeometry.boundingBox() );
170 if ( !fids.isEmpty() )
173 engine->prepareGeometry();
175 double absDensity = 0;
178 const QgsGeometry lineGeom = mIndex.geometry(
id );
180 if ( engine->intersects( lineGeom.
constGet() ) )
182 const double analysisLineLength = mDa.measureLength(
QgsGeometry( engine->intersection( mIndex.geometry(
id ).constGet() ) ) );
185 if ( !mWeightField.isEmpty() )
187 weight = mFeatureWeights.value(
id );
190 absDensity += ( analysisLineLength * weight );
194 double lineDensity = 0;
195 if ( absDensity > 0 )
198 const double analysisSearchGeometryArea = mDa.measureArea( mSearchGeometry );
199 lineDensity = absDensity / analysisSearchGeometryArea;
201 rasterDataLine->setValue( 0, col, lineDensity );
206 rasterDataLine->setValue( 0, col, 0.0 );
209 feedback->
setProgress(
static_cast<double>( cellcnt ) /
static_cast<double>( totalCellcnt ) * 100 );
212 provider->writeBlock( rasterDataLine.get(), 1, 0, row );
215 mSearchGeometry.translate( ( cols - 1 ) * -mPixelSize, -mPixelSize );
219 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );