博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
3D数学 矩阵和线性变换之正交投影
阅读量:4087 次
发布时间:2019-05-25

本文共 6845 字,大约阅读时间需要 22 分钟。

矩阵和线性变换之正交投影

1. 具有正交投影效果的矩阵是怎样的?

这里给出一个正交投影在法向量(而且同时又是单位向量)为(x,y,z)平面上的投影矩阵,数学证明暂时不说,详见《3d数学基础 图形与游戏开发》。

投影矩阵

2. 投影矩阵编程示例

void Matrix3X3::setOrthProject(Vector3 &vec){    assert(fabs(vec*vec) - 1 < 0.0001);    m11 = 1 - vec.x*vec.x;    m12 = m21 = -vec.x * vec.y;    m13 = m31 = -vec.x * vec.z;    m22 = 1 - vec.y * vec.y;    m23 = m32 = -vec.y * vec.z;    m33 = 1 -  vec.z * vec.z;}

3. 投影矩阵编程完整示例代码

//MathUtil.h#pragma once#include 
enum E_Axis{Axis_x,Axis_y,Axis_z};const float Pi = 3.14159;
//Vector3.h#pragma onceclass Vector3{public:    Vector3();    Vector3(float X,float Y,float Z);    //变为零向量    void Zero();    //求负向量    Vector3 operator-() const;    //求向量大小(长度或模)    float Length() const;    //标准化该向量    void Normal();    //向量的加法    Vector3 operator+(Vector3 &rhs) const;    Vector3& operator+=(Vector3 &rhs);    //向量的减法    Vector3 operator-(Vector3 &rhs) const;    Vector3& operator-=(Vector3 &rhs);    //向量乘标量    Vector3 operator*(float scalar);    //向量乘等于标量    Vector3& operator*=(float scalar);    //向量除以等于标量    Vector3& operator/=(float scalar);    //向量除以标量    Vector3 operator/(float scalar);    //距离公式    float Distance(Vector3 &vec) const;    //向量点乘    float operator*(Vector3 &rhs) const;    //向量叉积    Vector3 CrossProduct(Vector3& vec) const;public:    float x,y,z;};//标量乘向量Vector3 operator*(float scalar, Vector3& vec);
//Vector3.cpp#include "Vector3.h"#include 
Vector3::Vector3():x(0.0),y(0.0),z(0.0){}Vector3::Vector3(float X,float Y,float Z):x(X),y(Y),z(Z){}void Vector3::Zero(){ x = y = z = 0;}Vector3 Vector3::operator-() const{ return Vector3(-x,-y,-z);}float Vector3::Length() const{ return sqrt(x*x+y*y+z*z);}Vector3 Vector3::operator*(float scalar){ return Vector3(this->x * scalar, this->y * scalar, this->z * scalar);}Vector3& Vector3::operator*=(float scalar){ return *this = *this * scalar;}Vector3& Vector3::operator/=(float scalar){ return *this = *this / scalar;}Vector3 operator*(float scalar, Vector3& vec){ return vec*scalar;}Vector3 Vector3::operator/(float scalar){ float temp = 1/ scalar; return *this * temp;}void Vector3::Normal(){ //计算机计算乘法的速度比除法快 float temp = 1 / Length(); x *= temp; y *= temp; z *= temp;}Vector3 Vector3::operator+(Vector3& rhs) const{ return Vector3(x+rhs.x,y+rhs.y,z+rhs.z);}Vector3& Vector3::operator+=(Vector3& rhs){ *this = *this + rhs; return *this;}Vector3 Vector3::operator-(Vector3& rhs) const{ return Vector3(x-rhs.x,y-rhs.y,z-rhs.z);}Vector3& Vector3::operator-=(Vector3& rhs){ *this = *this - rhs; return *this;}float Vector3::Distance(Vector3& vec) const{ return (*this - vec).Length();}float Vector3::operator*(Vector3& rhs) const{ return this->x * rhs.x + this->y * rhs.y + this->z * rhs.z;}Vector3 Vector3::CrossProduct(Vector3& vec) const{ return Vector3(this->y * vec.z - this->z * vec.y, this->z * vec.x - this->x * vec.z, this->x * vec.y - this->y * vec.x);}
//Matrix3X3.h#pragma once#include "MathUtil.h"#include "Vector3.h"class Matrix3X3{public:    //矩阵相乘    Matrix3X3 operator*(Matrix3X3& rhs);    //矩阵乘等矩阵    Matrix3X3& operator*=(Matrix3X3& rhs);    void setRotate(E_Axis axis,float theta);    void setScale(Vector3 &vec);    void setOrthProject(Vector3 &vec);public:    float m11,m12,m13;    float m21,m22,m23;    float m31,m32,m33;};//向量乘以矩阵Vector3 operator*(Vector3& vec,Matrix3X3& mat);//向量乘等矩阵Vector3& operator*=(Vector3& vec,Matrix3X3& mat);
//Matrix3X3.cpp#include "Matrix3X3.h"#include 
Matrix3X3 Matrix3X3::operator*(Matrix3X3& rhs){ Matrix3X3 tempMat; tempMat.m11 = this->m11 * rhs.m11 + this->m12 * rhs.m21 + this->m13 * rhs.m31; tempMat.m12 = this->m11 * rhs.m12 + this->m12 * rhs.m22 + this->m13 * rhs.m32; tempMat.m13 = this->m11 * rhs.m13 + this->m12 * rhs.m23 + this->m13 * rhs.m33; tempMat.m21 = this->m21 * rhs.m11 + this->m22 * rhs.m21 + this->m23 * rhs.m31; tempMat.m22 = this->m21 * rhs.m12 + this->m22 * rhs.m22 + this->m23 * rhs.m32; tempMat.m23 = this->m21 * rhs.m13 + this->m22 * rhs.m23 + this->m23 * rhs.m33; tempMat.m31 = this->m31 * rhs.m11 + this->m32 * rhs.m21 + this->m33 * rhs.m31; tempMat.m32 = this->m31 * rhs.m12 + this->m32 * rhs.m22 + this->m33 * rhs.m32; tempMat.m33 = this->m31 * rhs.m13 + this->m32 * rhs.m23 + this->m33 * rhs.m33; return tempMat;}Matrix3X3& Matrix3X3::operator*=(Matrix3X3& rhs){ *this = *this * rhs; return *this;}Vector3 operator*(Vector3& vec,Matrix3X3& mat){ Vector3 tempVec; tempVec.x = vec.x * mat.m11 + vec.y * mat.m21 + vec.z * mat.m31; tempVec.y = vec.x * mat.m12 + vec.y * mat.m22 + vec.z * mat.m32; tempVec.z = vec.x * mat.m13 + vec.y * mat.m23 + vec.z * mat.m33; return tempVec;}Vector3& operator*=(Vector3& vec,Matrix3X3& mat){ vec = vec * mat; return vec;}void Matrix3X3::setRotate(E_Axis axis,float theta){ float sinValue,cosValue; sinValue = sin(theta); cosValue = cos(theta); switch(axis) { case Axis_x: { m11 = 1; m12 = 0; m13 = 0; m21 = 0; m22 = cosValue; m23 = sinValue; m31 = 0; m32 = -sinValue; m33 = cosValue; break; } case Axis_y: { m11 = cosValue; m12 = 0; m13 = -sinValue; m21 = 0; m22 = 1; m23 = 0; m31 = sinValue; m32 = 0; m33 = cosValue; break; } case Axis_z: { m11 = cosValue; m12 = sinValue; m13 = 0; m21 = -sinValue; m22 = cosValue; m23 = 0; m31 = 0; m32 = 0; m33 = 1; break; } default: assert(false); }}void Matrix3X3::setScale(Vector3& vec){ m11 = vec.x; m12 = 0; m13 = 0; m21 = 0; m22 = vec.y; m23 = 0; m31 = 0; m32 = 0; m33 = vec.z;}void Matrix3X3::setOrthProject(Vector3 &vec){ assert(fabs(vec*vec) - 1 < 0.0001); m11 = 1 - vec.x*vec.x; m12 = m21 = -vec.x * vec.y; m13 = m31 = -vec.x * vec.z; m22 = 1 - vec.y * vec.y; m23 = m32 = -vec.y * vec.z; m33 = 1 - vec.z * vec.z;}
//main.cpp#include 
#include "Vector3.h"#include "Matrix3X3.h"using namespace std;float ToZero(float num){ return (abs(num) < 0.0001 ? 0 : num);}void print_v(Vector3 v){ cout << "[ " << ToZero(v.x) << ", " << ToZero(v.y) << ", " << ToZero(v.z) << " ]" << endl; cout << endl;}void print_m(Matrix3X3 m){ cout << m.m11 << "\t" << m.m12 << "\t" << m.m13 << endl; cout << m.m21 << "\t" << m.m22 << "\t" << m.m23 << endl; cout << m.m31 << "\t" << m.m32 << "\t" << m.m33 << endl; cout << endl;}int main(){ Vector3 a(10,20,30),b,n(0,0,1); Matrix3X3 M; M.setOrthProject(n); print_m(M); print_v(a); b = a * M; print_v(b); system("pause"); return 0;}

4. 代码运行结果

1 -0 -0

-0 1 -0
-0 -0 0

[ 10, 20, 30 ]

[ 10, 20, 0 ]

你可能感兴趣的文章
这些网站有一些嵌入式面试题合集
查看>>
我觉得刷题是有必要的,不然小心实际被问的时候懵逼,我觉得你需要刷个50份面试题。跟考研数学疯狂刷卷子一样!
查看>>
我觉得嵌入式面试三要素:基础吃透+项目+大量刷题,缺一不可。不刷题是不行的。而且得是大量刷,刷出感觉套路,别人做题都做得是固定题型套路条件反射了,你还在那慢慢理解慢慢推是不行的,也是考研的教训。
查看>>
相机标定的目的:获取摄像机的内参和外参矩阵(同时也会得到每一幅标定图像的选择和平移矩阵),内参和外参系数可以对之后相机拍摄的图像就进行矫正,得到畸变相对很小的图像。
查看>>
现在来看,做个普罗米修斯的docker镜像对我而言并不难,对PX4仿真环境配置也熟悉了。
查看>>
删除docker容器和镜像的命令
查看>>
VINS-Fusion Intel® RealSense™ Depth Camera D435i
查看>>
使用Realsense D435i运行VINS-Fusion并建图
查看>>
gazebo似乎就是在装ROS的时候一起装了,装ROS的时候选择的是ros-melodic-desktop-full的话。
查看>>
React + TypeScript 实现泛型组件
查看>>
TypeScript 完全手册
查看>>
React Native之原理浅析
查看>>
Git操作清单
查看>>
基础算法
查看>>
前端面试
查看>>
React Hooks 异步操作踩坑记
查看>>
聊聊编码那些事,顺带实现base64
查看>>
TypeScript for React (Native) 进阶
查看>>
React 和 ReactNative 的渲染机制/ ReactNative 与原生之间的通信 / 如何自定义封装原生组件/RN中的多线程
查看>>
JavaScript实现DOM树的深度优先遍历和广度优先遍历
查看>>