/// <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];
            double   res    = (double)args[4];
            int      width  = (int)Math.Ceiling((int)args[1] * res);
            int      height = (int)Math.Ceiling((int)args[2] * res);
            int      size   = (int)Math.Ceiling((int)args[3] * res);
            List <ThreadSafeGradientStop> stops = (List <ThreadSafeGradientStop>)args[5];
            List <HeatPoint> points             = (List <HeatPoint>)args[6];
            OnImageComplete  onComplete         = (OnImageComplete)args[7];

            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;
            }
            PngEncoder ei = new PngEncoder(width, height);

            for (int idx = 0; idx < height; idx++)                  // Height (y)
            {
                int rowstart = ei.GetRowStart(idx);
                for (int jdx = 0; jdx < width; jdx++)                     // Width (x)
                {
                    Color c = InterpolateColor(output[idx * width + jdx] / (float)max, stops);
                    ei.SetPixelAtRowStart(jdx, rowstart, c.R, c.G, c.B, c.A);
                }
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                    e.Result = null;
                    output   = null;
                    ei       = null;
                    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
            e.Result = new object[] { ei, width, height, extent, onComplete };
        }
		/// <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];
			double res = (double)args[4];
			int width = (int)Math.Ceiling((int)args[1] * res);
			int height = (int)Math.Ceiling((int)args[2] * res);
			int size = (int)Math.Ceiling((int)args[3] * res);
			List<ThreadSafeGradientStop> stops = (List<ThreadSafeGradientStop>)args[5];
			List<HeatPoint> points = (List<HeatPoint>)args[6];
			OnImageComplete onComplete = (OnImageComplete)args[7];

			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; 
			PngEncoder ei = new PngEncoder(width, height);
			for (int idx = 0; idx < height; idx++)      // Height (y)
			{
				int rowstart = ei.GetRowStart(idx);
				for (int jdx = 0; jdx < width; jdx++)     // Width (x)
				{
					Color c = InterpolateColor(output[idx * width + jdx] / (float)max, stops);
					ei.SetPixelAtRowStart(jdx, rowstart, c.R, c.G, c.B, c.A);
				}
				if (worker.CancellationPending)
				{
					e.Cancel = true;
					e.Result = null;
					output = null;
					ei = null;
					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
			e.Result = new object[] { ei, width, height, extent, onComplete };
		}