# 機能設計書 148-PlotLines

## 概要

本ドキュメントは、Dear ImGuiライブラリにおけるPlotLines関数の機能設計を記述する。PlotLinesは浮動小数点データの折れ線グラフを表示する関数である。

### 本機能の処理概要

PlotLines関数は、配列またはコールバック関数から取得した数値データを折れ線グラフとして描画する。シンプルなデータ可視化のためのウィジェットで、リアルタイムデータの監視やデバッグに適している。

**業務上の目的・背景**：数値データの時系列変化や傾向を視覚的に確認する必要がある場面は多い。PlotLinesは、ImGuiアプリケーション内で簡単にグラフを表示できる機能を提供する。より高度なグラフ機能が必要な場合はImPlotの使用を推奨。

**機能の利用シーン**：
- FPSやフレームタイムの推移表示
- センサーデータのリアルタイム監視
- オーディオ波形の表示
- メモリ使用量の推移表示
- デバッグ情報の可視化

**主要な処理内容**：
1. グラフ領域のレイアウト計算
2. スケール（最小値・最大値）の自動計算または指定値の使用
3. フレーム背景の描画
4. データポイント間の線分描画
5. ホバー時のツールチップ表示
6. オーバーレイテキストの描画

**関連システム・外部連携**：
- 内部でPlotEx関数を使用
- DrawListを使用した描画

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 23 | Widgets | 補助機能 | 折れ線グラフのデモ |

## 機能種別

データ可視化 / グラフ描画

## 入力仕様

### 入力パラメータ（配列版）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| label | const char* | Yes | グラフのラベル | NULL不可 |
| values | const float* | Yes | データ配列 | NULL不可 |
| values_count | int | Yes | データ数 | >= 2 |
| values_offset | int | No | データ開始オフセット（循環バッファ用） | >= 0 |
| overlay_text | const char* | No | グラフ上に表示するテキスト | - |
| scale_min | float | No | Y軸最小値（FLT_MAXで自動） | - |
| scale_max | float | No | Y軸最大値（FLT_MAXで自動） | - |
| graph_size | ImVec2 | No | グラフサイズ（0で自動） | - |
| stride | int | No | データ配列のストライド | > 0 |

### 入力パラメータ（コールバック版）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| label | const char* | Yes | グラフのラベル | NULL不可 |
| values_getter | float(*)(void*, int) | Yes | データ取得コールバック | NULL不可 |
| data | void* | Yes | コールバックに渡すデータ | 任意 |
| values_count | int | Yes | データ数 | >= 2 |
| values_offset | int | No | データ開始オフセット | >= 0 |
| overlay_text | const char* | No | グラフ上に表示するテキスト | - |
| scale_min | float | No | Y軸最小値（FLT_MAXで自動） | - |
| scale_max | float | No | Y軸最大値（FLT_MAXで自動） | - |
| graph_size | ImVec2 | No | グラフサイズ（0で自動） | - |

### 入力データソース

- 呼び出し元からの配列またはコールバックによるデータ取得
- グローバルコンテキスト（GImGui）からのスタイル設定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| （戻り値なし） | void | - |

### 出力先

- 画面描画（折れ線グラフ）
- ツールチップ（ホバー時）

## 処理フロー

### 処理シーケンス

```
1. ウィンドウスキップ確認
   └─ window->SkipItemsがtrueなら早期リターン

2. レイアウト計算
   └─ CalcItemSizeでグラフサイズを決定
   └─ フレームとインナーの矩形を計算

3. ItemAdd
   └─ アイテムを登録、クリッピング判定

4. ButtonBehavior
   └─ ホバー状態の検出

5. スケール計算
   └─ scale_min/max == FLT_MAXの場合、データから自動計算
   └─ NaN値は無視

6. フレーム背景描画
   └─ RenderFrameでFrameBg色を描画

7. データ点の描画（データ数 >= 2の場合）
   └─ res_w（描画解像度）の計算
   └─ ホバー時のインデックス計算とツールチップ表示
   └─ 線分の描画ループ

8. オーバーレイテキスト描画
   └─ overlay_textがある場合、中央に描画

9. ラベル描画
   └─ ラベルがある場合、右側に描画
```

### フローチャート

```mermaid
flowchart TD
    A[PlotLines開始] --> B{SkipItems?}
    B -->|Yes| C[return]
    B -->|No| D[レイアウト計算]
    D --> E[ItemAdd]
    E --> F{visible?}
    F -->|No| C
    F -->|Yes| G[ButtonBehavior ホバー検出]
    G --> H{scale自動計算?}
    H -->|Yes| I[データからmin/max計算]
    H -->|No| J[指定値使用]
    I --> K[RenderFrame 背景描画]
    J --> K
    K --> L{values_count >= 2?}
    L -->|No| M[オーバーレイ/ラベル描画]
    L -->|Yes| N{ホバー中?}
    N -->|Yes| O[ツールチップ表示]
    N -->|No| P[線分描画ループ]
    O --> P
    P --> M
    M --> C
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-148-01 | 最小データ数 | 折れ線には最低2点が必要 | 常時 |
| BR-148-02 | 自動スケール | FLT_MAX指定で自動計算 | scale_min/max == FLT_MAX |
| BR-148-03 | NaN無視 | NaN値はスケール計算で無視 | 自動スケール時 |
| BR-148-04 | ツールチップ | ホバー時に値を表示 | ホバー中 |

### 計算ロジック

スケール自動計算:
```cpp
if (scale_min == FLT_MAX || scale_max == FLT_MAX)
{
    float v_min = FLT_MAX;
    float v_max = -FLT_MAX;
    for (int i = 0; i < values_count; i++)
    {
        const float v = values_getter(data, i);
        if (v != v) // NaN check
            continue;
        v_min = ImMin(v_min, v);
        v_max = ImMax(v_max, v);
    }
    if (scale_min == FLT_MAX) scale_min = v_min;
    if (scale_max == FLT_MAX) scale_max = v_max;
}
```

ホバーインデックス計算:
```cpp
const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f);
const int v_idx = (int)(t * item_count);
```

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

該当なし（ImGuiはインメモリUIライブラリ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 描画スキップ | values_count < 2 | データなしとして処理継続 |

### リトライ仕様

該当なし

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

即時モードGUIのため、毎フレーム最新データを描画。

## パフォーマンス要件

- 描画解像度はフレーム幅に応じて自動調整
- 大量のデータポイントでも描画コールがマージされる

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

特になし。

## 備考

- 高機能なグラフが必要な場合はImPlot（https://github.com/epezent/implot）を推奨
- 色はImGuiCol_PlotLines / ImGuiCol_PlotLinesHoveredで設定
- values_offsetを使用して循環バッファを実現可能

---

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

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

### 推奨読解順序

#### Step 1: API宣言を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | PlotLines関数宣言（792-793行目）で2つのオーバーロードを確認 |
| 1-2 | imgui.h | `imgui.h` | ImGuiCol_PlotLines等の色定義（1777-1778行目） |

**読解のコツ**: 配列版とコールバック版の2つのオーバーロードがある。

#### Step 2: 実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | PlotLines配列版実装（8879-8883行目） |
| 2-2 | imgui_widgets.cpp | `imgui_widgets.cpp` | PlotLinesコールバック版実装（8885-8888行目） |
| 2-3 | imgui_widgets.cpp | `imgui_widgets.cpp` | PlotEx内部実装（8748-8862行目） |

**主要処理フロー（PlotEx）**:
1. **8752-8753行目**: ウィンドウスキップ確認
2. **8758-8764行目**: レイアウト計算
3. **8767-8768行目**: ButtonBehaviorでホバー検出
4. **8770-8787行目**: スケール自動計算
5. **8789行目**: フレーム背景描画
6. **8793-8850行目**: データ描画ループ
7. **8852-8857行目**: オーバーレイとラベル描画

#### Step 3: 配列ゲッターを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | ImGuiPlotArrayGetterData構造体（8864-8870行目） |
| 3-2 | imgui_widgets.cpp | `imgui_widgets.cpp` | Plot_ArrayGetter関数（8872-8877行目） |

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

```
PlotLines(label, values[], values_count, ...)
    │
    └─ PlotEx(ImGuiPlotType_Lines, label, Plot_ArrayGetter, &data, ...)
           │
           ├─ CalcItemSize() → frame_size
           │
           ├─ ItemAdd()
           │
           ├─ ButtonBehavior() → hovered
           │
           ├─ [if scale_min/max == FLT_MAX]
           │     └─ データループでmin/max計算
           │
           ├─ RenderFrame() → フレーム背景
           │
           ├─ [if values_count >= 2]
           │     │
           │     ├─ [if hovered] SetTooltip()
           │     │
           │     └─ [loop] DrawList->AddLine()
           │
           ├─ [if overlay_text] RenderTextClipped()
           │
           └─ [if label] RenderText()
```

### データフロー図

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

values[] ─────────────────────┐
                              │
values_count ─────────────────┼──▶ PlotLines() ──────────────▶ なし
                              │         │
values_offset ────────────────┤         ├──▶ 折れ線グラフ描画
                              │         │
scale_min/max ────────────────┤         ├──▶ ツールチップ
                              │         │    (ホバー時)
graph_size ───────────────────┤         │
                              │         └──▶ オーバーレイテキスト
overlay_text ─────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | 公開API宣言、色定義 |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | PlotLines/PlotEx実装 |
