Zum Inhalt springen
CADCAMFUN
Doku

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.

DateiLinienRolle
cad/solid.ts659Volumenschemata (Box, Zylinder, Kugel, Kegel, Torus, Extrudieren, Drehen), meshOf, meshVolume, meshBounds
cad/csg.ts459BSP Boolesche Werte, konvexer Klassifikator, übersetzen/drehen/zusammenführen
cad/mesh-clean.ts626schweißen, Reparatur von T-Verbindungen, koplanare Zusammenführung, erneute Triangulation
cad/mesh-topology.ts110mannigfaltigkeit, Schalen, Gattung, Volumen, Fläche
cad/triangulate.ts383polygon-mit-Löcher-Triangulation
Gebohrte Platte mit gebohrtem Vorsprung Zum Orbit ziehen · zum Zoomen scrollen · zum Schwenken mit der rechten Maustaste ziehen
Echte BooleanMesh-Ausgabe: ein 60 × 40 × 10-Kasten minus vier Ø6-Löcher (booleanAll subtract), vereint mit einem Ø20 × 8-Vorsprung, dann durchgebohrt Ø10. 640 Dreiecke; meshTopology meldet einen geschlossenen Körper, 1 Schale, Gattung 5, V 23981.4 mm³.

Der Mesh-Typ und die Grundelemente

solid.ts
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
SolideFelderGrenzen
Kastenursprung, Größe {x, y, z}größen > 0
Zylinderursprung, Radius, Höhe, Segmente, Achse?segmente 3–512; Achse z | x | j
Kugelmittelpunkt, Radius, Ringeringe 2–256
Kegelursprung, Basisradius, Topradius, Höhe, Segmente, Achse?topRadius ≥ 0; Segmente 3–512
Toruszentrum, Hauptradius, Nebenradius, Drehung?, Hauptsegmente, Nebensegmente, Achse?3–512 und 3–256
Extrudierenprofil (≥ 3 Punkte, nicht geschlossen), Höhe, Ursprung?profil in XY
Drehenprofil (≥ 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.
BewachenWertFehlermeldung
die Toleranz muss positiv und endlich sein—Die Netztoleranz muss positiv und endlich sein
segmente pro Kurve65 536Die Netztoleranz übersteigt das Unterteilungsbudget
gitterzeilen × Spalten (Kugel, Torus, Drehung)1 000 000Die 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.

  1. If either mesh is empty, or the bounding boxes do not meet (within tolerance), answer directly: union = merge, subtract = a, intersect = empty.
  2. Erstellen Sie die Klassifikatoren von A und B (konvexe Ebenen oder BSP).
  3. 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.
  4. Subtract and intersect follow the classic a.clipTo(b), b.clipTo(a), b.invert() sequence on polygon lists, without copying trees.
  5. 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.
csg.ts
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:

ErgebnisVolumen, mm³Dreiecke
kugel allein7 063.84 (genau 7 238.23)624
würfel ∩ Kugel882.98112
würfel ∪ Kugel14 180.86—
würfel − Kugel7 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.

würfel − Kugel Zum Orbit ziehen · zum Zoomen scrollen · zum Schwenken mit der rechten Maustaste ziehen
Ergebnis subtrahieren: der Würfel mit einer Achtelkugel aus seiner Ecke.
würfel ∩ Kugel Zum Orbit ziehen · zum Zoomen scrollen · zum Schwenken mit der rechten Maustaste ziehen
Schnittergebnis: das Achtel der Kugel, die im Würfel liegt.

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.
meshTopology(langweilig) – echte Ausgabe
{"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:
Echte Ausgabe
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

SymptomUrsacheFix
Das boolesche Ergebnis weist Löcher oder umgekehrte Flächen aufein 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 vorhandendie 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 Unterteilungsbudgettoleranz viel zu klein für den Radiusverwenden Sie die Toleranzvoreinstellungen (0.1 bis 0.0005 mm)
volumen weicht von der Formel abfacettierung bei grober Toleranzmachen Sie ein feineres Netz oder verwenden Sie den B-Rep-Kernel für exakte Masseneigenschaften
Boolescher Wert langsam bei vielen Toolsvereinigung der zuerst gebauten Werkzeugesubtrahieren Sie die Werkzeuge einzeln (booleanAll bewirkt dies): Jedes konvexe Werkzeug ist eine Handvoll Ebenen