本文是利用python生成一颗行星以及它周围的环带,它是由线、点构造而成的二维平面图形。
源代码运行结果如下:
去掉坐标轴结果如下:
实现以上结果源码如下:
""" 本代码绘制了小行星以及它周围的环带 """ import numpy as np import matplotlib.pyplot as plt from math import sin, cos, radians, sqrt def rotx(xc, yc, zc, xp, yp, zp, Rx): g[0] = xp + xc g[1] = yp * cos(Rx) - zp * sin(Rx) + yc g[2] = yp * sin(Rx) + zp * cos(Rx) + zc return g def roty(xc, yc, zc, xp, yp, zp, Ry): g[0] = xp * cos(Ry) + zp * sin(Ry) + xc g[1] = yp + yc g[2] = -xp * sin(Ry) + zp * cos(Ry) + zc return g def rotz(xc, yc, zc, xp, yp, zp, Rz): g[0] = xp * cos(Rz) - yp * sin(Rz) + xc g[1] = xp * sin(Rz) + yp * cos(Rz) + yc g[2] = zp + zc return g plt.axis([0,150,100,0]) plt.axis('off') plt.grid(False) print('冲冲冲!!!!!') #定义参数 g=[0]*3 xc=80 #圆心 yc=50 zc=0 rs=25 #球面半径 lx=-1 #光线单位矢量分量 ly=0 lz=0 IA=0 # 定义曲线 IB=.8 n=2 Rx=radians(-20) Ry=radians(0) Rz=radians(30) # 添加背景色 for x in np.arange(0,150,1): for y in np.arange(0,100,1): plt.scatter(x,y,color = 'midnightblue') #绘制球体 ## 横向 phi1 = radians(-90) phi2 = radians(90) dhpi = radians(2) alpha1 = radians(0) alpha2 = radians(360) dalpha = radians(2) for alpha in np.arange(alpha1,alpha2+dalpha,dalpha): for phi in np.arange(phi1,phi2+dhpi,dhpi): xp = rs * cos(phi) * cos(alpha) yp = rs * sin(phi) zp = -rs * cos(phi) * sin(alpha) rotx(xc, yc, zc, xp, yp, zp, Rx) xp = g[0] - xc yp = g[1] - yc zp = g[2] - zc roty(xc, yc, zc, xp, yp, zp, Ry) xp = g[0] - xc yp = g[1] - yc zp = g[2] - zc rotz(xc, yc, zc, xp, yp, zp, Rz) xpg = g[0] ypg = g[1] zpg = g[2] a = xpg - xc b = ypg - yc c = zpg - zc qp = sqrt(a*a+b*b+c*c) nx = a/qp ny = b/qp nz = c/qp ndotl = nx * lx + ny * ly + nz * lz I = IA + (IB-IA)*((1+ndotl)/2)**n if phi == phi1: xpglast = xpg ypglast = ypg if nz < 0: plt.plot([xpglast,xpg],[ypglast,ypg],linewidth = 4, color = ((1-I),.8*(1-I),.45*(1-I))) xpglast = xpg ypglast = ypg ## 纵向 for phi in np.arange(phi1,phi2+dhpi,dhpi): r = rs * cos(phi) for alpha in np.arange(alpha1, alpha2 + dalpha, dalpha): xp = r * cos(alpha) yp = rs * sin(phi) zp = -rs * cos(phi) * sin(alpha) rotx(xc, yc, zc, xp, yp, zp, Rx) xp = g[0] - xc yp = g[1] - yc zp = g[2] - zc roty(xc, yc, zc, xp, yp, zp, Ry) xp = g[0] - xc yp = g[1] - yc zp = g[2] - zc rotz(xc, yc, zc, xp, yp, zp, Rz) xpg = g[0] ypg = g[1] zpg = g[2] a = xpg - xc b = ypg - yc c = zpg - zc qp = sqrt(a*a+b*b+c*c) nx = a/qp ny = b/qp nz = c/qp ndotl = nx * lx + ny * ly + nz * lz textbfI = IA + (IB-IA)*((1+ndotl)/2)**n if alpha == alpha1: xpglast = xpg ypglast = ypg if nz < 0: plt.plot([xpglast,xpg],[ypglast,ypg],linewidth = 4, color = ((1-I),.8*(1-I),.45*(1-I))) xpglast = xpg ypglast = ypg #绘制外围环形带 alpha1=radians(-10) alpha2=radians(370) dalpha=radians(.5) r1=rs*1.5 r2=rs*2.2 dr=rs*.02 deltar=(r2-r1)/7 #环形带宽 #旋转位于rα的环点p for r in np.arange(r1,r2,dr): for alpha in np.arange(alpha1,alpha2,dalpha): xp=r*cos(alpha) yp=0 zp=-r*sin(alpha) rotx(xc,yc,zc,xp,yp,zp,Rx) xp=g[0]-xc yp=g[1]-yc zp=g[2]-zc roty(xc,yc,zc,xp,yp,zp,Ry) xp=g[0]-xc yp=g[1]-yc zp=g[2]-zc rotz(xc,yc,zc,xp,yp,zp,Rz) xpg=g[0] ypg=g[1] zpg=g[2] #选择环带颜色 if r1 <= r < r1+1*deltar: clr=(.63,.54,.18) if r1+1*deltar <= r <= r1+2*deltar: clr=(.78,.7,.1) if r1+2*deltar <= r <= r1+3*deltar: clr=(.95,.85,.1) if r1+3*deltar <= r <= r1+4*deltar: clr=(.87,.8,.1) if r1+5*deltar <= r <= r1+7*deltar: clr=(.7,.6,.2) #阴影 magu=sqrt(lx*lx+ly*ly+lz*lz) ux=-lx/magu uy=-ly/magu uz=-lz/magu vx=xc-xpg vy=yc-ypg vz=zc-zpg Bx=uy*vz-uz*vy By=uz*vx-ux*vz Bz=ux*vy-uy*vx magB=sqrt(Bx*Bx+By*By+Bz*Bz) if magB < rs: #在阴影区域 if vx*lx+vy*ly+vz*lz <= 0: clr=(.5,.5,.2) if r1+4*deltar <= r <= r1+5*deltar: clr='midnightblue' #绘制线段 if alpha == alpha1: xstart=xpg ystart=ypg if zpg <= zc: plt.plot([xstart,xpg],[ystart,ypg],linewidth=2,color=clr) if zpg >= zc: a=xpg-xc b=ypg-yc c=sqrt(a*a+b*b) if c > rs*1.075: #仅绘制环的可见部分 plt.plot([xstart,xpg],[ystart,ypg],linewidth=2,color=clr) xstart=xpg ystart=ypg plt.show()
本绘制总共分为三部分:首先是定义参数,其次是绘制中心的球体,最后是绘制外围环带。
定义参数是通过建立数学模型,借了书中的示例,对数学感兴趣可参考《python图形编程2D和3D图像的创建》这本书。
绘制球体和外围环带有遮挡和阴影,需要消隐之类的操作,这些在实现的过程中有一定难度。
本图绘制是用线、点构成的,其中背景是用点来构成,而图形是采用线构成,前文效果展示时看不出来,但是将局部放大展示使可以很清楚的看到。这也让我更深刻的理解了“点动成线、线动成面”这句话。很棒!希望本文对学习中的您有帮助。
局部展示图:点为背景,线为图像。