Finally if I save the IntensityGridSeries to file using _contourChart.SaveToFile("contour.Png"); I get this (which has transparent background)
- contour.SaveToFile.Png.Png (3.41 KiB) Viewed 21409 times
Here is the code to create the first SurfaceGridSeries3D
Code: Select all
//Create new chart
m_chart = new LightningChartUltimate(LicenseKeys.LicenseKeyStrings.LightningChartUltimate);
//Disable rendering, strongly recommended before updating chart properties
m_chart.BeginUpdate();
//Set 3D as active view
m_chart.ActiveView = ActiveView.View3D;
//Chart parent must be set
m_chart.Parent = this.splitContainer1.Panel1;
//Fill parent area with chart
m_chart.Dock = DockStyle.Fill;
//Chart name
m_chart.Name = title;
m_chart.Title.Text = title;
//Set x-rotation
// m_chart.View3D.Camera.RotationX = 38;
m_chart.View3D.Camera.OrthographicCamera = true;
//scale X and Y (X and Z on lightning chart) for correct aspect ratio
double lX = ((nY - 1) * dy);
double lZ = ((nX - 1) * dx);
double maxdie = lZ;
if (lX > lZ) maxdie = lX;
m_chart.View3D.Dimensions.X = Convert.ToSingle(lX * 100.0 / maxdie);
m_chart.View3D.Dimensions.Z = Convert.ToSingle(lZ * 100.0 / maxdie);
m_chart.View3D.Dimensions.Y = m_yscale;
//Set transparent walls
List<WallBase> walls = m_chart.View3D.GetWalls();
foreach (WallBase wall in walls)
{
wall.Material.DiffuseColor = Color.FromArgb(30, wall.Material.DiffuseColor);
wall.SetGridStripColor1(Color.FromArgb(60, wall.GetGridStripColor1()));
wall.SetGridStripColor2(Color.FromArgb(60, wall.GetGridStripColor2()));
}
//Lightning Chart coords, our X = their Z, our Y = their X, our Z = their Y on 3D plots
m_chart.View3D.XAxisPrimary3D.SetRange(orgY, orgY + ((nY - 1) * dy));
m_chart.View3D.XAxisPrimary3D.Title.Text = "Y Axis";
m_chart.View3D.XAxisPrimary3D.Reversed = true;
m_chart.View3D.ZAxisPrimary3D.SetRange(orgX, orgX + ((nX - 1) * dx));
m_chart.View3D.ZAxisPrimary3D.Title.Text = "X Axis";
float[] fz = Z.Where(z => !Double.IsNaN(z)).ToArray();//filter out NaNs before getting Z (depth) min/max
m_chart.View3D.YAxisPrimary3D.SetRange(fz.Min(), fz.Max());
//m_chart.View3D.YAxisPrimary3D.Reversed = true;//depths are positive values "Below Sea Level", so reverse
m_chart.View3D.YAxisPrimary3D.Title.Text = "Burial Depth";
//this doesn't seem to work as expected with reversed axis, seems to be lit from bottom
//m_chart.View3D.SetPredefinedLightingScheme(LightingScheme.Default);
m_chart.View3D.ZoomPanOptions.AxisMouseWheelAction = AxisMouseWheelAction.ZoomAll;
//Add 3D surface grid
SurfaceGridSeries3D gridSeries = new SurfaceGridSeries3D(m_chart.View3D, Axis3DBinding.Primary, Axis3DBinding.Primary, Axis3DBinding.Primary);
IntensityGridSeries gridColourSeries = new IntensityGridSeries(m_chart.ViewXY, m_chart.ViewXY.XAxes[0], m_chart.ViewXY.YAxes[0]);
gridSeries.Title.Text = title;
float[] fcz = Z.Where(z => !Double.IsNaN(z)).ToArray();
float[] fcolourz = zColour.Where(z => !Double.IsNaN(z)).ToArray();
gridSeries.ContourPalette = CreatePalette(gridSeries, fcolourz.Min(), fcolourz.Max());
gridSeries.ContourLineType = ContourLineType.None;
gridSeries.ContourPalette.Type = PaletteType.Gradient;
gridSeries.WireframeType = SurfaceWireframeType.None;
gridSeries.Fill = SurfaceFillStyle.FromSurfacePoints;
gridSeries.SetRangesXZ(orgY, orgY + ((nY - 1) * dy), orgX, orgX + ((nX - 1) * dx));
gridSeries.SetSize(nY, nX);
gridColourSeries.SetRangesXY(orgX, orgX + ((nX - 1) * dx), orgY, orgY + ((nY - 1) * dy));
gridColourSeries.SetSize(nY, nX);
gridSeries.ColorSaturation = 65;
m_chart.View3D.SurfaceGridSeries3D.Add(gridSeries);
//Lightning Chart coords, our X = their Z, our Y = their X, our Z = their Y on 3D plots
for (int iNodeX = 0; iNodeX < nY; iNodeX++)
{
for (int iNodeZ = 0; iNodeZ < nX; iNodeZ++)
{
gridSeries.Data[(nY - 1) - iNodeX, iNodeZ].Y = (Z[iNodeZ * nY + iNodeX]);//stored column major
gridSeries.ContourPalette.GetColorByValue(zColour[iNodeZ * nY + iNodeX], out gridSeries.Data[(nY - 1) - iNodeX, iNodeZ].Color);
}
}
//Notify new values are ready
gridSeries.InvalidateData();
Create2DContourChart(gridColourSeries, zContour);
Create3DContourSurfaceChart(m_chart, gridSeries);
//Allow chart rendering
m_chart.EndUpdate();
Code to create Contours:
Code: Select all
private ValueRangePalette CreateContourPalette(Arction.LightningChartUltimate.SeriesXY.SeriesBaseXY ownerSeries, double ymin, double YRange)
{
ValueRangePalette palette = new ValueRangePalette(ownerSeries);
palette.Type = PaletteType.Gradient;
double yRange = YRange - ymin;
palette.Steps.Clear();
palette.MinValue = ymin;
palette.Steps.Add(new PaletteStep(palette, Color.FromArgb(0, 0, 0, 0), ymin));
palette.Steps.Add(new PaletteStep(palette, Color.FromArgb(0, 0, 0, 0), ymin + 33 * yRange / 100.0));
palette.Steps.Add(new PaletteStep(palette, Color.FromArgb(0, 0, 0, 0), ymin + 66 * yRange / 100.0));
palette.Steps.Add(new PaletteStep(palette, Color.FromArgb(0, 0, 0, 0), ymin + 100.0 * yRange / 100.0));
palette.Steps.Add(new PaletteStep(palette, Color.FromArgb(0, 0, 0, 0), ymin - 10)); //Aux step
palette.Steps.Add(new PaletteStep(palette, Color.FromArgb(0, 0, 0, 0), -1E9)); //Aux step
return palette;
}
/// <summary>
/// Intensity chart renders intensity data from given data set, and exports a bitmap image.
/// </summary>
void Create2DContourChart(IntensityGridSeries gridColourSeries, float[] contourData)
{
_contourChart = new LightningChartUltimate();
_contourChart.BeginUpdate();
this.splitContainer1.Panel2.BackColor = Color.Blue;
this.BackColor = Color.Red;
_contourChart.Parent = this.splitContainer1.Panel2;
_contourChart.Dock = DockStyle.Fill;
_contourChart.Width = gridColourSeries.SizeX;
_contourChart.Height = gridColourSeries.SizeY;
_contourChart.RenderOptions.AntiAliasLevel = 4;
_contourChart.Background.Color = Color.Transparent;
//_contourChart.Background.GradientColor = Color.Transparent;
//_contourChart.Background.GradientFill = GradientFill.Solid;
_contourChart.Background.Style = RectFillStyle.None;
//_contourChart.ViewXY.GraphBackground.Color = Color.DarkMagenta;
//_contourChart.ViewXY.GraphBackground.GradientColor = Color.DarkGreen;
_contourChart.ViewXY.GraphBackground.Style = RectFillStyle.None;
_contourChart.ActiveView = ActiveView.ViewXY;
_contourChart.Title.Visible = false;
ViewXY v = _contourChart.ViewXY;
v.LegendBox.Visible = false;
//Remove all margins
v.Margins = new System.Windows.Forms.Padding(0);
v.GraphBorderColor = Color.Transparent;
IntensityGridSeries grid = new IntensityGridSeries(v, v.XAxes[0], v.YAxes[0]);
grid.SetRangesXY(gridColourSeries.RangeMinX, gridColourSeries.RangeMaxX, gridColourSeries.RangeMinY, gridColourSeries.RangeMaxY);
grid.SetSize(gridColourSeries.SizeX, gridColourSeries.SizeY);
grid.ContourLineType = ContourLineType.ColorLine;
grid.ContourLineStyle.Color = Color.Black;
grid.ContourLineStyle.Pattern = LinePattern.Solid;
grid.ContourLineStyle.Width = 2;
v.AxisLayout.AutoAdjustMargins = false;
float[] fz = contourData.Where(z => !Double.IsNaN(z)).ToArray();//filter out NaNs before getting contour data
grid.ValueRangePalette = CreateContourPalette(grid, fz.Min(), fz.Max());
v.IntensityGridSeries.Add(grid);
//Set axis ranges sow that intensity grid fills it. Minimums same and Maximums same.
v.XAxes[0].SetRange(gridColourSeries.RangeMinX, gridColourSeries.RangeMaxX);
v.YAxes[0].SetRange(gridColourSeries.RangeMinY, gridColourSeries.RangeMaxY);
for (int iNodeX = 0; iNodeX < gridColourSeries.SizeX; iNodeX++)
{
for (int iNodeZ = 0; iNodeZ < gridColourSeries.SizeY; iNodeZ++)
{
grid.Data[(gridColourSeries.SizeX - 1) - iNodeX, iNodeZ].Value = (contourData[iNodeZ * gridColourSeries.SizeX + iNodeX]);//stored column major
}
}
_contourChart.EndUpdate();
_contourChart.SaveToStream(_bitmapStream, TargetImageFormat.Png);
_contourChart.SaveToFile("contour.Png");
}
Code to create second SurfaceGridSeries3D
Code: Select all
void Create3DContourSurfaceChart(LightningChartUltimate _surface3DChart, SurfaceGridSeries3D depthSurface)
{
View3D v = _surface3DChart.View3D;
v.LegendBox.Visible = false;
SurfaceGridSeries3D surface = new SurfaceGridSeries3D(v, Axis3DBinding.Primary, Axis3DBinding.Primary, Axis3DBinding.Primary);
surface.SetRangesXZ(depthSurface.RangeMinX, depthSurface.RangeMaxX, depthSurface.RangeMinZ, depthSurface.RangeMaxZ);
surface.SetSize(depthSurface.SizeX, depthSurface.SizeZ);
surface.BitmapFill.Image = Bitmap.FromStream(_bitmapStream);
surface.Fill = SurfaceFillStyle.Bitmap;
//surface.ToneColor = Color.Beige;
surface.ContourLineType = ContourLineType.None;
surface.WireframeType = SurfaceWireframeType.None;
surface.ColorSaturation = 75;
surface.BaseColor = Color.Transparent;
surface.ToneColor = Color.Transparent;
surface.ContourPalette = depthSurface.ContourPalette;
for (int i = 0; i < depthSurface.SizeX; i++)
{
for (int j = 0; j < depthSurface.SizeZ; j++)
{
surface.Data[i, j].Y = depthSurface.Data[i, j].Y + 500.0;//add some constant to Y so this surface is distinct from first, just for testing
}
}
v.SurfaceGridSeries3D.Add(surface);
surface.InvalidateData();
}
Any ideas to get this to work?
I will post the project file...