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">×</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...