Generating room boundaries with Python is relatively easy. It can be done by using following API call:
loops = room.GetBoundarySegments(options)
Options is a variable of SpatialElementBoundaryOptions type, which states desired boundary line location, eg. for walls it can be a finish line or centreline. As a result of the above we receive a list of loops, where each loop is a list itself – containing separate segments. In order to get all the single lines we can run a code like this:
for loop in loops: for segment in loop: c = segment.GetCurve()
Things get complicated though when we try to get boundaries from linked document’s rooms. Linked files can be moved or rotated within our base document and thus running the above code would give us wrong curves locations.
To solve this problem we have to know the transformation (rotation, location) of the linked document. Fortunately Revit API class RevitLinkInstance provides a GetTotalTransform() function that gives us exactly what we need for each instance of the linked doc (same document can be present multiple times within base document – eg. repeated storeys).
Knowing the exact transformation we can correct our curves like so:
transform = linkInstance.GetTotalTransform()<br> c = segment.GetCurve()<br> p0 = transform.OfPoint(c.GetEndPoint(0)).ToPoint() p1 = transform.OfPoint(c.GetEndPoint(1)).ToPoint()
Below a complete piece of code which for a specified link instance object will return a list of rooms and their boundary lines:
import clr clr.AddReference('ProtoGeometry') from Autodesk.DesignScript.Geometry import * clr.AddReference('RevitAPI') import Autodesk from Autodesk.Revit.DB import * clr.AddReference("RevitNodes") import Revit clr.ImportExtensions(Revit.GeometryConversion) #The inputs to this node will be stored as a list in the IN variables. linkInstance = UnwrapElement(IN) linkedDoc = linkInstance.GetLinkDocument() collector = FilteredElementCollector(linkedDoc).OfCategory(BuiltInCategory.OST_Rooms) transform = linkInstance.GetTotalTransform() rooms =  boundaries =  options = SpatialElementBoundaryOptions() options.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish for r in collector.ToElements(): rooms.append(r) lines =  for loop in r.GetBoundarySegments(options): for segment in loop: c = segment.GetCurve() p0 = transform.OfPoint(c.GetEndPoint(0)).ToPoint() p1 = transform.OfPoint(c.GetEndPoint(1)).ToPoint() #line = Line.CreateBound(p0,p1) line = Autodesk.DesignScript.Geometry.Line.ByStartPointEndPoint(p0,p1) lines.append(line) boundaries.append(lines) #Assign your output to the OUT variable. OUT = rooms, boundaries
And a Dynamo definition converting those boundaries into Revit model lines: