ThinkGeo Cloud
ThinkGeo UI Controls
ThinkGeo Open Source
Help and Support
External Resources
ThinkGeo Cloud
ThinkGeo UI Controls
ThinkGeo Open Source
Help and Support
External Resources
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Globalization; using System.IO; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.VehicleTracking.Properties; namespace ThinkGeo.MapSuite.VehicleTracking { public partial class MainForm : Form { private static readonly DateTime applicationStartTime = DateTime.Now; private static readonly DateTime adjustedStartTime = new DateTime(2009, 7, 10, 11, 31, 0); private static readonly string databasePathFilename = Path.GetFullPath(@"..\..\App_Data\VehicleTrackingDb.mdb"); private static readonly RectangleShape defaultExtent = new RectangleShape(-10785308.531782, 3915876.77825787, -10778644.195048, 3911615.42458998); private Timer timer; private Point originalPoint; private LayerSwitcher layerSwitcher; private PictureBox layerSwitcherButton; private Collection<Vehicle> vehicleItems; private Collection<Layer> baseLayers; private MapEngine mapEngine; private GeographyUnit mapUnit; private Bitmap bitmap; public MainForm() { mapEngine = new MapEngine(); vehicleItems = new Collection<Vehicle>(); baseLayers = new Collection<Layer>(); mapUnit = GeographyUnit.Meter; InitializeComponent(); InitializeBackground(); InitializeHeaderPanel(); InitializeAutoRefreshTimer(); DrawLeftPanelShadow(); originalPoint = CollapsPictureBox.Location; } private void MainForm_Load(object sender, EventArgs e) { InitializeMap(); bitmap = new Bitmap(mapPicture.Width, mapPicture.Height); UpdateSpatialFencesAndVehicles(); } private void AutoRefreshButton_Click(object sender, EventArgs e) { if (!timer.Enabled) { timer.Enabled = true; timer.Start(); AutoRefreshStatusLabel.Text = Resources.OnText; AutoRefreshStatusLabel.Font = new Font(AutoRefreshStatusLabel.Font.FontFamily, AutoRefreshStatusLabel.Font.Size, FontStyle.Regular); AutoRefreshStatusLabel.ForeColor = Color.Black; AutoRefreshRadioButton.Checked = true; } else { timer.Enabled = false; timer.Stop(); AutoRefreshStatusLabel.Text = Resources.OffText; AutoRefreshStatusLabel.Font = new Font(AutoRefreshStatusLabel.Font.FontFamily, AutoRefreshStatusLabel.Font.Size, FontStyle.Bold); AutoRefreshStatusLabel.ForeColor = Color.Red; AutoRefreshRadioButton.Checked = false; } } private void LayerSwitcherPictureBox_Click(object sender, EventArgs e) { PictureBox tempPictureBox = (PictureBox)sender; layerSwitcher.Visible = !layerSwitcher.Visible; tempPictureBox.Image = layerSwitcher.Visible ? Resources.switcher_minimize : Resources.switcher_maxmize; } private void LayerSwitcher_LayerChanged(object sender, LayerChangedLayerSwitcherEventArgs e) { RefreshMap(); } private void LayerSwitcher_LayerChanging(object sender, LayerChangingLayerSwitcherEventArgs e) { // the bing maps requires application Id, // we need to prompt a dialog to allow to input it before using it. BingMapsLayer bingMapsOverlay = e.Layer as BingMapsLayer; if (bingMapsOverlay != null) { e.Cancel = ApplyBingMapsKey(); } } private void RefreshButton_Click(object sender, EventArgs e) { AutoRefreshRadioButton.Checked = timer.Enabled; RefreshButton.Checked = false; UpdateSpatialFencesAndVehicles(); } private void WinformsMap1_MouseMove(object sender, MouseEventArgs e) { PointShape currentPoint = ExtentHelper.ToWorldCoordinate(mapEngine.CurrentExtent, new ScreenPointF(e.X, e.Y), mapPicture.Width, mapPicture.Height); LocationYToolStripStatusLabel.Text = string.Format(CultureInfo.InvariantCulture, "Y:{0:N2}", currentPoint.Y); LocationXToolStripStatusLabel.Text = string.Format(CultureInfo.InvariantCulture, "X:{0:N2}", currentPoint.X); } private void VehicleNameLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { LinkLabel linkLabel = (LinkLabel)sender; ZoomToCurrentVehicle(linkLabel.Text); } private void VehiclePictureBox_Click(object sender, EventArgs e) { if (VehiclePictureBox.DataBindings.Count > 0) { Image currentImage = ((PictureBox)sender).Image; Collection<Vehicle> dataSource = VehiclePictureBox.DataBindings[0].DataSource as Collection<Vehicle>; if (dataSource != null && currentImage != null) { Vehicle vehicle = dataSource.FirstOrDefault(d => d.Icon == currentImage); ZoomToCurrentVehicle(vehicle.Name); } } } private void RefreshRadioButton_CheckedChanged(object sender, EventArgs e) { RadioButton radioButton = sender as RadioButton; if (radioButton != null) { radioButton.FlatAppearance.BorderColor = radioButton.Checked ? Color.FromArgb(136, 136, 136) : Color.White; } } private void ZoomToCurrentVehicle(string vehicleName) { InMemoryFeatureLayer vehicleFeatureLayer = mapEngine.DynamicLayers[vehicleName] as InMemoryFeatureLayer; if (vehicleFeatureLayer != null) { mapEngine.ZoomIntoCenter(60, vehicleFeatureLayer.InternalFeatures[vehicleFeatureLayer.InternalFeatures.Count|- 1], mapPicture.Width, mapPicture.Height); RefreshMap(); } } private void RefreshMap() { if (mapEngine.StaticLayers.Count > 0 && mapPicture.Width > 0) { bitmap = new Bitmap(mapPicture.Width, mapPicture.Height); mapEngine.OpenAllLayers(); mapPicture.CreateGraphics().CompositingMode = CompositingMode.SourceCopy; mapEngine.CurrentExtent = ExtentHelper.GetDrawingExtent(mapEngine.CurrentExtent, mapPicture.Width, mapPicture.Height); mapEngine.DrawStaticLayers(bitmap, mapUnit); mapEngine.DrawDynamicLayers(bitmap, mapUnit); mapEngine.DrawAdornmentLayers(bitmap, mapUnit); mapEngine.CloseAllLayers(); UpdateImageSource(); mapPicture.Refresh(); } } private void UpdateImageSource() { Image oldImage = mapPicture.Image; mapPicture.Image = bitmap; if (oldImage != null) oldImage.Dispose(); } private void InitializeMap() { // Setup the map. mapUnit = GeographyUnit.Meter; mapPicture.BackColor = Color.FromArgb(255, 242, 239, 232); mapPicture.MouseMove += WinformsMap1_MouseMove; mapPicture.Resize += WinformsMap1_Resize; mapEngine.CurrentExtent = ExtentHelper.GetDrawingExtent(defaultExtent, mapPicture.Width, mapPicture.Height); // Add the various overlays such as vehicles, fences etc. // Add the World Map Kit WMS layer. It is a free demo set of data for the world accessable // via WMS. string shapeFilePath = Path.GetFullPath(@"..\..\App_Data\Street.shp"); ShapeFileFeatureLayer shapeFileFeatureLayer = new ShapeFileFeatureLayer(shapeFilePath); shapeFileFeatureLayer.Name = "Local Base Overlay"; ManagedProj4Projection projection = new ManagedProj4Projection(); projection.InternalProjectionParametersString = Proj4Projection.GetDecimalDegreesParametersString(); projection.ExternalProjectionParametersString = Proj4Projection.GetGoogleMapParametersString(); shapeFileFeatureLayer.FeatureSource.Projection = projection; shapeFileFeatureLayer.FeatureSource.Projection.Open(); ValueStyle valueStyle = new ValueStyle(); valueStyle.ColumnName = "ROAD_SUF"; valueStyle.ValueItems.Add(new ValueItem("PKWY", LineStyles.CreateSimpleLineStyle(GeoColor.FromArgb(255, 255, 255, 128), 8, true))); shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(LineStyles.CreateSimpleLineStyle(GeoColor.StandardColors.White, 6, GeoColor.FromArgb(255, 180, 180, 178), 7, true)); shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(valueStyle); TextStyle textStyle = TextStyles.CreateSimpleTextStyle("FULL_NAME", "Arial", 9, DrawingFontStyles.Regular, GeoColor.StandardColors.Black); textStyle.DuplicateRule = LabelDuplicateRule.UnlimitedDuplicateLabels; textStyle.BestPlacement = false; textStyle.OverlappingRule = LabelOverlappingRule.NoOverlapping; textStyle.TextLineSegmentRatio = 8; textStyle.SplineType = SplineType.ForceSplining; shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(textStyle); baseLayers.Add(shapeFileFeatureLayer); shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; mapEngine.StaticLayers.Add(shapeFileFeatureLayer); WorldMapKitLayer worldMapKitWmsLayer = new WorldMapKitLayer(); worldMapKitWmsLayer.Name = "World Map Kit"; worldMapKitWmsLayer.IsVisible = false; worldMapKitWmsLayer.Projection = WorldMapKitProjection.SphericalMercator; baseLayers.Add(worldMapKitWmsLayer); OpenStreetMapLayer openStreetMapLayer = new OpenStreetMapLayer(); openStreetMapLayer.Name = "Open Street Map"; openStreetMapLayer.IsVisible = false; baseLayers.Add(openStreetMapLayer); BingMapsLayer bingMapsAerialLayer = new BingMapsLayer(); bingMapsAerialLayer.Name = "Bing Maps Aerial Map"; bingMapsAerialLayer.IsVisible = false; bingMapsAerialLayer.MapType = BingMapsMapType.Aerial; baseLayers.Add(bingMapsAerialLayer); BingMapsLayer bingMapsRoadLayer = new BingMapsLayer(); bingMapsRoadLayer.Name = "Bing Maps Road Map"; bingMapsRoadLayer.IsVisible = false; bingMapsRoadLayer.MapType = BingMapsMapType.Road; baseLayers.Add(bingMapsRoadLayer); // Initialize SpatialFenceLayer. 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.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; mapEngine.DynamicLayers.Add("SpatialFenceOverlay", spatialFenceLayer); InMemoryFeatureLayer traceLayer = new InMemoryFeatureLayer(); mapEngine.DynamicLayers.Add("TraceOverlay", traceLayer); ScaleBarAdornmentLayer scaleBarAdornmentLayer = new ScaleBarAdornmentLayer(); scaleBarAdornmentLayer.UnitFamily = UnitSystem.Imperial; mapEngine.AdornmentLayers.Add("ScaleBar", scaleBarAdornmentLayer); layerSwitcher = new LayerSwitcher(baseLayers, mapEngine); layerSwitcher.Location = new Point(Width - 208, 85); layerSwitcher.Anchor = AnchorStyles.Right | AnchorStyles.Top; layerSwitcher.Cursor = Cursors.Hand; layerSwitcher.LayerChanged += LayerSwitcher_LayerChanged; layerSwitcher.LayerChanging += LayerSwitcher_LayerChanging; layerSwitcherButton = new PictureBox(); layerSwitcherButton.Anchor = AnchorStyles.Right | AnchorStyles.Top; layerSwitcherButton.Image = Resources.switcher_minimize; layerSwitcherButton.SizeMode = PictureBoxSizeMode.AutoSize; layerSwitcherButton.Location = new Point(layerSwitcher.Location.X + layerSwitcher.Width - layerSwitcherButton.Width - 8, layerSwitcher.Location.Y + 5); layerSwitcherButton.Click += LayerSwitcherPictureBox_Click; Controls.Add(layerSwitcherButton); Controls.Add(layerSwitcher); layerSwitcher.BringToFront(); layerSwitcherButton.BringToFront(); } private void InitializeAutoRefreshTimer() { timer = new Timer(); timer.Enabled = false; timer.Interval = 5000; timer.Tick += (s, e) => UpdateSpatialFencesAndVehicles(); } private void UpdateSpatialFencesAndVehicles() { Layer traceOverlay = mapEngine.DynamicLayers["TraceOverlay"]; Layer spatialFenceOverlay = mapEngine.DynamicLayers["SpatialFenceOverlay"]; Task.Factory.StartNew(() => { lock (spatialFenceOverlay) { // Update the fences from database. UpdateSpatialFences(spatialFenceOverlay); } lock (traceOverlay) { // Update the vehicle locations on the map. DateTime currentTime = GetAdjustedCurrentDateTime(); UpdateVehicles(spatialFenceOverlay, currentTime); } mapPicture.BeginInvoke(new Action(RefreshMap)); }); } private static void UpdateSpatialFences(Layer spatialFenceLayer) { // Get the spatial fence overlay and layer and then clear them InMemoryFeatureLayer tempSpatialFenceLayer = (InMemoryFeatureLayer)spatialFenceLayer; tempSpatialFenceLayer.InternalFeatures.Clear(); // Get the spatial fences from the database Collection<Feature> spatialFences; using (TrackingAccessProvider vehicleProvider = new TrackingAccessProvider(databasePathFilename)) { spatialFences = vehicleProvider.GetSpatialFences(); } // Insert fences from database into fence layer if (spatialFences != null) { foreach (Feature spatialFence in spatialFences) { spatialFence.ColumnValues["Restricted"] = "Restricted"; tempSpatialFenceLayer.InternalFeatures.Add(spatialFence); } } } // Here we update the vehicles from the database. In this sample we create our data provider each time and // when we are finsihed with it we dispose it. This is very safe however you may get better performance // if you were to cache this. We wanted to sample to be clean and safe and it is up to your expertise to // enhance it further private void UpdateVehicles(Layer spatialFenceLayer, DateTime currentTime) { Dictionary<int, Vehicle> vehicles; using (TrackingAccessProvider vehicleProvider = new TrackingAccessProvider(databasePathFilename)) { vehicles = vehicleProvider.GetCurrentVehicles(currentTime); } // Loop through all the vehicle to add the history points if (vehicles != null && vehicles.All(v => !string.IsNullOrEmpty(v.Value.IconPath))) { foreach (int vehicleId in vehicles.Keys) { Vehicle currentVehicle = vehicles[vehicleId]; vehicleItems.Add(currentVehicle); bool isInSpatialFence = CheckIsInSpatialFence(currentVehicle, spatialFenceLayer); currentVehicle.RestrictedAreaText = isInSpatialFence ? "In restricted area" : "Out of restricted area"; InMemoryFeatureLayer currentVehicleLayer; // Initialize vehicle overlay if it's not initialized if (!mapEngine.DynamicLayers.Contains(currentVehicle.Name)) { // Create an InMemoryMarkerOverlay for the vehicle to hold the points and current location currentVehicleLayer = new InMemoryFeatureLayer(); currentVehicleLayer.Open(); currentVehicleLayer.Name = currentVehicle.Id.ToString(CultureInfo.InvariantCulture); currentVehicleLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(GetValueStyle(currentVehicle.IconPath)); currentVehicleLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; // Add all the required columns so we can populate later currentVehicleLayer.FeatureSource.Open(); currentVehicleLayer.Columns.Add(new FeatureSourceColumn("IsCurrentPosition")); currentVehicleLayer.Columns.Add(new FeatureSourceColumn("Speed")); currentVehicleLayer.Columns.Add(new FeatureSourceColumn("DateTime")); currentVehicleLayer.Columns.Add(new FeatureSourceColumn("Longitude")); currentVehicleLayer.Columns.Add(new FeatureSourceColumn("Latitude")); currentVehicleLayer.Columns.Add(new FeatureSourceColumn("VehicleName")); currentVehicleLayer.Columns.Add(new FeatureSourceColumn("Duration")); mapEngine.DynamicLayers.Add(currentVehicle.Name, currentVehicleLayer); } else { // Find the overlay in the map currentVehicleLayer = (InMemoryFeatureLayer)mapEngine.DynamicLayers[currentVehicle.Name]; } // Clear old vehicle's old positions currentVehicleLayer.InternalFeatures.Clear(); // Add the vheicle's bread crumbs foreach (Location historyLocation in currentVehicle.HistoryLocations.Take(6)) { Feature breadcrumbFeature = new Feature(historyLocation.GetLocation().GetWellKnownBinary(), currentVehicle.Name + historyLocation.DateTime.ToString(CultureInfo.InvariantCulture)); breadcrumbFeature.ColumnValues["DateTime"] = historyLocation.DateTime.ToString(CultureInfo.InvariantCulture); breadcrumbFeature.ColumnValues["IsCurrentPosition"] = "IsNotCurrentPosition"; breadcrumbFeature.ColumnValues["Speed"] = historyLocation.Speed.ToString(CultureInfo.InvariantCulture); breadcrumbFeature.ColumnValues["Longitude"] = historyLocation.Longitude.ToString(CultureInfo.InvariantCulture); breadcrumbFeature.ColumnValues["Latitude"] = historyLocation.Latitude.ToString(CultureInfo.InvariantCulture); breadcrumbFeature.ColumnValues["VehicleName"] = currentVehicle.Name; breadcrumbFeature.ColumnValues["Duration"] = currentVehicle.GetSpeedDuration().ToString(CultureInfo.InvariantCulture); currentVehicleLayer.InternalFeatures.Add(breadcrumbFeature.Id, breadcrumbFeature); } // Add the vehicle's latest position Feature latestPositionFeature = new Feature(currentVehicle.Location.GetLocation().GetWellKnownBinary(), currentVehicle.Name); latestPositionFeature.ColumnValues["DateTime"] = currentVehicle.Location.DateTime.ToString(CultureInfo.InvariantCulture); latestPositionFeature.ColumnValues["IsCurrentPosition"] = "IsCurrentPosition"; latestPositionFeature.ColumnValues["Speed"] = currentVehicle.Location.Speed.ToString(CultureInfo.InvariantCulture); latestPositionFeature.ColumnValues["Longitude"] = currentVehicle.Location.Longitude.ToString(CultureInfo.InvariantCulture); latestPositionFeature.ColumnValues["Latitude"] = currentVehicle.Location.Latitude.ToString(CultureInfo.InvariantCulture); latestPositionFeature.ColumnValues["VehicleName"] = currentVehicle.Name; latestPositionFeature.ColumnValues["Duration"] = currentVehicle.GetSpeedDuration().ToString(CultureInfo.InvariantCulture); currentVehicleLayer.InternalFeatures.Add(latestPositionFeature.Id, latestPositionFeature); } } testPanel.BeginInvoke(new Action(() => { if (testPanel.Controls.Count == 0) { for (int i = 0; i < vehicleItems.Count; i++) { VehicleStatus vehicleStatus = new VehicleStatus(vehicleItems[i]); vehicleStatus.VehicleClick += (s, e) => ZoomToCurrentVehicle(e.VehicleName); vehicleStatus.Location = new Point(3, 5 + i * vehicleStatus.Height); testPanel.Controls.Add(vehicleStatus); } } else if (testPanel.Controls.Count == vehicleItems.Count) { for (int i = 0; i < vehicleItems.Count; i++) { ((VehicleStatus)testPanel.Controls[i]).LoadStatus(vehicleItems[i]); } } })); } private bool ApplyBingMapsKey() { bool cancel = false; string bingMapsKey = MapSuiteSampleHelper.GetBingMapsApplicationId(); if (!string.IsNullOrEmpty(bingMapsKey)) { foreach (var bingOverlay in baseLayers.OfType<BingMapsLayer>()) { bingOverlay.ApplicationId = bingMapsKey; } } else { cancel = true; } return cancel; } private static 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 // double realSpentTime = TimeSpan.FromTicks(DateTime.Now.Ticks - applicationStartTime.Ticks).TotalSeconds; int sampleSpentTime = (int)(realSpentTime * 12); DateTime currentSampleTime = adjustedStartTime.AddSeconds(sampleSpentTime); return currentSampleTime; } private static ValueStyle GetValueStyle(string vehicleIconPath) { MemoryStream vehicleStream = new MemoryStream(); Bitmap bitmap = MapSuiteSampleHelper.GetVehicleBitmap(vehicleIconPath); bitmap.Save(vehicleStream, ImageFormat.Png); vehicleStream.Seek(0, SeekOrigin.Begin); MemoryStream historyStream = new MemoryStream(); Resources.ball_green.Save(historyStream, ImageFormat.Png); historyStream.Seek(0, SeekOrigin.Begin); GeoImage vehicleImage = new GeoImage(vehicleStream); GeoImage historyImage = new GeoImage(historyStream); ValueStyle iconValueStyle = new ValueStyle(); iconValueStyle.ColumnName = "IsCurrentPosition"; iconValueStyle.ValueItems.Add(new ValueItem("IsCurrentPosition", new PointStyle(vehicleImage))); iconValueStyle.ValueItems.Add(new ValueItem("IsNotCurrentPosition", new PointStyle(historyImage))); return iconValueStyle; } private static bool CheckIsInSpatialFence(Vehicle vehicle, Layer spatialFenceOverlay) { InMemoryFeatureLayer spatialFenceLayer = (InMemoryFeatureLayer)spatialFenceOverlay; // 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); bool isInSpatialFence; lock (spatialFenceLayer) { spatialFenceLayer.Open(); Collection<Feature> spatialFencesWithin = spatialFenceLayer.QueryTools.GetFeaturesContaining(pointShape, ReturningColumnsType.NoColumns); isInSpatialFence = spatialFencesWithin.Count > 0; } return isInSpatialFence; } #region UI private void WinformsMap1_Resize(object sender, EventArgs e) { if (layerSwitcher != null && layerSwitcherButton != null) { layerSwitcherButton.Left = mapPicture.Width - layerSwitcherButton.Width - 23; layerSwitcherButton.Refresh(); } } private static void SetRoundBorder(PictureBox pictureBox) { Bitmap newBitmap = new Bitmap(pictureBox.Width, pictureBox.Height); using (Graphics g = Graphics.FromImage(newBitmap)) { g.SmoothingMode = SmoothingMode.HighQuality; Rectangle rect = new Rectangle(0, 0, pictureBox.ClientRectangle.Width - 1, pictureBox.ClientRectangle.Height - 1); GraphicsPath path = MapSuiteSampleHelper.CreateRoundPath(rect, 10); g.DrawPath(new Pen(Color.FromArgb(255, 200, 200, 200), 1), path); } pictureBox.Image = newBitmap; } private void ToolBar_ButtonClick(object sender, ToolBarButtonClickEventArgs e) { switch (e.Button.Tag.ToString()) { case "Zoom In": mapEngine.CurrentExtent.ScaleDown(50); break; case "Zoom Out": mapEngine.CurrentExtent.ScaleUp(50); break; case "Full Extent": mapEngine.CurrentExtent = ExtentHelper.GetDrawingExtent(defaultExtent, bitmap.Width, bitmap.Height); break; case "Pan Left": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Left, 20); break; case "Pan Right": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Right, 20); break; case "Pan Up": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Up, 20); break; case "Pan Down": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Down, 20); break; } RefreshMap(); } private void CollapsPictureBox_Click(object sender, EventArgs e) { controlPanel.Visible = !controlPanel.Visible; if (controlPanel.Visible) { CollapsPictureBox.Left = originalPoint.X; grayPanel.Left = CollapsPictureBox.Left + 10; mapPicture.Left = grayPanel.Left + 10; mapPicture.Width = Width - controlPanel.Width - 20; ToolBar.Left = mapPicture.Left; ToolBar.Width = mapPicture.Width; CollapsPictureBox.Image = Resources.collapse; CollapsPictureBox.Refresh(); grayPanel.Refresh(); } else { CollapsPictureBox.Left = 0; grayPanel.Left = CollapsPictureBox.Left + 10; mapPicture.Left = grayPanel.Left + 10; mapPicture.Width = Width - 20; ToolBar.Left = mapPicture.Left; ToolBar.Width = mapPicture.Width; CollapsPictureBox.Image = Resources.expand; CollapsPictureBox.Refresh(); grayPanel.Refresh(); } } private void CollapsPictureBox_MouseEnter(object sender, EventArgs e) { ((PictureBox)sender).BackColor = Color.LightBlue; } private void CollapsPictureBox_MouseLeave(object sender, EventArgs e) { ((PictureBox)sender).BackColor = Color.Transparent; } private void MainForm_Resize(object sender, EventArgs e) { DrawLeftPanelShadow(); } private void DrawLeftPanelShadow() { grayPanel.Height = mapPicture.Height; if (grayPanel.Width > 0 && grayPanel.Height > 0) { Rectangle drawingRectangle = new Rectangle(0, 0, grayPanel.Width, grayPanel.Height); LinearGradientBrush myBrush = new LinearGradientBrush(drawingRectangle, Color.Gray, Color.White, LinearGradientMode.Horizontal); Bitmap tempBitmap = new Bitmap(grayPanel.Width, grayPanel.Height); Graphics g = Graphics.FromImage(tempBitmap); g.FillRectangle(myBrush, drawingRectangle); grayPanel.Image = tempBitmap; grayPanel.Refresh(); CollapsPictureBox.Top = (int)(grayPanel.Height * 0.5 - CollapsPictureBox.Height * 0.5 + grayPanel.Top); CollapsPictureBox.Refresh(); SetRoundBorder(VehiclesGroupPictureBox); } } private void InitializeHeaderPanel() { Label mapSuiteLabel = new Label(); Label demographicLabel = new Label(); mapSuiteLabel.AutoSize = true; mapSuiteLabel.BackColor = Color.Transparent; mapSuiteLabel.Font = new Font("Segoe UI", 11F, FontStyle.Regular, GraphicsUnit.Point, 0); mapSuiteLabel.Location = new Point(12, 10); mapSuiteLabel.TabIndex = 0; mapSuiteLabel.Text = Resources.MapSuiteName; demographicLabel.AutoSize = true; demographicLabel.BackColor = Color.Transparent; demographicLabel.Font = new Font("Segoe UI", 15F, FontStyle.Regular, GraphicsUnit.Point, 0); demographicLabel.Location = new Point(89, 3); demographicLabel.TabIndex = 1; demographicLabel.Text = Resources.VehicleTrackingSampleText; headerPanel.Controls.Add(mapSuiteLabel); headerPanel.Controls.Add(demographicLabel); } private void InitializeBackground() { dataRepeater1.Visible = false; SetRoundBorder(RefreshGroupPictureBox); SetRoundBorder(VehiclesGroupPictureBox); } #endregion } }
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.IconPath = 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.Name = 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 DeleteSpatialFencesExcluding(IEnumerable<Feature> excludeFeatures) { StringBuilder undeleteFeatureIds = new StringBuilder(); foreach (Feature undeleteFeature in excludeFeatures) { undeleteFeatureIds.AppendFormat(CultureInfo.InvariantCulture, "'{0}',", undeleteFeature.Id); } string sql = String.Format(CultureInfo.InvariantCulture, "DELETE FROM SpatialFence WHERE (FeatureID NOT IN ({0}))", undeleteFeatureIds.ToString().TrimEnd(',')); ExecuteNonQuery(sql); } public override int UpdateSpatialFenceByFeature(Feature feature) { return ExecuteNonQuery(String.Format(CultureInfo.InvariantCulture, "UPDATE SpatialFence SET FenceGeometry = '{0}' WHERE (FeatureID = '{1}')", feature.GetWellKnownText(), feature.Id)); } 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 commandText) { OleDbCommand dataCommand = null; int affectedRowNumber; try { dataCommand = new OleDbCommand(commandText, 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; } } } } }
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 DeleteSpatialFencesExcluding(IEnumerable<Feature> excludeFeatures); public abstract int UpdateSpatialFenceByFeature(Feature feature); public abstract void InsertSpatialFence(Feature feature); public abstract void Dispose(); } }
using System; using ThinkGeo.MapSuite.Core; namespace ThinkGeo.MapSuite.VehicleTracking { /// <summary> /// This class specify the basic information for a location. /// </summary> public class Location { private double speed; private double latitude; private double longitude; private DateTime dateTime; public Location() : this(0, 0, 0, DateTime.Now) { } public Location(double longitude, double latitude, double speed, DateTime dateTime) { Longitude = longitude; Latitude = latitude; Speed = speed; DateTime = dateTime; } public double Speed { get { return speed; } set { speed = value; } } public double Longitude { get { return longitude; } set { longitude = value; } } public double Latitude { get { return latitude; } set { latitude = value; } } public DateTime DateTime { get { return dateTime; } set { dateTime = value; } } public PointShape GetLocation() { return new PointShape(Longitude, Latitude); } } }
using System; namespace ThinkGeo.MapSuite.VehicleTracking { [Serializable] public enum TrackMode { None = 0, Point = 1, Line = 2, Polygon = 3, Rectangle = 4, Square = 5, Circle = 6, Ellipse = 7, StraightLine = 8, Freehand = 9, Custom = 10, } }
using System.Collections.ObjectModel; using System.Drawing; namespace ThinkGeo.MapSuite.VehicleTracking { /// <summary> /// This class stands for a vehicle. /// </summary> public class Vehicle { private int id; private string name; private string iconPath; private Location location; private string restrictedAreaText; private Collection<Location> historyLocations; public Vehicle() : this(0) { } public Vehicle(int id) { Id = id; Name = string.Empty; Location = new Location(); historyLocations = new Collection<Location>(); } public Bitmap Icon { get { return MapSuiteSampleHelper.GetVehicleBitmap(IconPath); } } public string RestrictedAreaText { get { return restrictedAreaText; } set { restrictedAreaText = value; } } public int Id { get { return id; } set { id = value; } } public Location Location { get { return location; } set { location = value; } } public string Name { get { return name; } set { name = value; } } public string IconPath { get { return iconPath; } set { iconPath = value; } } public Collection<Location> HistoryLocations { get { return historyLocations; } } public int GetSpeedDuration() { int speedDuration = 0; double lastSpeed = Location.Speed; foreach (Location tempLocation in HistoryLocations) { if (tempLocation.Speed == lastSpeed) speedDuration++; else break; } return speedDuration; } /// <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 GetCurrentState() { VehicleMotionState vehicleState = VehicleMotionState.Idle; if (Location.Speed != 0) { vehicleState = VehicleMotionState.Motion; } else { int locationIndex = 0; foreach (Location historyLocation in HistoryLocations) { if (locationIndex > 3) { break; } if (historyLocation.Speed != 0) { vehicleState = VehicleMotionState.Motion; break; } locationIndex++; } } return vehicleState; } } }
namespace ThinkGeo.MapSuite.VehicleTracking { /// <summary> /// This enumeration specifies the Possible states for Vehicles. /// </summary> public enum VehicleMotionState { Motion = 0, Idle = 1, } }
using System; using System.Configuration; using System.Drawing; using System.Drawing.Drawing2D; using System.Globalization; using System.IO; using System.Net; using System.Reflection; using System.Windows.Forms; using System.Xml; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.VehicleTracking.Properties; namespace ThinkGeo.MapSuite.VehicleTracking { public static class MapSuiteSampleHelper { public static GraphicsPath CreateRoundPath(Rectangle rect, int arcRadius) { var path = new GraphicsPath(); if (rect.Width == 0 || rect.Height == 0) { return path; } if (arcRadius > 0) { path.AddArc(rect.Left, rect.Top, arcRadius, arcRadius, 180, 90); path.AddArc(rect.Right - arcRadius, rect.Top, arcRadius, arcRadius, -90, 90); path.AddArc(rect.Right - arcRadius, rect.Bottom - arcRadius, arcRadius, arcRadius, 0, 90); path.AddArc(rect.Left, rect.Bottom - arcRadius, arcRadius, arcRadius, 90, 90); } path.CloseFigure(); return path; } internal static Bitmap GetVehicleBitmap(string vehicleIconVirtualPath) { string fileName = Path.GetFileNameWithoutExtension(vehicleIconVirtualPath); switch (fileName) { case "Robert_vehicle": return Resources.Robert_vehicle; case "Bob_vehicle": return Resources.Bob_vehicle; case "Jim_vehicle": return Resources.Jim_vehicle; case "Micheal_vehicle": return Resources.Micheal_vehicle; case "Jenny_vehicle": return Resources.Jenny_vehicle; default: return Resources.Jeremy_vehicle; } } public static string GetBingMapsApplicationId() { string bingMapsKey = string.Empty; string exePath = Assembly.GetExecutingAssembly().Location; Configuration config = ConfigurationManager.OpenExeConfiguration(exePath); KeyValueConfigurationElement appMapKeySetting = config.AppSettings.Settings["BingMapKey"]; if (appMapKeySetting != null) { bingMapsKey = appMapKeySetting.Value; } else { BingMapsApplicationIdPromptForm inputBingMapKeyWindow = new BingMapsApplicationIdPromptForm(); inputBingMapKeyWindow.StartPosition = FormStartPosition.CenterParent; if (inputBingMapKeyWindow.ShowDialog() == DialogResult.OK && IsBingMapsKeyValid(inputBingMapKeyWindow.ApplicationId)) { SaveBingMapsKey(inputBingMapKeyWindow.ApplicationId); bingMapsKey = inputBingMapKeyWindow.ApplicationId; } } return bingMapsKey; } private static void SaveBingMapsKey(string bingMapsKey) { string exePath = Assembly.GetExecutingAssembly().Location; Configuration config = ConfigurationManager.OpenExeConfiguration(exePath); config.AppSettings.Settings.Add("BingMapKey", bingMapsKey); config.Save(); ConfigurationManager.RefreshSection("appSettings"); } private static bool IsBingMapsKeyValid(string bingMapsKey) { bool result = false; const string loginServiceTemplate = "http://dev.virtualearth.net/REST/v1/Imagery/Metadata/{0}?&incl=ImageryProviders&o=xml&key={1}"; try { string loginServiceUri = string.Format(CultureInfo.InvariantCulture, loginServiceTemplate, BingMapsMapType.Road, bingMapsKey); WebRequest request = WebRequest.Create(loginServiceUri); WebResponse response = request.GetResponse(); Stream stream = response.GetResponseStream(); if (stream != null) { XmlDocument xDoc = new XmlDocument(); xDoc.Load(stream); XmlNamespaceManager nsmgr = new XmlNamespaceManager(xDoc.NameTable); nsmgr.AddNamespace("bing", "http://schemas.microsoft.com/search/local/ws/rest/v1"); XmlNode root = xDoc.SelectSingleNode("bing:Response", nsmgr); if (root != null) { XmlNode imageUrlElement = root.SelectSingleNode("bing:ResourceSets/bing:ResourceSet/bing:Resources/bing:ImageryMetadata/bing:ImageUrl", nsmgr); XmlNodeList subdomainsElement = root.SelectNodes("bing:ResourceSets/bing:ResourceSet/bing:Resources/bing:ImageryMetadata/bing:ImageUrlSubdomains/bing:string", nsmgr); if (imageUrlElement != null && subdomainsElement != null) { result = true; } } } } catch (Exception ex) { MessageBox.Show(ex.Message, Resources.WarningText, MessageBoxButtons.OK, MessageBoxIcon.Warning); } return result; } } }