ドキュメント
メッシュとCSGカーネル
パラメトリック ソリッドからの閉じた三角形メッシュ、凸状の高速パスを備えた BSP ブール値、クリーンアップおよびトポロジ チェック。
英語から自動翻訳されています。 英語の原文を見る
メッシュカーネルとは
メッシュ カーネルは閉じた三角形メッシュ上で動作します。パラメトリック プリミティブからメッシュを構築します (meshOf)、それらを測定します(meshVolume, meshBounds, meshTopology)、それらをブール値と組み合わせます (booleanMesh, booleanAll)。これは、ビューポートが表示するもの、CAM ジェネレーター マシンが表示するもの、STL エクスポートが書き込むものです。
これは正確な境界表現ではありません。切断された円柱はファセットされた円柱のままであり、フィレットや測定を行う面トポロジはありません。正確な面、フィレット、質量特性、STEP については、 B-repカーネル は別のコードです。
| ファイル | ライン | 役割 |
|---|---|---|
cad/solid.ts | 659 | ソリッド スキーマ (ボックス、シリンダー、球、円錐、トーラス、押し出し、回転)、meshOf、meshVolume、meshBounds |
cad/csg.ts | 459 | BSP ブール値、凸型分類器、変換/回転/マージ |
cad/mesh-clean.ts | 626 | 溶接、T ジャンクションの修復、共面マージ、再三角形分割 |
cad/mesh-topology.ts | 110 | 多様体、貝殻、属、体積、面積 |
cad/triangulate.ts | 383 | 穴のある多角形の三角形分割 |
メッシュタイプとプリミティブ
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 | 固体 | フィールド | 限界 |
|---|---|---|
| 箱 | 原点、サイズ {x, y, z} | サイズ > 0 |
| シリンダー | 原点、半径、高さ、セグメント、軸? | セグメント 3 ~ 512; z軸 | × | y |
| 球 | 中心、半径、リング | リング 2 – 256 |
| 円錐 | 原点、baseRadius、topRadius、高さ、セグメント、軸? | トップ半径 ≥ 0;セグメント 3 ~ 512 |
| トーラス | 中心、majorRadius、minorRadius、回転?、majorSegments、minorSegments、軸? | 3-512 および 3-256 |
| 押し出す | プロファイル (≥ 3 ポイント、閉じていない)、高さ、原点? | xYのプロファイル |
| 回転する | プロファイル (XZ 内の ≥ 2 点)、角度、セグメント? | zについて。セグメント 3 ~ 512、デフォルト 16 |
segments そして rings 最小値は次のとおりです。 meshOf コードエラーが範囲内に収まるまでそれらを上げます tolerance, using step = 4·asin(√(min(1, tol/r)/2)). Two budgets stop runaway tolerances.
| ガード | 価値 | エラーメッセージ |
|---|---|---|
| 許容誤差は正で有限である必要があります | — | メッシュ許容値は正で有限でなければなりません |
| 曲線ごとのセグメント数 | 65 536 | メッシュ許容値がサブディビジョンの予算を超えています |
| グリッドの行×列(球、トーラス、回転) | 1 000 000 | メッシュ許容値が頂点バジェットを超えています |
Ø6 シリンダー segments: 24 許容値 0.05 では、96 個の三角形 (24 個の辺、2 つの 24 角のキャップ) が得られました。 Ø20 は 128 です。これは、より大きな半径では 32.0 mm 以内に収まるために 05 個のセグメントが必要だったためです。
バイナリ空間分割によるブール値
各オペランドは分類子になります。一般的なメッシュは BSP ツリーを取得します。凸面メッシュ (閉じていて接続されており、すべてのエッジが凸面) は、その別個の面にすぎないため、ボックスは 6 つの平面であり、1 万個の三角形からなる球は、凸面固体の BSP が縮退する二次連鎖を構築することなく分類されます。ポリゴンはリストとして分類され、他のオペランドの境界ボックスから離れたポリゴンは、何も歩かずに保持または削除されます。
- If either mesh is empty, or the bounding boxes do not meet (within tolerance), answer directly: union = merge, subtract = a, intersect = empty.
- A と B の分類器 (凸面または BSP) を構築します。
- ユニオン: A を B の外側に、B を A の外側に保ち、B の面を A が同じ方向を向いているのと一致するようにドロップします。そのため、共有された面が一度保持されます。
- Subtract and intersect follow the classic a.clipTo(b), b.clipTo(a), b.invert() sequence on polygon lists, without copying trees.
- ポリゴン スープをクリーンアップします。max(10・eps, 1e-9・size) 以内のポイントを溶接し、T 字路を閉じ、スライバー間の最大 1e-4・size のギャップを閉じ、同一平面上のフラグメントをマージして再三角形化します。
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 三角形の数は、ブール値の数ではなく、フィーチャとともに増加します。マージ ステップでは、同一平面上のスライバーが面全体に戻されます。上のプレートでは、箱には 12 個の三角形があり、4 つの穴の後に 412、ボスの後に 540、穴の後に 640 がありました。チェーン全体は 96 ミリ秒で実行されました。
曲線入力での結合、減算、交差
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:
| 結果 | 体積、mm3 | 三角形 |
|---|---|---|
| 球体だけ | 7 063.84 (正確な 7 238.23) | 624 |
| 立方体∩球 | 882.98 | 112 |
| 立方体∪球 | 14 180.86 | — |
| 立方体 - 球 | 7 117.02 | — |
チェック: 8 000 + 7 063.84 − 882.98 = 14 180.86 および 8 000 − 882.98 = 7 117.02 であるため、3 つの結果は互いに一致しています。百番目まで。球メッシュ自体は、正確な球よりも 2.4 % 下にあります。これは、ブール誤差ではなく、粗い許容値のファセットです。
トポロジチェック
meshTopology 頂点、辺、三角形を数え、境界、非多様体および方向が間違っている辺を見つけ、三角形と殻を縮退させ、オイラー特性と属数を導き出します。 describeTopology アシスタントとビューポートが使用する 1 行の概要を出力します。
{"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.
ポリゴンの三角形分割
triangulatePolygon(outer, holes) インデックス トリプルを外側のリングと穴の連結に返します。 4 × 4 の正方形に 2 × 2 の穴があると、8 つの三角形が得られます。
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 返品 undefined 入力を三角測量できない場合 (自己交差リング、外側リングの外側の穴) の部分的な結果の代わりに。
トラブルシューティング
| 症状 | 原因 | 修理 |
|---|---|---|
| ブール値の結果に穴または反転した面があります | 入力が開いているか、時計回りに巻かれています | 両方の入力を MeshTopology で確認してください:boundaryEdges と missorientedEdges は 0 である必要があります |
| 両方のオペランドに共有される面が欠落しているか、二重になっています | 面はほぼ一致していますが、正確には一致していません (許容値よりも離れています) | オペランドを同じ平面にスナップするか、CsgOptions.tolerance を上げます |
| RangeError: メッシュ許容値がサブディビジョンの予算を超えています | 半径に対して公差が小さすぎます | 公差プリセットを使用します (0.1 ~ 0.0005 mm) |
| 体積は式と異なります | 粗い公差でのファセット加工 | メッシュをより細かくするか、正確な質量特性を得るには B-rep カーネルを使用します |
| 多くのツールでブール演算が遅い | 最初に構築されたツールの結合 | ツールを 1 つずつ減算します (booleanAll はこれを実行します): 各凸ツールは少数の平面です |