diff --git a/docs/specs/089-isometric-view.md b/docs/specs/089-isometric-view.md deleted file mode 100644 index 8169fdd6..00000000 --- a/docs/specs/089-isometric-view.md +++ /dev/null @@ -1,301 +0,0 @@ -# #89 — Опциональный объёмный 2.5D/изометрический вид плана - -**Статус:** исследование завершено; черновик продуктового и технического решения -**Дата:** 2026-08-11 -**Приоритет:** P1 — высокая продуктовая ценность, высокая стоимость реализации -**Область:** режим просмотра и киоск; редакторы в первую версию не входят -**Исходные референсы:** предоставленные владельцем проекта `isometric-plan-demo.zip` и изображение `photo_2026-08-11_18-30-38.jpg` - -## 1. Краткое решение - -Добавить в Houseplan опциональный **«Объёмный вид»** — стилизованное 2.5D-представление существующего плана с приподнятыми стенами, видимыми боковыми гранями, мягкой тенью и изометрической камерой. - -Это не отдельный редактор и не новая модель плана. Комнаты, стены, проёмы, перегородки, колонны, устройства, Glow и все состояния продолжают использовать текущие данные. Меняется только способ их проекции и визуализации. - -Рекомендуемая первая пользовательская версия: - -- переключаемый плоский/объёмный вид; -- только режим просмотра и киоск; -- фиксированный проверенный ракурс без свободного вращения камеры; -- редакторы всегда открываются в обычном плоском виде; -- без WebGL/Three.js и без 32 копий всего SVG; -- стены строятся из канонической геометрии Houseplan, проёмы действительно вырезаются из объёма; -- Glow, солнечные лучи, заливки и hover остаются функционально теми же эффектами на плоскости пола; -- диалоги и tooltips остаются обычным экранным UI и не наклоняются вместе с планом. - -## 2. Пользовательская ценность - -Ценность оценивается как **очень высокая**: - -- план превращается из утилитарной схемы в визуально сильный центр dashboard; -- различия стен, комнат, проёмов и внешних зон считываются быстрее; -- скриншоты и демонстрации продукта становятся существенно убедительнее; -- Houseplan получает заметное визуальное отличие от обычных floorplan-карточек; -- существующая модель данных уже содержит большую часть необходимой геометрии — пользователь не строит второй план. - -При этом объёмный вид не должен становиться обязательным. Плоский вид точнее для редактирования, плотных планов и слабых устройств и остаётся полностью поддерживаемым. - -## 3. Что показало исследование демо - -Переданный demo — удачный визуальный proof of concept, но не готовая архитектура для Houseplan. - -Он использует: - -- один SVG с вручную заданной геометрией; -- CSS `perspective`, `rotateX`, `rotateZ` и `preserve-3d`; -- 32 копии одного контура стен, поднятые последовательными `translateZ`, чтобы имитировать толщину по высоте; -- отдельный верхний контур стен; -- статические подписи и устройства внутри наклонённой плоскости; -- drag для вращения и wheel для масштаба. - -Для маленькой статической сцены это работает и хорошо показывает продуктовый эффект. Прямой перенос подхода в Houseplan не подходит, потому что: - -1. Геометрия Houseplan динамическая: смешанная толщина, T/X-стыки, перегородки, круглые и квадратные колонны, двери, окна и ворота. -2. В карточке есть тяжёлые динамические слои: Glow, spill через проёмы, солнечные лучи, hover, vacuum overlays и HTML-маркеры. -3. 20–32 копии сложных wall paths заметно увеличат DOM, raster/compositing cost и вероятность швов. -4. CSS 3D-контекст разрушается или уплощается рядом свойств, уже используемых карточкой: `filter`, opacity на предках, `clip-path`, mask и часть blend/compositing-сценариев. -5. Сейчас day/night использует `filter: brightness(...)` на `.zoomwrap`, а Glow — `mix-blend-mode: screen`; слепое помещение существующего дерева в CSS 3D создаёт высокий риск регрессий. -6. Координаты устройств и room labels сейчас считаются для плоского `viewBox` и выводятся HTML-слоем. Их нужно проецировать тем же каноническим преобразованием, иначе они разойдутся с планом. - -Вывод: demo подтверждает **реализуемость и ценность визуального направления**, но production-рендерер нужно строить на геометрии Houseplan. - -## 4. Рекомендуемая архитектура - -### 4.1. Не полноценный 3D, а детерминированная 2.5D-проекция - -Для первой версии рекомендуется обычный SVG с явной 2D-проекцией, а не CSS-стопка и не WebGL: - -- floor/decor/room/glow-слои помещаются в SVG-группу с одной аффинной изометрической матрицей; -- верх стены — каноническое объединённое тело стены, спроецированное и сдвинутое на визуальную высоту; -- боковые грани — четырёхугольники, построенные из граничных рёбер wall body и вектора высоты; -- видимые боковые грани фильтруются по направлению камеры и сортируются по глубине; -- HTML-маркеры получают экранные координаты через ту же чистую функцию проекции; -- tooltips, dialogs и системные controls остаются вне проецируемой сцены. - -Это позволяет сохранить обычный SVG compositor, mask/blend-поведение Glow и предсказуемую деградацию, а число элементов растёт по числу реальных граней, а не умножается на 20–32 слоя. - -### 4.2. Канонические источники геометрии - -Нельзя создавать вторую независимую модель стен. Рендерер обязан использовать: - -- `wallBodiesGeometry()` / объединённые wall bodies из `src/wall-thickness.ts`; -- текущие opening cuts/tunnel geometry; -- существующую модель перегородок и колонн; -- текущие room polygons и decor geometry; -- текущий канонический light resolver и описанную в `docs/LIGHT.md` семантику. - -Возможные новые модули: - -- `src/render/isometric-projection.ts` — чистая математика проекции и обратного hit mapping; -- `src/render/isometric-walls.ts` — top/side faces и depth ordering; -- `src/render/isometric-scene.ts` — композиция слоёв; -- детерминированные fixtures/golden matrix отдельно от основной карточки. - -Кэш геометрии строится по содержательному fingerprint геометрии, а не только по `_cfgEpoch`. - -### 4.3. Высота стен - -В модели сейчас нет полноценной высоты помещений/стен. В первой версии высота — **визуальный параметр представления**, а не архитектурный размер: - -- единое безопасное значение по умолчанию; -- один общий параметр для карточки/пространства, если настройка вообще выводится пользователю; -- одинаковая высота у обычных стен, перегородок и колонн; -- виртуальные стены остаются линиями пола и не получают объём. - -Не следует выводить высоту в сантиметрах: это создаст ложное обещание настоящей 3D-модели. - -## 5. UX первой версии - -### 5.1. Переключение - -- В режиме просмотра появляется компактная кнопка с `mdi:cube-outline` и accessible name «Объёмный вид». -- Повторное нажатие возвращает «Плоский вид». -- Переключение не изменяет геометрию и не создаёт запись в command stack. -- Предпочтение вида хранится отдельно от модели плана; оно не должно создавать конфликтов совместного редактирования. -- В киоске используется настроенный вид по умолчанию; скрытая панель не должна делать возврат в плоский вид невозможным из настроек. -- Вход в любой редактор временно показывает плоский вид. После выхода восстанавливается предыдущий режим просмотра. - -Плоский вид остаётся значением по умолчанию для существующих установок и fallback при ошибке/неподдерживаемом окружении. - -### 5.2. Камера и навигация - -MVP использует один тщательно подобранный ракурс либо 2–3 пресета. Свободное вращение и изменение tilt не входят в первую версию. - -Причины: - -- свободное вращение конфликтует с pan, pinch zoom, long press и кликами устройств; -- оно требует динамической сортировки граней на каждом кадре; -- маркетинговый эффект достигается фиксированным хорошим ракурсом; -- фиксированный ракурс детерминирован для golden image и поддержки. - -Обычный zoom/pan сохраняется. Изменение масштаба должно быть совместимо с #82 и не менять фокус плана скачком при переключении вида. - -### 5.3. Устройства и подписи - -Для первой версии рекомендуется: - -- позиция marker/room label проецируется вместе с планом; -- сама интерактивная карточка устройства остаётся достаточно читаемой и получает мягкую объёмную тень; -- tooltip/dialog всегда экранные и не наклоняются; -- touch target не уменьшается из-за визуального наклона; -- tab order и accessible name совпадают с плоским режимом. - -Полностью «лежащие на полу» подписи красивее, но хуже читаются. Допустим компромисс: лёгкое согласование с ракурсом для подложки и screen-facing содержимое. Точный вариант выбирается по прототипу и a11y-проверке. - -## 6. Поведение слоёв - -| Слой/объект | Поведение в объёмном виде | -|---|---| -| Пол/заливка комнаты | Лежит на нижней плоскости, текущая семантика цвета сохраняется | -| Room hover | Затемняет заливку и подсвечивает внутренние границы без вспышки Glow | -| Физические стены | Верхняя поверхность + видимые боковые грани | -| Перегородки | Как физические стены; комнату автоматически не делят | -| Квадратные/круглые колонны | Экструдируются из своей текущей геометрии | -| Виртуальные стены | Пунктир на плоскости пола, без высоты | -| Дверь | Проём реально разрывает стену; символ состояния сохраняется. Вертикальная створка — polish-этап | -| Окно | Разрыв объёма с отдельным стилизованным оконным элементом; без моделирования реальной высоты подоконника | -| Ворота | Разрыв объёма; две наружные створки сохраняются | -| Opening tunnel fill | Цвет комнаты на полу, без швов; семантика Glow не меняется | -| Glow и spill | На плоскости пола, стеновые барьеры и проёмы работают по `docs/LIGHT.md` | -| Солнечные лучи | На плоскости пола, геометрия и настройки остаются текущими | -| Decor/backdrop | Лежит на floor plane; не создаёт объём автоматически | -| Vacuum path/outline | На floor plane; robot marker остаётся интерактивным | -| Device markers | Проецированная позиция, безопасный z-order и неизменная логика состояний | -| Tooltips/dialogs | Экранный overlay поверх сцены | -| `show_borders: false` | Невидимые стены остаются невидимыми, но продолжают влиять на площадь и свет | - -## 7. Обязательные edge cases - -Реализация и fixtures должны покрыть: - -1. Выпуклые и вогнутые комнаты, отверстия и несколько несвязанных контуров. -2. Смешанную толщину стен, короткие сегменты, T/X-стыки и сложные объединения. -3. Проём у угла, несколько соседних проёмов, дверь/окно/ворота шире толщины стены. -4. Перегородку, примыкающую к стене без визуального шва. -5. Квадратную повёрнутую и круглую колонну. -6. Виртуальную стену между двумя толстыми стенами. -7. Комнату без физических стен и старую конфигурацию без thickness. -8. Glow с несколькими источниками, spill через открытые проёмы и hover комнаты. -9. Day/night brightness, непрозрачные/полупрозрачные заливки и additive blending. -10. Большую подложку, decor, текст, пунктирные линии и мебель. -11. Скрытые/удалённые/недоступные устройства и все режимы device presentation. -12. Touch: pinch не вызывает click, long press не оставляет phantom pan. -13. Возврат на вкладку: сцена не мигает и не пересобирается из пустого состояния. -14. Очень широкий/высокий план, detached terrace/porch и несколько пространств. -15. Светлая/тёмная тема, kiosk, reduced motion и high zoom. - -## 8. Производительность и технические ограничения - -- Не клонировать весь SVG или wall body десятки раз. -- Число side faces должно быть O(числу граничных рёбер), а не O(рёбра × визуальная высота). -- Pan/zoom не пересчитывает модельную геометрию; меняется только transform/viewBox. -- Геометрия стен пересчитывается только при изменении содержательного fingerprint. -- Цель на детерминированном большом fixture: плавный pan/zoom на desktop и не более 20% регрессии frame time относительно плоского вида. -- Переключение вида не должно показывать пустой/чёрный промежуточный кадр. -- При нехватке возможностей или исключении renderer карточка безопасно возвращается в плоский вид и сообщает диагностируемую причину в dev log. -- Новая тяжёлая runtime-зависимость и WebGL не допускаются без отдельного архитектурного решения. - -## 9. Доступность - -- «Объёмный вид» — визуальная альтернатива, не отдельный набор функций. -- Все устройства, комнаты и действия доступны с клавиатуры так же, как в плоском виде. -- Focus ring виден и не обрезается стеной/контейнером. -- Screen reader получает те же имена и состояния. -- `prefers-reduced-motion` отключает переход между проекциями, но не сам режим. -- Минимальные touch targets сохраняются в экранных координатах. -- Плоский вид остаётся fallback для пользователей, которым перспектива мешает чтению. - -## 10. План реализации - -### Этап 0 — технический spike, 2–4 рабочих дня - -- детерминированный fixture со стенами, mixed thickness, проёмами, колонной, Glow и устройствами; -- два прототипа: CSS wall slices и явные side faces; -- замеры Chrome/Edge, Firefox и Safari/WebKit; -- проверка Glow/mask/blend, day/night и HTML overlays; -- ADR с окончательным выбором renderer. - -Spike не включается пользователям и не считается завершением issue. - -### Этап 1 — ship-ready фиксированный объёмный вид, 8–15 рабочих дней - -- чистая математика проекции; -- floor plane, wall top и side faces; -- проёмы, перегородки и колонны; -- проекция markers/labels и pointer mapping; -- переключение view/editor/kiosk; -- кэш, fallback, unit/integration/golden/performance gates; -- RU/EN документация и changelog. - -### Этап 2 — визуальный polish уровня референса, ещё 8–15 рабочих дней - -- улучшенные двери, окна и ворота; -- мягкие тени/ambient depth без дорогого dynamic lighting; -- аккуратные floor/platform edges; -- доводка markers/labels и occlusion; -- дополнительные пресеты камеры и качества. - -### Отдельный будущий этап — свободная камера, ещё 5–10+ рабочих дней - -Свободное вращение/tilt, gesture arbitration и динамический depth sort не входят в базовый scope. Их ценность ниже, а риск заметно выше. - -## 11. Оценка сложности - -| Вариант | Срок | Риск | Оценка | -|---|---:|---:|---| -| Демонстрационный CSS stack на одном fixture | 2–4 дня | Средний | Хорош для spike, не для релиза | -| Production MVP с фиксированным ракурсом | 8–15 дней | Высокий | Рекомендуемый первый релиз | -| Визуально отполированный вариант уровня референса | 16–30 дней суммарно | Высокий | Реалистичная конечная цель | -| Свободная камера поверх polished renderer | +5–10 дней | Высокий | Позже, только по подтверждённой ценности | -| Настоящий WebGL/Three.js 3D renderer | 1–2+ месяца | Очень высокий | Не рекомендуется для этой цели | - -Общая оценка: **L/XL, высокий архитектурный и визуальный риск, но очень высокая продуктовая отдача**. Сам эффект дешёв в статичном demo; дорого стоит сохранение всей существующей интерактивности и световой модели без регрессий. - -## 12. Риски и меры - -| Риск | Вероятность/влияние | Мера | -|---|---|---| -| Glow/blend/filter ломает CSS 3D | Высокие | Обычная SVG 2.5D-проекция вместо вложенного `preserve-3d` | -| Неверные T/X-стыки и проёмы | Высокие | Только канонические union bodies + geometry fixtures | -| Маркеры расходятся с планом | Высокие | Одна pure projection для SVG и HTML overlays | -| Падение FPS на больших планах | Средние/высокие | Side faces вместо десятков slices, кэш и perf gate | -| Нечитаемые подписи | Средние | Screen-facing/гибридный marker prototype и a11y review | -| Touch misclick при навигации | Средние/высокие | В MVP нет свободной камеры; существующие pan/pinch правила сохраняются | -| Режим превращается в второй renderer со своей логикой | Высокие | Общие resolvers/geometry; новый слой отвечает только за projection/presentation | -| Референс обещает больше, чем модель умеет | Средние | Называть «Объёмный вид», не «полноценный 3D»; явно ограничить высоту и окна | - -## 13. Не входит в первую версию - -- редактирование геометрии в перспективе; -- пользовательская высота каждой стены/комнаты; -- 3D-мебель и импорт моделей; -- настоящая физика света и динамические тени; -- свободный orbit camera; -- WebGL/Three.js; -- автоматическое превращение растровой подложки в 3D; -- изменение формата существующих room/wall/opening данных. - -## 14. Acceptance criteria пользовательской версии - -1. Пользователь может переключить текущий план между плоским и объёмным видом без изменения данных. -2. Существующие планы открываются плоскими и не требуют миграции. -3. В объёмном виде физические стены, перегородки и колонны имеют непрерывные top/side faces; виртуальные стены не экструдируются. -4. Двери, окна и ворота образуют реальные разрывы объёма, без тонких швов и торцов внутри проёма. -5. Glow, spill, sunlight, room fill и hover сохраняют текущую семантику и не мигают. -6. Device markers, room controls, tooltips и dialogs остаются кликабельными, читаемыми и доступными с клавиатуры. -7. Открытие редактора показывает плоский вид; выход восстанавливает предыдущий просмотр. -8. Zoom/pan/fit работают без скачка, phantom click и изменения сохранённой геометрии. -9. При ошибке объёмного renderer доступен безопасный плоский fallback. -10. Пройдены unit tests проекции/side faces, smoke interactions, golden matrix и performance comparison на детерминированных fixtures. -11. Обновлены `README.md`, `docs/USER-GUIDE.ru.md`, RU/EN changelog и release screenshots. - -## 15. Рекомендуемая поставка - -Фичу лучше вести отдельным релизным циклом: - -1. внутренняя beta/spike без публичного toggle; -2. beta с фиксированным объёмным видом и полным fallback; -3. beta с doors/windows/markers polish и performance fixes; -4. stable только после golden review на реальных больших планах и проверки мобильного просмотра. - -Главный критерий успеха — не максимальная «трёхмерность», а визуально сильный вид без потери надёжности Houseplan как интерактивной HA-карточки.