Skip to content

Commit b567a6d

Browse files
committedMar 7, 2013
Refactor to avoid creating multiple QgsDistanceArea objects and recalculation of static or unused variables. Results in massive speed increase and fixes #6756, #6691 and #6692.
1 parent d628c2c commit b567a6d

File tree

2 files changed

+57
-30
lines changed

2 files changed

+57
-30
lines changed
 

‎src/plugins/heatmap/heatmap.cpp

Lines changed: 54 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -159,17 +159,35 @@ void Heatmap::run()
159159
QgsAttributeList myAttrList;
160160
int rField = 0;
161161
int wField = 0;
162+
163+
// Handle different radius options
164+
float radius;
165+
float radiusToMapUnits = 1;
166+
int myBuffer;
162167
if ( d.variableRadius() )
163168
{
164169
rField = d.radiusField();
165170
myAttrList.append( rField );
166171
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 );
167183
}
184+
168185
if ( d.weighted() )
169186
{
170187
wField = d.weightField();
171188
myAttrList.append( wField );
172189
}
190+
173191
// This might have attributes or mightnot have attibutes at all
174192
// based on the variableRadius() and weighted()
175193
QgsFeatureIterator fit = inputLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( myAttrList ) );
@@ -201,26 +219,14 @@ void Heatmap::run()
201219
{
202220
continue;
203221
}
204-
float radius;
222+
223+
// If radius is variable then fetch it and calculate new pixel buffer size
205224
if ( d.variableRadius() )
206225
{
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 );
223228
}
229+
224230
int blockSize = 2 * myBuffer + 1; //Block SIDE would be more appropriate
225231
// calculate the pixel position
226232
unsigned int xPosition, yPosition;
@@ -243,6 +249,13 @@ void Heatmap::run()
243249
for ( int yp = 0; yp <= myBuffer; yp++ )
244250
{
245251
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+
246259
float pixelValue = weight * ( 1 - (( 1 - myDecay ) * distance / myBuffer ) );
247260

248261
// clearing anamolies along the axes
@@ -255,21 +268,18 @@ void Heatmap::run()
255268
pixelValue /= 2;
256269
}
257270

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++ )
259277
{
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 )
266279
{
267-
if ( dataBuffer[ pos[p] ] == NO_DATA )
268-
{
269-
dataBuffer[ pos[p] ] = 0;
270-
}
271-
dataBuffer[ pos[p] ] += pixelValue;
280+
dataBuffer[ pos[p] ] = 0;
272281
}
282+
dataBuffer[ pos[p] ] += pixelValue;
273283
}
274284
}
275285
}
@@ -278,7 +288,7 @@ void Heatmap::run()
278288
dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 );
279289
CPLFree( dataBuffer );
280290
}
281-
//Finally close the dataset
291+
// Finally close the dataset
282292
GDALClose(( GDALDatasetH ) heatmapDS );
283293

284294
// Open the file in QGIS window
@@ -291,6 +301,7 @@ void Heatmap::run()
291301
* Local functions
292302
*
293303
*/
304+
294305
float Heatmap::mapUnitsOf( float meters, QgsCoordinateReferenceSystem layerCrs )
295306
{
296307
// Worker to transform metres input to mapunits
@@ -304,6 +315,19 @@ float Heatmap::mapUnitsOf( float meters, QgsCoordinateReferenceSystem layerCrs )
304315
return meters / da.measureLine( QgsPoint( 0.0, 0.0 ), QgsPoint( 0.0, 1.0 ) );
305316
}
306317

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+
307331
// Unload the plugin by cleaning up the GUI
308332
void Heatmap::unload()
309333
{

‎src/plugins/heatmap/heatmap.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ class Heatmap: public QObject, public QgisPlugin
8383
private:
8484
//! Worker to convert meters to map units
8585
float mapUnitsOf( float meters, QgsCoordinateReferenceSystem crs );
86+
//! Worker to calculate buffer size in pixels
87+
int bufferSize( float radius, float cellsize );
88+
8689
// MANDATORY PLUGIN PROPERTY DECLARATIONS .....
8790

8891
int mPluginType;

0 commit comments

Comments
 (0)
Please sign in to comment.