# 画面設計書 24-Custom Drawing

## 概要

本ドキュメントは、Avalonia ControlCatalogサンプルアプリケーションにおけるCustom Drawingデモページの画面設計を定義するものです。

### 本画面の処理概要

本画面は、Avaloniaのカスタム描画機能（DrawingContext API）をデモンストレーションするためのページです。2D座標変換（Translation、Rotation、Scale）をインタラクティブに操作しながら、リアルタイムレンダリングの仕組みを学習・検証できる環境を提供します。

**業務上の目的・背景**：カスタム描画は、標準コントロールでは実現できない高度なビジュアル表現を必要とするアプリケーションで使用されます。例えば、CADアプリケーション、データビジュアライゼーション、ゲーム、図面エディタなどで必要となります。DrawingContextを使用した低レベル描画、座標変換、マウスホイールによるズーム、ドラッグによるパン操作など、2D描画アプリケーションの基礎技術を学ぶことができます。

**画面へのアクセス方法**：ControlCatalogアプリケーションのメインウィンドウから、HamburgerMenuのナビゲーションで「Custom Drawing」を選択することでアクセスできます。

**主要な操作・処理内容**：
1. Translationパラメータの表示（水平・垂直ビューポート中心座標）
2. Rotationパラメータの調整（±ボタンで回転角度変更）
3. Scaleパラメータの調整（±ボタンでズームイン/アウト）
4. 描画領域のドラッグによるパン操作
5. マウスホイールによるズーム操作
6. リアルタイムアニメーション描画（軌道上を移動する円）

**画面遷移**：MainViewからHamburgerMenuナビゲーションを通じて遷移。画面内での追加遷移なし。

**権限による表示制御**：特になし（サンプルアプリケーション）

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 77 | DrawingContext | 主機能 | カスタム描画のデモ。図形やテキストの描画API使用 |

## 画面種別

デモ / サンプル表示（インタラクティブ）

## URL/ルーティング

HamburgerMenu内部ナビゲーション（直接URLルーティングなし）

## 入出力項目

| 項目名 | 種別 | データ型 | 必須 | 説明 |
|--------|------|----------|------|------|
| Horizontal（表示のみ） | 出力 | double | - | ViewportCenterXの値（読み取り専用） |
| Vertical（表示のみ） | 出力 | double | - | ViewportCenterYの値（読み取り専用） |
| Rotation（表示のみ） | 出力 | double | - | 回転角度（度数、読み取り専用） |
| Scale（表示のみ） | 出力 | double | - | スケール値（読み取り専用） |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| Translationセクション | StackPanel | 水平・垂直座標値の表示 |
| Rotationセクション | StackPanel | 回転角度と±ボタン |
| Scaleセクション | StackPanel | スケール値と±ボタン |
| 描画領域 | CustomDrawingExampleControl | スマイルフェイス、軌道上の円、カーソル追跡円 |

## イベント仕様

### 1-Rotation「-」ボタンクリック

RotateMinusメソッドが呼び出され、Rotationプロパティがπ/20ラジアン減算される。

### 2-Rotation「+」ボタンクリック

RotatePlusメソッドが呼び出され、Rotationプロパティがπ/20ラジアン加算される。

### 3-Scale「-」ボタンクリック

ZoomOutメソッドが呼び出され、Scaleプロパティが1.2で除算される（縮小）。

### 4-Scale「+」ボタンクリック

ZoomInメソッドが呼び出され、Scaleプロパティが1.2倍される（拡大）。

### 5-描画領域のマウスホイール操作

OnPointerWheelChangedハンドラが呼び出され、ホイール回転量に応じてScaleが変更される。同時にカーソル位置を基準にViewportCenterが調整され、カーソル位置を中心にズームが行われる。

### 6-描画領域のドラッグ操作

OnPointerPressed/OnPointerMoved/OnPointerReleasedハンドラにより、ポインターキャプチャとパン操作が実現される。ドラッグ中はワールド座標系での差分がViewportCenterに適用される。

### 7-描画領域へのマウス移動

OnPointerMovedハンドラにより、カーソル位置が更新される。描画時にカーソル位置にグレーの円が描画される。

### 8-リアルタイムアニメーション

Renderメソッドの最後でDispatcher.UIThread.PostによりInvalidateVisualが呼び出され、バックグラウンド優先度で継続的な再描画が行われる。Stopwatchで経過時間を計測し、軌道上の円がアニメーションする。

## データベース更新仕様

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

本画面はUIコントロールのデモであり、データベース操作は行いません。

## メッセージ仕様

本画面にはメッセージ表示機能はありません。

## 例外処理

- 描画処理中の例外は画面のフリーズを引き起こす可能性あり

## 備考

- 座標変換の順序：Translation → Rotation → Scale → MapPosition
- DrawingContextのPush/Pop（Dispose）パターンで変換を管理
- DegToRadConverterでラジアン・度数変換を行う
- Rotationプロパティにはcoerce関数で2π未満に正規化される

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、描画コントロールのプロパティ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CustomDrawingExampleControl.cs | `samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs` | Scale、Rotation、ViewportCenterX/YのStyledProperty定義（行19-38） |

**読解のコツ**: AvaloniaProperty.Registerでプロパティを登録し、coerce引数で値の正規化ができます。

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

処理の起点となるUserControlとXAMLレイアウトを特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CustomDrawing.xaml | `samples/ControlCatalog/Pages/CustomDrawing.xaml` | Grid構造、TextBoxへのバインディング、ボタンイベント定義、CustomDrawingExampleControlの配置 |

**主要処理フロー**:
1. **行14-47**: Translationセクション（ViewportCenterX/Yへのバインディング）
2. **行49-73**: Rotationセクション（DegToRadConverter使用、±ボタン）
3. **行75-98**: Scaleセクション（±ボタン）
4. **行100-104**: CustomDrawingExampleControlの配置

#### Step 3: コードビハインドを理解する

ボタンクリックハンドラを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | CustomDrawing.xaml.cs | `samples/ControlCatalog/Pages/CustomDrawing.xaml.cs` | RotateMinus/Plus、ZoomIn/Outメソッドの実装 |

**主要処理フロー**:
- **行14-17**: RotateMinus - π/20減算
- **行19-24**: RotatePlus - π/20加算
- **行26-31**: ZoomIn - 1.2倍
- **行33-38**: ZoomOut - 1.2で除算

#### Step 4: カスタム描画コントロールを理解する

レンダリングロジックを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | CustomDrawingExampleControl.cs | `samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs` | Renderメソッド、座標変換、ポインターイベントハンドラ |

**主要処理フロー**:
- **行46-68**: コンストラクタ - Pen、StreamGeometry（スマイル）の初期化
- **行71-89**: OnPointerMoved - カーソル位置更新、ドラッグ時のパン処理
- **行91-97**: OnPointerPressed - ポインターキャプチャ
- **行99-112**: OnPointerWheelChanged - ズーム処理
- **行114-119**: OnPointerReleased - キャプチャ解放
- **行121-186**: Render - 座標変換、描画処理、アニメーション
- **行188-213**: 座標変換ヘルパーメソッド

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

```
CustomDrawing (UserControl)
    │
    ├─ CustomDrawingExampleControl
    │      │
    │      ├─ OnPointerMoved
    │      │      └─ UIPointToWorldPoint → ViewportCenter更新
    │      │
    │      ├─ OnPointerPressed
    │      │      └─ Pointer.Capture
    │      │
    │      ├─ OnPointerWheelChanged
    │      │      └─ Scale更新 → ViewportCenter調整
    │      │
    │      ├─ OnPointerReleased
    │      │      └─ Pointer.Capture(null)
    │      │
    │      └─ Render
    │             ├─ PushClip → 描画領域クリップ
    │             ├─ PushTransform(Translation) → 中央移動
    │             ├─ PushTransform(Rotation) → 回転
    │             ├─ PushTransform(Scale) → スケール
    │             ├─ PushTransform(MapPosition) → ビューポート位置
    │             ├─ DrawEllipse/DrawLine/DrawGeometry → 描画
    │             ├─ Dispose群 → 変換スタック解放
    │             └─ Dispatcher.Post(InvalidateVisual) → 再描画要求
    │
    └─ コードビハインド
           ├─ RotateMinus/Plus → Rotation更新
           └─ ZoomIn/Out → Scale更新
```

### データフロー図

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

ボタンクリック ─────────▶ Rotation/Scale更新 ────────────▶ プロパティ変更通知
                              │
                              └─ InvalidateVisual ──────▶ Render呼び出し

マウスホイール ─────────▶ OnPointerWheelChanged ─────────▶ Scale + ViewportCenter更新
                              │
                              └─ UIPointToWorldPoint計算

ドラッグ操作 ──────────▶ OnPointerMoved ─────────────────▶ ViewportCenter更新
                              │
                              └─ ワールド座標差分計算

経過時間 ───────────────▶ Stopwatch.Elapsed ─────────────▶ 軌道位置計算 → 描画
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CustomDrawing.xaml | `samples/ControlCatalog/Pages/CustomDrawing.xaml` | XAML | 画面レイアウト定義 |
| CustomDrawing.xaml.cs | `samples/ControlCatalog/Pages/CustomDrawing.xaml.cs` | ソース | コードビハインド |
| CustomDrawingExampleControl.cs | `samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs` | ソース | カスタム描画コントロール |
| DegToRadConverter.cs | `samples/ControlCatalog/Converter/DegToRadConverter.cs` | ソース | 度数⇔ラジアン変換コンバーター |
