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という複雑な空間をあなたの指先でコントロールする第一歩だ。さあ、次はどのオブジェクトを掌握する?
