@@ -159,17 +159,35 @@ void Heatmap::run()
159
159
QgsAttributeList myAttrList;
160
160
int rField = 0 ;
161
161
int wField = 0 ;
162
+
163
+ // Handle different radius options
164
+ float radius;
165
+ float radiusToMapUnits = 1 ;
166
+ int myBuffer;
162
167
if ( d.variableRadius () )
163
168
{
164
169
rField = d.radiusField ();
165
170
myAttrList.append ( rField );
166
171
QgsDebugMsg ( QString ( " Radius Field index received: %1" ).arg ( rField ) );
172
+
173
+ // If not using map units, then calculate a conversion factor to convert the radii to map units
174
+ if ( d.radiusUnit () == HeatmapGui::Meters )
175
+ {
176
+ radiusToMapUnits = mapUnitsOf ( 1 , inputLayer->crs () );
177
+ }
178
+ }
179
+ else
180
+ {
181
+ radius = d.radius (); // radius returned by d.radius() is already in map units
182
+ myBuffer = bufferSize ( radius, cellsize );
167
183
}
184
+
168
185
if ( d.weighted () )
169
186
{
170
187
wField = d.weightField ();
171
188
myAttrList.append ( wField );
172
189
}
190
+
173
191
// This might have attributes or mightnot have attibutes at all
174
192
// based on the variableRadius() and weighted()
175
193
QgsFeatureIterator fit = inputLayer->getFeatures ( QgsFeatureRequest ().setSubsetOfAttributes ( myAttrList ) );
@@ -201,26 +219,14 @@ void Heatmap::run()
201
219
{
202
220
continue ;
203
221
}
204
- float radius;
222
+
223
+ // If radius is variable then fetch it and calculate new pixel buffer size
205
224
if ( d.variableRadius () )
206
225
{
207
- radius = myFeature.attribute ( rField ).toFloat ();
208
- }
209
- else
210
- {
211
- radius = d.radius ();
212
- }
213
- // convert the radius to map units if it is in meters
214
- if ( d.radiusUnit () == HeatmapGui::Meters )
215
- {
216
- radius = mapUnitsOf ( radius, inputLayer->crs () );
217
- }
218
- // convert radius in map units to pixel count
219
- int myBuffer = radius / cellsize;
220
- if ( radius - ( cellsize * myBuffer ) > 0.5 )
221
- {
222
- ++myBuffer;
226
+ radius = myFeature.attribute ( rField ).toFloat () * radiusToMapUnits;
227
+ myBuffer = bufferSize ( radius, cellsize );
223
228
}
229
+
224
230
int blockSize = 2 * myBuffer + 1 ; // Block SIDE would be more appropriate
225
231
// calculate the pixel position
226
232
unsigned int xPosition, yPosition;
@@ -243,6 +249,13 @@ void Heatmap::run()
243
249
for ( int yp = 0 ; yp <= myBuffer; yp++ )
244
250
{
245
251
float distance = sqrt ( pow ( xp, 2.0 ) + pow ( yp, 2.0 ) );
252
+
253
+ // is pixel outside search bandwidth of feature?
254
+ if ( distance > myBuffer )
255
+ {
256
+ continue ;
257
+ }
258
+
246
259
float pixelValue = weight * ( 1 - (( 1 - myDecay ) * distance / myBuffer ) );
247
260
248
261
// clearing anamolies along the axes
@@ -255,21 +268,18 @@ void Heatmap::run()
255
268
pixelValue /= 2 ;
256
269
}
257
270
258
- if ( distance <= myBuffer )
271
+ int pos[4 ];
272
+ pos[0 ] = ( myBuffer + xp ) * blockSize + ( myBuffer + yp );
273
+ pos[1 ] = ( myBuffer + xp ) * blockSize + ( myBuffer - yp );
274
+ pos[2 ] = ( myBuffer - xp ) * blockSize + ( myBuffer + yp );
275
+ pos[3 ] = ( myBuffer - xp ) * blockSize + ( myBuffer - yp );
276
+ for ( int p = 0 ; p < 4 ; p++ )
259
277
{
260
- int pos[4 ];
261
- pos[0 ] = ( myBuffer + xp ) * blockSize + ( myBuffer + yp );
262
- pos[1 ] = ( myBuffer + xp ) * blockSize + ( myBuffer - yp );
263
- pos[2 ] = ( myBuffer - xp ) * blockSize + ( myBuffer + yp );
264
- pos[3 ] = ( myBuffer - xp ) * blockSize + ( myBuffer - yp );
265
- for ( int p = 0 ; p < 4 ; p++ )
278
+ if ( dataBuffer[ pos[p] ] == NO_DATA )
266
279
{
267
- if ( dataBuffer[ pos[p] ] == NO_DATA )
268
- {
269
- dataBuffer[ pos[p] ] = 0 ;
270
- }
271
- dataBuffer[ pos[p] ] += pixelValue;
280
+ dataBuffer[ pos[p] ] = 0 ;
272
281
}
282
+ dataBuffer[ pos[p] ] += pixelValue;
273
283
}
274
284
}
275
285
}
@@ -278,7 +288,7 @@ void Heatmap::run()
278
288
dataBuffer, blockSize, blockSize, GDT_Float32, 0 , 0 );
279
289
CPLFree ( dataBuffer );
280
290
}
281
- // Finally close the dataset
291
+ // Finally close the dataset
282
292
GDALClose (( GDALDatasetH ) heatmapDS );
283
293
284
294
// Open the file in QGIS window
@@ -291,6 +301,7 @@ void Heatmap::run()
291
301
* Local functions
292
302
*
293
303
*/
304
+
294
305
float Heatmap::mapUnitsOf ( float meters, QgsCoordinateReferenceSystem layerCrs )
295
306
{
296
307
// Worker to transform metres input to mapunits
@@ -304,6 +315,19 @@ float Heatmap::mapUnitsOf( float meters, QgsCoordinateReferenceSystem layerCrs )
304
315
return meters / da.measureLine ( QgsPoint ( 0.0 , 0.0 ), QgsPoint ( 0.0 , 1.0 ) );
305
316
}
306
317
318
+ int Heatmap::bufferSize ( float radius, float cellsize )
319
+ {
320
+ // Calculate the buffer size in pixels
321
+
322
+ int buffer = radius / cellsize;
323
+ if ( radius - ( cellsize * buffer ) > 0.5 )
324
+ {
325
+ ++buffer;
326
+ }
327
+ return buffer;
328
+ }
329
+
330
+
307
331
// Unload the plugin by cleaning up the GUI
308
332
void Heatmap::unload ()
309
333
{
0 commit comments