C#ATIA

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

siren v0.14 を試してみました

こちらの続きです。
siren v0.13 線の種類を判断する - C#ATIA

sirenをv0.14にして頂きました。
Release siren v0.14(draft version) binary package for MS-Windows · dyama/mruby-siren · GitHub

ナカナカ取り掛かれ無い為、前回のスプリクトをv0.13とv0.14で
実行してみたのですが
f:id:kandennti:20170807124424p:plain
左がv0.13で右がv0.14です。
to_sメソッドの表記が変わったのは良いのですが、
最後の2本の線種が "curve" から "circle" になってしまい
正しく判断出来なくなりました・・・。
恐らくnurbs_defメソッドが機能しなくなっているような気がしてます。

nurbs_defメソッドが利用できないとなると、苦しいところです。

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

こちらの続きです。
siren v0.13 線の種類を判断したい - C#ATIA

業務が忙しく・・・。
こんな感じのデータを作り、Igesでエクスポート。
f:id:kandennti:20170801202910p:plain
"直線" "円弧" "曲線" "点" "サーフェス" "ソリッド" が
混在しています。 このIgesから境界線等ではない
純粋な線の要素を抜き出します。

又、抜き出した線の種類を標準出力に表示します。

#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

def GetEdgeType(shp)
	return unless shp.edge?
	begin
		return "curve" unless shp.nurbs_def.size < 1
	rescue
	end
	
	begin
		return "line" if shp.to_pts.size < 3
	rescue
	end
	
	return "circle"
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 + "" +  GetEdgeType(x) + " です\n"
}

cmp = edgelst.to_comp

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

悩んだ挙句、GetEdgeType関数を作り、各メソッドが成功するか?どうか?
で線のタイプを判断する と言うかなりベタな方法しか思い付かない
上に、Rubyっぽさの微塵も感じないコードになりました。
(本来なら、もっと素敵なコードで実現できるはず・・・)

実行結果はこちらで、出来上がったIgesをインポートすると
f:id:kandennti:20170801202921p:plain
判断も出来てます。
本当は ".edge_type" みたいにしたいんだけどなぁ。

siren v0.13 線の種類を判断したい

こちらの続きです。
siren v0.13 NURBS曲線・Bスプライン曲線 - C#ATIA

通過点を指定するスプラインを試したところ出来たので、
NURBS曲線・Bスプライン曲線はちょっと諦める事にしました。

次に線が "直線" "円弧" "曲線" を判断出来るようにしたい
所なんです。

こんなデータをIgesで吐き出し
f:id:kandennti:20170727182716p:plain
それを試しに読み込んで調べてみました。
試していくうちに、直線・円弧・曲線・面・点となってしまい
変数名等がおかしいですが・・・

#
include Siren

fName = "/curves"
$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()
  print "押して!"
  str = gets
end

open($dpPath, "w") {|f| f.write "start"}
###########
crvs = Siren.load_model $inPath
p "total : " + crvs.subshapes.size.to_s
shps = crvs.to_a

begin
 shps.each{|shp|
  p "***"
  p "to_s : " + shp.to_s	
  p "shapetype : " + shp.shapetype.to_s
  #p shp.shapetype.to_sname -ng
  #p shp.curvetype -ng
  #p shp.geomtype -ng
  #p shp.siren_curve_type -ng
 }
rescue
 p $@
end
###########
wDump("end")
puts "done."
Pause()

読み込んだIgesをバラシ、ループさせて1個づつ調べているのですが
f:id:kandennti:20170727182736p:plain
やっと見つけたshapetypeで、線の種類を判断できると思ったの
ですが、直線・円弧・曲線 全て "6" が返って来ており
判断できません・・・。(恐らくSiren::Edgeが返って来ているのでしょう)

こちらにあったテストコードの最後の方に
mruby-siren/mruby-siren.rb at ae31b439725ec39b5c998239a547f0ca15ce6385 · dyama/mruby-siren · GitHub
".shapetype.to_sname" を見つけたのですが、エラーになります。
(コード的にv0.13のものでは無いので・・・)

他にも "curvetype" "geomtype" "siren_curve_type" 等、それっぽい
ものも試したのですが全てダメでした。

ん~諦めようかな・・・。

siren v0.13 NURBS曲線・Bスプライン曲線

こちらの続きです。

行き詰まり感たっぷりなのですが、ちょっと試してみたい事が
あったので引き続き挑戦。

こちらの何でもない3Dな曲線をCATIAで作成しIgesでエクスポート。(curve1.igs)
f:id:kandennti:20170727152855p:plain
続いてSirenスプリクトをこんな感じで作成します。

#
include Siren

fName = "/curve1"
$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

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

shp = Siren.load_model $inPath
wDump(shp.to_s)
wDump(shp.nurbs_def.to_s)
Siren.save_model shp, $exPath

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

何をしているかと言いますと、CATIAで作成したIgesを
Sirenで読み込み、再度別名のIgesでエクスポートしているだけです。
但し、途中で読み込んだ曲線の次数やノットベクトル等の情報を
ダンプさせています。

ダンプさせた内容がこちら

start

#<Shape:0x27577e8 @type=EDGE>

[5, 

[0, 17.39738523, 28.8962564, 39.23864718, 50.07377854, 67.53908293], 

[6, 3, 3, 3, 3, 6], 

[#<Vec:0x27573a5 @x=10.000000, @y=-20.000000, @z=-10.000000>,
 #<Vec:0x2757395 @x=9.587310, @y=-19.663785, @z=-7.111170>,
 #<Vec:0x2757345 @x=9.066687, @y=-19.247257, @z=-4.318377>,
 #<Vec:0x2757335 @x=8.414916, @y=-18.739432, @z=-1.647258>,
 #<Vec:0x27572e5 @x=7.064933, @y=-17.728351, @z=2.468286>,
 #<Vec:0x27572d5 @x=5.183948, @y=-16.463305, @z=5.802195>,
 #<Vec:0x2757285 @x=4.342483, @y=-15.922227, @z=6.978457>,
 #<Vec:0x2757275 @x=2.558949, @y=-14.842477, @z=8.853440>,
 #<Vec:0x2757225 @x=0.445590, @y=-13.724272, @z=9.964573>,
 #<Vec:0x2757215 @x=-0.623246, @y=-13.198986, @z=10.301741>,
 #<Vec:0x27571c5 @x=-2.929444, @y=-12.162037, @z=10.599622>,
 #<Vec:0x27571b5 @x=-5.413111, @y=-11.251836, @z=10.141983>,
 #<Vec:0x2757165 @x=-6.714933, @y=-10.831739, @z=9.723114>,
 #<Vec:0x2757155 @x=-10.156001, @y=-9.869701, @z=8.217441>,
 #<Vec:0x2757105 @x=-13.650081, @y=-9.267638, @z=5.788367>,
 #<Vec:0x27570f5 @x=-15.795199, @y=-9.037527, @z=4.030341>,
 #<Vec:0x27570a5 @x=-17.911583, @y=-8.933958, @z=2.088417>,
 #<Vec:0x2757095 @x=-20.000000, @y=-8.944927, @z=0.000000>],

[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],

0, 

67.53908293]

end

恐らく、(僕を含めて)何の事だか判らないだろうと思います。

開発者の方のこちらを参考に見てみると
OpenCASCADE で NURBS 曲線を作成する – dyama's page
ん~ 引数multsの説明がされていました。

ダンプさせた際の
[0, 17.39738523,・・・
が、multsに該当するのかと思ったのですが、説明書きとは違います。
OpenCascadeと引数の順番が違うのも、ちょっと気になるのですが・・・。

イロイロやっているのですが、上手く行かないなぁ。

siren v0.13 再び挑戦してみる2

こちらの続きです。
siren v0.13 再び挑戦してみる - C#ATIA

既に諦めかかってます。 欲しかったのは3Dな曲線で
NURBS曲線・Bスプライン曲線辺りです。

GitHubの "シェイプ生成メソッド" を参考に テストされたスプリクトコードを
試しているのですが、上手く出来ないです・・・。

include Siren

degree = 2
knots = [0.0, 1.0, 2.0]
mults = [3, 1, 3]
poles = [[10, 0, 7], [7, 0, 7], [3, 0, 8], [0, 0, 7]]
weights = [1.0, 1.2, 1.0, 1.0]

bs = Siren.curve[bscurve.new[degree, knots, mults, poles, weights], 0.1, 1.2]
Siren.save_model bs, ARGV[0] + "/bs.igs"

puts "done."

数値的にはUpされていたテストコードのまま(と言いますか、ほぼそのまま)
ダメなんです。 デバッグの方法がわからないので、ちょっと変えては実行しか
方法がわからないんです。 ん~ 一日で諦めちゃおうかな・・・。

siren v0.13 再び挑戦してみる

昨日ちょっと良い事を思いついたので、1年半ぶりぐらいにsiren
再挑戦する事にしました。

以前利用させてもらった時は "v0.11" だったのですが、
最新版は "v0.13" です。

こちらで作ったsirenスプリクト実行用vbsを参照先パスだけ
変更したのですが、ダメでした。
Sirenテスト-polygon - C#ATIA

sirenの実行ファイル名やファイル位置等がv0.12 → v0.13で
大きく変更されたりしたようです。
ついでにD&Dで実行するように修正してみました。

'vbs SirenTestStart013.vbs
'D&DによるSirenスプリクト実行  Siren v0.13用
Language = "VBSCRIPT"

'*** setting ***
'mruby.exe(Siren)ファイルのフルパス
SirenPath="C:\siren\siren_0.13_mingw32\bin\mruby.exe"
'******

Main()
WScript.Quit 0

Sub Main()
    If wscript.Arguments.Count < 1 Then
        MsgBox "SirenスプリクトファイルをD&Dして下さい"
        Exit Sub
    End If	
    Dim Args : Args = wscript.Arguments(0)
    Dim fso : set fso = createObject("Scripting.FileSystemObject")
    Dim ScriptPath : ScriptPath = Replace(fso.getParentFolderName(Args), "\", "/")
    Dim ScriptName : ScriptName = fso.GetFileName(Args)
    Dim WshShell : Set WshShell = CreateObject("WScript.Shell")
    Call WshShell.Run(SirenPath + " " + ScriptPath + "/" + ScriptName + " " + ScriptPath, 1, False)
End Sub

D&Dは1ファイルだけにしています。(他にもイマイチな部分多数)

こちらのサンプルをお借りし、エクスポートフォーマットを変更したりし
テストしてみました。
mruby-siren/tree.rb at master · dyama/mruby-siren · GitHub

#!/usr/bin/siren
# coding: utf-8
#
# fractal tree 
#
include Siren
expFileName = ARGV[0] + "/tree"

$start_len = 100.0

def tree(cur_pt, dir, len)
  nxt_pt = cur_pt + dir * len
  edges = [ line(cur_pt, nxt_pt) ]
  len *= 0.75
  if len > $start_len / 10.0
    edges.concat tree(nxt_pt, dir.rotate(Vec.ydir, 30.0.to_rad), len)
    edges.concat tree(nxt_pt, dir.rotate(Vec.ydir, -30.0.to_rad), len)
  end
  return edges
end

lines = tree([0, 0, 0].to_v, Vec.zdir, $start_len)

comp = lines.to_comp
Siren.save_iges comp, expFileName + ".igs"
Siren.save_step comp, expFileName + ".stp"

puts "done."

スプリクトの書式も少し変更されたような・・・。
Stepフォーマットのエクスポートがサポートされてるんですよ。
f:id:kandennti:20170726154324p:plain
無事出来ました。
StepファイルがIgesファイルの10倍ぐらいのサイズなんですが、
こんなもんなんですかね?

3Dの点をリンク付きでスケッチ投影

COEでこちらの記述を見て、作ってみました。
http://www.coe.org/p/fo/st/thread=29815

レスしたものはインデントが消えてしまっているので

Sub CATMain()
    'HybridBody-Points
    Dim HBdy As HybridBody
    Set HBdy = SelectItem("Select a HybridBody : ESC = Cancel", Array("HybridBody"))
    If HBdy Is Nothing Then Exit Sub
    
    'Part
    Dim Pt As Part: Set Pt = GetParent_Of_T(HBdy, "Part")
    If Pt Is Nothing Then Exit Sub
    
    'Point Refs
    Dim PntRefLst As Collection: Set PntRefLst = GetPntRefs(HBdy, Pt)
    If PntRefLst Is Nothing Then Exit Sub
    
    'Sketch_Support
    Dim Pln As Plane
    Set Pln = SelectItem("Select a Sketch_Support_Plane : ESC = Cancel", Array("Plane"))
    If Pln Is Nothing Then Exit Sub
    
    'Part Check
    Dim TmpPt As Part: Set TmpPt = GetParent_Of_T(Pln, "Part")
    If Not (Pt Is TmpPt) Then
        MsgBox "Please choose the Plane of the same Part!"
        Exit Sub
    End If
    
    'HybridBody_Sketch
    Dim NewHbdy As HybridBody: Set NewHbdy = Pt.HybridBodies.Add()
    Dim Skt As Sketch: Set Skt = InitSketch(NewHbdy, Pt.CreateReferenceFromObject(Pln))
    
    'Projection
    Call ProjectionPnts(Skt, PntRefLst)
    Pt.UpdateObject Skt
    
    MsgBox "Done"
End Sub

'点投影
Private Sub ProjectionPnts(ByVal Skt As Sketch, ByVal PntRefLst As Collection)
    Dim Fact2D As Factory2D
    Dim Ref As Reference
    Dim Geos As GeometricElements
    
    On Error Resume Next
        Set Fact2D = Skt.OpenEdition()
        For Each Ref In PntRefLst
            Set Geos = Fact2D.CreateProjections(Ref)
            Geos.Item(1).Name = Ref.DisplayName
        Next
        Skt.CloseEdition
    On Error GoTo 0
End Sub

'スケッチ生成
Private Function InitSketch(ByVal HBdy As HybridBody, ByVal SktSptRef As Reference) As Sketch
    Set InitSketch = HBdy.HybridSketches.Add(SktSptRef)
End Function

'点リファレンス取得
Private Function GetPntRefs(ByVal HBdy As HybridBody, ByVal Pt As Part) As Collection
    Set GetPntRefs = Nothing
    
    Dim HShps As HybridShapes: Set HShps = HBdy.HybridShapes
    If HShps.Count < 1 Then Exit Function
    
    Dim Fact As HybridShapeFactory: Set Fact = Pt.HybridShapeFactory
    
    Dim PntRefLst As Collection: Set PntRefLst = New Collection
    Dim HShp As HybridShape
    For Each HShp In HShps
        If Fact.GetGeometricalFeatureType(HShp) = 1 Then
            PntRefLst.Add Pt.CreateReferenceFromObject(HShp)
        End If
    Next
    If PntRefLst.Count < 1 Then Exit Function
    
    Set GetPntRefs = PntRefLst
End Function


'選択
''' @param:Msg-メッセージ
''' @param:Filter-array(string),string 選択フィルター(指定無し時AnyObject)
''' @return:AnyObject
Private Function SelectItem(ByVal Msg$, _
                           Optional ByVal Filter As Variant = Empty) _
                           As AnyObject
    Dim SE As SelectedElement
    Set SE = SelectElement(Msg, Filter)
    
    If IsNothing(SE) Then
        Set SelectItem = SE
    Else
        Set SelectItem = SE.Value
    End If
End Function

'選択
''' @param:Msg-メッセージ
''' @param:Filter-array(string),string 選択フィルター(指定無し時AnyObject)
''' @return:SelectedElement
Private Function SelectElement(ByVal Msg$, _
                           Optional ByVal Filter As Variant = Empty) _
                           As SelectedElement
    Dim Sel As Variant: Set Sel = CATIA.ActiveDocument.Selection
    Sel.Clear
    Select Case Sel.SelectElement2(Filter, Msg, False)
        Case "Cancel", "Undo", "Redo"
            Exit Function
    End Select
    Set SelectElement = Sel.Item(1)
    Sel.Clear
End Function

'T型のParent取得 Nameでのチェックも必要
''' @param:AOj-AnyObject
''' @param:T-String
''' @return:AnyObject
Private Function GetParent_Of_T(ByVal AOj As AnyObject, ByVal t$) As AnyObject
    If TypeName(AOj) = TypeName(AOj.Parent) And _
       AOj.Name = AOj.Parent.Name Then
        Set GetParent_Of_T = Nothing
        Exit Function
    End If
    If TypeName(AOj) = t Then
        Set GetParent_Of_T = AOj
    Else
        Set GetParent_Of_T = GetParent_Of_T(AOj.Parent, t)
    End If
End Function

作ったものは、スケッチから全て作ってしまうマクロなんですが、
質問者の望んでいるものは、手動でスケッチに投影したものの
リンク元の名前に取得したい ってことだろうと
レスした後に気が付きました・・・。