Hello and thanks for the response. I figured out that I need to use a triangulated surface. I am including the code I wrote to generate the contour plot. At this point, I have two questions for you.
1) How can I display a horizontal plane at the 0th elevation. If you look at my code, I attempted to display a plane by simply obtaining the max and min X and Z values and setting their depth to zero. The results were not favorable. In one of the images provided by way of another plotting application, you can see the horizontal plane.
2) Is there a limitation on the number of data points to plot? When attempting to plot the data in the attached file LargeNumberOfData.csv, I get a Stack Overflow error. "An unhandled exception of type 'System.StackOverflowException' occurred in Nevron.Presentation.dll"
Lastly, I should point out that in my could I have added "Convert.ToDouble(point[2]) <= 5)" to deal with the data outlier issue. I suspect that I will have to add some logic to clean my data of outliers before plotting..
using Nevron.Chart;
using Nevron.Chart.Windows;
using Nevron.GraphicsCore;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
nChartControl1.Settings.ShapeRenderingMode = ShapeRenderingMode.None;
nChartControl1.Controller.Tools.Add(new NSelectorTool());
nChartControl1.Controller.Tools.Add(new NTrackballTool());
// set a chart title
NLabel title = nChartControl1.Labels.AddHeader("Mesh Surface Chart");
title.TextStyle.FontStyle = new NFontStyle("Times New Roman", 18, FontStyle.Italic);
title.TextStyle.FillStyle = new NColorFillStyle(Color.AliceBlue);
// setup chart
NChart chart = nChartControl1.Charts[0];
chart.Enable3D = true;
chart.Width = 70.0f;
chart.Depth = 70.0f;
chart.Height = 30.0f;
chart.Projection.SetPredefinedProjection(PredefinedProjection.PerspectiveTilted);
// setup axes
NLinearScaleConfigurator linearScale = new NLinearScaleConfigurator();
linearScale.MajorGridStyle.SetShowAtWall(ChartWallType.Floor, true);
linearScale.MajorGridStyle.SetShowAtWall(ChartWallType.Back, true);
linearScale.RoundToTickMax = false;
linearScale.RoundToTickMin = false;
chart.Axis(StandardAxis.PrimaryX).ScaleConfigurator = linearScale;
linearScale = new NLinearScaleConfigurator();
linearScale.MajorGridStyle.SetShowAtWall(ChartWallType.Floor, true);
linearScale.MajorGridStyle.SetShowAtWall(ChartWallType.Left, true);
linearScale.RoundToTickMax = false;
linearScale.RoundToTickMin = false;
chart.Axis(StandardAxis.Depth).ScaleConfigurator = linearScale;
// setup surface series
NTriangulatedSurfaceSeries surface = new NTriangulatedSurfaceSeries();
surface.Name = "Surface";
surface.Legend.Mode = SeriesLegendMode.SeriesLogic;
surface.FillMode = SurfaceFillMode.ZoneTexture;
surface.ShadingMode = ShadingMode.Smooth;
surface.FrameMode = SurfaceFrameMode.None;
surface.FrameColorMode = SurfaceFrameColorMode.Zone;
surface.DrawFlat = false;
surface.PositionValue = 0.5;
//surface.Data.SetGridSize(20, 20);
surface.SyncPaletteWithAxisScale = false;
surface.PaletteSteps = 8;
surface.ValueFormatter.FormatSpecifier = "0.00";
surface.FillStyle = new NColorFillStyle(Color.YellowGreen);
chart.Series.Add(surface);
List<GeospatialPoint> geospatialPoints = GetSurveyData();
for (int i = 0; i < geospatialPoints.Count; i++)
{
surface.Values.Add(geospatialPoints[i].y);
surface.XValues.Add(geospatialPoints[i].x);
surface.ZValues.Add(geospatialPoints[i].z);
}
nChartControl1.Refresh();
}
private List<GeospatialPoint> GetSurveyData()
{
List<GeospatialPoint> geospatialPoints = new List<GeospatialPoint>();
try
{
// Open the text file using a stream reader.
using (StreamReader sr = new StreamReader("TestData.csv"))
{
string headerLine = sr.ReadLine();
string line;
double minX = 0;
double maxX = 0;
double minZ = 0;
double maxZ = 0;
// Read the stream to a string.
while ((line = sr.ReadLine()) != null)
{
if (line.Contains(","))
{
string[] point = line.Split(',');
if (IsValidGeospatialPoint(point) && Convert.ToDouble(point[2]) <= 5)
{
double latitude = ConvertDegreeAngleToDouble(point[0]);
double longitude = ConvertDegreeAngleToDouble(point[1]);
double elevation = Convert.ToDouble(point[2]);
double cosLat = Math.Cos(latitude * Math.PI / 180.0);
double sinLat = Math.Sin(latitude * Math.PI / 180.0);
double cosLon = Math.Cos(longitude * Math.PI / 180.0);
double sinLon = Math.Sin(longitude * Math.PI / 180.0);
double rad = 6378137.0;
double f = 1.0 / 298.257224;
double C = 1.0 / Math.Sqrt(cosLat * cosLat + (1 - f) * (1 - f) * sinLat * sinLat);
double S = (1.0 - f) * (1.0 - f) * C;
double h = 0;
double cartesianX = ((rad * C + h) * cosLat * cosLon);
double cartesianY = -elevation;
double cartesianZ = ((rad * S + h) * sinLat);
if (geospatialPoints.Find(geoPoint => (geoPoint.x == cartesianX && geoPoint.y == cartesianY && geoPoint.z == cartesianZ)) == null)
{
System.Diagnostics.Debug.WriteLine("{0}, {1}, {2}", cartesianX, cartesianZ, cartesianY);
geospatialPoints.Add(new GeospatialPoint()
{
x = cartesianX,
y = cartesianY,
z = cartesianZ
});
}
}
}
}
//minX = (from p in geospatialPoints select p.x).Min();
//minZ = (from p in geospatialPoints select p.z).Min();
//maxX = (from p in geospatialPoints select p.x).Max();
//maxZ = (from p in geospatialPoints select p.z).Max();
//geospatialPoints.Add(new GeospatialPoint() { x = minX, z = minZ, y = 0 });
//geospatialPoints.Add(new GeospatialPoint() { x = maxX, z = minZ, y = 0 });
//geospatialPoints.Add(new GeospatialPoint() { x = maxX, z = maxZ, y = 0 });
//geospatialPoints.Add(new GeospatialPoint() { x = minX, z = maxZ, y = 0 });
}
}
catch (Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
return geospatialPoints;
}
private double ConvertDegreeAngleToDouble(string degreesMinutes)
{
// Decimal degrees =
// whole number of degrees,
// plus minutes divided by 60,
// plus seconds divided by 3600
// 3357.4196
// degrees = 33
// minutes = 57.4196
string[] degreesMinutesDivided = degreesMinutes.Split('.');
string degrees = degreesMinutesDivided[0].Substring(0, degreesMinutesDivided[0].Length - 2);
string minutes = degreesMinutesDivided[0].Substring(degrees.Length ) + "." + degreesMinutesDivided[1];
string seconds = "0";
return Convert.ToDouble(degrees) + (Convert.ToDouble(minutes) / 60) + (Convert.ToDouble(seconds) / 3600);
}
private bool IsValidGeospatialPoint(string[] point)
{
if (point.Length >= 3)
{
double latitude;
double longitude;
double elevation;
if (Double.TryParse(point[0], out latitude) && Double.TryParse(point[1], out longitude) && Double.TryParse(point[2], out elevation))
{
return true;
}
return false;
}
return false;
}
}
}