25 : mSource( parameters.source )
26 , mOutputFile( outputFile )
27 , mOutputFormat( outputFormat )
28 , mRadius( parameters.radius )
29 , mPixelSize( parameters.pixelSize )
30 , mShape( parameters.shape )
31 , mDecay( parameters.decayRatio )
32 , mOutputValues( parameters.outputValues )
33 , mDatasetH( nullptr )
36 mRadiusField = mSource->fields().lookupField( parameters.
radiusField );
38 mWeightField = mSource->fields().lookupField( parameters.
weightField );
49 if ( mRadiusField >= 0 )
50 requiredAttributes << mRadiusField;
52 if ( mWeightField >= 0 )
53 requiredAttributes << mWeightField;
70 GDALDriverH driver = GDALGetDriverByName( mOutputFormat.toUtf8() );
79 mBounds = calculateBounds();
80 if ( mBounds.isNull() )
83 const int rows = std::max( std::ceil( mBounds.height() / mPixelSize ) + 1, 1.0 );
84 const int cols = std::max( std::ceil( mBounds.width() / mPixelSize ) + 1, 1.0 );
86 if ( !createEmptyLayer( driver, mBounds, rows, cols ) )
90 mDatasetH.reset( GDALOpen( mOutputFile.toUtf8().constData(), GA_Update ) );
93 mRasterBandH = GDALGetRasterBand( mDatasetH.get(), 1 );
98 if ( mRadiusField < 0 )
99 mBufferSize = radiusSizeInPixels( mRadius );
107 if ( featureGeometry.
isNull() )
118 if ( !mBounds.contains( p ) )
129 double radius = mRadius;
130 int buffer = mBufferSize;
131 if ( mRadiusField >= 0 )
133 radius = feature.
attribute( mRadiusField ).toDouble();
134 buffer = radiusSizeInPixels( radius );
136 const int blockSize = 2 * buffer + 1;
140 if ( mWeightField >= 0 )
142 weight = feature.
attribute( mWeightField ).toDouble();
148 for ( QgsMultiPointXY::const_iterator pointIt = multiPoints.constBegin(); pointIt != multiPoints.constEnd(); ++pointIt )
151 if ( !mBounds.contains( *pointIt ) )
157 const unsigned int xPosition = ( ( ( *pointIt ).x() - mBounds.xMinimum() ) / mPixelSize ) - buffer;
158 const unsigned int yPosition = ( ( ( *pointIt ).y() - mBounds.yMinimum() ) / mPixelSize ) - buffer;
159 const unsigned int yPositionIO = ( ( mBounds.yMaximum() - ( *pointIt ).y() ) / mPixelSize ) - buffer;
163 float *dataBuffer = (
float * ) CPLMalloc(
sizeof(
float ) * blockSize * blockSize );
164 if ( GDALRasterIO( mRasterBandH, GF_Read, xPosition, yPositionIO, blockSize, blockSize, dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 ) != CE_None )
169 for (
int xp = 0; xp < blockSize; xp++ )
171 for (
int yp = 0; yp < blockSize; yp++ )
173 const double pixelCentroidX = ( xPosition + xp + 0.5 ) * mPixelSize + mBounds.xMinimum();
174 const double pixelCentroidY = ( yPosition + yp + 0.5 ) * mPixelSize + mBounds.yMinimum();
176 const double distance = std::sqrt( std::pow( pixelCentroidX - ( *pointIt ).x(), 2.0 ) + std::pow( pixelCentroidY - ( *pointIt ).y(), 2.0 ) );
179 if ( distance > radius )
184 const double pixelValue = weight * calculateKernelValue( distance, radius, mShape, mOutputValues );
185 const int pos = xp + blockSize * yp;
186 if ( dataBuffer[pos] ==
NO_DATA )
190 dataBuffer[pos] += pixelValue;
193 if ( GDALRasterIO( mRasterBandH, GF_Write, xPosition, yPositionIO, blockSize, blockSize, dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 ) != CE_None )
197 CPLFree( dataBuffer );
206 mRasterBandH =
nullptr;
210int QgsKernelDensityEstimation::radiusSizeInPixels(
double radius )
const
212 int buffer = radius / mPixelSize;
213 if ( radius - ( mPixelSize * buffer ) > 0.5 )
220bool QgsKernelDensityEstimation::createEmptyLayer( GDALDriverH driver,
const QgsRectangle &bounds,
int rows,
int columns )
const
222 double geoTransform[6] = { bounds.
xMinimum(), mPixelSize, 0, bounds.
yMaximum(), 0, -mPixelSize };
223 const gdal::dataset_unique_ptr emptyDataset( GDALCreate( driver, mOutputFile.toUtf8(), columns, rows, 1, GDT_Float32,
nullptr ) );
227 if ( GDALSetGeoTransform( emptyDataset.get(), geoTransform ) != CE_None )
231 if ( GDALSetProjection( emptyDataset.get(), mSource->sourceCrs().toWkt().toLocal8Bit().data() ) != CE_None )
234 GDALRasterBandH poBand = GDALGetRasterBand( emptyDataset.get(), 1 );
238 if ( GDALSetRasterNoDataValue( poBand,
NO_DATA ) != CE_None )
241 float *line =
static_cast<float *
>( CPLMalloc(
sizeof(
float ) * columns ) );
242 for (
int i = 0; i < columns; i++ )
247 for (
int i = 0; i < rows; i++ )
249 if ( GDALRasterIO( poBand, GF_Write, 0, i, columns, 1, line, columns, 1, GDT_Float32, 0, 0 ) != CE_None )
264 return triangularKernel( distance, bandwidth, outputType );
267 return uniformKernel( distance, bandwidth, outputType );
270 return quarticKernel( distance, bandwidth, outputType );
273 return triweightKernel( distance, bandwidth, outputType );
276 return epanechnikovKernel( distance, bandwidth, outputType );
292 switch ( outputType )
297 const double k = 2. / ( M_PI * bandwidth );
300 return k * ( 0.5 / bandwidth );
310 switch ( outputType )
315 const double k = 16. / ( 5. * M_PI * std::pow( bandwidth, 2 ) );
318 return k * ( 15. / 16. ) * std::pow( 1. - std::pow( distance / bandwidth, 2 ), 2 );
321 return std::pow( 1. - std::pow( distance / bandwidth, 2 ), 2 );
328 switch ( outputType )
333 const double k = 128. / ( 35. * M_PI * std::pow( bandwidth, 2 ) );
336 return k * ( 35. / 32. ) * std::pow( 1. - std::pow( distance / bandwidth, 2 ), 3 );
339 return std::pow( 1. - std::pow( distance / bandwidth, 2 ), 3 );
346 switch ( outputType )
351 const double k = 8. / ( 3. * M_PI * std::pow( bandwidth, 2 ) );
354 return k * ( 3. / 4. ) * ( 1. - std::pow( distance / bandwidth, 2 ) );
357 return ( 1. - std::pow( distance / bandwidth, 2 ) );
365 switch ( outputType )
374 const double k = 3. / ( ( 1. + 2. * mDecay ) * M_PI * std::pow( bandwidth, 2 ) );
377 return k * ( 1. - ( 1. - mDecay ) * ( distance / bandwidth ) );
382 return ( 1. - ( 1. - mDecay ) * ( distance / bandwidth ) );
386 return ( 1. - ( 1. - mDecay ) * ( distance / bandwidth ) );
391QgsRectangle QgsKernelDensityEstimation::calculateBounds()
const
394 return QgsRectangle();
396 QgsRectangle bbox = mSource->sourceExtent();
399 if ( mRadiusField >= 0 )
402 radius = mSource->maximumValue( mRadiusField ).toDouble();
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
A geometry is the spatial representation of a feature.
QgsMultiPointXY asMultiPoint() const
Returns the contents of the geometry as a multi-point.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
QgsKernelDensityEstimation(const Parameters ¶meters, const QString &outputFile, const QString &outputFormat)
Constructor for QgsKernelDensityEstimation.
Result run()
Runs the KDE calculation across the whole layer at once.
Result addFeature(const QgsFeature &feature)
Adds a single feature to the KDE surface.
Result finalise()
Finalises the output file.
KernelShape
Kernel shape type.
@ Triweight
Triweight kernel.
@ Triangular
Triangular kernel.
@ Epanechnikov
Epanechnikov kernel.
@ Uniform
Uniform (flat) kernel.
OutputValues
Output values type.
@ Raw
Output the raw KDE values.
@ Scaled
Output mathematically correct scaled values.
Result prepare()
Prepares the output file for writing and setups up the surface calculation.
Result
Result of operation.
@ InvalidParameters
Input parameters were not valid.
@ Success
Operation completed successfully.
@ RasterIoError
Error writing to raster.
@ FileCreationError
Error creating output file.
@ DriverError
Could not open the driver for the specified format.
A rectangle specified with double values.
void setYMinimum(double y)
Set the minimum y value.
void setXMinimum(double x)
Set the minimum x value.
void setYMaximum(double y)
Set the maximum y value.
void setXMaximum(double x)
Set the maximum x value.
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
QList< int > QgsAttributeList
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
QString radiusField
Field for radius, or empty if using a fixed radius.
QString weightField
Field name for weighting field, or empty if not using weights.