Curtain wall dimensions with API and Dynamo

In this post I want to show a method that allows to automatically dimension curtain walls in Revit, with the result as on an image above.
First let’s assume that our input data are: a curtain wall, a line specifying location of the future dimension line and a view. In order to create a new dimension line in Revit we use such code:

doc.Create.NewDimension(view,line,refArray);

Where “doc” is our Revit document, “view” a view where we want to draw the dimension, “line” dimension placement line and “refArray” a list references to all measured objects/lines.

To get result as above we need to find two kinds of references:
-the ones that point to side edges of the wall
-the ones that point to vertical grid lines

The first ones will be collected directly from the wall geometry. In order to do that we need to find a Geometry Object of our wall, like so:

Options options = this.Application.Create.NewGeometryOptions();
options.ComputeReferences = true;
options.IncludeNonVisibleObjects = true;

Where”w” is the wall and “options” is a helper object containing parameters of the geometry extraction. It is important here to set it so it takes into account non visible objects and object references.

Next we iterate the geoElement to find solid objects. Then we check direction of all the solid’s faces (normal vector). If it is parallel to the direction of the dimension line we can add this face’s reference to the list. (refArray). It would look like that:

foreach(GeometryObject obj in geoElement){
  Solid s = obj as Solid;
  if(s!=null) {
    foreach(Face f in s.Faces){
      PlanarFace pf = f as PlanarFace;
      if(pf!=null) {
        XYZ faceNormal = pf.FaceNormal;
        if(isParallel(faceNormal,line.GetEndPoint(1)-line.GetEndPoint(0))) {
          refArray.Append(f.Reference);
        }
      }
    }
  }
}

Now we are gonna collect references to the vertical grid lines of the wall. We can do it using such code:

ICollection gridIds = w.CurtainGrid.GetVGridLineIds();

The above function returns ids of the grid lines, not the objects themselves. Therefore we have to find them in the document (using the ids) and then query them for any line geometries. References to those lines are added again to the list. Like so:

foreach(ElementId gridId in gridIds) {
  CurtainGridLine gridLine = doc.GetElement(gridId) as CurtainGridLine;
  if(gridLine!=null) {
    GeometryElement gridGeo = gridLine.get_Geometry(options);
    foreach(GeometryObject obj in gridGeo) {
      Line l = obj as Line;
      if(l!=null) refArray.Append(l.Reference);
    }
  }
}

Code for the entire function could look like this:

private void horizontalDimension(Document doc, View view, Wall w, Line line) {
                        
  ReferenceArray refArray = new ReferenceArray();
            
  Options options = this.Application.Create.NewGeometryOptions();
  options.ComputeReferences = true;
  options.IncludeNonVisibleObjects = true;
            
  GeometryElement geoElement = w.get_Geometry(options);
            
  //get side references            
  foreach(GeometryObject obj in geoElement){
    Solid s = obj as Solid;
    if(s!=null) {
      foreach(Face f in s.Faces){
        PlanarFace pf = f as PlanarFace;
        if(pf!=null) {
          XYZ faceNormal = pf.FaceNormal;
          if(isParallel((faceNormal,line.GetEndPoint(1)-line.GetEndPoint(0))) {
            refArray.Append(f.Reference);
          }
        }
      }
    }
  }
            
  //get grid references            
  ICollection<ElementId> gridIds = w.CurtainGrid.GetVGridLineIds();
            
  foreach(ElementId gridId in gridIds) {
    CurtainGridLine gridLine = doc.GetElement(gridId) as CurtainGridLine;
    if(gridLine!=null) {
      GeometryElement gridGeo = gridLine.get_Geometry(options);
      foreach(GeometryObject obj in gridGeo) {
        Line l = obj as Line;
        if(l!=null) refArray.Append(l.Reference);
      }
    }
  }
            
  using(Transaction t = new Transaction(doc,"horizontal dimension")) {                      
    t.Start();
    doc.Create.NewDimension(view,line,refArray);
    t.Commit();
  }
}

And this would be a Dynamo version, in Python:

import clr

#The inputs to this node will be stored as a list in the IN variables.
wall = UnwrapElement(IN[0])
lineElement = UnwrapElement(IN[1])
view = UnwrapElement(IN[2])

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

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

def isParallel(v1,v2):
  return v1.CrossProduct(v2).IsAlmostEqualTo(XYZ(0,0,0))

line = lineElement.GeometryCurve
lineDir = line.GetEndPoint(1) - line.GetEndPoint(0)

refArray = ReferenceArray()

doc = DocumentManager.Instance.CurrentDBDocument

options = Options()
options.ComputeReferences = True
options.IncludeNonVisibleObjects = True

geoElement = wall.get_Geometry(options)

#get side references
for obj in geoElement:
  if isinstance(obj,Solid):
    for f in obj.Faces:
      faceNormal = f.FaceNormal
      if isParallel(faceNormal,lineDir):
        refArray.Append(f.Reference)
    
    
#get grid references
for id in wall.CurtainGrid.GetVGridLineIds():
  gridLine = doc.GetElement(id)
  gridGeo = gridLine.get_Geometry(options)
  for obj in gridGeo:
    if isinstance(obj,Line):
      refArray.Append(obj.Reference)


TransactionManager.Instance.EnsureInTransaction(doc)
doc.Create.NewDimension(view, line, refArray)
TransactionManager.Instance.TransactionTaskDone()

#Assign your output to the OUT variable.
OUT = 0
Posts created 28

5 thoughts on “Curtain wall dimensions with API and Dynamo

  1. Hi,

    Thanks for sharing this script! It’s very handy for complex curtain walls. Though is it possible to use it for sloped glazing? I’ve tried to use it with a simple roof, but no result. I’ve also tried to rewrite the python script, but my lack of knowledge got me to reply to this forum. Hopefully you can help me!

Leave a Reply

Your email address will not be published.

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top