[FreeCAD使い方講座] Pythonコンソールから操作する方法③ ~ 翼形状をスクリプトで生成する


2021/02/15

複雑形状の代表格と言えば、タービンローターなどの翼形状などが挙げられます。

参考としてちょうど
こちらの技術リファレンス(参照:FreeCAD 翼形状の作成 - Xsim)で、手動によるシンプルな羽根形状の作成手順をまとめていらっしゃるので、これに後追いする形で手順をPythonマクロ化することを今回この記事の中で検討してみます。

なお以前の関連記事は以下のリンクになります。


DraftからPartへ ~ ワイヤーモデルからソリッド化まで

前回はDraftモジュールからベシェ曲線・Bスプライン曲線の作成方法を詳しく解説していきました。

今回は予告していた通りの内容で、Partモジュールを使ったソリッド化のポイントを掘り下げていきます。

PythonスクリプティングではGUIによる操作に特化したSketcherではなく、よりコアなモジュールであるDraftを中心に使ってモデリングしていく流れになります。

最終的なソリッド化を上手く成功させるコツとしては、Draftモジュールでの強力な機能である、
アップグレードダウングレードの機能を良く理解しておく必要があります。

そこでまずはDraftオブジェクトで混乱必至な、
エッジワイヤーフェイスに関して復習しておきます。

Draftオブジェクトの変換

Dfartモジュールでは、形状によってFreeCADの4つの内部状態(エッジワイヤーフェイスシェル)を自由に転移操作することができます。

            エッジ:
    点か辺のどちらかの1つのオブジェクト。
    これ以上は分解できない最小の構成要素
ワイヤー:
    複数のエッジをグループ化したユニットを表すオブジェクト
フェイス:
    閉じたワイヤーによって面を定義したオブジェクト
シェル:
    複数のフェイスで閉じた空間を定義したオブジェクト
        
合同会社タコスキングダム|蛸壺の中の工作室

ここでいうオブジェクトのランクという考え方とは、最低位をエッジ、最高位をシェルとみなした状態の格付けになります。

よってより低位に状態を遷移させる操作を
ダウングレード、上位に遷移させる操作をアップグレードと表現しているのもなんとなく分かっていただけると思います。

この操作を以下でもう少し掘り下げてみましょう。

アップグレード

アップグレードはより低位のオブジェクトを高位のオブジェクトに転移させる操作です。

一例を挙げると、下の図のように個別の辺から面を張ったり、閉スプラインのフェイスと面合成したりすることがアップグレード一つで行うことができます。

合同会社タコスキングダム|蛸壺の中の工作室

ということで、
アップグレードの変換則をまとめると以下です。

変換前の状態

変換後

複数のエッジ(ただし切断していない)

閉じたワイヤー

開いたワイヤー

閉じたワイヤー

閉じたワイヤー

(一つの)フェイス

複数のフェイス(同一平面)

和集合として統合された一つのフェイス

複数のフェイス(立体的に閉じている)

シェル(閉じたソリッド)

ダウングレード

ダウングレードに関してもやってみます。一見アップグレードの逆操作のようにも考えられますが、一部不可逆的な操作(差集合を取るとオリジナルの面が消える)も含みます。

ユースケースとしては面の細かな修正をするときに、個別のエッジレベルでの手直しなどが可能です。

合同会社タコスキングダム|蛸壺の中の工作室

この操作をまとめると、

変換前の状態

変換後

シェル(閉じたソリッド)

シェルを構成するフェイスに分解

フェイス

フェイスを構成するワイヤー

複数のフェイス

1番目のフェイスから2番目以降のフェイスで差集合をとった一つのフェイス

ワイヤー

ワイヤーを構成するエッジに分解

になります。

Draftベンチのアップグレードとダウングレードの内容の復習は以上ですが、以降で翼形状を作っていく際にはダウングレード機能しか使いません。

個人的にはアップグレードも面からシェルにするときに、頻繁に使うメソッドですがこのテクニックに関しては時間があればいつか紹介してみたいと考えています。


翼形状を作る ~ 手動編

さて、ここからは本題であった簡単な翼を作る操作からpythonコマンドを抽出する方法を紹介していきます。

まず
'blade'という名前を付けてドキュメントを新規作成し、Draftベンチから翼形状の断面を適当なベシェ曲線で作成します。

合同会社タコスキングダム|蛸壺の中の工作室

ベシェ曲線の作成に関しては前回詳しく解説したので割愛しますが、以下のようなスクリプトが得られます。

            points = [FreeCAD.Vector(20.0,0.0,0.0),FreeCAD.Vector(-20.0,10.0,0.0),FreeCAD.Vector(-24.0,0.0,0.0),FreeCAD.Vector(-19.0,-7.0,0.0),FreeCAD.Vector(20.0,0.0,0.0)]
bez = Draft.makeBezCurve(points,closed=False,support=None)
Draft.autogroup(bez)
        
先程のベシェ曲線のワイヤーを、ダウングレード機能によってエッジに変換すると、

合同会社タコスキングダム|蛸壺の中の工作室

            Draft.downgrade(FreeCADGui.Selection.getSelection(),delete=True)
        
が得られます。

次にこのエッジを複製するためにクローンすると、

合同会社タコスキングダム|蛸壺の中の工作室

            Draft.clone(FreeCAD.ActiveDocument.Edge)
        
このクローンをz軸方向に並行移動させると、

合同会社タコスキングダム|蛸壺の中の工作室

            FreeCAD.getDocument("blade").getObject("Clone").Placement = App.Placement(App.Vector(0,0,64),App.Rotation(App.Vector(0,0,1),0))
        
これで断面形状のエッジが2つ用意できましたので、ここからはPartワークベンチに移り、ロフトからソリッド化を行います。

合同会社タコスキングダム|蛸壺の中の工作室

合同会社タコスキングダム|蛸壺の中の工作室

先程の2つのエッジを指定して、ロフトを掛ます。このとき、ソリッド化の項目にはチェックを入れておく必要があります。

            App.getDocument('blade').addObject('Part::Loft','Loft')
App.getDocument('blade').ActiveObject.Sections=[App.getDocument('blade').Edge, App.getDocument('blade').Clone, ]
App.getDocument('blade').ActiveObject.Solid=True
App.getDocument('blade').ActiveObject.Ruled=False
App.getDocument('blade').ActiveObject.Closed=False
        

合同会社タコスキングダム|蛸壺の中の工作室

これでソリッド化は完成しましたので、あとはソリッドの表示を
Shadedにしたり、翼の端面を回転・伸縮させたりと細かな修正を加えてみます。

! 767*570*
8

            FreeCADGui.getDocument("blade").getObject("Loft").DisplayMode = u"Shaded"
FreeCAD.getDocument("blade").getObject("Clone").Placement = App.Placement(App.Vector(0,0,32),App.Rotation(App.Vector(0,0,1),18))
FreeCAD.getDocument("blade").getObject("Clone").Scale = (0.50, 0.50, 1.00)
        
合同会社タコスキングダム|蛸壺の中の工作室

これに以上の操作から、実用性は無いですが簡単な翼形状のようなものが出力できたことになります。


スクリプトの作成

では以上の手順を踏まえてスクリプトを作成します。

            import FreeCAD
import FreeCADGui
import Draft
import Part

App.newDocument("blade")

points = [FreeCAD.Vector(20.0,0.0,0.0),FreeCAD.Vector(-20.0,10.0,0.0),FreeCAD.Vector(-24.0,0.0,0.0),FreeCAD.Vector(-19.0,-7.0,0.0),FreeCAD.Vector(20.0,0.0,0.0)]
bez = Draft.makeBezCurve(points,closed=False,support=None)
Draft.autogroup(bez)

Draft.downgrade(FreeCADGui.Selection.getSelection(),delete=True)

Draft.clone(FreeCAD.ActiveDocument.Edge)
FreeCAD.getDocument("blade").getObject("Clone").Placement = App.Placement(App.Vector(0,0,64),App.Rotation(App.Vector(0,0,1),0))

App.getDocument('blade').addObject('Part::Loft','Loft')
App.getDocument('blade').ActiveObject.Sections=[App.getDocument('blade').Edge, App.getDocument('blade').Clone, ]
App.getDocument('blade').ActiveObject.Solid=True
App.getDocument('blade').ActiveObject.Ruled=False
App.getDocument('blade').ActiveObject.Closed=False

FreeCADGui.getDocument("blade").getObject("Loft").DisplayMode = u"Shaded"
FreeCAD.getDocument("blade").getObject("Clone").Placement = App.Placement(App.Vector(0,0,32),App.Rotation(App.Vector(0,0,1),18))
FreeCAD.getDocument("blade").getObject("Clone").Scale = (0.50, 0.50, 1.00)

FreeCAD.ActiveDocument.recompute()

#👇はファイルを保存する場合に追記する
App.getDocument("blade").saveAs("[保存先までのパス]/blade.FCStd")
        
これをマクロから実行すると手動でモデリングを行っていた操作をスクリプトとして再現できるようになります。


まとめ

ローターの翼形状は流体効果の数値計算を三次元的にシミュレーションする場合に、パラメトリックに羽根のモデルが生成できるようになるのが理想的です。

よってFreeCADの提供する強力なモデリングスクリプトが工学分野と非常に親和性が高いのに、どれだけ使い倒しても無償!というのが本当にありがたいところです。

さて、次回は羽根形状1枚だけのモデリングではかなり寂しいので、何か完成品を仕上げる応用例的な課題を取り上げていきたいと考えています。
記事を書いた人

記事の担当:taconocat

ナンデモ系エンジニア

電子工作を身近に知っていただけるように、材料調達からDIYのハウツーまで気になったところをできるだけ細かく記事にしてブログ配信してます。