1 / 2
E8 Lie group or E8 lattice — image 1
1 / 2

E8 Lie group or E8 lattice

Order a print of this model

We calculate the final price from your selected file. You review and accept it before payment.

Saved on this device.

E8 Lie group or E8 lattice

Rating
0 / 5
Likes
12
Downloads
65
Makes
0
Views
321
Reviews
0

Updated at source:

Model information

License
Creative Commons — Attribution — Noncommercial

E8 Lie group or E8 lattice (go with E8 Thick)

E8 root system projected onto its first three basis vectors.

Below is some code I generated in Gemini.

A simple game to learn the basics of E8. (some of the edu diags are sketch)

Below is a phyton script for blender. cut and paste it into the scripting window. hit play

# E8 Lattice Generation Script for Blender (Final Correction)
#
# Fixes a bug in edge generation where only the first edge was correctly placed.
# This version now correctly connects all vertices.

import bpy import bmesh import random from mathutils import Vector, Matrix

--- Configuration ---

Set the fraction of vertices to generate (1.0 = all, 0.25 = 25% random sample)

SAMPLING_FRACTION = 1.0

VERT_RADIUS = 0.08 # Radius of the spheres representing vertices EDGE_RADIUS = 0.02 # Radius of the cylinders representing edges COLLECTION_NAME = "E8_Lattice" # Name for the new collection

--- Helper Functions ---

def create_collection(name): """Creates a new collection or gets it if it already exists.""" if name in bpy.data.collections: return bpy.data.collections[name] else: new_collection = bpy.data.collections.new(name) bpy.context.scene.collection.children.link(new_collection) return new_collection

def get_e8_root_vectors(): """Generates the 240 root vectors of the E8 lattice.""" roots = set() # Type 1: (±1, ±1, 0, ..., 0) permutations. (112 vectors) for i in range(8): for j in range(i + 1, 8): for s1 in [-1, 1]: for s2 in [-1, 1]: v = [0] * 8 v[i] = s1 v[j] = s2 roots.add(tuple(v))

# Type 2: (±½, ±½, ..., ±½) with an even number of minus signs. (128 vectors)
for i in range(2**8):
    v = []
    neg_count = 0
    for k in range(8):
        if (i >> k) & 1:
            v.append(0.5)
        else:
            v.append(-0.5)
            neg_count += 1
    if neg_count % 2 == 0:
        roots.add(tuple(v))
        
# Scale roots by a factor of 2 for better visualization
return [Vector(r) * 2 for r in roots]

def create_mesh_object(name, collection, verts, faces, edges=None): """Creates a single mesh object from vertex, face, and edge data.""" if edges is None: edges = [] mesh = bpy.data.meshes.new(name) mesh.from_pydata(verts, edges, faces) mesh.update() obj = bpy.data.objects.new(name, mesh) collection.objects.link(obj) return obj

--- Core BMesh Generation Functions ---

def generate_vertices_mesh(name, vectors, radius, collection): """Generates a single object containing spheres for all vertices.""" print(f"Generating mesh for {len(vectors)} vertices...") if not vectors: return None

bm = bmesh.new()

for vec in vectors:
    loc_3d = Vector((vec[0], vec[1], vec[2]))
    bmesh.ops.create_icosphere(bm, subdivisions=2, radius=radius, matrix=Matrix.Translation(loc_3d))

obj = create_mesh_object(name, collection, [v.co for v in bm.verts], [[v.index for v in f.verts] for f in bm.faces])
bm.free()

obj.data.polygons.foreach_set('use_smooth', [True] * len(obj.data.polygons))
obj.data.update()

print("Vertex mesh created.")
return obj

def generate_edges_mesh(name, vectors, radius, collection): """Generates a single object containing cylinders for all edges.""" if not vectors or len(vectors) < 2: return None, 0 print("Calculating and generating edge mesh... (this is the slow part)")

bm = bmesh.new()
edge_count = 0
segments = 12

for i in range(len(vectors)):
    for j in range(i + 1, len(vectors)):
        v1 = vectors[i]
        v2 = vectors[j]

        # Check for connectivity (squared distance is 8.0 after scaling)
        if abs((v1 - v2).length_squared - 8.0) &lt; 0.001:
            p1 = Vector((v1[0], v1[1], v1[2]))
            p2 = Vector((v2[0], v2[1], v2[2]))
            
            # --- BUG FIX AREA ---
            # Robustly get the new cylinder's vertices by checking the mesh
            # state before and after the operator.
            verts_before = set(bm.verts)

            bmesh.ops.create_cone(
                bm,
                cap_ends=True,
                segments=segments,
                radius1=radius,
                radius2=radius,
                depth=(p1 - p2).length
            )
            
            new_verts = list(set(bm.verts) - verts_before)
            # --- END FIX ---
            
            # Calculate rotation and translation to position the cylinder
            direction = p2 - p1
            if direction.length &gt; 0: # Avoid issues with zero-length vectors
                location = p1 + direction / 2.0
                rotation_quat = direction.to_track_quat('Z', 'Y')
                
                # Apply the transformation to ONLY the new vertices
                bmesh.ops.rotate(bm, verts=new_verts, cent=Vector((0,0,0)), matrix=rotation_quat.to_matrix().to_4x4())
                bmesh.ops.translate(bm, verts=new_verts, vec=location)
            
            edge_count += 1
            if edge_count % 500 == 0:
                print(f"  ...processed {edge_count} edges...")

obj = create_mesh_object(name, collection, [v.co for v in bm.verts], [[v.index for v in f.verts] for f in bm.faces])
bm.free()

obj.data.polygons.foreach_set('use_smooth', [True] * len(obj.data.polygons))
obj.data.update()

print(f"Edge mesh with {edge_count} edges created.")
return obj, edge_count

--- Main Execution ---

def main(): """Main function to generate the E8 lattice.""" e8_collection = create_collection(COLLECTION_NAME)

for obj in e8_collection.objects:
    bpy.data.objects.remove(obj, do_unlink=True)

print("Generating 240 E8 root vectors...")
root_vectors = get_e8_root_vectors()

if SAMPLING_FRACTION &lt; 1.0:
    num_to_sample = int(len(root_vectors) * SAMPLING_FRACTION)
    sampled_vectors = random.sample(root_vectors, num_to_sample)
    print(f"Sampling {num_to_sample} of {len(root_vectors)} vertices ({SAMPLING_FRACTION * 100:.0f}%).")
else:
    sampled_vectors = root_vectors
    print("Using all 240 vertices.")

generate_vertices_mesh("E8_Vertices", sampled_vectors, VERT_RADIUS, e8_collection)
generate_edges_mesh("E8_Edges", sampled_vectors, EDGE_RADIUS, e8_collection)

print("\n✅ Finished! E8 lattice generated successfully.")

--- Run the Script ---

if name == "main": main()

Tags