E8 Lie group or E8 lattice
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
- Source
- Printables
- Category
- Physics & Astronomy
- 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) < 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 > 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 < 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()