Home ยป BlogEngine.NET

BlogEngine.NET HeatMaps: Part II

2 Mar 2009 7:27 PM 13 Comments Bookmark and Share kick it on DotNetKicks.com

So, in this final part I’ll explain the HeatMap Generator control.  I recommend you read Part I if you haven’t yet.  With this piece again I created a control that was placed on my MasterPage for my theme.  I wrapped the control around an ‘if’ statement so it only rendered when I was logged in.

 HeatMap

   1: <%@ Register src="~/User controls/ThirteenSides/HeatMapGenerator.ascx" TagName="HeatMapGenerator" TagPrefix="ucHMG" %>
   2:  
   3: <% if (Page.User.Identity.IsAuthenticated)
   4:    { %>
   5:         <!-- Alt+W(Show) and Alt+Q (Hide) -->
   6:         <ucHMG:HeatMapGenerator ID="ucHeatMapGenerator" runat="server" 
   7:                 ImageName="HeatMap.png"
   8:                 HideHeatMapKey="81" 
   9:                 ShowHeatMapKey="87" />
  10: <% } %>              

 

 

This control exposes a few properties to allow the user (me) to show or hide the control panel.  This control panel is just a couple of basic Html controls to filter the date(s), etc.  I didn’t spend more than 5 minutes creating the look’n feel here.  At this moment, I feel ashamed of the use of tables here but I digress, it was done very quickly.

 

HeatMapGenerator.ascx

   1: <%@ Control Language="C#" AutoEventWireup="true" CodeFile="HeatMapGenerator.ascx.cs" Inherits="HeatMapGenerator" %>
   2: <%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxtoolkit" %>
   3:  
   4: <style type="text/css">
   5:     .HeatMapOptions_hide {
   6:         display: none;
   7:         float: right;
   8:         position: relative;
   9:         top: 0px;
  10:         width: 277px;
  11:     }
  12:     .HeatMapOptions_show {
  13:         background-color: Silver;
  14:         border-color: #42718B;
  15:         border-style: solid;
  16:         border-width: thin;
  17:         color: #000000;
  18:         float: right;
  19:         font-family: Arial, Helvetica, sans-serif;
  20:         font-size: 11px;
  21:         margin: 0px 0px 0px 0px;
  22:         position: relative;
  23:         top: 0px;
  24:         width: 277px;
  25:         z-index: 1000;
  26:     }
  27:     .HeatMapImage_hide {
  28:         display: none;
  29:         left: 0px;
  30:         position: absolute;
  31:         top: 0px;
  32:         z-index: 999;
  33:     }
  34:     .HeatMapImage_show {
  35:         left: 0px;
  36:         position: absolute;
  37:         top: 0px;
  38:         z-index: 999;
  39:     }
  40:     #HMO_Outer {
  41:         background-color: White;
  42:         height: 200px;
  43:         width: 300px;
  44:     }
  45:     #HMO_Inner {
  46:         background-color: White;
  47:         height: 200px;
  48:         left: 0px;
  49:         position: relative;
  50:         top: 0px;
  51:         width: 277px;
  52:     }
  53:     .HMOCalendar .ajax__calendar_container {
  54:         border: 1px solid #646464;
  55:         background-color: lemonchiffon;
  56:         color: red;
  57:     }
  58:     .HMOCalendar .ajax__calendar_other .ajax__calendar_day, .HMOCalendar .ajax__calendar_other .ajax__calendar_year {
  59:         color: black;
  60:     }
  61:     .HMOCalendar .ajax__calendar_hover .ajax__calendar_day, .HMOCalendar .ajax__calendar_hover .ajax__calendar_month, .HMOCalendar .ajax__calendar_hover .ajax__calendar_year {
  62:         color: black;
  63:     }
  64:     .HMOCalendar .ajax__calendar_active .ajax__calendar_day, .HMOCalendar .ajax__calendar_active .ajax__calendar_month, .HMOCalendar .ajax__calendar_active .ajax__calendar_year {
  65:         color: black;
  66:         font-weight: bold;
  67:     }
  68: </style>
  69:  
  70: <script type="text/javascript" language="javascript">
  71:  
  72:     ///////////////////////////////////////////////////
  73:     // Internal Variables
  74:     ///////////////////////////////////////////////////
  75:     var IE = document.all ? true : false
  76:     if (!IE) document.captureEvents(Event.MOUSEUP)
  77:  
  78:     document.onkeydown = checkKeycode
  79:     ///////////////////////////////////////////////////
  80:  
  81:     ///////////////////////////////////////////////////
  82:     // Check to show Options DIV and Generate/Show HeatMap IMAGE
  83:     ///////////////////////////////////////////////////
  84:     function checkKeycode(e)
  85:     {
  86:         var keycode;
  87:         if (window.event)
  88:             keycode = window.event.keyCode;
  89:         else if (e)
  90:             keycode = e.which;
  91:         var e = e || window.event;
  92:  
  93:         if (keycode == HMG_SHOW_HeatMap_KEY && e.altKey)
  94:         {
  95:             // Show HeatMap Options DIV
  96:             document.getElementById($get('<%= this.pnlHeatMapOptions.ClientID %>').id).className = 'HeatMapOptions_show';
  97:         }
  98:         else if (keycode == HMG_HIDE_HeatMap_KEY && e.altKey)
  99:         {
 100:             // Hide both HeatMap Options DIV and IMAGE 
 101:             document.getElementById($get('<%= this.pnlHeatMapOptions.ClientID %>').id).className = 'HeatMapOptions_hide';
 102:             document.getElementById($get('<%= this.pnlHeatMap.ClientID %>').id).style.display = 'none';
 103:         }
 104:         return true;
 105:     }
 106:     function HideHMO()
 107:     {
 108:         if (document.getElementById($get('<%= this.HMO_Outer.ClientID %>').id).style.display == "none")
 109:             document.getElementById($get('<%= this.HMO_Outer.ClientID %>').id).style.display = "";
 110:         else
 111:             document.getElementById($get('<%= this.HMO_Outer.ClientID %>').id).style.display = "none"
 112:     }
 113: </script>
 114:  
 115: <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
 116:     <ContentTemplate>
 117:         
 118:         <asp:Panel ID="pnlHeatMapOptions" runat="server" CssClass="HeatMapOptions_hide">
 119:             <a href="#" onclick="HideHMO()">HeatMap Options</a>
 120:             <div id="HMO_Outer" runat="server" style="display: none;">
 121:                 <div id="HMO_Inner">
 122:                     <table width="100%" cellpadding="0" cellspacing="0">
 123:                         <tr>
 124:                             <td rowspan="12">
 125:                                 &nbsp;&nbsp;&nbsp;
 126:                             </td>
 127:                         </tr>
 128:                         <tr>
 129:                             <td>
 130:                                 &nbsp;
 131:                             </td>
 132:                         </tr>
 133:                         <tr>
 134:                             <td>
 135:                                 <asp:CheckBox ID="chkAllDates" runat="server" Checked="true" Text="All Dates" />
 136:                             </td>
 137:                         </tr>
 138:                         <tr>
 139:                             <td>
 140:                                 &nbsp;
 141:                             </td>
 142:                         </tr>
 143:                         <tr>
 144:                             <td>
 145:                                 <asp:CheckBox ID="chkMonth" runat="server" Checked="false" Text="Current Month" />
 146:                             </td>
 147:                         </tr>
 148:                         <tr>
 149:                             <td>
 150:                                 &nbsp;
 151:                             </td>
 152:                         </tr>
 153:                         <tr>
 154:                             <td>
 155:                                 <asp:Label ID="lblDateFrom" runat="server" Text="From:" />
 156:                                 <asp:TextBox ID="txtDateFrom" runat="server" autocomplete="off" />
 157:                                 <ajaxtoolkit:calendarextender id="txtDateFromEX" runat="server" targetcontrolid="txtDateFrom"
 158:                                     cssclass="HMOCalendar" format="MMMM d, yyyy" />
 159:                             </td>
 160:                         </tr>
 161:                         <tr>
 162:                             <td>
 163:                                 &nbsp;
 164:                             </td>
 165:                         </tr>
 166:                         <tr>
 167:                             <td>
 168:                                 <asp:Label ID="lblDateTo" runat="server" Text="To:" />
 169:                                 <asp:TextBox ID="txtDateTo" runat="server" />
 170:                                 <ajaxtoolkit:calendarextender id="txtDateToEx" runat="server" targetcontrolid="txtDateTo"
 171:                                     cssclass="HMOCalendar" format="MMMM d, yyyy" />
 172:                             </td>
 173:                         </tr>
 174:                         <tr>
 175:                             <td style="text-align: right">
 176:                                 <asp:Button ID="Generate" runat="server" Text="Generate" OnClick="Generate_Click" />
 177:                                 &nbsp;&nbsp;
 178:                             </td>
 179:                         </tr>
 180:                     </table>
 181:                 </div>
 182:             </div>
 183:         </asp:Panel>
 184:         <ajaxtoolkit:dragpanelextender id="pnlHeatMapOptionsExt" runat="server" targetcontrolid="pnlHeatMapOptions"
 185:             draghandleid="pnlHeatMapOptions" />
 186:         <asp:Panel ID="pnlHeatMap" runat="server" CssClass="HeatMapImage_hide">
 187:             <asp:Image ID="imgHeatMap" runat="server" />
 188:         </asp:Panel>
 189:         
 190:     </ContentTemplate>
 191:     <Triggers>
 192:         <asp:PostBackTrigger ControlID="Generate" />
 193:     </Triggers>
 194: </asp:UpdatePanel>

 

HeatMapGenerator.cs

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Web;
   5: using System.Web.UI;
   6: using System.Web.UI.WebControls;
   7: using System.ComponentModel;
   8: using BlogEngine.Core;
   9:  
  10: public partial class HeatMapGenerator : System.Web.UI.UserControl
  11: {
  12:     #region Properties
  13:     [Category("HeatMap")]
  14:     [Description("String - ACSII key code to hide HeatMap image.")]
  15:     public string HideHeatMapKey { get; set; }
  16:     [Category("HeatMap")]
  17:     [Description("String - ACSII key code to show HeatMap image.")]
  18:     public string ShowHeatMapKey { get; set; }
  19:     [Category("HeatMap")]
  20:     [Description("String - Name of HeatMap image, i.e. HeatMap.png")]
  21:     public string ImageName { get; set; }
  22:     #endregion
  23:     
  24:     protected void Page_Load(object sender, EventArgs e)
  25:     {
  26:         // HeatMap Config Options Script
  27:         string ss = @"var HMG_SHOW_HeatMap_KEY = " + ShowHeatMapKey + ";" + System.Environment.NewLine;
  28:         ss += @"var HMG_HIDE_HeatMap_KEY = " + HideHeatMapKey + ";" + System.Environment.NewLine;
  29:         Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "HeatMap_Generator_Config", ss, true);
  30:     }
  31:  
  32:     protected void Generate_Click(object sende, EventArgs e)
  33:     {
  34:         DateTime dteFrom = DateTime.Parse("1/1/1900");
  35:         DateTime dteTo = DateTime.Parse("1/1/1900");
  36:  
  37:         string pageName = System.IO.Path.GetFileName(HttpContext.Current.Request.RawUrl);
  38:  
  39:         int transparency = 25;
  40:  
  41:         if (chkAllDates.Checked)
  42:             HeatMap.GenerateHeatMap(pageName, true, dteFrom, dteTo, transparency, ImageName);
  43:         else if (chkMonth.Checked)
  44:         {
  45:             dteFrom = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
  46:             dteTo = dteFrom.AddMonths(1).AddSeconds(-1);
  47:  
  48:             HeatMap.GenerateHeatMap(pageName, false, dteFrom, dteTo, transparency, ImageName);
  49:         }
  50:         else
  51:         {
  52:             dteFrom = DateTime.Parse(txtDateFrom.Text);
  53:             dteTo = DateTime.Parse(txtDateTo.Text);
  54:  
  55:             HeatMap.GenerateHeatMap(pageName, false, dteFrom, dteTo, transparency, ImageName);
  56:         }
  57:  
  58:         // Show Generated HeatMap Image
  59:         // Including the time (in ticks) in the response parameter will always
  60:         // force the browser to display the latest image (i.e. no caching !!!)
  61:  
  62:         string query = HttpContext.Current.Request.QueryString["theme"];
  63:         string theme = !string.IsNullOrEmpty(query) ? query : BlogSettings.Instance.Theme;
  64:         string path = string.Concat(Utils.AbsoluteWebRoot, "themes/", theme, "/images/Heatmap/" + ImageName);
  65:  
  66:         this.imgHeatMap.ImageUrl = path + "?" + DateTime.Now.Ticks.ToString();
  67:         this.pnlHeatMap.CssClass = "HeatMapImage_show";
  68:         this.pnlHeatMapOptions.CssClass = "HeatMapOptions_show";
  69:     }
  70: }

 

The purpose of the code-behind is simple.  Just pass the user parameters to the HeatMap business class.  I completely separated the Collector and Generator code due to the need to have the Generator located on a completely separate web server.

 

HeatMap Generator Business Logic

Now, I’m not much of a graphics artist nor a Mathematician.  I left most of this to a good friend with the premise that I’d learn some of it.  All I knew from researching other solutions was that I wanted regions of my screen coloured-coded based on the number of mouse clicks each area received.  Red being the hottest zone, Blue the coldest.  Some of the formulas in this code I don’t pretend to fully understand but their overall usage is straight-forward.

 

The basic steps of this class is to read in a List<HeatMapClick> objects from the HeatMap.xml file (Part I) and create a transparent PNG file on the file system.  I used Linq-Xml for this as its just such a beautiful way to code.  I refuse to remember the “old school” xml programming practices.

 

Have a look at the code, I tried to comment the basics of it at least.

 

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Configuration;
   4: using System.Drawing;
   5: using System.IO;
   6: using System.Linq;
   7: using System.Web;
   8: using System.Xml.Linq;
   9:  
  10: using BlogEngine.Core;
  11:  
  12: public class HeatMap
  13: {
  14:     #region Variables
  15:     private const int RADIUS = 8;               // Radius of click blob in image
  16:     private static int[][] _coordsArray;        // Contains the # of Clicks for each Coordinate pair
  17:     private static int _maxClick = 0;           // Max # Clicks anywhwere
  18:     private static int _width = 0;
  19:     private static int _height = 0;
  20:     private static List<HeatMapClick> _clicks;  // Actual data retrieved from XML data source
  21:  
  22:     private static string _pageName;
  23:     private static bool _allDates = true;
  24:     private static DateTime _from = DateTime.MinValue;
  25:     private static DateTime _to = DateTime.MinValue;
  26:     private static int _transparency;
  27:     private static string _imageName;           // FileName of Generated HeatMap Image
  28:     #endregion
  29:  
  30:     public static void GenerateHeatMap(string pageName, 
  31:                                        bool allDates, 
  32:                                        DateTime from, 
  33:                                        DateTime to, 
  34:                                        int transparency,
  35:                                        string imageName)
  36:     {
  37:         _allDates = allDates;
  38:         _from = from;
  39:         _to = to;
  40:         _transparency = transparency;
  41:         _pageName = pageName;
  42:         _imageName = imageName;
  43:  
  44:         Generate();
  45:     }
  46:  
  47:     #region Internal
  48:     private static int[] ColourSequence(long value)
  49:     {
  50:         // _transparency is a percentage value to establish the base colour
  51:         // 100% = 235 for rgb
  52:         // 0%   = completely transparent as shown in the alpha
  53:  
  54:  
  55:         int baseColour = 235;
  56:         int alpha = 0;
  57:         int red = 1;
  58:         int green = 2;
  59:         int blue = 3;
  60:  
  61:         // the alpha is the transparency
  62:         int[] argb = new int[4];
  63:         argb[alpha] = (int)((Double)235 * (Double)((Double)_transparency / 100));
  64:  
  65:         if (value == 0)
  66:         {
  67:             argb[red] = baseColour;
  68:             argb[green] = baseColour;
  69:             argb[blue] = baseColour;
  70:         }
  71:         else if (0 < value && value < 255) // from white to blue (255 colours)
  72:         {
  73:             argb[red] = (int)(baseColour - value);
  74:             argb[green] = (int)(baseColour - value);
  75:  
  76:             if (argb[red] < 0) argb[red] = 0;
  77:             if (argb[green] < 0) argb[green] = 0;
  78:  
  79:             argb[blue] = (int)(235 + (double)((double)(value) * 20 / 255));
  80:         }
  81:         else if (255 <= value && value < 510) // from blue to cyan (255 colours)
  82:         {
  83:             argb[red] = 0;
  84:             argb[green] = (int)(value - 255);
  85:             argb[blue] = 255;
  86:         }
  87:         else if (510 <= value && value < 765) // from cyan to green (255 colours)
  88:         {
  89:             argb[red] = 0;
  90:             argb[green] = 255;
  91:             argb[blue] = 255 - (int)(value - 510);
  92:         }
  93:         else if (765 <= value && value < 1020) // from green to yellow (255 colours)
  94:         {
  95:             argb[red] = (int)(value - 765);
  96:             argb[green] = 255;
  97:             argb[blue] = 0;
  98:         }
  99:         else if (1020 <= value && value < 1275)  // from yellow to red (255 colours)
 100:         {
 101:             argb[red] = 255;
 102:             argb[green] = 255 - (int)(value - 1020);
 103:             argb[blue] = 0;
 104:         }
 105:         else if (value >= 1275) // return red
 106:         {
 107:             argb[red] = 255;
 108:             argb[green] = 0;
 109:             argb[blue] = 0;
 110:         }
 111:         return argb;
 112:     }
 113:     /// <summary>
 114:     /// Creates the Actual HeatMap Image from the Processed _coordsArray
 115:     /// </summary>
 116:     /// <param name="pageName"></param>
 117:     /// <returns></returns>
 118:     private static byte[] CreateImage()
 119:     {
 120:         System.IO.MemoryStream ms = null;
 121:         Bitmap b = new Bitmap(_width, _height);
 122:         Graphics g = Graphics.FromImage(b);
 123:         Pen p = null;
 124:  
 125:         try
 126:         {
 127:             for (int x = 0; x < _width; x++)
 128:             {
 129:                 for (int y = 0; y < _height; y++)
 130:                 {
 131:                     if (_coordsArray[x][y] >= 0)
 132:                     {
 133:                         p = new Pen(GetColor(_maxClick, _coordsArray[x][y], 5));
 134:                         g.DrawLine(p, x, y, x + 1, y + 1);
 135:                     }
 136:                 }
 137:             }
 138:  
 139:             ms = new MemoryStream();
 140:             b.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
 141:         }
 142:         catch (Exception)
 143:         {
 144:             throw;
 145:         }
 146:         finally
 147:         {
 148:             ms.Dispose();
 149:             b.Dispose();
 150:             g.Dispose();
 151:         }
 152:         return ms.GetBuffer();
 153:     }
 154:     private static Double Distance(int x1, int y1, int x2, int y2)
 155:     {
 156:         return Math.Sqrt(Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2));
 157:     }
 158:     /// <summary>
 159:     /// Fetches all HeatMap Clicks based on user criteria
 160:     /// </summary>
 161:     /// <returns></returns>
 162:     private static List<HeatMapClick> FetchHeatMapClicks()
 163:     {
 164:         string settings = ConfigurationManager.AppSettings["HeatMap_Settings"];
 165:         string path = string.Concat(HttpContext.Current.Request.PhysicalApplicationPath,
 166:                                     "App_Data/" + settings);
 167:  
 168:         XElement heatmapClicks = null;
 169:         try
 170:         {
 171:             heatmapClicks = XElement.Load(path);
 172:         }
 173:         catch { }
 174:  
 175:         if ((heatmapClicks != null) && (heatmapClicks.Elements().Count() > 0))
 176:         {
 177:  
 178:             if (_allDates)
 179:             {
 180:                 var clicks = from c in heatmapClicks.Elements()
 181:                              where c.Element("Page").Value == _pageName
 182:                              select new HeatMapClick()
 183:                              {
 184:                                  Date = Convert.ToDateTime(c.Element("Date").Value),
 185:                                  Page = c.Element("Page").Value,
 186:                                  CoordX = Convert.ToInt32(c.Element("CoordX").Value),
 187:                                  CoordY = Convert.ToInt32(c.Element("CoordY").Value)
 188:                              };
 189:                 return clicks.ToList();
 190:             }
 191:             else
 192:             {
 193:                 var clicks = from c in heatmapClicks.Elements()
 194:                              where c.Element("Page").Value == _pageName
 195:                                 && Convert.ToDateTime(c.Element("Date").Value) >= _from
 196:                                 && Convert.ToDateTime(c.Element("Date").Value) <= _to
 197:                              select new HeatMapClick()
 198:                              {
 199:                                  Date = Convert.ToDateTime(c.Element("Date").Value),
 200:                                  Page = c.Element("Page").Value,
 201:                                  CoordX = Convert.ToInt32(c.Element("CoordX").Value),
 202:                                  CoordY = Convert.ToInt32(c.Element("CoordY").Value)
 203:                              };
 204:                 return clicks.ToList();
 205:             }
 206:         }
 207:         else
 208:             return null;
 209:     }
 210:     /// <summary>
 211:     /// Corrdinates the building of the HeatMap image.
 212:     /// Saves the Image to the current Theme Images folder
 213:     /// </summary>
 214:     private static void Generate()
 215:     {
 216:         _clicks = FetchHeatMapClicks();
 217:  
 218:         if (_clicks == null || _clicks.Count == 0)
 219:             return;
 220:  
 221:         int[] wh = GetWidthHeight();
 222:         _width = wh[0] + RADIUS;
 223:         _height = wh[1] + RADIUS;
 224:  
 225:         _coordsArray = new int[_width][];
 226:         for (int i = 0; i < _width; i++)
 227:         {
 228:             _coordsArray[i] = new int[_height];
 229:             for (int j = 0; j < _height; j++)
 230:             {
 231:                 _coordsArray[i][j] = 0;
 232:             }
 233:         }
 234:  
 235:         GenerateClickBlobs();
 236:         GetMaxClick();
 237:  
 238:         byte[] imgBytes = CreateImage();
 239:  
 240:         string query = HttpContext.Current.Request.QueryString["theme"];
 241:         string theme = !string.IsNullOrEmpty(query) ? query : BlogSettings.Instance.Theme;
 242:         string path = string.Concat(HttpContext.Current.Request.PhysicalApplicationPath, 
 243:                                     "themes/", 
 244:                                     theme, 
 245:                                     "/images/Heatmap/", 
 246:                                     _imageName);
 247:  
 248:         try
 249:         {
 250:             FileStream fs = File.Create(path);
 251:             fs.Write(imgBytes, 0, imgBytes.Length);
 252:             fs.Close();
 253:         }
 254:         catch (Exception)
 255:         {
 256:             throw;
 257:         }
 258:     }
 259:     private static void GenerateClickBlobs()
 260:     {
 261:         try
 262:         {
 263:             foreach (HeatMapClick c in _clicks)
 264:             {
 265:                 RootedIncrementOnPoint(c.CoordX, c.CoordY);
 266:                 // OR use
 267:                 //LinearSlideIncrementOnPoint(hc.CoordX, hc.CoordY);
 268:             }
 269:         }
 270:         catch (Exception)
 271:         {
 272:             throw;
 273:         }
 274:     }
 275:     private static Color GetColor(long upperBound, long value, int error)
 276:     {
 277:         int[] argb = new int[4];
 278:         argb = ColourSequence(value * ((1275 * (100 + error) / 100) / upperBound));
 279:         return Color.FromArgb(argb[0], argb[1], argb[2], argb[3]);
 280:     }
 281:     private static void GetMaxClick()
 282:     {
 283:         _maxClick = 0;
 284:         for (int x = 0; x < _width; x++)
 285:         {
 286:             for (int y = 0; y < _height; y++)
 287:             {
 288:                 if (_coordsArray[x][y] > _maxClick)
 289:                     _maxClick = _coordsArray[x][y];
 290:             }
 291:         }
 292:     }
 293:     /// <summary>
 294:     /// Determines the Width and Height of the Image to be processed
 295:     /// by obtaining the largest X-coord and Y-coord values
 296:     /// </summary>
 297:     /// <returns></returns>
 298:     private static int[] GetWidthHeight()
 299:     {
 300:         int[] wh = { 0, 0 };
 301:  
 302:         try
 303:         {
 304:             foreach (HeatMapClick c in _clicks)
 305:             {
 306:                 if (c.CoordX > wh[0])
 307:                     wh[0] = c.CoordX;
 308:                 if (c.CoordY > wh[1])
 309:                     wh[1] = c.CoordY;
 310:             }
 311:         }
 312:         catch (Exception)
 313:         {
 314:             throw;
 315:         }
 316:         return wh;
 317:     }
 318:     private static void LinearSlideIncrementOnPoint(int x, int y)
 319:     {
 320:         for (int i = x - RADIUS; i < x + RADIUS; i++)
 321:         {
 322:             for (int j = y - RADIUS; j < y + RADIUS; j++)
 323:             {
 324:                 if (((i > 0) && (j > 0)) && ((i < _width) && (j < _height)))
 325:                 {
 326:                     if (Distance(x, y, i, j) < RADIUS)
 327:                     {
 328:                         _coordsArray[i][j] += (int)(RADIUS - Distance(x, y, i, j));
 329:                     }
 330:                 }
 331:             }
 332:         }
 333:     }
 334:     private static void RootedIncrementOnPoint(int x, int y)
 335:     {
 336:         for (int i = x - RADIUS; i < x + RADIUS; i++)
 337:         {
 338:             for (int j = y - RADIUS; j < y + RADIUS; j++)
 339:             {
 340:                 if (((i >= 0) && (j >= 0)) && ((i < _width) && (j < _height)))
 341:                 {
 342:                     if (Distance(x, y, i, j) < RADIUS)
 343:                     {
 344:                         _coordsArray[i][j] += (int)Math.Sqrt(RADIUS - Distance(x, y, i, j));
 345:                     }
 346:                 }
 347:             }
 348:         }
 349:     }
 350:     #endregion
 351:  
 352:     private class HeatMapClick
 353:     {
 354:         public DateTime Date { get; set; }
 355:         public string Page { get; set; }
 356:         public int CoordX { get; set; }
 357:         public int CoordY { get; set; }
 358:     }
 359: }

 

Well that’s it for this post.  I apologize for the shortness of describing the code but it could be a start to something beautiful.  I’ve zipped up all the classes and controls for easier download.  You can download that here [BlogEngine HeatMap.zip].

 

My next project is to create an application that accumulates a variety of “items” from my HTC Touch and automatically create and upload a blog entry.  Stay tuned.

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Comments

Comments are closed