Exemple #1
0
def generate_polytope_data(coxeter_diagram,
                           trunc_type,
                           extra_relations=(),
                           snub=False,
                           dual=False):
    """
    Generate polyhedra vertex coordinates and face indices.
    The result is output to the file `data.frag`.
    """
    if snub:
        P = models.Snub(coxeter_diagram, extra_relations=extra_relations)
    else:
        P = models.Polyhedra(coxeter_diagram, trunc_type, extra_relations)

    if dual:
        P = models.Catalan3D(P)

    P.build_geometry()
    vertices_coords = P.vertices_coords

    def get_oriented_faces(face_group, name):
        """The faces returned by `P.build_geometry()` may not have their
        normal vectors pointing outward, we need to rearange them in the
        right order before sending them to the gpu.
        """
        m = len(face_group)
        n = len(face_group[0])
        faces_data = np.zeros((m, n, 3), dtype=float)
        for ind, face in enumerate(face_group):
            face_coords = [vertices_coords[ind] for ind in face]
            face_center = sum(face_coords) / len(face)
            v0, v1, v2 = face_coords[:3]
            normal = np.cross(v1 - v0, v2 - v0)
            if np.dot(face_center, normal) < 0:
                face_coords = face_coords[::-1]

            faces_data[ind, :, :] = face_coords

        faces_data = faces_data.reshape(m * n, 3)
        vec_string = ",\n".join(f"    vec3({x}, {y}, {z})"
                                for x, y, z in faces_data)
        return (f"#define {name}Enabled  {n}\n\n" +
                f"vec3[{m * n}] {name} = vec3[{m * n}](\n{vec_string}\n);\n\n")

    result = get_oriented_faces(P.face_indices[0], "facesA")

    if len(P.face_indices) > 1:
        result += get_oriented_faces(P.face_indices[1], "facesB")
    if len(P.face_indices) > 2:
        result += get_oriented_faces(P.face_indices[2], "facesC")

    with open(os.path.join(GLSL_DIR, "data.frag"), "w") as f:
        f.write(result)
def anim(
        coxeter_diagram,
        trunc_type,
        extra_relations=(),
        snub=False,
        description="polytope-animation",
):
    """
    Call POV-Ray to render the frames and call FFmpeg to generate the movie.
    """
    if len(coxeter_diagram) == 3:
        if snub:
            P = models.Snub(coxeter_diagram, extra_relations=extra_relations)
        else:
            P = models.Polyhedra(coxeter_diagram, trunc_type, extra_relations)
        scene_file = "polyhedra_animation.pov"

    elif len(coxeter_diagram) == 6:
        P = models.Polychora(coxeter_diagram, trunc_type, extra_relations)
        scene_file = "polytope_animation.pov"

    elif len(coxeter_diagram) == 10:
        P = models.Polytope5D(coxeter_diagram, trunc_type, extra_relations)
        scene_file = "polytope_animation.pov"

    else:
        raise ValueError("Invalid Coxeter diagram: {}".format(coxeter_diagram))

    P.build_geometry()

    # POV-Ray does not support 5d vectors well, so project the vertices in python
    if isinstance(P, models.Polytope5D):
        P.proj4d()
    vert_data, edge_data, face_data = P.get_povray_data()
    with open(data_file, "w") as f:
        f.write(POV_TEMPLATE.format(vert_data, edge_data, face_data))

    subprocess.call(POV_COMMAND.format(scene_file, description), shell=True)
    subprocess.call(FFMPEG_COMMAND.format(description, description),
                    shell=True)
    return P