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
<Window x:Class="ThinkGeo.MapSuite.VehicleTracking.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ThinkGeo.MapSuite.VehicleTracking" xmlns:wpf="clr-namespace:ThinkGeo.MapSuite.WpfDesktopEdition;assembly=WpfDesktopEdition" Title="Vehicle Tracking" Height="675" Width="1155" WindowState="Maximized" Loaded="Window_Loaded" Icon="/Image/MapSuite.ico"> <Window.Resources> <ResourceDictionary> <local:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" /> <local:EnumToBoolConverter x:Key="EnumToBoolConverter" /> </ResourceDictionary> </Window.Resources> <Grid Style="{StaticResource sampleBody}"> <Grid.RowDefinitions> <RowDefinition Height="auto" /> <RowDefinition Height="*" /> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <Border BorderThickness="0,0,0,5" Padding="10" CornerRadius="2" KeyboardNavigation.TabNavigation="Local" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabIndex="2"> <Border.Background> <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> <LinearGradientBrush.GradientStops> <GradientStop Offset="0" Color="#ffffff" /> <GradientStop Offset="0.4" Color="#fafafa" /> <GradientStop Offset="0.55" Color="#f2f2f2" /> <GradientStop Offset="0.6" Color="#f0f0f0" /> <GradientStop Offset="0.9" Color="#e2e2e2" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Border.Background> <Border.BorderBrush> <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> <LinearGradientBrush.GradientStops> <GradientStop Offset="0.85" Color="#5c707d" /> <GradientStop Offset="1" Color="#305c707d" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Border.BorderBrush> <StackPanel Orientation="Horizontal"> <TextBlock Margin="{StaticResource TitleMargin}"> <Run FontSize="16">Map Suite</Run> <Run FontSize="20">Vehicle Tracking</Run> </TextBlock> </StackPanel> </Border> <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid Margin="5 0 0 10"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="5" /> </Grid.ColumnDefinitions> <Grid Grid.Row="0" Grid.Column="0" Style="{StaticResource collapseExpandEffect}" 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 h4}" Margin="0 10 0 10" /> <Border Grid.Row="1" Style="{StaticResource fileset}"> <StackPanel> <StackPanel Orientation="Horizontal"> <ToggleButton IsChecked="{Binding AutoRefresh,Mode=TwoWay}" Content="/Image/AutoRefresh.png" ToolTip="Auto Refresh" Template="{StaticResource newAutoRefreshTemplate}" Margin="{StaticResource normalMargin}" /> <TextBlock Text="Auto Refresh: " Style="{StaticResource bodyText}" VerticalAlignment="Center" /> <TextBlock Text="{Binding AutoRefreshMode}" Style="{StaticResource warningBodyText1}" VerticalAlignment="Center" /> </StackPanel> <StackPanel Orientation="Horizontal" Margin="0 5 0 0"> <Button Content="/Image/RefreshManually.png" Command="{Binding RefreshCommand}" 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 h4}" Margin="0 10 0 0" /> <Border Grid.Row="3" Style="{StaticResource fileset}"> <StackPanel Orientation="Horizontal"> <RadioButton IsChecked="{Binding MapMode,Mode=TwoWay,Converter={StaticResource EnumToBoolConverter},ConverterParameter=Pan}" GroupName="Map" Content="/Image/pan.png" ToolTip="Pan map" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource normalMargin}" /> <RadioButton GroupName="Map" Content="/Image/draw.png" ToolTip="Draw fences" IsChecked="{Binding MapMode,Mode=TwoWay,Converter={StaticResource EnumToBoolConverter},ConverterParameter=DrawFence}" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource normalMargin}" /> <RadioButton GroupName="Map" Content="/Image/measure.png" ToolTip="Measure distance" IsChecked="{Binding MapMode,Mode=TwoWay,Converter={StaticResource EnumToBoolConverter},ConverterParameter=Measure}" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource normalMargin}" /> </StackPanel> </Border> <StackPanel Grid.Row="4" Orientation="Horizontal" x:Name="editPanel" Visibility="{Binding EditPanelVisibility}"> <RadioButton x:Name="rbtnDrawNewFence" IsChecked="{Binding DrawFenceMode,Mode=TwoWay,Converter={StaticResource EnumToBoolConverter},ConverterParameter=NewFence}" Content="/Image/draw_polygon.png" GroupName="draw" ToolTip="Track new fences" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}" /> <RadioButton x:Name="rbtnEditFence" IsChecked="{Binding DrawFenceMode,Mode=TwoWay,Converter={StaticResource EnumToBoolConverter},ConverterParameter=EditFence}" Content="/Image/edit_polygon.png" GroupName="draw" ToolTip="Edit the selected fence" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}" /> <Button Content="/Image/Remove_Polygon.png" Command="{Binding DeleteFenceCommand}" ToolTip="Delete" Template="{StaticResource imageButtonTemplate}" Margin="15 0 5 0" /> <Button Content="/Image/save.png" Command="{Binding SaveFenceCommand}" ToolTip="Save" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}" /> <Button Content="/Image/clear.png" Command="{Binding CancelEditCommand}" ToolTip="Cancel" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}" /> </StackPanel> <StackPanel Grid.Row="4" Orientation="Horizontal" x:Name="measurePanel" Visibility="{Binding MeasurePanelVisibility}"> <RadioButton x:Name="rbtnMeasureLine" GroupName="Measure" IsChecked="{Binding MeasureMode,Mode=TwoWay,Converter={StaticResource EnumToBoolConverter},ConverterParameter=MeasureLine}" Content="/Image/line.png" ToolTip="Measure line" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}" /> <RadioButton GroupName="Measure" Content="/Image/polygon.png" IsChecked="{Binding MeasureMode,Mode=TwoWay,Converter={StaticResource EnumToBoolConverter},ConverterParameter=MeasurePolygon}" ToolTip="Measure polygon" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}" /> <Button Content="/Image/clear.png" Command="{Binding CancelMeasureCommand}" ToolTip="Cancel" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}" /> <TextBlock Text="Measure Unit:" VerticalAlignment="Center" Margin="10 0 5 0" /> <ComboBox ItemsSource="{Binding UnitSystems}" SelectedItem="{Binding SelectedUnitSystem,Mode=TwoWay}" Height="20" Width="72" 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="15" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Button Content="{Binding IconUri}" Command="{Binding ZoomToVehicleCommand}" Template="{StaticResource imageButtonTemplate}" HorizontalAlignment="Center" VerticalAlignment="Top" /> <StackPanel Grid.Column="2"> <TextBlock Cursor="Hand" FontWeight="Bold" TextDecorations="Underline" Style="{StaticResource bodyText}"> <Hyperlink Command="{Binding ZoomToVehicleCommand}" Foreground="Black"> <Run Text="{Binding OwnerName}"/> </Hyperlink> </TextBlock> <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> <ToggleButton x:Name="PanelToggleButton" Template="{DynamicResource collapseExpandTemplate}" Grid.Row="0" Grid.Column="1" Cursor="Hand" Background="Transparent" BorderBrush="Transparent" /> <Rectangle Grid.Row="0" 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> <wpf:WpfMap Grid.Column="1" x:Name="wpfMap1" Panel.ZIndex="-1" /> <Grid Grid.Column="1" x:Name="loadingControl" Visibility="{Binding IsBusy, Converter={StaticResource BoolToVisibilityConverter}}" Background="#30D6D6D6" DockPanel.Dock="Bottom"> <local:LoadingImageUserControl /> </Grid> </Grid> <Grid Grid.Row="2"> <Border BorderBrush="Gray" BorderThickness="0 1 0 0"> <StatusBar Height="30"> <StatusBarItem HorizontalContentAlignment="Stretch"> <Grid HorizontalAlignment="Right"> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="5" /> <ColumnDefinition Width="auto" /> </Grid.ColumnDefinitions> <TextBlock Text="{Binding CoordinateX,StringFormat=X: {0:N2}}" HorizontalAlignment="Right" Width="95" VerticalAlignment="Center" Grid.Column="0" /> <TextBlock Text="{Binding CoordinateY,StringFormat=Y: {0:N2}}" VerticalAlignment="Center" Width="100" Grid.Column="2" /> </Grid> </StatusBarItem> </StatusBar> </Border> </Grid> </Grid> </Window>
using System.Windows; namespace ThinkGeo.MapSuite.VehicleTracking { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { DataContext = new MainWindowViewModel(wpfMap1); } } }
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Configuration; using System.Data.OleDb; using System.Globalization; using System.IO; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using System.Windows.Threading; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.VehicleTracking.Properties; using ThinkGeo.MapSuite.WpfDesktopEdition; namespace ThinkGeo.MapSuite.VehicleTracking { public class MainWindowViewModel : ViewModelBase { private static readonly DateTime adjustedStartTime = DateTime.Parse("2009/7/10 11:31:0"); private static readonly DateTime applicationStartTime = DateTime.Now; private static readonly string databasePathFileName; private bool isBusy; private bool autoRefresh; private double coordinateX; private double coordinateY; private WpfMap mapControl; private MapModel mapModel; private ControlMapMode mapMode; private MeasureMode measureMode; private DrawFenceMode drawFenceMode; private UnitSystem selectedUnitSystem; private DispatcherTimer dispatcherTimer; private Visibility editPanelVisibility; private Visibility measurePanelVisibility; private AutoRefreshMode autoRefreshMode; private Collection<UnitSystem> unitSystems; private ObservableCollection<VehicleViewModel> vehicles; private CommandBase refreshCommand; private CommandBase saveFenceCommand; private CommandBase cancelEditCommand; private CommandBase deleteFenceCommand; private CommandBase cancelMeasureCommand; static MainWindowViewModel() { databasePathFileName = ConfigurationManager.AppSettings["databasePathFileName"]; } public MainWindowViewModel() : this(null) { } public MainWindowViewModel(WpfMap map) { dispatcherTimer = new DispatcherTimer(); dispatcherTimer.Interval = TimeSpan.FromMilliseconds(5000); dispatcherTimer.Tick += AutoRefreshTimer_Tick; vehicles = new ObservableCollection<VehicleViewModel>(); unitSystems = new Collection<UnitSystem>(); unitSystems.Add(UnitSystem.Imperial); unitSystems.Add(UnitSystem.Metric); selectedUnitSystem = UnitSystem.Metric; autoRefreshMode = AutoRefreshMode.On; autoRefresh = true; drawFenceMode = DrawFenceMode.DrawNewFence; measureMode = MeasureMode.Line; mapMode = ControlMapMode.Pan; measurePanelVisibility = Visibility.Collapsed; editPanelVisibility = Visibility.Collapsed; MapControl = map; dispatcherTimer.Start(); } public WpfMap MapControl { get { return mapControl; } set { mapControl = value; RaisePropertyChanged(() => MapControl); if (mapControl != null) { mapModel = new MapModel(mapControl); mapModel.MapControl.MapTools.MouseCoordinate.CustomFormatted += MouseCoordinate_CustomFormatted; mapModel.MapControl.OverlaysDrawing += WpfMap1_OverlaysDrawing; mapModel.MapControl.OverlaysDrawn += WpfMap1_OverlaysDrawn; UpdateSpatialFencesAndVehicles(); } } } public bool IsBusy { get { return isBusy; } set { isBusy = value; RaisePropertyChanged(() => IsBusy); } } public bool AutoRefresh { get { return autoRefresh; } set { autoRefresh = value; RaisePropertyChanged(() => AutoRefresh); if (value) { dispatcherTimer.Start(); AutoRefreshMode = AutoRefreshMode.On; } else { dispatcherTimer.Stop(); AutoRefreshMode = AutoRefreshMode.Off; } } } public ControlMapMode MapMode { get { return mapMode; } set { mapMode = value; RaisePropertyChanged(() => MapMode); switch (value) { case ControlMapMode.Pan: MeasurePanelVisibility = Visibility.Collapsed; EditPanelVisibility = Visibility.Collapsed; mapModel.TrackMode = TrackMode.None; break; case ControlMapMode.DrawFence: mapModel.MapControl.TrackOverlay.TrackEnded -= TrackOverlay_TrackEnded; mapModel.MapControl.TrackOverlay.TrackMode = TrackMode.Polygon; mapModel.MapControl.Cursor = Cursors.Arrow; MeasurePanelVisibility = Visibility.Collapsed; EditPanelVisibility = Visibility.Visible; break; case ControlMapMode.Measure: mapModel.MapControl.TrackOverlay.MapMouseClick -= TrackOverlay_MapMouseClick; if (mapModel.MapControl.EditOverlay.EditShapesLayer.InternalFeatures.Count > 0) { SaveSpatialFences(); } else if (mapModel.MapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.Count > 0) { CancelEditCommand.Execute(null); } mapModel.MapControl.Cursor = Cursors.Arrow; mapModel.TrackMode = measureMode == MeasureMode.Line ? TrackMode.Line : TrackMode.Polygon; mapModel.MapControl.TrackOverlay.TrackStarting -= TrackOverlay_TrackStarting; mapModel.MapControl.TrackOverlay.TrackStarting += TrackOverlay_TrackStarting; mapModel.MapControl.TrackOverlay.TrackEnded -= TrackOverlay_TrackEnded; mapModel.MapControl.TrackOverlay.TrackEnded += TrackOverlay_TrackEnded; MeasurePanelVisibility = Visibility.Visible; EditPanelVisibility = Visibility.Collapsed; break; } } } public MeasureMode MeasureMode { get { return measureMode; } set { measureMode = value; RaisePropertyChanged(() => MeasureMode); switch (value) { case MeasureMode.Line: mapModel.TrackMode = TrackMode.Line; break; case MeasureMode.Polygon: mapModel.TrackMode = TrackMode.Polygon; break; } } } public DrawFenceMode DrawFenceMode { get { return drawFenceMode; } set { drawFenceMode = value; RaisePropertyChanged(() => DrawFenceMode); switch (value) { case DrawFenceMode.DrawNewFence: ResetFences(); break; case DrawFenceMode.EditFence: ClearMeasuresAndPopups(); mapModel.MapControl.TrackOverlay.TrackMode = TrackMode.None; // Move spatial fences from spatial fence layer to edit overlay for editing foreach (Feature feature in mapModel.SpatialFenceLayer.InternalFeatures) { if (!mapModel.MapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.Contains(feature.Id)) { mapModel.MapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.Add(feature.Id, feature); } if (!mapModel.SpatialFenceLayer.FeatureIdsToExclude.Contains(feature.Id)) { mapModel.SpatialFenceLayer.FeatureIdsToExclude.Add(feature.Id); } } mapModel.MapControl.TrackOverlay.MapMouseClick -= TrackOverlay_MapMouseClick; mapModel.MapControl.TrackOverlay.MapMouseClick += TrackOverlay_MapMouseClick; UpdateVehicles(mapModel.TraceOverlay, GetAdjustedCurrentDateTime()); mapModel.MapControl.Refresh(mapModel.SpatialFenceOverlay); mapModel.MapControl.Refresh(mapModel.MapControl.TrackOverlay); break; } } } public Visibility EditPanelVisibility { get { return editPanelVisibility; } set { editPanelVisibility = value; RaisePropertyChanged(() => EditPanelVisibility); } } public Visibility MeasurePanelVisibility { get { return measurePanelVisibility; } set { measurePanelVisibility = value; RaisePropertyChanged(() => MeasurePanelVisibility); } } public CommandBase RefreshCommand { get { return refreshCommand ?? (refreshCommand = new CommandBase(UpdateSpatialFencesAndVehicles)); } } public CommandBase CancelMeasureCommand { get { return cancelMeasureCommand ?? (cancelMeasureCommand = new CommandBase(ClearMeasuresAndPopups)); } } public CommandBase SaveFenceCommand { get { return saveFenceCommand ?? (saveFenceCommand = new CommandBase(() => { mapModel.MapControl.TrackOverlay.MapMouseClick -= TrackOverlay_MapMouseClick; SaveSpatialFences(); UpdateSpatialFencesAndVehicles(); if (drawFenceMode == DrawFenceMode.EditFence) { DrawFenceMode = DrawFenceMode.DrawNewFence; ResetFences(); } })); } } public CommandBase CancelEditCommand { get { return cancelEditCommand ?? (cancelEditCommand = new CommandBase(() => { mapModel.MapControl.EditOverlay.EditShapesLayer.InternalFeatures.Clear(); foreach (var editFeature in mapModel.MapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.Where(f => f.Tag != "Measure").ToList()) { mapModel.MapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.Remove(editFeature); } mapModel.SpatialFenceLayer.FeatureIdsToExclude.Clear(); mapModel.MapControl.Refresh(); if (drawFenceMode == DrawFenceMode.EditFence) { DrawFenceMode = DrawFenceMode.DrawNewFence; ResetFences(); } })); } } public CommandBase DeleteFenceCommand { get { return deleteFenceCommand ?? (deleteFenceCommand = new CommandBase(() => { if (mapModel.MapControl.EditOverlay.EditShapesLayer.InternalFeatures.Count > 0) { if (MessageBox.Show(Resources.DeleteFenceWarning, "Vehicle Tracking", MessageBoxButton.OKCancel) == MessageBoxResult.OK) { mapModel.MapControl.TrackOverlay.MapMouseClick -= TrackOverlay_MapMouseClick; mapModel.MapControl.EditOverlay.EditShapesLayer.InternalFeatures.Clear(); mapModel.SpatialFenceLayer.InternalFeatures.Clear(); SaveSpatialFences(); UpdateSpatialFencesAndVehicles(); } } else { MessageBox.Show(Resources.ChooseFenceWarning, "Vehicle Tracking"); } })); } } public AutoRefreshMode AutoRefreshMode { get { return autoRefreshMode; } set { autoRefreshMode = value; RaisePropertyChanged(() => AutoRefreshMode); } } public double CoordinateX { get { return coordinateX; } set { coordinateX = value; RaisePropertyChanged(() => CoordinateX); } } public double CoordinateY { get { return coordinateY; } set { coordinateY = value; RaisePropertyChanged(() => CoordinateY); } } public Collection<UnitSystem> UnitSystems { get { return unitSystems; } } public UnitSystem SelectedUnitSystem { get { return selectedUnitSystem; } set { selectedUnitSystem = value; mapModel.UpdateUnitSystem(SelectedUnitSystem); RaisePropertyChanged(() => SelectedUnitSystem); } } public ObservableCollection<VehicleViewModel> Vehicles { get { return vehicles; } } private void TrackOverlay_MapMouseClick(object sender, MapMouseClickInteractiveOverlayEventArgs e) { PointShape clickedPoint = new PointShape(e.InteractionArguments.WorldX, e.InteractionArguments.WorldY); RectangleShape rect = MapSuiteSampleHelper.GetBufferedRectangle(clickedPoint, mapModel.MapControl.CurrentResolution); Collection<Feature> intersectingFeatures = mapModel.MapControl.TrackOverlay.TrackShapeLayer.QueryTools.GetFeaturesIntersecting(rect, ReturningColumnsType.AllColumns); if (intersectingFeatures.Count > 0) { if (mapModel.MapControl.EditOverlay.EditShapesLayer.InternalFeatures.Count > 0) { foreach (var item in mapModel.MapControl.EditOverlay.EditShapesLayer.InternalFeatures) { mapModel.MapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.Add(item.Id, item); } mapModel.MapControl.EditOverlay.EditShapesLayer.InternalFeatures.Clear(); } mapModel.MapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.Remove(intersectingFeatures[0].Id); mapModel.MapControl.EditOverlay.EditShapesLayer.InternalFeatures.Add(intersectingFeatures[0]); mapModel.MapControl.EditOverlay.CalculateAllControlPoints(); mapModel.MapControl.Refresh(mapModel.MapControl.TrackOverlay); mapModel.MapControl.Refresh(mapModel.MapControl.EditOverlay); } } private void MouseCoordinate_CustomFormatted(object sender, CustomFormattedMouseCoordinateMapToolEventArgs e) { CoordinateX = e.WorldCoordinate.X; CoordinateY = e.WorldCoordinate.Y; } private void WpfMap1_OverlaysDrawing(object sender, OverlaysDrawingWpfMapEventArgs e) { IsBusy = true; } private void WpfMap1_OverlaysDrawn(object sender, OverlaysDrawnWpfMapEventArgs e) { IsBusy = false; } private void AutoRefreshTimer_Tick(object sender, EventArgs e) { UpdateSpatialFencesAndVehicles(); } private void TrackOverlay_TrackEnded(object sender, TrackEndedTrackInteractiveOverlayEventArgs e) { if (mapModel.MapControl.TrackOverlay.TrackMode == TrackMode.Polygon) { PolygonShape polygonShape = e.TrackShape as PolygonShape; if (polygonShape != null) { double area = -1; string areaUnit = "sq.m."; switch (SelectedUnitSystem) { case UnitSystem.Metric: areaUnit = "sq.m."; area = polygonShape.GetArea(GeographyUnit.Meter, AreaUnit.SquareMeters); break; case UnitSystem.Imperial: areaUnit = "ac."; area = polygonShape.GetArea(GeographyUnit.Meter, AreaUnit.Acres); break; } if (area > 0) { string content = string.Format(CultureInfo.InvariantCulture, "Area: {0} {1}", area.ToString("N1"), areaUnit); ShowPopup(new PointShape(polygonShape.OuterRing.Vertices[polygonShape.OuterRing.Vertices.Count|- 2]), content); } mapModel.MapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.LastOrDefault().Tag = "Measure"; } } if (mapModel.MapControl.TrackOverlay.TrackMode == TrackMode.Line) { string unit = string.Empty; LineShape lineShape = e.TrackShape as LineShape; if (lineShape != null) { double lenth = 0; if (SelectedUnitSystem == UnitSystem.Metric) { lenth = lineShape.GetLength(GeographyUnit.Meter, DistanceUnit.Meter); unit = "m"; if (lenth >= 1000) { unit = "km"; lenth = Math.Round(lenth / 1000d, 1, MidpointRounding.AwayFromZero); } } else if (SelectedUnitSystem == UnitSystem.Imperial) { lenth = lineShape.GetLength(GeographyUnit.Meter, DistanceUnit.Feet); unit = "ft"; if (lenth >= 5280) { unit = "mi"; lenth = Math.Round(lenth / 5280d, 1, MidpointRounding.AwayFromZero); } } string lengthString = lenth.ToString("N1"); string content = string.Format(CultureInfo.InvariantCulture, "Total Length: {0} {1}", lengthString, unit); ShowPopup(new PointShape(lineShape.Vertices[lineShape.Vertices.Count|- 1]), content); mapModel.MapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.LastOrDefault().Tag = "Measure"; } } } private void TrackOverlay_TrackStarting(object sender, TrackStartingTrackInteractiveOverlayEventArgs e) { if (mapModel.TrackMode == TrackMode.Line || mapModel.TrackMode == TrackMode.Polygon) { ClearMeasuresAndPopups(); } } private void UpdateSpatialFencesAndVehicles() { DateTime currentTime = GetAdjustedCurrentDateTime(); Task.Factory.StartNew(() => { lock (mapModel.SpatialFenceOverlay) { // Update the fences from database. UpdateSpatialFences(); } lock (mapModel.TraceOverlay) { // Update the vehicle locations on the map. UpdateVehicles(mapModel.TraceOverlay, currentTime); } Application.Current.Dispatcher.BeginInvoke(new Action(mapModel.MapControl.Refresh)); }); } // 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, DateTime currentTime) { Dictionary<int, Vehicle> currentVehicles; using (TrackingAccessProvider vehicleProvider = new TrackingAccessProvider(databasePathFileName)) { currentVehicles = vehicleProvider.GetCurrentVehicles(currentTime); } // Loop through all the vehicle to add the history points if (currentVehicles != null && currentVehicles.All(v => !string.IsNullOrEmpty(v.Value.IconPath))) { InMemoryFeatureLayer vehicleTrailLayer; // Initialize vehicle overlay if it's not initialized if (!traceOverlay.Layers.Contains("VehicleTrail")) { // Create an InMemoryMarkerOverlay for the vehicle to hold the points and current location vehicleTrailLayer = new InMemoryFeatureLayer(); vehicleTrailLayer.Open(); vehicleTrailLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = GetVehicleTrailStyle(); vehicleTrailLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; // Add all the required columns so we can populate later vehicleTrailLayer.FeatureSource.Open(); vehicleTrailLayer.Columns.Add(new FeatureSourceColumn("Speed")); vehicleTrailLayer.Columns.Add(new FeatureSourceColumn("DateTime")); vehicleTrailLayer.Columns.Add(new FeatureSourceColumn("Longitude")); vehicleTrailLayer.Columns.Add(new FeatureSourceColumn("Latitude")); vehicleTrailLayer.Columns.Add(new FeatureSourceColumn("VehicleName")); vehicleTrailLayer.Columns.Add(new FeatureSourceColumn("Duration")); Application.Current.Dispatcher.BeginInvoke(new Action(() => { lock (traceOverlay.Layers) { traceOverlay.Layers.Add("VehicleTrail", vehicleTrailLayer); } })); } else { // Find the overlay in the map vehicleTrailLayer = (InMemoryFeatureLayer)traceOverlay.Layers["VehicleTrail"]; } vehicleTrailLayer.InternalFeatures.Clear(); foreach (int vehicleId in currentVehicles.Keys) { Vehicle currentVehicle = currentVehicles[vehicleId]; VehicleViewModel tempVehicleViewModel = Vehicles.FirstOrDefault(v => v.OwnerName == currentVehicle.Name); if (tempVehicleViewModel == null) { tempVehicleViewModel = new VehicleViewModel(currentVehicle, mapModel); Application.Current.Dispatcher.BeginInvoke(new Action(() => Vehicles.Add(tempVehicleViewModel))); } else { tempVehicleViewModel.Vehicle = currentVehicle; tempVehicleViewModel.Load(); } bool isInSpatialFence = IsInSpatialFence(currentVehicle); tempVehicleViewModel.Area = isInSpatialFence ? "In restricted area" : "Out of restricted area"; // 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["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); vehicleTrailLayer.InternalFeatures.Add(breadcrumbFeature.Id, breadcrumbFeature); } InMemoryFeatureLayer currentVehicleLayer; if (!traceOverlay.Layers.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.DefaultPointStyle = GetCurrentVehicleStyle(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("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")); Application.Current.Dispatcher.BeginInvoke(new Action(() => { lock (traceOverlay.Layers) { traceOverlay.Layers.Add(currentVehicle.Name, currentVehicleLayer); } })); } else { // Find the overlay in the map currentVehicleLayer = (InMemoryFeatureLayer)traceOverlay.Layers[currentVehicle.Name]; } currentVehicleLayer.InternalFeatures.Clear(); // 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["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); } } } private void UpdateSpatialFences() { // Get the spatial fence overlay and layer and then clear them mapModel.SpatialFenceLayer.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"; mapModel.SpatialFenceLayer.InternalFeatures.Add(spatialFence.Id, spatialFence); } } } private bool IsInSpatialFence(Vehicle vehicle) { InMemoryFeatureLayer spatialFenceLayer = (InMemoryFeatureLayer)mapModel.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); bool isInSpatialFence = false; lock (spatialFenceLayer) { spatialFenceLayer.Open(); Collection<Feature> spatialFencesWithin = spatialFenceLayer.QueryTools.GetFeaturesContaining(pointShape, ReturningColumnsType.NoColumns); if (spatialFencesWithin.Count > 0) { isInSpatialFence = true; } } return isInSpatialFence; } private void SaveSpatialFences() { TrackingAccessProvider vehicleProvider = null; try { foreach (var item in mapModel.SpatialFenceLayer.FeatureIdsToExclude) { if (mapModel.SpatialFenceLayer.InternalFeatures.Contains(item)) { mapModel.SpatialFenceLayer.InternalFeatures.Remove(item); } } mapModel.SpatialFenceLayer.FeatureIdsToExclude.Clear(); foreach (Feature feature in mapModel.MapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.Where(f => f.Tag != "Measure")) { if (!mapModel.SpatialFenceLayer.InternalFeatures.Contains(feature.Id)) { mapModel.SpatialFenceLayer.InternalFeatures.Add(feature.Id, feature); } } foreach (Feature feature in mapModel.MapControl.EditOverlay.EditShapesLayer.InternalFeatures) { if (!mapModel.SpatialFenceLayer.InternalFeatures.Contains(feature.Id)) { mapModel.SpatialFenceLayer.InternalFeatures.Add(feature.Id, feature); } } mapModel.SpatialFenceOverlay.Refresh(); vehicleProvider = new TrackingAccessProvider(databasePathFileName); // Delete Spatial fences which is not in current spatial fence layer vehicleProvider.DeleteSpatialFencesExcluding(mapModel.SpatialFenceLayer.InternalFeatures); // Add or update the spatial fences that already exist foreach (Feature feature in mapModel.SpatialFenceLayer.InternalFeatures) { // Update Spatial fence by feature Id // if the affected data row number is 0, we will add a new row in the database int updatedCount = vehicleProvider.UpdateSpatialFenceByFeature(feature); if (updatedCount == 0) { vehicleProvider.InsertSpatialFence(feature); } } } catch (OleDbException) { MessageBox.Show(string.Format(CultureInfo.InvariantCulture, "Please make sure {0} is writable", databasePathFileName), "Save Spatial Fences"); } catch (Exception e) { MessageBox.Show(e.Message, "Save Spatial Fences"); } finally { mapModel.MapControl.TrackOverlay.TrackMode = TrackMode.None; mapModel.MapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.Clear(); mapModel.MapControl.EditOverlay.EditShapesLayer.InternalFeatures.Clear(); mapModel.PopupOverlay.Popups.Clear(); mapModel.MapControl.Refresh(); if (vehicleProvider != null) { vehicleProvider.Dispose(); } if (drawFenceMode == DrawFenceMode.EditFence || drawFenceMode == DrawFenceMode.DrawNewFence) { DrawFenceMode = DrawFenceMode.DrawNewFence; ResetFences(); } } } private void ResetFences() { CancelEditCommand.Execute(null); mapModel.MapControl.TrackOverlay.MapMouseClick -= TrackOverlay_MapMouseClick; mapModel.MapControl.TrackOverlay.TrackMode = TrackMode.Polygon; } private void ShowPopup(PointShape pointShape, string content) { Popup popup = new Popup(pointShape); PopupUserControl popupUserControl = new PopupUserControl(content); popupUserControl.PopupOverlay = mapModel.PopupOverlay; popup.Content = popupUserControl; mapModel.PopupOverlay.Popups.Add(popup); mapModel.PopupOverlay.Refresh(); } private void ClearMeasuresAndPopups() { foreach (var measureFeature in mapModel.MapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.Where(f => f.Tag == "Measure").ToList()) { mapModel.MapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.Remove(measureFeature); } mapModel.PopupOverlay.Popups.Clear(); mapModel.MapControl.Refresh(mapModel.MapControl.TrackOverlay); mapModel.MapControl.Refresh(mapModel.PopupOverlay); } 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 sampleSecondPerActualSecond = 12; double realSpentTime = TimeSpan.FromTicks(DateTime.Now.Ticks - applicationStartTime.Ticks).TotalSeconds; int sampleSpentTime = (int)(realSpentTime * sampleSecondPerActualSecond); DateTime currentSampleTime = adjustedStartTime.AddSeconds(sampleSpentTime); return currentSampleTime; } private static PointStyle GetVehicleTrailStyle() { Stream historyStream = MapSuiteSampleHelper.GetResourceStream("trail point.png"); historyStream.Seek(0, SeekOrigin.Begin); return new PointStyle(new GeoImage(historyStream)); } private static PointStyle GetCurrentVehicleStyle(string iconVirtualPath) { Stream vehicleStream = MapSuiteSampleHelper.GetResourceStream(iconVirtualPath); GeoImage vehicleImage = new GeoImage(vehicleStream); return new PointStyle(vehicleImage); } } }
using System.Globalization; using System.Linq; using ThinkGeo.MapSuite.Core; namespace ThinkGeo.MapSuite.VehicleTracking { public class VehicleViewModel : ViewModelBase { private static string vehicleImageFormat = "/Image/{0}"; private string area; private string speed; private string status; private string iconUri; private string duration; private string ownerName; private MapModel mapModel; private Vehicle vehicle; private CommandBase zoomToVehicleCommand; public VehicleViewModel() : this(null, null) { } public VehicleViewModel(Vehicle vehicle, MapModel mapModel) : base() { this.vehicle = vehicle; this.ownerName = vehicle.Name; this.mapModel = mapModel; this.iconUri = string.Format(CultureInfo.InvariantCulture, vehicleImageFormat, vehicle.IconPath); this.Load(); } public Vehicle Vehicle { get { return vehicle; } set { vehicle = value; } } 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); } } public CommandBase ZoomToVehicleCommand { get { return zoomToVehicleCommand ?? (zoomToVehicleCommand = new CommandBase(() => { InMemoryFeatureLayer vehicleFeatureLayer = mapModel.TraceOverlay.Layers[OwnerName] as InMemoryFeatureLayer; if (vehicleFeatureLayer != null) { mapModel.MapControl.ZoomIntoCenter(60, vehicleFeatureLayer.InternalFeatures.LastOrDefault()); } })); } } public void Load() { Status = vehicle.GetCurrentState() == VehicleMotionState.Idle ? "Idle" : "In Motion"; Speed = vehicle.Location.Speed.ToString(CultureInfo.InvariantCulture) + " mph"; Duration = vehicle.GetSpeedDuration().ToString(CultureInfo.InvariantCulture) + " min"; } } }
<UserControl x:Class="ThinkGeo.MapSuite.VehicleTracking.PopupUserControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <Grid Margin="5"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBlock x:Name="txtContent" Visibility="Collapsed" /> <TextBlock x:Name="txtName" Style="{StaticResource h4}" FontWeight="Bold" HorizontalAlignment="Left" /> <Button Content="/Image/popup_close.png" Template="{StaticResource imageButtonTemplate}" Click="ClosePopupClick" HorizontalAlignment="Right" VerticalAlignment="Top" Grid.Column="1" Margin="5 0 0 0" /> </Grid> <Grid Grid.Row="1" x:Name="vehiclePanel"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="2" /> <RowDefinition Height="Auto" /> <RowDefinition Height="2" /> <RowDefinition Height="Auto" /> <RowDefinition Height="2" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="70" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TextBlock Text="Longitude:" Grid.Row="0" Grid.Column="0" /> <TextBlock x:Name="txtLongitude" Grid.Row="0" Grid.Column="1"/> <TextBlock Text="Latitude:" Grid.Row="2" Grid.Column="0"/> <TextBlock x:Name="txtLatitude" Grid.Row="2" Grid.Column="1"/> <TextBlock Text="Speed:" Grid.Row="4" Grid.Column="0"/> <TextBlock x:Name="txtSpeed" Grid.Row="4" Grid.Column="1"/> <TextBlock Text="Time:" Grid.Row="6" Grid.Column="0"/> <TextBlock x:Name="txtTime" Grid.Row="6" Grid.Column="1"/> </Grid> </Grid> </UserControl>
using System; using System.Globalization; using System.Windows; using System.Windows.Controls; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.WpfDesktopEdition; namespace ThinkGeo.MapSuite.VehicleTracking { /// <summary> /// Interaction logic for PopupUserControl.xaml /// </summary> public partial class PopupUserControl : UserControl { private PopupOverlay popupOverlay; public PopupUserControl() : this(string.Empty) { } public PopupUserControl(Feature feature) { InitializeComponent(); string speed = feature.ColumnValues["Speed"]; string name = feature.ColumnValues["VehicleName"]; string latitude = feature.ColumnValues["Latitude"]; string dateTime = feature.ColumnValues["DateTime"]; string longitude = feature.ColumnValues["Longitude"]; txtName.Text = name; double x, y; if (double.TryParse(longitude, out x) && double.TryParse(latitude, out y)) { ManagedProj4Projection proj4 = new ManagedProj4Projection(); proj4.InternalProjectionParametersString = Proj4Projection.GetDecimalDegreesParametersString(); proj4.ExternalProjectionParametersString = Proj4Projection.GetGoogleMapParametersString(); proj4.Open(); Vertex vertex = proj4.ConvertToInternalProjection(x, y); txtLongitude.Text = vertex.X.ToString("N6", CultureInfo.InvariantCulture); txtLatitude.Text = vertex.Y.ToString("N6", CultureInfo.InvariantCulture); proj4.Close(); } else { txtLongitude.Text = longitude; txtLatitude.Text = latitude; } txtSpeed.Text = speed + " mph"; txtTime.Text = dateTime; } public PopupUserControl(string content) { InitializeComponent(); txtContent.Text = content; txtContent.Visibility = Visibility.Visible; vehiclePanel.Visibility = Visibility.Collapsed; txtName.Visibility = Visibility.Collapsed; } public PopupOverlay PopupOverlay { get { return popupOverlay; } set { popupOverlay = value; } } private void ClosePopupClick(object sender, RoutedEventArgs e) { if (PopupOverlay != null) { PopupOverlay.Popups.Remove((Popup) Parent); PopupOverlay.Refresh(); } } } }
namespace ThinkGeo.MapSuite.VehicleTracking { public enum AutoRefreshMode { On = 0, Off = 1 } }
namespace ThinkGeo.MapSuite.VehicleTracking { public enum ControlMapMode { Pan = 0, DrawFence = 1, Measure = 2 } }
namespace ThinkGeo.MapSuite.VehicleTracking { public enum DrawFenceMode { DrawNewFence = 0, EditFence = 1 } }
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; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Windows; using System.Windows.Input; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.VehicleTracking.Properties; using ThinkGeo.MapSuite.WpfDesktopEdition; namespace ThinkGeo.MapSuite.VehicleTracking { public class MapModel { private static RectangleShape defaultExtent = new RectangleShape(-10785241.6495495, 3916508.33762434, -10778744.5183967, 3912187.74540771); private static Cursor handCursor = new Cursor(Application.GetResourceStream(new Uri("/MapSuiteVehicleTracking;component/Image/cursor_hand.cur", UriKind.RelativeOrAbsolute)).Stream); private WpfMap mapControl; public MapModel() : this(null) { } public MapModel(WpfMap map) { mapControl = map; InitializeMap(); } public WpfMap MapControl { get { return mapControl; } } public PopupOverlay PopupOverlay { get { return (PopupOverlay)mapControl.Overlays["PopupOverlay"]; } } public LayerOverlay TraceOverlay { get { return (LayerOverlay)mapControl.Overlays["TraceOverlay"]; } } public LayerOverlay SpatialFenceOverlay { get { return (LayerOverlay)mapControl.Overlays["SpatialFenceOverlay"]; } } public InMemoryFeatureLayer SpatialFenceLayer { get { return (InMemoryFeatureLayer)SpatialFenceOverlay.Layers["SpatialFenceLayer"]; } } public TrackMode TrackMode { get { return mapControl.TrackOverlay.TrackMode; } set { mapControl.TrackOverlay.TrackMode = value; mapControl.Cursor = mapControl.TrackOverlay.TrackMode == TrackMode.None ? handCursor : Cursors.Arrow; } } private void InitializeMap() { TrackMode = TrackMode.None; mapControl.MapClick += WpfMap1_MapClick; mapControl.MapUnit = GeographyUnit.Meter; mapControl.CurrentExtent = defaultExtent; InitializeMapTools(); InitializeOverlays(); } public void UpdateUnitSystem(UnitSystem selectedUnitSystem) { if (mapControl.AdornmentOverlay.Layers.Contains("ScaleBar")) { ScaleBarAdornmentLayer scaleBarLayer = (ScaleBarAdornmentLayer)mapControl.AdornmentOverlay.Layers["ScaleBar"]; scaleBarLayer.UnitFamily = selectedUnitSystem; mapControl.AdornmentOverlay.Refresh(); } } private void WpfMap1_MapClick(object sender, MapClickWpfMapEventArgs e) { if (e.MouseButton == MapMouseButton.Left) { RectangleShape clickedArea = MapSuiteSampleHelper.GetBufferedRectangle(e.WorldLocation, mapControl.CurrentResolution); PopupOverlay.Popups.Clear(); foreach (InMemoryFeatureLayer vehicleLayer in TraceOverlay.Layers.OfType<InMemoryFeatureLayer>()) { vehicleLayer.Open(); Collection<Feature> resultFeatures = vehicleLayer.QueryTools.GetFeaturesIntersecting(clickedArea, ReturningColumnsType.AllColumns); if (resultFeatures.Count > 0) { Popup popup = new Popup(e.WorldLocation); PopupUserControl popupUserControl = new PopupUserControl(resultFeatures[0]); popupUserControl.PopupOverlay = PopupOverlay; popup.Content = popupUserControl; PopupOverlay.Popups.Add(popup); PopupOverlay.Refresh(); break; } } } } private void OverlaySwitcher_BaseOverlayChanged(object sender, OverlayChangedOverlaySwitcherEventArgs e) { BingMapsOverlay bingMapsOverlay = e.Overlay as BingMapsOverlay; if (bingMapsOverlay != null) { bool cancel = ApplyBingMapsKey(); e.Cancel = cancel; } } private bool ApplyBingMapsKey() { bool cancel = false; string bingMapsKey = MapSuiteSampleHelper.GetBingMapsKey(); if (!string.IsNullOrEmpty(bingMapsKey)) { foreach (var bingOverlay in MapControl.Overlays.OfType<BingMapsOverlay>()) { bingOverlay.ApplicationId = bingMapsKey; } } else { cancel = true; } return cancel; } private void InitializeOverlays() { string cacheFolder = Path.Combine(Path.GetTempPath(), "TileCache"); WorldMapKitWmsWpfOverlay worldMapKitOverlay = new WorldMapKitWmsWpfOverlay(); worldMapKitOverlay.Name = Resources.WorldMapKitName; worldMapKitOverlay.TileHeight = 512; worldMapKitOverlay.TileWidth = 512; worldMapKitOverlay.IsVisible = true; worldMapKitOverlay.Projection = WorldMapKitProjection.SphericalMercator; worldMapKitOverlay.TileCache = new FileBitmapTileCache(cacheFolder, "WorldMapKit"); mapControl.Overlays.Add(Resources.WorldMapKitKey, worldMapKitOverlay); OpenStreetMapOverlay openStreetMapOverlay = new OpenStreetMapOverlay(); openStreetMapOverlay.Name = Resources.OpenStreetMapName; openStreetMapOverlay.TileHeight = 512; openStreetMapOverlay.TileWidth = 512; openStreetMapOverlay.IsVisible = false; openStreetMapOverlay.TileCache = new FileBitmapTileCache(cacheFolder, "OpenStreetMap"); mapControl.Overlays.Add(Resources.OpenStreetMapKey, openStreetMapOverlay); BingMapsOverlay bingMapsAerialOverlay = new BingMapsOverlay(); bingMapsAerialOverlay.Name = Resources.BingMapsAerialMapName; bingMapsAerialOverlay.TileHeight = 512; bingMapsAerialOverlay.TileWidth = 512; bingMapsAerialOverlay.MapType = BingMapsMapType.Aerial; bingMapsAerialOverlay.IsVisible = false; bingMapsAerialOverlay.TileCache = new FileBitmapTileCache(cacheFolder, "BingMapsAerial"); mapControl.Overlays.Add(Resources.BingAerialKey, bingMapsAerialOverlay); BingMapsOverlay bingMapsRoadOverlay = new BingMapsOverlay(); bingMapsRoadOverlay.Name = Resources.BingMapsRoadMapName; bingMapsRoadOverlay.TileHeight = 512; bingMapsRoadOverlay.TileWidth = 512; bingMapsRoadOverlay.MapType = BingMapsMapType.Road; bingMapsRoadOverlay.IsVisible = false; bingMapsRoadOverlay.TileCache = new FileBitmapTileCache(cacheFolder, "BingMapsRoad"); mapControl.Overlays.Add(Resources.BingRoadKey, bingMapsRoadOverlay); InMemoryFeatureLayer spatialFenceLayer = new InMemoryFeatureLayer(); spatialFenceLayer.Open(); spatialFenceLayer.Columns.Add(new FeatureSourceColumn(Resources.RestrictedName, "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(Resources.RestrictedName, "Arial", 12, DrawingFontStyles.Regular, GeoColor.StandardColors.Black, GeoColor.SimpleColors.White, 2); spatialFenceLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; LayerOverlay spatialFenceOverlay = new LayerOverlay(); spatialFenceOverlay.TileType = TileType.SingleTile; spatialFenceOverlay.Name = Resources.SpatialFenceOverlayName; spatialFenceOverlay.Layers.Add(Resources.SpatialFenceLayerName, spatialFenceLayer); mapControl.Overlays.Add(Resources.SpatialFenceOverlayName, spatialFenceOverlay); LayerOverlay traceOverlay = new LayerOverlay(); traceOverlay.Name = Resources.TraceOverlayName; traceOverlay.TileType = TileType.SingleTile; mapControl.Overlays.Add(Resources.TraceOverlayName, traceOverlay); mapControl.Overlays.Add(Resources.PopupOverlayName, new PopupOverlay { Name = Resources.PopupOverlayName }); ScaleBarAdornmentLayer scaleBarAdormentLayer = new ScaleBarAdornmentLayer(); scaleBarAdormentLayer.UnitFamily = UnitSystem.Metric; mapControl.AdornmentOverlay.Layers.Add(Resources.ScaleBarName, scaleBarAdormentLayer); } private void InitializeMapTools() { mapControl.MapTools.MouseCoordinate.IsEnabled = true; mapControl.MapTools.MouseCoordinate.Visibility = Visibility.Hidden; mapControl.MapTools.MouseCoordinate.MouseCoordinateType = MouseCoordinateType.Custom; mapControl.MapTools.PanZoomBar.GlobeButtonClick += PanZoomBar_GlobeButtonClick; OverlaySwitcher overlaySwitcher = new OverlaySwitcher(); overlaySwitcher.Initialize(mapControl); overlaySwitcher.OverlayChanged += OverlaySwitcher_BaseOverlayChanged; mapControl.MapTools.Add(overlaySwitcher); } private static void PanZoomBar_GlobeButtonClick(object sender, GlobeButtonClickPanZoomBarMapToolEventArgs e) { e.NewExtent = defaultExtent; } } }
namespace ThinkGeo.MapSuite.VehicleTracking { public enum MeasureMode { Line = 0, Polygon = 1 } }
using System.Collections.ObjectModel; 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 Collection<Location> historyLocations; public Vehicle() : this(0) { } public Vehicle(int id) { Id = id; Name = string.Empty; Location = new Location(); historyLocations = new Collection<Location>(); } public int Id { get { return id; } set { id = value; } } public Location Location { get { return location; } set { location = value; } } public Collection<Location> HistoryLocations { get { return historyLocations; } } public string Name { get { return name; } set { name = value; } } public string IconPath { 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; } } }
namespace ThinkGeo.MapSuite.VehicleTracking { /// <summary> /// This enumeration specifies the Possible states for Vehicles. /// </summary> public enum VehicleMotionState { Motion = 0, Idle = 1, } }