Inventor2014 APIで「親アセンブリ原点からの現在のオフセット」の情報を取り出す方法

SubAsm

SubPart

アセンブリファイルに配置されたオカレンスの位置情報は、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


Comments

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading