スケッチ内にあるマーク(Mark)の座標を取得する|CATIAマクロの作成方法
今回の記事は「お問い合わせ」でいただいた内容です。
送って頂いた内容は以下のようなマクロです。
まず自分がやりたいことを説明します。
①Bodyの中にHole を作ります
②Plane上にpointを数点作り、それらをsketchに投影してUserPatternでHoleを複製します
③DrawingTableにX,Y座標とHoleの直径と深さを出力するマクロを作りたいと思っています。
ここから質問なのですが、UserPatternで選択している 複数pointのX,Y座標を取得することはできるのでしょうか 。色々と調べてUserPattern(object)のFea tureToLocatePositions を使いましたが複数point情報は取得することはできませんでした。sketch(object)のGeometricElementsでplane上のpointまで辿り着けるかと思いましたがmark.1というところで行き止まりになってしまって独学では限界が来てしまいました。
CATIA VBAで座標を取得するには多くの場合「GetCoordinates」というメソッドを使います。
このメソッドは「Point」や「Point2D」のような”点”のオブジェクトにしか用意されていません。しかしながら今回取得したいマーク(Mark)はオブジェクトタイプが「Geometry2D」のためこのメソッドが用意されていません。
こういった場合の対処法はいくつかありますが、ここではマークのオブジェクトタイプを「Geometry2D」から「Point2D」に変換して「GetCoordinatesメソッド」で座標を取得していきます。(ほかにもMeasurableオブジェクトを使っていくつかの値を取得し、計算で座標を導くこともできると思います)
マクロの機能
今回作成したのはスケッチ内にある「マーク(Mark)」の座標を取得するマクロです。上画像の場合、「投影.1~4」の4つの点の”スケッチ平面上”でのXY座標をすべて取得します。
具体的な機能は以下のとおりです。
(スケッチ内には投影した点のみしか存在しない前提)
・座標はスケッチ平面上でのX,Y座標
・コード内の「coords」コレクション内に全座標が格納される
今回のマクロは最終的に結果はイミディエイトウィンドウ上に表示されます。
ドキュメント内で作業は行いますが最終的にドキュメント内には何も残らないので、イミディエイトウィンドウもしくはデバックモードで「coords」コレクション内の中身を確認して下さい。
サンプルコード
マクロのコードは以下のとおりです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
Option Explicit Sub CATMain() 'アクティブドキュメント/Selection定義 If TypeName(CATIA.ActiveDocument) <> "PartDocument" Then MsgBox "このマクロはPartDocument専用です。" & vbLf & _ "アセンブリーワークベンチに切り替えて実行してください。" Exit Sub End If Dim doc As PartDocument: Set doc = CATIA.ActiveDocument Dim sel As Variant: Set sel = doc.Selection sel.Clear 'ユーザーパターン選択 Dim filter: filter = Array("UserPattern") Dim msg As String: msg = "ユーザーパターンを選択して下さい。" Dim status As String status = sel.SelectElement2(filter, msg, False) If status <> "Normal" Then MsgBox "キャンセルしました。" Exit Sub End If 'ユーザーパターン取得 Dim up As UserPattern Set up = sel.Item(1).Value 'ユーザーパターン内のスケッチを取得 Dim sk As Sketch Set sk = up.FeatureToLocatePositions 'スケッチを複製 With sel .Clear .Add sk 'ユーザーパターン内のスケッチを選択 .Copy 'スケッチをコピー .Clear .Add up.Parent 'ユーザーパターンの親ボディーを選択 .Paste 'スケッチをボディーに貼り付け End With Dim skIso As Sketch Set skIso = sel.Item(1).Value skIso.Name = "座標取得用スケッチ(残っていたら削除してください)" '複製したスケッチを分離(Isolate) CATIA.StartCommand ("分離") '英語環境:「Isolate」 '分離したスケッチから点の座標をすべて取得 Dim coords As Collection Set coords = New Collection Dim coord() Dim p 'As Point2D For Each p In skIso.GeometricElements If TypeName(p) = "Point2D" Then ReDim coord(1) Call p.GetCoordinates(coord) coords.Add coord(0) coords.Add coord(1) End If Next p '座標取得用のスケッチを削除 sel.Add skIso sel.Delete 'coords内の座標を使った処理 Dim i As Long For i = 1 To coords.Count Step 2 Debug.Print (i + 1) / 2 & "番目 MarkのX座標: " & coords.Item(i) Debug.Print (i + 1) / 2 & "番目 MarkのY座標: " & coords.Item(i + 1) Next i End Sub |
コード解説
アクティブドキュメント/Selection定義
1 2 3 4 5 6 7 8 9 10 |
'アクティブドキュメント/Selection定義 If TypeName(CATIA.ActiveDocument) <> "PartDocument" Then MsgBox "このマクロはPartDocument専用です。" & vbLf & _ "アセンブリーワークベンチに切り替えて実行してください。" Exit Sub End If Dim doc As PartDocument: Set doc = CATIA.ActiveDocument Dim sel As Variant: Set sel = doc.Selection sel.Clear |
まずはじめにアクティブドキュメントを定義をします。
今回のマクロはCATPartのみ有効なものなので、アクティブドキュメントがCATPart以外の場合はTypeName関数を使った条件分岐でマクロを終了するようにしています。つまり、アクティブドキュメントがCATPartの場合のみ変数「doc」にアクティブドキュメントを代入し、マクロの処理を続けます。
アクティブドキュメントが定義出来たら、あわせて「Selectionオブジェクト」も定義します。
ユーザーパターン/スケッチ選択
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
'ユーザーパターン選択 Dim filter: filter = Array("UserPattern") Dim msg As String: msg = "ユーザーパターンを選択して下さい。" Dim status As String status = sel.SelectElement2(filter, msg, False) If status <> "Normal" Then MsgBox "キャンセルしました。" Exit Sub End If 'ユーザーパターン取得 Dim up As UserPattern Set up = sel.Item(1).Value 'ユーザーパターン内のスケッチを取得 Dim sk As Sketch Set sk = up.FeatureToLocatePositions |
つぎに「SelectElement2メソッド」を使ってユーザーが選択した任意の「ユーザーパターン」を取得します。
ユーザーパターンを取得したら「UserPatternオブジェクト」の「FeatureToLocatePositionsプロパティ」を使ってユーザーパターン内にあるスケッチを取得します。
座標取得用のスケッチを作成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
'スケッチを複製 With sel .Clear .Add sk 'ユーザーパターン内のスケッチを選択 .Copy 'スケッチをコピー .Clear .Add up.Parent 'ユーザーパターンの親ボディーを選択 .Paste 'スケッチをボディーに貼り付け End With Dim skIso As Sketch Set skIso = sel.Item(1).Value skIso.Name = "座標取得用スケッチ(残っていたら削除してください)" '複製したスケッチを分離(Isolate) CATIA.StartCommand ("分離") '英語環境:「Isolate」 |
次に座標取得用のスケッチを作成します。
作成方法は先ほど取得したスケッチを複製して”分離(Isolate)”するだけです。
スケッチを分離すると下画像のように「エッジを使用」内がすべて”形状”として変換されます。
これにより分離したスケッチ内の点を取得すると「Point2D」として取得することができます。
つまり冒頭でいっていた「GetCoordinatesメソッド」で座標を取得することが可能になった訳です。
分離したスケッチから点の座標をすべて取得
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
'分離したスケッチから点の座標をすべて取得 Dim coords As Collection Set coords = New Collection Dim coord() Dim p 'As Point2D For Each p In skIso.GeometricElements If TypeName(p) = "Point2D" Then ReDim coord(1) Call p.GetCoordinates(coord) coords.Add coord(0) coords.Add coord(1) End If Next p '座標取得用のスケッチを削除 sel.Add skIso sel.Delete |
最後に先ほど作成した座標取得用のスケッチを使い、点の座標をすべて取得していきます。
点の座標は「Point2Dオブジェクト」の「GetCoordinatesメソッド」を使います。
上記コードでは「coord(0)」がX座標、「coord(1)」がY座標となっています。
これをまとめて「coords」というコレクションに順に格納していきます。
これにより任意の点座標をいつでも呼び出せることが可能になります。
ちなみにcoordsコレクションの中身は下記のようになっています。
coords.Item(2) = 1番目の点のY座標
coords.Item(3) = 2番目の点のX座標
coords.Item(4) = 2番目の点のY座標
: :
coords.Item(i) = ((i + 1) / 2)番目の点のX座標
coords.Item(i+1) = ((i + 1) / 2)番目の点のY座標
分離したスケッチから点の座標をすべて取得
1 2 3 4 5 6 |
'coords内の座標を使った処理 Dim i As Long For i = 1 To coords.Count Step 2 Debug.Print (i + 1) / 2 & "番目 MarkのX座標: " & coords.Item(i) Debug.Print (i + 1) / 2 & "番目 MarkのY座標: " & coords.Item(i + 1) Next i |
座標の取得はできたので、あとはその座標を使った処理を書くだけです。
今回はcoordsコレクション内に格納されている座標をイミディエイトウィンドウに出力するだけの簡単な処理を行っています。
あとは「Debug.Print」を任意の処理に書き換えてください。
(今回のお問い合わせ内容でいえばDrawingTableへの出力のように)
まとめ
今回はスケッチ内にあるマーク(Mark)の座標を取得する方法についての内容でした。
「CATIA.StartCommand」は少し不安定なところもあるのであまり使いたくはありませんが、「Point2D」に変換するための妥協策です。(他にもいい案はあるかもしれません)
今回重要なのは「マーク(Mark)」をいかにしてPointに変換するかです。
マクロの答えは1つではないので、その他の方法もまだ眠っていると思います。
いろいろ試行錯誤し知識を得て、様々な方法を編み出してみてください。
(冒頭でもいっていたMeasurableオブジェクトを使うのも1つの手ですが、スケッチ平面が基準の座標取得と考えるとあまり得策ではないです)