Dokumentation
Mesh- und CSG-Kernel
Geschlossene Dreiecksnetze aus parametrischen Festkörpern, BSP-Boolesche Werte mit konvexem Schnellpfad, Bereinigung und Topologieprüfungen.
Automatisch aus dem Englischen übersetzt. Englisches Original ansehen
Was ist der Mesh-Kernel?
Der Mesh-Kernel arbeitet mit geschlossenen Dreiecksnetzen: Er baut sie aus parametrischen Grundelementen auf (meshOf), misst sie (meshVolume, meshBounds, meshTopology) und kombiniert sie mit Booleschen Werten (booleanMesh, booleanAll). Es geht darum, was das Ansichtsfenster zeigt, was die CAM-Generatoren bearbeiten und was der STL-Export schreibt.
Es handelt sich nicht um eine exakte Grenzdarstellung. Ein geschnittener Zylinder bleibt ein facettierter Zylinder und es gibt keine Flächentopologie zum Verrunden oder Messen. Für exakte Flächen, Verrundungen, Masseneigenschaften und STEP, die B-Rep-Kernel ist ein separater Code.
| Datei | Linien | Rolle |
|---|---|---|
cad/solid.ts | 659 | Volumenschemata (Box, Zylinder, Kugel, Kegel, Torus, Extrudieren, Drehen), meshOf, meshVolume, meshBounds |
cad/csg.ts | 459 | BSP Boolesche Werte, konvexer Klassifikator, übersetzen/drehen/zusammenführen |
cad/mesh-clean.ts | 626 | schweißen, Reparatur von T-Verbindungen, koplanare Zusammenführung, erneute Triangulation |
cad/mesh-topology.ts | 110 | mannigfaltigkeit, Schalen, Gattung, Volumen, Fläche |
cad/triangulate.ts | 383 | polygon-mit-Löcher-Triangulation |
Der Mesh-Typ und die Grundelemente
export interface Mesh {
readonly positions: Float32Array // x, y, z per vertex
readonly indices: Uint32Array // three per triangle, counter-clockwise seen from outside
}
export const meshOf: (solid: Solid, tolerance?: number /* 0.1 mm */) => Mesh
export const meshVolume: (mesh: Mesh) => number // signed; positive when outward-facing
export const meshBounds: (mesh: Mesh) => SolidBounds | Solide | Felder | Grenzen |
|---|---|---|
| Kasten | ursprung, Größe {x, y, z} | größen > 0 |
| Zylinder | ursprung, Radius, Höhe, Segmente, Achse? | segmente 3–512; Achse z | x | j |
| Kugel | mittelpunkt, Radius, Ringe | ringe 2–256 |
| Kegel | ursprung, Basisradius, Topradius, Höhe, Segmente, Achse? | topRadius ≥ 0; Segmente 3–512 |
| Torus | zentrum, Hauptradius, Nebenradius, Drehung?, Hauptsegmente, Nebensegmente, Achse? | 3–512 und 3–256 |
| Extrudieren | profil (≥ 3 Punkte, nicht geschlossen), Höhe, Ursprung? | profil in XY |
| Drehen | profil (≥ 2 Punkte in XZ), Winkel, Segmente? | über Z; Segmente 3–512, Standard 16 |
segments und rings sind Mindestwerte: meshOf hebt sie an, bis der Akkordfehler innerhalb liegt tolerance, using step = 4·asin(√(min(1, tol/r)/2)). Two budgets stop runaway tolerances.
| Bewachen | Wert | Fehlermeldung |
|---|---|---|
| die Toleranz muss positiv und endlich sein | — | Die Netztoleranz muss positiv und endlich sein |
| segmente pro Kurve | 65 536 | Die Netztoleranz übersteigt das Unterteilungsbudget |
| gitterzeilen × Spalten (Kugel, Torus, Drehung) | 1 000 000 | Die Netztoleranz überschreitet das Scheitelpunktbudget |
Ein Ø6 Zylinder mit segments: 24 bei der Toleranz 0.05 ergab 96 Dreiecke (24 Seiten, zwei 24-Eckkappen); ein Ø20 mit 128, da der größere Radius 32 Segmente benötigte, um innerhalb von 0.05 mm zu bleiben.
Boolesche Werte durch binäre Raumpartitionierung
Jeder Operand wird zu einem Klassifikator. Ein allgemeines Netz erhält einen BSP-Baum; Ein konvexes Netz (geschlossen, verbunden, jede Kante konvex) besteht nur aus seinen unterschiedlichen Flächenebenen. Ein Kasten besteht also aus sechs Ebenen und eine Kugel aus zehntausend Dreiecken wird klassifiziert, ohne die quadratische Kette zu bilden, zu der ein BSP eines konvexen Körpers degeneriert. Polygone werden als Listen klassifiziert, und ein Polygon, das sich außerhalb des Begrenzungsrahmens des anderen Operanden befindet, wird beibehalten oder gelöscht, ohne dass etwas passiert.
- If either mesh is empty, or the bounding boxes do not meet (within tolerance), answer directly: union = merge, subtract = a, intersect = empty.
- Erstellen Sie die Klassifikatoren von A und B (konvexe Ebenen oder BSP).
- Vereinigung: Halten Sie A außerhalb von B, B außerhalb von A und legen Sie die Flächen von B so ab, dass sie mit denen von A übereinstimmen, die in die gleiche Richtung zeigen, sodass eine gemeinsame Fläche einmal erhalten bleibt.
- Subtract and intersect follow the classic a.clipTo(b), b.clipTo(a), b.invert() sequence on polygon lists, without copying trees.
- Reinigen Sie die Polygonsuppe: Schweißen Sie Punkte innerhalb von max(10·eps, 1e-9·size, schließen Sie T-Verbindungen, schließen Sie Lücken von bis zu 1e-4·size zwischen Splittern, fügen Sie koplanare Fragmente zusammen und triangulieren Sie erneut.
export type BooleanOp = "union" | "subtract" | "intersect"
export interface CsgOptions {
/** Distance below which a point counts as on a plane, mm. Default 1e-7 × the larger extent. */
readonly tolerance?: number
/** Merge coplanar fragments and re-triangulate (default true). */
readonly mergeCoplanar?: boolean
}
export const booleanMesh: (a: Mesh, b: Mesh, op: BooleanOp, options?: CsgOptions) => Mesh
/** Union reduced as a balanced tree; subtract and intersect fold left to right. */
export const booleanAll: (meshes: ReadonlyArray<Mesh>, op: BooleanOp, options?: CsgOptions) => Mesh
export const translateMesh: (mesh: Mesh, dx: number, dy: number, dz: number) => Mesh
export const rotateMesh: (mesh: Mesh, axis: V3, radians: number, origin?: V3) => Mesh
export const mergeMeshes: (meshes: ReadonlyArray<Mesh>) => Mesh Die Anzahl der Dreiecke wächst mit den Features, nicht mit der Anzahl der Booleschen Werte: Der Zusammenführungsschritt fügt koplanare Splitter wieder zu ganzen Flächen zusammen. In der Abbildung oben hatte der Kasten 12 Dreiecke, nach vier Löchern 412, nach der Nabe 540, nach der Bohrung 640; Die gesamte Kette lief in 96 ms.
Vereinigung, Subtraktion, Schnittmenge bei gekrümmter Eingabe
A 20 mm cube at the origin against a sphere of radius 12 centred on its far corner (20, 20, 20), meshed at tolerance 0.2 (624 triangles). Real volumes:
| Ergebnis | Volumen, mm³ | Dreiecke |
|---|---|---|
| kugel allein | 7 063.84 (genau 7 238.23) | 624 |
| würfel ∩ Kugel | 882.98 | 112 |
| würfel ∪ Kugel | 14 180.86 | — |
| würfel − Kugel | 7 117.02 | — |
Überprüfen Sie: 8 000 + 7 063.84 − 882.98 = 14 180.86 und 8 000 − 882.98 = 7 117.02, sodass die drei Ergebnisse miteinander konsistent sind Hundertstel. Das Kugelnetz selbst liegt 2.4 % unter der exakten Kugel, was der Facettierung einer groben Toleranz und nicht einem booleschen Fehler entspricht.
Topologieprüfung
meshTopology zählt Eckpunkte, Kanten und Dreiecke, findet Randkanten, nicht-mannigfaltige und fehlorientierte Kanten, degenerierte Dreiecke und Schalen und leitet Euler-Merkmale und Gattungen ab. describeTopology druckt die einzeilige Zusammenfassung, die der Assistent und das Ansichtsfenster verwenden.
{"vertices":312,"triangles":640,"edges":960,"boundaryEdges":0,"nonManifoldEdges":0,
"misorientedEdges":0,"degenerateTriangles":0,"shells":1,"eulerCharacteristic":-8,"genus":5,
"closed":true,"solid":true,"volume":23981.43509870267,"area":8238.640705862534}
// describeTopology → "closed solid, 1 shell, genus 5, 640 triangles, V 23981.4 mm³, A 8238.6 mm²" V − E + F = 312 − 960 + 640 = −8 = 2 − 2g, so g = 5: the four drilled holes plus the bore, which runs through the boss and the plate.
Polygon-Triangulation
triangulatePolygon(outer, holes) gibt Indextripel in die Verkettung des Außenrings und der Löcher zurück. Ein 4 × 4-Quadrat mit einem 2 × 2-Loch ergibt acht Dreiecke:
triangulatePolygon(
[{x:0,y:0},{x:4,y:0},{x:4,y:4},{x:0,y:4}],
[[{x:1,y:1},{x:1,y:3},{x:3,y:3},{x:3,y:1}]])
// [[0,4,5],[7,4,0],[3,0,5],[7,0,1],[2,3,5],[6,7,1],[2,5,6],[6,1,2]] triangulatePolygonChecked kehrt zurück undefined anstelle eines Teilergebnisses, wenn die Eingabe nicht trianguliert werden kann (sich selbst schneidende Ringe, Löcher außerhalb des äußeren Rings).
Fehlerbehebung
| Symptom | Ursache | Fix |
|---|---|---|
| Das boolesche Ergebnis weist Löcher oder umgekehrte Flächen auf | ein Eingang ist offen oder im Uhrzeigersinn gewickelt | überprüfen Sie beide Eingaben mit meshTopology: BoundaryEdges und misorientedEdges müssen 0 sein. |
| eine von beiden Operanden geteilte Fläche fehlt oder ist doppelt vorhanden | die Flächen stimmen nahezu, aber nicht genau überein (weiter voneinander entfernt als die Toleranz). | rasten Sie die Operanden auf derselben Ebene ein oder erhöhen Sie CsgOptions.tolerance |
| RangeError: Netztoleranz überschreitet Unterteilungsbudget | toleranz viel zu klein für den Radius | verwenden Sie die Toleranzvoreinstellungen (0.1 bis 0.0005 mm) |
| volumen weicht von der Formel ab | facettierung bei grober Toleranz | machen Sie ein feineres Netz oder verwenden Sie den B-Rep-Kernel für exakte Masseneigenschaften |
| Boolescher Wert langsam bei vielen Tools | vereinigung der zuerst gebauten Werkzeuge | subtrahieren Sie die Werkzeuge einzeln (booleanAll bewirkt dies): Jedes konvexe Werkzeug ist eine Handvoll Ebenen |