こちらの続きです。
指定した要素の周囲要素を取得する2 - C#ATIA
前回は無意味だったので、結局素直に距離を測り判断します。
リフレームオンと検索でHitした要素だけの距離測定のため、全部の要素に
対して行うより短時間で済むはずです。
'vba sample_Get_Outskirt_Items ver0.03 using-'KCL' '指定した要素(GSD)の周囲の要素を取得 Option Explicit Const NearLength = 2# '周囲とする距離 Sub CATMain() 'クリア Dim Doc As Document: Set Doc = CATIA.ActiveDocument Dim Sel As Selection: Set Sel = Doc.Selection Call Sel.Clear '言語別 "リフレーム オン" コマンド文字取得 Dim ReframeOnCommand$ ReframeOnCommand = GetReframeOnString() If ReframeOnCommand = vbNullString Then Exit Sub '選択 Dim Msg$: Msg = "GSD要素を選択して下さい : ESCキー 終了" Dim HShape As SelectedElement ' HybridShape Set HShape = KCL.SelectElement(Msg, Array("HybridShape")) If KCL.IsNothing(HShape) Then Exit Sub 'スタートView Dim StartScene As Variant: StartScene = GetScene3D(GetViewPnt3D()) 'リフレーム オン の為の再選択 Call Sel.Add(HShape.Value) Call CATIA.StartCommand(ReframeOnCommand) 'リフレーム オンし終わるまでの時間稼ぎ If MsgBox("これの周辺要素を取得しますか?", vbYesNo) = vbNo Then Exit Sub 'リフレーム オン 要素取得 Dim Items As Variant: Items = GetSearchItems() Debug.Print "Search:" + CStr(Sel.Count2) '指定距離外要素除外 Call RemoveSelItem(Sel, GetFarItemsIdx(HShape, Items, NearLength)) Debug.Print "Remove:" + CStr(Sel.Count2) '表示を戻す Call UpdateScene(StartScene) MsgBox CStr(Sel.Count2) + "個選択しました" End Sub '指定距離より遠い要素のインデックス取得 Private Function GetFarItemsIdx(ByRef SelElm As SelectedElement, ByRef AryElms As Variant, ByVal Lng#) As Collection Dim Ref As Reference: Set Ref = SelElm.Reference Dim SearchRef() As Variant: ReDim SearchRef(UBound(AryElms)) Dim i& For i = 1 To UBound(AryElms) Set SearchRef(i) = AryElms(i).Reference Next Dim Pt As Part: Set Pt = SelElm.Document.Part Dim Mes As Measurable Set Mes = Pt.Parent.GetWorkbench("SPAWorkbench").GetMeasurable(Ref) Dim FarItems As Collection: Set FarItems = New Collection For i = UBound(AryElms) To 1 Step -1 If Mes.GetMinimumDistance(SearchRef(i)) > Lng Then Call FarItems.Add(i) End If Next Set GetFarItemsIdx = FarItems End Function 'リストのインデックスをを元に選択解除する Private Sub RemoveSelItem(ByRef Sel As Selection, ByVal List As Collection) Dim Idx CATIA.HSOSynchronized = False For Each Idx In List Sel.Remove2 Idx Next CATIA.HSOSynchronized = True End Sub '検索の "画面上の表示" で取得 Private Function GetSearchItems() As Variant Dim Sel As Selection: Set Sel = CATIA.ActiveDocument.Selection CATIA.HSOSynchronized = False Sel.Clear Sel.Search "Type=*,scr" Dim Items() As Variant: ReDim Items(Sel.Count2) Dim i& For i = 1 To Sel.Count2 Set Items(i) = Sel.Item2(i) '.Value Next CATIA.HSOSynchronized = True GetSearchItems = Items End Function '言語別リフレーム オンコマンド文字取得 Private Function GetReframeOnString() As String Select Case KCL.GetLanguage() Case "ja" GetReframeOnString = "リフレーム オン" Case "en" GetReframeOnString = "Reframe On" Case Else '日本語でメッセージ出して意味が有るのか? MsgBox "言語設定が、日本語か英語のみしか対応していません" End Select End Function '表示のUpdate Private Sub UpdateScene(ByVal Scene As Variant) Dim Viewer As Viewer3D: Set Viewer = CATIA.ActiveWindow.ActiveViewer Dim VPnt3D As Variant 'Viewpoint3D Set VPnt3D = Viewer.Viewpoint3D Dim Ary As Variant Ary = GetRangeAry(Scene, 0, 2) Call VPnt3D.PutOrigin(Ary) Ary = GetRangeAry(Scene, 3, 5) Call VPnt3D.PutSightDirection(Ary) Ary = GetRangeAry(Scene, 6, 8) Call VPnt3D.PutUpDirection(Ary) VPnt3D.FieldOfView = Scene(9) VPnt3D.FocusDistance = Scene(10) Call Viewer.Update End Sub 'Viewpoint3Dからシーン取得 Private Function GetScene3D(ByVal ViewPnt3D As Viewpoint3D) As Variant Dim vp As Variant: Set vp = ViewPnt3D Dim SceneAry As Variant Dim origin(2) As Variant: Call vp.GetOrigin(origin) Dim sight(2) As Variant: Call vp.GetSightDirection(sight) SceneAry = JoinAry(origin, sight) Dim up(2) As Variant: Call vp.GetUpDirection(up) SceneAry = JoinAry(SceneAry, up) Dim FieldOfView(0) As Variant: FieldOfView(0) = vp.FieldOfView SceneAry = JoinAry(SceneAry, FieldOfView) Dim FocusDist(0) As Variant: FocusDist(0) = vp.FocusDistance GetScene3D = JoinAry(SceneAry, FocusDist) End Function '現状の視点取得 Private Function GetViewPnt3D() As Viewpoint3D Set GetViewPnt3D = CATIA.ActiveWindow.ActiveViewer.Viewpoint3D End Function
先頭の方にある "NearLength" 定数が "周囲"と判断する距離です。
適切な値に設定してください。
実際試した感じですが、
適当なワイヤーなデータの赤のラインを指定してみます。
左が最初に作成したコードの実行結果で、右が今回の実行結果です。
より "周囲の要素" のみの結果になっているかと思います。