【実務・中級編】Shape.GetBoundingBoxを用いた高精度な描画エリア算出:回転された図形でも正確な外接矩形を特定するアルゴリズム – Visio VBA解析バイブル

スポンサーリンク

Visioの「境界」を支配せよ:回転シェイプを撃ち抜くShape.GetBoundingBoxの極意

Visio自動化の現場で、多くのエンジニアが最初の壁にぶつかる。「なぜ、座標計算がズレるのか」。

図形を回転させた瞬間、`Shape.Cells(“Width”).ResultIU` を用いた計算は崩壊する。Visioにおいて図形の境界ボックス(Bounding Box)を算出する際、標準的なプロパティに頼ることは、不安定な地盤の上に高層ビルを建てるようなものだ。

今回は、回転した図形や複雑なグループに対しても、ミリ単位の精度で正確な座標を導き出す `Shape.GetBoundingBox` の真髄と、プロダクション環境で耐えうる設計手法を伝授する。

1. なぜ「Width/Height」では不十分なのか

Visioのオブジェクトモデルにおいて、`Shape.Width` や `Shape.Height` は「図形そのもののローカルなサイズ」を指す。しかし、図形が回転(Angle)している場合、Visioの描画エンジンが管理する「描画領域(外接矩形)」は、ローカル座標から幾何学的に変換される必要がある。

安易にこれらの数値を加算・減算してレイアウトを決定するコードは、数ヶ月後に必ずバグを生む。なぜなら、「シェイプのデータ上のサイズ」と「画面上で占有している物理的な領域」は、回転が入った瞬間に別物になるからだ。

2. 禁断のメソッド「GetBoundingBox」の正体

我々が真に使うべきは、`Shape.GetBoundingBox` メソッドである。このメソッドには、計算の精度を決定づける `Flags` というパラメータが存在する。

‘ 構文の要点
Shape.GetBoundingBox(Flags, Left, Bottom, Right, Top)

この `Flags` に `visBBoxUprightWH`(回転を考慮した外接矩形を算出するフラグ)を指定しなければ、正確なレイアウト計算など夢のまた夢だ。

プロダクションコード:高精度座標取得関数

この関数は、あらゆるシェイプに対して「実際の描画領域」を返す、自動化ツールの心臓部となる。

”’

”’ 回転を考慮した正確な描画境界を取得する
”’

Public Function GetAbsoluteBounds(shp As Visio.Shape) As Variant
Dim l As Double, b As Double, r As Double, t As Double

‘ visBBoxUprightWH (1): 回転された図形であっても、水平・垂直な外接矩形を返す
‘ visBBoxIncludeGuides (16): ガイド線を含める場合は加算する
‘ 現場では基本 1 を使用し、グループ構成に応じた適正な値を取得する
shp.GetBoundingBox visBBoxUprightWH, l, b, r, t

‘ 結果を配列で返す(呼び出し側の保守性を考慮)
GetAbsoluteBounds = Array(l, b, r, t)
End Function

3. 実践:レイアウトの自動配置における落とし穴

「座標を計算して、別の図形の横に配置する」という単純なタスクでも、以下の設計思想が欠けているとツールは死ぬ。

1. PinX/PinYとBoundingBoxの分離: `PinX` は回転の中心点であり、境界ではない。配置計算には必ず `GetBoundingBox` の結果を用いてオフセットを算出すること。
2. 単位の正規化: Visio内部の単位は常に「インチ(内部値)」である。ユーザーに見せるUIやDB連携時は、`Application.ConvertResult` でセンチメートルやピクセルに変換するフローを挟むこと。
3. 再帰的思考: グループ化されたシェイプに対しては、グループ単位の境界を取得するのか、構成要素全ての境界の和集合をとるのかを明確に定義せよ。

4. 堅牢な設計のためのベストプラクティス

データベース連携や外部ツールとの連携を行う場合、以下のチェックリストを遵守せよ。

  • グループの階層を意識する: `GetBoundingBox` は対象シェイプの階層に依存する。グループ内の子要素を取得したい場合は、再帰的に関数を呼び出す設計が必須だ。
  • 誤差の許容: 浮動小数点数(Double型)の計算誤差は避けられない。比較演算を行う際は、必ず `Abs(a – b) < 0.0001` のようなデルタ比較を行うこと。
  • イベント駆動の排他: 自動レイアウト中に `ShapeAdded` イベントなどが発火し、無限ループに陥るケースがある。処理中は `Application.DeferRecalc = True` を活用し、再計算を一時停止させるのがプロの定石だ。

最後に:エンジニアとしての矜持

Visio VBAは「古い言語」と揶揄されることがある。しかし、オブジェクトモデルの深淵を理解した上で記述されるコードは、他のモダンな言語と同様に、極めて強力で美しい。「動けばいい」というレベルを脱し、「将来の変更に耐えうるか」「数学的に正確か」を常に自問自答せよ。

この `GetBoundingBox` を使いこなすことは、Visioという複雑な空間をあなたの指先でコントロールする第一歩だ。さあ、次はどのオブジェクトを掌握する?

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