Documentação
Kernel de malha e CSG
Malhas de triângulo fechado a partir de sólidos paramétricos, booleanos BSP com caminho rápido convexo, limpeza e verificações de topologia.
Traduzido automaticamente do inglês. Ver o original em inglês
O que é o kernel de malha
O kernel da malha funciona em malhas triangulares fechadas: ele as constrói a partir de primitivas paramétricas (meshOf), mede-os (meshVolume, meshBounds, meshTopology) e os combina com booleanos (booleanMesh, booleanAll). É o que a janela de visualização mostra, o que os geradores CAM maquinam e o que a exportação STL grava.
Não é uma representação exata dos limites. Um cilindro que foi cortado permanece um cilindro facetado e não há topologia de face para fazer filetes ou medições. Para faces exatas, filetes, propriedades de massa e STEP, o Kernel B-rep é um pedaço de código separado.
| Arquivo | Linhas | Papel |
|---|---|---|
cad/solid.ts | 659 | Esquemas sólidos (Caixa, Cilindro, Esfera, Cone, Toro, Extrusão, Revolução), meshOf, meshVolume, meshBounds |
cad/csg.ts | 459 | Booleanos BSP, classificador convexo, traduzir/girar/mesclar |
cad/mesh-clean.ts | 626 | solda, reparo de junção em T, fusão coplanar, retriangulação |
cad/mesh-topology.ts | 110 | variedade, conchas, gênero, volume, área |
cad/triangulate.ts | 383 | triangulação de polígono com buracos |
O tipo de malha e primitivas
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 | Sólido | Campos | Limites |
|---|---|---|
| Caixa | origem, tamanho {x, y, z} | tamanhos > 0 |
| Cilindro | origem, raio, altura, segmentos, eixo? | segmentos 3–512; eixo z | x | sim |
| Esfera | centro, raio, anéis | anéis 2–256 |
| Cone | origem, baseRadius, topRadius, altura, segmentos, eixo? | raio superior ≥ 0; segmentos 3–512 |
| Toro | centro, majorRadius, minorRadius, rotação?, majorSegments, minorSegments, eixo? | 3–512 e 3–256 |
| Extrusão | perfil (≥ 3 pontos, não fechado), altura, origem? | perfil em XY |
| Girar | perfil (≥ 2 pontos em XZ), ângulo, segmentos? | sobre Z; segmentos 3–512, padrão 16 |
segments e rings são mínimos: meshOf aumenta-os até que o erro do acorde esteja dentro tolerance, using step = 4·asin(√(min(1, tol/r)/2)). Two budgets stop runaway tolerances.
| Guarda | Valor | Mensagem de erro |
|---|---|---|
| a tolerância deve ser positiva e finita | — | A tolerância da malha deve ser positiva e finita |
| segmentos por curva | 65 536 | A tolerância da malha excede o orçamento da subdivisão |
| linhas da grade × colunas (esfera, toro, revolução) | 1 000 000 | A tolerância da malha excede o orçamento do vértice |
Um cilindro Ø6 com segments: 24 na tolerância 0.05 saiu com 96 triângulos (24 lados, dois 24-gon caps); um Ø20 com 128, porque o raio maior precisava de 32 segmentos para ficar dentro de 0.05 mm.
Booleanos por particionamento de espaço binário
Cada operando se torna um classificador. Uma malha geral obtém uma árvore BSP; uma malha convexa (fechada, conectada, cada aresta convexa) é apenas seus planos de face distintos, então uma caixa tem seis planos e uma esfera de dez mil triângulos é classificada sem construir a cadeia quadrática para a qual um BSP de um sólido convexo degenera. Os polígonos são classificados como listas, e um polígono livre da caixa delimitadora do outro operando é mantido ou descartado sem percorrer nada.
- If either mesh is empty, or the bounding boxes do not meet (within tolerance), answer directly: union = merge, subtract = a, intersect = empty.
- Construa os classificadores de A e B (planos convexos ou BSP).
- União: mantenha A fora de B, B fora de A e descarte as faces de B coincidentes com as de A apontando na mesma direção, de modo que uma face compartilhada seja mantida uma vez.
- Subtract and intersect follow the classic a.clipTo(b), b.clipTo(a), b.invert() sequence on polygon lists, without copying trees.
- Limpe a sopa de polígonos: solde pontos dentro do tamanho máximo (10·eps, 1e-9·), feche junções em T, feche lacunas de até 1e-4·tamanho entre lascas, mescle fragmentos coplanares e triangule novamente.
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 A contagem de triângulos aumenta com os recursos, não com o número de booleanos: a etapa de mesclagem coloca fatias coplanares de volta em faces inteiras. Na placa acima, a caixa tinha 12 triângulos, depois de quatro furos 412, depois da saliência 540, depois do furo 640; toda a cadeia foi executada em 96 ms.
Unir, subtrair, cruzar na entrada curva
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:
| Resultado | Volume, mm³ | Triângulos |
|---|---|---|
| esfera sozinha | 7 063.84 (exato 7 238.23) | 624 |
| cubo ∩ esfera | 882.98 | 112 |
| cubo ∪ esfera | 14 180.86 | — |
| cubo - esfera | 7 117.02 | — |
Verifique: 8 000 + 7 063.84 − 882.98 = 14 180.86 e 8 000 − 882.98 = 7 117.02, para que os três resultados sejam consistentes entre si para o centésimo. A malha da esfera em si está 2.4% abaixo da esfera exata, que é a lapidação de uma tolerância grosseira, não de um erro booleano.
Verificação de topologia
meshTopology conta vértices, arestas e triângulos, encontra limites, arestas não múltiplas e mal orientadas, triângulos e conchas degenerados e deriva características e gênero de Euler. describeTopology imprime o resumo de uma linha que o assistente e a janela de visualização usam.
{"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.
Triangulação de polígonos
triangulatePolygon(outer, holes) retorna triplos de índice na concatenação do anel externo e dos furos. Um quadrado 4 × 4 com um buraco 2 × 2 dá oito triângulos:
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 retorna undefined em vez de um resultado parcial quando a entrada não pode ser triangulada (anéis que se cruzam, furos fora do anel externo).
Solução de problemas
| Sintoma | Causa | Consertar |
|---|---|---|
| O resultado booleano tem buracos ou faces invertidas | uma entrada está aberta ou girada no sentido horário | verifique ambas as entradas com meshTopology: borderEdges e misorientedEdges devem ser 0 |
| uma face compartilhada por ambos os operandos está faltando ou é duplicada | as faces são quase, mas não exatamente coincidentes (mais distantes umas das outras do que a tolerância) | encaixe os operandos no mesmo plano ou aumente CsgOptions.tolerance |
| RangeError: A tolerância da malha excede o orçamento da subdivisão | tolerância muito fina para o raio | use as predefinições de tolerância (0.1 a 0.0005 mm) |
| o volume difere da fórmula | lapidação com tolerância grosseira | malha mais fina ou use o kernel B-rep para propriedades de massa exatas |
| Booleano lento em muitas ferramentas | união de ferramentas construídas primeiro | subtraia as ferramentas uma por uma (booleanAll faz isso): cada ferramenta convexa é um punhado de planos |