Setting of Altitude of a wavepoint in the route in 3D globe

A forum dedicated to WinForms version of LightningChart Ultimate.

Moderator: Queue Moderators

Post Reply
hallo888
Posts: 43
Joined: Wed Mar 26, 2014 10:56 am

Setting of Altitude of a wavepoint in the route in 3D globe

Post by hallo888 » Fri Apr 11, 2014 2:47 am

Hi,

Inside the ExampleGlobeSurface3D, the wave points in the route is derived from the lat/long position which is converted into a point on the globe(X,Y,Z) by using ConvertMapCoordTo3DPointOnSphere(). Any function for me to find out the altitude of the wavepoint from the earth as well as for me to set the altitude of a particular wavepoint?

I realised that in the ExampleGlobeSurface3D example, inside CreateSurfaceSeries() the DRadius is set to 50, which i supposed is the raidius for the globe. And then in CreateRoute(), the radius or value used in CalculateSphericalRoute() and ConvertMapCoordTo3DPointOnSphere() is 53. Does that mean that the route will be "3" away from the globe surface? Is my understanding correct? If so, what does the 3 translates to? What is the unit? Anyway for me to convert to feet?

Thank you in advance for your advice!

User avatar
ArctionPasi
Posts: 1367
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland
Contact:

Re: Setting of Altitude of a wavepoint in the route in 3D gl

Post by ArctionPasi » Sun Apr 13, 2014 12:44 pm

The X, Y and Z axes have been defined from -50 to 50. So if you set axes visible or walls visible, you will notice the sphere fills 3D space box. And the routes are actually outside it by 3.

You can set any value to axis ranges, in km or miles, or feet. Just scale the sphere respectively. Keep all axes ranges same, otherwise the sphere is stretched.

For example, to define the sphere in km
m_chart.View3D.XAxisPrimary3D.SetRange(-6371, 6371);
m_chart.View3D.YAxisPrimary3D.SetRange(-6371, 6371);
m_chart.View3D.ZAxisPrimary3D.SetRange(-6371, 6371);

Here's the demo app's ExampleGlobeSurface3D.cs modified to use those ranges:

Code: Select all

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Arction.LightningChartUltimate;
using Arction.LightningChartUltimate.Series3D;
using Arction.LightningChartUltimate.Views.View3D;
using Arction.LightningChartUltimate.Axes;
using Arction.LightningChartUltimate.Annotations;
using System.Diagnostics;
using System.Reflection;


namespace DemoAppLightningChartUltimate
{
    /// <summary>
    /// Globe surface example
    /// </summary>
    public partial class ExampleGlobeSurface3D : UserControl
    {
        //Chart
        private LightningChartUltimate m_chart = null;

        //2D array of elevation data
        private double[,] m_aElevationData = null;

        //Photo that is shown over the surface
        private Image m_photo = null;

        private const double EarthDiameterKm = 6371; 


        /// <summary>
        /// Constructor.
        /// </summary>
        public ExampleGlobeSurface3D()
        {
            InitializeComponent();

            m_photo = Bitmap.FromFile(Application.StartupPath + "\\Resources\\WorldPhoto3600x1800.jpg");

            CreateChart();
        }

        /// <summary> 
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            if (m_chart != null)
            {
                m_chart.Dispose(); //Chart should be explicitely disposed, to free graphics resources instantly 
                m_chart = null;
            }
            base.Dispose(disposing);
        }

        /// <summary>
        /// Get demo description and source file name.
        /// </summary>
        /// <param name="sourceCodeFilename">Demo source file name</param>
        /// <returns>description</returns>
        public string GetDescription(out string sourceCodeFilename)
        {
            //Resolve source code file name by throwing an exception and investigating the source file name 
            try
            {
                throw new Exception();
            }
            catch (Exception e)
            {
                sourceCodeFilename = ChartTools.GetSourceCodeFilenameFromStackTrace(e.StackTrace);
            }
            return "Globe demo, earth surface is made with SurfaceMeshSeries3D, from manipulated SRTM-90 (CGIAR-CSI) elevation data and a photo (NASA)."
             + "\nFlight routes are calculated with ChartTools methods from city coordinates using shortest Great Circle route. "
             + "PointLineSeries3D and Annotation objects are used to present them.";
        }

        /// <summary>
        /// Create chart.
        /// </summary>
        private void CreateChart()
        {
            //Create new chart
            m_chart = new LightningChartUltimate(LicenseKeys.LicenseKeyStrings.LightningChartUltimate);

            //Disable rendering, strongly recommended before updating chart properties
            m_chart.BeginUpdate();

            //Set active view
            m_chart.ActiveView = ActiveView.View3D;

            //Chart parent must be set
            m_chart.Parent = splitContainer1.Panel1;

            //Fill parent area with chart
            m_chart.Dock = DockStyle.Fill;

            //Chart name
            m_chart.Name = "Globe chart";

            //Hide walls
            List<WallBase> listWalls = m_chart.View3D.GetWalls();
            foreach (WallBase wall in listWalls)
                wall.Visible = false;

            //Set all axis range same
            m_chart.View3D.XAxisPrimary3D.SetRange(-EarthDiameterKm, EarthDiameterKm);
            m_chart.View3D.YAxisPrimary3D.SetRange(-EarthDiameterKm, EarthDiameterKm);
            m_chart.View3D.ZAxisPrimary3D.SetRange(-EarthDiameterKm, EarthDiameterKm);

            //Disable second light
            m_chart.View3D.Lights[1].Enabled = false;
            m_chart.View3D.Lights[1].LocationFromCamera = true;

            //Set enhanced surface rendering mode 
            m_chart.View3D.UsePerPixelLighting = true;

            //Setup dimensions to same value
            m_chart.View3D.Dimensions.X = 200;
            m_chart.View3D.Dimensions.Y = 200;
            m_chart.View3D.Dimensions.Z = 200;

            //Setup camera
            m_chart.View3D.Camera.MinimumViewDistance = 10;
            m_chart.View3D.Camera.SetPredefinedCamera(PredefinedCamera.FrontPerspective);
            m_chart.View3D.Camera.ViewDistance = 200;
            m_chart.View3D.Camera.RotationX = 60;
            m_chart.View3D.Camera.RotationY = -25;

            //Hide legend box
            m_chart.View3D.LegendBox.Visible = false;

            //Don't allow panning because it shifts the center point of rotation
            m_chart.View3D.ZoomPanOptions.RightMouseButtonAction = MouseButtonAction3D.Rotate; 

            //Hide all axes
            List<Axis3DBase> listAxes = m_chart.View3D.GetAxes();
            foreach (Axis3DBase axis in listAxes)
                axis.Visible = false;

            //Make data
            MakeElevationData();

            //Create series
            CreateSurfaceSeries();
            CreateRoutes();

            //Set view point
            viewPointEditor1.Chart = m_chart;


            //Allow chart rendering
            m_chart.EndUpdate();

        }


        /// <summary>
        /// Make elevation data.
        /// </summary>
        private void MakeElevationData()
        {
            //Get surface elevation data from bitmap. In this elevation bitmap, white value represents high elevation, 
            //and dark value low elevation
            Bitmap bitmapElevation = (Bitmap)ChartTools.ImageFromResource("Resources." + "WorldElevation1024x512.png", Assembly.GetExecutingAssembly());

            //Use fast method for getting pixel colors 
            Color[,] aElevationData = ChartTools.GetPixelColors(bitmapElevation);

            int iWidth = aElevationData.GetLength(0);
            int iHeight = aElevationData.GetLength(1);

            m_aElevationData = new double[iWidth, iHeight];

            for (int iColumn = 0; iColumn < iWidth; iColumn++)
            {
                for (int iRow = 0; iRow < iHeight; iRow++)
                {
                    m_aElevationData[iColumn, iRow] = (double)(
                        aElevationData[iColumn, iRow].R +
                        aElevationData[iColumn, iRow].G +
                        aElevationData[iColumn, iRow].B) / (3.0 * 255.0);
                }
            }
        }

        /// <summary>
        /// Create routes.
        /// </summary>
        private void CreateRoutes()
        {
            //Route1 : Helsinki, Finland - New York, USA
            MapCoordinate[] route1WayPoints = new MapCoordinate[2];
            route1WayPoints[0] = new MapCoordinate(60, 10, 0, LatitudePostfix.N, 24, 53, 0, LongitudePostfix.E);
            route1WayPoints[1] = new MapCoordinate(40, 47, 0, LatitudePostfix.N, 73, 58, 0, LongitudePostfix.W);
            CreateRoute(route1WayPoints, Color.Green, new string[] { "Helsinki, Finland", "New York, USA" });

            //Route2: Los Angeles, USA - Tokyo, Japan - Zürich, Switzerland 
            MapCoordinate[] route2WayPoints = new MapCoordinate[3];
            route2WayPoints[0] = new MapCoordinate(34, 37, 4, LatitudePostfix.N, 117, 50, 1, LongitudePostfix.W);
            route2WayPoints[1] = new MapCoordinate(35, 40, 60, LatitudePostfix.N, 139, 46, 0, LongitudePostfix.E);
            route2WayPoints[2] = new MapCoordinate(47, 22, 0, LatitudePostfix.N, 8, 33, 0, LongitudePostfix.E);
            CreateRoute(route2WayPoints, Color.Red, new string[] { "Los Angeles, USA", "Tokyo, Japan", "Zürich, Switzerland" });

            //Melbourne, Australia - Wellington, New Zealand - Sao Paulo, Brazil
            MapCoordinate[] route4WayPoints = new MapCoordinate[3];
            route4WayPoints[0] = new MapCoordinate(37, 48, 49, LatitudePostfix.S, 144, 57, 47, LongitudePostfix.E);
            route4WayPoints[1] = new MapCoordinate(41, 17, 20, LatitudePostfix.S, 174, 46, 38, LongitudePostfix.E);
            route4WayPoints[2] = new MapCoordinate(23, 31, 60, LatitudePostfix.S, 46, 37, 0, LongitudePostfix.W);
            CreateRoute(route4WayPoints, Color.Blue, new string[] { "Melbourne, Australia", "Wellington, New Zealand", "Sao Paulo, Brazil" });
        }

        /// <summary>
        /// Create route as PointLineSeries3D.
        /// </summary>
        /// <param name="wayPoints">Route points</param>
        /// <param name="lineColor">Route color</param>
        /// <param name="wayPointNames">Names of waypoints</param>
        private void CreateRoute(MapCoordinate[] wayPoints, Color lineColor, string[] wayPointNames)
        {
            const double AngleStep = 3.0;
            const double Radius = EarthDiameterKm * 1.02; //above the globe surface

            for (int iLeg = 0; iLeg < wayPoints.Length - 1; iLeg++)
            {
                //Line series per successive route point pair (leg)
                PointLineSeries3D lineSeries = new PointLineSeries3D(m_chart.View3D, Axis3DBinding.Primary, Axis3DBinding.Primary, Axis3DBinding.Primary);
                lineSeries.PointsVisible = false;
                lineSeries.LineVisible = true;
                lineSeries.LineStyle.Width = 3;
                lineSeries.LineStyle.Color = lineColor;

                //Coordinates as "Great Circle route" for current and next point
                MapCoordinate[] aCoords = ChartTools.CalculateSphericalRoute(wayPoints[iLeg], wayPoints[iLeg + 1], Radius, AngleStep);
                if (aCoords != null)
                {
                    int iCoordCount = aCoords.Length;
                    PointDouble3D[] aPoints = new PointDouble3D[iCoordCount];
                    int iPoint = 0;
                    foreach (MapCoordinate coord in aCoords)
                    {
                        aPoints[iPoint++] = ChartTools.ConvertMapCoordTo3DPointOnSphere(coord, Radius);
                    }
                    lineSeries.Points = aPoints;
                    m_chart.View3D.PointLineSeries3D.Add(lineSeries);

                    double dDistanceKm = ChartTools.CalculateMapDistance(wayPoints[iLeg], wayPoints[iLeg + 1]);

                    //Add label to show the statistics of the route 
                    Annotation3D label = new Annotation3D(m_chart.View3D, Axis3DBinding.Primary, Axis3DBinding.Primary, Axis3DBinding.Primary);
                    label.Fill.Style = RectFillStyle.None;
                    label.Shadow.Visible = false;
                    label.BorderVisible = false;
                    label.Style = AnnotationStyle.Rectangle;
                    label.TextStyle.Color = lineColor;
                    label.LocationCoordinateSystem = CoordinateSystem.RelativeCoordinatesToTarget;
                    label.LocationRelativeOffset.SetValues(0, 0);
                    label.MouseInteraction = false;
                    label.TextStyle.Font = new Font(FontFamily.GenericSansSerif, 9, FontStyle.Bold);
                    label.TextStyle.Shadow.Style = TextShadowStyle.HighContrast;
                    label.TextStyle.Shadow.ContrastColor = Color.FromArgb(200, Color.White);
                    label.Text = wayPointNames[iLeg] + " - " + wayPointNames[iLeg + 1] + "\nDistance: " + dDistanceKm.ToString("0") + " km";
                    PointDouble3D midPoint = aPoints[aPoints.Length / 2];
                    label.TargetAxisValues.SetValues(midPoint.X, midPoint.Y, midPoint.Z);
                    label.Visible = false;
                    m_chart.View3D.Annotations.Add(label);

                }
            }

            //Add waypoints separate point line series 
            PointLineSeries3D pointSeries = new PointLineSeries3D(m_chart.View3D, Axis3DBinding.Primary, Axis3DBinding.Primary, Axis3DBinding.Primary);
            pointSeries.PointsVisible = true;
            pointSeries.LineVisible = false;
            pointSeries.PointStyle.Shape = PointShape3D.Sphere;
            pointSeries.PointStyle.Size.SetValues(2, 2, 2);

            PointDouble3D[] aWaypoints3D = new PointDouble3D[wayPoints.Length];
            for (int iWaypoint = 0; iWaypoint < wayPoints.Length; iWaypoint++)
            {
                aWaypoints3D[iWaypoint] = ChartTools.ConvertMapCoordTo3DPointOnSphere(wayPoints[iWaypoint], Radius);
            }
            pointSeries.Points = aWaypoints3D;
            m_chart.View3D.PointLineSeries3D.Add(pointSeries);
        }



        /// <summary>
        /// Delete routes (labels and point line series).
        /// </summary>
        private void DeleteRoutes()
        {
            m_chart.View3D.PointLineSeries3D.Clear();
            m_chart.View3D.Annotations.Clear();
        }

        /// <summary>
        /// Use surface mesh series to represent globe.
        /// </summary>
        private void CreateSurfaceSeries()
        {
            //Remove old series
            if (m_chart.View3D.SurfaceMeshSeries3D.Count > 0)
                m_chart.View3D.SurfaceMeshSeries3D.Clear();

            SurfaceMeshSeries3D surface = new SurfaceMeshSeries3D(m_chart.View3D, Axis3DBinding.Primary, Axis3DBinding.Primary, Axis3DBinding.Primary);
            surface.BitmapFill.Image = m_photo;
            surface.BitmapFill.MirrorHorizontal = false;
            surface.BitmapFill.MirrorVertical = true;
            surface.Fill = SurfaceFillStyle.Bitmap;

            surface.WireframeType = SurfaceWireframeType.None;
            surface.ContourLineType = ContourLineType.None;
            //Lit the other side, as the surface is constructed backwards
            surface.LightedSurface = LightedSurfaceSide.Bottom;
            surface.Material.DiffuseColor = Color.FromArgb(200, 200, 200);
            surface.Material.SpecularPower = 5;
            surface.ColorSaturation = 80;

            int iSlices = m_aElevationData.GetLength(0);
            int iStacks = m_aElevationData.GetLength(1);

            surface.SizeX = iSlices;
            surface.SizeZ = iStacks;

            SurfacePoint[,] data = surface.Data;
            double dRadius = EarthDiameterKm;
            double dX, dY, dZ;
            double dScale;
            double dTheta;
            double dElevation;
            double dPhi;
            double dElevationFactor = (double)trackBarElevation.Value * dRadius/100.0;
            for (int iStack = 0; iStack < iStacks; iStack++)
            {
                dPhi = Math.PI / 2.0 - (double)iStack * Math.PI / (double)(iStacks - 1);
                for (int iSlice = 0; iSlice < iSlices; iSlice++)
                {
                    dElevation = m_aElevationData[iSlice, iStack] * dElevationFactor;

                    dY = (dRadius + dElevation) * Math.Sin(dPhi);

                    dScale = -Math.Cos(dPhi) * (dRadius + dElevation);

                    dTheta = -(double)iSlice * 2.0 * Math.PI / (double)(iSlices - 1) - Math.PI;

                    dX = dScale * Math.Sin(dTheta);
                    dZ = dScale * Math.Cos(dTheta);

                    data[iSlice, iStack].X = dX;
                    data[iSlice, iStack].Y = dY;
                    data[iSlice, iStack].Z = dZ;
                }
            }
            m_chart.View3D.SurfaceMeshSeries3D.Add(surface);
        }

        /// <summary>
        /// Delete grid.
        /// </summary>
        private void DeleteGrid()
        {
            //Disable rendering, strongly recommended before updating chart properties
            m_chart.BeginUpdate();

            int iCount = m_chart.View3D.PointLineSeries3D.Count;
            for (int iLineSeries = iCount - 1; iLineSeries >= 0; iLineSeries--)
            {
                if (m_chart.View3D.PointLineSeries3D[iLineSeries].Title.Text.IndexOf("LatLon") >= 0)
                {
                    m_chart.View3D.PointLineSeries3D.RemoveAt(iLineSeries);
                }
            }

            //Allow chart rendering
            m_chart.EndUpdate();
        }

        /// <summary>
        /// Create grid.
        /// </summary>
        private void CreateGrid()
        {
            const double Radius = EarthDiameterKm * 1.01;

            Color lineColor = Color.FromArgb(60, Color.Cyan);

            //Disable rendering, strongly recommended before updating chart properties
            m_chart.BeginUpdate();

            //Longitude circles
            int iCircle = 0;
            for (double dLongitude = -180; dLongitude < 0; dLongitude += 15)
            {
                PointLineSeries3D circleSeries = new PointLineSeries3D(m_chart.View3D, Axis3DBinding.Primary, Axis3DBinding.Primary, Axis3DBinding.Primary);
                circleSeries.PointsVisible = false;
                circleSeries.LineStyle.Color = lineColor;
                circleSeries.Title.Text = "LatLon " + iCircle.ToString();
                MapCoordinate[] aCoords = ChartTools.CalculateSphereFullGreatCircleCoords(new MapCoordinate(100, dLongitude), new MapCoordinate(-100, dLongitude), 5);
                int iCount = 0;
                if (aCoords != null)
                {
                    iCount = aCoords.Length;
                    PointDouble3D[] aPoints = new PointDouble3D[iCount];
                    int iPoint = 0;
                    foreach (MapCoordinate coord in aCoords)
                    {
                        aPoints[iPoint++] = ChartTools.ConvertMapCoordTo3DPointOnSphere(coord, Radius);
                    }
                    circleSeries.Points = aPoints;
                }
                m_chart.View3D.PointLineSeries3D.Add(circleSeries);
                iCircle++;
            }

            //Latitude circles 
            //Great circle routine is not valid for this, because the radius center is not in the center of the globe. 
            for (double dLatitude = -75; dLatitude <= 75; dLatitude += 15)
            {
                PointLineSeries3D circleSeries = new PointLineSeries3D(m_chart.View3D, Axis3DBinding.Primary, Axis3DBinding.Primary, Axis3DBinding.Primary);
                circleSeries.PointsVisible = false;
                circleSeries.LineStyle.Color = lineColor;
                circleSeries.Title.Text = "LatLon " + iCircle.ToString();
                PointDouble3D[] aPoints = new PointDouble3D[360 / 5 + 1];
                int iPoint = 0;
                for (double dLongitude = -180; dLongitude <= 180; dLongitude += 5)
                {
                    aPoints[iPoint++] = ChartTools.ConvertMapCoordTo3DPointOnSphere(new MapCoordinate(dLatitude, dLongitude), Radius);
                }
                circleSeries.Points = aPoints;
                m_chart.View3D.PointLineSeries3D.Add(circleSeries);
                iCircle++;
            }

            //Allow chart rendering
            m_chart.EndUpdate();
        }

        /// <summary>
        /// Create new series if elevation changes.
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="args">arguments</param>
        private void trackBarElevation_Scroll(object sender, EventArgs e)
        {
            //Disable rendering, strongly recommended before updating chart properties
            m_chart.BeginUpdate();

            CreateSurfaceSeries();

            //Allow chart rendering
            m_chart.EndUpdate();
        }

        /// <summary>
        /// Show/hide routes.
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="args">arguments</param>
        private void checkBoxRoute_CheckedChanged(object sender, EventArgs e)
        {
            //Disable rendering, strongly recommended before updating chart properties
            m_chart.BeginUpdate();

            if (checkBoxRoute.Checked)
            {
                CreateRoutes();
            }
            else
            {
                DeleteRoutes();
            }

            //Allow chart rendering
            m_chart.EndUpdate();
        }

        /// <summary>
        /// Toggle route labels visibility.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void checkBoxShowRouteLabels_CheckedChanged(object sender, EventArgs e)
        {
            if (m_chart != null)
            {
                m_chart.BeginUpdate();
                foreach (Annotation3D annotation in m_chart.View3D.Annotations)
                {
                    annotation.Visible = checkBoxShowRouteLabels.Checked;
                }
                m_chart.EndUpdate();
            }
        }

        /// <summary>
        /// Show/hide lon/lat grid.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void checkBoxLonLatGrid_CheckedChanged(object sender, EventArgs e)
        {
            DeleteGrid();
            if (checkBoxLonLatGrid.Checked)
            {
                CreateGrid();
            }
        }
    }
}


So if you pass 6372 to CalculateSphericalRoute method, the altitude is 6372 km - 6371 km = 1 km = 3280 feet
LightningChart Support Team, PT

hallo888
Posts: 43
Joined: Wed Mar 26, 2014 10:56 am

Re: Setting of Altitude of a wavepoint in the route in 3D gl

Post by hallo888 » Mon Apr 14, 2014 1:09 am

Hi Pasi,

Thank you so much for ur help! May i ask what is the appropriate ElevationFactor that i should use in order to show a realistic elevation when the radius of the globe is now defined is km?

And also lets say if my route comprises of 3 points. Each of the point has a different altitude value, are there any functions that cater to this. Reason for asking is that currently CalculateSphericalRoute() takes in 2 points but only one altitude value (in a form of Radius in the example below), which is to say that the 2 points (n and n+1 point have the same altitude). So is it possible to have n and n+1 point each with its own altitude value? Any way to do that?

Code: Select all

//Coordinates as "Great Circle route" for current and next point
                MapCoordinate[] aCoords = ChartTools.CalculateSphericalRoute(wayPoints[iLeg], wayPoints[iLeg + 1], Radius, AngleStep);
                if (aCoords != null)
                {
                    int iCoordCount = aCoords.Length;
                    PointDouble3D[] aPoints = new PointDouble3D[iCoordCount];
                    int iPoint = 0;
                    foreach (MapCoordinate coord in aCoords)
                    {
                        aPoints[iPoint++] = ChartTools.ConvertMapCoordTo3DPointOnSphere(coord, Radius);
                    }
                    lineSeries.Points = aPoints;
                    m_chart.View3D.PointLineSeries3D.Add(lineSeries);

                    double dDistanceKm = ChartTools.CalculateMapDistance(wayPoints[iLeg], wayPoints[iLeg + 1]);

                    //Add label to show the statistics of the route 
                    Annotation3D label = new Annotation3D(m_chart.View3D, Axis3DBinding.Primary, Axis3DBinding.Primary, Axis3DBinding.Primary);
                    label.Fill.Style = RectFillStyle.None;
                    label.Shadow.Visible = false;
                    label.BorderVisible = false;
                    label.Style = AnnotationStyle.Rectangle;
                    label.TextStyle.Color = lineColor;
                    label.LocationCoordinateSystem = CoordinateSystem.RelativeCoordinatesToTarget;
                    label.LocationRelativeOffset.SetValues(0, 0);
                    label.MouseInteraction = false;
                    label.TextStyle.Font = new Font(FontFamily.GenericSansSerif, 9, FontStyle.Bold);
                    label.TextStyle.Shadow.Style = TextShadowStyle.HighContrast;
                    label.TextStyle.Shadow.ContrastColor = Color.FromArgb(200, Color.White);
                    label.Text = wayPointNames[iLeg] + " - " + wayPointNames[iLeg + 1] + "\nDistance: " + dDistanceKm.ToString("0") + " km";
                    PointDouble3D midPoint = aPoints[aPoints.Length / 2];
                    label.TargetAxisValues.SetValues(midPoint.X, midPoint.Y, midPoint.Z);
                    label.Visible = false;
                    m_chart.View3D.Annotations.Add(label);

                }
Thanks you in advance for your advise.

Post Reply