<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ThinkGeo.MapSuite.AjaxVehicleTracking.Default" %>
<%@ Register Assembly="WebEdition" Namespace="ThinkGeo.MapSuite.WebEdition" TagPrefix="cc1" %>
Ajax Vehicle Tracking
====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 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(eventArgument);
switch (callbackRequest.Request)
{
case "editFences":
callbackResult = JSONSerializer.Serialize(GetSpatialFencesInJsonFeature());
break;
case "saveFences":
callbackResult = SaveSpatialFences(callbackRequest.Features).ToString();
break;
case "refreshVehicles":
Collection vehicels = GetVehicles(GetAdjustedCurrentDateTime());
UpdateVehiclesToOverlays(vehicels);
List jsonVehicels = vehicels.Select((t) =>
{
return ConvertToJsonVehicle(t);
}).ToList();
callbackResult = JSONSerializer.Serialize(jsonVehicels);
break;
default:
break;
}
}
private JsonVehicle ConvertToJsonVehicle(Vehicle vehicle)
{
Collection historyLocations = new Collection();
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 GetSpatialFencesInJsonFeature()
{
Collection jsonFeatures = new Collection();
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 features)
{
LayerOverlay spatialFenceOverlay = (LayerOverlay)Map1.CustomOverlays["SpatialFenceOverlay"];
InMemoryFeatureLayer spatialFenceLayer = (InMemoryFeatureLayer)spatialFenceOverlay.Layers["SpatialFenceLayer"];
try
{
spatialFenceLayer.Open();
Collection newAddedFeatures = new Collection();
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 modifiedFeatures = new Collection();
Dictionary keyedJsonFeatures = new Dictionary();
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 removedFeatures = new Collection();
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 spatialFencesWithin = spatialFenceLayer.QueryTools.GetFeaturesContaining(pointShape, ReturningColumnsType.NoColumns);
spatialFenceLayer.Close();
bool isInFence = false;
if (spatialFencesWithin.Count > 0)
{
isInFence = true;
}
return isInFence;
}
private Collection GetVehicles(DateTime currentTime)
{
Collection vehicles = new Collection();
// 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 GetSpatialFences()
{
// Get the spatial fences from the database
Collection spatialFences = new Collection();
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 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 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("");
popupHtml.Append("[#VehicleName#] ");
popupHtml.Append(" ");
popupHtml.Append("Longitude: [#Longitude#] ");
popupHtml.Append("Latitude: [#Latitude#] ");
popupHtml.Append("Speed: [#Speed#] ");
popupHtml.Append("Time [#DateTime#] ");
popupHtml.Append("
");
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 = $("
");
for (var i = 0; i < vehiclesJson.length; i++) {
var currentVehicle = vehiclesJson[i];
var tr1 = $(" ");
var tr1Content = $(' ' +
'' + currentVehicle.name + ' ');
tr1Content.appendTo(tr1);
var tr2 = $('');
var motionStatusImg = currentVehicle.motion == 1?"Images/ball_green.png":"Images/ball_gray.png";
var motionLabel = currentVehicle.motion == 1 ? "In Motion" : "Idle";
var tr2Content = $(' ' + motionLabel + ' ');
tr2Content.appendTo(tr2);
var tr3 = $(' ');
var isInFenceLabel = currentVehicle.isIn ? "In Restrict Area" : "Out Of Restrict Area"
var tr3Content = $('Area: ' + isInFenceLabel + ' ');
tr3Content.appendTo(tr3);
var tr4 = $(' ');
var tr4Content = $('Speed: ' + currentVehicle.loc.s + ' mph ');
tr4Content.appendTo(tr4);
var tr5 = $(' ');
var tr5Content = $('Duration: ' + currentVehicle.dur + ' min ');
tr5Content.appendTo(tr5);
var tr6 = $(' ');
var tr6Content = $(' ');
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 GetCurrentVehicles(DateTime currentTime)
{
Dictionary vehiclesList = new Dictionary();
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 historySpeeds = new Collection();
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 GetSpatialFences()
{
Collection spatialFences = new Collection();
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 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 GetCurrentVehicles(DateTime currentTime);
public abstract Collection GetSpatialFences();
public abstract void DeleteSpatialFences(IEnumerable 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
{
///
/// This class specify the basic information for a location.
///
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
{
///
/// This class stands for a vehicle.
///
public class Vehicle
{
private int id;
private Location location;
private string vehicleName;
private string vehicleIconVirtualPath;
private bool isInFence;
private string motionStateIconVirtualPath;
private Collection historyLocations;
private Vehicle()
: this(0)
{ }
public Vehicle(int id)
{
this.Id = id;
this.VehicleName = string.Empty;
this.Location = new Location();
this.historyLocations = new Collection();
}
public int Id
{
get { return id; }
set { id = value; }
}
public Location Location
{
get { return location; }
set { location = value; }
}
public Collection 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;
}
}
///
/// If the Vehicle's speed is not 0 in the passed 4 minutes, we say it is in Motion.
///
/// State of current vehicle.
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
{
///
/// This enumeration specifies the Possible states for Vehicles.
///
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; }
}
}
}