还是在读书的时候帮外专业朋友做作业,用GDI实现三维空间的立方体绘制和旋转的操作,那个时候自己根据《线性代数与空间解析几何》以及《计算机图形学》等课程的相关知识写了一个三维向量类。后来做了些二维和三维的东西发现用向量操作会使很多问题变得简单直观,尤其是在OpenGL编程的时候这种感觉尤为明显。经过这么长时间的使用现在这个类已经比较完善了,早些时候将它上传到了CSDN,近来比较闲索性写个介绍吧,希望对从事三维图形开发的朋友有所帮助,也期待着与大家的交流中会有所提高。

先把代码贴上,当然有兴趣的朋友也可以在我的资源中下载。

类的定义是这样的

class CVector

{

public:

float m_fVectorX, m_fVectorY, m_fVectorZ, //向量的空间坐标

m_fAngleX, m_fAngleY, m_fAngleZ, //向量与坐标轴的夹角

m_fMod; //向量的模

public:

CVector();

CVector(float fVectorX, float fVectorY, float fVectorZ);

virtual ~CVector();

void CalculateAngles();

void SetVector(float fStartX, float fStartY, float fStartZ, float fEndX, float fEndY, float fEndZ);

void SetVector(float fVectorX, float fVectorY, float fVectorZ);

float GetMod(){return m_fMod;}

void Invert();

void MakeUnitVector();

void Rotate(float fAngle, CVector vtrAxis);

void operator=(CVector vectorOther);

CVector operator+(CVector vectorOther);

CVector operator*(float fNum);

float operator^(CVector vectorOther);

CVector operator*(CVector vectorOther);

};

大家应该都知道所谓向量其实就是一组数,在笛卡尔坐标系中一个向量就是起点在原点的有向线段,虽然向量的起点可以在任意位置,但是标记向量的有序数却还是当起点在原点时终点的坐标。所以m_fVectorX, m_fVectorY, m_fVectorZ就唯一确定了一个向量。当然向量还有一些其他属性,比如模(也就是向量的长度),比如其和各个坐标轴的夹角,所以我做了另外四个变量m_fMod、m_fAngleX、m_fAngleY、m_fAngleZ来保存这些属性。

生成变量有很多方法,比如直接设置终点坐标、比如通过起点和终点做差,所以我也实现了两个版本的SetVector。当然也有通过模和角度来生成变量的,但这种方法极其不常用,尤其是在三维条件下这个角度其实很不容易计算,所以我也就没有实现相应的方法。获取向量的模是常用的向量操作,我自然也对其进行了实现,GetMod就是返回模的函数。和矢量有关的操作中反向也是比较常用的一个,我也用Invert实现了这个操作。具体应用时,我们可能经常会用到单位向量,MakeUnitVector的功能就是将当前向量变成单位向量。最值得一提的就是Rotate函数,有过三维制作经验的人都应该知道在三维空间中旋转操作是最让人头疼的了,需要进行繁琐的矩阵运算。根据实际使用的经验,我实现了简单易用的Rotate函数,第一个参数fAngle用于指定旋转角度,而第二个参数vtrAxis用于指定旋转轴。这样通过调用这个函数我们就可以轻松实现任意的旋转操作,也可以初始向量到一个特殊方向,通过旋转达到指定方向,这样也省掉了自行计算复杂向量初始参数的麻烦。当然作为一个数学操作单元重载操作符是必须的,加、减、赋值不必多说,向量乘法有两种,叉积和内积,我通过“*”实现了叉积运算而通过“^”号实现了内积运算。各个向量操作主要都是通过坐标实现的,而某些操作实现之后需要相应的修正其他参数,CalculateAngles函数就是重新计算新向量的角度参数的,使用在各个函数的内部。以下是这个类的实现代码:

CVector::CVector()

{

//参数初始化

m_fVectorX = 0;

m_fVectorY = 0;

m_fVectorZ = 0;

m_fAngleX = 0;

m_fAngleY = 0;

m_fAngleZ = 0;

m_fMod = 0;

}

CVector::CVector(float fVectorX, float fVectorY, float fVectorZ)

{

SetVector(fVectorX, fVectorY, fVectorZ);

}

CVector::~CVector()

{

}

void CVector::CalculateAngles()

{

//计算与坐标轴的夹角

m_fAngleX = (float)acos(m_fVectorX/m_fMod);

m_fAngleY = (float)acos(m_fVectorY/m_fMod);

m_fAngleZ = (float)acos(m_fVectorZ/m_fMod);

}

void CVector::SetVector(float fStartX, float fStartY, float fStartZ, float fEndX, float fEndY, float fEndZ)

{

//设置空间坐标

m_fVectorX = fEndX-fStartX;

m_fVectorY = fEndY-fStartY;

m_fVectorZ = fEndZ-fStartZ;

//计算模

m_fMod = (float)sqrt(m_fVectorX*m_fVectorX+m_fVectorY*m_fVectorY+m_fVectorZ*m_fVectorZ);

//计算与坐标轴的夹角

CalculateAngles();

}

void CVector::SetVector(float fVectorX, float fVectorY, float fVectorZ)

{

//设置空间坐标

m_fVectorX = fVectorX;

m_fVectorY = fVectorY;

m_fVectorZ = fVectorZ;

//计算模

m_fMod = (float)sqrt(m_fVectorX*m_fVectorX+m_fVectorY*m_fVectorY+m_fVectorZ*m_fVectorZ);

//计算与坐标轴的夹角

CalculateAngles();

}

void CVector::Invert()

{

//设置空间坐标

m_fVectorX = -m_fVectorX;

m_fVectorY = -m_fVectorY;

m_fVectorZ = -m_fVectorZ;

//计算与坐标轴的夹角

CalculateAngles();

}

void CVector::MakeUnitVector()

{

//模归一化

m_fMod = 1;

//重新设置向量坐标

m_fVectorX = (float)cos(m_fAngleX);

m_fVectorY = (float)cos(m_fAngleY);

m_fVectorZ = (float)cos(m_fAngleZ);

}

void CVector::Rotate(float fAngle, CVector vtrAxis)

{

float fResaultX, fResaultY, fResaultZ;

//计算角度的cos和sin值

float fCosValue = (float)cos(fAngle);

float fSinValue = (float)sin(fAngle);

//计算旋转后的向量坐标

fResaultX = (fCosValue+(1-fCosValue)*vtrAxis.m_fVectorX*vtrAxis.m_fVectorX)*m_fVectorX;

fResaultX += ((1-fCosValue)*vtrAxis.m_fVectorX*vtrAxis.m_fVectorY-vtrAxis.m_fVectorZ*fSinValue)*m_fVectorY;

fResaultX += ((1-fCosValue)*vtrAxis.m_fVectorX*vtrAxis.m_fVectorZ+vtrAxis.m_fVectorY*fSinValue)*m_fVectorZ;

fResaultY = ((1-fCosValue)*vtrAxis.m_fVectorX*vtrAxis.m_fVectorY+vtrAxis.m_fVectorZ*fSinValue)*m_fVectorX;

fResaultY += (fCosValue+(1-fCosValue)*vtrAxis.m_fVectorY*vtrAxis.m_fVectorY)*m_fVectorY;

fResaultY += ((1-fCosValue)*vtrAxis.m_fVectorY*vtrAxis.m_fVectorZ-vtrAxis.m_fVectorX*fSinValue)*m_fVectorZ;

fResaultZ = ((1-fCosValue)*vtrAxis.m_fVectorX*vtrAxis.m_fVectorZ-vtrAxis.m_fVectorY*fSinValue)*m_fVectorX;

fResaultZ += ((1-fCosValue)*vtrAxis.m_fVectorY*vtrAxis.m_fVectorZ+vtrAxis.m_fVectorX*fSinValue)*m_fVectorY;

fResaultZ += (fCosValue+(1-fCosValue)*vtrAxis.m_fVectorZ*vtrAxis.m_fVectorZ)*m_fVectorZ;

//更新向量坐标

m_fVectorX = fResaultX;

m_fVectorY = fResaultY;

m_fVectorZ = fResaultZ;

//更新向量与坐标的夹角

CalculateAngles();

}

void CVector::operator=(CVector vectorOther)

{

CVector vectorResult;

//参数赋值

m_fVectorX = vectorOther.m_fVectorX;

m_fVectorY = vectorOther.m_fVectorY;

m_fVectorZ = vectorOther.m_fVectorZ;

m_fAngleX = vectorOther.m_fAngleX;

m_fAngleY = vectorOther.m_fAngleY;

m_fAngleZ = vectorOther.m_fAngleZ;

m_fMod = vectorOther.m_fMod;

}

CVector CVector::operator+(CVector vectorOther)

{

CVector vectorResult;

vectorResult.m_fVectorX = m_fVectorX+vectorOther.m_fVectorX;

vectorResult.m_fVectorY = m_fVectorY+vectorOther.m_fVectorY;

vectorResult.m_fVectorZ = m_fVectorZ+vectorOther.m_fVectorZ;

vectorResult.m_fMod = m_fMod+vectorOther.m_fMod;

//计算角度

vectorResult.CalculateAngles();

return vectorResult;

}

CVector CVector::operator*(float fNum)

{

CVector vectorResult;

vectorResult.m_fVectorX = m_fVectorX*fNum;

vectorResult.m_fVectorY = m_fVectorY*fNum;

vectorResult.m_fVectorZ = m_fVectorZ*fNum;

vectorResult.m_fMod = m_fMod*fNum;

vectorResult.CalculateAngles();

return vectorResult;

}

float CVector::operator^(CVector vectorOther)

{

float fResult;

fResult = m_fVectorX*vectorOther.m_fVectorX+m_fVectorY*vectorOther.m_fVectorY+m_fVectorZ*vectorOther.m_fVectorZ;

return fResult;

}

CVector CVector::operator*(CVector vectorOther)

{

CVector vectorResult;

//计算新向量

vectorResult.m_fVectorX = ((m_fVectorY*vectorOther.m_fVectorZ)-(m_fVectorZ*vectorOther.m_fVectorY));

vectorResult.m_fVectorY = ((m_fVectorZ*vectorOther.m_fVectorX)-(m_fVectorX*vectorOther.m_fVectorZ));

vectorResult.m_fVectorZ = ((m_fVectorX*vectorOther.m_fVectorY)-(m_fVectorY*vectorOther.m_fVectorX));

//计算新向量的模

vectorResult.m_fMod = (float)sqrt(vectorResult.m_fVectorX*vectorResult.m_fVectorX+vectorResult.m_fVectorY*vectorResult.m_fVectorY+vectorResult.m_fVectorZ*vectorResult.m_fVectorZ);

//计算新向量的角度

vectorResult.CalculateAngles();

return vectorResult;

}

我在网上也看过一些向量类,多半只是有坐标参数,没有相应操作。这个类体现出了向量的所有属性,而且封装了我能想到的向量的所有常用操作。尤其是旋转操作功能比较全面,在我实际的三维编程应用中也有很好的效果。这次拿出来和大家分享,希望大家多提宝贵意见。

java 三维向量类_三维向量类相关推荐

  1. 复习Object类_日期时间类_System类_StringBuilder_包装类以及各类的细节

    Object类_日期时间类_System类_StringBuilder_包装类以及各类的细节 主要内容 Object类 Date类 DateFormat类 Calendar类 System类 Stri ...

  2. java枚举返回字符串_枚举工具类-通过给定值获取对应的枚举类

    开发背景: 在开发过程中遇到需要通过给定的值来获取对应的枚举值,如下例枚举类中,需要通过传入"春"来获取SPRING. public 开始尝试通过Enum的内置方法valueOf( ...

  3. 三维坐标 偏转_三维坐标系旋转

    在做单目三维位姿估计(即估计目标物相对相机的姿态或相机相对目标物的姿态)时会用到solvepnp函数, 函数原型为:cv2.solvePnP(objectPoints, imagePoints, ca ...

  4. c++ 实现一个object类_说说Object类下面有几种方法呢?

    欢迎关注头条号:Java小野猫 今天说一道基础题型,不过很多人会忽略或者至少说不完整,但是面试时被问到的几率还是很大的. 面试题 Object有几种方法呢? Java语言是一种单继承结构语言,Java ...

  5. c ++向量库_将向量复制到C ++中的另一个向量

    c ++向量库 The ways that we are using to copy vectors in C++, are: 我们用于在C ++中复制向量的方法是: Copy one vector' ...

  6. java graphics 类_对于 Graphics 类的一点认识(转)

    AWT 提供了一些用户接口的构件,但是它不提供一些类似的纯粹的绘制图形的对象,例如 Rectangle.Polygon 和 Point 类没有任何绘制图形的能力.换句话说它们不具备 draw 方法,仅 ...

  7. java ajax翻页_分页 工具类 前后台代码 Java JavaScript (ajax) 实现 讲解

    [博客园cnblogs笔者m-yb原创, 转载请加本文博客链接,笔者github: https://github.com/mayangbo666,公众号aandb7,QQ群927113708] htt ...

  8. java .class 实例对象_通过Class类获取对象(实例讲解)

    通过Class对象获取对象的方式是通过class.newInstance()方式获取,通过调用默认构造参数实例化一个对象. /** * Created by hunt on 2017/6/27. * ...

  9. java 圆类 圆锥类_以圆类 Circle 及立体图形类 Solid 为基础设计圆锥类 Cone

    学习内容:以圆类 Circle 及立体图形类 Solid 为基础设计圆锥类 Cone 代码示例: import java.util.Scanner; class Point4{ private dou ...

最新文章

  1. mysql 常用小工具包_mssql+mysql小工具(无需环境依赖)-mysql数据库批量实体CS类导出工具下载v3.0免费版-西西软件下载...
  2. boost::log模块实现logging旋转文本文件的示例
  3. 用C++设计一个不能被继承的类
  4. 如何在Python中建立回归模型
  5. bert关键词提取_BERT可以上几年级了?Seq2Seq“硬刚”小学数学应用题
  6. 今天开始学习QT for sysbiam 1
  7. Django 踩过的坑(二)
  8. Android Dialog Activity
  9. 组件源码——拖动条Slider
  10. flash mx拖拽实例_Flash MX 2004中的像素溶解效果
  11. 昆仑固件涉密专用计算机,存储处理国家秘密的计算机信息系统按照涉密程序实行...
  12. 论文阅读笔记——野外和非侵入性遗传方法评估棕熊种群规模
  13. Tableau同比或环比计算方法
  14. 【屏幕适配】像素密度 分辨率 dp px的关系
  15. 上上下下左右左右BABA - 那些80后最难忘的游戏
  16. 实践:Linux上安装nginx后同一服务器进行多域名反向代理
  17. 游戏程序员的核心竞争力是什么?
  18. 设计模式C++描述----01.单例(Singleton)模式
  19. 拉丁超立方抽样的Python实现
  20. 前端换肤功能如何实现

热门文章

  1. 智能服装门店解决方案
  2. 【兴趣书签】近视眼从800度降到100度是怎样的体验
  3. 第三方框架简介ios
  4. ABP无法使用异步操作,但要调用异步方法
  5. LWN:机器学习模型的偏见和伦理问题
  6. 杨雅晴的索吻----一己之见
  7. 扯淡的Mysql性能 论
  8. 腾讯优测亮相2020第二届中国金融CIO年会
  9. wps修改csv文件中的科学计数法修改为完整显示
  10. 计算10的阶乘以及10以内阶乘的和