Mini Kabibi Habibi

Current Path : C:/Users/Public/Documents/DXperience 13.1 Demos/WPF/VB/MapDemo.Wpf/Modules/
Upload File :
Current File : C:/Users/Public/Documents/DXperience 13.1 Demos/WPF/VB/MapDemo.Wpf/Modules/MapElements.xaml.vb

Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Globalization
Imports System.Windows
Imports System.Windows.Data
Imports System.Windows.Media
Imports System.Windows.Threading
Imports System.Xml.Linq
Imports DevExpress.Xpf.Map

Namespace MapDemo
	Partial Public Class MapElements
		Inherits MapDemoModule
		Private dataGenerator As FlightMapDataGenerator

		Public Sub New()
			InitializeComponent()
			dataGenerator = New FlightMapDataGenerator(TryCast(Resources("airportTemplate"), DataTemplate), TryCast(Resources("planeTemplate"), DataTemplate), planeInfoPanel)
			DataContext = dataGenerator
			dataGenerator.SpeedScale = Convert.ToDouble(tbSpeedScale.Value)

		End Sub
		Private Sub tbSpeedScale_EditValueChanged(ByVal sender As Object, ByVal e As DevExpress.Xpf.Editors.EditValueChangedEventArgs)
			If dataGenerator IsNot Nothing Then
				dataGenerator.SpeedScale = Convert.ToDouble(e.NewValue)
			End If
		End Sub
	End Class

	Public Class PlaneTrajectory
		Private Class TrajectoryPart
			Private ReadOnly startPointField As GeoPoint
			Private ReadOnly endPointField As GeoPoint
			Private ReadOnly flightTimeField As Double
			Private ReadOnly courseField As Double

			Public ReadOnly Property StartPoint() As GeoPoint
				Get
					Return startPointField
				End Get
			End Property
			Public ReadOnly Property EndPoint() As GeoPoint
				Get
					Return endPointField
				End Get
			End Property
			Public ReadOnly Property FlightTime() As Double
				Get
					Return flightTimeField
				End Get
			End Property
			Public ReadOnly Property Course() As Double
				Get
					Return courseField
				End Get
			End Property

			Public Sub New(ByVal projection As IProjection, ByVal startPoint As GeoPoint, ByVal endPoint As GeoPoint, ByVal speedInKmH As Double)
				Me.startPointField = startPoint
				Me.endPointField = endPoint
				Dim sizeInKm As Size = projection.GeoToKilometersSize(startPoint, New Size(Math.Abs(startPoint.Longitude - endPoint.Longitude), Math.Abs(startPoint.Latitude - endPoint.Latitude)))
				Dim partlength As Double = Math.Sqrt(sizeInKm.Width * sizeInKm.Width + sizeInKm.Height * sizeInKm.Height)
				flightTimeField = partlength / speedInKmH
				courseField = Math.Atan2((endPoint.Longitude - startPoint.Longitude), (endPoint.Latitude - startPoint.Latitude)) * 180 / Math.PI
			End Sub
			Public Function GetPointByCurrentFlightTime(ByVal currentFlightTime As Double, ByVal projection As IProjection) As GeoPoint
				If currentFlightTime > FlightTime Then
					Return endPointField
				End If
				Dim ratio As Double = currentFlightTime / FlightTime
				Return New GeoPoint(startPointField.Latitude + ratio * (endPointField.Latitude - startPointField.Latitude), startPointField.Longitude + ratio * (endPointField.Longitude - startPointField.Longitude))
			End Function
		End Class

		Private ReadOnly trajectory As New List(Of TrajectoryPart)()

		Public ReadOnly Property StartPoint() As GeoPoint
			Get
				Return If((trajectory.Count > 0), trajectory(0).StartPoint, New GeoPoint(0, 0))
			End Get
		End Property
		Public ReadOnly Property EndPoint() As GeoPoint
			Get
				Return If((trajectory.Count > 0), trajectory(trajectory.Count - 1).EndPoint, New GeoPoint(0, 0))
			End Get
		End Property
		Public ReadOnly Property FlightTime() As Double
			Get
				Dim result As Double = 0.0
				For Each part As TrajectoryPart In trajectory
					result += part.FlightTime
				Next part
				Return result
			End Get
		End Property

		Public Sub New(ByVal points As List(Of GeoPoint), ByVal speedInKmH As Double)
			Dim projection As New SphericalMercatorProjection()
			For i As Integer = 0 To points.Count - 2
				trajectory.Add(New TrajectoryPart(projection, points(i), points(i + 1), speedInKmH))
			Next i
		End Sub
		Public Function GetPointByCurrentFlightTime(ByVal currentFlightTime As Double) As GeoPoint
			Dim projection As New SphericalMercatorProjection()
			Dim time As Double = 0.0
			For i As Integer = 0 To trajectory.Count - 2
				If trajectory(i).FlightTime > currentFlightTime - time Then
					Return trajectory(i).GetPointByCurrentFlightTime(currentFlightTime - time, projection)
				End If
				time += trajectory(i).FlightTime
			Next i
			Return trajectory(trajectory.Count - 1).GetPointByCurrentFlightTime(currentFlightTime - time, projection)
		End Function
		Public Function GetAirPath() As GeoPointCollection
			Dim result As New GeoPointCollection()
			Dim currentFlightTime As Double = 0.0
			Do While currentFlightTime < FlightTime
				result.Add(GetPointByCurrentFlightTime(currentFlightTime))
				currentFlightTime += 0.001
			Loop
			result.Add(GetPointByCurrentFlightTime(FlightTime))
			Return result
		End Function
		Public Function GetCourseByCurrentFlightTime(ByVal currentFlightTime As Double) As Double
			Dim time As Double = 0.0
			For i As Integer = 0 To trajectory.Count - 2
				If trajectory(i).FlightTime > currentFlightTime - time Then
					Return trajectory(i).Course
				End If
				time += trajectory(i).FlightTime
			Next i
			Return trajectory(trajectory.Count - 1).Course
		End Function
	End Class

	Public Class PlaneInfo
		Inherits DependencyObject
		Public Shared ReadOnly CurrentFlightTimeProperty As DependencyProperty = DependencyProperty.Register("CurrentFlightTime", GetType(Double), GetType(PlaneInfo), New PropertyMetadata(0.0, New PropertyChangedCallback(AddressOf CurrentFlightTimePropertyChanged)))
		Public Shared ReadOnly PositionProperty As DependencyProperty = DependencyProperty.Register("Position", GetType(GeoPoint), GetType(PlaneInfo), New PropertyMetadata(New GeoPoint(0, 0)))
		Public Shared ReadOnly CourseProperty As DependencyProperty = DependencyProperty.Register("Course", GetType(Double), GetType(PlaneInfo), New PropertyMetadata(0.0))

		Public Property CurrentFlightTime() As Double
			Get
				Return CDbl(GetValue(CurrentFlightTimeProperty))
			End Get
			Set(ByVal value As Double)
				SetValue(CurrentFlightTimeProperty, value)
			End Set
		End Property
		Public ReadOnly Property Position() As GeoPoint
			Get
				Return CType(GetValue(PositionProperty), GeoPoint)
			End Get
		End Property
		Public ReadOnly Property Course() As Double
			Get
				Return CDbl(GetValue(CourseProperty))
			End Get
		End Property

		Private Shared Sub CurrentFlightTimePropertyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
			Dim info As PlaneInfo = TryCast(d, PlaneInfo)
			If info IsNot Nothing Then
				info.UpdatePosition(CDbl(e.NewValue))
			End If
		End Sub
		Private Shared Function ConvertPlaneNameToFilePath(ByVal PlaneName As String) As String
			Dim result As String = PlaneName.Replace(" ", "")
			result = "../Images/Planes/" & result.Replace("-", "") & ".png"
			Return result
		End Function

		Private isLandedField As Boolean = False
		Private ReadOnly planeIDField As String
		Private ReadOnly nameField As String
		Private ReadOnly endPointNameField As String
		Private ReadOnly startPointNameField As String
		Private ReadOnly speedInKmHField As Double
		Private ReadOnly flightAltitudeField As Double
		Private ReadOnly imagePathField As String
		Private ReadOnly trajectoryField As PlaneTrajectory

		Public ReadOnly Property PlaneID() As String
			Get
				Return planeIDField
			End Get
		End Property
		Public ReadOnly Property Name() As String
			Get
				Return nameField
			End Get
		End Property
		Public ReadOnly Property EndPointName() As String
			Get
				Return endPointNameField
			End Get
		End Property
		Public ReadOnly Property StartPointName() As String
			Get
				Return startPointNameField
			End Get
		End Property
		Public ReadOnly Property SpeedKmH() As Double
			Get
				Return If(isLandedField, 0.0, speedInKmHField)
			End Get
		End Property
		Public ReadOnly Property FlightAltitude() As Double
			Get
				Return If(isLandedField, 0.0, flightAltitudeField)
			End Get
		End Property
		Public ReadOnly Property ImagePath() As String
			Get
				Return imagePathField
			End Get
		End Property
		Public ReadOnly Property IsLanded() As Boolean
			Get
				Return isLandedField
			End Get
		End Property
		Public ReadOnly Property TotalFlightTime() As Double
			Get
				Return trajectoryField.FlightTime
			End Get
		End Property

		Public Sub New(ByVal name As String, ByVal id As String, ByVal endPointName As String, ByVal startPointName As String, ByVal speedInKmH As Double, ByVal flightAltitude As Double, ByVal points As List(Of GeoPoint))
			Me.nameField = name
			Me.planeIDField = id
			Me.endPointNameField = endPointName
			Me.startPointNameField = startPointName
			Me.speedInKmHField = speedInKmH
			Me.flightAltitudeField = flightAltitude
			imagePathField = ConvertPlaneNameToFilePath(name)
			trajectoryField = New PlaneTrajectory(points, speedInKmH)
			UpdatePosition(CurrentFlightTime)
		End Sub
		Private Sub UpdatePosition(ByVal flightTime As Double)
			Dim pos As GeoPoint = trajectoryField.GetPointByCurrentFlightTime(flightTime)
			Dim course As Double = trajectoryField.GetCourseByCurrentFlightTime(flightTime)
			isLandedField = flightTime >= trajectoryField.FlightTime
			SetValue(PositionProperty, pos)
			SetValue(CourseProperty, course)
		End Sub
		Public Function GetAirPath(ByVal airportTemplate As DataTemplate) As List(Of MapItem)
			Dim mapItemList As New List(Of MapItem)()
			mapItemList.Add(New MapPolyline() With {.Points = trajectoryField.GetAirPath(), .Fill = New SolidColorBrush(Colors.Transparent), .Stroke = New SolidColorBrush(Color.FromArgb(127, 255, 0, 199)), .StrokeStyle = New StrokeStyle() With {.Thickness = 4}})
			mapItemList.Add(New MapCustomElement() With {.Location = trajectoryField.StartPoint, .ContentTemplate = airportTemplate})
			mapItemList.Add(New MapCustomElement() With {.Location = trajectoryField.EndPoint, .ContentTemplate = airportTemplate})
			Return mapItemList
		End Function
	End Class

	Public Class FlightMapDataGenerator
		Inherits DependencyObject
		Public Shared ReadOnly PlanesProperty As DependencyProperty = DependencyProperty.Register("Planes", GetType(ObservableCollection(Of MapCustomElement)), GetType(FlightMapDataGenerator), New PropertyMetadata(Nothing))
		Public Shared ReadOnly ActualAirPathProperty As DependencyProperty = DependencyProperty.Register("ActualAirPath", GetType(ObservableCollection(Of MapItem)), GetType(FlightMapDataGenerator), New PropertyMetadata(Nothing))
		Public Shared ReadOnly ActualPlaneInfoProperty As DependencyProperty = DependencyProperty.Register("ActualPlaneInfo", GetType(PlaneInfo), GetType(FlightMapDataGenerator), New PropertyMetadata(Nothing))
		Public Shared ReadOnly SelectedPlaneProperty As DependencyProperty = DependencyProperty.Register("SelectedPlane", GetType(MapCustomElement), GetType(FlightMapDataGenerator), New PropertyMetadata(Nothing, New PropertyChangedCallback(AddressOf SelectedPlaneProperyChanged)))

		Public ReadOnly Property Planes() As ObservableCollection(Of MapCustomElement)
			Get
				Return CType(GetValue(PlanesProperty), ObservableCollection(Of MapCustomElement))
			End Get
		End Property
		Public ReadOnly Property ActualAirPath() As ObservableCollection(Of MapItem)
			Get
				Return CType(GetValue(ActualAirPathProperty), ObservableCollection(Of MapItem))
			End Get
		End Property
		Public Property ActualPlaneInfo() As PlaneInfo
			Get
				Return CType(GetValue(ActualPlaneInfoProperty), PlaneInfo)
			End Get
			Set(ByVal value As PlaneInfo)
				SetValue(ActualPlaneInfoProperty, value)
			End Set
		End Property
		Public Property SelectedPlane() As MapCustomElement
			Get
				Return CType(GetValue(SelectedPlaneProperty), MapCustomElement)
			End Get
			Set(ByVal value As MapCustomElement)
				SetValue(SelectedPlaneProperty, value)
			End Set
		End Property
		Public Property SpeedScale() As Double
			Get
				Return speedScaleField
			End Get
			Set(ByVal value As Double)
				speedScaleField = value
			End Set
		End Property

		Private Shared Sub SelectedPlaneProperyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
			Dim flightMapDataGenerator As FlightMapDataGenerator = TryCast(d, FlightMapDataGenerator)
			If flightMapDataGenerator IsNot Nothing Then
				flightMapDataGenerator.UpdatePlaneInfo(TryCast(e.NewValue, MapCustomElement))
			End If
		End Sub

		Private Const mSecPerHour As Double = 3600000

		Private ReadOnly timer As New DispatcherTimer()
		Private ReadOnly airportTemplate As DataTemplate
		Private ReadOnly planesInfo As New List(Of PlaneInfo)()
		Private ReadOnly infoPanel As PlaneInfoPanel
		Private speedScaleField As Double
		Private lastTime As DateTime

		Public Sub New(ByVal airportTemplate As DataTemplate, ByVal planeTemplate As DataTemplate, ByVal infoPanel As PlaneInfoPanel)
			Me.SetValue(PlanesProperty, New ObservableCollection(Of MapCustomElement)())
			Me.SetValue(ActualAirPathProperty, New ObservableCollection(Of MapItem)())
			Me.airportTemplate = airportTemplate
			Me.infoPanel = infoPanel
			LoadFromXML(planeTemplate)
			AddHandler timer.Tick, AddressOf OnTimedEvent
			timer.Interval = New TimeSpan(0, 0, 2)
			lastTime = DateTime.Now
			timer.Start()
			If Planes IsNot Nothing Then
				SelectedPlane = Planes(1)
			End If
		End Sub
		Private Sub LoadFromXML(ByVal planeTemplate As DataTemplate)
			Dim document As XDocument = DataLoader.LoadXmlFromResources("/Data/FlightMap.xml")
			If document IsNot Nothing Then
				For Each element As XElement In document.Element("Planes").Elements()
					Dim points As New List(Of GeoPoint)()
					For Each infoElement As XElement In element.Element("Path").Elements()
						Dim geoPoint As New GeoPoint(Convert.ToDouble(infoElement.Element("Latitude").Value, CultureInfo.InvariantCulture), Convert.ToDouble(infoElement.Element("Longitude").Value, CultureInfo.InvariantCulture))
						points.Add(geoPoint)
					Next infoElement
					Dim info As New PlaneInfo(element.Element("PlaneName").Value, element.Element("PlaneID").Value, element.Element("EndPointName").Value, element.Element("StartPointName").Value, Convert.ToInt32(element.Element("Speed").Value), Convert.ToInt32(element.Element("Altitude").Value), points)
					info.CurrentFlightTime = Convert.ToDouble(element.Element("CurrentFlightTime").Value, CultureInfo.InvariantCulture)
					planesInfo.Add(info)
				Next element
			End If
			For Each info As PlaneInfo In planesInfo
				Dim mapCustomElement As New MapCustomElement() With {.Content = info, .ContentTemplate = planeTemplate}
				BindingOperations.SetBinding(mapCustomElement, MapCustomElement.LocationProperty, New Binding("Position") With {.Source = info})
				Planes.Add(mapCustomElement)
			Next info
		End Sub
		Private Sub UpdateCurrentPath(ByVal planeInfo As PlaneInfo)
			ActualAirPath.Clear()
			If planeInfo IsNot Nothing Then
				For Each item As MapItem In planeInfo.GetAirPath(airportTemplate)
					ActualAirPath.Add(item)
				Next item
			End If
		End Sub
		Private Sub UpdatePlaneInfo(ByVal plane As MapCustomElement)
			ActualPlaneInfo = If((plane IsNot Nothing), (TryCast(plane.Content, PlaneInfo)), Nothing)
			infoPanel.Visible = ActualPlaneInfo IsNot Nothing
			UpdateCurrentPath(ActualPlaneInfo)
		End Sub
		Private Sub OnTimedEvent(ByVal source As Object, ByVal e As EventArgs)
			Dim currentTime As DateTime = DateTime.Now
			Dim interval As TimeSpan = currentTime.Subtract(lastTime)
			For Each info As PlaneInfo In planesInfo
				If (Not info.IsLanded) Then
					info.CurrentFlightTime += speedScaleField * interval.TotalMilliseconds / mSecPerHour
				End If
			Next info
			lastTime = currentTime
		End Sub
	End Class
End Namespace