Appearance
Daedalus WebCAD 現状分析・リファクタリング計画レポート
作成日: 2026-06-16 対象: frontend/src(Vue3 + TypeScript)の Daedalus / CAD Core
0. エグゼクティブサマリ
- CAD Core は想像以上に成熟している。
frontend/src/cad-coreは 222 個の TS ファイルを持ち、Entity モデル・Geometry・Snap・Selection・History・Dimensions・Layers・DXF I/O・Constraints がモジュール分割で実装済み。 - 最大の問題は UI 層の肥大化。
D_Daedalus.vueは 48,124 行 の巨大モノリスで、CAD ロジック(描画プレビュー・グリップ・スナップ・寸法計算)が大量に混在している。 - CAD Core の独立性に重大な「漏れ」がある。 汎用変換のうち Move のみが CAD Core にあり、Copy / Rotate / Scale / Mirror は Drafting 層(
D_cadPointCommandExecutor.ts)に、しかも設備(equipment)モデル(eq.x,eq.width)に結合した形で実装されている。これにより汎用CadEntityに対する回転・拡縮・ミラーが CAD Core に存在しない。 - 結論: 新規実装よりも「既存資産の昇格・集約」が最優先。 破壊せず、Drafting に散らばったロジックを CAD Core に引き上げ、薄い UI へ近づける。
1. 現状分析レポート
1.1 ディレクトリ構成(CAD 関連の中核)
frontend/src/
├── cad-core/ ← CAD Core(222 TS ファイル)
│ ├── models/ entities.ts / document.ts / editorState.ts / productStructure.ts
│ ├── geometry/ math / intersections / bounds / distance / projection / fillet / rect ...
│ ├── snaps/ + snapping.ts snapEngine / line・circle・arc・polylineSnap
│ ├── selection/ + selection.ts selectionEngine / selectionBox
│ ├── history/ + history.ts historyEngine / transactions
│ ├── commands/ lineEditCommands(Trim/Extend/Break/Join/Fillet/Chamfer/Offset)
│ ├── transform/ moveTransform / transformEngine / gripTransform ← Move のみ
│ ├── constraints/ constraintEngine(H/V/Coincident/EqualLength/FixedPoint)
│ ├── dimensions/ linear / aligned / styles / labelFormatter
│ ├── document/ operations / spaceTypes / operationHistoryAdapter
│ ├── adapters/dxf/ dxfIO / dxfAdapter / dimension・annotation・hatchAdapter
│ ├── exporters/ svg / pdf / raster(未) / exportEngine
│ ├── renderers/ 2d(svgRendererAdapter, viewportTransform) / 3d(threeSceneAdapter)
│ ├── hitTest/ grips/ hatches/ blocks/ annotations/ layouts/ interaction/
│ ├── spatialIndex/ versioning/ diff/ collaboration/ parametric/ pid/ plugins/
│ └── analysis/ analysisMesh / vtkAdapter / meshingService
│
├── stores/ cadDocumentStore.ts / cadHistoryStore.ts(Pinia)
│
└── components/Daedalus/Drafting/
├── D_Daedalus.vue ← 48,124 行のメイン(モノリス)
├── D_DaedalusRibbon.vue ← 7,043 行(リボン)
├── D_Daedalus{MenuBar,LeftSidebar,RightSidebar,Footer}.vue
├── D_cadPointCommandExecutor.ts ← Move/Copy/Rotate/Scale/Mirror(設備結合)
├── D_cadAliasCommandExecutor.ts ← AutoCAD 風エイリアス(L→LINE 等)
├── D_useLineEditCommandRunner.ts ← Trim/Extend... の UI ランナー
├── D_use*.ts (多数の composable)
└── SymbolRenderer/ D_sr.*.ts(Canvas 2D・適切に分離された良い例)1.2 各機能の実装状況(調査結果)
| 観点 | 実装 | 場所 | 備考 |
|---|---|---|---|
| Entity モデル | ✅ 完全 | cad-core/models/entities.ts | 10 型: LINE/POLYLINE/CIRCLE/ARC/TEXT/ELLIPSE/INSERT/DIMENSION/ANNOTATION/HATCH |
| Geometry | ✅ 完全 | cad-core/geometry/ | 距離・交差・射影・bounds・Fillet 幾何 |
| Snap | ✅ 完全 | cad-core/snaps/ | endpoint/midpoint/center/quadrant/intersection/nearest |
| Selection | ✅ 完全 | cad-core/selection/ | window/crossing, policy, modifier |
| Undo/Redo | ✅ 完全 | cad-core/history/ + cadHistoryStore | トランザクション対応、容量 80 |
| 線編集コマンド | ✅ 完全 | cad-core/commands/lineEditCommands.ts | Trim/Extend/Break/Join/Fillet/Chamfer/Offset |
| Move | ✅ 完全 | cad-core/transform/moveTransform.ts | 全 Entity 型対応 |
| Copy/Rotate/Scale/Mirror | ⚠️ 設備結合 | Drafting/D_cadPointCommandExecutor.ts | CAD Core に汎用版が無い |
| Constraints | ⚠️ 部分 | cad-core/constraints/ | 5 種のみ(Tangent/Perpendicular/Angle/Radius 無し) |
| Dimensions | ⚠️ 部分 | cad-core/dimensions/ | Linear/Aligned のみ(Angular/Radius/Diameter/Ordinate 無し) |
| Layers | ✅ 完全 | cad-core/models/document.ts | visible/locked/printable/colorIndex |
| DXF I/O | ✅ 完全 | cad-core/adapters/dxf/ | LINE/XLINE/TEXT/CIRCLE/ARC/ELLIPSE/POLYLINE/SPLINE/HATCH |
| Project Save/Load | ✅ あり | api/*AdapterDedicated.ts + backend snapshots | 複合キーで snapshot 保存 |
| State 管理 | ✅ Pinia | stores/cadDocumentStore.ts | applyOperation() で一元化、履歴連携 |
1.3 描画エンジン構成
| 技術 | 用途 | 場所 |
|---|---|---|
| SVG | モデル空間・レイアウトの寸法/注釈/ハッチ描画 | cad-core/renderers/2d/svgRendererAdapter.ts + D_Daedalus.vue テンプレート |
| Canvas 2D | シンボルエディタ | SymbolRenderer/D_sr.draw.ts(分離良好) |
| Three.js | 3D Feature プレビュー | D_feature3dThree*.ts |
| vtk.js | FEA 解析結果 | AnalysisVtkViewer.vue |
座標変換は cad-core/renderers/2d/viewportTransform.ts(worldToScreen/screenToWorld)と Drafting 側 D_useCoordinateSystem.ts / D_ucsCoordinate.ts に二重に存在。
2. 問題点一覧
P1: アーキテクチャ(CAD Core 独立性の漏れ)
- 汎用変換の欠落 — Rotate/Scale/Mirror/Copy が CAD Core に無く、Drafting の設備モデル(
eq.x/eq.width)に結合。CadEntityを回転できない。 - 座標変換の二重実装 —
viewportTransform.ts(Core)とD_useCoordinateSystem.ts(UI)が並存。UCS は UI 側のみ。 - 描画ロジックの Vue 混在 —
D_Daedalus.vue内にcadLinearDimensionScreen(),resolveCadQuickLineScreen(),onDrawLineEndpointMouseDown()等、幾何・グリップ・スナップ計算が直書き。
P2: 保守性
D_Daedalus.vue48,124 行のモノリス — レビュー・差分・HMR・型チェックすべてに悪影響。ユーザーメモリにも「巨大 SFC で apply_patch が隣接ブロックへ誤注入」の既知リスクあり。D_DaedalusRibbon.vue7,043 行 — タブ別 CSS は分割済みだが本体は肥大。- 責務の重複 — Trim 系は
cad-core/commandsとDrafting/D_useLineEditCommandRunnerの二段構成で、UI ランナーにも幾何ロジックが滲む。
P3: 機能完成度(機械系 2D CAD として)
- 寸法不足 — 角度・半径・直径・座標(Ordinate)寸法が無い。機械図面では必須。
- 拘束不足 — Tangent/Perpendicular/Parallel/Angle/Radius 拘束が無い。
- Polygon/Rectangle が専用 Entity でない — POLYLINE で代替(DXF 往復で意味が失われ得る)。
- PNG エクスポート未実装 —
rasterExporter.tsがスタブ。
P4: パフォーマンス
- 巨大 SFC の再描画 —
D_Daedalus.vueの reactive 状態が多すぎ、SVG テンプレートの再評価コスト大。spatialIndex/はあるが UI から十分活用されていない可能性。
3. 設計レビュー
| 観点 | 評価 | 所見 |
|---|---|---|
| 責務分離 | △ | CAD Core 内部は良好。だが UI ↔ Core 境界が崩れ、変換・座標・描画が UI に漏出。 |
| 保守性 | ✕ | 48k 行 SFC が最大のボトルネック。 |
| 拡張性 | ○ | Core はモジュール分割され寸法/拘束追加は容易。Entity は discriminated union で型安全。 |
| パフォーマンス | △ | 巨大 reactive SFC が懸念。Core の spatialIndex 活用余地。 |
| CAD Core 独立性 | △ | Vue 非依存だが、変換ロジックの一部が UI に逃げており「Core だけで図形を編集できない」。 |
Vue へのロジック混在: 重度(D_Daedalus.vue)。 SymbolRenderer(D_sr.*)は分離の良い手本であり、これを横展開の指針とする。
4. リファクタリング計画(方針)
原則(ユーザー指定): ①既存を壊さない ②既存を再利用 ③重複削減 ④CAD Core 中心へ ⑤将来の WASM 移植を考慮(今回 Rust/WASM は実装しない)。
WASM 移植を見据え、CAD Core は 純粋関数 + プレーンデータ(Vue リアクティブ非依存) を維持する。structuredClone 依存は将来 Rust 置換しやすい純データ操作に限定する。
目標アーキテクチャ(再掲)
UI Layer : Toolbar / Property / Layer / Command Input ← Vue は薄く
Rendering Layer : Canvas / SVG / Three.js ← Core の frame を描くだけ
CAD Core : Entities / Geometry / Snap / Selection /
Commands / Constraints / Dimensions / Layers / Transform
Data Layer : DXF Import/Export / Project Save/Load移行戦略(段階的・非破壊)
- Strangler パターン: 既存の Drafting 関数はそのまま残し、内部実装を Core 呼び出しへ差し替える「委譲」方式で 1 つずつ移す。
- 各ステップは 追加 → 委譲 → 旧実装削除 の 3 フェーズ。テストを伴わせる。
5. 優先順位付き改善ロードマップ
| # | 項目 | 内容 | 破壊リスク | 効果 |
|---|---|---|---|---|
| R1 | CAD Core 汎用変換モジュール | cad-core/transform/entityTransforms.ts を新設し、rotateEntity / scaleEntity / mirrorEntity / copyEntity を全 CadEntity 型に対応で追加(applyMoveToEntity と対のパターン)。追加のみ・既存不変。 | なし | 高(Core 独立性回復の核) |
| R2 | 変換モジュールの単体テスト | Vitest で各 Entity 型 × 各変換の不変条件(長さ・半径・角度)を検証。 | なし | 高 |
| R3 | Drafting の Copy/Rotate/Scale/Mirror を Core へ委譲 | D_cadPointCommandExecutor.ts の汎用図形分岐を R1 の関数呼び出しに置換(設備固有処理は残す)。 | 低 | 高 |
| R4 | 角度・半径・直径寸法 | cad-core/dimensions/ に angularDimension / radialDimension を追加。Entity 型へ dimensionType 拡張。 | 低 | 中(機械系で必須) |
| R5 | 追加スナップ(Perpendicular/Tangent) | cad-core/snaps/ に perpendicular/tangent 候補を追加。 | 低 | 中 |
| R6 | 座標変換の一本化 | UI の D_useCoordinateSystem を Core の viewportTransform の薄いラッパへ。UCS を Core へ昇格。 | 中 | 中 |
| R7 | D_Daedalus.vue の分割 | 描画プレビュー/グリップ/寸法計算を composable + Core へ抽出し SFC を縮小。 | 中〜高 | 高(保守性) |
| R8 | Rectangle/Polygon Entity・PNG エクスポート | 不足図形と raster 出力の整備。 | 低 | 低〜中 |
6. 今回の着手
ロードマップ R1(CAD Core 汎用変換モジュール)+ R2(テスト) から開始する。理由:
- 完全に 追加のみ で既存挙動を一切変えない(最も安全)。
- CAD Core 独立性という最重要課題の核心を埋める。
- 後続 R3(委譲)の前提資産になる。
以降の R3〜R8 は本レポートの順で、各々レビュー可能な小さな単位で実施する。
7. 【重要】R3 着手で判明したアーキテクチャの核心: 2 つの並行データモデル
R3(変換ロジックの Core 委譲)に着手して、Daedalus 作図アプリの最重要構造が判明した。
7.1 2 モデル並存の事実
Daedalus は2 つの異なる CAD データモデルを並行して持っている:
| A: Equipment モデル | B: CadEntity モデル(cad-core) | |
|---|---|---|
| 形 | フラットな AABB: { id, x, y, width, height, rotation, type, meta }。曲線・パスは meta.drawPathPoints 等に格納 | discriminated union(LINE/CIRCLE/ARC/...)、各型が固有 geometry を持つ |
| 用途 | メイン作図データ。 D_Daedalus.vue の SVG テンプレートに直接描画され、保存される実体 | hitTest / snap / grips / selection / spatialIndex / DXF I/O / analysis など補助サブシステムで利用 |
| 変換 | D_cadPointCommandExecutor.ts(equipment 専用、eq.x/eq.width 直接操作) | cad-core/transform(Move のみ存在 → R1 で Rotate/Scale/Mirror/Copy 追加済み) |
→ つまり D_Daedalus.vue が 48k 行に肥大化した根本原因はこれ。equipment モデル上に変換・幾何・描画を再実装しており、成熟した cad-core の資産(Entity 変換・寸法・拘束)を直接は使えていない。R1 で追加した entityTransforms.ts は CadEntity 用であり、equipment 用変換をそのまま置換できない(モデル不一致)。
7.2 R3 で実際に行った安全な改善(実装済み)
モデル不一致のため「変換ロジック全体の委譲」は一段で不可。代わりに 両モデルで重複していた純粋幾何プリミティブを CAD Core に集約した(挙動不変・低リスク):
- 新規:
cad-core/geometry/pointTransforms.ts—rotatePointAround/rotatePointAroundDeg/scalePointAround/reflectPointAcrossAxis(CAD Core を single source of truth 化) cad-core/transform/entityTransforms.ts— 内部の重複プリミティブを上記へ委譲Drafting/D_cadPointCommandExecutor.ts— ローカル複製のreflectPointAcrossAxisを削除し CAD Core 版を import(設備固有のミラー処理ロジックは温存)- テスト追加:
pointTransforms.test.ts(9 件)。entityTransforms.test.ts(13 件)と合わせ 22 件全パス
7.3 今後の収束方針(R3 の続き → R7 へ接続)
2 モデルは段階的に CadEntity へ収束させるのが本筋。一気の置換は破壊的なので Strangler で進める:
- 共有プリミティブ集約(R3 で着手済み)— 幾何演算を CAD Core に一本化。
- Equipment ⇄ CadEntity アダプタの明確化(Phase 0 完了)— equipment を CadEntity に投影する変換層を 1 箇所に集約。
- 新規図形を CadEntity ネイティブに — 以降の新機能(角度寸法など)は CadEntity 側に実装し、equipment へは描画時のみ投影。
- 段階的移行 — 図形種別ごとに描画・編集を CadEntity 経由へ差し替え、equipment を最終的に「ビューモデル」へ降格。
Phase 0 実装内容(完了)
frontend/src/cad-core/adapters/equipment/ を新設し、2 モデルの境界を 1 箇所に集約(追加のみ・既存挙動は不変)。
equipmentGeometry.ts— equipment 座標規約(左上基準・y 上向き・中心まわり回転)を純粋関数化。equipmentCenterWorld/equipmentWorldFromLocal(y 反転 → 中心回転)/equipmentLocalFromWorld(逆変換)/ 線・矩形・ポリゴン・パス・円弧・円・楕円のワールド幾何リゾルバ。線分は既存resolveLineAxisWorldSegmentを再利用。equipmentToCadEntity.ts—equipmentToCadEntity(eq)は{ok, entity}または{ok:false, reason, type}を返す。equipmentsToCadEntities(eqs)は一括変換+未対応をskipped[]に収集。3 点円弧の中心復元resolveArcFromThreePoints(外接円算出、共線時 null)を実装(再利用可能な既存関数は無かった)。- 対応種別:
drawLine→LINE/drawCircle→CIRCLE/drawEllipse→ELLIPSE/drawArc→ARC/drawRect→閉 POLYLINE(4頂点)/drawPolygon→閉 POLYLINE/drawPen→開 POLYLINE/drawText→TEXT。 - 後続フェーズへ繰り延べ(
ok:false): 寸法・引出線・中心線・雲マーク・表・スプライン・シンボル/レイアウト物。 - テスト:
equipmentToCadEntity.test.ts14 件全パス(座標往復・3 点円弧・各図形変換・未対応スキップ)。
Phase 1 実装内容(完了)— 新機能を CadEntity ネイティブで実装
方針 3「新規図形を CadEntity ネイティブに」の最初の実装として、角度/半径/直径寸法を CAD Core ネイティブで追加し、描画時のみ equipment へ投影する経路を整備した(追加のみ・既存挙動不変)。
CAD Core 側(寸法モデル拡張):
models/entities.ts—CadDimensionEntity.dimensionTypeに'angular' | 'radial' | 'diameter'を追加。任意フィールドvertex?(角の頂点),centerPoint?(円中心)を追加(既存 linear/aligned はそのまま)。dimensions/angularRadialDimension.ts(新規)—resolveAngularDimensionCore(vertex を頂点に 2 射線がなす角を円弧で表現。dimensionLinePointで弧の半径・向き=劣角/優角を決定。measuredValue = 度)とresolveRadialDimensionCore(radial/diameter。measuredValue = 半径/直径)。dimensions/types.ts—ResolvedDimensionGeometryに任意のarc?(角度寸法の円弧表現)を追加。DimensionKindも拡張。dimensions/resolveDimension.ts—resolveDimensionGeometryのディスパッチ、computeDimensionMeasurement、formatDimensionText(角度=°、半径=R、直径=⌀接頭/接尾)を拡張。dimensions/bounds.ts— 円弧をサンプリングして bounds に反映。dimensions/dimensionFactory.ts(新規)—createAngularDimension/createRadialDimension/createDiameterDimensionコンストラクタ。
描画投影(CadEntity → equipment):
adapters/equipment/cadEntityToEquipment.ts(新規・Phase 0 の逆方向)—cadEntityToEquipment(entity)で LINE→drawLine / CIRCLE→drawCircle / ELLIPSE→drawEllipse / ARC→drawArc / POLYLINE→drawPolygon・drawPen / TEXT→drawText に投影(rotation 0・meta にローカル点を明示)。adapters/equipment/dimensionRenderProjection.ts(新規)—dimensionToRenderEntities(dim)が寸法を普遍プリミティブ(LINE/ARC/閉 POLYLINE 矢じり/TEXT)へ分解。dimensionToEquipmentPrimitives(dim)= 分解 →cadEntityToEquipmentで equipment 群へ投影。CadEntity が source of truth、equipment は描画専用の派生物。- テスト:
angularRadialDimension.test.ts9 件全パス(角度 90°/優角 270°・R/⌀ 表示・textOverride 優先・プリミティブ分解・equipment 投影と drawArc 往復)。cad-core 全体 45 件全パス。
8. Rust / WASM 移植の判断(現時点の結論)
ユーザー目標「cad-core 完成後に Rust/WASM の要否を判断」に対する現時点の評価。
8.1 結論: 現段階では WASM 不要。先に TS で構造的負債を解消すべき。
理由:
- ボトルネックは計算性能ではなく構造。 現状の最大課題は 48k 行モノリスと 2 モデル並存であり、これは Rust では解決しない(むしろ FFI 境界が増えて悪化)。
- CAD Core は既に純粋関数 + プレーンデータで書かれている。 Vue 非依存・
structuredClone中心で、将来 WASM 化する場合の「移植しやすさ」は既に確保されている。今は移植の前提づくりが整っていれば十分。 - WASM のコストが効果を上回る局面ではない。 ビルド複雑化・デバッグ困難・バンドル増・JS↔WASM のデータマーシャリングコストは、現在の図形数規模では正当化されない。
8.2 WASM を検討すべき将来の閾値(トリガ条件)
以下が現実の問題になった時に初めて WASM/Rust を再評価する:
- 単一図面の Entity 数が 数万〜数十万規模になり、ヒットテスト/スナップ/再描画が JS で 16ms/frame を超える。
- 重い幾何カーネルが必要になる(ブーリアン演算・オフセット網羅・制約ソルバの大規模化・NURBS・メッシュブーリアン)。
- DXF/STEP の大規模パースが CPU バウンドになる。
8.3 WASM 化する場合の準備(今 TS でやっておくべきこと = 移植容易性の担保)
- 幾何プリミティブを
cad-core/geometryに集約(R3 で前進)。 - CAD Core を「純粋関数 + プレーン構造体(リアクティブ非依存)」に保つ(既に達成)。
- 変換・交差・スナップなど CPU 集約カーネルを副作用フリーの関数境界に閉じ込める(Rust 置換時にそのまま 1:1 で移せる単位にする)。
→ 方針: WASM は「いつでも移植できる状態」を TS で維持しつつ、当面は実装しない。 まず cad-core 収束(R3〜R7)と機械系機能拡充(R4〜R5)を TS で完了させる。
