空间向量类Vector3的C++实现

提要

两年前的我写下了这篇文章 - 向量类的实现。现在看来,这代码真是略显丑陋。

于是,重新写吧。

参照了一下Unity3d 的Vector3类的接口。话不多说,上代码。

编译器:gcc 4.6.3

代码清单

vector3.h

#ifndef VECTOR3_H
#define VECTOR3_H

#include <math.h>
#include <assert.h>
#include <iostream>
#define PI 3.14159265
using namespace std;

class Vector3
{
    public:
        float x;
        float y;
        float z;
        Vector3();
        Vector3(float x, float y, float z);
        ~Vector3();
        bool HasNaNs() const;
        void set(float _x, float _y, float _z);

        //Static functions
        static Vector3 back();
        static Vector3 down();
        static Vector3 forward();
        static Vector3 left();
        static Vector3 one();
        static Vector3 right();
        static Vector3 up();
        static Vector3 zero();

        float magnitude() const;
        float sqrtMagnitude() const;
        Vector3 normalized();

        //Operators
        //Add two Vectors
        Vector3 operator+(const Vector3 &v) const;
        //Subtracts one vector from another
        Vector3 operator-(const Vector3 &v) const;
        Vector3 operator*(float num) const;
        Vector3 operator/(float num) const;
        Vector3 &operator+=(const Vector3 &v);
        Vector3 &operator-=(const Vector3 &v);
        Vector3 &operator*=(float num);
        Vector3 &operator/=(float num);
        //Returns true if vectors different.
        bool operator!=(Vector3 &v) const;

        friend std::ostream& operator<<(std::ostream& output,const Vector3& v)
        {
            output<<"("<<v.x<<","<<v.y<<","<<v.z<<")"<<"\n";
            return output;
        }

           //Static Functions
        //Calculate angle between two vectors.
        static float Angle(const Vector3 &from, const Vector3 &to)
        {
            double c, d;
            c = from.x*to.x + from.y*to.y + from.z*to.z;
            d = sqrt(from.x*from.x + from.y*from.y + from.z*from.z) * sqrt(to.x*to.x + to.y*to.y + to.z*to.z);
            return acos(c/d) * 180.0 / PI;
        }

        //Get dot result of two vector2.
        static inline float Dot(const Vector3 &v1, const Vector3 &v2)
        {
            return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
        }

        //Get cross result of two vector2.
        static inline Vector3 Cross(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));
        }
        //Get a normalized vector3 from a given vector3.
        static inline Vector3 Normalize(const Vector3 &v1)
        {
            float tmpLength = v1.magnitude();
            return Vector3(v1.x/tmpLength, v1.y/tmpLength, v1.z/tmpLength);
        }

        //Construct a coordinateSystem by a given vector3. v2 and v3 are output.
        static inline void CoordinateSystem(const Vector3 &v1, Vector3 *v2, Vector3 *v3)
        {
            if(fabsf(v1.x) > fabsf(v1.y))
            {
                float invLen = 1.0f / sqrtf(v1.x*v1.x + v1.z*v1.z);
                *v2 = Vector3(-v1.z * invLen, 0.0f, v1.x * invLen);
            }else
            {
                float invLen = 1.0f / sqrt(v1.y*v1.y + v1.z*v1.z);
                *v2 = Vector3(0.0f, v1.z * invLen, -v1.y * invLen);
            }
            *v3 = Vector3::Cross(v1, *v2);
        }

        static Vector3 ClampMagnitude();
        static Vector3 Lerp(const Vector3 &v1, const Vector3 &v2);
        static Vector3 OrthoNormalize();
    protected:
    private:

};

#endif // VECTOR3_H

vector3.cpp

#include "vector3.h"

Vector3::Vector3()
{
    x = y = z = 0.0f;
}

Vector3::Vector3(float _x, float _y, float _z):x(_x),y(_y),z(_z)
{
    assert(!HasNaNs());
}

Vector3::~Vector3()
{
    //dtor
}

bool Vector3::HasNaNs() const
{
    return isnan(x) || isnan(y) || isnan(z);
}

Vector3 Vector3::one()
{
    return Vector3(1, 1, 1);
}

float Vector3::magnitude() const
{

    return sqrt(x*x + y*y + z*z);

}

float Vector3::sqrtMagnitude() const
{
    return x*x + y*y + z*z;
}

void Vector3::set(float _x, float _y, float _z)
{
    x = _x;
    y = _y;
    z = _z;
}

Vector3 Vector3::operator+(const Vector3 &v) const
{
    return Vector3(x + v.x, y+ v.y, z+ v.z);
}

Vector3 Vector3::operator-(const Vector3 &v) const
{
    return Vector3(x - v.x, y - v.y, z - v.z);
}

Vector3 Vector3::operator*(float num) const
{
    return Vector3(num*x, num*y, num*z);
}

Vector3 Vector3::operator/(float num) const
{
    return Vector3(x/num, y/num, z/num);
}

Vector3& Vector3::operator*=(float num)
{
    x *= num; y *= num; z *= num;
    return *this;
}

Vector3& Vector3::operator/=(float num)
{
    x /= num; y /= num; z /= num;
    return *this;
}

Vector3& Vector3::operator+=(const Vector3 &v)
{
    x += v.x; y += v.y; z += v.z;
    return *this;
}

Vector3& Vector3::operator-=(const Vector3 &v)
{
    x -= v.x; y -= v.y; z -= v.z;
    return *this;
}

bool Vector3::operator!=(Vector3 &v) const
{
    return x==v.x && y==v.y && z==v.z;
}

Vector3 Vector3::normalized()
{
    float tmpLength = this->magnitude();
    return Vector3(x/tmpLength, y/tmpLength, z/tmpLength);
}

测试代码

#include <iostream>
#include "vector3.h"

using namespace std;

int main()
{
    Vector3 v1,v2,v3;
    v1=Vector3(1.0,-1.0,0.0);
    v2=Vector3(-1.0,-1.0,0.0);
    cout<<"v1: "<<v1<<endl;
    v2=v2/2;
    cout<<"v2: "<<v2<<endl;
    cout<<"Angle: "<<Vector3::Angle(v1, v2)<<endl;
    v3=Vector3::Cross(v1,v2);
    float a=Vector3::Dot(v1,v2);
    cout<<"v1 dotMul v2:"<<a<<endl;
    cout<<"v3.Length:"<<v3.magnitude()<<endl;
    Vector3 v4 = v3.normalized();
    cout<<"v3 After nomarlize:"<<v4<<endl;
    return 0;
}

运行结果

代码说明

相对于前一个版本的代码,新版本的Vector3首先是包括了基本的向量运算,同时做了下面的改进:

1.重载了<<符号,这样就可以直接打印向量的内容了;

2.重载了基本的运算符号,包括返回引用和返回对象的,返回对象的不会改变本身,返回引用的会同时修改本省;

3.添加了一些静态的inline方法,用于向量的一些计算,关于static inline,可以理解是一个static的函数,加上了inline的属性。这个函数大部分表现和普通的static函数一样,只不过在调用这种函数的时候,gcc会在其调用处将其汇编码展开编译而不为这个函数生成独立的汇编码。

时间: 2024-10-09 06:43:03

空间向量类Vector3的C++实现的相关文章

[C++][代码库]Vector3空间向量类

本文用C++实现一个简单的Vector3类的功能,暂时有的功能是: 1 + - * /算术运算 2 向量的数量积,又叫:点乘 3 向量的向量积,又叫:叉乘 4 向量单位化(normalization) //Vecotr3.h #pragma once extern const double uZero; class Vector3 { float x, y, z; public: Vector3():x(0), y(0), z(0){} Vector3(float x1, float y1, f

图形开发之3D向量类(C#)

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace VectorDemo { /// <summary> /// 3D向量类 /// </summary> public class Vector3 { public float X { get; set; } public float Y { get; set; } public float Z

第二十章 内存等空间管理类的实现

                   第二十章   内存等空间管理类的实现      空间.时间对我来说,或许永远是一个迷.即使我曾经深入到原子的最深处,即使人类科学家是自欺欺人,即使我了解到的最深层次的部分真理是正确的:那又能怎样?那都是过去式,在那光明与黑暗一体之地.我的灵魂受伤了:我不得不回到电脑这块充满垃圾的地方修心养性. 或许我的论述方法不好,要完全理解本章是有点难度:你要对简单的空间概念需要一定的理解,即使只是论述1D的线性平面空间中的2个基本方法:分配与释放,但也很复杂.要知道LI

C++ Primer 学习笔记_105_特殊工具与技术 --联合:节省空间的类

特殊工具与技术 --联合:节省空间的类 联合是一种特殊的类.一个 union 对象可以有多个数据成员,但在任何时刻,只有一个成员可以有值.当将一个值赋给 union 对象的一个成员的时候,其他所有都变为未定义的. 为 union 对象分配的存储的量至少与包含其最大数据成员的一样多.联合提供了便利的办法表示一组相互排斥的值,这些值可以是不同类型的. 1.定义联合 作为例子,我们可能有一个处理不同各类数值或字符数据的过程.该过程可以定义一个 union 来保存这些值: union ToKenValu

[从头学数学] 第191节 空间向量与立体几何

剧情提要: [机器小伟]在[工程师阿伟]的陪同下进入了[九转金丹]之第五转的修炼. 这次要研究的是[空间向量与立体几何]. 正剧开始: 星历2016年04月23日 11:00:22, 银河系厄尔斯星球中华帝国江南行省. [工程师阿伟]正在和[机器小伟]一起研究[空间向量与立体几何]. <span style="font-size:18px;">#例5 def dot(a, b): if (len(a) >= 3): return a[0]*b[0] +a[1]*b[1

第九周项目4-我的向量类

建立一个向量类MyVector,声明如下,请完成类的定义. class MyVector //定义向量类 { public: MyVector(int m); //构造函数,共有m个元素的向量,元素值预置为0 MyVector(const MyVector &v); //复制构造函数 ~MyVector(); //析构函数:释放动态数组所占用的存储空间 friend istream &operator>>(istream &input, MyVector &d)

《3D数学基础》实践1 向量类代码分析

理解数学,理解代码! 大家好,我是老G! 今天为大家带来<3D数学基础>系列视频. 主要讲解:游戏开发中用到的3D数学知识,包括:定义,定理,推论. 也包括他们的推导过程,以及应用举例. 本套视频完全免费,欢迎捐助,帮助我完成这套视频 支付宝帐号:[email protected]gmail.com 今天带来的是系列第11讲--实践1 向量类代码分析 本次视频,主要讲解一下如下几个库中的向量类的代码: 1.3D Math Primer for Games and Graphics Develo

我的向量类

输入代码: /* *Copyright (c)2015,烟台大学计算机与控制工程学院 *All rights reserved. *文件名称:sum123.cpp *作 者:林海云 *完成日期:2015年5月23日 *版 本 号:v2.0 * *问题描述:建立一个向量类MyVector *程序输入:输入d1,d2 *程序输出:按要求输出 */ #include<iostream> using namespace std; class MyVector { public: MyVector(in

第九周上机实践项目4——我的向量类

建立一个向量类MyVector,声明如下,请完成类的定义 class MyVector //定义向量类 { public: MyVector(int m); //构造函数,共有m个元素的向量,元素值预置为0 MyVector(const MyVector &v); //复制构造函数 ~MyVector(); //析构函数:释放动态数组所占用的存储空间 friend istream &operator>>(istream &input, MyVector &d);