■ 별 인쇄하기

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


TestProject.zip


MainForm.cs

 

 

using System;

using System.Drawing;

using System.Drawing.Drawing2D;

using System.Drawing.Printing;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 메인 폼

    /// </summary>

    public partial class MainForm : Form

    {

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

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

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            #region 이벤트를 설정한다.

 

            this.pointNumericUpDown.ValueChanged += pointNumericUpDown_ValueChanged;

            this.skipNumericUpDown.ValueChanged  += skipNumericUpDown_ValueChanged;

            this.previewButton.Click             += previewButton_Click;

            this.canvasPictureBox.Paint          += canvasPictureBox_Paint;

            this.printDocument.PrintPage         += printDocument_PrintPage;

 

            #endregion

        }

 

        #endregion

 

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

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

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

 

        #region 포인트 숫자 UP/DOWN 값 변경시 처리하기 - pointNumericUpDown_ValueChanged(sender, e)

 

        /// <summary>

        /// 포인트 숫자 UP/DOWN 값 변경시 처리하기

        /// </summary>

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

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

        private void pointNumericUpDown_ValueChanged(object sender, EventArgs e)

        {

            this.skipNumericUpDown.Maximum = (int)(((int)this.pointNumericUpDown.Value - 1) / 2.0);

 

            this.canvasPictureBox.Refresh();

        }

 

        #endregion

        #region 건너뛰기 숫자 UP/DOWN 값 변경시 처리하기 - skipNumericUpDown_ValueChanged(sender, e)

 

        /// <summary>

        /// 건너뛰기 숫자 UP/DOWN 값 변경시 처리하기

        /// </summary>

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

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

        private void skipNumericUpDown_ValueChanged(object sender, EventArgs e)

        {

            this.canvasPictureBox.Refresh();

        }

 

        #endregion

        #region 미리보기 버튼 클릭시 처리하기 - previewButton_Click(sender, e)

 

        /// <summary>

        /// 미리보기 버튼 클릭시 처리하기

        /// </summary>

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

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

        private void previewButton_Click(object sender, EventArgs e)

        {

            this.printPreviewDialog.ShowDialog();

        }

 

        #endregion

        #region 캔버스 픽처 박스 페인트시 처리하기 - canvasPictureBox_Paint(sender, e)

 

        /// <summary>

        /// 캔버스 픽처 박스 페인트시 처리하기

        /// </summary>

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

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

        private void canvasPictureBox_Paint(object sender, PaintEventArgs e)

        {

            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

 

            DrawStar

            (

                e.Graphics,

                Pens.Red,

                Brushes.Yellow,

                (int)this.pointNumericUpDown.Value,

                (int)this.skipNumericUpDown.Value,

                this.canvasPictureBox.ClientRectangle

            );

        }

 

        #endregion

        #region 인쇄 문서 페이지 인쇄시 처리하기 - printDocument_PrintPage(sender, e)

 

        /// <summary>

        /// 인쇄 문서 페이지 인쇄시 처리하기

        /// </summary>

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

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

        private void printDocument_PrintPage(object sender, PrintPageEventArgs e)

        {

            try

            {

                float diameter = float.Parse(this.radiusTextBox.Text);

 

                diameter = diameter / 25.4f * 100f;

 

                float cx = (e.MarginBounds.Left + e.MarginBounds.Right ) / 2f;

                float cy = (e.MarginBounds.Top  + e.MarginBounds.Bottom) / 2f;

 

                float x = cx - diameter / 2f;

                float y = cy - diameter / 2f;

 

                RectangleF rectangle = new RectangleF(x, y, diameter, diameter);

 

                e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

 

                DrawStar

                (

                    e.Graphics,

                    Pens.Red,

                    Brushes.Yellow,

                    (int)pointNumericUpDown.Value,

                    (int)skipNumericUpDown.Value,

                    rectangle

                );

 

                //DrawAxes(e);

 

                e.HasMorePages = false;

            }

            catch(Exception exception)

            {

                MessageBox.Show(exception.Message);

            }

        }

 

        #endregion

 

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

 

        #region 교차점 찾기 - FindIntersectionPoint(startPoint1, endPoint1, startPoint2, endPoint2,

            lineIntersect, segmentIntersect, intersectionPoint, closePoint1, closePoint2)

 

        /// <summary>

        /// 교차점 찾기

        /// </summary>

        /// <param name="startPoint1">시작 포인트 1</param>

        /// <param name="endPoint1">종료 포인트 1</param>

        /// <param name="startPoint2">시작 포인트 2</param>

        /// <param name="endPoint2">종료 포인트 2</param>

        /// <param name="lineIntersect">선 교차 여부</param>

        /// <param name="segmentIntersect">세그먼트 교차 여부</param>

        /// <param name="intersectionPoint">교차 포인트</param>

        /// <param name="closePoint1">근접 포인트 1</param>

        /// <param name="closePoint2">근접 포인트 2</param>

        private void FindIntersectionPoint(PointF startPoint1, PointF endPoint1, PointF startPoint2, PointF endPoint2,

            out bool lineIntersect, out bool segmentIntersect, out PointF intersectionPoint, out PointF closePoint1, out PointF closePoint2)

        {

            float dx12 = endPoint1.X - startPoint1.X;

            float dy12 = endPoint1.Y - startPoint1.Y;

            float dx34 = endPoint2.X - startPoint2.X;

            float dy34 = endPoint2.Y - startPoint2.Y;

 

            float denominator = (dy12 * dx34 - dx12 * dy34);

 

            float t1 = ((startPoint1.X - startPoint2.X) * dy34 + (startPoint2.Y - startPoint1.Y) * dx34) / denominator;

 

            if(float.IsInfinity(t1))

            {

                lineIntersect    = false;

                segmentIntersect = false;

 

                intersectionPoint = new PointF(float.NaN, float.NaN);

 

                closePoint1 = new PointF(float.NaN, float.NaN);

                closePoint2 = new PointF(float.NaN, float.NaN);

 

                return;

            }

 

            lineIntersect = true;

 

            float t2 = ((startPoint2.X - startPoint1.X) * dy12 + (startPoint1.Y - startPoint2.Y) * dx12) / -denominator;

 

            intersectionPoint = new PointF(startPoint1.X + dx12 * t1, startPoint1.Y + dy12 * t1);

 

            segmentIntersect = ((t1 >= 0) && (t1 <= 1) && (t2 >= 0) && (t2 <= 1));

 

            if(t1 < 0)

            {

                t1 = 0;

            }

            else if(t1 > 1)

            {

                t1 = 1;

            }

 

            if(t2 < 0)

            {

                t2 = 0;

            }

            else if(t2 > 1)

            {

                t2 = 1;

            }

 

            closePoint1 = new PointF(startPoint1.X + dx12 * t1, startPoint1.Y + dy12 * t1);

            closePoint2 = new PointF(startPoint2.X + dx34 * t2, startPoint2.Y + dy34 * t2);

        }

 

        #endregion

        #region 오목 반지름 구하기 - GetConcaveRadius(pointCount, skip)

 

        /// <summary>

        /// 오목 반지름 구하기

        /// </summary>

        /// <param name="pointCount">포인트 카운트</param>

        /// <param name="skip">건너띄기</param>

        /// <returns>오목 반지름</returns>

        private double GetConcaveRadius(int pointCount, int skip)

        {

            if(pointCount < 5)

            {

                return 0.33f;

            }

 

            double deltaTheta = 2 * Math.PI / pointCount;

            double theta00    = -Math.PI / 2;

            double theta01    = theta00 + deltaTheta * skip;

            double theta10    = theta00 + deltaTheta;

            double theta11    = theta10 - deltaTheta * skip;

 

            PointF pt00 = new PointF

            (

                (float)Math.Cos(theta00),

                (float)Math.Sin(theta00)

            );

 

            PointF pt01 = new PointF

            (

                (float)Math.Cos(theta01),

                (float)Math.Sin(theta01)

            );

 

            PointF pt10 = new PointF

            (

                (float)Math.Cos(theta10),

                (float)Math.Sin(theta10)

            );

 

            PointF pt11 = new PointF

            (

                (float)Math.Cos(theta11),

                (float)Math.Sin(theta11)

            );

 

            bool lineIntersect;

            bool segmentIntersect;

 

            PointF intersectionPoint;

            PointF closePoint1;

            PointF closePoint2;

 

            FindIntersectionPoint

            (

                pt00,

                pt01,

                pt10,

                pt11,

                out lineIntersect,

                out segmentIntersect,

                out intersectionPoint,

                out closePoint1,

                out closePoint2

            );

 

            return Math.Sqrt(intersectionPoint.X * intersectionPoint.X + intersectionPoint.Y * intersectionPoint.Y);

        }

 

        #endregion

        #region 별 포인트 배열 구하기 - GetStarPointArray(startTheta, pointCount, skip, rectangle)

 

        /// <summary>

        /// 별 포인트 배열 구하기

        /// </summary>

        /// <param name="startTheta">시작 세타</param>

        /// <param name="pointCount">포인트 카운트</param>

        /// <param name="skip">건너띄기</param>

        /// <param name="rectangle">사각형</param>

        /// <returns>별 포인트 배열</returns>

        private PointF[] GetStarPointArray(double startTheta, int pointCount, int skip, RectangleF rectangle)

        {

            double   theta;

            double   deltaTheta;

            PointF[] resultArray;

 

            float rx = rectangle.Width / 2f;

            float ry = rectangle.Height / 2f;

            float cx = rectangle.X + rx;

            float cy = rectangle.Y + ry;

 

            if(skip == 1)

            {

                resultArray = new PointF[pointCount];

 

                theta = startTheta;

 

                deltaTheta = 2 * Math.PI / pointCount;

 

                for(int i = 0; i < pointCount; i++)

                {

                    resultArray[i] = new PointF

                    (

                        (float)(cx + rx * Math.Cos(theta)),

                        (float)(cy + ry * Math.Sin(theta))

                    );

 

                    theta += deltaTheta;

                }

 

                return resultArray;

            }

 

            double concaveRadius = GetConcaveRadius(pointCount, skip);

 

            resultArray = new PointF[2 * pointCount];

 

            theta = startTheta;

 

            deltaTheta = Math.PI / pointCount;

 

            for(int i = 0; i < pointCount; i++)

            {

                resultArray[2 * i] = new PointF

                (

                    (float)(cx + rx * Math.Cos(theta)),

                    (float)(cy + ry * Math.Sin(theta))

                );

 

                theta += deltaTheta;

 

                resultArray[2 * i + 1] = new PointF

                (

                    (float)(cx + rx * Math.Cos(theta) * concaveRadius),

                    (float)(cy + ry * Math.Sin(theta) * concaveRadius)

                );

 

                theta += deltaTheta;

            }

 

            return resultArray;

        }

        

        #endregion

        #region 별 그리기 - DrawStar(graphics, pen, brush, pointCount, skip, rectangle)

 

        /// <summary>

        /// 별 그리기

        /// </summary>

        /// <param name="graphics">그래픽스</param>

        /// <param name="pen"></param>

        /// <param name="brush">브러시</param>

        /// <param name="pointCount">포인트 카운트</param>

        /// <param name="skip">건너뛰기</param>

        /// <param name="rectangle">사각형</param>

        private void DrawStar(Graphics graphics, Pen pen, Brush brush, int pointCount, int skip, RectangleF rectangle)

        {

            PointF[] pointArray = GetStarPointArray(-Math.PI / 2, pointCount, skip, rectangle);

 

            graphics.FillPolygon(brush, pointArray);

 

            graphics.DrawPolygon(pen, pointArray);

        }

 

        #endregion

        #region 축 그리기 - DrawAxes(e)

 

        /// <summary>

        /// 축 그리기

        /// </summary>

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

        private void DrawAxes(PrintPageEventArgs e)

        {

            float cx = (e.MarginBounds.Left + e.MarginBounds.Right) / 2f;

            float cy = (e.MarginBounds.Top + e.MarginBounds.Bottom) / 2f;

 

            e.Graphics.DrawLine(Pens.Black, e.MarginBounds.Left, cy, e.MarginBounds.Right, cy);

 

            e.Graphics.DrawLine(Pens.Black, cx, e.MarginBounds.Top, cx, e.MarginBounds.Bottom);

 

            for(float x = cx; x <= e.MarginBounds.Right; x += 20)

            {

                e.Graphics.DrawLine(Pens.Black, x, cy - 10, x, cy + 10);

            }

 

            for(float x = cx; x >= e.MarginBounds.Left; x -= 20)

            {

                e.Graphics.DrawLine(Pens.Black, x, cy - 10, x, cy + 10);

            }

 

            for(float y = cy; y <= e.MarginBounds.Bottom; y += 20)

            {

                e.Graphics.DrawLine(Pens.Black, cx - 10, y, cx + 10, y);

            }

 

            for(float y = cy; y >= e.MarginBounds.Top; y -= 20)

            {

                e.Graphics.DrawLine(Pens.Black, cx - 10, y, cx + 10, y);

            }

        }

 

        #endregion

    }

}

 

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

Posted by 사용자 icodebroker
TAG

댓글을 달아 주세요