zudo-panel-designer docs
GitHub リポジトリ

検索したい単語を入力

いつでも検索バーを開ける

ドキュメントの状態とレイヤー

DocState、Layer のユニオン型、mm 座標空間、そしてドキュメントが PanelConfig へシリアライズされる仕組み。

座標空間: ミリメートル、原点は左上

ドキュメントモデル内のすべての幾何学的な値——レイヤーの x/ywidth/height、パスのアンカーとベジェハンドル、ストローク幅——は、パネルの左上の角を原点として、ミリメートル単位で保存されます。これは意図的な設計です。PCB の製造データは mm ベースであるため、@zpd/core 全体を通じて mm を唯一の保存空間としています。ピクセルはレンダリングの境界にのみ存在し、そこでアプリのカメラが表示のために mm を画面上の px へ変換します。ドキュメントモデル自体には、ピクセルベースのものは一切ありません。

DocState

interface DocState {
  panelHp: number;
  layers: PcbLayerStack; // Copper -> Solder mask -> Silkscreen
  guides: Guide[]; // ルーラーガイド — レイヤーではなく表示用の付帯物
}
  • panelHp — HP で表したパネルの幅(パネルサイズを参照)。

  • layers — 物理的な下から上の順に並ぶ固定スタックです。各ルートは通常のレイヤー/グループ子を所有します。

    type PcbLayerRole = 'copper' | 'solder-mask' | 'silkscreen';
    
    interface PcbLayerContainer {
      kind: 'pcb-layer';
      id: `pcb-layer-${PcbLayerRole}`;
      role: PcbLayerRole;
      children: LayerNode[];
      hidden?: boolean;
    }
    
    type PcbLayerStack = [
      PcbLayerContainer<'copper'>,
      PcbLayerContainer<'solder-mask'>,
      PcbLayerContainer<'silkscreen'>,
    ];

    これらのルートは選択・変更できる通常グループではありません。LayerNode は leaf Layer またはネストした通常の GroupNode で、名前変更、削除、 グループ化、移動ができるのは通常ノードだけです。

  • guides — ドキュメントのルーラーガイド。必須の配列です(ガイドを参照)。

Layer ユニオン型

レイヤーは 5 つのバリアントのいずれかであり、type によって判別されます。すべてのバリアントは LayerBase を共有します。

interface LayerBase {
  id: string;
  name: string;
  hidden?: boolean;
}
TypeManufacturable?概要
shapeYes長方形または楕円。所有コンテナのマテリアルで塗りつぶされます。
patternYes@zpd/patterns の名前付き・パラメータ化されたパターン(core からは不透明な値)。
pathYesベジェパス。塗り・線・その両方のいずれか。ペンツールまたは画像トレースから生成されます。
textYes固定のフォント/サイズと所有マテリアルで描画されるテキスト。
imageNo(設計時のみ)ラスターの参照画像。パネルはラスターそのものではなく、そこからトレースされたベクターレイヤーをもとに製造されます。

Shape レイヤー

interface ShapeLayer extends LayerBase {
  type: 'shape';
  shape: 'rect' | 'ellipse';
  x: number;
  y: number;
  width: number;
  height: number;
  rotation?: number; // deg clockwise around bbox center
  color: ColorIndex;
}

Pattern レイヤー

interface PatternLayer extends LayerBase {
  type: 'pattern';
  patternType: string;
  params: Record<string, number>;
  color: ColorIndex;
  x: number;
  y: number;
  size: number;
}

patternTypeparams は、@zpd/core がそのパターンを認識できない場合でも不透明なデータとして保持されます。パターンのレジストリはアプリレベルの関心事であり、core の依存対象ではありません。パターンレイヤーがヒットテストで特別な扱いを受けるのもこのためです。ジオメトリと編集の契約を参照してください。

Path レイヤー

interface PathPoint {
  x: number; // anchor, mm
  y: number;
  hin?: { x: number; y: number }; // absolute bezier handle coords, mm
  hout?: { x: number; y: number };
}

interface PathLayer extends LayerBase {
  type: 'path';
  points: PathPoint[]; // primary subpath (pen tool edits this one)
  extraSubpaths?: PathPoint[][];
  closed: boolean;
  fill: ColorIndex | null;
  stroke: ColorIndex | null;
  strokeWidth: number; // mm
}

extraSubpaths は、画像トレースによって生成される追加の閉じたサブパス——ある 1 つの色領域の穴や島——を保持します。これらはプライマリのサブパスと一緒に even-odd(偶奇)フィルで描画されるため、穴は穴として残ります。

colorfillstroke は互換用フィールドです。コンテナ所属が null でない paint を所有マテリアルへ強制します。パスでは null と非 null の違いが fill/stroke の有効状態として残ります。

Text レイヤー

interface TextLayer extends LayerBase {
  type: 'text';
  content: string; // may contain newlines
  fontFamily: string;
  sizeMm: number; // font size in mm (canvas font px == mm in doc space)
  x: number; // bbox top-left, mm
  y: number;
  rotation?: number;
  color: ColorIndex;
}

Image レイヤー

interface ImageLayer extends LayerBase {
  type: 'image';
  src: string; // dataURL
  x: number;
  y: number;
  width: number;
  height: number;
  rotation?: number;
}

src は設計時のソースにすぎません——ラスターはパネル上に製造できません。最終的なパネルは、このレイヤーではなく、そこからトレースされたベクターレイヤーを使用します。

ガイド

ガイドは、レイヤーを揃えやすくするためにエディタが描く、まっすぐな基準線です。ガイドは レイヤーではなく表示用の付帯物 です。DocState.guides に置かれ、layers には決して入りません。ですから色を持たず、製造されることもありません。

interface Guide {
  id: string;
  orientation: 'horizontal' | 'vertical';
  position: number; // mm
  hidden?: boolean;
}

horizontal ガイドは直線 y = position(パネルの幅いっぱい)、vertical ガイドは x = position(高さいっぱい)です。guides が任意ではなく必須なのは、読み取り側が doc.guides ?? [] を必要としないようにするためで、後方互換はシリアライズの境界が担います(guides を持たない古い設定は [] として読み込まれます。後述を参照)。エディタ側の挙動——ルーラーからのガイドの引き出し、スナップ、「Show guides」トグル——はエディタ → ガイドで扱います。

PanelConfig へのシリアライズ

DocState はメモリ上の作業ドキュメントです。PanelConfig は、ユーザーがダウンロードして製造に引き渡す、バージョン付きのエクスポート形式です。

const PANEL_CONFIG_VERSION = 5;

interface PanelConfig {
  version: 5;
  app: 'zpd';
  panel: { hp: number; widthMm: number; heightMm: number };
  palette: string[];
  layers: PcbLayerStack;
  guides: Guide[];
}

hplayersguides は正式なデータであり、ラウンドトリップします。panel.widthMmpanel.heightMmpalette は、人間や注文の読み手のための派生的で参考用の出力であり、エクスポート時に hp と固定パレットから計算されます。ファイルを読み込み直す際には、これらの値が再び信頼されることはありません。

v5 で固定 PCB マテリアルスタックが追加されました。v1–v4 の自由な ルート文書は、旧来の paint により Copper、Solder mask、Silkscreen へ 決定的に分割されます。複数マテリアルにまたがるグループは、可能な限り通常の 構造を保って分割され、id は決定的に修復され、null でない paint は所属へ 正規化されます。不正な v5 ルートも固定順へ正規化されます。 PanelConfig フォーマット → バージョニングを参照してください。

parsePanelConfig は決して例外を投げない

parsePanelConfig には、ユーザーが手で編集した JSON、古いエクスポート、あるいは別のツールが生成した JSON などが渡されるため、各フィールドを個別に防御します。不正な panel/layer フィールドはフォールバックまたは破棄され、v1–v4 は移行され、不正な v5 スタックは正規化されます。永続オートセーブ用の厳密なバージョン境界では、未対応または将来バージョンの設定を拒否します。

フィールドごとのパースルールの全容は、packages/core/src/serialize.ts のソースを参照してください。