# 機能設計書 4-自動レイアウト

## 概要

本ドキュメントは、Liamシステムにおける「自動レイアウト」機能の設計を記述したものである。ELK（Eclipse Layout Kernel）アルゴリズムを使用してER図のテーブルノードを自動的に最適配置する機能である。

### 本機能の処理概要

本機能は、elkjsライブラリを使用してグラフ構造のレイアウト計算を行い、テーブルノードの位置を自動決定する。リレーションシップ（エッジ）を考慮した階層型レイアウトアルゴリズムにより、視認性の高いER図を自動生成する。

**業務上の目的・背景**：手動でテーブルノードを配置することは、テーブル数が多い場合に非常に時間がかかる。自動レイアウト機能により、初期表示時に最適な配置を自動計算し、ユーザーの作業効率を大幅に向上させる。

**機能の利用シーン**：
- 初回スキーマ読み込み時の自動配置
- ユーザーによる「整列」ボタン押下時
- 表示モード変更時の再配置
- フィルタリング後の再配置

**主要な処理内容**：
1. React FlowノードをELKノード形式に変換
2. ELKレイアウトエンジンでレイアウト計算
3. 計算結果をReact Flowノードに反映
4. 非表示ノードの除外処理
5. 親子関係（グループノード）の処理

**関連システム・外部連携**：elkjsライブラリを使用。ER図表示機能（No.1）から呼び出される。

**権限による制御**：表示のみの機能のため、認証ユーザーであればアクセス可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 12 | スキーマ画面 | 主画面 | ELKアルゴリズムによるER図の自動配置 |
| 14 | デザインセッション詳細画面 | 主画面 | 設計中スキーマの自動配置 |
| 20 | 公開ERD画面 | 主画面 | 公開スキーマの自動配置 |

## 機能種別

計算処理 / レイアウト計算

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| nodes | Node[] | Yes | React Flowノード配列 | - |
| edges | Edge[] | Yes | React Flowエッジ配列 | - |

### 入力データソース

- convertSchemaToNodes関数で生成されたnodes/edges
- ノードのmeasured値（描画後のサイズ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| nodes | Node[] | 位置情報が更新されたノード配列 |
| edges | Edge[] | 元のエッジ配列（変更なし） |

### 出力先

React Flowコンポーネントのノード状態

## 処理フロー

### 処理シーケンス

```
1. 入力ノード分類
   └─ 表示/非表示ノードを分離
2. エッジフィルタリング
   └─ 表示ノード間のエッジのみ抽出
3. ELKノード変換
   └─ convertNodesToElkNodesで変換
4. ELKレイアウト計算
   └─ elk.layout(graph)を実行
5. 結果変換
   └─ convertElkNodesToNodesでReact Flow形式に戻す
6. ノード統合
   └─ 非表示ノード + 配置済みノードを結合
```

### フローチャート

```mermaid
flowchart TD
    A[nodes/edges入力] --> B[表示/非表示ノード分離]
    B --> C[表示ノード間エッジ抽出]
    C --> D[convertNodesToElkNodes]
    D --> E[ELKグラフ構築]
    E --> F[elk.layout実行]
    F --> G[レイアウト結果取得]
    G --> H[convertElkNodesToNodes]
    H --> I[非表示ノードと結合]
    I --> J[結果返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | レイアウトアルゴリズム | layeredアルゴリズムを使用 | 常時 |
| BR-002 | 非表示ノード除外 | hidden=trueのノードはレイアウト計算から除外 | 常時 |
| BR-003 | エッジフィルタリング | 両端が表示ノードのエッジのみ計算対象 | 常時 |
| BR-004 | 非関連テーブルグループ | aspectRatio=0.5625（縦長）で子ノードを配置 | type=nonRelatedTableGroup |
| BR-005 | 通常ノード | aspectRatio=1.6f（横長）で配置 | それ以外 |

### 計算ロジック

ELKレイアウトオプション:
```javascript
{
  'elk.algorithm': 'layered',
  'elk.layered.spacing.baseValue': '40',
  'elk.spacing.componentComponent': '80',
  'elk.layered.spacing.edgeNodeBetweenLayers': '120',
  'elk.layered.considerModelOrder.strategy': 'PREFER_EDGES',
  'elk.layered.crossingMinimization.forceNodeModelOrder': 'true',
  'elk.layered.mergeEdges': 'true',
  'elk.layered.nodePlacement.strategy': 'INTERACTIVE',
  'elk.layered.layering.strategy': 'INTERACTIVE'
}
```

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

### 操作別データベース影響一覧

本機能はデータベースを直接操作しない。計算処理機能。

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ELK_ERROR | レイアウト計算エラー | ELKライブラリでの計算失敗 | 元のノード配列を返却 |

### リトライ仕様

なし（計算失敗時は元のノード位置を維持）

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

該当なし（メモリ内計算処理）

## パフォーマンス要件

- 非同期処理（async/await）で実行
- 大規模グラフ（500ノード）でも数秒以内
- Web Worker使用可能（elkjs/lib/elk.bundled.js）

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

- 外部ライブラリ（elkjs）の信頼性確認済み
- 入力データのサニタイズは不要（内部生成データ）

## 備考

elkjsはEclipse Layout Kernelのemscriptenポートであり、高品質なグラフレイアウトを提供する。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | computeAutoLayout.ts | `frontend/packages/erd-core/src/features/erd/utils/computeAutoLayout/computeAutoLayout.ts` | メイン処理フロー |

**主要処理フロー**:
1. **5-13行目**: 表示/非表示ノードの分離
2. **16-19行目**: 表示ノード間エッジのフィルタリング
3. **21-24行目**: getElkLayoutの呼び出し
4. **26-29行目**: 結果の統合と返却

#### Step 2: ELKレイアウト計算を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | getElkLayout.ts | `frontend/packages/erd-core/src/features/erd/utils/computeAutoLayout/getElkLayout.ts` | ELK呼び出しとオプション設定 |

**主要処理フロー**:
- **9-19行目**: layoutOptionsの定義（アルゴリズム設定）
- **27-36行目**: グラフオブジェクトの構築
- **38行目**: elk.layout(graph)の実行
- **43行目**: 結果の変換

#### Step 3: ノード変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | convertNodesToElkNodes.ts | `frontend/packages/erd-core/src/features/erd/utils/computeAutoLayout/convertNodesToElkNodes.ts` | React Flow → ELK変換 |
| 3-2 | convertElkNodesToNodes.ts | `frontend/packages/erd-core/src/features/erd/utils/computeAutoLayout/convertElkNodesToNodes.ts` | ELK → React Flow変換 |

**主要処理フロー (convertNodesToElkNodes.ts)**:
- **9-23行目**: ElkNode構造への変換、サイズとlayoutOptions設定
- **26-37行目**: 親子関係の処理（parentIdがある場合）

**主要処理フロー (convertElkNodesToNodes.ts)**:
- **13-21行目**: 位置とサイズの反映
- **23-27行目**: 子ノードの再帰的処理

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

```
ERDContent (useInitialAutoLayout)
    │
    └─ computeAutoLayout
           │
           ├─ ノード分離（hidden判定）
           │
           ├─ エッジフィルタリング
           │
           └─ getElkLayout
                  │
                  ├─ convertNodesToElkNodes
                  │      └─ 親子関係処理
                  │
                  ├─ elk.layout(graph)
                  │
                  └─ convertElkNodesToNodes
                         └─ 再帰的子ノード処理
```

### データフロー図

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

Node[] ────────────▶ 表示/非表示分離 ─────────▶ visibleNodes[]
                                                hiddenNodes[]
                           │
                           ▼
Edge[] ────────────▶ エッジフィルタリング ───▶ visibleEdges[]
                           │
                           ▼
visibleNodes[] ────▶ convertNodesToElkNodes ─▶ ElkNode[]
                           │
                           ▼
ElkNode[] ─────────▶ elk.layout() ───────────▶ 位置計算済みElkNode[]
                           │
                           ▼
ElkNode[] ─────────▶ convertElkNodesToNodes ─▶ 位置更新済みNode[]
                           │
                           ▼
                    hiddenNodes + 配置済みnodes ▶ 最終Node[]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| computeAutoLayout.ts | `frontend/packages/erd-core/src/features/erd/utils/computeAutoLayout/computeAutoLayout.ts` | ソース | メインエントリーポイント |
| getElkLayout.ts | `frontend/packages/erd-core/src/features/erd/utils/computeAutoLayout/getElkLayout.ts` | ソース | ELKレイアウト実行 |
| convertNodesToElkNodes.ts | `frontend/packages/erd-core/src/features/erd/utils/computeAutoLayout/convertNodesToElkNodes.ts` | ソース | RF→ELK変換 |
| convertElkNodesToNodes.ts | `frontend/packages/erd-core/src/features/erd/utils/computeAutoLayout/convertElkNodesToNodes.ts` | ソース | ELK→RF変換 |
| index.ts | `frontend/packages/erd-core/src/features/erd/utils/computeAutoLayout/index.ts` | ソース | re-export |
