C#ATIA

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

PMillマクロ速度比べ2

こちらの続き? です。
PMillマクロ速度比べ - C#ATIA

週末に思い付いたので、テストしてみました。

〇配列とリスト
PMillには配列とリストがあるのですが、あまり配列は使った事が無いです。
単純にINT型を1~100までの値を持つ両方を作成する時間を
比べてみました。
・配列

//pm2018 macro arrya
function main() {
	call Sw_Start()
	int array lst[] = fill(100,0)
	int i = 0
	foreach idx in lst {
		$lst[i] = $i + 1
		$i = $i + 1
	}
	string time = ''
	call Sw_GetTime($time)
	message info  $time
}

//clock on
function Sw_Start() {
	CLOCK RESET QUIT
	CLOCK ON QUIT	
}

//clock off
function Sw_GetTime(output string out) {
	string $TraceFilePath = macro_path(false) + "\clock.txt"
	string list txts = {}
	ECHO OFF DCPDEBUG UNTRACE COMMAND ACCEPT
	TRACEFILE OPEN $TraceFilePath
	CLOCK OFF QUIT
	CLOCK PRINT QUIT
	TRACEFILE CLOSE
	ECHO ON DCPDEBUG TRACE COMMAND ACCEPT
	
	FILE OPEN $TraceFilePath FOR READ AS Input
	FILE READ $txts FROM Input
	FILE CLOSE Input
	DELETE FILE $TraceFilePath

	$out = $txts[0]
}

結果は4.5秒弱でした。

・リスト
同様の結果を得るだけなのですが、リストを拡張する為のadd_lastメソッドが
遅いのではないかな? と感じていた為です。

//pm2018 macro list
function main() {
	call Sw_Start()
	int list lst = {}
	int i = 0
	foreach s in fill(100,"") {
		$i = add_last($lst, $i+1)
	}
	string time = ''
	call Sw_GetTime($time)
	message info  $time
}
・・・

時間測定の為の関数は同様です。
結果は、2.5秒弱でした。add_lastは遅く無かったです。


〇ThicknessSetValuesのMode取得
ThicknessSetValuesのModeの取得する際、1つのツールパスの16個をまとめて
リストとして取得したいのですが、こんな感じに書くとエラーになります。

	object list tvs = $tp.ThicknessSetValues
	
	string list mode = extract($tvs, 'Mode')

ThicknessSetValuesのModeは、デバッガ上では文字列に見えるのですが、
実際はEnum型の為、"string list" ではNGなんです。
(しかし、マクロではEnum型が使えない)

・ForEach
一個だけの取得では文字列として受け取れるので、直接パラメータの
値を取得してみました。

//pm2018 macro ThicknessSetValues Mode Foreach
function main() {
	call Sw_Start()
	string list mode = {}
	int dmy = 0
	foreach tp in folder('toolpath') {
		object list tvs = $tp.ThicknessSetValues
		$mode = {}
		foreach $tv in $tvs {
			$dmy = add_last($mode, string($tv.Mode))
		}
	}
	string time = ''
	call Sw_GetTime($time)
	message info  $time
}

あるプロジェクトファイルで試した所、結果は8秒前後です。


・join_tokens
Enum型のリストを直接 "string list" としては受け取れない為、
変数に代入する前にJoinし再度tokensし、強引に string list化
しました。(思い付きで試した所、動きました)

//pm2018 macro ThicknessSetValues Mode joint_tokens
function main() {
	call Sw_Start()
	string list mode = {}
	int dmy = 0
	foreach tp in folder('toolpath') {
		object list tvs = $tp.ThicknessSetValues	
		$mode = tokens(join(extract($tvs, 'Mode'),','),',')	
	}
	string time = ''
	call Sw_GetTime($time)
	message info  $time
}
・・・

結果は1秒弱でした。 結構無理やりでも取得できるっぽいです。

HELP EDIT TOOLPATH

最近、加工をあまりしていなかったのでPowerMillネタから離れていましたが
フォーラムにはチョロチョロ参加してます。

今日教わった内容はこちら
Solved: command list - Autodesk Community
「Helpに載ってないコマンド類はこれで調べるしか方法無いよ」と、
AutodeskのPowerMillでは重鎮、5axisさんから直々にDMしてもらいました。

以前、これを読んだいたのに忘れていたので、覚書。

DrawingTextの中心座標

DrawingTextの中心座標を取得したい との記載を見て思い付きで書きました。
Size of the textbox on a drawing - DASSAULT: CATIA products - Eng-Tips
最初に、”遅いよ” って書いたんですけどね。

リトルクトゥルフさんがアッサリ答えを書いてくれました。
・・・やっぱりレベルが違いすぎですね。

コードが書かれていなかったので、作ってみたものの
リーダー(引き出し線)の削除でエラーになっちゃいます。

DrawingText.Leaders.Remove(0)

ん~ エラーにはなるものの削除は出来てます。
仕方ないので On Error Resume Next でエラーを回避するように
したのは良いのですが、すっきりしない。

探しまくってやっとCOEの記載を発見しました。
COE : Forums : Text box size
どうやっているのかな? と思い見てみると
やっぱり On Error Resume Next してます・・・。

僕だけじゃないようなので、すっきり。

VBA 言語環境による挙動の違い

先日のマクロですが、上手く動かないらしいのです。
draw with a catia all the Dual Geodesic Icosahedra - DASSAULT: CATIA products - Eng-Tips

原因が良くわからないのですが、CATIAのリリース違いが
影響するような程の最新の機能は使っていないはずです。

知識が無い為何とも言えないのですが、残る可能性は
言語の違いかと思っています。
マクロの内容的に、処理を速めるために正規表現を利用しているのですが
この辺がエンコードで上手く機能しないとか、エクスポートしたVBAファイル
(~.bas,~cls)が、他の言語だと文字化けし機能しないとか・・・。

何か情報をお持ちの方、教えて頂けると助かります。

Dual Geodesic Icosahedra3

こちらの続きです。
Dual Geodesic Icosahedra2 - C#ATIA

完成したので、テストデータと共にGrabCADにUpしました。
恐らく誰にも役には立たないでしょう。
3D CAD Model Collection | GrabCAD Community Library
結局一番苦労したのは、正規表記のパターンでした。
未だに宝探しをしている気分です。


面の作成に失敗していた理由がわかりました。
Visual PolyhedraのサイトにUpされている座標データの中に
こんな感じの☆型の面を、5個の頂点だけで表現している
データがあります。
f:id:kandennti:20180626165307p:plain
フィルサーフェスを利用して面を作成している為、こんな感じの自己交差
した状態ではエラーになる為、面が抜けてしまったようです。
対応策を考えるのも面倒な為、そのままにしました。

実は、こんなスケッチでもFusion360は面が作れるんですよね。
こちらでそれを利用したものを作りました。
Solved: How to remove inner sketch lines from an intersection sketch? - Autodesk Community
スケッチの考え方の違いを利用しています。


Upしたマクロファイルの "SurfaceFactory.cls" ですが(生意気なネーミングで申し訳ないのです)
このマクロだけではなく、他にも利用できるように考えて作っています。
英語じゃ書けそうになかったので、こちらで説明を。

3D点:array(double,double,double) でXYZの順です。都合上ArrayVariantです。
一枚の面:array(3D点,3D点,3D点…)です。各頂点を表す為、当然3点以上が必要です。
複数の面:array(一枚の面,一枚の面,一枚の面・・・)です。

一枚だけ面を作成したい場合は、ary(ary,・・・) な感じです。

Sub Example_Single()
    'パートドキュメント
    Dim doc As PartDocument: Set doc = CATIA.Documents.Add("Part")
    
    '座標値
    Dim pos As Variant
    pos = Array(Array(0, 0, 0), Array(1, 0, 0), Array(0, 1, 0))
    
    'SurfaceFactoryインスタンス
    Dim surfFact As SurfaceFactory: Set surfFact = New SurfaceFactory
    
    '面を作成するパートドキュメントをセット
    Call surfFact.SetPartDoc(doc)
    
    '座標値から面を作成 - 形状セットには入りません!
    '戻りは HybridShapeSurfaceExplicit
    Dim surf As HybridShapeSurfaceExplicit
    Set surf = surfFact.CreateSurf(pos)
    
    '形状セットに挿入
    Dim hBody As HybridBody: Set hBody = doc.Part.hybridBodies.Add()
    Call hBody.AppendHybridShape(surf)
    
    'インスタンス破棄 - 破棄することで内部の一時的なものを削除します。
    Set surfFact = Nothing
End Sub

複数面であれば、ary(ary(ary,・・・),・・・) な感じです。

Sub Example_Multi()
    'パートドキュメント
    Dim doc As PartDocument: Set doc = CATIA.Documents.Add("Part")
    
    '座標値郡
    Dim posary As Variant
    posary = Array( _
                Array(Array(0, 0, 0), Array(1, 0, 0), Array(0, 1, 0)), _
                Array(Array(0, 0, 0), Array(0, 1, 0), Array(-1, 1, 0)), _
                Array(Array(0, 0, 0), Array(-1, 0, 0), Array(0, -1, 0)), _
                Array(Array(0, 0, 0), Array(0, -1, 0), Array(1, -1, 0)))
    
    'SurfaceFactoryインスタンス
    Dim surfFact As SurfaceFactory: Set surfFact = New SurfaceFactory
    
    '面を作成するパートドキュメントをセット
    Call surfFact.SetPartDoc(doc)
    
    '座標値郡から面郡を作成 - 形状セットには入りません!
    '戻りは Collectiont
    Dim surfs As Collection
    Set surfs = surfFact.CreateSurfs(posary)
    
    '形状セットに挿入
    Dim hBody As HybridBody: Set hBody = doc.Part.hybridBodies.Add()
    Dim surf As HybridShapeSurfaceExplicit
    For Each surf In surfs
        Call hBody.AppendHybridShape(surf)
    Next
    
    'インスタンス破棄 - 破棄することで内部の一時的なものを削除します。
    Set surfFact = Nothing
    
End Sub

で、折れ線とフィルで作成可能な面が作れます。
その為、STLや3DDXF等のポリゴンっぽいものも、座標値配列にさえすれば
流用可能です。 恐らく使わないですが。

Dual Geodesic Icosahedra2

こちらの続きです。
Dual Geodesic Icosahedra - C#ATIA

結局、格好悪い方法で挑戦中。
やっと形になるようにはなりました。
f:id:kandennti:20180625200138p:plain

但し、自己交差しているタイプのもので、何面か抜けるものがあり
原因調査中。
接合するわけじゃないので、自己交差が原因の訳ではないような
気がしているのですが・・・。

Dual Geodesic Icosahedra

こちらに楽しそうなネタが。
draw with a catia all the Dual Geodesic Icosahedra - DASSAULT: CATIA products - Eng-Tips

リンクされているHelpのページ・・・探しましたよ。
f:id:kandennti:20180619172750p:plain
GSDの真ん中ぐらいにありました。

何処にマクロがあるのかな? と思っていたらExcelにマクロが入ってました。
ご興味あれば是非。
(僕が使用しているPCでは動かないです)

'Dual Geodesic Icosahedra' を、マクロじゃなくてパラメータで
イロイロと変更出来るファイルが作れると、カッコイイと思うのですが。
これみたいに。
3D CAD Model Collection | GrabCAD Community Library