This week we continue on the path to automating interior elevations. As a reminder, I have been building a plug-in that automates various parts of creating interior elevations, and I will continue to develop it. Since this project will evolve as I continue, I have determined to set my primary goal for each stage. With this goal in mind, I will develop a functioning piece of software to meet the goal. Then I will discuss topics that cover key aspects for each step for building the plug-in. At the end of each stage, I will move the plug-in to a public repository on GitHub so you can use it too.
Part 1: filtered element collector [c#]
Part 3: ViewFamilyTypeId
Part 4: ViewPlanId and Levels
Part 5: phases & goal #1 complete [includes GitHub link to the release]
Part 6: view tempaltes
Part 7: resizing CropBoxes
Override the view’s parameters to set a view template, update the extents of the views, create a masking region, override the inside line weight of the masking region
Since we resized the CropBox, we now want to place our masking region. The reason a masking region can be helpful is that when you want to have the border of the interior elevation follow along door openings and changes in ceilings and soffits, it can be easier to do it with a masking region. It also makes it easier to adjust the line weight around the elevation rather than having to worry about overriding the display graphics of the interior elevation crop every time.
Because we are using the filled regions to mask the parts around our view that are beyond the room, we need to create a donut-shaped filled region. Anything in the middle is visible and anything beyond that will be masked. For this, we need inside and outside boundaries.
We create a new public method that returns a list of CurveLoops which we will use to create our FilledRegion. We call it FilledRegionBoundary and it needs a ViewSection parameter which will be our interior elevation view. If you remember from Part 7, when we set the interior elevation view CropBox, we set it so that it was 1’-0” beyond the room in width and height. So when we get the bounds of the interior elevation CropBox, they will be 1’-0” beyond the room. This is why, for the inside boundary, we need to add 1 to the minimum value and subtract 1 from the maximum value. This will put the boundary back to the edge of the room. Also similar to Part 7, we have to perform some more transformations. I have to give a shoutout to my husband who helped me with the inverse matrices. If you remember, when you get the coordinates of the CropBox of the elevations view it uses the coordinate system of the view. However, to create our filled region, we need to work with the project coordinates. To to do this, we actually have to use an inverse matrix to reverse the translations and rotations back to the project coordinate system. I added these methods to a utility file for matrices. You can get access to it through my GitHub account. After we find the correct coordinates, we simply draw lines between them and add those lines to a list.
Since we want the outside curve to be set back from the CropBox a bit, we can take the CropBox coordinates and set them back 6”. Then we transform the coordinates with the inverse matrix as we did for the interior boundary. After we find the correct coordinates, we simply draw lines between them and add those lines to a list just like above.
Finally, we create a CurveLoop for both the inside and outside curves. We add both to a list of CurveLoops which we return to use to create our FilledRegion.
Now that we have the curves for the boundaries of our filled region, we just have to create the filled region. We create a new public method that does not return anything. It takes in our document, the interior elevation ViewSection, and the room’s BoundingBoxXYZ as parameters. The first thing we do is call our filledRegionBoundaries method to get our boundaries. Then we need to get the element Id of the type of filled region we want to create. Since we are using it to mask our view, we want the fill pattern to be white (RGB 255, 255, 255). For Revit 2019 and above, filled regions that are opaque have the IsMasking property set to true. You can also change the filters below or make them more specific if you need to. This code block then returns the TypeId of the filled region we need. We can then use this along with our interior elevation view’s Id and our boundaries to create our filled region. Finally, we override the line thickness to provide us with a thicker outline. For the code below, I just filtered for a line that contained “05” and “solid” in the name. It is more complex to filter for line style properties like the thickness and pattern. You may need to adjust the filter for the name based on how you name your lines.
Our final step is to add the methods we’ve created in Goal #2 to the Execute method. We circle through each elevation,
overwrite the CropBox, create the filled regions, and adjust the line weight of the filled regions. This means that we
have completed Goal #2. You can access the updated code on my
There you can also download the DLL so you can use the updated plug-in too. Have fun!
Please note that since we have now added even more filters and hard-coded selections, there are a couple of things you need to use this plug-in as written. Your Revit file needs:
I’m taking a break next week because of the holidays, but check back December 6 for the next post in the series. That week, we set our 3rd and final goal so that everyone can enjoy automated interior elevations by the end of the year. Have a great turkey day!