11 Dec

Create and Change Revit Family Instance with Dynamo Python

Creation of Revit family instances with Python code in Dynamo is easy to do if you have the right code snippet. So I am sharing it here.

Code snippet shows how to do few useful tasks:

  • How to select particular Revit family and type.
  • How to create instance of a type.
  • How to get particular parameter.
  • How to set particular parameter.
  • How to rotate family around it’s placement point (around Z axis).

Please have in mind that code will run only once if nothing has been changed in Dynamo. So I usually add one dummy true/false switch (see image) just for testing purposes (true or false is never used in code, it’s just telling (lying to) Dynamo that “something is changed”). This will convince Dynamo to run the code again. Also, have in mind that running the code several times will create new family instance each time (compared to basic Dynamo Revit family creation node).

Dynamo Python uses Revit API internal units (feet) for measurement. So when creating insertion points, make sure they are in feet. Or, create a function for conversion from “your units” to “Revit units”.

For this, I used the following versions:

  • Dynamo Core 2.0.3.8810
  • Dynamo Revit 2.0.3.8811
  • Out-of-the-box Architectural Revit template

Python node looks like this (read comments inside the code for mode details):

# Enable Python support and load DesignScript library
import clr
import math
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Import Revit API
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

# Import Manager Classes
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN

# Set desired family name and type name:
FamilyName = "M_Desk"
FamilyType = "1830 x 915mm"

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

collector = FilteredElementCollector(doc)

# to have shorter list of candidates, collector can be focused on just one category. 
# See full list of Revit categories here: https://www.revitapidocs.com/2019/ba1c5b30-242f-5fdc-8ea9-ec3b61e6e722.htm
collector.OfCategory(BuiltInCategory.OST_Furniture)

# get elements from collector
familyTypes = collector.OfClass(FamilySymbol).ToElements()

output = []

for typ in familyTypes:
     typeName = typ.get_Parameter(BuiltInParameter.SYMBOL_NAME_PARAM).AsString()
     
     # Check if the family is of the right family and type name:
    if typ.Family.Name == FamilyName and typeName == FamilyType:
        if typ.IsActive == False:
            typ.Activate()
            doc.Regenerate()
         
         # location of the family instance is set here:
        loc = XYZ(0,0,0)
        
        # create family instance:
        familyInstance = doc.Create.NewFamilyInstance(loc, typ, Structure.StructuralType.NonStructural)
        
        # This is how you get particular parameter:
        param = familyInstance.GetParameters("Phase Created")[0].AsValueString()
        
        # This is how you set particular instance parameter:
        familyInstance.LookupParameter("Comments").Set("This is sample comment")
        
        # This is how you set particular type parameter:
        typ.LookupParameter("Description").Set("This is sample description")
        
        angle = 40.0  # 40 degrees. Always add .0 even for round number to make sure Python see it as a float type
        point1 = XYZ(loc.X, loc.Y, loc.Z)
        
        # second point is just above the first point, so add any number to Z
        point2 = XYZ(loc.X, loc.Y, loc.Z + 100.0)
        axis = Line.CreateBound(point1, point2)
        
        # rotate family instance around axis (line), angle must be converted to radians
        ElementTransformUtils.RotateElement(doc, familyInstance.Id, axis, math.radians(angle))
        
        # add whatever you want to output list
        output.append(familyInstance)
        output.append(param)
        break
# End Transaction:
TransactionManager.Instance.TransactionTaskDone()

# Transaction ended 
# from this point onward, family instance had been created, you can do other stuff

# Assign your output to the OUT variable.
OUT = output

Hope you get good use of it!

Leave a Reply

Your email address will not be published. Required fields are marked *