C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

SelectElementからReferenceの取得

こちらの3Dの文字モデリングマクロを作成していますが、中々進みません。
3Dの文字モデリングマクロ1 - C#ATIA

で、今回はこちらを進めていて出てきた問題です。
何かしら形状(点・線・面等)を作成したい場合、何らかの参照(ガイド・サポート等)が
必要なコマンドがほとんどです。(線の場合なら点、面の場合なら線 等)
GSDの要素の作成であれば、HybridShapeFactoryクラスのAddNew~メソッドに
なるのですが、これらのパラメータ(引数)は参照要素のオブジェクトそのもの
ではなく、リファレンスになっています。

マクロユーザーに選択を促す一般的な方法は、SelectionクラスのSelectElement
2~4になると思うのですが、オートメーションマニュアルを見ると選択された要素から
Referenceを取得できるような記載がされています。

試しに、スケッチで四角を描きパッドで押し出します。
f:id:kandennti:20150615162738p:plain
このBodyのエッジ部分に、GSDのスイープの "直線-基本サーフェスを使用" を使い
面直のサーフェスを作成させるマクロを作成してみました。
尚、SelectElement2を2度利用し "ガイド曲線" と "基本サーフェス" を
指定できるようにしています。
f:id:kandennti:20150615162746p:plain

'vba
Private partDocument1 As PartDocument
Private part1 As Part

Sub CATMain()
    '準備
    Set partDocument1 = CATIA.ActiveDocument
    Set part1 = partDocument1.Part
    
    'ユーザーによる線と面の選択
    Dim Filter(0) As Variant
    Filter(0) = "Edge"
    Dim LineRef As Reference
    Set LineRef = SelectItemReference(Filter, "直線を選択")
    
    Filter(0) = "Face"
    Dim FaceRef As Reference
    Set FaceRef = SelectItemReference(Filter, "面を選択")
    
    'スイープ-直線-基本サーフェスを使用 作成
    Dim hybridShapeSweepLine1 As HybridShapeSweepLine
    Set hybridShapeSweepLine1 = CreateSweepLine(LineRef, FaceRef)
    
    '形状セット作成・挿入
    Dim hybridBody1 As HybridBody
    Set hybridBody1 = part1.HybridBodies.Add
    Call hybridBody1.AppendHybridShape(hybridShapeSweepLine1)
End Sub

'SelectElement2
Private Function SelectItemReference(Filter, Msg As String) As Reference
    Dim Status As String
    Dim selection1 'As Selection
    Set selection1 = partDocument1.Selection
    With selection1
        .Clear
        Status = .SelectElement2(Filter, Msg, False)
        If Status = "Cancel" Then
            Call MsgBox("中止します")
            End
        End If
        Set SelectItemReference = .Item(1).Reference'①
        .Clear
    End With
    Set sel = Nothing
End Function

'スイープ-直線-基本サーフェスを使用
Private Function CreateSweepLine(LineRef As Reference _
                               , FaceRef As Reference) As HybridShapeSweepLine'②
    Dim hybridShapeSweepLine1 As HybridShapeSweepLine
    Set hybridShapeSweepLine1 = part1.HybridShapeFactory.AddNewSweepLine(LineRef)
    
    With hybridShapeSweepLine1
        .FirstGuideSurf = FaceRef
        .Mode = 4
        .SetFirstLengthLaw 20#, 0#, 0
        .SetSecondLengthLaw 0#, 0#, 0
        .SetAngle 1, 90#
        .SolutionNo = 0
        .SmoothActivity = False
        .GuideDeviationActivity = False
        .SetbackValue = 0.02
        .FillTwistedAreas = 1
        .C0VerticesMode = True
    End With
    Call part1.UpdateObject(hybridShapeSweepLine1)
    Set CreateSweepLine = hybridShapeSweepLine1
End Function

何となく長ったらしいのですが、①の

        Set SelectItemReference = .Item(1).Reference'①

の部分で、選択された要素のReferenceを返し、②の部分で
"ガイド曲線" と "基本サーフェス" となるReferenceを受け取ってスイープを
作成しています。 結果はこちら。
f:id:kandennti:20150615162801p:plain
特に問題なく、作成されています。

続いて、Body天面に対角線を作成してみます。
f:id:kandennti:20150615162822p:plain
今度はこの対角線を "ガイド曲線" として先程のマクロを使用すると
f:id:kandennti:20150615162829p:plain
残念エラーです。 先程は問題無く実行できたのに・・・。
色々試しているうちに、どうやらSelectElement2で取得した要素からの
Referenceの取得方法が悪い事が判りました。
そこでSelectItemReferenc関数を変更し、新たにGetBrepName関数を追加しました。

'vba
'SelectElement2
Private Function SelectItemReference(Filter, Msg As String) As Reference
    Dim Status As String
    Dim selection1 'As Selection
    
    Set selection1 = partDocument1.Selection
    With selection1
        .Clear
        Status = .SelectElement2(Filter, Msg, False)
        If Status = "Cancel" Then
            Call MsgBox("中止します")
            End
        End If
        Set SelectItemReference = part1.CreateReferenceFromBRepName( _
                GetBrepName(.Item(1).Value.Name), .Item(1).Value.Parent)'③
        .Clear
    End With
    Set sel = Nothing
End Function

'SelectElement用BrapName取得
Private Function GetBrepName(MyBRepName As String) As String
    MyBRepName = Replace(MyBRepName, "Selection_", "")
    MyBRepName = Left(MyBRepName, InStrRev(MyBRepName, "));"))
    MyBRepName = MyBRepName + ");WithPermanentBody;WithoutBuildError;WithSelectingFeatureSupport;MFBRepVersion_CXR15)"
    GetBrepName = MyBRepName
End Function

SelectItemReferenc関数自体は③部分の変更のみで、PartクラスのCreateReferenceFromBRepName
メソッドを使用しました。 そこで問題となるのがB-Rep名の取得方法ですが、素直にギブアップ。
GetBrepName関数は、海外サイトのCOEに落ちていたものを拾ってきました。
これで実行すると問題無くできました。
f:id:kandennti:20150615162839p:plain

要素を作成する際にはReferenceが必要になるのですが、"Selection.Item(1).Reference"
ではNGな場合があるようで、今回のやり方の方が良いような気がします。
又、Referenceを取得する代表的な(マクロによく記録される)方法として、
オブジェクトからリファレンスを取得する、PartクラスのCreateReferenceFromObjectメソッドがありますが
今回の場合、全く歯が立ちません。

'vba
'SelectElement2
Private Function SelectItemReference(Filter, Msg As String) As Reference
    Dim Status As String
    Dim selection1 'As Selection
    
    Set selection1 = partDocument1.Selection
    With selection1
        .Clear
        Status = .SelectElement2(Filter, Msg, False)
        If Status = "Cancel" Then
            Call MsgBox("中止します")
            End
        End If
        Set SelectItemReference = part1.CreateReferenceFromObject(.Item(1).Value)'④
        .Clear
    End With
    Set sel = Nothing
End Function

④部分でエラーとなってしまうので、"Selection.Item(1).Value" では正式なオブジェクトとして
取得できないのではなかろうかと思います。
(最近ちっともC#じゃないです・・・)