本文適用於剛學習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()
可得到結果:
為了便於理解,將上述結果圖做一定的標記,如下:
圖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個參數的存儲值,即可明白後面兩個循環的意義。