<!DOCTYPE html>



 <html lang="ru">

<head>

    <meta charset="UTF-8">

    <title>3D Нейтрон — ПЭММ</title>

    <style>

        html, body { margin: 0; padding: 0; background-color: #11141a; overflow: hidden; width: 100%; height: 100%; }

    </style>

</head>

<body>


<div class="pemm-container-gold" style="max-width: 300px; margin: 20px auto; font-family: 'Roboto', sans-serif; background: #11141a; border: 1px solid #2c3440; border-radius: 8px; padding: 15px; color: #fff; box-shadow: 0 4px 15px rgba(0,0,0,0.5);">

 <h3 style="margin-top: 0; text-align: center; color: #ffd700; font-size: 18px;">Строение атома гелия-4:</h3>

 

 <!-- Вставили ваше прецизионное научное описание -->

 <p style="font-size: 12px; color: #a0aec0; text-align: justify; margin-bottom: 10px; line-height: 1.4;">

  вершины одного тетраэдра — протоны, вершины второго — электроны. 

   <b>Вращением фигуры мышкой можно превратить её в куб</b> (мезонная шуба протона).

 </p>


 <div style="position: relative; width: 300px; height: 550px; background: #0b0d11; border-radius: 6px; overflow: hidden;">

<canvas id="pemmCanvas" style="display: block; width: 100%; height: 100%; cursor: move;"></canvas>


</div>

 </div>

<script>

(function() {

 const canvas = document.getElementById('pemmCanvas');

 const ctx = canvas.getContext('2d');



 function resize() {

 canvas.width = window.innerWidth;

 canvas.height = window.innerHeight;

 }

 window.addEventListener('resize', resize);

 resize();


 // Исходная метрика из вашей страницы протона

 const fm_scale = 280;

 let r_muon = 0.25 * fm_scale; // 35

 let r_ball_visual = 45;       // Радиус шаров строго 45 из протона

 let r_positron = 0.833 * fm_scale; 

 let dist_muon_center = (2/3) * r_positron; 

 let scale = dist_muon_center / Math.sqrt(3);


 let angleX = 0.4;

 let angleY = 0.6;

 let isDragging = false;

 let previousMousePosition = { x: 0, y: 0 };


 // 8 вершин куба с полярной протонно-электронной расцветкой

 const vertices = [

 {x: -1, y: -1, z: -1, id: '1', col: '#0055ff'}, 

 {x: -1, y:  1, z: -1, id: '2', col: '#d90429'}, 

 {x: -1, y:  1, z:  1, id: '3', col: '#0055ff'}, 

 {x:  1, y:  1, z: -1, id: '4', col: '#0055ff'}, 

 {x:  1, y:  1, z:  1, id: '5', col: '#d90429'}, 

 {x:  1, y: -1, z: -1, id: '6', col: '#d90429'}, 

 {x:  1, y: -1, z:  1, id: '7', col: '#0055ff'}, 

 {x: -1, y: -1, z:  1, id: '8', col: '#d90429'}  

 ];


 // Геометрическая сетка звездчатого октаэдра (Полярное разделение)

 const stefanoLines = [

 // Тетраэдр ЭЛЕКТРОНОВ (Синие связи)

 {a: 0, b: 2, col: 'rgba(0, 85, 255, 0.4)'}, {a: 0, b: 3, col: 'rgba(0, 85, 255, 0.4)'}, {a: 0, b: 6, col: 'rgba(0, 85, 255, 0.4)'},

 {a: 2, b: 3, col: 'rgba(0, 85, 255, 0.4)'}, {a: 2, b: 6, col: 'rgba(0, 85, 255, 0.4)'}, {a: 3, b: 6, col: 'rgba(0, 85, 255, 0.4)'},

 // Тетраэдр ПРОТОНОВ (Красные связи)

 {a: 1, b: 4, col: 'rgba(217, 4, 41, 0.4)'}, {a: 1, b: 5, col: 'rgba(217, 4, 41, 0.4)'}, {a: 1, b: 7, col: 'rgba(217, 4, 41, 0.4)'},

 {a: 4, b: 5, col: 'rgba(217, 4, 41, 0.4)'}, {a: 4, b: 7, col: 'rgba(217, 4, 41, 0.4)'}, {a: 5, b: 7, col: 'rgba(217, 4, 41, 0.4)'}

 ];


 const beta = Math.PI / 4; 

 const alpha = Math.atan(Math.sqrt(2)); 

 

 // Проекция базовых точек куба на вертикальную полярную соосность

 const baseCubePoints = vertices.map(v => {

 let x1 = v.x * Math.cos(beta) - v.z * Math.sin(beta);

 let z1 = v.x * Math.sin(beta) + v.z * Math.cos(beta);

 let y2 = v.y * Math.cos(alpha) - z1 * Math.sin(alpha);

 let z2 = v.y * Math.sin(alpha) + z1 * Math.cos(alpha);

 return { x: x1, y: y2, z: z2, col: v.col, label: v.id };

 });


 canvas.addEventListener('mousedown', e => { 

 isDragging = true; 

 previousMousePosition = { x: e.clientX, y: e.clientY }; 

 });


 window.addEventListener('mouseup', () => isDragging = false);


 canvas.addEventListener('mousemove', e => {

 if (isDragging) {

 const deltaX = e.clientX - previousMousePosition.x;

 const deltaY = e.clientY - previousMousePosition.y;

 angleY += deltaX * 0.01;

 angleX += deltaY * 0.01;

 previousMousePosition = { x: e.clientX, y: e.clientY };

 }

 });


 function project(vertex, angleX, angleY, cx, cy) {

 let x1 = vertex.x * Math.cos(angleY) - vertex.z * Math.sin(angleY);

 let z1 = vertex.x * Math.sin(angleY) + vertex.z * Math.cos(angleY);

 let y2 = vertex.y * Math.cos(angleX) - z1 * Math.sin(angleX);

 let z2 = vertex.y * Math.sin(angleX) + z1 * Math.cos(angleX);

 return { x: cx + x1 * scale, y: cy + y2 * scale, z: z2, id: vertex.label, col: vertex.col };

 }


 function draw() {

 ctx.clearRect(0, 0, canvas.width, canvas.height);

 const cx = canvas.width / 2;

 const cy = canvas.height / 2;

 

 const projected = baseCubePoints.map(v => project(v, angleX, angleY, cx, cy));


 // 1. ОТРИСОВКА РЁБЕР ЗВЕЗДЧАТОГО КАРКАСА ( Stella Octangula )

 ctx.lineWidth = 1.2;

 stefanoLines.forEach(l => {

 ctx.beginPath();

 ctx.moveTo(projected[l.a].x, projected[l.a].y);

 ctx.lineTo(projected[l.b].x, projected[l.b].y);

 ctx.strokeStyle = l.col;

 ctx.stroke();

 });


 // Направляющая полярная вертикальная ось через пустой центр

 if (projected && projected) {

 ctx.beginPath();

 ctx.moveTo(projected.x, projected.y); 

 ctx.lineTo(projected.x, projected.y); 

 ctx.strokeStyle = 'rgba(255, 255, 255, 0.18)';

 ctx.lineWidth = 1;

 ctx.stroke();

 }


 // 2. СОРТИРОВКА Z-БУФЕРА ДЛЯ НЕПРОЗРАЧНОГО НАЛОЖЕНИЯ

 let sortedMuons = projected.map((p, i) => ({p: p, i: i}));

 sortedMuons.sort((a, b) => b.p.z - a.p.z);


 // 3. ВЫВОД СИЛОВЫХ ВЕКТОРОВ И СФЕР КАРКАСА

 sortedMuons.forEach(item => {

 let p = item.p;

 

 // ИЗМЕНЕНО: Непрозрачность цвета векторов поднята до 100% (1.0), толщина увеличена до 2.5

 ctx.beginPath();

 ctx.moveTo(cx, cy); 

 ctx.lineTo(cx + (p.x - cx) * 2.8, cy + (p.y - cy) * 2.8); 

 ctx.strokeStyle = p.col === '#0055ff' ? 'rgba(0, 85, 255, 1.0)' : 'rgba(217, 4, 41, 1.0)';

 ctx.lineWidth = 2.5;

 ctx.stroke();

 

 // Отрисовка плотных сфер из протона (Радиус 45, диаметр 90)

 ctx.beginPath();

 ctx.arc(p.x, p.y, r_ball_visual, 0, 2 * Math.PI);

 

 // Оригинальный расчет блика радиального градиента из протона

 let mG = ctx.createRadialGradient(p.x - r_muon * 0.2, p.y - r_muon * 0.2, r_muon * 0.1, p.x, p.y, r_ball_visual);

 if (p.col === '#0055ff') {

 mG.addColorStop(0, '#66fcf1'); // Электрон блик

 mG.addColorStop(0.5, '#0055ff'); 

 mG.addColorStop(1, '#001155');

 } else {

 mG.addColorStop(0, '#ff8787'); // Протон блик

 mG.addColorStop(0.5, '#d90429');  

 mG.addColorStop(1, '#5c0f0f');

 }

 ctx.fillStyle = mG;

 ctx.fill();

 ctx.strokeStyle = 'rgba(255,255,255,0.25)';

 ctx.lineWidth = 1;

 ctx.stroke();

 

 // Номера оригинальных векторов (1-8)

 ctx.fillStyle = '#ffffff';

 ctx.font = 'bold 10px sans-serif';

 ctx.textAlign = 'center';

 ctx.fillText(p.id, p.x, p.y + 3.5);

 });


 // Плавное автоматическое вращение вокруг полярной оси Y

 if (!isDragging) { angleY += 0.002; }

 requestAnimationFrame(draw);

 }


 canvas.width = window.innerWidth;

 canvas.height = window.innerHeight;

 draw();

})();

</script>

</body>

</html>