Skip to content

RU codex docs viewport api

rkfsociety edited this page Oct 21, 2026 · 1 revision

Общая сцена и Viewport API v1

Маршруты и снимки

GET /api/v1/projects/{id}/viewport и GET /api/v1/agent/projects/{id}/viewport возвращают идентичные JSON-сцены. Core читает атомарно сохранённый снимок проекта, поэтому каждый ответ соответствует одной зафиксированной ревизии. Для наблюдения не требуется блокировка на изменение; project.json, история команд и владение блокировкой не меняются.

Read-only-маршруты читают последний атомарно сохранённый снимок, не ожидая освобождения блокировки агента, чтобы окно показывало результат последней зафиксированной операции, пока выполняется следующая команда. Перед загрузкой и валидацией документа Core проверяет токен файла проекта по его метаданным; если токен не поменялся, повторно используется кешированная сцена. При отсутствии сцены результаты проверки геометрии привязываются к ревизии документа, которая меняется атомарно вместе с принятой правкой. Так для проверки кеша не приходится сериализовать и хешировать большие сетки скана. Правка документа инвалидирует сцену. Вызывающие стороны получают копии ответа, поэтому не могут изменить кеш. Для отсутствующего проекта используется существующий контракт 404, некорректная геометрия возвращает 400. Сцена производная и никогда не записывается в проект; миграция проекта/документа не требуется.

Соответствующие маршруты GET /api/v1/projects/{id}/viewport.png и GET /api/v1/agent/projects/{id}/viewport.png возвращают точный image/png кадр главного canvas модели в браузере, если доступен актуальный кадр. В нём совпадают камера, режим каркаса, ось вращения, мировые оси XYZ через начало координат с меткой 0, 0, 0, координатный виджет и сетка.

Браузер публикует кадры маршрутом POST /api/v1/agent/projects/{id}/viewport/snapshot, помечая их ревизией документа. Это read-only-обновление наблюдения; блокировка не нужна, кадры хранятся только в памяти процесса. По мере рендеринга кадры обновляются; загрузки объединяются, максимум до 2.5 раза в секунду. Размер пиксельного изображения совпадает с буфером canvas браузера.

Источник ответа обозначается заголовком X-CADYX-Viewport-Source (browser либо server-fallback), исходная ревизия — X-CADYX-Document-Revision. Если кадр браузера ещё не поступил, API возвращает автономное серверное изометрическое изображение 960×720. Если сохранённый кадр относится к старой ревизии документа, он отбрасывается и до синхронизации браузера возвращается текущее серверное изображение. Для одинакового состояния запроса оба read-маршрута возвращают одни и те же байты.

JSON-сцена

Ответ содержит version: 1, revision документа, coordinate_system: "XYZ", projection: "orthographic", bounds (min/max — тройки XYZ либо null, если сцена пуста) и objects. У каждого объекта отрисовки есть постоянный object_id, тип документа type, плоский массив координат XYZ positions и массивы индексов вершин с нулевой нумерацией: треугольники triangles (по три индекса), линии lines (по два) и точки points (по одному). Пустые массивы явно присутствуют в ответе. Элементы, эскизы и ограничения сами по себе отдельной видимой геометрии не имеют.

Треугольники B-rep OCCT формируются нативной триангуляцией с учётом смещений граней и наружной ориентации. Для отображения при близком масштабировании используется линейное отклонение 0.01 единицы документа, чтобы криволинейные грани и рёбра наложения совпадали. Это только приближение отображения; точная редактируемая B-rep и экспорт не меняются.

Рёбра B-rep OCCT дискретизируются с отклонением 0.01 единицы документа и возвращаются в lines объекта-тела. Не отображаются периодические швы и рёбра между соседними гранями, локальные нормали которых различаются менее чем на 30°. Браузер рисует контурные линии поверх затенённой сцены с проверкой буфера глубины, поэтому задние рёбра не просвечивают через передние грани. Допуск глубины линии учитывает совместное отклонение сетки отображения и выборки рёбер (по 0.01); линии дальше за поверхностью остаются скрыты.

Контуры силуэта гладкой поверхности определяются по ориентации треугольников и проверяются относительно глубины затенённой сцены. Глубина интерполируется по ближайшим растеризованным треугольникам, покрывающим выборку линии; если линия проходит по границе покрытия пикселя, используются и соседние пиксели. Треугольники, инцидентные текущему ребру, исключаются при проверке заслонения, чтобы не разрывать собственный контур; остальные покрывающие грани участвуют в тесте глубины.

Участки короче 1.5 пикселя экрана отбрасываются, чтобы не оставлять одиночные метки. Во время вращения камеры указателем кадр с уменьшенным разрешением повышает этот порог до 3 пикселей; после отпускания указателя полный кадр возвращает дополнительные детали.

Швы между треугольниками никогда не считаются рёбрами конструктивной детали. У тел-треугольных сеток нет рёбер B-rep, поэтому отображается только зависящий от вида силуэт с проверкой глубины. Активные линии и точки эскиза рисуются поверх сцены, без проверки скрытых линий.

Типы отображаемой геометрии

Редактируемые тела OCCT включают коробки, выдавливания и вращения замкнутых профилей, трубы sweep, булевы объединения, скругления и наружную метрическую резьбу. Эвольвентные прямозубые колёса строятся как обычные линии эскиза XY, пока эскиз не выдавлен командой профильного элемента.

Восстановленные импортированные сканы остаются проверенными треугольными сетками cadyx-mesh-v1, а не B-rep. Импортированное непосредственно из проекта облако точек использует тот же проверенный дескриптор с нулём треугольников и явными индексами вершин; общая сцена и серверный PNG показывают такие объекты точками. Облака точек не являются B-rep или треугольными сетками.

Элементы эскиза размещаются по сохранённой рабочей плоскости: XY по умолчанию находится при Z=0; у старых XZ локальная Y соответствует глобальной Z, а глобальная Y=0; рабочие плоскости YZ/CUSTOM/FACE документа v12 используют сохранённые трёхмерные системы координат. См. контракт рабочих плоскостей.

Окружности в viewport отображаются замкнутой цепочкой из 64 отрезков; это приближение отображения, а не замена геометрии CAD. Координаты используют единицы документа без предположений о физических единицах.

Синхронизация браузера и панель инспекции

При захвате на 360° в этом же canvas показывается временное превью текущего кадра. После импорта готового PLY превью в тело облака точек представление проекта возвращается к сохранённой серверной сцене и отдельное превью файла выключается. Viewport API и серверный PNG затем отображают сохранённое тело. Единицы его источника и физический масштаб не считаются подтверждёнными без известного калибровочного размера.

Перед показом кадра браузер сравнивает ревизии инспекции и сцены; если между запросами зафиксировалась команда, он повторно получает сцену. После локальных команд агента/человека обновление немедленно приходит по SSE. Дополнительный лёгкий снимок состояния раз в пять секунд проверяет версии workspace, проекта, файлов, активности и UI-ресурсов; так видны изменения, внесённые другим работающим хостом. При изменении HTML/CSS/JavaScript или версии совместимости браузера/API страница перезагружается и восстанавливает выбранный проект. Возвращение на скрытую вкладку и восстановление соединения также запускают синхронизацию.

Браузер сохраняет доминирующий read-only viewport модели; навигация разделов расположена слева, инспекция — справа. В колонке отображается один блок прогресса: статус, прогресс и прошедшее время, текущее или последнее реальное действие агента и текущая/последняя завершённая задача. Планируемые этапы и будущая очередь браузер не показывает; агент получает полный план и очередь через Agent API. Там же расположены проекции спереди/справа/сверху из той же проверенной геометрии viewport. Ортографические каркасные проекции учитывают зависимые от вида рёбра силуэта, поэтому плавные вращательные стенки остаются обведёнными спереди и сбоку.

Метрики геометрии сцены остаются в нижней части viewport. В Geometry можно выбрать объект; выбор элемента показывает его размеры без наложения контурных рёбер триангуляции. При смене ревизии выбор в дереве следует за последним видимым элементом, чтобы его размеры оставались привязанными к текущей операции моделирования. Ручной выбор сохраняется до следующей ревизии.

Для твердотельных B-rep-инструментов Geometry оценивает массу по сохранённому объёму CAD и выбранной плотности материала-референса в г/см³. Встроенные значения: PLA 1.24, PETG 1.27, ABS 1.04, ASA 1.07, алюминий 2.70, сталь 7.80, нержавеющая сталь 8.00, медь 8.94. Это ориентировочные значения материала; можно задать собственную плотность. Расчёт: mass_g = volume_mm3 * density_g_cm3 / 1000. Для треугольных сеток он не показывается, поскольку сетка не предоставляет проверенный объём твёрдого тела. Оценка предполагает сплошную деталь, не учитывая заполнение при 3D-печати.

Источники плотностей: PLA Prusament, PETG Prusament, ASA Prusament, данные ABS от Protolabs, Aluminum Association, данные стали Outokumpu, Copper Development Association.

Щелчок по пустому месту в дереве элементов снимает выбор дерева, подсветку viewport и свойства выбранного объекта. Отдельная панель свойств объектов отсутствует.

Files — пункт навигации 06. В активном проекте он перечисляет прямые пользовательские файлы через GET /api/v1/projects/{id}/files; содержимое выбранного файла выдаётся соответствующим маршрутом /files/{name}. Вкладка включается только если GET /api/v1/updates?project_id={id} показывает project_lock.state: FREE и в снимке активности нет выполняемой операции. Неизвестное или занятое состояние отключает вкладку. Изменения блокировки приходят по SSE и дополнительно проверяются опросом для совместно работающих хостов. Files не меняет активный проект.

Геометрия тел отображается вместе только с эскизом, который сейчас редактируется. Неактивные эскизы, их точки/линии и эскизы, уже используемые элементом твёрдого тела, убираются из viewport и пользовательского дерева. Повторно используемый эскиз может появиться лишь во время активного редактирования его профиля и снова скрывается после завершения.

События операций агента анимируют каждый новый штрих эскиза и плавные переходы выдавливаний/вращений профиля, построение метрической резьбы, sweep по пути, булевы объединения и скругления рёбер. При использовании эскиза накладка убирается по мере появления твёрдого тела. Эскизные площадки и рёбра жёсткости получают отдельный переход по нормали исходной плоскости и с учётом смещения станции; например, XZ-профиль растёт вдоль Y, а основание под профилем остаётся на месте. Превью площадки поэтому следует направлению выдавливания, а не изображает рост любого объединения вдоль Z.

Для анимации sweep прогресс каждой вершины сетки заранее рассчитывается вдоль ближайшего сегмента пути с помощью иерархии ограничивающих параллелепипедов сегментов; нет необходимости искать всю траекторию отдельно для каждой вершины. При булевом объединении исходные потреблённые тела скрываются, а новое соединённое B-rep плавно появляется в сцене. Линии и точки эскиза накладываются на твердое тело только пока эскиз активен; удаление скрытых линий и выбор объектов в viewport не реализованы.

Карточка прогресса показывает действие/результат, отдельную текущую или последнюю завершённую задачу и краткую историю завершённых/ошибочных действий агента, новые сначала. В строках действий указано локальное время завершения, рассчитанное по отметке времени снимка API. Полный журнал API доступен агентам, но в браузере не отображается как расшифровка команд.

Отчёты панели агента

GET /api/v1/projects/{id}/dashboard (также доступен по /api/v1/agent/projects/{id}/dashboard) возвращает последний сохранённый снимок панели:

{
  "workflow": {
    "title": "Проектирование детали",
    "progress_percent": 68,
    "eta_seconds": 252,
    "phases": [
      {"id": "concept", "title": "Подготовка модели", "state": "completed"},
      {"id": "design", "title": "Уточнение конструкции", "state": "in_progress"}
    ]
  },
  "tasks": [
    {"id": "042", "title": "Уточнение крепёжных элементов", "state": "running"}
  ],
  "revision": 1,
  "updated_at": "2026-10-14T12:00:00+00:00",
  "started_at": "2026-10-14T11:55:48+00:00",
  "elapsed_seconds": null
}

Агент заменяет текущий отчёт запросом POST /api/v1/agent/projects/{id}/dashboard. Если план отсутствует, указывается workflow: null; если очередь пуста — tasks: []. Рабочий процесс содержит от 1 до 24 упорядоченных этапов со статусом pending, in_progress, completed или failed, оценку прогресса агента от 0 до 100 и необязательное ETA в секундах.

Прогресс 100% принимается только тогда, когда все этапы и задачи очереди завершены. Нельзя очистить активный отчёт передачей workflow: null. Этапы проверки помечайте завершёнными лишь после осмотра модели и её результатов. Очередь допускает максимум 100 задач со статусом running, pending, completed или failed. Core задаёт revision и updated_at. Отчёт не изменяет CAD-документ и не требует блокировки изменения. Внешние агенты передают изменения рабочего процесса и очереди через эту конечную точку Agent API.

Каждый снимок Core отправляет по SSE как agent.dashboard; /api/v1/updates содержит dashboard_revision, позволяющую браузеру восстановить пропущенные события. Отчёты и монотонная глобальная ревизия работ сохраняются одной SQLite-транзакцией, которая меняет только строку указанного проекта и глобальную ревизию. Поэтому незавершённый процесс остаётся активным после перезапуска хоста. При первом создании хранилища SQLite импортируется прежнее состояние JSON.

/api/v1/updates показывает agent_work_active, agent_work_revision и активные ID проектов; для информационного статуса хост отправляет SSE workspace.agent-work. Элементы редактирования браузера блокируются по достоверному снимку блокировки/восстановления и снимку выполняющихся операций выбранного проекта, не по самому отчёту панели. Поэтому сохранённый незавершённый или устаревший отчёт не может оставить свободный проект заблокированным; серверные команды всё равно проверяют блокировки и ревизии. Пока не пришли оба снимка доступности проекта, система блокирует его по умолчанию. Данные оборудования не передаются, поэтому интерфейс не показывает придуманные значения CPU/GPU/памяти.

Core добавляет к сохранённым снимкам started_at и elapsed_seconds; агент не должен отправлять эти поля. started_at фиксируется, когда впервые появляется этап in_progress либо задача running. Браузер считает прошедшее время от этой отметки UTC и показывает его на полосе прогресса. При подтверждённом завершении на 100% либо ошибке этапа/задачи Core фиксирует длительность в целых секундах в elapsed_seconds; она доступна после перезапуска хоста или страницы. Старые снимки без полей таймера остаются читаемыми. API сохраняет переданный агентом eta_seconds для интеграций; в этом месте браузер показывает затраченное время.

Заголовок рабочего процесса, имена этапов, заголовки задач и значения agent.activity.action отображаются без перевода в том виде, как получены. Передавайте эти строки на русском, чтобы интерфейс браузера оставался локализованным. Имена проектов/объектов/файлов сохраняются на языке пользователя или источника.

Для запроса на моделирование агент сначала осматривает проект и референсы, затем до первой команды модели публикует конкретный последовательный план. Укажите от 3 до 7 этапов, подходящих этому запросу и дающих наблюдаемый результат; начальное состояние каждого — pending, начальный прогресс — 0%. ETA задавайте только если его можно честно оценить, иначе используйте null. Оставляйте очередь пустой, если задачи не стоят фактически в очереди. По мере работы обновляйте состояния этапов, прогресс и ETA; если выводы изменили план, прежде чем продолжить опубликуйте пересмотренный вариант. Завершайте этапы только после проверки результата; ошибку отмечайте failed. Публикуйте план заранее, чтобы у агента была стабильная последовательность исполнения. Браузер показывает последнее реальное действие, текущую/последнюю завершённую задачу и историю завершённых/ошибочных действий с отметками времени, не раскрывая будущие шаги.

Если последнее действие закончилось и ни одна операция или блокировка агента не активна, полоса прогресса добавляет к тексту действия · завершено, чтобы название в настоящем времени не воспринималось как ещё выполняющаяся работа.

Общий JavaScript-просмотрщик

window.CadyxViewport.createViewer(canvas) используется совместно с превью PLY и возвращает объект со следующими методами:

  • load({positions, triangles, bounds, lines?, points?, bodyTriangleRanges?, featureTriangleRanges?}, {reset = true, transition?}): загрузить сцену; для PLY-облака точек lines/points можно опустить. При обновлении документа используйте reset: false. Переходы эскизов и профилей агента плавные; обычная загрузка и PLY-превью статичны, если явно не задан переход.
  • setSelectedBody(bodyId): подсветить видимые грани выбранного тела в общем превью. bodyTriangleRanges сопоставляет ID тел с диапазонами индексов треугольников. Оттенок проверяется по глубине, поэтому скрытые грани не просвечивают сквозь модель. Передайте null, чтобы снять подсветку.
  • setSelectedFeature(featureId): подсветить только грани OCCT, принадлежащие выбранному fillet/chamfer. featureTriangleRanges сопоставляет ID элементов с диапазонами треугольников. Потреблённые поверхности краевых операций можно передавать через overlayTriangleRanges; рендерер проверяет их по глубине видимой сетки и исключает из обычного прохода затенения.
  • render(): перерисовать после изменения размера/видимости.
  • fit(): сбросить ориентацию и масштаб, чтобы вместить границы всей сцены.
  • getCamera(): вернуть {orientation, zoom, projection: "orthographic"}; orientation — строка-ориентированная матрица поворота камеры 3×3.
  • setCamera(camera): принимает эту матрицу либо старый вид {yaw, pitch}, а также масштаб 0.25–5 и ортографическую проекцию. Наклон pitch не ограничен, поэтому старые клиенты могут задавать ориентацию за любым полюсом.
  • orbitBy(yawDelta, pitchDelta, zoomFactor = 1): применить относительные повороты камеры и масштаб, не меняя документ.

Перетаскивание камеры и колесо прокрутки сразу меняют состояние камеры, а отрисовка canvas объединяется в один callback кадра анимации. При затенении CAD-тела нормали соседних треугольников усредняются в общих вершинах, чтобы более лёгкая отображаемая сетка имела плавную поверхность.

Браузер использует широкую двустороннюю основную подсветку и более слабое заполняющее освещение. Импортированные треугольные сетки в главном превью отображаются затенённой поверхностью; автоматически выведенные яркие границы, складки и силуэтная накладка не рисуются. Отверстия остаются частью реальной сетки. Клиентские surfaceTriangleRanges отмечают эти поверхности в объединённой сцене. В смешанной сцене сохраняются явные кривые CAD-тел и оформление рёбер CAD. В ортографических видах без затенения сетки каркас всё равно отображается. Это влияет только на показ и не меняет сохранённую геометрию либо сцену Viewport API.

Ориентация камеры переводит мировые XYZ в координаты камеры [right, depth, up]. Перетаскивание использует виртуальный трекбол и позволяет неограниченно вращать камеру вокруг всех трёх осей, включая полные обороты и крен. Координатный триэд и куб видов следуют всей ориентации. Колесо меняет масштаб; двойной щелчок или кнопка Вписать восстанавливает вписанный изометрический вид. API-события применяют инкрементальные повороты yaw/pitch без ограничения суммарного наклона.

Если запрос моделирования не задаёт другой датум, новая геометрия начинается на глобальном Z=0. Если сцена имеет общую ось вращения, камера вращается вокруг неё на середине тела по Z; асимметричная ручка не смещает центр камеры от оси кружки. Размер при вписывании вычисляется относительно полного габарита сцены и этого центра. Компактный триэд XYZ следует за ориентацией; у вращательных тел пунктирная ось Z проходит через ось вращения. Камера локальна для просмотрщика и проекта: её состояние сохраняется между ревизиями того же проекта, не требует правки документа и сбрасывается при выборе нового проекта/файла.

Агенты могут анимировать поворот камеры API-запросом, не имитируя ввод браузера:

{
  "yaw_delta": 1.2,
  "pitch_delta": 0.1,
  "zoom_factor": 1.0,
  "duration_ms": 1200
}

POST /api/v1/agent/projects/{id}/viewport/camera принимает yaw_delta в пределах ±2π, pitch_delta в пределах ±0.5 радиан, zoom_factor 0.5–2 и duration_ms 0–5000. Core записывает визуальную операцию камеры и отправляет viewport.camera через SSE. Браузер анимирует её, только если выбран этот проект. Камера остаётся локальной каждому просмотрщику; блокировка изменения не нужна, сохранённый документ не меняется. После переподключения SSE такие события не повторяются.

Проверки: tests/test_rendering.py проверяет порядок вершин/объём/границы сетки ядра, рендер эскизов, обновление параметров и сохранение без записи; tests/test_web_api.py проверяет оба маршрута и отсутствие изменений при инспекции; tests/test_viewport.cjs проверяет верхнюю ориентацию Z, повороты трекбола, ориентацию камеры, вид сверху, координатные оси, масштаб, проверки, вписывание и сохранение камеры. См. команды запуска и проверок.

Сравнение с источником

Read-only-маршрут GET /api/v1/agent/projects/{id}/comparison (также доступен через API проектов) возвращает совмещённое наложение исходной и результирующей сеток, исходный/изменённый/разностный объёмы. Необязательные original_body_id и modified_body_id задают родительское и дочернее тела; по умолчанию используются первое и последнее сохранённые тела. Жёсткие преобразования по цепочке источника применяются к референсной сетке.

Панель автоматически показывает доступные сравнения: исходник — голубой каркас, результат — зелёный. Это наложение триангуляций, не булев анализ добавленного/удалённого материала. Для независимых сборок по умолчанию возвращается available=false. Документ проекта не меняется.

Clone this wiki locally