座標系からXY,YZ,ZXの各平面のリファレンスを取得する場合、
座標系の作り方によっては、上手く取得出来たり出来なかったり
します。
例えば、XYZ軸を全て指定している場合
は、
X(Y,Z)AxisDirection(Referenceオブジェクト)が取得できています。
僕が結構やってしまう、XY軸のみを指定している場合
は、
指定していないZAxisDirectionのみ失敗しています。
"リンクの結果として"・"結果として"や分離した座標系の場合
は、全滅となります。
確かに、指定していない部分についてはリファレンスガ取得できていなくても
仕方が無いとは、薄々思います。
代案として考えた場合、こちらを見ると
http://www.coe.org/p/fo/st/topic=113&post=75726
Little Cthulhuさんが(この方物凄いです)
「座標系から原点とXY軸のベクトルが取得できるから
それを元に平面作っちゃえば良いじゃん」
的なサンプルを提示しています。
でも、個人的にはそうじゃなくやっぱり座標系の平面としてリファレンスを
取得したいのが本音です。 軸の指定が不足している座標系でも
手動で操作した場合であれば、通常通りの操作で出来ますし、
座標系の変更にも対応できる。だからやっぱり
座標系の平面としてリファレンスを取得したい
と思い取り組んだら、出来たっぽいので記載しておきます。
'vba '座標系の各平面のリファレンスの取得 'Return : 0-XY,1-YZ,2-ZY のリファレンス Private Function GetAxisPlaneRefs(ByVal Ax As AxisSystem) As Variant ' Reference() Dim Pt As Part: Set Pt = GetParent_Of_T(Ax, "Part") Dim Axs As AxisSystems: Set Axs = Pt.AxisSystems 'Ax要素取得 Dim AxData As Variant: AxData = GetAxisOriVec(Ax) 'Axのインデックスを取得 Dim TempAxData As Variant Dim i&, Idx&: Idx = -1 For i = 1 To Axs.Count If Ax.Name = Axs.Item(i).Name Then TempAxData = GetAxisOriVec(Axs.Item(i)) If isArrayEqual(AxData, TempAxData) Then Idx = i: Exit For End If End If Next If Idx < 0 Then Exit Function Dim PlaneRef(2) As Reference For i = 0 To UBound(PlaneRef) Set PlaneRef(i) = Pt.CreateReferenceFromBRepName(GetAxisPlaneBrepName(Idx, i), Ax) Next GetAxisPlaneRefs = PlaneRef End Function '座標系の原点XYベクトル取得 Private Function GetAxisOriVec(ByVal Ax As AxisSystem) As Variant Dim AxVri As Variant: Set AxVri = Ax Dim AryAxOri(2): Call AxVri.GetOrigin(AryAxOri) Dim AryAxXVec(2), AryAxYVec(2) Call AxVri.GetVectors(AryAxXVec, AryAxYVec) Dim Ary As Variant: Ary = Array_Push(AryAxOri, AryAxXVec) GetAxisOriVec = Array_Push(Ary, AryAxYVec) End Function '配列の値が一致するか? Private Function isArrayEqual(ByVal Ary1 As Variant, ByVal Ary2 As Variant) As Boolean isArrayEqual = False If Not IsArray(Ary1) Or Not IsArray(Ary2) Then Exit Function If Not UBound(Ary1) = UBound(Ary2) Then Exit Function Dim i& For i = 0 To UBound(Ary1) If Not Ary1(i) = Ary2(i) Then Exit Function Next isArrayEqual = True End Function '配列の連結 Private Function Array_Push(ByVal Ary1 As Variant, ByVal Ary2 As Variant) As Variant If Not IsArray(Ary1) Or Not IsArray(Ary2) Then Exit Function Dim StCount&: StCount = UBound(Ary1) ReDim Preserve Ary1(UBound(Ary1) + UBound(Ary2) + 1) Dim i& For i = StCount + 1 To UBound(Ary1) Ary1(i) = Ary2(i - StCount - 1) Next Array_Push = Ary1 End Function '座標系BrepNameの取得 ' Idx : 該当するAxisSystems.Itemのインデックス ' PlaneN0 : 0-XY,1-YZ,2-ZYの何れか Private Function GetAxisPlaneBrepName$(ByVal Idx&, ByVal PlaneNo&) If PlaneNo < 0 Or PlaneNo > 2 Then Exit Function GetAxisPlaneBrepName = "RSur:(Face:(Brp:(AxisSystem." + CStr(Idx) + ";" + CStr(PlaneNo + 1) + ");None:();Cf11:());" + _ "WithPermanentBody;WithoutBuildError;WithSelectingFeatureSupport;MFBRepVersion_CXR15)" End Function 'T型のParent取得 Private Function GetParent_Of_T(ByVal AnyOj As AnyObject, ByVal T$) As AnyObject If TypeName(AnyOj) = TypeName(AnyOj.Parent) Then Set GetParent_Of_T = Nothing Exit Function End If If TypeName(AnyOj) = T Then Set GetParent_Of_T = AnyOj Else Set GetParent_Of_T = GetParent_Of_T(AnyOj.Parent, T) End If End Function
思った以上のボリュームになってしまいましたが、直接使用するのは
最初のGetAxisPlaneRefs関数で、他はこの関数から呼び出しています。
戻り値はReference型の配列で、指定座標系の
0-XY平面 , 1-YZ平面 , 2-ZX平面
のリファレンスです。
結果的にはBrepNameでムリムリにリファレンスを取得しています。
GetAxisPlaneBrepName関数がそれに該当し、こちらの拾ってきた
GetBrepName関数の応用です。
SelectElementからReferenceの取得 - C#ATIA
これを使ったサンプルです。 対象データは、座標系2を作成し、データム化。
コンパスで適当な位置や角度に変更。 点1を始点とし、座標系2の各平面
の向きで長さ100mmの押し出し(線)を作成させます。
コードはこんな感じです。
'vba Sub GetAxisPlaneRefs_Test() '点の選択 Dim Pnt As AnyObject: Set Pnt = SelectItem("点を選択", Array("Point")) If Pnt Is Nothing Then Exit Sub '座標系の選択 Dim Ax As AxisSystem: Set Ax = SelectItem("座標系を選択", Array("AxisSystem")) If Ax Is Nothing Then Exit Sub '点のリファレンス取得 Dim Pt As Part: Set Pt = CATIA.ActiveDocument.Part Dim PntRef As Reference: Set PntRef = Pt.CreateReferenceFromObject(Pnt) '座標系平面のリファレンス取得 Dim AxPlnRefs As Variant: AxPlnRefs = GetAxisPlaneRefs(Ax) '形状セット作成 Dim HB As HybridBody: Set HB = Pt.HybridBodies.Add() '押し出し作成 Dim i& For i = 0 To UBound(AxPlnRefs) Call HB.AppendHybridShape(InitExtrude(Pt, PntRef, AxPlnRefs(i))) Next End Sub '押し出し作成 Private Function InitExtrude(ByVal Pt As Part, ByVal OriRef As Reference, _ ByVal Dir As Reference) As HybridShapeExtrude Dim Fact As HybridShapeFactory: Set Fact = Pt.HybridShapeFactory Dim Extrude As HybridShapeExtrude Set Extrude = Fact.AddNewExtrude(OriRef, 100#, 0#, Fact.AddNewDirection(Dir)) Extrude.SymmetricalExtension = 0 Call Pt.UpdateObject(Extrude) Set InitExtrude = Extrude End Function '選択 Private Function SelectItem(ByVal Msg$, ByVal Filter As Variant) As AnyObject Dim Sel As Variant: Set Sel = CATIA.ActiveDocument.Selection Sel.Clear Select Case Sel.SelectElement2(Filter, Msg, False) Case "Cancel", "Undo", "Redo" Exit Function End Select Set SelectItem = Sel.Item(1).Value Sel.Clear End Function
実行結果はこちら
試しに、座標系2のXY平面の向きに作成した線を見てみると
方向が正しく出来ています。
試しに、座標系2をコンパスでグリグリ移動させても、変更に対応している為
リファレンスは正しく取得できていると思います。
追記です。
最初にグズグズ書いている部分ですが、よく考えたら座標系の
各平面のリファレンスではなく、各軸のリファレンスでした。スイマセン。
又、今回のGetAxisPlaneRefs関数に関しては
Treeの "座標系" 以下に入っているもののみが対応しており、
形状セット等に入っている座標系に関しては、エラーとなります。
再度追記です。
上記NGのものも取得でき、シンプルなコードをこちらに記載しました。
座標系からXY,YZ,ZXの各平面のリファレンスを取得2(InternalName) - C#ATIA