To support hot-spot within the new VE TEmplate II - use must implement IPreDrawHandler. For example:
using System;
using System.Drawing;
using ISC.MapDotNetServer.Common;
using ISC.MapDotNetServer.Controls;
using ISC.MapDotNetServer.Controls.VirtualEarth;
using ISC.MapDotNetServer.VETemplate.Handler;
public class HotSpotPreDrawHandler : IPreDrawHandler
{
/// <summary>
/// Takes a MapControlBridge just prior to drawing a tile.
/// Here you can make modifications to the MapRequest object for custom tile drawing.
/// This is useful in creating overlays on the tile itself (e.g. hot-spot)
/// </summary>
/// <param name="mcb">MapControlBridge.</param>
/// <param name="rp">Tile request processor.</param>
public bool DrawSetup(
MapControlBridge mcb,
RequestProcessor rp)
{
// use a bleed so tiles align better and feature near the edge do not get clipped
// 1.0625 will add an 8-pixel bleed around the tile
mcb.MapRequest.BleedRatio = 1.0625;
// add hotspot layer - "traffic crashes" is the name of the layer we want to show a denisty map for
Layer layer = mcb.MapRequest.Map.GetLayerByID("Traffic Crashes");
if (layer != null)
{
AddHotSpot(mcb, layer);
}
// continue processing tile in RequestProcessor
return true;
}
/// <summary>
/// Add a crash hot-spot layer
/// </summary>
/// <param name="mcb">MapControlBridge.</param>
/// <param name="layer">The layer to density map.</param>
public void AddHotSpot(MapControlBridge mcb, Layer layer)
{
// get map request from MapControlBridge
MapRequest request = mcb.MapRequest;
// computational envelope must be in the resultant map units (for VE this is mercator)
// since we are tiling, expand envelope to capture adjacent tile data so tile mozaic is correct
// otherwise you will not pick up thermal points from nearby tiles and the mozaic will show tile boundaries
// here we expand the hot spot computational envelope by a 33% margin all the way around
// if we need look further into the adjacent tiles, reduce the denominator (3.0)
Envelope cEnv = request.RequestEnvelope.Clone();
cEnv.Expand(cEnv.MagX / 3.0);
// setup query envelope - the map is in mercator but crash data is in WGS84 which we are querying
Envelope qEnv = Tiles.ConvertMercEnvelopeToDegrees(cEnv);
// this is an instance of the hot spot rendering engine
HotSpotHelper helper = new HotSpotHelper();
// setup an appropriate looking color matrix
// you can tweak this to get different color schemes - note the first integer in each set of 4 is the alpha
// because we are using Virtual Earth tile opacity, we want an opaque except for the very edge
helper.ARGBColorMatrix = new int[][] {
new int[] {0,0,0,0},
new int[] {128,0,0,255},
new int[] {255,0,0,224},
new int[] {255,0,0,192},
new int[] {255,32,0,160},
new int[] {255,64,0,128},
new int[] {255,128,0,64},
new int[] {255,160,0,32},
new int[] {255,192,0,0},
new int[] {255,224,0,0},
new int[] {255,255,0,0}
};
// this lets the hot spot helper know what projection we are projecting the source data to to perform
// computations on
// 50000 happens to be the SRID of the VE mercator projection as defined in the spatial database used for this example.
// Note that you will need to add this defiition as it is not standard
// MDNS versions prior to 6.5
/*
helper.ProjectionCoordSys = new CoordSys();
helper.ProjectionCoordSys.ProjectionID = "50000";
*/
// As of 6.5
ProjCoordSys cs = new ProjCoordSys();
cs.ID = 50000;
helper.ProjectionCoordSys = cs;
// compute a rough max magnitude based on current tile mapscale
// we must use absolute max-value instead of auto-computed since we are tiling
// since each tile may have a different density, we can not auto-compute the max (the tile mozaic will not line up)
// note in this case max value changes with changes in VE zoom level and the computation is not linear
double maxValue = Math.Pow(cEnv.MagX, 1.125) / 100.0;
// render hotspot map
Bitmap bmp = helper.GenerateThermalPNG(mcb,
layer, // layer to analyze
qEnv, // query envelope in datasource map units
cEnv, // computational envelope in VE Mercator
null, // optional where clause
null, // you can sum an attribute column, null means count features only
HotSpotHelper.NegativeSumBehavior.Discard, // how to handle negative sum (previous field must be used)
64, // number of grid cells across (cells deep are computed from envelope)
5, // filter size in grid cells
2, // filter radius in grid cells
0, // minimum sample value (you can increase this to set a rendering threshold)
maxValue, // maximum value per grid cell (Double.NaN will use auto-compute)
32); // 0 - max color depth or a positive integrer limiting the max number of colors displayed
// if the hot spot renderer returned a bitmap
if (bmp != null)
{
// add it as a map request overlay
request.Overlay = new OverlayPNG();
request.Overlay.OverlayEnvelope = cEnv;
request.Overlay.LoadPNG32(bmp);
}
else
{
// clear the overlay in the map request
request.Overlay = null;
}
}
}