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

I not able to load in revit 2019, could you please share dynamo file
Hi, I have added a .dyn file to the post.
I tried the code based on your suggestion, but I still not it work. I post my question to the original post in Dynamo Forum at the below, hoping you may able to offer more your helps.
https://forum.dynamobim.com/t/dimensioning-curtain-wall-grid-in-linked-model/31917/3
Thanks in advance.
Hi,
I have replied in the forum topic. Let me know if it solves the problem ๐
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!
Thank you for your code,
for some reason, It doesn’t work for me, it gives me an error on the python script command on Dynamo.
It says, IronpythonEvaluator.EvaluateIronPythonScript
operation Failed
Traceback( most recent call last(:
file””, line 6, in
indexErrorL index out of range: 2
Hi MBI,
it seems to me it is a python node input error. Have you added necessary number of inputs to the code node?
Great! thank you so much for sharing this.
I was trying to make this action on several walls at the same time.
I’ve tried to iterate with another for loop inserting each time only one wall and its corresponding line, but for some reason, it only puts dimensions on the first wall.
any suggestions?
I would send a picture if possible…
Hi,
can you send the picture to lu@lubim.co then? I will try to help then ๐