첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

■ 스케일 정규 분포 곡선(Normal Distribution Curve) 그리기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip


MainForm.cs

 

 

using System;

using System.Collections.Generic;

using System.Drawing;

using System.Drawing.Drawing2D;

using System.Drawing.Text;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 메인 폼

    /// </summary>

    public partial class MainForm : Form

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            #region 이벤트를 설정한다.

 

            this.drawButton.Click += drawButton_Click;

 

            #endregion

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 그리기 버튼 클릭시 처리하기 - drawButton_Click(sender, e)

 

        /// <summary>

        /// 그리기 버튼 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void drawButton_Click(object sender, EventArgs e)

        {

            float mean              = float.Parse(this.meanTextBox.Text);

            float standardDeviation = float.Parse(this.standardDeviationTextBox.Text);

            float variance          = standardDeviation * standardDeviation;

            float deviationCount    = float.Parse(this.deviationCountTextBox.Text);

 

            this.canvasPictureBox.Image = GetNormalDistributionCurveImage

            (

                deviationCount,

                this.canvasPictureBox.ClientSize.Width,

                this.canvasPictureBox.ClientSize.Height,

                mean,

                standardDeviation,

                variance

            );

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////// Function

 

        #region Y 좌표 구하기 - GetY(x, oneOver2PI, mean, standardDeviation, veriance)

 

        /// <summary>

        /// Y 좌표 구하기

        /// </summary>

        /// <param name="x">X 좌표</param>

        /// <param name="oneOver2PI">ONT OVER 2 PI</param>

        /// <param name="mean">평균</param>

        /// <param name="standardDeviation">표준 편차</param>

        /// <param name="veriance">분산</param>

        /// <returns>Y 좌표</returns>

        private float GetY(float x, float oneOver2PI, float mean, float standardDeviation, float veriance)

        {

            return (float)(oneOver2PI * Math.Exp(-(x - mean) * (x - mean) / (2 * veriance)));

        }

 

        #endregion

        #region 정규 분포 곡선 이미지 구하기 - GetNormalDistributionCurveImage(deviationCount, width, height, mean, standardDeviation, variance)

 

        /// <summary>

        /// 정규 분포 곡선 이미지 구하기

        /// </summary>

        /// <param name="deviationCount">편차 수</param>

        /// <param name="width">너비</param>

        /// <param name="height">높이</param>

        /// <param name="mean">평균</param>

        /// <param name="standardDeviation">표준 편차</param>

        /// <param name="variance">분산</param>

        /// <returns>정규 분포 곡선 이미지</returns>

        private Bitmap GetNormalDistributionCurveImage(float deviationCount, int width, int height, float mean, float standardDeviation,

            float variance)

        {

            Bitmap bitmap = new Bitmap(width, height);

 

            using(Graphics graphics = Graphics.FromImage(bitmap))

            {

                graphics.SmoothingMode = SmoothingMode.AntiAlias;

 

                float minimumWorldX = mean - standardDeviation * deviationCount;

                float maximumWorldX = mean + standardDeviation * deviationCount;

                float oneOver2PI    = (float)(1.0 / (standardDeviation * Math.Sqrt(2 * Math.PI)));

                float maximumWorldY = GetY(mean, oneOver2PI, mean, deviationCount, variance) * 1.1f;

                float minimumWorldY = -0.2f * maximumWorldY;

 

                float worldWidth  = maximumWorldX - minimumWorldX;

                float worldHeight = maximumWorldY - minimumWorldY;

 

                RectangleF worldRectangle = new RectangleF(minimumWorldX, minimumWorldY, worldWidth, worldHeight);

 

                PointF[] devicepointArray =

                {

                    new PointF(0, height),

                    new PointF(width, height),

                    new PointF(0, 0),

                };

 

                Matrix transformMatrix = new Matrix(worldRectangle, devicepointArray);

 

                Matrix inverseMatrix = transformMatrix.Clone();

 

                inverseMatrix.Invert();

 

                PointF[] tickPointArray = { new PointF(5, 5) };

 

                inverseMatrix.TransformVectors(tickPointArray);

 

                float tickDeltaX =  tickPointArray[0].X;

                float tickDeltaY = -tickPointArray[0].Y;

 

                using(Pen pen = new Pen(Color.Red, 0))

                {

                    using(Font font = new Font("Arial", 8))

                    {

                        graphics.Transform = transformMatrix;

 

                        pen.Color = Color.Black;

 

                        graphics.DrawLine(pen, minimumWorldX, 0, maximumWorldX, 0);

 

                        for(int x = (int)minimumWorldX - 1; x <= maximumWorldX; x++)

                        {

                            graphics.DrawLine(pen, x        , -tickDeltaY * 2, x        , tickDeltaY * 2);

                            graphics.DrawLine(pen, x + 0.25f, -tickDeltaY    , x + 0.25f, tickDeltaY    );

                            graphics.DrawLine(pen, x + 0.50f, -tickDeltaY    , x + 0.50f, tickDeltaY    );

                            graphics.DrawLine(pen, x + 0.75f, -tickDeltaY    , x + 0.75f, tickDeltaY    );

                        }

 

                        graphics.Transform = new Matrix();

 

                        graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;

 

                        List<PointF> pointList1 = new List<PointF>();

 

                        for(int x = (int)minimumWorldX; x <= maximumWorldX; x++)

                        {

                            pointList1.Add(new PointF(x, -2 * tickDeltaY));

                        }

 

                        PointF[] pointArray = pointList1.ToArray();

 

                        transformMatrix.TransformPoints(pointArray);

 

                        using(StringFormat stringFormat = new StringFormat())

                        {

                            stringFormat.Alignment     = StringAlignment.Center;

                            stringFormat.LineAlignment = StringAlignment.Near;

 

                            int index = 0;

 

                            for(int x = (int)minimumWorldX; x <= maximumWorldX; x++)

                            {

                                graphics.DrawString

                                (

                                    x.ToString(),

                                    font,

                                    Brushes.Black,

                                    pointArray[index++],

                                    stringFormat

                                );

                            }

                        }

 

                        graphics.Transform = transformMatrix;

 

                        pen.Color = Color.Black;

 

                        graphics.DrawLine(pen, 0, minimumWorldY, 0, maximumWorldY);

 

                        for(int y = (int)minimumWorldY - 1; y <= maximumWorldY; y++)

                        {

                            graphics.DrawLine(pen, -tickDeltaX * 2, y        , tickDeltaX * 2, y        );

                            graphics.DrawLine(pen, -tickDeltaX    , y + 0.25f, tickDeltaX    , y + 0.25f);

                            graphics.DrawLine(pen, -tickDeltaX    , y + 0.50f, tickDeltaX    , y + 0.50f);

                            graphics.DrawLine(pen, -tickDeltaX    , y + 0.75f, tickDeltaX    , y + 0.75f);

                        }

 

                        graphics.Transform = new Matrix();

 

                        graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;

 

                        List<PointF> pointList2 = new List<PointF>();

 

                        for(float y = 0.25f; y < maximumWorldY; y += 0.25f)

                        {

                            pointList2.Add(new PointF(2 * tickDeltaX, y));

                        }

 

                        if(pointList2.Count > 0)

                        {

                            pointArray = pointList2.ToArray();

 

                            transformMatrix.TransformPoints(pointArray);

                        }

 

                        using(StringFormat stringFormat = new StringFormat())

                        {

                            stringFormat.Alignment     = StringAlignment.Near;

                            stringFormat.LineAlignment = StringAlignment.Center;

 

                            int index = 0;

 

                            for(float y = 0.25f; y < maximumWorldY; y += 0.25f)

                            {

                                graphics.DrawString

                                (

                                    y.ToString("0.00"),

                                    font,

                                    Brushes.Black,

                                    pointArray[index++],

                                    stringFormat

                                );

                            }

                        }

 

                        graphics.Transform = transformMatrix;

 

                        List<PointF> pointList3 = new List<PointF>();

 

                        float deltaX = (maximumWorldX - minimumWorldX) / width;

 

                        for(float x = minimumWorldX; x <= maximumWorldX; x += deltaX)

                        {

                            float y = GetY(x, oneOver2PI, mean, standardDeviation, variance);

 

                            pointList3.Add(new PointF(x, y));

                        }

 

                        pen.Color = Color.Red;

 

                        graphics.DrawLines(pen, pointList3.ToArray());

                    }

                }

            }

 

            return bitmap;

        }

 

        #endregion

    }

}

 

------------------------------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker

댓글을 달아 주세요