728x90
반응형
728x170
▶ 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
}
}
728x90
반응형
그리드형(광고전용)
'C# > WinForm' 카테고리의 다른 글
[C#/WINFORM] TextureBrush 클래스 사용하기 (0) | 2018.12.10 |
---|---|
[C#/WINFORM] 영역 채우기(Flood Fill) (0) | 2018.12.10 |
[C#/WINFORM] 유니코드 문자 조회하기 (0) | 2018.12.09 |
[C#/WINFORM] 움직이는 GIF 이미지 사용하기 (0) | 2018.12.09 |
[C#/WINFORM] 시어핀스키 가스켓(Sierpinski Gasket) 그리기 (0) | 2018.12.09 |
[C#/WINFORM] 직선과 원의 교차 여부 구하기 (0) | 2018.12.09 |
[C#/WINFORM] 타원 버튼 그리기 (0) | 2018.12.09 |
[C#/WINFORM] 피코버 별난 끌개 프랙탈(Pickover Strange Attractor Fractal) 그리기 (0) | 2018.12.09 |
[C#/WINFORM] Graphics 클래스 : TextRenderingHint 속성을 사용해 폰트 안티-알리아싱 설정하기 (0) | 2018.12.09 |
[C#/WINFORM] PathGradientBrush 클래스 사용하기 (0) | 2018.12.09 |
댓글을 달아 주세요