C#のWinFormsでワールド変換で図形を回転

コンピュータ

ワールド変換を使うと画像を回転することが出来るということなので、サンプルプログラムを作成してみたいと思います。

namespace PictureBox02;

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        // タイマーオブジェクトの生成と初期化
        if (this.components == null) return;
        var timer = new System.Windows.Forms.Timer(this.components)
        {
            Interval = 15,
        };
        // ピクチャボックスの生成
        var picbox = new PictureBox()
        {
            Dock = DockStyle.Fill,
            Parent = this,
        };
        Graphics? g = null;
        // イメージを初期化
        Action ImageInitiazlied = new Action(()=>
        {
            picbox.Image?.Dispose();
            picbox.Image = new Bitmap(picbox.Width, picbox.Height);
            g?.Dispose();
            g = Graphics.FromImage(picbox.Image);
        });
        // ピクチャボックスのリサイズイベント
        picbox.Resize += (s, e) => ImageInitiazlied();
        long lastClock = 0;
        int fpsCounter = 0;
        int fps = 0;
        bool timerExecutingFlag = false;
        long counter = 0;

        // 四角形
        Bitmap[] rectangles = new Bitmap[90];
        for(int i=0; i < 90; i++)
        {
            var b = new Bitmap(384, 384);
            using(var gg = Graphics.FromImage(b))
            {
                gg.ResetTransform();
                gg.TranslateTransform(128.0f, 128.0f);
                gg.RotateTransform((float)i);
                gg.TranslateTransform(-128.0f, -128.0f);
                gg.FillRectangle(Brushes.White, 64.0f, 64.0f, 128.0f, 128.0f);
            }
            rectangles[i] = b;
        }

        // フォームのロードイベント
        this.Load += (s, e) =>
        {
            // タイマーの開始
            timer.Start();
            lastClock = Environment.TickCount64;
            ImageInitiazlied();
        };
        // フォームのクローズイベント
        this.FormClosed += (s, e) =>
        {
            // タイマーの終了
            timer.Stop();
            g?.Dispose();
            picbox.Image?.Dispose();            
        };
        // タイマーイベント
        timer.Tick += (s, e) =>
        {

            if (Environment.TickCount64 > (lastClock+1000))
            {
                fps = fpsCounter;
                fpsCounter = 0;
                lastClock = Environment.TickCount64;
            }
            counter++;

            if (timerExecutingFlag) return;
            timerExecutingFlag = true;
            picbox.Invalidate();
            fpsCounter++;
            timerExecutingFlag = false;
        };
        Font fnt = new Font("", 12.0f);
        // ピクチャボックスのペイントイベント
        picbox.Paint += (s, e) =>
        {
            if (g == null) return;
            int i = (int)(counter % 90);

            g.Clear(Color.Blue);
            g.DrawString(string.Format("{0} {1}", fps, i), fnt, Brushes.White, 20, 20);

            g.DrawImage(rectangles[i], 64, 64);
        };
    }
}

実行

簡単に図形を回転させることが出来るかと思ったのですが、ワールド変換は画像と言いますかGraphicsオブジェクトに対して回転処理を施すようです。回転の中心座標を出すため試行錯誤しました。
回転する図形をあらかじめ角度を変えて90枚用意し、怪しげなタイマー処理で画像を切り替えてアニメーションさせています。

コメント