こんにちは!AutoCAD VBAの自動化の世界へようこそ。
マクロの記録ボタンを押して「動いた!」と喜んでいた時期を通り越し、「もっと現場で実用的なツールを作りたい!」と一歩踏み出したあなたへ。
今回は、実務で死ぬほど使うテクニック「2点間の角度を瞬時に算出し、図面上のオブジェクト(ブロックや文字など)をピタッとその角度に整列させる自動化ロジック」を伝授します。
ここをクリアすれば、AutoCAD VBAのオブジェクトモデルの操り方がグッと体に入り、あなたも立派な自動化エンジニアの仲間入りです。一緒に本質をマスターしていきましょう!
—
1. なぜ「2点間の角度」が必要なのか?(実務の現場から)
図面を描いていて、こんな面倒な作業をしたことはありませんか?
- 「斜めの道路や境界線に沿って、マンホールや街路樹のブロックを配置したい」
- 「配管の傾きに合わせて、バルブのシンボルや注記の文字を回転させたい」
これを手作業でやると、「オブジェクトを選択 ➔ 回転コマンド(ROTATE) ➔ 基準点を指定 ➔ 参照(Reference)を選んで…」と、何度もマウスをカチカチ言わせる必要があります。気が遠くなりますよね。
これをVBAで一瞬にして解決します。
ユーザーに「基点」と「方向を決める2点目」を指定してもらい、そのベクトルから数学的な角度を算出してオブジェクトを回転させる。この一連の流れをコードに落とし込みます。
—
2. 核心に迫る:`AngleFromPoint` とオブジェクトモデル
AutoCAD VBAには、図面空間を司る `AcadDocument` があり、その中にユーザー入力を受け付ける最強の相棒 `Utility` オブジェクトが隠されています。
その `Utility` が持つ秘技の一つが `AngleFromPoint` です。
🧠 `AngleFromPoint` の本質
このメソッドは、「ある基準点から見て、もう一つの点がどの方向にあるか(ラジアン角)」をCADの数学空間(反時計回りが正)に基づいて一発で計算してくれます。
- 構文のイメージ:
`doubleVar = doc.Utility.AngleFromPoint(基準点, 対象点)`
trigonometry(三角関数)を自分でゴリゴリ書く必要は一切ありません。AutoCADのエンジンが瞬時に計算してくれます。
—
3. 【実践】2点間角度でオブジェクトを自動整列させるマクロ
それでは、実際の現場で即戦力として使えるコードを公開します。
適当な図面に「ブロック」または「文字(テキスト)」を一つ用意し、VBAエディタ(Alt + F11)の標準モジュールに貼り付けて実行してみてください。
Sub AlignObjectByTwoPoints()
Dim acadDoc As AcadDocument
Set acadDoc = ThisDrawing.ActiveDocument
On Error GoTo ErrorHandler ‘ ユーザーがESCキーでキャンセルした時の対策
‘ 1. 対象となるオブジェクトを選択する
Dim objEnt As AcadEntity
Dim basePnt As Variant
acadDoc.Utility.GetEntity objEnt, basePnt, vbCrLf & “整列させたいオブジェクトをクリックしてください: ”
‘ 2. 角度の基準となる「1点目(始点)」をユーザーに入力させる
Dim pnt1 As Variant
pnt1 = acadDoc.Utility.GetPoint(, vbCrLf & “角度の基準となる1点目(始点)を指定: “)
‘ 3. 角度の方向を決める「2点目(終点)」をユーザーに入力させる
Dim pnt2 As Variant
pnt2 = acadDoc.Utility.GetPoint(pnt1, vbCrLf & “向きを決める2点目(終点)を指定: “)
‘ 4. Utility.AngleFromPoint を使って2点間の角度(ラジアン)を算出!
Dim targetAngle As Double
targetAngle = acadDoc.Utility.AngleFromPoint(pnt1, pnt2)
‘ 5. オブジェクトの回転プロパティを書き換える
‘ ※すべてのAcadEntityがRotationプロパティを持つわけではないため、TypeNameで安全に分岐します
Select Case TypeName(objEnt)
Case “AcadBlockReference”, “AcadText”, “AcadMText”, “AcadSymbolTableRecord”
objEnt.Rotation = targetAngle
objEnt.Update ‘ 画面を強制更新
MsgBox “オブジェクトを指定した角度に整列しました!”, vbInformation, “自動化完了”
Case Else
MsgBox “選択されたオブジェクトは回転に対応していないか、未対応のタイプです。”, vbExclamation
End Select
Exit Sub
ErrorHandler:
‘ エラー番号が Err.Number = -2147352567 (キャンセルの場合など) は無視する処理
If Err.Number <> 0 Then
‘ ユーザーキャンセル時は静かに抜ける
If Err.Number <> -2147467259 Then
‘ 想定外のエラーのみ通知
‘ MsgBox “エラーが発生しました: ” & Err.Description
End If
End If
End Sub
—
4. コードの深掘り解説:ここがプロの技
初心者のうちは、ただ動くコードをコピペしがちですが、チーフアーキテクトとして「なぜこの書き方をしているのか」の急所を解説します。
① ユーザー入力を安全に受け取る作法 (`GetEntity`, `GetPoint`)
AutoCAD VBAでは、画面上でユーザーにクリックを促す際、`Utility` オブジェクトのメソッドを使います。
- `GetEntity` は、図形そのものと、マウスでクリックした「生の位置(基点)」を同時に取得できます。
- `GetPoint` の第1引数に `pnt1` を渡している点に注目してください。これにより、CAD特有の「ゴム紐(ラバーバンド)」が1点目から2点目に向かって表示され、視覚的に非常に分かりやすいインターフェースになります。
② ラジアン(Radian)の罠
AutoCADのプロパティ(`Rotation` など)が受け付ける角度の単位は、私たちが普段使う「度(Degree)」ではなく、「ラジアン(Radian)」です。
`AngleFromPoint` が返す値も最初からラジアンなので、そのまま `objEnt.Rotation` に代入できます。「あれ?変な方向に向いちゃったぞ?」という時は、大体度とラジアンの換算ミス(`Deg Atn(1) / 45` など)が原因ですが、今回はその心配もありません。
③ `TypeName` による型安全性の確保
AutoCADの図形(`AcadEntity`)には、線(Line)や円(Circle)など、回転させても意味がない(あるいはRotationプロパティを持たない)ものが存在します。
ここで `Select Case TypeName(objEnt)` を使って、ブロック(`AcadBlockReference`)や文字(`AcadText`)など、回転可能なオブジェクトだけに処理を限定しています。これを怠ると、実行時エラー(エラー438: オブジェクトは、このプロパティまたはメソッドをサポートしていません)でマクロがクラッシュします。実務のコードには、こうした「防衛策」が不可欠です。
—
5. 初学者が絶対にハマる!陥りやすいエラーと対策
1. ユーザーが「ESC」キーを押したときの強制終了
- 対策: コード内に `On Error GoTo ErrorHandler` を仕込んでおかないと、ユーザーが途中で入力をやめてESCキーを押した瞬間に、VBAが黄色いエラー画面を出して停止してしまいます。プロのツールは例外処理まで美しく書きましょう。
2. 3D空間(Z座標)の落とし穴
- 対策: `GetPoint` は通常 `Variant型` の配列(X, Y, Z)を返します。水平な2点間であればZは同じですが、もし3Dの立体空間でこれを扱う場合は、XY平面に投影した角度計算が必要になるケースもあります。まずはXY平面(2D図面)の整列から確実にマスターしてください。
—
まとめ
今回は `AcadDocument.Utility.AngleFromPoint` を駆使した、2点間の角度に基づくオブジェクトの自動回転整列のロジックを解説しました。
- `Utility.AngleFromPoint` を使えば、2点間の角度がラジアンで一発計算できる。
- `GetPoint` のラバーバンドを活用して、ユーザーフレンドリーな入力を実現する。
- `TypeName` でオブジェクトの型をチェックし、安全性を担保する。
ここをクリアできれば、単なる「お絵描きマクロ」から、現場の設計効率を何倍にも跳ね上げる「本格的な業務自動化ツール」へとステップアップできます。
ぜひあなたの手元でもコードを動かして、その圧倒的なスピード感を体感してください。
AutoCAD VBAの基本は、もうバッチリですね!次のステップへ進みましょう。
