C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

画像にバルーンを付ける2(PDFからJPEG)

こちら関連です。
画像にバルーンを付ける - C#ATIA

画像の図面って大体TIFFかPDFですよね?(個人的にはPDF派)


あちらの方法はTIFFはOKですがPDFはNGなんです。
要はPDFから何かしらの画像ファイルかPSファイルにしたいのですが、
今さら何かソフトをインストールするのが面倒です。

色々と試したんですけどね、こちらのサイトを利用しPDF→JPEG
上手く行きました。
PDFをJPGに変換。PDFから画像を抽出

こちらのPDFファイルの連結でお世話になっているサイトです。
PDFの連結 - C#ATIA

メッチャお世話になってます。

ユーザーパターン1

内容的には、こちらの続きです。
スケッチの点を元にボディを複製したい2 - C#ATIA

boxerを改造しつつ、何とか進めています。
f:id:kandennti:20210715163020p:plain
赤の矢印のボディとスケッチを元に、タイムラインの赤い部分が
出来上がって、青いボディ3個が出来上がります。
これはタイムライン以外は前回と同じ結果です。

Custom Featuresの威力はここからで、タイムラインのアイコンを
ダブルクリックすると編集できます。
f:id:kandennti:20210715163450p:plain
配置されるボディを、円柱から球体に変更してみます。

f:id:kandennti:20210715163617p:plain
消える・・・。 と言う現象に悩まされています。
ここ2日間。

僕が悪いのは十分承知していますが、直せるかな?

グラフ

あぁ これ凄そう。
thom.hateblo.jp
まだ中身を見ていないのですが、CADでも役立ちそう。
CATIAのドキュメント間リンクを表示させるダイアログは
"どうやって配置しているのだろう" と以前から思ってました。

Treeの表示は別に難しそうではないのですが、Graphとなると
全く思いつかない。

後に何かしらで利用してみたいな。

基準フューチャーのボディを差し替える

ナカナカ本題が進みません。

いつもAPIではお世話になっている基準フューチャーに
updateBodyメソッドがあるんです。
Fusion 360 Help
使ったこと無いんです。 が、必要になりそうなので試しています。


まず、この様なデータを用意しました。
f:id:kandennti:20210713144154p:plain
・基準フューチャーを作成し、円柱のボディを作成し、
 基準フューチャーから抜ける。
・ブロックを作る。
・2個のボディをブーリアン和。
・お互いのボディの境界付近が絡むようなフィレット(ルールド)。
色ぐらい付けるべきですかね?

タイムラインではこんな感じです。
f:id:kandennti:20210713144531p:plain
一番最初が基準フューチャーです。
要は、基準フューチャーで作成されたボディが関連するタイムラインが
欲しく、updateBodyメソッドの効果を知りたかったんです。

念のため、GUIの操作で
f:id:kandennti:20210713145018p:plain
基準フューチャーに戻り、新たなボディ(ボディ19)を作成。
古いボディ(ボディ18)を削除し、基準フューチャーから
抜けると・・・ブーリアンとフィレットが赤くなりエラーです。
そりゃ参照すべきボディが消えてしまったので、迷子になるのは
当然です。


実験の為に、こんな感じで作りました。

# Fusion360API Python script
import adsk.core, adsk.fusion, traceback

def run(context):
    ui = adsk.core.UserInterface.cast(None)
    try:
        app :adsk.fusion.Application = adsk.core.Application.get()
        ui = app.userInterface
        des :adsk.fusion.Design = app.activeProduct
        # root :adsk.fusion.Component = des.rootComponent

        # 差し替え用円柱
        tmpMgr :adsk.fusion.TemporaryBRepManager = adsk.fusion.TemporaryBRepManager.get()
        PNT3D = adsk.core.Point3D
        radius = 10
        brep :adsk.fusion.BRepBody = tmpMgr.createCylinderOrCone(
            PNT3D.create(0,0,0),
            radius,
            PNT3D.create(0,0,2),
            radius)

        # BaseFeature取得
        tl :adsk.fusion.Timeline = des.timeline
        tlObj :adsk.fusion.TimelineObject = tl.item(0)
        # tlObj.rollTo(True) # タイムラインのロールは必要無し
        baseFeat :adsk.fusion.BaseFeature = adsk.fusion.BaseFeature.cast(tlObj.entity)
        # sourceBody :adsk.fusion.BRepBody = baseFeat.bodies[0] # 編集に入ってからじゃないとNG

        # BaseFeature編集
        baseFeat.startEdit()

        sourceBody :adsk.fusion.BRepBody = baseFeat.bodies[0]
        # newBody = root.bRepBodies.add(brep, baseFeat) #入れちゃダメ
        baseFeat.updateBody(sourceBody, brep) # 差し替え!

        # BaseFeature編集終了
        baseFeat.finishEdit()

        # tl.moveToEnd() # ロールを戻す必要無し

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

コメントにしている行が多数あるのは、それだけ失敗したからです。

実行すると
f:id:kandennti:20210713145705p:plain
見栄えの問題から色を付けましたが、関係ないです。
驚くことに、エラーになりません。updateBodyの名称は嘘じゃないです。

これ、こちらのBoxerで使用されているんです。
FusionBoxer/OffsetBoundingBoxCommand.py at master · tapnair/FusionBoxer · GitHub
最初見た時 "こんな事出来るんだぁ" と思いましたよ。
ドキュメントの日付を見ると、CustomFeaturesと同じタイミングで
実装されたっぽいですね。

ちいさなプライド

こちらの続きです。
画像にバルーンを付ける - C#ATIA

無事バルーンを200個程作りました・・・。

プロットしてみると悲劇が。
かなり最初の方でバルーン付け忘れの寸法を発見しました。

忘れているところに最後のバルーン付ければ良いのですが、
周囲のバルーンと数値が違いすぎ、
"忘れてたから付け足しました" 感が半端ないです。
小さなプライドが邪魔をします。

と言って、100個以上のバルーンの文字をチマチマ書き
換えるなんて、一番嫌なヤツです。

で、マクロを作りました。

'vba
'バルーンの数値を書き換える、小さなプライド
Option Explicit

Sub CATMain()

    Dim doc As DrawingDocument
    Set doc = CATIA.ActiveDocument

    Dim ballons As Collection
    Set ballons = getBallons(doc)
    
    Call chengeBallonText(ballons, 68, 1)

End Sub


Private Sub chengeBallonText( _
    ByVal ballons As Collection, _
    ByVal startValue As Long, _
    ByVal addValue As Long)
    
    Dim ball As DrawingText
    Dim oriVal As Long
    For Each ball In ballons
        
        On Error Resume Next
            oriVal = CLng(ball.Text)
        On Error GoTo 0
        
        If oriVal < startValue Then GoTo continue

        ball.Text = CStr(oriVal + addValue)
        
        Debug.Print Str(oriVal) + " -> " + ball.Text
continue:
    Next
        
End Sub


Private Function getBallons( _
    ByVal doc As DrawingDocument) As Collection

    Dim sel As Selection
    Set sel = doc.Selection
    
    CATIA.HSOSynchronized = False
    
    sel.Clear
    sel.Search "(CAT2DLSearch.DrwBalloon + CATDrwSearch.DrwBalloon),all"

    Dim lst As Collection
    Set lst = New Collection
    
    Dim i As Long
    For i = 1 To sel.Count2
        Call lst.Add(sel.Item2(i).Value)
    Next

    Set getBallons = lst
    
    sel.Clear
    CATIA.HSOSynchronized = True
    
End Function

chengeBallonTextに、バルーンのコレクションと書き換え先頭の番号と
足す数値を投げると、指定した番号以上を書き換えます。
そう、68個目から書き換えたかったんです。

スケッチの点を元にボディを複製したい2

こちらの続きです。
スケッチの点を元にボディを複製したい1 - C#ATIA

前回はTemporaryBRepManagerとBaseFeatureを利用して
配置を行ったのですが、ひょっとしたらCustom Featuresに
した時に上手く行かないと、精神的ダメージが大きいので
他の方法も検討しておこうと思い、CopyPasteBodyと
MoveFeatureで同様の処理を行うものも作ってみました。

Custom Featuresは、TemporaryBRepManagerとBaseFeatureは
対応しているんですけどね。

# 将来的に body skt は同一コンポーネントの制限を行いたい
def execUserPattern(
    body :adsk.fusion.BRepBody,
    skt :adsk.fusion.Sketch):

    # get points - 次回xyPlane上に制限する?
    origin :adsk.fusion.SketchPoint = skt.originPoint
    p :adsk.fusion.SketchPoint
    pnts = [p.worldGeometry for p in skt.sketchPoints
        if p != origin]

    # body cog
    VERYHI = adsk.fusion.CalculationAccuracy.VeryHighCalculationAccuracy
    prop :adsk.fusion.PhysicalProperties = body.getPhysicalProperties(VERYHI)
    bodyCenter :adsk.core.Point3D = prop.centerOfMass

    # get sketch axis
    _, _, _, zAxis = skt.transform.getAsCoordinateSystem()

    # projection body cog
    infinite :adsk.core.InfiniteLine3D = adsk.core.InfiniteLine3D.create(bodyCenter, zAxis)
    plane :adsk.core.Plane = skt.referencePlane.geometry
    bodyProjectionCog :adsk.core.Point3D = plane.intersectWithLine(infinite)

    # get matrix
    mats = []
    for p in pnts:
        vec :adsk.core.Vector3D = bodyProjectionCog.vectorTo(p)
        mat = adsk.core.Matrix3D.create()
        mat.translation = vec
        mats.append(mat)

    # BaseFeature
    comp :adsk.fusion.Component = body.parentComponent
    # baseFeat : adsk.fusion.BaseFeature = comp.features.baseFeatures.add() #ここ

    # start edit
    # baseFeat.startEdit() #ここ

    # CopyPasteBody
    copyBodies :adsk.fusion.CopyPasteBodies = comp.features.copyPasteBodies

    # move
    moves :adsk.fusion.MoveFeatures = comp.features.moveFeatures
    objs :adsk.core.ObjectCollection = adsk.core.ObjectCollection.create()
    for mat in mats:
        objs.clear()
        objs.add(body)
        copyPasteFeat = copyBodies.add(objs)
        objs.clear()
        objs.add(copyPasteFeat.bodies[0])
        moveIpt :adsk.fusion.MoveFeatureInput = moves.createInput(objs, mat)
        moves.add(moveIpt)

    # baseFeat.finishEdit() #ここ

実行結果は同じなのですが、タイムラインが違います。
f:id:kandennti:20210709123310p:plain
コピペして移動。コピペして・・・・となります。

上記のコードで ”#ここ” の記載している3行のコメント化を
外すとBaseFeature内での作業になるのですが、エラーになります。

BaseFeature内でCopyPasteBodyはエラーになるようです。
知らなかった。逆にGUIではBaseFeature内で行わないと
出来ないのに。調べ方が足りないかも。

画像にバルーンを付ける

あまりやらないのですが、偶に客先支給の画像(PDFやTIFF)の図面に
バルーンでナンバリングしなきゃならない時があるんです。
・・・検査の為に。

どんな方法でも構わないのですが、今まで悩みながらExcelで行ったり
してました。

・・・Excelだと、挿入した画像が動いちゃうんですよ。マウスで
触っちゃうと。検索しても ”セルの変更に対しての固定” のような
機能しか見つからない。恐らく完全に固定する方法は無いんだろう。

バルーン代わりに図形を利用したりするので、どうしても画像に
触れないように作業が出来ないんですよね。

悩みに悩んだ挙句(それ程でも無いんですが)気が付きました。
CATIA V5 のDrawの背景として図面を取り込めば良いことに!!

f:id:kandennti:20210709114708p:plain

当然、バルーン使えるし。
もっと早く気が付け、俺。