Home | Products | Issue Tracker | FAQ | Download | |
Date: | 2014/01 |
---|---|
Author: | Thomas Bonfort |
Contact: | tbonfort@terriscope.fr |
Author: | Mathieu Coudert |
Contact: | mathieu.coudert@gmail.com |
Status: | Adopted |
Version: | MapServer 7.0 |
Last Updated: | 2014/02/13 |
Heatmaps are a popular method to represent sparse data on a regular raster grid, where each pixel on the grid is influenced inversely to its distance to each sample of the sparse dataset. They are usually represented with a color-ramp where the hue encodes the density of the data sample, optionally along with the intensity of an attribute. The “heatmap” term itself is used with varying meanings; in the context of this RFC, we will be using it to reference Kernel Density Estimation maps.
This RFC proposes the addition of a vector to raster processing pipeline that will transform an input vector source into a 1-band 8-bit raster that can then be styled with mapserver’s native raster handling.
Adding a heatmap layer requires the following major changes to the mapserver library:
The vector to raster pipeline is called from inside mapserver’s high-level raster handling when handling a layer with CONNECTIONTYPE KERNELDENSITY. The output of this operation is a handle to a GDAL datasource that can then be processed normally by the remainder of the raster handling code.
While a more generic API could be designed for handling this vector-to-raster pipeline, the initial implementation will branch off to a heatmap specific handler. Reflections on the design of such an API can be delayed until the need for other vector-to-raster transformations arises, designing one for the scope of this RFC seems like premature over-engineering.
The heatmap vector-to-raster takes the following parameters:
By default, each feature is assigned a weight of 1.0, and the resulting heatmap will represent the spatial density of the vector features. If this is not the desired behavior, different weights can be applied on a feature by feature basis by using regular CLASS/STYLE syntax on the source vector layer. The weight used will be read from the SIZE value of the matched STYLE. Standard EXPRESSION and MIN/MAXSCALEDENOM apply; if a feature results in no matching CLASS and/or STYLE, it is ignored and discarded from the resulting heatmap. The examples at the end of this RFC give some examples as to how this can be achieved.
The features added in MS RFC 6: Color Range Mapping of Continuous Feature Values for vector features, and since extended to support raster layers, will be extended in order to support more complex color ramps. Note that these additions will apply to all raster classifications, not only for heatmap layers.
Support for multiple stops : The actual support for ranges for raster layers is limited to a single COLORRANGE/DATARANGE. We will support multiple ranges in order to allow multiple color stops, and will also account for optional alpha values. The following example creates a ramp ranging from fully transparent blue to blue for values between 0 and 32, then blue to red for values ranging from 32 to 255.
class
style
COLORRANGE "#0000ff00" "#0000ffff"
DATARANGE 0 32
end
style
COLORRANGE "#0000ffff" "#ff0000ff"
DATARANGE 32 255
end
end
注解
A single style block will be used for each pixel value. It is up to the user to ensure that the supplied DATARANGEs span 0 to 255 with no overlap, and that the chosen COLORRANGE stops are continous from one stop to the next.
PROCESSING RANGE_COLORSPACE=RGB|HSL: The current RANGE support interpolates colors between stops in RGB space, which usually results in washed out colors. The interpolation can be done in HSL space which usually results in wanted output for heatmaps.
In order to easily adapt kernel density parameters depending on the actual map scaledenom, the implementation of MS RFC 86: Scale-dependant String Substitutions will be extended to also replace tokens inside PROCESSING keys. See the examples at the end of this RFC to see how this can be used in the context of heatmaps.
None expected. The behavior of the range support in RGB space is to extend the color interpolation outside the supplied DATARANGE (for DATARANGEs that do not span 0-255), whereas the behavior for HSL interpolation is to treat such values as NODATA. Given that this behavior hasn’t been officially formalized, it might be wanted to modify the RGB interpolation so it behaves identically.
The gaussian filter allocates two temporary float* bitmaps of the size of the requested image, optionally expanded in case border computation has been activated or not. For very large image requests this may result in large allocations. The cost of the gaussian filtering is also dependent on the chosen radius,
Options enabling tiling-compatible output have been added and must be used when tiling. Failure to do so will result in tiles that are not consistent from one another.
map
size 1000 500
extent -180 -90 180 90
name "test heat"
imagetype "png"
web
metadata
"ows_srs" "epsg:4326 epsg:3857 epsg:900913"
"ows_enable_request" "*"
end
end
projection
"+init=epsg:4326"
end
layer
name "heatmap"
type raster
connectiontype kerneldensity
connection "points"
status on
processing "RANGE_COLORSPACE=HSL"
processing "KERNELDENSITY_RADIUS=20"
processing "KERNELDENSITY_ATTRIBUTE=VAL"
processing "KERNELDENSITY_COMPUTE_BORDERS=ON"
processing "KERNELDENSITY_NORMALIZATION=AUTO"
offsite 0 0 0
class
style
COLORRANGE "#0000ff00" "#0000ffff"
DATARANGE 0 32
end
style
COLORRANGE "#0000ffff" "#ff0000ff"
DATARANGE 32 255
end
end
end
layer
name "points"
status on
type POINT
data "pnts.shp"
end
end
With the addition of MS RFC 86: Scale-dependant String Substitutions PROCESSING scaletokens, the kernel radius can be set dynamically depending on the scale. Note that any other PROCESSING key can be updated by the same method. In the following example, the kernel radius will be of 50 pixels for scales 1/1 to 1/25000000, and of 10 pixels for scales 1/25000000 and smaller:
layer
name "heatmap"
...
processing "KERNELDENSITY_RADIUS=%radius%"
SCALETOKEN
NAME "%radius%"
VALUES
"0" "50"
"25000000" "10"
END
END
...
end
Different weights can be applied by using CLASS->STYLE->SIZE syntax on the source vector layer to apply a non default weight to each sample:
Weight read from a feature attribute:
layer
name "points"
status on
type POINT
data "pnts.shp"
class
style
size [attribute]
end
end
end
Weight read from a non numeric attribute:
layer
name "points"
status on
type POINT
data "pnts.shp"
classitem "risk"
class
expression "high"
style
size 5
end
end
class
expression "medium"
style
size 3
end
end
class
expression "low"
style
size 1
end
end
end
+1 from ThomasB, TomK, DanielM, SteveW, TamaS, StephanM, MichaelS, PerryN, JeffM, SteveL and YewondwossenA