Mini Kabibi Habibi

Current Path : C:/Users/Public/Documents/DXperience 13.1 Demos/WinForms/CS/MapMainDemo/Modules/
Upload File :
Current File : C:/Users/Public/Documents/DXperience 13.1 Demos/WinForms/CS/MapMainDemo/Modules/MapElements.cs

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Xml.Linq;
using System.Globalization;
using System.Collections;
using System.ComponentModel;
using System.Drawing.Imaging;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;

namespace DevExpress.XtraMap.Demos {

    public partial class MapElements : MapTutorialControl {
        FlightMapDataGenerator dataGenerator;
        VectorItemsLayer PlanesLayer { get { return (VectorItemsLayer)(mapControl1.Layers[2]); } }
        VectorItemsLayer PathsLayer { get { return (VectorItemsLayer)(mapControl1.Layers[1]); } }
        ImageTilesLayer TilesLayer { get { return (ImageTilesLayer)(mapControl1.Layers[0]); } }
        PlaneInfoVisualizer planeInfoVisualizer;


        public MapElements() {
            InitializeComponent();
            InitializePlaneInfoVisualizer();
            mapControl1.SetMapItemFactory(new FlightMapFactory());
            TilesLayer.DataProvider = CreateBingDataProvider(BingMapKind.Road);
            dataGenerator = new FlightMapDataGenerator(planeInfoVisualizer);
            dataGenerator.DataChanged += OnDataChanged;
            PlanesLayer.DataSource = dataGenerator.Planes;
            PathsLayer.DataSource = dataGenerator.AirPath;
            UpdateSpeedScale();
        }

        void OnDataChanged(object sender, EventArgs e) {
            foreach (PlaneInfo info in dataGenerator.Planes) {
                if (!info.IsLanded) {
                    MapCustomElement item = PlanesLayer.GetMapItemBySourceObject(info) as MapCustomElement;
                    if (item != null) item.Location = new GeoPoint(info.Latitude, info.Longitude);
                }
            }
        }

        void InitializePlaneInfoVisualizer() {
            planeInfoVisualizer = new PlaneInfoVisualizer() {
                AltitudeLabel = lbAltitude,
                SpeedLabel = lbSpeed,
                FlightTimeLabel = lbFlightTime,
                CurrentTimeLabel = lbCurrentTime,
                ToLabel = lbTo,
                FromLabel = lbFrom,
                FlightNumberLabel = lbFlightNaumber,
                NameLabel = lbName,
                PlaneImage = pictureEdit1,
                PlaneInfoPanel = planeInfoPanel
            };
        }
        void mapControl1_DrawMapItem(object sender, DrawMapItemEventArgs e) {
            DrawMapPointerEventArgs args = e as DrawMapPointerEventArgs;
            if (args != null) {
                MapItem item = e.Item;
                InfoBase info = ((VectorItemsLayer)e.Item.Layer).GetItemSourceObject(item) as InfoBase;
                if (info != null)
                    args.Image = info.Icon;
            }
        }
        void mapControl1_SelectionChanged(object sender, MapSelectionChangedEventArgs e) {
            if (e.Selection.Count > 0) {
                dataGenerator.SelectedPlane = (PlaneInfo)PlanesLayer.GetItemSourceObject((MapItem)(e.Selection[0]));
                return;
            }
            dataGenerator.SelectedPlane = null;
        }
        void trackBarControl1_ValueChanged(object sender, EventArgs e) {
            UpdateSpeedScale();
        }
        void UpdateSpeedScale() {
            if (dataGenerator != null) dataGenerator.SpeedScale = trackBarControl1.Value;
        }
        protected override void OnVisibleChanged(EventArgs e) {
            base.OnVisibleChanged(e);
            if (this.Visible)
                dataGenerator.Start();
            else
                dataGenerator.Stop();
        }
    }

    public abstract class InfoBase {
        protected abstract MapItemType Type { get; }
        public int ItemType { get { return (int)Type; } }
        public virtual Image Icon { get { return null; } }

        public double Latitude { get; set; }
        public double Longitude { get; set; }
    }

    public class AirportInfo : InfoBase {
        static Bitmap icon = new Bitmap(DemoUtils.GetRelativePath("\\Images\\Airport.png"));

        protected override MapItemType Type { get { return MapItemType.Custom; } }
        public override Image Icon { get { return icon; } }

        public AirportInfo(GeoPoint location) {
            this.Latitude = location.Latitude;
            this.Longitude = location.Longitude;
        }
    }

    public class PlaneTrajectory : InfoBase {
        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;
                MapSize sizeInKm = projection.GeoToKilometersSize(startPoint, new MapSize(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>();
        readonly AirportInfo startPoint;
        readonly AirportInfo endPoint;

        protected override MapItemType Type { get { return MapItemType.Polyline; } }
        public AirportInfo StartPoint { get { return startPoint; } }
        public AirportInfo EndPoint { get { return endPoint; } }
        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));
            startPoint = new AirportInfo((trajectory.Count > 0) ? trajectory[0].StartPoint : new GeoPoint(0, 0));
            endPoint = new AirportInfo((trajectory.Count > 0) ? trajectory[trajectory.Count - 1].EndPoint : new GeoPoint(0, 0));
        }
        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 : InfoBase {
        static double Degree2Radian(double angleDegree) {
            return angleDegree * Math.PI / 180.0;
        }

        static Image RotateImage(Image inputImage, double angleDegrees) {
            Color backgroundColor = Color.Transparent;
            bool upsizeOk = false;
            bool clipOk = true;
            if (angleDegrees == 0f)
                return (Bitmap)inputImage.Clone();

            int oldWidth = inputImage.Width;
            int oldHeight = inputImage.Height;
            int newWidth = oldWidth;
            int newHeight = oldHeight;
            float scaleFactor = 1f;

            if (upsizeOk || !clipOk) {
                double angleRadians = angleDegrees * Math.PI / 180d;
                double cos = Math.Abs(Math.Cos(angleRadians));
                double sin = Math.Abs(Math.Sin(angleRadians));
                newWidth = (int)Math.Round(oldWidth * cos + oldHeight * sin);
                newHeight = (int)Math.Round(oldWidth * sin + oldHeight * cos);
            }
            if (!upsizeOk && !clipOk) {
                scaleFactor = Math.Min((float)oldWidth / newWidth, (float)oldHeight / newHeight);
                newWidth = oldWidth;
                newHeight = oldHeight;
            }
            Bitmap newBitmap = new Bitmap(newWidth, newHeight, backgroundColor == Color.Transparent ?
                                             PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb);
            newBitmap.SetResolution(inputImage.HorizontalResolution, inputImage.VerticalResolution);
            using (Graphics graphicsObject = Graphics.FromImage(newBitmap)) {
                graphicsObject.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphicsObject.PixelOffsetMode = PixelOffsetMode.HighQuality;
                graphicsObject.SmoothingMode = SmoothingMode.HighQuality;
                if (backgroundColor != Color.Transparent)
                    graphicsObject.Clear(backgroundColor);
                graphicsObject.TranslateTransform(newWidth / 2f, newHeight / 2f);
                if (scaleFactor != 1f)
                    graphicsObject.ScaleTransform(scaleFactor, scaleFactor);
                graphicsObject.RotateTransform((float)angleDegrees);
                graphicsObject.TranslateTransform(-oldWidth / 2f, -oldHeight / 2f);
                graphicsObject.DrawImage(inputImage, 0, 0);
            }
            return newBitmap;
        }
        static string ConvertPlaneNameToFilePath(string PlaneName) {
            string result = PlaneName.Replace(" ", "");
            result = "\\Images\\Planes\\" + result.Replace("-", "") + ".png";
            return DemoUtils.GetRelativePath(result);
        }

        bool isLandedField = false;
        double currentFlightTime;
        double course;
        Image icon;
        readonly Image sourceIcon;
        readonly string planeIDField;
        readonly string nameField;
        readonly string endPointNameField;
        readonly string startPointNameField;
        readonly double speedInKmHField;
        readonly double flightAltitudeField;
        readonly Image imageField;
        readonly PlaneTrajectory trajectoryField;

        double Course {
            get { return course; }
            set {
                if (course == value)
                    return;
                course = value;
                UpdateIcon();
            }
        }
        protected override MapItemType Type { get { return MapItemType.Custom; } }
        public double CurrentFlightTime {
            get { return currentFlightTime; }
            set {
                if (currentFlightTime == value)
                    return;
                currentFlightTime = value;
                UpdatePosition(currentFlightTime);
            }
        }
        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 Image Image { get { return imageField; } }
        public bool IsLanded { get { return isLandedField; } }
        public double TotalFlightTime { get { return trajectoryField.FlightTime; } }
        public override Image Icon { get { return icon; } }

        public PlaneInfo(string name, string id, string endPointName, string startPointName, double speedInKmH, double flightAltitude, List<GeoPoint> points, Image sourceIcon) {
            this.nameField = name;
            this.planeIDField = id;
            this.sourceIcon = sourceIcon;
            this.endPointNameField = endPointName;
            this.startPointNameField = startPointName;
            this.speedInKmHField = speedInKmH;
            this.flightAltitudeField = flightAltitude;
            this.imageField = new Bitmap(ConvertPlaneNameToFilePath(name));
            trajectoryField = new PlaneTrajectory(points, speedInKmH);
            UpdatePosition(CurrentFlightTime);
        }
        void UpdatePosition(double flightTime) {
            isLandedField = flightTime >= trajectoryField.FlightTime;
            GeoPoint point = trajectoryField.GetPointByCurrentFlightTime(flightTime);
            Latitude = point.Latitude;
            Longitude = point.Longitude;
            Course = trajectoryField.GetCourseByCurrentFlightTime(flightTime);
        }
        void UpdateIcon() {
            if (icon != null)
                icon.Dispose();
            icon = RotateImage(sourceIcon, Course);
        }
        public void UpdateAirPath(InfoList airPath) {
            airPath.Add(trajectoryField);
            airPath.Add(trajectoryField.StartPoint);
            airPath.Add(trajectoryField.EndPoint);
        }
    }

    public class FlightMapDataGenerator : IDisposable {
        const double mSecPerHour = 3600000;

        PlaneInfo selectedPlane;
        DateTime lastTime;
        bool isDisposed;
        readonly InfoList planes = new InfoList();
        readonly InfoList airPath = new InfoList();
        readonly Timer timer = new Timer();
        readonly Image sourcePlaneIcon;
        readonly PlaneInfoVisualizer visualizer;

        public InfoList Planes { get { return planes; } }
        public InfoList AirPath { get { return airPath; } }
        public PlaneInfo SelectedPlane {
            get { return selectedPlane; }
            set {
                if (selectedPlane == value)
                    return;
                selectedPlane = value;
                UpdatePlaneInfo(selectedPlane);
            }
        }
        public double SpeedScale { get; set; }

        public FlightMapDataGenerator(PlaneInfoVisualizer visualizer) {
            this.visualizer = visualizer;
            sourcePlaneIcon = new Bitmap(DemoUtils.GetRelativePath("Images\\Plane.png"));
            LoadFromXML();
            timer.Tick += new EventHandler(OnTimedEvent);
            timer.Interval = 2000;
            SelectedPlane = (PlaneInfo)Planes[1];
        }
        ~FlightMapDataGenerator() {
            Dispose(false);
        }

        public event EventHandler DataChanged;

        void RaiseDataChanged() {
            if (DataChanged != null) DataChanged(this, EventArgs.Empty);
        }
        void LoadFromXML() {
            XDocument document = DemoUtils.LoadXml("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, sourcePlaneIcon);
                    info.CurrentFlightTime = Convert.ToDouble(element.Element("CurrentFlightTime").Value, CultureInfo.InvariantCulture);
                    planes.Add(info);
                }
            }
        }
        void UpdatePlaneInfo(PlaneInfo planeInfo) {
            visualizer.SelectedPlane = planeInfo;
            airPath.Clear();
            if (planeInfo != null)
                planeInfo.UpdateAirPath(airPath);
        }
        void OnTimedEvent(object source, EventArgs e) {
            DateTime currentTime = DateTime.Now;
            TimeSpan interval = currentTime.Subtract(lastTime);
            foreach (PlaneInfo info in planes) {
                if (!info.IsLanded)
                    info.CurrentFlightTime += SpeedScale * interval.TotalMilliseconds / mSecPerHour;
            }
            lastTime = currentTime;
            visualizer.Update();
            RaiseDataChanged();
        }
        void Dispose(bool disposing) {
            if (disposing && !isDisposed) {
                isDisposed = true;
                Stop();
                if (timer != null)
                    timer.Dispose();
                if (sourcePlaneIcon != null)
                    sourcePlaneIcon.Dispose();
            }
        }
        public void Dispose() {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        public void Start() {
            lastTime = DateTime.Now;
            timer.Start();
        }
        public void Stop() {
            timer.Stop();
        }
    }

    public class PlaneInfoVisualizer {
        PlaneInfo selectedPlane;

        public LabelControl NameLabel { get; set; }
        public LabelControl FlightNumberLabel { get; set; }
        public LabelControl FromLabel { get; set; }
        public LabelControl ToLabel { get; set; }
        public LabelControl CurrentTimeLabel { get; set; }
        public LabelControl FlightTimeLabel { get; set; }
        public LabelControl SpeedLabel { get; set; }
        public LabelControl AltitudeLabel { get; set; }
        public PanelControl PlaneInfoPanel { get; set; }
        public PictureEdit PlaneImage { get; set; }
        public PlaneInfo SelectedPlane {
            get { return selectedPlane; }
            set {
                if (selectedPlane == value)
                    return;
                selectedPlane = value;
                Update();
            }
        }

        public void Update() {
            if (selectedPlane == null) {
                PlaneInfoPanel.Visible = false;
                return;
            }
            PlaneInfoPanel.Visible = true;
            NameLabel.Text = selectedPlane.Name;
            FlightNumberLabel.Text = selectedPlane.PlaneID;
            FromLabel.Text = selectedPlane.StartPointName;
            ToLabel.Text = selectedPlane.EndPointName;
            CurrentTimeLabel.Text = new TimeSpan(0, 0, (int)Math.Ceiling(selectedPlane.CurrentFlightTime * 3600)).ToString();
            FlightTimeLabel.Text = new TimeSpan(0, 0, (int)Math.Ceiling(selectedPlane.TotalFlightTime * 3600)).ToString();
            SpeedLabel.Text = selectedPlane.SpeedKmH.ToString();
            AltitudeLabel.Text = selectedPlane.FlightAltitude.ToString();
            PlaneImage.Image = selectedPlane.Image;
        }
    }

    public class FlightMapFactory : DefaultMapItemFactory {
        protected override void InitializeItem(MapItem item, object obj) {
            base.InitializeItem(item, obj);
            MapPolyline polyLine = item as MapPolyline;
            PlaneTrajectory trajectory = obj as PlaneTrajectory;
            if (polyLine != null && trajectory != null) {
                polyLine.Points = trajectory.GetAirPath();
                polyLine.Fill = Color.Empty;
                polyLine.Stroke = Color.FromArgb(127, 255, 0, 199);
                polyLine.StrokeWidth = 4;
            }
        }
    }

    public class InfoList : CollectionBase, IBindingList {
        ListChangedEventHandler listChangedHandler;

        public InfoBase this[int idx] { get { return (InfoBase)base.List[idx]; } }
        public bool AllowEdit { get { return true; } }
        public bool AllowNew { get { return false; } }
        public bool AllowRemove { get { return true; } }

        public event ListChangedEventHandler ListChanged {
            add { listChangedHandler += value; }
            remove { listChangedHandler -= value; }
        }

        protected override void OnRemoveComplete(int index, object value) {
            OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index));
        }
        protected override void OnInsertComplete(int index, object value) {
            OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index));
        }
        internal void OnListChanged(ListChangedEventArgs args) {
            if (listChangedHandler != null) {
                listChangedHandler(this, args);
            }
        }
        protected override void OnClearComplete() {
            base.OnClearComplete();
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }
        public void Add(InfoBase appointment) {
            base.List.Add(appointment);
        }
        public int IndexOf(InfoBase appointment) {
            return List.IndexOf(appointment);
        }
        public object AddNew() { throw new NotSupportedException(); }
        public void AddIndex(PropertyDescriptor pd) { throw new NotSupportedException(); }
        public void ApplySort(PropertyDescriptor pd, ListSortDirection dir) { throw new NotSupportedException(); }
        public int Find(PropertyDescriptor property, object key) { throw new NotSupportedException(); }
        public bool IsSorted { get { return false; } }
        public void RemoveIndex(PropertyDescriptor pd) { throw new NotSupportedException(); }
        public void RemoveSort() { throw new NotSupportedException(); }
        public ListSortDirection SortDirection { get { throw new NotSupportedException(); } }
        public PropertyDescriptor SortProperty { get { throw new NotSupportedException(); } }
        public bool SupportsChangeNotification { get { return true; } }
        public bool SupportsSearching { get { return false; } }
        public bool SupportsSorting { get { return false; } }
    }
}