There are times where you wish you could automate some things to do with Levels, Grids or Reference Planes. For instance, you want to change all the Grid Bubble locations for a set of grids in one hit instead of having to manually do each Grid one by one (you know this is painful, everyone moans about this), so we will have a little excursion into Datum Planes and how we can use the API and Dynamo/Python to automate some things…
What is a Datum Plane?
The DatumPlane Class is the Base Class of Elements such as Levels, Grids and Reference Planes. (Base Class means that Elements of that Base Class will inherit some of the same properties of that Base Class). The Datum Plane Class gives us access to properties such as the 2D and 3D endpoints of the Datum Element, or the end of which the Grid Bubble is shown or getting the Curves used to create the Datum Element.
Have a look here for the members of the DatumPlane Class as you will get a rough feel for what can be done. Also, have a look at the DatumPlanes sub-classes (Grids, Levels and Reference Planes). Note how similar the methods are for each.
Using DatumPlanes in Dynamo/Python
For an example, we will do a simple Flip Bubble Ends script. This will flip the end of which the DatumPlane Bubble is shown. This does not work with Reference Planes as these don’t have a “Bubble”, but will work with Grids and Levels. The end result should do something like this…
The DatumPlane Class inherits from the Element Class which is part of the Autodesk.Revit.DB Namespace. This means that when we use Python in Dynamo we need to make sure we reference the RevitAPI and the DB namespace. Here is the first part of what you will need to get started…
import clr clr.AddReference("RevitNodes") import Revit clr.ImportExtensions(Revit.Elements) # Import DocumentManager and TransactionManager clr.AddReference("RevitServices") import RevitServices from RevitServices.Persistence import DocumentManager from RevitServices.Transactions import TransactionManager doc = DocumentManager.Instance.CurrentDBDocument uidoc = DocumentManager.Instance.CurrentUIDocument # Import RevitAPI clr.AddReference("RevitAPI") import Autodesk from Autodesk.Revit.DB import *
I won’t go into details of the above code as this is explained in detail in the Intro To The Python Node series under References, References, References. If you are new to Python for Dynamo, read those first as this will make more sense.
Here we will add a Definition to ensure we are always using a list (just in case the user passes a singleton we can still use a for loop) and we are also defining the IN and OUT variables…
############# DEFINITIONS ############### #convert to list... def tolist(obj1): if hasattr(obj1,"__iter__"): return obj1 else: return [obj1] ############# VARIABLES ############### # Declare IN-Variables... dpElems = tolist(UnwrapElement(IN[0])) views = tolist(UnwrapElement(IN[1])) # Declare OUT-Variables... outList = [] errList = []
Now for the main part of the script. We will Loop through all view passes in and then loop through all Datum Elements in that view, Test the ends which the Bubbles are shown and flip them by showing/hiding depending which side they are shown…
## Main Script - flip DatumPlane Elements Bubble from one end to the other... # Open a transaction so we can make changes to the Revit Document... TransactionManager.Instance.EnsureInTransaction(doc) # Loop through all the Views... for v in views: # Empty Arrays to collect results for each DatumPlane for each view... dpArr = [] errArr = [] # Loop through each DatumPlane Element... for dp in dpElems: try: # Test if Bubbles at both ends are visible... if dp.IsBubbleVisibleInView(DatumEnds.End0,v) and dp.IsBubbleVisibleInView(DatumEnds.End1,v): dp.HideBubbleInView(DatumEnds.End0,v) dp.HideBubbleInView(DatumEnds.End1,v) dpArr.append(dp) errArr.append(None) # Test if Bubbles at both ends are NOT visible... elif not dp.IsBubbleVisibleInView(DatumEnds.End0,v) and not dp.IsBubbleVisibleInView(DatumEnds.End1,v): dp.ShowBubbleInView(DatumEnds.End0,v) dp.ShowBubbleInView(DatumEnds.End1,v) dpArr.append(dp) errArr.append(None) # Test if Bubble is visible at End 0 (or the start) elif dp.IsBubbleVisibleInView(DatumEnds.End0,v): dp.HideBubbleInView(DatumEnds.End0,v) dp.ShowBubbleInView(DatumEnds.End1,v) dpArr.append(dp) errArr.append(None) # Test if Bubble is visible at End 1 (or the end) elif dp.IsBubbleVisibleInView(DatumEnds.End1,v): dp.HideBubbleInView(DatumEnds.End1,v) dp.ShowBubbleInView(DatumEnds.End0,v) dpArr.append(dp) errArr.append(None) # catch any exceptions... except Exception, e: dpArr.append(None) errArr.append(e.message) # append to our OUT-Variables... outList.append(dpArr) errList.append(errArr) # Regenerate the document to allow us to see changes... doc.Regenerate() # Close the Transaction and commit changes to Revit... TransactionManager.Instance.TransactionTaskDone()
Note, the Methods IsBubbleVisibleInView(), HideBubbleInView() and ShowBubbleInView() require two arguments of a DatumEnd and a view. The DatumEnd is an Enum (more about Enums here). DatumEnds have just two members, End0 (start of the DatumPlane) and End1 (end of the DatumPlane). For instance, the IsBubbleVisibleInView() Method takes a DatumEnd and a view and returns a bool whether a Bubble is being shown at the specified end in the specified View for that DatumPlane. See below for the Syntax as shown in the Revit API help…
#SAMPLE OF SYNTAX FROM REVIT API DOCS - DO NOT COPY THIS INTO PYTHON...
public bool IsBubbleVisibleInView(
DatumEnds datumEnd,
View view
)
Finally, we will finish off with the following, this will refresh the active view so the changes are visible and return the DatumPlane Elements that have been updated or the errors that occurred while trying to flip the Bubbles.
# Refresh the ActiveView so changes are visible... uidoc.RefreshActiveView() # Return the OUT-Variables... OUT = outList, errList
So, the full script should look like this…
import clr clr.AddReference("RevitNodes") import Revit clr.ImportExtensions(Revit.Elements) # Import DocumentManager and TransactionManager clr.AddReference("RevitServices") import RevitServices from RevitServices.Persistence import DocumentManager from RevitServices.Transactions import TransactionManager doc = DocumentManager.Instance.CurrentDBDocument uidoc = DocumentManager.Instance.CurrentUIDocument # Import RevitAPI clr.AddReference("RevitAPI") import Autodesk from Autodesk.Revit.DB import * ############# DEFINITIONS ############### #convert to list... def tolist(obj1): if hasattr(obj1,"__iter__"): return obj1 else: return [obj1] ############# VARIABLES ############### # Declare IN-Variables... dpElems = tolist(UnwrapElement(IN[0])) views = tolist(UnwrapElement(IN[1])) # Declare OUT-Variables... outList = [] errList = [] ## Main Script - flip DatumPlane Elements Bubble from one end to the other... # Open a transaction so we can make changes to the Revit Document... TransactionManager.Instance.EnsureInTransaction(doc) # Loop through all the Views... for v in views: # Empty Arrays to collect results for each DatumPlane for each view... dpArr = [] errArr = [] # Loop through each DatumPlane Element... for dp in dpElems: try: # Test if Bubbles at both ends are visible... if dp.IsBubbleVisibleInView(DatumEnds.End0,v) and dp.IsBubbleVisibleInView(DatumEnds.End1,v): dp.HideBubbleInView(DatumEnds.End0,v) dp.HideBubbleInView(DatumEnds.End1,v) dpArr.append(dp) errArr.append(None) # Test if Bubbles at both ends are NOT visible... elif not dp.IsBubbleVisibleInView(DatumEnds.End0,v) and not dp.IsBubbleVisibleInView(DatumEnds.End1,v): dp.ShowBubbleInView(DatumEnds.End0,v) dp.ShowBubbleInView(DatumEnds.End1,v) dpArr.append(dp) errArr.append(None) # Test if Bubble is visible at End 0 (or the start) elif dp.IsBubbleVisibleInView(DatumEnds.End0,v): dp.HideBubbleInView(DatumEnds.End0,v) dp.ShowBubbleInView(DatumEnds.End1,v) dpArr.append(dp) errArr.append(None) # Test if Bubble is visible at End 1 (or the end) elif dp.IsBubbleVisibleInView(DatumEnds.End1,v): dp.HideBubbleInView(DatumEnds.End1,v) dp.ShowBubbleInView(DatumEnds.End0,v) dpArr.append(dp) errArr.append(None) # catch any exceptions... except Exception, e: dpArr.append(None) errArr.append(e.message) # append to our OUT-Variables... outList.append(dpArr) errList.append(errArr) # Regenerate the document to allow us to see changes... doc.Regenerate() # Close the Transaction and commit changes to Revit... TransactionManager.Instance.TransactionTaskDone() # Refresh the ActiveView so changes are visible... uidoc.RefreshActiveView() # Return the OUT-Variables... OUT = outList, errList
More scripts using DatumPlanes
Here are some more examples of using DatumPlanes which might be useful or you can build upon…
(Content T.B.C)
May 4, 2021 at 11:11 am
Thanks for this useful tutorial.
LikeLiked by 1 person