第一节:矩阵的数学定义
1.矩阵的定义
在线性代数中,矩阵就是以行和列形式组成的矩形数字块(向量是标量的数组,矩阵是向量的数组)。
2.矩阵的记法
矩阵我们通常使用大中括号来表示,也可以使用竖线的方式来表示,通常用大写字母来表示矩阵。当使用矩阵的分量时,我们用下标法来表示矩阵的分量,注意的是矩阵的分量是从1开始,而不是0。
3.方阵
行数和列数相同的矩阵称为方阵。方阵的概念非常重要,通常在3D中使用的矩阵就是2x2,3x3,4x4方阵。
方阵的对角线元素就是方阵中分量行号和列号相同的元素,例如3x3矩阵中的m11,m22,m33这三个分量就是对角线元素,其他的元素则是非对角线元素。
4.对角矩阵
在方阵中,如果非对角元素都为0,则该方阵称为对角矩阵。例如
5.单位矩阵
在对角矩阵中,如果对角线元素都为1,则该对角矩阵为单位矩阵。单位矩阵是一种特殊的对角矩阵,单位矩阵乘以任意矩阵得到都是原来的矩阵。例如,3D单位矩阵如下
6.向量的矩阵含义
向量也可以看做为矩阵,行向量可以看做是1xn矩阵,列向量可以看做nx1矩阵。
7.矩阵的转置
所谓的矩阵的转置就是将矩阵的行元素变为矩阵的列元素,将矩阵的列元素变为矩阵的行元素,矩阵M的转置记做MT。
行向量的矩阵转置为列向量,列向量的矩阵转置为行向量。
对于任意对角矩阵D,都有DT=D,同样对于单位矩阵I,都有IT = I。
对于任意矩阵D,都有(DT)T =D,即矩阵转置两次等于其本身。
8.标量和矩阵的乘法
标量k和矩阵M相乘会得到一个和原矩阵维数相同的矩阵N,矩阵N的每个元素等于矩阵M的每个元素与标量k相乘,公式如下。
9.矩阵与矩阵的乘法
矩阵的乘法定义为一个r x n矩阵A与一个n x c矩阵B相乘,则得到一个r x c矩阵AB。
例如一个4 x 2矩阵A与一个2 x 5矩阵B相乘,得到的是一个4x5矩阵AB。
对于新得到的矩阵AB记做C,则矩阵C的每个元素Cij等于矩阵A第i行向量与矩阵B第j列向量的点乘结果。示例如下
矩阵C的元素c24就等于矩阵A的第二行向量与矩阵B的第4行向量的点乘的结果。
10.向量与矩阵的乘法
因为向量也属于矩阵,所以也必须要满足矩阵与矩阵的乘法规则,所以对于行向量而言,行向量要左乘矩阵,对于列向量而言,列向量要右乘矩阵。行向量和列向量与一个相同的矩阵相乘的时候会得到不同的结果,因此我们要注意这是行向量和列向量的区别之一,在进行矩阵运算时特别小心。
示例如下,对于行向量和列向量而言,得到的结果是不一样的。
、
我们觉得使用行向量是比较符合的,以为行向量是左乘矩阵,符合我们的书写和理解,例如vABC,行向量v乘以3个矩阵得到最后的向量。但是对于ABCh,列向量h要从右往左乘才符合我们的理解。在DX3中使用的是行向量,但是在OpenGL中使用的是列向量,因此在运算前要注意行向量和列向量的转置才能保证不会出现计算的问题。
第二节:矩阵的几何解释
1.2D向量与矩阵相乘的几何意义
对于2D向量v乘以矩阵M得到的依然是2D向量,所以我们可以理解矩阵M是对向量v的一种坐标变换。
2D向量由原来的[1 1]变换为了[1 3]在几何中的表示如下,我们可以将矩阵M的每一行都能解释为转换后的基向量。所以原来的向量[1 1]可以被分解为[1 0]和[0 1],矩阵可以分解为[2 1]和[-1 2],那么可以看做基向量x,y轴从向量v变换到矩阵M。
我们发现不光是2D向量v进行了变换,在这一个区域里的点都得到了关于矩阵M的变换。我们可以用下面的小机器人来表示。
2.3D向量与矩阵相乘的几何意义
3D向量与矩阵相乘表示的含义是一样的,只不过与3D向量相乘的矩阵是影响的x,y,z三个轴。
3.矩阵的几何意义
- 向量的几何意义是一条有向线段,而且向量可以进行三角形法则,所以我们可以将向量进行拆分成坐标轴的加法或者减法。
- 矩阵我们可以将每一行元素看做一个向量,它用来表示我们最终向量所对应坐标轴的最终状态,这就是矩阵的几何意义。
- 向量与矩阵的乘法本质就是坐标的转换,其几何意义就是表示向量拆分后,坐标进行变换,变成矩阵的每一行元素所表示的向量的位置。
第三节:3x3矩阵乘法的编程实现
1.3x3矩阵的乘法实现(头文件)
#pragma once #include <iostream> using namespace std; class Matrix3x3 { public: /* 3x3矩阵的元素 */ float m11, m12, m13; float m21, m22, m23; float m31, m32, m33; public: /* 默认构造函数 */ Matrix3x3(); public: /* 矩阵相乘 */ Matrix3x3& operator*(const Matrix3x3& otherMatrix); public: /* 打印矩阵数据 */ void print(); };
2.3x3矩阵的乘法实现(cpp文件)
#include "Matrix3x3.h" /* 默认构造函数 */ Matrix3x3::Matrix3x3() { } /* 3x3矩阵的乘法 */ Matrix3x3& Matrix3x3::operator*(const Matrix3x3& otherMatrix) { Matrix3x3 m; m.m11 = this->m11*otherMatrix.m11 + this->m12*otherMatrix.m21 + this->m13*otherMatrix.m31; m.m12 = this->m11*otherMatrix.m12 + this->m12*otherMatrix.m22 + this->m13*otherMatrix.m32; m.m13 = this->m11*otherMatrix.m13 + this->m12*otherMatrix.m23 + this->m13*otherMatrix.m33; m.m21 = this->m21*otherMatrix.m11 + this->m22*otherMatrix.m12 + this->m23*otherMatrix.m31; m.m22 = this->m21*otherMatrix.m12 + this->m22*otherMatrix.m22 + this->m23*otherMatrix.m32; m.m23 = this->m21*otherMatrix.m13 + this->m22*otherMatrix.m23 + this->m23*otherMatrix.m33; m.m31 = this->m31*otherMatrix.m11 + this->m32*otherMatrix.m21 + this->m33*otherMatrix.m31; m.m32 = this->m31*otherMatrix.m12 + this->m32*otherMatrix.m22 + this->m33*otherMatrix.m32; m.m33 = this->m31*otherMatrix.m13 + this->m32*otherMatrix.m23 + this->m33*otherMatrix.m33; return m; } /* 打印矩阵元素 */ void Matrix3x3::print() { cout << m11 << " " << m12 << " " << m13 << endl; cout << m21 << " " << m22 << " " << m23 << endl; cout << m31 << " " << m32 << " " << m33 << endl; }
第四节:3d向量和3x3矩阵乘法的编程实现
1.头文件(和前面3d向量的编程实现类似的则省略)
#pragma once #include <iostream> #include "Matrix3x3.h" using namespace std; class Vector3 { ....... // 重载 "*" 操作符(向量和矩阵相乘) Vector3 operator*(const Matrix3x3& matrix3x3); ...... };
2.cpp文件(和前面3d向量的编程实现类似的则省略)
#include "Vector3.h" // 其他操作...... // 重载 "*" 操作符(向量和矩阵相乘) Vector3 Vector3::operator*(const Matrix3x3& matrix3x3) { Vector3 vector3; vector3.x = this->x*matrix3x3.m11 + this->y*matrix3x3.m21 + this->z*matrix3x3.m31; vector3.y = this->x*matrix3x3.m12 + this->y*matrix3x3.m22 + this->z*matrix3x3.m32; vector3.z = this->x*matrix3x3.m13 + this->y*matrix3x3.m23 + this->z*matrix3x3.m33; return vector3; } // 其他操作......