三维向量类

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

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

      类的定义是这样的

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

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

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

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
1、 一个三维向量,并定义相应的特殊方法实现两个该对象之间的加、减运算(要求支持运算符+、-),实现该对象与标量的乘、除运算(要求支持运算符*、/),以及向量长度的计算(要求使用属性实现)。 2、 编程实现如下功能: (1)定义一个抽象Shape,在抽象 Shape中定义求面积 getArea()和周长 getPerimeter()的抽象方法。 (2)分别定义继承抽象Shape的3个子即Triangle、Rectangle、和Circle,在这3个子中重写 Shape中的方法getArea()和 getPerimeter( )。 (3)创建Triangle、 Rectangle、 Circle的对象,对3个中的方法进行调用测试。 3、使用第六章(王雷春版)介绍的知识设计一个“书籍出租管理系统”,该系统包括以下功能。 (1) 菜单项“1”:显示书籍(包括书籍名称、价格和借出状态)。 (2) 菜单项“2”:增加书籍(包括书籍名称和价格)。 (3) 菜单项“3”:借出书籍(包括借出书籍名称和借出天数)。 (4) 菜单项“4”:归还书籍(包括归还书籍名称和应付的租书费)。 (5) 菜单项“5”:统计书籍(包括借出书籍册数、未借出书籍册数和总册数)。 (6) 菜单项“-1”:退出系统。 体会利用面向对象编程的思想。 4、设计一个“超市进销存管理系统”,要求如下: (1)系统包括7种操作,分别是:1查询所有商品;2添加商品;3修改商品;4.删除商品;5卖出端口;6.汇总;-1.退出系统。 (2)选择操作序号“1”,显示所有商品 (3)选择操作序号“2”,添加新的商品(包括商品名称、数量和进货价格)。 (4)选择操作序号“3”,修改商品 (5)选择操作序号“4”,删除商品 (6)选择操作序号“5”,卖出商品(包括商品名称、数量和售出价格)。 (7)选择操作序号“6”,汇总当天卖出商品,包括每种销售商品名称、数量、进货总价、销售总价等。 (8)选择操作序号“-1”,退出系统。
/* * 基于数组的向量实现 */ 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; } }
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值