Skip to content

Repository files navigation

Daiza

English · ไทย · 日本語

PNG画像からアクリルフィギュアの重心を解析し、差込口の位置台座サイズを自動計算するWebアプリです。カットライン(アクリル外形)と台座の図面を、実寸(mm)座標系のSVGとして書き出せます。

公開URL: https://mimaraka.github.io/daiza/

画像解析・幾何計算・SVG生成はすべてブラウザ内で完結します。読み込んだ画像や解析データが外部へ送信されることは一切ありません(サーバーを持たない静的サイトです)。

できること

  • 重心解析 — 不透明領域(既定は α>0。アルファ閾値で判定境界を変更可)を均一密度とみなし、カットラインが囲む領域の面積重心を算出
  • 差込部の自動配置 — 重心の真下に「首部+ツメ」の2段構造を配置し、アクリル板本体と一体のカットラインへ拡張
  • 台座サイズの検査 — 支持多角形の考え方で、指定した台座幅で自立するか(重心が支持範囲内か)・指定した台座奥行にスリットが収まるかを判定
  • 転倒シミュレーション — 左右・前後の転倒角 θ = atan(支持端距離 / 重心高さ) を算出
  • カットライン生成 — 余白オフセット・狭い隙間の充填・平滑化・曲線補完(ベジェ)を経た滑らかな外形
  • 複数パーツの連結 — 分離した絵柄は凸包で包まず、輪郭に沿わせたままブリッジで1枚に連結
  • リアルタイムプレビュー — オーバーレイ表示・ホイールズーム・ドラッグパン・実寸ルーラー・実寸グリッド(トグル、既定OFF)。ガイドを消して仕上がりを見る完成プレビューモードへも切り替えられます
  • 3Dプレビュー — 完成品を立体で確認(透明アクリル・裏面の絵柄/白版・貫通スリット付き台座)。傾けスライダーで転倒を、分解アニメーションで差込部の噛み合いを確認。床は実寸グリッド(10mmマス、既定ON)を表示し、任意のテクスチャ(同梱の木目サンプル/画像アップロード)を貼れます
  • SVG / Illustrator(.ai) エクスポート — 外形(本体+首部+ツメ)・差込口・台座スリットを実寸(mm)で出力。.ai は絵柄画像を常に埋め込み、レイヤーを分離します。SVGは線データのみが既定で、チェックを入れたときだけ絵柄画像を埋め込みます

使い方

  1. PNG画像(RGBA)をドラッグ&ドロップ、またはファイル選択で読み込みます。既定では α=0を透明、α>0をアクリルとみなします(判定境界はアルファ閾値で変更できます)。
  2. 左パネルでフィギュア高さ(mm)を入力します。これは接地面(台座の底面)からカットライン上端までの全高です。ここから絵柄の外側の高さ(カットライン余白×2 + 持ち上げ量 + 板厚)を差し引いた「絵柄の高さ(mm)」と絵柄の高さ(px)の比から mm_per_pixel が決まり、以降すべての実寸計算の基準になります(画像高さは使いません。PNGの透明余白の量で実寸が変わらないようにするためです)。
  3. 各パラメータを調整します。変更のたびに解析・再描画が即座に走ります。
  4. 右パネルの解析結果・転倒角を確認し、SVGをエクスポートします。

パラメータ

パラメータ 既定値 範囲 説明
アルファ閾値 0 0〜0.99 アクリルとみなす境界(α > 閾値 × 255)。上げると半透明の縁・影を無視
フィギュア高さ 160 mm 1〜2000 接地面からカットライン上端までの全高。絵柄の高さ(px)との比でスケールを決める
板厚 3 mm 0.1〜20 アクリル板の厚み。ツメの深さもこの値になる
カットライン余白 3 mm 0〜10 絵柄の外側へオフセットする余白
カットライン平滑化 0 0〜5 大きいほど輪郭が滑らかになる
隙間埋め閾値 3 mm 0〜20 この幅より狭い隙間・くびれをアクリルで埋める(0=無効)
パーツ連結部の最小幅 6 mm 0.5〜20 分離パーツをつなぐブリッジの下限幅
差込口幅 20 mm 0.1〜50 ツメの幅(=台座スリットの幅)
差込口オフセット 0 mm -50〜50 重心直下からの左右微調整(正=右)
差込口の前後オフセット 0 mm -150〜150 台座の奥行中心から見たスリット位置(正=前)
首部幅 40 mm 1〜(上限なし) 必ず差込口幅より大きい(後述)
アクリル板の持ち上げ量 0 mm 0〜50 0で板の下端が台座上面に接する
台座幅 50 mm 1〜300 指定値がそのまま実寸幅(2倍・加算はしない)
台座奥行 30 mm 1〜300 指定値がそのまま実寸奥行(自動算出しない)

差込部の構造(首部+ツメ)

差込部は幅の異なる2つの矩形で構成されます。首部はツメより幅が広く、その差分としてできる肩(ショルダー)が台座上面に乗ることで、挿入深さがツメ深さ(=板厚)で止まります

         ┌─────────────────┐
         │   アクリル板     │   ← カットライン(本体)
         └────┬───────┬────┘
              │  首部  │           幅 = 首部幅(mm) > 差込口幅
              │       │
   ═══════┌───┴──┐┌───┴───┐═════   ← 肩が台座上面に乗って止まる
   台座    │ 肩   ││  肩   │  台座
   ───────┴───┐  └┘  ┌───┴──────  台座上面
              │ ツメ  │           幅 = 差込口幅(mm)
              │       │           深さ = 板厚(mm)
              └───────┘

この設計上、首部幅 ≧ 差込口幅 + 2 × 最小ショルダー幅(片側0.5mm) が常に成立する必要があります。差込口幅を広げた結果として首部幅が下限を割る場合、首部幅は自動的に下限まで押し上げられます。

エラーになる場合

例外でクラッシュはせず、UI上にメッセージを表示します。

  • アクリル領域が無い — 全透明の画像、またはアルファ閾値が高すぎて不透明画素が残らない
  • スケール計算不可 — フィギュア高さが絵柄の外側の高さ(カットライン余白×2 + 持ち上げ量 + 板厚)以下で、絵柄の高さが取れない
  • 差込口が配置不可 — オフセットが大きすぎる、首部が板から外れる等
  • 台座計算不可 — 指定した台座幅が必要幅(max(2 × |重心X − 差込口中心X|, 差込口幅))を下回る、または指定した台座奥行が必要奥行(板厚 + 2 × |前後オフセット|)を下回る。台座は自動では広げず、パラメータの見直しを促します

開発

npm install
npm run dev          # 開発サーバー
npm run build        # 本番ビルド(dist/ を生成)
npm run preview      # ビルド結果のローカル確認
npm run lint         # ESLint(warningゼロが要件)
npm run format       # Prettier

GitHub Pages ではリポジトリ名配下で配信されるため、Viteの base/daiza/ に固定しています。main への push で .github/workflows/deploy.yml が lint → build → デプロイを実行します。

技術スタック

React 19 / TypeScript (strict) / Vite / Tailwind CSS v4 / shadcn/ui / polygon-clipping / pdf-lib(.ai)/ Three.js + React Three Fiber(3Dプレビュー)。状態管理は React Hooks のみで、Redux等のグローバル状態管理ライブラリは使いません。

pdf-lib と 3D 一式は dynamic import で分離チャンクに置き、使うまでダウンロードしません(初期バンドルに影響させない)。

アーキテクチャ

UI・画像解析・物理計算・描画・エクスポートを厳密に分離しています。analysis/ 以下は React に依存しない純粋関数で、失敗は例外ではなく null で返します。

src/
  components/   LeftPanel / Preview / ResultPanel / ExportPanel / Ruler / Grid  … UI(3ペイン構成)
                preview3d/                                  … 3Dビュー(R3F。lazy 読み込み)
  analysis/     imageLoader, contour, centroid, distance, slot, base, stability,
                scale, pipeline, analysis.worker            … 純粋ロジック
  render/       overlay, simulation, ruler, scene3d         … 描画モデル(純粋)
                texture3d                                   … 絵柄/白版・床タイルのテクスチャ(DOM)
  assets/       textures/wood.png                           … 床の木目サンプル(3Dチャンクのみ参照)
  export/       geometry, svg, ai, raster                   … 実寸(mm)でSVG / Illustrator生成
  model/        state.ts, types.ts, errors.ts, pixelStore.ts
  hooks/        useAnalysis, useAppState, useViewport
  utils/        geometry.ts, image.ts, curve.ts

3Dシーンの幾何(カットライン → 押し出し形状、mm座標系への変換)は render/scene3d.ts に純粋関数として置き、three にも React にも依存させていません。原点は接地面上の台座中心、Y上正・Z前正で、ツメ底面が Y=0(台座底面とツライチ)になります。

解析パイプライン

3000px級の画像でもフリーズさせないため、パイプラインを2相に分け、Web Worker 上で駆動します。

  • 第1相 analyzeImage — 画像だけに依存する前処理(αプレーン抽出)。O(W×H)。画像が変わった時だけ実行し、αプレーンは Worker 内に保持します(メインスレッドへは送りません)。不透明判定はアルファ閾値(パラメータ)に依存するため、二値化はこの相では行いません。
  • 第2相 runAnalysis — パラメータに依存する計算(二値化 → カットライン → 重心 → 差込部 → 台座 → 転倒角)。このうち重い段(二値化・EDT膨張・カットライン生成・差込部の合流)は依存パラメータを鍵に段ごとメモ化し、台座幅等の無関係な変更では再計算しません。

カットラインは次の順で確定し、以降の重心解析・差込口配置・台座計算・オーバーレイ・SVG出力はすべてこの外形に追従します。

輪郭抽出 → 余白オフセット(EDT膨張) → 隙間埋め(円板クロージング) → 自己交差の除去 → 平滑化 → 曲線補完 → 差込部の一体化

ドキュメント

  • docs/SPEC.md — 仕様書(正典)
  • docs/TODO.md — 残タスク(実機確認・任意の解析解像度上限・将来拡張)

将来拡張

複数差込口、円形/楕円/任意形状台座、金属スタンド対応、密度マップ、複数PNG同時計算、PWA化 / WebAssembly置き換えなどを想定し、解析ロジックをUIから切り離した設計にしています。

About

Daiza - Acrylic Figure Designer

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages