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
<UserControl x:Class="ThinkGeo.MapSuite.VehicleTracking.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:ThinkGeo.MapSuite.VehicleTracking" xmlns:silverlight="clr-namespace:ThinkGeo.MapSuite.SilverlightEdition;assembly=SilverlightEdition" mc:Ignorable="d" Width="Auto" Height="Auto"> <UserControl.Resources> <Style TargetType="ButtonBase"> </Style> </UserControl.Resources> <Grid Style="{StaticResource sampleBody}"> <Grid.RowDefinitions> <RowDefinition Height="auto" /> <RowDefinition Height="*" /> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <local:Header Grid.Row="0"/> <Grid Grid.Row="1" SizeChanged="Grid_SizeChanged"> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid Margin="5 0 0 0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="5" /> </Grid.ColumnDefinitions> <Grid x:Name="statusPanel" Grid.Row="0" Grid.Column="0" Margin="0 0 5 10"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <TextBlock Grid.Row="0" Text="Click to refresh vehicles:" Style="{StaticResource h5}" Margin="0 5 0 5"/> <Border Grid.Row="1" Style="{StaticResource fileset}"> <StackPanel> <StackPanel Orientation="Horizontal"> <ToggleButton x:Name="AutoRefreshToggleButton" Content="Image/AutoRefresh.png" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Click="AutoRefreshClick" ToolTipService.ToolTip="Auto Refresh" Template="{StaticResource newAutoRefreshTemplate}" Margin="{StaticResource normalMargin}" /> <TextBlock Text="Auto Refresh: " Style="{StaticResource bodyText}" VerticalAlignment="Center"/> <TextBlock x:Name="OnOffTextBlock" Text="Off" FontWeight="SemiBold" Foreground="Red" VerticalAlignment="Center"/> </StackPanel> <StackPanel Orientation="Horizontal" Margin="0 5 0 0"> <Button Content="Image/RefreshManually.png" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Click="RefreshClick" ToolTipService.ToolTip="Refresh" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource normalMargin}" /> <TextBlock Text="Refresh Manually" Style="{StaticResource bodyText}" VerticalAlignment="Center" /> </StackPanel> </StackPanel> </Border> <TextBlock Grid.Row="2" Text="Interact with the map using these tools:" Style="{StaticResource h5}" Margin="0 5 0 5"/> <Border Grid.Row="3" Style="{StaticResource fileset}"> <StackPanel Orientation="Horizontal"> <RadioButton IsChecked="True" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" GroupName="Map" Content="Image/pan.png" Click="ControlMapClick" ToolTipService.ToolTip="Pan map" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource normalMargin}" /> <RadioButton GroupName="Map" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Content="Image/draw.png" ToolTipService.ToolTip="Draw fences" Click="DrawFenceClick" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource normalMargin}" /> <RadioButton GroupName="Map" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Content="Image/measure.png" ToolTipService.ToolTip="Measure distance" Click="MeasureDistanceClick" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource normalMargin}" /> </StackPanel> </Border> <StackPanel Grid.Row="4" x:Name="editPanel" Orientation="Horizontal" Visibility="Collapsed" > <RadioButton x:Name="DrawNewFenceRadioButton" Content="Image/draw_polygon.png" IsChecked="True" GroupName="Edit" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Click="DrawNewFenceClick" ToolTipService.ToolTip="Track new fences" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}"/> <RadioButton x:Name="EditFenceRadioButton" Content="Image/edit_polygon.png" GroupName="Edit" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Click="EditFenceClick" ToolTipService.ToolTip="Edit the selected fence" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}"/> <Button Content="Image/Remove_Polygon.png" Click="DeleteFenceClick" ToolTipService.ToolTip="Delete" Template="{StaticResource imageButtonTemplate}" Margin="15 0 5 0" /> <Button Content="Image/save.png" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Click="SaveFenceClick" ToolTipService.ToolTip="Save" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}" /> <Button Content="Image/clear.png" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Click="CancelEditClick" ToolTipService.ToolTip="Delete" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}" /> </StackPanel> <StackPanel Grid.Row="4" Orientation="Horizontal" x:Name="measurePanel" Visibility="Collapsed"> <RadioButton x:Name="rbtnMeasureLine" GroupName="Measure" IsChecked="True" Content="Image/line.png" Click="MeasureLineClick" ToolTipService.ToolTip="Measure line" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}"/> <RadioButton x:Name="rbtnMeasurePolygon" GroupName="Measure" Content="Image/polygon.png" Click="MeasurePolygonClick" ToolTipService.ToolTip="Measure polygon" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}"/> <Button Content="Image/clear.png" Click="CancelMeasureClick" ToolTipService.ToolTip="Cancel" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}" /> <TextBlock Text="Unit:" VerticalAlignment="Center" Margin="10 0 5 0" /> <ComboBox ItemsSource="{Binding UnitSystems}" SelectedItem="{Binding SelectedUnitSystem,Mode=TwoWay}" Height="20" Width="78" VerticalAlignment="Center"> <ComboBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding .}" VerticalAlignment="Center" /> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> </StackPanel> <Border Grid.Row="5" Style="{StaticResource headerBanner}"> <TextBlock Style="{StaticResource headerText2}" Text="Tracked Vehicles"></TextBlock> </Border> <Border Grid.Row="6" Style="{StaticResource fileset}" Width="300" > <ScrollViewer VerticalScrollBarVisibility="Auto"> <ItemsControl ItemsSource="{Binding Vehicles}" > <ItemsControl.ItemTemplate> <DataTemplate> <Grid Margin="0 0 0 10"> <Grid.ColumnDefinitions> <ColumnDefinition Width="40" /> <ColumnDefinition Width="5" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Button Content="{Binding IconUri}" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Click="ZoomToVehicleClick" Template="{StaticResource imageButtonTemplate}" HorizontalAlignment="Center" VerticalAlignment="Top" /> <StackPanel Grid.Column="2"> <HyperlinkButton Click="ZoomToVehicleClick" Foreground="Black" FontWeight="Bold" FontSize="12" > <TextBlock Text="{Binding OwnerName}" TextDecorations="Underline" /> </HyperlinkButton> <StackPanel Orientation="Horizontal"> <Image Stretch="None" Source="Image/ball_green.png" /> <TextBlock Text="{Binding Status}" Style="{StaticResource bodyText}" Foreground="#339900" Margin="3 0 0 0" /> </StackPanel> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="5" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <TextBlock Style="{StaticResource bodyText}" Text="Area:" /> <TextBlock Style="{StaticResource bodyText}" Text="Speed:" Grid.Row="1" /> <TextBlock Style="{StaticResource bodyText}" Text="Duration:" Grid.Row="2" /> <TextBlock Style="{StaticResource bodyText}" Text="{Binding Area}" Grid.Column="2" /> <TextBlock Style="{StaticResource bodyText}" Text="{Binding Speed}" Grid.Row="1" Grid.Column="2" /> <TextBlock Style="{StaticResource bodyText}" Text="{Binding Duration}" Grid.Row="2" Grid.Column="2" /> </Grid> </StackPanel> </Grid> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </ScrollViewer> </Border> </Grid> <CheckBox x:Name="toggle" Template="{StaticResource collapseExpandTemplate}" Content="Image/collapse.png" Click="CollapsExpandClick" Grid.Column="1" Cursor="Hand" Background="Transparent" BorderBrush="Transparent" /> <Rectangle Grid.Column="2"> <Rectangle.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="1,0"> <GradientStop Color="#5c707d" Offset="0"></GradientStop> <GradientStop Color="#305c707d" Offset="1"></GradientStop> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> </Grid> <silverlight:Map Grid.Column="1" x:Name="map1" MouseMove="Map_MouseMove" HorizontalAlignment="Left" VerticalAlignment="Top" Click="WpfMap_MapClick" /> <local:OverlaySwitcher x:Name="overlaySwitcher" OverlayNames="{Binding OverlayNames}" DefaultOverlayName="{Binding DefaultOverlayName}" ExpandImageUri="/MapSuiteVehicleTracking;component/Image/switcher_minimize.png" CollapseImageUri="/MapSuiteVehicleTracking;component/Image/switcher_maxmize.png" OverlayChanged="OverlaySwitcher_OverlayChanged" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Top" Width="200" Height="Auto" /> <Grid Grid.Column="1" x:Name="_loading" Visibility="Collapsed" Background="#30D6D6D6" > <local:LoadingImageUserControl /> </Grid> </Grid> <Border Grid.Row="2" BorderBrush="Gray" BorderThickness="0 1 0 0"> <Grid Height="31" Background="#e2e2e2"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="5" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBlock x:Name="LocationXTextBlock" Width="105" VerticalAlignment="Center" Grid.Column="1" /> <TextBlock x:Name="LocationYTextBlock" Width="100" VerticalAlignment="Center" Grid.Column="3" /> </Grid> </Border> <!--<local:Bottom Grid.Row="2" Height="45" ></local:Bottom>--> </Grid> </UserControl>
using System; using System.Collections.ObjectModel; using System.Globalization; using System.IO; using System.IO.IsolatedStorage; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Effects; using System.Windows.Threading; using ThinkGeo.MapSuite.SilverlightCore; using ThinkGeo.MapSuite.SilverlightEdition; using ThinkGeo.MapSuite.VehicleTracking.ServiceReference; namespace ThinkGeo.MapSuite.VehicleTracking { public partial class MainPage { private const string worldMapKitName = "World Map Kit Map"; private const string openStreetMapName = "Open Street Map"; private const string bingMapsKeyFileName = "BingMapsKey.key"; private const string bingMapsRoadMapName = "Bing Maps Road Map"; private const string bingMapsAerialMapName = "Bing Maps Aerial Map"; private static readonly DateTime applicationStartTime = DateTime.Now; private static readonly DateTime adjustedStartTime = new DateTime(2009, 7, 10, 11, 31, 0); private bool isFirst = true; private Storyboard storyboard; private DropShadowEffect dropShadowEffect; private VehicleTrackingViewModel viewModel; private DispatcherTimer autoRefreshDispatcherTimer; public MainPage() { InitializeComponent(); dropShadowEffect = new DropShadowEffect(); dropShadowEffect.Opacity = 0.8; dropShadowEffect.ShadowDepth = 2; dropShadowEffect.Color = Color.FromArgb(255, 254, 111, 63); viewModel = new VehicleTrackingViewModel(); viewModel.OverlayNames.Add(worldMapKitName); viewModel.OverlayNames.Add(openStreetMapName); viewModel.OverlayNames.Add(bingMapsRoadMapName); viewModel.OverlayNames.Add(bingMapsAerialMapName); DataContext = viewModel; Application.Current.Host.Content.IsFullScreen = true; autoRefreshDispatcherTimer = new DispatcherTimer(); autoRefreshDispatcherTimer.Interval = TimeSpan.FromMilliseconds(5000); autoRefreshDispatcherTimer.Tick += (s, e) => UpdateSpatialFencesAndVehicles(); AutoRefreshToggleButton.IsChecked = true; StartAutoRefresh(AutoRefreshToggleButton); } private void SetupBaseOverlays() { // Add the World Map Kit WMS layer. It is a free demo set of data for the world accessable with WMS. WorldMapKitWmsSilverlightOverlay worldMapKitWmsOverlay = new WorldMapKitWmsSilverlightOverlay(); worldMapKitWmsOverlay.Projection = WorldMapKitProjection.SphericalMercator; map1.Overlays.Add(worldMapKitName, worldMapKitWmsOverlay); // 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, false, GeoColor.StandardColors.Black, GeoColor.StandardColors.White, 2); spatialFenceLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; // Initialize SpatialFenceOverlay. LayerOverlay spatialFenceOverlay = new LayerOverlay(); spatialFenceOverlay.Name = "SpatialFenceOverlay"; spatialFenceOverlay.Layers.Add("SpatialFenceLayer", spatialFenceLayer); LayerOverlay traceOverlay = new LayerOverlay(); traceOverlay.Name = "TraceOverlay"; map1.Overlays.Add("SpatialFenceOverlay", spatialFenceOverlay); map1.Overlays.Add("TraceOverlay", traceOverlay); } private void UpdateSpatialFencesAndVehicles(bool needRefresh = true) { // Update the fences from database. UpdateSpatialFences(); // Update the vehicle locations on the map. UpdateVehicles(); if (needRefresh) map1.Refresh(); } private void UpdateSpatialFences() { // Get the spatial fence overlay and layer and then clear them LayerOverlay spatialFenceOverlay = (LayerOverlay)map1.Overlays["SpatialFenceOverlay"]; InMemoryFeatureLayer spatialFenceLayer = (InMemoryFeatureLayer)spatialFenceOverlay.Layers["SpatialFenceLayer"]; spatialFenceLayer.InternalFeatures.Clear(); TrackingAccessPrividerSourceClient client = new TrackingAccessPrividerSourceClient(); client.GetSpatialFencesCompleted += (s, e) => { // Insert fences from database into fence layer if (e.Result != null) { foreach (string spatialFence in e.Result) { var array = spatialFence.Split('|'); if (array.Length == 2) { Feature feature = new Feature(array[0], array[1]); feature.ColumnValues["Restricted"] = "Restricted"; if (spatialFenceLayer.InternalFeatures.Contains(array[1])) { spatialFenceLayer.InternalFeatures.Remove(array[1]); } spatialFenceLayer.InternalFeatures.Add(array[1], feature); } } spatialFenceOverlay.Refresh(); } }; client.GetSpatialFencesAsync(); } // 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() { LayerOverlay traceOverlay = (LayerOverlay)map1.Overlays["TraceOverlay"]; TrackingAccessPrividerSourceClient client = new TrackingAccessPrividerSourceClient(); client.GetCurrentVehiclesCompleted += (s, e) => { // Loop through all the vehicle to add the history points if (e.Result != null && e.Result.All(v => !string.IsNullOrEmpty(v.Value.VehicleIconVirtualPath))) { foreach (int vehicleId in e.Result.Keys) { Vehicle currentVehicle = e.Result[vehicleId]; VehicleViewModel tempVehicleViewModel = viewModel.Vehicles.FirstOrDefault(v => v.OwnerName == currentVehicle.VehicleName); if (tempVehicleViewModel == null) { tempVehicleViewModel = new VehicleViewModel(currentVehicle); Dispatcher.BeginInvoke(() => viewModel.Vehicles.Add(tempVehicleViewModel)); } else { tempVehicleViewModel.Vehicle = currentVehicle; tempVehicleViewModel.Load(); } bool isInSpatialFence = CheckIsInSpatialFence(currentVehicle); tempVehicleViewModel.Area = isInSpatialFence ? "In restricted area" : "Out of restricted area"; InMemoryFeatureLayer currentVehicleLayer; // Initialize vehicle overlay if it's not initialized if (!traceOverlay.Layers.Contains(currentVehicle.VehicleName)) { // 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.VehicleIconVirtualPath)); 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")); Dispatcher.BeginInvoke(() => { lock (traceOverlay.Layers) { traceOverlay.Layers.Add(currentVehicle.VehicleName, currentVehicleLayer); traceOverlay.Refresh(); } }); } else { // Find the overlay in the map currentVehicleLayer = (InMemoryFeatureLayer)traceOverlay.Layers[currentVehicle.VehicleName]; } // 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(MapSuiteSampleHelper.GetLocationPointShape(historyLocation).GetWellKnownBinary(), currentVehicle.VehicleName + 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.VehicleName; breadcrumbFeature.ColumnValues["Duration"] = MapSuiteSampleHelper.GetSpeedDuration(currentVehicle).ToString(CultureInfo.InvariantCulture); currentVehicleLayer.InternalFeatures.Add(breadcrumbFeature.Id, breadcrumbFeature); } // Add the vehicle's latest position Feature latestPositionFeature = new Feature(MapSuiteSampleHelper.GetLocationPointShape(currentVehicle.Location).GetWellKnownBinary(), currentVehicle.VehicleName); 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.VehicleName; latestPositionFeature.ColumnValues["Duration"] = MapSuiteSampleHelper.GetSpeedDuration(currentVehicle).ToString(CultureInfo.InvariantCulture); currentVehicleLayer.InternalFeatures.Add(latestPositionFeature.Id, latestPositionFeature); } traceOverlay.Refresh(); } }; DateTime currentTime = GetAdjustedCurrentDateTime(); client.GetCurrentVehiclesAsync(currentTime); } private bool CheckIsInSpatialFence(Vehicle vehicle) { LayerOverlay spatialFenceOverlay = (LayerOverlay)map1.Overlays["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); bool isInSpatialFence = spatialFencesWithin.Count > 0; return isInSpatialFence; } private static ValueStyle GetValueStyle(string vehicleIconVirtualPath) { GeoImage vehicleImage = GetGeoImage(new Uri("/MapSuiteVehicleTracking;component/Image/" + vehicleIconVirtualPath, UriKind.RelativeOrAbsolute)); GeoImage historyImage = GetGeoImage(new Uri("/MapSuiteVehicleTracking;component/Image/ball_green.png", UriKind.RelativeOrAbsolute)); ValueStyle iconValueStyle = new ValueStyle(); iconValueStyle.ColumnName = "IsCurrentPosition"; iconValueStyle.ValueItems.Add(new ValueItem("IsCurrentPosition", new PointStyle(vehicleImage) { XOffsetInPixel = -16, YOffsetInPixel = -16 })); iconValueStyle.ValueItems.Add(new ValueItem("IsNotCurrentPosition", new PointStyle(historyImage))); return iconValueStyle; } private static GeoImage GetGeoImage(Uri uri) { Stream stream = Application.GetResourceStream(uri).Stream; stream.Seek(0, SeekOrigin.Begin); GeoImage geoImage = new GeoImage(); geoImage.SourceStream = stream; return geoImage; } private void AutoRefreshClick(object sender, RoutedEventArgs e) { ToggleButton autoRefreshToggleButton = (ToggleButton)sender; StartAutoRefresh(autoRefreshToggleButton); } private void StartAutoRefresh(ToggleButton autoRefreshToggleButton) { if (autoRefreshToggleButton.IsChecked.GetValueOrDefault()) { autoRefreshDispatcherTimer.Start(); OnOffTextBlock.Foreground = new SolidColorBrush(Colors.Black); OnOffTextBlock.Text = "On"; if (storyboard == null) { RotateTransform rotateTransform = new RotateTransform(); rotateTransform.CenterX = 14; rotateTransform.CenterY = 14; autoRefreshToggleButton.RenderTransform = rotateTransform; DoubleAnimation AscendingDoubleAnimation = new DoubleAnimation(); AscendingDoubleAnimation.From = 0; AscendingDoubleAnimation.To = 360; AscendingDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever; AscendingDoubleAnimation.Duration = TimeSpan.FromSeconds(1.5); storyboard = new Storyboard(); storyboard.Children.Add(AscendingDoubleAnimation); Storyboard.SetTarget(AscendingDoubleAnimation, rotateTransform); Storyboard.SetTargetProperty(AscendingDoubleAnimation, new PropertyPath("Angle")); } storyboard.Begin(); } else { autoRefreshDispatcherTimer.Stop(); OnOffTextBlock.Foreground = new SolidColorBrush(Colors.Red); OnOffTextBlock.Text = "Off"; storyboard.Stop(); } } private void RefreshClick(object sender, RoutedEventArgs e) { UpdateSpatialFencesAndVehicles(); } private void WpfMap_MapClick(object sender, MapClickEventArgs e) { RectangleShape rectangle = GetBufferedRectangle(e.WorldPointShape); LayerOverlay traceOverlay = (LayerOverlay)map1.Overlays["TraceOverlay"]; map1.Popups.Clear(); lock (traceOverlay.Layers) { foreach (Layer layer in traceOverlay.Layers) { InMemoryFeatureLayer vehicleLayer = (InMemoryFeatureLayer)layer; vehicleLayer.Open(); if (vehicleLayer.GetBoundingBox().Intersects(rectangle)) { var resultFeatures = vehicleLayer.QueryTools.GetFeaturesIntersecting(rectangle, ReturningColumnsType.AllColumns); if (resultFeatures.Count > 0) { ShowPopup(e.WorldPointShape, GetVehicleInfor(resultFeatures[0])); break; } } } } } private void ShowPopup(PointShape pointShape, string popupContent) { GeoPopup popup = new GeoPopup(pointShape); TextBlock textBlock = new TextBlock { Foreground = new SolidColorBrush(Colors.Black), Text = popupContent, Margin = new Thickness(5) }; popup.Content = textBlock; popup.Width = textBlock.ActualWidth + 32; popup.Height = textBlock.ActualHeight + 20; map1.Popups.Add(popup); map1.Refresh(); } private RectangleShape GetBufferedRectangle(PointShape pointShape) { PointShape clickedPoint = pointShape; double currentResolution = map1.CurrentScale / (39.3701 * 96); double offset = currentResolution * 16; RectangleShape rectangle = new RectangleShape(clickedPoint.X - offset, clickedPoint.Y + offset, clickedPoint.X + offset, clickedPoint.Y - offset); return rectangle; } private static string GetVehicleInfor(Feature feature) { ProjNetProjection proj4 = new ProjNetProjection(4326, 900913); proj4.Open(); string longitudeString = "--"; string latitudeString = "--"; double longitude = double.NaN; double latitude = double.NaN; if (double.TryParse(feature.ColumnValues["Longitude"], out longitude) && double.TryParse(feature.ColumnValues["Latitude"], out latitude)) { PointShape pointShape = new PointShape(longitude, latitude); pointShape = (PointShape)proj4.ConvertToInternalProjection(pointShape); longitudeString = pointShape.X.ToString("N2", CultureInfo.InvariantCulture); latitudeString = pointShape.Y.ToString("N2", CultureInfo.InvariantCulture); } proj4.Close(); return string.Format(CultureInfo.InvariantCulture, "Name:{0}\r\nLongitude:{1}\r\nLatitude:{2}\r\nSpeed:{3}mph\r\nTime:{4}" , feature.ColumnValues["VehicleName"] , longitudeString , latitudeString , feature.ColumnValues["Speed"] , feature.ColumnValues["DateTime"]); } private void ControlMapClick(object sender, RoutedEventArgs e) { if (((RadioButton)sender).IsChecked.GetValueOrDefault()) { editPanel.Visibility = Visibility.Collapsed; measurePanel.Visibility = Visibility.Collapsed; map1.TrackOverlay.TrackMode = TrackMode.None; } } private void DrawFenceClick(object sender, RoutedEventArgs e) { if (((RadioButton)sender).IsChecked.GetValueOrDefault()) { map1.TrackOverlay.TrackEnded -= TrackOverlay_TrackEnded; map1.TrackOverlay.TrackMode = TrackMode.Polygon; editPanel.Visibility = Visibility.Visible; measurePanel.Visibility = Visibility.Collapsed; } } private void MeasureLineClick(object sender, RoutedEventArgs e) { map1.TrackOverlay.TrackMode = TrackMode.Line; } private void MeasurePolygonClick(object sender, RoutedEventArgs e) { map1.TrackOverlay.TrackMode = TrackMode.Polygon; } private void CancelMeasureClick(object sender, RoutedEventArgs e) { ClearMeasuresAndPopups(); } private void ClearMeasuresAndPopups() { foreach (Feature measureFeature in map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Where(f => (string)f.Tag == "Measure").ToList()) { map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Remove(measureFeature); } map1.Popups.Clear(); map1.TrackOverlay.Refresh(); } private void MeasureDistanceClick(object sender, RoutedEventArgs e) { if (((RadioButton)sender).IsChecked.GetValueOrDefault()) { map1.TrackOverlay.MapMouseClick -= TrackOverlay_MapMouseClick; if (map1.EditOverlay.EditShapesLayer.InternalFeatures.Count > 0) { SaveSpatialFences(() => UpdateSpatialFencesAndVehicles()); } else if (map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Count > 0) { CancelEdit(); } editPanel.Visibility = Visibility.Collapsed; measurePanel.Visibility = Visibility.Visible; map1.TrackOverlay.TrackMode = rbtnMeasureLine.IsChecked.GetValueOrDefault() ? TrackMode.Line : TrackMode.Polygon; map1.TrackOverlay.TrackStarting -= TrackOverlay_TrackStarting; map1.TrackOverlay.TrackStarting += TrackOverlay_TrackStarting; map1.TrackOverlay.TrackEnded -= TrackOverlay_TrackEnded; map1.TrackOverlay.TrackEnded += TrackOverlay_TrackEnded; } } private void TrackOverlay_TrackStarting(object sender, TrackStartingTrackInteractiveOverlayEventArgs e) { if (map1.TrackOverlay.TrackMode == TrackMode.Line || map1.TrackOverlay.TrackMode == TrackMode.Polygon) { ClearMeasuresAndPopups(); } } private void TrackOverlay_TrackEnded(object sender, TrackEndedTrackInteractiveOverlayEventArgs e) { if (map1.TrackOverlay.TrackMode == TrackMode.Polygon) { PolygonShape polygonShape = e.TrackShape as PolygonShape; if (polygonShape != null) { double area = -1; string areaUnit = "sqr.m."; if (viewModel.SelectedUnitSystem == UnitSystem.Metric) { areaUnit = "sqr.m."; area = polygonShape.GetArea(GeographyUnit.Meter, AreaUnit.SquareMeters); } else if (viewModel.SelectedUnitSystem == UnitSystem.Imperial) { areaUnit = "ac."; area = polygonShape.GetArea(GeographyUnit.Meter, AreaUnit.Acres); } if (area > 0) { ShowPopup(new PointShape(polygonShape.OuterRing.Vertices[polygonShape.OuterRing.Vertices.Count|- 1]), string.Format("Area: {0} {1}", area.ToString("N1"), areaUnit)); } if (map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Count > 0) { Feature lastFeature = map1.TrackOverlay.TrackShapeLayer.InternalFeatures.LastOrDefault(); lastFeature.Tag = "Measure"; map1.TrackOverlay.TrackShapeLayer.InternalFeatures.RemoveAt(map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Count - 1); map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Add(lastFeature); } } } if (map1.TrackOverlay.TrackMode == TrackMode.Line) { string unit = string.Empty; LineShape lineShape = e.TrackShape as LineShape; if (lineShape != null) { double lenth = 0; if (viewModel.SelectedUnitSystem == UnitSystem.Metric) { lenth = lineShape.GetLength(GeographyUnit.Meter, DistanceUnit.Meter); unit = "m"; if (lenth >= 1000) { unit = "km"; lenth = Math.Round(lenth / 1000d, 1); } } else if (viewModel.SelectedUnitSystem == UnitSystem.Imperial) { lenth = lineShape.GetLength(GeographyUnit.Meter, DistanceUnit.Feet); unit = "ft"; if (lenth >= 5280) { unit = "mi"; lenth = Math.Round(lenth / 5280d, 1); } } string lengthString = lenth.ToString("N1"); ShowPopup(new PointShape(lineShape.Vertices[lineShape.Vertices.Count|- 1]), string.Format("Total Length: {0} {1}", lengthString, unit)); if (map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Count > 0) { var lastFeature = map1.TrackOverlay.TrackShapeLayer.InternalFeatures.LastOrDefault(); lastFeature.Tag = "Measure"; map1.TrackOverlay.TrackShapeLayer.InternalFeatures.RemoveAt(map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Count - 1); map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Add(lastFeature); } } } } private void DrawNewFenceClick(object sender, RoutedEventArgs e) { DrawNewFence(); } private void DrawNewFence() { CancelEdit(); map1.TrackOverlay.MapMouseClick -= TrackOverlay_MapMouseClick; map1.TrackOverlay.TrackMode = TrackMode.Polygon; } private void DeleteFenceClick(object sender, RoutedEventArgs e) { if (map1.EditOverlay.EditShapesLayer.InternalFeatures.Count == 0) { MessageBox.Show("Please choose a fence!", "Vehicle Tracking", MessageBoxButton.OK); } else if (map1.EditOverlay.EditShapesLayer.InternalFeatures.Count > 0) { if (MessageBox.Show("Are you sure you want to delete the fence you have selected?", "Vehicle Tracking", MessageBoxButton.OKCancel) == MessageBoxResult.OK) { map1.TrackOverlay.MapMouseClick -= TrackOverlay_MapMouseClick; map1.EditOverlay.EditShapesLayer.InternalFeatures.Clear(); LayerOverlay spatialFenceOverlay = (LayerOverlay)map1.Overlays["SpatialFenceOverlay"]; ((InMemoryFeatureLayer)spatialFenceOverlay.Layers["SpatialFenceLayer"]).InternalFeatures.Clear(); SaveSpatialFences(() => UpdateSpatialFencesAndVehicles()); } } } private void SaveFenceClick(object sender, RoutedEventArgs e) { map1.TrackOverlay.MapMouseClick -= TrackOverlay_MapMouseClick; SaveSpatialFences(() => UpdateSpatialFencesAndVehicles()); if (EditFenceRadioButton.IsChecked.GetValueOrDefault()) { EditFenceRadioButton.IsChecked = false; DrawNewFenceRadioButton.IsChecked = true; DrawNewFence(); } } private void EditFenceClick(object sender, RoutedEventArgs e) { ClearMeasuresAndPopups(); map1.TrackOverlay.TrackMode = TrackMode.None; LayerOverlay spatialFenceOverlay = (LayerOverlay)map1.Overlays["SpatialFenceOverlay"]; InMemoryFeatureLayer spatialFenceLayer = (InMemoryFeatureLayer)spatialFenceOverlay.Layers["SpatialFenceLayer"]; // Move spatial fences from spatial fence layer to edit overlay for editing foreach (Feature feature in spatialFenceLayer.InternalFeatures) { if (!map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Contains(feature.Id)) { map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Add(feature.Id, feature); } if (!spatialFenceLayer.FeatureIdsToExclude.Contains(feature.Id)) { spatialFenceLayer.FeatureIdsToExclude.Add(feature.Id); } } map1.TrackOverlay.MapMouseClick -= TrackOverlay_MapMouseClick; map1.TrackOverlay.MapMouseClick += TrackOverlay_MapMouseClick; UpdateVehicles(); map1.Refresh(); } private void TrackOverlay_MapMouseClick(object sender, MapMouseClickInteractiveOverlayEventArgs e) { PointShape clickedPoint = new PointShape(e.InteractionArguments.WorldX, e.InteractionArguments.WorldY); RectangleShape rect = GetBufferedRectangle(clickedPoint); if (!map1.TrackOverlay.TrackShapeLayer.IsOpen) { map1.TrackOverlay.TrackShapeLayer.Open(); } Collection<Feature> intersectingFeatures = map1.TrackOverlay.TrackShapeLayer.QueryTools.GetFeaturesIntersecting(rect, ReturningColumnsType.AllColumns); if (intersectingFeatures.Count > 0) { if (map1.EditOverlay.EditShapesLayer.InternalFeatures.Count > 0) { foreach (var item in map1.EditOverlay.EditShapesLayer.InternalFeatures) { map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Add(item); } map1.EditOverlay.EditShapesLayer.InternalFeatures.Clear(); } map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Remove(intersectingFeatures[0].Id); map1.EditOverlay.EditShapesLayer.InternalFeatures.Add(intersectingFeatures[0]); map1.EditOverlay.CalculateAllControlPoints(); map1.Refresh(); } } private void SaveSpatialFences(Action executeAction) { LayerOverlay spatialFenceOverlay = (LayerOverlay)map1.Overlays["SpatialFenceOverlay"]; InMemoryFeatureLayer spatialFenceLayer = (InMemoryFeatureLayer)spatialFenceOverlay.Layers["SpatialFenceLayer"]; foreach (var item in spatialFenceLayer.FeatureIdsToExclude) { if (spatialFenceLayer.InternalFeatures.Contains(item)) { spatialFenceLayer.InternalFeatures.Remove(item); } } spatialFenceLayer.FeatureIdsToExclude.Clear(); // Save the new spatial fences from edit overlay into the spatial fence layer foreach (Feature feature in map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Where(f => (string)f.Tag != "Measure")) { if (!spatialFenceLayer.InternalFeatures.Contains(feature.Id)) { spatialFenceLayer.InternalFeatures.Add(feature.Id, feature); } } foreach (Feature feature in map1.EditOverlay.EditShapesLayer.InternalFeatures) { if (!spatialFenceLayer.InternalFeatures.Contains(feature.Id)) { spatialFenceLayer.InternalFeatures.Add(feature.Id, feature); } } spatialFenceOverlay.Refresh(); TrackingAccessPrividerSourceClient client = new TrackingAccessPrividerSourceClient(); client.DeleteAndUpdateAndInsertSpatialFencesCompleted += (s, e) => { // Turn the track mode to none and clear the features in the edit overlay map1.TrackOverlay.TrackMode = TrackMode.None; map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Clear(); map1.EditOverlay.EditShapesLayer.InternalFeatures.Clear(); map1.Popups.Clear(); map1.TrackOverlay.Refresh(); map1.EditOverlay.CalculateAllControlPoints(); map1.EditOverlay.Refresh(); if (executeAction != null) { executeAction(); if (EditFenceRadioButton.IsChecked.GetValueOrDefault() || DrawNewFenceRadioButton.IsChecked.GetValueOrDefault()) { EditFenceRadioButton.IsChecked = false; DrawNewFenceRadioButton.IsChecked = true; DrawNewFence(); } } }; ObservableCollection<string> excludeFeatureWktIds = new ObservableCollection<string>(spatialFenceLayer.InternalFeatures.Select(f => f.GetWellKnownText() + "|" + f.Id).ToList()); client.DeleteAndUpdateAndInsertSpatialFencesAsync(excludeFeatureWktIds); } private void ZoomToVehicleClick(object sender, RoutedEventArgs e) { LayerOverlay traceOverlay = (LayerOverlay)map1.Overlays["TraceOverlay"]; FrameworkElement frameworkElement = (FrameworkElement)sender; VehicleViewModel vehicleViewModel = frameworkElement.DataContext as VehicleViewModel; if (vehicleViewModel != null) { InMemoryFeatureLayer vehicleFeatureLayer = traceOverlay.Layers[vehicleViewModel.OwnerName] as InMemoryFeatureLayer; if (vehicleFeatureLayer != null) { PointShape centerPoint = vehicleFeatureLayer.InternalFeatures[vehicleFeatureLayer.InternalFeatures.Count|- 1].GetShape() as PointShape; map1.ZoomTo(centerPoint, 15); } } } private void CollapsExpandClick(object sender, RoutedEventArgs e) { CheckBox CollapsExpandCheckBox = sender as CheckBox; if (CollapsExpandCheckBox != null) { if (CollapsExpandCheckBox.IsChecked.GetValueOrDefault()) { CollapsExpandCheckBox.Content = new Uri("Image/expand.png", UriKind.RelativeOrAbsolute); statusPanel.Visibility = Visibility.Collapsed; Grid grid = map1.Parent as Grid; if (grid != null) { map1.Width = grid.ActualWidth; } } else { CollapsExpandCheckBox.Content = new Uri("Image/collapse.png", UriKind.RelativeOrAbsolute); statusPanel.Visibility = Visibility.Visible; Grid grid = map1.Parent as Grid; if (grid != null) { map1.Width = grid.ColumnDefinitions.Last().ActualWidth; } } } } private void Control_MouseEnter(object sender, MouseEventArgs e) { Control control = sender as Control; if (control != null) { control.Effect = dropShadowEffect; } } private void Control_MouseLeave(object sender, MouseEventArgs e) { Control control = sender as Control; if (control != null) { control.Effect = null; } } private void CancelEditClick(object sender, RoutedEventArgs e) { CancelEdit(); } private void CancelEdit() { map1.EditOverlay.EditShapesLayer.InternalFeatures.Clear(); foreach (var editFeature in map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Where(f => (string)f.Tag != "Measure").ToList()) { map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Remove(editFeature); } LayerOverlay spatialFenceOverlay = (LayerOverlay)map1.Overlays["SpatialFenceOverlay"]; InMemoryFeatureLayer spatialFenceLayer = (InMemoryFeatureLayer)spatialFenceOverlay.Layers["SpatialFenceLayer"]; spatialFenceLayer.FeatureIdsToExclude.Clear(); map1.EditOverlay.Refresh(); map1.TrackOverlay.Refresh(); spatialFenceOverlay.Refresh(); if (EditFenceRadioButton.IsChecked.GetValueOrDefault()) { EditFenceRadioButton.IsChecked = false; DrawNewFenceRadioButton.IsChecked = true; DrawNewFence(); } } private void Grid_SizeChanged(object sender, SizeChangedEventArgs e) { Grid grid = sender as Grid; if (grid != null) { map1.Width = grid.ColumnDefinitions[1].ActualWidth; map1.Height = grid.ActualHeight; if (isFirst) { isFirst = false; // Setup the map. map1.MapUnit = GeographyUnit.Meter; map1.MapTools.ScaleLine.IsEnabled = true; // Add the various overlays such as vehicles, fences etc. SetupBaseOverlays(); UpdateSpatialFencesAndVehicles(false); map1.CurrentExtent = new RectangleShape(-10785099.4221547, 3916104.57324868, -10779357.0938025, 3912421.26612761); } } } private void OverlaySwitcher_OverlayChanged(object sender, OverlayChangedOverlaySwitcherEventArgs e) { switch (e.NewCheckedOverlayName) { case worldMapKitName: if (map1.Overlays.Contains(worldMapKitName)) map1.Overlays.Remove(worldMapKitName); map1.Overlays.Insert(0, worldMapKitName, new WorldMapKitWmsSilverlightOverlay { Projection = WorldMapKitProjection.SphericalMercator }); if (map1.Overlays.Contains(openStreetMapName)) map1.Overlays.Remove(openStreetMapName); if (map1.Overlays.Contains(bingMapsRoadMapName)) map1.Overlays.Remove(bingMapsRoadMapName); map1.Refresh(); break; case openStreetMapName: if (map1.Overlays.Contains(openStreetMapName)) map1.Overlays.Remove(openStreetMapName); map1.Overlays.Insert(0, openStreetMapName, new OpenStreetMapOverlay()); if (map1.Overlays.Contains(worldMapKitName)) map1.Overlays.Remove(worldMapKitName); if (map1.Overlays.Contains(bingMapsRoadMapName)) map1.Overlays.Remove(bingMapsRoadMapName); map1.Refresh(); break; case bingMapsRoadMapName: case bingMapsAerialMapName: bool needShowInputBingMapKeyWindow = true; if (IsolatedStorageSettings.ApplicationSettings.Contains(bingMapsKeyFileName)) { string bingmapsKey = IsolatedStorageSettings.ApplicationSettings[bingMapsKeyFileName].ToString(); if (!string.IsNullOrEmpty(bingmapsKey)) { LoadBingMaps(e.NewCheckedOverlayName, bingmapsKey); needShowInputBingMapKeyWindow = false; } } if (needShowInputBingMapKeyWindow) { BingMapsApplicationIdPromptWindow bingMapsApplicationIdPromptWindow = new BingMapsApplicationIdPromptWindow(); bingMapsApplicationIdPromptWindow.Closing += (s, args) => { if (bingMapsApplicationIdPromptWindow.DialogResult.GetValueOrDefault()) { LoadBingMaps(e.NewCheckedOverlayName, bingMapsApplicationIdPromptWindow.ApplicationId); IsolatedStorageSettings.ApplicationSettings.Add(bingMapsKeyFileName, bingMapsApplicationIdPromptWindow.ApplicationId); } else overlaySwitcher.BindingOverlayNames(e.OldCheckedOverlayName); }; bingMapsApplicationIdPromptWindow.Show(); } break; } } private void LoadBingMaps(string newCheckedOverlayName, string bingMapsKey) { BingMapsStyle bingMapsStyle = newCheckedOverlayName == bingMapsRoadMapName ? BingMapsStyle.Roads : BingMapsStyle.Aerial; if (map1.Overlays.Contains(bingMapsRoadMapName)) map1.Overlays.Remove(bingMapsRoadMapName); map1.Overlays.Insert(0, bingMapsRoadMapName, new BingMapsOverlay(bingMapsRoadMapName, bingMapsKey, bingMapsStyle)); if (map1.Overlays.Contains(openStreetMapName)) map1.Overlays.Remove(openStreetMapName); if (map1.Overlays.Contains(worldMapKitName)) map1.Overlays.Remove(worldMapKitName); map1.Refresh(); } private void Map_MouseMove(object sender, MouseEventArgs e) { Point screenPoint = e.GetPosition(map1); PointShape worldPoint = ExtentHelper.ToWorldCoordinate(map1.CurrentExtent, screenPoint, map1.ActualWidth, map1.ActualHeight); LocationXTextBlock.Text = string.Format("X:{0:#,0.##}", worldPoint.X); LocationYTextBlock.Text = string.Format("Y:{0:#,0.##}", worldPoint.Y); } 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; } } }
using System.Collections.ObjectModel; using System.Linq; namespace ThinkGeo.MapSuite.VehicleTracking { public class VehicleTrackingViewModel : ViewModelBase { private string defaultOverlayName; private UnitSystem selectedUnitSystem; private Collection<string> overlayNames; private Collection<UnitSystem> unitSystems; private ObservableCollection<VehicleViewModel> vehicles; public VehicleTrackingViewModel() { overlayNames = new Collection<string>(); vehicles = new ObservableCollection<VehicleViewModel>(); unitSystems = new Collection<UnitSystem> { UnitSystem.Imperial, UnitSystem.Metric }; selectedUnitSystem = unitSystems[0]; } public ObservableCollection<VehicleViewModel> Vehicles { get { return vehicles; } } public Collection<UnitSystem> UnitSystems { get { return unitSystems; } } public UnitSystem SelectedUnitSystem { get { return selectedUnitSystem; } set { selectedUnitSystem = value; } } public Collection<string> OverlayNames { get { return overlayNames; } } public string DefaultOverlayName { get { return string.IsNullOrEmpty(defaultOverlayName) ? overlayNames.FirstOrDefault() : defaultOverlayName; } set { defaultOverlayName = value; } } } public enum UnitSystem { Imperial = 0, Metric = 1, } }
using System.Globalization; using ThinkGeo.MapSuite.VehicleTracking.ServiceReference; namespace ThinkGeo.MapSuite.VehicleTracking { public class VehicleViewModel : ViewModelBase { private string area; private string speed; private string status; private string iconUri; private string duration; private string ownerName; private Vehicle vehicle; public VehicleViewModel() : this(null) { } public VehicleViewModel(Vehicle vehicle) { ownerName = vehicle.VehicleName; iconUri = "Image/" + vehicle.VehicleIconVirtualPath; Vehicle = vehicle; Load(); } public Vehicle Vehicle { get { return vehicle; } set { vehicle = value; } } public void Load() { Status = MapSuiteSampleHelper.GetCurrentState(vehicle); Speed = vehicle.Location.Speed.ToString(CultureInfo.InvariantCulture) + " mph"; Duration = MapSuiteSampleHelper.GetSpeedDuration(vehicle).ToString(CultureInfo.InvariantCulture) + " min"; } public string Status { get { return status; } set { status = value; RaisePropertyChanged(() => Status); } } public string IconUri { get { return iconUri; } set { iconUri = value; RaisePropertyChanged(() => IconUri); } } public string Area { get { return area; } set { area = value; RaisePropertyChanged(() => Area); } } public string OwnerName { get { return ownerName; } set { ownerName = value; RaisePropertyChanged(() => OwnerName); } } public string Speed { get { return speed; } set { speed = value; RaisePropertyChanged(() => Speed); } } public string Duration { get { return duration; } set { duration = value; RaisePropertyChanged(() => Duration); } } } }
using System; using System.ComponentModel; using System.Linq.Expressions; namespace ThinkGeo.MapSuite.VehicleTracking { public class ViewModelBase : INotifyPropertyChanged { public ViewModelBase() { } public event PropertyChangedEventHandler PropertyChanged; protected virtual void RaisePropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } protected virtual void RaisePropertyChanged<T>(Expression<Func<T>> expreesion) { RaisePropertyChanged(((MemberExpression)expreesion.Body).Member.Name); } } }
using System; using System.Runtime.Serialization; using ThinkGeo.MapSuite.Core; namespace ThinkGeo.MapSuite.VehicleTracking { /// <summary> /// This class specify the basic information for a location. /// </summary> [DataContract] 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; } [DataMember] public double Longitude { get { return longitude; } set { longitude = value; } } [DataMember] public double Latitude { get { return latitude; } set { latitude = value; } } [DataMember] public double Speed { get { return speed; } set { speed = value; } } [DataMember] public DateTime DateTime { get { return dateTime; } set { dateTime = value; } } } }
using System; using System.Linq; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.Data.OleDb; using System.Globalization; using System.Text; 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 = 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<string> GetSpatialFences() { Collection<string> spatialFences = new Collection<string>(); 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(wkt + "|" + id); } return spatialFences; } public void DeleteAndUpdateAndInsertSpatialFences(IEnumerable<string> excludeFeatureWktIds) { Dictionary<string, string> featureWktIds = new Dictionary<string, string>(); foreach (var item in excludeFeatureWktIds) { var array = item.Split('|'); if (array.Length == 2) { featureWktIds.Add(array[0], array[1]); } } DeleteSpatialFencesExcluding(featureWktIds.Values.ToList()); foreach (var item in featureWktIds) { int result = UpdateSpatialFenceByFeature(item.Key, item.Value); if (result == 0) { InsertSpatialFence(item.Key, item.Value); } } } public override void DeleteSpatialFencesExcluding(IEnumerable<string> excludeFeatureIds) { StringBuilder undeleteFeatureIds = new StringBuilder(); foreach (string undeleteFeatureId in excludeFeatureIds) { undeleteFeatureIds.AppendFormat(CultureInfo.InvariantCulture, "'{0}',", undeleteFeatureId); } string sql = String.Format(CultureInfo.InvariantCulture, "DELETE FROM SpatialFence WHERE (FeatureID NOT IN ({0}))", undeleteFeatureIds.ToString().TrimEnd(',')); ExecuteNonQuery(sql); } public override int UpdateSpatialFenceByFeature(string wkt, string featureId) { int updatedSpatialFenceCount = ExecuteNonQuery(String.Format(CultureInfo.InvariantCulture, "UPDATE SpatialFence SET FenceGeometry = '{0}' WHERE (FeatureID = '{1}')", wkt, featureId)); return updatedSpatialFenceCount; } public override void InsertSpatialFence(string wkt, string featureId) { ExecuteNonQuery(String.Format(CultureInfo.InvariantCulture, "Insert into SpatialFence(FenceGeometry,FeatureID) values('{0}','{1}')", wkt, featureId)); } 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; } } } } }
using System; using System.Collections.Generic; using System.Collections.ObjectModel; namespace ThinkGeo.MapSuite.VehicleTracking { public abstract class TrackingDataProvider : IDisposable { public abstract Dictionary<int, Vehicle> GetCurrentVehicles(DateTime currentTime); public abstract Collection<string> GetSpatialFences(); public abstract void DeleteSpatialFencesExcluding(IEnumerable<string> excludeFeatureIds); public abstract int UpdateSpatialFenceByFeature(string wkt, string featureId); public abstract void InsertSpatialFence(string wkt, string featureId); public abstract void Dispose(); } }
using System.Collections.ObjectModel; using System.Runtime.Serialization; namespace ThinkGeo.MapSuite.VehicleTracking { /// <summary> /// This class stands for a vehicle. /// </summary> [DataContract] public class Vehicle { private int id; private string name; private string iconPath; private Location location; private Collection<Location> historyLocations; private Vehicle() : this(0) { } public Vehicle(int id) { Id = id; name = string.Empty; Location = new Location(); historyLocations = new Collection<Location>(); } [DataMember] public int Id { get { return id; } set { id = value; } } [DataMember] public Location Location { get { return location; } set { location = value; } } [DataMember] public Collection<Location> HistoryLocations { get { return historyLocations; } } [DataMember] public string VehicleName { get { return name; } set { name = value; } } [DataMember] public string VehicleIconVirtualPath { get { return iconPath; } set { iconPath = value; } } 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; } } }
using System.Runtime.Serialization; namespace ThinkGeo.MapSuite.VehicleTracking { /// <summary> /// This enumeration specifies the Possible states for Vehicles. /// </summary> [DataContract] public enum VehicleMotionState { [DataMember] Motion = 0, [DataMember] Idle = 1, } }