Документация
Область просмотра
Инструменты рисования на холсте и рендеринг Three.js используют общую геометрию, сохраняя при этом явное состояние редактирования и воспроизведения.
Автоматически переведено с английского. Смотреть оригинал на английском
Компоненты видового экрана
apps/desktop/src/viewport/index.ts экспорт Editor2D, View3D, их типы опор, доступные идентификаторы инструментов и solidsFromProfiles. Оба компонента заполняют своего родителя: предоставляют контейнер с ненулевой шириной и высотой. Основные объекты САПР и программы CAM представляют собой общую модель данных.
Редактор 2D выполняет рендеринг в Canvas 2D и сохраняет собственную историю выделения, камеры и команд. Средство просмотра 3D использует Three.js, элементы управления орбитой и преобразованием, асинхронные задания сетки и программное воспроизведение. Рендеринг траектории или твердого тела не зависит от его сохранения или проверки производственной операции.
Интеграционный договор
Editor2DProps требует drawing, onChange, и selectedTool. Подайте созданные рисунки обратно в реквизит. Компонент распознает собственные созданные объекты документа; замена документа извне загружает новый рисунок и сбрасывает состояние редактора.
import { createSignal } from "solid-js"
import { Editor2D, type ToolId } from "./viewport/index.ts"
const [drawing, setDrawing] = createSignal(initialDrawing)
const [tool, setTool] = createSignal<ToolId>("select")
<Editor2D drawing={drawing()} onChange={setDrawing} selectedTool={tool()} /> Выбор исключает заблокированные объекты и объекты на заблокированных слоях. Невидимые объекты и скрытые слои исключаются из отображаемого пространственного индекса. Новые объекты получают уникальные для документа идентификаторы и назначаются видимому, разблокированному слою, когда он доступен.
Инструменты рисования и жесты
В реестре инструментов есть фабрики для выбора, линии, прямоугольника, круга, эллипса, полилинии, дуги, текста, размеров, перемещения, поворота, масштабирования, зеркального отражения, смещения, обрезки и скругления. AVAILABLE_TOOLS производится на этих зарегистрированных заводах. startTool дополнительно признает chamfer через фабрику инструментов для скругления, но фаска не объявляется в этом массиве. Потребители должны использовать реальный реестр, чтобы решить, какие инструменты включить.
- Масштабирование колесиком или щипком; Перетаскивание пробелом, среднее перетаскивание и панорамирование правой кнопкой мыши.
Fсоответствует индексированному рисунку. Удалить или Backspace удаляет разблокированный выбор.Cmd/Ctrl+Zотменяет;Cmd/Ctrl+Shift+ZилиCmd/Ctrl+Yпеределывает.- Enter фиксирует ломаную линию. Escape доставляется активному инструменту для отмены текущего жеста.
- Когда текст активен, перед размещением введите символы или клавишу Backspace; исходный текст
Text.
Позиции указателей преобразуются в мировые координаты перед отправкой инструмента. Привязка объединяет пространственный индекс, геометрические кандидаты и сетку, зависящую от камеры; допуск попадания при выборе соответствует восьми пикселям экрана. Машины-инструменты создают команды и предварительный просмотр, а не пишут файлы или вызывают API.
3D-рендеринг и воспроизведение
View3D принимает чертежи, твердые тела, дополнительную экструзию профиля, cam.Program, размеры заготовки и определения инструментов. Он поддерживает предварительные настройки перспективы, сверху, снизу, спереди, сзади, слева, справа, изометрии и четырех видов. Режимы отображения: затенение, затенение с краями, каркасный и рентгеновский. Освещение, свойства материала, секции обрезки, сетка, оси и начало координат настраиваются с помощью реквизита.
Управляйте воспроизведением с помощью playing, playbackTime в секундах, playbackRate, и onPlaybackTimeChange. Воспроизведение расширяет циклы сверления, мозаично формирует круговые/спиральные движения, сохраняет время задержки и отчетливо отображает быстрые движения. Карты инструментов и дополнительная геометрия фрезы, хвостовика и державки по умолчанию; предполагаемая геометрия визуально выделяется.
Обратные вызовы выбора сообщают о надежном индексе. Элементы управления преобразованием определяют положение, вращение и масштабирование. onTransformCommit; вызывающие стороны решают, как сохранить это преобразование. Наложения траектории инструмента могут отображать точки и метки, фильтры типов точек, центры дуг, радиусы дуг и прозрачность заготовки.
Воспроизведение — это визуальное представление
Зритель анимирует предоставленную программу и рисует инвентарь и инструменты. Он не выполняет удаление материала. К модулям проверки CAM относятся проверки столкновений и машинных границ; просмотр программы не означает одобрения машины.
Координаты и единицы
Координаты чертежа сердцевины и размеры заготовки указаны в миллиметрах. Углы рисования и компоненты вращения Three.js используют радианы; не применяйте это соглашение к значениям поворотной оси CAM или входным параметрам, которые явно используют градусы. viewport/units.ts содержит помощники преобразования отображаемых миллиметров и дюймов. Преобразуйте границы ввода/вывода, чтобы привязка, геометрия и движение траектории инструмента сохраняли согласованную систему единиц.
Камера 2D отображает мировые координаты в пикселях CSS; Размеры холста подложки включают соотношение пикселей устройства. При изменении размера обновляется камера и резервный буфер. ResizeObserver. Масштаб камеры определяет шаг сетки и допуски попадания в экранное пространство.
Дюймовый дисплей преобразуется ровно с точностью 25.4 мм на дюйм, а длины по умолчанию равны 3 десятичным знакам (apps/desktop/src/viewport/units.ts). В редакторе 2D каждый шаг колеса масштабируется с коэффициентом 1.15, масштаб фиксируется между 0.001 и 100,000, а при показе по размеру остается запас 10 % (editor2d/camera.ts).
Ресурсы и жизненный цикл
Компонент 2D отменяет поставленные в очередь кадры анимации и отключает наблюдатель изменения размера при размонтировании. Компонент 3D реализует прослушиватели изменения размера и видимости, элементы управления орбитой и преобразованием, рабочие сетки, планирование анимации, геометрию, материалы, спрайты, сетки инструментов и средство рендеринга WebGL.
Планировщик кадров объединяет недействительности и запрашивает дополнительные кадры, когда они необходимы для демпфирования камеры или воспроизведения. Изменения видимости приостанавливают работу. Это политика планирования, а не гарантированный бюджет частоты кадров для каждой модели и устройства.
Карта модуля
editor2d/editor2d.tsx: управляемый компонент, отправка указателя, камера, выбор, история и рисование на холсте.editor2d/tools/: машины состояний жестов и построение команд.editor2d/camera.ts,render.ts, иsnap-pipeline.ts: преобразования координат, рендеринг объектов, выбор и оркестровка привязок.spatial/grid.ts: рисование пространственного индекса.view3d/view3d.tsx: композиция сцены, элементы управления камерой, выбор, преобразования, инвентарь и инструменты.view3d/playback.ts,toolpath-overlays.ts, иmodeling.ts: временная шкала движения, наложение данных и преобразование профиля в твердое тело.view3d/mesh-jobs.tsиmesh-worker.ts: построение фоновой геометрии и владение заданиями.
Доступность инструмента
ToolId описывает более широкий словарь инструментов; AVAILABLE_TOOLS описывает зарегистрированное подмножество. Для интерактивных инструментов используйте startTool(id, lookup, context, text). Поиск выбора запрашивает объекты-кандидаты; контекст предоставляет текущий выбор и доступ к объекту; text предоставляет содержимое аннотации.
Пропавшая фабрика возвращается undefined. Обработайте это явно, а не представляйте отключенный или нереализованный инструмент как активный режим редактирования. Инструменты, изменяющие существующую геометрию, требуют текущего выделения и контекста объекта; вызова фабрики без этих зависимостей недостаточно для полезного редактирования.
Создание сетки и проверка
Для тел с предполагаемым количеством вершин выше 50,000 и поддержкой Worker браузера средство просмотра ставит построение сетки в очередь в Worker модуля. Меньшие твердые тела сцепляются синхронно. Сетчатая очередь обрабатывает завершение, устаревшие задания, ошибки рабочих процессов и очистку. Порог — это оценка, используемая для планирования, а не документированный предел размера модели.
bun test apps/desktop/src/viewport
bun run --filter @cadcamfun/desktop typecheck Логические тесты охватывают помощники рендеринга, жесты инструментов, пространственную индексацию, воспроизведение и наложения. Поведение браузера/WebGL также зависит от графической среды; проверяйте фактическое взаимодействие области просмотра при изменении элементов управления камерой, жизненного цикла сцены или рендеринга.
Пример контролируемого воспроизведения
Родитель может владеть элементами управления транспортировкой, не дублируя временную шкалу движения зрителя. Этот компонент принимает уже созданную CAM-программу и управляет временем, состоянием воспроизведения, скоростью и предустановкой области просмотра. Его пути импорта предполагают, что файл находится непосредственно под apps/desktop/src.
import { createSignal } from "solid-js"
import { cam } from "@cadcamfun/core"
import { View3D } from "./viewport/index.ts"
export function ProgramPreview(props: { program: cam.Program }) {
const [seconds, setSeconds] = createSignal(0)
const [playing, setPlaying] = createSignal(false)
return <div style={{ height: "600px" }}>
<button onClick={() => setPlaying(value => !value)}>Play / pause</button>
<button onClick={() => { setSeconds(0); setPlaying(true) }}>Restart</button>
<View3D
program={props.program}
preset="isometric"
playing={playing()}
playbackTime={seconds()}
playbackRate={1}
onPlaybackTimeChange={setSeconds}
stock={{ origin: { x: 0, y: 0, z: -10 }, size: { x: 100, y: 80, z: 10 } }}
/>
</div>
} Построитель воспроизведения начинает с начала координат, разбивает циклы на ходы и вычисляет длительность на основе длины перемещения и подачи. Его быстрая скорость по умолчанию составляет 5,000 мм/мин, а допуск тесселяции дуги по умолчанию составляет 0,1 мм. Это предварительные предположения, а не измеренное ускорение машины или синхронизация контроллера. Команды Dwell сохраняют установленные секунды; комментарии и записи, предназначенные только для ориентации, не добавляют линейного перемещения.
Цвета инструментов назначаются при первом появлении каждого идентификатора инструмента и сохраняются на всех его путях. Предоставление карты инструментов/инструмента по умолчанию для геометрии сборки; Цветная траектория сама по себе не определяет размеры фрезы или держателя, использованные при проверке.
Редактирование рецептов и текущих ограничений инструмента
| Операция | Жест и предварительные условия | Текущее поведение |
|---|---|---|
| Компенсировать | Выберите поддерживаемый объект, затем перетащите; Вместо этого Shift выбирает объект под курсором. | Линии/полилинии/прямоугольники дают результат полилинии. Реализации круга и дуги перемещают центр, сохраняя при этом радиус; этот инструмент не является общей операцией концентрического смещения кривых. |
| Обрезать/удлинить | Сначала выберите исходные и граничные объекты, активируйте «Обрезать» и щелкните цель. Alt выбирает режим расширения. | Реализация ищет пересечения в других выбранных объектах. Он меняет линии и полилинии; неподдерживаемые типы целей или отсутствующие пересечения не производят редактирования. |
| Скругление/фаска | Выберите две пересекающиеся линии. Shift переключается на фаску. | Общий инструмент использует начальный радиус 5 мм и заменяет пару обрезанными линиями и соединительной полилинией. Это не произвольное скругление со сплошной кромкой. |
| Преобразование твердого тела | Предоставлять onTransformCommit, выберите сетку, затем активируйте перемещение/поворот/масштабирование. | Обратный вызов сообщает твердый индекс и значения преобразования. Инструменты выбора и преобразования отключены в режиме четырех представлений. |
Эти детали взяты из реализации жестов, а не из меток их палитры. Проверьте предварительный просмотр перед фиксацией и используйте «Отменить», если результат отличается от предполагаемой геометрии. Инструмент, не возвращающий команду, может означать, что его геометрические предпосылки не были выполнены, а не то, что редактор потерял событие указателя.
Сбои рендеринга и создания сетки
Очередь фоновой сетки по умолчанию допускает не более 128 ожидающих заданий, запускается по одному и имеет по умолчанию время ожидания в 15 секунды для каждого задания. Сброс сцены завершает работу работника и очищает работу в очереди; устаревшие ответы игнорируются. Неправильные ответы работника, ошибки декодирования сообщений, тайм-ауты и сбои емкости очереди сообщают об ошибках через обратный вызов очереди.
| Симптом | Действие |
|---|---|
| Пустой холст без геометрии. | Присвойте родительскому элементу ненулевой размер, проверьте видимость объекта/слоя и подгоните представление. |
| Ничего нельзя выбрать | Проверьте блокировки объектов/слоев в 2D; проверьте режим четырех представлений и состояние преобразования в 3D. |
| Тайм-аут сетки или полная очередь | Уменьшите сложность сцены или количество одновременно отправляемых тел и проверьте рабочую ошибку. Неудавшийся пакет удаляется, а не устанавливается частично как завершенное задание. |
| Время воспроизведения кажется неправильным | Проверьте подачу программы, ходы задержки, предположения о высокой скорости и проверьте, не сбрасывает ли измененная программа родительское время. |
| WebGL недоступен | Используйте поддерживаемую графическую среду и проверьте состояние недоступности средства рендеринга компонента; логические тесты не могут доказать доступность графического процессора. |
Соответствующие тесты включают в себя editor2d/tools/offset.test.ts, annotation-transform.test.ts, spatial/grid.test.ts, view3d/playback.test.ts, и toolpath-overlays.test.ts. Реализация сетчатой очереди view3d/mesh-jobs.ts.
Подробное описание единиц отображения
Редактор всегда работает в миллиметрах. Преобразовывается только то, что пользователь читает и печатает, с использованием точных коэффициентов, указанных ниже. Собственная единица сохраненного чертежа остается mm или inch; дополнительные единицы доступны только для отображения.
| Единица | Этикетка | мм на единицу | Десятичные дроби по умолчанию | Программный блок G-кода |
|---|---|---|---|---|
mm | мм | 1 | 3 | мм |
um | µm | 0.001 | 1 | мм |
cm | см | 10 | 4 | мм |
m | m | 1000 | 6 | мм |
inch | дюйм | 25.4 | 4 | дюйм |
thou | thou | 0.0254 | 2 | дюйм |
import { formatLength, parseLength, formatAngle, programUnitsOf } from "./units"
formatLength(25.4, "inch") // "1.0000 inch"
formatLength(12.5) // "12.500 mm"
formatLength(0.0254, "thou") // "1.00 thou"
parseLength("2 in", "inch") // 50.8 (a trailing unit word is ignored)
parseLength("abc") // undefined
formatAngle(Math.PI / 2) // "90.0°"
programUnitsOf("thou") // "inch" parseLength удаляет конечный буквенный суффикс (включая µ и °) и интерпретирует число в текущей единице отображения. Суффикс не используется для выбора юнита, поэтому введите 2 mm при отображении в дюймах получается 50.8 мм. Пустые, нечисловые и бесконечные входные данные возвращаются. undefined, и в этом случае редакторы должны сохранить предыдущее значение.
2D-камера и сетка
worldToScreen переворачивает Y так, чтобы мир +Y указывал вверх на экране.| Константа/функция | Ценить | Поведение |
|---|---|---|
ZOOM_STEP | 1.15 | Коэффициент на шаг колеса; zoomAt сохраняет фиксированную точку мира под курсором. |
MIN_SCALE / MAX_SCALE | 0.001 / 100,000 пикселей на мм | Масштаб ограничен этим диапазоном. |
FIT_MARGIN | 0.1 | Часть области просмотра, сохраняемая в качестве поля cameraForBounds. |
createCamera() | центр (0, 0), масштаб 1, 800 × 600 | Исходная камера до первого изменения размера. |
gridStep(scale, major = 10, minPixels = 8) | 1-2-5 лестница | Наименьший шаг, при котором точки сетки располагаются на расстоянии не менее 8 пикселя. |
const camera = createCamera({ x: 0, y: 0 }, 2, 800, 600) // 2 px per mm
worldToScreen(camera, { x: 10, y: 10 }) // { x: 420, y: 280 }
screenToWorld(camera, { x: 420, y: 280 }) // { x: 10, y: 10 }
gridStep(2) // 5 -> 5 mm apart = 10 px
gridStep(0.5) // 20 -> 20 mm apart = 10 px Рендеринг отбраковки объектов против visibleBounds(camera). Привязка также позволяет избежать сканирования всего чертежа: однородная пространственная сетка возвращает объекты, границы которых находятся в пределах допуска привязки плюс допустимый запас 2 мм, и только они передаются в ядро. findSnap. Это обеспечивает быстрое перемещение указателя на рисунках со многими объектами.
Привязка ссылки
Типы привязок проверяются в порядке приоритета. Порядок по умолчанию соответствует устаревшему редактору: endpoint, midpoint, center, intersection, perpendicular, tangent, nearest, и quadrant. Конечные точки — это вершины исходного объекта, а не его тесселяции.
| Параметр | Значение |
|---|---|
enabled | Главный переключатель; false отключает все привязки. |
types | Включенные типы привязки, сначала наивысший приоритет. |
tolerance | Радиус привязки в миллиметрах; это не зависит от зума. |
gridEnabled, gridSpacing | Привязка к сетке, когда объектная привязка не применяется. |
referencePoint | Точка, из которой сделан вывод. perpendicular и tangent без него ничего не найти. |
Конвейер возвращает снимок, идентификаторы объектов под курсором (ближайшие первыми, которые использует инструмент выбора) и количество рассматриваемых кандидатов.
Как синхронизируется воспроизведение траектории
buildPlayback(program, rapidRate = 5000, tolerance = 0.1) преобразует программу CAM в временные сегменты. Продолжительность каждого движения равна его длине, разделенной на подачу (или на быструю скорость для порогов), умноженную на 60, что дает секунды. Жители добавляют свое время, не двигаясь. Комментарии, перемещения ориентации и постоянные циклы не отображаются как сегменты. Дуги делятся на хорды, сагитта которых остается внутри. tolerance (между 2 и 65, 536 хорд на дугу), а Z интерполируется вдоль дуги для спиралей.
const playback = buildPlayback(program) // rapids at 5000 mm/min
playback.duration // total seconds
positionAt(playback, 12.5) // tool position at t = 12.5 s
toolAt(playback, 12.5) // toolId cutting at that time
toolColors(program) // Map toolId -> colour, first use order
// A 10 mm feed move at 600 mm/min lasts 10 / 600 × 60 = 1 s.
// The same 10 mm as a rapid lasts 10 / 5000 × 60 = 0.12 s. segmentIndexAt находит воспроизводимый сегмент с помощью двоичного поиска, поэтому поиск не требует больших затрат даже для длинных программ. Поиск за концом возвращает конечную позицию, и toolAt затем сообщает последний инструмент. Время воспроизведения представляет собой визуальную оценку, основанную на запрограммированных каналах; он игнорирует ускорение машины, поэтому реальной машине требуется больше времени.
Практика видового экрана
- Конвертируйте на краю: сохраняйте и вычисляйте в миллиметрах и радианах и форматируйте только для отображения с помощью
formatLengthиformatAngle. - Никогда повторно не используйте проанализированную длину после
parseLengthвозвращаетundefined; сохраните предыдущее значение и отобразите подсказку для проверки. - При добавлении инструмента рисования зарегистрируйте его в таблице фабрики инструментов, чтобы панель инструментов, ярлыки и тесты обращались к нему по одному и тому же идентификатору.
- Сохраняйте пространственные запросы-кандидаты. Передача каждой сущности в
findSnapпри каждом перемещении указателя индекс побеждает. - Считайте продолжительность воспроизведения предварительным просмотром, а не цитатой времени цикла.
Хит-тестирование в масштабе: пространственная сетка
Редактор 2D нацелен на 60 кадров в секунду с объектами 10,000, поэтому проверка попадания и отбраковка никогда не сканируют каждый объект для каждого события указателя. viewport/spatial/grid.ts сохраняет однородную сетку: каждый элемент регистрируется в каждой ячейке, которой касается ограничивающая рамка, а запрос возвращает все элементы, границы которых пересекают поле запроса, в порядке вставки. Результат точный, а не образец.
| Параметр | Ценить | Почему |
|---|---|---|
| Размер ячейки по умолчанию | 50 мировые единицы (мм) | Подходит для рисунка размером около 1 м в поперечнике. |
| Минимальный размер ячейки | 1e-6 | Защищает от нулевого или отрицательного размера, который будет зацикливаться навсегда. |
| Лимит ячеек на элемент | 4,096 | Более крупные элементы (длинная линия поперек листа) отслеживаются отдельно, а не по ячейкам. |
| Метод | Поведение |
|---|---|
build(items) | Восстановить с нуля |
upsert(id, item) | Вставить или заменить один элемент по идентификатору |
remove(id) | Удалять; неизвестные идентификаторы игнорируются |
query(bounds) | Идентификаторы, границы которых пересекают поле |
Ячейки, затронутые пунктирным полем запроса, посещаются; A и длинная линия возвращаются, поскольку их границы пересекают ее, а B — нет.
3Очередь D-сетки
Твердые тела объединяются в веб-воркере, поэтому поток пользовательского интерфейса никогда не блокируется. MeshWorkerQueue в view3d/mesh-jobs.ts запускает одно задание за раз:
| Правило | Ценить | Сообщение о неудаче |
|---|---|---|
| Емкость (в очереди + работа) | 128 | Очередь 3D-сетки заполнена. Уменьшите сложность сцены. |
| Тайм-аут на задание | 15 s | 3Время создания D-сетки истекло. Уменьшите сложность сцены. |
| Ошибка работника | — | Сообщение рабочего, или «Рабочая сетка неожиданно остановилась». |
| Нерасшифрованный ответ | — | Mesh Worker не смог расшифровать свой ответ. |
| Плохая геометрия | позиции должны быть Float32Array, индексы Uint32Array | Сетчатый рабочий вернул неверную геометрию. |
Любой сбой завершает работу работника и очищает всю очередь, поэтому устаревшая работа сцены никогда не сохраняется после нового редактирования; следующее представление запускает нового работника. Ответы сопоставляются по идентификатору задания, поэтому поздний ответ от уволенного работника игнорируется.
2Реализации инструмента D
| Файл | Инструменты |
|---|---|
tools/two-point.ts | линия, прямоугольник, круг по диаметру, эллипс |
tools/chained.ts | полилиния, трехточечная дуга |
tools/fillet-chamfer.ts | закруглите или скосите угол между двумя линиями |
tools/offset.ts | сместить полилинию, прямоугольник, круг или дугу на расстояние |
tools/trim.ts | обрезать и расширить |
tools/select.ts | щелкните, установите флажок и добавьте/удалит выделение |
tools/annotation-transform.ts | перемещать и трансформировать аннотации |
Каждый инструмент представляет собой небольшой конечный автомат с onPointerDown, onPointerMove и onPointerUp, созданный на заводе в tools/index.ts, по одному на запись палитры. Позиции указателя проходят через snap-pipeline.ts прежде чем инструмент их увидит.