学习笔记——关于向量

来源:互联网 发布:mac 安装win10 蓝屏 编辑:程序博客网 时间:2024/06/07 02:00

一、向量运算


点乘:a * b = |a| |b| cosα
投影
叉乘:|a X b| = |a| |b| sinα  向量计算: x =y1*z2 - z1*y2;    y = z1*x2 - x1*z2;    z = x1*y2 - y1*x2;
...

二、设计决策


  1. 这里用float类型。当今的处理器处理浮点数能在处理整数的周期内完成,并且还提供向量处理器来执行浮点向量运算,所以不用担心浮点类型的计算效率。
  2. 关于返回类型,一般来说,返回类型是一个引用会提高效率(因为少调用构造函数)。但是在一些情况下(如+等重载运算)则需要返回类实例,这里的处理是在return时直接构造,显式构造临时对象。但是这还是会造成性能下降(因为还是需要调用构造函数)。然而,我们似乎可以使用对象池以减少这种效率问题,但是除了轻微的性能提升,提高了巨大的代码复杂性。所以这里还是使用了return时直接构造。
  3. 在设计代码时,时刻牢记效率问题。保持类的精简,同时也不要为了轻微的性能优化付出很大的代码复杂性。

三、向量类

/*************************************************************** * *vector3类:简单的3D向量类 *****************************************************************/#include <math.h>class Vector3 {public:float x, y, z;/**************构造函数****************************///默认初始化函数Vector3(){}/****与构造函数体内赋值不一样 赋值是先调用无参构造,再调用赋值 初始化是直接调用带参构造***///构造函数初始化表 传入为一个Vector3实例Vector3(const Vector3 &v) : x(v.x), y(v.y), z(v.z) {}//构造函数 传入为三个分量Vector3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}/***************标准对象操作***********************///赋值重载 返回引用Vector3 &operator = (const Vector3 &v) {x = v.x; y = v.y; z = v.z;return *this;}/****(这里的const表明此函数不会对数据成员进行更改)*///重载比较算符bool operator ==(const Vector3 &v) const {return x==v.x && y==v.y && z==v.z;}bool operator !=(const Vector3 &v) const {return x!=v.x || y!=v.y || z!=v.z;}/***************向量运算***************************///置为零向量void zero() { x = y = z = 0.0f; }//重载 取负 运算符Vector3 operator - () const { return Vector3(-x,-y,-z); }//重载 +,- 运算符Vector3 operator + (const Vector3 &v) const {return Vector3(x + v.x, y + v.y, z + v.z);}Vector3 operator - (const Vector3 &v) const {return Vector3(x - v.x, y - v.y, z - v.z);}//与标量的乘、除法Vector3 operator *(float k) const {return Vector3(x*k, y*k, z*k);}Vector3 operator /(float k) const {float oneOverK = 1.0f / k;//这里不对零进行检查return Vector3(x*oneOverK, y*oneOverK, z*oneOverK);}//自运算 算符Vector3 &operator +=(const Vector3 &v) {x += v.x; y += v.y; z += v.z;return *this;}Vector3 &operator -=(const Vector3 &v) {x -= v.x; y -= v.y; z -= v.z;return *this;}Vector3 &operator *=(float k) {x *= k; y *= k; z *= k;return *this;}Vector3 operator /=(float k) {float oneOverK = 1.0f / k;//这里不对零进行检查x *= oneOverK; y *= oneOverK; z *= oneOverK;return *this;}//向量标准化void normalize() {float magSq = x*x + y*y + z*z;if (magSq > 0.0f) { //检查除零float oneOverMag = 1.0 / sqrt(magSq);x *= oneOverMag;y *= oneOverMag;z *= oneOverMag;}}//向量点乘float operator *(const Vector3 &v) const {return x*v.x + y*v.y + z*v.z;}};/*************************************************************** * *非成员函数 *****************************************************************///向量求模inline float vectorMag(const Vector3 &v) {return sqrt(v.x*v.x + v.y*v.y + v.z*v.z);}//计算向量叉乘inline Vector3 crossProduct(const Vector3 &v1, const Vector3 &v2) {return Vector3(v1.y*v2.z - v1.z*v2.y,v1.z*v2.x - v1.x*v2.z,v1.x*v2.y - v1.y*v2.x);}//实现标量左乘inline Vector3 operator *(float k, const Vector3 &v) {return Vector3(k*v.x, k*v.y, k*v.z);}//计算两点距离inline float distance(const Vector3 &a, const Vector3 &b) {float dx = a.x - b.x;float dy = a.y - b.y;float dz = a.z - b.z;return sqrt(dx*dx + dy*dy + dz*dz);}/*************************************************************** * *全局变量 *****************************************************************///全局零向量extern const Vector3 zeroVector;


0 0