User Tools

Site Tools


source_code_map_suite_wpf_desktop_edition_label_flight_lines.zip

Source Code Labeling Flight Lines

MainWindow.xaml.cs

using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.WpfDesktopEdition;
 
namespace LabelingFlightLines
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
 
        private void WindowLoaded(object sender, RoutedEventArgs e)
        {
            map.MapUnit = GeographyUnit.DecimalDegree;
            map.CurrentExtent = new RectangleShape(-126.5183123, 89.08823382097, 50.6691877, -39.0562974290296);
 
            //Create a world map kit
            map.Overlays.Add(new WorldMapKitWmsWpfOverlay());
 
            //Create a layer to display oll of the flight points and lines
            LayerOverlay overlay = new LayerOverlay();
            InMemoryFeatureLayer flightsLayer = new InMemoryFeatureLayer();
            flightsLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = new LineStyle(new GeoPen(GeoColors.LightGreen, 2));
            flightsLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(), new GeoPen(GeoColors.Black, 1.5f), 7);
            flightsLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            overlay.Layers.Add("FlightsLayer", flightsLayer);
            map.Overlays.Add("FlightsOverlay", overlay);
 
            //Create a layer for the popups
            map.Overlays.Add("PopupOverlay", new PopupOverlay());
 
            InitializeData();
        }
 
        private void InitializeData()
        {
            Collection<Flight> flights = new Collection<Flight>();
            InMemoryFeatureLayer flightsLayer = (InMemoryFeatureLayer)((LayerOverlay)map.Overlays["FlightsOverlay"]).Layers["FlightsLayer"];
 
            //Parse the data out of the csv file
            string[] flightsSource = File.ReadAllLines("./AppData/SampleData.csv", Encoding.ASCII);
            foreach (var item in flightsSource.Skip(1))
            {
                string[] cell = item.Split(',');
                Flight flight = new Flight
                {
                    Name = cell[0],
                    FlightNumber = cell[1],
                    Date = cell[2],
                    FlightTime = cell[3],
                    OriginAddress = cell[4],
                    DestinationAddress = cell[10]
                };
 
                string[] originLocation = cell[5].Split(' ');
                flight.OriginLocation = new PointShape(Convert.ToDouble(originLocation[1]), Convert.ToDouble(originLocation[0]));
                string[] destinationLocation = cell[11].Split(' ');
                flight.DestinationLocation = new PointShape(Convert.ToDouble(destinationLocation[1]), Convert.ToDouble(destinationLocation[0]));
 
                double offset = 0;
                foreach (var existingFlight in flights)
                {
                    //If the flight already exists we offset the crest of the arc by an ammount to seperate the lines so that both are visible
                    if (flight.OriginLocation.Equal2D(existingFlight.OriginLocation) && flight.DestinationLocation.Equal2D(existingFlight.DestinationLocation))
                    {
                        offset += flight.OriginLocation.GetDistanceTo(flight.DestinationLocation, GeographyUnit.DecimalDegree, DistanceUnit.Mile)/3500;
                    }
                }
 
                //get arc to draw for flight
                MultilineShape flightLine = flight.GetArc(offset);
 
                flight.FlightLineShape = flightLine.Lines[0];
                flight.FlightLineCenter = flightLine.GetPointOnALine(StartingPoint.FirstPoint, 50f);
                flightsLayer.InternalFeatures.Add(new Feature(flight.OriginLocation));
                flightsLayer.InternalFeatures.Add(new Feature(flight.DestinationLocation));
                flightsLayer.InternalFeatures.Add(new Feature(flight.FlightLineShape));
                flights.Add(flight);
            }
 
            FlightsList.ItemsSource = flights;
        }
 
        private void DisplayFlightsPopup(object sender, RoutedEventArgs e)
        {
            //Create a popup for the origin, destination, and flight line the flight when the radio button is clicked
            RadioButton radioButton = (RadioButton)sender;
            Flight flight = (Flight)radioButton.DataContext;
 
            PopupOverlay popupOverlay = (PopupOverlay)map.Overlays["PopupOverlay"];
            popupOverlay.Popups.Clear();
 
            Popup originPopup = new Popup(flight.OriginLocation) { Content = new FlightsContent(flight, false) };
            popupOverlay.Popups.Add(originPopup);
 
            Popup destinationPopup = new Popup(flight.DestinationLocation) { Content = new FlightsContent(flight, false) };
            popupOverlay.Popups.Add(destinationPopup);
 
            Popup flightLinePopup = new Popup(flight.FlightLineCenter) { Content = new FlightsContent(flight, true) };
            popupOverlay.Popups.Add(flightLinePopup);
 
            map.Refresh();
        }
    }
}

Flight.cs

using System;
using ThinkGeo.MapSuite.Core;
 
namespace LabelingFlightLines
{
    public class Flight
    {
        private string name;
        private string flightNumber;
        private string date;
        private string flightTime;
        private string originAddress;
        private PointShape originLocation;
        private string destinationAddress;
        private PointShape destinationLocation;
        private PointShape flightLineCenter;
        private LineShape flightLineShape;
 
        public Flight()
        { }
 
        public string Key
        {
            get { return Name + "-" + FlightNumber; }
        }
 
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
 
        public string FlightNumber
        {
            get { return flightNumber; }
            set { flightNumber = value; }
        }
 
        public string Date
        {
            get { return date; }
            set { date = value; }
        }
 
        public string FlightTime
        {
            get { return flightTime; }
            set { flightTime = value; }
        }
 
        public string OriginAddress
        {
            get { return originAddress; }
            set { originAddress = value; }
        }
 
        public PointShape OriginLocation
        {
            get { return originLocation; }
            set { originLocation = value; }
        }
 
        public string DestinationAddress
        {
            get { return destinationAddress; }
            set { destinationAddress = value; }
        }
 
        public PointShape DestinationLocation
        {
            get { return destinationLocation; }
            set { destinationLocation = value; }
        }
 
        public PointShape FlightLineCenter
        {
            get { return flightLineCenter; }
            set { flightLineCenter = value; }
        }
 
        public LineShape FlightLineShape
        {
            get { return flightLineShape; }
            set { flightLineShape = value; }
        }
 
        public MultilineShape GetArc(double offset)
        {
            RectangleShape rectangle = new RectangleShape(-180, 90, 180, -90);
            if (rectangle.Contains(destinationLocation) && rectangle.Contains(originLocation))
            {
                return GetArc(1000, offset);
            }
            else
            {
                return null;
            }
        }
 
        private MultilineShape GetArc(int count, double offset)
        {
            //Create a stylized arc with the given offset to allow the lines to be visible next to each other
 
            double radiansFactor = Math.PI / 180;
            double degreesFactor = 180 / Math.PI;
 
            double newX = 0;
            double newY = 0;
 
            double long1 = originLocation.X * radiansFactor;
            double lat1 = originLocation.Y * radiansFactor;
            double long2 = destinationLocation.X * radiansFactor;
            double lat2 = destinationLocation.Y * radiansFactor;
 
            double x1 = Math.Cos(long1) * Math.Cos(lat1);
            double x2 = Math.Cos(long2) * Math.Cos(lat2);
            double y1 = Math.Sin(long1) * Math.Cos(lat1);
            double y2 = Math.Sin(long2) * Math.Cos(lat2);
            double z1 = Math.Sin(lat1);
            double z2 = Math.Sin(lat2);
 
            double alpha = Math.Acos((x1 * x2) + (y1 * y2) + (z1 * z2));
 
            if (alpha == 0)
            {
                return new MultilineShape(new LineShape[] { new LineShape(new Vertex[] { new Vertex(originLocation), new Vertex(destinationLocation) }) });
            }
 
            double x3 = (x2 - (x1 * Math.Cos(alpha))) / Math.Sin(alpha);
            double y3 = (y2 - (y1 * Math.Cos(alpha))) / Math.Sin(alpha);
            double z3 = (z2 - (z1 * Math.Cos(alpha))) / Math.Sin(alpha);
 
            MultilineShape returnMultiLine = new MultilineShape();
            LineShape lineShape1 = new LineShape();
            LineShape lineShape2 = new LineShape();
            lineShape1.Vertices.Add(new Vertex(originLocation.X, originLocation.Y));
            bool isDisconnected = false;
            for (int i = 1; i <= count; i++)
            {
                double xbm = (x1 * Math.Cos((i * alpha) / (count + 1))) + (x3 * Math.Sin((i * alpha) / (count + 1)));
                double ybm = (y1 * Math.Cos((i * alpha) / (count + 1))) + (y3 * Math.Sin((i * alpha) / (count + 1)));
                double zbm = (z1 * Math.Cos((i * alpha) / (count + 1))) + (z3 * Math.Sin((i * alpha) / (count + 1)));
 
                if (ybm < 0 && xbm < 0)
                {
                    newX = Math.Atan(ybm / xbm) * degreesFactor - 180;
                }
                else if (ybm > 0 && xbm < 0)
                {
                    newX = Math.Atan(ybm / xbm) * degreesFactor + 180;
                }
                else
                {
                    newX = Math.Atan(ybm / xbm) * degreesFactor;
                }
                newY = Math.Asin(zbm) * degreesFactor + ((-1) * (offset / Math.Pow(count / 2, 2)) * Math.Pow(i - count / 2, 2) + offset);
                if ((i > 2) && (isDisconnected == false))
                {
                    double lastDistance = Math.Sqrt(Math.Pow((lineShape1.Vertices[i - 2].X - lineShape1.Vertices[i - 3].X), 2) + Math.Pow((lineShape1.Vertices[i - 2].Y - lineShape1.Vertices[i - 3].Y), 2));
                    double currentDistance = Math.Sqrt(Math.Pow((newX - lineShape1.Vertices[i - 2].X), 2) + Math.Pow((newY - lineShape1.Vertices[i - 2].Y), 2));
                    if (currentDistance > (lastDistance * 6))
                    {
                        isDisconnected = true;
                    }
                }
                if (isDisconnected == false)
                {
                    lineShape1.Vertices.Add(new Vertex(newX, newY));
                }
                else
                {
                    lineShape2.Vertices.Add(new Vertex(newX, newY));
                }
            }
 
            if (isDisconnected == false)
            {
                lineShape1.Vertices.Add(new Vertex(destinationLocation.X, destinationLocation.Y));
                returnMultiLine.Lines.Add(lineShape1);
            }
            else
            {
                lineShape2.Vertices.Add(new Vertex(destinationLocation.X, destinationLocation.Y));
                returnMultiLine.Lines.Add(lineShape1);
                returnMultiLine.Lines.Add(lineShape2);
            }
            return returnMultiLine;
        }
    }
}
source_code_map_suite_wpf_desktop_edition_label_flight_lines.zip.txt · Last modified: 2016/09/16 21:04 by jd