我想在曲面图中显示散点。这在闪电图中可行吗?
谢谢,
是的,这是可能的。
请参阅 LC WPF 演示应用程序中的 ExampleSurfaceMouseEditing。它在 Surface 的每个数据值中显示散点,并显示如何通过鼠标拖动点来修改曲面几何 Y 值。
using System;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Controls;
using Arction.Wpf.Charting;
using Arction.Wpf.Charting.Series3D;
using Arction.Wpf.Charting.Views.View3D;
namespace DemoAppWpf
{
/// <summary>
/// 3D surface data modifying by mouse. Illustrates MovePoint feature of View3D.
/// </summary>
public partial class ExampleSurfaceMouseEdit : Example
{
/// <summary>
/// LightningChart component.
/// </summary>
LightningChartUltimate _chart;
/// <summary>
/// 3D surface.
/// </summary>
SurfaceGridSeries3D _surface;
/// <summary>
/// Surface verteces.
/// </summary>
PointLineSeries3D _points;
/// <summary>
/// Mouse state for editing the surface.
/// </summary>
bool _editing = false;
/// <summary>
/// Index of editable vertice.
/// </summary>
int _editingPointIndex;
/// <summary>
/// Surface vertices size.
/// </summary>
const float NormalPointSize = 1f;
/// <summary>
/// Size for selected surface vertices.
/// </summary>
const float LargePointSize = 2f;
/// <summary>
/// Surface vertices color.
/// </summary>
static Color NormalPointColor = Colors.Gray;
/// <summary>
/// Color for selected surface vertices.
/// </summary>
static Color HighlightedPointColor = Colors.Yellow;
public ExampleSurfaceMouseEdit()
{
InitializeComponent();
CreateChart();
}
/// <summary>
/// Create chart.
/// </summary>
private void CreateChart()
{
_chart = new LightningChartUltimate();
// Disable rendering, strongly recommended before updating chart properties.
_chart.BeginUpdate();
_chart.ChartName = "Surface mouse edit chart";
_chart.Title.Text = "Move mouse over surface, and press mouse button down to start moving a point";
_chart.ActiveView = ActiveView.View3D;
View3D view = _chart.View3D;
// Disable rotation from left button, so it can be used for adjusting points.
view.ZoomPanOptions.LeftMouseButtonAction = MouseButtonAction3D.None;
view.ZoomPanOptions.RightMouseButtonAction = MouseButtonAction3D.Rotate;
view.Camera.RotationX += 20;
// Create Surface.
_surface = new SurfaceGridSeries3D(view, Axis3DBinding.Primary, Axis3DBinding.Primary, Axis3DBinding.Primary);
_surface.ContourLineType = ContourLineType3D.None;
_surface.Fill = SurfaceFillStyle.PalettedByY;
_surface.SetRangesXZ(10, 90, 10, 90);
_surface.MouseInteraction = false;
_surface.WireframeType = SurfaceWireframeType3D.WireframePalettedByY;
view.SurfaceGridSeries3D.Add(_surface);
// Create series of poits to interract with surface.
_points = new PointLineSeries3D(_chart.View3D, Axis3DBinding.Primary, Axis3DBinding.Primary, Axis3DBinding.Primary);
_points.ShowInLegendBox = false;
_points.PointStyle.Shape3D = PointShape3D.Sphere;
_points.PointStyle.Size3D.SetValues(1, 1, 1);
_points.Material.DiffuseColor = Color.FromArgb(255, 120, 120, 120);
_points.MouseInteraction = true;
_points.MouseHighlight = MouseOverHighlight.None;
_points.LineVisible = false;
_points.IndividualPointColors = true;
_points.IndividualPointSizes = true;
view.PointLineSeries3D.Add(_points);
SurfacePoint[,] surfaceData;
SeriesPoint3D[] pointsData;
// Set data for surface and points
CreateData(out surfaceData, out pointsData, _surface.RangeMinX, _surface.RangeMaxX, _surface.RangeMinZ, _surface.RangeMaxZ);
_surface.Data = surfaceData;
_points.Points = pointsData;
// Registrate mouse events.
_chart.PreviewMouseLeftButtonDown += _chart_MouseDown;
_chart.PreviewMouseLeftButtonUp += _chart_MouseUp;
_chart.MouseMove += _chart_MouseMove;
// Allow chart rendering.
_chart.EndUpdate();
(Content as Grid).Children.Add(_chart);
base.ChartsCreated(_chart);
}
private void _chart_MouseDown(object sender, MouseButtonEventArgs e)
{
if (_editingPointIndex >= 0)
_editing = true;
}
private void _chart_MouseUp(object sender, MouseButtonEventArgs e)
{
_editing = false;
ResetPointsToNormalState();
_editingPointIndex = -1;
}
private void _chart_MouseMove(object sender, MouseEventArgs e)
{
// Right mouse button is set for Rotation; if it is pressed no further execution of the code here is required.
if (e.RightButton == MouseButtonState.Pressed)
return;
var position = e.GetPosition(_chart);
if (_editing)
{
_chart.BeginUpdate();
PointDouble3D startPoint = new PointDouble3D(_points.Points[_editingPointIndex].X, _points.Points[_editingPointIndex].Y, _points.Points[_editingPointIndex].Z);
// Move the point in Y dimension
var movedPoint = _chart.View3D.MovePoint(Axis3DBinding.Primary, new PointDouble3D(startPoint.X, startPoint.Y, startPoint.Z),
new PointFloatXY((float)position.X, (float)position.Y), MovementDimension.Y);
_points.Points[_editingPointIndex].X = movedPoint.X;
_points.Points[_editingPointIndex].Y = movedPoint.Y;
_points.Points[_editingPointIndex].Z = movedPoint.Z;
_points.InvalidateData();
_surface.Data[_editingPointIndex / _surface.SizeZ, _editingPointIndex % _surface.SizeZ].Y = movedPoint.Y;
_surface.InvalidateData();
_chart.EndUpdate();
}
else
{
int pointIndex = -1;
bool overLine = false;
bool overPoint = false;
if (_points.IsMouseOver((int)position.X, (int)position.Y, out pointIndex, out overLine, out overPoint, true))
{
_chart.BeginUpdate();
if (pointIndex != _editingPointIndex && _editingPointIndex >= 0)
ResetPointsToNormalState();
_editingPointIndex = pointIndex;
_points.Points[pointIndex].SizeFactor = LargePointSize;
_points.Points[pointIndex].Color = HighlightedPointColor;
_points.InvalidateData();
_chart.EndUpdate();
}
else
{
ResetPointsToNormalState();
}
}
}
/// <summary>
/// Reset points to normal state
/// </summary>
void ResetPointsToNormalState()
{
if (_editingPointIndex >= 0)
{
int pointCount = _points.Points.Length;
for (int i = 0; i < pointCount; i++)
{
_points.Points[i].SizeFactor = NormalPointSize;
_points.Points[i].Color = NormalPointColor;
}
_points.InvalidateData();
}
}
/// <summary>
/// Create data array for surface.
/// <param name="pointsData">Points</param>
/// <param name="surfaceData">Surface data</param>
/// <param name="xMax">X Max</param>
/// <param name="xMin">X Min</param>
/// <param name="zMax">Z Max</param>
/// <param name="zMin">Z Min</param>
/// </summary>
void CreateData(out SurfacePoint[,] surfaceData, out SeriesPoint3D[] pointsData, double xMin, double xMax, double zMin, double zMax)
{
int xCount = 50;
int zCount = 30;
surfaceData = new SurfacePoint[xCount, zCount];
pointsData = new SeriesPoint3D[xCount * zCount];
double xStep = (xMax - xMin) / (double)(xCount - 1);
double zStep = (zMax - zMin) / (double)(zCount - 1);
double y;
for (int xIndex = 0; xIndex < xCount; xIndex++)
{
for (int zIndex = 0; zIndex < zCount; zIndex++)
{
y = 30 + 20.0 * Math.Sin(0.01 * (double)(xIndex * zIndex) + 0.2);
if ((xIndex + 5) % 20 == 0)
y += 20;
if ((zIndex + 5) % 20 == 0)
y += 30;
surfaceData[xIndex, zIndex].Y = y;
pointsData[xIndex * zCount + zIndex] = new SeriesPoint3D(xMin + (double)xIndex * xStep, y, zMin + (double)zIndex * zStep, NormalPointColor, NormalPointSize);
}
}
}
public override void Dispose()
{
// Don't forget to clear chart grid child list.
(Content as Grid).Children.Clear();
if (_chart != null)
{
_chart.Dispose();
_chart = null;
}
// Disposing of unmanaged resources done.
base.DisposedOf();
}
}
}