引言

选修了一门“艺术与科学实验室”的课,第三次作业是在自然中发现数学规律,并将其通过技术实现出来。在生活中花随处可见,并且具有极高的美感和艺术价值。对于花的绘制用数学方式实现出来使我十分激动。学校里花的原图一张:
在这里插入图片描述

python 源代码

此代码借来源此CSDN博客

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.gca(projection='3d')
[x, t] = np.meshgrid(np.array(range(25)) / 24.0, np.arange(0, 575.5, 0.5) / 575 * 17 * np.pi - 2 * np.pi)
p = (np.pi / 2) * np.exp(-t / (8 * np.pi))
u = 1 - (1 - np.mod(3.6 * t, 2 * np.pi) / np.pi) ** 4 / 2
y = 2 * (x ** 2 - x) ** 2 * np.sin(p)
r = u * (x * np.sin(p) + y * np.cos(p))
h = u * (x * np.cos(p) - y * np.sin(p))
surf = ax.plot_surface(r * np.cos(t), r * np.sin(t), h, rstride=1, cstride=1,
                       cmap=cm.gist_rainbow_r, linewidth=0, antialiased=True)
plt.show()

思路解读

思路零:3D!

对于自然中的植物,我们很难将其抽象为二维世界中的存在物,不真实。故我们使用python的matplotlib绘制3D图像。这是整体的效果图:
1

可见该用彩虹色绘制出来的花非常接近现实生活中的花,比传统中2D的花要真实很多,以下是一些2D绘制的花:(借鉴网上的某些代码)

3

2

思路一:中心旋转——center

花的花瓣总是围绕中心轴生长,我们不妨将花看做一个中心旋转3D图。在此基础上建立柱状极坐标系。
在这个极坐标系中,图像上的每个点有三个自由度(r,t,h)(其中t表示theta

思路二:旋进——radius & height

观察花瓣生长规律,我们发现,其外边缘线在一条旋转内缩的曲线上。这条曲线里中心轴的距离r逐渐缩短,距离地平面h逐渐变高。且该曲线大概符合以下公式:

p = (np.pi / 2) * np.exp(-t / (8 * np.pi))
r = np.sin(p) 
h = np.cos(p)

p是一个特殊的函数,只需要设置成关于t单调递减
6
7

思路三:花瓣状——pattern

花瓣状乘类似于水滴状关于中心轴旋转。因此r和h都是关于模式u的函数

u = 1 - (1 - np.mod(3.6 * t, 2 * np.pi) / np.pi) ** 4 / 2
r = u * np.sin(p) 
h = u * np.cos(p)

8
如图可见r和t都呈花瓣的波形,而且做到了同步进行

思路四:下凸——convex

为了图像更加真实,我们选择将h和r进行修正,添加一个修正项y,使花瓣的形态向下凸,更接近真实生活:
00

y = 2 * (x ** 2 - x) ** 2 * np.sin(p)
r = u * (x * np.sin(p) + y * np.cos(p))
h = u * (x * np.cos(p) - y * np.sin(p))

对比y=0:
0
和经过修正后的图像
1
显然修正后图像的层次和立体感更强,花瓣有向内部卷曲的趋势

思路五:以点逼面

实际上我们画出来的不是花瓣的平面,而是一个个离散的点(总共25*1150 = 28750个),经过python的plot_surface逼近花瓣的面状

[x, t] = np.meshgrid(np.array(range(25)) / 24.0, 
    np.arange(0, 575.5, 0.5) / 575 * 17 * np.pi - 2 * np.pi)

x,t是两个自变量,相当于参数方程中两个参数,最终表示为三维坐标系下的某点(rcos(θ),rsin(θ),h),x是在[0,25)上取的25个点,t是-2*pi15*pi上取的1150个点,在3D图像中共计28750个点,绘制出的散点图通过python自带的函数连成曲面状。

其他种类的花

分析了用python绘制3D花的原理,绘制了一个彩色的花。里面提到了6个idea(3D, center, radius&height, pattern, convex和approach),是时候应用这些原理,绘制一些现实中不同品种的的花(为原来的花继承一些花的子类),添加细节去丰富它。

玫瑰花

  • 原始图片
    在这里插入图片描述
  • 特征:①叶片较宽,大概一片花瓣围绕中心轴的角度120°;②花瓣较往中心靠拢,故初相位可以尝试加上4pi到8pi之间;③边缘并不是完美的弧线,而是添加了些许扰动;④颜色修改成红色
  • 代码修改
# 省略了头文件,可以在之前的博客里看到
fig = plt.figure()
ax = fig.gca(projection='3d')
# 将相位向后移动了6*pi
[x, t] = np.meshgrid(np.array(range(25)) / 24.0, np.arange(0, 575.5, 0.5) / 575 * 20 * np.pi + 4*np.pi)
p = (np.pi / 2) * np.exp(-t / (8 * np.pi))
# 添加边缘扰动
change = np.sin(15*t)/150
# 将t的参数减少,使花瓣的角度变大
u = 1 - (1 - np.mod(3.3 * t, 2 * np.pi) / np.pi) ** 4 / 2 + change
y = 2 * (x ** 2 - x) ** 2 * np.sin(p)
r = u * (x * np.sin(p) + y * np.cos(p))
h = u * (x * np.cos(p) - y * np.sin(p))
c= cm.get_cmap('Reds')
surf = ax.plot_surface(r * np.cos(t), r * np.sin(t), h, rstride=1, cstride=1,
                       cmap= c, linewidth=0, antialiased=True)
plt.show()
  • 新图
    边缘扰动之前:
    在这里插入图片描述
    边缘扰动之后:
    在这里插入图片描述
    看出来边缘稍微的扰动使画面更逼真而立体

月季花

  • 原始图片
    在这里插入图片描述
  • 特征:①花瓣很多很密,可以将t的周期沿得更长,初相位更早;②颜色为粉色;③扰动的周期更长,扰动更剧烈;④半径比普通的花长
  • 代码:
fig = plt.figure()
ax = fig.gca(projection='3d')
[x, t] = np.meshgrid(np.array(range(25)) / 24.0, np.arange(0, 575.5, 0.5) / 575 * 30 * np.pi - 4*np.pi)
p = (np.pi / 2) * np.exp(-t / (8 * np.pi))
change = np.sin(20*t)/50
u = 1 - (1 - np.mod(3.3 * t, 2 * np.pi) / np.pi) ** 4 / 2 + change
y = 2 * (x ** 2 - x) ** 2 * np.sin(p)
r = u * (x * np.sin(p) + y * np.cos(p)) * 1.5
h = u * (x * np.cos(p) - y * np.sin(p))
c= cm.get_cmap('magma')
surf = ax.plot_surface(r * np.cos(t), r * np.sin(t), h, rstride=1, cstride=1,
                       cmap= c, linewidth=0, antialiased=True)
plt.show()
  • 图像
    在这里插入图片描述

桃花

  • 原始图片:
    在这里插入图片描述
  • 特征:①花瓣很小较窄,可以将t的周期变得更短,初相位更早;②颜色为淡粉色;③扰动的周期短,扰动更剧烈
  • 代码:
fig = plt.figure()
ax = fig.gca(projection='3d')
[x, t] = np.meshgrid(np.array(range(25)) / 24.0, np.arange(0, 575.5, 0.5) / 575 * 6 * np.pi - 4*np.pi)
p = (np.pi / 2) * np.exp(-t / (8 * np.pi))
change = np.sin(10*t)/20
u = 1 - (1 - np.mod(5.2 * t, 2 * np.pi) / np.pi) ** 4 / 2 + change
y = 2 * (x ** 2 - x) ** 2 * np.sin(p)
r = u * (x * np.sin(p) + y * np.cos(p)) * 1.5
h = u * (x * np.cos(p) - y * np.sin(p))
c= cm.get_cmap('spring_r')
surf = ax.plot_surface(r * np.cos(t), r * np.sin(t), h, rstride=1, cstride=1,
                       cmap= c, linewidth=0, antialiased=True)
plt.show()
  • 图像
    在这里插入图片描述
    由于时间关系,只能草草做了3个品种的花,但以python的强大功能,我们还能尝试更多,更精妙的算法。不仅仅在颜色、扰动、大小上变化。我们还能改变花的形态,甚至创造出一些生活中本来不存在的花,更加充分感受科学与艺术的结合。