# 機能設計書 134-Plane

## 概要

本ドキュメントは、Three.jsの数学ライブラリにおける3D平面を表現するPlaneクラスの機能設計書である。

### 本機能の処理概要

Planeクラスは、3D空間において無限に広がる平面を表現するためのクラスである。[ヘッセの法線形式](http://mathworld.wolfram.com/HessianNormalForm.html)（Hessian Normal Form）を採用し、単位法線ベクトル（normal）と原点からの符号付き距離（constant）によって平面を定義する。視錐台の構成、レイとの交差判定、オブジェクトの空間分割など、多くの3D計算の基盤となる。

**業務上の目的・背景**：3Dグラフィックスにおいて、平面は視錐台カリング（6つの平面で構成）、クリッピング処理、反射計算、衝突検出など、多くの重要な処理で使用される。Planeクラスは、これらの処理に必要な平面の数学的表現と操作を提供する。

**機能の利用シーン**：
- Frustum（視錐台）の6つの境界平面として使用
- レイキャスティングでの平面との交差判定
- オブジェクトのクリッピング処理
- 鏡面反射の計算
- 空間分割（BSP木など）のパーティション平面
- 点の平面への投影計算

**主要な処理内容**：
1. 平面の生成と初期化（法線と定数の設定）
2. 3点（共面点）からの平面設定
3. 法線と共面点からの平面設定
4. 点・球・ボックス・線分との距離・交差判定
5. 点の平面への投影
6. 線分との交点計算
7. Matrix4による変換

**関連システム・外部連携**：Frustum、Ray、Line3、Box3、Sphereなどと連携。

**権限による制御**：なし（純粋な数学ユーティリティクラス）

## 関連画面

本機能は数学ユーティリティであり、直接的な画面との関連はない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 内部計算処理として使用 |

## 機能種別

計算処理 / ジオメトリ演算

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| normal | Vector3 | No | 平面の単位法線ベクトル | デフォルト: (1, 0, 0) |
| constant | number | No | 原点から平面への符号付き距離 | デフォルト: 0 |

### 入力データソース

コンストラクタ引数またはメソッド呼び出しによる直接設定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| isPlane | boolean | Planeインスタンス識別フラグ（常にtrue） |
| normal | Vector3 | 平面の単位法線ベクトル |
| constant | number | 原点から平面への符号付き距離 |

### 出力先

メモリ上のオブジェクトとして保持

## 処理フロー

### 処理シーケンス

```
1. 平面の初期化
   └─ normal=(1,0,0), constant=0で初期化
2. データソースからの平面設定
   ├─ set/setComponents: 直接設定
   ├─ setFromNormalAndCoplanarPoint: 法線+共面点から
   └─ setFromCoplanarPoints: 3共面点から
       └─ 2辺の外積で法線を計算
3. 距離・交差判定
   ├─ distanceToPoint/distanceToSphere
   ├─ intersectsLine/intersectsBox/intersectsSphere
   └─ intersectLine: 交点の計算
4. 点の操作
   ├─ projectPoint: 点を平面に投影
   └─ coplanarPoint: 共面点を取得
5. 変換
   ├─ applyMatrix4: 行列変換
   ├─ translate: 平行移動
   └─ negate: 法線と定数を反転
```

### フローチャート

```mermaid
flowchart TD
    A[Planeインスタンス生成] --> B{初期化方法}
    B -->|set/setComponents| C[法線と定数を直接設定]
    B -->|setFromNormalAndCoplanarPoint| D[法線と共面点から計算]
    B -->|setFromCoplanarPoints| E[3点から法線を計算]
    D --> D1[constant = -dot/point, normal/]
    E --> E1[外積で法線算出]
    E1 --> D1
    C --> F[平面確定]
    D1 --> F
    F --> G{操作種別}
    G -->|距離計算| H[distanceToPoint/Sphere]
    G -->|交差判定| I[intersects系]
    G -->|投影| J[projectPoint]
    G -->|交点計算| K[intersectLine]
    G -->|変換| L[applyMatrix4/translate]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | ヘッセの法線形式 | 平面方程式: n・p + d = 0（nは単位法線、dは定数） | 全操作 |
| BR-002 | 符号付き距離 | 正=法線方向、負=逆方向 | distanceToPoint |
| BR-003 | 法線の正規化 | normalize()呼び出しで法線を単位ベクトルに | 正規化時 |
| BR-004 | 巻き順序 | setFromCoplanarPointsは反時計回りで法線方向を決定 | 3点から設定時 |

### 計算ロジック

**点との距離計算**:
```javascript
distanceToPoint = dot(normal, point) + constant
// 正の値 = 点は法線側
// 負の値 = 点は法線の反対側
```

**共面点からの定数計算**:
```javascript
constant = -dot(point, normal)
```

**3点からの法線計算**:
```javascript
edge1 = c - b
edge2 = a - b
normal = normalize(cross(edge1, edge2))
// 反時計回り（a->b->c）で法線は手前を向く
```

**点の平面への投影**:
```javascript
projectedPoint = point - normal * distanceToPoint(point)
```

**線分との交点計算**:
```javascript
direction = line.end - line.start
denominator = dot(normal, direction)
if (denominator == 0) // 平行または共面
t = -(dot(normal, line.start) + constant) / denominator
if (t < 0 || t > 1) // 線分外
intersectionPoint = line.start + direction * t
```

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

該当なし（純粋な計算処理クラス）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ゼロ除算 | normalize()で法線がゼロベクトル | 入力チェック必要 |
| - | 平行/共面 | intersectLineで線分が平面に平行 | nullを返す |
| - | 縮退三角形 | setFromCoplanarPointsで3点が一直線上 | 法線がゼロになる |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 全メソッドO(1)の計算量
- メモリ使用量: Vector3 + number = 28バイト程度

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

該当なし（純粋な数学計算）

## 備考

- Frustumは6つのPlaneで構成される
- Box3.intersectsPlane()やSphere.intersectsPlane()と相互参照
- ヘッセの法線形式は効率的な距離計算を可能にする
- applyMatrix4にはオプショナルな法線行列（normal matrix）を渡せる

---

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

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

### 推奨読解順序

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

Planeクラスはnormal（Vector3）とconstant（number）でヘッセの法線形式を表現する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Vector3.js | `src/math/Vector3.js` | Planeが依存する3Dベクトルクラス |
| 1-2 | Plane.js | `src/math/Plane.js` | クラスのプロパティ定義（normal, constant, isPlane） |

**読解のコツ**: ヘッセの法線形式（n・p + d = 0）を理解することが重要。normalは必ず単位ベクトル、constantは原点からの距離。

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

Planeクラスのコンストラクタと主要なsetterを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Plane.js | `src/math/Plane.js` | コンストラクタとset系メソッド群 |

**主要処理フロー**:
1. **21-47行目**: コンストラクタでnormal/constantを初期化
2. **56-63行目**: set() - 直接設定
3. **75-82行目**: setComponents() - x,y,z,wから設定
4. **92-99行目**: setFromNormalAndCoplanarPoint() - constant = -dot(point, normal)
5. **111-121行目**: setFromCoplanarPoints() - 3点の外積から法線を計算

#### Step 3: 距離計算と交差判定を理解する

平面と各種オブジェクトとの関係を計算するメソッドを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Plane.js | `src/math/Plane.js` | distanceTo系とintersects系メソッド |

**主要処理フロー**:
- **175-179行目**: distanceToPoint() - dot(normal, point) + constant
- **187-191行目**: distanceToSphere() - 中心との距離 - 半径
- **215-245行目**: intersectLine() - 線分との交点計算
- **253-262行目**: intersectsLine() - 始点と終点が平面の反対側にあるか

#### Step 4: 投影と変換を理解する

点の投影と行列変換のロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Plane.js | `src/math/Plane.js` | projectPointとapplyMatrix4 |

**主要処理フロー**:
- **200-204行目**: projectPoint() - 点から法線方向に距離分移動
- **295-297行目**: coplanarPoint() - normal * (-constant)で共面点を取得
- **313-325行目**: applyMatrix4() - 法線行列で法線を変換、共面点を変換後に再計算

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

```
Plane
    │
    ├─ setFromCoplanarPoints(a, b, c)
    │      ├─ _vector1.subVectors(c, b)
    │      ├─ _vector2.subVectors(a, b)
    │      ├─ normal = cross(edge1, edge2).normalize()
    │      └─ setFromNormalAndCoplanarPoint(normal, a)
    │
    ├─ setFromNormalAndCoplanarPoint(normal, point)
    │      ├─ this.normal.copy(normal)
    │      └─ this.constant = -point.dot(normal)
    │
    ├─ distanceToPoint(point)
    │      └─ normal.dot(point) + constant
    │
    ├─ intersectLine(line, target)
    │      ├─ line.delta(_vector1)
    │      ├─ denominator = normal.dot(direction)
    │      ├─ t = -(start.dot(normal) + constant) / denominator
    │      └─ target = start + direction * t
    │
    └─ applyMatrix4(matrix, optionalNormalMatrix)
           ├─ coplanarPoint(_vector1).applyMatrix4(matrix)
           ├─ normal.applyMatrix3(normalMatrix).normalize()
           └─ constant = -referencePoint.dot(normal)
```

### データフロー図

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

Vector3 x 3 ────────▶ setFromCoplanarPoints() ─▶ Plane {normal, constant}
(3つの共面点)          (外積で法線計算)

Vector3 ────────────▶ distanceToPoint() ────────▶ number
(点)                   (ドット積 + constant)      (符号付き距離)

Line3 ──────────────▶ intersectLine() ──────────▶ Vector3 | null
(線分)                 (パラメトリック交点計算)   (交点)

Matrix4 ────────────▶ applyMatrix4() ────────────▶ Plane {normal, constant}
(変換行列)             (法線行列 + 共面点変換)    (変換後)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Plane.js | `src/math/Plane.js` | ソース | 平面クラス本体 |
| Vector3.js | `src/math/Vector3.js` | ソース | 3Dベクトルクラス（依存） |
| Matrix3.js | `src/math/Matrix3.js` | ソース | 法線行列の計算に使用 |
| Matrix4.js | `src/math/Matrix4.js` | ソース | 変換行列（applyMatrix4で使用） |
| Line3.js | `src/math/Line3.js` | ソース | 線分クラス（交差判定で使用） |
| Box3.js | `src/math/Box3.js` | ソース | 境界ボックス（交差判定で相互参照） |
| Sphere.js | `src/math/Sphere.js` | ソース | 境界球（交差判定で相互参照） |
| Frustum.js | `src/math/Frustum.js` | ソース | 視錐台（6つのPlaneで構成） |
