Iteration X03: Enhanced Geodesic Visualizer

I’ve updated your code to: ✅ Filter out only the correct 30 edges by computing the minimal edge distance. ✅ Ensure tubes connect their respective vertices correctly instead of being vertical. ✅ Optimize the grid generation code while keeping it readable.

Now, your icosahedron should have precise edges with properly oriented tubes.

I’ve reintroduced the floor and ceiling hexagons, ensuring they are properly updated with the vertical translation parameter. Now, they should correctly appear along with the icosahedral structure.

import * as THREE from 'https://unpkg.com/three@latest/build/three.module.js?module';
import { OrbitControls } from 'https://unpkg.com/three@latest/examples/jsm/controls/OrbitControls.js?module';

// Golden Ratio and Scaling function
const PHI = (1 + Math.sqrt(5)) / 2;
const sqrt5 = Math.sqrt(5);

function transformCoord(k) {
    return (Math.round(k / PHI) + k * PHI) / sqrt5;
}

// Generate Icosahedron Vertices
const baseVertices = [
    [0, 5, 3], [0, -5, 3], [0, -5, -3], [0, 5, -3]
];

const icoVertices = [];
baseVertices.forEach(v => {
    icoVertices.push(v);
    icoVertices.push([v[1], v[2], v[0]]);
    icoVertices.push([v[2], v[0], v[1]]);
});

// Transform coordinates
const vertices = icoVertices.map(v => v.map(transformCoord));

// Parameters
let tubeThickness = 0.1;
let verticalTranslation = 0;
let gridOpacity = 0.5;

// Initialize Three.js Scene
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 10;

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Create Icosahedron Edges as Tubes
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const tubeMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const minEdgeDistance = Math.abs(transformCoord(3) - transformCoord(-3));

vertices.forEach((v1, i) => {
    vertices.forEach((v2, j) => {
        if (i < j) {
            const distance = Math.sqrt(
                (v1[0] - v2[0]) ** 2 +
                (v1[1] - v2[1]) ** 2 +
                (v1[2] - v2[2]) ** 2
            );
            if (Math.abs(distance - minEdgeDistance) < 0.01) {
                const tubeGeometry = new THREE.CylinderGeometry(tubeThickness, tubeThickness, distance, 8);
                const tube = new THREE.Mesh(tubeGeometry, tubeMaterial);
                const midpoint = v1.map((val, idx) => (val + v2[idx]) / 2);
                tube.position.set(midpoint[0], midpoint[1] + verticalTranslation, midpoint[2]);
                tube.lookAt(new THREE.Vector3(v2[0], v2[1] + verticalTranslation, v2[2]));
                scene.add(tube);
            }
        }
    });
});

// Create 3D Grid
const gridMaterial = new THREE.LineBasicMaterial({ color: 0xaaaaaa, transparent: true, opacity: gridOpacity });
const gridLines = [];

for (let k = -5; k <= 5; k++) {
    for (let i = 0; i < 3; i++) {
        let lineGeometry = new THREE.BufferGeometry();
        let points = [];
        for (let j = -5; j <= 5; j++) {
            let point = [0, 0, 0];
            point[i] = transformCoord(k);
            point[(i + 1) % 3] = transformCoord(j);
            points.push(new THREE.Vector3(...point));
        }
        lineGeometry.setFromPoints(points);
        gridLines.push(new THREE.Line(lineGeometry, gridMaterial));
    }
    for (let i = 0; i < 3; i++) {
        let lineGeometry = new THREE.BufferGeometry();
        let points = [];
        for (let j = -5; j <= 5; j++) {
            let point = [0, 0, 0];
            point[i] = transformCoord(j);
            point[(i + 1) % 3] = transformCoord(k);
            points.push(new THREE.Vector3(...point));
        }
        lineGeometry.setFromPoints(points);
        gridLines.push(new THREE.Line(lineGeometry, gridMaterial));
    }
}

gridLines.forEach(line => scene.add(line));

// Create Floor and Ceiling Hexagons
const hexagonMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 });
const floorHexagon = [
    [0, 5, -3], [4, 1, -3], [4, -1, -3],
    [0, -5, -3], [-4, -1, -3], [-4, 1, -3], [0, 5, -3]
].map(v => new THREE.Vector3(...v.map((coord, i) => i === 1 ? coord + verticalTranslation : coord)));
const ceilingHexagon = floorHexagon.map(v => new THREE.Vector3(v.x, v.y + 6, v.z));

const floorGeometry = new THREE.BufferGeometry().setFromPoints(floorHexagon);
const ceilingGeometry = new THREE.BufferGeometry().setFromPoints(ceilingHexagon);
scene.add(new THREE.LineLoop(floorGeometry, hexagonMaterial));
scene.add(new THREE.LineLoop(ceilingGeometry, hexagonMaterial));

// Controls
const controls = new OrbitControls(camera, renderer.domElement);

// Animation loop
function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}
animate();

Iteration X02: Enhanced Geodesic Visualizer

We have added the external icosahedron tubular structure.
Though the tubes are all vertical and dont have the right size.
There are too much because we have not selected only the short edges.
The grids are displayed as 3 square grids at the equators.

import * as THREE from 'https://unpkg.com/three@latest/build/three.module.js?module';
import { OrbitControls } from 'https://unpkg.com/three@latest/examples/jsm/controls/OrbitControls.js?module';

// Golden Ratio and Scaling function
const PHI = (1 + Math.sqrt(5)) / 2;
const sqrt5 = Math.sqrt(5);

function transformCoord(k) {
    return (Math.round(k / PHI) + k * PHI) / sqrt5;
}

// Generate Icosahedron Vertices
const baseVertices = [
    [0, 5, 3], [0, -5, 3], [0, -5, -3], [0, 5, -3]
];

const icoVertices = [];
baseVertices.forEach(v => {
    icoVertices.push(v);
    icoVertices.push([v[1], v[2], v[0]]);
    icoVertices.push([v[2], v[0], v[1]]);
});

// Transform coordinates
const vertices = icoVertices.map(v => v.map(transformCoord));

// Parameters
let tubeThickness = 0.1;
let verticalTranslation = 0;
let gridOpacity = 0.5;

// Initialize Three.js Scene
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 10;

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Create Icosahedron Edges as Tubes
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const tubeGeometry = new THREE.CylinderGeometry(tubeThickness, tubeThickness, 1, 8);

for (let i = 0; i < vertices.length; i++) {
    for (let j = i + 1; j < vertices.length; j++) {
        const midpoint = vertices[i].map((v, idx) => (v + vertices[j][idx]) / 2);
        const tube = new THREE.Mesh(tubeGeometry, material);
        tube.position.set(midpoint[0], midpoint[1] + verticalTranslation, midpoint[2]);
        scene.add(tube);
    }
}

// Create 3D Grid
const gridMaterial = new THREE.LineBasicMaterial({ color: 0xaaaaaa, transparent: true, opacity: gridOpacity });
const gridLines = [];

for (let k = -5; k <= 5; k++) {
    for (let i = 0; i < 3; i++) {
        let lineGeometry = new THREE.BufferGeometry();
        let points = [];
        for (let j = -5; j <= 5; j++) {
            let point = [0, 0, 0];
            point[i] = transformCoord(k);
            point[(i + 1) % 3] = transformCoord(j);
            points.push(new THREE.Vector3(...point));
        }
        lineGeometry.setFromPoints(points);
        gridLines.push(new THREE.Line(lineGeometry, gridMaterial));
    }
}

gridLines.forEach(line => scene.add(line));

// Controls
const controls = new OrbitControls(camera, renderer.domElement);

// Animation loop
function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}
animate();

Iteration X01: Enhanced Geodesic Visualizer

We have updated the 3D visualizer to include interactive controls and floor scaling.

import * as THREE from 'https://unpkg.com/three@latest/build/three.module.js?module';
import { OrbitControls } from 'https://unpkg.com/three@latest/examples/jsm/controls/OrbitControls.js?module';

// Golden Ratio and Scaling function
const PHI = (1 + Math.sqrt(5)) / 2;
const sqrt5 = Math.sqrt(5);

function transformCoord(k) {
    return (Math.round(k / PHI) + k * PHI) / sqrt5;
}

// Generate Icosahedron Vertices with Circular Permutations
const baseVertices = [
    [0, 2, 1], [0, -2, 1], [0, -2, -1], [0, 2, -1]
];

const icoVertices = [];
baseVertices.forEach(v => {
    icoVertices.push(v);
    icoVertices.push([v[1], v[2], v[0]]);
    icoVertices.push([v[2], v[0], v[1]]);
});

// Transform coordinates
const vertices = icoVertices.map(v => v.map(transformCoord));

// Floor and Ceiling Hexagons
//const scaleMap = { 1: 3, 2: 5, -1: -3, -2: -5 };
const hexagonBase = [
    [0, 5, -3], [4, 1, -3], [4, -1, -3], 
    [0, -5, -3], [-4, -1, -3], [-4, 1, -3]
].map(v => v.map(transformCoord));

const hexagonTop = hexagonBase.map(v => [v[0], v[1], transformCoord(3)]);

// Initialize Three.js Scene
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 10;

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Create Icosahedron Geometry
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(vertices.flat());
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const material = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true });
const icosahedron = new THREE.Mesh(geometry, material);
scene.add(icosahedron);

// Floor and Ceiling Hexagons
function createHexagon(hexagonVertices, color) {
    const hexGeometry = new THREE.BufferGeometry();
    const hexPoints = hexagonVertices.map(v => new THREE.Vector3(...v));
    hexGeometry.setFromPoints(hexPoints);
    const hexMaterial = new THREE.LineBasicMaterial({ color });
    const hexMesh = new THREE.LineLoop(hexGeometry, hexMaterial);
    scene.add(hexMesh);
}

createHexagon(hexagonBase, 0x0000ff); // Floor in Blue
createHexagon(hexagonTop, 0xff0000); // Ceiling in Red

// Controls
const controls = new OrbitControls(camera, renderer.domElement);

// Animation loop
function animate() {
    requestAnimationFrame(animate);
    icosahedron.rotation.x += 0.01;
    icosahedron.rotation.y += 0.01;
    renderer.render(scene, camera);
}
animate();