BIM World
A Professional BIM Learning Platform


Dynamo Programming in Revit: Key Tips for Python Scripting and Revit API Integration


This article is translated from an original source.

This is arguably the best article on using RevitAPI within Dynamo. First and foremost, thank you to the original author for this translation!

Input Variables

Starting from Dynamo version 0.7, the number of input variables accepted by Python script nodes can vary. In versions before 0.6, each input value required a separate variable. Now, multiple input values are bundled into a list called IN. You can access each input by its index—for example, IN[0] for the first input, IN[1] for the second, and so forth.

Here’s a simple example to count and sum input values using a loop:

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

RevitAPI Integration

To facilitate better interaction between Dynamo and RevitAPI, a comprehensive library has been developed.

Accessing Document and Application

You can access Revit documents through the DocumentManager class available in Dynamo’s libraries:

import clr

clr.AddReference(“RevitServices”)
import RevitServices
from RevitServices.Persistence import DocumentManager

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

Working with Elements

In Dynamo, elements are wrapped by Revit classes. To manipulate them within Python scripts, use classes from the Revit.Elements namespace.

import clr

clr.AddReference(“RevitNodes”)
import Revit

from Revit.Elements import CurveByPoints, ReferencePoint

import System

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

Direct Use of RevitAPI

To use RevitAPI directly, you need to unwrap the wrapped elements first. Use the TransactionManager class to ensure your operations are executed within Revit transactions. Afterwards, wrap the results for output.

import clr

clr.AddReference(“RevitAPI”)
import Autodesk
from Autodesk.Revit.DB import ReferencePointArray

clr.AddReference(“RevitServices”)
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

clr.AddReference(“RevitNodes”)
import Revit
clr.ImportExtensions(Revit.Elements)

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

doc = DocumentManager.Instance.CurrentDBDocument
TransactionManager.Instance.EnsureInTransaction(doc)

arr = ReferencePointArray()
arr.Append(startRefPt)
arr.Append(endRefPt)
cbp = doc.FamilyCreate.NewCurveByPoints(arr)

TransactionManager.Instance.TransactionTaskDone()

OUT = cbp.ToDSType(False)

Unwrapping Elements

All wrapped elements inherit from Revit.Elements.Element in the Revit.Elements namespace. This class provides the InternalElement property, which references the underlying RevitAPI element. Dynamo offers the UnwrapElement(element) function to extract the RevitAPI element from a wrapped element. If the input is not a wrapped element, it remains unchanged.

wrappedElement = IN[0]
unwrappedElement = UnwrapElement(wrappedElement)

Now, unwrappedElement can be used directly with RevitAPI.

Encapsulation

To interact properly with Revit nodes, any element returned from a Python script must be wrapped in a class from Revit.Elements.Element. This is achieved using the ToDSType(boolean) method. The boolean flag indicates whether the element already exists in the Revit document (True) or was created within the script (False).

import clr

clr.AddReference(“RevitNodes”)
import Revit
clr.ImportExtensions(Revit.Elements)

docPt = FetchRefPtFromDoc() # Hypothetical function to read a point
newPt = CreateNewRefPt() # Hypothetical function to create a new point
OUT = [
  docPt.ToDSType(True), # Existing element
  newPt.ToDSType(False) # Newly created element
]

Units Conversion

Dynamo uses meters for length units, whereas RevitAPI uses feet. This requires manual conversions when transforming geometry or length values:

metersToFeet = 0.3048
feetToMeters = 1 / metersToFeet

Convert length from Dynamo to Revit units:

dynamoUnitsLength = someDynamoLengthFunction()
revitUnitsLength = dynamoUnitsLength * metersToFeet

Convert length from RevitAPI to Dynamo units:

revitUnitsLength = someRevitLengthFunction()
dynamoUnitsLength = revitUnitsLength * feetToMeters

Geometric Objects

Revit geometry includes entities such as points and curves, which are Revit geometric objects. Dynamo-generated geometry is not directly compatible with Revit geometry, so conversion is necessary. Note that Dynamo uses meters while Revit uses feet for units. Dynamo provides the GeometryConversion tool to assist with this process.

To import GeometryConversion:

import clr

clr.AddReference(“RevitNodes”)
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

Convert from Revit to Dynamo geometry:

dynamoGeometry = revitGeometryObject.ToProtoType()

Convert from Dynamo to Revit geometry:

revitGeometryObject = dynamoGeometry.ToRevitType()

The XYZ class in Revit represents a point but is not considered a geometric object. You can convert it as follows:

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

You can skip unit conversion by passing False to the methods ToRevitType(), ToProtoType(), ToXyz(), ToPoint(), and ToVector().

import clr

clr.AddReference(“RevitAPI”)
import Autodesk

clr.AddReference(“RevitNodes”)
import Revit

clr.AddReference(“RevitServices”)
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

clr.ImportExtensions(Revit.GeometryConversion)

clr.ImportExtensions(Revit.Elements)

xyz = IN[0].ToXyz()

doc = DocumentManager.Instance.CurrentDBDocument
TransactionManager.Instance.EnsureInTransaction(doc)

refPt = doc.FamilyCreate.NewReferencePoint(xyz)

TransactionManager.Instance.TransactionTaskDone()

OUT = refPt.ToDSType(False)

Transactions

Dynamo provides its own transaction framework that can be used within Python scripts. When working with RevitAPI transactions, utilize Dynamo’s TransactionManager class as follows:

TransactionManager.EnsureInTransaction(): Starts a Dynamo transaction
TransactionManager.TransactionTaskDone(): Ends the transaction
TransactionManager.ForceCloseTransaction(): Forces Dynamo to commit the transaction

import clr

clr.AddReference(“RevitServices”)
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument

TransactionManager.Instance.EnsureInTransaction(doc)

refPt = doc.FamilyCreate.NewReferencePoint(XYZ(0, 0, 0))

TransactionManager.Instance.TransactionTaskDone()

You can also manage transactions using RevitAPI subtransactions. Unlike main transactions, subtransactions allow rollbacks for changes.

xuebim
Follow the latest BIM developments in the architecture industry, explore innovative building technologies, and discover cutting-edge industry insights.
← Scan with WeChat
Like(0) 打赏
BIM WORLD » Dynamo Programming in Revit: Key Tips for Python Scripting and Revit API Integration

Comment Get first!

Must log in before commenting!

 

BIM World, A Professional BIM Learning Platform

Stay updated on the latest architecture trends and share new building technologies.

Contact UsAbout Us

觉得文章有用就打赏一下小编吧

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

Account Login

By signing in, you agree toUser Agreement

Sign Up