Zum Inhalt springen
CADCAMFUN
Doku

Dokumentation

Exakter B-Rep-Kernel

Exakte Grenzdarstellung: analytische und NURBS-Geometrie, Boolesche Werte, Verrundungen, Locherkennung, Masseneigenschaften, Validierung, Tessellation und STEP.

Automatisch aus dem Englischen übersetzt. Englisches Original ansehen

Was der B-Rep-Kernel ist

Der genaue Kernel in packages/core/src/cad/brep (24 Quelldateien, etwa 8 660 Zeilen, plus Tests) stellt Körper anhand ihrer genauen Grenze dar: analytische und NURBS-Oberflächen, getrimmt durch Schleifen exakter Kanten. Alles besteht aus einfachen Daten und reinen Funktionen, daher wird ein B-Rep in JSON serialisiert, überschreitet eine Worker-Grenze und ändert sich unverändert im Projektverlauf. Boolesche Werte, Verrundungen und Fasen, Locherkennung, Masseneigenschaften, Validierung, wasserdichte Tessellation und STEP-Austausch funktionieren alle auf dieser einen Struktur.

Exakte Platte nach Subtrahieren und Verrunden Zum Orbit ziehen · zum Zoomen scrollen · zum Schwenken mit der rechten Maustaste ziehen
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³.

Topologietabellen

A Brep ist eine Reihe von Indextabellen. Entitäten verweisen aufeinander über einen Index, niemals über einen Objektverweis.

Juristische PersonHältSTEP-Gegenstück
Scheitelpunkt, ToleranzVERTEX_POINT
Randexact curve, [t0, t1] with t0 < t1, v0 = C(t0), v1 = C(t1), toleranceEDGE_CURVE
Coedgeeine Verwendung einer Kante durch eine Schleife: Kantenindex, umgekehrt, optionale p-Kurve in der Fläche (u, v)ORIENTED_EDGE + PCURVE
Schleifegeschlossener Kreislauf von Kanten; Material links von außen gesehen (äußere CCW, Löcher CW)EDGE_LOOP
Gesichtbereich einer Oberfläche; umgekehrt bedeutet, dass die äußere Normale −(S_u × S_v) ist.ADVANCED_FACE
Hülseverbundener Satz von Gesichtern; Eine geschlossene Hülle begrenzt ein VolumenCLOSED_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.

Anzahl der Grundelemente – tatsächliche Ausgabe
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"]}

Kurven und Flächen

Analysetypen verwenden die STEP-Parametrisierung (ISO 10303-42), sodass aus STEP gelesene und in STEP geschriebene Gesichter ihre Parameter behalten.

TypParametrierung
linieC(t) = O + t·d, d-Einheit, t Bogenlänge
kreisC(t) = O + r(cos t·x + sin t·y)
ellipseC(t) = O + a cos t·x + b sin t·y
flugzeugS(u,v) = O + u·x + v·y
zylinderS(u,v) = O + r(cos u·x + sin u·y) + v·z
kegelS(u,v) = O + (R + v tan α)(cos u·x + sin u·y) + v·z
kugelS(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
revolutionS(u,v) = rotate(C(v), axis, u)
extrusionS(u,v) = C(u) + v·d
nurbsrationale B-Spline-Kurve oder -Oberfläche (Piegl & Tiller-Algorithmen in nurbs.ts)
Exakte Grundelemente, mosaikiert Zum Orbit ziehen · zum Zoomen scrollen · zum Schwenken mit der rechten Maustaste ziehen
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.
Torus R20 r5 Zum Orbit ziehen · zum Zoomen scrollen · zum Schwenken mit der rechten Maustaste ziehen
makeTorus(20, 5): eine einzelne toroidale Fläche mit einer Naht und keinen anderen Kanten, mosaikiert bei chordTol 1 und 30°. Das genaue Volumen 2π²Rr² = 9 869.604 mm³ ist das, was massProperties zurückgibt.

Exakte Boolesche Werte

  1. Schneiden. Kanten jedes Volumenkörpers gegenüber den Flächen des anderen (genaue Punkte nach Newton), Kanten, die auf den Oberflächen des anderen Volumenkörpers liegen, und die Schnittkurven jedes Paares nicht zusammenfallender Flächen, verfeinert auf beiden Oberflächen und erkannt als Linien und Kreise, ansonsten innerhalb der Anpassungstoleranz als kubische B-Splines angepasst.
  2. Impressum. Jeder Schnittpunkt wird zu einem Scheitelpunkt in einem Register für beide Körper, Kanten werden dort geteilt und jede Fläche wird durch die darauf befindlichen Kurven durch eine planare Anordnung in ihrem (u, v)-Bereich geschnitten.
  3. Klassifizieren. Ein Punkt innerhalb jedes Fragments liegt gegenüber dem anderen Festkörper: innen, außen oder auf derselben oder entgegengesetzten Ausrichtung.
  4. Nähen. Fragmente werden durch die Regeln der Operation beibehalten, zusammenfallende Teile werden zu einer Kante, koplanare Nachbarn verschmelzen und das Ergebnis wird validiert. Ein Ergebnis, das kein geschlossener Mannigfaltigkeitskörper ist BooleanError; es wird nie zurückgegeben.
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 }
}
Box minus Zylinder – reale Leistung
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

Masseneigenschaften

Volumen, Fläche, Schwerpunkt und der Trägheitstensor (Einheitsdichte, um den Schwerpunkt, Hauptreihe) ergeben sich aus dem Divergenzsatz über die Grenzflächen. Planare Flächen werden nach dem Satz von Green entlang der exakten Kantenkurven exakt integriert; Gekrümmte Flächen werden auf einer Parameterschritt-Tessellation der exakten Oberfläche integriert.

KörpermassPropertiesGeschlossenes Formular
box − Ø12 Loch, Volumen34303.5399670615134303.539967061515
gleich, Bereich8139.2920065876848139.292006587698
gleich, Schwerpunkt(30.000, 20.000, 7.500)(30, 20, 7.5)
kugel r10, Volumen4188.7902047863794188.790204786391
torus 20/5, Volumen9869.604401094759869.604401089358
filetierter Teller, Volumen34097.5222039230234097.522203923065

The filleted-plate closed form is the subtracted plate minus four corner slivers of (r² − πr²/4)·h = (16 − 4π)·15 each.

Erkennung von Verrundungen, Fasen und Löchern

Unterschriften
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>

Auf dem Kasten-Zylinder-Körper befanden sich 14 Mischungskandidaten; selectBlendEdges(c, { parallel: "z" }) wählte die 4 vertikalen Außenkanten aus und blendBrep(b, sel, 4) alle 4 wurden in 94 ms filetiert und keiner wurde abgelehnt. Das Loch las allein aus den Gesichtern zurück:

recognizeHoles – echte Ausgabe
[{"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]}]}]

Formen sind simple, counterbore und countersink; böden sind through, flat und drill-point. Die Erkennung liest Gesichter, nicht den Verlauf, sodass ein STEP-Import, ein boolesches Ergebnis und ein parametrischer Teil gleichermaßen erkannt werden.

Wasserdichte Tessellation

Jede Kante wird einmal auf ihrer exakten Kurve abgetastet und jede Fläche, die sie verwendet, teilt diese Proben, sodass das geschweißte Netz keine Risse aufweist. Gesichter werden durch eingeschränktes Delaunay in ihrem (u, v)-Bereich trianguliert.

OptionStandardBedeutung
chordTol1/2000 der Modelldiagonale, eingespannt auf [0.001, 0.05] mmmaximaler Abstand zwischen Netz und exakter Oberfläche
angleTolDeg15maximale normale Drehung über ein Dreieck (0 deaktiviert)
maxEdge0 (keine)kantenlängenziel
maxPointsPerFace200 000sicherheitskappe
paramStep—von massProperties verwendeter Integrationsmodus

Für den filetierten Teller defaultChordTol gab 0.0368 mm zurück und tessellateBrep erzeugte 652 Dreiecke plus Flächennetze, Kantenpolylinien und Warnungen.

STEP-Austausch

writeStepBreps schreibt eine AP214 (AUTOMOTIVE_DESIGN)-Datei in Millimetern und Bogenmaß, eine ADVANCED_BREP_SHAPE_REPRESENTATION pro Teil. readStepBreps liest die Geometrie und Topologie von AP203, AP214 und AP242, einschließlich Baugruppen mit ihren Transformationen und Produktnamen. Unbekannte Entitäten werden in gemeldet warnings und ihre Gesichter hüpften; nichts wird erraten.
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.));

Das Zurücklesen dieser Datei ergab einen Teil mit einem Volumen von 34097,52220392303 mm³, was dem geschriebenen Text mit 11 signifikanten Ziffern entspricht.

Zeitbudget

Der Kernel ist synchron und läuft im Thread des Aufrufers. withBudget(ms, f) legt eine Frist fest; Aufruf von langen Schleifen (Flächenpaare eines Booleschen Werts, Flächenaufteilung, Flächenschnittpunkt, Tessellation). checkBudget, was wirft BudgetExceeded. Bei verschachtelten Budgets bleibt die frühere Frist erhalten; Ohne Budget kostet ein Scheck einen Vergleich.

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

Fehlerbehebung

SymptomUrsacheFix
BooleanErrordas genähte Ergebnis ist kein geschlossener Mannigfaltigkeitskörper (tangentiale oder nahezu zusammenfallende Flächen).einen Operanden leicht von der Tangentialität verschieben; Überprüfen Sie beide zuerst mit validateBrep
BudgetExceededdie Operation dauerte länger als vorgesehenvereinfachen oder dem Anrufer ein größeres Budget zur Verfügung stellen
RangeError von einem Grundelementnicht positive Größe oder kleinerer Torus ≥ großerz.B. „Der kleinere Radius des Torus muss kleiner sein als der große Radius.“
rand einblenden rejectedfläche zu schmal für Radius, Messerkante oder schräge Wandkleinerer Radius oder eine Fase
Im STEP-Teil fehlen Flächennicht unterstützte Entität in der Dateilesen warnings von readStepBreps
validateBrep meldet Problemeindex-, Orientierungs- oder Kante-auf-Oberfläche-Fehler in einem gebauten Körperdas Problem benennt die Entität; nichts wird automatisch repariert