This tutorial has been written by our community member Cillian Warfield. Cillian is an Architect and Building Information Manager at PES-Architects in Helsinki.
You can follow him on Twitter or on LinkedIn.

Speckle supports sending and receiving blocks in AutoCAD and Rhino, as well as receiving them as 2D generic models in Revit.  However, with an easy dynamo script, you can also map AutoCAD blocks to 3D Revit families directly!

Let’s take the scenario where an architect receives a furniture layout from an interior architect consultant. The consultant sends their layout in dwg format and the architect would like to include the layout in their Revit model as 3D elements. So we need to map the AutoCAD blocks to loaded Revit families and place them in our model.

To achieve this we need to do the following:

  1. From AutoCAD, send the blocks to a Speckle Stream
  2. Switch to Dynamo in Revit and pick up the relevant Speckle stream
  3. Get the insertion point of the Speckle block instances
  4. Select the relevant loaded Revit family and levels for insertion. Place the Revit family by point and level.
  5. Get the Speckle block instance transforms
  6. Get the rotation in degrees (from the 4x4 transformation matrix)
  7. Set the family instance rotation

Send AutoCAD blocks to Dynamo

With Speckle installed for both AutoCAD and Dynamo, send your blocks to a Speckle stream. Open Dynamo in Revit, and receive the blocks you just sent with a  Dynamo Receive node.

Place Revit families using the block instance insertion points

Each block instance includes an insertion point, which can be retrieved by running the code block below:

Then select the loaded family you want to use to generate instances, as well as the level to place them on. Using the insertion points from the previous block, place your family instances by point and level.

Extract block rotation angle from the instance transform matrices

Speckle block instances also include a transform matrix that contains the information for the instance translation and rotation. First retrieve the transform matrices form the block instances, and then extract the rotation angles in degrees from the 4x4 matrices using a python script.



The custom python script extracts the block instance rotation in degrees from its 4x4 transformation matrix:

import sys
import clr
import math
clr.AddReference('System.Numerics')
from System.Numerics import *

def euler_from_quaternion(x, y, z, w):
    t0 = +2.0 * (w * x + y * z)
    t1 = +1.0 - 2.0 * (x * x + y * y)
    roll_x = math.atan2(t0, t1)
 
    t2 = +2.0 * (w * y - z * x)
    t2 = +1.0 if t2 > +1.0 else t2
    t2 = -1.0 if t2 < -1.0 else t2
    pitch_y = math.asin(t2)
 
    t3 = +2.0 * (w * z + x * y)
    t4 = +1.0 - 2.0 * (y * y + z * z)
    yaw_z = math.atan2(t3, t4)
    
    return roll_x, pitch_y, yaw_z # in radians


#iterate list of transforms
transforms = IN[0]
angles = []

for v in transforms:

	matrix = Matrix4x4(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15])
	
	decomposed = Matrix4x4.Decompose(matrix)
	rotation = decomposed[2]
	euler = euler_from_quaternion(rotation.X, rotation.Y, rotation.Z, rotation.W)
	angles.append(math.degrees(euler[2]))

OUT = angles

Generate family instances with the rotation data

Using the rotation angle output from the python script, we can now place family instances with the FamilyInstance.SetRotation node. Run the dynamo script and watch your Revit families appear in the model!

Conclusion

We hope you enjoyed this tutorial and found it useful!