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 blueRodAnchorX = 200;
/// <summary>
/// 파란 막대 앵커 Y
/// </summary>
private float blueRodAnchorY = 250;
/// <summary>
/// 바퀴 중심 X
/// </summary>
private float wheelCenterX = 300;
/// <summary>
/// 바퀴 중심 Y
/// </summary>
private float wheelCenterY = 250;
/// <summary>
/// 파란 막대의 앵커와 바퀴 중심 사이 거리
/// </summary>
private float distance = 200;
/// <summary>
/// 녹색 막대 길이
/// </summary>
private float greenRodLength = 200;
/// <summary>
/// 파란 막대 길이
/// </summary>
private float blueRodLength = 220;
/// <summary>
/// 파란 막대 나머지 부분 길이
/// </summary>
private float blueRodOtherPartLength = 120;
/// <summary>
/// 바퀴 반지름
/// </summary>
private float wheelRadius = 60;
/// <summary>
/// 델타 세타
/// </summary>
private const double DELTA_THETA = Math.PI / 10;
/// <summary>
/// 세타
/// </summary>
private double theta = 0;
/// <summary>
/// 비트맵
/// </summary>
private Bitmap bitmap = null;
/// <summary>
/// 그래픽스
/// </summary>
private Graphics graphics;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary>
/// 생성자
/// </summary>
public MainForm()
{
InitializeComponent();
#region 이벤트를 설정한다.
this.startButton.Click += startButton_Click;
this.timer.Tick += timer_Tick;
#endregion
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 시작하기 버튼 클릭시 처리하기 - startButton_Click(sender, e)
/// <summary>
/// 시작하기 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void startButton_Click(object sender, EventArgs e)
{
if(this.startButton.Text == "시작하기")
{
this.startButton.Text = "중단하기";
this.distance = float.Parse(this.distanceTextBox.Text);
this.greenRodLength = float.Parse(this.greenRodLengthTextBox.Text);
this.blueRodLength = float.Parse(this.blueRodLengthTextBox.Text);
this.blueRodOtherPartLength = float.Parse(this.blueRodOtherPartLengthTextBox.Text);
this.wheelRadius = float.Parse(this.wheelRadiusTextBox.Text);
this.wheelCenterX = this.blueRodAnchorX + this.distance;
this.theta = 0;
this.bitmap = new Bitmap
(
this.canvasPictureBox.ClientSize.Width,
this.canvasPictureBox.ClientSize.Height
);
this.graphics = Graphics.FromImage(this.bitmap);
this.canvasPictureBox.Image = this.bitmap;
this.timer.Enabled = true;
}
else
{
this.startButton.Text = "시작하기";
this.timer.Enabled = false;
}
}
#endregion
#region 타이머 틱 처리하기 - timer_Tick(sender, e)
/// <summary>
/// 타이머 틱 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void timer_Tick(object sender, EventArgs e)
{
this.theta += DELTA_THETA;
Draw();
this.canvasPictureBox.Refresh();
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 원과 원의 교차 포인트 찾기 - FindCircleCircleIntersectionPoint(cx1, cy1, radius1, cx2, cy2, radius2, intersectionPoint1, intersectionPoint2)
/// <summary>
/// 원과 원의 교차 포인트 찾기
/// </summary>
/// <param name="cx1">원 1 중심 X</param>
/// <param name="cy1">원 1 중심 Y</param>
/// <param name="radius1">원 1 반지름</param>
/// <param name="cx2">원 2 중심 X</param>
/// <param name="cy2">원 2 중심 Y</param>
/// <param name="radius2">원 2 반지름</param>
/// <param name="intersectionPoint1">교차 포인트 1</param>
/// <param name="intersectionPoint2">교차 포인트 2</param>
/// <returns>교차 포인트 수</returns>
private int FindCircleCircleIntersectionPoint(float cx1, float cy1, float radius1, float cx2, float cy2, float radius2,
out PointF intersectionPoint1, out PointF intersectionPoint2)
{
float dx = cx1 - cx2;
float dy = cy1 - cy2;
double distance = Math.Sqrt(dx * dx + dy * dy);
if(distance > radius1 + radius2)
{
intersectionPoint1 = new PointF(float.NaN, float.NaN);
intersectionPoint2 = new PointF(float.NaN, float.NaN);
return 0;
}
else if(distance < Math.Abs(radius1 - radius2))
{
intersectionPoint1 = new PointF(float.NaN, float.NaN);
intersectionPoint2 = new PointF(float.NaN, float.NaN);
return 0;
}
else if((distance == 0) && (radius1 == radius2))
{
intersectionPoint1 = new PointF(float.NaN, float.NaN);
intersectionPoint2 = 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 cx3 = cx1 + a * (cx2 - cx1) / distance;
double cy3 = cy1 + a * (cy2 - cy1) / distance;
intersectionPoint1 = new PointF
(
(float)(cx3 + h * (cy2 - cy1) / distance),
(float)(cy3 - h * (cx2 - cx1) / distance)
);
intersectionPoint2 = new PointF
(
(float)(cx3 - h * (cy2 - cy1) / distance),
(float)(cy3 + h * (cx2 - cx1) / distance)
);
if(distance == radius1 + radius2)
{
return 1;
}
return 2;
}
}
#endregion
#region 그리기 - Draw()
/// <summary>
/// 그리기
/// </summary>
private void Draw()
{
this.graphics.Clear(BackColor);
this.graphics.SmoothingMode = SmoothingMode.AntiAlias;
using(Pen pen = new Pen(Color.Blue, 2))
{
RectangleF wheelRectangle = new RectangleF
(
this.wheelCenterX - this.wheelRadius,
this.wheelCenterY - this.wheelRadius,
2 * this.wheelRadius,
2 * this.wheelRadius
);
this.graphics.FillEllipse(Brushes.LightBlue, wheelRectangle);
pen.Color = Color.Blue;
pen.Width = 2;
this.graphics.DrawEllipse(pen, wheelRectangle);
float linkageX1 = (float)(this.wheelCenterX + Math.Cos(this.theta) * this.wheelRadius);
float linkageY1 = (float)(this.wheelCenterY + Math.Sin(this.theta) * this.wheelRadius);
PointF pt1;
PointF pt2;
FindCircleCircleIntersectionPoint
(
this.blueRodAnchorX,
this.blueRodAnchorY,
this.blueRodLength,
linkageX1,
linkageY1,
this.greenRodLength,
out pt1,
out pt2
);
float linkageX2 = pt1.X;
float linkageY2 = pt1.Y;
pen.Color = Color.Green;
pen.Width = 5;
this.graphics.DrawLine(pen, linkageX1, linkageY1, linkageX2, linkageY2);
pen.Color = Color.Lime;
pen.Width = 2;
this.graphics.DrawLine(pen, linkageX1, linkageY1, linkageX2, linkageY2);
pen.Color = Color.Blue;
pen.Width = 5;
this.graphics.DrawLine(pen, this.blueRodAnchorX, this.blueRodAnchorY, linkageX2, linkageY2);
pen.Color = Color.LightBlue;
pen.Width = 2;
this.graphics.DrawLine(pen, this.blueRodAnchorX, this.blueRodAnchorY, linkageX2, linkageY2);
float dx = this.blueRodAnchorX - linkageX2;
float dy = this.blueRodAnchorY - linkageY2;
double length = Math.Sqrt(dx * dx + dy * dy);
float lowerX1 = (float)(this.blueRodAnchorX + dx * this.blueRodOtherPartLength / length);
float lowerY1 = (float)(this.blueRodAnchorY + dy * this.blueRodOtherPartLength / length);
pen.Color = Color.Blue;
pen.Width = 5;
this.graphics.DrawLine(pen, this.blueRodAnchorX, this.blueRodAnchorY, lowerX1, lowerY1);
pen.Color = Color.LightBlue;
pen.Width = 2;
this.graphics.DrawLine(pen, this.blueRodAnchorX, this.blueRodAnchorY, lowerX1, lowerY1);
this.graphics.FillEllipse(Brushes.Black, this.wheelCenterX - 4, this.wheelCenterY - 4, 8, 8);
this.graphics.FillEllipse(Brushes.Green, linkageX1 - 4, linkageY1 - 4, 8, 8);
this.graphics.FillEllipse(Brushes.Green, linkageX2 - 4, linkageY2 - 4, 8, 8);
this.graphics.FillEllipse(Brushes.Black, this.blueRodAnchorX - 4, this.blueRodAnchorY - 4, 8, 8);
this.graphics.FillEllipse(Brushes.Blue, lowerX1 - 4, lowerY1 - 4, 8, 8);
}
}
#endregion
}
}
728x90
반응형
그리드형(광고전용)
'C# > WinForm' 카테고리의 다른 글
[C#/WINFORM] PictureBox 클래스 : 이미지 드래그 스크롤 하기 (0) | 2019.01.07 |
---|---|
[C#/WINFORM] PictureBox 클래스 : 진행바 텍스트 표시하기 (0) | 2019.01.07 |
[C#/WINFORM] Graphics 클래스 : DrawString 메소드를 사용해 양쪽 맞춤 텍스트 그리기 (0) | 2019.01.07 |
[C#/WINFORM] 이미지 거리 측정하기 (0) | 2019.01.07 |
[C#/WINFORM] 콤보 박스/리스트 박스 데이터 소스 연결하기 (0) | 2019.01.07 |
[C#/WINFORM] 로봇 팔 마우스 추적하기 (0) | 2019.01.07 |
[C#/WINFORM] 타원을 임의 선으로 채우기 (0) | 2019.01.06 |
[C#/WINFORM] RichTextBox 클래스 : 위/아래 첨자 사용하기 (0) | 2019.01.06 |
[C#/WINFORM] Graphics 클래스 : MeasureString 메소드를 사용해 텍스트 그리기 (0) | 2019.01.06 |
[C#/WINFORM] WebBrowser 클래스 : 구글 맵 사용하기 (0) | 2019.01.06 |
댓글을 달아 주세요