我正在尝试创建一个类似于此形状的,具有12个五边形的六边形,并具有任意大小。
(Image Source)
唯一的是,我完全不知道需要哪种代码来生成它!
目的是能够在3D空间中获取一个点并将其转换为网格上的位置坐标,反之亦然,并获取网格位置并获得用于绘制网格的相关顶点。
我什至不知道该如何存储网格位置。 3个五边形之间的每个“三角形部分”是否都有自己的2D坐标集?
我很可能会为此使用C#,但是我对使用哪种算法以及如何工作的解释更感兴趣,而不是有人给我一段代码。
最佳答案
首先对问题中的图像进行一些分析:由相邻五边形中心跨越的球形三角形似乎是等边的。当五个等边三角形在一个角处相交并覆盖整个球体时,这只能是icosahedron引起的构型。因此,有12个五边形和映射到球体的六边形网格的三角形切口的20个补丁。
因此,这是在球体上构造这种六边形网格的方法:
n
s.t的六边形网格上。三角形的角与六角形的中心重合,请参见n = 0,1,2,20
的示例:n = 10
的六边形网格的三角形切口映射到一个球形三角形(由二十面体的一个面定义)的图示,以及将网格映射到覆盖整个球体的所有这些球形三角形的图示(不同不同映射的颜色):这是Python代码,用于生成二十面体的角(坐标)和三角形(点索引):
from math import sin,cos,acos,sqrt,pi
s,c = 2/sqrt(5),1/sqrt(5)
topPoints = [(0,0,1)] + [(s*cos(i*2*pi/5.), s*sin(i*2*pi/5.), c) for i in range(5)]
bottomPoints = [(-x,y,-z) for (x,y,z) in topPoints]
icoPoints = topPoints + bottomPoints
icoTriangs = [(0,i+1,(i+1)%5+1) for i in range(5)] +\
[(6,i+7,(i+1)%5+7) for i in range(5)] +\
[(i+1,(i+1)%5+1,(7-i)%5+7) for i in range(5)] +\
[(i+1,(7-i)%5+7,(8-i)%5+7) for i in range(5)]
这是Python代码,使用双slerp将固定三角形映射(的点)到球形三角形:
# barycentric coords for triangle (-0.5,0),(0.5,0),(0,sqrt(3)/2)
def barycentricCoords(p):
x,y = p
# l3*sqrt(3)/2 = y
l3 = y*2./sqrt(3.)
# l1 + l2 + l3 = 1
# 0.5*(l2 - l1) = x
l2 = x + 0.5*(1 - l3)
l1 = 1 - l2 - l3
return l1,l2,l3
from math import atan2
def scalProd(p1,p2):
return sum([p1[i]*p2[i] for i in range(len(p1))])
# uniform interpolation of arc defined by p0, p1 (around origin)
# t=0 -> p0, t=1 -> p1
def slerp(p0,p1,t):
assert abs(scalProd(p0,p0) - scalProd(p1,p1)) < 1e-7
ang0Cos = scalProd(p0,p1)/scalProd(p0,p0)
ang0Sin = sqrt(1 - ang0Cos*ang0Cos)
ang0 = atan2(ang0Sin,ang0Cos)
l0 = sin((1-t)*ang0)
l1 = sin(t *ang0)
return tuple([(l0*p0[i] + l1*p1[i])/ang0Sin for i in range(len(p0))])
# map 2D point p to spherical triangle s1,s2,s3 (3D vectors of equal length)
def mapGridpoint2Sphere(p,s1,s2,s3):
l1,l2,l3 = barycentricCoords(p)
if abs(l3-1) < 1e-10: return s3
l2s = l2/(l1+l2)
p12 = slerp(s1,s2,l2s)
return slerp(p12,s3,l3)