# 解析面の復元と STEP 出力
[English](../brep-export.md) | 日本語
加工後の素材はメッシュだが、3 軸・フラットエンドミルの水平送り・突込み・水平な円弧移動でできた面は、平面と軸が +Z の円柱面に復元して B-rep として書き出せる。
```rust
let brep = engine.reconstruct_brep()?;
println!("faces (planes, cylinders) = {:?}", brep.surface_counts());
println!("edges (lines, arcs, polylines) = {:?}", brep.curve_counts());
brep.check(1e-6)?; // ループの閉性、稜線の端点が面の上にあること、頂点が重複しないことを検査する
engine.write_step(std::fs::File::create("machined.step")?, "machined")?;
```
## 仕組み
1. **由来情報。** メッシュブーリアンは結果の三角形ごとに「どの入力から来たか」を保持する。エンジンは素材と掃引体積の凸な部分ごとに固有の ID を与え、工具の半径と始点・終点の姿勢を記録する。水平な円弧移動では円弧の中心と半径も記録する。
2. **分類。** 由来が軸 +Z のフラットエンドミルの水平送りまたは突込みなら、既知の幾何から面を決める:底面(先端の高さの水平面)、直線部の側壁(経路から半径 r の鉛直面)、両端の円柱(先端の XY を軸、半径 r)。水平な円弧移動の側壁は、円弧の中心を軸とする半径 R ± r の円柱面。三角形を側壁や円柱に割り当てるのは 3 頂点すべてがその面の多角形の上にあるときだけなので、メッシュの三角形分割(タイル境界など)が結果を変えない。半径はメッシュの多角形ではなく工具の真の半径。素材は三角形の平面。それ以外(ボール・ブルノーズ、傾いた軸、ランプ、ヘリカル移動)は三角形自身の平面(ファセット)。
3. **面。** 同じ面で辺を共有する三角形をまとめる。重なる経路の底面は 1 つの面になる。180° を超える円柱面は角度で 2 つに分ける。タイル単位の場合は先に全タイルを結合し、結合で境界に残ることがある厚さゼロの壁を取り除く。
4. **稜線。** 面の境界をたどってループを作り、3 面以上が集まる頂点で分ける。平面同士は直線、水平面と円柱は円弧、鉛直面と円柱や円柱同士は鉛直な直線、それ以外は折れ線。頂点は接するすべての面に投影して揃える。側壁が端の円柱に接線で接する箇所(溝には必ずある)では接線を拘束に加えて頂点をその上に正確に置き、同じ点に集まった頂点は 1 つにまとめて間の稜線を捨てる。分割した円柱の継ぎ目は鉛直な直線に揃える。
5. **STEP。** AP214 の `MANIFOLD_SOLID_BREP`。面は `PLANE` / `CYLINDRICAL_SURFACE`、稜線は `LINE` / `CIRCLE` / `POLYLINE`、外周は `FACE_OUTER_BOUND`、穴は `FACE_BOUND`。
## 例
`examples/step_export.rs` が次の形状を STEP と STL に書き出す。
| 形状 | 面(平面, 円柱) | 稜線(直線, 円弧, 折れ線) |
|---|---|---|
| 10 mm 立方体の止まり穴(Ø4) | (7, 2) | (14, 4, 0) |
| 長円の溝(Ø3)と離れた穴(Ø2) | (10, 4) | (22, 8, 0) |
| 5 行のジグザグポケット(Ø6)、10 mm タイルで加工 | (13, 10) | (40, 20, 0) |
| 半円の円弧移動(Ø4、円弧半径 5) | (7, 5) | (17, 10, 0) |
| ボールエンドミルの突込み(Ø4) | (294, 0)、ファセット | (588, 0, 0) |
| 軸を 20° 傾けた送り(Ø4) | (57, 0)、ファセット | (145, 0, 0) |
FreeCAD 1.1.1 で開く(File → Open と `Part.read`)と、どのファイルも閉じた単一のソリッドとして読め、`Shape.check(True)` を通る。OpenCASCADE 7.8.1(`BRepCheck_Analyzer`)はすべて有効と判定し、形状公差の最大値は 1e-7 mm、体積は解析値に一致する(止まり穴付き立方体で 949.73 mm³。多角形メッシュの体積は 949.90 mm³)。タイル分割したポケットは分割なしと同じ 23 面に復元される。truck-stepio で読み戻しても同じ体積の閉じたメッシュになる。
## 制限
- 解析面になるのは 3 軸・フラットエンドミルの水平送り・突込み・水平な円弧移動の結果だけ。それ以外の面はファセットとして同じ STEP に含まれる。記録されたロボット経路のように高さがサンプルごとに僅かに変わる経路も、連続する姿勢の高さが厳密に一致しないためファセットになる。
- ファセットだけの結果(ボール工具、5 軸、記録経路)は平面ファセットごとに 1 面になるため、ファイルが大きい。記録された 99 秒のロボットサイクル(710 区間、15,900 面、20 MB)の B-rep は FreeCAD と OpenCASCADE で閉じたソリッドとして読め体積も一致するが、厳密な形状チェックではメッシュブーリアンが残す数十枚の細いファセットで自己交差するワイヤが指摘される。こうした結果はメッシュで受け渡すか、CAD 側で修復するのがよい。
- 検証は FreeCAD / OpenCASCADE と、メッシュ化して読み戻す方法で行っている。他の CAD は試していない。