Help on coding 3d surface mesh chart


https://www.nevron.com/Forum/Topic12278.aspx
Print Topic | Close Window

By lian jia jie - 7 Years Ago
Doing a project of a 3d surface chart to show the changing temperature from several sensors. The temperature data is retrieved from MySql database.  

I need help on manually assign the sensor data on certain coordinate. Eg. [x1,y1] - sensor1 , [x2,y1] -sensor 2, [x1,y2] - sensor3, [x2,y2]-sensor 4 , etc...
Any sample coding or guidance is appreciated.
By Nevron Support - 7 Years Ago
Hi,
First of all thank you for your interest in Nevron Chart for .NET. It is not sure what the actual format of the data is - in general we guess that the format is x,y - for the sensor placement and then z value for the sensor value. Also are the XY values for the sensor arbitrary or are they equally spaced from each other (a grid). Please elaborate a little bit on the format of the data and actual values and we'll gladly post an example.
By lian jia jie - 7 Years Ago
The project is based on winform. Hope this simple chart will clear your doubt.
https://www.nevron.com/forum/uploads/images/46d2b8c3-2e1c-490b-9523-0bff.png
The XY coordinates are merely an indicator of position of the sensors. 
Eg. (1,1) - sensor 1 , ( 2,1) - sensor 2 , (3,1) sensor 3 , etc..
The Z values will be retrieved from MySQL database and they should be constantly updating themselves. So that the chart will look like a live chart. 
By Nevron Support - 7 Years Ago

Hi,
We think that in this case it will be more appropriate to use the grid surface (as the distance on the x/z plane are always equal and the cells form a grid). The following code shows how to configure a grid surface chart and pass some sample data:

using Nevron.Chart;
using Nevron.Chart.Windows;
using Nevron.GraphicsCore;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace GridSurface
{
 public partial class Form1 : Form
 {
  public Form1()
  {
   InitializeComponent();
  }

  private void Form1_Load(object sender, EventArgs e)
  {
   nChartControl1.Settings.ShapeRenderingMode = ShapeRenderingMode.None;
   nChartControl1.Controller.Tools.Add(new NPanelSelectorTool());
   nChartControl1.Controller.Tools.Add(new NTrackballTool());

   // set a chart title
   NLabel title = nChartControl1.Labels.AddHeader("Surface Chart");
   title.TextStyle.FontStyle = new NFontStyle("Times New Roman", 18, FontStyle.Italic);
   title.TextStyle.FillStyle = new NColorFillStyle(Color.Gray);

   // setup chart
   NChart chart = nChartControl1.Charts[0];
   chart.Enable3D = true;
   chart.Width = 60.0f;
   chart.Depth = 60.0f;
   chart.Height = 25.0f;
   chart.Projection.SetPredefinedProjection(PredefinedProjection.PerspectiveTilted);
   chart.LightModel.SetPredefinedLightModel(PredefinedLightModel.ShinyTopLeft);

   // setup axes
   NOrdinalScaleConfigurator ordinalScale = (NOrdinalScaleConfigurator)chart.Axis(StandardAxis.PrimaryX).ScaleConfigurator;
   ordinalScale.MajorGridStyle.SetShowAtWall(ChartWallType.Floor, true);
   ordinalScale.MajorGridStyle.SetShowAtWall(ChartWallType.Back, true);
   ordinalScale.DisplayDataPointsBetweenTicks = false;

   ordinalScale = (NOrdinalScaleConfigurator)chart.Axis(StandardAxis.Depth).ScaleConfigurator;
   ordinalScale.MajorGridStyle.SetShowAtWall(ChartWallType.Floor, true);
   ordinalScale.MajorGridStyle.SetShowAtWall(ChartWallType.Left, true);
   ordinalScale.DisplayDataPointsBetweenTicks = false;

   // add the surface series
   NGridSurfaceSeries surface = (NGridSurfaceSeries)chart.Series.Add(SeriesType.GridSurface);
   surface.Name = "Surface";
   surface.Legend.Mode = SeriesLegendMode.SeriesLogic;
   surface.SyncPaletteWithAxisScale = false;
   surface.PaletteSteps = 8;
   surface.ValueFormatter.FormatSpecifier = "0.00";

   surface.Data.SetGridSize(3, 3);
   surface.Data.SetValue(0, 0, 0);
   surface.Data.SetValue(0, 1, 0);
   surface.Data.SetValue(0, 2, 0);

   surface.Data.SetValue(1, 0, 0);
   surface.Data.SetValue(1, 1, 10);
   surface.Data.SetValue(1, 2, 0);

   surface.Data.SetValue(2, 0, 0);
   surface.Data.SetValue(2, 1, 0);
   surface.Data.SetValue(2, 2, 0);

  }
 }
}


You can also take a look at the examples shipped with the control. Take a look at the following examples -
All Examples \ Chart Gallery \ Grid Surface
All Examples \ Chart Gallery \ Mesh Surface
All Examples \ Chart Gallery \ Triangulated Surface

Hope this helps - let us know if you meet any problems or have any questions.

By lian jia jie - 7 Years Ago
What code to be added so that the chart will clear the series and refresh the data?
By Nevron Support - 7 Years Ago
Hi,
You need to call the Clear method of the surface data, update the values and then refresh the control - for example:

 // sets all values to 0
   surface.Data.Clear();

   // update data
   surface.Data.SetGridSize(3, 3);
   surface.Data.SetValue(1, 1, 11);
  
// refresh image
   nChartControl1.Refresh();

Let us know if you meet any problems.
By lian jia jie - 7 Years Ago
I did put the surface.data.clear() as below to clear the surface series. Somehow , the chart is still replicating. 


For refreshing the chart, I have a timer for counting the refresh interval.


So far from my understanding, the chart is created once more every time it refreshes. The surface.data.clear command doesn't seem to be working.

File attached is the codes i have for my project. Hope you can give some guidances on fixing this issue. Thank you.





By Nevron Support - 7 Years Ago
Hi,
Currently the code will add a new surface series to each timer tick - what you need to ensure is that the chart contains only one surface series and then clear / update the data - for example:

   NGridSurfaceSeries surface = null;

   if (chart.Series.Count > 0)
   {
    surface = chart.Series[0] as NGridSurfaceSeries;
   }
   
   if (surface == null)
   {
     surface = (NGridSurfaceSeries)chart.Series.Add(SeriesType.GridSurface);
   }

then after you're done updating the data you need to call:
nChartControl.Refresh();

There is no need to call refresh on a separate timer. Hope this helps let us know if you meet any problems or have any questions.
By lian jia jie - 7 Years Ago
Is there any way to create a label to show the z value of each sensor like the picture below as I want to see the changing value over time. Thank you.
https://www.nevron.com/forum/uploads/images/2864d6b4-7395-4656-9e43-ce7c.png

By Nevron Support - 7 Years Ago
Hi Lian,
Yes sure - the following code shows how to display a chart similar to the one you attached:

   NChart chart = nChartControl1.Charts[0];
   chart.Enable3D = true;
   chart.Projection.SetPredefinedProjection(PredefinedProjection.PerspectiveTilted);
   chart.Width = chart.Height = chart.Depth = 50;

   NOrdinalScaleConfigurator xScale = chart.Axis(StandardAxis.PrimaryX).ScaleConfigurator as NOrdinalScaleConfigurator;
   xScale.AutoLabels = false;
   xScale.Labels.Add("A");
   xScale.Labels.Add("B");
   xScale.Labels.Add("C");

   NOrdinalScaleConfigurator yScale = chart.Axis(StandardAxis.Depth).ScaleConfigurator as NOrdinalScaleConfigurator;
   yScale.AutoLabels = false;
   yScale.Labels.Add("X");
   yScale.Labels.Add("Y");
   yScale.Labels.Add("Z");

   NBarSeries bar1 = new NBarSeries();
   bar1.Values.Add(10);
   bar1.Values.Add(20);
   bar1.Values.Add(30);
   chart.Series.Add(bar1);

   NBarSeries bar2 = new NBarSeries();
   bar2.Values.Add(12);
   bar2.Values.Add(22);
   bar2.Values.Add(32);
   chart.Series.Add(bar2);

   NBarSeries bar3 = new NBarSeries();
   bar3.Values.Add(15);
   bar3.Values.Add(25);
   bar3.Values.Add(35);
   chart.Series.Add(bar3);

   NStyleSheet.CreatePredefinedStyleSheet(PredefinedStyleSheet.Bright).Apply(nChartControl1.Document);

Hope this helps - let us know if you have any questions.
By lian jia jie - 7 Years Ago
What if i like to label the z value of a surface chart like the one i did in the previous replies? Does the chart control provide the same label functionality for surface chart? Thank you.
By Nevron Support - 7 Years Ago
Hi,
Yes it applies to surface charts - in fact the code applies to any type of chart which uses an ordinal axis. By default the x and depth axes are configured as ordinal so the code is the same.
By lian jia jie - 7 Years Ago
I would like the Z-values to show up above each data point in the surface chart like how the value shows up in the bar chart in my previous reply.
By bob milanov - 7 Years Ago
Hi,
The grid surface series does not support data labels directly for performance reasons. However you can mix the grid surface series with several invisible bar series that are used to show those labels - for example the following code shows how to create several invisible bar series that show up only value labels:

NChart chart = nChartControl1.Charts[0];
chart.Enable3D = true;
chart.Projection.SetPredefinedProjection(PredefinedProjection.PerspectiveTilted);
chart.Width = chart.Height = chart.Depth = 50;

NOrdinalScaleConfigurator xScale = chart.Axis(StandardAxis.PrimaryX).ScaleConfigurator as NOrdinalScaleConfigurator;
xScale.AutoLabels = false;
xScale.Labels.Add("A");
xScale.Labels.Add("B");
xScale.Labels.Add("C");

NOrdinalScaleConfigurator yScale = chart.Axis(StandardAxis.Depth).ScaleConfigurator as NOrdinalScaleConfigurator;
yScale.AutoLabels = false;
yScale.Labels.Add("X");
yScale.Labels.Add("Y");
yScale.Labels.Add("Z");

NBarSeries bar1 = new NBarSeries();
bar1.Values.Add(10);
bar1.Values.Add(20);
bar1.Values.Add(30);
bar1.FillStyle = new NColorFillStyle(Color.Transparent);
bar1.BorderStyle.Width = new NLength(0);
chart.Series.Add(bar1);

NBarSeries bar2 = new NBarSeries();
bar2.Values.Add(12);
bar2.Values.Add(22);
bar2.Values.Add(32);
bar2.FillStyle = new NColorFillStyle(Color.Transparent);
bar2.BorderStyle.Width = new NLength(0);
chart.Series.Add(bar2);

NBarSeries bar3 = new NBarSeries();
bar3.Values.Add(15);
bar3.Values.Add(25);
bar3.Values.Add(35);
bar3.FillStyle = new NColorFillStyle(Color.Transparent);
bar3.BorderStyle.Width = new NLength(0);
chart.Series.Add(bar3);

Hope this helps - let us know if you meet any problems or have any questions.