Pular para o conteúdo
CADCAMFUN
Docs

Documentação

Kernel B-rep exato

Representação exata de limites: geometria analítica e NURBS, booleanos, filetes, reconhecimento de furos, propriedades de massa, validação, mosaico e STEP.

Traduzido automaticamente do inglês. Ver o original em inglês

O que é o kernel B-rep

O kernel exato em packages/core/src/cad/brep (24 arquivos de origem, cerca de 8 660 linhas, mais testes) representa sólidos por seu limite exato: superfícies analíticas e NURBS, aparadas por loops de arestas exatas. Tudo são dados simples e funções puras, portanto, um representante B serializa para JSON, cruza o limite do trabalhador e difere no histórico do projeto inalterado. Booleanos, filetes e chanfros, reconhecimento de furos, propriedades de massa, validação, mosaico estanque e troca STEP, todos funcionam nesta estrutura.

Prato exato após subtrair e filé Arraste para orbitar · role para ampliar · arraste com o botão direito para deslocar
A 60 × 40 × 15 box minus a Ø12 cylinder (booleanBrep), then the four vertical edges filleted R4 (blendBrep). Mesh from brepToMesh at chordTol 0.05. 18 vertices, 27 edges, 11 faces; exact volume 34 097.522 mm³.

Tabelas de topologia

A Brep é um conjunto de tabelas de índice. As entidades referem-se umas às outras por índice, nunca por referência de objeto.

EntidadeDetémContraparte STEP
Vérticeponto, tolerânciaVERTEX_POINT
Bordaexact curve, [t0, t1] with t0 < t1, v0 = C(t0), v1 = C(t1), toleranceEDGE_CURVE
Coedgeum uso de uma aresta por um loop: índice de aresta, invertido, curva p opcional na face (u, v)ORIENTED_EDGE + PCURVE
Laçociclo fechado de coedes; material à esquerda visto de fora (externo no sentido anti-horário, furos no sentido horário)EDGE_LOOP
Faceregião de uma superfície; invertido significa que o normal externo é −(S_u × S_v)ADVANCED_FACE
Conchaconjunto conectado de faces; uma concha fechada limita um volumeCLOSED_SHELL

Seams (an edge used twice by the same face, such as the generator line of a full cylinder) and poles (a loop through a degenerate point, such as a cone apex) need no special entities. That is why the exact sphere has 2 vertices, 1 edge and 1 face, and the torus 1 vertex, 2 edges and 1 face.

Contagens de primitivas — saída real
makeBox(60, 40, 15)    {"V":8,"E":12,"F":6,"S":1,"surfaces":["plane"]}
makeSphere(10)         {"V":2,"E":1,"F":1,"S":1,"surfaces":["sphere"]}
makeTorus(20, 5)       {"V":1,"E":2,"F":1,"S":1,"surfaces":["torus"]}
makeCone(10, 4, 20)    {"V":2,"E":3,"F":3,"S":1,"surfaces":["cone","plane"]}

Curvas e superfícies

Os tipos analíticos usam as parametrizações STEP (ISO 10303-42), portanto, as faces lidas e gravadas em STEP mantêm seus parâmetros.

TipoParametrização
linhaC(t) = O + t·d, unidade d, comprimento do arco t
círculoC(t) = O + r(cos t·x + sin t·y)
elipseC(t) = O + a cos t·x + b sen t·y
aviãoS(u,v) = O + u·x + v·y
cilindroS(u,v) = O + r(cos u·x + sin u·y) + v·z
coneS(u,v) = O + (R + v tan α)(cos u·x + sin u·y) + v·z
esferaS(u,v) = O + r cos v(cos u·x + sin u·y) + r sin v·z
toroS(u,v) = O + (R + r cos v)(cos u·x + sin u·y) + r sin v·z
revoluçãoS(u,v) = rotate(C(v), axis, u)
extrusãoS(u,v) = C(u) + v·d
incomodacurva ou superfície B-spline racional (algoritmos Piegl & Tiller em nurbs.ts)
Primitivas exatas, tesseladas Arraste para orbitar · role para ampliar · arraste com o botão direito para deslocar
makeBox(10,10,10), makeCylinder(5,10), makeCone(5,2,10) and makeSphere(5), each tessellated by brepToMesh at chordTol 0.2 (12, 430, 122 and 1810 triangles) and placed side by side.
Toro R20 r5 Arraste para orbitar · role para ampliar · arraste com o botão direito para deslocar
makeTorus(20, 5): uma única face toroidal com uma costura e nenhuma outra aresta, tesselada em cordTol 1 e 30°. O volume exato 2π²Rr² = 9 869.604 mm³ é o que massProperties retorna.

Booleanos exatos

  1. Cruzar. Arestas de cada sólido contra as faces do outro (pontos exatos de Newton), arestas situadas nas superfícies do outro sólido e as curvas de interseção de cada par de faces não coincidentes, refinadas em ambas as superfícies e reconhecidas como linhas e círculos, caso contrário ajustadas como splines B cúbicas dentro da tolerância de ajuste.
  2. Imprimir. Cada ponto de intersecção torna-se um vértice em um registro para ambos os sólidos, as arestas são divididas ali e cada face é cortada pelas curvas nela através de um arranjo planar em seu domínio (u, v).
  3. Classificar. Um ponto dentro de cada fragmento está localizado contra o outro sólido: dentro, fora ou sobre com orientação igual ou oposta.
  4. Costurar. Os fragmentos são mantidos pelas regras da operação, as peças coincidentes tornam-se uma aresta, os vizinhos coplanares se fundem e o resultado é validado. Um resultado que não é uma variedade fechada gera BooleanError; nunca é devolvido.
boolean.ts
export const booleanBrep: (A: Brep, B: Brep, op: BooleanOp, options?: BooleanOptions) => BooleanResult
export interface BooleanOptions {
  tol?: number          // coincidence, default 1e-8 × model size, at least 1e-7 mm
  fitTol?: number       // fitted intersection curves, default 1e-6 × size, at least 1e-6 mm
  seedAngleDeg?: number // normal turn per seed-mesh triangle, default 10
  debug?: (stage: string, data: unknown) => void
}
export interface BooleanResult {
  brep: Brep; warnings: string[]
  stats: { intersectionCurves: number; splitPoints: number; fragments: number; keptFaces: number }
}
Caixa menos cilindro – saída real
import { brep } from "@cadcamfun/core"
const { makeBox, makeCylinder, frame, booleanBrep, validateBrep, massProperties } = brep

const box = makeBox(60, 40, 15)
const hole = makeCylinder(6, 25, frame({ x: 30, y: 20, z: -5 }))
const r = booleanBrep(box, hole, "subtract")          // 141 ms
r.stats     // {"intersectionCurves":2,"splitPoints":12,"fragments":13,"keptFaces":7}
r.warnings  // []
validateBrep(r.brep)
// {"valid":true,"manifoldSolid":true,"genus":1,"volume":34303.53996706151,"issues":[]}
massProperties(r.brep).volume   // 34303.53996706151  = 60·40·15 − π·6²·15 exactly

Propriedades de massa

Volume, área, centróide e o tensor de inércia (densidade unitária, sobre o centróide, linha maior) vêm do teorema da divergência sobre as faces limite. As faces planas são integradas exatamente pelo teorema de Green ao longo das curvas exatas das arestas; faces curvas são integradas em um mosaico de etapas de parâmetro da superfície exata.

CorpomassPropertiesFormulário fechado
caixa − Ø12 furo, volume34303.5399670615134303.539967061515
mesmo, área8139.2920065876848139.292006587698
mesmo, centróide(30.000, 20.000, 7.500)(30, 20, 7.5)
esfera r10, volume4188.7902047863794188.790204786391
toro 20/5, volume9869.604401094759869.604401089358
prato filetado, volume34097.5222039230234097.522203923065

The filleted-plate closed form is the subtracted plate minus four corner slivers of (r² − πr²/4)·h = (16 − 4π)·15 each.

Filetes, chanfros e reconhecimento de furos

Assinaturas
export const blendCandidates: (b: Brep, minAngleDegrees?: number /* 0.5 */) => BlendCandidate[]
export const selectBlendEdges: (edges: ReadonlyArray<BlendCandidate>, s?: BlendSelector) => BlendCandidate[]
// BlendSelector: parallel?: "x"|"y"|"z", within?: box, kind?: "convex"|"concave"|"both" (default convex), minLength?, curved?
export const blendBrep: (b: Brep, edges: ReadonlyArray<BlendCandidate>, size: number,
  style?: "fillet" | "chamfer", options?: BlendOptions) => BlendResult
// BlendResult: brep, blended, vertices (rolling-ball corners), rejected (edge ids), ...
export const recognizeHoles: (b: Brep, options?: HoleRecognitionOptions) => ReadonlyArray<RecognizedHole>

Na caixa - corpo do cilindro havia 14 candidatos à mistura; selectBlendEdges(c, { parallel: "z" }) escolheu as 4 bordas externas verticais e blendBrep(b, sel, 4) filetou todos 4 sem nenhum rejeitado em 94 ms. O buraco era lido apenas pelos rostos:

reconhecerHoles — saída real
[{"entry":{"x":30,"y":20,"z":15},"direction":{"x":0,"y":0,"z":-1},"depth":15,"diameter":12,
  "form":"simple","bottom":"through",
  "segments":[{"kind":"cylinder","start":0,"end":15,"diameterStart":12,"diameterEnd":12,"faces":[6]}]}]

Os formulários são simple, counterbore e countersink; fundos são through, flat e drill-point. O reconhecimento lê rostos, não histórico, portanto, uma importação STEP, um resultado booleano e uma parte paramétrica são reconhecidos da mesma forma.

Tesselação estanque

Cada aresta é amostrada uma vez em sua curva exata e cada face que a utiliza compartilha essas amostras, de modo que a malha soldada não apresenta rachaduras. As faces são trianguladas por Delaunay restrito em seu domínio (u, v).

OpçãoPadrãoSignificado
chordTol1/2000 da diagonal do modelo, fixada em [0.001, 0.05] mmdistância máxima entre a malha e a superfície exata
angleTolDeg15giro normal máximo em um triângulo (0 desativa)
maxEdge0 (nenhum)alvo de comprimento de borda
maxPointsPerFace200 000tampa de segurança
paramStep—modo de integração usado por massProperties

Para o prato de filé defaultChordTol retornou 0.0368 mm e tessellateBrep produziu 652 triângulos mais malhas por face, polilinhas de borda e avisos.

Troca de ETAPA

writeStepBreps grava um arquivo AP214 (AUTOMOTIVE_DESIGN) em milímetros e radianos, um ADVANCED_BREP_SHAPE_REPRESENTATION por peça. readStepBreps lê geometria e topologia AP203, AP214 e AP242, incluindo montagens com suas transformações e nomes de produtos. Entidades desconhecidas são relatadas em warnings e seus rostos saltaram; nada é adivinhado.
writeStepBreps([{ name: "plate", brep }]) — first lines of the real 358-line file
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('CADCAMFUN exact B-rep'),'2;1');
FILE_NAME('plate','2026-10-15T04:49:21',(''),(''),'CADCAMFUN B-rep kernel','CADCAMFUN','');
FILE_SCHEMA(('AUTOMOTIVE_DESIGN { 1 0 10303 214 1 1 1 1 }'));
ENDSEC;
DATA;
#1=APPLICATION_CONTEXT('core data for automotive mechanical design processes');
#2=APPLICATION_PROTOCOL_DEFINITION('international standard','automotive_design',2000,#1);
#3=PRODUCT_CONTEXT('',#1,'mechanical');
#4=PRODUCT_DEFINITION_CONTEXT('part definition',#1,'design');
#5=(LENGTH_UNIT()NAMED_UNIT(*)SI_UNIT(.MILLI.,.METRE.));

A leitura desse arquivo deu uma parte cujo volume era 34097.52220392303 mm³, igual ao corpo escrito com 11 dígitos significativos.

Orçamento de tempo

O kernel é síncrono e é executado no thread do chamador. withBudget(ms, f) estabelece um prazo; loops longos (pares de faces de uma chamada booleana, divisão de faces, intersecção de superfície, mosaico) checkBudget, que lança BudgetExceeded. Os orçamentos aninhados mantêm o prazo anterior; sem orçamento, um cheque custa uma comparação.

Saída real
withBudget(1, () => booleanBrep(makeSphere(10), makeBox(10, 10, 10), "union"))
// BudgetExceeded: the exact model exceeded its time budget of 1 ms

Solução de problemas

SintomaCausaConsertar
BooleanErroro resultado costurado não é um sólido múltiplo fechado (tangentes ou faces quase coincidentes)mover um operando ligeiramente para fora da tangência; verifique ambos com validBrep primeiro
BudgetExceededa operação demorou mais do que o seu orçamentosimplificar ou dar ao chamador um orçamento maior
RangeError de um primitivotamanho não positivo ou toro menor ≥ maiorpor exemplo "o raio menor do toro deve ser menor que o raio maior"
misturar borda em rejectedface muito estreita para o raio, fio de navalha ou parede inclinadaraio menor ou um chanfro
Parte STEP faltando facesentidade não suportada no arquivoler warnings de readStepBreps
validateBrep relata problemaserro de índice, orientação ou borda na superfície em um corpo construídoa emissão nomeia a entidade; nada é reparado automaticamente