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)
            {
               
            }
        }
    }
}

No comments:

Post a Comment