During this really busy period and in between lots of preparation work for my Autodesk University 2015 classes, I finally found some time to explain you how Dynamo can help you automate the generation of section views based on the element selection in Revit. I must admit, this is part of my preparation too. So yes, I will explain this more in depth at AU 2015 !
When making detailed (fabrication) drawings of your reinforced concrete design model, you need to make a lot of section views in order to document the element geometry and rebar detailing. You might need some automation of these views to save a lot of your time. Especially when it comes to lots of objects, that need the same type of views (top view, front view, cross section view). With than in mind, I started to explore this in Dynamo and created a procedure to generate these types of views based on the element linear direction.
The whole dataset can be downloaded at the bottom of this article. By the end of this article you will be able to create automated views like in the screen shot below. The script works not only on straight elements, but also on rotated columns (C2, C3), slanted columns (C4) and inclined beams (B5). In case of section views that are not parallel with the level plan view, they are not shown in the view, but they are still created (as you can see in the Sections list).
Below you can see a video on how the script executes and reacts on changes made on the Revit objects.
The script consists of several parts (indicated by the groups) and there is some custom nodes that you will need in order to create the views. Let’s start with it:
The challenge for this script is to be able of handling several element configurations, from straight beams and columns, to rotated, inclined or slanted beams and columns.
Location line of selected elements
As basic input the script needs model geometry and a line indicating the “length axis” of the object. This is needed for the orientation of all the views. This length axis can either be the location line of a beam, or a manual selected edge, or a global indicated axis. In this case, the location line is the driving factor behind the sections.
In case of “Structural Framing” objects this can be done with the StructuralFraming.Location node. This node will return the Location Line as modelled in Revit. In this case the start-end direction of a beam is very important to define the section length direction.
In case of “Structural Column” it is not that simple. I got inspired for this one by a post by Marcello Sgambelluri about the location line of structural columns. By searching for the Vertex.PointGeometry of the faces of the column geometry, and by getting the Line.ByBestFitThroughPoints on these points, you get in fact the location line of the column. The reason for using this method is because vertical columns only return a “Location point” in the Revit API, while slanted columns have a “Location line” returned. The method applied here helps to get the location line in all cases.
Vector definition for section direction
The most important part of the script is the definition of the vectors along and on the location lines. These vectors are crucial for the definition of the section direction and for the detection of the “bounding” surface. See later in this post. There is a small difference in the detection of the vectors for beams and columns.
In the top part of the script, the vectors for the structural framing elements are defined. The next steps are executed for this:
Step 1 – Location line
In step 1, the output port of the StructuralFraming.LocationLine node is connected in a way that the user has the option to reverse the curve yes or no, but playing with the Boolean node. This has an influence on the section direction later on when generating the views in Revit.
Step 2 – Length axis direction
The Line.Direction node, returns the direction vector of the location line that results from the If node (reversed or not). This is the local x-axis of the element. This vector will be used for top and front views of the element and defines the 1st dimension of the section view crop region.
Step 3 – Local y-axis
We also need the local y-axis of the linear element, to help define the 2nd dimension of the section view crop region for the Top view and the Cross Section view in combination with the result from Step 4. The Curve.NormalAtParameter node positioned at the start of the line defines the vector perpendicular on the Line.Direction
Step 4 – Local z-axis
Finally the local z-axis is also needed. This axis will define the 2nd dimension of the section view crop region for the Front view and the Cross Section view in combination with the result from Step 3. To get this vector the result from Curve.NormalAtParameter node is rotated 90° around the length axis of the element.
The bottom part of the script uses a more extended method to define the local axes of the structural column. Follow the steps below:
For a structural column Step 1, 2 and 4 are the same as for structural framing. But Step 3 is different. Read below why.
Step 3 – Local y-axis with angle correction
The definition of the local y-axis of a structural column is not done by just detecting the ‘Normal’ vector. A vertical column with a cross-section rotation, returns the same location line than a column without rotation, and thus the same normal vector. This means we need to correct the normal vector by rotating the normal vector with the same angle as the column rotation, if we want the section views to be aligned to the column faces.
With the custom node Element.RotationAngle (which is also included in the dataset at the bottom of this article) you can detect the rotation angle of vertical columns. In the custom node, a Python node is used to read the rotation angle from the Revit API. Important here is that the cross-section rotation angle of slanted columns can’t be detected here and the node returns “null”. This null value is replaced by a zero value. This is not causing problems, as the Curve.NormalAtParameter node working on the location line of a slanted column, returns the vector aligned with the local y-axis of the column, and thus doesn’t need angle correction.
The result is used to define the 2nd dimension of the section view crop region for the Top view and the Cross Section view in combination with the result from Step 4.
Vector and element collection
The collection of the information of vectors, elements and view names is the last part before the section generation is executed. The information is collected with the List.Create node and then transposed with List.Transpose to finally be send in a flattened array to the custom Element View Creation node.
In (1) the vectors for the X-axis of the section are collected and similar is done for the Y-axis of the section.
The combination of these lists will results in the next sections in case of structural framing
Index 0 : X = length axis, Y = normal vector -> Front view
Index 1 : X = normal vector, Y = rotated normal vector -> Cross Section view
Index 2: X = length axis, Y = rotated normal vector -> Top (Side) view
In (2) the number of section view types are calculated. In this case we want 3 different views. For the ease of lacing of the Revit elements in the Element View Creation node, we will cycle the elements until 3 times (repeating).
Finally the view names need to be unique and so we will make a view name with a static part (Top, Front, Side, …) and a unique parameter of the element.
In this case the value of the “Mark” parameter within Revit is used.
Element view creation
All the datacollections for vectors, Revit elements and view names are joined with List.Join and send to the custom node Create Element View (which is also included in the dataset at the bottom of this article). Let me explain you how this custom node works below.
The goal of the custom node is to define a section view that is aligned to the boundaries of the element, whether it is a horizontal, vertical, inclined, rotated, slanted, … element. The Front, Top and Side view should follow the length axis, and the Cross section should be perpendicular.
The Revit nodes in Dynamo offer a specific node for that, called SectionView.ByCoordinateSystemMinPointMaxPoint. The inputs that we need here are:
– The coordinate system in which the section view should act (i.e. a coordinates system where x aligns with the element length, y with the normal vector, will return a section as a Top view on the element. Z = the section view depth)
– minPoint / maxPoint : these are coordinate values of the points in accordance to the local cs, which will define the crop region and view depth of the section view.
The custom node will calculate these input values from the element selection and defined vectors. If you open the custom node, by double clicking it, then you will see the script as explained below.
Step 1 – Input values
The first part of the custom node is the collection of the input values.
The Element.Geometry returns the solid geometry of the elements. Below an example of the structural framings with the location line and the solid geometry visible.
Step 2 – Coordinate System and Workplanes
The custom node will generate views that are aligned to the Solid.Centroid of the Revit Element.Geometry. Crucial in here is the definition of the CoordinateSystem.ByOriginVectors on that point and the input of the previously defined xAxis and yAxis. This will be the basis of the section direction.
Additionally the same input values are used to create a plane on the centroid. This plane will be used in Step 3, to generate the section crop region boundaries.
Step 3 – Definition of the section view crop region boundaries
In this step of the custom node, the section boundaries are defined.
(1) The Geometry.Intersect generates a surface as a result of the intersection of the Element.Geometry and the Plane.ByOriginXaxisYaxis. The last one was defined in step 2, according to the vectors along and on the location line of the element. When you would unpack the custom node, and run it as a project, then these surfaces as shown below would be the result.
(2) The countour curves of these surfaces are detected, in order to offset them according the CropRegionOffset input variable. The offset is executed with positive and negative value. This is to take into account possible different offset directions, depending on the way the Revit family has been built up.
We only want the outside offset contour, but that could be generated by the “–x” value in some cases.
(3) When the offset returns a closed curve with zero-length (ie in case of a negative offset that is greater than the smallest cross distance in the original closed curve), it is filtered out with the List.FilterByBoolMask node.
(4) As we now have two closed curves generated by the Curve.Offset node, we have to detect the outer one. This can be easily done by searching for the closed curve with the biggest length, which is done here with the MaximumItemByKey function on the nested list. (Thanks to Dimitar Venkov for the tip). The outer offset contour is indicated in blue in the next image.
(5) Because we need the Curve.Startpoint of each segment of these contour lines, we need to explode the closed polycurve (which acts as a single object) into single curves again. The result of Curve.Startpoint is used then to define the minPoint and maxPoint of the section view node.
Step 4 – Definition of minPoint / maxPoint
Once we have the corner points of the section boundary lines, we need to calculate their coordinates according to the local coordinate system of the element, formed by the centroid and the previously defined x- and y-vectors. Therefore we need to translate the Curve.Startpoint geometry from Step 3 (5) from the LCS (see step 2) to the WCS, indicated by the CoordinateSystem.Identity node. This will return new points in the WCS. From these points extract the maximum and minimum X- and Y-coordinate. These will be used in the final step 5.
Step 5 – Section view creation
In this last step of the custom node, the coordinatesystem, minPoint and maxPoint are used for the section creation and the view is instantly renamed to the required one, defined in earlier in the main workspace.
(1) The calculated local coordinates in step 4 are connected with Point.ByCoordinates nodes. The top one is used for the minimal X-Y coordinates, the bottom one for the maximal values.
(2) The CropRegionOffset is used to set the Z-value of the minPoint. This will define the position of the section line in Revit in accordance to the centroid of the solid. The ViewDepth value results in the “Far Clip Offset” parameter in Revit. But for the SectionView creation we need the absolute Z-value, which is recalculated here by subtracting the CropRegionOffset in order to have the distance of maxPoint.Z to the centroid point.
SectionView.ByCoordinateSystemMinPointMaxPoint is the magic node that generates the section views with all the calculations that are made before.
(4) The finishing touch is to rename the automatic created section into some logical name (ie. “Front – B4”).
The whole dataset can be downloaded here.
At the moment it is only implemented for columns and beams. Walls should be implemented very soon. But please, feel free to give any suggestions !
I hope you enjoy it !