読者です 読者をやめる 読者になる 読者になる

C#ATIA

↑タイトル詐欺 主にCATIA V5 の VBA

Ariawaseを利用してみたい2

こちらの続きです。
Ariawaseを利用してみたい1 - C#ATIA


元となるコードはこちらのスピードテストで利用したものです。
スピードテスト1 - C#ATIA

理解不足でかなり迷いましたが、何とか動く状態になったものが
こちらです。

'VBA - using_ariawase
Private Declare Function timeGetTime Lib "winmm.dll" () As Long

Dim oPart As MECMOD.Part
Dim oHybShpFact As HybridShapeTypeLib.HybridShapeFactory
Dim oHybBdy As MECMOD.HybridBody
Dim oHybShpPt 'As HybridShapeTypeLib.HybridShapePointCoord

Sub CATMain()
    Dim T As Long
    
    T = timeGetTime
    Call CreateDatumPoint
    MsgBox CDbl(timeGetTime - T) / 1000 & "秒"
End Sub

Private Sub CreateDatumPoint()
    Dim oHybShpPtExp As HybridShapeTypeLib.HybridShapePointExplicit
    Dim i As Integer
    
    Set oPart = CATIA.ActiveDocument.Part
    Set oHybShpFact = oPart.HybridShapeFactory

'------------ Add Body ------------------------------
    Set oHybBdy = oPart.HybridBodies.Add()

'------------ Create RefPoint ------------------------------
    oPt = Array(0, 0, 0)
    Set oHybShpPt = oHybShpFact.AddNewPointCoord(oPt(0), oPt(1), oPt(2))
    Call oHybBdy.AppendHybridShape(oHybShpPt)
    Call oPart.UpdateObject(oHybShpPt)

'------------ Create DetumPoints ------------------------------
    Dim Pnts As Variant
    Pnts = ArrMap(Init(New Func, vbVariant, AddressOf Create3dPos, vbLong), ArrRange(1&, 500&)) '-①
    Call ArrMap(Init(New Func, vbEmpty, AddressOf CreateDetumPoint, vbVariant), Pnts) '-③

    Call oHybShpFact.DeleteObjectForDatum(oHybShpPt)    'Delete RefPoint
    Call oPart.Update
End Sub

Private Function Create3dPos(ByVal v As Long) As Variant '-②
    Create3dPos = Array(v * 10&, 0&, 0&)
End Function

Private Sub CreateDetumPoint(ByVal pnt As Variant) '-④
    Call oHybShpPt.SetCoordinates(pnt)
    Call oPart.UpdateObject(oHybShpPt)
    Call oHybBdy.AppendHybridShape(oHybShpFact.AddNewPointDatum(oHybShpPt))
End Sub

"CATMain" 自体は変更しませんでした。 
"CreateDatumPoint" についても "Create DetumPoints" コメント前までは
変数宣言の一部を修正したのみです。


元のコードでは、ループさせる際にX座標を計算させ、点の座標を修正させて
いますが、今回のものは予め500個分の座標値を配列で用意し座標値を
修正させます。
①部分で、一度1~500までの値を持った配列を作成し、②部分で
XYZの座標値となる配列として生成させています。
実は②部分で手こずりました。 引数は値渡し(ByVal)でないといけないんですね。
(何度もCATIAを落とす事に・・・)

③部分では、座標値の配列を④部分に投げています。
④部分を関数化した為、"oPart" "oHybShpFact" "oHybBdy" "oHybShpPt" の
4つは、モジュールのローカル変数にします。

でも、これは元のコードと同等では無いのです。

'vba
'------------ Create DetumPoints ------------------------------
    For i = 1 To 500
        oPt(0) = oPt(0) + 10
        Call oHybShpPt.SetCoordinates(oPt)
        Call oPart.UpdateObject(oHybShpPt)
        Set oHybShpPtExp = oHybShpFact.AddNewPointDatum(oHybShpPt)
        Call colMyObj1.add(oHybShpPtExp)
    Next
'------------ Append DetumPoints ------------------------------
    With oHybBdy
        For Each oMyobj In colMyObj1
            Call .AppendHybridShape(oMyobj)
        Next
    End With

では、For文でデータムポイントを作成後、ForEach文で形状セットに全て入れていますが、
④部分ではデータムポイントを作成直後に、形状セットに入れています。
この方法では、自分の環境では2倍近い処理速度の差が出ています。

本当は、元のコードと同等の処理をさせたかったのですが、方法がわからず・・・。