# 機能設計書: Vector2（2次元ベクトル）

## 1. 機能概要

### 1.1 機能の目的
Vector2は、2次元空間における点や方向を表現するためのクラスである。UV座標、2Dポジション、スクリーン座標など、2次元データを扱うthree.jsのあらゆる場面で使用される基本的な数学クラスである。

### 1.2 主な機能
- 2次元ベクトルの基本演算（加算、減算、乗算、除算）
- ベクトルの正規化、長さ計算
- 内積、外積の計算
- 線形補間（lerp）
- 角度計算
- 行列変換の適用
- イテレータによる成分アクセス

### 1.3 関連する画面/コンポーネント
- UV座標の操作
- 2Dレンダリング
- スクリーン座標計算
- テクスチャマッピング

## 2. 機能仕様

### 2.1 データ構造

```javascript
class Vector2 {
    x: number;  // X成分
    y: number;  // Y成分
    isVector2: boolean;  // 型判定フラグ
}
```

### 2.2 プロパティ詳細

| プロパティ名 | 型 | 説明 | デフォルト値 |
|-------------|-----|------|-------------|
| x | number | X成分 | 0 |
| y | number | Y成分 | 0 |
| isVector2 | boolean | 型判定フラグ（読み取り専用） | true |
| width | number | xの別名アクセサ | - |
| height | number | yの別名アクセサ | - |

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

#### 2.3.1 constructor(x, y)
```javascript
constructor(x: number = 0, y: number = 0)
```
**処理内容:** X, Y成分を初期化

#### 2.3.2 set(x, y)
```javascript
set(x: number, y: number): Vector2
```
**処理内容:** 成分を設定し、自身を返す

#### 2.3.3 add(v)
```javascript
add(v: Vector2): Vector2
```
**処理内容:** ベクトルvを加算

#### 2.3.4 sub(v)
```javascript
sub(v: Vector2): Vector2
```
**処理内容:** ベクトルvを減算

#### 2.3.5 multiply(v)
```javascript
multiply(v: Vector2): Vector2
```
**処理内容:** 成分ごとに乗算

#### 2.3.6 divide(v)
```javascript
divide(v: Vector2): Vector2
```
**処理内容:** 成分ごとに除算

#### 2.3.7 length()
```javascript
length(): number
```
**処理内容:** ベクトルの長さ（ユークリッド距離）を計算

#### 2.3.8 normalize()
```javascript
normalize(): Vector2
```
**処理内容:** ベクトルを単位ベクトルに正規化

#### 2.3.9 dot(v)
```javascript
dot(v: Vector2): number
```
**処理内容:** ベクトルvとの内積を計算

#### 2.3.10 cross(v)
```javascript
cross(v: Vector2): number
```
**処理内容:** ベクトルvとの外積（z成分）を計算

#### 2.3.11 lerp(v, alpha)
```javascript
lerp(v: Vector2, alpha: number): Vector2
```
**処理内容:** ベクトルvとの線形補間

#### 2.3.12 angle()
```javascript
angle(): number
```
**処理内容:** 正のX軸からの角度をラジアンで返す

#### 2.3.13 rotateAround(center, angle)
```javascript
rotateAround(center: Vector2, angle: number): Vector2
```
**処理内容:** 指定点を中心に回転

#### 2.3.14 applyMatrix3(m)
```javascript
applyMatrix3(m: Matrix3): Vector2
```
**処理内容:** 3x3行列を適用

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

### 2.5 イテレータ対応
```javascript
*[Symbol.iterator]() {
    yield this.x;
    yield this.y;
}
```
for...of構文やスプレッド演算子で成分にアクセス可能。

## 3. 入出力設計

### 3.1 配列変換
| メソッド | 入力 | 出力 |
|---------|------|------|
| fromArray(array, offset) | number[], number | Vector2 |
| toArray(array, offset) | number[], number | number[] |
| fromBufferAttribute(attr, index) | BufferAttribute, number | Vector2 |

## 4. 処理フロー

### 4.1 ベクトル正規化フロー
```
[normalize()呼び出し]
        |
        v
[length()で長さ計算]
        |
        v
[長さが0?]
   Yes |         No
       v          |
[ゼロベクトル]     |
       |          v
       |   [各成分を長さで除算]
       |          |
       v          v
[自身を返却]<-----'
```

### 4.2 行列変換フロー
```
[applyMatrix3(m)]
        |
        v
[現在のx, yを保存]
        |
        v
[行列要素を取得]
        |
        v
[x = e[0]*x + e[3]*y + e[6]]
[y = e[1]*x + e[4]*y + e[7]]
        |
        v
[自身を返却]
```

## 5. エラーハンドリング

### 5.1 エラー条件
| エラー条件 | エラー種別 | 対処方法 |
|-----------|-----------|---------|
| 無効な引数 | TypeError | 数値以外が渡された場合NaNになる |
| ゼロ除算 | - | Infinityまたは-Infinityになる |

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

### 6.1 推奨読解順序
1. **Vector2.js** - クラス定義とプロパティ
2. コンストラクタとset()メソッド
3. 基本演算メソッド（add, sub, multiply, divide）
4. 長さと正規化（length, normalize）
5. 高度な演算（dot, cross, lerp, angle）

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

#### コンストラクタ（30-36行目）
```javascript
constructor( x = 0, y = 0 ) {
    Vector2.prototype.isVector2 = true;
    this.x = x;
    this.y = y;
}
```
**31行目**: 型判定フラグをプロトタイプに設定
**32-33行目**: 成分の初期化

#### length()（175-179行目）
```javascript
length() {
    return Math.sqrt( this.x * this.x + this.y * this.y );
}
```
ユークリッドノルムの計算

#### normalize()（219-233行目）
```javascript
normalize() {
    return this.divideScalar( this.length() || 1 );
}
```
**220行目**: 長さが0の場合は1で除算（ゼロベクトル維持）

#### dot()（243-247行目）
```javascript
dot( v ) {
    return this.x * v.x + this.y * v.y;
}
```
2次元内積の計算

#### cross()（256-260行目）
```javascript
cross( v ) {
    return this.x * v.y - this.y * v.x;
}
```
2次元外積（擬似外積、z成分のみ）

#### angle()（298-302行目）
```javascript
angle() {
    const angle = Math.atan2( - this.y, - this.x ) + Math.PI;
    return angle;
}
```
正のX軸からの角度を計算（0から2πの範囲）

### 6.3 プログラム呼び出し階層図
```
Vector2
├── 基本操作
│   ├── set() / setX() / setY()
│   ├── setScalar() / setComponent()
│   └── clone() / copy()
├── 算術演算
│   ├── add() / addScalar() / addVectors()
│   ├── sub() / subScalar() / subVectors()
│   ├── multiply() / multiplyScalar()
│   └── divide() / divideScalar()
├── 長さ・正規化
│   ├── length() / lengthSq()
│   ├── manhattanLength()
│   └── normalize() / setLength()
├── 比較・判定
│   ├── min() / max() / clamp()
│   ├── floor() / ceil() / round()
│   └── equals()
├── 幾何学演算
│   ├── dot() / cross()
│   ├── angle() / angleTo()
│   ├── distanceTo() / distanceToSquared()
│   └── rotateAround()
├── 補間
│   ├── lerp() / lerpVectors()
│   └── random()
└── 変換
    ├── applyMatrix3()
    ├── fromArray() / toArray()
    └── fromBufferAttribute()
```

### 6.4 データフロー図
```
[入力値 (x, y)]
      |
      v
[Vector2インスタンス]
      |
      +---> [算術演算] ---> [変更されたVector2]
      |
      +---> [長さ計算] ---> [number]
      |
      +---> [正規化] ---> [単位ベクトル]
      |
      +---> [行列変換] ---> [変換後Vector2]
      |
      +---> [配列変換] ---> [number[]]
```

### 6.5 関連ファイル一覧
| ファイルパス | 種別 | 役割 |
|-------------|------|------|
| src/math/Vector2.js | メイン | Vector2クラスの実装 |
| src/math/Matrix3.js | 関連 | 2D変換行列 |
| src/core/BufferAttribute.js | 関連 | 頂点データアクセス |
| src/math/MathUtils.js | 関連 | 数学ユーティリティ（clamp等） |

## 7. 使用例

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

// 加算
v1.add(v2);  // v1 = (4, 6)

// 長さの計算
const length = v1.length();  // √(16 + 36) = √52

// 正規化
v1.normalize();  // 単位ベクトル化
```

### 7.2 UV座標の操作
```javascript
const uv = new THREE.Vector2(0.5, 0.5);

// スケーリング
uv.multiplyScalar(2);  // (1.0, 1.0)

// オフセット
uv.add(new THREE.Vector2(0.1, 0.1));  // (1.1, 1.1)

// クランプ（0-1の範囲に制限）
uv.clamp(new THREE.Vector2(0, 0), new THREE.Vector2(1, 1));
```

### 7.3 角度と回転
```javascript
const direction = new THREE.Vector2(1, 0);

// 角度の取得（ラジアン）
const angle = direction.angle();  // 0

// 点を中心に回転
const center = new THREE.Vector2(0, 0);
direction.rotateAround(center, Math.PI / 2);  // (0, 1)
```

### 7.4 線形補間
```javascript
const start = new THREE.Vector2(0, 0);
const end = new THREE.Vector2(10, 10);

// 中間点の計算
const mid = start.clone().lerp(end, 0.5);  // (5, 5)
```

## 8. 備考

### 8.1 パフォーマンス考慮事項
- length()よりlengthSq()の方が高速（平方根計算なし）
- 比較目的ならlengthSq()を使用すべき
- 頻繁に生成する場合はオブジェクトプールの使用を検討

### 8.2 イミュータブルな操作
```javascript
// ミュータブル（元のベクトルが変更される）
v1.add(v2);

// イミュータブル（新しいベクトルを作成）
const v3 = v1.clone().add(v2);
```

### 8.3 関連クラスとの違い
| クラス | 次元 | 主な用途 |
|--------|------|---------|
| Vector2 | 2D | UV座標、スクリーン座標 |
| Vector3 | 3D | 位置、方向、色 |
| Vector4 | 4D | 同次座標、シェーダーデータ |
