Mini Kabibi Habibi

Current Path : C:/Users/Public/Documents/DXperience 13.1 Demos/Silverlight/CS/MapDemo/Modules/
Upload File :
Current File : C:/Users/Public/Documents/DXperience 13.1 Demos/Silverlight/CS/MapDemo/Modules/MapElements.xaml.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Threading;
using System.Xml.Linq;
using DevExpress.Xpf.Map;

namespace MapDemo {
    public partial class MapElements : MapDemoModule {
        FlightMapDataGenerator dataGenerator;

        public MapElements() {
            InitializeComponent();
            dataGenerator = new FlightMapDataGenerator(Resources["airportTemplate"] as DataTemplate, Resources["planeTemplate"] as DataTemplate, planeInfoPanel);
            DataContext = dataGenerator;
            dataGenerator.SpeedScale = Convert.ToDouble(tbSpeedScale.Value);

        }
        void tbSpeedScale_EditValueChanged(object sender, DevExpress.Xpf.Editors.EditValueChangedEventArgs e) {
            if (dataGenerator != null)
                dataGenerator.SpeedScale = Convert.ToDouble(e.NewValue);
        }
    }

    public class PlaneTrajectory {
        class TrajectoryPart {
            readonly GeoPoint startPointField;
            readonly GeoPoint endPointField;
            readonly double flightTimeField;
            readonly double courseField;

            public GeoPoint StartPoint { get { return startPointField; } }
            public GeoPoint EndPoint { get { return endPointField; } }
            public double FlightTime { get { return flightTimeField; } }
            public double Course { get { return courseField; } }

            public TrajectoryPart(IProjection projection, GeoPoint startPoint, GeoPoint endPoint, double speedInKmH) {
                this.startPointField = startPoint;
                this.endPointField = endPoint;
                Size sizeInKm = projection.GeoToKilometersSize(startPoint, new Size(Math.Abs(startPoint.Longitude - endPoint.Longitude), Math.Abs(startPoint.Latitude - endPoint.Latitude)));
                double partlength = 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;
            }
            public GeoPoint GetPointByCurrentFlightTime(double currentFlightTime, IProjection projection) {
                if (currentFlightTime > FlightTime)
                    return endPointField;
                double ratio = currentFlightTime / FlightTime;
                return new GeoPoint(startPointField.Latitude + ratio * (endPointField.Latitude - startPointField.Latitude), startPointField.Longitude + ratio * (endPointField.Longitude - startPointField.Longitude));
            }
        }

        readonly List<TrajectoryPart> trajectory = new List<TrajectoryPart>();

        public GeoPoint StartPoint {
            get { return (trajectory.Count > 0) ? trajectory[0].StartPoint : new GeoPoint(0, 0); }
        }
        public GeoPoint EndPoint {
            get { return (trajectory.Count > 0) ? trajectory[trajectory.Count - 1].EndPoint : new GeoPoint(0, 0); }
        }
        public double FlightTime {
            get {
                double result = 0.0;
                foreach (TrajectoryPart part in trajectory)
                    result += part.FlightTime;
                return result;
            }
        }

        public PlaneTrajectory(List<GeoPoint> points, double speedInKmH) {
            SphericalMercatorProjection projection = new SphericalMercatorProjection();
            for (int i = 0; i < points.Count - 1; i++)
                trajectory.Add(new TrajectoryPart(projection, points[i], points[i + 1], speedInKmH));
        }
        public GeoPoint GetPointByCurrentFlightTime(double currentFlightTime) {
            SphericalMercatorProjection projection = new SphericalMercatorProjection();
            double time = 0.0;
            for (int i = 0; i < trajectory.Count - 1; i++) {
                if (trajectory[i].FlightTime > currentFlightTime - time)
                    return trajectory[i].GetPointByCurrentFlightTime(currentFlightTime - time, projection);
                time += trajectory[i].FlightTime;
            }
            return trajectory[trajectory.Count - 1].GetPointByCurrentFlightTime(currentFlightTime - time, projection);
        }
        public GeoPointCollection GetAirPath() {
            GeoPointCollection result = new GeoPointCollection();
            double currentFlightTime = 0.0;
            while (currentFlightTime < FlightTime) {
                result.Add(GetPointByCurrentFlightTime(currentFlightTime));
                currentFlightTime += 0.001;
            }
            result.Add(GetPointByCurrentFlightTime(FlightTime));
            return result;
        }
        public double GetCourseByCurrentFlightTime(double currentFlightTime) {
            double time = 0.0;
            for (int i = 0; i < trajectory.Count - 1; i++) {
                if (trajectory[i].FlightTime > currentFlightTime - time)
                    return trajectory[i].Course;
                time += trajectory[i].FlightTime;
            }
            return trajectory[trajectory.Count - 1].Course;
        }
    }

    public class PlaneInfo : DependencyObject {
        public static readonly DependencyProperty CurrentFlightTimeProperty = DependencyProperty.Register("CurrentFlightTime",
           typeof(double), typeof(PlaneInfo), new PropertyMetadata(0.0, new PropertyChangedCallback(CurrentFlightTimePropertyChanged)));
        public static readonly DependencyProperty PositionProperty = DependencyProperty.Register("Position",
           typeof(GeoPoint), typeof(PlaneInfo), new PropertyMetadata(new GeoPoint(0, 0)));
        public static readonly DependencyProperty CourseProperty = DependencyProperty.Register("Course",
           typeof(double), typeof(PlaneInfo), new PropertyMetadata(0.0));

        public double CurrentFlightTime {
            get { return (double)GetValue(CurrentFlightTimeProperty); }
            set { SetValue(CurrentFlightTimeProperty, value); }
        }
        public GeoPoint Position {
            get { return (GeoPoint)GetValue(PositionProperty); }
        }
        public double Course {
            get { return (double)GetValue(CourseProperty); }
        }

        static void CurrentFlightTimePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            PlaneInfo info = d as PlaneInfo;
            if (info != null)
                info.UpdatePosition((double)e.NewValue);
        }
        static string ConvertPlaneNameToFilePath(string PlaneName) {
            string result = PlaneName.Replace(" ", "");
            result = "../Images/Planes/" + result.Replace("-", "") + ".png";
            return result;
        }

        bool isLandedField = false;
        readonly string planeIDField;
        readonly string nameField;
        readonly string endPointNameField;
        readonly string startPointNameField;
        readonly double speedInKmHField;
        readonly double flightAltitudeField;
        readonly string imagePathField;
        readonly PlaneTrajectory trajectoryField;

        public string PlaneID { get { return planeIDField; } }
        public string Name { get { return nameField; } }
        public string EndPointName { get { return endPointNameField; } }
        public string StartPointName { get { return startPointNameField; } }
        public double SpeedKmH { get { return isLandedField ? 0.0 : speedInKmHField; } }
        public double FlightAltitude { get { return isLandedField ? 0.0 : flightAltitudeField; } }
        public string ImagePath { get { return imagePathField; } }
        public bool IsLanded { get { return isLandedField; } }
        public double TotalFlightTime { get { return trajectoryField.FlightTime; } }

        public PlaneInfo(string name, string id, string endPointName, string startPointName, double speedInKmH, double flightAltitude, List<GeoPoint> points) {
            this.nameField = name;
            this.planeIDField = id;
            this.endPointNameField = endPointName;
            this.startPointNameField = startPointName;
            this.speedInKmHField = speedInKmH;
            this.flightAltitudeField = flightAltitude;
            imagePathField = ConvertPlaneNameToFilePath(name);
            trajectoryField = new PlaneTrajectory(points, speedInKmH);
            UpdatePosition(CurrentFlightTime);
        }
        void UpdatePosition(double flightTime) {
            GeoPoint pos = trajectoryField.GetPointByCurrentFlightTime(flightTime);
            double course = trajectoryField.GetCourseByCurrentFlightTime(flightTime);
            isLandedField = flightTime >= trajectoryField.FlightTime;
            SetValue(PositionProperty, pos);
            SetValue(CourseProperty, course);
        }
        public List<MapItem> GetAirPath(DataTemplate airportTemplate) {
            List<MapItem> mapItemList = new List<MapItem>();
            mapItemList.Add(new MapPolyline() { Points = trajectoryField.GetAirPath(), Fill = new SolidColorBrush(Colors.Transparent), Stroke = new SolidColorBrush(Color.FromArgb(127, 255, 0, 199)), StrokeStyle = new StrokeStyle() { Thickness = 4 } });
            mapItemList.Add(new MapCustomElement() { Location = trajectoryField.StartPoint, ContentTemplate = airportTemplate });
            mapItemList.Add(new MapCustomElement() { Location = trajectoryField.EndPoint, ContentTemplate = airportTemplate });
            return mapItemList;
        }
    }

    public class FlightMapDataGenerator : DependencyObject {
        public static readonly DependencyProperty PlanesProperty = DependencyProperty.Register("Planes",
            typeof(ObservableCollection<MapCustomElement>), typeof(FlightMapDataGenerator), new PropertyMetadata(null));
        public static readonly DependencyProperty ActualAirPathProperty = DependencyProperty.Register("ActualAirPath",
            typeof(ObservableCollection<MapItem>), typeof(FlightMapDataGenerator), new PropertyMetadata(null));
        public static readonly DependencyProperty ActualPlaneInfoProperty = DependencyProperty.Register("ActualPlaneInfo",
            typeof(PlaneInfo), typeof(FlightMapDataGenerator), new PropertyMetadata(null));
        public static readonly DependencyProperty SelectedPlaneProperty = DependencyProperty.Register("SelectedPlane",
            typeof(MapCustomElement), typeof(FlightMapDataGenerator), new PropertyMetadata(null, new PropertyChangedCallback(SelectedPlaneProperyChanged)));

        public ObservableCollection<MapCustomElement> Planes {
            get { return (ObservableCollection<MapCustomElement>)GetValue(PlanesProperty); }
        }
        public ObservableCollection<MapItem> ActualAirPath {
            get { return (ObservableCollection<MapItem>)GetValue(ActualAirPathProperty); }
        }
        public PlaneInfo ActualPlaneInfo {
            get { return (PlaneInfo)GetValue(ActualPlaneInfoProperty); }
            set { SetValue(ActualPlaneInfoProperty, value); }
        }
        public MapCustomElement SelectedPlane {
            get { return (MapCustomElement)GetValue(SelectedPlaneProperty); }
            set { SetValue(SelectedPlaneProperty, value); }
        }
        public double SpeedScale {
            get { return speedScaleField; }
            set { speedScaleField = value; }
        }

        static void SelectedPlaneProperyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            FlightMapDataGenerator flightMapDataGenerator = d as FlightMapDataGenerator;
            if (flightMapDataGenerator != null)
                flightMapDataGenerator.UpdatePlaneInfo(e.NewValue as MapCustomElement);
        }

        const double mSecPerHour = 3600000;

        readonly DispatcherTimer timer = new DispatcherTimer();
        readonly DataTemplate airportTemplate;
        readonly List<PlaneInfo> planesInfo = new List<PlaneInfo>();
        readonly PlaneInfoPanel infoPanel;
        double speedScaleField;
        DateTime lastTime;

        public FlightMapDataGenerator(DataTemplate airportTemplate, DataTemplate planeTemplate, PlaneInfoPanel infoPanel) {
            this.SetValue(PlanesProperty, new ObservableCollection<MapCustomElement>());
            this.SetValue(ActualAirPathProperty, new ObservableCollection<MapItem>());
            this.airportTemplate = airportTemplate;
            this.infoPanel = infoPanel;
            LoadFromXML(planeTemplate);
            timer.Tick += new EventHandler(OnTimedEvent);
            timer.Interval = new TimeSpan(0, 0, 2);
            lastTime = DateTime.Now;
            timer.Start();
            if (Planes != null)
                SelectedPlane = Planes[1];
        }
        void LoadFromXML(DataTemplate planeTemplate) {
            XDocument document = DataLoader.LoadXmlFromResources("/Data/FlightMap.xml");
            if (document != null) {
                foreach (XElement element in document.Element("Planes").Elements()) {
                    List<GeoPoint> points = new List<GeoPoint>();
                    foreach (XElement infoElement in element.Element("Path").Elements()) {
                        GeoPoint geoPoint = new GeoPoint(Convert.ToDouble(infoElement.Element("Latitude").Value, CultureInfo.InvariantCulture), Convert.ToDouble(infoElement.Element("Longitude").Value, CultureInfo.InvariantCulture));
                        points.Add(geoPoint);
                    }
                    PlaneInfo info = 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);
                }
            }
            foreach (PlaneInfo info in planesInfo) {
                MapCustomElement mapCustomElement = new MapCustomElement() { Content = info, ContentTemplate = planeTemplate };
                BindingOperations.SetBinding(mapCustomElement, MapCustomElement.LocationProperty, new Binding("Position") { Source = info });
                Planes.Add(mapCustomElement);
            }
        }
        void UpdateCurrentPath(PlaneInfo planeInfo) {
            ActualAirPath.Clear();
            if (planeInfo != null)
                foreach (MapItem item in planeInfo.GetAirPath(airportTemplate))
                    ActualAirPath.Add(item);
        }
        void UpdatePlaneInfo(MapCustomElement plane) {
            ActualPlaneInfo = (plane != null) ? (plane.Content as PlaneInfo) : null;
            infoPanel.Visible = ActualPlaneInfo != null;
            UpdateCurrentPath(ActualPlaneInfo);
        }
        void OnTimedEvent(object source, EventArgs e) {
            DateTime currentTime = DateTime.Now;
            TimeSpan interval = currentTime.Subtract(lastTime);
            foreach (PlaneInfo info in planesInfo) {
                if (!info.IsLanded)
                    info.CurrentFlightTime += speedScaleField * interval.TotalMilliseconds / mSecPerHour;
            }
            lastTime = currentTime;
        }
    }
}