LoginSignup
2
4

More than 3 years have passed since last update.

C#で立体を描く簡易的なプログラム

Posted at

C#で立体を描くプログラム

立体を描くライブラリはたくさんありますが、今回はそれらは一切使いません。

「極力ライブラリや人の作ったものに頼らない」という考えでやっています。が、高級なことができない・・・。

立体を描くクラス

G3D.cs
using System;
using System.Drawing;
using System.Windows.Forms;

namespace _3D
{
    class G3D
    {
        private Bitmap canvas;
        private Graphics g;
        private PictureBox pictureBox;
        private double x_adj, y_adj;
        private double x_theta = 0, y_theta = 0, z_theta = 0;

        public G3D(PictureBox p)
        {
            pictureBox = p;
            canvas = new Bitmap(p.Width, p.Height);
            g = Graphics.FromImage(canvas);
            x_adj = p.Width / 2;
            y_adj = p.Height / 2;
        }

        public void cuboid(double x1, double y1, double z1, double x2, double y2, double z2)
        {
            g.Clear(Color.Black);

            Point[] p = { point_culc(x_theta, y_theta, z_theta, x1, y1, z1),
                 point_culc(x_theta, y_theta, z_theta, x2, y1, z1),
                 point_culc(x_theta, y_theta, z_theta, x2, y2, z1),
                 point_culc(x_theta, y_theta, z_theta, x1, y2, z1)};

            g.DrawPolygon(Pens.White, p);

            Point[] p1 = { point_culc(x_theta, y_theta, z_theta, x2, y1, z1),
                 point_culc(x_theta, y_theta, z_theta, x2, y2, z1),
                 point_culc(x_theta, y_theta, z_theta, x2, y2, z2),
                 point_culc(x_theta, y_theta, z_theta, x2, y1, z2)};

            g.DrawPolygon(Pens.White, p1);

            Point[] p2 = { point_culc(x_theta, y_theta, z_theta, x1, y1, z1),
                 point_culc(x_theta, y_theta, z_theta, x1, y2, z1),
                 point_culc(x_theta, y_theta, z_theta, x1, y2, z2),
                 point_culc(x_theta, y_theta, z_theta, x1, y1, z2)};

            g.DrawPolygon(Pens.White, p2);

            Point[] p3 = { point_culc(x_theta, y_theta, z_theta, x1, y1, z2),
                 point_culc(x_theta, y_theta, z_theta, x2, y1, z2),
                 point_culc(x_theta, y_theta, z_theta, x2, y2, z2),
                 point_culc(x_theta, y_theta, z_theta, x1, y2, z2)};

            g.DrawPolygon(Pens.White, p3);

            Point[] p4 = { point_culc(x_theta, y_theta, z_theta, x1, y1, z1),
                 point_culc(x_theta, y_theta, z_theta, x2, y1, z1),
                 point_culc(x_theta, y_theta, z_theta, x2, y1, z2),
                 point_culc(x_theta, y_theta, z_theta, x1, y1, z2)};

            g.DrawPolygon(Pens.White, p4);

            Point[] p5 = { point_culc(x_theta, y_theta, z_theta, x1, y2, z1),
                 point_culc(x_theta, y_theta, z_theta, x2, y2, z1),
                 point_culc(x_theta, y_theta, z_theta, x2, y2, z2),
                 point_culc(x_theta, y_theta, z_theta, x1, y2, z2)};

            g.DrawPolygon(Pens.White, p5);

            g.DrawLine(Pens.Red,
                point_culc(x_theta, y_theta, z_theta, 100, 0, 0),
                point_culc(x_theta, y_theta, z_theta, 0, 0, 0)
                );
            g.DrawLine(Pens.Green,
                point_culc(x_theta, y_theta, z_theta, 0, 100, 0),
                point_culc(x_theta, y_theta, z_theta, 0, 0, 0)
                );
            g.DrawLine(Pens.Yellow,
                point_culc(x_theta, y_theta, z_theta, 0, 0, 100),
                point_culc(x_theta, y_theta, z_theta, 0, 0, 0)
                );

            pictureBox.Image = canvas;
        }

        public void camera_change(double rotx,double roty,double rotz)
        {
            x_theta = rotx;
            y_theta = roty;
            z_theta = rotz;
            theta_lim(ref x_theta);
            theta_lim(ref y_theta);
            theta_lim(ref z_theta);
        }

        public void camera_step(double rotx, double roty, double rotz)
        {
            x_theta += rotx;
            y_theta += roty;
            z_theta += rotz;
            theta_lim(ref x_theta);
            theta_lim(ref y_theta);
            theta_lim(ref z_theta);
        }

        private void theta_lim(ref double t)
        {
            if (t > 360)
            {
                t -= 360;
            }
            if (t < 0)
            {
                t = 360 + t;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rotx">X軸回転角度</param>
        /// <param name="roty">Y軸回転角度</param>
        /// <param name="rotz">Z軸回転角度</param>
        /// <param name="x">X座標</param>
        /// <param name="y">Y座標</param>
        /// <param name="z">Z座標</param>
        private Point point_culc(double rotx, double roty, double rotz, double x, double y, double z)
        {
            //X軸周りで回転
            double X_x = x * 1;
            double Y_x = y * Math.Cos(rotx * (Math.PI / 180)) - z * Math.Sin(rotx * (Math.PI / 180));
            double Z_x = y * Math.Sin(rotx * (Math.PI / 180)) + z * Math.Cos(rotx * (Math.PI / 180));

            //Y軸周りで回転
            double X_y = X_x * Math.Cos(roty * (Math.PI / 180)) + Z_x * Math.Sin(roty * (Math.PI / 180));
            double Y_y = Y_x * 1;
            double Z_y = -X_x * Math.Sin(roty * (Math.PI / 180)) + Z_x * Math.Cos(roty * (Math.PI / 180));

            //Z軸周りで回転
            double X_z = X_y * Math.Cos(rotz * (Math.PI / 180)) - Y_y * Math.Sin(rotz * (Math.PI / 180));
            double Y_z = X_y * Math.Sin(rotz * (Math.PI / 180)) + Y_y * Math.Cos(rotz * (Math.PI / 180));
            double Z_z = Z_y * 1;

            return new Point((int)(X_z + x_adj), (int)(Y_z + y_adj));
        }
    }
}

3D描画するクラスです。
コンストラクタは、描画するためのPictureBoxを引数に取っています。

void cuboid(double x1, double y1, double z1, double x2, double y2, double z2)

cuboid関数は、直方体の対角線上にある2点の座標を引数に取ります。
実行すれば、PictureBoxに直方体を描くことができます。

void camera_change(double rotx,double roty,double rotz)
void camera_step(double rotx, double roty, double rotz)

camera_change関数とcamera_step関数は視点を変える関数です。X,Y,Z軸の回転角度を引数に取ります。
camera_change関数は、指定された回転角度にします。
camera_step関数は、現在の回転角度から指定された回転角度分だけ回転させます。

実行結果

3d.png

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4