Table of Contents

Source Code WebEdition ProjectTemplates AjaxVehicleTracking CS.zip

Default.aspx

 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ThinkGeo.MapSuite.AjaxVehicleTracking.Default" %>  
 
 <%@ Register Assembly="WebEdition" Namespace="ThinkGeo.MapSuite.WebEdition" TagPrefix="cc1" %>  
 <!DOCTYPE html>  
 <html xml:en-us">  
 <head id="Head1" runat="server">  
     <title>Ajax Vehicle Tracking</title>  
     <meta charset="UTF-8">  
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />  
     <meta http-equiv="X-UA-Compatible" content="IE=Edge">  
     <link href="Images/MapSuite.ico" rel="shortcut icon" type="Images/x-icon" />  
     <link href="Styles/jquery-ui-1.10.4.custom.min.css" rel="stylesheet" type="text/css" />  
     <link href="Styles/Site.css" rel="stylesheet" type="text/css" />  
     <script type="text/javascript" src="Scripts/modernizr-2.5.3.js"></script>  
 </head>  
 <body>  
     <form id="Form1" runat="server">  
     <asp:ScriptManager ID="ScriptManager1" runat="server">  
     </asp:ScriptManager>  
     <div id="container">  
         <div id="header">  
             <div id="left-header">  
                 <span id="header-mapsuite">Map Suite</span> <span id="header-title">Ajax Vehicle Tracking</span>  
             </div>  
         </div>  
         <div id="content-container">  
             <div id="leftContainer">  
                 <div id="leftContent">  
                     <h4>  
                         Click to refresh vehicles:</h4>  
                     <div id="divRefresh" class="divBorder">  
                         <div class="divSettingItem">  
                             <img id="btnAutoRefresh" alt="Auto Refresh" title="Auto refresh" src="Images/AutoRefresh.png" class="imgButton" />  
                             <span class="title">Auto Refresh:</span> <span id="autoRefreshStatus" class="title redTxt">  
                                 On</span>  
                         </div>  
                         <div class="divSettingItem">  
                             <img id="btnRefresh" alt="Refresh Manually" title="Refresh" src="Images/RefreshManually.png" class="imgButton" />  
                             <span class="title">Refresh Manually</span>  
                         </div>  
                     </div>  
                     <h4>  
                         Interact with the map using these tools:  
                     </h4>  
                     <div id="divTrackMode" class="divBorder">  
                         <img id="btnPan" alt="Pan" title="Pan map" src="Images/pan.png" class="active imgButton" />  
                         <img id="btnDraw" alt="Draw" title="Draw fences" src="Images/draw.png" class="imgButton" />  
                         <img id="btnMeasure" alt="Measure" title="Measure distance" src="Images/measure.png" class="imgButton" />  
                     </div>  
                     <div id="divTrackType" class="divSubBorder">  
                         <img id="btnDrawPolygon" alt="Draw" title="Track new fences" src="Images/draw_polygon.png" class="active imgButton" />  
                         <img id="btnEditPolygon" alt="Edit" title="Edit the selected fence" src="Images/edit_polygon.png" class="imgButton" />  
                         <img id="btnRemovePolygon" alt="Remove" title="Delete" src="Images/Remove_Polygon.png" class="imgButton" />  
                         <img id="btnSave" alt="Save" title="Save" src="Images/save.png" class="imgButton" />  
                         <img id="btnClearShapes" title="Cancel" alt="Cancel" src="Images/clear.png" class="imgButton" />  
                     </div>  
                     <div id="divMeasure" class="divSubBorder">  
                         <img id="btnMeasureLength" alt="Distance" title="Measure line" src="Images/line.png" class="active imgButton" />  
                         <img id="btnMeasureArea" alt="Area" title="Measure polygon" src="Images/Polygon.png" class="imgButton" />  
                         <img id="btnClearMeasure" alt="Cancel" title="Cancel" src="Images/clear.png" class="imgButton" />  
                         <span class="title">Measure Unit:</span>  
                         <select>  
                             <option value="Metric">Metric</option>  
                             <option value="Imperial">Imperial</option>  
                         </select>  
                         <input id="mapMeasureMode" type="hidden" value="Area" />  
                     </div>  
                     <div class="blueBanner">  
                         Tracked Vehicles  
                     </div>  
                     <div class="divBorder" id="divVehicleList">  
                     </div>  
                 </div>  
             </div>  
             <div id="toggle">  
                 <img id="collapse" src="Images/collapse.gif" />  
             </div>  
             <div id="map-content">  
                 <cc1:Map ID="Map1" runat="server" Height="100%" Width="100%">  
                 </cc1:Map>  
                 <div id="divRemoveDialog">  
                     Are you sure you want to delete the spatial fence you have selected?  
                 </div>  
                 <div id="divMessage">  
                     Please choose a fence at first.  
                 </div>  
             </div>  
         </div>  
         <div id="footer">  
             <span id="coordinate"><span id="spanMouseCoordinate"></span></span>  
         </div>  
         <script src="Scripts/jquery-1.10.2.js" type="text/javascript"></script>  
         <script src="Scripts/jquery-ui-1.10.4.custom.min.js" type="text/javascript"></script>  
         <script type="text/javascript" src="Scripts/ready-functions.js"></script>  
         <script type="text/javascript" src="Scripts/VehiclesPanelHelper.js"></script>  
     </div>  
     </form>  
 </body>  
 </html>  
 
 

Default.aspx.cs

 using System;  
 using System.Linq;  
 using System.Collections.Generic;  
 using System.Collections.ObjectModel;  
 using System.Configuration;  
 using System.Globalization;  
 using System.Text;  
 using System.Web.UI;  
 using ThinkGeo.MapSuite.Core;  
 using ThinkGeo.MapSuite.WebEdition;  
 
 namespace ThinkGeo.MapSuite.AjaxVehicleTracking  
 {  
     public partial class Default : System.Web.UI.Page, ICallbackEventHandler  
     {  
         // For the sample we set the current time to the time below.  This is so the time will  
         // match the data in our sample database.  
         private readonly DateTime adjustedStartTime = new DateTime(2009, 7, 10, 11, 31, 0);  
 
         private string callbackResult;  
 
         protected void Page_Load(object sender, EventArgs e)  
         {  
             if (!Page.IsPostBack)  
             {  
                 // Initialize Map  
                 InitializeMap();  
 
                 // Read vehicles from database  
                 DateTime currentTime = GetAdjustedCurrentDateTime();  
                 Collection<Vehicle> vehicles = GetVehicles(currentTime);  
 
                 // Update vehicle information to Map  
                 UpdateVehiclesToOverlays(vehicles);  
 
                 // Register Callback references  
                 Page.ClientScript.GetCallbackEventReference(this, "", "", "");  
             }  
         }  
 
         public string GetCallbackResult()  
         {  
             return callbackResult;  
         }  
 
         public void RaiseCallbackEvent(string eventArgument)  
         {  
             CallbackRequest callbackRequest = JSONSerializer.Deserialize<CallbackRequest>(eventArgument);  
 
             switch (callbackRequest.Request)  
             {  
                 case "editFences":  
                     callbackResult = JSONSerializer.Serialize(GetSpatialFencesInJsonFeature());  
                     break;  
                 case "saveFences":  
                     callbackResult = SaveSpatialFences(callbackRequest.Features).ToString();  
                     break;  
                 case "refreshVehicles":  
                     Collection<Vehicle> vehicels = GetVehicles(GetAdjustedCurrentDateTime());  
                     UpdateVehiclesToOverlays(vehicels);  
 
                     List<JsonVehicle> jsonVehicels = vehicels.Select((t) =>  
                     {  
                         return ConvertToJsonVehicle(t);  
                     }).ToList();  
                     callbackResult = JSONSerializer.Serialize(jsonVehicels);  
                     break;  
                 default:  
                     break;  
             }  
         }  
 
         private JsonVehicle ConvertToJsonVehicle(Vehicle vehicle)  
         {  
             Collection<JsonLocation> historyLocations = new Collection<JsonLocation>();  
             foreach (Location item in vehicle.HistoryLocations)  
             {  
                 historyLocations.Add(new JsonLocation()  
                 {  
                     Latitude = item.Latitude,  
                     Longitude = item.Latitude,  
                     Speed = item.Speed,  
                     TrackTime = item.DateTime.ToString()  
                 });  
             }  
             return new JsonVehicle()  
             {  
                 Id = vehicle.Id + string.Empty,  
                 Name = vehicle.VehicleName,  
                 CurrentLocation = new JsonLocation(vehicle.Location.Longitude, vehicle.Location.Latitude, vehicle.Location.Speed, vehicle.Location.DateTime.ToString()),  
                 VehicleIconVirtualPath = vehicle.VehicleIconVirtualPath,  
                 VehicleMotionState = vehicle.MotionState == VehicleMotionState.Motion ? 1 : 0,  
                 HistoryLocations = historyLocations,  
                 IsInFence = CheckIsInSpatialFence(vehicle),  
             };  
         }  
 
         private Collection<JsonFence> GetSpatialFencesInJsonFeature()  
         {  
             Collection<JsonFence> jsonFeatures = new Collection<JsonFence>();  
 
             LayerOverlay spatialFenceOverlay = (LayerOverlay)Map1.CustomOverlays["SpatialFenceOverlay"];  
             InMemoryFeatureLayer spatialFenceLayer = (InMemoryFeatureLayer)spatialFenceOverlay.Layers["SpatialFenceLayer"];  
             foreach (Feature feature in spatialFenceLayer.InternalFeatures)  
             {  
                 // Add feature into editOverlay on server side to make sure it's synchronous on client and server side  
                 Map1.EditOverlay.Features.Add(feature);  
                 // Create feature on client side  
                 JsonFence jsonFeature = new JsonFence(feature.Id, feature.GetWellKnownText());  
                 jsonFeatures.Add(jsonFeature);  
             }  
 
             return jsonFeatures;  
         }  
 
         private bool SaveSpatialFences(Collection<JsonFence> features)  
         {  
             LayerOverlay spatialFenceOverlay = (LayerOverlay)Map1.CustomOverlays["SpatialFenceOverlay"];  
             InMemoryFeatureLayer spatialFenceLayer = (InMemoryFeatureLayer)spatialFenceOverlay.Layers["SpatialFenceLayer"];  
 
             try  
             {  
                 spatialFenceLayer.Open();  
 
                 Collection<Feature> newAddedFeatures = new Collection<Feature>();  
                 foreach (JsonFence jsonFeature in features)  
                 {  
                     if (string.IsNullOrEmpty(jsonFeature.Id))  
                     {  
                         Feature feature = new Feature(jsonFeature.Wkt, Guid.NewGuid().ToString());  
                         feature.ColumnValues["Restricted"] = "Restricted";  
                         newAddedFeatures.Add(feature);  
                     }  
                 }  
 
                 if (features.Count != 0 && newAddedFeatures.Count == features.Count) // if all the features are requested features, means map is under draw polygon  
                 {  
                     // add new features to spatial fence layer  
                     foreach (Feature feature in newAddedFeatures)  
                     {  
                         spatialFenceLayer.InternalFeatures.Add(feature);  
                     }  
 
                     // Insert new feature into the database  
                     using (TrackingAccessProvider vehicleProvider = new TrackingAccessProvider(MapPath(ConfigurationManager.AppSettings["AccessDataBase"])))  
                     {  
                         // Insert new added and modified features to database  
                         foreach (Feature feature in newAddedFeatures)  
                         {  
                             vehicleProvider.InsertSpatialFence(feature);  
                         }  
                     }  
                 }  
                 else // Deal with modify mode is activated scenario  
                 {  
                     Collection<Feature> modifiedFeatures = new Collection<Feature>();  
                     Dictionary<string, JsonFence> keyedJsonFeatures = new Dictionary<string, JsonFence>();  
                     foreach (JsonFence jsonFeature in features)  
                     {  
                         if (!string.IsNullOrEmpty(jsonFeature.Id))  // If id is not null, it's the feature after editing  
                         {  
                             keyedJsonFeatures.Add(jsonFeature.Id, jsonFeature);  
                             Feature feature = new Feature(jsonFeature.Wkt, jsonFeature.Id);  
                             feature.ColumnValues["Restricted"] = "Restricted";  
                             modifiedFeatures.Add(feature);  
                         }  
                     }  
 
                     // Get removed features  
                     Collection<Feature> removedFeatures = new Collection<Feature>();  
                     foreach (Feature feature in Map1.EditOverlay.Features)  
                     {  
                         if (!keyedJsonFeatures.ContainsKey(feature.Id))  
                         {  
                             removedFeatures.Add(feature);  
                         }  
                     }  
                     // Refine the spatial fence layer  
                     spatialFenceLayer.InternalFeatures.Clear();  
                     foreach (Feature feature in newAddedFeatures)  
                     {  
                         spatialFenceLayer.InternalFeatures.Add(feature);  
                     }  
                     foreach (Feature feature in modifiedFeatures)  
                     {  
                         spatialFenceLayer.InternalFeatures.Add(feature);  
                     }  
                     Map1.EditOverlay.Features.Clear();  
                     spatialFenceOverlay.Redraw();  
 
                     // Update the database  
                     using (TrackingAccessProvider vehicleProvider = new TrackingAccessProvider(MapPath(ConfigurationManager.AppSettings["AccessDataBase"])))  
                     {  
                         // Delete all spatial fences from database and then update the existing ones  
                         if (removedFeatures.Count > 0)  
                         {  
                             vehicleProvider.DeleteSpatialFences(removedFeatures);  
                         }  
                         // Insert new added and modified features to database  
                         foreach (Feature feature in newAddedFeatures)  
                         {  
                             vehicleProvider.InsertSpatialFence(feature);  
                         }  
                         foreach (Feature feature in modifiedFeatures)  
                         {  
                             vehicleProvider.UpdateSpatialFenceByFeature(feature);  
                         }  
                     }  
                 }  
                 return true;  
             }  
             catch  
             {  
                 return false;  
             }  
         }  
 
         private DateTime GetAdjustedCurrentDateTime()  
         {  
             // This vehicle tracking sample contains some simulated data  
             // This method stores the real time when the application started and reflects to the start sample time  
             // When the actual time increments 1 second, the sample time increments 6 seconds  
             //  
             // To make the application run in real time just have this method return to current date time  
             //  
             DateTime currentSampleTime;  
             if (ViewState["ApplicationStartTime"] == null)  
             {  
                 ViewState["ApplicationStartTime"] = DateTime.Now;  
                 currentSampleTime = adjustedStartTime;  
             }  
             else  
             {  
                 double sampleSecondPerActualSecond = 12;  
                 double realSpentTime = TimeSpan.FromTicks(DateTime.Now.Ticks - ((DateTime)ViewState["ApplicationStartTime"]).Ticks).TotalSeconds;  
                 int sampleSpentTime = (int)(realSpentTime * sampleSecondPerActualSecond);  
                 currentSampleTime = adjustedStartTime.AddSeconds(sampleSpentTime);  
             }  
 
             return currentSampleTime;  
         }  
 
         private bool CheckIsInSpatialFence(Vehicle vehicle)  
         {  
             LayerOverlay spatialFenceOverlay = (LayerOverlay)Map1.CustomOverlays["SpatialFenceOverlay"];  
             InMemoryFeatureLayer spatialFenceLayer = (InMemoryFeatureLayer)spatialFenceOverlay.Layers["SpatialFenceLayer"];  
 
             // Get the point shape and then check if it is within any of the sptail fences using the QueryTools  
             PointShape pointShape = new PointShape(vehicle.Location.Longitude, vehicle.Location.Latitude);  
             spatialFenceLayer.Open();  
             Collection<Feature> spatialFencesWithin = spatialFenceLayer.QueryTools.GetFeaturesContaining(pointShape, ReturningColumnsType.NoColumns);  
             spatialFenceLayer.Close();  
 
             bool isInFence = false;  
             if (spatialFencesWithin.Count > 0)  
             {  
                 isInFence = true;  
             }  
 
             return isInFence;  
         }  
 
         private Collection<Vehicle> GetVehicles(DateTime currentTime)  
         {  
             Collection<Vehicle> vehicles = new Collection<Vehicle>();  
 
             // If you want to use SQL server as database, please attach /App_Data/VehicleTrackingDb.mdf to  
             // SQL Server and change the connection string in the web.config first;  
             // Then use the the commended line of code below.  
             //  
             // using (TrackingSqlProvider vehicleProvider = new TrackingSqlProvider(ConfigurationManager.ConnectionStrings["VehicleTrackingDbConnectionString"].ConnectionString))  
             //  
             // Get all the vehicles from the database  
             using (TrackingAccessProvider vehicleProvider = new TrackingAccessProvider(Server.MapPath(ConfigurationManager.AppSettings["AccessDataBase"])))  
             {  
                 vehicles = vehicleProvider.GetCurrentVehicles(currentTime);  
             }  
 
             foreach (var vehicle in vehicles)  
             {  
                 vehicle.IsInFence = CheckIsInSpatialFence(vehicle);  
             }  
 
             return vehicles;  
         }  
 
         private Collection<Feature> GetSpatialFences()  
         {  
             // Get the spatial fences from the database  
             Collection<Feature> spatialFences = new Collection<Feature>();  
             using (TrackingAccessProvider vehicleProvider = new TrackingAccessProvider(MapPath(ConfigurationManager.AppSettings["AccessDataBase"])))  
             {  
                 spatialFences = vehicleProvider.GetSpatialFences();  
             }  
 
             return spatialFences;  
         }  
 
         private void InitializeMap()  
         {  
             Map1.MapUnit = GeographyUnit.Meter;  
             Map1.MapTools.MiniMap.Enabled = true;  
 
             Map1.MapTools.OverlaySwitcher.Enabled = true;  
             Map1.MapTools.OverlaySwitcher.BaseOverlayTitle = " ";  
 
             Map1.MapTools.MeasureMapTool.Enabled = true;  
             Map1.MapTools.MeasureMapTool.Geodesic = true;  
             Map1.MapTools.MeasureMapTool.MeasureUnitType = MeasureUnitType.Metric;  
             Map1.MapTools.MeasureMapTool.MeasureType = MeasureType.None;  
 
             Map1.EditOverlay.EditSettings.IsResizable = false;  
             Map1.CurrentExtent = new RectangleShape(-10785241.6495495, 3916508.33762434, -10778744.5183967, 3912187.74540771);  
 
             // base map layer  
             WorldMapKitWmsWebOverlay worldMapKitWmsOverlay = new WorldMapKitWmsWebOverlay("World Map Kit");  
             worldMapKitWmsOverlay.Projection = WorldMapKitProjection.SphericalMercator;  
             Map1.CustomOverlays.Add(worldMapKitWmsOverlay);  
 
             OpenStreetMapOverlay openStreetMapOverlay = new OpenStreetMapOverlay("Open Street Map");  
             Map1.CustomOverlays.Add(openStreetMapOverlay);  
 
             BingMapsOverlay bingMapsAerialOverlay = new BingMapsOverlay("Bing Maps Aerial");  
             bingMapsAerialOverlay.MapType = BingMapsStyle.Aerial;  
             Map1.CustomOverlays.Add(bingMapsAerialOverlay);  
 
             BingMapsOverlay bingMapsRoadOverlay = new BingMapsOverlay("Bing Maps Road");  
             bingMapsRoadOverlay.MapType = BingMapsStyle.Road;  
             Map1.CustomOverlays.Add(bingMapsRoadOverlay);  
 
             // Add spatial fences  
             AddSpatialFenceOverlay();  
 
             // Add scale bar  
             ScaleBarAdornmentLayer scaleBarAdormentLayer = new ScaleBarAdornmentLayer();  
             scaleBarAdormentLayer.XOffsetInPixel = 10;  
             scaleBarAdormentLayer.UnitFamily = UnitSystem.Metric;  
             Map1.AdornmentOverlay.Layers.Add(scaleBarAdormentLayer);  
         }  
 
         private void AddSpatialFenceOverlay()  
         {  
             LayerOverlay spatialFenceOverlay = new LayerOverlay("SpatialFenceOverlay");  
             spatialFenceOverlay.TileType = TileType.SingleTile;  
             spatialFenceOverlay.IsBaseOverlay = false;  
             spatialFenceOverlay.IsVisibleInOverlaySwitcher = false;  
             Map1.CustomOverlays.Add(spatialFenceOverlay);  
 
             // Initialize SpatialFenceLayers.  
             InMemoryFeatureLayer spatialFenceLayer = new InMemoryFeatureLayer();  
             spatialFenceLayer.Open();  
             spatialFenceLayer.Columns.Add(new FeatureSourceColumn("Restricted", "Charater", 10));  
             spatialFenceLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = new AreaStyle(new GeoPen(GeoColor.FromArgb(255, 204, 204, 204), 2), new GeoSolidBrush(GeoColor.FromArgb(112, 255, 0, 0)));  
             spatialFenceLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.CreateSimpleTextStyle("Restricted", "Arial", 12, DrawingFontStyles.Regular, GeoColor.StandardColors.Black, GeoColor.SimpleColors.White, 2);  
             spatialFenceLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle.OverlappingRule = LabelOverlappingRule.AllowOverlapping;  
             spatialFenceLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;  
             spatialFenceOverlay.Layers.Add("SpatialFenceLayer", spatialFenceLayer);  
 
             // Get the spatial fences from the database and insert fences from database into fence layer  
             Collection<Feature> spatialFences = GetSpatialFences();  
             foreach (Feature spatialFence in spatialFences)  
             {  
                 spatialFence.ColumnValues["Restricted"] = "Restricted";  
                 spatialFenceLayer.InternalFeatures.Add(spatialFence);  
             }  
         }  
 
         private Location ProjectLocation(Location location)  
         {  
             Proj4Projection prj4 = new Proj4Projection();  
             prj4.InternalProjectionParametersString = Proj4Projection.GetGoogleMapParametersString();  
             prj4.ExternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326);  
             prj4.Open();  
             PointShape projectedPoint = prj4.ConvertToExternalProjection(new PointShape(location.Longitude,location.Latitude)) as PointShape;  
 
             location.Longitude = Math.Round(projectedPoint.X,6);  
             location.Latitude = Math.Round(projectedPoint.Y,6);  
             return location;  
         }  
 
         private void UpdateVehiclesToOverlays(Collection<Vehicle> vehicles)  
         {  
             foreach (var currentVehicle in vehicles)  
             {  
                 // Create an InMemoryMarkerOverlay for the vehicle to hold the points and current location  
                 InMemoryMarkerOverlay vehicleOverlay = null;  
                 if (Map1.CustomOverlays.Contains(currentVehicle.VehicleName))  
                 {  
                     vehicleOverlay = Map1.CustomOverlays[currentVehicle.VehicleName] as InMemoryMarkerOverlay;  
                 }  
                 else  
                 {  
                     vehicleOverlay = new InMemoryMarkerOverlay(currentVehicle.VehicleName);  
                     vehicleOverlay.Name = currentVehicle.Id.ToString(CultureInfo.InvariantCulture);  
                     vehicleOverlay.ZoomLevelSet.ZoomLevel01.CustomMarkerStyle = GetCustomMarkerStyle(currentVehicle.VehicleIconVirtualPath);  
                     vehicleOverlay.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;  
                     vehicleOverlay.IsVisibleInOverlaySwitcher = false;  
                     Map1.CustomOverlays.Add(vehicleOverlay);  
 
                     // Add all the required columns so we can populate later  
                     vehicleOverlay.FeatureSource.Open();  
                     vehicleOverlay.Columns.Add(new FeatureSourceColumn("IsCurrentPosition"));  
                     vehicleOverlay.Columns.Add(new FeatureSourceColumn("Speed"));  
                     vehicleOverlay.Columns.Add(new FeatureSourceColumn("DateTime"));  
                     vehicleOverlay.Columns.Add(new FeatureSourceColumn("Longitude"));  
                     vehicleOverlay.Columns.Add(new FeatureSourceColumn("Latitude"));  
                     vehicleOverlay.Columns.Add(new FeatureSourceColumn("VehicleName"));  
                     vehicleOverlay.Columns.Add(new FeatureSourceColumn("Duration"));  
                 }  
 
                 // Clear old vehicle's old positions  
                 vehicleOverlay.FeatureSource.InternalFeatures.Clear();  
 
                 // Add the vheicle's location histories  
                 foreach (Location historyLocation in currentVehicle.HistoryLocations)  
                 {  
                     Feature breadcrumbFeature = new Feature(historyLocation.GetLocationPointShape().GetWellKnownBinary(), currentVehicle.VehicleName + historyLocation.DateTime.ToString());  
                     breadcrumbFeature.ColumnValues["DateTime"] = historyLocation.DateTime.ToString();  
                     breadcrumbFeature.ColumnValues["IsCurrentPosition"] = "IsNotCurrentPosition";  
                     breadcrumbFeature.ColumnValues["Speed"] = historyLocation.Speed.ToString(CultureInfo.InvariantCulture);  
 
                     Location projectedLocation = ProjectLocation(historyLocation);  
                     breadcrumbFeature.ColumnValues["Longitude"] = projectedLocation.Longitude.ToString("N6", CultureInfo.InvariantCulture);  
                     breadcrumbFeature.ColumnValues["Latitude"] = projectedLocation.Latitude.ToString("N6", CultureInfo.InvariantCulture);  
                     breadcrumbFeature.ColumnValues["VehicleName"] = currentVehicle.VehicleName;  
                     breadcrumbFeature.ColumnValues["Duration"] = currentVehicle.SpeedDuration.ToString(CultureInfo.InvariantCulture);  
                     vehicleOverlay.FeatureSource.InternalFeatures.Add(breadcrumbFeature.Id, breadcrumbFeature);  
                 }  
 
                 // Add the vehicle's latest position  
                 Feature latestPositionFeature = new Feature(currentVehicle.Location.GetLocationPointShape().GetWellKnownBinary(), currentVehicle.VehicleName);  
                 latestPositionFeature.ColumnValues["DateTime"] = currentVehicle.Location.DateTime.ToString();  
                 latestPositionFeature.ColumnValues["IsCurrentPosition"] = "IsCurrentPosition";  
                 latestPositionFeature.ColumnValues["Speed"] = currentVehicle.Location.Speed.ToString(CultureInfo.InvariantCulture);  
 
                 Location projectedCurrentLocation = ProjectLocation(currentVehicle.Location);  
                 latestPositionFeature.ColumnValues["Longitude"] = projectedCurrentLocation.Longitude.ToString("N6", CultureInfo.InvariantCulture);  
                 latestPositionFeature.ColumnValues["Latitude"] = projectedCurrentLocation.Latitude.ToString("N6", CultureInfo.InvariantCulture);  
                 latestPositionFeature.ColumnValues["VehicleName"] = currentVehicle.VehicleName;  
                 latestPositionFeature.ColumnValues["Duration"] = currentVehicle.SpeedDuration.ToString(CultureInfo.InvariantCulture);  
                 vehicleOverlay.FeatureSource.InternalFeatures.Add(latestPositionFeature.Id, latestPositionFeature);  
 
                 vehicleOverlay.FeatureSource.Close();  
             }  
 
         }  
 
         private static ValueMarkerStyle GetCustomMarkerStyle(string vehicleIconVirtualPath)  
         {  
             StringBuilder popupHtml = new StringBuilder("<table>");  
             popupHtml.Append("<tr><td colspan='2' class='vehicleName'>[#VehicleName#]</td></tr>");  
             popupHtml.Append("<tr><td colspan='2'><div class='hrLine'></div></td></tr>");  
             popupHtml.Append("<tr class='vehicleTxt'><td>Longitude:</td><td>[#Longitude#]</td></tr>");  
             popupHtml.Append("<tr class='vehicleTxt'><td>Latitude:</td><td>[#Latitude#]</td></tr>");  
             popupHtml.Append("<tr class='vehicleTxt'><td>Speed:</td><td>[#Speed#]</td></tr>");  
             popupHtml.Append("<tr class='vehicleTxt'><td>Time</td><td>[#DateTime#]</td></tr>");  
             popupHtml.Append("</table>");  
 
             ValueMarkerStyle valueStyle = new ValueMarkerStyle("IsCurrentPosition");  
 
             WebImage currentPositionImage = new WebImage(vehicleIconVirtualPath);  
             PointMarkerStyle currentPositionStyle = new PointMarkerStyle(currentPositionImage);  
             currentPositionStyle.Popup.BorderWidth = 1;  
             currentPositionStyle.Popup.BorderColor = GeoColor.StandardColors.Gray;  
             currentPositionStyle.Popup.ContentHtml = popupHtml.ToString();  
             currentPositionStyle.Popup.AutoSize = true;  
             MarkerValueItem currentPositionItem = new MarkerValueItem("IsCurrentPosition", (MarkerStyle)currentPositionStyle);  
             valueStyle.ValueItems.Add(currentPositionItem);  
 
             WebImage historyPositionImage = new WebImage("images/trail point.png", 6, 6, -3, -3);  
             PointMarkerStyle historyPositionStyle = new PointMarkerStyle(historyPositionImage);  
             historyPositionStyle.Popup.BorderWidth = 1;  
             historyPositionStyle.Popup.BorderColor = GeoColor.StandardColors.Gray;  
             historyPositionStyle.Popup.ContentHtml = popupHtml.ToString();  
             historyPositionStyle.Popup.AutoSize = true;  
             MarkerValueItem historyPositionItem = new MarkerValueItem("IsNotCurrentPosition", (MarkerStyle)historyPositionStyle);  
             valueStyle.ValueItems.Add(historyPositionItem);  
 
             return valueStyle;  
         }  
     }  
 }  
 
 

ready-functions.js

 $(document).ready(function () {  
     // Initialize the dom elements in the page  
     initializePageElements();  
     // attach event to the buttons for track shapes  
     attachEventsToTrackButtons();  
     // init vihecles in the first time.  
     refreshVehicle();  
     // auto-refresh button  
     var autoRefreshTimer = setInterval(autoRefresh, 1000);  
     $('#btnAutoRefresh').on('click', function () {  
         // attach animation to auto-refresh button  
         if ($(this).attr("src") == "Images/AutoRefresh.png") {  
             $("#autoRefreshStatus").text("On");  
             // let server start reading history  
             autoRefreshTimer = setInterval(autoRefresh, 1000);  
         } else if (autoRefreshTimer != null) {  
             $("#autoRefreshStatus").text("Off");  
 
             $("#btnAutoRefresh").attr("src", "Images/AutoRefresh.png")  
             clearInterval(autoRefreshTimer);  
             autoRefreshTimer = null;  
         }  
     });  
 
     // Refresh manually  
     $("#btnRefresh").bind("click", function (e) {  
         refreshVehicle();  
     });  
 
     // zoom to vehicle  
     $("#tbVehiclelist a").bind("click", function (e) {  
         var lonlatVal = $(this).parent().find("#lonlat").val().split(',');  
         if (lonlatVal.length >= 2) {  
             var lonlat = new OpenLayers.LonLat(parseFloat(lonlatVal[0]), parseFloat(lonlatVal[1]));  
             var map = Map1.GetOpenLayersMap();  
             map.zoomToScale(4513.988880);  
             map.panTo(lonlat);  
         }  
     })  
 
     // Measure Buttons  
     $("#divMeasure Img").bind("click", function (e) {  
         Map1.SetDrawMode('Normal');  
         var command = $(this).attr("alt");  
         switch (command) {  
             case "Distance":  
                 Map1.SetMeasureMode('PathMeasure');  
                 break;  
             case "Area":  
                 Map1.SetMeasureMode('PolygonMeasure');  
                 break;  
             case "Cancel":  
                 Map1.SetMeasureMode('Normal');  
                 break;  
             default:  
                 break;  
         }  
     });  
     $("#divMeasure Select").bind("change", function () {  
         var displaySystem = $(this).val();  
         var measureTools = MapHelper.getMeasureTools();  
         for (var i = 0; i < measureTools.length; i++) {  
             switch (displaySystem) {  
                 case "Metric":  
                     measureTools[i].displaySystem = "metric";  
                     break;  
                 case "Imperial":  
                     measureTools[i].displaySystem = "english";  
                     break;  
                 default:  
                     break;  
             }  
         }  
         var args = { "request": CallbackTypes.changeDisplaySystem, "displaySystem": displaySystem };  
         $DoCallback(JSON.stringify(args), function (e, context) {  
             MapHelper.getAdormentOverlay().redraw(true);  
         });  
     })  
 });  
 
 
 function autoRefresh() {  
     if ($("#btnAutoRefresh").attr("src") == "Images/AutoRefresh_2.png") {  
         $("#btnAutoRefresh").attr("src", "Images/AutoRefresh_1.png")  
     } else {  
         $("#btnAutoRefresh").attr("src", "Images/AutoRefresh_2.png")  
     }  
     // refresh vechiles  
     refreshVehicle();  
 };  
 
 function refreshVehicle() {  
     var args = { "request": CallbackTypes.refreshVihecle };  
     $DoCallback(JSON.stringify(args), function (e, context) {  
         var jsonVihecles = JSON.parse(e);  
         // refresh vihecle panel.  
         $("#divVehicleList").empty();  
         $("#divVehicleList").html(new vehiclesPanel(jsonVihecles).generateTable());  
         // refresh vihecle marker layers.  
         var vehicleOverlays = MapHelper.getVehicleOverlays();  
         for (var i = 0; i < vehicleOverlays.length; i++) {  
             vehicleOverlays[i].redraw(true);  
         }  
 
         // zoom to vehicle  
         $("#divVehicleList a").bind("click", function (e) {  
             var lonlatVal = $(this).parent().find("#lonlat").val().split(',');  
             if (lonlatVal.length >= 2) {  
                 var lonlat = new OpenLayers.LonLat(parseFloat(lonlatVal[0]), parseFloat(lonlatVal[1]));  
                 Map1.GetOpenLayersMap().zoomToScale(4513.988880);  
                 Map1.GetOpenLayersMap().panTo(lonlat);  
             }  
         })  
     });  
 
 }  
 
 var OnMapCreated = function (map) {  
     map.events.register("mousemove", map, function (e) {  
         var mouseCoordinate = this.getLonLatFromPixel(new OpenLayers.Pixel(e.clientX, e.clientY));  
         if (mouseCoordinate) {  
             $("#spanMouseCoordinate").text("X:" + mouseCoordinate.lon.toFixed(2) + "  Y: " + mouseCoordinate.lat.toFixed(2));  
         }  
     });  
 
     // A workaround here to make sure the marker always have a higher zIndex than editOverlay  
     var markerOverlays = MapHelper.getVehicleOverlays();  
     for (var i = 0; i < markerOverlays.length; i++) {  
         markerOverlays[i].setZIndex(750 + i); // 750 is the default zIndex of popup  
     }  
 }  
 
 var MapHelper = {  
     getEditOverlay: function () {  
         var editOverlay = Map1.GetOpenLayersMap().getLayersByName("EditOverlay");  
         if (editOverlay.length == 0) {  
             Map1.GetMapParser().initDrawControls();  
         }  
         return Map1.GetOpenLayersMap().getLayersByName("EditOverlay")[0];  
     },  
     getFenceOverlay: function () {  
         var map = Map1.GetOpenLayersMap();  
         return map.getLayer("SpatialFenceOverlay");  
     },  
     getMeasureTools: function () {  
         var map = Map1.GetOpenLayersMap();  
         return map.getControlsByClass("OpenLayers.Control.Measure");  
     },  
     getAdormentOverlay: function () {  
         var adornmentOverlay = Map1.GetOpenLayersMap().getLayersByName("AdornmentOverlay");  
         return adornmentOverlay[0];  
     },  
     getVehicleOverlays: function () {  
         var map = Map1.GetOpenLayersMap();  
         return Map1.GetOpenLayersMap().getLayersByClass("OpenLayers.Layer.Markers");  
     }  
 }  
 
 function attachEventsToTrackButtons() {  
     // Process track mode buttons  
     $("#divTrackType Img").bind("click", function (e) {  
         var command = $(this).attr("alt");  
         switch (command) {  
             case "Draw":  
                 // Back to draw polygon mode and cacel edit geometries  
                 Map1.SetDrawMode('Polygon');  
                 // clear all editing fences if it's in editing mode before  
                 var fenceOverlay = MapHelper.getFenceOverlay();  
                 if (!fenceOverlay.getVisibility()) {  
                     var editOverlay = MapHelper.getEditOverlay();  
                     editOverlay.destroyFeatures(editOverlay.features);  
 
                     fenceOverlay.setVisibility(true);  
                 }  
                 break;  
             case "Edit":  
                 Map1.SetDrawMode('Modify');  
                 if (MapHelper.getFenceOverlay().getVisibility() || MapHelper.getEditOverlay().features.length <= 0) {  
                     editFences();  
                 }  
                 break;  
             case "Remove":  
                 var parser = Map1.GetMapParser();  
                 if (parser.editOverlay == null || parser.editOverlay.selectedFeatures.length == 0) {  
                     // Show no fence selected dialog  
                     $("#divMessage").dialog("open");  
                 } else {  
                     $("#divRemoveDialog").dialog("open");  
                 }  
                 $(".ui-dialog-titlebar").hide();    // Hide dialog header bar  
                 break;  
             case "Save":  
                 if (!MapHelper.getFenceOverlay().getVisibility() || MapHelper.getEditOverlay().features.length > 0) {  
                     saveFences();  
                 }  
                 break;  
             case "Cancel":  
                 $("#btnDrawPolygon").trigger("click");  
                 break;  
             default:  
                 break;  
         }  
     })  
 
     // Functions related map  
     var editFences = function () {  
         var args = { "request": CallbackTypes.editFences };  
         $DoCallback(JSON.stringify(args), function (e, context) {  
             if (e) {  
                 var jsonFeatures = $.parseJSON(e);  
                 var editingFeatures = new Array();  
                 for (var i = 0; i < jsonFeatures.length; i++) {  
                     var spatialFence = new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT(jsonFeatures[i].wkt));  
                     spatialFence.fid = jsonFeatures[i].id;  
 
                     editingFeatures.push(spatialFence);  
                 }  
 
                 MapHelper.getEditOverlay().addFeatures(editingFeatures);  
                 MapHelper.getFenceOverlay().setVisibility(false);  
             }  
         }, this)  
     }  
     var saveFences = function () {  
         var editOverlay = MapHelper.getEditOverlay();  
         var features = new Array();  
         for (var i = 0; i < editOverlay.features.length; i++) {  
             var geometry = editOverlay.features[i].geometry;  
             if (geometry.CLASS_NAME != "OpenLayers.Geometry.Point") {  
                 var feature = { id: editOverlay.features[i].fid, wkt: geometry.toString() };  
                 features.push(feature);  
             }  
         }  
 
         var args = { "trackMode": $("#mapTrackMode").val(), "request": CallbackTypes.saveFences, "features": features };  
         $DoCallback(JSON.stringify(args), function (e, context) {  
             if (e == "True") {  
                 var editOverlay = MapHelper.getEditOverlay();  
                 editOverlay.destroyFeatures(editOverlay.features);  
 
                 var fenceOverlay = MapHelper.getFenceOverlay();  
                 fenceOverlay.setVisibility(true);  
                 fenceOverlay.redraw(true);  
                 $("#btnDrawPolygon").trigger("click");  
             } else {  
                 $("#divMessage").html("Failed to save the edit spatial fences.");  
                 $("#divMessage").dialog("open");  
             }  
         }, this)  
     }  
 
     // Init dialog for tracking shapes  
     $("#divRemoveDialog").dialog({  
         autoOpen: false,  
         modal: true,  
         buttons: {  
             Yes: function () {  
                 var parser = Map1.GetMapParser();  
                 if (parser.editOverlay && parser.editOverlay.selectedFeatures.length > 0) {  
                     var selectedFeatures = [];  
                     for (var i = 0; i < parser.editOverlay.selectedFeatures.length; i++) {  
                         for (var j = 0; j < parser.editOverlay.features.length; j++) {  
                             if (parser.editOverlay.features[j].id == parser.editOverlay.selectedFeatures[i].id) {  
                                 selectedFeatures.push(parser.editOverlay.features[j]);  
                             }  
                         }  
                     }  
                     if (parser.paintControls['Modify'].active) {  
                         parser.paintControls['Modify'].deactivate();  
                     }  
                     parser.editOverlay.removeFeatures(selectedFeatures);  
                     // Synchronize the edited features to server side  
                     saveFences();  
 
                     $(this).dialog("close");  
                 }  
             },  
             No: function () {  
                 // back to previous status  
                 if (MapHelper.getFenceOverlay().getVisibility()) {  
                     // Back to draw edit mode  
                     $("#btnDrawPolygon").trigger("click");  
                 } else {  
                     // Back to draw polygon mode  
                     $("#btnEditPolygon").trigger("click");  
                 }  
                 $(this).dialog("close");  
             }  
         }  
     });  
     $("#divMessage").dialog({  
         autoOpen: false,  
         modal: true,  
         buttons: {  
             ok: function () {  
                 // back to previous status  
                 if (MapHelper.getFenceOverlay().getVisibility()) {  
                     // Back to draw edit mode  
                     $("#btnDrawPolygon").trigger("click");  
                 } else {  
                     // Back to draw polygon mode  
                     $("#btnEditPolygon").trigger("click");  
                 }  
                 $(this).dialog("close");  
             }  
         }  
     });  
 }  
 
 function initializePageElements() {  
     // Resize map after browser if resized  
     var resizeElementHeight = function resizeElementHeight() {  
         var documentheight = $(window).height();  
         var contentDivH = documentheight - $("#footer").height() - $("#header").height() - 1;  
         $("#content-container").height(contentDivH + "px");  
 
         $("#leftContainer").height(contentDivH + "px");  
         $("#map-content").height(contentDivH + "px");  
         $("#toggle").css("line-height", contentDivH + "px");  
 
         if (contentDivH > 300) {  
             $("#divVehicleList").height(contentDivH - 300 + "px");  
         } else {  
             $("#divVehicleList").visible = false;  
         }  
 
         // refresh the map.  
         Map1.GetOpenLayersMap().updateSize();  
     }  
     window.onload = resizeElementHeight();  
     $(window).resize(resizeElementHeight);  
 
     // set the toggle style for group buttons  
     var resetToggleButtons = function (containerId) {  
         var btnImgs = $(containerId).find("img");  
         for (var i = 0; i < btnImgs.length; i++) {  
             $(btnImgs[i]).bind("click", function () {  
                 var btnImgs = $(containerId).find("img");  
                 for (var i = 0; i < btnImgs.length; i++) {  
                     $(btnImgs[i]).attr("class", "imgButton");  
                 }  
                 $(this).attr("class", "active imgButton");  
             })  
         };  
     };  
     resetToggleButtons("#divTrackMode");  
     resetToggleButtons("#divTrackType");  
     resetToggleButtons("#divMeasure");  
 
     // highlight all img buttons when mouse-over  
     var highlightImg = function (imgContainerIds) {  
         for (var i = 0; i < imgContainerIds.length; i++) {  
             var btnImgs = $(imgContainerIds[i]).find("img");  
             for (var j = 0; j < btnImgs.length; j++) {  
                 $(btnImgs[j]).bind("mouseover", function () {  
                     $(this).css("opacity", "0.4");  
                 });  
                 $(btnImgs[j]).bind("mouseout", function () {  
                     $(this).css("opacity", "1");  
                 });  
             }  
         }  
     }  
     highlightImg(["#divRefresh",|"#divTrackMode", "#divTrackType", "#divMeasure"]);  
 
     // attach toggle events to track buttons  
     $("#divTrackMode img").bind("click", function (e) {  
         switch ($(this).attr("alt")) {  
             case "Pan":  
                 $("#divTrackType").hide();  
                 $("#divMeasure").hide();  
                 Map1.SetDrawMode('Normal');  
                 Map1.SetMeasureMode('Normal');  
                 break;  
             case "Draw":  
                 $("#divTrackType").show();  
                 $("#divMeasure").hide();  
                 Map1.SetDrawMode('Polygon');  
                 Map1.SetMeasureMode('Normal');  
                 break;  
             case "Measure":  
                 $("#divTrackType").hide();  
                 $("#divMeasure").show();  
                 Map1.SetDrawMode('Normal');  
                 Map1.SetMeasureMode('PathMeasure');  
                 break;  
             default: break;  
         }  
     })  
 
     // hide track types button and measure type buttons  
     $("#divTrackType").hide();  
     $("#divMeasure").hide();  
 
     // Bind toggle button events  
     $("#toggle").bind("click", function () {  
         if ($("#leftContainer").is(':visible')) {  
             $("#collapse").attr("src", "Images/expand.gif");  
             $("#map-content").css("width", "99%");  
             $("#toggle").css("left", "5px");  
             $("#leftContainer").hide();  
         }  
         else {  
             $("#leftContainer").show();  
             $("#collapse").attr("src", "Images/collapse.gif");  
             $("#map-content").css("width", "80%");  
             $("#toggle").css("left", "20%");  
         }  
         resizeElementHeight();  
     });  
 }  
 
 var CallbackTypes = {  
     editFences: "editFences",  
     saveFences: "saveFences",  
     refreshVihecle: "refreshVehicles"  
 };  
 
 function $DoCallback(arg, callbackEvent, context) {  
     WebForm_DoCallback("__Page", arg, callbackEvent, context, null, false);  
 }  
 
 

VehiclesPanelHelper.js

 var vehiclesPanel = function (vehiclesJson) {  
     return {  
         generateTable: function () {  
             var table = $("<table id='tbVehiclelist'></table>");  
 
             for (var i = 0; i < vehiclesJson.length; i++) {  
                 var currentVehicle = vehiclesJson[i];  
 
                 var tr1 = $("<tr></tr>");  
                 var tr1Content = $('<td rowspan="5" class="vehicleImg"><img id="imgVehicle" alt="' + currentVehicle.name + '" src="' + currentVehicle.path + '" /></td>' +  
                              '<td colspan="2" class="vehicleName"><a href="#" name="btnZoomTo">' + currentVehicle.name + '</a><input type="hidden" id="lonlat" value="' + currentVehicle.loc.x + "," + currentVehicle.loc.y + '" /></td>');  
                 tr1Content.appendTo(tr1);  
 
                 var tr2 = $('<tr class="vehicleTxt">');  
                 var motionStatusImg = currentVehicle.motion == 1?"Images/ball_green.png":"Images/ball_gray.png";  
                 var motionLabel = currentVehicle.motion == 1 ? "In Motion" : "Idle";  
                 var tr2Content = $('<td colspan="2"> <img alt="ball" src="' + motionStatusImg + '" /><span id="motionStatus" class="greenTxt">' + motionLabel + '</span></td>');  
                 tr2Content.appendTo(tr2);  
 
                 var tr3 = $('<tr class="vehicleTxt">');  
                 var isInFenceLabel = currentVehicle.isIn ? "<span class='redTxt'>In Restrict Area</span>" : "<span>Out Of Restrict Area</span>"  
                 var tr3Content = $('<td>Area:</td><td id="isInFence">' + isInFenceLabel + '</td>');  
                 tr3Content.appendTo(tr3);  
 
                 var tr4 = $('<tr class="vehicleTxt">');  
                 var tr4Content = $('<td>Speed:</td><td>' + currentVehicle.loc.s + ' mph</td>');  
                 tr4Content.appendTo(tr4);  
 
                 var tr5 = $('<tr class="vehicleTxt">');  
                 var tr5Content = $('<td>Duration:</td><td>' + currentVehicle.dur + ' min</td>');  
                 tr5Content.appendTo(tr5);  
 
                 var tr6 = $('<tr class="vehicleTxt">');  
                 var tr6Content = $('<td colspan="3">&nbsp;</td>');  
                 tr6Content.appendTo(tr6);  
 
                 tr1.appendTo(table);  
                 tr2.appendTo(table);  
                 tr3.appendTo(table);  
                 tr4.appendTo(table);  
                 tr5.appendTo(table);  
                 tr6.appendTo(table);  
             }  
 
             return table.html();  
         }  
     }  
 }  
 

TrackingAccessProvider.cs

 using System;  
 using System.Collections.Generic;  
 using System.Collections.ObjectModel;  
 using System.Data;  
 using System.Data.OleDb;  
 using System.Globalization;  
 using System.Text;  
 using ThinkGeo.MapSuite.Core;  
 
 namespace ThinkGeo.MapSuite.VehicleTracking  
 {  
     public class TrackingAccessProvider : TrackingDataProvider  
     {  
         private OleDbConnection dataConnection;  
 
         public TrackingAccessProvider(string databaseFilePath)  
         {  
             string connectionString = string.Format(CultureInfo.InvariantCulture, "Provider=Microsoft.Jet.OLEDB.4.0; Data Source='{0}'", databaseFilePath);  
             dataConnection = new OleDbConnection(connectionString);  
         }  
 
         public override Dictionary<int, Vehicle> GetCurrentVehicles(DateTime currentTime)  
         {  
             Dictionary<int, Vehicle> vehiclesList = new Dictionary<int, Vehicle>();  
             DataSet vehiclesDataSet = ExecuteQuery("Select * from Vehicle");  
 
             TimeSpan trackHistoryVehicleTimeSpan = TimeSpan.FromHours(8);  
             foreach (DataRow row in vehiclesDataSet.Tables[0].Rows)  
             {  
                 int vehicleId = Convert.ToInt32(row["VehicleId"], CultureInfo.InvariantCulture);  
                 Vehicle vehicle = GetCurrentVehicle(vehicleId, currentTime, trackHistoryVehicleTimeSpan);  
                 vehiclesList.Add(vehicle.Id, vehicle);  
             }  
 
             return vehiclesList;  
         }  
 
         private Vehicle GetCurrentVehicle(int vehicleId, DateTime currentTime, TimeSpan trackHistoryVehicleTimeSpan)  
         {  
             string sql = "SELECT A.VehicleName, A.VehicleID, A.VehicleIconVirtualPath, B.Longitude, B.Latitude, B.[Date], B.Speed FROM (Vehicle A LEFT OUTER JOIN Location B ON A.VehicleID = B.VehicleID) WHERE (A.VehicleID = {0}) AND (B.[Date] <= #{1}# and B.[Date]>=#{2}#) ORDER BY A.VehicleID, B.[Date] DESC";  
             DateTime trackStartTime = currentTime.AddTicks(-trackHistoryVehicleTimeSpan.Ticks);  
             sql = String.Format(CultureInfo.InvariantCulture, sql, vehicleId, currentTime.ToString(CultureInfo.InvariantCulture), trackStartTime.ToString(CultureInfo.InvariantCulture));  
 
             Vehicle currentVechicle = new Vehicle(vehicleId);  
             DataSet currentLocations = null;  
             try  
             {  
                 // Get the locations from current time back to the passed time span  
                 currentLocations = ExecuteQuery(sql);  
                 Collection<double> historySpeeds = new Collection<double>();  
                 for (int rowIndex = 0; rowIndex < currentLocations.Tables[0].Rows.Count; rowIndex++)  
                 {  
                     DataRow dataRow = currentLocations.Tables[0].Rows[rowIndex];  
                     currentVechicle.VehicleIconVirtualPath = "Images/" + dataRow["VehicleIconVirtualPath"].ToString();  
 
                     double latitude = Convert.ToDouble(dataRow["Latitude"], CultureInfo.InvariantCulture);  
                     double longitude = Convert.ToDouble(dataRow["Longitude"], CultureInfo.InvariantCulture);  
                     double speed = Convert.ToDouble(dataRow["Speed"], CultureInfo.InvariantCulture);  
                     DateTime dateTime = Convert.ToDateTime(dataRow["Date"], CultureInfo.InvariantCulture);  
                     Location currentLocation = new Location(longitude, latitude, speed, dateTime);  
                     historySpeeds.Add(speed);  
 
                     if (rowIndex == 0)  
                     {  
                         string vehicleName = dataRow["VehicleName"].ToString();  
                         currentVechicle.Location = currentLocation;  
                         currentVechicle.Id = vehicleId;  
                         currentVechicle.VehicleName = vehicleName;  
                     }  
                     else  
                     {  
                         currentVechicle.HistoryLocations.Add(currentLocation);  
                     }  
                 }  
             }  
             finally  
             {  
                 if (currentLocations != null)  
                 {  
                     currentLocations.Dispose();  
                 }  
             }  
 
             return currentVechicle;  
         }  
 
         public override Collection<Feature> GetSpatialFences()  
         {  
             Collection<Feature> spatialFences = new Collection<Feature>();  
             DataSet dataSet = ExecuteQuery("Select * from SpatialFence");  
 
             foreach (DataRow row in dataSet.Tables[0].Rows)  
             {  
                 string wkt = row["FenceGeometry"].ToString();  
                 string id = row["FeatureID"].ToString();  
                 spatialFences.Add(new Feature(wkt, id));  
             }  
             return spatialFences;  
         }  
 
         public override void DeleteSpatialFences(IEnumerable<Feature> features)  
         {  
             StringBuilder deleteFeatureIds = new StringBuilder();  
             foreach (Feature deleteFeature in features)  
             {  
                 deleteFeatureIds.AppendFormat(CultureInfo.InvariantCulture, "'{0}',", deleteFeature.Id);  
             }  
             string sql = String.Format(CultureInfo.InvariantCulture, "DELETE FROM SpatialFence WHERE (FeatureID IN ({0}))", deleteFeatureIds.ToString().TrimEnd(','));  
             ExecuteNonQuery(sql);  
         }  
 
         public override int UpdateSpatialFenceByFeature(Feature feature)  
         {  
             int updatedSpatialFenceCount = ExecuteNonQuery(String.Format(CultureInfo.InvariantCulture, "UPDATE SpatialFence SET FenceGeometry = '{0}' WHERE (FeatureID = '{1}')", feature.GetWellKnownText(), feature.Id));  
             return updatedSpatialFenceCount;  
         }  
 
         public override void InsertSpatialFence(Feature feature)  
         {  
             ExecuteNonQuery(String.Format(CultureInfo.InvariantCulture, "Insert into SpatialFence(FenceGeometry,FeatureID) values('{0}','{1}')", feature.GetWellKnownText(), feature.Id));  
         }  
 
         private DataSet ExecuteQuery(string selectCommandText)  
         {  
             OleDbDataAdapter dataAdapter = null;  
             try  
             {  
                 dataAdapter = new OleDbDataAdapter(selectCommandText, dataConnection);  
                 dataConnection.Open();  
                 DataSet dataSet = new DataSet();  
                 dataSet.Locale = CultureInfo.InvariantCulture;  
                 dataAdapter.Fill(dataSet);  
                 return dataSet;  
             }  
             finally  
             {  
                 if (dataAdapter != null) { dataAdapter.Dispose(); }  
                 if (dataConnection != null) { dataConnection.Close(); }  
             }  
         }  
 
         private int ExecuteNonQuery(string cmdText)  
         {  
             OleDbCommand dataCommand = null;  
             int affectedRowNumber = 0;  
             try  
             {  
                 dataCommand = new OleDbCommand(cmdText, dataConnection);  
                 dataConnection.Open();  
                 affectedRowNumber = dataCommand.ExecuteNonQuery();  
             }  
             finally  
             {  
                 if (dataCommand != null) { dataCommand.Dispose(); }  
                 if (dataConnection != null) { dataConnection.Close(); }  
             }  
 
             return affectedRowNumber;  
         }  
 
         ~TrackingAccessProvider()  
         {  
             Dispose(false);  
         }  
 
         public override void Dispose()  
         {  
             Dispose(true);  
             GC.SuppressFinalize(this);  
         }  
 
         private void Dispose(bool flag)  
         {  
             if (flag)  
             {  
                 if (dataConnection != null)  
                 {  
                     dataConnection.Close();  
                     dataConnection.Dispose();  
                     dataConnection = null;  
                 }  
             }  
         }  
     }  
 }  
 
 

TrackingDataProvider.cs

 using System;  
 using System.Collections.Generic;  
 using System.Collections.ObjectModel;  
 using ThinkGeo.MapSuite.Core;  
 
 namespace ThinkGeo.MapSuite.VehicleTracking  
 {  
     public abstract class TrackingDataProvider : IDisposable  
     {  
         public abstract Dictionary<int, Vehicle> GetCurrentVehicles(DateTime currentTime);  
 
         public abstract Collection<Feature> GetSpatialFences();  
 
         public abstract void DeleteSpatialFences(IEnumerable<Feature> excludeFeatures);  
 
         public abstract int UpdateSpatialFenceByFeature(Feature feature);  
 
         public abstract void InsertSpatialFence(Feature feature);  
 
         public abstract void Dispose();  
     }  
 }  
 

Location.cs

 using System;  
 using ThinkGeo.MapSuite.Core;  
 
 namespace ThinkGeo.MapSuite.VehicleTracking  
 {  
     /// <summary>  
     /// This class specify the basic information for a location.  
     /// </summary>  
     public class Location  
     {  
         public Location()  
             : this(0, 0, 0, DateTime.Now)  
         { }  
 
         public Location(double longitude, double latitude, double speed, DateTime dateTime)  
         {  
             this.Longitude = longitude;  
             this.Latitude = latitude;  
             this.Speed = speed;  
             this.DateTime = dateTime;  
         }  
 
         public double Longitude { get; set; }  
 
         public double Latitude { get; set; }  
 
         public double Speed { get; set; }  
 
         public DateTime DateTime { get; set; }  
 
         public PointShape GetLocationPointShape()  
         {  
             return new PointShape(Longitude, Latitude);  
         }  
     }  
 }  
 
 

Vehicle.cs

 using System.Collections.ObjectModel;  
 
 namespace ThinkGeo.MapSuite.VehicleTracking  
 {  
     /// <summary>  
     /// This class stands for a vehicle.  
     /// </summary>  
     public class Vehicle  
     {  
         private int id;  
         private Location location;  
         private string vehicleName;  
         private string vehicleIconVirtualPath;  
         private bool isInFence;  
         private string motionStateIconVirtualPath;  
         private Collection<Location> historyLocations;  
 
         private Vehicle()  
             : this(0)  
         { }  
 
         public Vehicle(int id)  
         {  
             this.Id = id;  
             this.VehicleName = string.Empty;  
             this.Location = new Location();  
             this.historyLocations = new Collection<Location>();  
         }  
 
         public int Id  
         {  
             get { return id; }  
             set { id = value; }  
         }  
 
         public Location Location  
         {  
             get { return location; }  
             set { location = value; }  
         }  
 
         public Collection<Location> HistoryLocations  
         {  
             get { return historyLocations; }  
         }  
 
         public string VehicleName  
         {  
             get { return vehicleName; }  
             set { vehicleName = value; }  
         }  
 
         public string VehicleIconVirtualPath  
         {  
             get { return vehicleIconVirtualPath; }  
             set { vehicleIconVirtualPath = value; }  
         }  
 
         public bool IsInFence  
         {  
             get { return isInFence; }  
             set { isInFence = value; }  
         }  
 
         public int SpeedDuration  
         {  
             get  
             {  
                 int speedDuration = 0;  
                 double lastSpeed = Location.Speed;  
                 foreach (Location location in HistoryLocations)  
                 {  
                     if (location.Speed == lastSpeed)  
                     {  
                         speedDuration++;  
                     }  
                     else  
                     {  
                         break;  
                     }  
                 }  
 
                 return speedDuration;  
             }  
         }  
 
         public string MotionStateIconVirtualPath  
         {  
             get  
             {  
                 if (MotionState == VehicleMotionState.Idle)  
                 {  
                     motionStateIconVirtualPath = "Images/ball_gray.png";  
                 }  
                 else  
                 {  
                     motionStateIconVirtualPath = "Images/ball_green.png";  
                 }  
                 return motionStateIconVirtualPath;  
             }  
         }  
 
         /// <summary>  
         /// If the Vehicle's speed is not 0 in the passed 4 minutes, we say it is in Motion.  
         /// </summary>  
         /// <returns>State of current vehicle.</returns>  
         public VehicleMotionState MotionState  
         {  
             get  
             {  
                 VehicleMotionState vehicleState = VehicleMotionState.Idle;  
 
                 if (Location.Speed != 0)  
                 {  
                     vehicleState = VehicleMotionState.Motion;  
                 }  
                 else  
                 {  
                     int locationIndex = 0;  
                     foreach (Location historyLocation in HistoryLocations)  
                     {  
                         if (locationIndex > 3)  
                         {  
                             break;  
                         }  
                         else if (historyLocation.Speed != 0)  
                         {  
                             vehicleState = VehicleMotionState.Motion;  
                             break;  
                         }  
                         else  
                         {  
                             locationIndex++;  
                         }  
                     }  
                 }  
 
                 return vehicleState;  
             }  
         }  
     }  
 }  
 
 

VehicleMotionState.cs

 namespace ThinkGeo.MapSuite.VehicleTracking  
 {  
     /// <summary>  
     /// This enumeration specifies the Possible states for Vehicles.  
     /// </summary>  
     public enum VehicleMotionState  
     {  
         Motion = 0,  
         Idle = 1,  
     }  
 }  
 

JsonFeature.cs

 using System.Runtime.Serialization;  
 
 namespace ThinkGeo.MapSuite.VehicleTracking  
 {  
     [DataContract]  
     public class JsonFeature  
     {  
         private string id;  
         private string wkt;  
 
         public JsonFeature(string id, string wkt)  
         {  
             this.id = id;  
             this.wkt = wkt;  
         }  
 
         [DataMember(Name|= "id")]  
         public string Id  
         {  
             get { return id; }  
             set { id = value; }  
         }  
 
         [DataMember(Name|= "wkt")]  
         public string Wkt  
         {  
             get { return wkt; }  
             set { wkt = value; }  
         }  
     }  
 }