# 機能設計書: Vector3（3次元ベクトル）

## 1. 機能概要

### 1.1 機能の目的
Vector3は、3次元空間における点、方向、色などを表現するためのクラスである。three.jsの中核を担う数学クラスであり、位置座標、法線ベクトル、スケール値、RGB色など、3成分を持つあらゆるデータに使用される。

### 1.2 主な機能
- 3次元ベクトルの基本演算（加算、減算、乗算、除算）
- ベクトルの正規化、長さ計算
- 内積、外積の計算
- 線形補間（lerp）、球面線形補間
- 行列変換（3x3, 4x4）の適用
- クォータニオンによる回転
- 座標系変換（ワールド、ローカル）
- 投影、反射計算

### 1.3 関連する画面/コンポーネント
- Object3Dの位置、回転、スケール
- カメラとライトの位置・方向
- ジオメトリの頂点座標、法線
- レイキャスティング
- 物理シミュレーション

## 2. 機能仕様

### 2.1 データ構造

```javascript
class Vector3 {
    x: number;  // X成分
    y: number;  // Y成分
    z: number;  // Z成分
    isVector3: boolean;  // 型判定フラグ
}
```

### 2.2 プロパティ詳細

| プロパティ名 | 型 | 説明 | デフォルト値 |
|-------------|-----|------|-------------|
| x | number | X成分 | 0 |
| y | number | Y成分 | 0 |
| z | number | Z成分 | 0 |
| isVector3 | boolean | 型判定フラグ（読み取り専用） | true |

### 2.3 メソッド詳細（主要なもの）

#### 2.3.1 基本操作
| メソッド | 説明 |
|---------|------|
| set(x, y, z) | 成分を設定 |
| setScalar(scalar) | 全成分を同じ値に設定 |
| setX(x) / setY(y) / setZ(z) | 個別成分を設定 |
| clone() | 複製を作成 |
| copy(v) | 他のベクトルをコピー |

#### 2.3.2 算術演算
| メソッド | 説明 |
|---------|------|
| add(v) | ベクトル加算 |
| addScalar(s) | スカラー加算 |
| sub(v) | ベクトル減算 |
| multiply(v) | 成分ごとの乗算 |
| multiplyScalar(s) | スカラー乗算 |
| divide(v) | 成分ごとの除算 |
| divideScalar(s) | スカラー除算 |

#### 2.3.3 長さ・正規化
| メソッド | 説明 |
|---------|------|
| length() | ベクトルの長さ |
| lengthSq() | 長さの2乗 |
| manhattanLength() | マンハッタン距離 |
| normalize() | 単位ベクトルに正規化 |
| setLength(l) | 指定長さに設定 |

#### 2.3.4 幾何学演算
| メソッド | 説明 |
|---------|------|
| dot(v) | 内積 |
| cross(v) | 外積 |
| crossVectors(a, b) | 2ベクトルの外積 |
| angleTo(v) | 2ベクトル間の角度 |
| distanceTo(v) | 点間距離 |
| distanceToSquared(v) | 点間距離の2乗 |

#### 2.3.5 変換
| メソッド | 説明 |
|---------|------|
| applyMatrix3(m) | 3x3行列を適用 |
| applyMatrix4(m) | 4x4行列を適用 |
| applyNormalMatrix(m) | 法線行列を適用 |
| applyQuaternion(q) | クォータニオンで回転 |
| applyEuler(euler) | オイラー角で回転 |
| applyAxisAngle(axis, angle) | 軸回転を適用 |
| project(camera) | カメラ空間に投影 |
| unproject(camera) | 投影を逆変換 |
| transformDirection(m) | 方向ベクトルとして変換 |

#### 2.3.6 補間・制限
| メソッド | 説明 |
|---------|------|
| lerp(v, alpha) | 線形補間 |
| lerpVectors(v1, v2, alpha) | 2ベクトル間の線形補間 |
| clamp(min, max) | 範囲内に制限 |
| clampLength(min, max) | 長さを範囲内に制限 |
| floor() / ceil() / round() | 各成分を丸め |

#### 2.3.7 その他
| メソッド | 説明 |
|---------|------|
| reflect(normal) | 反射ベクトル計算 |
| projectOnVector(v) | ベクトルへの射影 |
| projectOnPlane(normal) | 平面への射影 |
| setFromMatrixPosition(m) | 行列から位置を抽出 |
| setFromMatrixScale(m) | 行列からスケールを抽出 |
| setFromMatrixColumn(m, i) | 行列から列を抽出 |
| setFromSpherical(s) | 球面座標から設定 |
| setFromCylindrical(c) | 円筒座標から設定 |
| random() | ランダムな単位ベクトル |

### 2.4 ビジネスルール
- ベクトル演算は元のベクトルを変更する（ミュータブル）
- clone()やcopy()で不変性が必要な場合に対応
- 長さ0のベクトルを正規化するとゼロベクトルになる
- cross()は右手座標系に従う

## 3. 処理フロー

### 3.1 外積計算フロー
```
[crossVectors(a, b)]
        |
        v
[各成分の計算]
ax = a.x, ay = a.y, az = a.z
bx = b.x, by = b.y, bz = b.z
        |
        v
[外積の公式適用]
this.x = ay * bz - az * by
this.y = az * bx - ax * bz
this.z = ax * by - ay * bx
        |
        v
[自身を返却]
```

### 3.2 クォータニオン回転フロー
```
[applyQuaternion(q)]
        |
        v
[クォータニオン成分取得]
qx, qy, qz, qw = q._x, q._y, q._z, q._w
        |
        v
[ベクトル成分取得]
vx, vy, vz = this.x, this.y, this.z
        |
        v
[回転計算（q * v * q^-1）]
ix = qw * vx + qy * vz - qz * vy
iy = qw * vy + qz * vx - qx * vz
iz = qw * vz + qx * vy - qy * vx
iw = -qx * vx - qy * vy - qz * vz
        |
        v
[結果成分計算]
this.x = ix * qw + iw * (-qx) + iy * (-qz) - iz * (-qy)
this.y = iy * qw + iw * (-qy) + iz * (-qx) - ix * (-qz)
this.z = iz * qw + iw * (-qz) + ix * (-qy) - iy * (-qx)
```

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

### 4.1 推奨読解順序
1. **Vector3.js** - クラス定義とプロパティ（1-50行目）
2. 基本操作メソッド（50-150行目）
3. 算術演算メソッド（150-300行目）
4. 長さと正規化（300-400行目）
5. 幾何学演算（400-500行目）
6. 行列・クォータニオン変換（500-650行目）

### 4.2 重要な処理の詳細

#### コンストラクタ（30-40行目）
```javascript
constructor( x = 0, y = 0, z = 0 ) {
    Vector3.prototype.isVector3 = true;
    this.x = x;
    this.y = y;
    this.z = z;
}
```

#### cross()（外積、324-336行目）
```javascript
cross( v ) {
    return this.crossVectors( this, v );
}

crossVectors( a, b ) {
    const ax = a.x, ay = a.y, az = a.z;
    const bx = b.x, by = b.y, bz = b.z;

    this.x = ay * bz - az * by;
    this.y = az * bx - ax * bz;
    this.z = ax * by - ay * bx;

    return this;
}
```

#### applyQuaternion()（回転、418-442行目）
```javascript
applyQuaternion( q ) {
    const vx = this.x, vy = this.y, vz = this.z;
    const qx = q.x, qy = q.y, qz = q.z, qw = q.w;

    // t = 2 * cross( q.xyz, v )
    const tx = 2 * ( qy * vz - qz * vy );
    const ty = 2 * ( qz * vx - qx * vz );
    const tz = 2 * ( qx * vy - qy * vx );

    // v + q.w * t + cross( q.xyz, t )
    this.x = vx + qw * tx + qy * tz - qz * ty;
    this.y = vy + qw * ty + qz * tx - qx * tz;
    this.z = vz + qw * tz + qx * ty - qy * tx;

    return this;
}
```

#### project()（カメラ投影、470-478行目）
```javascript
project( camera ) {
    return this.applyMatrix4( camera.matrixWorldInverse )
               .applyMatrix4( camera.projectionMatrix );
}
```

#### unproject()（逆投影、486-494行目）
```javascript
unproject( camera ) {
    return this.applyMatrix4( camera.projectionMatrixInverse )
               .applyMatrix4( camera.matrixWorld );
}
```

### 4.3 プログラム呼び出し階層図
```
Vector3
├── 基本操作
│   ├── set() / setScalar() / setX/Y/Z()
│   ├── setComponent() / getComponent()
│   └── clone() / copy()
├── 算術演算
│   ├── add() / addScalar() / addVectors() / addScaledVector()
│   ├── sub() / subScalar() / subVectors()
│   ├── multiply() / multiplyScalar() / multiplyVectors()
│   └── divide() / divideScalar()
├── 長さ・正規化
│   ├── length() / lengthSq() / manhattanLength()
│   ├── normalize() / setLength()
│   └── negate()
├── 比較・制限
│   ├── min() / max() / clamp()
│   ├── clampLength() / clampScalar()
│   ├── floor() / ceil() / round() / roundToZero()
│   └── equals()
├── 幾何学演算
│   ├── dot() / cross() / crossVectors()
│   ├── angleTo()
│   ├── distanceTo() / distanceToSquared() / manhattanDistanceTo()
│   ├── reflect() / projectOnVector() / projectOnPlane()
│   └── setFromSpherical() / setFromSphericalCoords()
├── 変換
│   ├── applyMatrix3() / applyNormalMatrix()
│   ├── applyMatrix4() / transformDirection()
│   ├── applyQuaternion() / applyEuler() / applyAxisAngle()
│   ├── project() / unproject()
│   └── setFromMatrixPosition/Scale/Column()
├── 補間
│   ├── lerp() / lerpVectors()
│   └── random()
└── 配列変換
    ├── fromArray() / toArray()
    └── fromBufferAttribute()
```

### 4.4 データフロー図
```
[入力値 (x, y, z)]
      |
      v
[Vector3インスタンス]
      |
      +---> [行列変換] ---> [変換後Vector3]
      |         |
      |         +---> applyMatrix3() / applyMatrix4()
      |
      +---> [クォータニオン回転] ---> [回転後Vector3]
      |
      +---> [投影] ---> [NDC座標 (-1 to 1)]
      |         |
      |         +---> project(camera)
      |
      +---> [外積] ---> [垂直なVector3]
      |
      +---> [正規化] ---> [単位Vector3]
```

### 4.5 関連ファイル一覧
| ファイルパス | 種別 | 役割 |
|-------------|------|------|
| src/math/Vector3.js | メイン | Vector3クラスの実装 |
| src/math/Matrix3.js | 関連 | 3x3行列変換 |
| src/math/Matrix4.js | 関連 | 4x4行列変換 |
| src/math/Quaternion.js | 関連 | クォータニオン回転 |
| src/math/Euler.js | 関連 | オイラー角回転 |
| src/math/Spherical.js | 関連 | 球面座標変換 |
| src/math/Cylindrical.js | 関連 | 円筒座標変換 |
| src/core/BufferAttribute.js | 関連 | 頂点データアクセス |

## 5. 使用例

### 5.1 基本的な使用例
```javascript
// ベクトルの作成
const v1 = new THREE.Vector3(1, 2, 3);
const v2 = new THREE.Vector3(4, 5, 6);

// 加算
v1.add(v2);  // v1 = (5, 7, 9)

// 外積（法線計算）
const normal = new THREE.Vector3();
normal.crossVectors(v1, v2);
normal.normalize();
```

### 5.2 カメラ投影
```javascript
// 3Dワールド座標をスクリーン座標に変換
const worldPos = new THREE.Vector3(10, 5, 0);
const screenPos = worldPos.clone().project(camera);

// NDC座標（-1 to 1）からピクセル座標に変換
const x = (screenPos.x + 1) / 2 * window.innerWidth;
const y = (-screenPos.y + 1) / 2 * window.innerHeight;
```

### 5.3 クォータニオンによる回転
```javascript
const direction = new THREE.Vector3(0, 0, 1);
const quaternion = new THREE.Quaternion();
quaternion.setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI / 2);

direction.applyQuaternion(quaternion);  // (1, 0, 0)
```

### 5.4 反射計算
```javascript
const incident = new THREE.Vector3(1, -1, 0).normalize();
const normal = new THREE.Vector3(0, 1, 0);

const reflected = incident.clone().reflect(normal);
// (1, 1, 0).normalize()
```

## 6. 備考

### 6.1 パフォーマンス考慮事項
- length()よりlengthSq()が高速（平方根計算なし）
- 比較目的ならdistanceToSquared()を使用
- 頻繁な生成を避け、オブジェクトを再利用
- three.js内部では_v1等の一時ベクトルをモジュールスコープで再利用

### 6.2 座標系
- three.jsは右手座標系
- Y軸が上、Z軸が手前（カメラが-Z方向を向く）
- cross()は右手座標系に従う

### 6.3 精度の注意
- 浮動小数点演算の誤差に注意
- equals()は厳密な比較（===）を使用
- 誤差許容比較にはdistanceTo()との組み合わせを検討
