# 機能設計書 164-CurvePath

## 概要

本ドキュメントは、Three.jsライブラリにおけるCurvePath機能の設計仕様を記述する。CurvePathは、複数の曲線を連結して一つのパスとして扱うためのクラスであり、Curveを継承しながら連続した曲線の集合を管理する。

### 本機能の処理概要

CurvePathクラスは、複数のCurveインスタンスを配列として保持し、それらを一つの連続したパスとして扱う機能を提供する。パス全体の長さ計算、任意の位置でのポイント取得、自動クローズ機能などを実装している。

**業務上の目的・背景**：複雑な2Dまたは3Dパスは、単一の曲線では表現できないことが多い。直線、ベジェ曲線、円弧などを組み合わせて複雑な形状を作成する必要がある。CurvePathはこれらの曲線を統一的なインターフェースで管理し、PathやShapeクラスの基盤となる。

**機能の利用シーン**：
- 複雑な2Dパスの作成（SVGパスの表現など）
- 3Dパスに沿ったカメラ移動
- ExtrudeGeometryやShapeGeometryの入力
- フォントグリフのアウトライン表現

**主要な処理内容**：
1. add() - パスに曲線を追加
2. closePath() - 開始点と終了点を結ぶ線分を追加してパスを閉じる
3. getPoint() - パス全体での補間位置の点を取得
4. getCurveLengths() - 各曲線の累積長を取得
5. getPoints() / getSpacedPoints() - パス全体のサンプリング
6. autoClose - パスを自動的に閉じるフラグ

**関連システム・外部連携**：Path、Shape、ExtrudeGeometry、ShapeGeometry、フォントシステムと連携。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 直接的な画面関連なし（基盤クラス） |

## 機能種別

計算処理 / データ構造

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| curve | Curve | Yes | 追加する曲線 | Curveインスタンス |
| t | number | Yes | 補間係数（0〜1） | 0以上1以下 |
| divisions | number | No | サンプリング分割数 | 正の整数 |

### 入力データソース

add()メソッドで追加されるCurveインスタンスの配列。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| point | Vector2/Vector3 | パス上の点 |
| points | Array<Vector2/Vector3> | サンプリングされた点の配列 |
| length | number | パスの全長 |
| curveLengths | Array<number> | 各曲線の累積長の配列 |

### 出力先

メモリ上に返却され、呼び出し元で利用される。

## 処理フロー

### 処理シーケンス

```
1. CurvePathインスタンス生成
   └─ curves配列を空で初期化
2. add()で曲線を追加
   └─ curves配列に曲線をpush
3. getPoint(t)呼び出し
   └─ getLength()でパス全体の長さを取得
   └─ getCurveLengths()で累積長を取得
   └─ 対象となる曲線を特定
   └─ 曲線内のローカルパラメータを計算
   └─ curve.getPointAt(u)で点を取得
4. closePath()呼び出し（オプション）
   └─ 開始点と終了点が異なる場合
   └─ LineCurve/LineCurve3を追加
```

### フローチャート

```mermaid
flowchart TD
    A[CurvePath生成] --> B[add曲線を追加]
    B --> C{getPoint呼び出し?}
    C -->|Yes| D[パス全長を計算]
    D --> E[目標距離を計算 d=t*length]
    E --> F[getCurveLengths呼び出し]
    F --> G{累積長 >= d?}
    G -->|Yes| H[対象曲線を特定]
    G -->|No| I[次の曲線へ]
    I --> G
    H --> J[曲線内パラメータuを計算]
    J --> K[curve.getPointAt実行]
    K --> L[点を返却]
    C -->|closePath| M{開始点 == 終了点?}
    M -->|No| N[LineCurve追加]
    M -->|Yes| O[何もしない]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 曲線タイプ判定 | 開始点がVector2ならLineCurve、Vector3ならLineCurve3 | closePath() |
| BR-002 | 累積長キャッシュ | cacheLengthsに曲線長をキャッシュ | getCurveLengths() |
| BR-003 | 自動クローズ | autoClose=trueで終点を開始点に接続 | getSpacedPoints(), getPoints() |
| BR-004 | 重複点除去 | 連続する曲線間の重複点を除去 | getPoints() |

### 計算ロジック

**getPoint計算**: パス全体の長さに対する相対位置から、対象曲線と曲線内パラメータを算出。`u = 1 - diff / segmentLength`で曲線内位置を計算。

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | null返却 | getPoint()でtが範囲外 | 有効なt値を使用 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- cacheLengthsで曲線長をキャッシュし、再計算を回避
- needsUpdate=trueまたは曲線数変更時にキャッシュを再計算

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

特になし

## 備考

- Curveを継承しているため、基底クラスのメソッドも利用可能
- getLength()はgetLengths()ではなくgetCurveLengths()に依存する設計

---

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

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

### 推奨読解順序

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

CurvePathはCurveを継承し、curves配列で複数の曲線を管理する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CurvePath.js | `src/extras/core/CurvePath.js` | クラス定義とプロパティ構造（10-38行目） |

**読解のコツ**: curvesプロパティが曲線の配列を保持し、autoCloseでパスの自動クローズを制御する。

#### Step 2: 曲線追加とクローズを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CurvePath.js | `src/extras/core/CurvePath.js` | add (45-49行目) |
| 2-2 | CurvePath.js | `src/extras/core/CurvePath.js` | closePath (56-71行目) |

**主要処理フロー**:
1. **47行目**: curves配列にcurveをpush
2. **59行目**: 最初の曲線の開始点を取得
3. **60行目**: 最後の曲線の終了点を取得
4. **62-65行目**: 開始点と終了点が異なる場合、LineCurve/LineCurve3を追加

#### Step 3: ポイント取得を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | CurvePath.js | `src/extras/core/CurvePath.js` | getPoint (81-120行目) |
| 3-2 | CurvePath.js | `src/extras/core/CurvePath.js` | getCurveLengths (148-177行目) |

**主要処理フロー**:
- **92-93行目**: 目標距離とcurveLengthsを取得
- **98-114行目**: 累積長が目標を超える曲線を探索
- **102-106行目**: 曲線内パラメータuを計算
- **108行目**: curve.getPointAt(u)で点を取得

#### Step 4: サンプリングメソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | CurvePath.js | `src/extras/core/CurvePath.js` | getSpacedPoints (179-197行目) |
| 4-2 | CurvePath.js | `src/extras/core/CurvePath.js` | getPoints (199-235行目) |

**主要処理フロー**:
- **181-186行目**: getSpacedPointsは等距離サンプリング
- **189-193行目**: autoCloseで終点を追加
- **204-224行目**: getPointsは曲線タイプに応じた分割数で適応的サンプリング
- **218行目**: 重複点を除去（last.equals(point)）

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

```
CurvePath extends Curve
    │
    ├─ add(curve)
    │      └─ curves.push(curve)
    │
    ├─ closePath()
    │      └─ LineCurve / LineCurve3 追加
    │
    ├─ getPoint(t)
    │      ├─ getLength()
    │      │     └─ getCurveLengths()
    │      ├─ 対象曲線を特定
    │      └─ curve.getPointAt(u)
    │
    ├─ getCurveLengths()
    │      └─ curves[i].getLength() [累積]
    │
    ├─ getSpacedPoints(divisions)
    │      └─ getPoint(i/divisions) [繰り返し]
    │
    └─ getPoints(divisions)
           └─ curves[i].getPoints(resolution) [適応的]
```

### データフロー図

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

Curve[] ───────────────▶ add() ───────────────────────▶ curves配列更新

t (0-1) ───────────────▶ getPoint(t) ─────────────────▶ Vector2/Vector3
                           ├─ getCurveLengths()
                           ├─ 曲線特定
                           └─ curve.getPointAt(u)

divisions ─────────────▶ getSpacedPoints ─────────────▶ Array<Vector>
                         または getPoints               (重複除去済み)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CurvePath.js | `src/extras/core/CurvePath.js` | ソース | 本機能のメイン実装 |
| Curve.js | `src/extras/core/Curve.js` | ソース | 基底クラス |
| Path.js | `src/extras/core/Path.js` | ソース | CurvePathを継承した2Dパス |
| Shape.js | `src/extras/core/Shape.js` | ソース | Pathを継承したシェイプ |
| Curves.js | `src/extras/curves/Curves.js` | ソース | 曲線タイプのエクスポート |
| LineCurve.js | `src/extras/curves/LineCurve.js` | ソース | 2D直線曲線 |
| LineCurve3.js | `src/extras/curves/LineCurve3.js` | ソース | 3D直線曲線 |
| EllipseCurve.js | `src/extras/curves/EllipseCurve.js` | ソース | 楕円曲線 |
| SplineCurve.js | `src/extras/curves/SplineCurve.js` | ソース | スプライン曲線 |
