Pular para o conteúdo
CADCAMFUN
Docs

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.

ArquivoLinhasPapel
cad/solid.ts659Esquemas sólidos (Caixa, Cilindro, Esfera, Cone, Toro, Extrusão, Revolução), meshOf, meshVolume, meshBounds
cad/csg.ts459Booleanos BSP, classificador convexo, traduzir/girar/mesclar
cad/mesh-clean.ts626solda, reparo de junção em T, fusão coplanar, retriangulação
cad/mesh-topology.ts110variedade, conchas, gênero, volume, área
cad/triangulate.ts383triangulação de polígono com buracos
Placa perfurada com saliência entediada Arraste para orbitar · role para ampliar · arraste com o botão direito para deslocar
Saída booleanMesh real: uma caixa 60 × 40 × 10 menos quatro Ø6 buracos (booleanAll subtrair), unida com uma saliência Ø20 × 8 e depois perfurada Ø10. 640 triângulos; meshTopology relata sólido fechado, 1 shell, gênero 5, V 23981.4 mm³.

O tipo de malha e primitivas

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
SólidoCamposLimites
Caixaorigem, tamanho {x, y, z}tamanhos > 0
Cilindroorigem, raio, altura, segmentos, eixo?segmentos 3–512; eixo z | x | sim
Esferacentro, raio, anéisanéis 2–256
Coneorigem, baseRadius, topRadius, altura, segmentos, eixo?raio superior ≥ 0; segmentos 3–512
Torocentro, majorRadius, minorRadius, rotação?, majorSegments, minorSegments, eixo?3–512 e 3–256
Extrusãoperfil (≥ 3 pontos, não fechado), altura, origem?perfil em XY
Girarperfil (≥ 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.
GuardaValorMensagem de erro
a tolerância deve ser positiva e finita—A tolerância da malha deve ser positiva e finita
segmentos por curva65 536A tolerância da malha excede o orçamento da subdivisão
linhas da grade × colunas (esfera, toro, revolução)1 000 000A 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.

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

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:

ResultadoVolume, mm³Triângulos
esfera sozinha7 063.84 (exato 7 238.23)624
cubo ∩ esfera882.98112
cubo ∪ esfera14 180.86—
cubo - esfera7 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.

cubo - esfera Arraste para orbitar · role para ampliar · arraste com o botão direito para deslocar
Resultado da subtração: o cubo com uma oitava esfera escavada em seu canto.
cubo ∩ esfera Arraste para orbitar · role para ampliar · arraste com o botão direito para deslocar
Resultado da interseção: o oitavo da esfera que está dentro do cubo.

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.
meshTopology(entediado) — resultado real
{"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:
Saída real
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

SintomaCausaConsertar
O resultado booleano tem buracos ou faces invertidasuma entrada está aberta ou girada no sentido horárioverifique ambas as entradas com meshTopology: borderEdges e misorientedEdges devem ser 0
uma face compartilhada por ambos os operandos está faltando ou é duplicadaas 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ãotolerância muito fina para o raiouse as predefinições de tolerância (0.1 a 0.0005 mm)
o volume difere da fórmulalapidação com tolerância grosseiramalha mais fina ou use o kernel B-rep para propriedades de massa exatas
Booleano lento em muitas ferramentasunião de ferramentas construídas primeirosubtraia as ferramentas uma por uma (booleanAll faz isso): cada ferramenta convexa é um punhado de planos