本文翻译自https://github.com/DynamoDS/Dynamo/wiki/Python-0.6.3-to-0.7.x-Migration 有改动,如有错误欢迎指出。

输入变量

在0.7版本之后的Dynamo中,Python脚本的节点可接受的变量数目是可变的。在0.6以前的旧版本中,每个输入值都要设定一个变量。而在新版本中,多个输入值被打包进一个名叫IN的列表变量中。你可以通过索引值来获取给列表中的每个输入值,例如使用IN[0]访问第一个输入值,使用IN[1]访问第二个输入值,以此类推。

可以利用以下代码查询输入值的个数,利用循环函数便可遍历每个输入值:

count = 0
for number in IN:
    count += number
OUT = count

RevitAPI

为了方便Dynamo更好地调用RevitAPI,我们编写了一个完整的库来与Revit交互。

Revit文档可通过Dynamo库中的DocumentManager类访问:

import clr

#引用DocumentManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application

元素

Dynamo中的元素都是由Revit封装的。在Python脚本中,你可以通过调用Revit.Elements命名空间中的类来对它们进行操作。

import clr

# 引用RevitNodes
clr.AddReference("RevitNodes")
import Revit
# 使用 'from Revit.Elements import *'来引用Revit.Elements中需要的类
from Revit.Elements import CurveByPoints, ReferencePoint

import System

startRefPt = IN[0]
endRefPt = IN[1]
refPtArray = System.Array[ReferencePoint]([startRefPt, endRefPt])
OUT = CurveByPoints.ByReferencePoints(refPtArray)

如果你希望直接使用RevitAPI,则需要在使用之前对元素进行解封。使用TransactionManager类来使你的操作是在RevitAPI的事务中进行,最后再将需要输出的值进行封装。

import clr

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import ReferencePointArray

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Import ToDSType(bool) extension method
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

# Unwrap
startRefPt = UnwrapElement( IN[0] )
endRefPt = UnwrapElement( IN[1] )

# 事务开始
doc = DocumentManager.Instance.CurrentDBDocument
TransactionManager.Instance.EnsureInTransaction(doc)

# Make the CurveByPoints
arr = ReferencePointArray()
arr.Append(startRefPt)
arr.Append(endRefPt)
cbp = doc.FamilyCreate.NewCurveByPoints(arr)

# 事务结束
TransactionManager.Instance.TransactionTaskDone()

# Wrap
OUT = cbp.ToDSType(false)

Unwrapping

(本段翻译有问题,还需修改) 所有经过封装的元素都继承自Revit.Elements命名空间中的Revit.Elements.Element类。这个类提供一个可以引用RevitAPI中低层元素的公共属性InternalElement。此外,Dynamo还提供了一个函数UnwrapElement(element)用来接受传递进来的元素。如果传递的不是元素,则不会有任何修改。

wrappedElement = IN[0]
unwrappedElement = UnwrapElement( wrappedElement )
# Now I can use 'unwrappedElement' with the RevitAPI

封装

为了能与Revit的节点交互,任何一个由Pyhon脚本返回的元素都必须封装成Revit.Elements.Element中的类。可使用ToDSType(bool)方法完成。布尔参数用于判断该元素是否存在于Revit文件中。如果元素是从文档直接读取的则为True,若为Python脚本创建的则为False。

import clr

# Import ToDSType(bool) extension method
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

docPt = FetchRefPtFromDoc() #从文件读取点(一个假设的方法)
newPt = CreateNewRefPt()    #创建一个新的点(一个假设的方法)
OUT = [
    docPt.ToDSType(True), #不是脚本创建的
    newPt.ToDSType(False) #由脚本创建的
]

单位

Dynamo使用米作为长度单位,而RevitAPI使用英尺。使用Dynamo的几何变换功能时,你需要经常考虑单位转换,然而你只能手动执行单位转换:

metersToFeet = 0.3048
feetToMeters = 1 / metersToFeet

# Convert a length from Dynamo to Revit API units
dynamoUnitsLength = someDynamoLengthFunction()
revitUnitsAfterConvert = dynamoUnitsLength * metersToFeet

# Convert a length from the Revit API to Dynamo units
revitUnitsLength = someRevitLengthFunction()
dynamoUnitsLengthAfterConvert = revitUnitsLength * feetToMeters

几何对象

Revit中的几何体(实体,点,曲线等)都是几何对象。而由Dynamo节点生成的几何体并不是Revit中的几何对象,所以我们需要使用RevitAPI进行转换。需要特别注意的是Dynamo中的几何体使用的单位是米,而Revit是英寸。Dynamo提供了GeometryConversion工具帮我们轻松完成转换工作。

使用以下代码导入GeometryConversion工具:

import clr

clr.AddReference("RevitNodes")
import Revit

# Import ToProtoType, ToRevitType geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

将Revit的几何对象转换成Dynamo中的,可以使用以下代码:

dynamoGeometry = revitGeometryObject.ToProtoType()

将Dynamo的几何体转成Revit的几何对象,可以使用以下代码:

revitGeometryObject = dynamoGeometry.ToRevitType()

Revit中的XYZ类(点)并不是一个几何对象但是有几种方法转换这个类:

point = xyz.ToPoint()
vector = xyz.ToVector()
xyz = pointOrVector.ToXyz()

你可以通过对ToRevitType()、ToProtoType() 、ToXyz()、ToPoint()、ToVector()方法输入False参数来省略单位转换。

import clr

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk

clr.AddReference("RevitNodes")
import Revit

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Import geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

# Import Element wrapper extension methods
clr.ImportExtensions(Revit.Elements)

# Unwrap the Point, yielding a Revit XYZ in Revit unit system
xyz = IN[0].ToXyz()

# Start Transaction
doc = DocumentManager.Instance.CurrentDBDocument
TransactionManager.Instance.EnsureInTransaction(doc)

# Create a Reference Point
refPt = doc.FamilyCreate.NewReferencePoint(xyz)

# End Transaction
TransactionManager.Instance.TransactionTaskDone()

# Wrap ReferencePoint Element
OUT = refPt.ToDSType(false)

事务

Dynamo提供了自己的事务框架,所以你可以在Python脚本中使用事务。 如果你需要使用RevitAPI的事务,你可以调用Dynamo的TransactionManager类。

TransactionManager.EnsureInTransaction(): 初始化Dynamo事务 TransactionManager.TransactionTaskDone(): 告诉Dynamo事务已结束 TransactionManager.ForceCloseTransaction(): 让Dynamo提交事务

import clr

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Get the document
doc = DocumentManager.Instance.CurrentDBDocument

# "Start" the transaction
TransactionManager.Instance.EnsureInTransaction(doc)

# Create a reference point (requires a transaction)
refPt = doc.FamilyCreate.NewReferencePoint(XYZ(0, 0, 0))

# "End" the transaction
TransactionManager.Instance.TransactionTaskDone()

你也可以使用RevitAPI的子事务来管理的事务。子事务允许你回滚的变化,而主事务无法回滚。