b46c761373
- подписи осей X/Y/Z цветами AxesHelper - мягкое additive-свечение вершин (без текстур), вершины поверх рёбер - рёбра контрастнее (opacity 0.9, renderOrder над полупрозрачным телом) - bump stereo.js?v=7 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
55 lines
7.3 KiB
Markdown
55 lines
7.3 KiB
Markdown
# План улучшения симуляции «Стереометрия 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` на модули (builders / sections / tools / ui), вынести константы и цвета.
|
||
- [ ] 5.2 Связать симуляцию с учебниками 10–11 (открывать тело/сечение из §-канвы и задач).
|
||
- [ ] 5.3 Доступность: клавиатура, `aria`, фокус.
|
||
|
||
---
|
||
|
||
История: создан 2026-05-30.
|