在 Scipy 的模組中,我個人最有興趣的,應該是 spatial
模組了吧!特別是其中的 Delaunay 三角分割,以及建立 Voronoi 圖的部份,畢竟我用 OpenSCAD 創作了許多 3D 模型,而其中有不少就是基於 Delaunay 或 Voronoi。
如果你想知道怎麼實作出 Delaunay 或 Voronoi,可以參考〈玩轉 p5.js〉中相關的文件,而在先前的〈圖片三角分割〉中,也曾透過 Matplotlib 的 mtri.Triangulation
來建立 Delaunay 三角分割。
Scipy 的 spatial
模組中,也有個 Delaunay
類別,來看看如何建立三角分割:
import numpy as np
from scipy import spatial
import matplotlib.pyplot as plt
n = 20
points = np.random.rand(n, 2)
xs = points[:,0]
ys = points[:,1]
tri = spatial.Delaunay(points)
# 換為 spatial.delaunay_plot_2d(tri) 也可以
plt.triplot(xs, ys, tri.simplices, marker = 'o')
plt.show()
simplices
是每個三角形,每個三角形的元素是最初指定點的索引,若只是要畫出三角分割,spatial
提供了 delaunay_plot_2d
函式可以直接使用,其底層基於 Matplotlib,來看看執行結果:
如果你看過〈玩轉 p5.js〉中 Delaunay 與 Voronoi 的文件,就會知道 Delaunay 與 Voronoi 是可以互轉的,如果你要建立 Voronoi,在 spatial
模組中有個 Voronoi
類別:
import numpy as np
from scipy import spatial
import matplotlib.pyplot as plt
n = 20
points = np.random.rand(n, 2)
vor = spatial.Voronoi(points)
spatial.voronoi_plot_2d(vor)
plt.show()
同樣地,spatial
提供了 voronoi_plot_2d
函式可以直接畫 Voronoi 圖,來看看畫出來的結果:
將兩個圖合在一起:
import numpy as np
from scipy import spatial
import matplotlib.pyplot as plt
n = 20
points = np.random.rand(n, 2)
vor = spatial.Voronoi(points)
spatial.voronoi_plot_2d(vor, show_vertices = False)
tri = spatial.Delaunay(points)
xs = points[:,0]
ys = points[:,1]
plt.triplot(xs, ys, tri.simplices, marker = 'o')
plt.show()
在執行結果中,Voronoi 圖就像是細胞,綠點是細胞核:
spatial
模組還有計算各種距離、凸包等的函式,有興趣可以看看〈Spatial data structures and algorithms〉,如果對空間計算方面有興趣,透過 spatial
模組可以省不少的功夫,例如在〈建立 Convex hull〉中,就有基於 ConvexHull
建立凸包模型的範例,另外,在〈Voronoi 2D/3D〉中,有建立 3D 版本的 Voronoi 範例,可以參考一下。