这篇文章向你展示了如何用Python绘制一个美丽的土星环。内容简洁易懂,一定会让你眼前一亮。希望通过这篇文章的详细介绍,你能有所收获。
土星环非常有名。虽然木星、土星、天王星和海王星也有光环,但土星环是我们太阳系中最大、最亮、最知名的行星环。
它由小如灰尘的颗粒和大如巨石的物体组成。这些天体的成分主要是冰,一般认为是彗星或较大的小行星与土星的一颗卫星相撞后产生的,两者都碰撞成小块。土星自古就为人所知,但直到1610年,伽利略才第一次用望远镜观测到它。
这颗行星以罗马农业之神土星命名,土星是我们一周的第六天。
图1到图5中的图像是由本文末尾的代码生成的。每张图片呈现不同的方向角,图片标题中给出了相应的描述。
标题中还列出了入射光的单位矢量分量,例如,lx=0.707,ly=0.707,lz=0表示左上象限的光源;Lx=-1,ly=0,lz=0表示光源来自右侧。请注意图中行星在环上投下的阴影,尤其是图5,可以看到行星轮廓的曲率。
图1土星1:Rx=-20度带土星环和阴影;Ry=0,Rz=-10 deg;lx=1,ly=0,lz=0
图2土星2带土星环和阴影:Rx=-8;Ry=0,Rz=-30 deg;lx=0.707,ly=0.707,lz=0
图3土星3带土星环和阴影:Rx=20度;Ry=0,Rz=25度;lx=0.707,ly=0.707,lz=0
图4土星4带土星环和阴影:Rx=-10度;Ry=0,Rz=25度;lx=0.707,ly=-0.707,lz=0
图5土星5包括土星环和阴影:Rx=20度;Ry=0,Rz=30度;lx=-1,ly=0,lz=0
作为对比,你可以在以下网站找到土星的照片:
https://www.jpl.nasa.gov/spaceimages/?搜索=saturncategory=#提交
图6显示了用于构建土星环的数学模型。介绍了一种实现球体着色的算法。首先,创建一个直立的球体,即经度是垂直的,纬度是水平的(即平行于XZ平面)。然后,从初始方向开始,围绕x、y和z轴旋转球体。
图6土星环模型:从XZ平面看行星和环的俯视图,Rx=0,Ry=0,Rz=0 0,Rz=0。
我们对土星环也是如此。我们可以创建一个平行于XZ平面的水平环,然后将其与土星以相同的角度旋转。土星环的平面穿过土星球体的中心,所以土星和环有相同的旋转中心。
土星环被绘制成一系列相邻的同心圆,每个同心圆都由小段组成。参考图6和文章末尾的代码,土星环的内半径和外半径设置在第42行和第43行,同心圆之间的距离设置在第44行。土星环被分成七个不同颜色的同心环形带(图6中未显示),第45行的deltar是它们的宽度。
构成同心圆的每个线段都是单独绘制的。第48条线是从r1画到r2,圆弧段是径向循环画的。线49是围绕圆周画的圆。在行50-61上执行的旋转操作产生行62和63中的全局绘图坐标xpg和ypg,并且旋转函数与先前程序中的相同。
接下来,设置第66-75行线段的颜色。土星环由不同颜色的带组成,这与美国宇航局观测图像中看到的物理组成结果一致。R=r1至r1。
deltar的第一个条带具有颜色clr=(.63,.54,.18),剩余的条带也是如此。
第五个条带省略掉了,因为它是空的,背景颜色能显示出来。第六个条带的宽度是其他条带的两倍,并且为第七个条带提供了颜色。
对于给定的光方向,从大多数角度上,行星体本身都会在环上投下阴影。参考图7,我们的目标是确定点p到底位于行星阴影区域内部还是外部。
球状的行星将产生圆形的阴影,阴影的直径与行星的尺寸相等,或者更准确地说,是球体的“大圆”。它是用通过圆心的平面切割球体而得到的最大圆,就像把橙子切成两半,你看到的是一个橙子的最大圆。
在图7中,这种阴影可能是由相同大小的圆盘投影产生的,也可能是由球状行星投影产生的,两种情况下,阴影的大小都是一样的。在土星的侧面图中,大圆显示为是一条通过平面中心的加粗线。
从图7的几何图形中可以看出,如果p位于|B| > rs的位置,则它位于阴影区之外,其中rs是土星的半径;如果|B| < rs,则p位于在阴影区之中。在绘制条带的时候,如果我们确定了p的位置在阴影区中,我们就把这个点涂成灰色,如果它在阴影区之外,我们就用第66-75行设置的条带颜色给它着色。
▲图7 阴影模型
我们的目标是求出给定位置p时的|B|值,由图7可看出:
|B|=|V|sin(φ)
并且我们知道:
V×û=|V||û|sin(φ)
其中û=-î 。将上述方程与|û|=1合并得:
B=V×û
|B|=|V×û|
在代码第78行中确定了入射光矢量î 的长度为1,但如果在第23-25行中输入的分量不计算为1,即
则入射光矢量可能不等于1。有必要的话,需要在第79-81行进行重构。第82-84行建立矢量V的分量。第85-87行计算B的分量。第88行给出其幅度magB = |B|。
第89行确定p是否位于阴影区内,如果是,则执行第90行V与î的点积。这是用来确定p是否位于行星朝向光源的一侧,在这种情况下,它与行星的暗侧相对,而不在阴影区。因为在第78-89行的阴影算法中并未区分p的位置,所以此处必须进行明确。如果p确实位于阴影区域内的暗侧,则在第91行中将p设置为中等灰色。
相信你一定注意到,图6的土星环上有一个暗色条带,这是因为土星环在该位置上是空的:那里没有固体颗粒物,不能反射阳光。因此我们透过条带看到了背景颜色'midnightblue'。但这会产生一个问题,即阴影颜色的绘制会覆盖该空白处的背景颜色,因此在第93和94行将其重置为'midnightblue'。
既然条带的颜色都建立好了,我们就可以通过一个个短线段来绘制土星环了。第97-100行计算第一个线段的起始位置。参考图6,第100-101行确定该线段与土星的遮挡关系,线段在前就会被绘制。
103-108行确定线段是否在土星后面,位于后面就不会被绘制。这种遮挡关系是通过计算点的全局坐标与土星中心之间的距离c来完成的。
第107行的意思是,如果c大于球体半径的1.075倍,则绘制该段。因子1.075的作用是防止线段与球体的表面重合,这是有必要的,不然小于球体半径的可见区段将不会被绘制。
本文代码生成的图像有两点需要注意:首先是颜色。美国宇航局的摄影图像呈现的是一种几乎没有颜色灰色,但是许多土星观察者都将它描述为金黄色,因此我们选择了金色。
所有摄影师都知道,在摄影图像中呈现物体的真实颜色是十分困难的,颜色取决于入射光和物体本身的颜色,或许最好的方法是依靠肉眼观察。
如果你不赞同本文代码所生成的图像中的颜色,可以通过更改程序中clr的定义来修改它们。需要注意的第二点,是图5中土星表面阴影的曲率,它表示着色算法是否按预期工作。
在程序的使用上,你可以自行更改第24-26行中的入射光的方向和第32-34行中的旋转角度。
运行代码也需要一段时间,请耐心等待。
1""" 2SATURN 3""" 4 5import numpy as np 6import matplotlib.pyplot as plt 7from math import sin, cos, radians, sqrt 8 9plt.axis([0,150,100,0]) 10plt.axis('off') 11plt.grid(False) 12 13print('running') 14#—————————————————parameters 15g=[0]*3 16 17xc=80 #———sphere center 18yc=50 19zc=0 20 21rs=25 #———sphere radius 22 23lx=-1 #———light ray unit vector components 24ly=0 25lz=0 26 27IA=0 28IB=.8 29+n=2 30 31Rx=radians(-20) 32Ry=radians(0) 33Rz=radians(30) 34 35#————————same as SHADESPHERE—————– 36 37#———————————————————rings 38alpha1=radians(-10) 39alpha2=radians(370) 40dalpha=radians(.5) 41 42r1=rs*1.5 43r2=rs*2.2 44dr=rs*.02 45deltar=(r2-r1)/7 #———ring band width 46 47#—————————————rotate ring point p which is at r, alpha 48for r in np.arange(r1,r2,dr): 49 for alpha in np.arange(alpha1,alpha2,dalpha): 50 xp=r*cos(alpha) 51 yp=0 52 zp=-r*sin(alpha) 53 rotx(xc,yc,zc,xp,yp,zp,Rx) 54 xp=g[0]-xc 55 yp=g[1]-yc 56 zp=g[2]-zc 57 roty(xc,yc,zc,xp,yp,zp,Ry) 58 xp=g[0]-xc 59 yp=g[1]-yc 60 zp=g[2]-zc 61 rotz(xc,yc,zc,xp,yp,zp,Rz) 62 xpg=g[0] 63 ypg=g[1] 64 65#—————————————————select ring band color 66 if r1 <= r < r1+1*deltar: 67 clr=(.63,.54,.18) 68 if r1+1*deltar <= r <= r1+2*deltar: 69 clr=(.78,.7,.1) 70 if r1+2*deltar <= r <= r1+3*deltar: 71 clr=(.95,.85,.1) 72 if r1+3*deltar <= r <= r1+4*deltar: 73 clr=(.87,.8,.1) 74 if r1+5*deltar <= r <= r1+7*deltar: 75 clr=(.7,.6,.2) 76 77#———————————————————————shadow 78 magu=sqrt(lx*lx+ly*ly+lz*lz) 79 ux=-lx/magu 80 uy=-ly/magu 81 uz=-lz/magu 82 vx=xc-xpg 83 vy=yc-ypg 84 vz=zc-zpg 85 Bx=uy*vz-uz*vy 86 By=uz*vx-ux*vz 87 Bz=ux*vy-uy*vx 88 magB=sqrt(Bx*Bx+By*By+Bz*Bz) 89 if magB < rs: #—————————if in the shadow region 90 if vx*lx+vy*ly+vz*lz <= 0: #———if v points toward light source 91 clr=(.5,.5,.2) #———shadow color 92 93 if r1+4*deltar <= r <= r1+5*deltar: #———overplot empty band 94 clr='midnightblue' #———with background color 95 96#——————————————————–plot line segment 97 if alpha == alpha1: 98 xstart=xpg 99 ystart=ypg 100 if zpg <= zc: #–front (z axis points into the screen) 101 plt.plot([xstart,xpg],[ystart,ypg],linewidth=2,color=clr) 102 103 if zpg >= zc: #–back 104 a=xpg-xc 105 b=ypg-yc 106 c=sqrt(a*a+b*b) 107 if c > rs*1.075: #——plot only the visible portion of rings 108 plt.plot([xstart,xpg],[ystart,ypg],linewidth=2,color=clr) 109 xstart=xpg 110 ystart=ypg 111 112plt.show()
上述内容就是如何用Python画一个绝美土星环,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/54364.html