CATDrawing内の長穴に対して軸線を作成するマクロ|CATIAマクロの作成方法

今回の記事はお問い合わせよりいただいた内容です。
送って頂いた内容は以下のようなマクロです。

CATDrawing マクロで長穴に“中心線”を作図することは可能でしょうか?

本来はCATPartやCATProductから投影した長穴に対して軸線を作成したいというご要望でしたが、投影された形状はマクロでは「DrawingView」として取得されてしまうためうまくマクロが作成できません。そこでここではCATDrawing内で作成された形状である「長穴」に対して軸線を作成するマクロを紹介していきます。

軸線は中高で学習した直線や座標、2点間の距離などの公式を使い計算によって求めています。あまり覚えていないという方は、中高校生時代の数学の教科書や数学のサイトなどを見ながら本ページを見ることをオススメします。

 

マクロの機能

今回作成したマクロはCATDrawing内で作成された形状である「長穴」に対して軸線を作成するマクロです。長穴の2つの円弧部を選択することで、その長穴の軸線を作成します。

具体的な機能は以下のとおりです。

 icon-wrench マクロの機能まとめ ・長穴の2つの円弧部を選択することで、その長穴の軸線を作成する
・長穴はCATDrawing内で作成された形状に限る(投影形状は不可)
・軸線は長穴のあるビュー内に作成される

 

サンプルコード

マクロのコードは以下のとおりです。

Option Explicit

Dim vw As DrawingView   'アクティブビュー
Dim r As Double         '円弧のR値
'――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
Sub CATMain()

 'アクティブドキュメント定義
    If TypeName(CATIA.ActiveDocument) <> "DrawingDocument" Then
       MsgBox "このマクロはDrawingDocument専用です。" & vbLf & _
              "CATDrawingに切り替えて実行してください。"
       Exit Sub
    End If
    
    Dim doc As DrawingDocument: Set doc = CATIA.ActiveDocument
    Dim sel As Selection:       Set sel = doc.Selection
    Dim vps As VisPropertySet:  Set vps = sel.VisProperties


 '長穴円弧部の中心座標取得
    Dim arc1_coord()
    arc1_coord = GetSelArcCoord("長穴の円弧(1つ目)を選択して下さい。")

    Dim arc2_coord()
    arc2_coord = GetSelArcCoord("長穴の円弧(2つ目)を選択して下さい。")
    
    
 '軸線延長の指定
    Dim L As Double
    L = r / 2 + r       
    
    
 '軸線1 作成
    vw.Activate
    Dim fac2d As Factory2D:     Set fac2d = vw.Factory2D
    
    Dim coord1() As Double, coord2() As Double, ctr_coord(1) As Double
    Dim x1 As Double, y1 As Double, x2 As Double, y2 As Double
    
    x1 = arc1_coord(0)
    y1 = arc1_coord(1)
    x2 = arc2_coord(0)
    y2 = arc2_coord(1)
    
    ctr_coord(0) = (x1 + x2) / 2
    ctr_coord(1) = (y1 + y2) / 2
    
    coord1 = ExtendLineCoord(x1, y1, x2, y2, L)
    coord2 = ExtendLineCoord(x2, y2, x1, y1, L)
    
    Dim line1 As Line2D
    Set line1 = fac2d.CreateLine(coord1(0), coord1(1), coord2(0), coord2(1))
    
    
 '軸線2 作成
    Dim norm_line()
    norm_line = Normal_Line(ctr_coord(0), ctr_coord(1), x2, y2)
    
    Dim coord3() As Double, coord4() As Double
    Dim x3 As Double, y3 As Double
    
    If norm_line(0) = 0 Then        '長穴がY軸方向の場合
    
        ReDim coord3(1)
        ReDim coord4(1)
        coord3(0) = ctr_coord(0) + L
        coord3(1) = norm_line(1)
        coord4(0) = ctr_coord(0) - L
        coord4(1) = norm_line(1)
    
    ElseIf norm_line(1) = 0 Then    '長穴がX軸方向の場合
    
        ReDim coord3(1)
        ReDim coord4(1)
        coord3(0) = norm_line(0)
        coord3(1) = ctr_coord(1) + L
        coord4(0) = norm_line(0)
        coord4(1) = ctr_coord(1) - L

    Else                            '長穴が傾いている場合
    
        x3 = ctr_coord(0) + 0.1
        y3 = norm_line(0) * x3 + norm_line(1)
        coord3 = ExtendLineCoord(ctr_coord(0), ctr_coord(1), x3, y3, L)
        
        x3 = ctr_coord(0) - 0.1
        y3 = norm_line(0) * x3 + norm_line(1)
        coord4 = ExtendLineCoord(ctr_coord(0), ctr_coord(1), x3, y3, L)
    
    End If

    Dim line2 As Line2D
    Set line2 = fac2d.CreateLine(coord3(0), coord3(1), coord4(0), coord4(1))
    
    
 '軸線の線種変更
    sel.Add line1
    sel.Add line2
    vps.SetRealLineType 4, 1
    
    
End Sub
'――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
Private Function GetSelArcCoord(msg As String) As Variant()
    
    Dim sel 'As Selection
    Set sel = CATIA.ActiveDocument.Selection
    
    Dim filter():       filter = Array("Circle2D")
    Dim status As String
    
    status = sel.SelectElement2(filter, msg, False)
    If status <> "Normal" Then
        MsgBox "キャンセルしました。"
        End
    End If

    Dim arc 'As Circle2D
    Set arc = sel.Item(1).Value
    sel.Clear
    
    r = arc.Radius
    
    Dim arc_coord(1)
    arc.GetCenter arc_coord

    Dim obj As AnyObject:   Set obj = arc
    Do
        Set obj = obj.Parent
    Loop Until TypeName(obj) = "DrawingView"
    
    Set vw = obj
    
    GetSelArcCoord = arc_coord()

End Function
'――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
Private Function ExtendLineCoord(ByVal x1 As Double, ByVal y1 As Double, _
                                 ByVal x2 As Double, ByVal y2 As Double, _
                                 ByVal L As Double) As Double()

    Dim coord(1) As Double
    
    Dim xy As Double
    xy = Sqr((x2 - x1) ^ 2 + (y2 - y1) ^ 2)
    
    coord(0) = (-L * x1 + (xy + L) * x2) / xy
    coord(1) = (-L * y1 + (xy + L) * y2) / xy
    
    ExtendLineCoord = coord()

End Function
'――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
Private Function Normal_Line(x1, y1, x2, y2)

    Dim Slope As Double
    
    If x2 - x1 <> 0 Then
        Slope = (y2 - y1) / (x2 - x1)
    Else
        Slope = 0
    End If
    
    Dim NormalSlope
    Dim NormalIntercept
    
    If y2 - y1 = 0 Then
    
        Normal_Line = Array(x1, 0)
    
    ElseIf Slope <> 0 Then
        NormalSlope = -1 / Slope
        NormalIntercept = y1 - (NormalSlope * x1)
        
        Normal_Line = Array(NormalSlope, NormalIntercept)
        
    ElseIf x2 - x1 = 0 Then
    
        Normal_Line = Array(0, y1)
        
    End If
    
End Function

 

コード解説

モジュールレベル変数の定義

Dim vw As DrawingView   'アクティブビュー
Dim r As Double         '円弧のR値

まずはモジュールレベル変数の定義を行います。
これは今後出てくる複数の関数にまたがって変数を使用するためです。

アクティブドキュメント/Selection/VisPropertySet定義

Sub CATMain()

 'アクティブドキュメント定義
    If TypeName(CATIA.ActiveDocument) <> "DrawingDocument" Then
       MsgBox "このマクロはDrawingDocument専用です。" & vbLf & _
              "CATDrawingに切り替えて実行してください。"
       Exit Sub
    End If
    
    Dim doc As DrawingDocument: Set doc = CATIA.ActiveDocument
    Dim sel As Selection:       Set sel = doc.Selection
    Dim vps As VisPropertySet:  Set vps = sel.VisProperties

続いてSubプロシージャのコードです。
まず初めにアクティブドキュメント / SelectionVisPropertySetの定義を行います。

VisPropertySetオブジェクトは、軸線の線種を変更するために定義しています。
 

長穴円弧部の中心座標取得

'長穴円弧部の中心座標取得
    Dim arc1_coord()
    arc1_coord = GetSelArcCoord("長穴の円弧(1つ目)を選択して下さい。")

    Dim arc2_coord()
    arc2_coord = GetSelArcCoord("長穴の円弧(2つ目)を選択して下さい。")

次に円弧の中心座標を取得します。
2つの円弧の中心座標が求まれば片方の軸線は作成可能になります。
(簡単にいうと円弧の中心点を結んだ線が軸線であるため)

ここでは「GetSelArcCoord関数」というオリジナル関数を作っています。
この関数では「SelectElement2メソッド」を使って”円弧の中心座標の取得” “円弧のR値の取得" “円弧のあるビューの取得"を行っています。

Private Function GetSelArcCoord(msg As String) As Variant()
    
    Dim sel 'As Selection
    Set sel = CATIA.ActiveDocument.Selection
    
    Dim filter():       filter = Array("Circle2D")
    Dim status As String
    
    status = sel.SelectElement2(filter, msg, False)
    If status <> "Normal" Then
        MsgBox "キャンセルしました。"
        End
    End If

    Dim arc 'As Circle2D
    Set arc = sel.Item(1).Value
    sel.Clear
    
 '円弧のR値の取得
    r = arc.Radius
    
 '円弧の中心座標の取得
    Dim arc_coord(1)
    arc.GetCenter arc_coord

 '円弧のあるビューの取得
    Dim obj As AnyObject:   Set obj = arc
    Do
        Set obj = obj.Parent
    Loop Until TypeName(obj) = "DrawingView"
    
    Set vw = obj
    
    GetSelArcCoord = arc_coord()

End Function

 
軸線延長の指定

 '軸線延長の指定
    Dim L As Double
    L = r / 2 + r    

先の2つの円弧を結んだ直線では軸線としては短いです。
そこで次に軸線を長穴からどれだけはみ出させるかの"量"を指定していきます。
ここで指定した長さだけ長穴からはみ出した軸線を作成することができます。

サンプルコードでは「r/2」つまりは円弧の半径の半分だけはみ出すようにしています。
(「r/2+r」の「+r」は不足分の長さなので延長量をしているのは「r/2」の部分です)
 

軸線1の作成

'軸線1 作成
    vw.Activate
    Dim fac2d As Factory2D:     Set fac2d = vw.Factory2D
    
    Dim coord1() As Double, coord2() As Double, ctr_coord(1) As Double
    Dim x1 As Double, y1 As Double, x2 As Double, y2 As Double
    
    x1 = arc1_coord(0)
    y1 = arc1_coord(1)
    x2 = arc2_coord(0)
    y2 = arc2_coord(1)
    
    ctr_coord(0) = (x1 + x2) / 2
    ctr_coord(1) = (y1 + y2) / 2
    
    coord1 = ExtendLineCoord(x1, y1, x2, y2, L)
    coord2 = ExtendLineCoord(x2, y2, x1, y1, L)
    
    Dim line1 As Line2D
    Set line1 = fac2d.CreateLine(coord1(0), coord1(1), coord2(0), coord2(1))

円弧の中心座標、延長量が決まったので実際に軸線を作成します。
直線の作成は「Factory2Dオブジェクト」の「CreateLineメソッド」を使います。
使い方は簡単で以下のように書けばOKです。

 icon-code CreateLineメソッドの使い方 

fac2d.CreateLine(始点のX座標, 始点のY座標, 終点のX座標, 終点のY座標)

ここでは円弧の中心座標から指定した延長量の位置の座標を取得する「ExtendLineCoord関数」を作成し、始点と終点の座標を計算しています。
引数は「x1」「y1」「x2」「y2」「L」の5つのDouble型の値です。

この関数を使うことで、(x1, y1)と(x2, y2)の2点を通る直線上にあり、(x2, y2)側に「L」の長さだけ延長した位置の座標を取得することができます。これを2つの円弧の中心座標に対して行うことで、任意の長さの軸線を作成することができます。
 

軸線2の作成

'軸線2 作成
    Dim norm_line()
    norm_line = Normal_Line(ctr_coord(0), ctr_coord(1), x2, y2)
    
    Dim coord3() As Double, coord4() As Double
    Dim x3 As Double, y3 As Double
    
    If norm_line(0) = 0 Then        '長穴がY軸方向の場合
    
        ReDim coord3(1)
        ReDim coord4(1)
        coord3(0) = ctr_coord(0) + L
        coord3(1) = norm_line(1)
        coord4(0) = ctr_coord(0) - L
        coord4(1) = norm_line(1)
    
    ElseIf norm_line(1) = 0 Then    '長穴がX軸方向の場合
    
        ReDim coord3(1)
        ReDim coord4(1)
        coord3(0) = norm_line(0)
        coord3(1) = ctr_coord(1) + L
        coord4(0) = norm_line(0)
        coord4(1) = ctr_coord(1) - L

    Else                            '長穴が傾いている場合
    
        x3 = ctr_coord(0) + 0.1
        y3 = norm_line(0) * x3 + norm_line(1)
        coord3 = ExtendLineCoord(ctr_coord(0), ctr_coord(1), x3, y3, L)
        
        x3 = ctr_coord(0) - 0.1
        y3 = norm_line(0) * x3 + norm_line(1)
        coord4 = ExtendLineCoord(ctr_coord(0), ctr_coord(1), x3, y3, L)
    
    End If

    Dim line2 As Line2D
    Set line2 = fac2d.CreateLine(coord3(0), coord3(1), coord4(0), coord4(1)

次にもう一方の軸線を作成します。
このコードは長くなるので割愛しますが、やっていることは「先程作った軸線に対して90度の直線を作成する」というだけのことです。

上記コードの場合、長穴がX平行,Y平行の場合(つまりは傾きが0の場合)にうまく計算ができないため、そこだけ条件分岐で専用の処理を書いています。
 

軸線の線種変更

 '軸線の線種変更
    sel.Add line1
    sel.Add line2
    vps.SetRealLineType 4, 1

最後に作成した2つの軸線の線種を変更します。
詳しくはVisPropertySetオブジェクトページで解説しているので合わせて確認してみてください。
線の太さや色を変更することもできるので、任意のものに書き換えてください。

 

まとめ

今回はCATDrawing内の長穴に対して軸線を作成するマクロについての内容でした。

マクロの内容としては一見簡単にできそうですが、実はかなり面倒な処理が必要になってきます。これはデフォルトで存在しているコマンドの内部で行われている処理を自分で書いているようなものです。

例えば座標変換(Axis to Axis)コマンドは普通に使えば、かなり簡単に使うことのできるコマンドですが、この機能をマクロで再現しようとすると座標変換の計算(行列計算)を全て書く必要が出てきます。

内部で行われている計算内容を考えなければならないためより深く"仕組み"を理解することはできますが、その分、数学知識も必要なのでそちらの勉強も行っていくことをオススメします。
 

サンプルマクロ集に戻る
目次へ戻る

 

 CATIAマクロを本気で勉強するなら

2024年8月26日CATIA,CATIAマクロ