Python は、シンプルな構文が特徴の、幅広く使用されているプログラミング言語です。構文が非常に読みやすいため、他の多くの言語より簡単に習得できます。Python はモジュールとパッケージをサポートしており、既存のアプリケーションに組み込むことができます。Python を実行する方法については、Python.org の「Getting Started」ページを参照してください。
Dynamo 2.0 では、初めて Python ウィンドウを開く際に、既定で使用するテンプレート (.py extension) を指定することができます。この機能があると、Dynamo 内で Python を効率よく使用できるため以前からご要望をいただいておりました。テンプレートを使用できる機能があるため、カスタム Python スクリプトを開発する際に既定のインポートをすぐに利用できます。
このテンプレートは、Dynamo をインストールした APPDATA にあります。
通常は次のように計算されます。( %appdata%\Dynamo\Dynamo Core\{version}\ )
この機能を使用するには、 DynamoSettings.xml ファイルで次の行を追加する必要があります。(メモ帳で編集します)
<PythonTemplateFilePath /> を見つけて、これを次のように置き換えるだけです。
注: CURRENTUSER を自分のユーザ名に置き換えてください
次に、使用する機能を組み込んだテンプレートを作成する必要があります。ここでは、Revit に関連するインポートおよび Revit で作業する際の他の一般的な項目の一部を組み込みます。
空のメモ帳を起動して、次のコードを貼り付けることができます。
貼り付けが完了したら、このファイルを PythonTemplate.py という名前で APPDATA フォルダ内に保存します。
Python テンプレートが定義されると、Python Script ノードが配置されるたびに、Dynamo はこのテンプレートを検索します。見つからない場合、既定の Python ウィンドウのように表示されます。
Python テンプレート(たとえばここで作成した Revit でのテンプレート)が見つかった場合、組み込んだ既定の項目がすべて表示されます。
この優れた追加機能(Radu Gidei 氏による)に関する詳細は、こちらを参照してください。https://github.com/DynamoDS/Dynamo/pull/8122

<PythonTemplateFilePath>
<string>C:\Users\CURRENTUSER\AppData\Roaming\Dynamo\Dynamo Core\2.0\PythonTemplate.py</string>
</PythonTemplateFilePath>import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import *
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import *
clr.AddReference('System')
from System.Collections.Generic import List
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uidoc=DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
#Preparing input from dynamo to revit
element = UnwrapElement(IN[0])
#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
TransactionManager.Instance.TransactionTaskDone()
OUT = element


Dynamo のビジュアル プログラミング環境で、テキスト プログラミングを使用するのはなぜでしょうか。ビジュアル プログラミングには、多くの利点があります。直感的なビジュアル インタフェースにより、特別な構文を学習することなくプログラムを作成することができます。ただし、ビジュアル プログラムは、処理が煩雑になったり、機能が不足することがあります。Python には、「if/then」の条件ステートメントやループを簡単に記述するための方法が用意されています。Python は、Dynamo の機能を拡張し、多数のノードを数行の簡潔なコード行で置き換えることができる強力なツールです。
ビジュアル プログラミング:
テキスト プログラム:
Code Block ノードと同様に、Python Script ノードはビジュアル プログラミング環境内のスクリプト インタフェースです。Python Script ノードは、ライブラリの[Script] > [Editor] > [Python Script]にあります。
このノードをダブルクリックすると、Python のスクリプト エディタが開きます。ノードを右クリックして[編集...]を選択することもできます。エディタ上部の定型文は、必要なライブラリを参照する際に役立ちます。Python Script ノードの入力値は、IN 配列に格納されます。値は、OUT 変数に割り当てられて Dynamo に返されます。
Autodesk.DesignScript.Geometry ライブラリにより、Code Block ノードと同様のドット表記を使用することができます。Dynamo 構文の詳細については、「」および「」を参照してください(この PDF 文書をダウンロードするには、リンクを右クリックし、[名前を付けてリンク先を保存...]をクリックしてください)。「Point.」などのジオメトリ タイプを入力すると、点の作成や点のクエリーを実行するためのメソッドのリストが表示されます。
これらのメソッドには、ByCoordinates などのコンストラクタ、Add などのアクション、X、Y、Z 座標などのクエリーがあります。
下のリンクをクリックして、サンプル ファイルをダウンロードします。
すべてのサンプルファイルの一覧については、付録を参照してください。
この例では、Python Script ノードを記述してソリッド モジュールからパターンを作成し、カスタム ノードに変換します。最初に、Dynamo ノードを使用してソリッド モジュールを作成します。
Rectangle.ByWidthLength: ノードを使用して、ソリッドのベースとなる長方形を作成します。
Surface.ByPatch: ノードの closedCurve 入力に Rectangle 出力を接続し、下部サーフェスを作成します。
Geometry.Translate: ノードの geometry 入力に Rectangle 出力を接続し、長方形を上に移動します。次に、Code Block ノードを使用してソリッドの厚さを指定します。
Polygon.Points: ノードを使用して、変換された長方形に対してクエリーを実行し、頂点を抽出します。
Geometry.Translate: ノードを使用して、4 つの点に対応する 4 つの値のリストを作成します。この操作により、ソリッドの 1 つの頂点が上に移動します。
これで、上部サーフェスと下部サーフェスが作成されました。次に、2 つのプロファイルの間をロフトしてソリッドの側面を作成しましょう。
List.Create: ノードの index 入力に、底面の長方形と上面のポリゴンを接続します。
Surface.ByLoft: ノードを使用して 2 つのプロファイルをロフトし、ソリッドの側面を作成します。
List.Create: ノードの index 入力に上部サーフェス、側面サーフェス、下部サーフェスを接続して、サーフェスのリストを作成します。
これで、ソリッドが作成されました。次に、ワークスペースに Python Script ノードをドロップします。
ノード上の[+]アイコンをクリックし、ノードに入力を追加します。入力には IN[0]、IN[1]などの名前が付いています。これらはリスト内の項目を表しています。
最初に、入力と出力を定義しましょう。ノードをダブルクリックして、Python エディタを開きます。エディタ内のコードを修正するには、次のコードを実行します。
このコードの意味については、演習を進めながら説明していきます。ここで、ソリッド モジュールを配列化するためには、どのような情報が必要になるかを考慮する必要があります。最初に、移動距離を決定するために、ソリッドの寸法を知る必要があります。境界ボックスにはバグがあるため、境界ボックスを作成するにはエッジ曲線のジオメトリを使用する必要があります。
ここで、Dynamo の Python Script ノードを確認します。Dynamo のノードのタイトルと同じ構文が使用されていることがわかります。以下のコメント付きコードを確認してください。
ここでは、ソリッドのモジュールの移動と回転を行うため、Geometry.Transform の操作を使用しましょう。Geometry.Transform ノードを確認すると、ソリッドを変換するにはソース座標系とターゲット座標系が必要になることがわかります。この場合、ソース座標系はソリッドのコンテキストの座標系で、ターゲット座標系は配列化された各モジュールの別の座標系になります。そのため、x 値と y 値をループして、座標系を毎回異なる距離と方向で変換する必要があります。
[実行]をクリックし、コードを保存します。次のように、Python Script ノードを既存のスクリプトに接続します。
Solid.ByJoinedSurfaces からの出力を、Python Script ノードの最初の入力として接続し、Code Block を使用してその他の入力を定義します。
Topology.Edges ノードを作成し、Python Script ノードからの出力を入力として使用します。
最後に Edge.CurveGeometry ノードを作成し、Topology.Edges からの出力を入力として使用します。
シード値を変更すると、異なるパターンが作成されます。ソリッド モジュールのパラメータを変更して、異なるエフェクトを作成することもできます。
これで、便利な Python Script ノードが作成されました。このノードをカスタム ノードとして保存しましょう。Python Script ノードを選択し、ワークスペースを右クリックして、[カスタム ノードを作成]を選択します。
名前、説明、カテゴリを設定します。
この操作により、カスタム ノードを編集するための新しいワークスペースが開きます。
Inputs: 入力名をわかりやすい名前に変更し、データ タイプと既定値を追加します。
Output: 出力名を変更します。
ノードを .dyf ファイルとして保存すると、先ほど行った変更がカスタム ノードに反映されます。
前のセクションでは、Dynamo で Python スクリプトを使用する方法について説明しました。このセクションでは、スクリプティング環境に Revit ライブラリを接続する方法を見てみましょう。ここまでの手順で、次のコード ブロックの最初の 4 行を使用して、Python 標準ライブラリと Dynamo の Core ノードが既に読み込まれています。数行のコードを追加するだけで、Revit の各種のノード、要素、ドキュメント マネージャを読み込むことができます。
これにより、Revit API にアクセスし、任意の Revit タスクでカスタム スクリプトを使用できるようになります。ビジュアル プログラミングのプロセスと Revit API スクリプトを組み合わせることにより、コラボレーションやツールの開発が容易になります。たとえば、BIM マネージャと回路設計者が、同じグラフを使用して同時に作業することができます。こうしたコラボレーションにより、モデルの設計と施工を改善できます。
Dynamo プロジェクトの背景には、プラットフォーム実装のスコープを拡大するという計画があります。そのため、Dynamo には新しいプログラムが追加されていく予定になっています。ユーザは、Python スクリプティング環境からプラットフォーム固有の API にアクセスできるようになります。このセクションでは Revit を扱いますが、今後は章の数を増やして、別のプラットフォーム上でのスクリプト作成に関する説明を追加する予定です。また、さまざまな ライブラリにアクセスして Dynamo に読み込むことができるようになりました。
次の例では、Dynamo で Python を使用して、Revit 固有の操作を実行する方法について説明します。Python と Dynamo および Revit との関係の詳細については、を参照してください。Python と Revit のもう 1 つの便利なリソースは、 プロジェクトです。
新しい Revit プロジェクトを作成します。
下のリンクをクリックして、サンプル ファイルをダウンロードします。
すべてのサンプルファイルの一覧については、付録を参照してください。
これ以降の一連の演習では、Dynamo for Revit における基本的な Python スクリプトについて説明します。この演習では、Revit のファイルと要素を使用します。また、Revit と Dynamo 間の通信についても説明します。
ここでは、Dynamo セッションにリンクされた Revit ファイルの doc、uiapp、app を取得するための一般的な方法について説明します。Revit API を使用したことのある方ならば、Watch リストのような項目を見たことがあるかもしれません。これらの項目を見たことがなくても、特に問題はありません。これ以降の演習で、別の例を使用して説明します。
RevitServices を読み込み、Dynamo のドキュメント データを取得するには、次のようなスクリプトを記述します。
ここで、Dynamo の Python Script ノードを確認します。次のコードを参照することもできます。
下のリンクをクリックして、サンプル ファイルをダウンロードします。
すべてのサンプルファイルの一覧については、付録を参照してください。
この演習では、Dynamo の Python Script ノードを使用して、Revit 内に単純なモデル曲線を作成します。
最初に、Revit 内に新しいコンセプト マス ファミリを作成します。
コンセプト マス フォルダ を開き、Metric Mass.rft テンプレート ファイルを使用します。
Revit で、キーボード ショートカット un を使用してプロジェクトの単位の設定を表示し、長さの単位をメートルに変更します。
Dynamo を起動し、下図に示す一連のノードを作成します。次に、Dynamo のノードを使用して、Revit 内に 2 つの参照点を作成します。
Code Block ノードを作成し、
"0;"の値を設定します。この値を、ReferencePoint.ByCoordinates ノードの X、Y、Z 入力に接続します。
-100 ~ 100 の範囲内で、ステップ値が 1 の Number Slider ノードを 3 つ作成します。
ここで、Dynamo の Python Script ノードを確認します。下の完全なコードを見つけます。
System Array: Revit の入力には、Python リストではなく System.Array が必要です。これは 1 行のコードに過ぎませんが、引数のタイプに注意すると、Revit での Python プログラミングが容易になります。
ここまでの手順では、Dynamo で Python を使用して、線分で接続された 2 つの参照点を作成しました。次の演習で、さらに操作を進めてみましょう。
下のリンクをクリックして、サンプル ファイルをダウンロードします。
すべてのサンプルファイルの一覧については、付録を参照してください。
この演習では、簡単な操作を実行することにより、Revit と Dynamo 間で相互にデータやジオメトリを接続する場合の要点について説明します。最初に Revit-StructuralFraming.rvt を開き、次に Dynamo を起動して、Revit-StructuralFraming.dyn ファイルを開きます。
この Revit ファイルは、基本的なファイルです。レベル 1 とレベル 2 にそれぞれ 1 本ずつ、2 本の異なる参照曲線が描画されています。これらの曲線を Dynamo に読み込み、ライブ リンクを作成します。
このファイルでは、Python Script ノードの 5 つの入力に一連のノードが接続されています。
各 Select Model Element ノードの[選択]ボタンをクリックし、Revit 内の対応する曲線を選択します。
Code Block ノードで「
0..1..#x;」という構文を使用して、 0 ~ 20 までの範囲を持つ Integer Slider ノードを x 入力に接続します。この操作により、2 本の曲線の間に作成する梁の数を指定します。Structural Framing Types ノードのドロップダウン メニューで、既定の W12x26 梁を選択します。
この Python コードは、これまでのコードよりも行数が多くなっていますが、コード行の前後のコメントを参照すると、プロセス内の処理内容を確認できます。
Revit で、2 つの曲線にわたる梁の配列が構造要素として作成されました。注: この構造要素は、Dynamo でネイティブの Revit インスタンスを作成する場合の例として使用しているもので、実際にはあり得ない構造要素であることに注意してください。
Dynamo でも、結果を確認できます。Watch3D ノードの梁は、Revit 要素からクエリーされたジオメトリを参照します。
このセクションでは、Revit 環境から Dynamo 環境にデータを変換する一連のプロセスを作成しました。このプロセスをまとめると、次のようになります。
Revit の要素を選択する
Revit の要素を Dynamo の曲線に変換する
Dynamo の曲線を一連の Dynamo の点に分割する
Dynamo の 2 つの曲線間の点を使用して Dynamo の線分を作成する
これは複雑なプロセスに見えるかもしれませんが、スクリプトを使用すると、Revit で曲線を編集してソルバを再実行するのと変わらないほど単純な処理になります(ただし、そのためには、元の梁を削除する必要があります)。これは、Python で梁を配置することによって、初期設定のままのノードにある関連付けが解除されるためです。
Revit で参照曲線を更新すると、梁の新しい配列が作成されます。
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
solid = IN[0]
seed = IN[1]
xCount = IN[2]
yCount = IN[3]
solids = []
yDist = solid.BoundingBox.MaxPoint.Y-solid.BoundingBox.MinPoint.Y
xDist = solid.BoundingBox.MaxPoint.X-solid.BoundingBox.MinPoint.X
for i in xRange:
for j in yRange:
fromCoord = solid.ContextCoordinateSystem
toCoord = fromCoord.Rotate(solid.ContextCoordinateSystem.Origin,Vector.ByCoordinates(0,0,1),(90*(i+j%val)))
vec = Vector.ByCoordinates((xDist*i),(yDist*j),0)
toCoord = toCoord.Translate(vec)
solids.append(solid.Transform(fromCoord,toCoord))
OUT = solidsimport sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Import RevitNodes
clr.AddReference("RevitNodes")
import Revit
# Import Revit elements
from Revit.Elements import *
# Import DocumentManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
import System変換後の点を Polygon.ByPoints: ノードで使用して、上部ポリゴンを再作成します。
Surface.ByPatch: ノードを使用してポリゴンを結合し、上部サーフェスを作成します。

各スライダを ReferencePoint.ByCoordinates ノードに接続します。
Python Script ノードをワークスペースに追加し、このノードの[+]ボタンをクリックして入力をもう 1 つ追加し、各入力に参照点を接続します。Python Script ノードを開きます。
Levels ノードで、「Level 1」を選択します。
Dynamo の線分を参照することにより、Revit の梁を作成する
Revit の梁のジオメトリに対してクエリーを実行することにより、Dynamo のサーフェスを出力する

# Load the Python Standard and DesignScript Libraries
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# The inputs to this node will be stored as a list in the IN variables.
#The solid module to be arrayed
solid = IN[0]
#A Number that determines which rotation pattern to use
seed = IN[1]
#The number of solids to array in the X and Y axes
xCount = IN[2]
yCount = IN[3]
#Create an empty list for the arrayed solids
solids = []
# Place your code below this line
# Assign your output to the OUT variable.
OUT = solids# Load the Python Standard and DesignScript Libraries
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# The inputs to this node will be stored as a list in the IN variables.
#The solid module to be arrayed
solid = IN[0]
#A Number that determines which rotation pattern to use
seed = IN[1]
#The number of solids to array in the X and Y axes
xCount = IN[2]
yCount = IN[3]
#Create an empty list for the arrayed solids
solids = []
#Create an empty list for the edge curves
crvs = []
# Place your code below this line
#Loop through edges an append corresponding curve geometry to the list
for edge in solid.Edges:
crvs.append(edge.CurveGeometry)
#Get the bounding box of the curves
bbox = BoundingBox.ByGeometry(crvs)
#Get the x and y translation distance based on the bounding box
yDist = bbox.MaxPoint.Y-bbox.MinPoint.Y
xDist = bbox.MaxPoint.X-bbox.MinPoint.X
# Assign your output to the OUT variable.
OUT = solids# Load the Python Standard and DesignScript Libraries
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# The inputs to this node will be stored as a list in the IN variables.
#The solid module to be arrayed
solid = IN[0]
#A Number that determines which rotation pattern to use
seed = IN[1]
#The number of solids to array in the X and Y axes
xCount = IN[2]
yCount = IN[3]
#Create an empty list for the arrayed solids
solids = []
#Create an empty list for the edge curves
crvs = []
# Place your code below this line
#Loop through edges an append corresponding curve geometry to the list
for edge in solid.Edges:
crvs.append(edge.CurveGeometry)
#Get the bounding box of the curves
bbox = BoundingBox.ByGeometry(crvs)
#Get the x and y translation distance based on the bounding box
yDist = bbox.MaxPoint.Y-bbox.MinPoint.Y
xDist = bbox.MaxPoint.X-bbox.MinPoint.X
#Get the source coordinate system
fromCoord = solid.ContextCoordinateSystem
#Loop through x and y
for i in range(xCount):
for j in range(yCount):
#Rotate and translate the coordinate system
toCoord = fromCoord.Rotate(solid.ContextCoordinateSystem.Origin, Vector.ByCoordinates(0,0,1), (90*(i+j%seed)))
vec = Vector.ByCoordinates((xDist*i),(yDist*j),0)
toCoord = toCoord.Translate(vec)
#Transform the solid from the source coord syste, to the target coord system and append to the list
solids.append(solid.Transform(fromCoord,toCoord))
# Assign your output to the OUT variable.
OUT = solids# Load the Python Standard and DesignScript Libraries
import sys
import clr
#Import DocumentManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
#Place your code below this line
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
#Assign your output to the OUT variable
OUT = [doc,uiapp,app]import sys
import clr
# Import RevitNodes
clr.AddReference("RevitNodes")
import Revit
#Import Revit elements
from Revit.Elements import *
import System
#define inputs
startRefPt = IN[0]
endRefPt = IN[1]
#define system array to match with required inputs
refPtArray = System.Array[ReferencePoint]([startRefPt, endRefPt])
#create curve by reference points in Revit
OUT = CurveByPoints.ByReferencePoints(refPtArray)import clr
#import Dynamo Geometry
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Import RevitNodes
clr.AddReference("RevitNodes")
import Revit
# Import Revit elements
from Revit.Elements import *
import System
#Query Revit elements and convert them to Dynamo Curves
crvA=IN[0].Curves[0]
crvB=IN[1].Curves[0]
#Define input Parameters
framingType=IN[3]
designLevel=IN[4]
#Define "out" as a list
OUT=[]
for val in IN[2]:
#Define Dynamo Points on each curve
ptA=Curve.PointAtParameter(crvA,val)
ptB=Curve.PointAtParameter(crvB,val)
#Create Dynamo line
beamCrv=Line.ByStartPointEndPoint(ptA,ptB)
#create Revit Element from Dynamo Curves
beam = StructuralFraming.BeamByCurve(beamCrv,designLevel,framingType)
#convert Revit Element into list of Dynamo Surfaces
OUT.append(beam.Faces)



























