7

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.

3

Mapserver can do it with the current development version which will be soon released as v7.0. How it works is best documented here: http://mapserver.org/development/rfc/ms-rfc-108.html

For testing the heatmap feature install MapServer 6.5-dev into your environment. Next download "pnts" shapefile (.shp, .shx, .dbf, and .prj) from github https://github.com/mapserver/msautotest/tree/master/gdal/data. Store the shapefile somewhere in your disk. Save the following mapfile as "heatmap.map" (slightly edited from https://github.com/mapserver/msautotest/blob/master/gdal/heat.map) into the same directory:

map
size 1000 500
extent -180 -90 180 90
name "test heat"
imagetype "png"
units dd
web
metadata
"ows_srs" "epsg:4326 epsg:3857 epsg:900913"
"ows_enable_request" "*"
end
end
projection
"+init=epsg:4326"
end
CONFIG "MS_ERRORFILE" "stderr"
layer
name "heatmap"
type raster
connectiontype kerneldensity
connection "points"
status on
processing "RANGE_COLORSPACE=%color%"
processing "KERNELDENSITY_RADIUS=%radius%"
processing "KERNELDENSITY_COMPUTE_BORDERS=%border%"
processing "KERNELDENSITY_NORMALIZATION=%norm%"
offsite 0 0 0
SCALETOKEN
NAME "%radius%"
VALUES
"0" "15"
"255000000" "20"
END
END
SCALETOKEN
NAME "%border%"
VALUES
"0" "ON"
"255000000" "OFF"
END
END
SCALETOKEN
NAME "%norm%"
VALUES
"0" "AUTO"
"255000000" "30"
END
END
SCALETOKEN
NAME "%color%"
VALUES
"0" "HSL"
"255000000" "RGB"
END
END
class
style
COLORRANGE "#0000ff00" "#0000ffff"
DATARANGE 0 32
end
style
COLORRANGE "#0000ffff" "#ff0000ff"
DATARANGE 32 255
end
end
end
symbol
name "circle"
type ellipse
points 1 1 end
end
layer
name "points"
status on
type POINT
data "pnts.shp"
projection
"+init=epsg:4326"
end
CLASS
MAXSCALE 255000000
STYLE
SIZE [VAL]
END
END
CLASS
MAXSCALE 265000000
STYLE
SIZE 0.1
END
END
CLASS
MAXSCALE 275000000
EXPRESSION ([VAL]>1)
STYLE
SIZE 1
END
END
CLASS
MAXSCALE 275000000
STYLE
SIZE 2
END
END
end
end

The following request, as edited to suit your installation, should show a heatmap on your browser:

http://localhost/cgi-bin/mapserv.exe?map=/ms4w/heatmap.map&mode=map&layers=heatmap

Heatmap is also available as WMS service at URL

http://localhost/cgi-bin/mapserv.exe?map=c:\ms4w\heatmap.map

Unfortunately I can't add a nice screen capture from my own computer here because I could not make it to work on Windows. Hopefully you have Linux and better luck. However, you can check some expected results from https://github.com/mapserver/msautotest/tree/master/gdal/expected, for example this https://github.com/mapserver/msautotest/blob/master/gdal/expected/heatmap-r20-noborder-fixednorm-rgb-expression.png

When you have managed to get the demo heatmap to work you will only need to edit the mapfile to read "points" layer from PostGIS instead of a shapefile and, if needed, to edit projection and extents to suit your data.

  • im using the latest 6.4.1 so according to this it cannot be done yet :-(. thanks allot. any idea on v7.0 release date? – dowi Jun 19 '14 at 13:03
  • Before FOSS4G 2014 in September 2014.foss4g.org – user30184 Jun 19 '14 at 13:13
  • FOSS4G has passed yet mapserver 7 is not out :-( – dowi Sep 22 '14 at 20:23
  • Nightly builds of MapServer-devel are available from gisinternals.com/sdk. – user30184 Sep 22 '14 at 20:39
11
+50

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.

  • How can I create a heatmap from points when I have no useful weightAttr field in my input data? I just want to have a point density map. – Stefan Nov 15 '15 at 11:07
  • @Stefan perhaps your weighting should be a nearest neighbour distance value, inverted – tomfumb Mar 8 '17 at 23:07
6

Thinking that you need heat maps rendered on the fly, I would go for these options instead:

Some on-the-fly examples:

  • thanks! but if there are a lot of points i think it'd be better done on the server, right? – dowi Sep 23 '14 at 11:28
  • 1
    @dowi you're welcome =) sure! server side is the best when there are a lot of points, in any case you can use WMS and pass that with mapserver/geoserver to openlayers/leaflet. Using strategy cluster you can speed things up. – Gery Sep 23 '14 at 12:07
  • well, i'll be able to do that when it will be available in mapserver (next version V7) – dowi Sep 23 '14 at 13:35
2

Geoserver can render a heatmap from vector points using Rendering Transformations. For this feature to work, you will have to install WPS Extension (but WPS service doesn't need to be enabled).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.