Heat Map Creation – Using Dynamic Points Table in MapServer/GeoServer

densitygeoserverheat mapmapserverpostgis

How can I create a heat map (some would call a density map) from a points layer in MapServer (or GeoServer)?
(preferably able to choose Interpolation method, NN, IDW, etc and color map with a transparent color)

The points are stored in PostGIS table and the table is dynamic, meaning I need to create the heat map on the fly.

Best Answer

Step-by-step for GeoServer. Note: As @michal-mackiewicz writes, the WPS extension for GeoServer must be installed.

  1. Acquire some point data, for example Natural Earth populated places http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_populated_places.zip
  2. Import data into Postgis for example with ogr2ogr

ogr2ogr -f PostgreSQL PG:"dbname='dbname' host='localhost' port='5432' user='username' password='passwd'" ne_10m_populated_places.shp

  1. Create a new layer for GeoServer and publish it. I suppose that PostGIS store already exists.
  2. Copy the heatmap SLD example from http://docs.geoserver.org/stable/en/user/styling/sld-extensions/rendering-transform.html
  3. Edit SLD to suit with the new layer and change the layer name, population attribute and the name of the geometry column.
<?xml version="1.0" encoding="ISO-8859-1"?>
   <StyledLayerDescriptor version="1.0.0"
       xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd"
       xmlns="http://www.opengis.net/sld"
       xmlns:ogc="http://www.opengis.net/ogc"
       xmlns:xlink="http://www.w3.org/1999/xlink"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     <NamedLayer>
       <Name>cite:ne_10m_populated_places</Name>
       <UserStyle>
         <Title>Heatmap</Title>
         <Abstract>A heatmap surface showing population density</Abstract>
         <FeatureTypeStyle>
           <Transformation>
             <ogc:Function name="gs:Heatmap">
               <ogc:Function name="parameter">
                 <ogc:Literal>data</ogc:Literal>
               </ogc:Function>
               <ogc:Function name="parameter">
                 <ogc:Literal>weightAttr</ogc:Literal>
                 <ogc:Literal>pop_max</ogc:Literal>
               </ogc:Function>
               <ogc:Function name="parameter">
                 <ogc:Literal>radiusPixels</ogc:Literal>
                 <ogc:Function name="env">
                   <ogc:Literal>radius</ogc:Literal>
                   <ogc:Literal>5</ogc:Literal>
                 </ogc:Function>
               </ogc:Function>
               <ogc:Function name="parameter">
                 <ogc:Literal>pixelsPerCell</ogc:Literal>
                 <ogc:Literal>20</ogc:Literal>
               </ogc:Function>
               <ogc:Function name="parameter">
                 <ogc:Literal>outputBBOX</ogc:Literal>
                 <ogc:Function name="env">
                   <ogc:Literal>wms_bbox</ogc:Literal>
                 </ogc:Function>
               </ogc:Function>
               <ogc:Function name="parameter">
                 <ogc:Literal>outputWidth</ogc:Literal>
                 <ogc:Function name="env">
                   <ogc:Literal>wms_width</ogc:Literal>
                 </ogc:Function>
               </ogc:Function>
               <ogc:Function name="parameter">
                 <ogc:Literal>outputHeight</ogc:Literal>
                 <ogc:Function name="env">
                   <ogc:Literal>wms_height</ogc:Literal>
                 </ogc:Function>
               </ogc:Function>
             </ogc:Function>
           </Transformation>
          <Rule>
            <RasterSymbolizer>
            <!-- specify geometry attribute to pass validation -->
              <Geometry>
                <ogc:PropertyName>wkb_geometry</ogc:PropertyName></Geometry>
              <Opacity>0.6</Opacity>
              <ColorMap type="ramp" >
                <ColorMapEntry color="#FFFFFF" quantity="0" label="nodata"
                  opacity="0"/>
                <ColorMapEntry color="#FFFFFF" quantity="0.02" label="nodata"
                  opacity="0"/>
                <ColorMapEntry color="#4444FF" quantity=".1" label="nodata"/>
                <ColorMapEntry color="#FF0000" quantity=".5" label="values" />
                <ColorMapEntry color="#FFFF00" quantity="1.0" label="values" />
              </ColorMap>
            </RasterSymbolizer>
           </Rule>
         </FeatureTypeStyle>
       </UserStyle>
     </NamedLayer>
    </StyledLayerDescriptor>

Save the edited SLD as name "heatmap" with the SLD editor of the GeoServer admin utility.

  1. From the Layer - Publishing menu add "heatmap" as an alternative style for the populated places layer.
  2. Test with QGIS. WMS layer shows all the available styles. Add layer first with the default style "point" and a second time with style "heatmap". enter image description here
  3. Look at the result.enter image description here

The rest is fine tuning the heatmap parameters and color ramp by editing the SLD. After the SLD file is saved the next pan or zoom on the map will show the effect of the edit.

Related Question