# PHYレイヤー ## 概要 PHYレイヤーは、キースイッチやキーキャップ、その他周辺部品の物理的な配置に関する情報を提供する。 付加的な情報として、matrix情報(ELCレイヤー)や入力キー情報(MAP/IMEレイヤー)を含ませることができるが、必須ではない。 ## 構造 ### キースイッチ/キーキャップの配置 各キーはスイッチ・キャップの情報を統合された状態で持ち、キャップの位置・サイズからスイッチ座標を特定する。 以下、単に「キー」と呼ぶ場合、キーキャップの位置・サイズを表すオブジェクトをさすこととする。 ### プロファイル設定 1ファイル内に複数のプロファイルを持たせることができる。 ユニットサイズ(1Uが何mmか、x軸・y軸それぞれ)を規定。 ビジュアル表現として、内側へのオフセット位置及びオフセット距離(mm or U単位)・R(U単位)を規定。 ### 座標と回転 各ノードは、親ノードから見た相対的な配置を持つ。絶対座標は保持しない。 クラスター単位の移動・回転を親ノード1つの書き換えで済ませるため、相対座標を正本とする。 配置は「親の座標系で θ 回転してから (x, y) 平行移動」と定義する。 ```txt p_parent = Translate(x, y) · Rotate(θ) · p_child ``` この定義により、(x, y) は自分のローカル原点が親座標系のどこに来るかを表し、θ は自分の向きを表す。 回転軸は常に自分自身のローカル原点であり、パラメータとしては持たない。 キーもクラスターも同じ変換を持つため、キーごとに向きが異なる配置のためにクラスターを作る必要はない。 ローカル原点はキーキャップの左上角とする。座標単位はU。1Uのサイズはプロファイルで指定する。 座標・回転角度は、ローカル座標系で0.25U単位・15度単位でスナップするが正規化しない。 KLE JSONやPCB向けの出力は、階層を畳んで絶対座標に変換した導出物として生成する。 ### キーのサイズ 0.25U単位でスナップするが正規化しない。 サイズはローカルの値であり、親の変換を受けない。 ### グルーピング 複数のキーを「クラスター」としてまとめて運用することができる。 クラスターのみにフォーカスして編集が可能。 クラスターの原点が、配下のノードの回転中心になる。 **内部処理での利用**: - クラスターごとの一括編集・移動・回転 - 階層構造による管理(クラスターの入れ子構造) - 編集時のフォーカス制御 - 回転中心を保存したい場合はクラスターにする(ノード自身は回転中心を持たないため) **外部連携での扱い**: - クラスター構造はBeyond KLEのデータにのみ存在する。外部形式へは階層を畳んだキー配置だけを出力する ### 何かある? ## 保存形式 各ノードは親から見た変換を持つ。キーとクラスターを混在させた木構造として保持する。 ```ts type Transform = { x: number, // 親座標系での位置 y: number, rotation: number // 親座標系での回転角度(度) } type Size = { w: number, // ローカル値。親の変換を受けない h: number } type Key = { transform: Transform, size: Size, profile: Profile } type Cluster = { transform: Transform, children: (Key | Cluster)[] } const root: (Key | Cluster)[] = [] ``` ## 連携用出力形式 ### KLEとの関係 KLEは、PHYデータを表示できる既存のビュワーとして扱う。 KLEで編集された時点で、そのデータはBeyond KLEのデータではない。 - KLE JSONにはBeyond KLE固有の情報(キーID、クラスター構造など)を含めない。出力は素のKLE JSONで、KLE JSONを読む他ツールにそのまま渡せる - KLE JSONの取り込みは、手元のPHYデータとの照合で行う。IDや埋め込み情報には頼らない - 過去のKLE JSONは、PHYデータがなくても読み込めなければならない。変換を伴ってよい ### KLE JSON出力 階層を畳んで絶対座標に変換し、標準的なKLE JSON形式で出力する。 ```ts type ConfigObject = { x?: number, y?: number, w?: number, h?: number, x2?: number, y2?: number, w2?: number, h2?: number, r?: number, // 回転角度 rx?: number, // 回転中心 ry?: number, l?: boolean, n?: boolean, d?: boolean, c?: string, t?: string, g?: boolean, a?: number, f?: number, f2?: number, fa?: number[], p?: string, sm?: string, sb?: string, st?: string } type KeyLabel = string // 表示用ラベルのみ。識別情報は含めない const kleData = (ConfigObject | KeyLabel)[][] ``` - 回転角度は正規化せずそのまま出力する。KLEのデータは任意の角度を受け付け、15度刻みはKLEのUI上の操作単位にすぎない - rx, ry はPHYに持たないので、出力時に選ぶ - ユニットサイズ(mm)、ビジュアルオフセット、クラスター構造はKLE JSONに出力されない - KLEの `p` はキーキャップのプロファイル名(SA、DCSなど)であり、PHYのプロファイルとは対応させない ### KLE JSONの取り込み 既存のPHYデータを畳んだ配置に対して、KLE JSONの各キーを形状(位置・サイズ・回転)とラベルで照合する。 - 照合できたキーは元のノードとして扱う。KLE側で配置が変わっていれば、元の親から見た相対座標に戻して反映する - 照合できないキーは root 直下に新規キーとして置く。クラスターへの割り当てはユーザーが行う - 構造の復元は保証しない。KLE側での編集が大きいほど、クラスター構造は失われる - 配列の順番は照合に使わない。KLEは保存時にキーを「角度 → rx → ry → y → x」の順に並べ替えるため、順番は形状から決まる以上の情報を持たない KLEの rx, ry, r はキーの絶対配置 (x, y, rotation) に変換して取り込む。元の rx, ry は保持しない。 ## 検討済み・非採用 - キーごとの絶対座標保持 (journal/2026-09-18-phy-coordinate-model.md) - 相対座標と絶対座標の併記 (journal/2026-09-18-phy-coordinate-model.md) - ノードごとの回転中心パラメータ (journal/2026-09-18-phy-coordinate-model.md) - KLE JSONへの識別・構造情報の埋め込み(labelのID、`_beyondkle` メタデータ、ゴーストキー) (journal/2026-09-18-kle-roundtrip.md) ## 未確認事項 ### P-1 KLE JSONへ書き出した配置が行のまとまりを保てるか - 位置づけ: 本文が前提にしているものではない。連携用出力形式の設計に関わる未解決の問い - 現状の認識: 階層を畳んでKLEに読み込ませると行のまとまりが崩れる。他レイヤーの情報を使ってでも行ごとにまとめたいが、方法は未検討 - 手がかり: KLEは r, rx, ry が同じで y が等しいキーを1行にまとめる。同じ絶対角度を持つキーに共通の rx, ry(例えばクラスターの原点)を選べば、行にまとめられる見込み - 格上げ条件: 回転を含むPHYデータをKLE JSONに変換してKLE本家に読み込ませ、rotation groupと行配列がどう再構成されるかを確認する ### P-2 KLE JSON取り込み時の照合基準 - 位置づけ: 本文「KLE JSONの取り込み」の具体化に必要な未解決の問い - 現状の認識: 形状の許容誤差、ラベルの扱い、複数候補がある場合の決め方が未定 - 格上げ条件: 照合規則を決めたうえで、KLE本家でキーの移動・追加・削除をしたJSONを取り込み、意図どおりに対応づくことを確認する ### P-3 KLE JSON取り込み時のクラスター自動推定 - 位置づけ: 未解決の問い。PHYデータなしで過去のKLE JSONを取り込むとき、座標の近さや角度からクラスターを推定するか - 現状の認識: 採用しない可能性が高い。ただし代わりに欲しい機能があり、それを思い出すきっかけとして残している - 格上げ条件: 代わりの機能を定義し、この推定を採るか捨てるかをユーザーが決める ### P-4 KLE固有の形状と属性の受け止め先 - 位置づけ: 本文「過去のKLE JSONは読み込めなければならない」を満たすために必要な未解決の問い - 現状の認識: 現在の Key 型(transform, size, profile)では次を受け止められない - 長方形でないキー(x2, y2, w2, h2。ISO Enterなど)。受け止められないとISO配列が読めない。ローカルの値なので Size の拡張で相対座標モデルに収まる見込み - デカールとゴースト(d, g)。PHYで持つか、取り込み時に捨てるか - 見た目の属性(ラベル、c, t, p, f系, l, n)。落としてよいか、別の層で保持するか。ラベルは照合にも使う - 格上げ条件: 各項目について、PHYで持つ・他の層で持つ・捨てるのいずれかをユーザーが決め、Key 型に反映する