座標を回転させる(描画図形を回転させる)
座標を回転させる方法をご紹介します。描画図形の回転に使えます。
高校の算数で、三角関数はこういうところに使えるんだよ、って教えることができたら、もっと算数が好きな人が増えると思うのですが。
下記が座標を回転させるメソッドです。
private bool RotatePoint(
ref double want_x,
ref double want_y,
int x,
int y,
double radian,
int org_x,
int org_y
)
{
// あらかじめ三角関数の値を計算しておく.
double cos = Math.Cos( radian );
double sin = Math.Sin( radian );
// いったん座標をシフト移動する.
double tmp_x = x - org_x;
double tmp_y = y - org_y;
// 座標を回転させる.
double buf_x = (( cos * tmp_x ) - ( sin * tmp_y ));
double buf_y = (( sin * tmp_x ) + ( cos * tmp_y ));
// 回転させた座標をシフト移動してもどす.
want_x = buf_x + org_x;
want_y = buf_y + org_y;
return true;
}
全体コード
クリックした点を左上隅座標として初期状態にします。ボタンを押すと図形が回転します。
Form1 に pictureBox1 と button1 を配置してください。
Form1_Load() を定義してください。
button1_Click() を定義してください。
pictureBox1_Paint() を定義してください。
pictureBox1_MouseDown() を定義してください。
using System;
using System.Drawing;
using System.Windows.Forms;
namespace aaa
{
public partial class Form1 : Form
{
const int RECT_W = 128;
const int RECT_H = 64;
int TheX0;
int TheY0;
int TheX1;
int TheY1;
int TheX2;
int TheY2;
int TheX3;
int TheY3;
public Form1()
{
InitializeComponent();
}
private void Form1_Load( object sender, EventArgs e )
{
int pw = pictureBox1.Width;
int ph = pictureBox1.Height;
// ピクチャボックスの中心座標.
int org_x = pw >> 1;
int org_y = ph >> 1;
TheX0 = org_x;
TheY0 = org_y;
TheX1 = TheX0 + RECT_W;
TheY1 = TheY0;
TheX2 = TheX0 + RECT_W;
TheY2 = TheY0 + RECT_H;
TheX3 = TheX0;
TheY3 = TheY0 + RECT_H;
}
private void pictureBox1_Paint( object sender, PaintEventArgs e )
{
int pw = pictureBox1.Width;
int ph = pictureBox1.Height;
// ピクチャボックスを塗りつぶす.
Color brush_color = Color.Navy;
using ( SolidBrush sb = new SolidBrush( brush_color ))
{
e.Graphics.FillRectangle( sb, 0, 0, pw, ph );
}
// 回転させた矩形を描画する.
const float PEN_WIDTH_RECT = 3.0f;
using ( Pen pen = new Pen( Color.Lime, PEN_WIDTH_RECT ))
{
// 4点をたどる線を描画.
e.Graphics.DrawLine( pen, TheX0, TheY0, TheX1, TheY1 );
e.Graphics.DrawLine( pen, TheX1, TheY1, TheX2, TheY2 );
e.Graphics.DrawLine( pen, TheX2, TheY2, TheX3, TheY3 );
e.Graphics.DrawLine( pen, TheX3, TheY3, TheX0, TheY0 );
// 対角線を描画.
e.Graphics.DrawLine( pen, TheX0, TheY0, TheX2, TheY2 );
}
// 補助線を描画する.
const float PEN_WIDTH_GUIDE_LINE = 1.0f;
using ( Pen pen = new Pen( Color.White, PEN_WIDTH_GUIDE_LINE ))
{
// 円を描画する.
const int R = 8;
int ex = TheX0 - R;
int ey = TheY0 - R;
int ew = ( R << 1 );
int eh = ( R << 1 );
e.Graphics.DrawEllipse( pen, ex, ey, ew, eh );
// 十字カーソルを描画する.
e.Graphics.DrawLine( pen, TheX0, 0, TheX0, ph );
e.Graphics.DrawLine( pen, 0, TheY0, pw, TheY0 );
}
}
private void pictureBox1_MouseDown( object sender, MouseEventArgs e )
{
TheX0 = e.X;
TheY0 = e.Y;
TheX1 = TheX0 + RECT_W;
TheY1 = TheY0;
TheX2 = TheX0 + RECT_W;
TheY2 = TheY0 + RECT_H;
TheX3 = TheX0;
TheY3 = TheY0 + RECT_H;
pictureBox1.Invalidate( true );
}
private bool RotatePoint(
ref double want_x,
ref double want_y,
int x,
int y,
double radian,
int org_x,
int org_y
)
{
// あらかじめ三角関数の値を計算しておく.
double cos = Math.Cos( radian );
double sin = Math.Sin( radian );
// いったん座標をシフト移動する.
double tmp_x = x - org_x;
double tmp_y = y - org_y;
// 座標を回転させる.
double buf_x = (( cos * tmp_x ) - ( sin * tmp_y ));
double buf_y = (( sin * tmp_x ) + ( cos * tmp_y ));
// 回転させた座標をシフト移動してもどす.
want_x = buf_x + org_x;
want_y = buf_y + org_y;
return true;
}
private void button1_Click( object sender, EventArgs e )
{
// 角度から弧度に変換.
const double ROTATE_DEG = 30.0;
double rad = Math.PI * ( ROTATE_DEG / 180.0 );
// クリックした場所が回転中心の座標.
int org_x = TheX0;
int org_y = TheY0;
// 回転させた座標を取得する.
double rot_x0 = 0;
double rot_y0 = 0;
RotatePoint( ref rot_x0, ref rot_y0, TheX0, TheY0, rad, org_x, org_y );
double rot_x1 = 0;
double rot_y1 = 0;
RotatePoint( ref rot_x1, ref rot_y1, TheX1, TheY1, rad, org_x, org_y );
double rot_x2 = 0;
double rot_y2 = 0;
RotatePoint( ref rot_x2, ref rot_y2, TheX2, TheY2, rad, org_x, org_y );
double rot_x3 = 0;
double rot_y3 = 0;
RotatePoint( ref rot_x3, ref rot_y3, TheX3, TheY3, rad, org_x, org_y );
// double から int へ丸める.
TheX0 = (int)( Math.Round( rot_x0 ));
TheY0 = (int)( Math.Round( rot_y0 ));
TheX1 = (int)( Math.Round( rot_x1 ));
TheY1 = (int)( Math.Round( rot_y1 ));
TheX2 = (int)( Math.Round( rot_x2 ));
TheY2 = (int)( Math.Round( rot_y2 ));
TheX3 = (int)( Math.Round( rot_x3 ));
TheY3 = (int)( Math.Round( rot_y3 ));
// 再描画を要請する.
this.Invalidate( true );
}
}
}