本文適用於剛學習voronoi小白,並對上面鏈接中解釋不詳細的地方進行一定的解釋

上源碼,可直接使用Python編譯器編譯:(如果編譯不了,顯示numpy等用不了請百度自行解決)

from scipy.spatial import *
import numpy as np
import random
import matplotlib.pyplot as plt

points = np.array([[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2],
                   [2, 0], [2, 1], [2, 2]])
vor = Voronoi(points)

vor.vertices
vor.regions
vor.ridge_vertices 
vor.ridge_points

print(vor.vertices,vor.regions,vor.ridge_vertices,vor.ridge_points)

plt.plot(points[:, 0], points[:, 1], 'o')
plt.plot(vor.vertices[:, 0], vor.vertices[:, 1], '*')
plt.xlim(-1, 3); plt.ylim(-1, 3)
# plt.show()

for simplex in vor.ridge_vertices:
    simplex = np.asarray(simplex)
    if np.all(simplex >= 0):
        plt.plot(vor.vertices[simplex, 0], vor.vertices[simplex, 1], 'k-')
# plt.show()  #畫出四個質心點的框

center = points.mean(axis=0)
for pointidx, simplex in zip(vor.ridge_points, vor.ridge_vertices):
    simplex = np.asarray(simplex)
    if np.any(simplex < 0):
                i = simplex[simplex >= 0][0]  # finite end Voronoi vertex
                t = points[pointidx[1]] - points[pointidx[0]]  # tangent
                t = t / np.linalg.norm(t)
                n = np.array([-t[1], t[0]])  # normal
                midpoint = points[pointidx].mean(axis=0)
                far_point = vor.vertices[i] + np.sign(np.dot(midpoint - center, n)) * n * 100
                plt.plot([vor.vertices[i, 0], far_point[0]],
                         [vor.vertices[i, 1], far_point[1]], 'k--')
plt.show()

可得到結果:

ovito操作轉python_ovito操作轉python

為了便於理解,將上述結果圖做一定的標記,如下:


ovito操作轉python_#幾何學_02

 圖1 

points = np.array([[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2],[2, 0], [2, 1], [2, 2]])

 points對應圖1中的point0,point1,……,point8

>>vor.vertices
#輸出結果為:
[[0.5 0.5]
 [0.5 1.5]
 [1.5 0.5]
 [1.5 1.5]]

vor.vertices對應的是圖橙色的四個點,即voronoi的四個頂點vertice0,vertice1,vertice2,vertice3,這四個頂點的順序以及數值很重要,後面要考。

>>vor.regions
[[], [-1, 0], [-1, 1], [1, -1, 0], [3, -1, 2], [-1, 3], [-1, 2], [0, 1, 3, 2], [2, -1, 0], [3, -1, 1]]

vor.regions裏面存儲的索引要結合上面vor.vertices的值來看(注意:-1表示voronoi 的頂點在無窮遠處)。結合圖1,vor.regions [-1, 0] 表示該區域中一個voronoi的頂點是vertice 0,另一個頂點在無窮遠處,由此可以確定voronoi region1(對應圖1中藍色字體)。

再看,vor.regions [1, -1, 0],表示該區域的兩個voronoi的頂點是 vertice 0和vertice 1,還有一個頂點在無窮遠處,由此課確定voronoi region3(對應圖1中藍色的字體)。

再看一個比較特殊的,vor.regions [0, 1, 3, 2],表示該區的四個頂點是分別vertice 0, vertice 1, vertice 3, vertice2.由此可確定voronoi region7(對應圖1中藍色的字體)

由上可以推出其他的voronoi region區域

注意vor.regions裏面存儲的索引[-1, 0], [-1. 1], [1, -1, 0]……[3, -1,1 ]分別對應voronoi region1, voronoi region2, voronoi region3, …… , voronoi region9, 是有順序的

>>vor.ridge_vertices 
[[-1, 0], [-1, 0], [-1, 1], [-1, 1], [0, 1], [-1, 3], [-1, 2], [2, 3], [-1, 3], [-1, 2], [1, 3], [0, 2]]

vor.ridege_vertices裏面存儲的索引對應圖1中的ridge line0, ridege line1, …… ,ridge line 11, 同上文-1表示頂點在無窮遠處

vor.ridege_vertices表示構成每個 Voronoi 脊線(ridge line)的 Voronoi 頂點(vertices)索引,要結合vertice頂點來區分,[-1, 0]表示脊線的一個頂點在vertice0,另一個在無窮遠處,[-1, 3]表示其中一個頂點在vertice3另一個在無窮遠處,由此規律可以找出ridge line0, ridege line1, …… ,ridge line 11所在的位置。

>>vor.ridge_points
[[0 3]
 [0 1]
 [2 5]
 [2 1]
 [1 4]
 [7 8]
 [7 6]
 [7 4]
 [8 5]
 [6 3]
 [4 5]
 [4 3]]

vor.ridge_points表示每條 Voronoi 脊線(ridge line)附近的點(points)的索引,即每條脊線的控制點。

結合圖1,可以看到ridge line1的控制點為point0,point3,即對應輸出結果的[0, 3],ridege line2對應的控制點為point0和point1,即對應輸出結果的[0, 1]

注意:vor.ridge_points裏面存儲的索引也存在一一對應的關係

for simplex in vor.ridge_vertices:
    simplex = np.asarray(simplex)
    if np.all(simplex >= 0):
        plt.plot(vor.vertices[simplex, 0], vor.vertices[simplex, 1], 'k-')

經過上面對每個參數的詳細解釋,此段代碼使用了for循環連接圖1中4個Vertices0,1,2,3頂點。ridge_vertices裏面存儲的索引是4個頂點之間的連接線,且只有大於0的時候才説明這條連接線是4個頂點之間的連接線。

center = points.mean(axis=0)
for pointidx, simplex in zip(vor.ridge_points, vor.ridge_vertices):
    simplex = np.asarray(simplex)
    if np.any(simplex < 0):
                i = simplex[simplex >= 0][0]  # finite end Voronoi vertex
                t = points[pointidx[1]] - points[pointidx[0]]  # tangent
                t = t / np.linalg.norm(t)
                n = np.array([-t[1], t[0]])  # normal
                midpoint = points[pointidx].mean(axis=0)
                far_point = vor.vertices[i] + np.sign(np.dot(midpoint - center, n)) * n * 100
                plt.plot([vor.vertices[i, 0], far_point[0]],
                         [vor.vertices[i, 1], far_point[1]], 'k--')
plt.show()

此段代碼為畫出圖1中的虛線,不做詳解。

此文主要為了解釋vor.vertices,vor.regions,vor.ridge_vertices,vor.ridge_points四個參數裏面存儲的是什麼索引,當弄清楚這4個參數的存儲值,即可明白後面兩個循環的意義。