Matrix3D(数式およびC#)
Matrix3D
データ構造とコンストラクタ
public class Matrix3D
{
#region データ
public double this[int i, int j]
{
get
{
if (i == 0 && j == 0) { return M00; }
if (i == 0 && j == 1) { return M01; }
if (i == 0 && j == 2) { return M02; }
if (i == 1 && j == 0) { return M10; }
if (i == 1 && j == 1) { return M11; }
if (i == 1 && j == 2) { return M12; }
if (i == 2 && j == 0) { return M20; }
if (i == 2 && j == 1) { return M21; }
if (i == 2 && j == 2) { return M22; }
throw new IndexOutOfRangeException();
}
}
public double M00;
public double M01;
public double M02;
public double M10;
public double M11;
public double M12;
public double M20;
public double M21;
public double M22;
public Vector3D GetRow(int index)
{
Vector3D ret = Vector3D.Zero;
for (int i = 0; i < 3; i++)
{
ret[i] = this[index, i];
}
return ret;
}
public Vector3D GetCol(int index)
{
Vector3D ret = Vector3D.Zero;
for (int i = 0; i < 3; i++)
{
ret[i] = this[i, index];
}
return ret;
}
public Vector3D Row0
{
get
{
return new Vector3D(M00, M01, M02);
}
}
public Vector3D Row1
{
get
{
return new Vector3D(M10, M11, M12);
}
}
public Vector3D Row2
{
get
{
return new Vector3D(M20, M21, M22);
}
}
public Vector3D Column0
{
get
{
return new Vector3D(M00, M10, M20);
}
}
public Vector3D Column1
{
get
{
return new Vector3D(M01, M11, M21);
}
}
public Vector3D Column2
{
get
{
return new Vector3D(M02, M12, M22);
}
}
#endregion
#region コンストラクタ
public Matrix3D(double m00, double m01, double m02, double m10, double m11, double m12, double m20, double m21, double m22)
{
M00 = m00;
M01 = m01;
M02 = m02;
M10 = m10;
M11 = m11;
M12 = m12;
M20 = m20;
M21 = m21;
M22 = m22;
}
public Matrix3D(Vector3D row1, Vector3D row2, Vector3D row3)
: this(row1.X, row1.Y, row1.Z, row2.X, row2.Y, row2.Z, row3.X, row3.Y, row3.Z) { }
public static Matrix3D MakeFromRow(Vector3D row1, Vector3D row2, Vector3D row3)
{
Matrix3D ret = new Matrix3D(
row1.X, row1.Y, row1.Z,
row2.X, row2.Y, row2.Z,
row3.X, row3.Y, row3.Z);
return ret;
}
//コンストラクタに転置ブチ込めるようになるまでのつなぎ
public static Matrix3D MakeFromColumn(Vector3D col1, Vector3D col2, Vector3D col3)
{
Matrix3D ret = new Matrix3D(
col1.X, col2.X, col3.X,
col1.Y, col2.Y, col3.Y,
col1.Z, col2.Z, col3.Z);
return ret;
}
#endregion
}
基本操作
$$
\begin{bmatrix}
a & b & c \\
d & e & f \\
g & h & i
\end{bmatrix}
$$
に対して
単位行列(unit)
$$
\begin{bmatrix}
1 & 0 & 0 \\
0 & 1 & 0 \\
0 & 0 & 1
\end{bmatrix}
$$
転置(transpose)
$$
\begin{bmatrix}
a & d & g \\
b & e & h \\
c & f & i
\end{bmatrix}
$$
行列式(determinant)
$$
a(ei - fh) - b(di - fg) + c(dh - eg)
$$
逆行列(inverse)
$$
\frac{1}{det}adj
$$
すなわち
$$
\frac{1}{\text{det}}\begin{bmatrix}
ei-fh & ch-bi & bf-ce \\
fg-di & ai-cg & cd-af \\
dh-ge & bg-ah & ae-bd
\end{bmatrix}
$$
余因子行列(cofactor)
$$
\begin{bmatrix}
ei-fh & fg-di & dh-ge \\
ch-bi & ai-cg & bg-ah \\
bf-ce & cd-af & ae-bd
\end{bmatrix}
$$
随伴行列(adjoint)
余因子行列の転置
$$
\begin{bmatrix}
ei-fh & ch-bi & bf-ce \\
fg-di & ai-cg & cd-af \\
dh-ge & bg-ah & ae-bd
\end{bmatrix}
$$
基本操作(コード)
#region 基本操作
public static Matrix3D Unit
{
get
{
return new Matrix3D(
1, 0, 0,
0, 1, 0,
0, 0, 1
);
}
}
//転置
public Matrix3D Transpose
{
//(m00,m01,m02) (m00,m10,m20)
//(m10,m11,m12) -> (m01,m11,m21)
//(m20,m21,m22) (m02,m12,m22)
get
{
return new Matrix3D(
M00, M10, M20,
M01, M11, M21,
M02, M12, M22);
}
}
//行列式
public double Determinant
{
get
{
//m00,m01,m02
//m10,m11,m12
//m20,m21,m22
//return M00 * M11 * M22 + M01 * M12 * M20 + M02 * M10 * M21
// - M02 * M11 * M20 - M01 * M10 * M22 - M00 * M12 * M21;
//これでもいいのか?
//Vector3.Dot(this.Row1, (Vector3.Cross(this.Row2, this.Row3)));
return M00 * (M11 * M22 - M12 * M21) + M01 * (M12 * M20 - M10 * M22) + M02 * (M10 * M21 - M11 * M20);
}
}
//逆行列
public Matrix3D Inverse
{
get
{
return Adjoint / Determinant;
}
}
//小行列:thisからi行j列を省いたもの
public Matrix2D SubMatrix(int i, int j)
{
List<double> ms = new List<double>();
for (int k = 0; k < 3; k++)
{
if (i != k)
{
for (int l = 0; l < 3; l++)
{
if (j != l) { ms.Add(this[k, l]); }
}
}
}
return new Matrix2D(ms[0], ms[1], ms[2], ms[3]);
}
//余因子:対応する小行列に対応する符号を付けたもの
public double GetCofactor(int i, int j)
{
int sign;
if ((i + j) % 2 == 0) { sign = 1; }
else { sign = -1; }
return sign * (SubMatrix(i, j).Determinant);
}
//余因子行列
public Matrix3D Cofactor
{
get
{
double c00 = GetCofactor(0, 0);
double c01 = GetCofactor(0, 1);
double c02 = GetCofactor(0, 2);
double c10 = GetCofactor(1, 0);
double c11 = GetCofactor(1, 1);
double c12 = GetCofactor(1, 2);
double c20 = GetCofactor(2, 0);
double c21 = GetCofactor(2, 1);
double c22 = GetCofactor(2, 2);
return new Matrix3D(c00, c01, c02, c10, c11, c12, c20, c21, c22);
}
}
//随伴行列:余因子行列の転置
public Matrix3D Adjoint
{
get
{
double c00 = GetCofactor(0, 0);
double c01 = GetCofactor(0, 1);
double c02 = GetCofactor(0, 2);
double c10 = GetCofactor(1, 0);
double c11 = GetCofactor(1, 1);
double c12 = GetCofactor(1, 2);
double c20 = GetCofactor(2, 0);
double c21 = GetCofactor(2, 1);
double c22 = GetCofactor(2, 2);
return new Matrix3D(c00, c01, c02, c10, c11, c12, c20, c21, c22).Transpose;
}
}
//見栄え用ヘルパー
private static double sin(double radian)
{
return Math.Sin(radian);
}
private static double cos(double radian)
{
return Math.Cos(radian);
}
#endregion
演算子のオーバーロード
#region Operator
public static Matrix3D operator +(Matrix3D m1, Matrix3D m2)
{
return new Matrix3D(
m1.M00 + m2.M00,
m1.M01 + m2.M01,
m1.M02 + m2.M02,
m1.M10 + m2.M10,
m1.M11 + m2.M11,
m1.M12 + m2.M12,
m1.M20 + m2.M20,
m1.M21 + m2.M21,
m1.M22 + m2.M22
);
}
public static Matrix3D operator -(Matrix3D m1, Matrix3D m2)
{
return new Matrix3D(
m1.M00 - m2.M00,
m1.M01 - m2.M01,
m1.M02 - m2.M02,
m1.M10 - m2.M10,
m1.M11 - m2.M11,
m1.M12 - m2.M12,
m1.M20 - m2.M20,
m1.M21 - m2.M21,
m1.M22 - m2.M22
);
}
public static Matrix3D operator *(Matrix3D m, double f)
{
return new Matrix3D(
m.M00 * f, m.M01 * f, m.M02 * f,
m.M10 * f, m.M11 * f, m.M12 * f,
m.M20 * f, m.M21 * f, m.M22 * f);
}
public static Matrix3D operator *(double f, Matrix3D m)
{
return new Matrix3D(
m.M00 * f, m.M01 * f, m.M02 * f,
m.M10 * f, m.M11 * f, m.M12 * f,
m.M20 * f, m.M21 * f, m.M22 * f);
}
#region Vector2D
//逆の演算はベクトルが転置しないと無理
//Matrix3の演算が右側に転置ベクトルを受ける形式になっているので
public static Vector2D operator *(Vector2D v, Matrix3D m)
{
//(x,y,1)* M00 M01 M02
// M10 M11 M12
// M20 M21 M22
return new Vector2D(
v.X * m.M00 + v.Y * m.M10 + 1 * m.M20,
v.X * m.M01 + v.Y * m.M11 + 1 * m.M21
);
}
//通常ベクトルを右に受けたら自動的に転置
public static Vector2D operator *(Matrix3D m, Vector2D v)
{
// M00 M01 M02 : x
// M10 M11 M12 : y
// M20 M21 M22 : 1
return new Vector2D(
v.X * m.M00 + v.Y * m.M01 + 1 * m.M02,
v.X * m.M10 + v.Y * m.M11 + 1 * m.M12
);
}
#endregion
#region Vector3D
//Vector3Dは他のプロジェクトに良くコピペするので
//余計な演算を実装しないようにしておく
public static Vector3D operator *(Vector3D v, Matrix3D m1)
{
Vector3D ret = Vector3D.Zero;
for (int i = 0; i < 3; i++)
{
ret[i] = Vector3D.Dot(m1.GetCol(i), v);
}
return ret;
}
public static Vector3D operator *(Matrix3D m1, Vector3D v)
{
// M00 M01 M02 : x
// M10 M11 M12 : y
// M20 M21 M22 : z
Vector3D ret = Vector3D.Zero;
for (int i = 0; i < 3; i++)
{
ret[i] = Vector3D.Dot(m1.GetRow(i), v);
}
return ret;
}
#endregion
public static Matrix3D operator *(Matrix3D m1, Matrix3D m2)
{
//左項行ベクトルと右項列ベクトルの内積→出力の成分
//左項は行ベクトルなのでそのまま
//右項は列ベクトルなので鏡像反転からの回転=転置
//(m00,m01,m02) (m00,m01,m02)
//(m10,m11,m12) (m10,m11,m12)
//(m20,m21,m22) (m20,m21,m22)
//↓
//行:(m00,m01,m02) 列:(m00,m10,m20)
//行:(m10,m11,m12) 列:(m01,m11,m21)
//行:(m20,m21,m22) 列:(m02,m12,m22)
return new Matrix3D(
//1行目
m1.M00 * m2.M00 + m1.M01 * m2.M10 + m1.M02 * m2.M20,
m1.M00 * m2.M01 + m1.M01 * m2.M11 + m1.M02 * m2.M21,
m1.M00 * m2.M02 + m1.M01 * m2.M12 + m1.M02 * m2.M22,
//2行目
m1.M10 * m2.M00 + m1.M11 * m2.M10 + m1.M12 * m2.M20,
m1.M10 * m2.M01 + m1.M11 * m2.M11 + m1.M12 * m2.M21,
m1.M10 * m2.M02 + m1.M11 * m2.M12 + m1.M12 * m2.M22,
//3行目
m1.M20 * m2.M00 + m1.M21 * m2.M10 + m1.M22 * m2.M20,
m1.M20 * m2.M01 + m1.M21 * m2.M11 + m1.M22 * m2.M21,
m1.M20 * m2.M02 + m1.M21 * m2.M12 + m1.M22 * m2.M22
);
}
public static Matrix3D operator /(Matrix3D m, double f)
{
return new Matrix3D(
m.M00 / f, m.M01 / f, m.M02 / f,
m.M10 / f, m.M11 / f, m.M12 / f,
m.M20 / f, m.M21 / f, m.M22 / f);
}
//値の等価を調べる
public override bool Equals(System.Object obj)
{
//どちらかnullないし型違いならfalse
if (obj == null || this.GetType() != obj.GetType())
{
return false;
}
Matrix3D m = (Matrix3D)obj;
return (this.M00 == m.M00) && (this.M01 == m.M01) && (this.M02 == m.M02)
&& (this.M10 == m.M10) && (this.M11 == m.M11) && (this.M12 == m.M12)
&& (this.M20 == m.M20) && (this.M21 == m.M21) && (this.M22 == m.M22);
}
public override int GetHashCode()
{
return this.M00.GetHashCode() ^ this.M01.GetHashCode() ^ this.M02.GetHashCode()
^ this.M10.GetHashCode() ^ this.M11.GetHashCode() ^ this.M12.GetHashCode()
^ this.M20.GetHashCode() ^ this.M21.GetHashCode() ^ this.M22.GetHashCode();
}
public static bool operator ==(Matrix3D m1, Matrix3D m2)
{
//参照が等しいなら必ず等しい
//両方ともnullないし両方とも同じ参照ならreturn true
if (System.Object.ReferenceEquals(m1, m2))
{
return true;
}
//片方だけがnullならばreturn false
if (((object)m1 == null) || ((object)m2 == null))
{
return false;
}
//値のチェック
return m1.Equals(m2);
}
public static bool operator !=(Matrix3D m1, Matrix3D m2)
{
return !(m1 == m2);
}
#endregion
アフィン変換2D(同次座標)
平行移動
#region Translation2D
public static Matrix3D CreateTranslateMatrixV(int dx, int dy)
{
//Vector2Dを転置して縦ベクトルを右から受ける場合
return new Matrix3D(
1, 0, dx,
0, 1, dy,
0, 0, 1);
}
public static Matrix3D CreateTranslateMatrixH(int dx, int dy)
{
//転置せず横ベクトルを左から受ける場合
return new Matrix3D(
1, 0, 0,
0, 1, 0,
dx, dy, 1);
}
public static Matrix3D CreateTranslateMatrixV(double dx, double dy)
{
//Vector2Dを転置して縦ベクトルを右から受ける場合
return new Matrix3D(
1, 0, dx,
0, 1, dy,
0, 0, 1);
}
public static Matrix3D CreateTranslateMatrixH(double dx, double dy)
{
//転置せず横ベクトルを左から受ける場合
return new Matrix3D(
1, 0, 0,
0, 1, 0,
dx, dy, 1);
}
public static Matrix3D CreateTranslateMatrixV(Vector2D delta)
{
//Vector2Dを転置して縦ベクトルを右から受ける場合
return new Matrix3D(
1, 0, delta.X,
0, 1, delta.Y,
0, 0, 1);
}
public static Matrix3D CreateTranslateMatrixH(Vector2D delta)
{
//転置せず横ベクトルを左から受ける場合
return new Matrix3D(
1, 0, 0,
0, 1, 0,
delta.X, delta.Y, 1);
}
public void Translate(ref Vector2D v, Vector2D delta)
{
//1,0,dx x
//0,1,dy y
//0,0, 1 1
double dx = 1 * v.X + 0 * v.Y + delta.X * 1;
double dy = 0 * v.X + 1 * v.Y + delta.Y * 1;
//double dz = 0 * v.X + 0 * v.Y + 1 * 1;
v.Set_Val(dx, dy);
}
#endregion
スケール
#region Scale2D
public static Matrix3D CreateScaleMatrix(double scale)
{
return CreateScaleMatrix(scale, scale);
}
public static Matrix3D CreateScaleMatrix(double sx, double sy)
{
//通常ベクトルだろうが転置ベクトルだろうが出力変わらず
return new Matrix3D(
sx, 0, 0,
0, sy, 0,
0, 0, 1);
}
public void Scale(ref Vector2D v, double scale)
{
this.Scale(ref v, scale, scale);
}
public void Scale(ref Vector2D v, double sx, double sy)
{
//sx,0,0 x
//0,sy,0 y
//0,0, 1 1
double dx = sx * v.X + 0 * v.Y + 0 * 1;
double dy = 0 * v.X + sy * v.Y + 0 * 1;
double dz = 0 * v.X + 0 * v.Y + 1 * 1;
v.Set_Val(dx, dy);
}
//任意向きスケール
public static Matrix3D CreateScaleMatrix(Vector2D direction, double scale)
{
double k = scale;
double x = direction.X;
double y = direction.Y;
return new Matrix3D(
1 + (k - 1) * x * x, (k - 1) * x * y, 0,
(k - 1) * x * y, 1 + (k - 1) * y * y, 0,
0, 0, 1);
}
//ピボット
public static Matrix3D CreatePivotScaleMatrix(Vector2D pivot, double scale)
{
Matrix3D T = CreateTranslateMatrixV(pivot.X, pivot.Y);
Matrix3D S = CreateScaleMatrix(scale);
Matrix3D TR = CreateTranslateMatrixV(-pivot.X, -pivot.Y);
return T * S * TR;
}
public static Matrix3D CreatePivotScaleMatrix(Vector2D pivot, double sx, double sy)
{
Matrix3D T = CreateTranslateMatrixV(pivot.X, pivot.Y);
Matrix3D S = CreateScaleMatrix(sx, sy);
Matrix3D TR = CreateTranslateMatrixV(-pivot.X, -pivot.Y);
return T * S * TR;
}
public static Matrix3D CreatePivotScaleMatrix(Vector2D pivot, Vector2D direction, double scale)
{
Matrix3D T = CreateTranslateMatrixV(pivot.X, pivot.Y);
Matrix3D S = CreateScaleMatrix(direction, scale);
Matrix3D TR = CreateTranslateMatrixV(-pivot.X, -pivot.Y);
return T * S * TR;
}
#endregion
回転
#region Rotation2D
//角度渡し
//2D
public static Matrix3D CreateRotationMatrixV_Degree(double degree)
{
//スクリーン座標において以下は時計回転
//デカルト座標においては反時計回りとなる
//xが縮み、yが伸びる、すなわちy+に向かって回転する
//double dx = v.X * Math.Cos(radian) - v.Y * Math.Sin(radian);
//double dy = v.X * Math.Sin(radian) + v.Y * Math.Cos(radian);
double radian = degree * (Math.PI / 180);
//縦ベクトルを右から掛けるならy+に向かって回転する
//横ベクトルを左から掛けるならx+に向かって回転する
return new Matrix3D(
cos(radian), -sin(radian), 0,
sin(radian), cos(radian), 0,
0, 0, 1
);
}
public static Matrix3D CreateRotationMatrixH_Degree(double degree)
{
double radian = degree * (Math.PI / 180);
//縦ベクトルを右から掛けるならx+に向かって回転する
//横ベクトルを左から掛けるならy+に向かって回転する
return new Matrix3D(
cos(radian), sin(radian), 0,
-sin(radian), cos(radian), 0,
0, 0, 1
);
}
public static Matrix3D CreateRotationMatrixV(double radian)
{
//縦ベクトルを右から掛けるならy+に向かって回転する
//横ベクトルを左から掛けるならx+に向かって回転する
return new Matrix3D(
cos(radian), -sin(radian), 0,
sin(radian), cos(radian), 0,
0, 0, 1
);
}
public static Matrix3D CreateRotationMatrixH(double radian)
{
//縦ベクトルを右から掛けるならx+に向かって回転する
//横ベクトルを左から掛けるならy+に向かって回転する
return new Matrix3D(
cos(radian), sin(radian), 0,
-sin(radian), cos(radian), 0,
0, 0, 1
);
}
public void Rotate_Degree(ref Vector2D v, double angle)
{
double radian = angle * (Math.PI / 180);
//cosθ,-sinθ,0 x
//sinθ, cosθ,0 y
// 0, 0,1 1
//縦ベクトルを右から掛けるならy+に向かって回転する
//横ベクトルを左から掛けるならx+に向かって回転する
double dx = cos(radian) * v.X - sin(radian) * v.Y + 0 * 1;
double dy = sin(radian) * v.X + cos(radian) * v.Y + 0 * 1;
//double dz = 0 * v.X + 0 * v.Y + 1 * 1;
v.Set_Val(dx, dy);
}
public void Rotate_Radian(ref Vector2D v, double radian)
{
//縦ベクトルを右から掛けるならy+に向かって回転する
//横ベクトルを左から掛けるならx+に向かって回転する
double dx = cos(radian) * v.X - sin(radian) * v.Y + 0 * 1;
double dy = sin(radian) * v.X + cos(radian) * v.Y + 0 * 1;
//double dz = 0 * v.X + 0 * v.Y + 1 * 1;
v.Set_Val(dx, dy);
}
//ピボット
public static Matrix3D CreatePivotRotationMatrixV_Degree(Vector2D pivot, double degree)
{
Matrix3D T = CreateTranslateMatrixV(pivot.X, pivot.Y);
Matrix3D S = CreateRotationMatrixV_Degree(degree);
Matrix3D TR = CreateTranslateMatrixV(-pivot.X, -pivot.Y);
return T * S * TR;
}
public static Matrix3D CreatePivotRotationMatrixV(Vector2D pivot, double radian)
{
Matrix3D T = CreateTranslateMatrixV(pivot.X, pivot.Y);
Matrix3D S = CreateRotationMatrixV(radian);
Matrix3D TR = CreateTranslateMatrixV(-pivot.X, -pivot.Y);
return T * S * TR;
}
//ピボット
public static Matrix3D CreatePivotRotationMatrixH_Degree(Vector2D pivot, double degree)
{
Matrix3D T = CreateTranslateMatrixV(pivot.X, pivot.Y);
Matrix3D S = CreateRotationMatrixH_Degree(degree);
Matrix3D TR = CreateTranslateMatrixV(-pivot.X, -pivot.Y);
return T * S * TR;
}
public static Matrix3D CreatePivotRotationMatrixH(Vector2D pivot, double radian)
{
Matrix3D T = CreateTranslateMatrixV(pivot.X, pivot.Y);
Matrix3D S = CreateRotationMatrixH(radian);
Matrix3D TR = CreateTranslateMatrixV(-pivot.X, -pivot.Y);
return T * S * TR;
}
#endregion
射影、鏡映、スキュ
#region Projection2D
//X軸へのProjection
public static Matrix3D CreateProjection2D_X()
{
return CreateScaleMatrix(new Vector2D(0, 1), 0);
}
//Y軸へのProjection
public static Matrix3D CreateProjection2D_Y()
{
return CreateScaleMatrix(new Vector2D(1, 0), 0);
}
//任意軸にProjection
public static Matrix3D CreateProjection2D_N(Vector2D n)
{
return CreateScaleMatrix(n, 0);
}
#endregion
#region Reflection2D
//X軸へのReflection
public static Matrix3D CreateReflection2D_X()
{
return CreateScaleMatrix(new Vector2D(0, 1), -1);
}
//Y軸へのReflection
public static Matrix3D CreateReflection2D_Y()
{
return CreateScaleMatrix(new Vector2D(1, 0), -1);
}
//任意軸にReflection
public static Matrix3D CreateReflection2D_N(Vector2D n)
{
return CreateScaleMatrix(n, -1);
}
#endregion
#region スキュー(せん断)2D
public static Matrix3D CreateSkew2D_X(double skewScale)
{
//X座標をY座標でせん断する
double s = skewScale;
return new Matrix3D(
1, 0, 0,
s, 1, 0,
0, 0, 1
);
}
public static Matrix3D CreateSkew2D_Y(double skewScale)
{
//Y座標をX座標でせん断する
double s = skewScale;
return new Matrix3D(
1, s, 0,
0, 1, 0,
0, 0, 1
);
}
#endregion
#endregion
アフィン変換3D(コード)
#region アフィン3D変換
#region Scale3D
public static Matrix3D CreateScale3D(double scale)
{
return CreateScale3D(scale, scale, scale);
}
public static Matrix3D CreateScale3D(double sx, double sy, double sz)
{
//通常ベクトルだろうが転置ベクトルだろうが出力変わらず
return new Matrix3D(
sx, 0, 0,
0, sy, 0,
0, 0, sz);
}
//任意向きスケール
public static Matrix3D CreateScale3D(Vector3D direction, double scale)
{
double k = scale;
double x = direction.X;
double y = direction.Y;
double z = direction.Z;
return new Matrix3D(
1 + (k - 1) * x * x, (k - 1) * x * y, (k - 1) * x * z,
(k - 1) * x * y, 1 + (k - 1) * y * y, (k - 1) * y * z,
(k - 1) * x * z, (k - 1) * y * z, 1 + (k - 1) * z * z);
}
#endregion
#region Rotation3D
//角度渡し
//軸を基準とした回転
public static Matrix3D CreateRotation3D_XV(double degree)
{
//右から縦ベクトルを掛けると
//x軸を回転の基準としてz+からy+に向かって回転する
//左から横ベクトルを掛けると
//x軸を回転の基準としてy+からz+に向かって回転する
double radian = degree * (Math.PI / 180);
return new Matrix3D(
1, 0, 0,
0, cos(radian), sin(radian),
0, -sin(radian), cos(radian)
);
}
public static Matrix3D CreateRotation3D_XH(double degree)
{
double radian = degree * (Math.PI / 180);
return new Matrix3D(
1, 0, 0,
0, cos(radian), -sin(radian),
0, sin(radian), cos(radian)
);
}
public static Matrix3D CreateRotation3D_YV(double degree)
{
//右から縦ベクトルを掛けると
//y軸を回転の基準としてx+からz+に向かって回転する
//左から横ベクトルを掛けると
//y軸を回転の基準としてz+からx+に向かって回転する
double radian = degree * (Math.PI / 180);
return new Matrix3D(
cos(radian), 0, -sin(radian),
0, 1, 0,
sin(radian), 0, cos(radian)
);
}
public static Matrix3D CreateRotation3D_YH(double degree)
{
double radian = degree * (Math.PI / 180);
return new Matrix3D(
cos(radian), 0, sin(radian),
0, 1, 0,
-sin(radian), 0, cos(radian)
);
}
public static Matrix3D CreateRotation3D_ZV(double degree)
{
//右から縦ベクトルを掛けると
//z軸を回転の基準としてy+からx+に向かって回転する
//左から横ベクトルを掛けると
//z軸を回転の基準としてx+からy+に向かって回転する
double radian = degree * (Math.PI / 180);
return new Matrix3D(
cos(radian), sin(radian), 0,
-sin(radian), cos(radian), 0,
0, 0, 1
);
}
public static Matrix3D CreateRotation3D_ZH(double degree)
{
double radian = degree * (Math.PI / 180);
return new Matrix3D(
cos(radian), -sin(radian), 0,
sin(radian), cos(radian), 0,
0, 0, 1
);
}
//任意軸回転
public static Matrix3D CreateRotation3D_N(double degree, Vector3D axis)
{
double r = degree * (Math.PI / 180);
double x = axis.X;
double y = axis.Y;
double z = axis.Z;
double cos = Matrix3D.cos(r);
double sin = Matrix3D.sin(r);
//反時計回り
return new Matrix3D(
x * x * (1 - cos) + cos, x * y * (1 - cos) + z * sin, x * z * (1 - cos) - y * sin,
x * y * (1 - cos) - z * sin, y * y * (1 - cos) + cos, y * z * (1 - cos) + z * sin,
x * z * (1 - cos) + y * sin, y * z * (1 - cos) - x * sin, z * z * (1 - cos) + cos
);
}
#endregion
#region Projection3D
public static Matrix3D CreateProjection3D_XY()
{
//1,0,0
//0,1,0
//0,0,0
return CreateScale3D(new Vector3D(0, 0, 1), 0);
}
public static Matrix3D CreateProjection3D_XZ()
{
//1,0,0
//0,0,0
//0,0,1
return CreateScale3D(new Vector3D(0, 1, 0), 0);
}
public static Matrix3D CreateProjection3D_YZ()
{
//0,0,0
//0,1,0
//0,0,1
return CreateScale3D(new Vector3D(1, 0, 0), 0);
}
public static Matrix3D CreateProjection3D_N(Vector3D n)
{
return CreateScale3D(n, 0);
}
#endregion
#region Reflection3D
public static Matrix3D CreateReflection3D_XY()
{
return CreateScale3D(new Vector3D(0, 0, 1), -1);
}
public static Matrix3D CreateReflection3D_XZ()
{
return CreateScale3D(new Vector3D(0, 1, 0), -1);
}
public static Matrix3D CreateReflection3D_YZ()
{
return CreateScale3D(new Vector3D(1, 0, 0), -1);
}
public static Matrix3D CreateReflection3D_N(Vector3D n)
{
return CreateScale3D(n, -1);
}
#endregion
#region スキュー(せん断)3D
public static Matrix3D CreateSkew3D_XY(double skew1, double skew2)
{
//XY平面をZ座標でせん断する
double s = skew1;
double t = skew2;
return new Matrix3D(
1, 0, 0,
0, 1, 0,
s, t, 1
);
}
public static Matrix3D CreateSkew3D_XZ(double skew1, double skew2)
{
//XY平面をZ座標でせん断する
double s = skew1;
double t = skew2;
return new Matrix3D(
1, 0, 0,
s, 1, t,
0, 0, 1
);
}
public static Matrix3D CreateSkew3D_YZ(double skew1, double skew2)
{
//XY平面をZ座標でせん断する
double s = skew1;
double t = skew2;
return new Matrix3D(
1, s, t,
0, 1, 0,
0, 0, 1
);
}
#endregion
#endregion
アフィン変換3D(同次座標の数式)
平行移動
$$
\begin{bmatrix}
1 & 0 & 0 & t_x \\
0 & 1 & 0 & t_y \\
0 & 0 & 1 & t_z \\
0 & 0 & 0 & 1 \end{bmatrix}
$$
スケール
$$
\begin{bmatrix}
s_x & 0 & 0 & 0 \\
0 & s_y & 0 & 0 \\
0 & 0 & s_z & 0 \\
0 & 0 & 0 & 1
\end{bmatrix}
$$
回転
X軸
$$
\begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & \cos \theta & -\sin \theta & 0 \\
0 & \sin \theta & \cos \theta & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
$$
Y軸
$$
\begin{bmatrix}
\cos \theta & 0 & \sin \theta & 0 \\
0 & 1 & 0 & 0 \\
-\sin \theta & 0 & \cos \theta & 0 \\
0 & 0 & 0 & 1 \end{bmatrix}
$$
Z軸
$$
\begin{bmatrix} \cos \theta & -\sin \theta & 0 & 0 \\
\sin \theta & \cos \theta & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & 1 \end{bmatrix}
$$
スキュ
X軸方向
$$
\begin{bmatrix}
1 & 0 & s_x & 0 \\
0 & 1 & s_y & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & 1 \end{bmatrix}
$$
Y軸方向
$$
\begin{bmatrix}
1 & s_x & 0 & 0 \\
s_y & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & 1 \end{bmatrix}
$$
鏡映
X軸
$$
\begin{bmatrix}
-1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
$$
Y軸
$$
\begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & -1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & 1 \end{bmatrix}
$$
Z軸
$$
\begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & -1 & 0 \\
0 & 0 & 0 & 1 \end{bmatrix}
$$
この記事が気に入ったらサポートをしてみませんか?