正多面体のデータが欲しい。簡単に作れそうだけど、作る方法を考えると、簡単ではなさそう。プログラムを作ってはみたものの泥縄感が漂う。
生成方法
頂点が半径1の球の上にある正多面体のデータを作ります。
正多面体($M$)に対するテーブルは「1面の角数($N$)」と「頂点に接する面の数($F$)」のみです。
面の法線を求める
最初の頂点を $\left( 0,0,1 \right)$ として、接する面の辺の生成を目指します。
次の頂点 $\left( \sin{\theta}, 0, \cos{\theta} \right)$ を求めて、x-y 平面を「接する面の数」分割するように回転します。
すると、3番目は $\left( \sin{\theta} \cos{\phi}, \sin{\theta} \sin{\phi}, \cos{\theta} \right)$ になります。
$\phi$ は「接する面の数($F$)」から求まります。
$\theta$ は3つの頂点から求められますが、頂点を作る前に求めておかなくてはならないので
\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} } \\
& = & 2 \cos^2{ \frac{\pi}{N} } \csc^2{ \frac{\pi}{F} } - 1 \\
\end{eqnarray}
として、$N,F$ から $\cos{\theta}$ を求めます。3つの頂点を求めたら、最初の「面の法線」が外積
N_1 = \frac{L_1 \times L_2}{ \left| L_1 \times L_2 \right|}
で求まるので、この法線を x-y 平面で一周分を角度 $\phi$ 毎に回転すると $F$ 個の「面の法線」が求まります。
正多面体の中心から面までの距離は、最初の頂点 $P_1$ と最初の面の法線 $N_1$ の内積になるので
\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}
として求めます。法線に対して $\left( n_z = D \right)$ の値を使うと面の式にできます。
追記: $D$ を変数のまま求めたところ
D = \cot{ \frac{\pi}{F} } \cot{ \frac{\pi}{N} }
となりました。
全ての面の法線を求める
法線は3つ以上求まっているので、隣接する面の法線 $N_1,N_2$ と、その隣の面の法線 $N_3$ の関係は
\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}
とすることができます。これで、隣接する面の法線 $N_1,N_2$ から新たな法線 $N_3$ が
\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| } \\
N_3 & = & X_{cos}\ n_x + Y_{cos}\ n_y + Z_{cos}\ n_z \\
\end{eqnarray}
で求められます。
2つの法線の総当たりで、新たな法線を求め、重複を排除して、増えなくなったら目的達成です。
頂点を求める
隣接する面の法線 $N_1,N_2$ と、正多面体の中心(原点)から面までの距離 $D$ で作られる平面の交線が「正多面体の辺」を通ります。この交線と半径 $1$ の球の交点が求める頂点です。
交線の方向は2つの法線の外積
L_V = \frac{ N_1 \times N_2 }{ \left| N_1 \times N_2 \right| }
で求まります。交線の基点を「辺の中心」にしたいので、2つの法線の中間を通る直線 $L_C$ と、面の交点 $L_P$ を
\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}
で求めます。$\left| L_P \right|$ は原点から頂点までの距離 $1$ に対して
\cos{\theta_P} = \left| L_P \right|
と表せるので、$L_P$ から頂点までの距離は
L_D = \sin{\theta_P} = \sqrt{1 - \cos^2{\theta_P}} = \sqrt{1 - \left( L_P \cdot L_P \right) }
となります。これは「面の法線を求める」にある $\left| L_1 \right|$ の半分だから
L_D = \frac{ \left| L_1 \right| }{2}
とすることもできます。(プログラムは前者のままです)
求める頂点は、辺の中心から等間隔にあるので
V = L_P \pm L_D L_V
になります。
これを「全ての法線」と同様に、2つの法線の総当たりで、辺と頂点を求めます。
あとは、データを整えて完了です。
プログラムと出力結果
正多面体 データ生成 Python プログラム
import math
flag_debug = False
flag_verbose = False
flag_rotate = False
paren_c = ('{', '}')
paren_vec = ('(', ')')
paren_out = ('(', ')')
paren_list = ('(', ')')
# 正多面体のデータ
# 面数: (面の角数, 頂点の接面数)
RP_TAB = {
+4: (3, 3),
+6: (4, 3),
+8: (3, 4),
12: (5, 3),
20: (3, 5),
}
FP_THR = 1.0 / 1024 # 判定時の演算誤差の許容範囲
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): # 内積
return (a[0] * b[0] + a[1] * b[1] + a[2] * b[2])
def vec_cross(a, b): # 外積
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): # 外積と正規化
return vec_normalize(vec_cross(a, b))
def vec_normalize(a): # 正規化
return vec_mul(a, 1.0 / math.sqrt(vec_inner(a, a)))
# X-Y 平面で回転
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])
# ベクトル データの追加 (重複を排除する)
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
# 正多面体データの作成
def make(F): # F = 面の数
P = RP_TAB[F][0] # P = 面の角数
K = RP_TAB[F][1] # K = 頂点の接面数
E = F * P / 2 # E = 辺数
V = E - F + 2 # V = 頂点数
if flag_verbose:
print('面数 : %d' % F)
print('辺数 : %d' % E)
print('頂点数: %d' % V)
pass
# 頂点の接面数で一周
rK1 = math.pi / K # rK1 = π / K
rK2 = math.pi * 2 / K # rK2 = 2π / K
cK1, sK1 = cos_sin(rK1)
cK2, sK2 = cos_sin(rK2)
# 多角形に関する要素
rP = math.pi * (P - 2) / P # rP = π(P-2) / P
cP, sP = cos_sin(rP)
# 辺と中心角に関する要素
cR = (cK1 * cK1 - cP) / (sK1 * sK1)
sR = math.sqrt(1 - cR * cR)
# 3つの面の法線を求める
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 = 中心から平面までの距離
sD = math.sqrt(1 - cD * cD)
# 隣接する面の角度要素を求める
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)
# 正多面体の向きを修正する
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
# 全ての面の法線を求める
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]
# n0 と n1 が隣接する面か?
nc = vec_inner(n0, n1)
if abs(N_cos - nc) >= FP_THR:
continue
# n0 から 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)) # 増えなくなったら終わり
continue
# 全ての辺と頂点を求める
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]
# n0 と n1 が隣接する面か?
nc = vec_inner(n0, n1)
if abs(N_cos - nc) >= FP_THR: continue
# n0 と n1 の交線を求める(辺の中心を通る)
lc = vec_normalize(vec_add(n0, n1))
lv = vec_cross_normalize(n0, n1)
lp = vec_mul(lc, cD / vec_inner(n0, lc))
# 交線と半径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)
# 頂点と辺のデータを追加
i1 = vec_append(vl, q1)
i2 = vec_append(vl, q2)
fl[s].append((i1, i2))
fl[e].append((i1, i2))
continue
continue
# データの整理
rl = []
el = {}
for f in range(len(fl)):
vd = fl[f]
# ワイヤー フレーム向け辺データ
for e in vd: el[e] = None
# バラバラの辺データを連続にする(ポリゴン化)
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
# ポリゴンの法線を修正
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())
# メイン関数
def main(F):
vl, fl, el = make(F)
# 頂点データの出力
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)
# 法線データの出力
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
# 面データの出力 (法線, 頂点リスト)
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)
# 辺データの出力
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='面数={4|6|8|12|20}')
parser.add_argument('-d', '--debug', action='store_true', help='デバッグ用')
parser.add_argument('-v', '--verbose', action='store_true', help='冗長出力')
parser.add_argument('-r', '--rotate', action='store_true', help='6,12面体の方向を修正')
parser.add_argument('-c', '--cparen', action='store_true', help='括弧の文字を変更')
parser.add_argument('-n', '--normal', action='store_true', help='法線データを分離')
parser.add_argument('-u', '--uncomment', action='store_true', help='インデックスを排除')
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 : 無効な面数です' % N)
parser.print_help()
pass
continue
if sep: print(s)
pass
# 無駄な pass, continue, return は Emacs のインデント対策
出力結果: 正四面体
面数 : 4
辺数 : 6
頂点数: 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 ),
)
出力結果: 正六面体
面数 : 6
辺数 : 12
頂点数: 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 ),
)
********* 以下は、空間軸と面の向きが同じ
面数 : 6
辺数 : 12
頂点数: 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 ),
)
出力結果: 正八面体
面数 : 8
辺数 : 12
頂点数: 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 ),
)
出力結果: 正十二面体
面数 : 12
辺数 : 30
頂点数: 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 ),
)
********* 以下は、Z軸の向きと同じ面がある
面数 : 12
辺数 : 30
頂点数: 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 ),
)
出力結果: 正二十面体
面数 : 20
辺数 : 30
頂点数: 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 ),
)
新しい方法で生成
正多面体のデータを作る[改] (HTML+JavaScript版) にある方法で生成します。
正多面体 データ生成 Python3 プログラム ([改]方式)
#!/usr/bin/env python3
import math
import numbers
import operator
####
# 正多面体のデータ生成
####
class RegularPolyhedron:
INDEX = {4: 1, 6: 2, 8: 3, 12: 4, 20: 5}
POLYHEDRON = (4, 4, 6, 8, 12, 20)
POLYGON = (3, 3, 4, 3, 5, 3)
# 3ベクトルから残りのベクトルを求める.
@staticmethod
def create_vector_list(p1, p2, p3):
v1 = p1.normalize()
v2 = (p1 * p2).normalize()
v3 = (v1 * v2).normalize()
xcos, ycos, zcos = [v.dot(p3) for v in (v1, v2, v3)]
pcos = p1.dot(p2)
vecs = [p1, p2, p3]
def vec_add(q1, q2):
x = q1.normalize()
y = (q1 * q2).normalize()
z = (x * y).normalize()
v = (x * xcos + y * ycos + z * zcos).normalize()
if len(tuple(filter((lambda p: v.neareq(p)), vecs))) == 0:
vecs.append(v)
last_vlen = 0
new_vlen = len(vecs)
while last_vlen != new_vlen:
for q1 in vecs[last_vlen:new_vlen]:
for q2 in vecs:
if q1.doteq(q2, pcos):
vec_add(q1, q2)
vec_add(q2, q1)
last_vlen = new_vlen
new_vlen = len(vecs)
return tuple([v.fixfp() for v in sorted(vecs, key=operator.itemgetter(2, 1, 0), reverse=True)])
# ポリゴン情報の一覧を作成.
@staticmethod
def create_polygon_list(vertex, normal, pcos, ncos):
vlen = len(vertex)
r = []
for n in normal:
pvl = tuple(filter((lambda vi: n.doteq(vertex[vi], ncos)), range(vlen)))
pvlen = len(pvl)
ll = []
for ci in range(pvlen):
pc = vertex[pvl[ci]]
pi, ni = tuple(filter(lambda qi: pc.doteq(vertex[pvl[qi]], pcos), range(pvlen)))
pp, pn = vertex[pvl[pi]], vertex[pvl[ni]]
pi, ni = (pi, ni) if n.neareq(((pc - pp) * (pn - pc)).normalize()) else (ni, pi)
ll.append([ci, ni])
ci, ni = ll[0]
vl = [pvl[ci]]
while ni != 0:
vl.append(pvl[ni])
ci, ni = ll[ni]
r.append(tuple(vl))
return tuple(r)
# 辺情報の一覧を作成.
@staticmethod
def create_edge_list(polygon):
r = []
for poly in polygon:
pp = poly[-1]
for pn in poly:
e = (pp, pn) if pp < pn else (pn, pp)
if e not in r:
r.append(e)
pp = pn
return tuple(sorted(r))
# コンストラクタ.
def __init__(self, M):
S = RegularPolyhedron
self.M = M
self.I = S.INDEX[M]
self.V = S.POLYHEDRON[self.I ^ 1]
self.F = S.POLYGON[self.I ^ 1]
self.N = S.POLYGON[self.I]
PPF = math.pi / self.F
PPN = math.pi / self.N
# 最初の3頂点を求める.
rotXY = 2 * PPF
cosXY = math.cos(rotXY)
sinXY = math.sin(rotXY)
cosZX = 2 * math.pow(math.cos(PPN) / math.sin(PPF), 2) - 1
sinZX = math.sqrt(1 - cosZX * cosZX)
p1 = Vector3(0, 0, 1)
p2 = Vector3(sinZX, 0, cosZX)
p3 = Vector3(sinZX * cosXY, sinZX * sinXY, cosZX)
# 最初の3法線を求める.
rm = Matrix33(cosXY, -sinXY, 0,
sinXY, cosXY, 0,
+ 0, 0, 1)
n1 = ((p1 - p3) * (p2 - p1)).normalize()
n2 = (rm * n1).normalize()
n3 = (rm * n2).normalize()
# 頂点と法線の一覧を作成する.
self.main_vertex = S.create_vector_list(p1, p2, p3)
self.main_normal = S.create_vector_list(n1, n2, n3)
self.dual_vertex = self.main_normal
self.dual_normal = self.main_vertex
self.vertex = self.main_vertex
self.normal = self.main_normal
# 正多面体と対の両方の多角形データを作成する.
self.main_polygon = S.create_polygon_list(self.main_vertex, self.main_normal, p1.dot(p2), p1.dot(n1))
self.dual_polygon = S.create_polygon_list(self.dual_vertex, self.dual_normal, n1.dot(n2), p1.dot(n1))
self.polygon = self.main_polygon
# 正多面体と対の両方の辺データを作成する.
self.main_edge = S.create_edge_list(self.main_polygon)
self.dual_edge = S.create_edge_list(self.dual_polygon)
self.edge = self.main_edge
####
# Vector3
####
class Vector3(numbers.Integral):
MESSAGE_FORMAT = '(%+.6e, %+.6e, %+.6e)'
def __init__(self, *args):
if len(args) == 3:
self.value = list(args)
return
if len(args) == 0:
self.value = [0, 0, 0]
return
if len(args) == 1:
self.value = args[0]
return
raise TypeError
def __int__(self): raise NotImplemented
def __repr__(self): return self.__str__()
def __str__(self): return (Vector3.MESSAGE_FORMAT % tuple(self.value))
def __bool__(self): return (sum(self.value) != 0)
def __eq__(self, rhs):
if type(rhs) is Vector3:
return (self.value == rhs.value)
return False
def __lt__(self, rhs): raise NotImplemented
def __le__(self, rhs): raise NotImplemented
def __neg__(self):
x, y, z = self.value
return Vector3(-x, -y, -z)
def __pos__(self): return Vector3(self)
def __invert__(self): raise NotImplemented
def __add__(self, rhs):
if type(rhs) is Vector3:
x1, y1, z1 = self.value
x2, y2, z2 = rhs.value
return Vector3(x1 + x2, y1 + y2, z1 + z2)
raise NotImplemented
def __sub__(self, rhs):
if type(rhs) is Vector3:
x1, y1, z1 = self.value
x2, y2, z2 = rhs.value
return Vector3(x1 - x2, y1 - y2, z1 - z2)
raise NotImplemented
def __mul__(self, rhs):
x1, y1, z1 = self.value
if type(rhs) in (int, float):
return Vector3(x1 * rhs, y1 * rhs, z1 * rhs)
if type(rhs) is Vector3:
x2, y2, z2 = rhs.value
return Vector3(y1 * z2 - z1 * y2,
z1 * x2 - x1 * z2,
x1 * y2 - y1 * x2)
if type(rhs) is Matrix33:
m11, m12, m13, m21, m22, m23, m31, m32, m33 = rhs.value
return Vector3(x1 * m11 + y1 * m21 + z1 * m31,
x1 * m12 + y1 * m22 + z1 * m32,
x1 * m13 + y1 * m23 + z1 * m33)
raise NotImplemented
def __pow__(self, rhs): raise NotImplemented
def __divmod__(self, rhs):
if type(rhs) in (int, float):
return [self.__truediv__(rhs), self.__mod__(rhs)]
raise NotImplemented
def __truediv__(self, rhs):
if type(rhs) in (int, float):
x, y, z = self.value
return Vector3(x / rhs, y / rhs, z / rhs)
raise NotImplemented
def __floordiv__(self, rhs):
if type(rhs) in (int, float):
x, y, z = self.value
return Vector3(math.floor(x / rhs),
math.floor(y / rhs),
math.floor(z / rhs))
raise NotImplemented
def __mod__(self, rhs):
if type(rhs) in (int, float):
x, y, z = self.value
return Vector3(x % rhs, y % rhs, z % rhs)
raise NotImplemented
# 内積とする.
def __and__(self, rhs):
if type(rhs) is Vector3:
return self.dot(rhs)
raise NotImplemented
def __xor__(self, rhs): raise NotImplemented
def __or__(self, rhs): raise NotImplemented
def __lshift__(self, rhs): raise NotImplemented
def __rshift__(self, rhs): raise NotImplemented
def __radd__(self, lhs): raise NotImplemented
def __rsub__(self, lhs): raise NotImplemented
def __rmul__(self, lhs): raise NotImplemented
def __rmod__(self, lhs): raise NotImplemented
def __rtruediv__(self, lhs): raise NotImplemented
def __rfloordiv__(self, lhs): raise NotImplemented
def __rpow__(self, lhs): raise NotImplemented
def __rand__(self, lhs): raise NotImplemented
def __rxor__(self, lhs): raise NotImplemented
def __ror__(self, lhs): raise NotImplemented
def __rlshift__(self, lhs): raise NotImplemented
def __rrshift__(self, lhs): raise NotImplemented
def __iadd__(self, rhs):
if type(rhs) is Vector3:
x1, y1, z1 = self.value
x2, y2, z2 = rhs.value
self.value = [x1 + x2, y1 + y2, z1 + z2]
return self
raise NotImplemented
def __isub__(self, rhs):
if type(rhs) is Vector3:
x1, y1, z1 = self.value
x2, y2, z2 = rhs.value
self.value = [x1 - x2, y1 - y2, z1 - z2]
return self
raise NotImplemented
def __imul__(self, rhs):
x1, y1, z1 = self.value
if type(rhs) in (int, float):
self.value = (x1 * rhs, y1 * rhs, z1 * rhs)
return self
if type(rhs) is Vector3:
x2, y2, z2 = rhs.value
self.value = [y1 * z2 - z1 * y2,
z1 * x2 - x1 * z2,
x1 * y2 - y1 * x2]
return self
if type(rhs) is Matrix33:
m11, m12, m13, m21, m22, m23, m31, m32, m33 = rhs.value
self.value = [x1 * m11 + y1 * m21 + z1 * m31,
x1 * m12 + y1 * m22 + z1 * m32,
x1 * m13 + y1 * m23 + z1 * m33]
return self
raise NotImplemented
def __itruediv__(self, rhs):
if type(rhs) in (int, float):
x, y, z = self.value
self.value = [x / rhs, y / rhs, z / rhs]
return self
raise NotImplemented
def __imod__(self, rhs):
if type(rhs) in (int, float):
x, y, z = self.value
self.value = [x % rhs, y % rhs, z % rhs]
return self
raise NotImplemented
def __abs__(self):
x, y, z = self.value
return math.sqrt(x * x + y * y + z * z)
def __ceil__(self):
x, y, z = self.value
return Vector3(math.ceil(x), math.ceil(y), math.ceil(z))
def __floor__(self):
x, y, z = self.value
return Vector3(math.floor(x), math.floor(y), math.floor(z))
def __round__(self):
x, y, z = self.value
return Vector3(round(x), round(y), round(z))
def __trunc__(self):
x, y, z = self.value
return Vector3(math.trunc(x), math.trunc(y), math.trunc(z))
def __getitem__(self, key):
return self.value[key]
def __setitem__(self, key, value):
self.value[key] = value
####
def dot(self, rhs):
x1, y1, z1 = self.value
x2, y2, z2 = rhs.value
return (x1 * x2 + y1 * y2 + z1 * z2)
def neareq(self, rhs, thr=(1 / (1 << 20))):
return (abs(1.0 - self.dot(rhs)) < thr)
def doteq(self, rhs, cos, thr=(1 / (1 << 20))):
return (abs(cos - self.dot(rhs)) < thr)
def normalize(self):
return self.__truediv__(self.__abs__())
def fixfp(self):
return Vector3([Vector3.vfixfp(v) for v in self.value])
@staticmethod
def vfixfp(v):
return (round(v) if (abs(v - round(v)) < (1 / (1 << 24))) else v)
####
# Matrix33
####
class Matrix33(numbers.Integral):
MESSAGE_FORMAT = '((%+.6e, %+.6e, %+.6e), (%+.6e, %+.6e, %+.6e), (%+.6e, %+.6e, %+.6e))'
def __init__(self, *args):
if len(args) == 9:
self.value = list(args)
return
if len(args) == 0:
self.value = [1, 0, 0, 0, 1, 0, 0, 0, 1]
return
if len(args) == 1:
arg = args[0]
if type(arg) is Matrix33:
self.value = arg.value * 1
return
raise TypeError
def __int__(self): raise NotImplemented
def __repr__(self): return self.__str__()
def __str__(self): return (Matrix33.MESSAGE_FORMAT % tuple(self.value))
def __bool__(self): return (sum(self.value) != 0)
def __eq__(self, rhs):
if type(rhs) is Matrix33:
return (self.value == rhs.value)
return False
def __lt__(self, rhs): raise NotImplemented
def __le__(self, rhs): raise NotImplemented
def __neg__(self):
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
return Matrix33(-m11, -m12, -m13,
-m21, -m22, -m23,
-m31, -m32, -m33)
def __pos__(self): return Matrix33(self)
def __invert__(self): return self.inverse()
def __add__(self, rhs):
if type(rhs) is Matrix33:
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
r11, r12, r13, r21, r22, r23, r31, r32, r33 = rhs.value
return Matrix33(m11 + r11, m12 + r12, m13 + r13,
m21 + r21, m22 + r22, m23 + r23,
m31 + r31, m32 + r32, m33 + r33)
raise NotImplemented
def __sub__(self, rhs):
if type(rhs) is Matrix33:
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
r11, r12, r13, r21, r22, r23, r31, r32, r33 = rhs.value
return Matrix33(m11 - r11, m12 - r12, m13 - r13,
m21 - r21, m22 - r22, m23 - r23,
m31 - r31, m32 - r32, m33 - r33)
raise NotImplemented
def __mul__(self, rhs):
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
if type(rhs) in (int, float):
return Matrix33(m11 * rhs, m12 * rhs, m13 * rhs,
m21 * rhs, m22 * rhs, m23 * rhs,
m31 * rhs, m32 * rhs, m33 * rhs)
if type(rhs) is Vector3:
x, y, z = rhs.value
return Vector3(m11 * x + m12 * y + m13 * z,
m21 * x + m22 * y + m23 * z,
m31 * x + m32 * y + m33 * z)
if type(rhs) is Matrix33:
r11, r12, r13, r21, r22, r23, r31, r32, r33 = rhs.value
return Matrix33(m11 * r11 + m12 * r21 + m13 * r31,
m21 * r11 + m22 * r21 + m23 * r31,
m31 * r11 + m32 * r21 + m33 * r31,
m11 * r12 + m12 * r22 + m13 * r32,
m21 * r12 + m22 * r22 + m23 * r32,
m31 * r12 + m32 * r22 + m33 * r32,
m11 * r13 + m12 * r23 + m13 * r33,
m21 * r13 + m22 * r23 + m23 * r33,
m31 * r13 + m32 * r23 + m33 * r33)
raise NotImplemented
def __pow__(self, rhs): raise NotImplemented
def __divmod__(self, rhs):
if type(rhs) in (int, float):
return [self.__truediv__(rhs), self.__mod__(rhs)]
raise NotImplemented
def __truediv__(self, rhs):
if type(rhs) in (int, float):
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
return Matrix33(m11 / rhs, m12 / rhs, m13 / rhs,
m21 / rhs, m22 / rhs, m23 / rhs,
m31 / rhs, m32 / rhs, m33 / rhs)
raise NotImplemented
def __floordiv__(self, rhs):
if type(rhs) in (int, float):
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
return Matrix33(math.floor(m11 / rhs), math.floor(m12 / rhs), math.floor(m13 / rhs),
math.floor(m21 / rhs), math.floor(m22 / rhs), math.floor(m23 / rhs),
math.floor(m31 / rhs), math.floor(m32 / rhs), math.floor(m33 / rhs))
raise NotImplemented
def __mod__(self, rhs):
if type(rhs) in (int, float):
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
return Matrix33(m11 % rhs, m12 % rhs, m13 % rhs,
m21 % rhs, m22 % rhs, m23 % rhs,
m31 % rhs, m32 % rhs, m33 % rhs)
raise NotImplemented
def __and__(self, rhs): raise NotImplemented
def __xor__(self, rhs): raise NotImplemented
def __or__(self, rhs): raise NotImplemented
def __lshift__(self, rhs): raise NotImplemented
def __rshift__(self, rhs): raise NotImplemented
def __radd__(self, lhs): raise NotImplemented
def __rsub__(self, lhs): raise NotImplemented
def __rmul__(self, lhs): raise NotImplemented
def __rmod__(self, lhs): raise NotImplemented
def __rtruediv__(self, lhs): raise NotImplemented
def __rfloordiv__(self, lhs): raise NotImplemented
def __rpow__(self, lhs): raise NotImplemented
def __rand__(self, lhs): raise NotImplemented
def __rxor__(self, lhs): raise NotImplemented
def __ror__(self, lhs): raise NotImplemented
def __rlshift__(self, lhs): raise NotImplemented
def __rrshift__(self, lhs): raise NotImplemented
def __iadd__(self, rhs):
if type(rhs) is Vector3:
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
r11, r12, r13, r21, r22, r23, r31, r32, r33 = rhs.value
self.value = [m11 + r11, m12 + r12, m13 + r13,
m21 + r21, m22 + r22, m23 + r23,
m31 + r31, m32 + r32, m33 + r33]
return self
raise NotImplemented
def __isub__(self, rhs):
if type(rhs) is Matrix33:
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
r11, r12, r13, r21, r22, r23, r31, r32, r33 = rhs.value
self.value = [m11 - r11, m12 - r12, m13 - r13,
m21 - r21, m22 - r22, m23 - r23,
m31 - r31, m32 - r32, m33 - r33]
return self
raise NotImplemented
def __imul__(self, rhs):
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
if type(rhs) in (int, float):
self.value = [m11 * rhs, m12 * rhs, m13 * rhs,
m21 * rhs, m22 * rhs, m23 * rhs,
m31 * rhs, m32 * rhs, m33 * rhs]
return self
if type(rhs) is Matrix33:
r11, r12, r13, r21, r22, r23, r31, r32, r33 = rhs.value
self.value = [m11 * r11 + m12 * r21 + m13 * r31,
m21 * r11 + m22 * r21 + m23 * r31,
m31 * r11 + m32 * r21 + m33 * r31,
m11 * r12 + m12 * r22 + m13 * r32,
m21 * r12 + m22 * r22 + m23 * r32,
m31 * r12 + m32 * r22 + m33 * r32,
m11 * r13 + m12 * r23 + m13 * r33,
m21 * r13 + m22 * r23 + m23 * r33,
m31 * r13 + m32 * r23 + m33 * r33]
return self
raise NotImplemented
def __itruediv__(self, rhs):
if type(rhs) in (int, float):
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
self.value = [m11 / rhs, m12 / rhs, m13 / rhs,
m21 / rhs, m22 / rhs, m23 / rhs,
m31 / rhs, m32 / rhs, m33 / rhs]
return self
raise NotImplemented
def __imod__(self, rhs):
if type(rhs) in (int, float):
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
self.value = [m11 % rhs, m12 % rhs, m13 % rhs,
m21 % rhs, m22 % rhs, m23 % rhs,
m31 % rhs, m32 % rhs, m33 % rhs]
return self
raise NotImplemented
def __abs__(self): return self.det()
def __ceil__(self):
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
return Matrix33(math.ceil(m11), math.ceil(m12), math.ceil(m13),
math.ceil(m21), math.ceil(m22), math.ceil(m23),
math.ceil(m31), math.ceil(m32), math.ceil(m33))
def __floor__(self):
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
return Matrix33(math.floor(m11), math.floor(m12), math.floor(m13),
math.floor(m21), math.floor(m22), math.floor(m23),
math.floor(m31), math.floor(m32), math.floor(m33))
def __round__(self):
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
return Matrix33(round(m11), round(m12), round(m13),
round(m21), round(m22), round(m23),
round(m31), round(m32), round(m33))
def __trunc__(self):
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
return Matrix33(trunc(m11), trunc(m12), trunc(m13),
trunc(m21), trunc(m22), trunc(m23),
trunc(m31), trunc(m32), trunc(m33))
def __getitem__(self, key):
if type(key) is tuple:
key = key[0] * 3 + key[1]
return self.value[key]
def __setitem__(self, key, value):
if type(key) is tuple:
key = key[0] * 3 + key[1]
self.value[key] = value
def det(self):
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
return (m11 * (m22 * m33 - m23 * m32) +
m12 * (m23 * m31 - m21 * m33) +
m13 * (m21 * m32 - m22 * m31))
def inverse(self):
det = self.det()
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
return Matrix33((m22 * m33 - m23 * m32) / det,
(m23 * m31 - m21 * m33) / det,
(m21 * m32 - m22 * m31) / det,
(m32 * m13 - m33 * m12) / det,
(m33 * m11 - m31 * m13) / det,
(m31 * m12 - m32 * m11) / det,
(m12 * m23 - m13 * m22) / det,
(m13 * m21 - m11 * m23) / det,
(m11 * m22 - m12 * m21) / det)
def transpose(self):
m11, m12, m13, m21, m22, m23, m31, m32, m33 = self.value
return Matrix33(m11, m21, m31, m12, m22, m32, m13, m23, m33)
####
# Main
####
if __name__ == '__main__':
def dump(dual, vertex, normal, edge, polygon):
M = len(normal)
m = []
m.append('*'*40)
m.append(('正%d面体' % M) + (dual and '(対)' or ''))
m.append('*'*40)
m.append('面数 : %d' % len(normal))
m.append('辺数 : %d' % len(edge))
m.append('頂点数: %d' % len(vertex))
m.append('')
m.append('VERTEX[%d] = %s' % (len(vertex), paren_out[0]))
for vi in range(len(vertex)):
v = vertex[vi]
m.append(' %s %+8.6f, %+8.6f, %+8.6f %s,%s'
% tuple([paren_vec[0], *v, paren_vec[1], (comment and (' # %d' % vi) or '')]))
m.append(paren_out[1])
m.append('')
if dump_normal:
m.append('NORMAL[%d] = %s' % (len(normal), paren_out[0]))
for ni in range(len(normal)):
n = normal[ni]
m.append(' %s %+8.6f, %+8.6f, %+8.6f %s,%s'
% tuple([paren_vec[0], *n, paren_vec[1], (comment and (' # %d' % ni) or '')]))
m.append(paren_out[1])
m.append('')
m.append('FACET[%d] = %s' % (len(polygon), paren_out[0]))
for pi in range(len(polygon)):
n = normal[pi]
p = polygon[pi]
mn = ('%s %+8.6f, %+8.6f, %+8.6f %s, ' % (paren_vec[0], *n, paren_vec[1])) if not dump_normal else ''
mp = paren_list[0] + ' ' + ', '.join(['%2d' % p for p in polygon[pi]]) + ' ' + paren_list[1]
m.append(' %s%s,%s' % tuple([mn, mp, (comment and (' # %d' % pi) or '')]))
m.append(paren_out[1])
m.append('')
m.append('EDGE[%d] = %s' % (len(edge), paren_out[0]))
es = [(paren_list[0] + ' ' + ', '.join(['%2d' % p for p in el]) + ' ' + paren_list[1]) for el in edge]
for e in range(0, len(es), 4):
m.append(' ' + ', '.join(es[e:e+4]) + ',')
m.append(paren_out[1])
m.append('')
m.append('')
print('\n'.join(m))
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-c', '--cparen', action='store_true', help='括弧の文字を変更')
parser.add_argument('-n', '--normal', action='store_true', help='法線データを分離')
parser.add_argument('-u', '--uncomment', action='store_true', help='インデックスのコメントを排除')
args = parser.parse_args()
paren_c = ('{', '}')
paren_vec = ('(', ')')
paren_out = ('(', ')')
paren_list = ('(', ')')
dump_normal = args.normal
comment = not args.uncomment
if args.cparen:
paren_vec = paren_c
paren_out = paren_c
paren_list = paren_c
rp_table = [RegularPolyhedron(i) for i in RegularPolyhedron.INDEX.keys()]
for rp in rp_table:
dump(False, rp.main_vertex, rp.main_normal, rp.main_edge, rp.main_polygon)
for ri in (0, 2, 1, 4, 3):
rp = rp_table[ri]
dump(True, rp.dual_vertex, rp.dual_normal, rp.dual_edge, rp.dual_polygon)
pass
####
# END
出力結果
****************************************
正4面体
****************************************
面数 : 4
辺数 : 6
頂点数: 4
VERTEX[4] = (
( +0.000000, +0.000000, +1.000000 ), # 0
( -0.471405, +0.816497, -0.333333 ), # 1
( +0.942809, +0.000000, -0.333333 ), # 2
( -0.471405, -0.816497, -0.333333 ), # 3
)
FACET[4] = (
( +0.471405, +0.816497, +0.333333 ), ( 0, 2, 1 ), # 0
( -0.942809, +0.000000, +0.333333 ), ( 0, 1, 3 ), # 1
( +0.471405, -0.816497, +0.333333 ), ( 0, 3, 2 ), # 2
( +0.000000, +0.000000, -1.000000 ), ( 1, 2, 3 ), # 3
)
EDGE[6] = (
( 0, 1 ), ( 0, 2 ), ( 0, 3 ), ( 1, 2 ),
( 1, 3 ), ( 2, 3 ),
)
****************************************
正6面体
****************************************
面数 : 6
辺数 : 12
頂点数: 8
VERTEX[8] = (
( +0.000000, +0.000000, +1.000000 ), # 0
( -0.471405, +0.816497, +0.333333 ), # 1
( +0.942809, +0.000000, +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 ), ( 0, 2, 4, 1 ), # 0
( -0.816497, +0.000000, +0.577350 ), ( 0, 1, 5, 3 ), # 1
( +0.408248, -0.707107, +0.577350 ), ( 0, 3, 6, 2 ), # 2
( +0.816497, +0.000000, -0.577350 ), ( 2, 6, 7, 4 ), # 3
( -0.408248, +0.707107, -0.577350 ), ( 1, 4, 7, 5 ), # 4
( -0.408248, -0.707107, -0.577350 ), ( 3, 5, 7, 6 ), # 5
)
EDGE[12] = (
( 0, 1 ), ( 0, 2 ), ( 0, 3 ), ( 1, 4 ),
( 1, 5 ), ( 2, 4 ), ( 2, 6 ), ( 3, 5 ),
( 3, 6 ), ( 4, 7 ), ( 5, 7 ), ( 6, 7 ),
)
****************************************
正8面体
****************************************
面数 : 8
辺数 : 12
頂点数: 6
VERTEX[6] = (
( +0.000000, +0.000000, +1.000000 ), # 0
( +0.000000, +1.000000, +0.000000 ), # 1
( -1.000000, +0.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 ), ( 0, 3, 1 ), # 0
( -0.577350, +0.577350, +0.577350 ), ( 0, 1, 2 ), # 1
( -0.577350, -0.577350, +0.577350 ), ( 0, 2, 4 ), # 2
( +0.577350, -0.577350, +0.577350 ), ( 0, 4, 3 ), # 3
( -0.577350, +0.577350, -0.577350 ), ( 1, 5, 2 ), # 4
( +0.577350, +0.577350, -0.577350 ), ( 1, 3, 5 ), # 5
( +0.577350, -0.577350, -0.577350 ), ( 3, 4, 5 ), # 6
( -0.577350, -0.577350, -0.577350 ), ( 2, 5, 4 ), # 7
)
EDGE[12] = (
( 0, 1 ), ( 0, 2 ), ( 0, 3 ), ( 0, 4 ),
( 1, 2 ), ( 1, 3 ), ( 1, 5 ), ( 2, 4 ),
( 2, 5 ), ( 3, 4 ), ( 3, 5 ), ( 4, 5 ),
)
****************************************
正12面体
****************************************
面数 : 12
辺数 : 30
頂点数: 20
VERTEX[20] = (
( +0.000000, +0.000000, +1.000000 ), # 0
( -0.333333, +0.577350, +0.745356 ), # 1
( +0.666667, +0.000000, +0.745356 ), # 2
( -0.333333, -0.577350, +0.745356 ), # 3
( +0.127322, +0.934172, +0.333333 ), # 4
( -0.872678, -0.356822, +0.333333 ), # 5
( +0.745356, -0.577350, +0.333333 ), # 6
( +0.127322, -0.934172, +0.333333 ), # 7
( -0.872678, +0.356822, +0.333333 ), # 8
( +0.745356, +0.577350, +0.333333 ), # 9
( -0.127322, +0.934172, -0.333333 ), # 10
( -0.745356, -0.577350, -0.333333 ), # 11
( -0.745356, +0.577350, -0.333333 ), # 12
( -0.127322, -0.934172, -0.333333 ), # 13
( +0.872678, +0.356822, -0.333333 ), # 14
( +0.872678, -0.356822, -0.333333 ), # 15
( -0.666667, +0.000000, -0.745356 ), # 16
( +0.333333, -0.577350, -0.745356 ), # 17
( +0.333333, +0.577350, -0.745356 ), # 18
( +0.000000, +0.000000, -1.000000 ), # 19
)
FACET[12] = (
( +0.303531, +0.525731, +0.794654 ), ( 0, 2, 9, 4, 1 ), # 0
( -0.607062, +0.000000, +0.794654 ), ( 0, 1, 8, 5, 3 ), # 1
( +0.303531, -0.525731, +0.794654 ), ( 0, 3, 7, 6, 2 ), # 2
( +0.982247, +0.000000, +0.187592 ), ( 2, 6, 15, 14, 9 ), # 3
( -0.491123, -0.850651, +0.187592 ), ( 3, 5, 11, 13, 7 ), # 4
( -0.491123, +0.850651, +0.187592 ), ( 1, 4, 10, 12, 8 ), # 5
( +0.491123, +0.850651, -0.187592 ), ( 4, 9, 14, 18, 10 ), # 6
( +0.491123, -0.850651, -0.187592 ), ( 6, 7, 13, 17, 15 ), # 7
( -0.982247, +0.000000, -0.187592 ), ( 5, 8, 12, 16, 11 ), # 8
( -0.303531, +0.525731, -0.794654 ), ( 10, 18, 19, 16, 12 ), # 9
( +0.607062, +0.000000, -0.794654 ), ( 14, 15, 17, 19, 18 ), # 10
( -0.303531, -0.525731, -0.794654 ), ( 11, 16, 19, 17, 13 ), # 11
)
EDGE[30] = (
( 0, 1 ), ( 0, 2 ), ( 0, 3 ), ( 1, 4 ),
( 1, 8 ), ( 2, 6 ), ( 2, 9 ), ( 3, 5 ),
( 3, 7 ), ( 4, 9 ), ( 4, 10 ), ( 5, 8 ),
( 5, 11 ), ( 6, 7 ), ( 6, 15 ), ( 7, 13 ),
( 8, 12 ), ( 9, 14 ), ( 10, 12 ), ( 10, 18 ),
( 11, 13 ), ( 11, 16 ), ( 12, 16 ), ( 13, 17 ),
( 14, 15 ), ( 14, 18 ), ( 15, 17 ), ( 16, 19 ),
( 17, 19 ), ( 18, 19 ),
)
****************************************
正20面体
****************************************
面数 : 20
辺数 : 30
頂点数: 12
VERTEX[12] = (
( +0.000000, +0.000000, +1.000000 ), # 0
( +0.276393, +0.850651, +0.447214 ), # 1
( -0.723607, +0.525731, +0.447214 ), # 2
( +0.894427, +0.000000, +0.447214 ), # 3
( +0.276393, -0.850651, +0.447214 ), # 4
( -0.723607, -0.525731, +0.447214 ), # 5
( -0.894427, +0.000000, -0.447214 ), # 6
( -0.276393, +0.850651, -0.447214 ), # 7
( +0.723607, +0.525731, -0.447214 ), # 8
( +0.723607, -0.525731, -0.447214 ), # 9
( -0.276393, -0.850651, -0.447214 ), # 10
( +0.000000, +0.000000, -1.000000 ), # 11
)
FACET[20] = (
( -0.187592, -0.577350, +0.794654 ), ( 0, 5, 4 ), # 0
( -0.187592, +0.577350, +0.794654 ), ( 0, 1, 2 ), # 1
( +0.491123, +0.356822, +0.794654 ), ( 0, 3, 1 ), # 2
( -0.607062, +0.000000, +0.794654 ), ( 0, 2, 5 ), # 3
( +0.491123, -0.356822, +0.794654 ), ( 0, 4, 3 ), # 4
( -0.303531, -0.934172, +0.187592 ), ( 4, 5, 10 ), # 5
( +0.794654, +0.577350, +0.187592 ), ( 1, 3, 8 ), # 6
( -0.982247, +0.000000, +0.187592 ), ( 2, 6, 5 ), # 7
( -0.303531, +0.934172, +0.187592 ), ( 1, 7, 2 ), # 8
( +0.794654, -0.577350, +0.187592 ), ( 3, 4, 9 ), # 9
( -0.794654, +0.577350, -0.187592 ), ( 2, 7, 6 ), # 10
( -0.794654, -0.577350, -0.187592 ), ( 5, 6, 10 ), # 11
( +0.303531, +0.934172, -0.187592 ), ( 1, 8, 7 ), # 12
( +0.982247, +0.000000, -0.187592 ), ( 3, 9, 8 ), # 13
( +0.303531, -0.934172, -0.187592 ), ( 4, 10, 9 ), # 14
( +0.187592, +0.577350, -0.794654 ), ( 7, 8, 11 ), # 15
( +0.607062, +0.000000, -0.794654 ), ( 8, 9, 11 ), # 16
( -0.491123, +0.356822, -0.794654 ), ( 6, 7, 11 ), # 17
( +0.187592, -0.577350, -0.794654 ), ( 9, 10, 11 ), # 18
( -0.491123, -0.356822, -0.794654 ), ( 6, 11, 10 ), # 19
)
EDGE[30] = (
( 0, 1 ), ( 0, 2 ), ( 0, 3 ), ( 0, 4 ),
( 0, 5 ), ( 1, 2 ), ( 1, 3 ), ( 1, 7 ),
( 1, 8 ), ( 2, 5 ), ( 2, 6 ), ( 2, 7 ),
( 3, 4 ), ( 3, 8 ), ( 3, 9 ), ( 4, 5 ),
( 4, 9 ), ( 4, 10 ), ( 5, 6 ), ( 5, 10 ),
( 6, 7 ), ( 6, 10 ), ( 6, 11 ), ( 7, 8 ),
( 7, 11 ), ( 8, 9 ), ( 8, 11 ), ( 9, 10 ),
( 9, 11 ), ( 10, 11 ),
)
****************************************
正4面体(対)
****************************************
面数 : 4
辺数 : 6
頂点数: 4
VERTEX[4] = (
( +0.471405, +0.816497, +0.333333 ), # 0
( -0.942809, +0.000000, +0.333333 ), # 1
( +0.471405, -0.816497, +0.333333 ), # 2
( +0.000000, +0.000000, -1.000000 ), # 3
)
FACET[4] = (
( +0.000000, +0.000000, +1.000000 ), ( 0, 1, 2 ), # 0
( -0.471405, +0.816497, -0.333333 ), ( 0, 3, 1 ), # 1
( +0.942809, +0.000000, -0.333333 ), ( 0, 2, 3 ), # 2
( -0.471405, -0.816497, -0.333333 ), ( 1, 3, 2 ), # 3
)
EDGE[6] = (
( 0, 1 ), ( 0, 2 ), ( 0, 3 ), ( 1, 2 ),
( 1, 3 ), ( 2, 3 ),
)
****************************************
正6面体(対)
****************************************
面数 : 6
辺数 : 12
頂点数: 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 ), ( 0, 5, 4, 1 ), # 1
( -1.000000, +0.000000, +0.000000 ), ( 1, 4, 7, 2 ), # 2
( +1.000000, +0.000000, +0.000000 ), ( 0, 3, 6, 5 ), # 3
( +0.000000, -1.000000, +0.000000 ), ( 2, 7, 6, 3 ), # 4
( +0.000000, +0.000000, -1.000000 ), ( 4, 5, 6, 7 ), # 5
)
EDGE[12] = (
( 0, 1 ), ( 0, 3 ), ( 0, 5 ), ( 1, 2 ),
( 1, 4 ), ( 2, 3 ), ( 2, 7 ), ( 3, 6 ),
( 4, 5 ), ( 4, 7 ), ( 5, 6 ), ( 6, 7 ),
)
****************************************
正8面体(対)
****************************************
面数 : 8
辺数 : 12
頂点数: 6
VERTEX[6] = (
( +0.408248, +0.707107, +0.577350 ), # 0
( -0.816497, +0.000000, +0.577350 ), # 1
( +0.408248, -0.707107, +0.577350 ), # 2
( +0.816497, +0.000000, -0.577350 ), # 3
( -0.408248, +0.707107, -0.577350 ), # 4
( -0.408248, -0.707107, -0.577350 ), # 5
)
FACET[8] = (
( +0.000000, +0.000000, +1.000000 ), ( 0, 1, 2 ), # 0
( -0.471405, +0.816497, +0.333333 ), ( 0, 4, 1 ), # 1
( +0.942809, +0.000000, +0.333333 ), ( 0, 2, 3 ), # 2
( -0.471405, -0.816497, +0.333333 ), ( 1, 5, 2 ), # 3
( +0.471405, +0.816497, -0.333333 ), ( 0, 3, 4 ), # 4
( -0.942809, +0.000000, -0.333333 ), ( 1, 4, 5 ), # 5
( +0.471405, -0.816497, -0.333333 ), ( 2, 5, 3 ), # 6
( +0.000000, +0.000000, -1.000000 ), ( 3, 5, 4 ), # 7
)
EDGE[12] = (
( 0, 1 ), ( 0, 2 ), ( 0, 3 ), ( 0, 4 ),
( 1, 2 ), ( 1, 4 ), ( 1, 5 ), ( 2, 3 ),
( 2, 5 ), ( 3, 4 ), ( 3, 5 ), ( 4, 5 ),
)
****************************************
正12面体(対)
****************************************
面数 : 12
辺数 : 30
頂点数: 20
VERTEX[20] = (
( -0.187592, -0.577350, +0.794654 ), # 0
( -0.187592, +0.577350, +0.794654 ), # 1
( +0.491123, +0.356822, +0.794654 ), # 2
( -0.607062, +0.000000, +0.794654 ), # 3
( +0.491123, -0.356822, +0.794654 ), # 4
( -0.303531, -0.934172, +0.187592 ), # 5
( +0.794654, +0.577350, +0.187592 ), # 6
( -0.982247, +0.000000, +0.187592 ), # 7
( -0.303531, +0.934172, +0.187592 ), # 8
( +0.794654, -0.577350, +0.187592 ), # 9
( -0.794654, +0.577350, -0.187592 ), # 10
( -0.794654, -0.577350, -0.187592 ), # 11
( +0.303531, +0.934172, -0.187592 ), # 12
( +0.982247, +0.000000, -0.187592 ), # 13
( +0.303531, -0.934172, -0.187592 ), # 14
( +0.187592, +0.577350, -0.794654 ), # 15
( +0.607062, +0.000000, -0.794654 ), # 16
( -0.491123, +0.356822, -0.794654 ), # 17
( +0.187592, -0.577350, -0.794654 ), # 18
( -0.491123, -0.356822, -0.794654 ), # 19
)
FACET[12] = (
( +0.000000, +0.000000, +1.000000 ), ( 0, 4, 2, 1, 3 ), # 0
( +0.276393, +0.850651, +0.447214 ), ( 1, 2, 6, 12, 8 ), # 1
( -0.723607, +0.525731, +0.447214 ), ( 1, 8, 10, 7, 3 ), # 2
( +0.894427, +0.000000, +0.447214 ), ( 2, 4, 9, 13, 6 ), # 3
( +0.276393, -0.850651, +0.447214 ), ( 0, 5, 14, 9, 4 ), # 4
( -0.723607, -0.525731, +0.447214 ), ( 0, 3, 7, 11, 5 ), # 5
( -0.894427, +0.000000, -0.447214 ), ( 7, 10, 17, 19, 11 ), # 6
( -0.276393, +0.850651, -0.447214 ), ( 8, 12, 15, 17, 10 ), # 7
( +0.723607, +0.525731, -0.447214 ), ( 6, 13, 16, 15, 12 ), # 8
( +0.723607, -0.525731, -0.447214 ), ( 9, 14, 18, 16, 13 ), # 9
( -0.276393, -0.850651, -0.447214 ), ( 5, 11, 19, 18, 14 ), # 10
( +0.000000, +0.000000, -1.000000 ), ( 15, 16, 18, 19, 17 ), # 11
)
EDGE[30] = (
( 0, 3 ), ( 0, 4 ), ( 0, 5 ), ( 1, 2 ),
( 1, 3 ), ( 1, 8 ), ( 2, 4 ), ( 2, 6 ),
( 3, 7 ), ( 4, 9 ), ( 5, 11 ), ( 5, 14 ),
( 6, 12 ), ( 6, 13 ), ( 7, 10 ), ( 7, 11 ),
( 8, 10 ), ( 8, 12 ), ( 9, 13 ), ( 9, 14 ),
( 10, 17 ), ( 11, 19 ), ( 12, 15 ), ( 13, 16 ),
( 14, 18 ), ( 15, 16 ), ( 15, 17 ), ( 16, 18 ),
( 17, 19 ), ( 18, 19 ),
)
****************************************
正20面体(対)
****************************************
面数 : 20
辺数 : 30
頂点数: 12
VERTEX[12] = (
( +0.303531, +0.525731, +0.794654 ), # 0
( -0.607062, +0.000000, +0.794654 ), # 1
( +0.303531, -0.525731, +0.794654 ), # 2
( +0.982247, +0.000000, +0.187592 ), # 3
( -0.491123, -0.850651, +0.187592 ), # 4
( -0.491123, +0.850651, +0.187592 ), # 5
( +0.491123, +0.850651, -0.187592 ), # 6
( +0.491123, -0.850651, -0.187592 ), # 7
( -0.982247, +0.000000, -0.187592 ), # 8
( -0.303531, +0.525731, -0.794654 ), # 9
( +0.607062, +0.000000, -0.794654 ), # 10
( -0.303531, -0.525731, -0.794654 ), # 11
)
FACET[20] = (
( +0.000000, +0.000000, +1.000000 ), ( 0, 1, 2 ), # 0
( -0.333333, +0.577350, +0.745356 ), ( 0, 5, 1 ), # 1
( +0.666667, +0.000000, +0.745356 ), ( 0, 2, 3 ), # 2
( -0.333333, -0.577350, +0.745356 ), ( 1, 4, 2 ), # 3
( +0.127322, +0.934172, +0.333333 ), ( 0, 6, 5 ), # 4
( -0.872678, -0.356822, +0.333333 ), ( 1, 8, 4 ), # 5
( +0.745356, -0.577350, +0.333333 ), ( 2, 7, 3 ), # 6
( +0.127322, -0.934172, +0.333333 ), ( 2, 4, 7 ), # 7
( -0.872678, +0.356822, +0.333333 ), ( 1, 5, 8 ), # 8
( +0.745356, +0.577350, +0.333333 ), ( 0, 3, 6 ), # 9
( -0.127322, +0.934172, -0.333333 ), ( 5, 6, 9 ), # 10
( -0.745356, -0.577350, -0.333333 ), ( 4, 8, 11 ), # 11
( -0.745356, +0.577350, -0.333333 ), ( 5, 9, 8 ), # 12
( -0.127322, -0.934172, -0.333333 ), ( 4, 11, 7 ), # 13
( +0.872678, +0.356822, -0.333333 ), ( 3, 10, 6 ), # 14
( +0.872678, -0.356822, -0.333333 ), ( 3, 7, 10 ), # 15
( -0.666667, +0.000000, -0.745356 ), ( 8, 9, 11 ), # 16
( +0.333333, -0.577350, -0.745356 ), ( 7, 11, 10 ), # 17
( +0.333333, +0.577350, -0.745356 ), ( 6, 10, 9 ), # 18
( +0.000000, +0.000000, -1.000000 ), ( 9, 10, 11 ), # 19
)
EDGE[30] = (
( 0, 1 ), ( 0, 2 ), ( 0, 3 ), ( 0, 5 ),
( 0, 6 ), ( 1, 2 ), ( 1, 4 ), ( 1, 5 ),
( 1, 8 ), ( 2, 3 ), ( 2, 4 ), ( 2, 7 ),
( 3, 6 ), ( 3, 7 ), ( 3, 10 ), ( 4, 7 ),
( 4, 8 ), ( 4, 11 ), ( 5, 6 ), ( 5, 8 ),
( 5, 9 ), ( 6, 9 ), ( 6, 10 ), ( 7, 10 ),
( 7, 11 ), ( 8, 9 ), ( 8, 11 ), ( 9, 10 ),
( 9, 11 ), ( 10, 11 ),
)