一个简单的三维向量类

作者:朱金灿
来源:http://blog.csdn.net/clever101/


最近在看《3D数学基础:图形与游戏开发》。该书第六章实现了一个简单三维向量类。我看了一下代码,发现有些地方是错的,于是做了一些小修改。该三维向量类实现了一些常用的向量运算,如点乘、叉乘等。对此不熟悉的同学可以参考相关线性代数教材。现把源码贴上:


#include <float.h> //@brief 浮点数比较宏,采用VC的浮点数单精度FLT_EPSILON #define FLOAT_EQ(x,v) (((v - FLT_EPSILON) < x) && (x <( v + FLT_EPSILON))) namespace TD_Math { class Vector3 { public: float x; float y; float z; //@brief 默认构造函数,不执行任何操作 Vector3() { zero();// 默认为零向量 } //@brief 复制构造函数 Vector3(const Vector3 &a):x(a.x),y(a.y),z(a.z){} //@brief 带参数的构造函数,用三个值完成初始化 Vector3(float fx,float fy,float fz):x(fx),y(fy),z(fz){} //@brief 重载复制运算符,并返回引用,以实现左值 Vector3& operator = (const Vector3 &a) { x = a.x; y = a.y; z = a.z; } //@brief 重载“==”操作符 bool operator ==(const Vector3 &a)const { return (FLOAT_EQ(x,a.x)&&FLOAT_EQ(y,a.y)&&FLOAT_EQ(z,a.z)); } //@brief 重载“!=”运算符 bool operator !=(const Vector3 &a)const { return ((!FLOAT_EQ(x,a.x))||(!FLOAT_EQ(y,a.y))||(!FLOAT_EQ(z,a.z))); } //@brief 置为零向量 void zero(){x = y = z = 0.0f;} //@brief 重载“-”运算符 Vector3 operator - () const {return Vector3(-x,-y,-z);} //@brief 重载二元“+”运算符 Vector3 operator +(const Vector3 &a) const { return Vector3(x+a.x,y+a.y,z+a.z); } //@brief 重载二元“-”运算符 Vector3 operator -(const Vector3 &a)const { return Vector3(x-a.x,y-a.y,z-a.z); } //@brief 与标量的乘法 Vector3 operator *(float a)const { return Vector3(x*a,y*a,z*a); } //@brief 与标量的除法 Vector3 operator /(float a)const { float oneOverA = 1.0f/a; // 注意:这里不对“除零”进行检查 return Vector3(x*oneOverA,y*oneOverA,z*oneOverA); } //@brief 重载自反运算符 Vector3& operator +=(const Vector3 &a) { x += a.x; y += a.y; z += a.z; return *this; } Vector3& operator -=(const Vector3 &a) { x -= a.x; y -= a.y; z -= a.z; return *this; } Vector3& operator *=(float a) { x*=a; y*=a; z*=a; return *this; } Vector3& operator /=(float a) { float oneOverA = 1.0f/a; x*=oneOverA; y*=oneOverA; z*=oneOverA; return *this; } //@brief 向量标准化 void normalize() { float magsq = x*x+y*y+z*z; if (magsq>0.0f) // 检查除零 { float oneOverMag = 1.0f/sqrt(magsq); x *=oneOverMag; y *=oneOverMag; z *=oneOverMag; } } //@brief 向量点乘 float operator *(const Vector3 &a)const { return (x*a.x+y*a.y+z*a.z); } }; // 非成员函数 //@brief 求向量模 inline float vectorMag(const Vector3 &a) { return sqrt(a.x*a.x+a.y*a.y+a.z*a.z); } //@brief 计算两向量的叉乘 inline Vector3 crossProduct(const Vector3 &a,const Vector3 &b) { return Vector3( a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x ); } //@brief 实现标量左乘 inline Vector3 operator *(float k,const Vector3 &v) { return Vector3(k*v.x,k*v.y,k*v.z); } //@brief 计算两点间距离 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); } //@brief 提供一个全局零向量 extern const Vector3 kZeroVector; }


参考文献:


1. 3D数学基础:图形与游戏开发,作者: 邓恩,译者: 陈洪 / 史银雪 / 王荣静






/* * 基于数组的向量实现 */ package dsa; public class Vector_Array implements Vector { private final int N = 1024;//数组的容量 private int n = 0;//向量的实际规模 private Object[] A;//对象数组 //构造函数 public Vector_Array() { A = new Object[N]; n = 0; } //返回向量中元素数目 public int getSize() { return n; } //判断向量是否为空 public boolean isEmpty() { return (0 == n) ? true : false; } //取秩为r的元素 public Object getAtRank(int r)//O(1) throws ExceptionBoundaryViolation { if (0 > r || r >= n) throw new ExceptionBoundaryViolation("意外:秩越界"); return A[r]; } //将秩为r的元素替换为obj public Object replaceAtRank(int r, Object obj) throws ExceptionBoundaryViolation { if (0 > r || r >= n) throw new ExceptionBoundaryViolation("意外:秩越界"); Object bak = A[r]; A[r] = obj; return bak; } //插入obj,作为秩为r的元素;返回该元素 public Object insertAtRank(int r, Object obj) throws ExceptionBoundaryViolation { if (0 > r || r > n) throw new ExceptionBoundaryViolation("意外:秩越界"); if (n >= N) throw new ExceptionBoundaryViolation("意外:数组溢出"); for (int i=n; i>r; i--) A[i] = A[i-1];//后续元素顺次后移 A[r] = obj;//插入 n++;//更新当前规模 return obj; } //删除秩为r的元素 public Object removeAtRank(int r) throws ExceptionBoundaryViolation { if (0 > r || r >= n) throw new ExceptionBoundaryViolation("意外:秩越界"); Object bak = A[r]; for (int i=r; i<n; i++) A[i] = A[i+1];//后续元素顺次前移 n--;//更新当前规模 return bak; } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值