Code snippets/jp

このページにはフォーラムでユーザーが作成したり議論した中から集めたFreeCAD用Pythonコードのサンプル、コード片、コードの一部を集めて載せています。あなたのスクリプトの参考にしてください・・・

典型的なInitGui.pyファイル

全てのモジュールにはメインモジュールファイルに加えてメインGUIにモジュールを挿入するためのInitGui.pyファイルが含まれていなければなりません。これはその単純な例です。

class ScriptWorkbench (Workbench): 
    MenuText = "Scripts"
    def Initialize(self):
        import Scripts # Scripts.pyがあなたのモジュールとします
        list = ["Script_Cmd"] # このリストにはScripts.pyで定義されているであろうコマンドの名前が代入されていなければなりません
        self.appendToolbar("My Scripts",list) 
        
Gui.addWorkbench(ScriptWorkbench())

典型的なモジュールファイル

モジュールが行う処理の全てが記載されているメインモジュールファイルの例です。前の例で呼び出されるScripts.pyファイルです。自作のコマンドの全てをここに記載します。

import FreeCAD, FreeCADGui 

class ScriptCmd: 
   def Activated(self): 
       # ここにあなたのScriptCmdが行うことを書きます・・・
       FreeCAD.Console.PrintMessage('Hello, World!')
   def GetResources(self): 
       return {'Pixmap' : 'path_to_an_icon/myicon.png', 'MenuText': 'Short text', 'ToolTip': 'More detailed text'} 
      
FreeCADGui.addCommand('Script_Cmd', ScriptCmd())

新しいファイルタイプをインポート

FreeCADでは簡単に新しいファイルタイプ用のインポート処理を作成することができます。FreeCADはデータを開かれているドキュメントからインポートするか、たんに直接新しいファイルタイプを開くかを区別しません。やらなければならないのは新しいファイル拡張子を FreeCADのリストに追加し、そのファイルを読み込んで欲しいFreeCADオブジェクトを作成するコードを書くことだけです:

リストに新しいファイル拡張子を追加するためには以下の行をInitGui.pyに追加しなければなりません:

# .extファイルを開いて読み込むためのコードがあるファイルをImport_Ext.pyとします
FreeCAD.addImportType("Your new File Type (*.ext)","Import_Ext") 

Import_Ext.pyファイルには以下のように書きます:

def open(filename): 
   doc=App.newDocument()
   # 読み込み、データの識別、対応するFreeCADオブジェクトの作成などfilenameを使って行う必要のある全てをここで行います
   doc.recompute()

新しいファイルタイプへのドキュメントのエクスポートも以下の行を使用する以外は同様にして行います:

FreeCAD.addExportType("Your new File Type (*.ext)","Export_Ext") 

ラインの追加

ラインは2点を持ちます:

import Part,PartGui 
doc=App.activeDocument() 
# ライン要素をドキュメントに追加し、その点を設定
l=Part.Line()
l.StartPoint=(0.0,0.0,0.0)
l.EndPoint=(1.0,1.0,1.0)
doc.addObject("Part::Feature","Line").Shape=l.toShape() 
doc.recompute()

ポリゴンの追加

ポリゴンはつながった線分の集合(AutoCADでいうポリライン)です。線分の集合が閉じている必要はありません。

import Part,PartGui 
doc=App.activeDocument()
n=list() 
# 3Dベクトルを作成し、座標を設定してリストに追加
v=App.Vector(0,0,0) 
n.append(v) 
v=App.Vector(10,0,0) 
n.append(v) 
#・・・全ての節点に対して繰り返します
# ポリゴンオブジェクトを作成し、その節点を設定
p=doc.addObject("Part::Polygon","Polygon") 
p.Nodes=n 
doc.recompute()

グループに対するオブジェクトの追加と削除

doc=App.activeDocument() 
grp=doc.addObject("App::DocumentObjectGroup", "Group") 
lin=doc.addObject("Part::Feature", "Line")
grp.addObject(lin) # linオブジェクトをグループgrpに追加
grp.removeObject(lin) # linオブジェクトをグループgrpから削除

注意: グループにグループを追加することも可能です・・・

メッシュの追加

import Mesh
doc=App.activeDocument()
# 新しい空のメッシュを作成
m = Mesh.Mesh()
# 12のファセットからボックスを作成
m.addFacet(0.0,0.0,0.0, 0.0,0.0,1.0, 0.0,1.0,1.0)
m.addFacet(0.0,0.0,0.0, 0.0,1.0,1.0, 0.0,1.0,0.0)
m.addFacet(0.0,0.0,0.0, 1.0,0.0,0.0, 1.0,0.0,1.0)
m.addFacet(0.0,0.0,0.0, 1.0,0.0,1.0, 0.0,0.0,1.0)
m.addFacet(0.0,0.0,0.0, 0.0,1.0,0.0, 1.0,1.0,0.0)
m.addFacet(0.0,0.0,0.0, 1.0,1.0,0.0, 1.0,0.0,0.0)
m.addFacet(0.0,1.0,0.0, 0.0,1.0,1.0, 1.0,1.0,1.0)
m.addFacet(0.0,1.0,0.0, 1.0,1.0,1.0, 1.0,1.0,0.0)
m.addFacet(0.0,1.0,1.0, 0.0,0.0,1.0, 1.0,0.0,1.0)
m.addFacet(0.0,1.0,1.0, 1.0,0.0,1.0, 1.0,1.0,1.0)
m.addFacet(1.0,1.0,0.0, 1.0,1.0,1.0, 1.0,0.0,1.0)
m.addFacet(1.0,1.0,0.0, 1.0,0.0,1.0, 1.0,0.0,0.0)
# エッジの長さを100倍にする
m.scale(100.0)
# アクティブなドキュメントにメッシュを追加
me=doc.addObject("Mesh::Feature","Cube")
me.Mesh=m

円弧または円の追加

import Part
doc = App.activeDocument()
c = Part.Circle() 
c.Radius=10.0  
f = doc.addObject("Part::Feature", "Circle") # 円フィーチャーを持つドキュメントを作成
f.Shape = c.toShape() # 円シェイプをシェイププロパティに代入
doc.recompute()

オブジェクト表現へのアクセスと変更

FreeCADドキュメント内の各オブジェクトは関連付けられたビュー表現オブジェクトを持ち、そのビュー表現オブジェクトはそのオブジェクトがどのように表示されるかを定義する色、ライン幅などの全てのプロパティを保持しています。

gad=Gui.activeDocument()   # 対応するAppドキュメント内のフィーチャーと
                          # 対応する全てのビュー表現を保持した
                          # アクティブなドキュメントにアクセス

v=gad.getObject("Cube")    # フィーチャー'Cube' のビュー表現にアクセス
v.ShapeColor               # 色をコンソールに表示
v.ShapeColor=(1.0,1.0,1.0) # シェイプの色を白に設定

Pythonから3Dビューアーのマウスイベントを監視

Inventorフレームワークでは 複数のコールバック用ノードをビューアーへのシーングラフへ追加することができます。デフォルトではFreeCADはビューアーごとに一つのコールバック用ノードがインストールされており、それを使うとグローバルまたはスタティックなC++関数を追加することができます。適切なPythonバインディングではこのテクニックをPythonコードから利用するためのメソッドが提供されています。

App.newDocument()
v=Gui.activeDocument().activeView()

# このクラスは全てのマウスボタンイベントを記録します。登録されたコールバック関数は'down'イベントと'up'イベントで
# 二回、ファイヤーします。これをハンドリングするためのブール値フラグが必要です。
class ViewObserver:
   def logPosition(self, info):
       down = (info["State"] == "DOWN")
       pos = info["Position"]
       if (down):
           FreeCAD.Console.PrintMessage("Clicked on position: ("+str(pos[0])+", "+str(pos[1])+")\n")
      
o = ViewObserver()
c = v.addEventCallback("SoMouseButtonEvent",o.logPosition)

さあ、3Dビューアーの領域のどこかをピックして出力ウィンドウにメッセージが表示されるのを見てください。監視を終了するには次のようにします。

v.removeEventCallback("SoMouseButtonEvent",c)

次のイベント型がサポートされています。

addEventCallback()によって登録されるPython関数は辞書を要求します。検知されたイベントに従って辞書には様々なキーが保持されます。

全てのイベントは次のキーを持ちます:

全てのボタンイベント、つまりキーボードイベント、マウスイベント、スペースボールイベントの場合:

キーボードイベントの場合:

マウスボタンイベントの場合:

スペースボールイベントの場合:

そして最後にモーションイベントの場合:

Pythonでのシーングラフ操作

Coin用のPythonバインディングである'pivy'モジュールを使ってPythonでシーングラフを取得して変更することも可能です。

from pivy.coin import *                # pivyモジュールをロード
view = Gui.ActiveDocument.ActiveView   # アクティブなビューアーを取得
root = view.getSceneGraph()            # ルートはSoSeparatorノード
root.addChild(SoCube())
view.fitAll()

pivyのPythonAPIはSWIGというツールを使って作られています。FreeCADで使用する場合、自作ノードをPythonで直接作成することはできません。 ただし、内部的な名称を使ってノードを作成することはできます。'SoFCSelection'型のインスタンスは次のようにして作成することが可能です:

type = SoType.fromName("SoFCSelection")
node = type.createInstance()

シーングラフに対するオブジェクトの追加と削除

シーングラフへの新しいノードの追加は以下のようにして行うことができます。オブジェクトのジオメトリー、座標、マテリアルの情報の追加のためには常にSoSeparatorの追加が必要なことに注意してください。次の例では (0,0,0)から(10,0,0):に引かれた赤いラインを追加しています。

from pivy import coin
sg = Gui.ActiveDocument.ActiveView.getSceneGraph()
co = coin.SoCoordinate3()
pts = [[0,0,0],[10,0,0]]
co.point.setValues(0,len(pts),pts)
ma = coin.SoBaseColor()
ma.rgb = (1,0,0)
li = coin.SoLineSet()
li.numVertices.setValue(2)
no = coin.SoSeparator()
no.addChild(co)
no.addChild(ma)
no.addChild(li)
sg.addChild(no)

削除は次の様にします:

sg.removeChild(no)

インターフェイスへの自作ウィジットの追加

Qtデザイナーを使って自作のウィジットを作成し、それをPythonスクリプトに変換し、PyQt4を使ってFreeCADインターフェイスへ読み込むことが可能です。

UI Pthonコンパイラ(Qtデザイナーの.uiファイルをPythonコードに変換するツール)を使って作成されたPythonコードは一般的に次の様になります(簡単なものです。直接Pythonで書くこともできます):

class myWidget_Ui(object):
 def setupUi(self, myWidget):
   myWidget.setObjectName("my Nice New Widget")
   myWidget.resize(QtCore.QSize(QtCore.QRect(0,0,300,100).size()).expandedTo(myWidget.minimumSizeHint())) # ウィジットのサイズを設定

   self.label = QtGui.QLabel(myWidget) # ラベルを作成
   self.label.setGeometry(QtCore.QRect(50,50,200,24)) # サイズを設定
   self.label.setObjectName("label") # 名前を設定。これによって名前での検索が可能になります。

 def retranslateUi(self, draftToolbar): # ウィジットの翻訳を管理する組み込みのQt関数
   myWidget.setWindowTitle(QtGui.QApplication.translate("myWidget", "My Widget", None, QtGui.QApplication.UnicodeUTF8))
   self.label.setText(QtGui.QApplication.translate("myWidget", "Welcome to my new widget!", None, QtGui.QApplication.UnicodeUTF8))

次に必要なことはFreeCADのQtウィンドウへの参照を作成し、そこに自作のウィジットを挿入して、このウィジットを作成したUIコードで"作り変える"ことだけです:

 app = QtGui.qApp
 FCmw = app.activeWindow() # アクティブなQtウィンドウ。その内部にいるのでFreeCADウィンドウです。
 myNewFreeCADWidget = QtGui.QDockWidget() # 新しい dockwidget を作成
 myNewFreeCADWidget.ui = myWidget_Ui() # UIスクリプトを読み込み
 myNewFreeCADWidget.ui.setupUi(myNewFreeCADWidget) # UIをセットアップ
 FCmw.addDockWidget(QtCore.Qt.RightDockWidgetArea,myNewFreeCADWidget) # メインウィンドウにウィジットを追加

コンボビューへのタブの追加

次のコードを使うとFreeCADのコンボビューの"Project"タブ、"Tasks"タブの隣にタブを追加することができます。またuiファイルを直接そのタブに読み込むためにuicモジュールを使用しています。

from PyQt4 import QtGui,QtCore
from PyQt4 import uic
#from PySide import QtGui,QtCore

def getMainWindow():
   "returns the main window"
   # QtGui.qApp.activeWindow()の使用は信頼性が高くありません。
   # これはメインウィンドウではなく別のウィジット(例えばダイアログ)が
   # アクティブな場合に間違ったウィジットが返されるためです
   toplevel = QtGui.qApp.topLevelWidgets()
   for i in toplevel:
       if i.metaObject().className() == "Gui::MainWindow":
           return i
   raise Exception("No main window found")

def getComboView(mw):
   dw=mw.findChildren(QtGui.QDockWidget)
   for i in dw:
       if str(i.objectName()) == "Combo View":
           return i.findChild(QtGui.QTabWidget)
   raise Exception("No tab widget found")

mw = getMainWindow()
tab = getComboView(getMainWindow())
tab2=QtGui.QDialog()
tab.addTab(tab2,"A Special Tab")
uic.loadUi("/myTaskPanelforTabs.ui",tab2)
tab2.show()

#tab.removeTab(2)

自作ウェブページを開く

import WebGui
WebGui.openBrowser("http://www.example.com")

開いたウェブページのHTMLコンテンツを取得

from PyQt4 import QtGui,QtWebKit
a = QtGui.qApp
mw = a.activeWindow()
v = mw.findChild(QtWebKit.QWebFrame)
html = unicode(v.toHtml())
print html


Online version: "http://www.freecadweb.org/wiki/index.php?title=Code_snippets/jp&oldid=211454"

Navigation menu