DirectShape with Python

Hello Dynamo Friends,

I want to create a DirectShape from a solid but setting the shape does not work with a solid i created in dynamo. While the creation of a “blank” DirectShape works, I get an error for the “ds.SetShape([solid])” line.

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument

solid = UnwrapElement(IN[0])

TransactionManager.Instance.EnsureInTransaction(doc)

ds = DirectShape.CreateElement(doc, ElementId(BuiltInCategory.OST_GenericModel))
ds.SetShape([solid])

TransactionManager.Instance.TransactionTaskDone()

If i create a solid in the python code it works fine.
So why does it not with the “dynamo” solid? Am i right that there is no difference between a dynamo and a revit solid?

import clr

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

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

doc = DocumentManager.Instance.CurrentDBDocument
def create_box_solid(width, height, depth):
    p0 = XYZ(0, 0, 0)
    p1 = XYZ(width, 0, 0)
    p2 = XYZ(width, depth, 0)
    p3 = XYZ(0, depth, 0)
    
    lines = [Line.CreateBound(p0, p1), Line.CreateBound(p1, p2), Line.CreateBound(p2, p3), Line.CreateBound(p3, p0)]
    loop = CurveLoop.Create(lines)
    
    direction = XYZ.BasisZ
    
    return GeometryCreationUtilities.CreateExtrusionGeometry([loop], direction, height)


TransactionManager.Instance.EnsureInTransaction(doc)

box_solid = create_box_solid(10, 10, 10)
ds = DirectShape.CreateElement(doc, ElementId(BuiltInCategory.OST_GenericModel))
ds.SetShape([box_solid])
OUT = box_solid

TransactionManager.Instance.TransactionTaskDone()

This is a Dynamo solid on input, and it remains a Dynamo solid after unwrapping (perhaps this should throw an error?). You have to convert it to a Revit solid object before you can use it in Revit API calls.

To convert Dynamo points and vectors, there is the ToXyz method. And for Dynamo lines there is the ToLine method. The Dynamo Python Primer has a pretty good explaination on those topics:

But as far as I know there isn’t a simple ‘ToSolid’ method to convert a Dynamo Solid to a Revit one. The built in Dynamo node has a whole series of steps (around lines 235 to 258 here to handle the many possible ways this can happen.

2 Likes

Thanks jacob, found more info here.
So it´s not that easy…

I managed to “convert” my dynamo solid to a proper Autodesk.DB.Solid and create a directshape :slight_smile:

def convert_dynamo_to_revit(dynamo_solid, material_id):
    return dynamo_solid.ToRevitType(TessellatedShapeBuilderTarget.AnyGeometry, TessellatedShapeBuilderFallback.Mesh, MaterialId=material_id)

dynamo_solid = IN[0]
material_id = ElementId(IN[1])

solid = convert_dynamo_to_revit(dynamo_solid, material_id)[0]

TransactionManager.Instance.EnsureInTransaction(doc)

ds = DirectShape.CreateElement(doc, ElementId(BuiltInCategory.OST_GenericModel))
ds.SetShape([solid])
OUT=ds
TransactionManager.Instance.TransactionTaskDone()

For me it was important that the material assigning works properly and I get this directshape object into my material takeoff as needed, and this works, nice!

PS: i could not find out what this magical DynamoToRevitBRep method is and how to get the corresponding library for that class?!

Since you’re already getting into ‘info’ requirements, I recommend going with family instances instead of direct shapes. More power, increased file stability, better performance, and portable. Changes a good bit of the workflow though…

Would take some digging; likely in another referenced library (check the using statements at the top of the code)