■ 원과 원의 교차 여부 구하기

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


TestProject.zip


MainForm.cs

 

 

using System;

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<RectangleF> circleList = new List<RectangleF>();

 

        /// <summary>

        /// X1

        /// </summary>

        private int x1;

        

        /// <summary>

        /// Y1

        /// </summary>

        private int y1;

        

        /// <summary>

        /// X2

        /// </summary>

        private int x2;

        

        /// <summary>

        /// Y2

        /// </summary>

        private int y2;

 

        /// <summary>

        /// 그리기 여부

        /// </summary>

        private bool isDrawing = false;

 

        /// <summary>

        /// 교차점 1

        /// </summary>

        private PointF intersectPoint1;

        

        /// <summary>

        /// 교차점 2

        /// </summary>

        private PointF intersectPoint2;

 

        /// <summary>

        /// 교차점 수

        /// </summary>

        private int intersectCount = 0;

 

        #endregion

 

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

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

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            #region 이벤트를 설정한다.

 

            MouseDown += Form_MouseDown;

            MouseMove += Form_MouseMove;

            MouseUp   += Form_MouseUp;

            Paint     += Form_Paint;

 

            #endregion

        }

 

        #endregion

 

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

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

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

 

        #region 폼 마우스 DOWN 처리하기 - Form_MouseDown(sender, e)

 

        /// <summary>

        /// 폼 마우스 DOWN 처리하기

        /// </summary>

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

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

        private void Form_MouseDown(object sender, MouseEventArgs e)

        {

            if(this.circleList.Count == 2)

            {

                this.circleList.Clear();

 

                this.intersectCount = 0;

            }

 

            this.x1 = this.x2 = e.X;

            this.y1 = this.y2 = e.Y;

 

            this.isDrawing = true;

        }

 

        #endregion

        #region 폼 마우스 이동시 처리하기 - Form_MouseMove(sender, e)

 

        /// <summary>

        /// 폼 마우스 이동시 처리하기

        /// </summary>

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

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

        private void Form_MouseMove(object sender, MouseEventArgs e)

        {

            if(!this.isDrawing)

            {

                return;

            }

 

            this.x2 = e.X;

            this.y2 = e.Y;

 

            Invalidate();

        }

 

        #endregion

        #region 폼 마우스 UP 처리하기 - Form_MouseUp(sender, e)

 

        /// <summary>

        /// 폼 마우스 UP 처리하기

        /// </summary>

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

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

        private void Form_MouseUp(object sender, MouseEventArgs e)

        {

            this.isDrawing = false;

 

            int width = Math.Min(Math.Abs(this.x1 - this.x2), Math.Abs(this.y1 - this.y2));

 

            RectangleF rectangle = new RectangleF

            (

                this.x1,

                this.y1,

                width,

                width

            );

 

            if(this.x1 > this.x2)

            {

                rectangle.X = this.x1 - width;

            }

 

            if(this.y1 > this.y2)

            {

                rectangle.Y = this.y1 - width;

            }

 

            this.circleList.Add(rectangle);

 

            if(this.circleList.Count == 2)

            {

                float radius0 = this.circleList[0].Height / 2;

                float cx0     = this.circleList[0].X + radius0;

                float cy0     = this.circleList[0].Y + radius0;

                float radius1 = this.circleList[1].Height / 2;

                float cx1     = this.circleList[1].X + radius1;

                float cy1     = this.circleList[1].Y + radius1;

 

                this.intersectCount = FindCircleCircleIntersection

                (

                    cx0,

                    cy0,

                    radius0,

                    cx1,

                    cy1,

                    radius1,

                    out this.intersectPoint1,

                    out this.intersectPoint2

                );

            }

 

            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;

 

            foreach(RectangleF rectangle in this.circleList)

            {

                e.Graphics.DrawEllipse(Pens.Blue, rectangle);

            }

 

            if(this.isDrawing)

            {

                int width = Math.Min(Math.Abs(this.x1 - this.x2), Math.Abs(this.y1 - this.y2));

 

                RectangleF rectangle = new RectangleF

                (

                    this.x1,

                    this.y1,

                    width,

                    width

                );

 

                if(this.x1 > this.x2)

                {

                    rectangle.X = this.x1 - width;

                }

 

                if(this.y1 > this.y2)

                {

                    rectangle.Y = this.y1 - width;

                }

 

                e.Graphics.DrawEllipse(Pens.Red, rectangle);

            }

 

            if(this.intersectCount >= 1)

            {

                DrawPoint(e.Graphics, this.intersectPoint1, Brushes.HotPink, Pens.Red);

            }

 

            if(this.intersectCount >= 2)

            {

                DrawPoint(e.Graphics, this.intersectPoint2, Brushes.HotPink, Pens.Red);

            }

        }

 

        #endregion

 

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

 

        #region 원/원 교차점 찾기 - FindCircleCircleIntersection(centerX1, centerY1, radius1, centerX2, centerY2, radius2,

            intersectPoint1, intersectPoint2)

 

        /// <summary>

        /// 원/원 교차점 찾기

        /// </summary>

        /// <param name="centerX1">원 1 중심점 X</param>

        /// <param name="centerY1">원 1 중심점 Y</param>

        /// <param name="radius1">원 1 반경</param>

        /// <param name="centerX2">원 2 중심 X</param>

        /// <param name="centerY2">원 2 중심 Y</param>

        /// <param name="radius2">원 2 반경</param>

        /// <param name="intersectPoint1">교차점 1</param>

        /// <param name="intersectPoint2">교차점 2</param>

        /// <returns>교차 수</returns>

        private int FindCircleCircleIntersection(float centerX1, float centerY1, float radius1, float centerX2, float centerY2, float radius2,

            out PointF intersectPoint1, out PointF intersectPoint2)

        {

            float  deltaX   = centerX1 - centerX2;

            float  deltaY   = centerY1 - centerY2;

            double distance = Math.Sqrt(deltaX * deltaX + deltaY * deltaY);

 

            if(distance > radius1 + radius2)

            {

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

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

 

                return 0;

            }

            else if(distance < Math.Abs(radius1 - radius2))

            {

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

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

 

                return 0;

            }

            else if((distance == 0) && (radius1 == radius2))

            {

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

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

 

                return 0;

            }

            else

            {

                double a = (radius1 * radius1 - radius2 * radius2 + distance * distance) / (2 * distance);

                double h = Math.Sqrt(radius1 * radius1 - a * a);

 

                double centaX3 = centerX1 + a * (centerX2 - centerX1) / distance;

                double centaY3 = centerY1 + a * (centerY2 - centerY1) / distance;

 

                intersectPoint1 = new PointF

                (

                    (float)(centaX3 + h * (centerY2 - centerY1) / distance),

                    (float)(centaY3 - h * (centerX2 - centerX1) / distance)

                );

 

                intersectPoint2 = new PointF

                (

                    (float)(centaX3 - h * (centerY2 - centerY1) / distance),

                    (float)(centaY3 + h * (centerX2 - centerX1) / distance)

                );

 

                if(distance == radius1 + radius2)

                {

                    return 1;

                }

 

                return 2;

            }

        }

 

        #endregion

        #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

    }

}

 

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

Posted by 사용자 icodebroker

댓글을 달아 주세요