[C#/WINFORM/REOGRID/.NET8] ReoGridControl 클래스 사용하기 (단순 객체 생성)
■ ReoGridControl 클래스를 사용하는 방법을 보여준다. (단순 객체 생성) TestProject.zip
■ ReoGridControl 클래스를 사용하는 방법을 보여준다. (단순 객체 생성) TestProject.zip
■ unvell.ReoGrid.dll 누겟을 설치하는 방법을 보여준다. 1. Visual Studio를 실행한다. 2. [도구] / [NuGet 패키지 관리자] / [패키지 관리자 콘솔] 메뉴를 실행한다.
■ UserControl 클래스를 사용해 등고선 차트 컨트롤을 만드는 방법을 보여준다. ▶ ContourChartControl.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; namespace TestProject; /// <summary> /// 등고선 차트 컨트롤 /// </summary> public partial class ContourChartControl : UserControl { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 레벨 배열 /// </summary> private float[] levelArray; /// <summary> /// 색상 배열 /// </summary> private Color[] colorArray; /// <summary> /// 데이터 배열 /// </summary> private float[,] valueArray; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - ContourChartControl() /// <summary> /// 생성자 /// </summary> public ContourChartControl() { InitializeComponent(); } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region 데이터 설정하기 - SetData(levelArray, colorArray, valueArray) /// <summary> /// 데이터 설정하기 /// </summary> /// <param name="levelArray">레벨 배열</param> /// <param name="colorArray">색상 배열</param> /// <param name="valueArray">값 배열</param> public void SetData(float[] levelArray, Color[] colorArray, float[,] valueArray) { this.levelArray = levelArray; this.colorArray = colorArray; this.valueArray = valueArray; Invalidate(); } #endregion ////////////////////////////////////////////////////////////////////////////////////////// Protected #region 페인트 처리하기 - OnPaint(e) /// <summary> /// 페인트 처리하기 /// </summary> /// <param name="e">이벤트 인자</param> protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); if(this.valueArray == null || this.levelArray == null || this.colorArray == null) { return; } DrawContour(e.Graphics); } #endregion ////////////////////////////////////////////////////////////////////////////////////////// Private #region 포인트 스케일 설정하기 - ScalePoint(sourcePoint) /// <summary> /// 포인트 스케일 설정하기 /// </summary> /// <param name="sourcePoint">소스 포인트</param> /// <returns>스케일 포인트</returns> private PointF ScalePoint(PointF sourcePoint) { return new PointF(sourcePoint.X * Width / (valueArray.GetLength(0) - 1), Height - sourcePoint.Y * Height / (valueArray.GetLength(1) - 1)); } #endregion #region 등고선 셀 그리기 - DrawContourCell(graphics, x, y, valueArray, lowLevel, highLevel, color) /// <summary> /// 등고선 셀 그리기 /// </summary> /// <param name="graphics">그래픽스</param> /// <param name="x">X</param> /// <param name="y">Y</param> /// <param name="valueArray">값 배열</param> /// <param name="lowLevel">하한 레벨</param> /// <param name="highLevel">상한 레벨</param> /// <param name="color">색상</param> private void DrawContourCell(Graphics graphics, int x, int y, float[] valueArray, float lowLevel, float highLevel, Color color) { List<PointF> pointList = new List<PointF>(); for(int i = 0; i < 4; i++) { int j = (i + 1) % 4; if((valueArray[i] < lowLevel && valueArray[j] >= lowLevel) || (valueArray[i] >= lowLevel && valueArray[j] < lowLevel)) { float t = (lowLevel - valueArray[i]) / (valueArray[j] - valueArray[i]); pointList.Add ( new PointF ( x + (i % 2) + t * ((j % 2) - (i % 2)), y + (i / 2) + t * ((j / 2) - (i / 2)) ) ); } } if(pointList.Count == 2) { using(Pen pen = new Pen(color, 1)) { graphics.DrawLine(pen, ScalePoint(pointList[0]), ScalePoint(pointList[1])); } } } #endregion #region 등고선 그리기 - DrawContour(graphics) /// <summary> /// 등고선 그리기 /// </summary> /// <param name="graphics">그래픽스</param> private void DrawContour(Graphics graphics) { int width = this.valueArray.GetLength(0); int height = this.valueArray.GetLength(1); for(int x = 0; x < width - 1; x++) { for(int y = 0; y < height - 1; y++) { float[] cellValueArray = new float[] { valueArray[x , y ], valueArray[x + 1, y ], valueArray[x + 1, y + 1], valueArray[x , y + 1] }; for(int i = 0; i < this.levelArray.Length - 1; i++) { DrawContourCell(graphics, x, y, cellValueArray, this.levelArray[i], this.levelArray[i + 1], this.colorArray[i]); } } } } #endregion } |
▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
using System; using System.Drawing; using System.Windows.Forms; namespace TestProject; /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : Form { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); float[] levelArray = { 0f, 0.2f, 0.4f, 0.6f, 0.8f, 1f }; Color[] colorArray = { Color.Blue, Color.Green, Color.Yellow, Color.Orange, Color.Red }; float[,] valueArray = GetValueArray(); contourChartControl.SetData(levelArray, colorArray, valueArray); } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 값 배열 구하기 - GetValueArray() /// <summary> /// 값 배열 구하기 /// </summary> /// <returns>값 배열</returns> public float[,] GetValueArray() { int width = this.contourChartControl.Width; int height = this.contourChartControl.Height; float[,] valueArray = new float[width, height]; for(int x = 0; x < width; x++) { for(int y = 0; y < height; y++) { float xNormalized = (float)x / width * 10; float yNormalized = (float)y / height * 10; valueArray[x, y] = (float)(Math.Sin(xNormalized) * Math.Cos(yNormalized) + Math.Cos(xNormalized * 0.5f) * Math.Sin(yNormalized * 0.5f)); valueArray[x, y] = (valueArray[x, y] + 1) / 2; } } return valueArray; } #endregion } |
TestProject.zip
■ TChart 클래스의 ClickLegend 이벤트를 사용해 레전드 클릭시 처리하는 방법을 보여준다. (.NET 오류 개선 버전) ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
using Steema.TeeChart.Styles; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : Form { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); for(int i = 0; i < 10; i++) { Points points = new Points(this.tChart.Chart); points.FillSampleValues(20); } this.tChart.ClickLegend += tChart_ClickLegend; this.tChart.MouseClick += tChart_MouseClick; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 티차트 레전드 클릭시 처리하기 - tChart_ClickLegend(sender, e) /// <summary> /// 티차트 레전드 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void tChart_ClickLegend(object sender, MouseEventArgs e) { // .NET6 버그 처리 double legendItemHeight = (double)this.tChart.Legend.Height / (double)this.tChart.Series.Count; int heightOffset = this.tChart.Legend.Height - (this.tChart.Legend.Height - (e.Y - this.tChart.Legend.Top)); int index = (int)((double)heightOffset / legendItemHeight); // .NET FRAMEWORK의 경우 //int index = this.tChart.Legend.Clicked(e.X, e.Y); if(index > -1) { for(int i = 0; i < this.tChart.Series.Count; i++) { this.tChart[i].Transparency = 0; if(i != index) { // 선택되지 않은 항목 반투명하게 처리한다. this.tChart[i].Transparency = 70; } } } } #endregion #region 티차트 마우스 클릭시 처리하기 - tChart_MouseClick(sender, e) /// <summary> /// 티차트 마우스 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void tChart_MouseClick(object sender, MouseEventArgs e) { // Legend 영역이 아닌 경우 모두 원상태로 돌리기 int index = this.tChart.Legend.Clicked(e.X, e.Y); if(index == -1) { for(int i = 0; i < this.tChart.Series.Count; i++) { this.tChart[i].Transparency = 0; } } } #endregion } } |
TestProject.zip
■ 데스크톱에서 눈송이(snowflake)를 내리는 방법을 보여준다. ▶ Snowflake.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
using System; using System.Drawing; using System.Windows.Forms; namespace TestProject { /// <summary> /// 눈송이 /// </summary> public class Snowflake : PictureBox { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 난수기 /// </summary> private Random random = new Random(); #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - Snowflake() /// <summary> /// 생성자 /// </summary> public Snowflake() { Create(); Move(); } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private //////////////////////////////////////////////////////////////////////////////// Event #region 타이머 틱 처리하기 - timer_Tick(sender, e) /// <summary> /// 타이머 틱 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void timer_Tick(object sender, EventArgs e) { Location += new Size(1, 3); if(Location.X > Screen.PrimaryScreen.Bounds.Width || Location.Y > Screen.PrimaryScreen.Bounds.Height) { Location = new Point ( this.random.Next(-Screen.PrimaryScreen.Bounds.Width , Screen.PrimaryScreen.Bounds.Width ), this.random.Next(-Screen.PrimaryScreen.Bounds.Height, Screen.PrimaryScreen.Bounds.Height) ); } } #endregion //////////////////////////////////////////////////////////////////////////////// Function #region 생성하기 - Create() /// <summary> /// 생성하기 /// </summary> private void Create() { Location = new Point ( this.random.Next(-Screen.PrimaryScreen.Bounds.Width , Screen.PrimaryScreen.Bounds.Width ), this.random.Next(-Screen.PrimaryScreen.Bounds.Height, Screen.PrimaryScreen.Bounds.Height) ); MinimumSize = new Size(7, 7); Size = new Size(10, 10); BackgroundImage = Image.FromFile("snowflake.jpg"); } #endregion #region 이동하기 - Move() /// <summary> /// 이동하기 /// </summary> private new void Move() { Timer timer = new Timer(); timer.Interval = 40; timer.Tick += timer_Tick; timer.Start(); } #endregion } } |
▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
using System; using System.Drawing; using System.Windows.Forms; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : Form { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 눈송이 카운트 /// </summary> private readonly int snowflakeCount = 40; /// <summary> /// 눈송이 배열 /// </summary> private Snowflake[] snowflakeArray; /// <summary> /// 인덱스 /// </summary> private int index = 0; /// <summary> /// 타이머 /// </summary> private Timer timer; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); Load += Form_Load; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 폼 로드시 처리하기 - Form_Load(sender, e) /// <summary> /// 폼 로드시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void Form_Load(object sender, EventArgs e) { Location = new Point(0, 0); Size = Screen.PrimaryScreen.Bounds.Size + (new Size(20, 20)); TopMost = true; FormBorderStyle = FormBorderStyle.None; BackColor = Color.Black; TransparencyKey = Color.Black; this.snowflakeArray = new Snowflake[this.snowflakeCount]; this.timer = new Timer(); this.timer.Interval = 1000; this.timer.Tick += timer_Tick; this.timer.Start(); } #endregion #region 타이머 틱 처리하기 - timer_Tick(sender, e) /// <summary> /// 타이머 틱 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void timer_Tick(object sender, EventArgs e) { if(this.index >= this.snowflakeCount) { this.timer.Stop(); return; } this.snowflakeArray[index] = new Snowflake(); Controls.Add(this.snowflakeArray[this.index]); this.index++; } #endregion } } |
TestProject.zip
■ HSV 색상 선택기를 만드는 방법을 보여준다. ▶ Point2D.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
namespace TestProject; /// <summary> /// 2D 포인트 /// </summary> public class Point2D { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region X 좌표 - X /// <summary> /// X 좌표 /// </summary> public double X { get; set; } #endregion #region Y 좌표 - Y /// <summary> /// Y 좌표 /// </summary> public double Y { get; set; } #endregion } |
▶ ColorPicker.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 |
using System.Drawing.Imaging; namespace TestProject; /// <summary> /// 색상 선택기 /// </summary> public class ColorPicker { //////////////////////////////////////////////////////////////////////////////////////////////////// Enumeration ////////////////////////////////////////////////////////////////////////////////////////// Public #region 영역 - Area /// <summary> /// 영역 /// </summary> public enum Area { /// <summary> /// 외부 /// </summary> Outside, /// <summary> /// 휠 /// </summary> Wheel, /// <summary> /// 삼각형 /// </summary> Triangle } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Structure ////////////////////////////////////////////////////////////////////////////////////////// Public #region 선택 결과 - PickResult /// <summary> /// 선택 결과 /// </summary> public struct PickResult { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 영역 - Area /// <summary> /// 영역 /// </summary> public Area Area { get; set; } #endregion #region 색상 - Hue /// <summary> /// 색상 /// </summary> public double? Hue { get; set; } #endregion #region 채도 - Saturation /// <summary> /// 채도 /// </summary> public double? Saturation { get; set; } #endregion #region 값 - Value /// <summary> /// 값 /// </summary> public double? Value { get; set; } #endregion } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 크기 - Size /// <summary> /// 크기 /// </summary> public int Size { get; } #endregion #region 중앙 X - CenterX /// <summary> /// 중앙 X /// </summary> public int CenterX => Size / 2; #endregion #region 중앙 Y - CenterY /// <summary> /// 중앙 Y /// </summary> public int CenterY => Size / 2; #endregion #region 내부 반경 - InnerRadius /// <summary> /// 내부 반경 /// </summary> public int InnerRadius => Size * 5 / 12; #endregion #region 외부 반경 - OuterRadius /// <summary> /// 외부 반경 /// </summary> public int OuterRadius => Size / 2; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - ColorPicker(size) /// <summary> /// 생성자 /// </summary> /// <param name="size">크기</param> public ColorPicker(int size = 400) { Size = size; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region 이미지 그리기 - DrawImage(hue, saturation, value) /// <summary> /// 이미지 그리기 /// </summary> /// <param name="hue">색상</param> /// <param name="saturation">채도</param> /// <param name="value">값</param> /// <returns>이미지</returns> public Image DrawImage(double hue = 0d, double saturation = 1d, double value = 1d) { Bitmap bitmap = new Bitmap(Size, Size, PixelFormat.Format32bppArgb); for(int y = 0; y < Size; y++) { for(int x = 0; x < Size; x++) { Color color; PickResult pickResult = Pick(x, y); if(pickResult.Area == Area.Outside) { color = Color.Transparent; } else if(pickResult.Area == Area.Wheel) { color = GetHSVColor(pickResult.Hue.Value, saturation, value, 1); } else { color = GetHSVColor(hue, pickResult.Saturation.Value, pickResult.Value.Value, 1); } bitmap.SetPixel(x, y, color); } } return bitmap; } #endregion #region 휠 위치 구하기 - GetWheelPosition(hue) /// <summary> /// 휠 위치 구하기 /// </summary> /// <param name="hue">색상</param> /// <returns>휠 위치</returns> public Point2D GetWheelPosition(double hue) { double middleRadius = (InnerRadius + OuterRadius) / 2; return new Point2D { X = CenterX + middleRadius * Math.Sin(hue), Y = CenterY - middleRadius * Math.Cos(hue) }; } #endregion #region 삼각형 위치 구하기 - GetTrianglePosition(saturation, value) /// <summary> /// 삼각형 위치 구하기 /// </summary> /// <param name="saturation">채도</param> /// <param name="value">값</param> /// <returns>삼각형 위치</returns> public Point2D GetTrianglePosition(double saturation, double value) { double squareRoot3 = Math.Sqrt(3); return new Point2D { X = CenterX + InnerRadius * (2 * value - saturation * value - 1) * squareRoot3 / 2, Y = CenterY + InnerRadius * (1 - 3 * saturation * value) / 2 }; } #endregion #region 선택하기 - Pick(x, y) /// <summary> /// 선택하기 /// </summary> /// <param name="x">X 좌표</param> /// <param name="y">Y 좌표</param> /// <returns>선택 결과</returns> public PickResult Pick(double x, double y) { double distanceFromCenter = Math.Sqrt((x - CenterX) * (x - CenterX) + (y - CenterY) * (y - CenterY)); double squareRoot3 = Math.Sqrt(3); if(distanceFromCenter > OuterRadius) { return new PickResult { Area = Area.Outside }; } else if(distanceFromCenter > InnerRadius) { double angle = Math.Atan2(y - CenterY, x - CenterX) + Math.PI / 2; if(angle < 0) { angle += 2 * Math.PI; } double hue = angle; return new PickResult { Area = Area.Wheel, Hue = hue }; } else { double x1 = (x - CenterX) * 1.0d / InnerRadius; double y1 = (y - CenterY) * 1.0d / InnerRadius; if(0 * x1 + 2 * y1 > 1) { return new PickResult { Area = Area.Outside }; } else if(squareRoot3 * x1 + (-1) * y1 > 1) { return new PickResult { Area = Area.Outside }; } else if(-squareRoot3 * x1 + (-1) * y1 > 1) { return new PickResult { Area = Area.Outside }; } else { double saturation = (1 - 2 * y1) / (squareRoot3 * x1 - y1 + 2); double value = (squareRoot3 * x1 - y1 + 2) / 3; return new PickResult { Area = Area.Triangle, Saturation = saturation, Value = value }; } } } #endregion ////////////////////////////////////////////////////////////////////////////////////////// Private #region RGB 색상 구하기 - GetRGBColor(red, green, blue, alpha) /// <summary> /// RGB 색상 구하기 /// </summary> /// <param name="red">적색</param> /// <param name="green">녹색</param> /// <param name="blue">청색</param> /// <param name="alpha">투명도</param> /// <returns>RGB 색상</returns> private Color GetRGBColor(double red, double green, double blue, double alpha) { return Color.FromArgb ( Math.Min(255, (int)(alpha * 256)), Math.Min(255, (int)(red * 256)), Math.Min(255, (int)(green * 256)), Math.Min(255, (int)(blue * 256)) ); } #endregion #region HSV 색상 구하기 - GetHSVColor(hue, saturation, value, alpha) /// <summary> /// HSV 색상 구하기 /// </summary> /// <param name="hue">색상</param> /// <param name="saturation">채도</param> /// <param name="value">값</param> /// <param name="alpha">알파</param> /// <returns>색상</returns> private Color GetHSVColor(double hue, double saturation, double value, double alpha) { double chroma = value * saturation; double step = Math.PI / 3; double interm = chroma * (1 - Math.Abs((hue / step) % 2.0 - 1)); double shift = value - chroma; if(hue < 1 * step) return GetRGBColor(shift + chroma, shift + interm, shift + 0 , alpha); if(hue < 2 * step) return GetRGBColor(shift + interm, shift + chroma, shift + 0 , alpha); if(hue < 3 * step) return GetRGBColor(shift + 0 , shift + chroma, shift + interm, alpha); if(hue < 4 * step) return GetRGBColor(shift + 0 , shift + interm, shift + chroma, alpha); if(hue < 5 * step) return GetRGBColor(shift + interm, shift + 0 , shift + chroma, alpha); return GetRGBColor(shift + chroma, shift + 0, shift + interm, alpha); } #endregion } |
▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : Form { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); double hue = 3.3d; double saturation = 0.4d; double value = 0.9d; ColorPicker colorPicker = new ColorPicker(400); Image colorPickerImage = colorPicker.DrawImage(hue, saturation, value); using(Graphics imageGraphics = Graphics.FromImage(colorPickerImage)) { Pen pen = value < 0.5d ? Pens.White : Pens.Black; Point2D wheelPoint = colorPicker.GetWheelPosition(hue); imageGraphics.DrawEllipse(pen, (float)wheelPoint.X - 5, (float)wheelPoint.Y - 5, 10, 10); Point2D trianglePoint = colorPicker.GetTrianglePosition(saturation, value); imageGraphics.DrawEllipse(pen, (float)trianglePoint.X - 5, (float)trianglePoint.Y - 5, 10, 10); } this.pictureBox.Image = colorPickerImage; } #endregion } } |
TestProject.zip
■ TypeConverter 클래스의 ConvertToString/ConvertFromString 메소드를 사용해 폰트 직렬화/역직렬화하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 4 5 6 7 8 9 10 11 |
using System.ComponentModel; Font sourceFont = new Font("나눔고딕코딩", 12f, FontStyle.Bold); TypeConverter converter = TypeDescriptor.GetConverter(typeof(Font)); string targetString = converter.ConvertToString(sourceFont); Font targetFont = converter.ConvertFromString(targetString) as Font; |
■ TypeDescriptor 클래스의 GetConverter 정적 메소드를 사용해 폰트 변환자를 구하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 4 5 6 7 |
using System.ComponentModel; Font sourceFont = new Font("나눔고딕코딩", 12f, FontStyle.Bold); TypeConverter converter = TypeDescriptor.GetConverter(typeof(Font)); |
■ RichEditControl 클래스에서 테이블 셀의 내용을 복사해서 붙여넣는 방법을 보여준다. ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
using System; using System.Collections.Generic; using System.Drawing; using DevExpress.XtraEditors; using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.API.Native; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : XtraForm { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 줄 문자열 /// </summary> private const string LINE_STRING = "----------------------------------------------------------------------------------------------------"; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); this.richEditControl.ActiveViewType = RichEditViewType.Simple; this.richEditControl.Options.HorizontalScrollbar.Visibility = RichEditScrollbarVisibility.Hidden; this.richEditControl.Options.VerticalScrollbar.Visibility = RichEditScrollbarVisibility.Auto; this.richEditControl.Document.DefaultCharacterProperties.FontName = "나눔고딕코딩"; this.richEditControl.Document.DefaultCharacterProperties.FontSize = 12f; this.richEditControl.Document.DefaultCharacterProperties.ForeColor = Color.Black; this.richEditControl.Document.ParagraphStyles[0].FontName = "나눔고딕코딩"; this.richEditControl.Document.ParagraphStyles[0].FontSize = 12f; this.richEditControl.Document.ParagraphStyles[0].ForeColor = Color.Black; this.richEditControl.LoadDocument("sample.rtf"); this.parseButton.Click += parseButton_Click; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private //////////////////////////////////////////////////////////////////////////////// Event #region 분석 버튼 클릭시 처리하기 - parseButton_Click(sender, e) /// <summary> /// 분석 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void parseButton_Click(object sender, EventArgs e) { Document document = this.richEditControl.Document; while(document.Tables.Count > 0) { PasteTableContent(document, document.Tables.Count - 1); document.Tables.RemoveTableAt(document.Tables.Count - 1); } } #endregion //////////////////////////////////////////////////////////////////////////////// Function #region 라인 분리자 문단 리스트 구하기 - GetLineSeparatorParagraphList(document) /// <summary> /// 라인 분리자 문단 리스트 구하기 /// </summary> /// <param name="document">문서</param> /// <returns>라인 분리자 문단 리스트</returns> private List<Paragraph> GetLineSeparatorParagraphList(Document document) { List<Paragraph> list = new List<Paragraph>(); for(int i = 0; i < document.Paragraphs.Count - 1; i++) { Paragraph paragraph1 = document.Paragraphs[i ]; Paragraph paragraph2 = document.Paragraphs[i + 1]; string text1 = document.GetText(paragraph1.Range); string text2 = document.GetText(paragraph2.Range); if(text1 == LINE_STRING && text2 == LINE_STRING) { list.Add(paragraph1); } } return list; } #endregion #region 테이블 내용 붙여넣기 - PasteTableContent(document, index) /// <summary> /// 테이블 내용 붙여넣기 /// </summary> /// <param name="document">문서</param> /// <param name="index">인덱스</param> private void PasteTableContent(Document document, int index) { List<Paragraph> list = GetLineSeparatorParagraphList(document); Table table = document.Tables[index]; DocumentRange contentRange = table.Cell(0, 0).ContentRange; DocumentRange range = document.CreateRange(contentRange.Start.ToInt() + 1, contentRange.End.ToInt() - contentRange.Start.ToInt() + 1 - 2); document.Copy(range); document.CaretPosition = document.CreatePosition(list[index].Range.End.ToInt()); document.Paste(); } #endregion } } |
TestProject.zip
■ TableCollection 인터페이스 : Create 메소드를 사용해 테이블 생성하기 ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
using System; using System.Collections.Generic; using System.Drawing; using System.Text; using DevExpress.XtraEditors; using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.API.Native; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : XtraForm { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 줄 문자열 /// </summary> private const string LINE_STRING = "------------------------------------------------------------------------------------------------------------------------"; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); this.richEditControl.ActiveViewType = RichEditViewType.Simple; this.richEditControl.Options.HorizontalScrollbar.Visibility = RichEditScrollbarVisibility.Hidden; this.richEditControl.Options.VerticalScrollbar.Visibility = RichEditScrollbarVisibility.Auto; this.richEditControl.Document.DefaultCharacterProperties.FontName = "나눔고딕코딩"; this.richEditControl.Document.DefaultCharacterProperties.FontSize = 12f; this.richEditControl.Document.DefaultCharacterProperties.ForeColor = Color.Black; this.richEditControl.Document.ParagraphStyles[0].FontName = "나눔고딕코딩"; this.richEditControl.Document.ParagraphStyles[0].FontSize = 12f; this.richEditControl.Document.ParagraphStyles[0].ForeColor = Color.Black; this.richEditControl.LoadDocument("sample.rtf"); this.parseButton.Click += parseButton_Click; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private //////////////////////////////////////////////////////////////////////////////// Event #region 분석 버튼 클릭시 처리하기 - parseButton_Click(sender, e) /// <summary> /// 분석 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void parseButton_Click(object sender, EventArgs e) { Document document = this.richEditControl.Document; StringBuilder stringBuilder = new StringBuilder(); Dictionary<Table, string> tableDictionary = new Dictionary<Table, string>(); foreach(Paragraph paragraph in document.Paragraphs) { ReadOnlyDocumentImageCollection imageCollection = document.Images.Get(paragraph.Range); if(imageCollection == null || imageCollection.Count == 0) { Table table = GetTable(paragraph.Range); if(table != null) { if(tableDictionary.ContainsKey(table)) { continue; } else { tableDictionary.Add(table, null); stringBuilder.AppendLine($"테이블 : {table.Rows.Count}×{table.Rows[0].Cells.Count}"); ParagraphCollection tableParagraphCollection = document.GetParagraphs(table.Range); foreach(Paragraph tableParagraph in tableParagraphCollection) { stringBuilder.AppendLine($" 문단 : {document.GetText(tableParagraph.Range)}"); } } } else { stringBuilder.AppendLine($"문단 : {document.GetText(paragraph.Range)}"); } } else { DocumentImage documentImage = imageCollection[0]; stringBuilder.AppendLine($"이미지 : {documentImage.Size}"); } } this.memoEdit.Text = stringBuilder.ToString(); document.BeginUpdate(); foreach(KeyValuePair<Table, string> keyValuePair in tableDictionary) { Table table = keyValuePair.Key; ParagraphCollection tableParagraphCollection = document.GetParagraphs(table.Range); Table newTable = document.Tables.Create(document.Range.End, 1, 1); for(int i = tableParagraphCollection.Count - 1; i > -1; i--) { Paragraph tableParagraph = tableParagraphCollection[i]; document.InsertText(newTable.Cell(0, 0).Range.Start, document.GetText(tableParagraph.Range) + (i < tableParagraphCollection.Count - 1 ? "\r\n" : "")); } document.InsertParagraph(document.Range.End); } document.EndUpdate(); } #endregion //////////////////////////////////////////////////////////////////////////////// Function #region 테이블 구하기 - GetTable(range) /// <summary> /// 테이블 구하기 /// </summary> /// <param name="range">문서 범위</param> /// <returns>테이블</returns> private Table GetTable(DocumentRange range) { Document document = this.richEditControl.Document; foreach(Table table in document.Tables) { if(table.Range.Contains(range.Start)) { return table; } } return null; } #endregion } } |
TestProject.zip
■ RichEditControl 클래스에서 이미지와 문단/테이블을 파싱하는 방법을 보여준다. (기능 개선) ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
using System; using System.Collections.Generic; using System.Drawing; using System.Text; using DevExpress.XtraEditors; using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.API.Native; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : XtraForm { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 줄 문자열 /// </summary> private const string LINE_STRING = "------------------------------------------------------------------------------------------------------------------------"; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); this.richEditControl.ActiveViewType = RichEditViewType.Simple; this.richEditControl.Options.HorizontalScrollbar.Visibility = RichEditScrollbarVisibility.Hidden; this.richEditControl.Options.VerticalScrollbar.Visibility = RichEditScrollbarVisibility.Auto; this.richEditControl.Document.DefaultCharacterProperties.FontName = "나눔고딕코딩"; this.richEditControl.Document.DefaultCharacterProperties.FontSize = 12f; this.richEditControl.Document.DefaultCharacterProperties.ForeColor = Color.Black; this.richEditControl.Document.ParagraphStyles[0].FontName = "나눔고딕코딩"; this.richEditControl.Document.ParagraphStyles[0].FontSize = 12f; this.richEditControl.Document.ParagraphStyles[0].ForeColor = Color.Black; this.richEditControl.LoadDocument("sample.rtf"); this.parseButton.Click += parseButton_Click; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private //////////////////////////////////////////////////////////////////////////////// Event #region 분석 버튼 클릭시 처리하기 - parseButton_Click(sender, e) /// <summary> /// 분석 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void parseButton_Click(object sender, EventArgs e) { Document document = this.richEditControl.Document; StringBuilder stringBuilder = new StringBuilder(); Dictionary<Table, string> tableDictionary = new Dictionary<Table, string>(); foreach(Paragraph paragraph in document.Paragraphs) { ReadOnlyDocumentImageCollection imageCollection = document.Images.Get(paragraph.Range); if(imageCollection == null || imageCollection.Count == 0) { Table table = GetTable(paragraph.Range); if(table != null) { if(tableDictionary.ContainsKey(table)) { continue; } else { tableDictionary.Add(table, null); stringBuilder.AppendLine($"테이블 : {table.Rows.Count}×{table.Rows[0].Cells.Count}"); ParagraphCollection tableParagraphCollection = document.GetParagraphs(table.Range); foreach(Paragraph tableParagraph in tableParagraphCollection) { stringBuilder.AppendLine($" 문단 : {document.GetText(tableParagraph.Range)}"); } } } else { stringBuilder.AppendLine($"문단 : {document.GetText(paragraph.Range)}"); } } else { DocumentImage documentImage = imageCollection[0]; stringBuilder.AppendLine($"이미지 : {documentImage.Size}"); } } this.memoEdit.Text = stringBuilder.ToString(); } #endregion //////////////////////////////////////////////////////////////////////////////// Function #region 테이블 구하기 - GetTable(range) /// <summary> /// 테이블 구하기 /// </summary> /// <param name="range">문서 범위</param> /// <returns>테이블</returns> private Table GetTable(DocumentRange range) { Document document = this.richEditControl.Document; foreach(Table table in document.Tables) { if(table.Range.Contains(range.Start)) { return table; } } return null; } #endregion } } |
TestProject.zip
■ RichEditControl 클래스에서 특정 문자열을 포함하는 문단을 볼드체로 설정하는 방법을 보여준다. ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
using System.Collections.Generic; using System.Drawing; using DevExpress.XtraEditors; using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.API.Native; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : XtraForm { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); this.richEditControl.ActiveViewType = RichEditViewType.Simple; this.richEditControl.Options.HorizontalScrollbar.Visibility = RichEditScrollbarVisibility.Hidden; this.richEditControl.Options.VerticalScrollbar.Visibility = RichEditScrollbarVisibility.Auto; this.richEditControl.Document.DefaultCharacterProperties.FontName = "나눔고딕코딩"; this.richEditControl.Document.DefaultCharacterProperties.FontSize = 12f; this.richEditControl.Document.DefaultCharacterProperties.ForeColor = Color.Black; this.richEditControl.Document.ParagraphStyles[0].FontName = "나눔고딕코딩"; this.richEditControl.Document.ParagraphStyles[0].FontSize = 12f; this.richEditControl.Document.ParagraphStyles[0].ForeColor = Color.Black; this.richEditControl.Document.InsertText(this.richEditControl.Document.Range.End, "가나다\r\n"); this.richEditControl.Document.InsertText(this.richEditControl.Document.Range.End, "라마바\r\n"); this.richEditControl.Document.InsertText(this.richEditControl.Document.Range.End, "사아자\r\n"); this.richEditControl.Document.InsertText(this.richEditControl.Document.Range.End, "차카타\r\n"); SetFontBold(this.richEditControl, new List<string> { "가", "자" }); } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 폰트 볼드체 만들기 - SetFontBold(richEditControl, sourceList) /// <summary> /// 폰트 볼드체 만들기 /// </summary> /// <param name="richEditControl">리치 에디트 컨트롤</param> /// <param name="sourceList">소스 리스트</param> private void SetFontBold(RichEditControl richEditControl, List<string> sourceList) { if(sourceList == null || sourceList.Count == 0) { return; } Document document = richEditControl.Document; for(int i = 0; i < richEditControl.Document.Paragraphs.Count; i++) { DocumentRange documentRange = richEditControl.Document.Paragraphs[i].Range; string text = richEditControl.Document.GetText(documentRange); foreach(string source in sourceList) { if(text.Contains(source)) { CharacterProperties characterProperties = document.BeginUpdateCharacters(documentRange); characterProperties.Bold = true; document.EndUpdateCharacters(characterProperties); } } } } #endregion } } |
TestProject.zip
■ DocumentVisitorBase 클래스를 사용해 커스텀 문서 방문자를 만드는 방법을 보여준다. ▶ CustomVisitor.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
using System.Text; using DevExpress.XtraRichEdit.API.Native; namespace TestProject { /// <summary> /// 커스텀 방문자 /// </summary> public class CustomVisitor : DocumentVisitorBase { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 문자열 빌더 /// </summary> private readonly StringBuilder stringBuilder; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Private #region 텍스트 - Text /// <summary> /// 텍스트 /// </summary> public string Text { get { return this.stringBuilder.ToString(); } } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - CustomVisitor() /// <summary> /// 생성자 /// </summary> public CustomVisitor() { this.stringBuilder = new StringBuilder(); } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region 방문하기 - Visit(documentText) /// <summary> /// 방문하기 /// </summary> /// <param name="documentText">문서 텍스트</param> public override void Visit(DocumentText documentText) { string prefix = (documentText.TextProperties.FontBold) ? "**" : ""; this.stringBuilder.Append(prefix); this.stringBuilder.Append(documentText.Text); this.stringBuilder.Append(prefix); } #endregion #region 방문하기 - Visit(documentParagraphEnd) /// <summary> /// 방문하기 /// </summary> /// <param name="documentParagraphEnd">문서 문단 끝</param> public override void Visit(DocumentParagraphEnd documentParagraphEnd) { this.stringBuilder.AppendLine(); } #endregion } } |
▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
using System; using System.Drawing; using DevExpress.XtraEditors; using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.API.Native; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : XtraForm { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 줄 문자열 /// </summary> private const string LINE_STRING = "------------------------------------------------------------------------------------------------------------------------"; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); this.richEditControl.ActiveViewType = RichEditViewType.Simple; this.richEditControl.Options.HorizontalScrollbar.Visibility = RichEditScrollbarVisibility.Hidden; this.richEditControl.Options.VerticalScrollbar.Visibility = RichEditScrollbarVisibility.Auto; this.richEditControl.Document.DefaultCharacterProperties.FontName = "나눔고딕코딩"; this.richEditControl.Document.DefaultCharacterProperties.FontSize = 12f; this.richEditControl.Document.DefaultCharacterProperties.ForeColor = Color.Black; this.richEditControl.Document.ParagraphStyles[0].FontName = "나눔고딕코딩"; this.richEditControl.Document.ParagraphStyles[0].FontSize = 12f; this.richEditControl.Document.ParagraphStyles[0].ForeColor = Color.Black; this.richEditControl.LoadDocument("sample.rtf"); this.parseButton.Click += parseButton_Click; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 분석 버튼 클릭시 처리하기 - parseButton_Click(sender, e) /// <summary> /// 분석 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void parseButton_Click(object sender, EventArgs e) { CustomVisitor visitor = new CustomVisitor(); DocumentIterator iterator = new DocumentIterator(this.richEditControl.Document, true); while(iterator.MoveNext()) { iterator.Current.Accept(visitor); } this.memoEdit.Text = visitor.Text; } #endregion } } |
TestProject.zip
■ RichEditControl 클래스에서 이미지와 문단/테이블을 파싱하는 방법을 보여준다. ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
using System; using System.Collections.Generic; using System.Drawing; using System.Text; using DevExpress.XtraEditors; using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.API.Native; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : XtraForm { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 줄 문자열 /// </summary> private const string LINE_STRING = "------------------------------------------------------------------------------------------------------------------------"; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); this.richEditControl.ActiveViewType = RichEditViewType.Simple; this.richEditControl.Options.HorizontalScrollbar.Visibility = RichEditScrollbarVisibility.Hidden; this.richEditControl.Options.VerticalScrollbar.Visibility = RichEditScrollbarVisibility.Auto; this.richEditControl.Document.DefaultCharacterProperties.FontName = "나눔고딕코딩"; this.richEditControl.Document.DefaultCharacterProperties.FontSize = 12f; this.richEditControl.Document.DefaultCharacterProperties.ForeColor = Color.Black; this.richEditControl.Document.ParagraphStyles[0].FontName = "나눔고딕코딩"; this.richEditControl.Document.ParagraphStyles[0].FontSize = 12f; this.richEditControl.Document.ParagraphStyles[0].ForeColor = Color.Black; this.richEditControl.LoadDocument("sample.rtf"); this.parseButton.Click += parseButton_Click; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 분석 버튼 클릭시 처리하기 - parseButton_Click(sender, e) /// <summary> /// 분석 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void parseButton_Click(object sender, EventArgs e) { Document document = this.richEditControl.Document; Dictionary<Table, List<Paragraph>> tableDictionary = new Dictionary<Table, List<Paragraph>>(); Dictionary<Paragraph, Table> paragraphDictionary = new Dictionary<Paragraph, Table>(); foreach(Table table in document.Tables) { ParagraphCollection paragraphCollection = document.GetParagraphs(table.Range); List<Paragraph> paragraphList = new List<Paragraph>(); for(int i = 0; i < paragraphCollection.Count; i++) { Paragraph paragraph = paragraphCollection[i]; paragraphList.Add(paragraph); paragraphDictionary.Add(paragraph, table); } tableDictionary.Add(table, paragraphList); } List<object> targetList = new List<object>(); Dictionary<Table, string> targetTableDictionary = new Dictionary<Table, string>(); foreach(Paragraph paragraph in document.Paragraphs) { ReadOnlyDocumentImageCollection imageCollection = document.Images.Get(paragraph.Range); if(imageCollection == null || imageCollection.Count == 0) { if(paragraphDictionary.ContainsKey(paragraph)) { Table table = paragraphDictionary[paragraph]; if(!targetTableDictionary.ContainsKey(table)) { targetTableDictionary.Add(table, null); targetList.Add(table); } } else { targetList.Add(paragraph); } } else { DocumentImage documentImage = imageCollection[0]; targetList.Add(documentImage); } } StringBuilder stringBuilder = new StringBuilder(); foreach(var item in targetList) { if(item is Paragraph paragraph) { stringBuilder.AppendLine($"문단 : {document.GetText(paragraph.Range)}"); } else if(item is DocumentImage documentImage) { stringBuilder.AppendLine($"이미지 : {documentImage.Size}"); } else if(item is Table table) { stringBuilder.AppendLine($"테이블 : {table.Rows.Count}×{table.Rows[0].Cells.Count}"); } } this.memoEdit.Text = stringBuilder.ToString(); } #endregion } } |
TestProject.zip
■ RichEditControl 클래스에서 이미지와 문단을 파싱하는 방법을 보여준다. ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
using System; using System.Drawing; using System.Text; using DevExpress.XtraEditors; using DevExpress.XtraRichEdit; using DevExpress.XtraRichEdit.API.Native; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : XtraForm { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); this.richEditControl.ActiveViewType = RichEditViewType.Simple; this.richEditControl.Options.HorizontalScrollbar.Visibility = RichEditScrollbarVisibility.Hidden; this.richEditControl.Options.VerticalScrollbar.Visibility = RichEditScrollbarVisibility.Auto; this.richEditControl.Document.DefaultCharacterProperties.FontName = "나눔고딕코딩"; this.richEditControl.Document.DefaultCharacterProperties.FontSize = 12f; this.richEditControl.Document.DefaultCharacterProperties.ForeColor = Color.Black; this.richEditControl.Document.ParagraphStyles[0].FontName = "나눔고딕코딩"; this.richEditControl.Document.ParagraphStyles[0].FontSize = 12f; this.richEditControl.Document.ParagraphStyles[0].ForeColor = Color.Black; this.richEditControl.LoadDocument("sample.rtf"); this.parseButton.Click += parseButton_Click; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 분석 버튼 클릭시 처리하기 - parseButton_Click(sender, e) /// <summary> /// 분석 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void parseButton_Click(object sender, EventArgs e) { Document document = this.richEditControl.Document; StringBuilder stringBuilder = new StringBuilder(); foreach(Paragraph paragraph in document.Paragraphs) { ReadOnlyDocumentImageCollection imageCollection = document.Images.Get(paragraph.Range); if(imageCollection == null || imageCollection.Count == 0) { stringBuilder.AppendLine($"문단 : {document.GetText(paragraph.Range)}"); } else { foreach(DocumentImage documentImage in imageCollection) { stringBuilder.AppendLine($"이미지 : {documentImage.Size}"); } } } this.memoEdit.Text = stringBuilder.ToString(); } #endregion } } |
TestProject.zip
■ SkewnessFunction 클래스를 사용해 확률 분포의 비대칭성을 측정하는 왜도를 구하는 방법을 보여준다. ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
using System; using System.Windows.Forms; using Steema.TeeChart.Functions; using Steema.TeeChart.Styles; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : Form { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); #region 영역 시리즈를 생성한다. Area area = new Area(this.tChart.Chart); area.Title = "area"; area.Smoothed = true; #endregion #region 라인 시리즈를 생성한다. Line line = new Line(this.tChart.Chart); line.Title = "line"; line.DataSource = area; line.Function = new SkewnessFunction(this.tChart.Chart); line.LinePen.Width = 4; line.VertAxis = VerticalAxis.Right; #endregion area.FillSampleValues(); line.CheckDataSource(); this.refreshButton.Click += refreshButton_Click; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 갱신하기 버튼 클릭시 처리하기 - refreshButton_Click(sender, e) /// <summary> /// 갱신하기 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void refreshButton_Click(object sender, EventArgs e) { this.tChart[0].FillSampleValues(); } #endregion } } |
TestProject.zip
■ HistogramFunction 클래스를 사용해 히스토그램 차트를 그리는 방법을 보여준다. ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
using System; using System.Drawing; using System.Windows.Forms; using Steema.TeeChart.Functions; using Steema.TeeChart.Styles; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : Form { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 라인 시리즈 /// </summary> private Line line; /// <summary> /// 히스토그램 함수 /// </summary> private HistogramFunction histogramFunction; /// <summary> /// 히스토그램 시리즈 /// </summary> private Histogram histogram; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); #region 라인 시리즈를 생성한다. this.line = new Line(); this.line.Title = "line"; this.line.Brush.Color = Color.FromArgb(255, 0, 0); this.line.LinePen.Color = Color.FromArgb(255, 0, 0); #endregion #region 히스토그램 함수를 생성한다. this.histogramFunction = new HistogramFunction(); this.histogramFunction.Cumulative = false; #endregion #region 히스토그램을 생성한다. this.histogram = new Histogram(); this.histogram.Title = "histogram"; this.histogram.Brush.Color = Color.FromArgb(255, 0, 0); this.histogram.DataSource = this.line; this.histogram.Function = this.histogramFunction; #endregion #region 티차트 1을 설정한다. this.tChart1.Axes.Bottom.Grid.Color = Color.FromArgb(128, 128, 128); this.tChart1.Legend.Visible = false; this.tChart1.Series.Add(this.line); #endregion #region 티차트 2를 설정한다. this.tChart2.Axes.Bottom.AxisPen.Visible = false; this.tChart2.Axes.Bottom.Grid.Color = Color.FromArgb(128, 128, 128); this.tChart2.Legend.Visible = false; this.tChart2.Series.Add(this.histogram); #endregion this.line.FillSampleValues(500); this.histogram.CheckDataSource(); this.binCountNumericUpDown.ValueChanged += binCountNumericUpDown_ValueChanged; this.cumulativeHistogramCheckBox.CheckedChanged += cumulativeHistogramCheckBox_CheckedChanged; this.refreshButton.Click += refreshButton_Click; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region BIN 수 숫자 UP/DOWN 값 변경시 처리하기 - binCountNumericUpDown_ValueChanged(sender, e) /// <summary> /// BIN 수 숫자 UP/DOWN 값 변경시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void binCountNumericUpDown_ValueChanged(object sender, EventArgs e) { this.histogramFunction.NumBins = (int)this.binCountNumericUpDown.Value; this.histogramFunction.Recalculate(); } #endregion #region 누적 히스토그램 체크 박스 체크 변경시 처리하기 - cumulativeHistogramCheckBox_CheckedChanged(sender, e) /// <summary> /// 누적 히스토그램 체크 박스 체크 변경시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void cumulativeHistogramCheckBox_CheckedChanged(object sender, EventArgs e) { this.histogramFunction.Cumulative = this.cumulativeHistogramCheckBox.Checked; if(this.histogramFunction.Cumulative) { this.tChart2.Header.Text = "Cumulative Histogram"; } else { tChart2.Header.Text = "Histogram"; } this.histogramFunction.Recalculate(); } #endregion #region 갱신하기 버튼 클릭시 처리하기 - refreshButton_Click(sender, e) /// <summary> /// 갱신하기 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void refreshButton_Click(object sender, EventArgs e) { this.line.FillSampleValues(500); this.histogramFunction.Recalculate(); } #endregion } } |
TestProject.zip
■ ColorLine 클래스를 사용해 SPC 품질 관리 시리즈의 상한 및 하한을 그리는 방법을 보여준다. ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
using System; using System.Drawing; using System.Windows.Forms; using Steema.TeeChart.Styles; using Steema.TeeChart.Tools; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : Form { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 라인 1 시리즈 /// </summary> private Line line1; /// <summary> /// 라인 2 시리즈 /// </summary> private Line line2; /// <summary> /// 색상 라인 1 도구 /// </summary> private ColorLine colorLine1; /// <summary> /// 색상 라인 2 도구 /// </summary> private ColorLine colorLine2; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); #region 라인 1 시리즈를 생성한다. this.line1 = new Line(); this.line1.Title = "Good"; this.line1.Color = Color.Blue; this.line1.Pointer.Visible = true; #endregion #region 라인 2 시리즈를 생성한다. this.line2 = new Line(); this.line2.Title = "Bad"; this.line2.Color = Color.Red; this.line2.Pointer.Visible = true; this.line2.VertAxis = VerticalAxis.Right; #endregion #region 색상 라인 1 도구를 생성한다. this.colorLine1 = new ColorLine(); this.colorLine1.Pen.Width = 2; this.colorLine1.Pen.Color = Color.Red; this.colorLine1.Axis = this.tChart.Axes.Right; #endregion #region 색상 라인 2 도구를 생성한다. this.colorLine2 = new ColorLine(); this.colorLine2.Pen.Width = 2; this.colorLine2.Pen.Color = Color.Blue; this.colorLine2.Axis = this.tChart.Axes.Right; #endregion #region 티차트를 설정한다. this.tChart.Axes.Left.Title.Caption = "Production (number of pieces)"; this.tChart.Axes.Left.Automatic = false; this.tChart.Axes.Left.AutomaticMaximum = false; this.tChart.Axes.Left.AutomaticMinimum = false; this.tChart.Axes.Left.Minimum = 0d; this.tChart.Axes.Left.Maximum = 1200d; this.tChart.Axes.Right.Title.Caption = "SPC (%)"; this.tChart.Axes.Right.Automatic = false; this.tChart.Axes.Right.AutomaticMaximum = false; this.tChart.Axes.Right.AutomaticMinimum = false; this.tChart.Axes.Right.Maximum = 10d; this.tChart.Axes.Right.Minimum = 0d; this.tChart.Axes.Bottom.Grid.Color = Color.FromArgb(130, 130, 130); this.tChart.Axes.Bottom.Grid.Visible = true; this.tChart.Tools.Add(this.colorLine1); this.tChart.Tools.Add(this.colorLine2); this.tChart.Series.Add(this.line1); this.tChart.Series.Add(this.line2); #endregion Random random = new Random(DateTime.Now.Millisecond); for(int i = 1 ; i < 19; i++) { this.line1.Add(800 + random.Next(200)); this.line2.Add(4 + random.Next(4 )); } CalculateLimits(this.line1, this.line2); this.upperLimitTextBox.Text = this.colorLine1.Value.ToString(); this.lowerLimitTextBox.Text = this.colorLine2.Value.ToString(); this.colorLine1.DragLine += colorLine1_DragLine; this.colorLine2.DragLine += colorLine2_DragLine; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private //////////////////////////////////////////////////////////////////////////////// Event #region 색상 라인 1 도구 라인 드래그시 처리하기 - colorLine1_DragLine(sender, e) /// <summary> /// 색상 라인 1 도구 라인 드래그시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void colorLine1_DragLine(object sender, EventArgs e) { this.upperLimitTextBox.Text = this.colorLine1.Value.ToString("#.00"); } #endregion #region 색상 라인 2 도구 라인 드래그시 처리하기 - colorLine2_DragLine(sender, e) /// <summary> /// 색상 라인 2 도구 라인 드래그시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void colorLine2_DragLine(object sender, EventArgs e) { this.lowerLimitTextBox.Text = this.colorLine2.Value.ToString("#.00"); } #endregion //////////////////////////////////////////////////////////////////////////////// Function #region 제한 계산하기 - CalculateLimits(goodSeries, badSeries) /// <summary> /// 제한 계산하기 /// </summary> /// <param name="goodSeries">양품 시리즈</param> /// <param name="badSeries">불량 시리즈</param> private void CalculateLimits(Series goodSeries, Series badSeries) { double sum1 = 0d; double sum2 = 0d; double temporaryValue1; double temporaryValue2; double lcp; // Likelihood of Correct Prediction double lcn; // Likelihood of Correct Non-prediction double temporaryValue3; double percent; int n = 0; this.colorLine1.Value = 0.0; this.colorLine2.Value = 0.0; for(int i = 0; i < goodSeries.Count; i++) { percent = badSeries.YValues[i] * goodSeries.YValues[i] / 100.0; temporaryValue3 = goodSeries.YValues[i] + percent; if(temporaryValue3 > 0) { sum1 += percent / temporaryValue3; sum2 += temporaryValue3; n++; } } lcp = sum1 / n; lcn = sum2 / n; temporaryValue1 = (lcp * (1.0 - lcp)) / lcn; if(temporaryValue1 > 0) { temporaryValue2 = 3 * Math.Sqrt(temporaryValue1); this.colorLine1.Value = 100.0 * (lcp + temporaryValue2); this.colorLine2.Value = 100.0 * (lcp - temporaryValue2); } } #endregion } } |
TestProject.zip
■ VarianceFunction 클래스를 사용해 분산(Variance)을 구하는 방법을 보여준다. ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
using System; using System.Drawing; using System.Windows.Forms; using Steema.TeeChart.Functions; using Steema.TeeChart.Styles; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : Form { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 포인트 시리즈 /// </summary> private Points points; /// <summary> /// 분산 함수 /// </summary> private VarianceFunction varianceFunction; /// <summary> /// 라인 시리즈 /// </summary> private Line line; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); #region 포인트 시리즈를 생성한다. this.points = new Points(); this.points.Title = "Data"; this.points.Color = Color.FromArgb(130, 155, 254); this.points.Pointer.Brush.Color = Color.FromArgb(130, 155, 254); #endregion #region 분산 함수를 생성한다. this.varianceFunction = new VarianceFunction(); #endregion #region 라인 시리즈를 생성한다. this.line = new Line(); this.line.Title = "Variance"; this.line.Brush.Color = Color.FromArgb(252, 209, 36); this.line.Color = Color.FromArgb(252, 209, 36); this.line.DataSource = this.points; this.line.Function = this.varianceFunction; this.line.VertAxis = VerticalAxis.Right; #endregion #region 티차트를 설정한다. this.tChart.Axes.Bottom.Grid.Color = Color.FromArgb(130, 130, 130); this.tChart.Axes.Bottom.Grid.Visible = true; this.tChart.Axes.Bottom.MaximumOffset = 5; this.tChart.Axes.Bottom.MinimumOffset = 5; this.tChart.Legend.Visible = false; this.tChart.Series.Add(this.points); this.tChart.Series.Add(this.line); #endregion this.points.FillSampleValues(); this.refreshButton.Click += refreshButton_Click; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 갱신하기 버튼 클릭시 처리하기 - refreshButton_Click(sender, e) /// <summary> /// 갱신하기 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void refreshButton_Click(object sender, EventArgs e) { this.points.FillSampleValues(); } #endregion } } |
TestProject.zip
■ TrendFunction 클래스를 사용해 트렌드 차트를 그리는 방법을 보여준다. ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
using System; using System.Drawing; using System.Windows.Forms; using Steema.TeeChart.Functions; using Steema.TeeChart.Styles; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : Form { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 영역 시리즈 /// </summary> private Area area; /// <summary> /// 트렌드 함수 /// </summary> private TrendFunction trendFunction; /// <summary> /// 라인 시리즈 /// </summary> private Line line; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); #region 영역 시리즈를 생성한다. this.area = new Area(); this.area.Title = "Data"; this.area.Color = Color.FromArgb(68, 102, 163); this.area.AreaBrush.Color = Color.FromArgb(68, 102, 163); this.area.AreaLines.Color = Color.FromArgb(41, 61 , 98 ); #endregion #region 트렌드 함수를 생성한다. this.trendFunction = new TrendFunction(); #endregion #region 라인 시리즈를 생성한다. this.line = new Line(); this.line.Brush.Color = Color.FromArgb(243, 156, 53); this.line.Color = Color.FromArgb(243, 156, 53); this.line.DataSource = this.area; this.line.Function = this.trendFunction; #endregion #region 티차트를 설정한다. this.tChart.Series.Add(this.area); this.tChart.Series.Add(this.line); #endregion this.area.FillSampleValues(); for(int i = 0; i < this.area.Count; i++) { this.area.XValues[i] += 1; } this.trendFunction.Recalculate(); Load += Form_Load; this.refreshButton.Click += refreshButton_Click; this.trendStyleComboBox.SelectedIndexChanged += trendStyleComboBox_SelectedIndexChanged; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 폼 로드시 처리하기 - Form_Load(sender, e) /// <summary> /// 폼 로드시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void Form_Load(object sender, EventArgs e) { this.trendStyleComboBox.SelectedIndex = 0; } #endregion #region 갱신하기 버튼 클릭시 처리하기 - refreshButton_Click(sender, e) /// <summary> /// 갱신하기 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void refreshButton_Click(object sender, EventArgs e) { this.area.FillSampleValues(); for(int i = 0; i < this.area.Count; i++) { this.area.XValues[i] += 1; } this.trendFunction.Recalculate(); } #endregion #region 트렌드 스타일 선택 인덱스 변경시 처리하기 - trendStyleComboBox_SelectedIndexChanged(sender, e) /// <summary> /// 트렌드 스타일 선택 인덱스 변경시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void trendStyleComboBox_SelectedIndexChanged(object sender, EventArgs e) { switch(this.trendStyleComboBox.SelectedIndex) { case 0 : this.trendFunction.Series.Title = "Trendline"; this.trendFunction.TrendStyle = TrendStyles.Normal; break; case 1 : this.trendFunction.Series.Title = "Exp.trendline"; this.trendFunction.TrendStyle = TrendStyles.Exponential; break; case 2 : this.trendFunction.Series.Title = "Log.trendline"; this.trendFunction.TrendStyle = TrendStyles.Logarithmic; break; } } #endregion } } |
TestProject.zip
■ StdDeviation 클래스를 사용해 표준 편차(Standard Deviation)를 구하는 방법을 보여준다. ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
using System; using System.Drawing; using System.Windows.Forms; using Steema.TeeChart.Functions; using Steema.TeeChart.Styles; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : Form { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 라인 1 시리즈 /// </summary> private Line line1; /// <summary> /// 표준 편차 함수 /// </summary> private StdDeviation stdDeviation; /// <summary> /// 라인 2 시리즈 /// </summary> private Line line2; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); #region 라인 1 시리즈를 생성한다. this.line1 = new Line(); this.line1.Title = "Source"; this.line1.Brush.Color = Color.FromArgb(200, 230, 90); this.line1.Color = Color.FromArgb(200, 230, 90); #endregion #region 표준 편차 함수를 생성한다. this.stdDeviation = new StdDeviation(); #endregion #region 라인 2 시리즈를 생성한다. this.line2 = new Line(); this.line2.Title = "Std. dev."; this.line2.Brush.Color = Color.FromArgb(90, 150, 220); this.line2.Color = Color.FromArgb(90, 150, 220); this.line2.Pointer.Visible = true; this.line2.DataSource = this.line1; this.line2.Function = this.stdDeviation; this.line2.VertAxis = VerticalAxis.Right; #endregion #region 티차트를 설정한다. this.tChart.Series.Add(this.line1); this.tChart.Series.Add(this.line2); #endregion this.line1.FillSampleValues(30); Load += Form_Load; this.styleComboBox.SelectedIndexChanged += styleComboBox_SelectedIndexChanged; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 폼 로드시 처리하기 - Form_Load(sender, e) /// <summary> /// 폼 로드시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void Form_Load(object sender, EventArgs e) { this.styleComboBox.SelectedIndex = 0; } #endregion #region 스타일 콤보 박스 선택 인덱스 변경시 처리하기 - styleComboBox_SelectedIndexChanged(sender, e) /// <summary> /// 스타일 콤보 박스 선택 인덱스 변경시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void styleComboBox_SelectedIndexChanged(object sender, EventArgs e) { this.stdDeviation.Complete = (this.styleComboBox.SelectedIndex == 1); } #endregion } } |
TestProject.zip
■ Smoothing 클래스에서 B-Spline 알고리즘을 사용해 포인트를 보간하는 방법을 보여준다. ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
using System; using System.Drawing; using System.Windows.Forms; using Steema.TeeChart.Functions; using Steema.TeeChart.Styles; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : Form { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 라인 1 시리즈 /// </summary> private Line line1; /// <summary> /// 스무딩 함수 /// </summary> private Smoothing smoothing; /// <summary> /// 라인 2 시리즈 /// </summary> private Line line2; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); #region 라인 1 시리즈를 생성한다. this.line1 = new Line(); this.line1.Title = "line1"; this.line1.Brush.Color = Color.FromArgb(200, 230, 90 ); this.line1.Color = Color.FromArgb(200, 230, 90 ); this.line1.Pointer.Brush.Color = Color.FromArgb(255, 255, 255); this.line1.Pointer.Brush.Solid = true; this.line1.Pointer.Brush.Visible = true; this.line1.Pointer.HorizSize = 3; this.line1.Pointer.VertSize = 3; this.line1.Pointer.Style = PointerStyles.Triangle; this.line1.Pointer.Pen.Color = Color.FromArgb(255, 255, 0); this.line1.Pointer.Visible = true; #endregion #region 스무딩 함수를 생성한다. this.smoothing = new Smoothing(); this.smoothing.Interpolate = false; this.smoothing.Period = 1d; #endregion #region 라인 2 시리즈를 생성한다. this.line2 = new Line(); this.line2.Title = "line2"; this.line2.Brush.Color = Color.FromArgb(90, 150, 220); this.line2.Color = Color.FromArgb(90, 150, 220); this.line2.DataSource = this.line1; this.line2.Function = this.smoothing; #endregion #region 티차트를 설정한다. this.tChart.Series.Add(this.line1); this.tChart.Series.Add(this.line2); #endregion #region 라인 1 시리즈를 설정한다. this.line1.Clear(); this.line1.Add(new int[] { 4, 9, 5, 7, 2, 12, 15 }); this.line1.RefreshSeries(); #endregion this.showSourcePointerCheckBox.CheckedChanged += showSourcePointerCheckBox_CheckedChanged; this.showSourceCheckBox.CheckedChanged += showSourceCheckBox_CheckedChanged; this.interpolationCheckBox.CheckedChanged += interpolationCheckBox_CheckedChanged; this.factorNumericUpDown.ValueChanged += factorNumericUpDown_ValueChanged; this.refreshButton.Click += refreshButton_Click; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 소스 포인터 표시 체크 박스 체크 변경시 처리하기 - showSourcePointerCheckBox_CheckedChanged(sender, e) /// <summary> /// 소스 포인터 표시 체크 박스 체크 변경시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void showSourcePointerCheckBox_CheckedChanged(object sender, EventArgs e) { this.line1.Pointer.Visible = this.showSourcePointerCheckBox.Checked; } #endregion #region 소스 표시 체크 박스 체크 변경시 처리하기 - showSourceCheckBox_CheckedChanged(sender, e) /// <summary> /// 소스 표시 체크 박스 체크 변경시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void showSourceCheckBox_CheckedChanged(object sender, EventArgs e) { this.line1.Visible = this.showSourceCheckBox.Checked; } #endregion #region 보전 체크 박스 체크 변경시 처리하기 - interpolationCheckBox_CheckedChanged(sender, e) /// <summary> /// 보전 체크 박스 체크 변경시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void interpolationCheckBox_CheckedChanged(object sender, EventArgs e) { this.smoothing.Interpolate = this.interpolationCheckBox.Checked; } #endregion #region 팩터 숫자 UP/DOWN 값 변경시 처리하기 - factorNumericUpDown_ValueChanged(sender, e) /// <summary> /// 팩터 숫자 UP/DOWN 값 변경시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void factorNumericUpDown_ValueChanged(object sender, EventArgs e) { this.smoothing.Factor = (int)this.factorNumericUpDown.Value; } #endregion #region 갱신하기 버튼 클릭시 처리하기 - refreshButton_Click(sender, e) /// <summary> /// 갱신하기 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void refreshButton_Click(object sender, EventArgs e) { this.line1.FillSampleValues(10); } #endregion } } |
TestProject.zip
■ RootMeanSquare 클래스를 사용해 제곱 평균 제곱근(RMS, Root Mean Square)을 구하는 방법을 보여준다. ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
using System; using System.Drawing; using System.Windows.Forms; using Steema.TeeChart.Functions; using Steema.TeeChart.Styles; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : Form { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 라인 1 시리즈 /// </summary> private Line line1; /// <summary> /// 제곱 평균 제곱근 함수 /// </summary> private RootMeanSquare rootMeanSquare; /// <summary> /// 라인 2 시리즈 /// </summary> private Line line2; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); #region 라인 1 시리즈를 생성한다. this.line1 = new Line(); this.line1.Title = "Data"; this.line1.Color = Color.FromArgb(68, 102, 163); #endregion #region 제곱 평균 제곱근 함수를 생성한다. this.rootMeanSquare = new RootMeanSquare(); #endregion #region 라인 2 시리즈를 생성한다. this.line2 = new Line(); this.line2.Title = "RMS"; this.line2.Color = Color.FromArgb(243, 156, 53); this.line2.Pointer.Brush.Color = Color.FromArgb(255, 255, 255); this.line2.Pointer.Brush.Visible = true; this.line2.Pointer.Visible = true; this.line2.DataSource = this.line1; this.line2.Function = this.rootMeanSquare; #endregion #region 티차트를 설정한다. this.tChart.Series.Add(this.line1); this.tChart.Series.Add(this.line2); #endregion this.line1.FillSampleValues(30); Load += Form_Load; this.styleComboBox.SelectedIndexChanged += styleComboBox_SelectedIndexChanged; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 폼 로드시 처리하기 - Form_Load(sender, e) /// <summary> /// 폼 로드시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void Form_Load(object sender, EventArgs e) { this.styleComboBox.SelectedIndex = 0; } #endregion #region 스타일 콤보 박스 선택 인덱스 변경시 처리하기 - styleComboBox_SelectedIndexChanged(sender, e) /// <summary> /// 스타일 콤보 박스 선택 인덱스 변경시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void styleComboBox_SelectedIndexChanged(object sender, EventArgs e) { this.rootMeanSquare.Complete = (this.styleComboBox.SelectedIndex == 1); this.rmsValueLabel.Text = this.line2.YValues[0].ToString("0.00"); } #endregion } } |
TestProject.zip
■ DownSampling 클래스를 사용해 다운 샘플링 차트를 그리는 방법을 보여준다. ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
using System; using System.Windows.Forms; using Steema.TeeChart; using Steema.TeeChart.Functions; using Steema.TeeChart.Styles; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : Form { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 포인트 시리즈 /// </summary> private Points points; /// <summary> /// 다운 샘플링 함수 /// </summary> private DownSampling downSampling; /// <summary> /// 패스트 라인 시리즈 /// </summary> private FastLine fastLine; /// <summary> /// X 배열 /// </summary> private Nullable<double>[] xArray; /// <summary> /// Y 배열 /// </summary> private Nullable<double>[] yArray; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); #region 다운 샘플링 메소드 콤보 박스를 설정한다. this.downSamplingMethodComboBox.Items.AddRange(Enum.GetNames(typeof(DownSamplingMethod))); this.downSamplingMethodComboBox.SelectedIndex = 4; #endregion #region X/Y 배열을 설정한다. int length = 20000; xArray = new Nullable<double>[length]; yArray = new Nullable<double>[length]; Random random = new Random(DateTime.Now.Millisecond); for(int i = 0; i < length; i++) { xArray[i] = i; if(i % 20 == 0) { yArray[i] = null; } else { yArray[i] = random.Next(100); } } #endregion #region 포인트 시리즈를 생성한다. this.points = new Points(); this.points.Add(this.xArray, this.yArray); this.points.Active = false; #endregion #region 다운 샘플링 함수를 생성한다. this.downSampling = new DownSampling(); this.downSampling.DisplayedPointCount = 1000; this.downSampling.Method = DownSamplingMethod.MinMaxFirstLastNull; #endregion #region 패스트 라인 시리즈를 생성한다. this.fastLine = new FastLine(); this.fastLine.DataSource = points; this.fastLine.Function = downSampling; this.fastLine.TreatNulls = TreatNullsStyle.DoNotPaint; #endregion #region 티차트를 설정한다. this.tChart.Zoom.Direction = ZoomDirections.Horizontal; this.tChart.Series.Add(points); this.tChart.Series.Add(fastLine); #endregion this.pointCountNumericUpDown.ValueChanged += pointCountNumericUpDown_ValueChanged; this.downSamplingMethodComboBox.SelectedIndexChanged += downSamplingMethodComboBox_SelectedIndexChanged; this.tChart.Zoomed += tChart_Zoomed; this.tChart.UndoneZoom += tChart_UndoneZoom; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 포인트 수 숫자 UP/DOWN 값 변경시 처리하기 - pointCountNumericUpDown_ValueChanged(sender, e) /// <summary> /// 포인트 수 숫자 UP/DOWN 값 변경시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void pointCountNumericUpDown_ValueChanged(object sender, EventArgs e) { this.downSampling.DisplayedPointCount = (int)this.pointCountNumericUpDown.Value; this.tChart.Axes.Bottom.SetMinMax(0, this.tChart[0].Count); this.tChart[1].CheckDataSource(); } #endregion #region 다운 샘플링 메소드 콤보 박스 선택 인덱스 변경시 처리하기 - downSamplingMethodComboBox_SelectedIndexChanged(sender, e) /// <summary> /// 다운 샘플링 메소드 콤보 박스 선택 인덱스 변경시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void downSamplingMethodComboBox_SelectedIndexChanged(object sender, EventArgs e) { this.downSampling.Method = (DownSamplingMethod)Enum.Parse(typeof(DownSamplingMethod), this.downSamplingMethodComboBox.SelectedItem.ToString()); this.tChart[1].CheckDataSource(); } #endregion #region 티차트 확대시 처리하기 - tChart_Zoomed(sender, e) /// <summary> /// 티차트 확대시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void tChart_Zoomed(object sender, EventArgs e) { this.tChart[1].CheckDataSource(); } #endregion #region 티차트 확대 취소시 처리하기 - tChart_UndoneZoom(sender, e) /// <summary> /// 티차트 확대 취소시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void tChart_UndoneZoom(object sender, EventArgs e) { this.tChart.Axes.Bottom.SetMinMax(0, this.tChart[0].Count); this.tChart[1].CheckDataSource(); } #endregion } } |
TestProject.zip
■ PolyFitting 클래스의 Coefficient 메소드를 사용해 다항식 계수를 구하는 방법을 보여준다. ▶ MainForm.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
using System; using System.Drawing; using System.Text; using System.Windows.Forms; using Steema.TeeChart.Drawing; using Steema.TeeChart.Functions; using Steema.TeeChart.Styles; using Steema.TeeChart.Tools; namespace TestProject { /// <summary> /// 메인 폼 /// </summary> public partial class MainForm : Form { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 패스트 라인 1 시리즈 /// </summary> private FastLine fastLine1; /// <summary> /// 다항식 맞춤 함수 /// </summary> private PolyFitting polyFitting; /// <summary> /// 패스트 라인 2 시리즈 /// </summary> private FastLine fastLine2; /// <summary> /// 커서 도구 /// </summary> private CursorTool cursorTool; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainForm() /// <summary> /// 생성자 /// </summary> public MainForm() { InitializeComponent(); #region 패스트 라인 1 시리즈를 생성한다. this.fastLine1 = new FastLine(); this.fastLine1.Title = "Data"; this.fastLine1.Color = Color.FromArgb(68, 102, 163); #endregion #region 다항식 맞춤 함수를 생성한다. this.polyFitting = new PolyFitting(); this.polyFitting.PolyDegree = 4; #endregion #region 패스트 라인 2 시리즈를 생성한다. this.fastLine2 = new FastLine(); this.fastLine2.Title = "Poly"; this.fastLine2.Color = Color.FromArgb(243, 156, 53); this.fastLine2.DataSource = this.fastLine1; this.fastLine2.Function = this.polyFitting; #endregion #region 커서 도구를 생성한다. this.cursorTool = new CursorTool(); #endregion #region 티차트를 설정한다. this.tChart.Tools.Add(this.cursorTool); this.tChart.Series.Add(this.fastLine1); this.tChart.Series.Add(this.fastLine2); #endregion Load += Form_Load; this.tChart.MouseMove += tChart_MouseMove; this.tChart.AfterDraw += tChart_AfterDraw; this.fastLine1.FillSampleValues(100); } #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) { ShowFunction(); } #endregion #region 티차트 마우스 이동시 처리하기 - tChart_MouseMove(sender, e) /// <summary> /// 티차트 마우스 이동시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void tChart_MouseMove(object sender, MouseEventArgs e) { double x = this.fastLine2.GetHorizAxis.CalcPosPoint(e.X); double y = this.polyFitting.GetCurveYValue(this.fastLine1, x); this.cursorTool.XValue = x; this.cursorTool.YValue = y; } #endregion #region 티차트 그리기 후 처리하기 - tChart_AfterDraw(sender, graphics) /// <summary> /// 티차트 그리기 후 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="graphics">그래픽스 3D</param> private void tChart_AfterDraw(object sender, Graphics3D graphics) { if(this.cursorTool.XValue > this.tChart.Axes.Bottom.Minimum && this.cursorTool.XValue < this.tChart.Axes.Bottom.Maximum) { graphics.Brush.Color = Color.Red; graphics.Brush.Visible = true; int x = this.cursorTool.GetHorizAxis.CalcPosValue(this.cursorTool.XValue); int y = this.cursorTool.GetVertAxis.CalcPosValue (this.cursorTool.YValue); graphics.Rectangle(x - 5, y + 5, x + 5, y - 5); } } #endregion //////////////////////////////////////////////////////////////////////////////// Function #region 함수 표시하기 - ShowFunction() /// <summary> /// 함수 표시하기 /// </summary> private void ShowFunction() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("y ="); for(int i = 0; i < this.polyFitting.PolyDegree; i++) { stringBuilder.Append(" "); if(this.polyFitting.Coefficient(i) >= 0.0) { if(i > 0) { stringBuilder.Append("+ "); } } stringBuilder.Append(this.polyFitting.Coefficient(i).ToString("0.00##")); if(i > 0) { stringBuilder.Append("*x"); } if(i > 1) { stringBuilder.Append("^" + i.ToString()); } } this.messageLabel.Text = "Function : " + stringBuilder.ToString().Replace("-", "- ").Replace("*", " * ").Replace("^", " ^ "); } #endregion } } |
TestProject.zip