import tkinter as tk
import math
import random

# ---------- 基础二十面体 ----------
PHI = (1 + math.sqrt(5)) / 2
verts = [
    (-1, PHI, 0), (1, PHI, 0), (-1, -PHI, 0), (1, -PHI, 0),
    (0, -1, PHI), (0, 1, PHI), (0, -1, -PHI), (0, 1, -PHI),
    (PHI, 0, -1), (PHI, 0, 1), (-PHI, 0, -1), (-PHI, 0, 1)
]

faces = [
    (0, 11, 5), (0, 5, 1), (0, 1, 7), (0, 7, 10), (0, 10, 11),
    (1, 5, 9), (5, 11, 4), (11, 10, 2), (10, 7, 6), (7, 1, 8),
    (3, 9, 4), (3, 4, 2), (3, 2, 6), (3, 6, 8), (3, 8, 9),
    (4, 9, 5), (2, 4, 11), (6, 2, 10), (8, 6, 7), (9, 8, 1)
]


def normalize(v):
    x, y, z = v
    l = math.sqrt(x*x+y*y+z*z)
    return (x/l, y/l, z/l)


def midpoint(a, b):
    return ((a[0]+b[0])/2, (a[1]+b[1])/2, (a[2]+b[2])/2)

# ---------- 高递归细分 ----------


def subdivide(verts, faces, n):
    for _ in range(n):
        new_faces = {}
        cache = {}

        def idx(a, b):
            key = tuple(sorted((a, b)))
            if key not in cache:
                cache[key] = len(verts)
                verts.append(normalize(midpoint(verts[a], verts[b])))
            return cache[key]

        for a, b, c in faces:
            ab = idx(a, b)
            bc = idx(b, c)
            ca = idx(c, a)
            new_faces[(a, ab, ca)] = True
            new_faces[(b, bc, ab)] = True
            new_faces[(c, ca, bc)] = True
            new_faces[(ab, bc, ca)] = True
        faces = list(new_faces.keys())
    return verts, faces


verts, faces = subdivide(verts[:], faces[:], 4)

# ---------- 曲面扰动 ----------
perturbed = []
for x, y, z in verts:
    d = math.sin(x*6)*math.sin(y*6)*0.08
    perturbed.append(normalize((x+d, y+d, z+d)))
verts = perturbed

# ---------- 旋转 & 投影 ----------
angle = 0


def rotateY(v, a):
    x, y, z = v
    return x*math.cos(a)+z*math.sin(a), y, -x*math.sin(a)+z*math.cos(a)


def project(v):
    x, y, z = v
    f = 5/(6+z)
    return 450+x*f*260, 450-y*f*260


root = tk.Tk()
root.title("极限复杂件面 · 纯Python")
canvas = tk.Canvas(root, width=900, height=900, bg="black")
canvas.pack()


def draw():
    global angle
    canvas.delete("all")
    polys = []
    for a, b, c in faces:
        va, vb, vc = [rotateY(verts[i], angle) for i in (a, b, c)]
        z = va[2]+vb[2]+vc[2]
        polys.append((z, [project(va), project(vb), project(vc)]))
    for _, pts in sorted(polys, reverse=True):
        canvas.create_polygon(pts, outline="#00ffff", fill="", width=1)
    angle += 0.005
    root.after(20, draw)


draw()
root.mainloop()
