翼度科技»论坛 编程开发 python 查看内容

Python工程数学7VPython制作3D图形和动画(上)坐标系、基本形状、点和线

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
7 简介

VPython是一个基于Python语言的开源库,专门用于创建三维图形和动画。它为用户提供了一种简单而直观的方式,通过Python代码构建出生动的三维场景。VPython的设计初衷是让用户能够轻松地将物理概念可视化,因此在教学、科研和学习物理等领域得到了广泛应用。

  • VPython的特点

    • 易于学习: VPython的语法简单易懂,即使没有编程基础的用户也能很快上手。
    • 直观可视化: 通过简单的代码,就可以创建出复杂的3D模型和动画效果。
    • 物理模拟: VPython内置了许多物理模型,可以模拟各种物理现象,如运动、力、碰撞等。
    • 交互性强: 用户可以通过鼠标、键盘等方式与创建的3D场景进行交互。
    • 开源免费: VPython是一个开源项目,用户可以免费使用和修改。

  • VPython的应用

    • 物理教学: VPython可以用来模拟各种物理实验,帮助学生更好地理解物理概念。
    • 科学可视化: VPython可以将科学数据可视化,使复杂的数据变得更加直观。
    • 游戏开发: VPython可以用于开发简单的3D游戏。
    • 虚拟现实: VPython可以用于创建简单的虚拟现实场景。

VPython 模块名称中的字母 “V”代表视觉(visual),指的是物体在三维空间中的表示和运动。
物理关系和过程的动态不再像 SciPy 模块那样以函数图的形式来描述,而是以观察者在现实中的感知来描述。重要的是要考虑到许多物理过程(如斜抛)可能无法被人眼捕捉到细节。VPython 提供了根据需要使用速率(频率)函数放慢(慢动作)或加速过程的功能。在计算机上模拟真实动作时,计算机图形学领域将这一过程称为动画,即赋予物体 “生命”。
表示物体的画布(canvas)称为场景(scene)。在场景中,您可以按住鼠标右键并移动鼠标光标,使显示的对象绕 x-y-z 轴旋转。这允许观察者从不同角度查看对象。
从第 7 版开始,VPython 模块使用 from vpython import * 语句导入。其他模块无需导入。启动程序后,默认浏览器会打开,程序在网络图形库(WebGL)中运行。WebGL 是一个 JavaScript 编程接口,允许在网络浏览器中显示硬件加速的 3D 图形,而无需额外的扩展程序。
使用 vector(x, y, z) 方法可以确定物体在三维空间中的位置,如果物体要移动,还可以更改位置。由于向量的概念在 VPython 中起着核心作用,让我们用一个小型控制台示例来简要讨论这一主题:
  1. >>> 从 vpython 导入 *
  2. >>> v1=vector(1,2,3)
  3. >>> v2=vector(4,5,6)
  4. >>> v1+v2 <5, 7, 9>
  5. >>> type(v1)
  6. <class 'vpython.cyvector.vector'>
复制代码
在第二行和第三行中,vector(x,y,z) 方法将 v1 和 v2 对象创建为三维向量,其中包含 x-y-z 坐标的数据。第四行是这些向量的加法运算。除了加法之外,还实现了标量积和交叉积。也可以使用 vec() 代替 vector()。
使用以下语句可以创建一个体对象 obj:
  1. obj=body(pos=vec,size=vec,axis=vec,color=color.color,...)
复制代码
在这种情况下,body 方法代表基本形状,如 box()、sphere()、cylinder()、cone() 等,它们由 VPython 模块提供。如果需要其他体,可以使用 compound ([k1,k2, ...])方法从基本体(k1、k2 等)创建它们。
7.1 坐标系


上图坐标原点位于画布中心,X 轴从左到右,Y 轴从下到上,Z 轴垂直于画布。 启动程序,稍作延迟后程序将在默认浏览器中运行。然后,右键单击画布,按住鼠标右键,旋转坐标系,以便观察到尽可能多的视角。在坐标系中插入坐标为(5,5,0)的灰色点可方便您在空间中定位,并明确 VPython 中坐标变换的作用模式。
  1. #01_coordinates.py
  2. from vpython import *
  3. h=10. #height
  4. b=10. #width
  5. t=10. #depth
  6. scene.title="<h2>VPython坐标系</h2>"
  7. scene.width=scene.height=600
  8. scene.background=color.white
  9. scene.center=vector(0,0,0)
  10. scene.range=1.5*b
  11. x0=vector(-b,0,0)
  12. y0=vector(0,-h,0)
  13. z0=vector(0,0,-t)
  14. #x-axis is red
  15. arrow(pos=x0,axis=vector(2*b,0,0),shaftwidth=0.15,color=color.red)
  16. #y-axis is green
  17. arrow(pos=y0,axis=vector(0,2*h,0),shaftwidth=0.15,color=color.green)
  18. #z-axis is blue
  19. arrow(pos=z0,axis=vector(0,0,2*t),shaftwidth=0.15,color=color.blue)
  20. label( pos=vec(b,-1,0),text="x",height=30,box=False,opacity=0)
  21. label( pos=vec(-1,h,0),text="y",height=30,box=False,opacity=0)
  22. label( pos=vec(-1,0,t),text="z",height=30,box=False,opacity=0)
  23. points(pos=vector(5,5,0))
  24. scene.caption="\n点击鼠标右键然后拖动"
复制代码
执行结果

第 03 至 05 行定义了显示窗口(画布)的高度、宽度和深度。
第06 行中的 scene.title=“...” 命令用 HTML H2输出程序的标题。
在第 07 行,scene.width=scene.height=600 命令将显示窗口的宽度和高度分别设置为 600 像素。
在第 08 行,scene.background=color.white 将画布背景设置为白色。默认设置为黑色。
第 09 行中的 scene.center=vector(0,0,0) 语句用于设置坐标系的原点,实际上并无必要,因为默认值正好将原点置于画布的中心。
我们在本例中加入该语句只是为了进行进一步的程序测试。
由于 scene.range=1.5*b(第 10 行),显示范围被放大,因此在旋转坐标系时,画布上会有足够的空间。
第 11 行至第 13 行使用 VPython 方法 vector() 移动坐标轴。负号会导致坐标轴向右(x 轴)、向上(y 轴)或向前(z 轴)移动。三个坐标轴的长度均为 20 个单位。
在第 15、17 和 19 行中,arrow() 方法将坐标轴绘制为箭头对象。
label()方法对坐标轴进行标注(第 20 至 22 行)。
使用 points(pos=vector(5,5,0)) 方法创建的点应能证实坐标变换的正确性: 该点正好位于 x 轴和 y 轴截距的一半。
使用 scene.caption=“...”,可以在浏览器中输出任何文本(第 24 行)。
练习 应在第二、第三和第四象限表示该点。分别修改源代码并重新启动程序。在场景中旋转坐标系,检查点的位置。
7.2 基本形状、点和线

可以使用 VPython 创建以下基本形状:长方体、球体、圆柱体、圆锥体、金字塔、椭圆体和圆环。创建体对象的一般语法是
  1. obj=body(pos=vec(x0,y0,z0),axis=vec(x,y,z),size=vec(a,b,c), color=color.red)
复制代码
第一个参数指定物体在三维空间中的位置。位置的默认设置为 pos=vector(0,0,0)。可以使用 obj.pos=vector(x,y,z) 在动画循环中更改位置。如果只需更改 x 方向的位置,则使用 obj.pos.x= 值语句即可。
轴向向量定义了主体对象的方向。例如,如果将向量(1,0,0)赋值给轴,则主体将沿 x 轴方向对齐。这同样适用于 Y 轴和 Z 轴。
尺寸向量决定了主体对象的尺寸。例如,box(size=vector(10,5,2)) 方法将创建一个宽度为 10 个长度单位(LE)、高度为 5 个长度单位、深度为 2 个长度单位的长方体对象。
颜色属性可以通过 obj.color=vector(R,G,B) 向量来改变。默认颜色设置为灰色。
7.2.1 圆柱体

圆柱体对象具有以下属性:位置、长度、方向、半径和颜色。pos=vector(x0,y0,z0) 矢量定义了圆柱体在空间中的位置(圆柱体底部的中心)。轴=vector(x,y,z)向量确定圆柱体对象的长度和方向。使用下面的方法,可以从圆柱体()类中创建一个圆柱体对象。
类的圆柱体对象:
  1. cylinder(pos=vector(x0,y0,z0),axis=vector(x,y,z),radius=r,...)
复制代码
默认颜色(默认值)为灰色。半径的默认值为 radius=1。
例如,如果 x0=-20,x=40,且位置和轴向量的所有其他值均为零,那么将创建一个长度为 40 个长度单位(LE)的圆柱体对象,并在 x 轴上左移 20 LE。圆柱体的中心线正好位于 X 轴上。
另外,也可以使用 size= vector(length,height,width) 属性指定圆柱体对象的尺寸。

  • 实例:在 VPython 中创建圆柱体对象
  1. #02_cylinder.py
  2. from vpython import *
  3. scene.title="<h2>圆柱体</h2>"
  4. scene.autoscale=True
  5. scene.background=color.white
  6. scene.width=600
  7. scene.height=600
  8. scene.center=vector(0,0,0)
  9. scene.range=30
  10. #Position: x0,y0,z0
  11. p=vector(-20,0,0)
  12. #alignment and length
  13. a=vector(40,0,0)
  14. r=10.  #radius
  15. #col=color.gray(0.5)
  16. #red, green, blue
  17. col=vector(1,0,0)
  18. cylinder(pos=p,axis=a,radius=r,color=col,opacity=0.5)
  19. #length, height, width
  20. #cylinder(pos=p,size=vector(40,20,20),color=col)
  21. scene.caption="\n点击鼠标右键然后旋转"
复制代码
scene.range=30 属性(第 09 行)改变了显示区域的宽度。小于 30 的值(第 09 行)会放大圆柱体对象,大于 30 的值会缩小圆柱体对象。
第 11 行中的 p=vector(-20,0,0) 向量指定圆柱体在 x 轴上向左移动 20 LE。a=vector(40,0,0)向量(第 13 行)定义圆柱体的长度为 40 LE。由于对齐矢量轴的 y 和 z 分量值为零,因此圆柱体的中心线位于 x 轴上。
在第 17 行中,通过 col=vector(1,0,0) 向量,以 RGB 值确定主体的颜色。颜色饱和度可设置为 0 至 1。颜色的不透明度。可设置的值在 0 和 1 之间。如果不透明度值为 0,则主体完全透明。
在第 18 行,以下方法生成了一个圆柱体对象:cylinder(pos=p,axis=a,radius=r,color=col,opacity=0.5)这个圆柱体对象的属性存储在 p、a、r 和 col 对象中(第 11、13、14 和 17 行)。

7.2.2 立方体

可以使用以下方法创建一个立方体对象:
  1. box(pos=vec(x0,y0,z0),axis=vec(x,y,z),size=vec(L,H,B), ...)
复制代码
pos 向量定义了长方体的位置。与圆柱体对象不同的是,这里的位置不是指对象的一端,而是指长方体的中心。轴向量定义方向,尺寸向量定义长方体对象的尺寸(长、高、宽)。

  • 实例: 创建了一个长 40、高 20、宽 10 的长方体。
  1. #03_cuboid.py
  2. from vpython import *
  3. scene.title="<h2>立方体</h2>"
  4. scene.autoscale=True
  5. scene.background=color.white
  6. scene.width=600
  7. scene.height=600
  8. scene.center=vector(0,0,0)
  9. #x0,y0,z0
  10. p=vector(0,0,0)
  11. #alignment
  12. a=vector(1,0,0)
  13. #dimensions: length, height, width
  14. dim=vector(40,20,10)
  15. scene.range=30
  16. #rotation
  17. d=vector(0,0,0)
  18. c=color.gray(0.5)
  19. box(pos=p,axis=a,size=dim,up=d,color=c)
  20. scene.caption="\n点击鼠标右键然后旋转"
复制代码
在第 10 行中,p=vector(0,0,0) 向量指定长方体正好位于绘图区域的中心。a=vector(1,0,0) 向量(第 12 行)确定了长方体的方向: 其中心线位于 x 轴上。第 14 行的 dim=vector(40,20,10)
向量(第 14 行)提供了盒子的尺寸: 它的长度为 40 LE,高度为 20 LE,宽度为 10 LE。使用第 17 行中的 d=vector(0,0,0) 向量,可以使对象绕其自身轴线旋转。
在第 19 行中,box() 方法创建了具有给定属性的长方体对象。

7.2.3 点

可以使用以下方法创建点对象:
  1. points(pos=[vector(-1,0,0), vector(1,0,0)], radius=0, ...)
复制代码
pos 属性需要一个包含点对象位置的向量列表。无需指定半径属性。
根据 VPython 文档,半径的默认值应为 2.5 像素,即使赋值为 0 也是如此。

  • 实例 将立方体的中心和顶点表示为点对象
  1. #04_points.py
  2. from vpython import *
  3. scene.width=600
  4. scene.height=600
  5. scene.background=color.white
  6. e=1.
  7. scene.center=vector(e/2,e/2,e/2)
  8. scene.range=1.2*e
  9. v=[(0,0,0),(0,0,e),(0,e,0),(0,e,e),
  10.     (e,0,0),(e,0,e),(e,e,0),(e,e,e),(e/2,e/2,e/2)]
  11. box(pos=vector(e/2,e/2,e/2),size=vector(e,e,e),
  12.     axis=vector(1,0,0),opacity=0.5)
  13. points(pos=v,color=color.red)
复制代码
第 06 行指定立方体的边长 e。在第 07 行中,坐标系中心被缩放为边长的一半。第 09 行包含一个名为 v 的列表,其中包含立方体中心和顶点的位置。第 11 行,box() 方法创建了一个边长为 e 的透明立方体。第 13 行,points() 方法创建了 9 个红色点对象,半径为默认值。

7.2.4 直线

以下方法在两点之间绘制直线:
  1. curve(vector(-1,0,0), vector(1,0,0), ...)
复制代码
例如,假设给出了两个向量 v1 和 v2。然后,您可以使用五种不同的语法在这两个向量之间画一条连线。
语法变体:
  1. >>> curve(v1,v2) #1
  2. >>> curve([v1,v2]) #2
  3. >>> curve(pos=[v1,v2]) #3
  4. >>> c = curve(v1) #4
  5. >>> c.append(v2)
  6. >>> c=curve() #5
  7. >>> c.append(v1,v2)
复制代码

  • 直线实例
展示了 curve() 方法如何用长度为e, 四面体的底面位于 x-y 平面。根据底面圆周的半径 r,可以按以下方法计算边长:

四面体的高指向 Z 轴的正方向:
  1. #05_lines.py
  2. from vpython import *
  3. scene.width=600
  4. scene.height=600
  5. scene.background=color.white
  6. r=10. #radius of the plane
  7. e=sqrt(3.)*r #edge length
  8. scene.center=vector(0,0,0)
  9. scene.range=1.8*r
  10. x=r*cos(pi/6.)
  11. y=r*sin(pi/6.)
  12. z=sqrt(6.)*e/3. #height
  13. #triangle: bottom left-top, bottom right-bottom left
  14. v1=[(-x,-y,0),(0,r,0),(x,-y,0),(-x,-y,0)]
  15. #star: bottom left-center, top-center, bottom right-center
  16. v2=[(-x,-y,0),(0,0,z),(0,r,0),(0,0,z),(x,-y,0)]
  17. points(pos=v2,radius=10.,color=color.red)
  18. c=curve(pos=v1,color=color.green)
  19. c.append(v2,color=color.yellow)
复制代码
分析 第 06 行将 x-y 平面圆周(周界圆)的半径 r 设为 10 个单位长度。第 07 行计算边长 e。第 10 行和第 11 行计算 x-y 平面的 x 坐标和 y 坐标。第 12 行的语句计算四面体在 Z 轴方向的高度 z。第 14 行的 v1 列表包含 x-y 平面三角形底面积的坐标数据。第 16 行的 v2 列表包含四面体边角的 x-yz 坐标。第 17 行,points() 方法绘制了四面体的四个顶点。第 18 行,curve() 方法将 v1 列表中的线条对象绘制成三角形。第 19 行,将 v2 列表中的星形线条添加到折线 c 中。

参考资料

7.2.5 球体

sphere(pos=vector(x0,y0,z0),radius=r,...) 方法创建一个球体对象。pos 向量决定了球体在空间中的中心坐标,半径属性决定了球体的半径。

  • 实例:使用 sphere() 方法在空间中对称排列九个球体。
  1. #06_spheres1.py
  2. from vpython import *
  3. scene.width=600
  4. scene.hight=600
  5. scene.background=color.white
  6. x0=5.
  7. y0=5.
  8. z0=5.
  9. R1=1.
  10. R2=0.25
  11. #center
  12. sphere(pos=vector(0,0,0),radius=R1,color=color.red)
  13. #top
  14. sphere(pos=vector(0,y0,0),radius=R2,color=color.blue)
  15. #bottom
  16. sphere(pos=vector(0,-y0,0),radius=R2,color=color.blue)
  17. #left
  18. sphere(pos=vector(-x0,0,0),radius=R2,color=color.blue)
  19. #right
  20. sphere(pos=vector(x0,0,0),radius=R2,color=color.blue)
  21. #back
  22. sphere(pos=vector(0,0,-z0),radius=R2,color=color.blue)
  23. #front
  24. sphere(pos=vector(0,0,z0),radius=R2,color=color.blue)
  25. label( pos=vec(0,0,0), text="O",height=30,box=False,opacity=0)
  26. sphere(pos=vector(x0/2,0,0),radius=R2,color=color.blue)
  27. sphere(pos=vector(-x0/2,0,0),radius=R2,color=color.blue)
复制代码
第 06 至 08 行定义了蓝色小球在空间中的坐标。
中心红球的半径为 R1=1(第 09 行),其他六个球的半径为 R1=0(第 10 行)。
球的半径分别为 R2=0.25。在第 12 至 24 行,sphere() 方法创建了各个球体对象。注释描述了各个球体的位置。第 25 行创建了一个名为 O 的标签对象。

  • 实例:晶格
  1. #07_spheres2.py
  2. from vpython import *
  3. scene.background=color.white
  4. scene.width=600
  5. scene.height=600
  6. e = 5 #lattice spacing
  7. R = 0.5 #radius of an atomic nucleus
  8. for x in range(-e,e):
  9.     for y in range(-e,e):
  10.         for z in range(-e,e):
  11.             sphere(pos=vector(x,y,z),radius=R,color=color.red)
复制代码

三个嵌套 for 循环(第 08 至 11 行)计算红色球体的 x-yz 坐标。第 08 行的第一个 for 循环设置球体在 x 轴上的位置。第 09 行的第二个 for 循环设置球体在 Y 轴上的位置。第 10 行的第三个 for 循环设置 Z 轴上的位置。在第 11 行中,sphere(pos=vector(x,y,z),...)
方法创建单个红球对象。
7.2.6 穿透

穿透探讨了相互穿透的物体必须如何在三视图中表示,这对初学者来说往往是一个困难的概念。为此,我们提供了一个说明相互穿透体空间表示的程序。其图形输出如图 7.8 所示,在空间上表示了一个圆锥体和一个圆柱体的相互穿透。该程序可用于模拟该穿透的不同视图。
  1. #08_penetration.py
  2. from vpython import *
  3. rc=10. #radius of the cone
  4. hc=3.*rc #height of the cone
  5. scene.background=color.white
  6. scene.width=600
  7. scene.hight=600
  8. scene.range=2.1*rc
  9. rz=rc/2. #radius of the cylinder
  10. lz=2.5*rc #length of the cylinder
  11. z=rc/1.5 #displacement of the cylinder
  12. cone(pos=vec(0,-hc/2.5,0),axis=vec(0,hc,0),radius=rc)
  13. cylinder(pos=vec(-lz/2.,0,z),axis=vec(lz,0,0),radius=rz)
复制代码
圆锥的半径 rc 和高度 hc 是参考值(03 和 04 行)。圆柱体的半径 rz 和长度 lz(第 09 和 10 行)取决于这些值。
在第 12 行,使用 cone() 方法创建了一个圆锥体对象。轴线=vec(0,hc,0)矢量定义了圆锥在 Y 轴方向上的方向。
第 13 行,使用 cylinder() 方法创建一个圆柱体对象。
axis=vec(lz,0,0)向量定义了它在 x 轴方向上的方向。

7.2.7 复合体

您可以使用 compound([G1,G2,G3, ...])方法从基本形状 G1、G2 和 G3 创建实体对象。下例展示了如何通过两个基本形状(立方体和金字塔)的组合创建复合体。
  1. #09_combination.py
  2. from vpython import *
  3. scene.background=color.white
  4. scene.width=scene.height=600
  5. a=5.
  6. b=10.
  7. scene.range=1.5*b
  8. scene.autocenter=True
  9. p1=pyramid(pos=vec(0,a,0),axis=vec(0,1,0),size=vec(a,a,a),color=color.green)
  10. q1=box(pos=vector(0, a/2,0),size=vector(a,a,a),color=color.red)
  11. q2=box(pos=vector(0,-b/2,0),size=vector(b,b,b),color=color.blue)
  12. werkstueck=compound([p1,q1,q2])
复制代码
在第 09 行,使用以下方法创建了 p1 对象:pyramid(pos=vec(0,a,0),axis=vec(0,1,0),size=vec(a,a,a)
金字塔对象 p1 沿 y 轴正方向向上移动了 5 个单位长度。对齐方向为 y 轴。金字塔的长、宽、高各有 5 个单位长度的值。
q1 立方体在 y 轴正方向上向上移动了 2.5 个单位长度(第 10 行)。q2 立方体在负 y 轴上向下移动 5 个单位长度(第 11 行)。
第 12 行中的 compound([p1,q1,q2]) 方法将工件对象创建为复合体。


来源:https://www.cnblogs.com/testing-/p/18487463
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具