Skip to content

Commit 03fd388

Browse files
committedFeb 8, 2012
Merged in Arunmozhi's heatmap plugin into QGIS core
1 parent bc43fdd commit 03fd388

File tree

14 files changed

+1268
-15
lines changed

14 files changed

+1268
-15
lines changed
 

‎INSTALL

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
Quantum GIS (QGIS)
22
Building QGIS from source - step by step
3-
Tuesday December 27, 2011
3+
Monday February 06, 2012
44

55

6-
Last Updated: Tuesday December 27, 2011
7-
Last Change : Tuesday December 27, 2011
6+
Last Updated: Monday February 06, 2012
7+
Last Change : Wednesday February 01, 2012
88

99

1010
1. Introduction

‎doc/INSTALL.html

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,13 @@
8080
<DIV CLASS="header" ID="header">
8181
<H1>Quantum GIS (QGIS)</H1>
8282
<H2>Building QGIS from source - step by step</H2>
83-
<H3>Sunday November 06, 2011</H3>
83+
<H3>Monday February 06, 2012</H3>
8484
</DIV>
8585

8686
<DIV CLASS="body" ID="body">
8787
<P>
88-
Last Updated: Sunday November 06, 2011
89-
Last Change : Sunday November 06, 2011
88+
Last Updated: Monday February 06, 2012
89+
Last Change : Wednesday February 01, 2012
9090
</P>
9191
<DIV CLASS="toc">
9292

@@ -1753,7 +1753,7 @@ <H2>5.2. Install development frameworks for QGIS dependencies</H2>
17531753
</P>
17541754
<P>
17551755
William provides an additional installer package for Postgresql (for PostGIS
1756-
support). Qgis just needs the libpq client library, so unless you want to
1756+
support). QGIS just needs the libpq client library, so unless you want to
17571757
setup the full Postgres + PostGIS server, all you need is the client-only
17581758
package. It's available here:
17591759
</P>
@@ -1772,7 +1772,7 @@ <H3>5.2.1. Additional Dependencies: General compatibility note</H3>
17721772
<P>
17731773
There are some additional dependencies that, at the time of writing, are not
17741774
provided as frameworks or installers so we will need to build these from source.
1775-
If you are wanting to build Qgis as a 64-bit application, you will need to
1775+
If you are wanting to build QGIS as a 64-bit application, you will need to
17761776
provide the appropriate build commands to produce 64-bit support in dependencies.
17771777
Likewise, for 32-bit support on Snow Leopard, you will need to override the
17781778
default system architecture, which is 64-bit, according to instructions for
@@ -2001,7 +2001,7 @@ <H3>5.2.6. Additional Dependencies: Qwt/PyQwt</H3>
20012001
<P>
20022002
Double-click the tarball to unpack it. The following assumes PyQwt v5.2.0
20032003
(comes with Qwt 5.2.1). Normal compilation does both Qwt and PyQwt at the same
2004-
time, but Qwt is statically linked into PyQwt, and Qgis can't use it. So, we
2004+
time, but Qwt is statically linked into PyQwt, and QGIS can't use it. So, we
20052005
need to split the build.
20062006
</P>
20072007
<P>
@@ -2155,7 +2155,7 @@ <H2>5.5. Configure the build</H2>
21552155
</P>
21562156
<P>
21572157
Or, to use a Unix-style build of GRASS, use the following cmake invocation
2158-
(minimum GRASS version as stated in the Qgis requirements, substitute the GRASS
2158+
(minimum GRASS version as stated in the QGIS requirements, substitute the GRASS
21592159
path and version as required):
21602160
</P>
21612161

@@ -2194,7 +2194,7 @@ <H2>5.5. Configure the build</H2>
21942194
</PRE></div>
21952195

21962196
<P>
2197-
The Qgis Mapserver feature requires fastcgi support. This is included in
2197+
The QGIS Mapserver feature requires fastcgi support. This is included in
21982198
Leopard and Snow Leopard, but was dropped at Lion. To build the Mapserver
21992199
component on Leopard and Snow, add the followling line before the last line in
22002200
the above configuration:
@@ -2210,9 +2210,9 @@ <H2>5.5. Configure the build</H2>
22102210
</P>
22112211
<P>
22122212
<U>Bundling note:</U> Older Qt versions may have problems with some Qt plugins and
2213-
Qgis. The way to handle this is to bundle Qt inside the Qgis application. You
2214-
can do this now or wait to see if there are immediate crashes when running Qgis.
2215-
It's also a good idea to bundle Qt if you need to copy Qgis to other Macs (where
2213+
QGIS. The way to handle this is to bundle Qt inside the QGIS application. You
2214+
can do this now or wait to see if there are immediate crashes when running QGIS.
2215+
It's also a good idea to bundle Qt if you need to copy QGIS to other Macs (where
22162216
you would have to install Xcode just so Qt would install!).
22172217
</P>
22182218
<P>
@@ -2311,5 +2311,5 @@ <H1>6. Authors and Acknowledgments</H1>
23112311

23122312
</DIV>
23132313
<!-- html code generated by txt2tags 2.6 (http://txt2tags.org) -->
2314-
<!-- cmdline: txt2tags -t html -o INSTALL.html INSTALL.t2t -->
2314+
<!-- cmdline: txt2tags -o INSTALL.html -t html INSTALL.t2t -->
23152315
</BODY></HTML>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<h1>Heatmap Plugin Help</h1>
2+
<p>Heatmap Plugin creates a heatmap raster for the input point vector layer. The heatmap is generated based on the number of points in a given location. The higher the number of points, the higher will be the corresponding pixel(s) value in the raster.</p>
3+
4+
<h2>The Dialog Parameters</h2>
5+
6+
<h3>Input Point Vector</h3>
7+
<p>The input is always a vector layer of point type. All the point vector layers that are currently loaded in the window are automatically populated in the input layer drop-down list. Click the Dropdown button and select the required layer.</p>
8+
9+
<h3>Output Ratser</h3>
10+
<p>The output raster location and filename can be set by clicking the <label>...</label> button next to the output raster textbox.<br/>
11+
<b>Note:</b>The file format is automatically added depending upon the output format selected, if not explicitly given.</p>
12+
13+
<h3>Output Format</h3>
14+
<p>All the file creation supporting GDAL formats are available in the drop down list. Click and select the required output format for your file.<br/>
15+
<b>Note:</b> GeoTiff and ERDAS Imagine .img formats are recommended. Some formats makes the application crash. Kindly stick to the recommended formats until the crash issue is resolved or Use other formats if you know about its GDAL support completely.</p>
16+
17+
<h3>Heatmap Point Attributes</h3>
18+
<h4>Buffer Radius</h4>
19+
<p>The buffer radius specifies the number of <b>pixels or cells</b> around a point where the heat(influence) of the point will be felt. Smaller values give you clear distinction between points and bigger values gives you nicely merged heatmap regions. This is the spatial parameter of the heat region of a point.<br/>
20+
<b>Note:</b> The value is always a whole number.</p>
21+
<h4>Decay Ratio</h4>
22+
<p>The decay ratio defines amount of heat(influence) that should reach the outermost pixel in the Buffer Radius. It is the direct measure of the outer most value.<br/>
23+
<b>Example:</b> If Buffer Ratio is set as 0 and Radius as 10, then the centre pixel of a point will have value and the pixel away by a distance of 10 units will have the value 0, a pixel which is 5 units away will have a value of 0.5 and so on. Here distance is measure not by pixel count rather using sqrt( xOffset^2 + yOffset^2 ), so you always get a circular heat region.</p>
24+
25+
<h2>Further Details</h2>
26+
<p>Contact the author through aruntheguy at gmail dot com</p>
27+

‎src/plugins/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,5 @@ IF (WITH_GLOBE)
3737
ENDIF (WITH_GLOBE)
3838

3939
# headers installed in qgis_core target
40+
41+
SUBDIRS (heatmap)

‎src/plugins/heatmap/CMakeLists.txt

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
2+
########################################################
3+
# Files
4+
5+
SET (heatmap_SRCS
6+
heatmap.cpp
7+
heatmapgui.cpp
8+
)
9+
10+
SET (heatmap_UIS heatmapguibase.ui)
11+
12+
SET (heatmap_MOC_HDRS
13+
heatmap.h
14+
heatmapgui.h
15+
)
16+
17+
SET (heatmap_RCCS heatmap.qrc)
18+
19+
########################################################
20+
# Build
21+
22+
QT4_WRAP_UI (heatmap_UIS_H ${heatmap_UIS})
23+
24+
QT4_WRAP_CPP (heatmap_MOC_SRCS ${heatmap_MOC_HDRS})
25+
26+
QT4_ADD_RESOURCES(heatmap_RCC_SRCS ${heatmap_RCCS})
27+
28+
ADD_LIBRARY (heatmapplugin MODULE ${heatmap_SRCS} ${heatmap_MOC_SRCS} ${heatmap_RCC_SRCS} ${heatmap_UIS_H})
29+
30+
INCLUDE_DIRECTORIES(
31+
${CMAKE_CURRENT_BINARY_DIR}
32+
${GEOS_INCLUDE_DIR}
33+
${GDAL_INCLUDE_DIR}
34+
../../core
35+
../../core/raster
36+
../../gui
37+
../../analysis/raster
38+
..
39+
)
40+
41+
TARGET_LINK_LIBRARIES(heatmapplugin
42+
qgis_core
43+
qgis_gui
44+
)
45+
46+
47+
########################################################
48+
# Install
49+
50+
INSTALL(TARGETS heatmapplugin
51+
RUNTIME DESTINATION ${QGIS_PLUGIN_DIR}
52+
LIBRARY DESTINATION ${QGIS_PLUGIN_DIR})
53+

‎src/plugins/heatmap/README

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
Welcome to your automatically generated plugin!
2+
-------------------------------------------------------------
3+
4+
This is just a starting point. You now need to modify the code to make it do
5+
something useful....read on for a more information to get yourself started.
6+
7+
Documentation:
8+
-------------------------------------------------------------
9+
10+
You really need to read the QGIS API Documentation now at:
11+
12+
http://qgis.org/api/
13+
14+
In particular look at the following classes:
15+
16+
QGisInterface : http://qgis.org/api/classQgisInterface.html
17+
QgsMapCanvas : http://qgis.org/api/classQgsMapCanvas.html
18+
QgsMapTool : http://qgis.org/api/classQgsMapTool.html
19+
QgisPlugin : http://qgis.org/api/classQgisPlugin.html
20+
21+
QGisInterface is an abstract base class (ABC) that specifies what publicly
22+
available features of QGIS are exposed to third party code and plugins. An
23+
instance of the QgisInterface is passed to the plugin when it loads. Please
24+
consult the QGIS development team if there is functionality required in the
25+
QGisInterface that is not available.
26+
27+
QgsPlugin is an ABC that defines required behaviour your plugin must provide.
28+
See below for more details.
29+
30+
What are all the files in my generated plugin directory for?
31+
-------------------------------------------------------------
32+
33+
CMakeLists.txt
34+
This is the generated CMake file that builds the plugin. You should add you
35+
application specific dependencies and source files to this file.
36+
37+
heatmap.h
38+
heatmap.cpp
39+
This is the class that provides the 'glue' between your custom application
40+
logic and the QGIS application. You will see that a number of methods are
41+
already implemented for you - including some examples of how to add a raster or
42+
vector layer to the main application map canvas. This class is a concrete
43+
implementation of QgisPlugin (which defines required behaviour for a plugin).
44+
In particular, a plugin has a number of static methods and members so that the
45+
QgsPluginManager and plugin loader logic can identify each plugin, create an
46+
appropriate menu entry for it etc. Note there is nothing stopping you creating
47+
multiple toolbar icons and menu entries for a single plugin. By default though
48+
a single menu entry and toolbar button is created and its pre-configured to
49+
call the run() method in this class when selected. This default implementation
50+
provided for you by the plugin builder is well documented, so please refer to
51+
the code for further advice.
52+
53+
heatmapgui.ui
54+
This is a Qt designer 'ui' file. It defines the look of the default plugin
55+
dialog without implementing any application logic. You can modify this form to
56+
suite your needs or completely remove it if your plugin does not need to
57+
display a user form (e.g. for custom MapTools).
58+
59+
60+
heatmapgui.cpp
61+
heatmapgui.h
62+
This is the concrete class where application logic for the above mentioned
63+
dialog should go. The world is your oyster here really....
64+
65+
heatmap.qrc
66+
This is the Qt4 resources file for your plugin. The Makefile generated for your
67+
plugin is all set up to compile the resource file so all you need to do is add
68+
your additional icons etc using the simple xml file format. Note the namespace
69+
used for all your resources e.g. (":/Heatmap/"). It is important to use
70+
this prefix for all your resources. We suggest you include any other images and
71+
run time data in this resurce file too.
72+
73+
heatmap.png
74+
This is the icon that will be used for your plugin menu entry and toolbar icon.
75+
Simply replace this icon with your own icon to make your plugin disctinctive
76+
from the rest.
77+
78+
README
79+
This file contains the documentation you are reading now!
80+
81+
82+
Getting developer help:
83+
-------------------------------------------------------------
84+
85+
For Questions and Comments regarding the plugin builder template and creating
86+
your features in QGIS using the plugin interface please contact us via:
87+
88+
* the QGIS developers mailing list, or
89+
* IRC (#qgis on freenode.net)
90+
91+
QGIS is distributed under the Gnu Public License. If you create a useful plugin
92+
please consider contributing it back to the community.
93+
94+
Have fun and thank you for choosing QGIS.
95+
96+
The QGIS Team
97+
2007

‎src/plugins/heatmap/heatmap.cpp

Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
/***************************************************************************
2+
heatmap.cpp
3+
Creates a Heatmap raster for the input point vector
4+
-------------------
5+
begin : January 2012
6+
copyright : [(C) Arunmozhi]
7+
email : [aruntheguy at gmail dot com]
8+
9+
***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
// GDAL includes
19+
#include "gdal_priv.h"
20+
#include "cpl_string.h"
21+
#include "cpl_conv.h"
22+
23+
// QGIS Specific includes
24+
#include <qgisinterface.h>
25+
#include <qgisgui.h>
26+
27+
#include "heatmap.h"
28+
#include "heatmapgui.h"
29+
30+
#include "qgsgeometry.h"
31+
#include "qgsvectorlayer.h"
32+
#include "qgsvectordataprovider.h"
33+
34+
// Qt4 Related Includes
35+
#include <QAction>
36+
#include <QToolBar>
37+
#include <QMessageBox>
38+
#include <QFileInfo>
39+
#include <QProgressDialog>
40+
41+
#define NO_DATA -9999
42+
43+
44+
static const QString sName = QObject::tr( "Heatmap" );
45+
static const QString sDescription = QObject::tr( "Creates a Heatmap raster for the input point vector" );
46+
static const QString sCategory = QObject::tr( "Raster" );
47+
static const QString sPluginVersion = QObject::tr( "Version 0.1" );
48+
static const QgisPlugin::PLUGINTYPE sPluginType = QgisPlugin::UI;
49+
static const QString sPluginIcon = ":/heatmap/heatmap.png";
50+
51+
/**
52+
* Constructor for the plugin. The plugin is passed a pointer
53+
* an interface object that provides access to exposed functions in QGIS.
54+
* @param theQGisInterface - Pointer to the QGIS interface object
55+
*/
56+
Heatmap::Heatmap( QgisInterface * theQgisInterface ):
57+
QgisPlugin( sName, sDescription, sCategory, sPluginVersion, sPluginType ),
58+
mQGisIface( theQgisInterface )
59+
{
60+
}
61+
62+
Heatmap::~Heatmap()
63+
{
64+
65+
}
66+
67+
/*
68+
* Initialize the GUI interface for the plugin - this is only called once when the plugin is
69+
* added to the plugin registry in the QGIS application.
70+
*/
71+
void Heatmap::initGui()
72+
{
73+
74+
// Create the action for tool
75+
mQActionPointer = new QAction( QIcon( ":/heatmap/heatmap.png" ), tr( "Heatmap" ), this );
76+
// Set the what's this text
77+
mQActionPointer->setWhatsThis( tr( "Creats a heatmap raster for the input point vector." ) );
78+
// Connect the action to the run
79+
connect( mQActionPointer, SIGNAL( triggered() ), this, SLOT( run() ) );
80+
// Add the icon to the toolbar
81+
mQGisIface->addToolBarIcon( mQActionPointer );
82+
mQGisIface->addPluginToRasterMenu( tr( "&Heatmap" ), mQActionPointer );
83+
84+
}
85+
//method defined in interface
86+
void Heatmap::help()
87+
{
88+
//implement me!
89+
}
90+
91+
// Slot called when the menu item is triggered
92+
// If you created more menu items / toolbar buttons in initiGui, you should
93+
// create a separate handler for each action - this single run() method will
94+
// not be enough
95+
void Heatmap::run()
96+
{
97+
HeatmapGui *myPluginGui = new HeatmapGui( mQGisIface->mainWindow(), QgisGui::ModalDialogFlags );
98+
myPluginGui->setAttribute( Qt::WA_DeleteOnClose );
99+
100+
// Connect the createRaster signal to createRaster Slot
101+
connect( myPluginGui, SIGNAL( createRaster( QgsVectorLayer*, int, float, QString, QString ) ),
102+
this, SLOT( createRaster( QgsVectorLayer*, int, float, QString, QString ) ) );
103+
104+
myPluginGui->show();
105+
}
106+
107+
// Unload the plugin by cleaning up the GUI
108+
void Heatmap::unload()
109+
{
110+
// remove the GUI
111+
mQGisIface->removePluginMenu( "&Heatmap", mQActionPointer );
112+
mQGisIface->removeToolBarIcon( mQActionPointer );
113+
delete mQActionPointer;
114+
}
115+
116+
// The worker
117+
void Heatmap::createRaster( QgsVectorLayer* theVectorLayer, int theBuffer, float theDecay, QString theOutputFilename, QString theOutputFormat )
118+
{
119+
// generic variables
120+
int xSize, ySize;
121+
double xResolution, yResolution;
122+
double rasterX, rasterY;
123+
124+
// Getting the rasterdataset in place
125+
GDALAllRegister();
126+
127+
GDALDataset *emptyDataset;
128+
GDALDriver *myDriver;
129+
130+
myDriver = GetGDALDriverManager()->GetDriverByName( theOutputFormat.toUtf8() );
131+
if( myDriver == NULL )
132+
{
133+
QMessageBox::information( 0, tr("Error in GDAL Driver!"), tr("Cannot open the driver for the format specified") );
134+
return;
135+
}
136+
137+
// bounding box info
138+
QgsRectangle myBBox = theVectorLayer->extent();
139+
// fixing a base width of 500 px/cells
140+
xSize = 500;
141+
xResolution = myBBox.width()/xSize;
142+
yResolution = xResolution;
143+
ySize = myBBox.height()/yResolution;
144+
// add extra extend to cover the corner points' heat region
145+
xSize = xSize + ( theBuffer * 2 ) + 10 ;
146+
ySize = ySize + ( theBuffer * 2 ) + 10 ;
147+
// Define the new lat,lon for the buffered raster area
148+
rasterX = myBBox.xMinimum() - ( theBuffer + 5 ) * xResolution;
149+
rasterY = myBBox.yMinimum() - ( theBuffer + 5 ) * yResolution;
150+
151+
double geoTransform[6] = { rasterX, xResolution, 0, rasterY, 0, yResolution };
152+
153+
emptyDataset = myDriver->Create( theOutputFilename.toUtf8(), xSize, ySize, 1, GDT_Float32, NULL );
154+
155+
emptyDataset->SetGeoTransform( geoTransform );
156+
157+
GDALRasterBand *poBand;
158+
poBand = emptyDataset->GetRasterBand(1);
159+
poBand->SetNoDataValue( NO_DATA );
160+
161+
float* line = ( float * ) CPLMalloc( sizeof( float ) * xSize );
162+
std::fill_n( line, xSize, NO_DATA );
163+
// Write the empty raster
164+
for ( int i = 0; i < ySize ; i += 1 )
165+
{
166+
poBand->RasterIO( GF_Write, 0, 0, xSize, 1, line, xSize, 1, GDT_Float32, 0, 0 );
167+
}
168+
169+
CPLFree( line );
170+
//close the dataset
171+
GDALClose( (GDALDatasetH) emptyDataset );
172+
173+
// open the raster in GA_Update mode
174+
GDALDataset *heatmapDS;
175+
heatmapDS = ( GDALDataset * ) GDALOpen( theOutputFilename.toUtf8(), GA_Update );
176+
if( !heatmapDS )
177+
{
178+
QMessageBox::information( 0, tr("Error in Updating Raster!"), tr("Couldnot open the created raster for updation. The Heatmap was not generated.") );
179+
return;
180+
}
181+
poBand = heatmapDS->GetRasterBand( 1 );
182+
// Get the data buffer ready
183+
int blockSize = 2 * theBuffer + 1; // block SIDE would have been more appropriate
184+
// Open the vector features
185+
QgsVectorDataProvider* myVectorProvider = theVectorLayer->dataProvider();
186+
if( !myVectorProvider )
187+
{
188+
QMessageBox::information( 0, tr( "Error in Point Layer!"), tr("Couldnot identify the vector data provider.") );
189+
return;
190+
}
191+
QgsAttributeList dummyList;
192+
myVectorProvider->select( dummyList );
193+
194+
int totalFeatures = myVectorProvider->featureCount();
195+
int counter = 0;
196+
197+
QProgressDialog p( "Creating Heatmap ... ", "Abort", 0, totalFeatures );
198+
p.setWindowModality(Qt::WindowModal);
199+
200+
QgsFeature myFeature;
201+
202+
while( myVectorProvider->nextFeature( myFeature ) )
203+
{
204+
counter += 1;
205+
p.setValue( counter );
206+
if( p.wasCanceled() )
207+
{
208+
QMessageBox::information( 0, tr("Heatmap Generation Aborted!"), tr("QGIS will now load the partially-computed raster.") );
209+
break;
210+
}
211+
212+
QgsGeometry* myPointGeometry;
213+
myPointGeometry = myFeature.geometry();
214+
// convert the geometry to point
215+
QgsPoint myPoint;
216+
myPoint = myPointGeometry->asPoint();
217+
// avoiding any empty points or out of extent points
218+
if( ( myPoint.x() < rasterX ) || ( myPoint.y() < rasterY ) )
219+
{
220+
continue;
221+
}
222+
// calculate the pixel position
223+
unsigned int xPosition, yPosition;
224+
xPosition = (( myPoint.x() - rasterX )/ xResolution ) - theBuffer;
225+
yPosition = (( myPoint.y() - rasterY )/ yResolution ) - theBuffer;
226+
227+
// get the data
228+
float *dataBuffer = ( float * ) CPLMalloc( sizeof( float ) * blockSize * blockSize );
229+
poBand->RasterIO( GF_Read, xPosition, yPosition, blockSize, blockSize, dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 );
230+
231+
for( int xp = 0; xp <= theBuffer; xp += 1 )
232+
{
233+
for( int yp = 0; yp <= theBuffer; yp += 1 )
234+
{
235+
float distance = sqrt( pow( xp, 2 ) + pow( yp, 2 ) );
236+
float pixelValue = 1 - ( (1-theDecay) * distance / theBuffer );
237+
238+
// clearing anamolies along the axes
239+
if( xp == 0 && yp == 0 )
240+
{
241+
pixelValue /= 4;
242+
}
243+
else if( xp == 0 || yp == 0 )
244+
{
245+
pixelValue /= 2;
246+
}
247+
248+
if( distance <= theBuffer )
249+
{
250+
int pos[4];
251+
pos[0] = ( theBuffer + xp ) * blockSize + ( theBuffer + yp );
252+
pos[1] = ( theBuffer + xp ) * blockSize + ( theBuffer - yp );
253+
pos[2] = ( theBuffer - xp ) * blockSize + ( theBuffer + yp );
254+
pos[3] = ( theBuffer - xp ) * blockSize + ( theBuffer - yp );
255+
for( int p = 0; p < 4; p += 1 )
256+
{
257+
if( dataBuffer[ pos[p] ] == NO_DATA )
258+
{
259+
dataBuffer[ pos[p] ] = 0;
260+
}
261+
dataBuffer[ pos[p] ] += pixelValue;
262+
}
263+
}
264+
}
265+
}
266+
267+
poBand->RasterIO( GF_Write, xPosition, yPosition, blockSize, blockSize, dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 );
268+
CPLFree( dataBuffer );
269+
}
270+
271+
//Finally close the dataset
272+
GDALClose( (GDALDatasetH) heatmapDS );
273+
274+
// Open the file in QGIS window
275+
mQGisIface->addRasterLayer( theOutputFilename, QFileInfo( theOutputFilename ).baseName() );
276+
}
277+
278+
//////////////////////////////////////////////////////////////////////////
279+
//
280+
//
281+
// THE FOLLOWING CODE IS AUTOGENERATED BY THE PLUGIN BUILDER SCRIPT
282+
// YOU WOULD NORMALLY NOT NEED TO MODIFY THIS, AND YOUR PLUGIN
283+
// MAY NOT WORK PROPERLY IF YOU MODIFY THIS INCORRECTLY
284+
//
285+
//
286+
//////////////////////////////////////////////////////////////////////////
287+
288+
289+
/**
290+
* Required extern functions needed for every plugin
291+
* These functions can be called prior to creating an instance
292+
* of the plugin class
293+
*/
294+
// Class factory to return a new instance of the plugin class
295+
QGISEXTERN QgisPlugin * classFactory( QgisInterface * theQgisInterfacePointer )
296+
{
297+
return new Heatmap( theQgisInterfacePointer );
298+
}
299+
// Return the name of the plugin - note that we do not user class members as
300+
// the class may not yet be insantiated when this method is called.
301+
QGISEXTERN QString name()
302+
{
303+
return sName;
304+
}
305+
306+
// Return the description
307+
QGISEXTERN QString description()
308+
{
309+
return sDescription;
310+
}
311+
312+
// Return the category
313+
QGISEXTERN QString category()
314+
{
315+
return sCategory;
316+
}
317+
318+
// Return the type (either UI or MapLayer plugin)
319+
QGISEXTERN int type()
320+
{
321+
return sPluginType;
322+
}
323+
324+
// Return the version number for the plugin
325+
QGISEXTERN QString version()
326+
{
327+
return sPluginVersion;
328+
}
329+
330+
QGISEXTERN QString icon()
331+
{
332+
return sPluginIcon;
333+
}
334+
335+
// Delete ourself
336+
QGISEXTERN void unload( QgisPlugin * thePluginPointer )
337+
{
338+
delete thePluginPointer;
339+
}

‎src/plugins/heatmap/heatmap.h

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/***************************************************************************
2+
heatmap.h
3+
-------------------
4+
begin : Jan 21, 2004
5+
copyright : (C) 2004 by Tim Sutton
6+
email : tim@linfiniti.com
7+
8+
***************************************************************************/
9+
10+
/***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************/
18+
/***************************************************************************
19+
* QGIS Programming conventions:
20+
*
21+
* mVariableName - a class level member variable
22+
* sVariableName - a static class level member variable
23+
* variableName() - accessor for a class member (no 'get' in front of name)
24+
* setVariableName() - mutator for a class member (prefix with 'set')
25+
*
26+
* Additional useful conventions:
27+
*
28+
* theVariableName - a method parameter (prefix with 'the')
29+
* myVariableName - a locally declared variable within a method ('my' prefix)
30+
*
31+
* DO: Use mixed case variable names - myVariableName
32+
* DON'T: separate variable names using underscores: my_variable_name (NO!)
33+
*
34+
* **************************************************************************/
35+
#ifndef Heatmap_H
36+
#define Heatmap_H
37+
38+
//QT4 includes
39+
#include <QObject>
40+
41+
//QGIS includes
42+
#include "../qgisplugin.h"
43+
#include "qgsvectorlayer.h"
44+
45+
//forward declarations
46+
class QAction;
47+
class QToolBar;
48+
49+
class QgisInterface;
50+
51+
/**
52+
* \class Plugin
53+
* \brief heatmap plugin for QGIS
54+
* \description generates a heatmap raster for the input point vector
55+
*/
56+
class Heatmap: public QObject, public QgisPlugin
57+
{
58+
Q_OBJECT
59+
public:
60+
61+
// MANDATORY PLUGIN METHODS FOLLOW
62+
63+
/**
64+
* Constructor for a plugin. The QgisInterface pointer is passed by
65+
* QGIS when it attempts to instantiate the plugin.
66+
* @param theInterface Pointer to the QgisInterface object.
67+
*/
68+
Heatmap( QgisInterface * theInterface );
69+
//! Destructor
70+
virtual ~Heatmap();
71+
72+
public slots:
73+
//! init the gui
74+
virtual void initGui();
75+
//! Show the dialog box
76+
void run();
77+
//! unload the plugin
78+
void unload();
79+
//! show the help document
80+
void help();
81+
//! the worker slot to create heatmap
82+
/*
83+
* Signal: createRaster
84+
* Params:
85+
* QgsVectorLayer* -> Input point layer
86+
* int -> Buffer distance
87+
* float -> Decay ratio
88+
* QString -> Output filename
89+
* QString -> Output Format Short Name
90+
*/
91+
void createRaster( QgsVectorLayer*, int, float, QString, QString );
92+
93+
private:
94+
95+
// MANDATORY PLUGIN PROPERTY DECLARATIONS .....
96+
97+
int mPluginType;
98+
//! Pointer to the QGIS interface object
99+
QgisInterface *mQGisIface;
100+
//!pointer to the qaction for this plugin
101+
QAction * mQActionPointer;
102+
103+
};
104+
105+
#endif //Heatmap_H

‎src/plugins/heatmap/heatmap.png

1.24 KB
Loading

‎src/plugins/heatmap/heatmap.qrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<RCC>
2+
<qresource prefix="/heatmap/" >
3+
<file>heatmap.png</file>
4+
</qresource>
5+
</RCC>

‎src/plugins/heatmap/heatmap.svg

Lines changed: 143 additions & 0 deletions
Loading

‎src/plugins/heatmap/heatmapgui.cpp

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
/***************************************************************************
2+
* Copyright (C) 2003 by Tim Sutton *
3+
* tim@linfiniti.com *
4+
* *
5+
* This is a plugin generated from the QGIS plugin template *
6+
* *
7+
* This program is free software; you can redistribute it and/or modify *
8+
* it under the terms of the GNU General Public License as published by *
9+
* the Free Software Foundation; either version 2 of the License, or *
10+
* (at your option) any later version. *
11+
***************************************************************************/
12+
// qgis includes
13+
#include "qgis.h"
14+
#include "heatmapgui.h"
15+
#include "qgscontexthelp.h"
16+
#include "qgsmaplayer.h"
17+
#include "qgsmaplayerregistry.h"
18+
#include "qgsvectorlayer.h"
19+
20+
// GDAL includes
21+
#include "gdal_priv.h"
22+
#include "cpl_string.h"
23+
#include "cpl_conv.h"
24+
25+
//qt includes
26+
#include <QComboBox>
27+
#include <QFileDialog>
28+
#include <QSettings>
29+
#include <QMessageBox>
30+
31+
//standard includes
32+
33+
HeatmapGui::HeatmapGui( QWidget* parent, Qt::WFlags fl )
34+
: QDialog( parent, fl )
35+
{
36+
setupUi( this );
37+
38+
// Adding point layers to the mInputVectorCombo
39+
QMap<QString, QgsMapLayer*> mapLayers = QgsMapLayerRegistry::instance()->mapLayers();
40+
QMapIterator<QString, QgsMapLayer*> layers(mapLayers);
41+
42+
while( layers.hasNext() )
43+
{
44+
layers.next();
45+
QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>(layers.value());
46+
if( ( vl ) && ( vl->geometryType() == QGis::Point ) )
47+
{
48+
mInputVectorCombo->addItem( vl->name(), QVariant( vl->id() ) );
49+
}
50+
}
51+
52+
// Adding GDAL drivers with CREATE to the mFormatCombo
53+
int myTiffIndex = -1;
54+
int myIndex = -1;
55+
GDALAllRegister();
56+
int nDrivers = GDALGetDriverCount();
57+
for( int i = 0; i < nDrivers; i +=1 )
58+
{
59+
GDALDriver* nthDriver = GetGDALDriverManager()->GetDriver( i );
60+
char** driverMetadata = nthDriver->GetMetadata();
61+
if( CSLFetchBoolean( driverMetadata, GDAL_DCAP_CREATE, false ) )
62+
{
63+
++myIndex;
64+
QString myLongName = nthDriver->GetMetadataItem( GDAL_DMD_LONGNAME );
65+
// Add LongName text, shortname variant; GetDescription actually gets the shortname
66+
mFormatCombo->addItem( myLongName, QVariant( nthDriver->GetDescription() ) );
67+
// Add the drivers and their extensions to a map for filename correction
68+
mExtensionMap.insert( nthDriver->GetDescription(), nthDriver->GetMetadataItem( GDAL_DMD_EXTENSION ) );
69+
if ( myLongName == "GeoTIFF" )
70+
{
71+
myTiffIndex = myIndex;
72+
}
73+
}
74+
}
75+
mFormatCombo->setCurrentIndex(myTiffIndex);
76+
77+
//finally set right the ok button
78+
enableOrDisableOkButton();
79+
}
80+
81+
HeatmapGui::~HeatmapGui()
82+
{
83+
}
84+
85+
void HeatmapGui::on_mButtonBox_accepted()
86+
{
87+
// Variables to be emitted with the createRaster signal
88+
QgsVectorLayer* inputLayer;
89+
int bufferDistance;
90+
float decayRatio;
91+
QString outputFileName;
92+
QString outputFormat;
93+
94+
QString dummyText;
95+
96+
// The input vector layer
97+
int myLayerId = mInputVectorCombo->itemData( mInputVectorCombo->currentIndex() ).toInt();
98+
99+
QMap<QString, QgsMapLayer*> mapLayers = QgsMapLayerRegistry::instance()->mapLayers();
100+
QMapIterator<QString, QgsMapLayer*> layers(mapLayers);
101+
102+
while( layers.hasNext() )
103+
{
104+
layers.next();
105+
QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>(layers.value());
106+
if ( vl )
107+
{
108+
dummyText = vl->id();
109+
if( dummyText.toInt() == myLayerId )
110+
{
111+
inputLayer = vl;
112+
}
113+
}
114+
}
115+
116+
// The buffer distance
117+
dummyText = mBufferLineEdit->text();
118+
bufferDistance = dummyText.toInt();
119+
if( bufferDistance == NULL )
120+
{
121+
QMessageBox::information( 0, tr("Invalid Buffer Value!"), tr("Buffer distance cannot be NULL, kindly enter a valid value.") );
122+
return;
123+
}
124+
// The decay ratio
125+
dummyText = mDecayLineEdit->text();
126+
decayRatio = dummyText.toFloat();
127+
128+
// The output filename
129+
outputFileName = mOutputRasterLineEdit->text();
130+
QFileInfo myFileInfo( outputFileName );
131+
if( outputFileName.isEmpty() || !myFileInfo.dir().exists() )
132+
{
133+
QMessageBox::information( 0, tr("Output filename is invalid!"), tr("Kindly enter a valid output file path and name.") );
134+
return;
135+
}
136+
137+
// The output format
138+
outputFormat = mFormatCombo->itemData( mFormatCombo->currentIndex() ).toString();
139+
140+
// append the file format if the suffix is empty
141+
QString suffix = myFileInfo.suffix();
142+
if( suffix.isEmpty() )
143+
{
144+
QMap<QString, QString>::const_iterator it = mExtensionMap.find( outputFormat );
145+
if( it != mExtensionMap.end() && it.key() == outputFormat )
146+
{
147+
// making sure that there is really a extension value available
148+
// Some drivers donot seem to have any extension at all
149+
if( it.value() != NULL || it.value() != "" )
150+
{
151+
outputFileName.append(".");
152+
outputFileName.append( it.value() );
153+
}
154+
}
155+
}
156+
157+
emit createRaster( inputLayer, bufferDistance, decayRatio, outputFileName, outputFormat );
158+
//and finally
159+
accept();
160+
}
161+
162+
void HeatmapGui::on_mButtonBox_rejected()
163+
{
164+
reject();
165+
}
166+
167+
void HeatmapGui::on_mButtonBox_helpRequested()
168+
{
169+
QgsContextHelp::run( metaObject()->className() );
170+
}
171+
172+
void HeatmapGui::on_mBrowseButton_clicked()
173+
{
174+
QSettings s;
175+
QString lastDir = s.value( "/Heatmap/lastOutputDir", "" ).toString();
176+
177+
QString outputFilename = QFileDialog::getSaveFileName( 0, tr( "Save Heatmap as: "), lastDir );
178+
if( !outputFilename.isEmpty() )
179+
{
180+
mOutputRasterLineEdit->setText( outputFilename );
181+
QFileInfo outputFileInfo( outputFilename );
182+
QDir outputDir = outputFileInfo.absoluteDir();
183+
if( outputDir.exists() )
184+
{
185+
s.setValue( "/Heatmap/lastOutputDir", outputFileInfo.absolutePath() );
186+
}
187+
}
188+
189+
enableOrDisableOkButton();
190+
}
191+
192+
void HeatmapGui::on_mOutputRasterLineEdit_editingFinished()
193+
{
194+
enableOrDisableOkButton();
195+
}
196+
197+
void HeatmapGui::enableOrDisableOkButton()
198+
{
199+
bool enabled = true;
200+
QString filename = mOutputRasterLineEdit->text();
201+
QFileInfo theFileInfo( filename );
202+
if( filename.isEmpty() || !theFileInfo.dir().exists() || ( mInputVectorCombo->count() == 0 ) )
203+
{
204+
enabled = false;
205+
}
206+
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( enabled );
207+
}

‎src/plugins/heatmap/heatmapgui.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/***************************************************************************
2+
* Copyright (C) 2003 by Tim Sutton *
3+
* tim@linfiniti.com *
4+
* *
5+
* This is a plugin generated from the QGIS plugin template *
6+
* *
7+
* This program is free software; you can redistribute it and/or modify *
8+
* it under the terms of the GNU General Public License as published by *
9+
* the Free Software Foundation; either version 2 of the License, or *
10+
* (at your option) any later version. *
11+
***************************************************************************/
12+
#ifndef HeatmapGUI_H
13+
#define HeatmapGUI_H
14+
15+
#include <QDialog>
16+
#include <ui_heatmapguibase.h>
17+
18+
#include "qgsvectorlayer.h"
19+
/**
20+
@author Tim Sutton
21+
*/
22+
class HeatmapGui : public QDialog, private Ui::HeatmapGuiBase
23+
{
24+
Q_OBJECT
25+
public:
26+
HeatmapGui( QWidget* parent = 0, Qt::WFlags fl = 0 );
27+
~HeatmapGui();
28+
29+
private:
30+
QMap<QString, QString> mExtensionMap;
31+
void enableOrDisableOkButton();
32+
33+
private slots:
34+
void on_mButtonBox_accepted();
35+
void on_mButtonBox_rejected();
36+
void on_mButtonBox_helpRequested();
37+
void on_mBrowseButton_clicked(); // Function to open the file dialog
38+
void on_mOutputRasterLineEdit_editingFinished();
39+
40+
signals:
41+
/*
42+
* Signal: createRaster
43+
* Params:
44+
* QgsVectorLayer* -> Input point layer
45+
* int -> Buffer distance
46+
* float -> Decay ratio
47+
* QString -> Output filename
48+
* QString -> Output Format Short Name
49+
*/
50+
void createRaster( QgsVectorLayer*, int, float, QString, QString );
51+
52+
};
53+
54+
#endif

‎src/plugins/heatmap/heatmapguibase.ui

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>HeatmapGuiBase</class>
4+
<widget class="QDialog" name="HeatmapGuiBase">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>400</width>
10+
<height>260</height>
11+
</rect>
12+
</property>
13+
<property name="windowTitle">
14+
<string>Heatmap Plugin</string>
15+
</property>
16+
<property name="locale">
17+
<locale language="English" country="UnitedStates"/>
18+
</property>
19+
<widget class="QLabel" name="mInputLabel">
20+
<property name="geometry">
21+
<rect>
22+
<x>10</x>
23+
<y>20</y>
24+
<width>110</width>
25+
<height>21</height>
26+
</rect>
27+
</property>
28+
<property name="text">
29+
<string>Input Point Vector</string>
30+
</property>
31+
</widget>
32+
<widget class="QComboBox" name="mInputVectorCombo">
33+
<property name="geometry">
34+
<rect>
35+
<x>125</x>
36+
<y>20</y>
37+
<width>260</width>
38+
<height>25</height>
39+
</rect>
40+
</property>
41+
</widget>
42+
<widget class="QLabel" name="mOutputLabel">
43+
<property name="geometry">
44+
<rect>
45+
<x>10</x>
46+
<y>65</y>
47+
<width>110</width>
48+
<height>16</height>
49+
</rect>
50+
</property>
51+
<property name="text">
52+
<string>Output Raster</string>
53+
</property>
54+
</widget>
55+
<widget class="QLineEdit" name="mOutputRasterLineEdit">
56+
<property name="geometry">
57+
<rect>
58+
<x>125</x>
59+
<y>60</y>
60+
<width>230</width>
61+
<height>25</height>
62+
</rect>
63+
</property>
64+
</widget>
65+
<widget class="QPushButton" name="mBrowseButton">
66+
<property name="geometry">
67+
<rect>
68+
<x>355</x>
69+
<y>60</y>
70+
<width>30</width>
71+
<height>25</height>
72+
</rect>
73+
</property>
74+
<property name="focusPolicy">
75+
<enum>Qt::ClickFocus</enum>
76+
</property>
77+
<property name="text">
78+
<string>...</string>
79+
</property>
80+
<property name="autoDefault">
81+
<bool>false</bool>
82+
</property>
83+
</widget>
84+
<widget class="QDialogButtonBox" name="mButtonBox">
85+
<property name="geometry">
86+
<rect>
87+
<x>10</x>
88+
<y>225</y>
89+
<width>375</width>
90+
<height>30</height>
91+
</rect>
92+
</property>
93+
<property name="standardButtons">
94+
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
95+
</property>
96+
</widget>
97+
<widget class="QGroupBox" name="mPointAttributeBox">
98+
<property name="geometry">
99+
<rect>
100+
<x>10</x>
101+
<y>140</y>
102+
<width>370</width>
103+
<height>80</height>
104+
</rect>
105+
</property>
106+
<property name="title">
107+
<string>Heatmap Point Attributes</string>
108+
</property>
109+
<widget class="QLabel" name="mBufferLabel">
110+
<property name="geometry">
111+
<rect>
112+
<x>10</x>
113+
<y>27</y>
114+
<width>101</width>
115+
<height>16</height>
116+
</rect>
117+
</property>
118+
<property name="text">
119+
<string>Buffer Radius</string>
120+
</property>
121+
</widget>
122+
<widget class="QLabel" name="mDecayLabel">
123+
<property name="geometry">
124+
<rect>
125+
<x>10</x>
126+
<y>56</y>
127+
<width>101</width>
128+
<height>16</height>
129+
</rect>
130+
</property>
131+
<property name="text">
132+
<string>Decay Ratio</string>
133+
</property>
134+
</widget>
135+
<widget class="QLineEdit" name="mBufferLineEdit">
136+
<property name="geometry">
137+
<rect>
138+
<x>110</x>
139+
<y>20</y>
140+
<width>113</width>
141+
<height>25</height>
142+
</rect>
143+
</property>
144+
<property name="text">
145+
<string>10</string>
146+
</property>
147+
</widget>
148+
<widget class="QLineEdit" name="mDecayLineEdit">
149+
<property name="geometry">
150+
<rect>
151+
<x>110</x>
152+
<y>50</y>
153+
<width>113</width>
154+
<height>25</height>
155+
</rect>
156+
</property>
157+
<property name="text">
158+
<string>0.5</string>
159+
</property>
160+
</widget>
161+
</widget>
162+
<widget class="QLabel" name="mFormatLabel">
163+
<property name="geometry">
164+
<rect>
165+
<x>10</x>
166+
<y>105</y>
167+
<width>110</width>
168+
<height>15</height>
169+
</rect>
170+
</property>
171+
<property name="text">
172+
<string>Output Format</string>
173+
</property>
174+
</widget>
175+
<widget class="QComboBox" name="mFormatCombo">
176+
<property name="geometry">
177+
<rect>
178+
<x>125</x>
179+
<y>100</y>
180+
<width>260</width>
181+
<height>25</height>
182+
</rect>
183+
</property>
184+
</widget>
185+
</widget>
186+
<resources/>
187+
<connections>
188+
<connection>
189+
<sender>mButtonBox</sender>
190+
<signal>accepted()</signal>
191+
<receiver>HeatmapGuiBase</receiver>
192+
<slot>accept()</slot>
193+
<hints>
194+
<hint type="sourcelabel">
195+
<x>195</x>
196+
<y>123</y>
197+
</hint>
198+
<hint type="destinationlabel">
199+
<x>199</x>
200+
<y>79</y>
201+
</hint>
202+
</hints>
203+
</connection>
204+
<connection>
205+
<sender>mButtonBox</sender>
206+
<signal>rejected()</signal>
207+
<receiver>HeatmapGuiBase</receiver>
208+
<slot>reject()</slot>
209+
<hints>
210+
<hint type="sourcelabel">
211+
<x>195</x>
212+
<y>123</y>
213+
</hint>
214+
<hint type="destinationlabel">
215+
<x>199</x>
216+
<y>79</y>
217+
</hint>
218+
</hints>
219+
</connection>
220+
</connections>
221+
</ui>

0 commit comments

Comments
 (0)
Please sign in to comment.