# 機能設計書 149-PlotHistogram

## 概要

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

### 本機能の処理概要

PlotHistogram関数は、配列またはコールバック関数から取得した数値データをヒストグラム形式で描画する。各データポイントを垂直の棒として表示し、データの分布や大きさを視覚化する。

**業務上の目的・背景**：データの分布やカテゴリ別の値を視覚的に比較する必要がある場面で使用される。PlotHistogramは、ImGuiアプリケーション内で簡単にヒストグラムを表示できる機能を提供する。より高度なグラフ機能が必要な場合はImPlotの使用を推奨。

**機能の利用シーン**：
- データ分布の可視化
- パフォーマンス指標の比較
- リソース使用量の棒グラフ表示
- 統計データの可視化
- カテゴリ別数値の比較

**主要な処理内容**：
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 | データ数 | >= 1 |
| 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 | データ数 | >= 1 |
| 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. ゼロラインの計算
   └─ 負の値がある場合、ゼロラインを計算

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

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

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

### フローチャート

```mermaid
flowchart TD
    A[PlotHistogram開始] --> 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[ゼロライン計算]
    L --> M{values_count >= 1?}
    M -->|No| N[オーバーレイ/ラベル描画]
    M -->|Yes| O{ホバー中?}
    O -->|Yes| P[ツールチップ表示]
    O -->|No| Q[矩形描画ループ]
    P --> Q
    Q --> N
    N --> C
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-149-01 | 最小データ数 | ヒストグラムには最低1点が必要 | 常時 |
| BR-149-02 | 自動スケール | FLT_MAX指定で自動計算 | scale_min/max == FLT_MAX |
| BR-149-03 | NaN無視 | NaN値はスケール計算で無視 | 自動スケール時 |
| BR-149-04 | ツールチップ | ホバー時に値を表示 | ホバー中 |
| BR-149-05 | ゼロライン | 負の値がある場合、ゼロラインを基準に描画 | scale_min < 0 && scale_max > 0 |
| BR-149-06 | 棒間隔 | 棒が2ピクセル以上の場合、1ピクセルの間隔 | 棒幅 >= 2.0f |

### 計算ロジック

ゼロライン計算:
```cpp
float histogram_zero_line_t = (scale_min * scale_max < 0.0f)
    ? (1 + scale_min * inv_scale)
    : (scale_min < 0.0f ? 0.0f : 1.0f);
```

棒の描画:
```cpp
ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0);
ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, ImVec2(tp1.x, histogram_zero_line_t));
if (pos1.x >= pos0.x + 2.0f)
    pos1.x -= 1.0f;  // 1ピクセルの間隔
window->DrawList->AddRectFilled(pos0, pos1, col);
```

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

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

## エラー処理

### エラーケース一覧

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

### リトライ仕様

該当なし

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

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

## パフォーマンス要件

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

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

特になし。

## 備考

- 高機能なグラフが必要な場合はImPlot（https://github.com/epezent/implot）を推奨
- 色はImGuiCol_PlotHistogram / ImGuiCol_PlotHistogramHoveredで設定
- values_offsetを使用して循環バッファを実現可能
- PlotLinesとの違い：1点から描画可能、矩形で描画

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | PlotHistogram関数宣言（794-795行目）で2つのオーバーロードを確認 |
| 1-2 | imgui.h | `imgui.h` | ImGuiCol_PlotHistogram等の色定義（1779-1780行目） |

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

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

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

**主要処理フロー（PlotEx - Histogram部分）**:
1. **8791行目**: values_count_min = 1（ヒストグラムは1点から描画可能）
2. **8809-8810行目**: ヒストグラム用ツールチップ（単一値表示）
3. **8820行目**: ゼロライン計算
4. **8840-8844行目**: 矩形描画（AddRectFilled）と間隔処理

#### Step 3: PlotLinesとの違いを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | ImGuiPlotType列挙型でLines/Histogramを確認 |

**主な違い**:
- values_count_min: Lines = 2, Histogram = 1
- 描画: Lines = AddLine, Histogram = AddRectFilled
- ツールチップ: Lines = 2値表示, Histogram = 1値表示

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

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

### データフロー図

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

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

### 関連ファイル一覧

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