Aller au contenu
CADCAMFUN
Docs

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époserLignesRôle
cad/solid.ts659Schémas solides (Boîte, Cylindre, Sphère, Cône, Torus, Extrude, Revolve), meshOf, meshVolume, meshBounds
cad/csg.ts459Booléens BSP, classificateur convexe, traduction/rotation/fusion
cad/mesh-clean.ts626soudure, réparation de jonction en T, fusion coplanaire, retriangulation
cad/mesh-topology.ts110collecteur, coquilles, genre, volume, superficie
cad/triangulate.ts383triangulation polygonale avec trous
Plaque percée avec un bossage alésé Faites glisser vers l'orbite · faites défiler pour zoomer · faites glisser vers la droite pour effectuer un panoramique
Sortie réelle de booleanMesh : une boîte 60 × 40 × 10 moins quatre trous Ø6 (soustraction booleanAll), unis avec un bossage Ø20 × 8, puis percé Ø10 à travers. 640triangles ; meshTopology rapporte un solide fermé, une coque 1, un genre 5, V 23981.4 mm³.

Le type Mesh et les primitives

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
SolideChampsLimites
Boîteorigine, taille {x, y, z}tailles > 0
Cylindreorigine, rayon, hauteur, segments, axe ?segments 3–512 ; axe z | X | oui
Sphèrecentre, rayon, anneauxanneaux 2–256
Côneorigine, baseRadius, topRadius, hauteur, segments, axe ?rayon supérieur ≥ 0 ; segments 3–512
Toruscentre, majorRadius, mineurRadius, rotation ?, majorSegments, mineurSegments, axe ?3–512 et 3–256
Extruderprofil (≥ 3 points, non fermé), hauteur, origine ?profil en XY
Tournerprofil (≥ 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.
GardeValeurMessage d'erreur
la tolérance doit être positive et finie—La tolérance du maillage doit être positive et finie
segments par courbe65 536La tolérance du maillage dépasse le budget du lotissement
lignes de la grille × colonnes (sphère, tore, révolution)1 000 000La 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.

  1. If either mesh is empty, or the bounding boxes do not meet (within tolerance), answer directly: union = merge, subtract = a, intersect = empty.
  2. Construisez les classificateurs de A et B (plans convexes ou BSP).
  3. 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.
  4. Subtract and intersect follow the classic a.clipTo(b), b.clipTo(a), b.invert() sequence on polygon lists, without copying trees.
  5. 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.
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

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ésultatVolume, mm³Triangles
sphère seule7 063.84 (exactement 7 238.23)624
cube ∩ sphère882.98112
cube ∪ sphère14 180.86—
cube − sphère7 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.

cube − sphère Faites glisser vers l'orbite · faites défiler pour zoomer · faites glisser vers la droite pour effectuer un panoramique
Résultat de la soustraction : le cube avec une huitième sphère creusée dans son coin.
cube ∩ sphère Faites glisser vers l'orbite · faites défiler pour zoomer · faites glisser vers la droite pour effectuer un panoramique
Résultat de l'intersection : le huitième de la sphère qui se trouve à l'intérieur du cube.

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.
meshTopology (bored) - sortie réelle
{"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 :
Sortie réelle
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ômeCauseRéparer
Le résultat booléen comporte des trous ou des faces inverséesune entrée est ouverte ou enroulée dans le sens des aiguilles d'une montrevé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 subdivisiontolérance beaucoup trop fine pour le rayonutilisez les préréglages de tolérance (0.1 à 0.0005 mm)
le volume diffère de la formulefacettage à tolérance grossièremaillez plus finement, ou utilisez le noyau B-rep pour les propriétés de masse exactes
Booléen lent sur de nombreux outilsunion d'outils construits en premiersoustraire les outils un par un (booleanAll fait cela) : chaque outil convexe est une poignée de plans