【テクニカル・上級編】【中級】Shape.BoundingBoxによる図形の重なり判定:レイアウト崩れをVBAで検知する – Visio VBA解析バイブル

スポンサーリンク

Visio自動化の深淵:Shape.BoundingBoxで「レイアウトの無秩序」を制圧する

Visioの図面を「単なるお絵描き」だと思っているなら、君はまだVisioの本当の力を知らない。Visioは座標系を持つ極めて精緻なグラフィカル・データベースだ。

特に、数千のノードが複雑に絡み合うシステム構成図やネットワーク図において、人手によるレイアウト調整は「技術的負債」の温床となる。図形同士の重なりは可読性を奪い、ドキュメントの信頼性を根底から揺るがす。

今回は、`Shape.BoundingBox`メソッドを極限まで使い倒し、レイアウトの崩れを自動検知・排除するためのアーキテクチャを伝授する。

—

1. BoundingBoxの真実:Visio座標系の罠

`Shape.BoundingBox`は、単に四角形を返すメソッドではない。引数に渡すフラグによって、図形の「見えている部分」を取得するか、「グループ化された内部構造まで含めるか」を制御できる。

多くのエンジニアが犯すミスは、`visBBoxExtents`(図形の外枠)を盲信することだ。影やコネクタの端点を含めた「実質的な占有領域」を算出するには、常に`visBBoxIncludeOutlines`を指定せよ。

‘ 伝説のアーキテクトが推奨するBoundingBox取得パターン
‘ flags:
‘ visBBoxUprightWH (0) – 回転を無視した矩形
‘ visBBoxExtents (1) – 図形の境界線
‘ visBBoxIncludeOutlines (16) – 線幅や影を含む完全な占有領域
Dim left As Double, bottom As Double, right As Double, top As Double
shp.BoundingBox visBBoxExtents + visBBoxIncludeOutlines, left, bottom, right, top

—

2. 重なり判定のアルゴリズム:衝突検知の最適化

図形Aと図形Bが重なっているかを判定する際、二重ループで全件比較するのは愚行だ。N個の図形に対してO(N^2)の計算量を強いるコードは、巨大な図面ではシステムをフリーズさせる。

シニアエンジニアの流儀:
1. 空間分割法(簡易版):図面をグリッドで区切り、同じセルにある図形同士のみを比較する。
2. 早期リターン:外接矩形を比較し、明らかに離れているものは即座に処理対象から外す。

‘ 2つのShapeが物理的に重なっているかを判定する関数
Public Function IsOverlapping(shpA As Visio.Shape, shpB As Visio.Shape) As Boolean
Dim l1 As Double, b1 As Double, r1 As Double, t1 As Double
Dim l2 As Double, b2 As Double, r2 As Double, t2 As Double

shpA.BoundingBox visBBoxExtents + visBBoxIncludeOutlines, l1, b1, r1, t1
shpB.BoundingBox visBBoxExtents + visBBoxIncludeOutlines, l2, b2, r2, t2

‘ 重なり判定のロジック(ド・モルガンの法則を用いた判定の反転)
‘ これが最も高速かつ直感的な「非接触」の条件
If r1 < l2 Or l1 > r2 Or t1 < b2 Or b1 > t2 Then
IsOverlapping = False
Else
IsOverlapping = True
End If
End Function

—

3. メモリ管理とパフォーマンスの極致

VBAはガベージコレクションが脆弱だ。特にVisioのオブジェクトモデルをループ内で頻繁に生成・破棄すると、メモリリークの温床となる。

  • `Set shp = Nothing` の徹底:ループの最後で必ずオブジェクト参照を解放せよ。
  • イベントの抑制:座標計算中に`Application.ScreenUpdating = False`と`Application.DeferRecalc = True`を必ず挟め。再計算イベントを抑えるだけで、処理速度は一桁変わる。

Public Sub ValidateLayout(doc As Visio.Document)
Dim pag As Visio.Page
Dim shp As Visio.Shape

‘ 最適化の定石
Application.ScreenUpdating = False
Application.DeferRecalc = True

On Error GoTo Cleanup

For Each pag In doc.Pages
‘ ここに判定ロジックを配置
Next

Cleanup:
‘ 確実にリソースを解放する
Application.DeferRecalc = False
Application.ScreenUpdating = True
Set pag = Nothing
End Sub

—

4. 最後に:なぜ自動化するのか

このスクリプトは、単なるバリデーターではない。ドキュメントの「品質保証」を自動化するための武器だ。

巨大なVisioファイルを修正する際、人間は必ず見落とす。しかし、コードは嘘をつかない。`BoundingBox`による検知をCI/CDパイプラインに組み込む、あるいはGitで管理されたVisioファイルの差分チェックに組み込めば、君のチームのドキュメント作成コストは劇的に削減されるだろう。

技術とは、人間を退屈な手作業から解放するためにある。さあ、このコードを武器に、混沌とした図面を秩序あるデータに変えていくとしよう。

何かあればいつでも聞け。VBAの深淵で待っている。

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