# 機能設計書 137-Triangle

## 概要

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

### 本機能の処理概要

Triangleクラスは、3D空間における三角形を表現するためのクラスである。3つの頂点（a, b, c）によって三角形を定義し、法線計算、面積計算、重心座標（Barycentric Coordinates）による補間、点の包含判定、最近点計算などの幾何学計算を提供する。3Dメッシュの基本構成要素として、レイキャスティング、衝突検出、属性補間など多くの処理で使用される。

**業務上の目的・背景**：3Dグラフィックスにおいて、三角形はポリゴンメッシュの基本構成単位である。三角形に対する各種計算（法線、面積、重心座標など）は、シェーディング、テクスチャマッピング、衝突検出、LOD計算など、レンダリングとインタラクションの核心的な処理で必要とされる。

**機能の利用シーン**：
- メッシュの各三角形面に対する法線計算
- Raycasterでの三角形との交差判定
- 重心座標によるUV座標・法線・頂点カラーの補間
- 点と三角形の最近点計算（衝突応答）
- 三角形の面積計算（LODの重要度計算）
- 表裏判定（背面カリング）

**主要な処理内容**：
1. 三角形の生成と初期化（3頂点の設定）
2. 法線ベクトル・中点・面積の計算
3. 重心座標の計算と補間
4. 点の包含判定・最近点計算
5. 表裏判定（isFrontFacing）
6. ボックスとの交差判定
7. BufferAttributeからの頂点データ読み込み

**関連システム・外部連携**：Mesh、Raycaster、BufferAttribute、Box3、Planeなどと連携。

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

## 関連画面

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

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

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| a | Vector3 | No | 三角形の第1頂点 | デフォルト: (0, 0, 0) |
| b | Vector3 | No | 三角形の第2頂点 | デフォルト: (0, 0, 0) |
| c | Vector3 | No | 三角形の第3頂点 | デフォルト: (0, 0, 0) |

### 入力データソース

コンストラクタ引数、メソッド呼び出し、またはBufferAttributeからの読み込み

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| a | Vector3 | 三角形の第1頂点 |
| b | Vector3 | 三角形の第2頂点 |
| c | Vector3 | 三角形の第3頂点 |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. 三角形の初期化
   └─ a, b, c = (0,0,0)で初期化
2. 三角形の設定
   ├─ set: 3頂点を直接設定
   ├─ setFromPointsAndIndices: 配列とインデックスから設定
   └─ setFromAttributeAndIndices: BufferAttributeから設定
3. 幾何学プロパティ計算
   ├─ getNormal: 法線ベクトル（外積で計算）
   ├─ getMidpoint: 中点
   ├─ getArea: 面積（外積の長さ/2）
   └─ getPlane: 三角形を含む平面
4. 重心座標計算
   ├─ getBarycoord: 点の重心座標
   ├─ getInterpolation: 重心座標による補間
   └─ getInterpolatedAttribute: 属性の補間
5. 点との関係
   ├─ containsPoint: 包含判定
   └─ closestPointToPoint: 最近点計算
6. 方向判定
   └─ isFrontFacing: 表裏判定
```

### フローチャート

```mermaid
flowchart TD
    A[Triangleインスタンス生成] --> B{設定方法}
    B -->|set| C[3頂点を直接設定]
    B -->|setFromPointsAndIndices| D[配列から設定]
    B -->|setFromAttributeAndIndices| E[BufferAttributeから設定]
    C --> F[三角形確定]
    D --> F
    E --> F
    F --> G{操作種別}
    G -->|プロパティ| H[getNormal/getMidpoint/getArea]
    G -->|重心座標| I[getBarycoord/getInterpolation]
    G -->|包含判定| J[containsPoint]
    G -->|最近点| K[closestPointToPoint]
    G -->|表裏| L[isFrontFacing]
    I --> M{縮退三角形?}
    M -->|Yes| N[nullを返す]
    M -->|No| O[重心座標を計算]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 巻き順序 | a->b->cの反時計回りで法線が手前を向く | getNormal |
| BR-002 | 縮退三角形 | 3点が一直線上にある場合、面積0でnullを返す | getBarycoord |
| BR-003 | 重心座標の合計 | 重心座標の3成分の合計は常に1 | 有効な三角形内の点 |
| BR-004 | 表裏判定 | dot(normal, direction) < 0 で表向き | isFrontFacing |

### 計算ロジック

**法線ベクトルの計算**:
```javascript
edge1 = c - b
edge2 = a - b
normal = normalize(cross(edge1, edge2))
```

**面積の計算**:
```javascript
area = length(cross(c - b, a - b)) * 0.5
```

**重心座標の計算**:
```javascript
// http://www.blackpawn.com/texts/pointinpoly/ を参考
v0 = c - a, v1 = b - a, v2 = point - a
dot00 = dot(v0, v0), dot01 = dot(v0, v1), dot02 = dot(v0, v2)
dot11 = dot(v1, v1), dot12 = dot(v1, v2)
denom = dot00 * dot11 - dot01 * dot01
if (denom == 0) return null  // 縮退三角形
u = (dot11 * dot02 - dot01 * dot12) / denom
v = (dot00 * dot12 - dot01 * dot02) / denom
barycoord = (1 - u - v, v, u)
```

**重心座標による補間**:
```javascript
interpolated = v1 * barycoord.x + v2 * barycoord.y + v3 * barycoord.z
```

**点の包含判定**:
```javascript
barycoord = getBarycoord(point)
contained = barycoord.x >= 0 && barycoord.y >= 0 && (barycoord.x + barycoord.y) <= 1
```

**最近点計算（Ericsonアルゴリズム）**:
```javascript
// "Real-Time Collision Detection" by Christer Ericson, chapter 5.1.5
// ボロノイ領域に基づく判定で、最も近い領域（頂点/辺/面）を特定
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 縮退三角形 | 3点が一直線上（面積0） | getBarycoordがnullを返す |
| - | ゼロ法線 | 縮退三角形の法線計算 | getNormalが(0,0,0)を返す |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

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

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

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

## 備考

- Mesh.raycast()で三角形との交差判定に使用
- 重心座標はテクスチャ座標、法線、頂点カラーの補間に広く使用
- closestPointToPointはEricsonの"Real-Time Collision Detection"を基にしている
- 静的メソッドとインスタンスメソッドの両方を提供

---

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

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

### 推奨読解順序

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

Triangleクラスはa, b, c（各Vector3）で三角形を表現する。

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

**読解のコツ**: 三角形の頂点の巻き順（winding order）が法線の方向を決定する。a->b->cの反時計回りで法線が手前を向く。

#### Step 2: 静的メソッドを理解する

Triangleクラスの静的メソッドを理解する。これらはインスタンスなしで使用可能。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Triangle.js | `src/math/Triangle.js` | static getNormal, getBarycoord, containsPoint, getInterpolation |

**主要処理フロー**:
1. **66-81行目**: static getNormal() - 外積で法線を計算
2. **94-125行目**: static getBarycoord() - 重心座標の計算
3. **138-149行目**: static containsPoint() - 重心座標による包含判定
4. **165-184行目**: static getInterpolation() - 重心座標による補間

#### Step 3: インスタンスメソッドを理解する

三角形インスタンスに対する操作メソッドを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Triangle.js | `src/math/Triangle.js` | set系、getArea、getMidpoint、getNormal |

**主要処理フロー**:
- **243-251行目**: set() - 3頂点を設定
- **262-270行目**: setFromPointsAndIndices() - 配列から設定
- **281-289行目**: setFromAttributeAndIndices() - BufferAttributeから設定
- **323-330行目**: getArea() - 外積の長さ/2
- **338-342行目**: getMidpoint() - (a + b + c) / 3

#### Step 4: 重心座標と補間を理解する

重心座標の計算と属性補間のロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Triangle.js | `src/math/Triangle.js` | getBarycoord, getInterpolation, getInterpolatedAttribute |

**主要処理フロー**:
- **94-125行目**: getBarycoord() - blackpawn.comのアルゴリズム
  - **108行目**: denom == 0 で縮退三角形を検出
  - **123行目**: 重心座標(1-u-v, v, u)を返す
- **197-214行目**: getInterpolatedAttribute() - BufferAttributeから補間

#### Step 5: 最近点計算を理解する

点と三角形の最近点計算（ボロノイ領域判定）を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | Triangle.js | `src/math/Triangle.js` | closestPointToPoint()の詳細 |

**主要処理フロー**:
- **444-523行目**: closestPointToPoint() - Ericsonアルゴリズム
  - **449-453行目**: "Real-Time Collision Detection"への参照
  - **455-465行目**: 頂点Aのボロノイ領域判定
  - **467-476行目**: 頂点Bのボロノイ領域判定
  - **478-484行目**: 辺ABのボロノイ領域判定
  - **486-495行目**: 頂点Cのボロノイ領域判定
  - **496-503行目**: 辺ACのボロノイ領域判定
  - **505-513行目**: 辺BCのボロノイ領域判定
  - **516-521行目**: 面領域（三角形内部）

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

```
Triangle
    │
    ├─ static getNormal(a, b, c, target)
    │      ├─ _v0.subVectors(c, b)
    │      ├─ target.subVectors(a, b)
    │      └─ target.cross(_v0).normalize()
    │
    ├─ static getBarycoord(point, a, b, c, target)
    │      ├─ v0 = c - a, v1 = b - a, v2 = point - a
    │      ├─ ドット積の計算
    │      ├─ denom = dot00 * dot11 - dot01 * dot01
    │      └─ target.set(1 - u - v, v, u)
    │
    ├─ static getInterpolation(point, p1, p2, p3, v1, v2, v3, target)
    │      ├─ getBarycoord(point, p1, p2, p3, _v3)
    │      └─ target = v1 * bary.x + v2 * bary.y + v3 * bary.z
    │
    ├─ getPlane(target)
    │      └─ target.setFromCoplanarPoints(a, b, c)
    │
    └─ closestPointToPoint(p, target)
           ├─ ボロノイ領域の判定
           ├─ 頂点領域 -> 頂点を返す
           ├─ 辺領域 -> 辺上の最近点を計算
           └─ 面領域 -> 面内の点を計算
```

### データフロー図

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

Vector3 x 3 ────────▶ new Triangle() ──────────▶ Triangle {a, b, c}
(3頂点)

Vector3 ───────────▶ getBarycoord() ────────────▶ Vector3 | null
(点)                  (重心座標計算)              (u, v, w)

Vector3 x 3 ────────▶ getInterpolation() ───────▶ Vector3
(頂点属性)            (重心座標補間)              (補間値)

BufferAttribute ────▶ setFromAttributeAndIndices() ▶ Triangle
(頂点データ)          (インデックスで設定)

Vector3 ───────────▶ closestPointToPoint() ────▶ Vector3
(点)                  (ボロノイ領域判定)          (最近点)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Triangle.js | `src/math/Triangle.js` | ソース | 三角形クラス本体 |
| Vector3.js | `src/math/Vector3.js` | ソース | 3Dベクトルクラス（依存） |
| Vector4.js | `src/math/Vector4.js` | ソース | getInterpolatedAttributeで使用 |
| Plane.js | `src/math/Plane.js` | ソース | getPlaneで使用 |
| Box3.js | `src/math/Box3.js` | ソース | intersectsBoxで相互参照 |
| BufferAttribute.js | `src/core/BufferAttribute.js` | ソース | 頂点データの読み込みに使用 |
