業務上欲しくなったので、久々にCATIAのマクロを作成しました。
穴あけ加工をCAMで作る際、Space-eでは穴位置となる点が
欲しかったので、こちらのマクロをかなり前に作成しました。
指定した平面から、穴の中心点を作成する1 - C#ATIA
本来であれば、3Dの形状から穴位置と深さを取得した上で
バァーっと作りたいのが本音です。面倒なので・・・。
Space-eにもそれっぽい機能がある事を薄々は知っていたの
ですが、サポートさんに相談し試したものの、打率が悪く
処理もイマイチ(ダメならダメとさっさと返してきて欲しい)
最終的には、出来上がる工程がこちらの運用とちょっと
異なる為、断念しました。
PowerMillの穴あけは、3Dの形状から穴位置と深さを取得
出来るのですが、こちらもちょっと馴染めず諦め、
Space-eで利用しやすいようCATIA側で何とかしてみようかな?
と行き着きました。(結論から書くと点を作成するだけです)
金型をモデリングする際、加工することを想定し(邪魔になるので)
穴はモデリングしない会社を知っているのですが、うちもそれに
近い状況です。
エジェクタピンの穴はモデル内に無いのですが、裏からの逃がし穴は
モデリングして有ります。
緑色が製品側で、黄色が逃がし穴です。
(穴の先端が平らなのは、穴コマンドじゃないからです。・・・僕が
モデルを作っているわけじゃないので。)
金型の裏面を指定する事で、
穴の入口、穴深さの位置、表まで貫通しきった位置
の3ヶ所の穴中心位置に点を作成します。
'vba CreateCenterPoint_ver0.0.2 using-'KCL0.0.10' '個人的に欲しかったもの Option Explicit Sub CATMain() 'ドキュメントのチェック If Not CanExecute("PartDocument") Then Exit Sub '面選択 Dim Msg$ Msg = "穴位置となる面を選択して下さい : ESCキー 終了" Dim TgtFaceElm As SelectedElement Set TgtFaceElm = KCL.SelectElement(Msg, "PlanarFace") If KCL.IsNothing(TgtFaceElm) Then Exit Sub Dim TgtFace As PlanarFace Set TgtFace = TgtFaceElm.Value 'ボディ取得 Dim TgtBody As Body Set TgtBody = KCL.GetParent_Of_T(TgtFace, "Body") If KCL.IsNothing(TgtFaceElm) Then MsgBox "ボディの面を選択する必要が有ります" Exit Sub End If 'モロモロ Dim Pt As Part Set Pt = KCL.GetParent_Of_T(TgtFace, "Part") Dim Fact As HybridShapeFactory Set Fact = Pt.HybridShapeFactory Dim Sel As Selection Set Sel = Pt.Parent.Selection Dim Dustbox As Collection '削除用 Set Dustbox = New Collection '押し出し方向 Dim Dir As HybridShapeDirection Set Dir = GetDirection(Pt, Fact, False) 'True) Dustbox.Add Dir '形状セット Dim HBdyBase As HybridBody Set HBdyBase = InitHBdy(Pt, "HolesCenter") '中心取得 Dim Cnts As Collection Set Cnts = GetCenter(Pt, Fact, Sel, TgtFaceElm.Value, HBdyBase) If KCL.IsNothing(Cnts) Then MsgBox "穴の中心は見つかりませんでした" Dustbox.Add HBdyBase GoTo SubEnd End If Dustbox.Add Cnts 'Call DumpGeo(HBdyBase, Cnts) 'debug '直線 Dim LinRefs As Collection Set LinRefs = GetLineRefs(Pt, Fact, Dir, Cnts, 10000#) Dustbox.Add LinRefs 'Call DumpGeo(HBdyBase, LinRefs) 'debug '交差 Dim IntRefs As Collection Set IntRefs = GetIntersectRefs(Pt, Fact, TgtBody, LinRefs) Dustbox.Add IntRefs 'Call DumpGeo(HBdyBase, IntRefs) 'debug '交差チェック If Not IsInValue(IntRefs) Then MsgBox "穴の中心は見つかりませんでした" Dustbox.Add HBdyBase GoTo SubEnd End If '直線の終点 Dim FarRefs As Collection Set FarRefs = GetPntFarRefs(Pt, Fact, LinRefs) Dustbox.Add FarRefs 'Call DumpGeo(HBdyBase, FarRefs) 'debug '近傍 Dim Nears As Collection Set Nears = GetNear(Pt, Fact, IntRefs, Cnts) 'Call DumpGeo(HBdyBase, Nears) 'debug '遠方 Dim Fars As Collection Set Fars = GetNear(Pt, Fact, IntRefs, FarRefs) 'Call DumpGeo(HBdyBase, Fars) 'debug '作成 Call ToHybridBody(HBdyBase, Pt, Fact, IntRefs, Cnts, Nears, Fars) Pt.UpdateObject HBdyBase SubEnd: 'ゴミ処理 Call Disposal(Dustbox, Fact, Sel) MsgBox "Done" End Sub '全てNothingチェック Private Function IsInValue(ByVal Lst As Collection) As Boolean IsInValue = True Dim v As Variant For Each v In Lst If Not (v Is Nothing) Then Exit Function Next IsInValue = False End Function 'ゴミ処理 Private Sub Disposal(ByRef Lst, _ ByVal Fact As HybridShapeFactory, _ ByVal Sel As Selection) On Error Resume Next Dim v1, v2 For Each v1 In Lst Select Case TypeName(v1) Case "Collection" For Each v2 In v1 Fact.DeleteObjectForDatum v2 Next Case "HybridBody" Call DelItem(Sel, v1) Case Else Fact.DeleteObjectForDatum v1 End Select Next On Error GoTo 0 End Sub '削除 Private Sub DelItem(ByVal Sel As Selection, ByVal itm As Variant) Dim i& CATIA.HSOSynchronized = False With Sel .Clear .Add itm .Delete End With CATIA.HSOSynchronized = True End Sub '階層作って形状セットに代入 Private Sub ToHybridBody(ByVal Hbdy As HybridBody, _ ByVal Pt As Part, _ ByVal Fact As HybridShapeFactory, _ ByVal IntRefs As Collection, _ ByVal Btms As Collection, _ ByVal Mids As Collection, _ ByVal Tops As Collection) Dim TopHbdy As HybridBody: Set TopHbdy = InitHBdy(Hbdy, "Top") Dim MidHbdy As HybridBody: Set MidHbdy = InitHBdy(Hbdy, "Mid") Dim BtmHbdy As HybridBody: Set BtmHbdy = InitHBdy(Hbdy, "Btm") Dim i& For i = 1 To IntRefs.Count If KCL.IsNothing(IntRefs.Item(i)) Then GoTo Continue_For TopHbdy.AppendHybridShape Tops.Item(i) MidHbdy.AppendHybridShape Mids.Item(i) BtmHbdy.AppendHybridShape Fact.AddNewPointDatum(Btms.Item(i)) Continue_For: Next End Sub '形状セット Private Function InitHBdy(ByVal Parent, ByVal Name$) Dim Hb As HybridBody Set Hb = Parent.HybridBodies.Add() Hb.Name = Name Set InitHBdy = Hb End Function '近傍 Private Function GetNear(ByVal Pt As Part, _ ByVal Fact As HybridShapeFactory, _ ByVal IntRefs As Collection, _ ByVal PntRefs As Collection) As Collection Dim i& Dim Near As HybridShapeNear, Ref As Reference, Pnt As AnyObject Dim Nears As Collection: Set Nears = New Collection For i = 1 To IntRefs.Count If KCL.IsNothing(IntRefs.Item(i)) Then Nears.Add Nothing GoTo Continue_For End If Set Near = Fact.AddNewNear(IntRefs.Item(i), PntRefs.Item(i)) Pt.UpdateObject Near Set Ref = Pt.CreateReferenceFromGeometry(Near) Set Pnt = Fact.AddNewPointDatum(Ref) Nears.Add Pnt Continue_For: Next Set GetNear = Nears End Function 'AddNewFarが無い為対策用の点 Private Function GetPntFarRefs(ByVal Pt As Part, _ ByVal Fact As HybridShapeFactory, _ ByVal LinRefs As Collection) As Collection Dim Pnt As HybridShapePointOnCurve, Ref As Reference Dim FarRefs As Collection: Set FarRefs = New Collection For Each Ref In LinRefs Set Pnt = Fact.AddNewPointOnCurveFromPercent(Ref, 1#, False) Pt.UpdateObject Pnt FarRefs.Add Pt.CreateReferenceFromGeometry(Pnt) Next Set GetPntFarRefs = FarRefs End Function '交差 Private Function GetIntersectRefs(ByVal Pt As Part, _ ByVal Fact As HybridShapeFactory, _ ByVal Bdy As Body, _ ByVal LinRefs As Collection) As Collection Dim BdyRef As Reference Set BdyRef = Pt.CreateReferenceFromGeometry(Bdy) On Error Resume Next Dim LinRef As AnyObject, Intsect As HybridShapeIntersection Dim IntRefs As Collection: Set IntRefs = New Collection For Each LinRef In LinRefs Set Intsect = Fact.AddNewIntersection(BdyRef, LinRef) Intsect.PointType = 0 Pt.UpdateObject Intsect If Err.Number = 0 Then IntRefs.Add Pt.CreateReferenceFromGeometry(Intsect) Else IntRefs.Add Nothing 'Fact.DeleteObjectForDatum Intsect'これNG End If Next On Error GoTo 0 Set GetIntersectRefs = IntRefs End Function '直線 Private Function GetLineRefs(ByVal Pt As Part, _ ByVal Fact As HybridShapeFactory, _ ByVal Dir As HybridShapeDirection, _ ByVal Pnts As Collection, _ ByVal Leng As Double) As Collection Dim Pnt As AnyObject, PntRef As Reference Dim LineRefs As Collection: Set LineRefs = New Collection Dim Lin As HybridShapeLinePtDir, LinRef As Reference For Each Pnt In Pnts Set PntRef = Pt.CreateReferenceFromGeometry(Pnt) Set Lin = Fact.AddNewLinePtDir(PntRef, Dir, 0#, Leng, False) Pt.UpdateObject Lin LineRefs.Add Pt.CreateReferenceFromGeometry(Lin) Next Set GetLineRefs = LineRefs End Function '押し出し方向 'SelectFG : True-ユーザー指定座標系 False-PartのXYPlane Private Function GetDirection(ByVal Pt As Part, _ ByVal Fact As HybridShapeFactory, _ ByVal SelectFG As Boolean) As HybridShapeDirection Set GetDirection = Nothing Dim Ref As Reference If SelectFG Then Dim Msg$ Msg = "チェック方向をZ軸とする座標系を選択して下さい : ESCキー 終了" Dim Axis As AxisSystem Set Axis = KCL.SelectItem(Msg, "AxisSystem") If KCL.IsNothing(Axis) Then Exit Function Set Ref = Axis.ZAxisDirection Else Set Ref = Pt.CreateReferenceFromGeometry(Pt.OriginElements.PlaneXY) End If Set GetDirection = Fact.AddNewDirection(Ref) End Function '中心点 Private Function GetCenter(ByVal Pt As Part, _ ByVal Fact As HybridShapeFactory, _ ByVal Sel As Selection, _ ByVal FaceRef, _ ByVal Hbdy As HybridBody) As Collection Set GetCenter = Nothing Dim Ext As HybridShapeExtract Set Ext = Fact.AddNewExtract(FaceRef) With Ext .PropagationType = 3 .ComplementaryExtract = False .IsFederated = False End With Call Pt.UpdateObject(Ext) Hbdy.AppendHybridShape Ext CATIA.HSOSynchronized = False With Sel .Clear .Add Ext .Search "Topology.CGMEdge,sel" End With Dim i&, Edges As Collection Set Edges = New Collection For i = 1 To Sel.Count Edges.Add Sel.Item(i) Next Sel.Clear CATIA.HSOSynchronized = True If Edges.Count < 1 Then GoTo Exit_Func On Error Resume Next Dim EgElm As AnyObject, Cnt As AnyObject, Pnt As AnyObject, Ref As Reference Dim Pnts As Collection: Set Pnts = New Collection For Each EgElm In Edges Set Cnt = Fact.AddNewPointCenter(EgElm.Reference) Pt.UpdateObject Cnt If KCL.IsNothing(Cnt) Then GoTo Continue_ForEach Set Ref = Pt.CreateReferenceFromGeometry(Cnt) Set Pnt = Fact.AddNewPointDatum(Ref) Pt.UpdateObject Pnt Fact.DeleteObjectForDatum Cnt If KCL.IsNothing(Pnt) Then GoTo Continue_ForEach If Not Lst_Contains(Pnts, Pnt) Then Pnts.Add Pnt Continue_ForEach: Next On Error GoTo 0 If Pnts.Count < 1 Then GoTo Exit_Func Set GetCenter = Pnts Exit_Func: Fact.DeleteObjectForDatum Ext End Function '重複チェック Private Function Lst_Contains(ByVal Lst As Collection, _ ByVal Value As AnyObject) As Boolean Lst_Contains = True Dim itm As AnyObject For Each itm In Lst If itm Is Value Then Exit Function Next Lst_Contains = False End Function 'デバッグ用 Private Sub DumpGeo(ByVal Hbdy As HybridBody, ByVal Lst As Collection) Dim Oj As AnyObject If TypeName(Lst.Item(1)) = "Reference" Then Dim Fact As HybridShapeFactory Set Fact = KCL.GetParent_Of_T(Hbdy, "Part").HybridShapeFactory For Each Oj In Lst If Not KCL.IsNothing(Oj) Then Hbdy.AppendHybridShape Fact.GSMGetObjectFromReference(Oj) End If Next Else For Each Oj In Lst If Not KCL.IsNothing(Oj) Then Hbdy.AppendHybridShape Oj End If Next End If End Sub
うっかりしていましたが、貫通穴には点が作成されません。
こんな感じです。
実は、交差を処理している辺りに一時的に作成したものが
上手く削除しきれていない為、CATDUAのクリーン実行すると
幾つもゴミを処理されます。(イマイチです)
他人には役立つとは思えませんが。