Documentazione
Kernel B-rep esatto
Rappresentazione esatta dei confini: geometria analitica e NURBS, booleani, raccordi, riconoscimento dei fori, proprietà di massa, validazione, tassellatura e STEP.
Tradotto automaticamente dall'inglese. Vedi l'originale in inglese
Cos'è il kernel B-rep
Il nocciolo esatto in packages/core/src/cad/brep (24 file sorgente, circa 8 660 righe, più test) rappresenta i solidi in base al loro confine esatto: superfici analitiche e NURBS, tagliate da cicli di bordi esatti. Tutto è costituito da dati semplici e funzioni pure, quindi un B-rep viene serializzato su JSON, attraversa il confine del lavoratore e si differenzia invariato nella cronologia del progetto. Booleani, raccordi e smussi, riconoscimento dei fori, proprietà di massa, convalida, tassellatura a tenuta stagna e scambio STEP funzionano tutti su questa struttura.
Tabelle topologiche
A Brep è un insieme di tabelle indice. Le entità si riferiscono tra loro tramite indice, mai tramite riferimento a oggetto.
| Entità | Tiene | Controparte STEP |
|---|---|---|
| Vertice | punto, tolleranza | VERTEX_POINT |
| Bordo | exact curve, [t0, t1] with t0 < t1, v0 = C(t0), v1 = C(t1), tolerance | EDGE_CURVE |
| Coedge | un uso di un bordo da parte di un ciclo: indice del bordo, invertito, curva p opzionale nella faccia (u, v) | BORDO_ORIENTATO + PCURVA |
| Ciclo continuo | ciclo chiuso dei bordi; materiale a sinistra visto dall'esterno (esterno CCW, fori CW) | EDGE_LOOP |
| Viso | regione di una superficie; invertito significa che la normale esterna è −(S_u × S_v) | ADVANCED_FACE |
| Conchiglia | insieme di facce connesso; un guscio chiuso delimita 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"]} Curve e superfici
I tipi analitici utilizzano le parametrizzazioni STEP (ISO 10303-42), quindi i volti letti e scritti in STEP mantengono i propri parametri.
| Tipo | Parametrizzazione |
|---|---|
| linea | C(t) = O + t·d, d unità, t lunghezza dell'arco |
| cerchio | C(t) = O + r(cos t·x + sin t·y) |
| ellisse | C(t) = O + a cos t·x + b sin t·y |
| aereo | S(u,v) = O + u·x + v·y |
| cilindro | S(u,v) = O + r(cos u·x + sin u·y) + v·z |
| cono | S(u,v) = O + (R + v tan α)(cos u·x + sin u·y) + v·z |
| sfera | S(u,v) = O + r cos v(cos u·x + sin u·y) + r sin v·z |
| toro | S(u,v) = O + (R + r cos v)(cos u·x + sin u·y) + r sin v·z |
| rivoluzione | S(u,v) = rotate(C(v), axis, u) |
| estrusione | S(u,v) = C(u) + v·d |
| nurbs | curva o superficie razionale B-spline (algoritmi Piegl e Tiller in nurbs.ts) |
Booleani esatti
- Intersecare. Bordi di ciascun solido contro le facce dell'altro (punti esatti di Newton), bordi che giacciono sulle superfici dell'altro solido e curve di intersezione di ogni coppia di facce non coincidenti, rifinite su entrambe le superfici e riconosciute come linee e cerchi, altrimenti adattate come B-spline cubiche all'interno della tolleranza di adattamento.
- Impronta. Ogni punto di intersezione diventa un vertice in un registro per entrambi i solidi, i bordi vengono divisi lì e ciascuna faccia viene tagliata dalle curve su di essa attraverso una disposizione planare nel suo dominio (u, v).
- Classificare. Un punto all'interno di ciascun frammento si trova contro l'altro solido: dentro, fuori o sopra con lo stesso orientamento o opposto.
- Cucire. I frammenti vengono mantenuti secondo le regole dell'operazione, i pezzi coincidenti diventano un bordo, i vicini complanari si uniscono e il risultato viene convalidato. Un risultato che non è un solido collettore chiuso lancia
BooleanError; non viene mai restituito.
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 Proprietà di massa
Volume, area, baricentro e tensore d'inerzia (densità unitaria, attorno al baricentro, riga maggiore) derivano dal teorema della divergenza sulle facce di confine. Le facce planari sono integrate esattamente dal teorema di Green lungo le curve esatte dei bordi; le facce curve sono integrate su una tassellatura a fasi parametriche della superficie esatta.
| Corpo | massProperties | Forma chiusa |
|---|---|---|
| scatola − Ø12 foro, volume | 34303.53996706151 | 34303.539967061515 |
| stesso, zona | 8139.292006587684 | 8139.292006587698 |
| stesso, baricentro | (30.000, 20.000, 7.500) | (30, 20, 7.5) |
| sfera r10, volume | 4188.790204786379 | 4188.790204786391 |
| toro 20/5, volume | 9869.60440109475 | 9869.604401089358 |
| piatto filettato, 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.
Raccordi, smussi e riconoscimento fori
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> Sul corpo scatola − cilindro c'erano 14 candidati blend; selectBlendEdges(c, { parallel: "z" }) ho scelto i 4 bordi esterni verticali e blendBrep(b, sel, 4) compilato tutti i 4 senza rifiutare nessuno in 94 ms. Il buco si leggeva solo dai volti:
[{"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]}]}] Le forme sono simple, counterbore e countersink; i fondi sono through, flat e drill-point. Il riconoscimento legge i volti, non la cronologia, quindi un'importazione STEP, un risultato booleano e una parte parametrica vengono riconosciuti allo stesso modo.
Tassellatura a tenuta stagna
Ogni bordo viene campionato una volta sulla sua curva esatta e ogni faccia che lo utilizza condivide questi campioni, quindi la rete saldata non presenta crepe. Le facce vengono triangolate da Delaunay vincolato nel loro dominio (u, v).
| Opzione | Predefinito | Senso |
|---|---|---|
| chordTol | 1/2000 della diagonale del modello, fissato a [0.001, 0.05] mm | distanza massima tra mesh e superficie esatta |
| angleTolDeg | 15 | virata normale massima attraverso un triangolo (0 disabilita) |
| maxEdge | 0 (nessuno) | target di lunghezza del bordo |
| maxPointsPerFace | 200 000 | tappo di sicurezza |
| paramStep | — | modalità di integrazione utilizzata da massProperties |
Per il piatto filettato defaultChordTol ha restituito 0.0368 mm e tessellateBrep ha prodotto 652 triangoli più mesh per faccia, polilinee di bordo e avvisi.
Scambio PASSO
writeStepBreps scrive un file AP214 (AUTOMOTIVE_DESIGN) in millimetri e radianti, un ADVANCED_BREP_SHAPE_REPRESENTATION per parte. readStepBreps legge la geometria e la topologia AP203, AP214 e AP242, inclusi gli assiemi con le relative trasformazioni e nomi di prodotto. Vengono segnalate entità sconosciute warnings e i loro volti saltarono; nulla è indovinato.
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 rilettura di quel file ha dato una parte il cui volume era 34097.52220392303 mm³, pari al corpo scritto a 11 cifre significative.
Budget temporale
Il kernel è sincrono e viene eseguito sul thread del chiamante. withBudget(ms, f) fissa una scadenza; chiamata di cicli lunghi (coppie di facce di un booleano, suddivisione delle facce, intersezione di superfici, tassellatura). checkBudget, che lancia BudgetExceeded. I budget nidificati mantengono la scadenza precedente; senza budget un assegno costa un confronto.
withBudget(1, () => booleanBrep(makeSphere(10), makeBox(10, 10, 10), "union"))
// BudgetExceeded: the exact model exceeded its time budget of 1 ms Risoluzione dei problemi
| Sintomo | Causa | Aggiustare |
|---|---|---|
BooleanError | il risultato cucito non è un solido collettore chiuso (facce tangenti o quasi coincidenti) | spostare un operando leggermente fuori dalla tangenza; controlla prima entrambi con validateBrep |
BudgetExceeded | l'operazione ha richiesto più tempo del suo budget | semplificare o assegnare al chiamante un budget maggiore |
| RangeError da una primitiva | dimensione non positiva o toro minore ≥ maggiore | per esempio. "il raggio minore del toro deve essere più piccolo del raggio maggiore" |
sfumare il bordo rejected | faccia troppo stretta per il raggio, il bordo del coltello o la parete inclinata | raggio più piccolo o uno smusso |
| Facce mancanti della parte STEP | entità non supportata nel file | leggere warnings da readStepBreps |
| validateBrep segnala problemi | indice, orientamento o errore del bordo sulla superficie in un corpo costruito | l'emissione nomina l'entità; nulla viene riparato automaticamente |