첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.

728x90
반응형
728x170

TestProject.zip
다운로드

▶ MainForm.cs

using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace TestProject
{
    /// <summary>
    /// 메인 폼
    /// </summary>
    public partial class MainForm : Form
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 포인트 리스트
        /// </summary>
        private List<PointF> pointList = new List<PointF>();

        /// <summary>
        /// 근접점 1
        /// </summary>
        private PointF closePoint1;
        
        /// <summary>
        /// 근접점 2
        /// </summary>
        private PointF closePoint2;
        
        /// <summary>
        /// 교차점
        /// </summary>
        private PointF intersectPoint;

        /// <summary>
        /// 직선 교차 여부
        /// </summary>
        private bool lineIntersect = false;

        /// <summary>
        /// 세그먼트 교차 여부
        /// </summary>
        private bool segmentIntersect = false;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainForm()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            #region 이벤트를 설정한다.

            MouseClick += Form_MouseClick;
            Paint      += Form_Paint;

            #endregion
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private
        //////////////////////////////////////////////////////////////////////////////// Event

        #region 폼 마우스 클릭시 처리하기 - Form_MouseClick(sender, e)

        /// <summary>
        /// 폼 마우스 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Form_MouseClick(object sender, MouseEventArgs e)
        {
            if(this.pointList.Count == 4)
            {
                this.pointList = new List<PointF>();

                this.lineIntersect = false;
            }

            this.pointList.Add(new PointF(e.X, e.Y));

            if(this.pointList.Count == 4)
            {
                FindIntersection
                (
                    this.pointList[0],
                    this.pointList[1],
                    this.pointList[2],
                    this.pointList[3],
                    out this.lineIntersect,
                    out this.segmentIntersect,
                    out this.intersectPoint,
                    out this.closePoint1,
                    out this.closePoint2
                );
            }

            Invalidate();
        }

        #endregion
        #region 폼 페인트시 처리하기 - Form_Paint(sender, e)

        /// <summary>
        /// 폼 페인트시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Form_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

            if(this.pointList.Count == 4)
            {
                e.Graphics.DrawLine(Pens.Green, this.pointList[2], this.pointList[3]);
            }

            if(this.pointList.Count >= 2)
            {
                e.Graphics.DrawLine(Pens.Blue, this.pointList[0], this.pointList[1]);
            }

            if(this.lineIntersect)
            {
                using(Pen dashPen = new Pen(Color.Red))
                {
                    dashPen.DashStyle   = DashStyle.Custom;
                    dashPen.DashPattern = new float[] { 4, 4 };

                    e.Graphics.DrawLine(dashPen, this.closePoint1, this.closePoint2);
                }
            }

            foreach(PointF point in this.pointList)
            {
                DrawPoint(e.Graphics, point, Brushes.White, Pens.Black);
            }

            if(this.lineIntersect)
            {
                DrawPoint(e.Graphics, this.closePoint1   , Brushes.LightBlue, Pens.Blue);
                DrawPoint(e.Graphics, this.closePoint2   , Brushes.LightBlue, Pens.Blue);
                DrawPoint(e.Graphics, this.intersectPoint, Brushes.HotPink  , Pens.Red );
            }
        }

        #endregion

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

        #region 포인트 그리기 - DrawPoint(graphics, point, brush, pen)

        /// <summary>
        /// 포인트 그리기
        /// </summary>
        /// <param name="graphics">그래픽스</param>
        /// <param name="point">포인트</param>
        /// <param name="brush">브러시</param>
        /// <param name="pen">펜</param>
        private void DrawPoint(Graphics graphics, PointF point, Brush brush, Pen pen)
        {
            const int RADIUS = 3;

            graphics.FillEllipse(brush, point.X - RADIUS, point.Y - RADIUS, 2 * RADIUS, 2 * RADIUS);

            graphics.DrawEllipse(pen, point.X - RADIUS, point.Y - RADIUS, 2 * RADIUS, 2 * RADIUS);
        }

        #endregion
        #region 교차점 찾기 - FindIntersection(p1, p2, p3, p4, lineIntersect, segmentIntersect, intersectPoint, closePoint1, closePoint2)

        /// <summary>
        /// 교차점 찾기
        /// </summary>
        /// <param name="p1">직선 1 포인트 1</param>
        /// <param name="p2">직선 1 포인트 2</param>
        /// <param name="p3">직선 2 포인트 1</param>
        /// <param name="p4">직선 2 포인트 2</param>
        /// <param name="lineIntersect">선 교차 여부</param>
        /// <param name="segmentIntersect">세그먼트 교차 여부</param>
        /// <param name="intersectPoint">교차점</param>
        /// <param name="closePoint1">근접점 1</param>
        /// <param name="closePoint2">근접점 2</param>
        private void FindIntersection
        (
            PointF     p1,
            PointF     p2,
            PointF     p3,
            PointF     p4,
            out bool   lineIntersect,
            out bool   segmentIntersect,
            out PointF intersectPoint,
            out PointF closePoint1,
            out PointF closePoint2)
        {
            float dx21 = p2.X - p1.X;
            float dy21 = p2.Y - p1.Y;
            float dx43 = p4.X - p3.X;
            float dy43 = p4.Y - p3.Y;

            float denominator = (dy21 * dx43 - dx21 * dy43);

            float t1 = ((p1.X - p3.X) * dy43 + (p3.Y - p1.Y) * dx43) / denominator;

            if(float.IsInfinity(t1))
            {
                lineIntersect     = false;
                segmentIntersect  = false;

                intersectPoint = 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 = ((p3.X - p1.X) * dy21 + (p1.Y - p3.Y) * dx21) / -denominator;

            intersectPoint = new PointF(p1.X + dx21 * t1, p1.Y + dy21 * 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(p1.X + dx21 * t1, p1.Y + dy21 * t1);
            closePoint2 = new PointF(p3.X + dx43 * t2, p3.Y + dy43 * t2);
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요