我开发了一些自动生成等边n维多边形的代码:
# Create equilateral n-dimensional polygon
def polygon(side, radius=1, rotation=0, translation=None):
import math
vertex = 2 * math.pi / side
points = [
(math.sin(vertex * i + rotation) * radius,
math.cos(vertex * i + rotation) * radius)
for i in range(side)]
if translation:
points = [[sum(pair) for pair in zip(point, translation)]
for point in points]
return np.array(points)
现在,我想将标签整齐地放在这个n维多边形的外部角落。在下面的例子中,我创建了一个半径为10的六边形,以(3,3)为中心。
import matplotlib.pyplot as plt
pol = polygon(7, 10, 0, [3,3])
hull = ConvexHull(pol)
labels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', "L", 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
fig = plt.figure(figsize=(4, 4), dpi=100)
for simplex in hull.simplices:
plt.plot(pol[simplex,0], pol[simplex,1], 'k-')
plt.plot(pol[:,0], pol[:,1], 'gs', ms=10)
if labels is not None:
for i, label in enumerate(labels):
if i <= len(pol)-1:
plt.annotate(label, xy=(pol[:,0][i],pol[:,1][i]), xytext=(0, 8),
textcoords='offset points', ha="center", va="bottom")
plt.axis('off')
plt.show()
不幸的是,如图所示,只有A,B和F点整齐地位于六边形之外。是否有一种系统的方法来标注多边形的外角(在这种情况下是六边形),无论尺寸 n ?提前谢谢!
答案 0 :(得分:0)
首先,让我们看一下n维正多边形的特殊情况。
为此,您可以将注释放在稍大的多边形的顶点上(我使用原始半径的1.2倍)。
以下是完整的代码和结果。
import matplotlib.pyplot as plt
from scipy.spatial import ConvexHull
r = 10 # radius
center = [3, 3]
pol = polygon(7, r, 0, center)
pol2 = polygon(7, 1.2*r, 0, center) # for annotations
hull = ConvexHull(pol)
labels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', "L", 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
fig = plt.figure(figsize=(4, 4), dpi=100)
for simplex in hull.simplices:
plt.plot(pol[simplex,0], pol[simplex,1], 'k-')
plt.plot(pol[:,0], pol[:,1], 'gs', ms=10)
if labels is not None:
for i, label in enumerate(labels):
if i <= len(pol)-1:
plt.annotate(label, xy=(pol2[i,0], pol2[i,1]), xytext=(0, 0),
textcoords='offset points', ha="center", va="center")
plt.xlim(center[0] - 1.5*r, center[0] + 1.5*r)
plt.ylim(center[1] - 1.5*r, center[1] + 1.5*r)
plt.axis('off')
plt.show()
现在,让我们看看一般的凸壳。一个简单的解决方案如下:
对于每个单纯形S,计算其相邻的两个单纯形的中点M(称为N_1和N_2)。我们知道这个中点必须位于凸壳的内部。
(N_1, N_2) = hull.neighbors(S)
M = (pol[N_1] + pol[N_2]) / 2
绘制从M到S的线,并取出线上的新点M_ext,使S与M和M_ext等距,但M_ext在另一侧。在这种情况下,我们知道M_ext肯定是。
M_ext = pol[S] + (pol[S] - M)
您可以对其进行标准化,以便注释与单纯形的距离相同(例如,使用numpy.linalg.norm)。在我的代码中,我还乘以常数因子,以便文本不与顶点重叠。
M_ext = pol[S] + (pol[S] - M) / np.linalg.norm(pol[S]-M)
再次完整代码&amp;结果如下:
import matplotlib.pyplot as plt
import numpy as np
from scipy.spatial import ConvexHull
r = 10 # radius
center = [3, 3]
pol = polygon(7, r, 0, center)
pol2 = polygon(7, 1.2*r, 0, center) # for annotations
hull = ConvexHull(pol)
labels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', "L", 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
fig = plt.figure(figsize=(4, 4), dpi=100)
for simplex in hull.simplices:
plt.plot(pol[simplex,0], pol[simplex,1], 'k-')
plt.plot(pol[:,0], pol[:,1], 'gs', ms=10)
if labels is not None:
for i, label in enumerate(labels):
if i <= len(pol)-1:
S = i
(N_1, N_2) = hull.neighbors[S]
M = (pol[N_1] + pol[N_2]) / 2
M_ext = pol[S] + (pol[S] - M) / np.linalg.norm(pol[S] - M) * 0.2*r
plt.annotate(label, xy=M_ext, xytext=(0, 0),
textcoords='offset points', ha="center", va="center")
plt.xlim(center[0] - 1.5*r, center[0] + 1.5*r)
plt.ylim(center[1] - 1.5*r, center[1] + 1.5*r)
plt.axis('off')
plt.show()