C#ATIA

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

バッチ処理前にマクロでモデルをチェックする

久々にPowerMillのマクロです。 かなり忘れています。

PowerMillで苦労している部分は多々あるのですが、
一番精神的にダメージを受けるのが、モデルのインポート。

お互いイロイロとライセンスが無い為、Igesで受け渡しを行っています。
どうやら苦労されているのは、僕だけではなく・・・
http://www.coe.org/p/fo/et/thread=29121
Stepでも面が抜け落ちたりしているようです。
(解決されたみたいですが)

時間のかかる処理を行った後に、
「あっここの小さな面が抜けてる・・・」
となると、途端にモチベーションが下がりまくります。
(でも、どのCAMソフトでも経験があるはず)


事前にデータをチェックし修復さえしていれば、かなりストレス軽減に
なるはずなので、マクロで処理してしまいます。

//pm2018 macro
//Find_Surface_Clearance.mac Ver0.0.2
//モデルの隙間とバッドサーフェスの検索

function Main() {
	real MeshTolDef = 0.005 //メッシュトレランス-デフォルト
	real ClearTolDef= 0.1 //隙間トレランス-デフォルト
	
	//**ユーザー選択**
	//モデル
	string msg = '隙間と不良面をチェックするモデルを選択してください'
	string list models = input entity multiple model $msg
	if is_empty(models) {
		return
	}
	
	//サーフェス方向
	$msg = 'サーフェス方向処理を行いますか?'
	bool NormalFg= 0
	$NormalFg= QUERY $msg
	
	//メッシュトレランス
	$msg = '不良面チェックトレランスを入力して下さい'	
	real MeshTol = $MeshTolDef 
	call InputReal($Msg, $MeshTolDef , $MeshTol )
	if $MeshTol  < 0 {
		return
	}	
	
	//隙間トレランス
	$msg = '隙間チェックトレランスを入力して下さい'	
	real ClearTol  = $ClearTolDef
	call InputReal($Msg, $ClearTolDef , $ClearTol )
	if $ClearTol   < 0 {
		return
	}

	//**処理**
	call DialogOff()
	
	//サーフェス方向
	if $NormalFg {
		call Exec_OrientNormals($models)
	} 
	
	//BadSurfaces
	call Exec_BadSurfaces($models, $MeshTol) 
	
	//バウンダリ作成
	call Create_Boundary($models , $ClearTol ) 
	
	call DialogOn()
	message info 'Done'
}

//不良面
function Exec_BadSurfaces(string list Models, real Tol) {
	EDIT MODEL ALL DESELECT ALL
	foreach name in $Models {
		EDIT MODEL $name SELECT ALL
	}	
	
	string nxtset = new_entity_name('Level')
	CREATE LEVEL ; MODELCOMPSET
	EDIT LEVEL $nxtset ACQUIRE SELECTED
	string cmd = 'EDIT LEVEL $nxtset MESH "' + string($Tol) +'"'
	DoCommand $cmd
	DELETE LEVEL $nxtset
	
	EDIT MODEL ALL DESELECT ALL	
	VIEW MODEL ; SHADE NORMAL
}

//サーフェス方向
function Exec_OrientNormals(string list Models) {
	EDIT MODEL ALL DESELECT ALL
	foreach name in $Models {
		EDIT MODEL $name SELECT ALL
		EDIT MODEL $name ORIENT_NORMALS SELECTED
	}	
}

//バウンダリ
function Create_Boundary(string list Models, real Tol ) {
	EDIT MODEL ALL DESELECT ALL
	string newname = ''
	foreach name in $Models {
		EDIT MODEL $name SELECT ALL
		$newname = $newname + $name + '_' 
	}	
	$newname = $newname + '_Checked-Tol_' + string($Tol)
	
	string Bouname = new_entity_name('Boundary')
	CREATE BOUNDARY ; SKETCH FORM BOUNDARY
	EDIT BOUNDARY $Bouname TOLERANCE $Tol
	EDIT BOUNDARY $Bouname INSERT MODEL
	
	RENAME BOUNDARY $Bouname $newname
	
	EDIT BOUNDARY $newname ACCEPT BOUNDARY ACCEPT
	EDIT MODEL ALL DESELECT ALL
}

//数値入力 不正時は-1を返す
function InputReal(string Msg, real Defreal, output real  Outreal) {
	$Outreal = -1
	real res = $Defreal
	$res = input $Msg
	bool err = 0
	$err = error $res
	if $err {
		message error '数値を入力して下さい!'
		return
	} 
	if $res <=0 {
		message error '0以上の数値を入力して下さい!'
		return
	} 	
	$Outreal = $res
}

//ダイアログ類オン
function DialogOn() {
	GRAPHICS UNLOCK
	DIALOGS MESSAGE ON
	DIALOGS ERROR ON
	ECHO ON DCPDEBUG TRACE COMMAND ACCEPT
}

//ダイアログ類オフ
function DialogOff() {
	GRAPHICS LOCK
	DIALOGS MESSAGE OFF
	DIALOGS ERROR OFF
	ECHO OFF DCPDEBUG UNTRACE COMMAND ACCEPT
}

マクロ実行後
・対象モデルの選択
・サーフェスの方向付け(任意)
・メッシュトレランス入力
・隙間トレランス入力
で自動的に、BadSurfcesの検出と隙間となるバウンダリを作成します。
(BadSurfcesは処理上で弊害となる不正面で、存在しているとツールパスを
 計算してくれません)

実際に試した感じです。

最初はモデルの色がグレーと茶色が整っていないのですが、
マクロ内で処理させています・・・が、最後にズームさせた位置に
反転した面があるんですよね。(完全じゃないです)

差分を抽出マクロ修正中

こちらの続きです。
マクロを直したい(愚痴) - C#ATIA

少しづつ時間が確保出来たので、修正しているのですが・・・。
こちらのマクロの問題点は、互いの面を総当りで比較している
と言う点です。
二つのボディ/形状セットを比較して、差分を抽出する - C#ATIA

過去に作ったこちらの8分木を無理やり適応させて、
組み合わせ総数を減らしているのですが、
単独な3D曲線の取得する3 - C#ATIA
・・・結果が一致しない。

f:id:kandennti:20170719185435p:plain
赤い面は総当りと8分木で同一の面を抽出できているのですが、
黄色い面は、本来抽出されるべきでない面で8分木のみで抽出されて
しまいます。


テストデータは、ちょこっと変更しただけで何度も送られてきたもの(腹が立つ)
2タイプで行っているのですが、両方とも8分木の方が6枚余計に抽出してしまいます。

面の一致(重心・表面積)を判断する段階で余計に抽出しているのではなく
8分木を利用して比較する為の組み合わせを見つける段階で
"比較相手が無し"
として抽出してしまっている所までは突き止めたのですが、
何処をどの様に直せば良いのかな・・・。

Autodesk OnDemand Webinars

Autodeskさんは取り扱い製品数が多すぎて、迷子になってしまう為
完全に個人的な覚書です。

https://www.autodesk.co.uk/campaigns/mfg-webinar/webinars-on-demand/cad-cam

最近はほぼ使用していないPowerMillなのですが、正直な所使いこなせて
いないですし、知らない使い方が大量に有り、メーカー主催のウェビナーは
非常にありがたい存在です。

リアルタイムなウェビナーに参加しても、恐らく英語な為ほぼ理解できない
ことは想定できる為、オンデマンドで一時停止・巻き戻しでアイコンを確認しながら・・・。
バージョンアップの新機能紹介動画より、遥かに実践的で助かります。

"Japan" 無いんですけど・・・
f:id:kandennti:20170718185852p:plain

Parasolidのインポートエラーを修復するVBS

こちらの続きです。
Parasolidのエラー2 - C#ATIA

少しづつ時間が確保出来たので、こちらを真剣に調べてみました。
結果的に・・・ どうやらスペース文字だったようです。
(使用したエディタではスペース文字が上手く検索できなかったのかな・・・)

2件続いた事例を考えると、小数点直後のスペース文字が原因だった為
それらを削除する為のVBScriptを作成しました。

Language = "VBSCRIPT"
'*********************************
'RepairX_TFile.vbs ver 0.0.1
'不要なスペース文字によるインポートエラーとなるParasolidファイルを修復
'*********************************

'*** 設定 変更しないで下さい ***
Const BeforeKey = ". "
Const AfterKey = "."
'***

Call Main
wscript.Quit 0

'*********************************
Sub Main()
    'D&D
    Dim DDlist 'As Variant
    DDlist = GetDropList(wscript.Arguments)
    If Not IsArray(DDlist) Then Exit Sub

    '確認
    Dim DDlistStr 'as String

    Dim Msg 'As String
    Msg = "以下のファイルをチェックします。よろしいですか?" + vbNewLine + _
      DDList2String(DDlist)
    If MsgBox(Msg, vbYesNo) = vbNo Then Exit Sub

    '処理
    Msg = ExecReplace(DDlist, BeforeKey, AfterKey)
    If Msg = vbNullString Then
        MsgBox "修正したファイルはありませんでした"
    Else
        MsgBox Msg + "の修正したファイルを作成しました"
    End If
End Sub

Private Function ExecReplace(ByVal Ary, ByVal Before, ByVal After)
    Dim i, Msg
    Msg = vbNullString
    For i = 0 To UBound(Ary)
        If IsCreateNewX_T(Ary(i), Before, After) Then
            Msg = Msg + Ary(i) + vbNewLine
        End If
    Next
    ExecReplace = Msg
End Function

Private Function IsCreateNewX_T(ByVal Path, ByVal Before, ByVal After)
    IsCreateNewX_T = False
    Dim txt
    txt = ReadFile(Path)
    If InStr(1, txt, Before) < 1 Then
        Exit Function
    End If
    
    Dim NewPath
    NewPath = GetNewName(Path)
    txt = Replace(txt, Before, After)
    Call WriteFile(NewPath, txt)
    IsCreateNewX_T = True
End Function

' *** D&D ***
'ドロップ処理
Private Function GetDropList(ByVal Args) 'As Variant
    Dim ArgsCount 'As Long
    ArgsCount = Args.Count
    If ArgsCount < 1 Then
        MsgBox "x_tファイル(パラソリッド)をD&Dして下さい"
        Exit Function
    End If

    Dim i 'As Long
    Dim X_tList() 'As Variant
    ReDim X_tList(ArgsCount)
    Dim X_tCount 'As Long
    X_tCount = -1
    Dim Path 'As Variant
    Dim ArgsPath 'As String
	
    'ContinueかGoto使いたかった・・・
    For i = 1 To ArgsCount
        ArgsPath = Args(i - 1)
        If IsExists(ArgsPath) Then
            Path = SplitPathName(ArgsPath)
            If Isx_tFile(Path(2)) Then
                X_tCount = X_tCount + 1
                X_tList(X_tCount) = JoinPathName(Path)
            End If
        End If
    Next
	
    If X_tCount < 0 Then
        Msg = "チェックするx_tファイル(パラソリッド)がありません!"
        MsgBox Msg, vbOKOnly
        Exit Function
    End If
    ReDim Preserve X_tList(X_tCount)
    GetDropList = X_tList
End Function

'Parasolidチェック 拡張子のみ
Private Function Isx_tFile(ByVal Ext) 'As Boolean
    Isx_tFile = False
    If UCase(Ext) = "X_T" Then Isx_tFile = True
End Function

'リストのファイルメイのみ取得
Private Function DDList2String(ByVal DDlist) 'As Boolean
    Dim Ts, ToStr, i
    ToStr = ""
    For i = 0 To UBound(DDlist)
        Ts = SplitPathName(DDlist(i))
        ToStr = ToStr + Ts(1) + "." + Ts(2) + vbNewLine
    Next
    DDList2String = ToStr
End Function


' *** IO ***
'FileSystemObject
Private Function GetFSO() 'As Object
    Set GetFSO = CreateObject("Scripting.FileSystemObject")
End Function

'パス/ファイル名/拡張子 分割
'Return: 0-Path 1-BaseName 2-Extension
Private Function SplitPathName(ByVal FullPath) 'As Variant
    Dim Path(2) 'As String
    With GetFSO
        Path(0) = .getParentFolderName(FullPath)
        Path(1) = .GetBaseName(FullPath)
        Path(2) = .GetExtensionName(FullPath)
    End With
    SplitPathName = Path
End Function

'パス/ファイル名/拡張子 連結
Private Function JoinPathName(ByVal Path) 'As String
    If Not IsArray(Path) Then Stop '未対応
    If Not UBound(Path) = 2 Then Stop '未対応
    JoinPathName = Path(0) + "\" + Path(1) + "." + Path(2)
End Function

'ファイルの有無
Private Function IsExists(ByVal Path) 'As Boolean
    IsExists = GetFSO.FileExists(Path)
End Function

'ファイル読み込み
Private Function ReadFile(ByVal Path) 'As Variant
    With GetFSO.GetFile(Path).OpenAsTextStream
        ReadFile = .ReadAll
        .Close
    End With
End Function

'ファイル書き込み
Private Sub WriteFile(ByVal Path, ByVal txt)
    With GetFSO.OpenTextFile(Path, 2, True)
        .Write txt
        .Close
    End With
End Sub

'重複しない名前取得
''' @param:Path-ファイルパス
''' @return:新たなファイルパス
Private Function GetNewName(ByVal OldPath)
    Dim Path
    Path = SplitPathName(OldPath)
    Path(2) = "." & Path(2)
    Dim NewPath
    NewPath = Path(0) + "\" + Path(1)
    If Not IsExists(NewPath + Path(2)) Then
        GetNewName = NewPath + Path(2)
        Exit Function
    End If
    Dim TempName, i
    i = 0
    Do
        i = i + 1
        TempName = NewPath + "_" + CStr(i) + Path(2)
        If Not IsExists(TempName) Then
            GetNewName = TempName
            Exit Function
        End If
    Loop
End Function

・複数ファイルをD&Dすることが可能です。
・処理後のファイルはD&Dしたファイルと同一フォルダ内に、
 「元のファイル名」+「_数字」+「.x_t」ファイルが出来上がり、元のファイルを上書きは
 行いません。
・過去の事例から、小数点直後に不要なスペース文字が入っていたため
 そのスペース文字を削除しているだけです。
 インポートエラーの全ての原因を修復する為のものでは有りません。

正直な所、客先のメール環境が原因のような気がするので、他人には全く役立たない
様な気がしてます。


週末この暑さの中、グランドを駆け回って疲労感たっぷりの月曜日に作っている為
不要な関数等が残っているかも・・・・。

マクロを直したい(愚痴)

最近忙しい一番の原因は、週に2~3回変更が入ってくる案件。
一体何時終わるのだろう・・・。

"あぁこんな事が出来るんだなぁ" 程度に思って作ったこちらのマクロが
活躍してくれます。

二つのボディ/形状セットを比較して、差分を抽出する - C#ATIA
サーフェスの色をボディに反映する2 - C#ATIA

活躍してくれるのはありがたいのですが、とにかく処理が遅い。
原因はわかっているし、何をすれば速くなるかもわかっているのですが、
直している暇がありません。


社名は記載しませんが、変更箇所が33ヶ所って別部品ですよ。
ものづくり辞めちゃった会社だから、仕方ないのかな・・・。

滑らかさを手に入れる

最近忙しかったのですが、一山だけ超えました。

二番目の原因が、リバースエンジニアリングな仕事のマネキンのモデリングです。
3Dスキャンしたものからサーフェス化したものの一部(背中)がこち

f:id:kandennti:20170707130316p:plain

フリースタイルなライセンスが無い為、ゼブラ表示が出来ません。
代わりに "サーフェスの曲率 - 屈折領域" で表示させると
細かなうねりが有りまくりな事がわかります。
f:id:kandennti:20170707130334p:plain
"もっとスキャンデータの時点でスムージングやれよ" と言うご意見が
正しいのですが、不慣れなソフト・時間的な制約が有り
ナカナカ思うように行きません。(最終的にこの面は不採用)

折角なので、ブログのネタとして
これを何とかしてスムーズな面に出来ないか? と挑戦してみました。
(面を重ねた状態の画像は、水色が元面 オレンジ色が処理後の面です)

・ラフオフセット-オフセット
ラフオフセットで一度オフセットし、同じ値を再度オフセットして見ました。
当方ライセンスがないためラフオフセット利用できないのですが、
こちらのグレーな方法を利用しています。
ライセンスの無いコマンドを使用する - C#ATIA
適切な値がわからないのですが、このような設定です。
f:id:kandennti:20170707130358p:plain
見た目の結果はこち
f:id:kandennti:20170707130407p:plain
f:id:kandennti:20170707130419p:plain
細かなシワシワが無くなっています。
但し処理時間が結構かかるんですよね、ラフオフセット。

・スケーリング
単純にスケーリングで1/1000にし、再度1000倍します。
f:id:kandennti:20170707130433p:plain
f:id:kandennti:20170707130449p:plain
重ねた画像を見てもわからないぐらい、ほぼ効果がありません


ここからは、履歴を捨てた方法です。

・スケーリング-Iges
スケーリングで1/1000にしIgesでエクスポート。再度インポートし
1000倍します。
f:id:kandennti:20170707130457p:plain
f:id:kandennti:20170707130505p:plain
"悪い悪い" と言われているIgesですが、再現性が良く
ほぼ効果がありません。

・スケーリング-model
スケーリングで1/1000にしmodel(V4フォーマット)でエクスポート。
再度インポートし1000倍します。
f:id:kandennti:20170707130515p:plain
f:id:kandennti:20170707130524p:plain
面が2枚に分かれてしまいましたが、オプションの設定で
1枚で取り込むことが可能かと思います。
V4のトレランスの甘さを利用している為、効果をかなり感じます。

Fusion360-スケーリング-Iges
Fusion360のスケーリングで1/1000し、CATIAで1000倍します。
f:id:kandennti:20170707130544p:plain
f:id:kandennti:20170707130552p:plain
CATIAと大差無く、ほぼ効果がありません。


Fusion360-Tスプライン
Fusion360にはTスプラインがあるので、単純にBrep→Tスプライン
→Brepにしてみます。
Tスプライン化の際の分割数は、適切な値がわからないのですが
とりあえず 20x20 で行ってみました。(最大は100っぽいです)
f:id:kandennti:20170707130606p:plain
f:id:kandennti:20170707130615p:plain
f:id:kandennti:20170707130623p:plain
効果を実感します。


実は、このテストの最大の目的はデータの軽さです。
以前、客先より "データが重くてCAMで処理できない" と
クレームを頂いたので・・・。
軽さをどの様に比較すべきか? がよくわかっておりませんが
全てIgesでエクスポートし、サイズを比較してみます。
各ファイル名はこの様になっています。

・元のデータ : smooth_test1-Original.igs
・ラフオフセット-オフセット : smooth_test2-Rough_Offset.igs
・スケーリング : smooth_test3-Scaling.igs
・スケーリング-Iges : smooth_test4-Scaling-iges.igs
・スケーリング-model : smooth_test5-Scaling-model.igs
Fusion360-スケーリング-Iges : smooth_test6-fusion-Scaling-iges.igs
Fusion360-Tスプライン : smooth_test7-fusion-Tspline.igs

結果はこち
f:id:kandennti:20170707130635p:plain
視覚的にもそうでしたが、”スケーリング-model”と ”Fusion360-Tスプライン”が
効果を実感できます。
特にTスプラインの場合はプレビューされる為、分割数を調整する事で
案外良いのかもしれません。(個人的にはmodel方式を利用しますが)
それにしてもラフオフセットのデータの巨大さにはガッカリ・・・。

本来であれば、ある程度碁盤の目のようにワイヤーを作成し
ロフト・ブレンド・フィル辺りを利用して行うのが正攻法なのかも
しれないのですが、結構手間がかかるんですよね。
他にもお手軽に行える方法はあるのかな?

今回試しませんでしたが、Space-eの場合はサーフェスのUVの本数を
減らす事で滑らかさを手に入れることが可能だと思います。

もう一件あるんだよなぁ案件が・・・

Parasolidのエラー2

こちらの続きです。
Parasolidのエラー - C#ATIA

これの続きを書くと思っていませんでした・・・。


新規に支給されたParasolidファイル、再び変換できなかったので
前回の出来事を教訓に、エディタで検索したもののHitせず。
断念して再度支給してもらいました。

前回同様比較してみると、
f:id:kandennti:20170623183013p:plain
やっぱり。 前回はてっきりスペース文字だと思っていたのですが
どうやらスペースでは無く、表示されない何かの文字のようです。

この文字を何とか見つけ出す良い方法は、無いもんですかね?