Files
Learn_System/plans/STEREO_3D_IMPROVEMENT.md
T
Maxim Dolgolyov 3801d0cfa8 feat(stereo3d): Фаза 6 — построение сечения «по следам» (метод следов)
Путь (b): надёжный полигон (есть) + аналитический след и вспом. точки.
- _traceLine(): след = π ∩ плоскость основания y=0 (проверено численно)
- _auxiliaryPoints(): продление сторон сечения до следа (dist=0 на следе)
- _hasBase()/_sameFace(): топология тел с основанием
- настоящий пошаговый _drawSection3PStep: 6 подписанных шагов, финал скрыт
  до шага 5 (showFull); подписи в #sect3p-hint через _stepCaption
- scope: куб, параллелепипед, призма, пирамида, усеч. пирамида, тетраэдр
- bump stereo.js?v=9

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 11:49:16 +03:00

68 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# План улучшения симуляции «Стереометрия 3D»
Файлы: `frontend/js/labs/stereo.js` (StereoSim, ~3720 строк), панель в `frontend/lab.html` (`#sim-stereo`), роутинг `frontend/js/labs/lab-init.js`.
Статус-легенда: [ ] не начато · [~] в работе · [x] готово
---
## Фаза 0 — Производительность и гигиена (быстрый эффект, низкий риск) — ГОТОВО
- [x] 0.1 Останавливать loop при переключении симуляций.
Добавлен `_pauseAllSims()` в `lab-init.js`, вызывается в начале `openSim()` — все rAF-симы (включая стерео) паузятся при переходе. Раньше предыдущий сим рендерил невидимый canvas вечно.
- [x] 0.2 Pointer/touch-слушатели перенесены с `window` на `renderer.domElement`, с pointer-capture для драга вне холста; все слушатели трекаются и снимаются в `dispose()`. Canvas получил `tabindex`/`role`/`aria-label`.
- [x] 0.3 Render-on-demand: `_invalidate()` + dirty-флаг `_needsRender`; loop засыпает (`_rafId=null`), просыпается по взаимодействию/изменению сцены. Хук в `_clearGroup()` покрывает все rebuild/clear; защита от двойного rAF.
- [x] 0.4 Обработка `webglcontextlost`/`webglcontextrestored` (пересборка сцены); метод `dispose()` (renderer, ResizeObserver, слушатели, текстуры). Бонус: `_clearGroup` стал рекурсивным — устранена утечка вложенных групп (измерения и т.п.).
## Фаза 1 — Камера и навигация — ГОТОВО
- [x] 1.1 Инерция орбиты (плавное затухание после отпускания) + панорамирование: правая/средняя кнопка или Shift+ЛКМ на десктопе, два пальца на тач. Орбита вокруг сдвигаемого таргета (`_panOffset`). _(zoom-to-cursor отложен — pan покрывает рецентрирование; перенесён в бэклог Фазы 2.)_
- [x] 1.2 Overlay-тулбар в правом верхнем углу viewport: сброс вида + пресеты ракурса (Изо / Спереди / Сбоку / Сверху). Пресет «держит» вид (спин выключается).
- [x] 1.3 Тумблер авто-вращения (с реальным засыпанием loop при выключении), fullscreen (по `.graph-canvas-outer`), снимок PNG (`preserveDrawingBuffer` + синхронный рендер → download). a11y: `aria-pressed`/`aria-label` на кнопках.
## Фаза 2 — Геометрия и пикинг — ГОТОВО
- [x] 2.1 Аналитические сечения кривых тел `_sliceCurvedByNormal()`: шар → точная окружность (плоскость∩сфера), цилиндр/конус/усеч.конус → гладкая кривая через точное решение y(θ) для образующей `r(y)=r0+k·y`. Старый пороговый сэмплинг оставлен как fallback (почти вертикальные плоскости). Проверено численно (диапазон y цилиндра и радиус окружности шара совпадают с формулами).
- [x] 2.2 Общий хелпер `_edgePickNDC()` (расстояние точка-отрезок в NDC); `_pickNearestEdge` и `_pickNearestEdgeIdx` переведены с «по середине ребра» на корректный пикинг по всей длине.
- [x] 2.3 HiDPI-метки: `_makeTextSprite` рендерит на canvas с учётом DPR, корректный аспект по ширине текста, тёмная обводка для читаемости, анизотропная фильтрация. Тип сечения для кривых = «окружность»/«эллипс», вершинные маркеры не плодятся (cap ≤12 точек).
Бэклог: zoom-to-cursor (перенесён из 1.1); SDF-шрифт и пул текстур (текущая резкость достаточна).
## Фаза 3 — Педагогика сечений — ГОТОВО (частично, см. бэклог)
- [x] 3.1 Подписи вершин сечения буквами (K, L, M…) в наклонном/произвольном сечении и сечении-по-3-точкам (для настоящих многоугольников ≤12 вершин). Пошаговый режим сечения-по-3-точкам уже был. _(Полное «построение по следам» — в бэклоге, крупная отдельная фича.)_
- [x] 3.2 Точки на произвольной точке грани: `_raycastFace()` — в режиме «точки» клик по грани (не у ребра/вершины) ставит точку на поверхности. Через произвольное сечение (3 кастомные точки) это даёт плоскость через внутренние точки граней.
- [x] 3.3 Live-readout overlay (`#stereo-readout`, низ-слева): тип сечения, площадь S, периметр P, последнее измерение. Обновляется через `info().readout` при любом изменении сечения/измерения.
Бэклог: полное «построение сечения по следам» (продление рёбер, след на грани); readout углов (двугранный/линия-плоскость) — сейчас угол только в 3D-метке.
## Фаза 4 — Визуал — ГОТОВО (см. бэклог)
- [x] 4.1 Свечение вершин (мягкий additive-ореол без текстур, безопасно с `_clearGroup`); рёбра контрастнее (opacity 0.9, `renderOrder` поверх полупрозрачного тела), вершины поверх рёбер. _(Подсветка грани по ховеру отложена — текущий centroid-пикинг граней грубоват для плавного hover.)_
- [x] 4.2 Подписи осей X/Y/Z, цвета совпадают с AxesHelper (X крас., Y зел., Z син.).
Бэклог: подсветка грани по ховеру (нужен точный raycast по логическим граням); градиентный/бумажный фон (учесть захват в скриншоте).
## Фаза 5 — Интеграция и архитектура — ГОТОВО (без дробления файла, по решению пользователя)
- [~] 5.1 Дробление `stereo.js` на модули — **отложено по решению пользователя** (риск регрессий, не видно пользователю). Остаётся в бэклоге.
- [x] 5.2 Deep-link фигуры из учебников без изменения общего hash-роутера: `openSim('stereo:<figure>')` и `/lab?stereofig=<figure>#sim/stereo`. `_openStereo(figureType)` применяет фигуру и подсвечивает кнопку. Допустимые: cube, parallelepiped, prism, pyramid, truncpyramid, tetrahedron, octahedron, icosahedron, dodecahedron, cylinder, cone, trunccone, sphere.
- [x] 5.3 a11y: клавиатурная навигация по сфокусированному canvas — стрелки (орбита), +/− (зум), R/Home (сброс); `tabindex`/`role`/`aria-label` на canvas (Фаза 0), `aria-pressed`/`aria-label` на кнопках вида (Фаза 1), `aria-live` на readout.
Бэклог Фазы 5: модульное дробление файла; deep-link конкретного сечения/инструмента (не только фигуры).
## Фаза 6 — Построение сечения «по следам» (метод следов) — ГОТОВО (путь b)
Реализован гибрид: финальный полигон считается надёжно (Фаза 2), а след и вспомогательные точки выводятся аналитически — без риска несходимости конструктивного алгоритма. Scope: тела с основанием (куб, параллелепипед, призма, пирамида, усеч. пирамида, тетраэдр).
- [x] 6.1 `_hasBase()` + `_traceLine(data)` — след = π ∩ плоскость основания (y=0): `n.x·x + n.z·z + D = 0`; возвращает `{p0, dir}` или null (плоскость параллельна основанию). Проверено численно (точка следа на плоскости, остаток 0).
- [x] 6.2 `_auxiliaryPoints(polygon)` — продление боковых сторон сечения до y=0; точка пересечения лежит ровно на следе (численно dist=0). Сортировка по «дальности продления», берём 2 ближайшие.
- [x] 6.3 Настоящий пошаговый `_drawSection3PStep` (заменил бутафорию): 6 подписанных шагов — 3 точки → стороны в одной грани (`_sameFace`) → след → вспом. точки T₁,T₂ → вершины+замыкание → итог. В step-режиме финальное сечение скрыто до шага 5 (`showFull`), пиковые линии тоже скрыты. Подписи шагов в `#sect3p-hint` через `_stepCaption`. Для тел без основания — деградация к простым шагам с пояснением.
- bump stereo.js?v=9
Бэклог Фазы 6: «честный» конструктивный алгоритм (шаг по граням через след для поиска каждой новой вершины); анимация перехода между шагами; ветка для плоскости, параллельной основанию.
---
История: создан 2026-05-30. Фаза 6 добавлена 2026-05-30.