C#ATIA

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

Fusion360APIでLine Arc Nurbsを作成してみる2

こちらの続き
Fusion360APIでLine Arc Nurbsを作成してみる1 - C#ATIA

少しマシになりましたが、ちょっと遠回りだな…

#FusionAPI_python
#Author-kantoku
#Description-CurvesTest2
#Line Arc Nurbs作成テスト

import adsk.core, adsk.fusion, traceback

_app = adsk.core.Application.get()
_ui = _app.userInterface

def run(context):
    try:
        global _app, _ui
        des = adsk.fusion.Design.cast(_app.activeProduct)
        comp = des.rootComponent
        
        crv_infos = []
        crv_infos.append(["Siren::Line",[[1,2,3],[7, 8, 9]]])  
        crv_infos.append(["Siren::Circle",
                           [[9.999999998279, 10.999999997875, 11.999999999064],
                            [24.682458367311, 23.30947502125, 21.936491673766],
                            [4.9999999978654, 14.99999999931, 25.000000001367]]])                            
        crv_infos.append(["Siren::BSCurve",
                           [[10, -20, -10], 
                            [9.587310041, -19.66378473, -7.111170289], 
                            [9.066687233, -19.24725683, -4.318376656], 
                            [8.414915532, -18.73943189, -1.64725845], 
                            [7.064932775, -17.72835072, 2.46828599], 
                            [5.183948194, -16.46330539, 5.802194902], 
                            [4.342483009, -15.92222727, 6.978456889], 
                            [2.558949274, -14.84247725, 8.853440155], 
                            [0.4455897088, -13.72427175, 9.964573277], 
                            [-0.6232459496, -13.19898599, 10.30174101], 
                            [-2.929444025, -12.16203711, 10.59962188], 
                            [-5.413111131, -11.2518361, 10.14198332], 
                            [-6.714932791, -10.8317392, 9.723113911], 
                            [-10.15600129, -9.869701012, 8.217440862], 
                            [-13.65008051, -9.267637855, 5.788366698], 
                            [-15.79519881, -9.037527212, 4.03034148], 
                            [-17.91158269, -8.933957503, 2.08841731], 
                            [-20, -8.944926835, 0]],
                            5,
                            [0, 17.39738523, 28.8962564, 
                             39.23864718, 50.07377854, 67.53908293],
                            [6, 3, 3, 3, 3, 6],
                            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
        #ここまでは基本的に読み込み
        
        #スケッチ作成
        sk = comp.sketches.add(comp.xYConstructionPlane)
        
        #Geometry
        geos = curve_Factory(crv_infos)
        
        #include
        include_Geo(sk, geos)
        
        _ui.messageBox('done')
    except:
        if _ui:
            _ui.messageBox('エラー\n{}'.format(traceback.format_exc()))

def include_Geo(sk, geos):
    for geo in geos:
        geo_type = geo.classType()
        if geo_type == "adsk::core::Line3D":
            fs = sk.sketchCurves.sketchLines.addByTwoPoints(
                geo.startPoint, 
                geo.endPoint)
        elif geo_type == "adsk::core::Arc3D":
            fs = sk.sketchCurves.sketchArcs.addByThreePoints(
                geo.startPoint, 
                geo.midPoint,
                geo.endPoint)
        elif geo_type == "adsk::core::NurbsCurve3D":
            fs = sk.sketchCurves.sketchFittedSplines.addByNurbsCurve(geo)
            fs.isFixed = True            
        else:        
            pass

        sk.include(fs)
        fs.deleteMe()
    return

def curve_Factory(lst):
    geos = []
    for cv_info in lst:
        cv_type = cv_info[0]
        if cv_type == "Siren::Line":
            geos.append(create_Line(cv_info))
        elif cv_type == "Siren::Circle":
            geos.append(create_Arc(cv_info))
        elif cv_type == "Siren::BSCurve":
            geos.append(create_BSCurve(cv_info))
        else:
            pass
    return geos
    
def create_Point(pos):
    return adsk.core.Point3D.create(
        pos[0] * 0.1, pos[1] * 0.1, pos[2] * 0.1)
                
def create_Line(lst):
    pos = lst[1]
    return adsk.core.Line3D.create(
        create_Point(pos[0]), 
        create_Point(pos[1]))

def create_Arc(lst):
    pos = lst[1]
    mid_pnt = create_Point(pos[1])
    arc = adsk.core.Arc3D.createByThreePoints(
            create_Point(pos[0]), 
            mid_pnt, 
            create_Point(pos[2]))
    arc.midPoint = mid_pnt
    return arc

def create_BSCurve(lst):
    poles = [create_Point(pos) for pos in lst[1]]
    degree = lst[2]
    knots = []
    for i, m in enumerate(lst[4]):
        for k in range(0, m):
            knots.append(lst[3][i])
    weights = lst[5]
    
    return adsk.core.NurbsCurve3D.createRational(
        poles, degree, knots, weights, False)

create_Arc関数部分で、インスタンス変数の動的追加と言う方法を利用しました。
勉強になりました。

Fusion360APIでLine Arc Nurbsを作成してみる1

こちらの続き
Fusion360APIでNURBS曲線を作成してみる3 - C#ATIA

Line Arc Nurbsの各種入ったIgesをこちらにUpしました。
GrabCAD - CAD library
(ファイル名:nurbs_curve_3d_sample1.igs)

閉じた円弧はArc3Dでは都合悪いかも知れませんが(未テスト)
siren側で2つの開いた円弧に分割しているような気がするので後回し。
Nurbs以外の曲線が現実的に存在しているものか不明なので無視。

一応途中ですが、こんな感じです。
f:id:kandennti:20170816190312p:plain
実は円弧に苦労しています。

コードは全く駄目なものですが、自宅で続きをやるかもしれないので記載。

#FusionAPI_python
#Author-kantoku
#Description-CurvesTest1
#Line Arc Nurbs作成テスト

import adsk.core, adsk.fusion, traceback

_app = adsk.core.Application.get()
_ui = _app.userInterface

def run(context):
    try:
        global _app, _ui
        des = adsk.fusion.Design.cast(_app.activeProduct)
        comp = des.rootComponent
        
        geos = []
        
        lin_ary = ["Siren::Line",[[1,2,3],[7, 8, 9]]]
        geos.append(create_Line(lin_ary).asNurbsCurve)
        
        arc_ary = ["Siren::Circle",
                   [[9.999999998279, 10.999999997875, 11.999999999064],
                    [24.682458367311, 23.30947502125, 21.936491673766],
                    [4.9999999978654, 14.99999999931, 25.000000001367]]]
        geos.append(create_Arc(arc_ary))
        
        
        nsc_ary = ["Siren::BSCurve",
                   [[10, -20, -10], 
                    [9.587310041, -19.66378473, -7.111170289], 
                    [9.066687233, -19.24725683, -4.318376656], 
                    [8.414915532, -18.73943189, -1.64725845], 
                    [7.064932775, -17.72835072, 2.46828599], 
                    [5.183948194, -16.46330539, 5.802194902], 
                    [4.342483009, -15.92222727, 6.978456889], 
                    [2.558949274, -14.84247725, 8.853440155], 
                    [0.4455897088, -13.72427175, 9.964573277], 
                    [-0.6232459496, -13.19898599, 10.30174101], 
                    [-2.929444025, -12.16203711, 10.59962188], 
                    [-5.413111131, -11.2518361, 10.14198332], 
                    [-6.714932791, -10.8317392, 9.723113911], 
                    [-10.15600129, -9.869701012, 8.217440862], 
                    [-13.65008051, -9.267637855, 5.788366698], 
                    [-15.79519881, -9.037527212, 4.03034148], 
                    [-17.91158269, -8.933957503, 2.08841731], 
                    [-20, -8.944926835, 0]],
                    5,
                    [0, 17.39738523, 28.8962564, 
                     39.23864718, 50.07377854, 67.53908293],
                    [6, 3, 3, 3, 3, 6],
                    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
        geos.append(create_BSCurve(nsc_ary))
        
        #スケッチ作成
        sk = comp.sketches.add(comp.xYConstructionPlane)
        
        #円弧テスト
        pos = arc_ary[1]
        Arcs = sk.sketchCurves.sketchArcs
        Arcs.addByThreePoints(
            create_Point(pos[0]), 
            create_Point(pos[1]), 
            create_Point(pos[2]))
            
        for geo in geos:
            if geo.classType() == "adsk::core::Arc3D":
                #これNG
                a = geo.center
                b = geo.startPoint
                c = geo.endAngle - geo.startAngle
                #fs = sk.sketchCurves.sketchArcs.addByCenterStartSweep(a, b, c)
            else:
                fs = sk.sketchCurves.sketchFittedSplines.addByNurbsCurve(geo)
                sk.include(fs)
                fs.deleteMe()
        
        _ui.messageBox('done')
    except:
        if _ui:
            _ui.messageBox('エラー\n{}'.format(traceback.format_exc()))
#使ってない
def curve_Factory(lst):
    for cv_info in lst:
        cv_type = cv_info(0)
        if cv_type == "Siren::Line":
            pass
        elif cv_type == "Siren::Circle":
            pass
        elif cv_type == "Siren::BSCurve":
            pass
        else:
            pass

def create_Point(pos):
    return adsk.core.Point3D.create(
        pos[0] * 0.1, pos[1] * 0.1, pos[2] * 0.1)
                
def create_Line(lst):
    pos = lst[1]
    return adsk.core.Line3D.create(
        create_Point(pos[0]), 
        create_Point(pos[1]))

def create_Arc(lst):
    pos = lst[1]
    return adsk.core.Arc3D.createByThreePoints(
        create_Point(pos[0]), 
        create_Point(pos[1]), 
        create_Point(pos[2]))

def create_BSCurve(lst):
    poles = [create_Point(pos) for pos in lst[1]]
    degree = lst[2]
    knots = []
    for i, m in enumerate(lst[4]):
        for k in range(0, m):
            knots.append(lst[3][i])
    weights = lst[5]
    
    return adsk.core.NurbsCurve3D.createRational(
        poles, degree, knots, weights, False)

本当は・・・拡張メソッド作れそうだからその方法かな?

Fusion360APIでNURBS曲線を作成してみる3

こちらの続きです。
Fusion360APIでNURBS曲線を作成してみる2 - C#ATIA

前回のものを修正し、より実践的なNURBS曲線を作ってみます。
耐え切れなかった為、こちらにサンプルデータをUpしました。
GrabCAD - CAD library
CATIAで作成した曲線と、確認用に押出ししたサーフェスをIgesにしています。
(ファイル名:nurbs_curve_3d_sample1.igs)

こちらをFusion360でインポート(サーフェスだけです)し、以下のスプリクトを
実行します。

#FusionAPI_python
#Author-kantoku
#Description-NurbsCurve3D_Test3
#Nurbsカーブ作成テスト

import adsk.core, adsk.fusion, traceback

_app = adsk.core.Application.get()
_ui = _app.userInterface

def run(context):
    try:
        global _app, _ui
        des = adsk.fusion.Design.cast(_app.activeProduct)
        comp = des.rootComponent
        
        #NURBSカーブ作成準備
        poss = [[10, -20, -10], 
                [9.587310041, -19.66378473, -7.111170289], 
                [9.066687233, -19.24725683, -4.318376656], 
                [8.414915532, -18.73943189, -1.64725845], 
                [7.064932775, -17.72835072, 2.46828599], 
                [5.183948194, -16.46330539, 5.802194902], 
                [4.342483009, -15.92222727, 6.978456889], 
                [2.558949274, -14.84247725, 8.853440155], 
                [0.4455897088, -13.72427175, 9.964573277], 
                [-0.6232459496, -13.19898599, 10.30174101], 
                [-2.929444025, -12.16203711, 10.59962188], 
                [-5.413111131, -11.2518361, 10.14198332], 
                [-6.714932791, -10.8317392, 9.723113911], 
                [-10.15600129, -9.869701012, 8.217440862], 
                [-13.65008051, -9.267637855, 5.788366698], 
                [-15.79519881, -9.037527212, 4.03034148], 
                [-17.91158269, -8.933957503, 2.08841731], 
                [-20, -8.944926835, 0]]      
        poles = [adsk.core.Point3D.create(
                pos[0] * 0.1, pos[1] * 0.1, pos[2] * 0.1)
                for pos in poss]
        
        degree = 5
        
        knot_vec = [0, 17.39738523, 28.8962564, 39.23864718, 50.07377854, 67.53908293]
        mults = [6, 3, 3, 3, 3, 6]
        knots = []
        for i, m in enumerate(mults):
            for k in range(0, m):
                knots.append(knot_vec[i])
        
        weights = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        
        #NURBSカーブ作成 - 画面上には出来ない
        nc = adsk.core.NurbsCurve3D.createRational(poles, degree, knots, weights, False)
        print(str(nc is None))
        #スケッチ作成
        sk = comp.sketches.add(comp.xYConstructionPlane)
        
        #スケッチにNURBSカーブ挿入
        fs = sk.sketchCurves.sketchFittedSplines.addByNurbsCurve(nc)
        
        #NURBSカーブをスケッチから抽出
        sk.include(fs)
        
        #元のNURBSカーブ削除
        fs.deleteMe()
        
        _ui.messageBox('done')
    except:
        if _ui:
            _ui.messageBox('エラー\n{}'.format(traceback.format_exc()))

NURBSカーブの各パラメータはsirenで取得したデータです。結果はこちら
f:id:kandennti:20170816141436p:plain
(ファイル名:nurbs_curve_3d_sample1.f3d)
何だかわかりにくいのですが、サーフェスの境界部分の1ヶ所だけ曲線が追加されます。
(個人的には感動してます)

最初はFusion360APIの長さ単位が "Cm" だと言うことをすっかり忘れていたので
とんでもない結果になりましたが、単位を合わせた所一致しました。
(コントロールポイント以外はそのままの数値です・・・恐らく)

polesリストを作る時の処理はpythonの内包表記で "らしく" 書けたのですが、
knotsのリストを作る辺りのコードが2重ループになっており、ちょっと残念です。
内包表記で2重ループ回避出来そうな気がしたんだけどなぁ・・・。

Fusion360APIでNURBS曲線を作成してみる2

こちらの続きです。
Fusion360APIでNURBS曲線を作成してみる - C#ATIA

前回スプリクトで作成したNURBS曲線の方法では、不要なコントロールポイントが
削除し切れなかったのですが、思い付きで遠回りな方法を行ったら
意図していた結果となりました。

#FusionAPI_python
#Author-kantoku
#Description-NurbsCurve3D_Test2
#Nurbsカーブ作成テスト

import adsk.core, adsk.fusion, traceback

_app = adsk.core.Application.get()
_ui = _app.userInterface

def run(context):
    try:
        global _app, _ui
        des = adsk.fusion.Design.cast(_app.activeProduct)
        comp = des.rootComponent
        
        #NURBSカーブ作成準備
        poles = [adsk.core.Point3D.create(10, 0, 70), 
                 adsk.core.Point3D.create(7, 50, 7), 
                 adsk.core.Point3D.create(3, -30, 8), 
                 adsk.core.Point3D.create(10, -20, 7)]
        degree = 2
        knots = [0.0, 0.0, 0.0, 1.0, 2.0, 2.0, 2.0]
        weights = [1.0, 1.2, 1.0, 1.0]
        
        #NURBSカーブ作成 - 画面上には出来ない
        nc = adsk.core.NurbsCurve3D.createRational(poles, degree, knots, weights, False)
        
        #スケッチ作成
        sk = comp.sketches.add(comp.xYConstructionPlane)
        
        #スケッチにNURBSカーブ挿入
        fs = sk.sketchCurves.sketchFittedSplines.addByNurbsCurve(nc)
        
        #NURBSカーブをスケッチから抽出
        sk.include(fs)
        
        #元のNURBSカーブ削除
        fs.deleteMe()
        
        _ui.messageBox('done')
    except:
        if _ui:
            _ui.messageBox('エラー\n{}'.format(traceback.format_exc()))

こんな感じです。

手順としては、
・各パラメータに基づいたNURBSカーブ作成
 ↓
・スケッチに取り込み(.sketchCurves.sketchFittedSplines.addByNurbsCurve)
 ↓
・NURBSカーブをスケッチから抽出
 ↓
・スケッチに取り込んだNURBSカーブを削除
です。
「NURBSカーブをスケッチから抽出」を行っているincludeメソッドは恐らく
「3Dジオメトリを含める」のコマンドではないかな?と思います。
f:id:kandennti:20170816102912p:plain
過去の経験から、一度スケッチ等画面上に表示される状態じゃないと
includeメソッドはエラーになっちゃうんですよね。

Fusion360APIでNURBS曲線を作成してみる

避けては通れないNURBS曲線のスプリクト作成ですが、
困った程にサンプルが見当たりませんでした。

手探りまくりでようやくこのようなコードが出来上がりました。

#FusionAPI_python
#Author-kantoku
#Description-NurbsCurve3D_Test1
#Nurbsカーブ作成テスト

import adsk.core, adsk.fusion, traceback

_app = adsk.core.Application.get()
_ui = _app.userInterface

def run(context):
    try:
        global _app, _ui
        des = adsk.fusion.Design.cast(_app.activeProduct)
        comp = des.rootComponent
        
        #NURBSカーブ作成準備
        poles = [adsk.core.Point3D.create(10, 0, 70), 
                 adsk.core.Point3D.create(7, 50, 7), 
                 adsk.core.Point3D.create(3, -30, 8), 
                 adsk.core.Point3D.create(10, -20, 7)]
        degree = 2
        knots = [0.0, 0.0, 0.0, 1.0, 2.0, 2.0, 2.0]
        weights = [1.0, 1.2, 1.0, 1.0]
        
        #NURBSカーブ作成 - 画面上には出来ない
        nc = adsk.core.NurbsCurve3D.createRational(poles, degree, knots, weights, False)
        
        #スケッチ作成
        sk = comp.sketches.add(comp.xYConstructionPlane)
        
        #スケッチにNURBSカーブ挿入
        fs = sk.sketchCurves.sketchFittedSplines.addByNurbsCurve(nc)
        
        #NURBSカーブ固定
        fs.isFixed = True
        
        #不要な制御点を削除
        for skp in sk.sketchPoints:
            print(skp.deleteMe())
        
        _ui.messageBox('done')
    except:
        if _ui:
            _ui.messageBox('エラー\n{}'.format(traceback.format_exc()))

実行結果はこちら
f:id:kandennti:20170814234531p:plain
何とか出来たのですが、画像上の赤印部の点を消したいのですが
削除出来ません。(手動でも)

忘れてしまいそうなので、簡単な手順を覚書
・各パラメータに基づいたNURBSカーブ作成
 ↓
・スケッチに取り込み(.sketchCurves.sketchFittedSplines.addByNurbsCurve)
 ↓
・NURBSカーブ固定(これを行わないと、スケッチで修正した際おかしくなる)
 ↓
・不要な制御点を削除 ← ここが不完全?

ここまで来るのに本当に苦労しました。 他の方法があるものでしょうか?
Sketch.include(NurbsCurve)の様な方法は、過去に試しましたが出来なかったです。
(ご存知の方教えて頂けると助かります。)

siren v0.14 線の情報を取得する2

時間が無い。 こちらの続きです。
siren v0.14 線の情報を取得する - C#ATIA

曲線を扱う以上、パラメータを取得したかったのですが
こちらの説明の first last params が反応しませんでした。
class Edge · dyama/mruby-siren Wiki · GitHub

サンプルコードにパラメータの取得を行っているものがあったので、前回の物を拡張

・・・
class  Siren::Edge
	def first()
		return self.param(self.sp, 0.001)
	end 
	
	def last()
		return self.param(self.tp, 0.001)
	end 
	
	def info()
		crv = self.curve
		arr = ["class : " + crv.class.name]
		arr <<  ["length : " + self.length.to_s]
		arr <<  "first_pos(first_param) : %s (%f)" % [self.sp.to_s, self.first]
		arr <<  "last_pos(last_param) : %s (%f)" % [self.tp.to_s, self.last]
・・・

残りは前回と同じ。トレランスは強制的に0.001にしました。
実行結果はこちら
f:id:kandennti:20170810162327p:plain
パラメータは Siren::Edge クラスに実装されているようなので、
赤印の直線でも取得出来ちゃうんですね。 終点のパラメータは結果的に長さなんですね。

黄色印の長さですが、Siren::Edge クラスに実装されつつ Siren::Circle クラスにも
実装されていて、最初は何でかな? と思っていたのですが、
Siren::Edge.length は、実際の長さで
Siren::Circle.length は、定義された(要は閉じた)時の長さ
になっているようです。 (開いた円弧でareaはどうやって・・・と最初は思ってました)

.curve で取得できるものは、トリム解除された状態で始点終点パラメータで
トリムされた物が Siren::Edge クラスになっているのだろ と言う解釈してみました。

問題を解決したい・・・

先月末辺りから再びsiren(mruby-siren)に再挑戦しているのですが、
その理由は、これらの問題をsirenを利用すれば解決できるかな?
と思い付いたからです。

解決済み: igesライン(カーブ)データのインポート - Autodesk Community

stp形式等のファイルを読み込み、書き出しを行った時に、点、線などの要素が消えている - Autodesk Community

中間ファイルフォーマット・mruby・python全てで知識が足らず、素人で到達出来る
ものかどうかも怪しいのですが、全く届かない話でもなさそうと言う
見込みは付いてます。

点・直線・円弧辺りは何とかなりそうな気もしているのですが、
NURBS曲線は避けて通れない気がしています。
他の曲線については、定義はされているものの実際にはほぼ見かけない
ような気がしていますし、こちらを見ても
Help
asNurbsCurveメソッドが存在しているので、何とかなっちゃいそうな。

年内までに完成するかな?(モチベーション続くかな・・・)