Aller au contenu
CADCAMFUN
Docs

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.

Plaque exacte après soustraction et congé Faites glisser vers l'orbite · faites défiler pour zoomer · faites glisser vers la droite pour effectuer un panoramique
A 60 × 40 × 15 box minus a Ø12 cylinder (booleanBrep), then the four vertical edges filleted R4 (blendBrep). Mesh from brepToMesh at chordTol 0.05. 18 vertices, 27 edges, 11 faces; exact volume 34 097.522 mm³.

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étientHomologue STEP
Sommetpoint, toléranceVERTEX_POINT
Bordexact curve, [t0, t1] with t0 < t1, v0 = C(t0), v1 = C(t1), toleranceEDGE_CURVE
Coedgeune utilisation d'une arête par une boucle : indice d'arête, inversé, courbe p optionnelle dans la face (u, v)ORIENTED_EDGE + PCURVE
Bouclecycle fermé de coedges; matériau à gauche vu de l'extérieur (extérieur CCW, trous CW)EDGE_LOOP
Affronterrégion d'une surface ; inversé signifie que la normale extérieure est −(S_u × S_v)ADVANCED_FACE
Coquilleensemble de visages connectés ; une coque fermée délimite un volumeCLOSED_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.

Nombre de primitives - sortie réelle
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.

TaperParamétrage
doublerC(t) = O + t·d, unité d, longueur d'arc t
cercleC(t) = O + r(cos t·x + sin t·y)
ellipseC(t) = O + a cos t·x + b sin t·y
avionS(u,v) = O + u·x + v·y
cylindreS(u,v) = O + r(cos u·x + sin u·y) + v·z
côneS(u,v) = O + (R + v tan α)(cos u·x + sin u·y) + v·z
sphèreS(u,v) = O + r cos v(cos u·x + sin u·y) + r sin v·z
torusS(u,v) = O + (R + r cos v)(cos u·x + sin u·y) + r sin v·z
révolutionS(u,v) = rotate(C(v), axis, u)
extrusionS(u,v) = C(u) + v·d
nurbscourbe ou surface B-spline rationnelle (algorithmes de Piegl & Tiller dans nurbs.ts)
Primitives exactes, tesselées Faites glisser vers l'orbite · faites défiler pour zoomer · faites glisser vers la droite pour effectuer un panoramique
makeBox(10,10,10), makeCylinder(5,10), makeCone(5,2,10) and makeSphere(5), each tessellated by brepToMesh at chordTol 0.2 (12, 430, 122 and 1810 triangles) and placed side by side.
Tore R20 r5 Faites glisser vers l'orbite · faites défiler pour zoomer · faites glisser vers la droite pour effectuer un panoramique
makeTorus(20, 5) : une seule face toroïdale avec une couture et aucun autre bord, pavée à chordTol 1 et 30°. Le volume exact 2π²Rr² = 9 869.604 mm³ est ce que renvoie massProperties.

Booléens exacts

  1. 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.
  2. 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).
  3. 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.
  4. 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é.
boolean.ts
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 }
}
Boîte moins cylindre – sortie réelle
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.

CorpsmassPropertiesFormulaire fermé
boîte − Ø12 trou, volume34303.5399670615134303.539967061515
pareil, zone8139.2920065876848139.292006587698
idem, centroïde(30.000, 20.000, 7.500)(30, 20, 7.5)
sphère r10, volume4188.7902047863794188.790204786391
tore 20/5, volume9869.604401094759869.604401089358
plaque filetée, volume34097.5222039230234097.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

Signature
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 :

reconnaîtreHoles - sortie réelle
[{"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).

OptionDéfautSignification
chordTol1/2000 de la diagonale du modèle, serré à [0.001, 0.05] mmdistance maximale entre le maillage et la surface exacte
angleTolDeg15virage normal maximum à travers un triangle (0 désactive)
maxEdge0 (aucun)cible de longueur de bord
maxPointsPerFace200 000bouchon 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é.
writeStepBreps([{ name: "plate", brep }]) — first lines of the real 358-line file
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.

Sortie réelle
withBudget(1, () => booleanBrep(makeSphere(10), makeBox(10, 10, 10), "union"))
// BudgetExceeded: the exact model exceeded its time budget of 1 ms

Dépannage

SymptômeCauseRéparer
BooleanErrorle 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
BudgetExceededl'opération a pris plus de temps que son budgetsimplifier ou donner à l'appelant un budget plus important
RangeError d'une primitivetaille non positive, ou tore mineur ≥ majeurpar ex. "le rayon mineur du tore doit être plus petit que le rayon majeur"
mélanger le bord rejectedface trop étroite pour le rayon, le bord du couteau ou le mur inclinérayon plus petit ou chanfrein
Faces manquantes de la pièce STEPentité non prise en charge dans le fichierlire warnings de readStepBreps
validateBrep signale des problèmeserreur d'indice, d'orientation ou de bord sur surface dans un corps bâtile problème nomme l'entité ; rien n'est réparé automatiquement