Project conceived as a 3D extension of the 2D political compass. HTML5 Canvas chosen for zero-dependency, cross-platform rendering. First commit: base HTML/CSS structure and canvas helper scripts.
Implemented full 3D rendering pipeline: Euler rotation (Y then X axes), perspective projection, and Phong-inspired lighting with ambient and diffuse components. Sphere rendered as 2,500 random surface points with RGB-from-coordinate color mapping.
20 political ideologies hand-positioned in 3D space with historical start years. Trail system added to visualize ideological drift — each ideology stores its last 80 positions, rendered as white path lines.
Major historical events (1789, 1917, 1933, 1945, 1989, 2008) modeled as gravitational forces in ideological space. Linear temporal decay within 60-year windows. Inter-ideology interaction term added using dot-product attraction/repulsion.
Implemented spherical K-means (k=3) using angular/cosine distance. Active ideologies are clustered in real time, revealing dominant groupings. User self-placement added via X/Y/Z sliders with radicality metric and nearest-ideology detection.
Added zoom (scroll + +/− keys), full keyboard rotation (arrow keys), PNG export. Codebase split into 9 specialized modules: core, data, projection, interaction, physics, clustering, rendering, time, main.
Formal mathematical documentation published: ideology vectors, base positions, historical force equations with Σ notation, clustering centroid formulas, perspective projection derivation, and an end-to-end numerical example (Fascism, 1935).
44 unit tests across 4 modules (clustering, projection, physics, data) using Jest. System instability metric added — average velocity of active ideologies per frame. GitHub Actions pipeline: tests on every PR, deploy to GitHub Pages on main.
Full migration to Astro 5 + Tailwind CSS v4. Home page with model explanation, 15-question ideological positioning quiz (Likert scale, 3 axes), mobile touch support, URL params for quiz-to-tool handoff, and this About page.
v_i = (x_i, y_i, z_i) ∈ [−1,1]³ f_e(t) = s_e · g · (1 − |t−t_e| / T) v_i(t) = v_i_base + Σ f_e(t) · (h_e − v_i_base) r_u = ||v_u|| = √(x² + y² + z²) C_j = normalize(Σ v_i ∈ G_j / |G_j|) scale = r · zoom / (2 − z_rot)
Full formal documentation available in docs/ACADEMICAL_DOCUMENTATION.md and docs/TECHNICAL_DOCUMENTATION.md.