数学生成球形六边形网格 [英] Mathematically producing sphere-shaped hexagonal grid

查看:30
本文介绍了数学生成球形六边形网格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个与此类似的形状,带有 12 个五边形的六边形,任意大小.

(

  • 计算

    这是生成二十面体的角(坐标)和三角形(点索引)的 Python 代码:

    从数学导入 sin,cos,acos,sqrt,pis,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 + bottomPointsicoTriangs = [(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)]

    这是使用双 slerp 将固定三角形(点)映射到球面三角形的 Python 代码:

    # 三角形的重心坐标 (-0.5,0),(0.5,0),(0,sqrt(3)/2)def 重心坐标(p):x,y = p# l3*sqrt(3)/2 = yl3 = y*2./sqrt(3.)# l1 + l2 + l3 = 1# 0.5*(l2 - l1) = xl2 = x + 0.5*(1 - l3)l1 = 1 - l2 - l3返回 l1,l2,l3从数学导入 atan2def scalProd(p1,p2):return sum([p1[i]*p2[i] for i in range(len(p1))])# 由 p0, p1 定义的圆弧的均匀插值(围绕原点)# t=0 ->p0, t=1 ->p1def slerp(p0,p1,t):断言 abs(scalProd(p0,p0) - scalProd(p1,p1)) <1e-7ang0Cos = 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))])# 将 2D 点 p 映射到球面三角形 s1,s2,s3(等长的 3D 向量)def mapGridpoint2Sphere(p,s1,s2,s3):l1,l2,l3 = 重心坐标(p)如果 abs(l3-1) <1e-10:返回 s3l2s = l2/(l1+l2)p12 = slerp(s1,s2,l2s)返回 slerp(p12,s3,l3)

    I am trying to create a shape similar to this, hexagons with 12 pentagons, at an arbitrary size.

    (Image Source)

    The only thing is, I have absolutely no idea what kind of code would be needed to generate it!

    The goal is to be able to take a point in 3D space and convert it to a position coordinate on the grid, or vice versa and take a grid position and get the relevant vertices for drawing the mesh.

    I don't even know how one would store the grid positions for this. Does each "triagle section" between 3 pentagons get their own set of 2D coordinates?

    I will most likely be using C# for this, but I am more interested in which algorithms to use for this and an explanation of how they would work, rather than someone just giving me a piece of code.

    解决方案

    First some analysis of the image in the question: the spherical triangle spanned by neighbouring pentagon centers seems to be equilateral. When five equilateral triangles meet in one corner and cover the whole sphere, this can only be the configuration induced by a icosahedron. So there are 12 pentagons and 20 patches of a triangular cutout of a hexongal mesh mapped to the sphere.

    So this is a way to construct such a hexagonal grid on the sphere:

    1. Create triangular cutout of hexagonal grid: a fixed triangle (I chose (-0.5,0),(0.5,0),(0,sqrt(3)/2) ) gets superimposed a hexagonal grid with desired resolution n s.t. the triangle corners coincide with hexagon centers, see the examples for n = 0,1,2,20:

    2. Compute corners of icosahedron and define the 20 triangular faces of it (see code below). The corners of the icosahedron define the centers of the pentagons, the faces of the icosahedron define the patches of the mapped hexagonal grids. (The icosahedron gives the finest regular division of the sphere surface into triangles, i.e. a division into congruent equilateral triangles. Other such divisions can be derived from a tetrahedron or an octahedron; then at the corners of the triangles one will have triangles or squares, resp. Furthermore the fewer and bigger triangles would make the inevitable distortion in any mapping of a planar mesh onto a curved surface more visible. So choosing the icosahedron as a basis for the triangular patches helps minimizing the distortion of the hexagons.)

    3. Map triangular cutout of hexagonal grid to spherical triangles corresponding to icosaeder faces: a double-slerp based on barycentric coordinates does the trick. Below is an illustration of the mapping of a triangular cutout of a hexagonal grid with resolution n = 10 onto one spherical triangle (defined by one face of an icosaeder), and an illustration of mapping the grid onto all these spherical triangles covering the whole sphere (different colors for different mappings):

    Here is Python code to generate the corners (coordinates) and triangles (point indices) of an icosahedron:

    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)]
    

    And here is the Python code to map (points of) the fixed triangle to a spherical triangle using a double 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)
    

    这篇关于数学生成球形六边形网格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆