【テクニカル・上級編】【実務中級】図面比較を自動化!2つの図面の差分を検出するVBAテクニック – AutoCAD VBA解析バイブル

スポンサーリンク

【AutoCAD VBA】図面比較の深淵:ハッシュアルゴリズムとオブジェクト・ライフサイクル管理による差分検出の極致

AutoCADの図面比較(DWG Compare)は、オートデスクが提供する標準機能だが、現場のシニアエンジニアであれば「あれはあくまで視覚的な補助に過ぎない」と知っているはずだ。設計変更の履歴追跡、あるいは自動検査システムに組み込むためには、ブラックボックスのコマンドではなく、我々自身の手で「データ構造」を解析せねばならない。

本稿では、VBAというレガシーかつ強力なインターフェースを使い、オブジェクトの属性値を抽出・ハッシュ化することで、図面間の論理的な差異を高速に検出するアーキテクチャを解説する。

—

1. 比較エンジンの設計思想:なぜ「図面全体」を回してはいけないのか

AutoCADの`ModelSpace`を単にループして比較するようなコードは、図面規模が大きくなった瞬間に崩壊する。オブジェクトの数、複雑なブロック参照、XData……。これらを単純比較すれば、メモリリークと計算量爆発を招くのは自明だ。

極限の知見:

  • ハッシュ化の導入: 全プロパティを逐一比較するのではなく、Handle、Layer、LayerState、Color、Linetype、そして座標値(Vector)を連結した文字列からMD5相当のハッシュ値を生成し、Dictionaryオブジェクトで比較せよ。
  • メモリの解放: `AcadEntity`オブジェクトへの参照は、ループのイテレーションごとに即座に `Nothing` をセットし、`CollectGarbage`(VBAにはないが、オブジェクトのスコープ管理で代用)を意識する。

—

2. 実装:高速差分検出アルゴリズム

以下のコードは、2つの図面から「Entityのハッシュマップ」を生成し、その差分を抽出するコアロジックの断片だ。

‘ 必要な参照設定: Microsoft Scripting Runtime
‘ 比較対象のエンティティのプロパティをハッシュ化して保持
Public Function GetEntityHash(ent As AcadEntity) As String
‘ パフォーマンスの要:座標等の浮動小数点は精度を丸めてから文字列化する
‘ ここを疎かにすると、微小な浮動小数点誤差で差分と誤認される
Dim hashBase As String
hashBase = ent.ObjectName & “|” & ent.Layer & “|” & _
Format(ent.InsertionPoint(0), “0.0000”) & “|” & _
Format(ent.InsertionPoint(1), “0.0000”)

‘ 本来はここでSHA256等のAPIを呼び出すのがベストだが、
‘ VBA環境であれば簡易的にVBScript.Encodeやハッシュ関数を利用する
GetEntityHash = hashBase
End Function

Public Sub CompareDrawings(doc1 As AcadDocument, doc2 As AcadDocument)
Dim dict1 As Object: Set dict1 = CreateObject(“Scripting.Dictionary”)
Dim ent As AcadEntity

‘ 図面1の解析(DictionaryにHandleをキーとして保存)
For Each ent In doc1.ModelSpace
dict1.Add ent.Handle, GetEntityHash(ent)
Set ent = Nothing ‘ ライフサイクルの明示的解放
Next ent

‘ 図面2と比較
For Each ent In doc2.ModelSpace
If dict1.Exists(ent.Handle) Then
If dict1(ent.Handle) <> GetEntityHash(ent) Then
Debug.Print “変更検知: ” & ent.Handle
End If
dict1.Remove ent.Handle
Else
Debug.Print “新規追加: ” & ent.Handle
End If
Set ent = Nothing
Next ent

‘ 残ったdict1のキーは「削除されたオブジェクト」
‘ …
End Sub

—

3. パフォーマンスを極めるためのエンジニアリングTips

Windows APIによる「フリーズ」の回避

大規模図面を処理する際、AutoCADが「応答なし」になるのを防ぐ必要がある。VBAのループ内で `DoEvents` を叩くのは定石だが、多用するとオーバーヘッドが大きい。1000要素ごとに `DoEvents` を実行するカウンターを実装せよ。

オブジェクトの明示的解放の真実

VBAの参照カウンタは優秀だが、AutoCADのCOMオブジェクトは複雑な循環参照を抱えやすい。`For Each` ループ内で取得したオブジェクトは、必ずそのスコープの終わりで `Nothing` を代入する。これだけで、長時間稼働後のメモリ消費量が劇的に安定する。

レガシー環境の保守:なぜVBAで戦うのか

現在では .NET (ObjectARX) が主流だが、社内の古いシステムやドキュメント管理ツールとの連携において、VBAの「手軽さ」は捨てがたい。もし将来的に .NET へ移行する可能性があるなら、ロジックをVBAのフォームコードに書かず、`Class` モジュールにカプセル化せよ。インターフェースを分離しておくことで、将来的にDLLへ容易に移植可能となる。

—

終わりに:アーキテクトからの提言

図面比較を自動化するということは、単にツールを作ることではない。「設計者の意図がどこで変化したか」をデータとして定義する行為である。

AutoCADのオブジェクトモデルは、CADという巨大なグラフ構造の一部に過ぎない。今回紹介したハッシュベースのアプローチは、その氷山の一角だ。さらに踏み込むのであれば、`AcDbDatabase` を直接操作する ObjectARX (C++) への道が待っている。

しかし、まずはこのVBAで、現場の「見落とし」を撲滅する第一歩を踏み出してほしい。コードは語る。君がどれだけ細部に魂を込めたかを。

タイトルとURLをコピーしました