2Dリージョンのマスプロパティを取得するマクロ|AutoCAD VBAマクロの作成方法
AutoCADでは[MASSPROP]コマンドを実行することで、リージョンのマスプロパティ(面積、慣性モーメント、図心、回転半径など)を取得することができますが、これらの情報はVBAでも取得可能です。
VBAを使用してマスプロパティの情報を取得することで、その情報を処理の一連の流れに組み込むことができます。これにより、たとえば、取得したマスプロパティの情報を表として出力したり、複数のリージョンからマスプロパティを一括で取得したりすることが可能になります。
マクロ機能
(※1 面積, 周囲, 境界ボックス, 図心座標, 慣性モーメント, 慣性乗積, 回転半径, 主慣性モーメント)
・取得したマスプロパティ情報はイミディエイトウィンドウに出力する
・取得したマスプロパティ情報から主軸を作図する
イミディエイトウィンドウへの出力は[MASSPROP]コマンドの出力結果に合わせていますが、取得できる値は各項目の値です。VBAではかなり細かい値まで取得することができるため、小数点以下第何位で丸めたいという場合はFormat関数やRound関数などを使う必要があります。
サンプルコード
マクロのサンプルコードは下記のとおりです。事前にアクティブドキュメントのモデル空間にリージョンを作成しておく必要があります。マクロ実行後、ユーザーの選択待ち状態となるので対象のリージョンを選択することでマスプロパティを取得することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
Option Explicit '******************************************************************** '* リージョンのマスプロパティを取得する '******************************************************************** Sub GetRegionMassProperty() Dim oRegion As AcadRegion Dim oEntity As AcadEntity Dim dArea As Double Dim dPerimeter As Double Dim vCog As Variant Dim vBBMin As Variant Dim vBBMax As Variant Dim vMoI As Variant Dim vPoI As Variant Dim vRoG As Variant Dim vPMoments As Variant Dim vPDirs As Variant 'ユーザー選択でリージョン取得 On Error Resume Next Call ThisDrawing.Utility.GetEntity(oEntity, Empty, "リージョンを選択") On Error GoTo 0 If TypeName(oEntity) <> "IAcadRegion" Then Exit Sub Set oRegion = oEntity '//----- マスプロパティの取得 -----// dArea = oRegion.Area '<面積> dPerimeter = oRegion.perimeter '<周囲> Call oRegion.GetBoundingBox(vBBMin, vBBMax) '<境界ボックス> vCog = oRegion.Centroid '<図心座標> vMoI = oRegion.momentOfInertia '<慣性モーメント> vPoI = oRegion.ProductOfInertia '<慣性乗積> vRoG = oRegion.RadiiOfGyration '<回転半径> vPMoments = oRegion.PrincipalMoments '<主慣性モーメント> vPDirs = oRegion.PrincipalDirections '<主方向> 'マスプロパティをイミディエイトウィンドウに出力 Debug.Print "---------------- リージョン ----------------" Debug.Print "面積: " & dArea Debug.Print "周囲: " & dPerimeter Debug.Print "境界ボックス: X: " & vBBMin(0) & " -- " & vBBMax(0) Debug.Print " Y: " & vBBMin(1) & " -- " & vBBMax(1) Debug.Print "図心: X: " & vCog(0) Debug.Print " Y: " & vCog(1) Debug.Print "慣性モーメント: X: " & vMoI(0) Debug.Print " Y: " & vMoI(1) Debug.Print "慣性乗積: XY: " & vPoI Debug.Print "回転半径: X: " & vRoG(0) Debug.Print " Y: " & vRoG(1) Debug.Print "図心についての主慣性モーメントおよび X-Y 方向:" Debug.Print " I: " & vPMoments(0) & " 方向 [" & vPDirs(0) & " , " & vPDirs(2) & "]" Debug.Print " J: " & vPMoments(1) & " 方向 [" & vPDirs(1) & " , " & vPDirs(3) & "]" '//----- 主軸作成 -----// Const AXIS_LENGTH As Double = 1000 Dim oLinPAxisX As AcadLine Dim oLinPAxisY As AcadLine Dim oColor As AcadAcCmColor Dim vCoordStart As Variant Dim vCoordEnd As Variant ReDim Preserve vCog(2) '主軸1作成 vCoordStart = CalculateEndPoint(vCog(0), vCog(1), vPDirs(0), vPDirs(2), AXIS_LENGTH) '始点座標計算 vCoordEnd = CalculateEndPoint(vCog(0), vCog(1), -vPDirs(0), -vPDirs(2), AXIS_LENGTH) '終点座標計算 ReDim Preserve vCoordStart(2) ReDim Preserve vCoordEnd(2) Set oLinPAxisX = ThisDrawing.ModelSpace.AddLine(vCoordStart, vCoordEnd) '主軸2作成 vCoordStart = CalculateEndPoint(vCog(0), vCog(1), vPDirs(1), vPDirs(3), AXIS_LENGTH) '始点座標計算 vCoordEnd = CalculateEndPoint(vCog(0), vCog(1), -vPDirs(1), -vPDirs(3), AXIS_LENGTH) '終点座標計算 ReDim Preserve vCoordStart(2) ReDim Preserve vCoordEnd(2) Set oLinPAxisY = ThisDrawing.ModelSpace.AddLine(vCoordStart, vCoordEnd) '軸色を設定 Set oColor = New AcadAcCmColor Call oColor.SetRGB(0, 255, 0) oLinPAxisX.TrueColor = oColor oLinPAxisY.TrueColor = oColor '描画更新 Call ThisDrawing.Regen(acActiveViewport) End Sub '-------------------------------------------------------------------- '- 始点座標と方向成分、長さから終点座標を計算する '- dX :始点X座標 '- dY :始点Y座標 '- dDirX :X方向成分 '- dDirY :Y方向成分 '- dLength :長さ '- 戻り値 :終点のXY座標が入った配列 '-------------------------------------------------------------------- Private Function CalculateEndPoint(ByVal dStartX As Double, ByVal dStartY As Double, _ ByVal dDirX As Double, ByVal dDirY As Double, _ ByVal dLength As Double) As Double() Dim dCoordEnd(1) As Double Dim dMagnitude As Double Dim dVecUnitX As Double Dim dVecUnitY As Double Dim dEndX As Double Dim dEndY As Double '方向ベクトルの大きさを計算 dMagnitude = Sqr(dDirX * dDirX + dDirY * dDirY) '単位ベクトルを計算 dVecUnitX = dDirX / dMagnitude dVecUnitY = dDirY / dMagnitude '終点の座標を計算 dEndX = dStartX + dVecUnitX * dLength dEndY = dStartY + dVecUnitY * dLength dCoordEnd(0) = dEndX dCoordEnd(1) = dEndY '結果を配列として返す CalculateEndPoint = dCoordEnd End Function |
コード解説
ユーザー選択でリージョン取得
マスプロパティを取得する対象のリージョンをユーザー選択で取得するためには、UtilityオブジェクトのGetEntityメソッドを利用します。GetEntityメソッドは実行されるとユーザーの選択待ち状態となり対話的にユーザーが選択したオブジェクトを取得することができます。
1 2 3 4 5 6 7 8 |
'ユーザー選択でリージョン取得 On Error Resume Next Call ThisDrawing.Utility.GetEntity(oEntity, Empty, "リージョンを選択") On Error GoTo 0 If TypeName(oEntity) <> "IAcadRegion" Then Exit Sub Set oRegion = oEntity |
ユーザーが選択されたオブジェクトは第1引数の変数に、選択された座標は第2引数の変数にそれぞれ格納されます。第3引数はユーザー選択時に表示するメッセージで省略も可能です。GetEntityメソッドはユーザーが選択キャンセル([Esc]キーの押下)した場合にエラーが発生してしまうため、「On Error Resume Next」でエラーを無視する等の何らかの対策が必要になります。
サンプルコードでは変数「oEntity」にユーザーが選択されたオブジェクトが入るため、そのオブジェクトがリージョンであるかをTypeName関数を使って判定し、リージョンでなかったり選択されなかった場合(Nothingの場合)は処理を終了するようにしています。
マスプロパティの取得
[MASSPROP]コマンドで取得可能なマスプロパティはRegionオブジェクトのプロパティ/メソッドとしてすべて用意されています。それぞれ下記の通り取得が可能です。
1 2 3 4 5 6 7 8 9 10 11 12 |
'//----- マスプロパティの取得 -----// dArea = oRegion.Area '<面積> dPerimeter = oRegion.perimeter '<周囲> Call oRegion.GetBoundingBox(vBBMin, vBBMax) '<境界ボックス> vCog = oRegion.Centroid '<図心座標> vMoI = oRegion.momentOfInertia '<慣性モーメント> vPoI = oRegion.ProductOfInertia '<慣性乗積> vRoG = oRegion.RadiiOfGyration '<回転半径> vPMoments = oRegion.PrincipalMoments '<主慣性モーメント> vPDirs = oRegion.PrincipalDirections '<主方向> |
図心、慣性モーメント、慣性累積、回転半径、主慣性モーメントとその方向はすべて配列として複数値が返されるため、受け取る変数はVariant型で宣言しておく必要があります。
リージョンの境界ボックスの範囲はGetBoundingBoxメソッドを使うことで取得可能です。取得できる値はXY方向でリージョンを囲む最小の長方形を作成したときの最小(左下点)のXY座標と最大(右上点)のXY座標で、これらの数値だけあれば境界ボックスの高さや幅なども計算で求めることが可能です。
主軸作成
RegionオブジェクトのPrincipalDirectionsメソッドにより取得できた情報はリージョンの主方向を表しています。サンプルコードでは図心からこの主方向に線分を作成しています。線分はModelSpaceオブジェクトのAddLineメソッドに始終点座標を入力することで作成が可能です。
1 2 3 4 5 6 7 8 |
'主軸1作成 vCoordStart = CalculateEndPoint(vCog(0), vCog(1), vPDirs(0), vPDirs(2), AXIS_LENGTH) '始点座標計算 vCoordEnd = CalculateEndPoint(vCog(0), vCog(1), -vPDirs(0), -vPDirs(2), AXIS_LENGTH) '終点座標計算 ReDim Preserve vCoordStart(2) ReDim Preserve vCoordEnd(2) Set oLinPAxisX = ThisDrawing.ModelSpace.AddLine(vCoordStart, vCoordEnd) |
このとき線分の長さは定数値とし、始終点の座標は計算により求めています。
作成した線分の色の変更はAcCmColorオブジェクトにより設定することが可能です。
詳しくは「オブジェクトの色の取得と編集」を参照ください。
まとめ
マスプロパティの情報はRegionオブジェクトからすべて簡単に取得できるため、[MASSPROP]コマンドと同等の処理をVBAで再現するだけであればRegionオブジェクトさえ取得できればすぐに実装することが可能です。[MASSPROP]コマンドは取得した情報をファイル出力することは可能ですが、細かな設定はできません。VBAであれば、たとえばExcelの指定のセルに出力したり、表として出力したりなどの細かい処理を行うことも可能です。