こちらの続きです。
ボディ - ボディ の最短距離の測定2 - C#ATIA
もう一つの測定方法です。
スペース アナリシス ワークベンチ を利用する方法
こちらの方法では、表面積や体積・重心等も取得できる為
測定に関するコマンドに近い感覚です。
海外のサイトを見ても、わりと "上手くいかないよ" と言った書き込みを
目にするのですが、恐らく次の2点が原因のような気がします。
- Helpのサンプルコードが間違っている
AutomationManual(当方R2012です)にサンプルコードが載っているのですが
間違っています。 こちらは改行させて見やすくしたものです。
'VBA これはエラーになります Dim reference1 As Reference Set reference1 = part1.CreateReferenceFromObject(object1) Dim reference2 As Reference Set reference2 = part1.CreateReferenceFromObject(object1) Dim TheSPAWorkbench As Workbench Set TheSPAWorkbench = CATIA.ActiveDocument.GetWorkbench("SPAWorkbench") Dim TheMeasurable As Measurable Set TheMeasurable = TheSPAWorkbench.Measurable(reference1) '←ここが間違っている Dim MinimumDistance As Double MinimumDistance = TheMeasurable.GetMinimumDistance(reference2)
コメントを付けた部分、正しくは
Set TheMeasurable = TheSPAWorkbench.GetMeasurable(reference1)
です。
- ボディではリファレンスは取得できない
スペース アナリシス ワークベンチを利用する場合、測定対象要素のリファレンスが必要に
なります。 ある程度マクロの経験がある方ならわかると思うのですが、
ボディは単なる入れ物です。
GSDの点や線等に該当するのがパッドやアセンブルで、ボディは形状セット
のようなものです。
その為、ボディからはリファレンスを取得しようとするとエラーになります。
サンプルです。
'vba Sub CATMain() Dim partDocument1 As PartDocument Set partDocument1 = CATIA.ActiveDocument Dim part1 As Part Set part1 = partDocument1.Part Dim SelFilter As Variant SelFilter = Array("BiDim") Dim Ref1 As Reference Set Ref1 = SelectItem_Ref("一つ目のボディを選択して下さい : [Esc]=キャンセル", SelFilter) If Ref1 Is Nothing Then Exit Sub Dim Ref2 As Reference Set Ref2 = SelectItem_Ref("二つ目のボディを選択して下さい : [Esc]=キャンセル", SelFilter) If Ref2 Is Nothing Then Exit Sub MsgBox CStr(GetMinimumLength(part1, Ref1, Ref2)) + "mm" End Sub '選択しリファレンスを返す Private Function SelectItem_Ref(ByVal Msg$, ByVal Filter As Variant) As Reference Dim Sel As Variant: Set Sel = CATIA.ActiveDocument.Selection Dim Pt As Part: Set Pt = CATIA.ActiveDocument.Part Dim LeafBody As Body, LastFuture As AnyObject Do Sel.Clear Select Case Sel.SelectElement2(Filter, Msg, False) Case "Cancel", "Undo", "Redo" Exit Function End Select Set LeafBody = GetLeafBody(Sel.Item(1).Value) If Not LeafBody Is Nothing Then Set LastFuture = GetLastFuture(LeafBody, Pt) If LastFuture Is Nothing Then MsgBox "空のボディは測定できません!" Else Exit Do End If End If MsgBox "ボディの要素を選択して下さい!" Loop Set SelectItem_Ref = Pt.CreateReferenceFromObject(LastFuture) Sel.Clear End Function 'Treeに直接ぶら下がっているボディの取得 Private Function GetLeafBody(AnyOj As AnyObject) As Body If TypeName(AnyOj) = TypeName(AnyOj.Parent) Then Set GetLeafBody = Nothing Exit Function End If If TypeName(AnyOj.Parent) = "Bodies" Then If AnyOj.InBooleanOperation Then Set GetLeafBody = GetLeafBody(AnyOj.Parent) Else Set GetLeafBody = AnyOj End If Else Set GetLeafBody = GetLeafBody(AnyOj.Parent) End If End Function 'Shapesから最後の活動化されたフィーチャーを取得 - 要らなかったかも Private Function GetLastFuture(ByVal Shs As Shapes, ByVal Pt As Part) As AnyObject 'Set GetLastFuture = Shs.Item(Shs.Count): Exit Function 'これでもOKみたい Dim i As Long For i = Shs.Count To 1 Step -1 If Not IsEmpty(Shs.Item(i)) Then If False = Pt.IsInactive(Shs.Item(i)) Then '←Notじゃ上手く行かない Set GetLastFuture = Shs.Item(i) Exit Function End If End If Next End Function '最短距離測定 Private Function GetMinimumLength(ByVal Pt As Part, _ ByVal Ref1 As Reference, _ ByVal Ref2 As Reference) As Double GetMinimumLength = Pt.Parent.GetWorkbench("SPAWorkbench") _ .GetMeasurable(Ref1) _ .GetMinimumDistance(Ref2) End Function
基本的にボディを選択する手順は同様ですが、前回は選択したボディの
名前が必要だったのですが、今回はボディの最後のパートデザインフューチャーの
リファレンスが必要な為、リファレンスを返すようにしています。
GetLastFuture関数は、このような感じで
最後の要素が非活動化になっていた場合、"上手く取得出来ないかも"
と思ったのですが、非活動化したものでもリファレンスが取得出来、
正しい数値が取得できたので、無駄なコードです・・・。
(が、作ってしまった為、記載しておきます)
GetMaximumLength関数が最短距離を測定している部分です。
リファレンスさえ取得できていれば、かなりシンプルになります。