C#ATIA

↑タイトル詐欺 主にCATIA V5 の VBA

形状セット内の線の長さを表示する

「形状セット内の、線のみの長さを取得したい」と言う質問を頂きました。
早速コードです。

(「選択」部分付近のコードが正しくなかった為、修正しました)

'vba GetCurvesLength
Sub CATMain()
    '選択
    Dim Msg$: Msg = "形状セットを選択して下さい"
    Dim SelItem As SelectedElement: Set SelItem = SelectItem(Msg, Array("HybridBody"))
    If IsNothing(SelItem) Then Exit Sub
    Dim HBody As HybridBody: Set HBody = SelItem.Value
    
    'Partの取得
    Dim Pt As Part: Set Pt = GetParent_Of_T(HBody, "Part")
    
    'HybridShapeFactory取得 - 形状判定の為必要
    Dim Fact As HybridShapeFactory: Set Fact = Pt.HybridShapeFactory
    
    '形状セット内の直線・円弧・スプラインを取得
    Dim HSps As HybridShapes: Set HSps = HBody.HybridBodies
    Dim Hsp As HybridShape
    Dim CurveRefs As New Collection
    Dim Ref As Reference
    Dim GeoType&
    For Each Hsp In HSps
        Set Ref = Pt.CreateReferenceFromObject(Hsp)
        GeoType = Fact.GetGeometricalFeatureType(Ref)
        'AutomationManualの記述が間違えやすいが、
        '2-Curve , 3-Line , 4-Circle になる
        If GeoType >= 2 And GeoType <= 4 Then
            Call CurveRefs.Add(Ref)
        End If
    Next
    
    '長さ測定
    Dim CurveLeng#
    Msg$ = vbNullString
    For Each Ref In CurveRefs
        CurveLeng = Pt.Parent.GetWorkbench("SPAWorkbench") _
                             .GetMeasurable(Ref).Length
        Msg$ = Msg$ + Ref.DisplayName + " : " + CStr(CurveLeng) + " mm" + vbNewLine
    Next
    
    '結果
    MsgBox Msg
End Sub

'選択
''' @param:Msg-メッセージ
''' @param:Filter-選択フィルター(指定無し時AnyObject)
''' @return:AnyObject
Public Function SelectItem(ByVal Msg$, _
                           Optional ByVal Filter As Variant = Empty) _
                           As SelectedElement
    If IsEmpty(Filter) Then Filter = Array("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)
    Sel.Clear
End Function

'Nothing 書き方に統一感が無い為
''' @param:OJ-Variant(Of Object)
''' @return:Boolean
Public Function IsNothing(ByVal Oj As Variant) As Boolean
    IsNothing = Oj Is Nothing
End Function

'T型のParent取得 Nameでのチェックも必要
''' @param:AOj-AnyObject
''' @param:T-String
''' @return:AnyObject
Public Function GetParent_Of_T(ByVal AOj As AnyObject, ByVal T$) As AnyObject
    If TypeName(AOj) = TypeName(AOj.Parent) And _
       AOj.Name = AOj.Parent.Name Then
        Set GetParent_Of_T = Nothing
        Exit Function
    End If
    If TypeName(AOj) = T Then
        Set GetParent_Of_T = AOj
    Else
        Set GetParent_Of_T = GetParent_Of_T(AOj.Parent, T)
    End If
End Function

「CATMain」以外は、作りかかっている非常に個人的なCATVBA用のライブラリから
抜き出したものです。


形状セット内から線(直線・円弧・スプライン)を抜き出す方法ですが、
HybridShapeFactoryクラスのGetGeometricalFeatureType関数を利用します。
(戻り値については、昔からAutomationManualの記載が非常に悪く、
 勘違いしやすいので注意してください。)
TypeName関数で変数の型名が取得できるのですが、それでは本当に
線なのか判断しきれない場合が有ります。
例えば、GSDの交差コマンドや極値コマンドの場合、結果の状態によっては
点・線・面の何れかになる可能性があり、型名だけでは判断出来ません。
GetGeometricalFeatureType関数であれば、出来上がった結果に応じた
タイプを返してくれます。


線の長さ取得については、こちらと同様に2つ方法が有ります。
ボディ - ボディ の最短距離の測定1 - C#ATIA
ボディ - ボディ の最短距離の測定3 - C#ATIA


最後に不要な式を削除する手間を考え、サンプルでは「SPAWorkbench」の
方法で測定しています。


試した感じはこの様になってます。
f:id:kandennti:20160524162743p:plain
「パラメータ」の'長さ.1'は手動で式を使って長さを測定したもので
マクロとは無関係です。

ツリーの'交差.1'は ボディ-平面 の交差をサーフェスとして取得したもの
なので、MsgBoxには表示されていません。

'交差.2'はXY平面とYZ平面の交差です。CATIAの無限直線は、
20000000mmの扱いになるようですね。