Documentation
Noyau B-rep exact
Représentation exacte des limites : géométrie analytique et NURBS, booléens, congés, reconnaissance des trous, propriétés de masse, validation, tessellation et STEP.
Traduit automatiquement de l'anglais. Voir l'original en anglais
Qu'est-ce que le noyau B-rep
Le noyau exact dans packages/core/src/cad/brep (24 fichiers sources, environ 8 660 lignes, plus tests) représente les solides par leur limite exacte : surfaces analytiques et NURBS, découpées par des boucles d'arêtes exactes. Tout est constitué de données simples et de fonctions pures, donc un B-rep sérialise en JSON, traverse une frontière de travail et diffère dans l'historique du projet sans changement. Les booléens, les congés et les chanfreins, la reconnaissance des trous, les propriétés de masse, la validation, la tessellation étanche et l'échange STEP fonctionnent tous sur cette structure unique.
Tableaux de topologie
A Brep est un ensemble de tables d'index. Les entités se réfèrent les unes aux autres par index, jamais par référence d'objet.
| Entité | Détient | Homologue STEP |
|---|---|---|
| Sommet | point, tolérance | VERTEX_POINT |
| Bord | exact curve, [t0, t1] with t0 < t1, v0 = C(t0), v1 = C(t1), tolerance | EDGE_CURVE |
| Coedge | une utilisation d'une arête par une boucle : indice d'arête, inversé, courbe p optionnelle dans la face (u, v) | ORIENTED_EDGE + PCURVE |
| Boucle | cycle fermé de coedges; matériau à gauche vu de l'extérieur (extérieur CCW, trous CW) | EDGE_LOOP |
| Affronter | région d'une surface ; inversé signifie que la normale extérieure est −(S_u × S_v) | ADVANCED_FACE |
| Coquille | ensemble de visages connectés ; une coque fermée délimite un volume | 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"]} Courbes et surfaces
Les types analytiques utilisent les paramétrages STEP (ISO 10303-42), de sorte que les visages lus et écrits dans STEP conservent leurs paramètres.
| Taper | Paramétrage |
|---|---|
| doubler | C(t) = O + t·d, unité d, longueur d'arc t |
| cercle | C(t) = O + r(cos t·x + sin t·y) |
| ellipse | C(t) = O + a cos t·x + b sin t·y |
| avion | S(u,v) = O + u·x + v·y |
| cylindre | S(u,v) = O + r(cos u·x + sin u·y) + v·z |
| cône | S(u,v) = O + (R + v tan α)(cos u·x + sin u·y) + v·z |
| sphère | S(u,v) = O + r cos v(cos u·x + sin u·y) + r sin v·z |
| torus | S(u,v) = O + (R + r cos v)(cos u·x + sin u·y) + r sin v·z |
| révolution | S(u,v) = rotate(C(v), axis, u) |
| extrusion | S(u,v) = C(u) + v·d |
| nurbs | courbe ou surface B-spline rationnelle (algorithmes de Piegl & Tiller dans nurbs.ts) |
Booléens exacts
- Couper. Arêtes de chaque solide contre les faces de l'autre (points exacts par Newton), arêtes situées sur les surfaces de l'autre solide et courbes d'intersection de chaque paire de faces non coïncidentes, affinées sur les deux surfaces et reconnues comme des lignes et des cercles, sinon ajustées sous forme de splines B cubiques dans la tolérance d'ajustement.
- Imprimer. Chaque point d'intersection devient un sommet dans un registre pour les deux solides, les arêtes y sont divisées et chaque face est coupée par les courbes qui la composent via un arrangement planaire dans son domaine (u, v).
- Classer. Un point à l'intérieur de chaque fragment est situé contre l'autre solide : à l'intérieur, à l'extérieur ou sur avec une orientation identique ou opposée.
- Coudre. Les fragments sont conservés selon les règles de l'opération, les pièces coïncidentes deviennent une seule arête, les voisins coplanaires fusionnent et le résultat est validé. Un résultat qui n’est pas une variété fermée
BooleanError; il n'est jamais restitué.
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 Propriétés de masse
Le volume, l'aire, le centroïde et le tenseur d'inertie (densité unitaire, autour du centroïde, ligne principale) proviennent du théorème de divergence sur les faces limites. Les faces planaires sont intégrées exactement par le théorème de Green le long des courbes de bord exactes ; les faces courbes sont intégrées sur une tessellation par étapes paramétriques de la surface exacte.
| Corps | massProperties | Formulaire fermé |
|---|---|---|
| boîte − Ø12 trou, volume | 34303.53996706151 | 34303.539967061515 |
| pareil, zone | 8139.292006587684 | 8139.292006587698 |
| idem, centroïde | (30.000, 20.000, 7.500) | (30, 20, 7.5) |
| sphère r10, volume | 4188.790204786379 | 4188.790204786391 |
| tore 20/5, volume | 9869.60440109475 | 9869.604401089358 |
| plaque filetée, volume | 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.
Reconnaissance des congés, chanfreins et trous
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> Sur la boîte − corps du cylindre, il y avait 14 candidats au mélange ; selectBlendEdges(c, { parallel: "z" }) sélectionné les 4 bords extérieurs verticaux, et blendBrep(b, sel, 4) a créé tous les 4 sans rejeter aucun en 94 ms. Le trou se lit à partir des seuls visages :
[{"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]}]}] Les formulaires sont simple, counterbore et countersink; les bas sont through, flat et drill-point. La reconnaissance lit les visages, pas l'historique, donc une importation STEP, un résultat booléen et une partie paramétrique sont reconnus de la même manière.
Pavage étanche
Chaque bord est échantillonné une fois sur sa courbe exacte et chaque face qui l'utilise partage ces échantillons, de sorte que le treillis soudé ne présente aucune fissure. Les faces sont triangulées par Delaunay contraint dans leur domaine (u, v).
| Option | Défaut | Signification |
|---|---|---|
| chordTol | 1/2000 de la diagonale du modèle, serré à [0.001, 0.05] mm | distance maximale entre le maillage et la surface exacte |
| angleTolDeg | 15 | virage normal maximum à travers un triangle (0 désactive) |
| maxEdge | 0 (aucun) | cible de longueur de bord |
| maxPointsPerFace | 200 000 | bouchon de sécurité |
| paramStep | — | mode d'intégration utilisé par massProperties |
Pour l'assiette filetée defaultChordTol a renvoyé 0.0368 mm et tessellateBrep produit 652 triangles ainsi que des maillages par face, des polylignes de bord et des avertissements.
Échange STEP
writeStepBreps écrit un fichier AP214 (AUTOMOTIVE_DESIGN) en millimètres et en radians, un ADVANCED_BREP_SHAPE_REPRESENTATION par pièce. readStepBreps lit la géométrie et la topologie AP203, AP214 et AP242, y compris les assemblages avec leurs transformations et noms de produits. Des entités inconnues sont signalées dans warnings et leurs visages sautillèrent ; rien n'est deviné.
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.)); La relecture de ce fichier a donné une partie dont le volume était de 34097.52220392303 mm³, égal au corps écrit à 11 chiffres significatifs.
Budget-temps
Le noyau est synchrone et s'exécute sur le thread de l'appelant. withBudget(ms, f) fixe un délai ; appel de boucles longues (paires de faces d'un booléen, fractionnement de faces, intersection de surfaces, tessellation) checkBudget, ce qui jette BudgetExceeded. Les budgets imbriqués conservent la date limite antérieure ; sans budget, un chèque coûte une comparaison.
withBudget(1, () => booleanBrep(makeSphere(10), makeBox(10, 10, 10), "union"))
// BudgetExceeded: the exact model exceeded its time budget of 1 ms Dépannage
| Symptôme | Cause | Réparer |
|---|---|---|
BooleanError | le résultat cousu n'est pas un solide collecteur fermé (faces tangentes ou presque coïncidentes) | déplacer légèrement un opérande hors de la tangence ; vérifiez d'abord les deux avec validateBrep |
BudgetExceeded | l'opération a pris plus de temps que son budget | simplifier ou donner à l'appelant un budget plus important |
| RangeError d'une primitive | taille non positive, ou tore mineur ≥ majeur | par ex. "le rayon mineur du tore doit être plus petit que le rayon majeur" |
mélanger le bord rejected | face trop étroite pour le rayon, le bord du couteau ou le mur incliné | rayon plus petit ou chanfrein |
| Faces manquantes de la pièce STEP | entité non prise en charge dans le fichier | lire warnings de readStepBreps |
| validateBrep signale des problèmes | erreur d'indice, d'orientation ou de bord sur surface dans un corps bâti | le problème nomme l'entité ; rien n'est réparé automatiquement |