在VPython中使用向量计算3D物体移动
在VPython中,多处用到了向量。但在VPython中向量的主要用途还是处理3D物体的移动和旋转。处理3D物体的移动,不止一种方法。本用一个实例,介绍用向量和不用向量的方法的不同。实例如下:小球用40帧从(-7,-5,0)点移到(13, 3, -2)点。你可以认为这是足球运动员从起点(-7,-5,0)处射门,在终点(13, 3, -2)处被守门员接住。
首先介绍不用向量的方法。dx,dy,dz是小球移动终点x、y、z坐标值分别减去小球移动起点x、y、z坐标值。vx,vy,vz分别是小球在x、y、z方向每帧移动的值。
from vpython import *
scene.title="小球用40帧从(-7,-5,0)移到(13,3,-2)"
ball=sphere(pos=vector(-7,-5,0),radius=2,color=color.blue)
dx,dy,dz=13-(-7),3-(-5),-2-0
vx,vy,vz=dx/40,dy/40,dz/40
for n in range(40):rate(10) ball.pos.x +=vxball.pos.y +=vyball.pos.z +=vz#ball.pos+=vector(vx,vy,vz) #可用此语句代替以上3条语句
在VPython程序设计中,经常会涉及到3D物体的运动,例如上边例子中,小球用40帧从(-7,-5,0)点移到(13, 3, -2)点。3D物体的运动中,有些变量只需用数值表示,例如,两点间的距离,从起点到终点的距离和从终点到起点的距离没有区别,这种只用数值就可以表示的量,称为标量。还有很多的量既有大小,又有方向,例如上例小球移动速度vx,vy,vz,以及上例的小球位移dx,dy,dz,不仅有移动距离,还有移动方向,这种需用数值和方向表示的量,在运动学中被称为矢量,在数学中被称为向量。向量(矢量)可用于数学和物理等多个领域,例如物理中力的合成分解,物体的运动等。这里仅介绍在VPython中,如何使用三维向量,内容包括如何用向量记录3D物体的位置,以及3D物体的移动速度向量和位移向量等概念。这些实际上是计算机图形学的有关内容。
可用有向线段来代表向量,线段长度是向量长度,从线段起点到线段终点方向是向量的方向。在3D直角坐标系中,其原点坐标为(0,0,0),坐标系中点的位置用(a,b,c)表示,a,b,c是整数或浮点数,称为点的坐标,其中a为x坐标值,是距离yz平面的距离,b为y坐标值,是距离xz平面的距离,c为z坐标值,是距离xy平面的距离。线段就是连接两个坐标点的线,可用3D直角坐标系中连接两个坐标点的线段,代表一个向量。向量的运算规则如下,向量旋转函数可参见本人博文“VPython程序设计入门”的例5。
>>> from vpython import *
>>> a=vector(3,4,5) #从点(0,0,0)到点(3,4,5)的向量
>>> b=vector(1,2,3) #从点(0,0,0)到点(1,2,3)的向量
>>> print(a+b) #向量加法,向量的和仍是向量,为vector(4,6,8)
<4, 6, 8>
>>> print(a-b) #向量减法,向量的差仍是向量,为vector(2,2,2)
<2, 2, 2>
>>> c=2*b #向量乘或除标量
>>> print(c) #向量乘或除标量的结果仍是向量
<2, 4, 6>
>>> print(a.x,a.y,a.z) #得到向量a的x、y、z分量
3.0 4.0 5.0
>>> print(vector(a)) #用向量a创建新向量,作为向量a的副本
<3, 4, 5>
>>> print(mag(a),a.mag) #可用2种方法得到向量a的长度
7.0710678118654755 7.0710678118654755
>>> print(mag2(a),a.mag2) #可用2种方法得到向量a的长度的平方
50.0 50.0
>>> print(hat(a),a.hat) #可用4种方法得到向量a的单位向量
<0.424264, 0.565685, 0.707107> <0.424264, 0.565685, 0.707107>
>>> print(norm(a),a.norm()) #向量a的单位向量,其长度为1,方向不变
<0.424264, 0.565685, 0.707107> <0.424264, 0.565685, 0.707107>
>>> print(dot(a,b),a.dot(b)) #可用2种方法得到向量的点积,为标量
26.0 26.0 #点积值=两向量长度积再乘两向量夹角余弦值
#有2种方法得到两向量叉积。右手食指指向向量a,中指指向b,拇指指向叉积向量
>>> print(cross(a,b),a.cross(b)) #叉积长度=两向量长度积再乘两向量夹角正弦值
<2, -4, 2> <2, -4, 2>
>>> print(diff_angle(a,b),a.diff_angle(b)) #有2种方法得到两向量之间夹角,以弧度为单位
0.18623876586485016 0.18623876586485016
print(proj(a,b),a.proj(b),dot(a,norm(b))*norm(b)) #a在b方向上的向量投影
<1.85714, 3.71429, 5.57143> <1.85714, 3.71429, 5.57143> <1.85714, 3.71429, 5.57143>
>>> print(comp(a,b),a.comp(b),dot(a,norm(b))) #a在b方向上的标量投影
6.948792289723034 6.948792289723034 6.948792289723034
>>> print(a.equals(b)) #如a和b有相同分量(即量向量长度和方向都相同),为真
False
>>> vector.random() #随机生成向量,其每个分量都是-1到+1范围内的随机数
vector(0.179799, -0.339963, -0.737216)
必须理解上述公式在运动学中的物理意义,才能使用这些公式。首先,要解决用向量记录3D物体位置的方法。如果3D物体在3维坐标系统的坐标为(a,b,c),可从原点(0,0,0)到终点(a,b,c)画一条线段代表一个向量,该向量方向从原点(0,0,0)到终点(a,b,c),该向量长度是从原点(0,0,0)到终点(a,b,c)的距离,用这个向量记录3D物体位置,称这个向量为“位置向量”。为了用向量代表坐标为(a,b,c)的点,向量起点必须是直角坐标系原点(0,0,0),终点是坐标(a,b,c)点,其它和该向量平行,且长度相等,但起点不是(0,0,0)向量,都不能代表坐标为(a,b,c)的点。VPython的所有3D模型都有属性pos,一般是该3D模型的中心点的坐标,一般都被赋值一个向量,这个向量就代表该3D模型的中心点的坐标。VPython模型的其它一些属性,例如Color、size属性,也被赋予一个向量,这些向量可以认为是一个列表。
本文例子:小球用40帧从(-7,-5,0)点移到(13, 3, -2)点,小球运动起点和终点可分别用向量vecter(-7,-5,0)和vecter(13,3,-2)代表。那么d=vecter(13,3,-2)-vecter(-7,-5,0),即小球移动的终点向量-小球移动的起点向量,d=vecter(13-(-7),3-(-5),-2-0),所得向量d被称为小球的位移向量。一般来讲,3D物体从起点到终点的位移向量,等于终点位置向量减起点位置向量。向量d的x、y、z分量被记为:d.x、d.y、d.z,就是不用向量法得到dx、dy、dz,也就是说,用向量法和不用向量法,两者的减法运算规则是相同的。该位移向量的长度就是两点之间的距离。为了得到小球每帧的位移量,即小球移动速度,向量d必须除以40。
不像位置向量,向量起点必须从原点开始,对于多个位移向量或速度向量,如果这些向量的长度和方向相同,这些向量都是相同向量,或者说,多个位移向量或速度向量是否相等,和起点无关,只决定于这些向量的长度和方向是否相等。
可用向量公式:pos=pos+v,计算小球中心点每帧的位置向量。其中pos+v中的pos是小球中心点在上一帧的位置向量,v是小球每帧位移,pos+v是两向量相加,结果仍是向量,是小球中心点在当前帧的位置向量,将pos+v重新赋值给pos,小球将移到新位置。该公式也可以这样理解,将小球每帧位移向量平移,使其起点移到小球中心点上一帧位置,每帧位移向量的终点,就是小球中心点在当前帧的位置。例子:小球用40帧从(-7,-5,0)点移到(13, 3, -2)点,使用向量方法的程序如下。
from vpython import *
scene.title="小球用40帧从(-7,-5,0)移到(13,3,-2)"
ball=sphere(pos=vector(-7,-5,0),radius=2,color=color.blue)
start=vector(-7,-5,0) #起点的位置向量
end=vector(13,3,-2) #终点的位置向量
s=end-start #从起点到终点的位移向量
v=s/40 #每帧位移向量,即速度
#v=(vector(13,3,-2)-vector(-7,-5,0))/40 #可用此语句代替以上4条语句
for n in range(40):rate(10) ball.pos+=v
一个向量,由于其所在语句中的表达式不同,或在同一表达式的位置不同,向量代表的意义也可能不同,例如,在小球移动中,向量可能是代表一个点的位置向量,也可能是位移向量,还可能是速度向量,即每帧位移向量,以及法线向量等。在使用中,要根据具体情况,来判断向量的用途。例如上例s=end-start,两个向量相减,向量end是是小球移动起点的位置向量,向量start是小球移动终点的位置向量,s是从球从移动起点到移动终点的位移向量。又如ball.pos+=v,即ball.pos=ball.pos+v,在小球移动中,等号后边的ball.pos是上一帧小球位置向量,v是速度向量(一帧的位移向量),等号前边的ball.pos是当前帧小球位置向量,即小球从上一阵小球的位置向量作为起点出发,按照速度向量v前进,小球在当前帧所的位置向量。
