# 機能設計書 40-TubeGeometry

## 概要

本ドキュメントはThree.jsにおけるチューブ（パイプ）ジオメトリ（TubeGeometry）クラスの機能設計を記述する。TubeGeometryはBufferGeometryを継承し、3D曲線に沿って円形断面を押し出すことでチューブ形状を生成するジオメトリクラスである。

### 本機能の処理概要

TubeGeometryは3Dグラフィックスにおいてパイプやチューブ形状のメッシュを生成するためのジオメトリクラスである。任意の3D曲線（Curve）に沿って一定の半径を持つチューブを生成する。曲線の形状に追従して滑らかに曲がるパイプ、ホース、ケーブルなどを表現できる。

**業務上の目的・背景**：3Dグラフィックスにおいて、曲線に沿ったパイプやケーブルの表現は多くのアプリケーションで必要とされる。配管設計、電気配線の可視化、血管の医療用可視化、ゲームのレールやトラック、アート作品など、様々な用途でチューブ形状が使用される。TubeGeometryはこれらの形状を任意の3D曲線から自動生成する。

**機能の利用シーン**：配管設計の可視化、電気ケーブルやホースの表現、医療用途での血管・神経の可視化、ゲームのレールやトラック、コースターのレール、アート作品や装飾要素の作成。

**主要な処理内容**：
1. 3D曲線（Curveオブジェクト）を受け取る
2. Frenet-Serretフレーム（接線・法線・従法線）を計算
3. 曲線上の各点で円形断面を生成
4. 断面をフレームに沿って配置して頂点を生成
5. UV座標を曲線に沿って配置
6. 閉じた曲線（closed=true）にも対応

**関連システム・外部連携**：レンダラー（WebGLRenderer、WebGPURenderer）と連携してメッシュを描画する。Curveクラスと連携する。

**権限による制御**：特になし。全てのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに直接の関連なし |

## 機能種別

計算処理 / ジオメトリ生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| path | Curve | No | チューブの経路を定義する3D曲線（デフォルト: QuadraticBezierCurve3） | なし |
| tubularSegments | number | No | 曲線方向の分割数（デフォルト: 64） | なし |
| radius | number | No | チューブの半径（デフォルト: 1） | なし |
| radialSegments | number | No | 円形断面の分割数（デフォルト: 8） | なし |
| closed | boolean | No | チューブを閉じるか（デフォルト: false） | なし |

### 入力データソース

コンストラクタ引数として直接指定される。pathはCurveクラス（LineCurve3、CatmullRomCurve3、BezierCurve3等）のインスタンス。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| position | Float32BufferAttribute | 頂点の3D位置座標 |
| normal | Float32BufferAttribute | 頂点の法線ベクトル |
| uv | Float32BufferAttribute | テクスチャマッピング用UV座標 |
| index | Uint16/Uint32BufferAttribute | 三角形面のインデックス |
| tangents | Array<Vector3> | 曲線上の接線ベクトル配列 |
| normals | Array<Vector3> | 曲線上の法線ベクトル配列 |
| binormals | Array<Vector3> | 曲線上の従法線ベクトル配列 |

### 出力先

BufferGeometry属性として保持され、Meshオブジェクトを通じてGPUに送信される。

## 処理フロー

### 処理シーケンス

```
1. コンストラクタ呼び出し
   └─ path, tubularSegments, radius, radialSegments, closed を受け取る
2. Frenet-Serretフレーム計算
   └─ path.computeFrenetFrames(tubularSegments, closed)
3. フレームをインスタンス変数に保存
   └─ tangents, normals, binormals
4. generateBufferData 呼び出し
   └─ 頂点・法線・UV・インデックス生成
5. BufferGeometry属性を設定
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[パラメータを受け取る]
    B --> C[path.computeFrenetFrames]
    C --> D[tangents/normals/binormals保存]
    D --> E[generateBufferData]
    E --> F[tubularSegmentsループ]
    F --> G[generateSegment呼び出し]
    G --> H[path.getPointAtで曲線上の点P取得]
    H --> I[radialSegmentsループ]
    I --> J[円形断面の頂点計算]
    J --> K[法線計算: cos×N + sin×B]
    K --> L[頂点: P + radius×normal]
    L --> M{全断面完了?}
    M -->|No| I
    M -->|Yes| N{全セグメント完了?}
    N -->|No| F
    N -->|Yes| O[generateUVs]
    O --> P[generateIndices]
    P --> Q[setAttribute]
    Q --> R[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-40-001 | Frenet-Serretフレーム | 曲線上の各点で接線T、法線N、従法線Bを計算 | 常時 |
| BR-40-002 | 法線計算 | normal = cos(v)×N + sin(v)×B（vは断面角度） | 常時 |
| BR-40-003 | 頂点計算 | vertex = P + radius×normal | 常時 |
| BR-40-004 | 閉じた曲線 | closed=trueの場合、最初と最後のセグメントを接続 | closed=true時 |
| BR-40-005 | 均等サンプリング | getPointAtで曲線を均等にサンプリング | 常時 |

### 計算ロジック

Frenet-Serretフレーム:
- T（接線）: 曲線の進行方向
- N（法線）: T に垂直な方向
- B（従法線）: T × N

円形断面の頂点:
- v = j / radialSegments × 2π
- normal = cos(v) × N + sin(v) × B
- vertex = P + radius × normal

UV座標:
- u = i / tubularSegments
- v = j / radialSegments

## データベース操作仕様

該当なし（クライアントサイドのみで動作）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 注意 | 曲線が自己交差 | 視覚的な問題が発生する可能性 |
| - | 注意 | 曲率が急激に変化 | ねじれが発生する可能性 |

### リトライ仕様

該当なし

## トランザクション仕様

該当なし

## パフォーマンス要件

- 頂点数は (tubularSegments+1) × (radialSegments+1)
- 三角形数は tubularSegments × radialSegments × 2
- デフォルト設定（64×8）で585頂点、1,024三角形
- 複雑な曲線ほどtubularSegmentsを増やす必要がある

## セキュリティ考慮事項

特になし（クライアントサイドのジオメトリ生成処理）

## 備考

- tangents, normals, binormals はインスタンス変数として公開されている
- カスタム曲線クラスを定義してpathとして使用可能
- fromJSONは組み込み曲線のみ対応（カスタム曲線は非対応）

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

Curveクラスと Frenet-Serretフレームを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Curve.js | `src/extras/core/Curve.js` | 曲線の基底クラス、getPointAt、computeFrenetFrames |
| 1-2 | Vector3.js | `src/math/Vector3.js` | 3Dベクトル操作 |

**読解のコツ**: computeFrenetFramesがチューブ生成の鍵。接線・法線・従法線の3つのベクトルで曲線上の各点の座標系を定義する。

#### Step 2: エントリーポイントを理解する

TubeGeometryクラスのコンストラクタが処理の起点。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TubeGeometry.js | `src/geometries/TubeGeometry.js` | コンストラクタ全体の処理フロー |

**主要処理フロー**:
1. **45行目**: コンストラクタでパラメータを受け取る
2. **66行目**: path.computeFrenetFramesでフレーム計算
3. **70-72行目**: tangents, normals, binormalsを保存
4. **90行目**: generateBufferData呼び出し
5. **94-97行目**: BufferGeometry属性設定

#### Step 3: セグメント生成の詳細を理解する

generateSegment関数で円形断面を生成する処理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TubeGeometry.js | `src/geometries/TubeGeometry.js` | 127-166行目のgenerateSegment関数 |

**主要処理フロー**:
- **131行目**: path.getPointAtで曲線上の点Pを取得
- **135-136行目**: フレームのN（法線）とB（従法線）を取得
- **140-145行目**: 円形断面の各頂点で法線計算
- **149-152行目**: 法線を正規化
- **158-160行目**: 頂点位置 = P + radius × normal

### プログラム呼び出し階層図

```
TubeGeometry.constructor()
    │
    ├─ BufferGeometry.constructor()
    │
    ├─ path.computeFrenetFrames(tubularSegments, closed)
    │      └─ tangents, normals, binormals を計算
    │
    ├─ フレームをインスタンス変数に保存
    │
    └─ generateBufferData()
           │
           ├─ tubularSegmentsループ
           │      └─ generateSegment(i)
           │             │
           │             ├─ P = path.getPointAt(i / tubularSegments)
           │             ├─ N = frames.normals[i]
           │             ├─ B = frames.binormals[i]
           │             │
           │             └─ radialSegmentsループ
           │                    ├─ v = j / radialSegments × 2π
           │                    ├─ normal = cos(v)×N + sin(v)×B
           │                    └─ vertex = P + radius × normal
           │
           ├─ generateUVs()
           │      └─ u = i/tubularSegments, v = j/radialSegments
           │
           └─ generateIndices()
                  └─ 四角形→2三角形変換
```

### データフロー図

```
[入力]               [処理]                    [出力]

path ─────────▶ TubeGeometry ───▶ BufferGeometry
(Curve)            │                 (position,
                   │                  normal,
tubularSegments,   ▼                  uv,
radius,         computeFrenetFrames   index)
radialSegments,    │                     +
closed             ▼                  tangents,
               フレーム計算            normals,
               (T, N, B)              binormals
                   │
                   ▼
               円形断面生成
                   │
                   ▼
               頂点配置
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| TubeGeometry.js | `src/geometries/TubeGeometry.js` | ソース | チューブジオメトリクラス定義 |
| Curve.js | `src/extras/core/Curve.js` | ソース | 曲線基底クラス、computeFrenetFrames |
| CatmullRomCurve3.js | `src/extras/curves/CatmullRomCurve3.js` | ソース | よく使われる3D曲線 |
| QuadraticBezierCurve3.js | `src/extras/curves/QuadraticBezierCurve3.js` | ソース | デフォルトパス |
| BufferGeometry.js | `src/core/BufferGeometry.js` | ソース | 基底クラス |
| Vector3.js | `src/math/Vector3.js` | ソース | 3Dベクトル計算 |
| Vector2.js | `src/math/Vector2.js` | ソース | 2Dベクトル（UV座標） |
| Curves.js | `src/extras/curves/Curves.js` | ソース | 組み込み曲線のエクスポート |
