アセンブリファイルに配置されたオカレンスの位置情報は、QA-8359 「アセンブリファイルに配置されたオカレンスの位置情報を取得する方法」で紹介されている通りで、本来ComponentOccurrenceのTransformationであるマトリクスオブジェクトに格納されているTranslationプロパティ情報は、トップアセンブリから見ての相対座標が格納されています。
しかし、サブアセンブリなどにポジションリプリゼンテーション”が設定されている場合は、サブアセンブリのオカレンス情報「oSubAsmOccur.Definition.Occurrence.Item()」でオカレンスの位置を取得した場合、現在の位置ではなく、サブアセンブリドキュメント内の位置(ポジションリプリゼンテーションのマスター位置)を返し、同時にリプレゼンテーションでポジションが移動している場合のサブアセンブリパーツ位置(相対座標)を取得できず、この場合は、絶対座標になってしまいます。
ポジションリプリゼンテーションが設定されている場合では、直接オカレンス側ではなくサブオカレンス側のマトリクスを使い、更に移動後に反転などの計算に用いなければ求められません。
(計算後のマトリクスを与える必要があります。)
一方、”iPropart”の”オカレンス”タブ内に表示される”親アセンブリ原点からの現在のオフセット”内の「角度」情報は、Inventor製品側のオカレンスタブ内の「コアプログラム内」でこのComponentOccurrenceのTransformationであるマトリクスオブジェクト内のベクトルオブジェクト(Vector)を用いて「内積」による角度計算をして表示しています。
APIでは以下のサンプルコードのようにMatrixから角度計算にて求められます。
注意しなければならないのは、角度の計算に伴う符号検査の中で、値の符号を取り出すための Sgn 関数の取り扱いに注意が必要です。
number > 0 1
number = 0 0
number < 0 -1
つまり、検査したMatrixの値が”0″の場合、戻りが0となり、直後に乗算に用いていますので、2π(=180度)の値も、結果として “0”ラジアンにして デグリ変換しているので 0 度として現れますので、判定が必要となります。
Public Function Acos(value) As Double
Acos = Math.Atn(-value / Math.Sqr(-value * value + 1)) + 2 * Math.Atn(1)
End Function
Sub CalculateRotationAngles(ByVal oMatrix As Inventor.Matrix, ByRef aRotAngles() As Double)
Const PI = 3.14159265358979
Const TODEGREES As Double = 180 / PI
Dim oApp As Inventor.Application
Set oApp = ThisApplication
Dim dB As Double
Dim dC As Double
Dim dNumer As Double
Dim dDenom As Double
Dim dAcosValue As Double
Dim oRotate As Inventor.Matrix
Dim oAxis As Inventor.Vector
Dim oCenter As Inventor.Point
Set oRotate = oApp.TransientGeometry.CreateMatrix
Set oAxis = oApp.TransientGeometry.CreateVector
Set oCenter = oApp.TransientGeometry.CreatePoint
oCenter.X = 0
oCenter.Y = 0
oCenter.Z = 0
‘ Xに関するaRotAngles[0]の選択、X-Z平面上に軸を変換する
dB = oMatrix.Cell(2, 3)
dC = oMatrix.Cell(3, 3)
dNumer = dC
dDenom = Sqr(dB * dB + dC * dC)
‘符号検査用の値
Dim oFigou As Integer
If (Abs(dDenom) <= 0.000001) Then
aRotAngles(0) = 0#
Else
If (dNumer / dDenom >= 1#) Then
dAcosValue = 0#
Else
If (dNumer / dDenom <= -1#) Then
dAcosValue = PI
Else
dAcosValue = Acos(dNumer / dDenom)
End If
End If
‘ 符号の検査
oFigou = 1
If (Sgn(dB) < 0) Then
oFigou = -1
End If
aRotAngles(0) = oFigou * dAcosValue<br />
oAxis.X = 1
oAxis.Y = 0
oAxis.Z = 0
Call oRotate.SetToRotation(aRotAngles(0), oAxis, oCenter)<br />
Call oMatrix.PreMultiplyBy(oRotate)
End If
If (oMatrix.Cell(3, 3) >= 1#) Then
dAcosValue = 0#
Else
If (oMatrix.Cell(3, 3) <= -1#) Then
dAcosValue = PI
Else
dAcosValue = Acos(oMatrix.Cell(3, 3))
End If
End If
‘ 符号の検査
oFigou = 1
If ((-oMatrix.Cell(1, 3)) < 0) Then
oFigou = -1
End If
aRotAngles(1) = oFigou * dAcosValue
oAxis.X = 0
oAxis.Y = 1
oAxis.Z = 0
Call oRotate.SetToRotation(aRotAngles(1), oAxis, oCenter)
Call oMatrix.PreMultiplyBy(oRotate)
If (oMatrix.Cell(1, 1) >= 1#) Then
dAcosValue = 0#
Else
If (oMatrix.Cell(1, 1) <= -1#) Then
dAcosValue = PI
Else
dAcosValue = Acos(oMatrix.Cell(1, 1))
End If
End If
‘ 符号の検査
oFigou = 1
If ((-oMatrix.Cell(2, 1)) < 0) Then
oFigou = -1
End If
aRotAngles(2) = oFigou * dAcosValue
aRotAngles(0) = aRotAngles(0) * TODEGREES
aRotAngles(1) = aRotAngles(1) * TODEGREES
aRotAngles(2) = aRotAngles(2) * TODEGREES
Debug.Print “角度(deg) : ” & aRotAngles(0) & ” ,” _
& aRotAngles(1) & “, ” & aRotAngles(2) & vbCrLf
End Sub
Sub GetAngles()
Dim oDoc As AssemblyDocument
Set oDoc = ThisApplication.ActiveDocument
Dim oOcc As ComponentOccurrence
Set oOcc = oDoc.ComponentDefinition.Occurrences(1)
Dim oMat As Matrix
Set oMat = oOcc.Transformation
Dim aRotAngles(2) As Double<br />
Call CalculateRotationAngles(oMat, aRotAngles)
End Sub
‘==============================
‘ ”親アセンブリ原点からの現在のオフセット”の
‘ 情報を求める場合のマクロ
‘==============================
Public Sub GetOffset()
Dim oAsmDoc As AssemblyDocument
Set oAsmDoc = ThisApplication.ActiveDocument
‘ サブアセンブリオカレンス
Dim oSubAsmOccur As ComponentOccurrence
Set oSubAsmOccur = _
oAsmDoc.ComponentDefinition.Occurrences.Item(1)
‘サブアセンブリ内のパーツオカレンス
Dim oOccur1 As ComponentOccurrence
Set oOccur1 = oSubAsmOccur.SubOccurrences.Item(2)
Dim oTransSub As Matrix
Set oTransSub = oSubAsmOccur.Transformation
‘ トップアセンブリのTransformation マトリクス
Dim oTransPart As Matrix
Set oTransPart = oOccur1.Transformation
Dim oTransSubInv As Matrix
Set oTransSubInv = _
ThisApplication.TransientGeometry.CreateMatrix
oTransSubInv.TransformBy oTransSub
oTransSubInv.Invert
Dim oTransSubToPart As Matrix
Set oTransSubToPart = _
ThisApplication.TransientGeometry.CreateMatrix
oTransSubToPart.TransformBy oTransPart
oTransSubToPart.PreMultiplyBy oTransSubInv
Dim aRotAngles(2) As Double
Debug.Print oSubAsmOccur.Name & ” [” & _
oSubAsmOccur.ActivePositionalRepresentation & “]” _
& ” = ” & vbCr & “オフセット(mm) ” & _
oTransSub.Translation.X * 10# & ” , ” & _
oTransSub.Translation.Y * 10# & ” , ” & _
oTransSub.Translation.Z * 10#
Call CalculateRotationAngles(oTransSubInv, aRotAngles)
Debug.Print oOccur1.Name & ” = ” & vbCr & “オフセット(mm) ” & _
oTransSubToPart.Translation.X * 10# & ” , ” & _
oTransSubToPart.Translation.Y * 10# & ” , ” & _
oTransSubToPart.Translation.Z * 10#
Call CalculateRotationAngles(oTransSubToPart, aRotAngles)
End Sub
実行結果です。
SubAssembly:1 [New Test] =
オフセット(mm) -54.2881604011507 , -11.8148364991365 , 44.6815345195355
角度(deg) : 13.5838722978378 ,-37.4036005446772, -159.890668277901
Bolt:1 =
オフセット(mm) -0.764232373660239 , 12.2810417835483 , 81.106793287568
角度(deg) : -13.6836076758785 ,31.6637479393269, -129.098901591566
尚、サンプルファイルとコードは ここ よりダウンロードできます。
By Shigekazu Saito

Leave a Reply