文章目錄
- 前言
- 1. 極坐標系
- 2. 極坐標系花瓣
- 3. 三維花瓣
- 4. 花瓣微調
- 5. 結束語
前言
??在上篇博客中使用了matplotlib繪制了3D小紅花,本篇博客主要介紹一下3D小紅花的繪制原理,
1. 極坐標系
??對于極坐標系中的一點
P
P
P,我們可以用極徑
r
r
r 和極角
θ
\theta
θ 來表示,記為點
P
(
r
,
θ
)
P(r, \theta)
P(r,θ),其相關知識在高中就已經介紹,這里不再贅述,
??使用matplotlib繪制極坐標系:
import matplotlib.pyplot as plt
import numpy as np
if __name__ == '__main__':
# 極徑
r = np.arange(10)
# 角度
theta = 0.5 * np.pi * r
fig = plt.figure()
plt.polar(theta, r, c='r', marker='o', ms=3, ls='-', lw=1)
# plt.savefig('img/polar1.png')
plt.show()

??使用matplotlib繪制極坐標散點圖:
import matplotlib.pyplot as plt
import numpy as np
if __name__ == '__main__':
r = np.linspace(0, 10, num=10)
theta = 2 * np.pi * r
area = 3 * r ** 2
ax = plt.subplot(111, projection='polar')
ax.scatter(theta, r, c=theta, s=area, cmap='hsv', alpha=0.75)
# plt.savefig('img/polar2.png')
plt.show()

??有關
matplotlib極坐標的引數更多介紹,可參閱官網手冊,
2. 極坐標系花瓣
??繪制 r = s i n ( θ ) r=sin(\theta) r=sin(θ) 在極坐標系下的影像:
import matplotlib.pyplot as plt
import numpy as np
if __name__ == '__main__':
fig = plt.figure()
ax = plt.subplot(111, projection='polar')
ax.set_rgrids(radii=np.linspace(-1, 1, num=5), labels='')
theta = np.linspace(0, 2 * np.pi, num=200)
r = np.sin(theta)
ax.plot(theta, r)
# plt.savefig('img/polar3.png')
plt.show()

??以
2
π
2\pi
2π 為一個周期,增加影像的旋轉周期:
r = np.sin(2 * theta)

??繼續增加影像的旋轉周期:
r = np.sin(3 * theta)
r = np.sin(4 * theta)
??然后我們可以通過調整極徑系數和角度系數來調整影像:
import matplotlib.pyplot as plt
import numpy as np
if __name__ == '__main__':
fig = plt.figure()
ax = plt.subplot(111, projection='polar')
ax.set_rgrids(radii=np.linspace(-1, 1, num=5), labels='')
theta = np.linspace(0, 2 * np.pi, num=200)
r1 = np.sin(4 * (theta + np.pi / 8))
r2 = 0.5 * np.sin(5 * theta)
r3 = 2 * np.sin(6 * (theta + np.pi / 12))
ax.plot(theta, r1)
ax.plot(theta, r2)
ax.plot(theta, r3)
# plt.savefig('img/polar4.png')
plt.show()

3. 三維花瓣
??現在可以將花瓣放置在三維空間上了,根據花瓣的生成規律,其花瓣外邊緣線在一條旋轉內縮的曲線上,這條曲線的極徑
r
r
r 隨著角度的增大逐漸變小,其高度
h
h
h 逐漸變大,
??因此我們在
f
(
x
)
=
e
?
x
f(x) = e^{-x}
f(x)=e?x 的基礎之上定義了一個遞減函式,保證其值域在
(
0
,
π
2
]
(0, \frac {\pi} {2}]
(0,2π?],新的函式為:
f
(
θ
)
=
π
2
e
?
θ
f(\theta)=\frac {\pi} {2} e^{-\theta}
f(θ)=2π?e?θ??其函式影像如下:
??這樣定義
r
=
s
i
n
(
f
)
,
h
=
c
o
s
(
f
)
r=sin(f), h=cos(f)
r=sin(f),h=cos(f) 就滿足前面對花瓣外邊緣曲線的假設了,即
r
r
r 遞減,
h
h
h 遞增,
??現在將其放在三維空間中:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
if __name__ == '__main__':
fig = plt.figure()
ax = Axes3D(fig)
# plt.axis('off')
x = np.linspace(0, 1, num=30)
theta = np.linspace(0, 2 * np.pi, num=1200)
theta = 30 * theta
x, theta = np.meshgrid(x, theta)
# f is a decreasing function of theta
f = 0.5 * np.pi * np.exp(-theta / 50)
r = x * np.sin(f)
h = x * np.cos(f)
# 極坐標轉笛卡爾坐標
X = r * np.cos(theta)
Y = r * np.sin(theta)
ax = ax.plot_surface(X, Y, h,
rstride=1, cstride=1, cmap=plt.cm.cool)
# plt.savefig('img/polar5.png')
plt.show()

??笛卡爾坐標系
(Cartesian coordinate system),即直角坐標系,
??然而,上述的表達仍然沒有得到花瓣的細節,因此我們需要在此基礎之上進行處理,以得到花瓣形狀,因此設計了一個花瓣函式:
f
(
θ
)
=
1
?
1
?
∣
s
i
n
(
θ
2
)
∣
2
f(\theta) = 1 - \frac {1 - |sin(\frac {\theta} {2})|} {2}
f(θ)=1?21?∣sin(2θ?)∣???其是一個以
2
π
2\pi
2π 為周期的周期函式,其值域為
[
0.5
,
1.0
]
[0.5, 1.0]
[0.5,1.0],影像如下圖所示:

??再次繪制:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
if __name__ == '__main__':
fig = plt.figure()
ax = Axes3D(fig)
# plt.axis('off')
x = np.linspace(0, 1, num=30)
theta = np.linspace(0, 2 * np.pi, num=1200)
theta = 30 * theta
x, theta = np.meshgrid(x, theta)
# f is a decreasing function of theta
f = 0.5 * np.pi * np.exp(-theta / 50)
# 通過改變函式周期來改變花瓣的形狀
# 改變值域也可以改變花瓣形狀
# u is a periodic function
u = 1 - (1 - np.absolute(np.sin(3.3 * theta / 2))) / 2
r = x * u * np.sin(f)
h = x * u * np.cos(f)
# 極坐標轉笛卡爾坐標
X = r * np.cos(theta)
Y = r * np.sin(theta)
ax = ax.plot_surface(X, Y, h,
rstride=1, cstride=1, cmap=plt.cm.RdPu_r)
# plt.savefig('img/polar6.png')
plt.show()


4. 花瓣微調
??為了使花瓣更加真實,使花瓣的形態向下凹,因此需要對花瓣的形狀進行微調,這里添加一個修正項和一個噪聲擾動,修正函式影像為:

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
if __name__ == '__main__':
fig = plt.figure()
ax = Axes3D(fig)
# plt.axis('off')
x = np.linspace(0, 1, num=30)
theta = np.linspace(0, 2 * np.pi, num=1200)
theta = 30 * theta
x, theta = np.meshgrid(x, theta)
# f is a decreasing function of theta
f = 0.5 * np.pi * np.exp(-theta / 50)
noise = np.sin(theta) / 30
# u is a periodic function
u = 1 - (1 - np.absolute(np.sin(3.3 * theta / 2))) / 2 + noise
# y is a correction function
y = 2 * (x ** 2 - x) ** 2 * np.sin(f)
r = u * (x * np.sin(f) + y * np.cos(f))
h = u * (x * np.cos(f) - y * np.sin(f))
X = r * np.cos(theta)
Y = r * np.sin(theta)
ax = ax.plot_surface(X, Y, h,
rstride=1, cstride=1, cmap=plt.cm.RdPu_r)
# plt.savefig('img/polar7.png')
plt.show()

??修正前后影像區別對比如下:

5. 結束語
??3D花的繪制主要原理是極坐標,通過正弦/余弦函式進行旋轉變形構造,引數略微變化就會出現不同的花朵,有趣!

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/423951.html
標籤:AI
上一篇:DNS的各種記錄型別的應用決議
