Документация
Точное ядро B-rep
Точное представление границ: аналитическая и NURBS-геометрия, логические значения, скругления, распознавание отверстий, массовые свойства, проверка, тесселяция и STEP.
Автоматически переведено с английского. Смотреть оригинал на английском
Что такое ядро B-rep
Точное ядро в packages/core/src/cad/brep (Исходные файлы 24, около 8 660 линий, плюс тесты) представляют твердые тела по их точной границе: аналитические поверхности и поверхности NURBS, обрезанные контурами точных краев. Все представляет собой простые данные и чистые функции, поэтому B-представление сериализуется в JSON, пересекает рабочую границу и вносит изменения в историю проекта без изменений. Логические значения, скругления и фаски, распознавание отверстий, массовые свойства, проверка, водонепроницаемая тесселяция и обмен STEP — все это работает в одной структуре.
Таблицы топологии
A Brep представляет собой набор индексных таблиц. Сущности ссылаются друг на друга по индексу, а не по ссылке на объект.
| Сущность | держит | СТЕП аналог |
|---|---|---|
| Вертекс | точка, толерантность | VERTEX_POINT |
| Край | exact curve, [t0, t1] with t0 < t1, v0 = C(t0), v1 = C(t1), tolerance | EDGE_CURVE |
| Коэдж | одно использование ребра в цикле: индекс ребра, перевернутый, дополнительная p-кривая на грани (u, v) | ORIENTED_EDGE + PCURVE |
| Петля | замкнутый цикл коребер; материал слева, вид снаружи (внешняя сторона против часовой стрелки, отверстия по часовой стрелке) | EDGE_LOOP |
| Лицо | область одной поверхности; перевернутый означает, что внешняя нормаль равна −(S_u × S_v) | ADVANCED_FACE |
| Оболочка | связанный набор лиц; закрытая оболочка ограничивает объем | CLOSED_SHELL |
Seams (an edge used twice by the same face, such as the generator line of a full cylinder) and poles (a loop through a degenerate point, such as a cone apex) need no special entities. That is why the exact sphere has 2 vertices, 1 edge and 1 face, and the torus 1 vertex, 2 edges and 1 face.
makeBox(60, 40, 15) {"V":8,"E":12,"F":6,"S":1,"surfaces":["plane"]}
makeSphere(10) {"V":2,"E":1,"F":1,"S":1,"surfaces":["sphere"]}
makeTorus(20, 5) {"V":1,"E":2,"F":1,"S":1,"surfaces":["torus"]}
makeCone(10, 4, 20) {"V":2,"E":3,"F":3,"S":1,"surfaces":["cone","plane"]} Кривые и поверхности
Аналитические типы используют параметризацию STEP (ISO 10303-42), поэтому лица, считываемые и записываемые в STEP, сохраняют свои параметры.
| Тип | Параметризация |
|---|---|
| линия | C(t) = O + t·d, единица d, длина дуги t |
| круг | C(t) = O + r(cos t·x + sin t·y) |
| эллипс | C(t) = O + a cos t·x + b sin t·y |
| самолет | S(u,v) = O + u·x + v·y |
| цилиндр | S(u,v) = O + r(cos u·x + sin u·y) + v·z |
| конус | S(u,v) = O + (R + v tan α)(cos u·x + sin u·y) + v·z |
| сфера | S(u,v) = O + r cos v(cos u·x + sin u·y) + r sin v·z |
| тор | S(u,v) = O + (R + r cos v)(cos u·x + sin u·y) + r sin v·z |
| революция | S(u,v) = rotate(C(v), axis, u) |
| экструзия | S(u,v) = C(u) + v·d |
| заботится | рациональная кривая или поверхность B-сплайна (алгоритмы Пигля и Тиллера в nurbs.ts) |
Точные логические значения
- Пересекаться. Края каждого твердого тела относительно граней другого тела (точные точки по Ньютону), ребра, лежащие на поверхностях другого твердого тела, и кривые пересечения каждой пары несовпадающих граней, уточненные на обеих поверхностях и распознаваемые как линии и круги, в противном случае соответствующие кубическим B-сплайнам в пределах допуска посадки.
- Отпечаток. Каждая точка пересечения становится вершиной в одном реестре для обоих тел, ребра там разбиваются, и каждая грань разрезается кривыми на ней через плоское расположение в своей (u, v) области.
- Классифицировать. Точка внутри каждого фрагмента расположена относительно другого тела: внутрь, наружу или внутрь с той же или противоположной ориентацией.
- Шить. Фрагменты сохраняются по правилам операции, совпадающие части становятся одним ребром, копланарные соседи сливаются, и результат проверяется. Результат, который не является закрытым многообразием твердых бросков.
BooleanError; оно никогда не возвращается.
export const booleanBrep: (A: Brep, B: Brep, op: BooleanOp, options?: BooleanOptions) => BooleanResult
export interface BooleanOptions {
tol?: number // coincidence, default 1e-8 × model size, at least 1e-7 mm
fitTol?: number // fitted intersection curves, default 1e-6 × size, at least 1e-6 mm
seedAngleDeg?: number // normal turn per seed-mesh triangle, default 10
debug?: (stage: string, data: unknown) => void
}
export interface BooleanResult {
brep: Brep; warnings: string[]
stats: { intersectionCurves: number; splitPoints: number; fragments: number; keptFaces: number }
} import { brep } from "@cadcamfun/core"
const { makeBox, makeCylinder, frame, booleanBrep, validateBrep, massProperties } = brep
const box = makeBox(60, 40, 15)
const hole = makeCylinder(6, 25, frame({ x: 30, y: 20, z: -5 }))
const r = booleanBrep(box, hole, "subtract") // 141 ms
r.stats // {"intersectionCurves":2,"splitPoints":12,"fragments":13,"keptFaces":7}
r.warnings // []
validateBrep(r.brep)
// {"valid":true,"manifoldSolid":true,"genus":1,"volume":34303.53996706151,"issues":[]}
massProperties(r.brep).volume // 34303.53996706151 = 60·40·15 − π·6²·15 exactly Массовые свойства
Объем, площадь, центроид и тензор инерции (единичная плотность, около центроида, основная строка) берутся из теоремы о расходимости по граничным граням. Плоские грани интегрируются точно по теореме Грина вдоль точных краевых кривых; изогнутые грани интегрируются в мозаику точной поверхности с шагом по параметрам.
| Тело | massProperties | Закрытая форма |
|---|---|---|
| коробка − Ø12 отверстие, объем | 34303.53996706151 | 34303.539967061515 |
| то же, район | 8139.292006587684 | 8139.292006587698 |
| то же, центроид | (30.000, 20.000, 7.500) | (30, 20, 7.5) |
| сфера r10, объём | 4188.790204786379 | 4188.790204786391 |
| тор 20/5, объем | 9869.60440109475 | 9869.604401089358 |
| филе тарелка, объем | 34097.52220392302 | 34097.522203923065 |
The filleted-plate closed form is the subtracted plate minus four corner slivers of (r² − πr²/4)·h = (16 − 4π)·15 each.
Скругления, фаски и распознавание отверстий
export const blendCandidates: (b: Brep, minAngleDegrees?: number /* 0.5 */) => BlendCandidate[]
export const selectBlendEdges: (edges: ReadonlyArray<BlendCandidate>, s?: BlendSelector) => BlendCandidate[]
// BlendSelector: parallel?: "x"|"y"|"z", within?: box, kind?: "convex"|"concave"|"both" (default convex), minLength?, curved?
export const blendBrep: (b: Brep, edges: ReadonlyArray<BlendCandidate>, size: number,
style?: "fillet" | "chamfer", options?: BlendOptions) => BlendResult
// BlendResult: brep, blended, vertices (rolling-ball corners), rejected (edge ids), ...
export const recognizeHoles: (b: Brep, options?: HoleRecognitionOptions) => ReadonlyArray<RecognizedHole> На корпусе коробки − цилиндра было 14 кандидатов на смесь; selectBlendEdges(c, { parallel: "z" }) выбрал 4 вертикальные внешние края и blendBrep(b, sel, 4) скруглены все 4, и ни один из них не был отклонен в течение 94 мс. Дыра прочитала только по лицам:
[{"entry":{"x":30,"y":20,"z":15},"direction":{"x":0,"y":0,"z":-1},"depth":15,"diameter":12,
"form":"simple","bottom":"through",
"segments":[{"kind":"cylinder","start":0,"end":15,"diameterStart":12,"diameterEnd":12,"faces":[6]}]}] Формы simple, counterbore и countersink; низы through, flat и drill-point. При распознавании считываются лица, а не история, поэтому импорт STEP, логический результат и параметрическая часть распознаются одинаково.
Водонепроницаемая мозаика
Каждый край отбирается один раз по точной кривой, и каждая грань, которая его использует, разделяет эти образцы, поэтому сварная сетка не имеет трещин. Грани триангулируются по ограниченному Делоне в их области (u, v).
| Вариант | По умолчанию | Значение |
|---|---|---|
| chordTol | 1/2000 диагонали модели, закрепленной на [0.001, 0.05] мм. | максимальное расстояние между сеткой и точной поверхностью |
| angleTolDeg | 15 | максимальный нормальный поворот через треугольник (0 отключает) |
| maxEdge | 0 (нет) | цель с длиной ребра |
| maxPointsPerFace | 200 000 | защитная крышка |
| paramStep | — | режим интеграции, используемый MassProperties |
Для филе тарелки defaultChordTol вернул 0.0368 мм и tessellateBrep создал треугольники 652, а также сетки для каждой грани, полилинии ребер и предупреждения.
СТЕП биржа
writeStepBreps записывает файл AP214 (AUTOMOTIVE_DESIGN) в миллиметрах и радианах, по одному ADVANCED_BREP_SHAPE_REPRESENTATION на каждую часть. readStepBreps считывает геометрию и топологию AP203, AP214 и AP242, включая сборки с их преобразованиями и названиями продуктов. О неизвестных объектах сообщается в warnings и их лица перескакивали; ничего не угадывается.
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('CADCAMFUN exact B-rep'),'2;1');
FILE_NAME('plate','2026-10-15T04:49:21',(''),(''),'CADCAMFUN B-rep kernel','CADCAMFUN','');
FILE_SCHEMA(('AUTOMOTIVE_DESIGN { 1 0 10303 214 1 1 1 1 }'));
ENDSEC;
DATA;
#1=APPLICATION_CONTEXT('core data for automotive mechanical design processes');
#2=APPLICATION_PROTOCOL_DEFINITION('international standard','automotive_design',2000,#1);
#3=PRODUCT_CONTEXT('',#1,'mechanical');
#4=PRODUCT_DEFINITION_CONTEXT('part definition',#1,'design');
#5=(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT(.MILLI.,.METRE.)); При обратном чтении этого файла была получена одна часть, объем которой составлял 34097.52220392303 мм³, что соответствует записанному телу с 11 значащими цифрами.
Бюджет времени
Ядро является синхронным и выполняется в потоке вызывающей стороны. withBudget(ms, f) устанавливает срок; длинные циклы (пары граней логического значения, разделение граней, пересечение поверхностей, тесселяция) вызов checkBudget, который выбрасывает BudgetExceeded. Вложенные бюджеты сохраняют более ранний срок; без бюджета проверка стоит одного сравнения.
withBudget(1, () => booleanBrep(makeSphere(10), makeBox(10, 10, 10), "union"))
// BudgetExceeded: the exact model exceeded its time budget of 1 ms Поиск неисправностей
| Симптом | Причина | Исправить |
|---|---|---|
BooleanError | результат сшивания не является замкнутым многообразием (касательные или почти совпадающие грани) | немного отклонить операнд от касания; сначала проверьте оба с помощью validateBrep |
BudgetExceeded | операция заняла больше времени, чем было запланировано | упростить или предоставить звонящему больший бюджет |
| RangeError из примитива | неположительный размер, или малый тор ≥ большого | например «малый радиус тора должен быть меньше большого радиуса» |
смешать края rejected | грань слишком узкая для радиуса, ножевой кромки или наклонной стены | меньший радиус или фаска |
| В STEP-детали отсутствуют грани | неподдерживаемый объект в файле | читать warnings из readStepBreps |
| validateBrep сообщает о проблемах | ошибка индекса, ориентации или края на поверхности в построенном теле | в выпуске упоминается сущность; ничего не восстанавливается автоматически |