Spherical Scalar and Vector Harmonics (With Spin 1/2 and Charge)

by Chantal Roth

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Spherical and Vector Harmonics Visualization</title>

  <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>

  <!-- Include Three.js library -->
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
  <!-- Include OrbitControls -->
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js"></script>
  <!-- Include dat.GUI library for controls -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/10.0.0/math.min.js"></script>

  <link rel="stylesheet" type="text/css" href="style.css">

  <!-- Styling for scrolling and modal -->
  <style>
    #info-popup {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      display: none;
      z-index: 10000;
      background-color: rgba(0,0,0,0.5);
      overflow-y: auto;
    }
    #info-popup-content {
      background-color: #fff;
      margin: 40px auto;
      padding: 20px;
      border: 1px solid #888;
      width: 80%;
      max-width: 1000px;
      max-height: 90%;
      overflow-y: auto;
      position: relative;
      border-radius: 6px;
    }
    .close-button {
      color: #aaa;
      float: right;
      font-size: 28px;
      font-weight: bold;
      cursor: pointer;
    }
    .close-button:hover,
    .close-button:focus {
      color: black;
      text-decoration: none;
      cursor: pointer;
    }
  </style>
</head>
<body>

<!-- Info Popup -->
<div id="info-popup">
  <div id="info-popup-content">
    <span class="close-button" id="info-close">&times;</span>

    <h2>Simulation Overview</h2>
    <p>
      This simulation offers a unique visualization of both <strong>scalar</strong> and <strong>vector spherical harmonics</strong>, essential in describing quantum...

CSS

body { margin: 0; overflow: hidden; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }

/* Style for the GUI container */

/* Ensure GUI container has appropriate z-index and positioning */
#gui-container {
    position: absolute;
    top: 30px;
    left: 10px;
    z-index: 1001; /* Adjusted to be above the popup background but below the close button */
    padding-right: 50px; /* Add padding to prevent overlap with the close button */
}
#quantum-gui-container {
    position: absolute;
    top: 30px;
    right: 10px;
    z-index: 1001; /* Adjusted to be above the popup background but below the close button */
    padding-right: 50px; /* Add padding to prevent overlap with the close button */
}

/* Styles for the info popup */
#info-popup {
    display: none; /* Hidden by default */
    position: fixed;
    z-index: 1000;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    overflow: auto; /* Enable scroll if needed */
    background-color: rgba(0, 0, 0, 0.6); /* Black background with opacity */
    backdrop-filter: blur(4px); /* Blur effect for background */
    animation: fadeIn 0.3s ease-out;
}

#info-popup-content {
    background-color: #fefefe;
    margin: 1% auto;
    padding: 20px 30px;
    border-radius: 10px;
    width: 90%;
    max-width: 1200px;
    box-shadow: 0 5px 15px rgba(0,0,0,0.3);
    position: relative;
    animation: slideIn 0.4s ease-out;
    max-height: 90vh; /* Slightly reduced max-height */
    overflow: auto; /* Enable scrollbars if content overflows */
}

/* Additional responsive adjustments for smaller screens */
@media (max-width: 768px) {
    .close-button {
        top: 5px;
        right: 5px;
        font-size: 24px; /* Slightly smaller to fit better on small screens */
    }

    #gui-container {
        padding-right: 30px; /* Less padding on smaller screens */
    }
}
/* Adjust the positioning and z-index of the close button */
.close-button {
    color: #ffffff;
    float: right;
    font-size: 20px;
  ...

JavaScript

// ===================== KNOTS =====================
function basicTwist(t, scale) {
    const R = 2, r = 1;
    const x = (R + r * Math.cos(t)) * Math.cos(t);
    const y = (R + r * Math.cos(t)) * Math.sin(t);
    const z = r * Math.sin(t);
    return new THREE.Vector3(x, y, z).multiplyScalar(scale);
}

function doubleHelix(t, scale) {
    const R = 2, r = 1;
    const x = (R + r * Math.cos(2*t)) * Math.cos(t);
    const y = (R + r * Math.cos(2*t)) * Math.sin(t);
    const z = r * Math.sin(2*t);
    return new THREE.Vector3(x, y, z).multiplyScalar(scale);
}

function trefoil(t, scale) {
    const x = Math.sin(t) + 2*Math.sin(2*t);
    const y = Math.cos(t) - 2*Math.cos(2*t);
    const z = -Math.sin(3*t);
    return new THREE.Vector3(x, y, z).multiplyScalar(scale);
}

// etc. ... for cinquefoil, torusKnot, quadrupleHelix
function cinquefoil(t, scale) {
    const R = 2, r = 1;
    const x = (R + r*Math.cos(5*t)) * Math.cos(2*t);
    const y = (R + r*Math.cos(5*t)) * Math.sin(2*t);
    const z = r*Math.sin(5*t);
    return new THREE.Vector3(x, y, z).multiplyScalar(scale);
}

function torusKnot(t, p, q, scale) {
    const R = 2, r = 1;
    const x = (R + r*Math.cos(q*t)) * Math.cos(p*t);
    const y = (R + r*Math.cos(q*t)) * Math.sin(p*t);
    const z = r*Math.sin(q*t);
    return new THREE.Vector3(x, y, z).multiplyScalar(scale);
}

function quadrupleHelix(t, scale) {
    const R = 2, r = 1;
    const x = (R + r*Math.cos(4*t)) * Math.cos(t);
    const y = (R + r*Math.cos(4*t)) * Math.sin(t);
    const z = r*Math.sin(4*t);
    return new THREE.Vector3(x, y, z).multiplyScalar(scale);
}
function getKnotPosition(knotType, t, knotScale) {
    t= 2*t;
    switch (knotType) {
        case 'basicTwist':
            return basicTwist(t, knotScale);
        case 'doubleHelix':
            return doubleHelix(t, knotScale);
        case 'trefoil':
            return trefoil(t, knotScale);
        case 'cinquefoil':
            return cinquefoil(t, knotScale);
        case...