【極限設計】製造DBから図面へ:溶接・表面粗さ記号の「自律的アノテーション・エンジン」構築論
製造現場における「設計意図のデジタル化」は、単なるCADの自動化とは一線を画す。
多くのエンジニアが「VBAで図面に文字を書く」程度の認識でツールを作成し、その結果、メンテナンス不能なスパゲッティコードと、実務では使い物にならない「位置のズレまくるアノテーション」を生み出している。
本稿では、製造要件データベース(ERP/PLM)の情報を起点とし、モデルの幾何学的特徴から溶接記号や表面粗さ記号を自律的に配置する、プロフェッショナル仕様の「アノテーション・エンジン」の設計思想と実装手法を伝授する。
1. 凡庸な自動化と、真のエンジニアリングの境界線
多くの開発者が陥る罠がある。それは、「図面上の座標に直接書き込む」という思考停止だ。
図面は3Dモデルの投影である。モデルの形状が変われば、投影されるビューも、面の位置も変わる。座標をハードコードしたツールは、モデルの修正が入った瞬間にゴミと化す。
真のアーキテクトが設計すべきは、「どこに書くか」をプログラムに教え込むことではない。「どの面に対して、どのような要件を適用すべきか」という「紐付け(Mapping)」のロジックを構築することである。
設計の3大原則
1. Single Source of Truth (SSOT): 記号の内容(溶接サイズ、粗さ値)は、図面ではなくデータベースから取得する。
2. Geometric Anchoring: アノテーションは、図面座標ではなく、モデルの「面(Face)」または「エッジ(Edge)」のIDに紐付ける。
3. View-Agnostic Logic: どのビューに投影されていても、対象の面が映っているビューを動的に特定し、そのビューの座標系へ変換して配置する。
2. システムアーキテクチャ:データ駆動型フロー
堅牢なエンジンは、以下の4つのレイヤーで構成されるべきである。
1. Data Acquisition Layer: SQLやExcel等から「PartNumber」「FaceID」「RequirementType(Weld/Roughness)」「Value」をロードする。
2. Geometric Resolver Layer: モデル内の`FaceID`を検索し、その面が現在開いている図面のどの`View`に投影されているかを特定する。
3. Coordinate Transformation Layer: 3D空間の面中心座標を、図面ビュー内の2D座標へと投影変換する。
4. Annotation Factory Layer: SolidWorks APIを叩き、`WeldSymbol`や`Note`オブジェクトを生成・配置する。
3. プロダクション・コードの実装例
以下に示すのは、単なるサンプルではない。エラーハンドリング、オブジェクトのライフサイクル管理、そして座標変換のロジックを組み込んだ、実務に耐えうるクラスモジュールの設計思想に基づいたコードである。
※このコードは、論理構造を理解するための「コア・ロジック」である。実務では、データベース接続部分(ADO等)を組み込んで使用せよ。
' ==============================================================================
' Module: AnnotationEngine
' Description: 製造DBに基づき、図面に溶接・表面粗さ記号を自動配置するエンジン
' Author: Chief Architect
' ==============================================================================
Option Explicit
' 構造体定義:DBから取得した製造要件
Private Type ManufacturingRequirement
TargetFaceID As Long ' モデル上の面の識別子
ReqType As String ' "WELD" or "ROUGHNESS"
Value As String ' 記号の値 (例: "Ra 3.2", "6mm")
SymbolType As String ' 記号の種類
End Type
' メインプロセス
Public Sub ExecuteAutomaticAnnotation()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swDraw As SldWorks.DrawingDoc
Dim swSheet As SldWorks.Sheet
On Error GoTo ErrorHandler
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
' 1. ドキュメントのバリデーション
If swModel Is Nothing Then Exit Sub
If swModel.GetType <> swDocDRAWING Then
MsgBox "図面ファイルを開いてください。", vbCritical
Exit Sub
End If
Set swDraw = swModel
' 2. DBから要件を取得 (ここではモックデータを使用)
Dim requirements() As ManufacturingRequirement
requirements = GetMockRequirements()
' 3. エンジンの実行
Dim i As Long
For i = LBound(requirements) To UBound(requirements)
ProcessRequirement swApp, swModel, swDraw, requirements(i)
Next i
swModel.ForceRebuild3 True
MsgBox "アノテーションの生成が完了しました。", vbInformation
Exit Sub
ErrorHandler:
MsgBox "致命的なエラーが発生しました: " & Err.Description, vbCritical
End Sub
' 個別の要件を処理するコアロジック
Private Sub ProcessRequirement(swApp As SldWorks.SldWorks, swModel As SldWorks.ModelDoc2, _
swDraw As SldWorks.DrawingDoc, req As ManufacturingRequirement)
Dim swPart As SldWorks.PartDoc
Dim swView As SldWorks.View
Dim swAnnotation As SldWorks.Annotation
Dim swNote As SldWorks.Note
Dim targetView As SldWorks.View
Dim targetPos As Variant
' モデル(Part)への参照取得
Set swPart = swModel.GetModelDoc2.GetPart
If swPart Is Nothing Then Exit Sub ' 図面がモデルを参照していない場合
' --- STEP 1: ターゲット面が投影されているビューの特定 ---
' 全ビューを走査し、対象のFaceIDが含まれるビューを探す
Set swView = swDraw.GetFirstView ' Sheet自体が最初のView
Set targetView = Nothing
Do While Not swView Is Nothing
' ビュー内のエンティティを走査してFaceIDを照合(実際にはより高度な検索ロジックが必要)
If IsFaceInView(swView, req.TargetFaceID) Then
Set targetView = swView
Exit Do
End If
Set swView = swView.GetNextView
Loop
If targetView Is Nothing Then
Debug.Print "警告: FaceID " & req.TargetFaceID & " が投影されているビューが見つかりません。"
Exit Sub
End If
' --- STEP 2: 3D座標から2D投影座標への変換 ---
' ここでは簡略化のため、面の中心座標を取得するロジックを想定
' 本来は View.GetProjectionPoint を使用して正確な位置を計算する
targetPos = GetFaceCenterInDrawingView(swPart, req.TargetFaceID, targetView)
' --- STEP 3: アノテーションの生成 ---
If req.ReqType = "ROUGHNESS" Then
' 表面粗さ記号の生成 (Noteとして作成し、記号書式を適用するアプローチ)
Set swNote = targetView.CreateNote(req.Value)
If Not swNote Is Nothing Then
Set swAnnotation = swNote.GetAnnotation
swAnnotation.SetPosition targetPos(0), targetPos(1), 0
' ここで表面粗さ専用のプロパティ設定を行う
End If
ElseIf req.ReqType = "WELD" Then
' 溶接記号の生成
' WeldSymbol APIは複雑なため、Noteの作成後にSymbol設定を行う
Set swNote = targetView.CreateNote(req.Value)
If Not swNote Is Nothing Then
Set swAnnotation = swNote.GetAnnotation
swAnnotation.SetPosition targetPos(0), targetPos(1), 0
End If
End If
End Sub
' --- 補助関数群 (実装の骨子) ---
' 指定したFaceIDがビュー内に存在するか判定
Private Function IsFaceInView(swView As SldWorks.View, faceID As Long) As Boolean
' 実務では swView.GetFirstEntity をループし、
' Entity.GetType が swEntitytype_e.swEntitytype_Face かつ IDが一致するかを確認する
' 今回はロジックのデモのため True を返す
IsFaceInView = True
End Function
' 面の中心座標を、図面ビュー上の2D座標として取得する
Private Function GetFaceCenterInDrawingView(swPart As SldWorks.PartDoc, faceID As Long, swView As SldWorks.View) As Variant
' 1. 3D空間上の面中心を取得
' 2. swView.GetViewMatrix を用いて、3D座標をビューの座標系へ変換
' 3. 変換後の(x, y)を返す
' ※ 非常に重い処理になるため、キャッシュ戦略を推奨
GetFaceCenterInDrawingView = Array(0.1, 0.1) ' ダミー座標
End Function
' モックデータ生成
Private Function GetMockRequirements() As ManufacturingRequirement
Dim reqs(1) As ManufacturingRequirement
reqs(0).TargetFaceID = 101
reqs(0).ReqType = "ROUGHNESS"
reqs(0).Value = "Ra 1.6"
reqs(1).TargetFaceID = 202
reqs(1).ReqType = "WELD"
reqs(1).Value = "6"
GetMockRequirements = reqs
End Function
4. プロフェッショナルが守るべき「実装の作法」
座標変換の計算コストを制御せよ
`View.GetProjectionPoint` や行列計算は、ループ内で数千回呼び出すとSolidWorksの動作を著しく低下させる。
「変更があった面のみ再計算する」、あるいは「計算結果を一時的なキャッシュ(Dictionaryオブジェクト等)に保持する」設計を組み込め。
エラーハンドリングは「部分的な失敗」を許容せよ
全アノテーションの生成プロセスにおいて、一つのFaceIDが見つからないだけでプロセス全体を `Exit Sub` させてはいけない。
「どのIDの処理に失敗したか」をログに出力し、「可能な限り多くの記号を配置して終了する」のが、実務ツールとしての正しい挙動である。
オブジェクトの解放
VBAはガベージコレクションが弱いため、巨大なループ内で `Set swEntity = Nothing` を明示的に行わないと、メモリリークを引き起こし、SolidWorksが「応答なし」になる原因となる。特に、`SelectionMgr` や `Entity` オブジェクトを扱う際は細心の注意を払え。
結論
図面自動化の真の価値は、単に「作業を速くすること」ではない。
「設計変更に対して、常にデータに基づいた正確な図面を、瞬時に再生成できる体制を作ること」にある。
このアーキテクチャを理解し、実装できるエンジニアこそが、次世代のスマートマニュファクチャリングを支えるリーダーとなるのだ。
