C#ATIA

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

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メソッドが存在しているので、何とかなっちゃいそうな。

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

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

既にタイトルがあやふやですが、こちらの続きです。
siren v0.14 線の種類を判断する - C#ATIA

実際には使わない事になりそうな・・・ あぁ後々の為の練習です。

#Siren_script
include Siren

fName = "/curves"
$inPath = ARGV[0] + fName + ".igs"
$exPath = ARGV[0] + fName + "-res.igs"

def Pause()
	str = gets
end

class  Siren::Edge
	def info()
		crv = self.curve
		arr = ["class : " + crv.class.name]
		arr <<  ["length : " + self.length.to_s]
		case crv.class.name
		when "Siren::Line" then
			arr <<  ["dir : " + crv.dir.to_s]
		when "Siren::Circle" then
			arr <<  ["length : " + crv.length.to_s]
			arr <<  ["radius : " + crv.radius.to_s]
			arr <<  ["center : " + crv.center.to_s]
			arr <<  ["area : " + crv.area.to_s]
			arr <<  ["normal : " + crv.normal.to_s]
			arr <<  ["dir : " + crv.dir.to_s]
		when "Siren::BSCurve" then
			arr <<  ["degree : " + crv.degree.to_s]		
			arr <<  ["knots : " + crv.knots.to_s]		
			arr <<  ["mults : " + crv.mults.to_s]		
			arr <<  ["poles : " + crv.poles.to_s]		
			arr <<  ["weights : " + crv.weights.to_s]		
		else
			#arr = ["non"]
		end
		return arr.join("\n ") + "\n "
	end
end

###########
comp = Siren.load_model $inPath
p "total_edges : " + comp.edges().size.to_s
edgelst = comp.to_a.select { |x| x.edge? == true }
edgelst.concat(comp.to_a.select { |x| x.wire? == true }.edges ).flatten

p "**************"
edgelst.each{|x| puts x.info }

begin
	Siren.save_model edgelst.to_comp , $exPath
rescue
	p "export errer!"
end
 
###########
puts "done."
Pause()

読み込んだIgesファイルの線を列挙して、取得できる情報を出力するだけです。
VBA脳の僕ならループさせて線種を判断して、線種毎に処理を分ける事を
真っ先に考えるのですが、mrubyにはクラスを拡張する方法があるんじゃないかな?
と思いやってみました。
結果はこんな感じです。
f:id:kandennti:20170809200145p:plain
これ自体は使わないのですが、手法は勉強になりました。

本当はチマチマ書かずに、各クラスのメソッドを列挙して文字列としてメソッド呼び出し
出来るんじゃないのかな? とも思ったのですがよくわかりませんでした。
僕のような凡人で思い付く様なコードは、mrubyで可能なんじゃないかと
思うのですが。

siren v0.14 NURBS曲線2

こちらの続きです。
siren v0.14 NURBS曲線 - C#ATIA

以前はIgesを読み込み、読み込んだ曲線をそのまま書き出していましたが
今度は読み込んだ曲線から各要素を読み取り、コントロールポイントのみを2倍にし
新たな曲線をsirenで作成し書き出してみました。

#!siren
# coding: utf-8
include Siren

fName = "/nurbs5"
$inPath = ARGV[0] + fName + ".igs"
$exPath = ARGV[0] + fName + "-res.igs"
$dpPath = ARGV[0] + fName + "_dump.txt"

def wDump(i)
  if i.kind_of?(String)
     open($dpPath, "a") {|f| f.write "\r\n" + i}
  end
end

def Pause()
	str = gets
end

wDump("start")
###########

shp = Siren.load_model $inPath
wDump(shp.to_s)

degree = shp.curve.degree
wDump(degree.to_s)

knots = shp.curve.knots
wDump(knots.to_s)

mults = shp.curve.mults
wDump(mults.to_s)

poles = shp.curve.poles
wDump(poles.to_s)

poles2 = poles.map{ |n| n.map{ |p| p * 2 }}
wDump(poles2.to_s)

weights = shp.curve.weights
wDump(weights.to_s)

crv= Siren.bscurve degree, knots, mults, poles2, weights
Siren.save_model crv, $exPath

###########
wDump("end")
puts "done."
Pause()

書き出したIgesと元の曲線を比べた結果がこちら
f:id:kandennti:20170808190305p:plain
黄色が元の曲線で、水色が2倍な曲線です。(原点で2倍のスケーリングで一致します)

出来てる・・・結構苦労したので、他人には伝わらないと思いますが
感動してます。

でも、multsの説明書きが一致していないような・・・単に理解できていないだけかな?

siren v0.14 NURBS曲線

どちらかと言うと、こちらの続き。
siren v0.13 NURBS曲線・Bスプライン曲線 - C#ATIA

githubにUpされていた数値をそのままお借りして再挑戦しました。

#!siren
# coding: utf-8
include Siren

fName = "/nurbu3"
$inPath = ARGV[0] + fName + ".igs"
$exPath = ARGV[0] + fName + "-res.igs"
$dpPath = ARGV[0] + fName + "_dump.txt"

def wDump(i)
  if i.kind_of?(String)
     open($dpPath, "a") {|f| f.write "\r\n" + i}
  end
end

def Pause()
	str = gets
end

wDump("start")
###########

degree = 2
wDump(degree.to_s)

knots = [0.0, 1.0, 2.0]
wDump(knots.to_s)

mults = [3, 1, 3]
wDump(mults.to_s)

poles = [[10, 0, 7], [7, 0, 7], [3, 0, 8], [0, 0, 7]]
wDump(poles.to_s)

weights = [1.0, 1.2, 1.0, 1.0]
wDump(weights.to_s)

shp = Siren.bscurve degree, knots, mults, poles, weights, 0.1, 1.2
puts shp.class.name

Siren.save_model shp , $exPath
###########
wDump("end")
puts "done."
Pause()

ずっとエラーで、NURBS曲線が作れなかったのですがやっと出来ました。
Reference manualを見ながらやっていたのですが、

shp = Siren.bscurve [degree, knots, mults, poles, weights, 0.1, 1.2]

これ(角括弧付き)ではNGでした。 Rubyの括弧の扱いがわからない・・・。

siren v0.14 線の種類を判断する

こちらの続きです。
siren v0.14 を試してみました - C#ATIA

開発者の方にちょっとサンプルコードを書いていただいたのですが、
回答として書いて頂いたこと以上に、重要な方法がサンプルに入っていました。

#Siren_script Export_Curve_Test
include Siren

fName = "/curves"
$inPath = ARGV[0] + fName + ".igs"
$exPath = ARGV[0] + fName + "-res.igs"

def Pause()
	print "押して!"
	str = gets
end

###########
comp = Siren.load_model $inPath
p "total_edges : " + comp.edges().size.to_s

edgelst = comp.to_a.select { |x|
	x.edge? == true
}

edgelst = edgelst + comp.to_a.select { |x|
	x.wire? == true
}.edges.flatten

p "**************"
edgelst.each{|x|
	print x.to_s + "" +  x.curve.class.name + " です\n"
}

cmp = edgelst.to_comp

begin
	Siren.save_model cmp , $exPath
rescue
	p "export errer!"
end
 
###########
puts "done."
Pause()

結果はこちら。
f:id:kandennti:20170807184638p:plain
"BSCurve" は、BSplineCurveです。
GetEdgeType関数と言うクズ関数は、要りませんでした。

エッジのクラス名を取得すると Siren::Edge が返って来る為、線種を取得できないと
思い込んでしたのですが

  edge.curve.class.name

とすると線種か返ってきました。 エッジはエッジでカーブじゃないんですね。
少し理解が深まりました。