-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhopf31.php
93 lines (79 loc) · 3.45 KB
/
hopf31.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hopf Fibration of S³</title>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script>
<script>
// Escena, càmera i renderitzador
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Controls d'òrbita per moure la càmera
const controls = new THREE.OrbitControls(camera, renderer.domElement);
// Fons negre per a la visualització
scene.background = new THREE.Color(0x000000);
// Funció per generar una línia fina tridimensional per a cada fibra
function createFiber(color, points) {
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = new THREE.LineBasicMaterial({ color: color, linewidth: 1 });
const line = new THREE.Line(geometry, material);
return line;
}
// Funció de projecció estereogràfica per a S^3
function stereographicProjection(x1, x2, x3, x4) {
const denom = 1 - x4; // Factor de projecció
return new THREE.Vector3(x1 / denom, x2 / denom, x3 / denom);
}
// Genera fibres entrellaçades projectades des de la 3-esfera (S^3)
function generateHopfFibration(numFibres) {
const colors = [0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff, 0x00ffff, 0xffffff, 0xff8000]; // 8 colors diferents
for (let i = 0; i < numFibres; i++) {
const theta = (i / numFibres) * Math.PI * 2; // Distribueix les fibres de manera uniforme al voltant de la 3-esfera
const points = [];
for (let t = 0; t <= Math.PI * 2; t += 0.02) { // Pas més petit per a més punts en cada fibra
// Parametritza un cercle a la 3-esfera
const x1 = Math.cos(t);
const x2 = Math.sin(t);
const x3 = Math.sin(theta) * Math.cos(t);
const x4 = Math.cos(theta);
// Projecció estereogràfica a 3D
const denom = 1 - x4 + 1e-6; // S'afegeix un petit valor a x4 per evitar que el denominador sigui zero
const projectedPoint = new THREE.Vector3(x1 / denom, x2 / denom, x3 / denom);
points.push(projectedPoint);
}
// Crea una fibra com una línia que connecta els punts projectats
const fiber = createFiber(colors[i % colors.length], points);
scene.add(fiber);
}
}
// Crea la fibració de Hopf amb 200 fibres per donar un aspecte toroidal
generateHopfFibration(200);
// Posició inicial de la càmera
camera.position.z = 8;
// Funció d'animació
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
// Ajusta la mida del canvas si la finestra canvia de mida
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
</script>
</body>
</html>