Wednesday, May 2, 2012

Code for HeatMap.js and BingHeatMap.aspx file

Code for heatmap.js is taken from http://alastaira.wordpress.com

/*******************************************************************************
* Description:
* This JavaScript file provides an algorithm that can be used to add a heatmap
* overlay on a Bing Maps v7 control. The intensity and temperature palette
* of the heatmap are designed to be easily customisable.
*
* Requirements:
* The heatmap layer itself is created dynamically on the client-side using
* the HTML5 <canvas> element, and therefore requires a browser that supports
* this element. It has been tested on IE9, Firefox 3.6/4 and
* Chrome 10 browsers. If you can confirm whether it works on other browsers or
* not, I'd love to hear from you!

* Usage:
* The HeatMapLayer constructor requires:
* - A reference to a map object
* - An array or Microsoft.Maps.Location items
* - Optional parameters to customise the appearance of the layer
*  (Radius, Intensity, and ColourGradient), and a callback function
*
*/

var HeatMapLayer = function(map, locations, options) {

  /* Private Properties */
  var _map = map,
      _canvas,
      _temperaturemap,
      _locations = [];

  // Set default options
  var _options = {
    // Opacity at the centre of each heat point
    intensity: 0.5,

    // Affected radius of each heat point
    radius: 20,

    // Colour temperature gradient of the map
    colourgradient: {
      "0.00": 'rgba(255,0,255,20)',  // Magenta
      "0.25": 'rgba(0,0,255,40)',    // Blue
      "0.50": 'rgba(0,255,0,80)',    // Green
      "0.75": 'rgba(255,255,0,120)', // Yellow
      "1.00": 'rgba(255,0,0,150)'    // Red
    },

    // Callback function to be fired after heatmap layer has been redrawn
    callback: null
  };

  /* Private Methods */
  function _init() {

    // Create the canvas element and place it in the DOM
    _canvas = document.createElement('canvas');
    _canvas.id = 'heatmapcanvas'
    _canvas.style.position = 'relative';
    var _mapDiv = _map.getRootElement();
    _mapDiv.parentNode.lastChild.appendChild(_canvas);

    // Override defaults with any options passed in the constructor
    setOptions(options);

    // Load array of location data
    setPoints(locations);

    // Create a colour gradient from the suppied colourstops
    _temperaturemap = createColourGradient(_options.colourgradient);

    // Wire up the event handler to redraw heatmap canvas
    Microsoft.Maps.Events.addHandler(_map, 'viewchangestart', clearHeatMap);
    Microsoft.Maps.Events.addHandler(_map, 'viewchangeend', createHeatMap);

    delete _init;
  }

  /* Public Methods */
  function clearHeatMap() {
    var ctx = _canvas.getContext("2d");
    ctx.clearRect(0, 0, _canvas.width, _canvas.height)
  }

  function createColourGradient(colourstops) {
    var ctx = document.createElement('canvas').getContext('2d');
    var grd = ctx.createLinearGradient(0, 0, 256, 0);
    for (var c in colourstops) {
      grd.addColorStop(c, colourstops[c]);
    }
    ctx.fillStyle = grd;
    ctx.fillRect(0, 0, 256, 1);
    return ctx.getImageData(0, 0, 256, 1).data;
  }

  function colouriseHeatMap() {
    var ctx = _canvas.getContext("2d");
    // Colourise
    var dat = ctx.getImageData(0, 0, _canvas.width, _canvas.height);
    var pix = dat.data; // pix is a CanvasPixelArray containing height x width x 4 bytes of data (RGBA)
    for (var p = 0; p < pix.length; ) {
      var a = pix[p + 3] * 4; // get the alpha of this pixel
      if (a != 0) { // If there is any data to plot
        pix[p] = _temperaturemap[a]; // set the red value of the gradient that corresponds to this alpha
        pix[p + 1] = _temperaturemap[a + 1]; //set the green value based on alpha
        pix[p + 2] = _temperaturemap[a + 2]; //set the blue value based on alpha
      }
      p += 4; // Move on to the next pixel
    }
    ctx.putImageData(dat, 0, 0);
  }

  function setOptions(options) {
    for (attrname in options) {
      _options[attrname] = options[attrname];
    }
  }

  function setPoints(locations) {
    _locations = locations;
  }

  function createHeatMap() {
    // Ensure the canvas matches the current dimensions of the map
    // This also has the effect of resetting the canvas
    _canvas.height = _map.getHeight();
    _canvas.width = _map.getWidth();

    var ctx = _canvas.getContext("2d");

    // Create the Intensity Map
    for (var i = 0; i < _locations.length; i++) {
      var loc = _locations[i];

      // Convert lat/long to pixel location
      var pixloc = _map.tryLocationToPixel(loc, Microsoft.Maps.PixelReference.control);
      var x = pixloc.x;
      var y = pixloc.y;

      // Create radial gradient centred on this point
      var grd = ctx.createRadialGradient(x, y, 0, x, y, _options.radius);
      grd.addColorStop(0.0, 'rgba(0, 0, 0, ' + _options.intensity + ')');
      grd.addColorStop(1.0, 'transparent');

      // Draw the heatpoint onto the canvas
      ctx.fillStyle = grd;
      ctx.fillRect(x - _options.radius, y - _options.radius, x + _options.radius, y + _options.radius);
    }

    // Apply the specified colour gradient to the intensity map
    colouriseHeatMap();

    // Call the callback function, if specified
    if (_options.callback) {
      _options.callback();
    }

  }

  this.SetOptions = function(options) {
    setOptions(options);
  }

  this.SetPoints = function(points) {
    clearHeatMap();
    setPoints(points);
    createHeatMap();
  }

  this.Remove = function() {
    var _mapDiv = _map.getRootElement();
    _mapDiv.parentNode.lastChild.removeChild(_canvas);
  }

  // Call the initalisation routine
  _init();

};

BingHeatMap.aspx –
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="BingHeatMap.aspx.cs" Inherits="HeatMapGenerator.BingHeatMap" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Bing Maps Client Side Heat Map</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>
    <!-- Include the heatmap library -->
    <script type="text/javascript" src="Scripts/heatmap.js"></script>
    <script type="text/javascript">
           var map;
           var heatmapLayer;

        var coordinatesToMap = <%= coodinateString%>;


           function GetMap() {
               map = new Microsoft.Maps.Map(document.getElementById("divMap"),
           { credentials: "YourBing Map Key",
               center: new Microsoft.Maps.Location(36.592, -95.332),
               mapTypeId: Microsoft.Maps.MapTypeId.road,
               labelOverlay: Microsoft.Maps.LabelOverlay.hidden,
               zoom: 4
           });

               heatmapLayer = new HeatMapLayer(
           map,
           coordinatesToMap,
             { intensity: 0.25,
             radius: 25,
             colourgradient:
                {
                 0.0: '#FF0000',
                 0.1: '#FF0000',
                 0.2: '#FF0000',
                 0.3: '#FF0000',
                 0.4: '#FF0000',
                 0.5: '#FFFF00',
                 0.6: '#FFFF00',
                 0.7: '#90EE90',
                 0.8: '#9ACD32',
                 0.9: '#228B22',
                 1.0: '#008000'                    

//                 0.0: '#FF0000',
//                 0.1: '#FF0000',
//                 0.2: '#FF0000',
//                 0.3: '#FF0000',
//                 0.4: '#FF0000',
//                 0.5: '#FF0000',
//                 0.6: '#FFFF00',
//                 0.7: '#90EE90',
//                 0.8: '#9ACD32',
//                 0.9: '#228B22',
//                 1.0: '#008000' 
                }                     
             }
             );

           }
    </script>   
    <style type="text/css">
        .style1
        {
            width: 100%;
            height: 113%;
        }
    </style>
</head>
<body onload="GetMap();" style="height: 100%">
    <form id="form1" runat="server">
    <table border="1" style="width: 100%; height: 100%;">
       
        <tr>
            <td id="k" >
                <table style="height: 100%; width: 100%;">
                    <tr>
                        <td style="height: 100%; width: 70%;">
                            <div id="divMap" style="position:relative; width:840px; height:480px;"></div>
                           
                         </td>                      
                    </tr>
                </table>
            </td>
        </tr>
    </table>
    </form>
</body>
</html>

BingHeatMap.aspx.cs –
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;


namespace HeatMapGenerator
{
    public partial class BingHeatMap : System.Web.UI.Page
    {
        /// <summary>
        /// variable used for creating point to plot on bing map. This variable will be accessed in javascript code after finalising points to plot.
        /// </summary>
        public string coodinateString = "[";       

        /// <summary>
        /// Page load function used for downloading the input from blob and plotting points on Bing map
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {  
                string line = string.Empty;

                // Read the file and display it line by line.
                System.IO.StreamReader file = new System.IO.StreamReader(AppDomain.CurrentDomain.BaseDirectory + "Input/HeatMapInput.txt");               

                //create random number generator
                Random r = new Random();

                int pointCount = 1;
                while ((line = file.ReadLine()) != null)//read till end of file is reached
                {
                    //split the lne based on ',' delimiter and retrieve lattitude and longitude
                    string[] words = line.Split(new char[] { ',' });
                    double baseLat = Convert.ToDouble(words[0]);
                    words[1] = words[1].Substring(0, (words[1].Length - 1));
                    double baseLongi = Convert.ToDouble(words[1]);
                    double lat = baseLat;
                    double longi = baseLongi;

                    //loop to plot bing map points in the near vicinity
                    for (int i = 1; i <= pointCount + 6; i++)
                    {
                        coodinateString = coodinateString + "new Microsoft.Maps.Location(" + lat.ToString() + "," + longi.ToString() + "),";

                        #region point plotting combination 1
                        if (lat >= baseLat + 2)
                        {
                            lat = lat - r.Next(1, 3);
                        }
                        else
                        {
                            lat = lat + r.Next(0, 3);
                        }

                        if (longi >= baseLongi + 2)
                        {
                            longi = longi - r.Next(1, 3);
                        }
                        else
                        {
                            longi = longi + r.Next(0, 3);
                        }
                        #endregion

                        #region point plotting combination 2
                        //if (lat >= baseLat + 2)
                        //{
                        //    lat = lat - r.NextDouble() - 1;
                        //}
                        //else
                        //{
                        //    lat = lat + r.NextDouble() + 1;
                        //}

                        //if (longi >= baseLongi - 3)
                        //{
                        //    longi = longi - r.Next(1, 3) - 1;
                        //}
                        //else
                        //{
                        //    longi = longi + r.Next(0, 3) + 1;
                        //}
                        #endregion
                    }
                    pointCount = pointCount + 3;
                    //pointCount = pointCount + 1;
                }
                coodinateString = coodinateString + "]";

                //close the file streamreader
                file.Close();
               
            }
            catch (Exception ex)
            {
               
            }
        }
    }
}

Tuesday, April 17, 2012

Windows Azure Blob - Unable to read data from the transport connection: The connection was closed

I had file of 1.5GB uploaded on Azure Blob Storage. My supervisor asked me to write a simple console application to download this huge file of 1.5 GB from Blob storage and send to the client. As my client don’t wanted to have complexities involved in using Windows Azure Cloud Storage Explorer (he never wants any type of complexities other than Notepad... anyways) I started with Console Application with simple code to download the blob.
I added the reference of Microsoft.WindowsAzure.ServiceRuntime.dll and Microsoft.WindowsAzure.StorageClient.dll in my application. Then wrote following code in Main method –
CloudBlobClient blobClient = new CloudBlobClient("https://myStorageService.blob.core.windows.net/");
           
CloudBlob blob = blobClient.GetBlobReference("mycontainer/job2/part-00000");

try
{
            blob.DownloadToFile(AppDomain.CurrentDomain.BaseDirectory + "HeatMapperInput.txt", options);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine("=------------------------------------" + ex.StackTrace);
Console.ReadLine();
}

I ran the console application. 28MB out of 1.5 GB of file was downloaded and suddently received following error –
“Unable to read data from the transport connection: The connection was closed.”
It was really strange and I had received this error for the first time. After digging in Blob Storage I found this –