/// <summary>
/// Handles the DoWork event of the renderThread control. This is where we
/// render the heatmap outside the UI thread.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance
/// containing the event data.</param>
private void renderThread_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = (BackgroundWorker)sender;
object[] args = (object[])e.Argument;
Envelope extent = (Envelope)args[0];
int width = (int)args[1];
int height = (int)args[2];
int size = (int)args[3];
List <ThreadSafeGradientStop> stops = (List <ThreadSafeGradientStop>)args[4];
List <HeatPoint> points = (List <HeatPoint>)args[5];
OnImageComplete onComplete = (OnImageComplete)args[6];
size = size * 2 + 1;
ushort[] matrix = CreateDistanceMatrix(size);
int[] output = new int[width * height];
foreach (HeatPoint p in points)
{
AddPoint(matrix, size, p.X, p.Y, output, width);
if (worker.CancellationPending)
{
e.Cancel = true;
e.Result = null;
return;
}
}
matrix = null;
int max = 0;
foreach (int val in output) //find max - used for scaling the intensity
{
if (max < val)
{
max = val;
}
}
//If we only have single points in the view, don't show them with too much intensity.
if (max < 2)
{
max = 2;
}
#if SILVERLIGHT
PngEncoder ei = new PngEncoder(width, height);
#else
int[] pixels = new int[height * width];
#endif
for (int idx = 0; idx < height; idx++) // Height (y)
{
#if SILVERLIGHT
int rowstart = ei.GetRowStart(idx);
#endif
for (int jdx = 0; jdx < width; jdx++) // Width (x)
{
Color c = InterpolateColor(output[idx * width + jdx] / (float)max, stops);
#if SILVERLIGHT
ei.SetPixelAtRowStart(jdx, rowstart, c.R, c.G, c.B, c.A);
#else
int color = (c.A << 24) + (c.R << 16) + (c.G << 8) + c.B;
pixels[idx * width + jdx] = color;
#endif
}
if (worker.CancellationPending)
{
e.Cancel = true;
e.Result = null;
output = null;
#if SILVERLIGHT
ei = null;
#else
pixels = null;
#endif
return;
}
//Raise the progress event for each line rendered
worker.ReportProgress((idx + 1) * 100 / height);
}
stops.Clear();
output = null;
// Get stream and set image source
#if SILVERLIGHT
e.Result = new object[] { ei, width, height, extent, onComplete };
#else
e.Result = new object[] { pixels, width, height, extent, onComplete };
#endif
}