728x90
반응형
728x170
▶ MainForm.cs
using System;
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>
/// 원 중심점 X
/// </summary>
private float circleCenterX;
/// <summary>
/// 원 중심점 Y
/// </summary>
private float circleCenterY;
/// <summary>
/// 원 반경
/// </summary>
private float circleRadius;
/// <summary>
/// 직선 포인트 1
/// </summary>
private PointF linePoint1;
/// <summary>
/// 직선 포인트 2
/// </summary>
private PointF linePoint2;
/// <summary>
/// 그리기 여부
/// </summary>
private bool isDrawing = false;
/// <summary>
/// 포인트 보유 여부
/// </summary>
private bool havePoints = false;
/// <summary>
/// 교차점 1
/// </summary>
private PointF intersectPoint1;
/// <summary>
/// 교차점 2
/// </summary>
private PointF intersectPoint2;
/// <summary>
/// 교차 수
/// </summary>
private int intersectCount;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary>
/// 생성자
/// </summary>
public MainForm()
{
InitializeComponent();
ResizeRedraw = true;
InitializeCircle();
#region 이벤트를 설정한다.
Resize += Form_Resize;
MouseDown += Form_MouseDown;
MouseMove += Form_MouseMove;
MouseUp += Form_MouseUp;
Paint += Form_Paint;
#endregion
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 폼 크기 조정시 처리하기 - Form_Resize(sender, e)
/// <summary>
/// 폼 크기 조정시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void Form_Resize(object sender, EventArgs e)
{
this.intersectCount = 0;
this.havePoints = false;
InitializeCircle();
}
#endregion
#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)
{
this.isDrawing = true;
this.intersectCount = 0;
this.linePoint1 = new PointF(e.X, e.Y);
this.linePoint2 = new PointF(e.X, e.Y);
this.havePoints = true;
Invalidate();
}
#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.linePoint2 = new PointF(e.X, 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;
this.intersectCount = FindLineCircleIntersection
(
this.circleCenterX,
this.circleCenterY,
this.circleRadius,
this.linePoint1,
this.linePoint2,
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;
e.Graphics.DrawEllipse
(
Pens.Blue,
this.circleCenterX - this.circleRadius,
this.circleCenterY - this.circleRadius,
this.circleRadius * 2,
this.circleRadius * 2
);
if(this.havePoints && this.intersectCount > 0)
{
using(Pen pen = new Pen(Color.Red))
{
pen.DashPattern = new float[] { 3, 3 };
e.Graphics.DrawLine(pen, this.intersectPoint1, this.linePoint1);
}
}
switch(this.intersectCount)
{
case 0 :
break;
case 1 :
DrawPoint(e.Graphics, this.intersectPoint1, Brushes.HotPink, Pens.Red);
break;
case 2 :
DrawPoint(e.Graphics, this.intersectPoint1, Brushes.HotPink, Pens.Red);
DrawPoint(e.Graphics, this.intersectPoint2, Brushes.HotPink, Pens.Red);
break;
}
if(this.havePoints)
{
DrawPoint(e.Graphics, this.linePoint1, Brushes.White, Pens.Black);
DrawPoint(e.Graphics, this.linePoint2, Brushes.White, Pens.Black);
e.Graphics.DrawLine(Pens.BlueViolet, this.linePoint1, this.linePoint2);
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 원 초기화 하기 - InitializeCircle()
/// <summary>
/// 원 초기화 하기
/// </summary>
private void InitializeCircle()
{
this.circleCenterX = ClientSize.Width / 2;
this.circleCenterY = ClientSize.Height / 2;
this.circleRadius = (float)(Math.Min(this.circleCenterX, this.circleCenterY) * 0.8);
this.havePoints = false;
Invalidate();
}
#endregion
#region 직선/원 교차점 찾기 - FindLineCircleIntersection(circleCenterX, circleCenterY, circleRadius, linePoint1, linePoint2, intersectPoint1, intersectPoint2)
/// <summary>
/// 직선/원 교차점 찾기
/// </summary>
/// <param name="circleCenterX">원 중심점 X</param>
/// <param name="circleCenterY">원 중심점 Y</param>
/// <param name="circleRadius">원 반경</param>
/// <param name="linePoint1">직선 포인트 1</param>
/// <param name="linePoint2">직선 포인트 2</param>
/// <param name="intersectPoint1">교차점 1</param>
/// <param name="intersectPoint2">교차점 2</param>
/// <returns>교차점 수</returns>
private int FindLineCircleIntersection(float circleCenterX, float circleCenterY, float circleRadius, PointF linePoint1, PointF linePoint2,
out PointF intersectPoint1, out PointF intersectPoint2)
{
float deltaX;
float deltaY;
float a;
float b;
float c;
float det;
float t;
deltaX = linePoint2.X - linePoint1.X;
deltaY = linePoint2.Y - linePoint1.Y;
a = deltaX * deltaX + deltaY * deltaY;
b = 2 * (deltaX * (linePoint1.X - circleCenterX) + deltaY * (linePoint1.Y - circleCenterY));
c = (linePoint1.X - circleCenterX) * (linePoint1.X - circleCenterX) + (linePoint1.Y - circleCenterY) * (linePoint1.Y - circleCenterY) - circleRadius * circleRadius;
det = b * b - 4 * a * c;
if((a <= 0.0000001) || (det < 0))
{
intersectPoint1 = new PointF(float.NaN, float.NaN);
intersectPoint2 = new PointF(float.NaN, float.NaN);
return 0;
}
else if(det == 0)
{
t = -b / (2 * a);
intersectPoint1 = new PointF(linePoint1.X + t * deltaX, linePoint1.Y + t * deltaY);
intersectPoint2 = new PointF(float.NaN, float.NaN);
return 1;
}
else
{
t = (float)((-b + Math.Sqrt(det)) / (2 * a));
intersectPoint1 = new PointF(linePoint1.X + t * deltaX, linePoint1.Y + t * deltaY);
t = (float)((-b - Math.Sqrt(det)) / (2 * a));
intersectPoint2 = new PointF(linePoint1.X + t * deltaX, linePoint1.Y + t * deltaY);
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] 영역 채우기(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 |
[C#/WINFORM] 비교차 스타 그리기 (0) | 2018.12.09 |
댓글을 달아 주세요