[PYTHON] Create regular polyhedron data

I want data on regular polyhedra. It seems easy to make, but considering how to make it, it doesn't seem to be easy. I tried to make a program, but it feels like a muddy rope.

Generation method

Create data for a regular polyhedron whose vertices are on a sphere with a radius of 1.

The only tables for regular polyhedrons ($ M ) are "the number of angles of one face ( N )" and "the number of faces tangent to vertices ( F $)".

Find the normal of the surface

Let the first vertex be $ \ left (0,0,1 \ right) $ and aim to generate the edges of the tangent faces.

Find the next vertex $ \ left (sin \ \ theta, \ theta, cos \ \ theta \ right) $ and rotate the x-y plane to divide it into "the number of tangent faces".

Then, the third is $ \ left (sin \ \ theta \ cos \ \ phi, \ sin \ \ theta \ cos \ \ phi, \ cos \ \ theta \ right) $.

$ \ phi $ can be obtained from "the number of tangent faces ($ F $)".

$ \ Theta $ can be calculated from three vertices, but it must be calculated before creating the vertices.


\begin{eqnarray}
\phi & = & \frac{2\pi}{F} \\
P_1 & = & (0, 0, 1) \\
P_2 & = & (sin \theta, 0, cos \theta) \\
P_3 & = & (sin \theta\ cos \phi, sin \theta\ sin \phi, cos \theta) \\
L_1 & = & P_2 - P_1 \\
L_2 & = & P_3 - P_1 \\
\frac{L_1 \cdot L_2}{|L_1||L_2|} & = & cos \frac{ \pi \left( N-2 \right) }{N} \\
cos \theta & = & \left( cos^2 \frac{\pi}{F} - cos \frac{ \pi \left( N-2 \right) }{N} \right)\ csc^2 \frac{\pi}{F} \\
\end{eqnarray}

Find $ cos \ \ theta $ from $ N, F $. If you find the three vertices, the first "face normal" is the cross product.


N_1 = \frac{L_1 \times L_2}{ \left| L_1 \times L_2 \right|}

Therefore, if you rotate this normal in the x-y plane by an angle of $ \ phi $, you can find $ F $ of "face normals".

Since the distance from the center of the regular polyhedron to the face is the inner product of the first vertex $ P_1 $ and the normal $ N_1 $ of the first face.


\begin{eqnarray}
P_1 & = & \left( 0, 0, 1 \right) \\
N_1 & = & \left( n_x\ , n_y\ , n_z \right) \\
n_z & = & P_1 \cdot N_1 = D \\
\end{eqnarray}

Ask as. You can use the value of $ \ left (n_z = D \ right) $ for the normal to make a face expression.

Find the normals of all faces

Since three or more normals are found, the relationship between two adjacent normals $ N_1, N_2 $ and the adjacent normal $ N_3 $ is


\begin{eqnarray}
n_x & = & N_1 \\
n_y & = & \frac{ n_x \times N_2 }{ \left| n_x \times N_2 \right| } \\
n_z & = & \frac{ n_x \times n_y }{ \left| n_x \times n_y \right| } \\
X_{cos} & = & n_x \cdot N_3 \\
Y_{cos} & = & n_y \cdot N_3 \\
Z_{cos} & = & n_z \cdot N_3 \\
\end{eqnarray}

Can be. Now, from the two adjacent normals $ N_1, N_2 $, a new normal $ N_3 $ is created.


\begin{eqnarray}
n_x & = & N_1 \\
n_y & = & \frac{ n_x \times N_2 }{ \left| n_x \times N_2 \right| } \\
n_z & = & \frac{ n_y \times n_y }{ \left| n_x \times n_y \right| } \\
N_3 & = & X_{cos}\ n_x + Y_{cos}\ n_y + Z_{cos}\ n_z \\
\end{eqnarray}

Is required at.

By brute force the two normals, seek a new normal, eliminate duplication, and achieve the goal when it does not increase.

Find the apex

The line of intersection of two adjacent normals $ N_1, N_2 $ and the plane formed by the distance $ D $ from the center (origin) of the regular polyhedron to the plane passes through the "sides of the regular polyhedron". This is the vertex found at the intersection of this line of intersection and a sphere with a radius of $ 1 $.

The direction of intersection is the cross product of the two normals


L_V = \frac{ N_1 \times N_2 }{ \left| N_1 \times N_2 \right| }

It can be found by. Since we want the base point of the intersection line to be the "center of the side", we will set the straight line $ L_C $ that passes between the two normals and the intersection $ L_P $ of the surface.


\begin{eqnarray}
L_C & = & \frac{ N_1 + N_2 }{ \left| N_1 + N_2 \right| } \\
cos\ \theta_{L} & = & L_C \cdot N_1 = L_C \cdot N_2 \\
L_P & = & \frac{D}{cos\ \theta_{L}} L_C
\end{eqnarray}

I will ask for it.\left| L_P \right|Is the distance from the origin to the apex1Against


cos\ \theta_P = \left| L_P \right|

The distance from $ L_P $ to the apex is


L_D = sin\ \theta_P = \sqrt{1 - cos^2\theta_P} = \sqrt{1 - \left( L_P \cdot L_P \right) }

It will be. This is in "finding the normal of the surface"\left| L_1 \right|Because it's half of


L_D = \frac{ \left| L_1 \right| }{2}

You can also. (The program remains the former)

Since the vertices to be obtained are evenly spaced from the center of the side


V = L_P \pm L_D L_V

Will be.

As with "all normals", find the edges and vertices by brute force the two normals.

After that, the data is prepared and it is completed.

Program and output result

Regular polyhedron data generation Python program

import math

flag_debug = False
flag_verbose = False
flag_rotate = False

paren_c = ('{', '}')
paren_vec = ('(', ')')
paren_out = ('(', ')')
paren_list = ('(', ')')

#Regular polyhedron data
#Number of faces: (Number of face angles,Number of vertices contacted)
RP_TAB = {
    +4: (3, 3),
    +6: (4, 3),
    +8: (3, 4),
    12: (5, 3),
    20: (3, 5),
}

FP_THR = 1.0 / 1024  #Allowable range of calculation error at the time of judgment

def cos_sin(r): return (math.cos(r), math.sin(r))

def vec_dump(v): return (paren_vec[0] + (' %+8.6f, %+8.6f, %+8.6f ' % tuple(v)) + paren_vec[1])
def vec_add(a, b): return (a[0] + b[0], a[1] + b[1], a[2] + b[2])
def vec_sub(a, b): return (a[0] - b[0], a[1] - b[1], a[2] - b[2])
def vec_mul(a, b): return (a[0] * b,    a[1] * b,    a[2] * b)

def vec_inner(a, b): #inner product
    return (a[0] * b[0] + a[1] * b[1] + a[2] * b[2])

def vec_cross(a, b): #Cross product
    c1 = a[1] * b[2] - a[2] * b[1]
    c2 = a[2] * b[0] - a[0] * b[2]
    c3 = a[0] * b[1] - a[1] * b[0]
    return (c1, c2, c3)

def vec_cross_normalize(a, b): #Cross product and normalization
    return vec_normalize(vec_cross(a, b))

def vec_normalize(a): #Normalization
    return vec_mul(a, 1.0 / math.sqrt(vec_inner(a, a)))

# X-Rotate in Y plane
def vec_rot_xy(v, r):
    c, s = cos_sin(r)
    x = v[0] * c - v[1] * s
    y = v[0] * s + v[1] * c
    return (x, y, v[2])

#Add vector data(Eliminate duplication)
def vec_append(l, v):
    r = len(l)
    for n in range(r):
        c = vec_inner(v, l[n])
        if c >= (1.0 - FP_THR):
            return n
        continue
    l.append(v)
    return r

#Creation of regular polyhedron data
def make(F):          # F =Number of faces
    P = RP_TAB[F][0]  # P =Number of face angles
    K = RP_TAB[F][1]  # K =Number of vertices contacted
    E = F * P / 2     # E =Number of sides
    V = E - F + 2     # V =Number of vertices

    if flag_verbose:
        print('Number of faces: %d' % F)
        print('Number of sides: %d' % E)
        print('Number of vertices: %d' % V)
        pass

    #One round with the number of contact surfaces of vertices
    rK1 = math.pi     / K   # rK1 =  π / K
    rK2 = math.pi * 2 / K   # rK2 = 2π / K
    cK1, sK1 = cos_sin(rK1)
    cK2, sK2 = cos_sin(rK2)

    #Elements related to polygons
    rP = math.pi * (P - 2) / P  # rP = π(P-2) / P
    cP, sP = cos_sin(rP)

    #Elements related to sides and central angles
    cR = (cK1 * cK1 - cP) / (sK1 * sK1)
    sR = math.sqrt(1 - cR * cR)

    #Find the normals of the three faces
    p1 = (0, 0, 1)
    p2 = (sR, 0, cR)
    p3 = (sR * cK2, sR * sK2, cR)
    l1 = vec_sub(p2, p1)
    l2 = vec_sub(p3, p1)
    n0 = vec_cross_normalize(l1, l2)
    n1 = vec_rot_xy(n0, rK2 * 1)
    n2 = vec_rot_xy(n0, rK2 * 2)

    cD = n0[2]  # cD =Distance from center to plane
    sD = math.sqrt(1 - cD * cD)

    #Find the angular elements of adjacent faces
    ny = vec_cross_normalize(n0, n1)
    nz = vec_cross_normalize(n0, ny)
    N_cos = vec_inner(n0, n1)
    X_cos = vec_inner(n0, n2)
    Y_cos = vec_inner(ny, n2)
    Z_cos = vec_inner(nz, n2)

    #Correct the orientation of the regular polyhedron
    if P != 3 and flag_rotate:
        n0 = (0, 0, 1)
        ny = (cP, -sP, 0)
        nz = (sP,  cP, 0)
        ax = vec_mul(n0, X_cos)
        ay = vec_mul(ny, Y_cos)
        az = vec_mul(nz, Z_cos)
        n1 = vec_add(vec_add(ax, ay), az)
        pass

    #Find the normals of all faces
    nl = [n0, n1]
    loop = True
    while loop:
        CF = len(nl)
        for s in range(CF-1):
            for e in range(s+1,CF):
                n0 = nl[s]
                n1 = nl[e]

                #Is n0 and n1 adjacent faces??
                nc = vec_inner(n0, n1)
                if abs(N_cos - nc) >= FP_THR:
                    continue

                #Added adjacent faces from n0 to n1
                ny = vec_cross_normalize(n0, n1)
                nz = vec_cross_normalize(n0, ny)
                ax = vec_mul(n0, X_cos)
                ay = vec_mul(ny, Y_cos)
                az = vec_mul(nz, Z_cos)
                na = vec_add(vec_add(ax, ay), az)
                vec_append(nl, na)
                continue
            continue
        loop = (CF != len(nl)) #It's over when it doesn't increase
        continue

    #Find all edges and vertices
    CF = len(nl)
    vl = []
    fl = {}
    for n in range(CF): fl[n] = []
    for s in range(CF):
        for e in range(s+1, CF):
            n0 = nl[s]
            n1 = nl[e]

            #Is n0 and n1 adjacent faces??
            nc = vec_inner(n0, n1)
            if abs(N_cos - nc) >= FP_THR: continue

            #Find the line of intersection of n0 and n1(Pass through the center of the side)
            lc = vec_normalize(vec_add(n0, n1))
            lv = vec_cross_normalize(n0, n1)
            lp = vec_mul(lc, cD / vec_inner(n0, lc))

            #Find the intersection of the line of intersection and a sphere with a radius of 1
            t0 = math.sqrt(1 - vec_inner(lp, lp))
            q1 = vec_add(vec_mul(lv, -t0), lp)
            q2 = vec_add(vec_mul(lv, +t0), lp)

            #Add vertex and edge data
            i1 = vec_append(vl, q1)
            i2 = vec_append(vl, q2)
            fl[s].append((i1, i2))
            fl[e].append((i1, i2))
            continue
        continue

    #Data organization
    rl = []
    el = {}
    for f in range(len(fl)):
        vd = fl[f]

        #Edge data for wireframes
        for e in vd: el[e] = None

        #Make disjointed edge data continuous(Polygonization)
        vm = {}
        s, e = vd[0]
        vm[s] = e
        il = vd[1:]
        while len(il):
            for n in range(len(il)):
                p, q = il[n]
                if e == p:
                    vm[e] = q
                    e = q
                elif e == q:
                    vm[e] = p
                    e = p
                else:
                    continue
                del il[n]
                break
            continue

        s, e = vd[0]
        il = [s]
        while s != e:
            il.append(e)
            e = vm[e]
            continue

        #Fixed polygon normals
        nv = nl[f]
        p0 = vl[il[0]]
        p1 = vl[il[1]]
        p2 = vl[il[2]]
        v1 = vec_sub(p1, p0)
        v2 = vec_sub(p2, p1)
        pn = vec_cross(v1, v2)
        if vec_inner(nv, pn) < 0: il.reverse()

        rl.append((nv, il))
        continue

    return (vl, rl, el.keys())

#Main function
def main(F):
    vl, fl, el = make(F)

    #Output of vertex data
    m = ('VERTEX[%d] = ' % len(vl)) + paren_out[0] + '\n'
    for n in range(len(vl)):
        m = m + ('  %s,' % vec_dump(vl[n]))
        if not args.uncomment: m = m + ('  #%d' % n)
        m = m + '\n'
        continue
    m = m + paren_out[1]
    print(m)

    #Output normal data
    if args.normal:
        m = ('NORMAL[%d] = ' % len(fl)) + paren_out[0] + '\n'
        for n in range(len(fl)):
            m = m + ('  %s,' % vec_dump(fl[n][0]))
            if not args.uncomment: m = m + ('  #%d' % n)
            m = m + '\n'
            continue
        m = m + paren_out[1]
        print(m)
        pass

    #Output of surface data(Normal,Vertex list)
    m = ('FACET[%d] = ' % len(fl)) + paren_out[0] + '\n'
    for n in range(len(fl)):
        if args.normal: m = m + ' '
        else: m = m + '  ' + vec_dump(fl[n][0]) + ','
        m = m + ' ' + paren_list[0]
        s = ''
        for i in fl[n][1]:
            m = m + ('%s %2d' % (s, i))
            s = ','
            continue
        m = m + ' ' + paren_list[1] + ','
        if not args.uncomment: m = m + ('  #%d' % n)
        m = m + '\n'
        continue
    m = m + paren_out[1]
    print(m)

    #Edge data output
    el = sorted(el)
    m = ('EDGE[%d] = ' % len(el)) + paren_out[0]
    for n in range(len(el)):
        if ((n & 3) == 0): m = m + '\n '
        m = m + (' %s %2d, %2d %s,' % (paren_list[0], el[n][0], el[n][1], paren_list[1]))
        continue
    m = m + '\n' + paren_out[1]
    print(m)

    return

if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument('N', nargs='+', type=int, help='Number of faces={4|6|8|12|20}')
    parser.add_argument('-d', '--debug', action='store_true', help='For debugging')
    parser.add_argument('-v', '--verbose', action='store_true', help='Redundant output')
    parser.add_argument('-r', '--rotate', action='store_true', help='6,Corrected dodecahedron orientation')
    parser.add_argument('-c', '--cparen', action='store_true', help='Change the characters in parentheses')
    parser.add_argument('-n', '--normal', action='store_true', help='Separate normal data')
    parser.add_argument('-u', '--uncomment', action='store_true', help='Eliminate index')
    args = parser.parse_args()

    flag_debug = args.debug
    flag_verbose = args.verbose
    flag_rotate = args.rotate

    if args.cparen:
        paren_vec = paren_c
        paren_out = paren_c
        paren_list = paren_c
        pass

    s = '-' * 72
    sep = (len(args.N) > 1)
    for N in args.N:
        if sep: print(s)
        if N in RP_TAB:
            main(N)
        else:
            print('N=%d :Invalid number of pages' % N)
            parser.print_help()
            pass
        continue
    if sep: print(s)
    pass

#Useless pass, continue,return is Emacs indentation protection

Output result: Regular tetrahedron

Number of faces: 4
Number of sides: 6
Number of vertices: 4
VERTEX[4] = (
  ( +0.000000, +0.000000, +1.000000 ),  #0
  ( +0.942809, +0.000000, -0.333333 ),  #1
  ( -0.471405, +0.816497, -0.333333 ),  #2
  ( -0.471405, -0.816497, -0.333333 ),  #3
)
FACET[4] = (
  ( +0.471405, +0.816497, +0.333333 ), (  2,  0,  1 ),  #0
  ( -0.942809, +0.000000, +0.333333 ), (  3,  0,  2 ),  #1
  ( +0.471405, -0.816497, +0.333333 ), (  3,  1,  0 ),  #2
  ( +0.000000, -0.000000, -1.000000 ), (  3,  2,  1 ),  #3
)
EDGE[6] = (
  (  0,  1 ), (  1,  2 ), (  2,  0 ), (  2,  3 ),
  (  3,  0 ), (  3,  1 ),
)

Output: Regular hexahedron

Number of faces: 6
Number of sides: 12
Number of vertices: 8
VERTEX[8] = (
  ( +0.000000, +0.000000, +1.000000 ),  #0
  ( +0.942809, +0.000000, +0.333333 ),  #1
  ( -0.471405, +0.816497, +0.333333 ),  #2
  ( +0.471405, +0.816497, -0.333333 ),  #3
  ( -0.471405, -0.816497, +0.333333 ),  #4
  ( -0.942809, +0.000000, -0.333333 ),  #5
  ( +0.471405, -0.816497, -0.333333 ),  #6
  ( +0.000000, +0.000000, -1.000000 ),  #7
)
FACET[6] = (
  ( +0.408248, +0.707107, +0.577350 ), (  2,  0,  1,  3 ),  #0
  ( -0.816497, +0.000000, +0.577350 ), (  5,  4,  0,  2 ),  #1
  ( +0.408248, -0.707107, +0.577350 ), (  4,  6,  1,  0 ),  #2
  ( +0.816497, -0.000000, -0.577350 ), (  6,  7,  3,  1 ),  #3
  ( -0.408248, +0.707107, -0.577350 ), (  7,  5,  2,  3 ),  #4
  ( -0.408248, -0.707107, -0.577350 ), (  7,  6,  4,  5 ),  #5
)
EDGE[12] = (
  (  0,  1 ), (  1,  3 ), (  2,  0 ), (  2,  5 ),
  (  3,  2 ), (  4,  0 ), (  4,  6 ), (  5,  4 ),
  (  6,  1 ), (  6,  7 ), (  7,  3 ), (  7,  5 ),
)

*********The following has the same spatial axis and surface orientation

Number of faces: 6
Number of sides: 12
Number of vertices: 8
VERTEX[8] = (
  ( -0.577350, -0.577350, +0.577350 ),  #0
  ( +0.577350, -0.577350, +0.577350 ),  #1
  ( +0.577350, +0.577350, +0.577350 ),  #2
  ( -0.577350, +0.577350, +0.577350 ),  #3
  ( +0.577350, -0.577350, -0.577350 ),  #4
  ( -0.577350, -0.577350, -0.577350 ),  #5
  ( +0.577350, +0.577350, -0.577350 ),  #6
  ( -0.577350, +0.577350, -0.577350 ),  #7
)
FACET[6] = (
  ( +0.000000, +0.000000, +1.000000 ), (  0,  1,  2,  3 ),  #0
  ( -0.000000, -1.000000, +0.000000 ), (  5,  4,  1,  0 ),  #1
  ( +1.000000, -0.000000, +0.000000 ), (  4,  6,  2,  1 ),  #2
  ( +0.000000, +1.000000, +0.000000 ), (  6,  7,  3,  2 ),  #3
  ( -1.000000, +0.000000, +0.000000 ), (  7,  5,  0,  3 ),  #4
  ( -0.000000, -0.000000, -1.000000 ), (  7,  6,  4,  5 ),  #5
)
EDGE[12] = (
  (  0,  1 ), (  0,  5 ), (  1,  2 ), (  2,  3 ),
  (  3,  0 ), (  4,  1 ), (  4,  6 ), (  5,  4 ),
  (  6,  2 ), (  6,  7 ), (  7,  3 ), (  7,  5 ),
)

Output result: Octahedron

Number of faces: 8
Number of sides: 12
Number of vertices: 6
VERTEX[6] = (
  ( +0.000000, +0.000000, +1.000000 ),  #0
  ( +1.000000, +0.000000, +0.000000 ),  #1
  ( +0.000000, +1.000000, +0.000000 ),  #2
  ( -1.000000, +0.000000, +0.000000 ),  #3
  ( -0.000000, -1.000000, +0.000000 ),  #4
  ( +0.000000, -0.000000, -1.000000 ),  #5
)
FACET[8] = (
  ( +0.577350, +0.577350, +0.577350 ), (  2,  0,  1 ),  #0
  ( -0.577350, +0.577350, +0.577350 ), (  3,  0,  2 ),  #1
  ( -0.577350, -0.577350, +0.577350 ), (  4,  0,  3 ),  #2
  ( +0.577350, -0.577350, +0.577350 ), (  4,  1,  0 ),  #3
  ( +0.577350, -0.577350, -0.577350 ), (  5,  1,  4 ),  #4
  ( +0.577350, +0.577350, -0.577350 ), (  5,  2,  1 ),  #5
  ( -0.577350, +0.577350, -0.577350 ), (  5,  3,  2 ),  #6
  ( -0.577350, -0.577350, -0.577350 ), (  5,  4,  3 ),  #7
)
EDGE[12] = (
  (  0,  1 ), (  1,  2 ), (  2,  0 ), (  2,  3 ),
  (  3,  0 ), (  3,  4 ), (  4,  0 ), (  4,  1 ),
  (  4,  5 ), (  5,  1 ), (  5,  2 ), (  5,  3 ),
)

Output: Regular dodecahedron

Number of faces: 12
Number of sides: 30
Number of vertices: 20
VERTEX[20] = (
  ( +0.000000, +0.000000, +1.000000 ),  #0
  ( +0.666667, +0.000000, +0.745356 ),  #1
  ( -0.333333, +0.577350, +0.745356 ),  #2
  ( +0.745356, +0.577350, +0.333333 ),  #3
  ( +0.127322, +0.934172, +0.333333 ),  #4
  ( -0.333333, -0.577350, +0.745356 ),  #5
  ( -0.872678, +0.356822, +0.333333 ),  #6
  ( -0.872678, -0.356822, +0.333333 ),  #7
  ( +0.745356, -0.577350, +0.333333 ),  #8
  ( +0.127322, -0.934172, +0.333333 ),  #9
  ( +0.872678, +0.356822, -0.333333 ),  #10
  ( +0.872678, -0.356822, -0.333333 ),  #11
  ( -0.127322, +0.934172, -0.333333 ),  #12
  ( +0.333333, +0.577350, -0.745356 ),  #13
  ( -0.745356, +0.577350, -0.333333 ),  #14
  ( -0.745356, -0.577350, -0.333333 ),  #15
  ( -0.666667, +0.000000, -0.745356 ),  #16
  ( -0.127322, -0.934172, -0.333333 ),  #17
  ( +0.333333, -0.577350, -0.745356 ),  #18
  ( +0.000000, -0.000000, -1.000000 ),  #19
)
FACET[12] = (
  ( +0.303531, +0.525731, +0.794654 ), (  2,  0,  1,  3,  4 ),  #0
  ( -0.607062, +0.000000, +0.794654 ), (  6,  7,  5,  0,  2 ),  #1
  ( +0.303531, -0.525731, +0.794654 ), (  5,  9,  8,  1,  0 ),  #2
  ( +0.982247, -0.000000, +0.187592 ), (  8, 11, 10,  3,  1 ),  #3
  ( +0.491123, +0.850651, -0.187592 ), ( 10, 13, 12,  4,  3 ),  #4
  ( -0.491123, +0.850651, +0.187592 ), ( 12, 14,  6,  2,  4 ),  #5
  ( -0.982247, +0.000000, -0.187592 ), ( 14, 16, 15,  7,  6 ),  #6
  ( -0.491123, -0.850651, +0.187592 ), ( 15, 17,  9,  5,  7 ),  #7
  ( +0.491123, -0.850651, -0.187592 ), ( 17, 18, 11,  8,  9 ),  #8
  ( +0.607062, -0.000000, -0.794654 ), ( 18, 19, 13, 10, 11 ),  #9
  ( -0.303531, +0.525731, -0.794654 ), ( 19, 16, 14, 12, 13 ),  #10
  ( -0.303531, -0.525731, -0.794654 ), ( 19, 18, 17, 15, 16 ),  #11
)
EDGE[30] = (
  (  0,  1 ), (  1,  3 ), (  2,  0 ), (  2,  6 ),
  (  3,  4 ), (  4,  2 ), (  5,  0 ), (  5,  9 ),
  (  6,  7 ), (  7,  5 ), (  8,  1 ), (  8, 11 ),
  (  9,  8 ), ( 10,  3 ), ( 10, 13 ), ( 11, 10 ),
  ( 12,  4 ), ( 12, 14 ), ( 13, 12 ), ( 14,  6 ),
  ( 14, 16 ), ( 15,  7 ), ( 15, 17 ), ( 16, 15 ),
  ( 17,  9 ), ( 17, 18 ), ( 18, 11 ), ( 18, 19 ),
  ( 19, 13 ), ( 19, 16 ),
)

*********The following has the same plane as the Z-axis orientation

Number of faces: 12
Number of sides: 30
Number of vertices: 20
VERTEX[20] = (
  ( -0.577350, -0.187592, +0.794654 ),  #0
  ( -0.000000, -0.607062, +0.794654 ),  #1
  ( +0.577350, -0.187592, +0.794654 ),  #2
  ( +0.356822, +0.491123, +0.794654 ),  #3
  ( -0.356822, +0.491123, +0.794654 ),  #4
  ( -0.000000, -0.982247, +0.187592 ),  #5
  ( -0.934172, -0.303531, +0.187592 ),  #6
  ( -0.577350, -0.794654, -0.187592 ),  #7
  ( +0.934172, -0.303531, +0.187592 ),  #8
  ( +0.577350, -0.794654, -0.187592 ),  #9
  ( +0.577350, +0.794654, +0.187592 ),  #10
  ( +0.934172, +0.303531, -0.187592 ),  #11
  ( -0.577350, +0.794654, +0.187592 ),  #12
  ( +0.000000, +0.982247, -0.187592 ),  #13
  ( -0.934172, +0.303531, -0.187592 ),  #14
  ( -0.356822, -0.491123, -0.794654 ),  #15
  ( -0.577350, +0.187592, -0.794654 ),  #16
  ( +0.356822, -0.491123, -0.794654 ),  #17
  ( +0.577350, +0.187592, -0.794654 ),  #18
  ( +0.000000, +0.607062, -0.794654 ),  #19
)
FACET[12] = (
  ( +0.000000, +0.000000, +1.000000 ), (  0,  1,  2,  3,  4 ),  #0
  ( -0.525731, -0.723607, +0.447214 ), (  6,  7,  5,  1,  0 ),  #1
  ( +0.525731, -0.723607, +0.447214 ), (  5,  9,  8,  2,  1 ),  #2
  ( +0.850651, +0.276393, +0.447214 ), (  8, 11, 10,  3,  2 ),  #3
  ( +0.000000, +0.894427, +0.447214 ), ( 10, 13, 12,  4,  3 ),  #4
  ( -0.850651, +0.276393, +0.447214 ), ( 12, 14,  6,  0,  4 ),  #5
  ( -0.850651, -0.276393, -0.447214 ), ( 14, 16, 15,  7,  6 ),  #6
  ( -0.000000, -0.894427, -0.447214 ), ( 15, 17,  9,  5,  7 ),  #7
  ( +0.850651, -0.276393, -0.447214 ), ( 17, 18, 11,  8,  9 ),  #8
  ( +0.525731, +0.723607, -0.447214 ), ( 18, 19, 13, 10, 11 ),  #9
  ( -0.525731, +0.723607, -0.447214 ), ( 19, 16, 14, 12, 13 ),  #10
  ( -0.000000, -0.000000, -1.000000 ), ( 19, 18, 17, 15, 16 ),  #11
)
EDGE[30] = (
  (  0,  1 ), (  0,  6 ), (  1,  2 ), (  2,  3 ),
  (  3,  4 ), (  4,  0 ), (  5,  1 ), (  5,  9 ),
  (  6,  7 ), (  7,  5 ), (  8,  2 ), (  8, 11 ),
  (  9,  8 ), ( 10,  3 ), ( 10, 13 ), ( 11, 10 ),
  ( 12,  4 ), ( 12, 14 ), ( 13, 12 ), ( 14,  6 ),
  ( 14, 16 ), ( 15,  7 ), ( 15, 17 ), ( 16, 15 ),
  ( 17,  9 ), ( 17, 18 ), ( 18, 11 ), ( 18, 19 ),
  ( 19, 13 ), ( 19, 16 ),
)

Output: Regular icosahedron

Number of faces: 20
Number of sides: 30
Number of vertices: 12
VERTEX[12] = (
  ( +0.000000, +0.000000, +1.000000 ),  #0
  ( +0.894427, +0.000000, +0.447214 ),  #1
  ( +0.276393, +0.850651, +0.447214 ),  #2
  ( -0.723607, +0.525731, +0.447214 ),  #3
  ( -0.723607, -0.525731, +0.447214 ),  #4
  ( +0.276393, -0.850651, +0.447214 ),  #5
  ( +0.723607, -0.525731, -0.447214 ),  #6
  ( +0.723607, +0.525731, -0.447214 ),  #7
  ( -0.276393, +0.850651, -0.447214 ),  #8
  ( -0.894427, -0.000000, -0.447214 ),  #9
  ( -0.276393, -0.850651, -0.447214 ),  #10
  ( -0.000000, +0.000000, -1.000000 ),  #11
)
FACET[20] = (
  ( +0.491123, +0.356822, +0.794654 ), (  2,  0,  1 ),  #0
  ( -0.187592, +0.577350, +0.794654 ), (  3,  0,  2 ),  #1
  ( -0.607062, +0.000000, +0.794654 ), (  4,  0,  3 ),  #2
  ( -0.187592, -0.577350, +0.794654 ), (  5,  0,  4 ),  #3
  ( +0.491123, -0.356822, +0.794654 ), (  5,  1,  0 ),  #4
  ( +0.794654, -0.577350, +0.187592 ), (  6,  1,  5 ),  #5
  ( +0.982247, -0.000000, -0.187592 ), (  7,  1,  6 ),  #6
  ( +0.794654, +0.577350, +0.187592 ), (  7,  2,  1 ),  #7
  ( +0.303531, +0.934172, -0.187592 ), (  8,  2,  7 ),  #8
  ( -0.303531, +0.934172, +0.187592 ), (  8,  3,  2 ),  #9
  ( -0.794654, +0.577350, -0.187592 ), (  9,  3,  8 ),  #10
  ( -0.982247, -0.000000, +0.187592 ), (  9,  4,  3 ),  #11
  ( -0.794654, -0.577350, -0.187592 ), ( 10,  4,  9 ),  #12
  ( -0.303531, -0.934172, +0.187592 ), ( 10,  5,  4 ),  #13
  ( +0.303531, -0.934172, -0.187592 ), ( 10,  6,  5 ),  #14
  ( +0.187592, -0.577350, -0.794654 ), ( 11,  6, 10 ),  #15
  ( +0.607062, +0.000000, -0.794654 ), ( 11,  7,  6 ),  #16
  ( +0.187592, +0.577350, -0.794654 ), ( 11,  8,  7 ),  #17
  ( -0.491123, +0.356822, -0.794654 ), ( 11,  9,  8 ),  #18
  ( -0.491123, -0.356822, -0.794654 ), ( 11, 10,  9 ),  #19
)
EDGE[30] = (
  (  0,  1 ), (  1,  2 ), (  2,  0 ), (  2,  3 ),
  (  3,  0 ), (  3,  4 ), (  4,  0 ), (  4,  5 ),
  (  5,  0 ), (  5,  1 ), (  5,  6 ), (  6,  1 ),
  (  6,  7 ), (  7,  1 ), (  7,  2 ), (  7,  8 ),
  (  8,  2 ), (  8,  3 ), (  8,  9 ), (  9,  3 ),
  (  9,  4 ), (  9, 10 ), ( 10,  4 ), ( 10,  5 ),
  ( 10,  6 ), ( 10, 11 ), ( 11,  6 ), ( 11,  7 ),
  ( 11,  8 ), ( 11,  9 ),
)

Recommended Posts

Create regular polyhedron data
Create a dummy data file
Create noise-filled audio data with SoX
Create document classification data quickly using NLTK