using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;
using Steema.TeeChart.Drawing;
using Steema.TeeChart.Styles;
using Steema.TeeChart.Tools;
namespace TestProject
{
/// <summary>
/// 메인 폼
/// </summary>
public partial class MainForm : Form
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 커서 툴
/// </summary>
private CursorTool cursorTool;
/// <summary>
/// 현재 X
/// </summary>
private double currentX;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary>
/// 생성자
/// </summary>
public MainForm()
{
InitializeComponent();
Text = "CursorTool 클래스 : 라인 시리즈 보간하기";
this.showMarkerCheckBox.Checked = true;
this.tChart.Panel.Pen = new ChartPen(Color.Black);
#region 라인을 추가한다.
for(int i = 0; i < 3; i++)
{
Line line = new Line();
line.Pointer.HorizSize = 3;
line.Pointer.VertSize = 3;
line.Pointer.Visible = true;
if(i == 0)
{
line.Pointer.Style = PointerStyles.Rectangle;
}
else if(i == 1)
{
line.Pointer.Style = PointerStyles.Circle;
}
else
{
line.Pointer.Style = PointerStyles.Triangle;
}
line.FillSampleValues(20);
this.tChart.Series.Add(line);
}
#endregion
#region 커서 툴을 설정한다.
this.cursorTool = new CursorTool();
this.cursorTool.Pen.Style = DashStyle.Dash;
this.cursorTool.Style = CursorToolStyles.Vertical;
this.cursorTool.FollowMouse = true;
this.tChart.Tools.Add(this.cursorTool);
#endregion
#region 이벤트를 설정한다.
Load += Form_Load;
this.cursorTool.Change += cursorTool_Change;
this.tChart.AfterDraw += tChart_AfterDraw;
#endregion
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 폼 로드시 처리하기 - Form_Load(sender, e)
/// <summary>
/// 폼 로드시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void Form_Load(object sender, EventArgs e)
{
cursorTool_Change(this.tChart, new CursorChangeEventArgs());
}
#endregion
#region 커서 툴 변경시 처리하기 - cursorTool_Change(sender, e)
/// <summary>
/// 커서 툴 변경시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void cursorTool_Change(object sender, CursorChangeEventArgs e)
{
this.currentX = e.XValue;
StringBuilder stringBuilder = new StringBuilder();
for(int i = 0; i < this.tChart.Series.Count; i++)
{
if(this.tChart.Series[i] is Custom)
{
stringBuilder.Append($"{this.tChart.Series[i].Title} : Y({e.XValue:0.00}) = ");
stringBuilder.AppendLine($"{GetInterpolateValue(this.tChart.Series[i] as Custom, e.XValue):0.00}");
}
}
this.tChart.Header.Text = stringBuilder.ToString();
}
#endregion
#region TChart 그리기 후 처리하기 - tChart_AfterDraw(sender, graphics3D)
/// <summary>
/// TChart 그리기 후 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="graphics3D">그래픽스 3D</param>
private void tChart_AfterDraw(object sender, Graphics3D graphics3D)
{
if(this.showMarkerCheckBox.Checked)
{
int xPixel = this.tChart.Axes.Bottom.CalcXPosValue(this.currentX);
graphics3D.Brush.Visible = true;
graphics3D.Brush.Solid = true;
for(int i = 0; i < this.tChart.Series.Count; i++)
{
if(this.tChart.Series[i] is Custom)
{
int yPixel = this.tChart.Series[i].GetVertAxis.CalcYPosValue(GetInterpolateValue(this.tChart.Series[i] as Custom, this.currentX));
graphics3D.Brush.Color = this.tChart.Series[i].Color;
graphics3D.Ellipse(new Rectangle(xPixel - 4, yPixel - 4, 8, 8));
}
}
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 보간 값 구하기 - GetInterpolateValue(custom, firstIndex, lastIndex, xValue)
/// <summary>
/// 보간 값 구하기
/// </summary>
/// <param name="custom">커스텀 시리즈</param>
/// <param name="firstIndex">첫번째 인덱스</param>
/// <param name="lastIndex">마지막 인덱스</param>
/// <param name="xValue">X 값</param>
/// <returns>보간 값</returns>
private double GetInterpolateValue(Custom custom, int firstIndex, int lastIndex, double xValue)
{
int index;
for(index = firstIndex; index <= lastIndex; index++)
{
if(index == -1 || custom.XValues.Value[index] > xValue)
{
break;
}
}
if(index < 1)
{
index = 1;
}
else if(index >= custom.Count)
{
index = custom.Count -1;
}
double deltaX = custom.XValues[index] - custom.XValues[index - 1];
double deltaY = custom.YValues[index] - custom.YValues[index - 1];
if(deltaX != 0.0)
{
return deltaY * (xValue - custom.XValues[index - 1]) / deltaX + custom.YValues[index - 1];
}
else
{
return 0.0;
}
}
#endregion
#region 보간 값 구하기 - GetInterpolateValue(custom, xValue)
/// <summary>
/// 보간 값 구하기
/// </summary>
/// <param name="custom">커스텀 시리즈</param>
/// <param name="xValue">X 값</param>
/// <returns>보간 값</returns>
private double GetInterpolateValue(Custom custom, double xValue)
{
return GetInterpolateValue(custom, custom.FirstVisibleIndex, custom.LastVisibleIndex, xValue);
}
#endregion
}
}