From this description it's a little bit hard to understand what you are actually requesting here.
We have an example that would probably suit your purpose, more or less. It's for WinForms, almost same code can be applied to WPF as well if you are using that.
In this example, there's bunch of data points, and based on them, a surface series data is composed. The data points are shown as balls.
Code: Select all
namespace HeatmapColorSpreading3D
{
public partial class Form1 : Form
{
LightningChartUltimate m_chart;
SurfaceGridSeries3D m_surface;
DataPoint[] m_dataPoints;
int m_iDataPointCount;
double MinX = double.MaxValue;
double MaxX = double.MinValue;
double MinZ = double.MaxValue;
double MaxZ = double.MinValue;
double MinValue = double.MaxValue;
double MaxValue = double.MinValue;
const int SizeX = 100;
const int SizeZ = 100;
public Form1()
{
InitializeComponent();
m_dataPoints = new DataPoint[]
{
new DataPoint(7.00,-2.35,79.61),
new DataPoint(8.25,-2.81,80.08),
new DataPoint(9.50,-2.36,77.40),
new DataPoint(12.50,-2.31,79.23),
new DataPoint(14.25,-2.34,81.42),
new DataPoint(15.50,-2.61,81.45),
new DataPoint(17.75,-2.63,81.34),
new DataPoint(20.38,-2.75,80.81),
new DataPoint(21.61,-2.84,80.87),
new DataPoint(22.79,-2.59,77.25),
new DataPoint(6.78,-1.79,61.79),
new DataPoint(8.60,-1.40,60.76),
new DataPoint(9.71,-2.13,63.18),
new DataPoint(11.49,-2.17,63.29),
new DataPoint(14.25,-1.29,61.68),
new DataPoint(15.83,-2.07,61.33),
new DataPoint(17.76,-1.76,61.08),
new DataPoint(19.61,-2.22,61.32),
new DataPoint(19.79,-2.08,60.60),
new DataPoint(20.38,-1.75,59.54),
new DataPoint(7.39,-0.61,44.00),
new DataPoint(8.49,-0.76,43.64),
new DataPoint(10.43,-1.04,45.80),
new DataPoint(13.44,-0.33,44.98),
new DataPoint(14.63,-1.07,41.53),
new DataPoint(16.12,-0.59,42.88),
new DataPoint(18.24,-0.73,43.56),
new DataPoint(21.18,-0.60,45.70),
new DataPoint(21.72,-0.54,44.27),
new DataPoint(23.19,-0.26,44.07),
new DataPoint(7.36,0.51,83.00),
new DataPoint(9.25,0.51,80.63),
new DataPoint(10.43,0.95,85.33),
new DataPoint(12.41,0.65,85.27),
new DataPoint(15.06,0.62,85.34),
new DataPoint(15.91,0.45,85.00),
new DataPoint(18.44,0.64,85.20),
new DataPoint(20.56,0.55,82.29),
new DataPoint(19.92,0.19,83.75),
new DataPoint(21.06,0.02,82.37),
new DataPoint(8.15,0.53,81.51),
new DataPoint(8.51,0.87,85.38),
new DataPoint(11.19,0.76,82.60),
new DataPoint(13.78,1.02,82.59),
new DataPoint(15.39,1.03,82.80),
new DataPoint(16.45,0.06,84.60),
new DataPoint(18.62,0.70,83.96),
new DataPoint(21.91,0.60,85.43),
new DataPoint(22.19,0.42,81.38),
new DataPoint(23.53,0.70,83.79),
};
m_iDataPointCount = m_dataPoints.Length;
//Seek minimums and maximums for all dimensions
double x,z,value;
for (int i = 0; i < m_iDataPointCount; i++)
{
x = m_dataPoints[i].X;
value = m_dataPoints[i].Value;
z = m_dataPoints[i].Z;
if (x > MaxX)
MaxX = x;
if (x < MinX)
MinX = x;
if (z > MaxZ)
MaxZ = z;
if (z < MinZ)
MinZ = z;
if (value > MaxValue)
MaxValue = value;
if (value < MinValue)
MinValue = value;
}
CreateChart();
}
void CreateChart()
{
m_chart = new LightningChartUltimate();
m_chart.BeginUpdate();
m_chart.Parent = this;
m_chart.Dock = DockStyle.Fill;
m_chart.ActiveView = ActiveView.View3D;
View3D v = m_chart.View3D;
AxisX3D xAxis = m_chart.View3D.XAxisPrimary3D;
AxisY3D yAxis = m_chart.View3D.YAxisPrimary3D;
AxisZ3D zAxis = m_chart.View3D.ZAxisPrimary3D;
xAxis.SetRange(MinX, MaxX);
yAxis.SetRange(MinValue, MaxValue);
zAxis.SetRange(MinZ, MaxZ);
xAxis.ValueType = AxisValueType.Number;
//Create heatmap series
m_surface = new SurfaceGridSeries3D(v, Axis3DBinding.Primary, Axis3DBinding.Primary, Axis3DBinding.Primary);
m_surface.ContourLineType = ContourLineType.ColorLine;
m_surface.ContourLineColor = Color.White;
m_surface.WireframeType = SurfaceWireframeType.None;
m_surface.ColorSaturation = 80;
m_surface.WireframeType = SurfaceWireframeType.WireframePaletted;
SurfacePoint[,] data = new SurfacePoint[SizeX, SizeZ];
m_surface.Data = data;
m_surface.ContourPalette = CreatePalette(m_surface);
m_surface.SetRangesXZ(MinX, MaxX, MinZ, MaxZ);
m_surface.MouseInteraction = false;
v.SurfaceGridSeries3D.Add(m_surface);
//Create invisible point-line series for data point markers
PointLineSeries3D pls = new PointLineSeries3D(v, Axis3DBinding.Primary, Axis3DBinding.Primary, Axis3DBinding.Primary);
pls.PointsVisible = true;
pls.LineVisible = false;
pls.PointStyle.Shape = PointShape3D.Sphere;
pls.PointStyle.Size.SetValues(1, 1, 1);
pls.ShowInLegendBox = false;
pls.IndividualPointColors = true;
v.PointLineSeries3D.Add(pls);
SeriesPoint3D[] points = new SeriesPoint3D[m_iDataPointCount];
for (int i = 0; i < m_iDataPointCount; i++)
{
Color c;
m_surface.ContourPalette.GetColorByValue(m_dataPoints[i].Value, out c);
points[i].X = m_dataPoints[i].X;
points[i].Z = m_dataPoints[i].Z;
points[i].Y = m_dataPoints[i].Value;
points[i].Color = c;
points[i].SizeFactor = 1;
}
pls.Points = points;
UpdateHeatmap();
m_chart.EndUpdate();
}
ValueRangePalette CreatePalette(SurfaceGridSeries3D series)
{
ValueRangePalette palette = new ValueRangePalette(series);
palette.Steps.Clear();
palette.Steps.Add(new PaletteStep(palette, Color.Blue, MinValue));
palette.Steps.Add(new PaletteStep(palette, Color.Lime, MinValue + (MaxValue - MinValue) * 0.25));
palette.Steps.Add(new PaletteStep(palette, Color.Yellow, MinValue + (MaxValue - MinValue) * 0.50));
palette.Steps.Add(new PaletteStep(palette, Color.Red, MinValue + (MaxValue - MinValue) * 0.75));
palette.Steps.Add(new PaletteStep(palette, Color.White, MinValue + (MaxValue - MinValue) * 1));
palette.Type = PaletteType.Gradient;
palette.MinValue = MinValue;
return palette;
}
void UpdateHeatmap()
{
m_chart.BeginUpdate();
double dStepX = (MaxX - MinX) / (double)(SizeX - 1);
double dStepY = (MaxZ - MinZ) / (double)(SizeZ - 1);
double dX;
double dY;
SurfacePoint[,] data = m_surface.Data;
for (int i = 0; i < SizeX; i++)
{
for (int j = 0; j < SizeZ; j++)
{
dX = MinX + (double)i * dStepX;
dY = MinZ + (double)j * dStepY;
//Calculate combined influence of data points to this heatmap cell
//Use weighted average method
double dSum = 0;
double dSumOfWeights = 0;
for (int iP = 0; iP < m_iDataPointCount; iP++)
{
double dDist = m_dataPoints[iP].GetDistanceTo(dX, dY);
double dWeight = 0;
if (dDist != 0)
{
dWeight = 1.0 / Math.Pow(dDist, 3);
dSum += m_dataPoints[iP].Value * dWeight;
}
else
dSum += m_dataPoints[iP].Value;
dSumOfWeights += dWeight;
}
double dHeatmapValue = dSum / dSumOfWeights;
data[i, j].Y = dHeatmapValue;
}
}
m_surface.Data = data;
m_chart.EndUpdate();
}
}
public class DataPoint
{
public double X;
public double Z;
public double Value;
public DataPoint(double x, double value, double z)
{
this.X = x;
this.Z = z;
this.Value = value;
}
public double GetDistanceTo(double x, double z)
{
return Math.Sqrt((x - X) * (x - X) + (z - Z) * (z - Z));
}
}
}