Documentation
Noyau Mesh et CSG
Maillages triangulaires fermés à partir de solides paramétriques, booléens BSP avec un chemin rapide convexe, nettoyage et vérifications de topologie.
Traduit automatiquement de l'anglais. Voir l'original en anglais
Qu'est-ce que le noyau maillé
Le noyau de maillage travaille sur des maillages en triangles fermés : il les construit à partir de primitives paramétriques (meshOf), les mesure (meshVolume, meshBounds, meshTopology), et les combine avec des booléens (booleanMesh, booleanAll). C'est ce que montre la fenêtre d'affichage, ce que machinent les générateurs CAM et ce qu'écrit l'export STL.
Il ne s'agit pas d'une représentation exacte des limites. Un cylindre qui a été découpé reste un cylindre à facettes et il n'existe aucune topologie de face sur laquelle effectuer un congé ou mesurer. Pour les faces exactes, les congés, les propriétés de masse et STEP, le Noyau B-rep est un morceau de code distinct.
| Déposer | Lignes | Rôle |
|---|---|---|
cad/solid.ts | 659 | Schémas solides (Boîte, Cylindre, Sphère, Cône, Torus, Extrude, Revolve), meshOf, meshVolume, meshBounds |
cad/csg.ts | 459 | Booléens BSP, classificateur convexe, traduction/rotation/fusion |
cad/mesh-clean.ts | 626 | soudure, réparation de jonction en T, fusion coplanaire, retriangulation |
cad/mesh-topology.ts | 110 | collecteur, coquilles, genre, volume, superficie |
cad/triangulate.ts | 383 | triangulation polygonale avec trous |
Le type Mesh et les primitives
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 | Champs | Limites |
|---|---|---|
| Boîte | origine, taille {x, y, z} | tailles > 0 |
| Cylindre | origine, rayon, hauteur, segments, axe ? | segments 3–512 ; axe z | X | oui |
| Sphère | centre, rayon, anneaux | anneaux 2–256 |
| Cône | origine, baseRadius, topRadius, hauteur, segments, axe ? | rayon supérieur ≥ 0 ; segments 3–512 |
| Torus | centre, majorRadius, mineurRadius, rotation ?, majorSegments, mineurSegments, axe ? | 3–512 et 3–256 |
| Extruder | profil (≥ 3 points, non fermé), hauteur, origine ? | profil en XY |
| Tourner | profil (≥ 2 points dans XZ), angle, segments ? | à propos de Z ; segments 3–512, par défaut 16 |
segments et rings sont des minimums : meshOf les élève jusqu'à ce que l'erreur d'accord soit comprise tolerance, using step = 4·asin(√(min(1, tol/r)/2)). Two budgets stop runaway tolerances.
| Garde | Valeur | Message d'erreur |
|---|---|---|
| la tolérance doit être positive et finie | — | La tolérance du maillage doit être positive et finie |
| segments par courbe | 65 536 | La tolérance du maillage dépasse le budget du lotissement |
| lignes de la grille × colonnes (sphère, tore, révolution) | 1 000 000 | La tolérance du maillage dépasse le budget des sommets |
Un cylindre Ø6 avec segments: 24 à la tolérance 0.05 est sorti avec des triangles 96 (24 côtés, deux capuchons 24-gon) ; un Ø20 avec 128, car le rayon le plus grand nécessitait 32 segments pour rester dans 0.05 mm.
Booléens par partition binaire de l'espace
Chaque opérande devient un classificateur. Un maillage général obtient un arbre BSP ; un maillage convexe (fermé, connecté, chaque bord convexe) n'est que ses plans de face distincts, donc une boîte est composée de six plans et une sphère de dix mille triangles est classée sans construire la chaîne quadratique vers laquelle un BSP d'un solide convexe dégénère. Les polygones sont classés sous forme de listes, et un polygone dégagé du cadre de délimitation de l'autre opérande est conservé ou supprimé sans rien parcourir.
- If either mesh is empty, or the bounding boxes do not meet (within tolerance), answer directly: union = merge, subtract = a, intersect = empty.
- Construisez les classificateurs de A et B (plans convexes ou BSP).
- Union : gardez A à l'extérieur de B, B à l'extérieur de A et déposez les faces de B coïncidant avec celles de A pointant dans la même direction, afin qu'une face partagée soit conservée une fois.
- Subtract and intersect follow the classic a.clipTo(b), b.clipTo(a), b.invert() sequence on polygon lists, without copying trees.
- Nettoyez la soupe de polygones : points de soudure dans une taille maximale (10·eps, 1e-9·size), fermez les jonctions en T, comblez les espaces allant jusqu'à 1e-4·size entre les éclats, fusionnez les fragments coplanaires et re-triangulez.
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 Le nombre de triangles augmente avec les caractéristiques, pas avec le nombre de booléens : l'étape de fusion remet les éclats coplanaires en faces entières. Dans la plaque ci-dessus, la boîte avait 12 triangles, après quatre trous 412, après le bossage 540, après l'alésage 640 ; toute la chaîne s'est déroulée en 96 ms.
Union, soustraction, intersection sur une entrée courbe
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:
| Résultat | Volume, mm³ | Triangles |
|---|---|---|
| sphère seule | 7 063.84 (exactement 7 238.23) | 624 |
| cube ∩ sphère | 882.98 | 112 |
| cube ∪ sphère | 14 180.86 | — |
| cube − sphère | 7 117.02 | — |
Vérifiez : 8 000 + 7 063.84 − 882.98 = 14 180.86 et 8 000 − 882.98 = 7 117.02, donc les trois résultats sont cohérents les uns avec les autres centième. Le maillage de la sphère lui-même est 2,4 % sous la sphère exacte, qui est la facette d'une tolérance grossière, et non d'une erreur booléenne.
Vérification de la topologie
meshTopology compte les sommets, les arêtes et les triangles, trouve les arêtes limites, non variées et mal orientées, les triangles et les coques dégénérés, et dérive les caractéristiques et le genre d'Euler. describeTopology imprime le résumé d'une ligne utilisé par l'assistant et la fenêtre d'affichage.
{"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.
Triangulation de polygones
triangulatePolygon(outer, holes) renvoie les triples d'index dans la concaténation de l'anneau extérieur et des trous. Un carré 4 × 4 avec un trou 2 × 2 donne huit triangles :
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 retours undefined au lieu d'un résultat partiel lorsque l'entrée ne peut pas être triangulée (anneaux auto-entrecroisés, trous à l'extérieur de l'anneau extérieur).
Dépannage
| Symptôme | Cause | Réparer |
|---|---|---|
| Le résultat booléen comporte des trous ou des faces inversées | une entrée est ouverte ou enroulée dans le sens des aiguilles d'une montre | vérifiez les deux entrées avec meshTopology : borderEdges et misorientedEdges doivent être 0 |
| un visage partagé par les deux opérandes est manquant ou doublé | les visages coïncident presque mais pas exactement (plus éloignés que la tolérance) | alignez les opérandes sur le même plan ou augmentez CsgOptions.tolerance |
| RangeError : la tolérance du maillage dépasse le budget de la subdivision | tolérance beaucoup trop fine pour le rayon | utilisez les préréglages de tolérance (0.1 à 0.0005 mm) |
| le volume diffère de la formule | facettage à tolérance grossière | maillez plus finement, ou utilisez le noyau B-rep pour les propriétés de masse exactes |
| Booléen lent sur de nombreux outils | union d'outils construits en premier | soustraire les outils un par un (booleanAll fait cela) : chaque outil convexe est une poignée de plans |