Revit 2014 API Developer Guide
Revit 2014 API Developer Guide
Developers Guidelines
Keldar67@gmail.com
Index
Developers
Introduction
Welcome to the Revit Platform API
What Can you do with the Revit Platform API
Requirements
Installation
Supported Programming Languages
User Manual
Documentation Conventions
Whats new in this release
o Getting Started
Walkthroughs
Walkthrough: Hello World
Walkthrough: Add Hello World Ribbon Panel
Walkthrough: Retrieve Selected Elements
Walkthrough: Retrieve Filtered Elements
o Add-In Integration
Overview
External Commands
External Application
Add-In Registration
Localization
Attributes
Revit Exceptions
Ribbon Panels and Controls
Revit Style Task Dialogs
DB Level External Applications
o Application and Document
Application Functions
Discipline Controls
How to use Application properties to enforce a correct version for your add-in
Document Functions
Document and File Management
Settings
Units
o Element Essentials
Element Classification
Other Classifications
Element Retrieval
General Properties
Basic Interaction with Revit Elements
o Filtering
Create a FilteredElementCollector
Applying Filters
Getting filtered elements or element ids
LINQ Queries
Bounding Box filters
Element Intersection Filters
o Selection
Changing the Selection
User Selection
Filtered User Selection
o Parameters
Walkthrough: Get Selected Elements Parameters
Definition
Builtin Parameters
Storage Types
asValueString() and SetValueString()
Parameter Relationships
Adding Parameters to Elements
Collections
Interface
Collections and Iterators
o Editing Elements
Moving Elements
Copying Elements
Rotating Elements
Aligning Elements
Mirroring Elements
Grouping Elements
Creating Arrays of Elements
Deleting Elements
Pinned Elements
o Views
About views
View Types
Overview
View3D
ViewPlan
ViewDrafting
ViewSelection
ViewSheet
ViewSchedule
o Creating a schedule
o Working with ViewSchedule
o TableView and TableData
View Filters
View Cropping
Displaced Views
UIView
Revit Geometric Elements
o Walls, Floors, Ceilings, Roofs and Openings
Walls
Floors, Ceilings and Foundations
Roofs
Curtains
Other Elements
Compound Structure
Opening
Thermal Properties
o Family Instances
Identifying Elements
Family
Family Instances
Code Samples
FamilySymbol
o Family Documents
About family documents
Creating elements in families
Create a Form Element
Create an Annotation
Visibility of family elements
Managing family types and parameters
o Conceptual Design
Point and curve objects
Forms
Rationalizing a Surface
Adaptive Components
o Datum and Information Elements
Levels
Grids
Phase
Design Options
o
Annotation Elements
Dimensions and Constraints
Detail Curve
Tags
Text
Annotation Symbol
o Geometry
Example: Retrieve Geometry Data from a Wall
Geometry Object Class
Curves
o Curve Analysis
o Curve Collections
o Curve Creation
o Curve Parameterization
o Curve Types
o Mathematical representations of curve types
GeometryInstances
Meshes
Points
PolyLines
Solids, Faces and Edges
o Edge and face parameterization
o Faces
o Face analysis
o Face splitting
o Face types
o Mathematical representation of face types
o Solid analysis
o Solid and face creation
Geometry Helper Class
Collection Classes
Example: Retrieve Geometry Data from a Beam
Extrusion Analysis of a Solid
Finding geometry by ray projection
Geometry Utility Classes
Room and Space Geometry
o Sketching
The 2D Sketch Class
3D Sketch Class
Model Curve
o Material
General Material Information
Material Management
Element Material
Material quantities
Painting the Face of an Element
o Stairs and Railings
Creating and Editing Stairs
Railings
Stairs Annotations
Stair Components
Discipline-Specific Functionality
o Revit Architecture
Rooms
o Revit Structure
Structural Model Elements
Analytical Model
Loads
Analysis Links
Analytical Links
o
Revit MEP
MEP Element Creation
Create Pipes and Ducts
Placeholders
Systems
Connectors
Family Creation
Mechanical Settings
Electrical Settings
Routing Preferences
Advanced Topics
o Storing Data in the Revit model
Shared Parameters
Definition File
Definition File Access
Binding
Extensible Storage
o Transactions
Transaction Classes
Transactions in Events
Failure Handling Options
Getting Element Geometry and AnalyticalModel
Temporary Transations
o Events
Database Events
DocumentChanged event
User Interface Events
Registering Events
Canceling Events
o External Events
o Dockable Dialog Panes
o Dynamic Model Update
Implementing IUpdater
The Execute method
Registering Updaters
Exposure to End-User
o Commands
o Failure Posting and Handling
Posting Failures
Handling Failures
o Performance Advisor
o Point Clouds
Point Cloud Client
Point Cloud Engine
o Analysis
Energy Data
Analysis Visualization
Manager for analysis results
Creating analysis results data
Anlaysis Results Display
Updating Analysis Results
Conceptual Energy Analysis
Detailed Energy Analysis Model
o Place and Locations
Place
City
Project Location
Project Position
o Worksharing
Elements in Worksets
Element Ownership
Opening a Workshared Document
Visibility and Display
Worksets
Workshared File Management
o
Construction Modeling
Assemblies and Views
Parts
o Linked Files
Revit Links
Managing External Files
o Export
Export Tables
IFC Export
Custom Export
Appendices
o Glossary
Array
BIM
Class
Events
Iterator
Method
Namespace
Overloading
Properties
Revit Families
Revit Parameters
Revit Types
Sets
Element ED
Element UID
o FAQ
General Questions
Revit Structure Questions
o Hello World for VB.Net
Create a New Project
Add Reference and Namespace
Change the Class Name
Add Code
Creat a *.addin manifest file
Build the Program
Debug the Program
o Material Properties Internal Units
o Concrete Section Definitions
Concrete-Rectangular Beam
Precast-Rectangular Beam
Precast-L Shaped Beam
Precast-Single Tee
Precast-Inverted Tee
Precast-Double Tee
o API User Interface Guidelines
Introduction
Consistency
Speaking the Users Language
Good Layout
Good Defaults
Progressive Disclosure
Localization of the User Interface
Dialog Guidelines
Ribbon Guidelines
Common Definitions
Terminology Definitions
o
Note: The Contents of this document were copied from the http://wikihelp.autodesk.com/Revit/enu/2014/Help/3665-Developers website on 16 & 17/11/2013
and are up to date as of that point. The Copyright and ownership of the information contained within remain as per the original copyright notices on the
website. This document has been put together for the purposes of offline reading and educational purposes and should only be used for this purpose. By
reading further you are agreeing to respect all copyright and ownership laws. Thank you
Most links copied will direct back to the orginal source location on the internet rather than internally within the document so differences may occur depending
on information updates
Developers
This API Developer's Guide describes how to use the application programming interface (API) for Autodesk Revit 2014.
Topics in this section
Introduction
Discipline-Specific Functionality
Advanced Topics
Appendices
Introduction
Welcome to the Revit Platform API
All Revit-based products are Parametric Building Information Modeling (BIM) tools. These tools are similar to Computer-Aided Design (CAD)
programs but are used to build 3D models as well as 2D drawings. In Revit, you place real-world elements like columns and walls into the
model. Once the model is built, you can create model views such as sections and callouts. Views are generated from the 3D physical model;
consequently, changes made in one view automatically propagate through all views. This virtually eliminates the need to update multiple
drawings and details when you make changes to the model.
Requirements
To go through the user manual, you need the following:
1. A working understanding of Revit Architecture 2013, Revit Structure 2013, or Revit MEP 2013.
2. Familiarity with a Common Language Specification compliant language like C# or VB.NET.
3. Microsoft Visual Studio 2010, or Microsoft Visual Studio 2010 Express Edition. Alternatively, you can use the built-in SharpDevelop
development environment in Revit.
4. Microsoft .NET Framework 4.0.
5. The Revit Software Developer's Kit (SDK) which you can download from the Autodesk Developer Network (ADN) or the Revit
installation CD/DVD (<DVD_Drive>:\Utilities\Common\Software Development Kit).
Installation
The Revit Platform API is installed with Revit Architecture, Revit Structure, and Revit MEP. Any .NET based application will reference the
RevitAPI.dll and the RevitAPIUI.dll located in the Revit Program directory. The RevitAPI.dll contains methods used to access Revit's
application, documents, elements and parameters at the database level. The RevitAPIUI.dll contains the interfaces related to manipulation
and customization of the Revit user interface.
User Manual
This document is part of the Revit SDK. It provides an introduction to implementing Revit add-in applications using the Revit Platform API.
Before creating a Revit Platform API add-in application read through the manual and try the sample code. If you already have some
experience with the Revit Platform API, you may just want to review the Notes and Troubleshooting sections.
Introduction to the Revit Platform API
The first two chapters present an introduction to the Revit Platform API and provide an overview of the User Manual.
Welcome to the Revit Platform API - Presents an introduction to the Revit Platform API and necessary prerequisite knowledge before you
create your first add-in.
Getting Started - Step-by-step instructions for creating your first Hello World add-in application using Visual Studio 2010 and four other
walkthroughs covering primary add-in functions.
Basic Topics
These chapters cover the Revit Platform API basic mechanisms and functionality.
Add-in Integration - Discusses how an add-in is integrated into the Revit UI and invoked by user commands or specific Revit events such as
program startup.
Application and Document - Application and Document classes respectively represent the Revit application and project file in the Revit
Platform API. This chapter explains basic concepts and links to pertinent chapters and sections.
Elements Essentials - The bulk of the data in a Revit project is in a collection of Elements. This chapter discusses the essential Element
mechanism, classification, and features.
Filtering - Filtering is used to get a set of elements from the document.
Selection - Working with the set of selected elements in a document
Parameters - Most Element information is stored as Parameters. This chapter discusses Parameter functionality.
Collection - Utility collection types such as Array, Map, Set collections, and related Iterators.
Element Topics
Elements are introduced based on element classification. Make sure that you read the Elements Essentials and Parameter chapters before
reading about the individual elements.
Editing Elements - Learn how to move, rotate, delete, mirror, group, and array elements.
Wall, Floors, Roofs and Openings - Discusses Elements, their corresponding ElementTypes representing built-in place construction, and
different types of Openings in the API.
Family Instances - Learn about the relationship between family and family instance, family and family instance features, and how to load or
create them.
Family Creation - Learn about creation and modification of Revit Family documents.
Conceptual Design - Discusses how to create complex geometry and forms in a Revit Conceptual Mass document.
Datum and Information Elements - Learn how to set up grids, add levels, use design options, and more.
Annotation Elements - Discusses document annotation including adding dimensions, detail curves, tags, and annotation symbols.
Sketching - Sketch functions include 2D and 3D sketch classes such as SketchPlane, ModelCurve, GenericForm, and more.
Views - Learn about the different ways to view models and components and how to manipulate the view in the API.
Material - Material data is an Element that identifies the physical materials used in the project as well as texture, color, and more.
Advanced Topics
Geometry - Discusses graphics-related types in the API used to describe the graphical representation of the model including the three
classes that describe and store the geometry information.
Place and Locations - Defines the project location including city, country, latitude, and longitude.
Shared Parameters - Shared parameters are external text files containing parameter specifications. This chapter introduces how to access to
shared parameters through the Revit Platform API.
Transaction - Introduces the two uses for Transaction and the limits that you must consider when using Transaction.
Events - Discusses how to take advantage of Revit Events.
Dynamic Model Update - Learn how to use updaters to modify the model in reaction to changes in the document.
Failure Posting and Handling - Learn how to post failures and interact with Revit's failure handling mechanism.
Analysis Visualization - How to display analysis results in a Revit project.
Product Specific
Revit products include Revit Architecture, Revit Structure, and Revit MEP. Some APIs only work in specific products.
Revit Architecture - Discusses the APIs specific to Revit Architecture.
Revit Structure - Discusses the APIs specific to Revit Structure.
Revit MEP - Discusses the APIs specific to Revit MEP.
Other
Appendix - Additional information such as Frequently Asked Questions, Using Visual Basic.Net for programming, and more.
Documentation Conventions
This document contains class names in namespace format, such as Autodesk.Revit.DB.Element. In C++/CLI Autodesk.Revit.Element is
Autodesk::Revit::DB::Element. Since only C# is used for sample code in this manual, the default namespace is Autodesk.Revit.DB. If you
want to see code in Visual Basic, you will find several VB.NET applications in the SDK Samples directory.
Indexed Properties
Some Revit Platform API class properties are "indexed", or described as overloaded in the API help file (RevitAPI.chm). For example, the
Element.Geometry property. In the text of this document, these are referred to as properties, although you access them as if they were
methods in C# code by pre-pending the property name with "get_" or "set_". For example, to use the Element.Geometry(Options) property,
you use Element.get_Geometry(Options).
Getting Started
The Revit Platform API is fully accessible by any language compatible with the Microsoft .NET Framework 4.0, such as Visual C# or Visual
Basic .NET (VB.NET). Both Visual C# and VB.NET are commonly used to develop Revit Platform API applications. However, the focus of this
manual is developing applications using Visual C#.
Walkthroughs
If you are new to the Revit Platform API, the following topics are good starting points to help you understand the product. Walkthroughs
provide step-by-step instructions for common scenarios, helping you learn about the product or a particular feature. The following
walkthroughs will help you get started using the Revit Platform API:
Walkthrough: Hello World - Illustrates how to create an add-in using the Revit Platform API.
Walkthrough: Add Hello World Ribbon Panel - Illustrates how to add a custom ribbon panel.
Walkthrough: Retrieve Selected Elements - Illustrates how to retrieve selected elements.
Walkthrough: Retrieve Filtered Elements - Illustrates how to retrieve elements based on filter criteria.
Project.
Add References
1. To add the RevitAPI reference:
o
From the View menu select Solution Explorer if the Solution Explorer window is not open.
From the context menu, click Add Reference. The Add Reference dialog box appears.
In the Add Reference dialog box, click the Browse tab. Locate the folder where Revit is installed and click the RevitAPI.dll. For
example, the installed folder location is usually C:\Program Files\Autodesk\Revit Architecture 2012\Program\RevitAPI.dll.
Click OK to select the .dll and close the dialog box. RevitAPI appears in the Solution Explorer reference tree.
Note: You should always set the Copy Local property of RevitAPI.dll to false for new projects. This saves disk space, and
prevents the Visual Studio debugger from getting confused about which copy of the DLL to use. Right-click the RevitAPI.dll,
select Properties, and change the Copy Local setting from true (the default) to false.
methods. After you add ":IExternaCommand" after Class1 in the example above, you can select "Implement IExternalCommand" from the
Intellisense menu to get the code:
Code Region 2-2: Creating a .addin manifest file for an external command
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<RevitAddIns>
<AddIn Type="Command">
<Assembly>D:\Sample\HelloWorld\bin\Debug\HelloWorld.dll</Assembly>
<AddInId>239BD853-36E4-461f-9171-C5ACEDA4E721</AddInId>
<FullClassName>HelloWorld.Class1</FullClassName>
<Text>HelloWorld</Text>
<VendorId>ADSK</VendorId>
<VendorDescription>Autodesk, www.autodesk.com</VendorDescription>
</AddIn>
</RevitAddIns>
3. Save the file as HelloWorld.addin and put it in the following location:
o
If your application assembly dll is on a network share instead of your local hard drive, you must modify Revit.exe.config to
allow .NET assemblies outside your local machine to be loaded. In the "runtime" node in Revit.exe.config, add the element
<loadFromRemoteSources enabled="true"/> " as shown below.
<runtime>
<generatePublisherEvidence enabled="false" />
<loadFromRemoteSources enabled="true"/>
</runtime>
o
o
o
Troubleshooting
Q: My add-in application will not compile.
A: If an error appears when you compile the sample code, the problem may be with the version of the RevitAPI used to compile the add-in.
Delete the old RevitAPI reference and load a new one. For more details, refer to Add Reference.
Q: Why is there no Add-Ins tab or why isn't my add-in application displayed under External Tools?
A: In many cases, if an add-in application fails to load, Revit will display an error dialog on startup with information about the failure. For
example, if the add-in DLL cannot be found in the location specified in the manifest file, a message similar to the following appears.
However, in some cases, an add-in application may fail to load without any message. Possible causes include:
The add-in application is compiled with a different RevitAPI version
The manifest file is not found
There is a formatting error in the .addin manifest file
Q: Why does my add-in application not work?
A: Even though your add-in application is available under External Tools, it may not work. This is most often caused by an exception in the
code.
For example:
From the context menu, click Add Reference. The Add Reference dialog box appears.
Click OK to close the dialog box. PresentationCore appears in the Solution Explorer reference tree.
The Add Panel project is different from Hello World because it is automatically invoked when Revit runs. Use the IExternalApplication
interface for this project. The IExternalApplication interface contains two abstract methods, OnStartup() and OnShutdown(). For more
information about IExternalApplication, refer to Add-in Integration.
Add the following code for the ribbon panel:
Autodesk.Revit.UI;
Autodesk.Revit.DB;
System.Windows.Media.Imaging;
CsAddpanel : Autodesk.Revit.UI.IExternalApplication
public Autodesk.Revit.UI.Result OnStartup(UIControlledApplication application)
{
// add new ribbon panel
RibbonPanel ribbonPanel = application.CreateRibbonPanel("NewRibbonPanel");
//Create a push button in the ribbon panel "NewRibbonPanel"
//the add-in application "HelloWorld" will be triggered when button is pushed
PushButton pushButton = ribbonPanel.AddItem(new PushButtonData("HelloWorld",
"HelloWorld", @"D:\HelloWorld.dll", "HelloWorld.CsHelloWorld")) as PushButton;
// Set the large image shown on button
Uri uriImage = new Uri(@"D:\Sample\HelloWorld\bin\Debug\39-Globe_32x32.png");
BitmapImage largeImage = new BitmapImage(uriImage);
pushButton.LargeImage = largeImage;
return Result.Succeeded;
}
public Result OnShutdown(UIControlledApplication application)
{
return Result.Succeeded;
}
}
Build the Application
After completing the code, build the application. From the Build menu, click Build Solution. Output from the build appears in the Output
window indicating that the project compiled without errors. AddPanel.dll is located in the project output directory.
Create the .addin manifest file
To invoke the application in Revit, create a manifest file to register it into Revit.
1. Create a new text file using Notepad.
2. Add the following text to the file:
Note The AddPanel.dll file is in the default file folder in a new folder called Debug (D:\Sample\HelloWorld\bin\Debug\AddPanel.dll). Use the
Add-In Integration
Developers add functionality by creating and implementing External Commands and External Applications. Revit identifies the new
commands and applications using .addin manifest files.
External Commands appear under the External Tools menu-button on the Add-Ins tab.
External Applications are invoked when Revit starts up and unloaded when Revit shuts down
This chapter focuses on the following:
Learning how to add functionality using External Commands and External Applications.
How to access Revit events.
How to customize the Revit UI.
Overview
The Revit Platform API is based on Revit application functionality. The Revit Platform API is composed of two class Libraries that only work
when Revit is running.
The RevitAPI.dll contains methods used to access Revit's application, documents, elements, and parameters at the database level. It also
contains IExternalDBApplication and related interfaces.
The RevitAPIUI.dll contains all API interfaces related to manipulation and customization of the Revit user interface, including:
IExternalCommand and External Command related interfaces
IExternalApplication and related interfaces
Selection
RibbonPanel, RibbonItem and subclasses
TaskDialogs
As the following picture shows, Revit Architecture, Revit Structure, and Revit MEP are specific to Architecture, Structure, and MEP
respectively.
External Commands
Developers can add functionality by implementing External Commands which appear in the External Tools menu-button.
Loading and Running External Commands
When no other commands or edit modes are active in Revit, registered external commands are enabled. When a command is selected, a
command object is created and its Execute() method is called. Once this method returns back to Revit, the command object is destroyed. As
a result, data cannot persist in the object between command executions. However, there are other ways to save data between command
executions; for example you can use the Revit shared parameters mechanism to store data in the Revit project.
You can add External Commands to the External Tools Panel under the External Tools menu-button, or as a custom ribbon panel on the AddIns tab, Analyze tab or a new custom ribbon tab. See the Walkthrough: Hello World and Walkthrough: Add Hello World Ribbon Panel for
examples of these two approaches.
External tools, ribbon tabs and ribbon panels are initialized upon start up. The initialization steps are as follows:
Revit reads manifest files and identifies:
o
External Tools that can be added to the Revit External Tools menu-button.
External Application session adds panels and content to the Add-ins tab.
IExternalCommand
You create an external command by creating an object that implements the IExternalCommand interface. The IExternalCommand interface
has one abstract method, Execute, which is the main method for external commands.
The Execute() method has three parameters:
commandData (ExternalCommandData)
message (String)
elements (ElementSet)
commandData (ExternalCommandData)
The ExternalCommandData object contains references to Application and View which are required by the external command. All Revit data is
retrieved directly or indirectly from this parameter in the external command.
For example, the following statement illustrates how to retrieve Autodesk.Revit.Document from the commandData parameter:
Description
Application (Autodesk.Revit.UI.UIApplication)
Retrieves an object that represents the current UIApplication for external command.
JournalData
A data map that can be used to read and write data to the Revit journal file.
(IDictionary<String, String>)
View (Autodesk.Revit.DB.View)
Retrieves an object that represents the View external commands work on.
message (String):
Error messages are returned by an external command using the output parameter message. The string-type parameter is set in the external
command process. When Autodesk.Revit.UI.Result.Failed or Autodesk.Revit.UI.Result.Cancelled is returned, and the message parameter is
set, an error dialog appears.
The following code sample illustrates how to use the message parameter.
Implementing the previous external command causes the following dialog box to appear:
Description
Autodesk.Revit.UI.Result.Succeeded
The external command completed successfully. Revit keeps all changes made by the external command.
Autodesk.Revit.UI.Result.Failed
The external command failed to complete the task. Revit reverses operations performed by the external command. If
the message parameter of Execute is set, Revit displays a dialog with the text "Error - cannot be ignored".
Autodesk.Revit.UI.Result.Cancelled
The user cancelled the external command. Revit reverses changes made by the external command. If the message
parameter of Execute is set, Revit displays a dialog with the text "Warning - can be ignored".
The following example displays a greeting message and allows the user to select the return value. Use the Execute() method as the entrance
to the Revit application.
IExternalCommandAvailability
This interface allows you control over whether or not an external command button may be pressed. The IsCommandAvailable interface
method passes the application and a set of categories matching the categories of selected items in Revit to your implementation. The typical
use would be to check the selected categories to see if they meet the criteria for your command to be run.
In this example the accessibility check allows a button to be clicked when there is no active selection, or when at least one wall is selected:
External Application
Developers can add functionality through External Applications as well as External Commands. Ribbon tabs and ribbon panels are customized
using the External Application. Ribbon panel buttons are bound to an External command.
IExternalApplication
To add an External Application to Revit, you create an object that implements the IExternalApplication interface.
The IExternalApplication interface has two abstract methods, OnStartup() and OnShutdown(), which you override in your external
application. Revit calls OnStartup() when it starts, and OnShutdown() when it closes.
This is the OnStartup() and OnShutdown() abstract definition:
// Show the prompt message, and allow the user to close the dialog directly.
TaskDialog taskDialog = new TaskDialog("Revit");
taskDialog.MainContent = promptInfo;
TaskDialogCommonButtons buttons = TaskDialogCommonButtons.Ok |
TaskDialogCommonButtons.Cancel;
taskDialog.CommonButtons = buttons;
TaskDialogResult result = taskDialog.Show();
if (TaskDialogResult.Cancel == result)
{
// Do not show the Revit dialog
args.OverrideResult(1);
}
else
{
// Continue to show the Revit dialog
args.OverrideResult(0);
}
}
}
Add-in Registration
External commands and external applications need to be registered in order to appear inside Revit. They can be registered by adding them
to a .addin manifest file.
The order that external commands and applications are listed in Revit is determined by the order in which they are read in when Revit starts
up.
Manifest Files
Starting with Revit 2011, the Revit API offers the ability to register API applications via a .addin manifest file. Manifest files are read
automatically by Revit when they are placed in one of two locations on a user's system:
In a non-user-specific location in "application data":
For Windows XP - C:\Documents and Settings\All Users\Application Data\Autodesk\Revit\Addins\2014\
For Vista/Windows 7 - C:\ProgramData\Autodesk\Revit\Addins\2014\
In a user-specific location in "application data":
For Windows XP - C:\Documents and Settings\<user>\Application Data\Autodesk\Revit\Addins\2014\
For Vista/Windows 7 - C:\Users\<user>\AppData\Roaming\Autodesk\Revit\Addins\2014\
All files named .addin in these locations will be read and processed by Revit during startup. All of the files in both the user-specific location
and the all users location are considered together and loaded in alphabetical order. If an all users manifest file shares the same name with a
user-specific manifest file, the all users manifest file is ignored. Within each manifest file, the external commands and external applications
are loaded in the order in which they are listed.
A basic file adding one ExternalCommand looks like this:
A basic file adding one DB-level External Application looks like this:
Description
Assembly
The full path to the add-in assembly file. Required for all ExternalCommands and ExternalApplications.
FullClassName
The full name of the class in the assembly file which implements IExternalCommand or IExternalApplication. Required for all
ExternalCommands and ExternalApplications.
AddInId
A GUID which represents the id of this particular application. AddInIds must be unique for a given session of Revit.
Autodesk recommends you generate a unique GUID for each registered application or command. Required for all
ExternalCommands and ExternalApplications.
Name
Text
The name of the button. Optional; use this tag for ExternalCommands only. The default is "External Tool".
VendorId
A string conforming to the Autodesk vendor ID standard. Required for all ExternalCommands and ExternalApplications.
Register your vendor id string with Autodesk at http://www.autodesk.com/symbreg.
VendorDescription
Description containing vendor's legal name and/or other pertinent information. Optional.
Description
Short description of the command, will be used as the button tooltip. Optional; use this tag for ExternalCommands only.
The default is a tooltip with just the command text.
VisibilityMode
The modes in which the external command will be visible. Multiple values may be set for this option. Optional; use this tag for
ExternalCommands only.
The default is to display the command in all modes, including when there is no active document. Previously written external
commands which need to run against the active document should either be modified to ensure that the code deals with
invocation of the command when there is no active document, or apply the NotVisibleWhenNoActiveDocument mode. See
table below for more information.
Discipline
The disciplines in which the external command will be visible. Multiple values may be set for this option. Optional; use this tag
for ExternalCommands only.
The default is to display the command in all disciplines. If any specific disciplines are listed, the command will only be visible in
those disciplines. See table below for more information.
AvailabilityClassName
The full name of the class in the assembly file which implemented IExternalCommandAvailability. This class allows the
command button to be selectively grayed out depending on context. Optional; use this tag for ExternalCommands only.
The default is a command that is available whenever it is visible.
LargeImage
The icon to use for the button in the External Tools pulldown menu. Optional; use this tag for ExternalCommands only.
The default is to show a button without an icon.
SmallImage
The icon to use if the button is promoted to the Quick Access Toolbar. Optional; use this tag for ExternalCommands only.
The default is to show a Quick Access Toolbar button without an icon, which can be confusing to users.
LongDescription
Long description of the command, will be used as part of the button extended tooltip, shown when the mouse hovers over the
command for a longer amount of time. Optional; use this tag for ExternalCommands only. If this property and TooltipImage
are not supplied, the button will not have an extended tooltip.
TooltipImage
An image file to show as a part of the button extended tooltip, shown when the mouse hovers over the command for a longer
amount of time. Optional; use this tag for ExternalCommands only. If this property and TooltipImage are not supplied, the
button will not have an extended tooltip.
LanguageType
Localization setting for Text, Description, LargeImage, LongDescription, and TooltipImage of external tools buttons. Revit will
load the resource values from the specified language resource dll. The value can be one of the eleven languages supported by
Revit. If no LanguageType is specified, the language resource which the current session of Revit is using will be automatically
loaded. For more details see the section on Localization.
AllowLoadIntoExistingSession
The flag for loading permission. Set to false to prevent Revit from automatically loading addins in a newly added .addin
manifest file without restarting. Optional. By default. Revit will automatically load addins from newly added .addin manifest
files without restarting Revit.
Description
AlwaysVisible
The command is available in all possible modes supported by the Revit API.
NotVisibleInProject
NotVisibleInFamily
NotVisibleWhenNoActiveDocument
Description
Any
The command is available in all possible disciplines supported by the Revit API.
Architecture
Structure
StructuralAnalysis
The command is visible when the Structural Analysis discipline editing tools are available.
MassingAndSite
The command is visible when the Massing and Site discipline editing tools are available.
EnergyAnalysis
The command is visible when Energy Analysis discipline editing tools are available.
Mechanical
The command is visible when the Mechanical discipline editing tools are available, e.g. in Autodesk Revit MEP.
Electrical
The command is visible when the Electrical discipline editing tools are available, e.g. in Autodesk Revit MEP.
Piping
The command is visible when the Piping discipline editing tools are available, e.g. in Autodesk Revit MEP.
MechanicalAnalysis
The command is visible when the Mechanical Analysis discipline editing tools are available.
PipingAnalysis
The command is visible when the Piping Analysis discipline editing tools are available.
ElectricalAnalysis
The command is visible when the Electrical Analysis discipline editing tools are available.
Add-in Registration
External commands and external applications need to be registered in order to appear inside Revit. They can be registered by adding them
to a .addin manifest file.
The order that external commands and applications are listed in Revit is determined by the order in which they are read in when Revit starts
up.
Manifest Files
Starting with Revit 2011, the Revit API offers the ability to register API applications via a .addin manifest file. Manifest files are read
automatically by Revit when they are placed in one of two locations on a user's system:
In a non-user-specific location in "application data":
For Windows XP - C:\Documents and Settings\All Users\Application Data\Autodesk\Revit\Addins\2014\
For Vista/Windows 7 - C:\ProgramData\Autodesk\Revit\Addins\2014\
In a user-specific location in "application data":
For Windows XP - C:\Documents and Settings\<user>\Application Data\Autodesk\Revit\Addins\2014\
For Vista/Windows 7 - C:\Users\<user>\AppData\Roaming\Autodesk\Revit\Addins\2014\
All files named .addin in these locations will be read and processed by Revit during startup. All of the files in both the user-specific location
and the all users location are considered together and loaded in alphabetical order. If an all users manifest file shares the same name with a
user-specific manifest file, the all users manifest file is ignored. Within each manifest file, the external commands and external applications
are loaded in the order in which they are listed.
A basic file adding one DB-level External Application looks like this:
Description
Assembly
The full path to the add-in assembly file. Required for all ExternalCommands and ExternalApplications.
FullClassName
The full name of the class in the assembly file which implements IExternalCommand or IExternalApplication. Required for all
ExternalCommands and ExternalApplications.
AddInId
A GUID which represents the id of this particular application. AddInIds must be unique for a given session of Revit.
Autodesk recommends you generate a unique GUID for each registered application or command. Required for all
ExternalCommands and ExternalApplications.
Name
Text
The name of the button. Optional; use this tag for ExternalCommands only. The default is "External Tool".
VendorId
A string conforming to the Autodesk vendor ID standard. Required for all ExternalCommands and ExternalApplications.
Register your vendor id string with Autodesk at http://www.autodesk.com/symbreg.
VendorDescription
Description containing vendor's legal name and/or other pertinent information. Optional.
Description
Short description of the command, will be used as the button tooltip. Optional; use this tag for ExternalCommands only.
The default is a tooltip with just the command text.
VisibilityMode
The modes in which the external command will be visible. Multiple values may be set for this option. Optional; use this tag for
ExternalCommands only.
The default is to display the command in all modes, including when there is no active document. Previously written external
commands which need to run against the active document should either be modified to ensure that the code deals with
invocation of the command when there is no active document, or apply the NotVisibleWhenNoActiveDocument mode. See
table below for more information.
Discipline
The disciplines in which the external command will be visible. Multiple values may be set for this option. Optional; use this tag
for ExternalCommands only.
The default is to display the command in all disciplines. If any specific disciplines are listed, the command will only be visible in
those disciplines. See table below for more information.
AvailabilityClassName
The full name of the class in the assembly file which implemented IExternalCommandAvailability. This class allows the
command button to be selectively grayed out depending on context. Optional; use this tag for ExternalCommands only.
The default is a command that is available whenever it is visible.
LargeImage
The icon to use for the button in the External Tools pulldown menu. Optional; use this tag for ExternalCommands only.
The default is to show a button without an icon.
SmallImage
The icon to use if the button is promoted to the Quick Access Toolbar. Optional; use this tag for ExternalCommands only.
The default is to show a Quick Access Toolbar button without an icon, which can be confusing to users.
LongDescription
Long description of the command, will be used as part of the button extended tooltip, shown when the mouse hovers over the
command for a longer amount of time. Optional; use this tag for ExternalCommands only. If this property and TooltipImage
are not supplied, the button will not have an extended tooltip.
TooltipImage
An image file to show as a part of the button extended tooltip, shown when the mouse hovers over the command for a longer
amount of time. Optional; use this tag for ExternalCommands only. If this property and TooltipImage are not supplied, the
button will not have an extended tooltip.
LanguageType
Localization setting for Text, Description, LargeImage, LongDescription, and TooltipImage of external tools buttons. Revit will
load the resource values from the specified language resource dll. The value can be one of the eleven languages supported by
Revit. If no LanguageType is specified, the language resource which the current session of Revit is using will be automatically
loaded. For more details see the section on Localization.
AllowLoadIntoExistingSession
The flag for loading permission. Set to false to prevent Revit from automatically loading addins in a newly added .addin
manifest file without restarting. Optional. By default. Revit will automatically load addins from newly added .addin manifest
files without restarting Revit.
Description
AlwaysVisible
The command is available in all possible modes supported by the Revit API.
NotVisibleInProject
NotVisibleInFamily
NotVisibleWhenNoActiveDocument
Description
Any
The command is available in all possible disciplines supported by the Revit API.
Architecture
Structure
StructuralAnalysis
The command is visible when the Structural Analysis discipline editing tools are available.
MassingAndSite
The command is visible when the Massing and Site discipline editing tools are available.
EnergyAnalysis
The command is visible when Energy Analysis discipline editing tools are available.
Mechanical
The command is visible when the Mechanical discipline editing tools are available, e.g. in Autodesk Revit MEP.
Electrical
The command is visible when the Electrical discipline editing tools are available, e.g. in Autodesk Revit MEP.
Piping
The command is visible when the Piping discipline editing tools are available, e.g. in Autodesk Revit MEP.
MechanicalAnalysis
The command is visible when the Mechanical Analysis discipline editing tools are available.
PipingAnalysis
The command is visible when the Piping Analysis discipline editing tools are available.
ElectricalAnalysis
The command is visible when the Electrical Analysis discipline editing tools are available.
Localization
You can let Revit localize the user-visible resources of an external command button (including Text, large icon image, long and short
descriptions and tooltip image). You will need to create a .NET Satellite DLL which contains the strings, images, and icons for the button.
Then change the values of the tags in the .addin file to correspond to the names of resources in the Satellite dll, but prepended with the
@character. So the tag:
Becomes:
where ExtensionText is the name of the resource found in the Satellite DLL.
The Satellite DLLs are expected to be in a directory with the name of the language of the language-culture, such as en or en-US. The
directory should be located in the directory that contains the add-in assembly. See http://msdn.microsoft.com/en-us/library/e9zazcx5.aspx
to create managed Satellite DLLs.
You can force Revit to use a particular language resource DLL, regardless of the language of the Revit session, by specifying the language
and culture explicitly with a LanguageType tag.
For example, the entry above would force Revit to always load the values from the en-US Satellite DLL and to ignore the current Revit
language and culture settings when considering the localizable members of the external command manifest file.
Revit supports the 11 languages defined in the Autodesk.Revit.ApplicationServices.LanguageType enumerated type: English_USA, German,
Spanish, French, Italian, Dutch, Chinese_Simplified, Chinese_Traditional, Japanese, Korean, and Russian.
Attributes
The Revit API provides several attributes for configuring ExternalCommand and ExternalApplication behavior.
TransactionAttribute
The custom attribute Autodesk.Revit.Attributes.TransactionMode must be applied to your implementation class of the IExternalCommand
interface to control transaction behavior for external command. There is no default for this option. This mode controls how the API
framework expects transactions to be used when the command is invoked. The supported values are:
TransactionMode.Automatic - Revit will create a transaction in the active document before the external command is executed and
the transaction will be committed or rolled back after the command is completed (based upon the return value of the
ExternalCommand callback). The command cannot create and start its own Transactions, but it can create SubTransactions. The
command must report its success or failure status with the Result return value.
TransactionMode.Manual - Revit will not create a transaction (but it will create an outer transaction group to roll back all changes if
the external command returns a failure). Instead, you may use combinations of Transactions, SubTransactions, and
TransactionGroups as you please. You will have to follow all rules regarding use of transactions and related classes. You will have to
give your transactions names which will then appear in the Undo menu. Revit will check that all transactions (also groups and subtransactions) are properly closed upon return from an external command. If not, Revit will discard all changes made to the model.
TransactionMode.ReadOnly - No transaction (nor group) will be created, and no transaction may be created for the lifetime of the
command. The External Command may only use methods that read from the model. Exceptions will be thrown if the command
either tries to start a transaction (or group) or attempts to write to the model.
In all three modes, the TransactionMode applies only to the active document. You may open other documents during the course of the
command, and you may have complete control over the creation and use of Transactions, SubTransactions, and TransactionGroups on those
other documents (even in ReadOnly mode).
For example, to set an external command to use automatic transaction mode:
Revit Exceptions
When API methods encounter a non-fatal error, they throw an exception. Exceptions should be caught by Revit add-ins. The Revit API help
file specifies exceptions that are typically encountered for specific methods. All Revit API methods throw a subclass of
Autodesk.Revit.Exceptions.ApplicationException. These exceptions closely mirror standard .NET exceptions such as:
ArgumentException
InvalidOperationException
FileNotFoundException
However, some of these subclasses are unique to Revit:
AutoJoinFailedException
RegenerationFailedException
ModificationOutsideTransactionException
In addition, there is a special exception type called InternalException, which represents a failure path which was not anticipated. Exceptions
of this type carry extra diagnostic information which can be passed back to Autodesk for diagnosis.
The following code outlines the steps taken to create the ribbon panel pictured above. Each of the functions called in this sample is provided
in subsequent samples later in this section. Those samples assume that there is an assembly located at D:\
Sample\HelloWorld\bin\Debug\Hello.dll which contains the External Command Types:
Hello.HelloButton
Hello.HelloOne
Hello.HelloTwo
Hello.HelloThree
Hello.HelloA
Hello.HelloB
Hello.HelloC
Hello.HelloRed
Hello.HelloBlue
Hello.HelloGreen
Ribbon Panel
Custom ribbon panels can be added to the Add-Ins tab (the default) or the Analyze tab, or they can be added to a new custom ribbon tab.
There are various types of ribbon controls that can be added to ribbon panels which are discussed in more detail in the next section. All
ribbon controls have some common properties and functionality.
Ribbon Control Classes
Each ribbon control has two classes associated with it - one derived from RibbonItemData that is used to create the control (i.e.
SplitButtonData) and add it to a ribbon panel and one derived from RibbonItem (i.e. SplitButton) which represents the item after it is added
to a panel. The properties available from RibbonItemData (and the derived classes) are also available from RibbonItem (and the
corresponding derived classes). These properties can be set prior to adding the control to the panel or can be set using the RibbonItem class
after it has been added to the panel.
Tooltips
Most controls can have a tooltip set (using the ToolTip property) which is displayed when the user moves the mouse over the control. When
the user hovers the mouse over a control for an extended period of time, an extended tooltip will be displayed using the LongDescription and
the ToolTipImage properties. If neither LongDescription nor ToolTipImage are set, the extended tooltip is not displayed. If no ToolTip is
provided, then the text of the control (RibbonItem.ItemText) is displayed when the mouse moves over the control.
Contextual Help
Controls can have contextual help associated with them. When the user hovers the mouse over the control and hits F1, the contextual help
is triggered. Contextual help options include linking to an external URL, launching a locally installed help (chm) file, or linking to a topic on
the Autodesk help wiki. The ContextualHelp class is used to create a type of contextual help, and then RibbonItem.SetContextualHelp() (or
RibbonItemData.SetContextualHelp()) associates it with a control. When a ContextualHelp instance is associated with a control, the text
"Press F1 for more help" will appear below the tooltip when the mouse hovers over the control, as shown below.
The following example associates a new ContextualHelp with a push button control. Pressing F1 when hovered over the push button will
open the Autodesk homepage in a new browser window.
The ContextualHelp class has a Launch() method that can be called to display the help topic specified by the contents of this ContextualHelp
object at any time, the same as when the F1 key is pressed when the control is active. This allows the association of help topics with user
interface components inside dialogs created by an add-in application.
Associating images with controls
All of these controls can have an image associated with them using the LargeImage property. The best size for images associated with large
controls, such as non-stacked ribbon and drop-down buttons, is 3232 pixels, but larger images will be adjusted to fit the button. Stacked
buttons and small controls such as text boxes and combo boxes should have a 1616 pixel image set. Large buttons should also have a
1616 pixel image set for the Image property. This image is used if the command is moved to the Quick Access Toolbar. If the Image
property is not set, no image will be displayed if the command is moved to the Quick Access Toolbar. Note that if an image larger than
1616 pixels is used, it will NOT be adjusted to fit the toolbar.
The ToolTipImage will be displayed below the LongDescription in the extended tooltip, if provided. There is no recommended size for this
image.
Ribbon control availability
Ribbon controls can be enabled or disabled with the RibbonItem.Enabled property or made visible or invisible with the RibbonItem.Visible
property.
Ribbon Controls
In addition to the following controls, vertical separators can be added to ribbon panels to group related sets of controls.
Push Buttons
There are three types of buttons you can add to a panel: simple push buttons, drop-down buttons, and split buttons. The HelloWorld button
in Figure 13 is a push button. When the button is pressed, the corresponding command is triggered.
In addition to the Enabled property, PushButton has the AvailabilityClassName property which can be used to set the name of an
IExternalCommandAvailability interface that controls when the command is available.
Drop-down buttons
Drop-down buttons expand to display two or more commands in a drop-down menu. In the Revit API, drop-down buttons are referred to as
PulldownButtons. Horizontal separators can be added between items in the drop-down menu.
Each command in a drop-down menu can also have an associated LargeImage as shown in the example above.
Split buttons
Split buttons are drop-down buttons with a default push button attached. The top half of the button works like a push button while the
bottom half functions as a drop-down button. The Option One button in Figure 13 is a split button.
Initially, the push button will be the top item in the drop-down list. However, by using the IsSynchronizedWithCurrentItem property, the
default command (which is displayed as the push button top half of the split button) can be synchronized with the last used command. By
default it will be synched. Selecting Option Two in the split button from Figure 13 above yields:
Radio buttons
A radio button group is a set of mutually exclusive toggle buttons; only one can be selected at a time. After adding a RadioButtonGroup to a
panel, use the AddItem() or AddItems() methods to add toggle buttons to the group. Toggle buttons are derived from PushButton. The
RadioButtonGroup.Current property can be used to access the currently selected button.
Note that tooltips do not apply to radio button groups. Instead, the tooltip for each toggle button is displayed as the mouse moves over the
individual buttons.
Text box
A text box is an input control for users to enter text. The image for a text box can be used as a clickable button by setting the
ShowImageAsButton property to true. The default is false. The image is displayed to the left of the text box when ShowImageAsButton is
false, and displayed at the right end of the text box when it acts as a button, as in Figure 13.
The text entered in the text box is only accepted if the user hits the Enter key or if they click the associated image when the image is shown
as a button. Otherwise, the text will revert to its previous value.
In addition to providing a tooltip for a text box, the PromptText property can be used to indicate to the user what type of information to
enter in the text box. Prompt text is displayed when the text box is empty and does not have keyboard focus. This text is displayed in italics.
The text box in Figure 13 has the prompt text "Enter a comment".
The width of the text box can be set using the Width property. The default is 200 device-independent units.
The TextBox.EnterPressed event is triggered when the user presses enter, or when they click on the associated image for the text box when
ShowImageAsButton is set to true. When implementing an EnterPressed event handler, cast the sender object to TextBox to get the value
the user has entered as shown in the following example.
The inherited ItemText property has no effect for TextBox. The user-entered text can be obtained from the Value property, which must be
converted to a string.
See the section on stacked ribbon items for an example of adding a TextBox to a ribbon panel, including how to register the event above.
Combo box
A combo box is a pulldown with a set of selectable items. After adding a ComboBox to a panel, use the AddItem() or AddItems() methods to
add ComboBoxMembers to the list.
Separators can also be added to separate items in the list or members can be optionally grouped using the ComboBoxMember.GroupName
property. All members with the same GroupName will be grouped together with a header that shows the group name. Any items not
assigned a GroupName will be placed at the top of the list. Note that when grouping items, separators should not be used as they will be
placed at the end of the group rather than in the order they are added.
The following example produces the stacked text box and combo box in Figure 13.
Code Region: Adding a text box and combo box as stacked items
1. private void AddStackedButtons(RibbonPanel panel)
2. {
3.
ComboBoxData cbData = new ComboBoxData("comboBox");
4.
5.
TextBoxData textData = new TextBoxData("Text Box");
6.
textData.Image =
7.
new BitmapImage(new Uri(@"D:\Sample\HelloWorld\bin\Debug\39-Globe_16x16.png"));
8.
textData.Name = "Text Box";
9.
textData.ToolTip = "Enter some text here";
10.
textData.LongDescription = "<p>This is text that will appear next to the image</p>"
11.
+ "<p>when the user hovers the mouse over the control</p>";
12.
textData.ToolTipImage =
13.
new BitmapImage(new Uri(@"D:\Sample\HelloWorld\bin\Debug\39-Globe_32x32.png"));
14.
15.
IList<RibbonItem> stackedItems = panel.AddStackedItems(textData, cbData);
16.
if (stackedItems.Count > 1)
17.
{
18.
TextBox tBox = stackedItems[0] as TextBox;
19.
if (tBox != null)
20.
{
21.
tBox.PromptText = "Enter a comment";
22.
tBox.ShowImageAsButton = true;
23.
tBox.ToolTip = "Enter some text";
24.
// Register event handler ProcessText
25.
tBox.EnterPressed +=
26.
new EventHandler<Autodesk.Revit.UI.Events.TextBoxEnterPressedEventArgs>(ProcessText);
27.
}
28.
29.
ComboBox cBox = stackedItems[1] as ComboBox;
30.
if (cBox != null)
31.
{
32.
cBox.ItemText = "ComboBox";
33.
cBox.ToolTip = "Select an Option";
34.
cBox.LongDescription = "Select a number or letter";
35.
36.
ComboBoxMemberData cboxMemDataA = new ComboBoxMemberData("A", "Option A");
37.
cboxMemDataA.Image =
38.
new BitmapImage(new Uri(@"D:\Sample\HelloWorld\bin\Debug\A.bmp"));
39.
cboxMemDataA.GroupName = "Letters";
40.
cBox.AddItem(cboxMemDataA);
41.
42.
ComboBoxMemberData cboxMemDataB = new ComboBoxMemberData("B", "Option B");
43.
cboxMemDataB.Image =
44.
new BitmapImage(new Uri(@"D:\Sample\HelloWorld\bin\Debug\B.bmp"));
45.
cboxMemDataB.GroupName = "Letters";
46.
cBox.AddItem(cboxMemDataB);
47.
48.
ComboBoxMemberData cboxMemData = new ComboBoxMemberData("One", "Option 1");
49.
cboxMemData.Image =
50.
new BitmapImage(new Uri(@"D:\Sample\HelloWorld\bin\Debug\One.bmp"));
51.
cboxMemData.GroupName = "Numbers";
52.
cBox.AddItem(cboxMemData);
53.
ComboBoxMemberData cboxMemData2 = new ComboBoxMemberData("Two", "Option 2");
54.
cboxMemData2.Image =
55.
new BitmapImage(new Uri(@"D:\Sample\HelloWorld\bin\Debug\Two.bmp"));
56.
cboxMemData2.GroupName = "Numbers";
57.
cBox.AddItem(cboxMemData2);
58.
ComboBoxMemberData cboxMemData3 = new ComboBoxMemberData("Three", "Option 3");
59.
cboxMemData3.Image =
60.
new BitmapImage(new Uri(@"D:\Sample\HelloWorld\bin\Debug\Three.bmp"));
61.
cboxMemData3.GroupName = "Numbers";
62.
cBox.AddItem(cboxMemData3);
63.
}
64.
}
65. }
Slide-out panel
Use the RibbonPanel.AddSlideOut() method to add a slide out to the bottom of the ribbon panel. When a slide-out is added, an arrow is
shown on the bottom of the panel, which when clicked will display the slide-out. After calling AddSlideOut(), subsequent calls to add new
items to the panel will be added to the slide-out, so the slide-out must be added after all other controls have been added to the ribbon panel.
The ControlledApplication parameter provides access to Revit database events. Events and Updaters to which the database-level application will respond can
be registered in the OnStartup method.
Autodesk.Revit.UI.UIApplication - provides access to UI-level interfaces for the application, including the ability to add
RibbonPanels to the user interface, and the ability to obtain the active document in the user interface.
The document object is a single Revit project file representing a building model. Revit can have multiple projects open and multiple
views for one project.
o
Autodesk.Revit.UI.UIDocument - provides access to UI-level interfaces for the document, such as the contents of the
selection and the ability to prompt the user to make selections and pick points
If multiple documents are open, the active document is the one whose view is active in the Revit session.
This chapter identifies all Application and Document functions, and then focuses on file management, settings, and units. For more details
about the Element class, refer to Elements Essentials and Editing Elements and refer to the Views for more details about the view elements.
Application Functions
Application functions provide access to documents, objects, and other application data and settings. All Application and UIApplication
functions are identified and defined in the following sections.
Application
The class represents the Autodesk Revit Application, providing access to documents, options and other application wide data and settings.
Application Version Information
Application properties include VersionBuild, VersionNumber and VersionName. These can be used to provide add-in behavior based on the
release and build of Revit, as shown in How to use Application properties to enforce a correct version for your add-in.
Application-wide Settings
The SharedParametersFilename property and GetLibraryPaths() and SetLibraryPaths() methods provide access to these application-wide
settings.
Document Management
The Application class provides methods to create the following types of documents:
Family document
Project document
Project template
The OpenDocumentFile() method can be used to open any of these document types.
All open documents can be retrieved using the Documents property.
For more details, see Document and Management.
Session Information
Properties such as UserName and methods such as GetRevitServerNetworkHosts() provide read-only access to this session specific
information.
Shared Parameter Management
Revit uses one shared parameter file at a time. The Application.OpenSharedParameterFile() method accesses the shared parameter file
whose path is set in the SharedParametersFilename property. For more details, see Shared Parameter.
Events
The Application class exposes document and application events such as document open and save. Subscribing to these events notifies the
application when the events are enabled and acts accordingly. For more details, see Access to Revit Event in the Add-In Integration section.
Create
The Create property returns an Object Factory used to create application-wide utility and geometric objects in the Revit Platform API. Create
is used when you want to create an object in the Revit application memory rather than your application's memory.
Failure Posting and Handling
The FailureDefinitionRegistry, which contains all registered FailureDefinitions is available from the static GetFailureDefinitionRegistry()
method. The static method RegisterFailuresProcessor() can be used to register a custom IFailuresProcessor. For more information on posting
and handling failures, see Failure Posting and Handling.
UIApplication
This class represents an active session of the Autodesk Revit user interface, providing access to UI customization methods, events, and the
active document.
Document Management
The UIApplication provides access to the active document using the UIActiveDocument property. Additionally, a Revit document may be
opened using the overloaded OpenAndActivateDocument() method. The document will be opened with the default view active. This method
may not be called inside a transaction and may only be invoked during an event when no active document is open yet in Revit and the event
is not nested inside another event.
Add-in Management
The ActiveAddInId property gets the current active external application or external command id, while the LoadedApplications property
returns an array of successfully loaded external applications.
Ribbon Panel Utility
Use the UIApplication object to add new ribbon panels and controls to Revit.
For more details, see Ribbon Panel and Controls in the Add-In Integration section.
Extents
The DrawingAreaExtents property returns a rectangle that represents the screen pixel coordinates of drawing area, while the
MainWindowExtents property returns the rectangle that represents the screen pixel coordinates of the Revit main window
Events
The UIApplication class exposes UI related events such as when a dialog box is displayed. Subscribing to these events notifies the application
when the events are enabled and acts accordingly. For more details, see Access to Revit Event in the Add-In Integration section.
Discipline Controls
The properties:
Application.IsArchitectureEnabled
Application.IsStructureEnabled
Application.IsStructuralAnalysisEnabled
Application.IsMassingEnabled
Application.IsEnergyAnalysisEnabled
Application.IsSystemsEnabled
Application.IsMechanicalEnabled
Application.IsMechanicalAnalysisEnabled
Application.IsElectricalEnabled
Application.IsElectricalAnalysisEnabled
Application.IsPipingEnabled
Application.IsPipingAnalysisEnabled
provide read and modify access to the available disciplines. An application can read the properties to determine when to enable or disable aspects of it's UI.
When a discipline's status is toggled, Revit's UI will be adjusted, and certain operations and features will be enabled or disabled as appropriate. Enabling an
analysis mode will only take effect if the corresponding discipline is enabled. For example, enabling mechanical analysis will not take effect unless the
mechanical discipline is also enabled.
Document Functions
Document stores the Revit Elements, manages the data, and updates multiple data views. The Document class mainly provides the following
functions.
Document
The Document class represents an open Autodesk Revit project.
Settings Property
The Settings property returns an object that provides access to general components within Revit projects. For more details, see Settings.
Place and Locations
Each project has only one site location that identifies the physical project location on Earth. There can be several project locations for one
project. Each location is an offset, or rotation, of the site location. For more details, see Place and Locations.
Type Collections
Document provides properties such as FloorTypes, WallTypes, and so on. All properties return a collection object containing the
corresponding types loaded into the project.
View Management
A project document can have multiple views. The ActiveView property returns a View object representing the active view. You can filter the
elements in the project to retrieve other views. For more details, see Views.
Element Retrieval
The Document object stores elements in the project. Retrieve specific elements by ElementId or UniqueId using the Element property.
For more details, see Elements Essential.
File Management
Each Document object represents a Revit project file. Document provides the following functions:
Retrieve file information such as file path name and project title.
Provides Close() and Save() methods to close and save the document.
For more details, see Document and File management.
Element Management
Revit maintains all Element objects in a project. To create new elements, use the Create property which returns an Object Factory used to
create new project element instances in the Revit Platform API, such as FamilyInstance or Group.
The Document class can also be used to delete elements. Use the Delete() method to delete an element in the project. Deleted elements and
any dependent elements are not displayed and are removed from the Document. References to deleted elements are invalid and cause an
exception. For more details, see Editing Element.
Events
Events are raised on certain actions, such as when you save a project using Save or Save As. To capture the events and respond in the
application, you must register the event handlers. For more details, see Events.
Document Status
Several properties provide information on the status of the document:
IsModifiable - whether the document may be modified
IsModified - whether the document was changed since it was opened or saved
IsReadOnly - whether the document is currently read only or can be modified
IsReadOnlyFile - whether the document was opened in read-only mode
IsFamilyDocument - whether the document is a family document
IsWorkshared - whether worksets have been enabled in the document
Others
Document also provides other functions:
ParameterBindings Property - Mapping between parameter definitions and categories. For more details, see Shared Parameter.
ReactionsAreUpToDate Property - Reports whether the reactionary loads changed. For more details, see Loads in the Revit Structure
section.
UIDocument
The UIDocument class represents an Autodesk Revit project opened in the Revit user interface.
Element Retrieval
Retrieve selected elements using the Selection property in UIDocument. This property returns an object representing the active selection
containing the selected project elements. It also provides UI interaction methods to pick objects in the Revit model.
For more details, see Elements Essential.
Element Display
The ShowElements() method uses zoom to fit to focus in on one more elements.
View Management
The UIDocument class can be used to refresh the active view in the active document by calling the RefreshActiveView() method. The
ActiveView property can be used to retrieve or set the active view for the document. Changing the active view has some restrictions. It can
only be used in an active document, which must not be in read-only state and must not be inside a transaction. Additionally, the active view
may not be changed during the ViewActivating or ViewActivated event, or during any pre-action event, such as DocumentSaving,
DocumentClosing, or other similar events.
The UIDocument can also be used to get a list of all open view windows in the Revit user interface. The GetOpenUIViews method returns a
list of UIViews which contain data about the view windows in the Revit user interface.
Event
DocumentOpened
Example
Disk errors
Resource errors
Event
DocumentCreated
DocumentCreated
DocumentCreated
Each method requires a template file name as the parameter. The created document is returned based on the template file.
Save and Close a Document
The Document class provides methods to save or close instances.
Table 6: Save and Close Document in API
Method
Event
Save()
DocumentSaved
SaveAs()
DocumentSavedAs
Close()
DocumentClosed
Save() has 2 overloads, one with no arguments and one with a SaveOptions argument that can specify whether to force the OS to delete all
dead data from the file on disk. If the file has not been previously saved, SaveAs() must be called instead.
SaveAs() has 3 overloads. One overload takes only the filename as an argument and an exception will be thrown if another file exists with
the given filename. The other 2 overloads takes a filename as an argument (in the form of a ModelPath in one case) as well as a second
SaveAsOptions argument that specifies whether to rename the file and/or whether to overwrite and existing file, if it exists. SaveAsOptions
can also be used to specify other relevant options such as whether to remove dead data on disk related to the file and worksharing options.
Save() and SaveAs() throw specific documented exceptions in the same 4 categories as when opening a document and listed in Table 4
above.
Close() has two overloads. One takes a Boolean argument that indicates whether to save the file before closing it. The second overload takes
no arguments and if the document was modified, the user will be asked if they want to save the file before closing. This method will throw an
exception if the document's path name is not already set or if the saving target file is read-only.
Note
The Close() method does not affect the active document or raise the DocumentClosed event, because the document is used by an external
application. You can only call this method on non-active documents.
The UIDocument class also provides methods to save and close instances.
Table 7: Save and Close UIDocument in API
Method
Event
SaveAndClose()
DocumentSaved, DocumentClosed
SaveAs()
DocumentSavedAs
SaveAndClose() closes the document after saving it. If the document's path name has not been set the "Save As" dialog will be shown to the
Revit user to set its name and location.
The SaveAs() method saves the document to a file name and path obtained from the Revit user via the "Save As" dialog.
Document Preview
The DocumentPreviewSettings class can be obtained from the Document and contains the settings related to the saving of preview images
for a given document.
Load Family
The Document class provides you with the ability to load an entire family and all of its symbols into the project. Because loading an entire
family can take a long time and a lot of memory, the Document class provides a similar method, LoadFamilySymbol() to load only specified
symbols.
For more details, see Loading Families.
Settings
The following table identifies the commands in the Revit Platform UI Manage tab, and corresponding APIs.
Table 7: Settings in API and UI
UI command
Associated API
Reference
Settings
Project Information
Document.ProjectInformation
Settings
Project Parameters
Document.ProjectLocations
Document.ActiveProjectLocation
Settings
Additional Settings
Settings
Fill Patterns
Materials
Document.Settings.Materials
Settings
Object Styles
Document.Settings.Categories
Phasing
Phases
Document.Phases
Settings
Structural Settings
Settings
Project Units
Document.GetUnits()
See Units
Document.Settings.VoumeCalculationSetting
Area and Volume Calculations (on the Room & Area panel)
Note
Project Information - The API provides the ProjectInfo class which is retrieved using Document.ProjectInformation to represent
project information in the Revit project. The following table identifies the corresponding APIs for the Project Information parameters.
Table 8: ProjectInformation
Parameters
Corresponding API
Built-in Parameters
ProjectInfo.IssueDate
PROJECT_ISSUE_DATE
Project Status
ProjectInfo.Status
PROJECT_STATUS
Client Name
ProjectInfo.ClientName
CLIENT_NAME
Project Address
ProjectInfo.Address
PROJECT_ADDRESS
Project Name
ProjectInfo.Name
PROJECT_NAME
Project Number
ProjectInfo.Number
PROJECT_NUMBER
Use the properties exposed by ProjectInfo to retrieve and set all strings. These properties are implemented by the corresponding
built-in parameters. You can get or set the values through built-in parameters directly. For more information about how to gain
access to these parameters through the built-in parameters, see Parameter in the Elements Essential section. The recommended
way to get project information is to use the ProjectInfo properties.
Fill Patterns - Retrieve all Fill Patterns in the current document using a FilteredElementCollector filtering on class FillPatternElement.
Specific FillPatterns can be retrieved using the static methods FillPatternElement.GetFillPattern(Document, ElementId) or
FillPatternElement.GetFillPatternByName (Document, string).
Object Styles - Use Settings.Categories to retrieve all information in Category objects except for Line Style. For more details, see
Categories in the Elements Essentialand Material sections.
Phases - Revit maintains the element lifetime by phases, which are distinct time periods in the project lifecycle. All phases in a
document are retrieved using the Document.Phases property. The property returns an array containing Phase class instances.
However, the Revit API does not expose functions from the Phase class.
Options - The Options command configures project global settings. You can retrieve an Options.Application instance using the
Application.Options property. Currently, the Options.Application class only supports access to library paths and shared parameters
file.
Area and Volume Calculations - The Document.Settings.VolumeCalculationSetting allows you to enable or disable volume calculations,
and to change the room boundary location.
Units
The two main classes in the Revit API for working with units are Units and FormatOptions. The Units class represents a document's default
settings for formatting numbers with units as strings. It contains a FormatOptions object for each unit type as well as settings related to
decimal symbol and digit grouping.
The Units class stores a FormatOptions object for every valid unit type, but not all of them can be directly modified. Some, like UT_Number
and UT_SiteAngle, have fixed definitions. Others have definitions which are automatically derived from other unit types. For example,
UT_SheetLength is derived from UT_Length and UT_ForceScale is derived from UT_Force.
The FormatOptions class contains settings that control how to format numbers with units as strings. It contains those settings that are
typically chosen by an end-user in the Format dialog and stored in the document, such as rounding, accuracy, display units, and whether to
suppress spaces or leading or trailing zeros.
The FormatOptions class is used in two different ways. A FormatOptions object in the Units class represents the default settings for the
document. A FormatOptions object used elsewhere represents settings that may optionally override the default settings.
The UseDefault property controls whether a FormatOptions object represents default or custom formatting. If UseDefault is true, formatting
will be according to the default settings in the Units class, and none of the other settings in the object are meaningful. If UseDefault is false,
the object contains custom settings that override the default settings in the Units class. UseDefault is always false for FormatOptions objects
in the Units class.
Important unit-related enumerations in the Revit API include:
UnitType - type of physical quantity to be measured, for example length or force (UT_Length or UT_Force)
DisplayUnitType - units and display format used to format numbers as strings or convert units (i.e. DUT_METERS)
UnitSymbolType - unit symbol displayed in the formatted string representation of a number to indicate the units of the value (i.e.
UST_M)
Unit Conversion
The Revit API provides utility classes to facilitate working with quantities in Revit. The UnitUtils class makes it easy to convert unit data to
and from Revit's internal units.
Revit has seven base quantities, each with its own internal unit. These internal units are identified in the following table.
Table 9: 7 Base Units in Revit Unit System
Base Unit
Unit In Revit
Unit System
Length
Feet (ft)
Imperial
Angle
Radian
Metric
Mass
Kilogram (kg)
Metric
Time
Seconds (s)
Metric
Electric Current
Ampere (A)
Metric
Temperature
Kelvin (K)
Metric
Luminous Intensity
Candela (cd)
Metric
Note: Since Revit stores lengths in feet and other basic quantities in metric units, a derived unit involving length will be a non-standard unit
based on both the Imperial and the Metric systems. For example, since a force is measured in "mass-length per time squared", it is stored in
kg-ft / s2.
The following example uses the UnitUtils.ConvertFromInternalUnits() method to get the minimum yield stress for a material in kips per
square inch.
The UnitUtils can also be used to convert a value from one unit type to another, such as square feet to square meters. In the following
example, a wall's top offset value that was entered in inches is converted to feet, the expected unit for setting that value.
The overloaded UnitFormatUtils.TryParse() method parses a formatted string, including units, into a value if possible, using the Revit internal
units of the specified unit type. The following example takes a user entered length value, assumed to be a number and length unit, and
attempts to parse it into a length value. The result is compared with the input string in a TaskDialog for demonstration purposes.
Elements Essentials
An Element corresponds to a single building or drawing component, such as a door, a wall, or a dimension. In addition, an Element can be a
door type, a view, or a material definition.
Element Classification
Revit Elements are divided into six groups: Model, Sketch, View, Group, Annotation and Information. Each group contains related Elements
and their corresponding symbols.
Model Elements
Model Elements represent physical items that exist in a building project. Elements in the Model Elements group can be subdivided into the
following:
Family Instances - Family Instances contain family instance objects. You can load family objects into your project or create them from
family templates. For more information, see Family Instances.
Host Elements - Host Elements contain system family objects that can contain other model elements, such as wall, roof, ceiling, and
floor. For more information about Host Elements, see Walls, Floors, Roofs and Openings.
Structure Elements. - Structure Elements contain elements that are only used in Revit Structure. For more information about
Structure Elements, see Revit Structure.
View Elements
View Elements represent the way you view and interact with other objects in Revit. For more information, see Views.
Group Elements
Group Elements represent the assistant Elements such as Array and Group objects in Revit. For more information, see Editing Elements.
Annotation and Datum Elements
Annotation and Datum Elements contain non-physical items that are visible.
Annotation Elements represent 2D components that maintain scale on paper and are only visible in one view. For more information
about Annotation Elements, see Annotation Elements.
Note Annotation Elements representing 2D components do not exist only in 2D views. For example, dimensions can be drawn in 3D view
Information Elements
Information Elements contain non-physical invisible items used to store project and application data. Information Elements are further
separated into the following:
Project Datum Elements
Project Datum Elements (Unique).
For more information about Datum Elements, see Datum and Information Elements.
Other Classifications
Elements are also classified by the following:
Category
Family
Symbol
Instance
There are some relationships between the classifications. For example:
You can distinguish different kinds of FamilyInstances by the category. Items such as structural columns are in the Structural
Columns category, beams and braces are in the Structural Framing category, and so on.
You can differentiate structural FamilyInstance Elements by their symbol.
Category
The Element.Category property represents the category or subcategory to which an Element belongs. It is used to identify the Element type.
For example, anything in the walls Category is considered a wall. Other categories include doors and rooms.
Categories are the most general class. The Document.Settings.Categories property is a map that contains all Category objects in the
document and is subdivided into the following:
Model Categories - Model Categories include beams, columns, doors, windows, and walls.
Annotation Categories. Annotation Categories include dimensions, grids, levels, and textnotes.
Note
There are exceptions such as ProjectInfo, which belongs to the Project Information category.
An element and its corresponding symbols are usually in the same category. For example, a basic wall and its wall type Generic - 8"
are all in the Walls category.
The same type of Elements can be in different categories. For example, SpotDimensions has the SpotDimensionType, but it can
belong to two different categories: Spot Elevations and Spot Coordinates.
Different Elements can be in the same category because of their similarity or for architectural reasons. ModelLine and DetailLine are
in the Lines category.
To gain access to the categories in a document' Setting class (for example, to insert a new category set), use one of the following
techniques:
Get the Categories from the document properties.
Get a specific category quickly from the categories map using the BuiltInCategory enumerated type.
NoteTo avoid Globalization problems when using Category.Name, BuiltInCategory is a better choice. Category.Name can be different in
different languages.
Family
Families are classes of Elements within a category. Families can group Elements by the following:
A common set of parameters (properties).
Identical use.
Similar graphical representation.
Most families are component Family files, meaning that you can load them into your project or create them from Family templates. You
determine the property set and the Family graphical representation.
Another family type is the system Family. System Families are not available for loading or creating. Revit predefines the system Family
properties and graphical representation; they include walls, dimensions, roofs, floors (or slabs), and levels.
For FamilyInstance, the Symbol property can be used instead of the GetTypeId() method to get the corresponding FamilySymbol. It is
convenient and safe since you do not need to do a type conversion.
Element Retrieval
Elements in Revit are very common. Retrieving the elements that you want from Revit is necessary before using the API for any Element
command. There are several ways to retrieve elements with the Revit API:
ElementId - If the ElementId of the element is known, the element can be retrieved from the document.
Element filtering and iteration - this is a good way to retrieve a set of related elements in the document.
Selected elements - retrieves the set of elements that the user has selected
Specific elements - some elements are available as properties of the document
Each of these methods of element retrieval is discussed in more details in the following sections.
Getting an Element by ID
When the ElementId of the desired element is known, use the Document.Element property to get the element.
Filtering the Elements Collection
The most common way to get elements in the document is to use filtering to retrieve a collection of elements. The Revit API provides the
FilteredElementCollector class, and supporting classes, to create filtered collections of element which can then be iterated. See Filtering for
more information.
Selection
Rather than getting a filtered collection of all of the elements in the model, you can access just the elements that have been selected. You
can get the selected objects from the current active document using the UIDocument.Selection.Elements property. For more information on
using the active selection, see Selection.
Accessing Specific Elements from Document
In addition to using the general way to access Elements, the Revit Platform API has properties in the Document class to get the specified
Elements from the current active document without iterating all Elements. The specified Elements you can retrieve are listed in the following
table.
Table 11: Retrieving Elements from document properties
Element
ProjectInfo
Document.ProjectInformation
ProjectLocation
Document.ProjectLocations
Document.ActiveProjectLocation
SiteLocation
Document.SiteLocation
Phase
Document.Phases
Material
Document.Settings.Materials
Document.DeckProfiles
Document.TitleBlocks
General Properties
The following properties are common to each Element created using Revit.
ElementId
Every element in an active document has a unique identifier represented by the ElementId storage type. ElementId objects are project wide.
It is a unique number that is never changed in the element model, which allows it to be stored externally to retrieve the element when
needed.
To view an element ID in Revit, complete the following steps:
1. From the Modify tab, on the Inquiry panel, select Element ID. The Element ID drop down menu appears.
Select IDs of Selection to get the ID number for one element.
separate projects.
Location
The location of an object is important in the building modeling process. In Revit, some objects have a point location. For example a table has
a point location. Other objects have a line location, representing a location curve or no location at all. A wall is an element that has a line
location.
The Revit Platform API provides the Location class and location functionality for most elements. For example, it has the Move() and Rotate()
methods to translate and rotate the elements. However, the Location class has no property from which you can get information such as a
coordinate. In this situation, downcast the Location object to its subclass-like LocationPoint or LocationCurve-for more detailed location
information and control using object derivatives.
Retrieving an element's physical location in a project is useful when you get the geometry of an object. The following rules apply when you
retrieve a location:
Wall, Beam, and Brace are curve-driven using LocationCurve.
Room, RoomTag, SpotDimension, Group, FamilyInstances that are not curve-driven, and all In-Place-FamilyInstances use
LocationPoint.
In the Revit Platform API, curve-driven means that the geometry or location of an element is determined by one or more associated curves.
Almost all analytical model elements are curve-driven - linear and area loads, walls, framing elements, and so on.
Other Elements cannot retrieve a LocationCurve or LocationPoint. They return Location with no information.
Table 12: Elements Location Information
Location Information
Elements
LocationCurve
LocationPoint
Only Location
Level, Floor, some Tags, BeamSystem, Rebar, Reinforcement, PointLoad, AreaLoad(without Host), Span Direction(IndependentTag)
No Location
NoteThere are other Elements without Location information. For example a LineLoad (with host) or an AreaLoad (with host) have no
Location.
Some FamilyInstance LocationPoints, such as all in-place-FamilyInstances and masses, are specified to point (0, 0, 0) when they are
created. The LocationPoint coordinate is changed if you transform or move the instance.
To change a Group-s LocationPoint, do one of the following:
Drag the Group origin in the Revit UI to change the LocationPoint coordinate. In this situation, the Group LocationPoint is changed
while the Group-s location is not changed.
Move the Group using the ElementTransformUtils.MoveElement() method to change the LocationPoint. This changes both the Group
location and the LocationPoint.
For more information about LocationCurve and LocationPoint, see Move.
Level
Levels are finite horizontal planes that act as a reference for level-hosted or level-based elements, such as roofs, floors, and ceilings. The
Revit Platform API provides a Level class to represent level lines in Revit. Get the Level object to which the element is assigned using the API
if the element is level-based.
A number of elements, such as a column, use a level as a basic reference. When you get the column level, the level you retrieve is the Base
Level.
Get the Beam or Brace level using the Reference Level parameter. From the Level property, you only get null instead of the reference level
information.
Level is the most commonly used element in Revit. In the Revit Platform API, all levels in the project are located by iterating over the entire
project and searching for Elements.Level objects.
For more Level details, see Datum and Information Elements.
Parameter
Every element has a set of parameters that users can view and edit in Revit. The parameters are visible in the Element Properties dialog box
(select any element and click the Properties button next to the type selector). For example, the following image shows Room parameters.
Code Region 6-1: Use element filtering to get all wall instances in document
// Find all Wall instances in the document by using category filter
ElementCategoryFilter filter = new ElementCategoryFilter(BuiltInCategory.OST_Walls);
// Apply the filter to the elements in the active document
// Use shortcut WhereElementIsNotElementType() to find wall instances only
FilteredElementCollector collector = new FilteredElementCollector(document);
IList<Element> walls =
collector.WherePasses(filter).WhereElementIsNotElementType().ToElements();
String prompt = "The walls in the current document are:\n";
foreach (Element e in walls)
{
prompt += e.Name + "\n";
}
TaskDialog.Show("Revit", prompt);
Create a FilteredElementCollector
The main class used for element iteration and filtering is called FilteredElementCollector. It is constructed in one of three ways:
1. From a document - will search and filter the set of elements in a document
2. From a document and set of ElementIds - will search and filter a specified set of elements
3. From a document and a view - will search and filter the visible elements in a view
NoteAlways check that a view is valid for element iteration when filtering elements in a specified view by using the static
FilteredElementCollector.IsViewValidForElementIteration().
When the object is first created, there are no filters applied. This class requires that at least one condition be set before making at attempt
to access the elements, otherwise an exception will be thrown.
Applying Filters
Filters can be applied to a FilteredElementCollector using ElementFilters. An ElementFilter is a class that examines an element to see if it
meets a certain criteria. The ElementFilter base class has three derived classes that divide element filters into three categories.
ElementQuickFilter - Quick filters operate only on the ElementRecord, a low-memory class which has a limited interface to read
element properties. Elements which are rejected by a quick filter will not be expanded in memory.
ElementSlowFilter - Slow filters require that the Element be obtained and expanded in memory first. Thus it is preferable to couple
slow filters with at least one ElementQuickFilter, which should minimize the number of Elements that are expanded in order to
evaluate against the criteria set by this filter.
ElementLogicalFilter - Logical filters combine two or more filters logically. The component filters may be reordered by Revit to
cause the quickest acting filters to be evaluated first.
Most filters may be inverted using an overload constructor that takes a Boolean argument indicating to invert the filter so that elements that
would normally be accepted by the filter will be rejected, and elements that would normally be rejected will be accepted. Filters that cannot
be inverted are noted in their corresponding sections below.
There is a set of predefined filters available for common uses. Many of these built-in filters provide the basis for the FilteredElementCollector
shortcut methods mentioned in the FilteredElementCollector section above. The next three sections provide more information on the built-in
filters.
Once a filter is created, it needs to be applied to the FilteredElementCollector. The generic method WherePasses() is used to apply a single
ElementFilter to the FilteredElementCollector.
Filters can also be applied using a number of shortcut methods provided by FilteredElementCollector. Some apply a specific filter without
further input, such as WhereElementIsCurveDriven(), while others apply a specific filter with a simple piece of input, such as the
OfCategory() method which takes a BuiltInCategory as a parameter. And lastly there are methods such as UnionWith() that join filters
together. All of these methods return the same collector allowing filters to be easily chained together.
Quick filters
Quick filters operate only on the ElementRecord, a low-memory class which has a limited interface to read element properties. Elements
which are rejected by a quick filter will not be expanded in memory. The following table summarizes the built-in quick filters, and some
examples follow for a few of the filters.
Table 13: Built-in Quick Filters
Built-in Filter
What it passes
Shortcut Method(s)
BoundingBoxContainsPointFilter
None
BoundingBoxIntersectsFilter
None
BoundingBoxIsInsideFilter
None
ElementCategoryFilter
OfCategoryId()
ElementClassFilter
OfClass()
ElementDesignOptionFilter
ContainedInDesignOption()
ElementIsCurveDrivenFilter
WhereElementIsCurveDriven()
ElementIsElementTypeFilter
WhereElementIsElementType()
WhereElementIsNotElementType()
ElementMulticategoryFilter
None
ElementMulticlassFilter
None
ElementOwnerViewFilter
OwnedByView() WhereElementIsViewIndependent()
ElementStructuralTypeFilter
None
ExclusionFilter
Excluding()
FamilySymbolFilter
The following example creates an outline in the document and then uses a BoundingBoxIntersectsFilter to find the elements in the document
with a bounding box that intersects that outline. It then shows how to use an inverted filter to find all walls whose bounding box do not
intersect the given outline. Note that the use of the OfClass() method applies an ElementClassFilter to the collection as well.
Outline myOutLn = new Outline(new XYZ(0, 0, 0), new XYZ(100, 100, 100));
// Create a BoundingBoxIntersects filter with this Outline
BoundingBoxIntersectsFilter filter = new BoundingBoxIntersectsFilter(myOutLn);
// Apply the filter to the elements in the active document
// This filter excludes all objects derived from View and objects derived from ElementType
FilteredElementCollector collector = new FilteredElementCollector(document);
IList<Element> elements = collector.WherePasses(filter).ToElements();
// Find all walls which don't intersect with BoundingBox: use an inverted filter
// to match elements
// Use shortcut command OfClass() to find walls only
BoundingBoxIntersectsFilter invertFilter = new BoundingBoxIntersectsFilter(myOutLn, true);
collector = new FilteredElementCollector(document);
IList<Element> notIntersectWalls = collector.OfClass(typeof(Wall)).WherePasses(invertFilter).ToElements();
The next example uses an exclusion filter to find all walls that are not currently selected in the document.
Type
Dedicated Filter
Subclasses of Autodesk.Revit.DB.Material
None
Subclasses of Autodesk.Revit.DB.CurveElement
CurveElementFilter
Subclasses of Autodesk.Revit.DB.ConnectorElement
None
Subclasses of Autodesk.Revit.DB.HostedSweep
None
Autodesk.Revit.DB.Architecture.Room
RoomFilter
Autodesk.Revit.DB.Mechanical.Space
SpaceFilter
Autodesk.Revit.DB.Area
AreaFilter
Autodesk.Revit.DB.Architecture.RoomTag
RoomTagFilter
Autodesk.Revit.DB.Mechanical.SpaceTag
SpaceTagFilter
Autodesk.Revit.DB.AreaTag
AreaTagFilter
Autodesk.Revit.DB.CombinableElement
None
Autodesk.Revit.DB.Mullion
None
Autodesk.Revit.DB.Panel
None
Autodesk.Revit.DB.AnnotationSymbol
None
Autodesk.Revit.DB.Structure.AreaReinforcementType
None
Autodesk.Revit.DB.Structure.PathReinforcementType
None
Autodesk.Revit.DB.AnnotationSymbolType
None
Autodesk.Revit.DB.Architecture.RoomTagType
None
Autodesk.Revit.DB.Mechanical.SpaceTagType
None
Autodesk.Revit.DB.AreaTagType
None
Autodesk.Revit.DB.Structure.TrussType
None
Slow Filters
Slow filters require that the Element be obtained and expanded in memory first. Thus it is preferable to couple slow filters with at least one
ElementQuickFilter, which should minimize the number of Elements that are expanded in order to evaluate against the criteria set by this
filter. The following table summarizes the built-in slow filters, while a few examples follow to provide an in-depth look at some of the filters.
What it passes
Shortcut Method(s)
AreaFilter
Areas
None
AreaTagFilter
Area tags
None
CurveElementFilter
CurveElements
None
ElementLevelFilter
None
ElementParameterFilter
None
ElementPhaseStatusFilter
None
FamilyInstanceFilter
None
FamilyStructuralMaterialTypeFilter
None
PrimaryDesignOptionMemberFilter
None
RoomFilter
Rooms
None
RoomTagFilter
Room tags
None
SpaceFilter
Spaces
None
SpaceTagFilter
Space tags
None
StructuralInstanceUsageFilter
None
StructuralMaterialTypeFilter
None
StructuralWallUsageFilter
None
ElementIntersectsElementFilter
None
ElementIntersectsSolidFilter
None
The example below uses an ElementParameterFilter to find rooms whose size is more than 100 square feet and rooms with less than 100
square feet.
What it passes
Shortcut Method(s)
LogicalAndFilter
LogicalOrFilter
In the example below, two quick filters are combined using a logical filter to get all door FamilyInstance elements in the document.
ToElementIds() - returns ElementIds of all elements which pass all applied filters
You should only use one of the methods from these groups at a time; the collector will reset if you call another method to extract elements.
Thus, if you have previously obtained an iterator, it will be stopped and traverse no more elements if you call another method to extract
elements.
Which method is best depends on the application. If just one matching element is required, FirstElement() or FirstElementId() is the best
choice. If all the matching elements are required, use ToElements(). If a variable number are needed, use an iterator.
If the application will be deleting elements or making significant changes to elements in the filtered list, ToElementIds() or an element id
iterator are the best options. This is because deleting elements or making significant changes to an element can invalidate an element
handle. With element ids, the call to Document.GetElement() with the ElementId will always return a valid Element (or a null reference if the
element has been deleted).
Using the ToElements() method to get the filter results as a collection of elements allows for the use of foreach to examine each element in
the set, as is shown below:
In some cases, FirstElement() is not sufficient. This next example shows how to use extension methods to get the first non-template 3D view
(which is useful for input to the ReferenceIntersector constructors).
Code Region 6-11: Get first passing element using extension methods
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
The following example demonstrates the use of the FirstElementId() method to get one passing element (a 3d view in this case) and the use
of ToElementIds() to get the filter results as a collection of element ids (in order to delete a set of elements in this case).
document.Delete(familyInstanceIds);
The GetElementIterator() method is used in the following example that iterates through the filtered elements to check the flow state of some
pipes.
In some cases, it may be useful to test a single element against a given filter, rather than getting all elements that pass the filter. There are
two overloads for ElementFilter.PassesFilter() that test a given Element, or ElementId, against the filter, returning true if the element passes
the filter.
LINQ Queries
In .NET, the FilteredElementCollector class supports the IEnumerable interface for Elements. You can use this class with LINQ queries and
operations to process lists of elements. Note that because the ElementFilters and the shortcut methods offered by this class process
elements in native code before their managed wrappers are generated, better performance will be obtained by using as many native filters
as possible on the collector before attempting to process the results using LINQ queries.
The following example uses an ElementClassFilter to get all FamilyInstance elements in the document, and then uses a LINQ query to narrow
down the results to those FamilyInstances with a specific name.
ElementIntersectsElementFilter
ElementIntersectsSolidFilter
pass elements whose actual 3D geometry intersects the 3D geometry of the target object.
With ElementIntersectsElementFilter, the target object is another element. The intersection is determined with the same logic used by Revit to determine if an
interference exists during generation of an Interference Report. (This means that some combinations of elements will never pass this filter, such as concrete
members which are automatically joined at their intersections). Also, elements which have no solid geometry, such as Rebar, will not pass this filter.
With ElementIntersectsSolidFilter, the target object is any solid. This solid could have been obtained from an existing element, created from scratch using the
routines in GeometryCreationUtilities, or the result of a secondary operation such as a Boolean operation. Similar to the ElementIntersectsElementFilter, this
filter will not pass elements which lack solid geometry.
Both filters can be inverted to match elements outside the target object volume.
Both filters are slow filters, and thus are best combined with one or more quick filters such as class or category filters.
Code region: using ElementIntersectsSolidFilter to match elements which block disabled egress to doors
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
/// <summary>
/// Finds any Revit physical elements which interfere with the target
/// solid region surrounding a door.</summary>
/// <remarks>This routine is useful for detecting interferences which are
/// violations of the Americans with Disabilities Act or other local disabled
/// access codes.</remarks>
/// <param name="doorInstance">The door instance.</param>
/// <param name="doorAccessibilityRegion">The accessibility region calculated
/// to surround the approach of the door.
/// Because the geometric parameters of this region are code- and
/// door-specific, calculation of the geometry of the region is not
/// demonstrated in this example.</param>
/// <returns>A collection of interfering element ids.</returns>
private ICollection<ElementId> FindElementsInterferingWithDoor(FamilyInstance doorInstance, Solid doorAccessibilityRegion)
{
// Setup the filtered element collector for all document elements.
FilteredElementCollector interferingCollector =
new FilteredElementCollector(doorInstance.Document);
// Only accept element instances
interferingCollector.WhereElementIsNotElementType();
// Exclude intersections with the door itself or the host wall for the door.
List<ElementId> excludedElements = new List<ElementId>();
excludedElements.Add(doorInstance.Id);
excludedElements.Add(doorInstance.Host.Id);
ExclusionFilter exclusionFilter = new ExclusionFilter(excludedElements);
interferingCollector.WherePasses(exclusionFilter);
// Set up a filter which matches elements whose solid geometry intersects
// with the accessibility region
ElementIntersectsSolidFilter intersectionFilter =
new ElementIntersectsSolidFilter(doorAccessibilityRegion);
interferingCollector.WherePasses(intersectionFilter);
Selection
You can get the selected objects from the current active document using the UIDocument.Selection.Elements property. The selected objects
are in an ElementSet in Revit. From this Element set, all selected Elements are retrieved. The Selection object can also be used to change
the current selection programmatically.
Alternatively, the Selection.GetElementIds() method retrieves the same set of elements as the Selection.Elements property. The collection
returned by this method can be used directly with FilteredElementCollector to filter the selected elements.
User Selection
The Selection class also has methods for allowing the user to select new objects, or even a point on screen. This allows the user to select one
or more Elements (or other objects, such as an edge or a face) using the cursor and then returns control to your application. These functions
do not automatically add the new selection to the active selection collection.
The PickObject() method prompts the user to select an object in the Revit model.
The PickObjects() method prompts the user to select multiple objects in the Revit model.
The PickElementsByRectangle() method prompts the user to select multiple elements using a rectangle.
The PickPoint() method prompts the user to pick a point in the active sketch plane.
The PickBox() method invokes a general purpose two-click editor that lets the user to specify a rectangular area on the screen.
The type of object to be selected is specified when calling PickObject() or PickObjects. Types of objects that can be specified are: Element,
PointOnElement, Edge or Face.
The StatusbarTip property shows a message in the status bar when your application prompts the user to pick objects or elements. Each of
the Pick functions has an overload that has a String parameter in which a custom status message can be provided.
Code Region 7-2: Adding selected elements with PickObject() and PickElementsByRectangle()
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
The PickPoint() method has 2 overloads with an ObjectSnapTypes parameter which is used to specify the type of snap types used for the
selection. More than one can be specified, as shown in the next example.
The PickBox() method takes a PickBoxStyle enumerator. The options are Crossing, the style used when selecting objects completely or
partially inside the box, Enclosing, the style used selecting objects that are completely enclosed by the box, and Directional, in which the
style of the box depends on the direction in which the box is being drawn. It uses the Crossing style if it is being drawn from right to left, or
the Enclosing style when drawn in the opposite direction.
PickBox() returns a PickedBox which contains the Min and Max points selected. The following example demonstrates the use of PickBox() in
Point Cloud selection.
// Create filter
PointCloudFilter filter = PointCloudFilterFactory.CreateMultiPlaneFilter(planes);
Transaction t = new Transaction(uiDoc.Document, "Highlight");
t.Start();
pcInstance.SetSelectionFilter(filter);
pcInstance.FilterAction = SelectionFilterAction.Highlight;
t.Commit();
uiDoc.RefreshActiveView();
The following example illustrates how to use an ISelectionFilter interface to limit the user's selection to elements in the Mass category. It
does not allow any references to geometry to be selected.
Parameters
Revit provides a general mechanism for giving each element a set of parameters that you can edit. In the Revit UI, parameters are visible in
the Element Properties dialog box. This chapter describes how to get and use built-in parameters using the Revit Platform API. For more
information about user-defined shared parameters, see Shared Parameters.
In the Revit Platform API, Parameters are managed in the Element class. You can access Parameters in these ways:
By iterating through the Element.Parameters collection of all parameters for an Element (for an example, see the sample code in
Walkthrough Get Selected Element Parameters).
By accessing the parameter directly through the overloaded Element.Parameter property. If the Parameter doesn't exist, the property
returns null.
By accessing a parameter by name via the Element.ParametersMap collection.
You can retrieve the Parameter object from an Element if you know the name string, built-in ID, definition, or GUID. The Parameter[String]
property overload gets a parameter based on its localized name, so your code should handle different languages if it's going to look up
parameters by name and needs to run in more than one locale.
The Parameter[GUID] property overload gets a shared parameter based on its Global Unique ID (GUID), which is assigned to the shared
parameter when it's created.
corresponding to the enumerated type for the Parameter using the Revit Platform API, but you cannot get the string representation for the
values using the Parameter.AsValueString() method.
Definition
The Definition object describes the data type, name, and other Parameter details. There are two kinds of definition objects derived from this
object.
InternalDefinition represents all kinds of definitions existing entirely in the Revit database.
ExternalDefinition represents definitions stored on disk in a shared parameter file.
You should write the code to use the Definition base class so that the code is applicable to both internal and external parameter Definitions.
The following code sample shows how to find a specific parameter using the definition type.
ParameterType
This property returns parameter data type, which affects how the parameter is displayed in the Revit UI. The ParameterType enumeration
members are:
Member name
Description
Number
The parameter data should be interpreted as a real number, possibly including decimal points.
Moment
AreaForce
LinearForce
Force
YesNo
Material
URL
Angle
The parameter data represents an angle. The internal representation will be in radians. The user visible representation will be in
the units that the user has chosen.
Volume
The parameter data represents a volume. The internal representation will be in decimal cubic feet. The user visible
representation will be in the units that the user has chosen.
Area
The parameter data represents an area. The internal representation will be in decimal square feet. The user visible
representation will be in the units that the user has chosen.
Integer
Invalid
Length
The parameter data represents a length. The internal representation will be in decimal feet. The user visible representation will
be in the units system that the user has chosen.
Text
BuiltInParameter
The Revit Platform API has a large number of built-in parameters, defined in the Autodesk.Revit.Parameters.BuiltInParameter enumeration
(see the RevitAPI Help.chm file for the definition of this enumeration). This enumeration has generated documentation visible from Visual
Studio intellisense as shown below. The documentation for each id includes the parameter name, as found in the Element Properties dialog in
the English version of Autodesk Revit. Note that multiple distinct parameter ids may map to the same English name; in those cases you
must examine the parameters associated with a specific element to determine which parameter id to use.
The parameter ID is used to retrieve the specific parameter from an element, if it exists, using the Element.Parameter property. However,
not all parameters can be retrieved using the ID. For example, family parameters are not exposed in the Revit Platform API, therefore, you
cannot get them using the built-in parameter ID.
The following code sample shows how to get the specific parameter using the BuiltInParameter Id:
Note With the Parameter overload, you can use an Enumerated type BuiltInParameter as the method parameter. For example, use
BuiltInParameter.GENERIC_WIDTH.
If you do not know the exact BuiltInParameter ID, get the parameter by iterating the ParameterSet collection. Another approach for testing
or identification purposes is to test each BuiltInParameter using the get_Parameter() method. When you use this method, it is possible that
the ParameterSet collection may not contain all parameters returned from the get_Parameter() method, though this is infrequent.
StorageType
StorageType describes the type of parameter values stored internally.
Based on the property value, use the corresponding get and set methods to retrieve and set the parameter data value.
The StorageType is an enumerated type that lists all internal parameter data storage types supported by Revit:
Table 16: Storage Type
Member Name
Description
String
ElementId
Double
Integer
None
In most cases, the ElementId value is a positive number. However, it can be a negative number. When the ElementId value is negative, it
does not represent an Element but has another meaning. For example, the storage type parameter for a beam's Vertical Projection is
ElementId. When the parameter value is Level 1 or Level 2, the ElementId value is positive and corresponds to the ElementId of that level.
However, when the parameter value is set to Auto-detect, Center of Beam or Top of Beam, the ElementId value is negative.
The Set() method return value indicates that the Parameter value was changed. The Set() method returns true if the Parameter value was
changed, otherwise it returns false.
Not all Parameters are writable. An Exception is thrown if the Parameter is read-only.
Parameter Relationships
There are relationships between Parameters where the value of one Parameter can affect:
whether another Parameter can be set, or is read-only
what parameters are valid for the element
the computed value of another parameter
Additionally, some parameters are always read-only.
Some parameters are computed in Revit, such as wall Length and Area parameter. These parameters are always read-only because they
depend on the element's internal state.
Collections
Most Revit Platform API properties and methods use .NET Framework collection classes when providing access to a group of related items.
The IEnumerable and IEnumerator interfaces implemented in Revit collection types are defined in the System.Collection namespace.
Interface
The following sections discuss interface-related collection types.
IEnumerable
The IEnumerable interface is in the System.Collections namespace. It exposes the enumerator, which supports a simple iteration over a nongeneric collection. The GetEnumerator() method gets an enumerator that implements this interface. The returned IEnumerator object is
iterated throughout the collection. The GetEnumerator() method is used implicitly by foreach loops in C#.
IEnumerator
The IEnumerator interface is in the System.Collections namespace. It supports a simple iteration over a non-generic collection. IEnumerator
is the base interface for all non-generic enumerators. The foreach statement in C# hides the enumerator's complexity.
NoteUsing foreach is recommended instead of directly manipulating the enumerator.
Enumerators are used to read the collection data, but they cannot be used to modify the underlying collection. Use IEnumerator as follows:
Initially, the enumerator is positioned in front of the first element in the collection. However, it is a good idea to always call Reset()
when you first obtain the enumerator.
o
The Reset() method moves the enumerator back to the original position. At this position, calling the Current property throws
an exception.
Call the MoveNext() method to advance the enumerator to the collection's first element before reading the current iterator
value.
The Current property returns the same object until either the MoveNext() method or Reset() method is called. The MoveNext()
method sets the current iterator to the next element.
If MoveNext passes the end of the collection, the enumerator is positioned after the last element in the collection and MoveNext
returns false.
o
When the enumerator is in this position, subsequent calls to the MoveNext also return false.
If the last call to the MoveNext returns false, calling the Current property throws an exception.
To set the current iterator to the first element in the collection again, call the Reset() method followed by MoveNext().
If changes are made to the collection, such as adding, modifying, or deleting elements, the enumerator is invalidated and
the next call to the MoveNext() or the Reset() method throws an InvalidOperationException.
If the collection is modified between the MoveNext and the current iterator, the Current property returns to the specified
element, even if the enumerator is already invalidated.
NoteAll calls to the Reset() method must result in the same state for the enumerator. The preferred implementation is to move the
enumerator to the collection beginning, before the first element. This invalidates the enumerator if the collection is modified after the
enumerator was created, which is consistent with the MoveNext() and the Current properties.
o
All collections implement the IEnumerable interface and all relevant iterators implement the IEnumerator interface. As a result, all methods
and properties are implemented in the Revit Platform API and can play a role in the relevant collections.
Implementing all of the collections is similar. The following example uses ElementSet and ModelCurveArray to demonstrate how to use the
main collection properties:
Editing Elements
In Revit, you can move, copy, rotate, align, delete, mirror, group, and array one element or a set of elements with the Revit Platform API.
Using the editing functionality in the API is similar to the commands in the Revit UI.
Moving Elements
The ElementTransformUtils class provides two static methods to move one or more elements from one place to another.
Table 19: Move Methods
Member
Description
Note When you use the MoveElement() or MoveElements() methods, the following rules apply.
The methods cannot move a level-based element up or down from the level. When the element is level-based, you cannot change the
Z coordinate value. However, you can place the element at any location in the same level. As well, some level based elements have
an offset instance parameter you can use to move them in the Z direction.
For example, if you create a new column at the original location (0, 0, 0) in Level1, and then move it to the new location (10, 20,
30), the column is placed at the location (10, 20, 0) instead of (10, 20, 30).
When you move one or more elements, associated elements are moved. For example, if a wall with windows is moved, the windows
are also moved.
Pinned elements cannot be moved.
Another way to move an element in Revit is to use Location and its derivative objects. In the Revit Platform API, the Location object provides
the ability to translate and rotate elements. More location information and control is available using the Location object derivatives such as
LocationPoint or LocationCurve. If the Location element is downcast to a LocationCurve object or a LocationPoint object, move the curve or
the point to a new place directly.
When you move the element, note that the vector (10, 20, 0) is not the destination but the offset. The following picture illustrates the wall
position before and after moving.
You can also get or set a curve-based element's join properties with the LocationCurve.JoinType property.
Use the LocationPoint Point property to set the element's physical location.
Copying Elements
The ElementTransformUtils class provides several static methods to copy one or more elements from one place to another, either within the same document or
view, or to a different document or view.
Table: Copy Methods
Member
Description
All of the methods return a collection of ElementIds of the newly created elements, including CopyElement(). The collection includes any elements created due
to dependencies.
The method for copying from one document to another can be used for copying non-view specific elements only. Copies are placed at their respective original
location or locations specified by the optional transformation.
View-specific elements should be copied using the method that copies from one view to another. That method can be used for both view-specific and model
elements however, drafting views cannot be used as a destination for model elements. The pasted elements are repositioned to ensure proper placement in
the destination view. For example, the elevation is changed when copying from one level to another. An additional transformation within the destination view
can be performed by providing the optional Transform argument. This additional transformation must be within the plane of the destination view.
When copying from one view to another, both the source and destination views must be 2D graphics views capable of drawing details and view-specific
elements, such as floor and ceiling plans, elevations, sections, or drafting views. The ElementTransformUtils.GetTransformFromViewToView() method will
return the transformation that is applied to elements when copying from a source view to a destination view.
When copying between views or between documents, an optional CopyPasteOptions parameter may be set to override default copy/paste settings. By default,
in the event of duplicate type names during a paste operation, Revit displays a modal dialog with options to either copy types with unique names only, or to
cancel the operation. CopyPasteOptions can be used to specify a custom handler, using the IDuplicateTypeNamesHandler interface, to handle duplicate type
names.
See the Duplicate Views sample in the Revit SDK for a detailed example of copying between documents and between views.
Rotating elements
The ElementTransformUtils class provides two static methods to rotate one or several elements in the project.
Table 20: Rotate Methods
Member
Description
Rotate an element in the document by a specified number of radians around a given axis.
Rotate several elements by IDs in the project by a specified number of radians around a
given axis.
In these methods, the angle of rotation is in radians. The positive radian means rotating counterclockwise around the specified axis, while
the negative radian means clockwise, as the following pictures illustrates.
If the element Location can be downcast to a LocationCurve or a LocationPoint, you can rotate the curve or the point directly.
Aligning Elements
The ItemFactoryBase.NewAlignment() method can create a new locked alignment between two references. These two references must be one of the following
combinations:
2 planar faces
2 lines
line and point
line and reference plane
2 arcs
2 cylindrical faces
These references must be already geometrically aligned as this function will not force them to become aligned. If the alignment can be created a new
Dimension object is returned representing the locked alignment. Otherwise an exception will be thrown.
The NewAlignment() method also requires a view which will determine the orientation of the alignment.
See the CreateTruss example in the FamilyCreation folder included with the SDK Samples. It has several examples of the use of NewAlignment(), such as locking
the bottom chord of a new truss to a bottom reference plane.
Mirroring Elements
The ElementTransformUtils class provides two static methods to mirror one or more elements in the project.
Table 21: Mirror Methods
Member
Description
After performing the mirror operation, you can access the new elements from the Selection ElementSet.
ElementTransformUtils.CanMirrorElement() and ElementTransformUtils.CanMirrorElements() can be used to determine if one or more
elements can be mirrored prior to attempting to mirror an element.
The following code illustrates how to mirror a wall using a plane calculated based on a side face of the wall.
Every FamilyInstance has a Mirrored property. It indicates whether a FamilyInstance (for example a column) is mirrored.
Grouping Elements
The Revit Platform API uses the Creation.Document.NewGroup() method to select an element or multiple elements or groups and then
combines them. With each instance of a group that you place, there is associatively among them. For example, you create a group with a
bed, walls, and window and then place multiple instances of the group in your project. If you modify a wall in one group, it changes for all
instances of that group. This makes modifying your building model much easier because you can change several instances of a group in one
operation.
Initially, the group has a generic name, such as Group 1. It can be modified by changing the name of the group type as follows:
There are three types of groups in Revit; Model Group, Detail Group, and Attached Detail Group. All are created using the NewGroup()
method. The created Group's type depends on the Elements passed.
If no detail Element is passed, a Model Group is created.
If all Elements are detail elements, then a Detail Group is created.
If both types of Elements are included, a Model Group that contains an Attached Detail Group is created and returned.
Note When elements are grouped, they can be deleted from the project.
When a model element in a model group is deleted, it is still visible when the mouse cursor hovers over or clicks the group, even if
the application returns Succeeded to the UI. In fact, the model element is deleted and you cannot select or access that element.
When the last member of a group instance is deleted, excluded, or removed from the project, the model group instance is deleted.
When elements are grouped, they cannot be moved or rotated. If you perform these operations on the grouped elements, nothing happens
to the elements, though the Move() or Rotate() method returns true.
You cannot group dimensions and tags without grouping the elements they reference. If you do, the API call will fail.
You can group dimensions and tags that refer to model elements in a model group. The dimensions and tags are added to an attached detail
group. The attached detail group cannot be moved, copied, rotated, arrayed, or mirrored without doing the same to the parent group.
Description
Description
Array one element in the project based on an input rotation axis.. The
resulting elements are not associated with a linear array.
The methods for arraying elements are useful if you need to create several instances of a component and manipulate them simultaneously.
Every instance in an array can be a member of a group.
Note When using the methods for arraying elements, the following rules apply:
When performing Linear and Radial Array operations, elements dependent on the arrayed elements are also arrayed.
Some elements cannot be arrayed because they cannot be grouped. See the Revit User's Guide for more information about
restrictions on groups and arrays.
Arrays are not supported by most annotation symbols.
Deleting Elements
The Revit Platform API provides Delete() methods to delete one or more elements in the project.
Table 23: Delete Members
Member
Description
Delete(ElementId)
Delete(ICollection<ElementId>)
The first method deletes a single element based on its Id, as shown in the example below.
NoteWhen an element is deleted, any child elements associated with that element are also deleted, as indicated in the sample above.
// Delete all the selected elements via the set of element ids.
ICollection<Autodesk.Revit.DB.ElementId> idSelection = null ;
UIDocument uidoc = new UIDocument(document);
foreach (Autodesk.Revit.DB.Element elem in uidoc.Selection.Elements)
{
Autodesk.Revit.DB.ElementId id = elem.Id;
idSelection.Add(id);
}
ICollection<Autodesk.Revit.DB.ElementId> deletedIdSet = document.Delete(idSelection);
if (0 == deletedIdSet.Count)
{
throw new Exception("Deleting the selected elements in Revit failed.");
}
TaskDialog.Show("Revit","The selected element has been removed.");
NoteAfter you delete the elements, any references to the deleted elements become invalid and throw an exception if they are accessed.
Pinned Elements
Elements can be pinned to prevent them from moving. The Element.Pinned property can be used to check if an Element is pinned or to pin or unpin an
element.
When Element.Pinned is set to true, the element cannot be moved or rotated.
Views
Views are images produced from a Revit model with privileged access to the data stored in the documents. They can be graphics, such as
plans, or text, such as schedules. Each project document has one or more different views. The last focused window is the active view.
The Autodesk.Revit.DB.View class is the base class for all view types in the Revit document. The Autodesk.Revit.UI.UIView class represents
the window view in the Revit user interface.
In the following sections, you learn how views are generated, the types of views supported by Revit, the features for each view, as well as
the functionality available for view windows in the user interface.
About views
This section is a high-level overview discussing the following:
How views are generated
View types
Display settings
Temporary view modes
Element visibility
Creating and deleting views.
View Process
The following figure illustrates how a view is generated.
Some portions of a 3D model space that do not display, such as those that are behind the viewer or are too far away to display clearly, are
excluded before being projected onto the projection plane. This action requires cropping the view. The following rules apply to cropping:
Elements outside of the crop region are no longer in the view.
The View.GetCropRegionShapeManager method returns a ViewCropRegionShapeManager which provides the boundary information for
the crop region, which may or may not be rectangular.
The View.CropBoxVisible property determines whether the crop box is visible in the view.
The View.CropBoxActive property determines whether the crop box is actually being used to crop the view.
After cropping, the model is projected onto the projection plane. The following rules apply to the projection:
The projection contents are mapped to the screen view port for display.
During the mapping process, the projection contents are scaled so that they are shown properly on the screen.
The View.Scale property is the ratio of the actual model size to the view size.
The view boundary on paper is the crop region, which is a projection of the crop shape on the projection plane.
The size and position of the crop region is determined by the View.OutLine property.
Display Settings
The view class has properties to get and set the display style settings and the detail level settings. The View.DisplayStyle property uses the
DisplayStyle enumeration and corresponds to the display options available at the bottom of the Revit window as shown below.
Because setting a view's display style to raytrace enters a special restricted mode with limited capabilities, it is not permitted to directly
assign the display style to this value.
The View.DetailLevel property uses the ViewDetailLevel enumeration and corresponds to the detail level options available at the bottom of
the Revit window as shown below.
The ViewDetailLevel enumeration includes Undefined in the case that a given View does not use detail level.
Description
RevealHiddenElements
TemporaryHideIsolate
WorksharingDisplay
AnalyticalModel
Rayrace
The View.IsInTemporaryViewMode method can be used to determine whether the view is currently in the specified TemporaryViewMode.
Element Visibility in a View
Views keep track of visible elements. All elements that are graphical and visible in the view can be retrieved using a FilteredElementCollector
constructed with a document and the id of the view. However, some elements in the set may be hidden or covered by other elements. You
can see them by rotating the view or removing the elements that cover them. Accessing these visible elements may require Revit to rebuild
the geometry of the view. The first time your code uses this constructor for a given view, or the first time your code uses this constructor for
a view whose display settings have just been changed, you may experience a significant performance degradation.
Elements are shown or hidden in a view by category.
The View.GetVisiblility() method queries a category to determine if it is visible or invisible in the view.
The View.SetVisibility() method sets all elements in a specific category to visible or invisible.
A FilteredElementCollector based on a view will only contain elements visible in the current view. You cannot retrieve elements that are not
graphical or elements that are invisible. A FilteredElementCollector based on a document retrieves all elements in the document including
invisible elements and non-graphical elements. For example, when creating a default 3D view in an empty project, there are no elements in
the view but there are many elements in the document, all of which are invisible.
The following code sample counts the number of wall category elements in the active document and active view. The number of elements in
the active view differs from the number of elements in the document since the document contains non-graphical wall category elements.
Temporary view modes can affect element visibility. The View.IsInTemporaryViewMode() method can be used to determine if a View is in a
temporary view mode. The method View.IsElementVisibleInTemporaryViewMode() identifies if an element should be visible in the indicated
view mode. This applies only to the TemporaryHideIsolate and AnalyticalModel view modes. Other modes will result in an exception.
Creating and Deleting Views
The Revit Platform API provides numerous methods to create the corresponding view elements derived from Autodesk.Revit.DB.View class.
Most view types are created using static methods of the derived view classes. If a view is created successfully, these methods return a
reference to the view, otherwise they return null. The methods are described in the following sections specific to each view class.
Views can also be created using the View.Duplicate() method. A new view can be created from an existing view with options for the new
view to be dependent or to have detailing.
Delete a view by using the Document.Delete method with the view ID. You can also delete elements associated with a view. For example,
deleting the level element causes Revit to delete the corresponding plan view or deleting the camera element causes Revit to delete the
corresponding 3D view.
View Types
Different types of Revit views are represented by different classes in the Revit API. See the following topics for more information on each type of view.
Overview
A project model can have several view types. The following picture demonstrates the different types of views in the Project browser.
Description
AreaPlan
Area view.
CeilingPlan
ColumnSchedule
CostReport
Detail
Detail view.
DraftingView
Drafting view.
DrawingSheet
Elevation
Elevation view.
EngineeringPlan
Engineering view.
FloorPlan
Internal
Legend
Legend view.
LoadsReport
PanelSchedule
Rendering view.
Report
Report view.
Schedule
Schedule view.
Section
ThreeD
3-D view.
Undefined
Undefined/unspecified view.
Walkthrough
Walkthrough view.
View Type
Class Type
Area Plans
ViewType.AreaPlan
Elements.ViewPlan
Ceiling Plans
ViewType.CeilingPlan
Elements.ViewPlan
ViewType.ColumnSchedule
Elements.View
Detail Views
ViewType.Detail
Elements.ViewSection
Drafting Views
ViewType.DraftingView
Elements.ViewDrafting
Sheets
ViewType.DrawingSheet
Elements.ViewSheet
Elevations
ViewType.Elevation
Elements.ViewSection
ViewType.EngineeringPlan
Elements.ViewPlan
Floor Plans
ViewType.FloorPlan
Elements.ViewPlan
Legends
ViewType.Legend
Elements.View
ViewType.LoadsReport
Elements.View
ViewType.PanelSchedule
Elements.PanelScheduleView
ViewType.PresureLossReport
Elements.View
Renderings
ViewType.Rendering
Elements.ViewDrafting
Reports
ViewType.Report
Elements.View
Schedules/Quantities
ViewType.Schedule
Elements.ViewSchedule
Sections
ViewType.Section
Elements.ViewSection
3D Views
ViewType.ThreeD
Elements.View3D
Walkthroughs
ViewType.Walkthrough
Elements.View3D
This example shows how to use the ViewType property of a view to determine the view's type.
The third way to classify views is using the ViewFamilyType class. Most view creation methods required the Id of a ViewFamilyType for the new
view. The Id of the ViewFamilyType can be retrieved from the View.GetTypeId() method. The ViewFamilyType.ViewFamily property returns a
ViewFamily enumeration which specifies the family of the ViewFamilyType and similar to the ViewType enum documented above. The following
example shows how to get the ViewFamily from a View.
Code Region: Determining view type from ViewFamilyType
1. public ViewFamily GetViewFamily(Document doc, View view)
2. {
3.
ViewFamily viewFamily = ViewFamily.Invalid;
4.
5.
ElementId viewTypeId = view.GetTypeId();
6.
if (viewTypeId.IntegerValue > 1) // some views may not have a ViewFamilyType
7.
{
8.
ViewFamilyType viewFamilyType = doc.GetElement(viewTypeId) as ViewFamilyType;
9.
viewFamily = viewFamilyType.ViewFamily;
10.
}
11.
12.
return viewFamily;
View3D
View3D is a freely-oriented three-dimensional view. There are two kinds of 3D views, perspective and isometric, also referred to as
orthographic in the Revit user interface. The difference is based on the projection ray relationship. The View3D.IsPerspective property
indicates whether a 3D view is perspective or isometric.
Perspective View
The following picture illustrates how a perspective view is created.
The view direction is from the target point to the viewer in the 3D space, and from the screen to the viewer in the screen space.
The static method View3D.CreatePerspective() method can be used to create new perspective views.
// turn off the far clip plane with standard parameter API
The perspective view crop box is part of a pyramid with the apex at the viewer position. It is the geometry between the two parallel clip
planes. The crop box bounds the portion of the model that is clipped out and projected onto the view plane.
The crop box is represented by the View.CropBox property, which returns a BoundingBoxXYZ object.
The CropBox.Min and CropBox.Max points are marked in the previous picture. Note that the CropBox.Min point in a perspective view
is generated by projecting the crop box front clip plane onto the back clip plane.
Crop box coordinates are based on the viewing coordinate system. Use Transform.OfPoint() to transform CropBox.Min and CropBox.Max to
the world coordinate system. For more detail about Transform, refer to Geometry.Transform in the Geometry section.
The project plane plus the front and back clip plane are all plumb to the view direction. The line between CropBox.Max and CropBox.Min is
parallel to the view direction. With these factors, the crop box geometry can be calculated.
Like the crop box, the crop region coordinates are based on the viewing coordinate system. The following expressions are equal.
View.CropBox.Max.X(Y) / View.OutLine.Max.X(Y) == View.CropBox.Min.X(Y) / View.OutLine.Min.X(Y)
Since the size of an object's perspective projection varies inversely with the distance from that object to the center of the projection, scale is
meaningless for perspective views. The perspective 3D view Scale property always returns zero.
Isometric View
A new isometric view can be created with the static View3D.CreateIsometric() method.
3D Views SectionBox
Each view has a crop box. The crop box focuses on a portion of the model to project and show in the view. For 3D views, there is another
box named section box.
The section box determines which model portion appears in a 3D view.
The section box is used to clip the 3D model's visible portion.
The part outside the box is invisible even if it is in the crop box.
The section box is different from the crop box in that it can be rotated and moved with the model.
The section box is particularly useful for large models. For example, if you want to render a large building, use a section box. The section
box limits the model portion used for calculation. To display the section box, in the 3D view Element Properties dialog box, select Section
Box in the Extents section. You can also set it using the API:
Note If you set view.SectionBox to null, it has the same effect as hiding the section box using the Section Box parameter. The current
section box is stored by view and is restored when you show the section box using the SectionBox parameter.
The coordinate of Max and Min points of BoundingBoxXYZ returned from SectionBox property is not WCS. To convert the coordinates of Max
and Min to WCS, you need to convert point via the transform obtained from BoundingBoxXYZ.Transform property.
View Locking
The View3D class has methods and properties corresponding to the locking feature available in the Revit user interface.
The View3D.SaveOrientationAndLock() method will save the orientation and lock the view while View3D.RestoreOrientationAndLock() will
restore the view's orientation and lock it. View3D.Unlock() will unlock the view if it is currently locked. The IsLocked property will return
whether the 3D view is currently locked.
ViewPlan
Plan views are level-based. There are three types of plan views, floor plan view, ceiling plan view, and area plan view.
Generally the floor plan view is the default view opened in a new project.
Most projects include at least one floor plan view and one ceiling plan view.
Plan views are usually created after adding new levels to the project.
Adding new levels using the API does not add plan views automatically. Use the static ViewPlan.Create() method to create new floor and
ceiling plan views. Use the static ViewPlan.CreateAreaPlan() method to create a new area plan view.
The viewFamilyTypeId parameter in ViewPlan.Create() needs to be a FloorPlan, CeilingPlan, AreaPlan, or StructuralPlan ViewType. The
levelId parameter represents the Id of the level element in the project to which the plan view is associated.
The following code creates a floor plan and a ceiling plan based on a certain level.
After creating a new plan view, the Discipline for the view can be set using the Discipline parameter which is type ViewDiscipline. Options
include Architectural, Structural, Mechanical, Electrical, Plumbing and Coordination.
For structural plan views, the view direction can be set to either Up or Down using the ViewFamilyType.PlanViewDirection property.
Although it is a property of the ViewFamilyType class, an exception will be thrown if the property is accessed for views other than
StructuralPlan views.
The view range for plan views can be retrieved via the ViewPlan.GetViewRange() method. The returned PlanViewRange object can be used
to find the levels which a plane is relative to and the offset of each plane from that level. It is the same information that is available in the
View Range dialog in the Revit user interface:
The following example shows how to get the top clip plane and the associated offset for a plan view
ViewDrafting
The drafting view is not associated with the model. It allows the user to create detail drawings that are not included in the model.
In the drafting view, the user can create details in different view scales (coarse, fine, or medium).
You can use 2D detailing tools, including:
Detail lines
Detail regions
Detail components
Insulation
Reference planes
Dimensions
Symbols
Text
These tools are the same tools used to create a detail view.
Drafting views do not display model elements.
Use the Autodesk.Revit.Creation.NewViewDrafting() method to create a drafting view. Model elements are not displayed in the drafting view.
ImageView
The ImageView class is derived from ViewDrafting. It can be used to create rendering views containing images imported from disk. Use the
static ImageView.Create() method to create new rendering views.
ViewSection
The ViewSection class can be used to create section views, detail views, callout views, reference callouts and reference sections. It also
represents elevation views.
Section Views and Reference Sections
Section views cut through the model to expose the interior structure. The ViewSection.CreateSection() method creates the section view.
The viewFamilyTypeId parameter is the Id for the ViewFamilyType which will be used by the new ViewSection. The type needs to be a
Section ViewFamily. The sectionBox parameter is the section view crop box. It provides the direction and extents which are required for the
section view. Usually, another view's crop box is used as the parameter. You can also build a custom BoundingBoxXYZ instance to represent
the direction and extents.
The following code shows how to create a section view. A bounding box for the section view is created at the center of a wall. The resulting
section view will be located in the Sections (Building Section) node in the Project Browser.
Reference sections are sections that reference an existing view. Revit does not add a new view when you create a new reference section.
The parentViewId parameter is the Id of the view in which the new reference section marker will appear. Reference sections can be created
in FloorPlan, CeilingPlan, StructuralPlan, Section, Elevation, Drafting, and Detail views. The viewIdToReference can be the Id of a Detail,
Drafting or Section view. The ViewFamilyType of the referenced view will be used by the new reference section. The two XYZ points will
determine the location of the section marker's head in the parent view.
Detail Views
A detail view is a view of the model that appears as a callout or section in other views. This type of view typically represents the model at
finer scales of detail than in the parent view. It is used to add more information to specific parts of the model. The static
ViewSection.CreateDetail() method is used to create a new detail ViewSection.
The viewFamilyTypeId parameter is the Id for the ViewFamilyType which will be used by the new ViewSection. The type needs to be a
Detail ViewFamily. Just as for a standard section view, the sectionBox parameter is the section view crop box. It provides the direction and
extents which are required for the section view.
When a new detail ViewSection is added, it will appear in the Detail Views (Detail) node in the Project Browser.
Elevation Views
An elevation view is a cross-section of the model where level lines are displayed. An elevation view is represented by the ViewSection class.
However, unlike the other types of section views, you cannot create elevation views using a static method on the ViewSection class. To
create an elevation view, first create an elevation marker, then use the marker to generate the elevation view. The newly created elevation
view will appear in the Elevations (Building Elevation) node in the Project Browser. It will be assigned a unique name.
The following example creates an elevation view based on the location of a beam.
The ElevationMarker.CreateElevation() method takes an id of a ViewPlan as a parameter. That is the ViewPlan in which the ElevationMarker
is visible. The new elevation ViewSection will derive its extents and inherit settings from the ViewPlan. The last parameter is the index on
the ElevationMarker where the new elevation view will be placed. The index on the ElevationMarker must be valid and unused. The view's
direction is determined by the index.
Callouts and Reference Callouts
A callout shows part of another view at a larger scale. Callout views can be created using the static method ViewSection.CreateCallout().
Callouts can be created in FloorPlan, CeilingPlan, StructuralPlan, Section, Elevation, Drafting and Detail views. The resulting view will be
either a ViewSection, ViewPlan or ViewDetail depending on the ViewFamilyType used and will appear in the corresponding node in the Project
Browser.
The parent view Id parameter can be the Id of any type of View on which callouts can be created. The point parameters determine the
extents of the callout symbol in the parent view.
A reference callout is a callout that refers to an existing view. When you add a reference callout, Revit does not create a view in the project.
Instead, it creates a pointer to a specified, existing view. Multiple reference callouts can point to the same view.
Creation of a reference callout is similar to creation of a callout. But rather than having the Id of the ViewFamilyType for the callout as a
parameter, the CreateReferenceCallout() method takes the Id of the view to reference. The ViewFamilyType of the referenced view will be
used by the new reference callout.
Only cropped views can be referenced, unless the referenced view is a Drafting view. Drafting views can always be referenced regardless of
the parent view type. Elevation views can be referenced from Elevation and Drafting parent views. Section views can be referenced from
Section and Drafting parent views. Detail views can be referenced from all parent views except for in FloorPlan, CeilingPlan and
StructuralPlan parent views where only horizontally-oriented Detail views can be referenced. FloorPlan, CeilingPlan and StructuralPlan views
can be referenced from FloorPlan, CeilingPlan and StructuralPlan parent views.
The following example creates a new callout using a Detail ViewFamilyType and then uses the new callout view to create a reference callout.
ViewSheet
A sheet contains views and a title block. When creating a sheet view with the ViewSheet.Create() method, a title block family symbol Id is a
required parameter for the method. The Autodesk.Revit.Document TitleBlocks property contains all title blocks in the document. Choose one
title block to create the sheet.
The newly created sheet has no views. The Viewport.Create() method is used to add views. The Viewport class is used to add regular views
to a view sheet, i.e. plan, elevation, drafting and three dimensional. To add schedules to a view, use ScheduleInstance.Create() instead.
The XYZ location parameter identifies where the added views are located. It points to the added view's center coordinate (measured
in inches).
The coordinates, [0, 0], are relative to the sheet's lower left corner.
Each sheet has a unique sheet number in the complete drawing set. The number is displayed before the sheet name in the Project Browser.
It is convenient to use the sheet number in a view title to cross-reference the sheets in your drawing set. You can retrieve or modify the
number using the SheetNumber property. The number must be unique; otherwise an exception is thrown when you set the number to a
duplicate value.
The following example illustrates how to create and print a sheet view. Begin by finding an available title block in the document (using a
filter in this case) and use it to create the sheet view. Next, add a 3D view. The view is placed with its lower left-hand corner at the center of
the sheet. Finally, print the sheet by calling the View.Print() method.
Note You cannot add a sheet view to another sheet and you cannot add a view to more than one sheet; otherwise an argument exception
occurs.
Printer Setup
You may want to change the settings of the printer before printing a sheet. The API exposes the settings for the printer with the
PrintManager class, and related Autodesk.Revit.DB classes:
Class
Functionality
Autodesk.Revit.DB.PrintManager
Represents the Print information in Print Dialog (File->Print) within the Revit UI.
Autodesk.Revit.DB.PrintParameters
Autodesk.Revit.DB.PrintSetup
Represents the Print Setup (File->Print Setup...) within the Revit UI.
Autodesk.Revit.DB.PaperSize
An object that represents a Paper Size of Print Setup within the Autodesk Revit project.
Autodesk.Revit.DB.PaperSizeSet
Autodesk.Revit.DB.PaperSource
An object that represents a Paper Source of Print Setup within the Autodesk Revit project.
Autodesk.Revit.DB.PaperSourceSet
Autodesk.Revit.DB.ViewSheetSetting
Autodesk.Revit.DB.PrintSetting
Represents the Print Setup (File->Print Setup...) within the Revit UI.
For an example of code that uses these objects, see the ViewPrinter sample application that is included with the Revit Platform SDK.
ViewSchedule
A schedule is a tabular representation of data. A typical schedule shows all elements of a category (doors, rooms, etc.) with each row representing
an element and each column representing a parameter.
The ViewSchedule class represents schedules and other schedule-like views, including single-category and multi-category schedules, key
schedules, material takeoffs, view lists, sheet lists, keynote legends, revision schedules, and note blocks.
The ViewSchedule.Export() method will export the schedule data to a text file.
Creating a Schedule
The ViewSchedule class has several methods for creating new schedules depending on the type of schedule. All of the methods have a Document parameter
that is the document to which the new schedule or schedule-like view will be added. The newly created schedule views will appear under the
Schedules/Quantities node in the Project Browser.
A standard single-category or multi-category schedule can be created with the static ViewSchedule.CreateSchedule() method.
The second parameters the ID of the category whose elements will be included in the schedule, or InvalidElementId for a multi-category schedule.
A second CreateSchedule() method can be used to create an area schedule and takes an additional parameter that is the ID of an area scheme for
the schedule.
//If you want to create an area schedule, you must use CreateSchedule method with three arguments.
//The input of second argument must be ElementId of BuiltInCategory.OST_Areas category and the input of third argument must be ElementId
of a areaScheme.
8. ViewSchedule areaSchedule = Autodesk.Revit.DB.ViewSchedule.CreateSchedule(doc, new ElementId(BuiltInCategory.OST_Areas), areaSchemeId);
A key schedule displays abstract "key" elements that can be used to populate parameters of ordinary model elements and can be created with the static
ViewSchedule.CreateKeySchedule() method whose second parameter is the ID of the category of elements with which the schedule's keys will be associated.
A material takeoff is a schedule that displays information about the materials that make up elements in the model. Unlike regular schedules
where each row (before grouping) represents a single element, each row in a material takeoff represents a single <element, material> pair. The
ViewSchedule.CreateMaterialTakeoff() method has the same parameters as the ViewSchedule.CreateSchedule() method and allows for both
single- and multi-category material takeoff schedules.
View lists, sheet lists, and keynote legends are associated with a designated category and therefore their creation methods do take a category ID
as a parameter. A view list is a schedule of views in the project. It is a schedule of the Views category and is created using
ViewSchedule.CreateViewList().
A sheet list is a schedule of sheets in the project. It is a schedule of the Sheets category and is created using the ViewSchedule.CreateSheetList()
method.
A keynote legend is a schedule of the Keynote Tags category and is created using ViewSchedule.CreateKeynoteLegend().
Revision schedules are added to titleblock families and become visible as part of titleblocks on sheets. The
ViewSchedule.CreateRevisionSchedule() method will throw an exception if the document passed in is not a titleblock family.
A note block is a schedule of the Generic Annotations category that shows elements of a single family rather than all elements in a category.
The second parameter is the ID of the family whose elements will be included in the schedule.
Code Region: Creating a note block schedule
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
The schedule's category and other basic properties that determine the type of schedule.
A set of fields that become the columns of the schedule.
Sorting and grouping criteria.
Filters that restrict the set of elements visible in the schedule.
Most schedules contain a single ScheduleDefinition which is retrieved via the ViewSchedule.Definition property. In Revit MEP, schedules of certain
categories can contain an "embedded schedule" containing elements associated with the elements in the primary schedule, for example a room
schedule showing the elements inside each room or a duct system schedule showing the elements associated with each system. An embedded
schedule has its own category, fields, filters, etc. Those settings are stored in a second ScheduleDefinition object. When present, the embedded
ScheduleDefinition is obtained from the ScheduleDefinition.EmbeddedDefinition property.
Adding Fields
Once a ViewSchedule is created, fields can be added. The ScheduleDefinition.GetSchedulableFields() method will return a list of SchedulableField
objects representing the non-calculated fields that may be included in the schedule. A new field can be added from a SchedulableField object or
using a ScheduleFieldType. The following table describes the options available from the ScheduleFieldType enumeration.
Member name
Description
Instance
An instance parameter of the scheduled elements. All shared parameters also use this type, regardless of whether they are instance or type
parameters.
ElementType
Count
ViewBased
Formula
Percentage
A value indicating what percent of the total of another field each element represents.
Room
FromRoom
ToRoom
ProjectInfo
A parameter of the Project Info element in the project that the scheduled element belongs to, which may be a linked file. Only allowed in
schedules that include elements from linked files.
Material
MaterialQuantity
In a material takeoff, a value representing how a particular material is used within a scheduled element. The parameter ID can be
MATERIAL_AREA, MATERIAL_VOLUME, or MATERIAL_ASPAINT.
RevitLinkInstance
A parameter of the RevitLinkInstance that an element in a linked file belongs to. Currently RVT_LINK_INSTANCE_NAME is the only supported
parameter. Only allowed in schedules that include elements from linked files.
RevitLinkType
A parameter of the RevitLinkType that an element in a linked file belongs to. Currently RVT_LINK_FILE_NAME_WITHOUT_EXT is the only
supported parameter. Only allowed in schedules that include elements from linked files.
Using one of the ScheduleDefinition.AddField() methods will add the field to the end of the field list. To place a new field in a specific location in
the field list, use one of the ScheduleDefinition.InsertField() methods. Fields can also be ordered after the fact
using ScheduleDefinition.SetFieldOrder().
The following is a simple example showing how to add fields to a view if they are not already in the view schedule.
Code Region: Adding fields to a schedule
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
/// <summary>
/// Add fields to view schedule.
/// </summary>
/// <param name="schedules">List of view schedule.</param>
public void AddFieldToSchedule(List<ViewSchedule> schedules)
{
IList<SchedulableField> schedulableFields = null;
foreach (ViewSchedule vs in schedules)
{
//Get all schedulable fields from view schedule definition.
schedulableFields = vs.Definition.GetSchedulableFields();
foreach (SchedulableField sf in schedulableFields)
{
bool fieldAlreadyAdded = false;
//Get all schedule field ids
IList<ScheduleFieldId> ids = vs.Definition.GetFieldOrder();
foreach (ScheduleFieldId id in ids)
{
//If the GetSchedulableField() method of gotten schedule field returns same schedulable field,
// it means the field is already added to the view schedule.
if (vs.Definition.GetField(id).GetSchedulableField() == sf)
{
fieldAlreadyAdded = true;
break;
}
}
The ScheduleField class represents a single field in a ScheduleDefinition's list of fields. Each (non-hidden) field becomes a column in the schedule.
Most commonly, a field represents an instance or type parameter of elements appearing in the schedule. Some fields represent parameters of
other related elements, like the room to which a scheduled element belongs. Fields can also represent data calculated from other fields in the
schedule, specifically Formula and Percentage fields.
The ScheduleField class has properties to control column headings, both the text as well as the orientation. Column width and horizontal
alignment of text within a column can also be defined.
The ScheduleField.IsHidden property can be used to hide a field. A hidden field is not displayed in the schedule, but it can be used for filtering,
sorting, grouping, and conditional formatting and can be referenced by Formula and Percentage fields.
Some ScheduleFields can be totaled and if the HasTotals property is set to true, totals will be displayed if a footer row is enabled where the totals
will be displayed. It can either be a grand total row at the end of the schedule or a footer row for one of the schedule's grouped fields. In a nonitemized schedule, totals are also displayed in regular rows when multiple elements appear on the same row.
Style and Formatting of Fields
ScheduleField.GetStyle() and ScheduleField.SetStyle() use the TableCellStyle class to work with the style of fields in a schedule. Using SetStyle(),
various attributes of the field can be set, including the line style for the border of the cell as well as the text font, color and size.
ScheduleField.SetFormatOptions() and ScheduleField.GetFormatOptions() use the FormatOptions class to work with the formatting of a field's
data. The FormatOptions class contains settings that control how to format numbers with units as strings. It contains those settings that are
typically chosen by an end user in the Format dialog and stored in the document.
In the following example, all length fields in a ViewSchedule are formatted to display in feet and fractional inches.
Code Region: Formatting a field
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
// Group columns of related data and remove redundant text from column headings
public void GroupRelatedData(ViewSchedule colSchedule, int startIndex, int endIndex, string groupText)
{
colSchedule.GroupHeaders(0, startIndex, 0, endIndex, groupText);
Filtering
A ScheduleFilter can be used to filter the elements that will be displayed in a schedule. A filter is a condition that must be satisfied for an element
to appear in the schedule. All filters must be satisfied for an element to appear in the schedule.
A schedule can be filtered by data that is not displayed in the schedule by marking the field used for filtering as hidden using the
ScheduleField.IsHidden property.
Working with Schedule Data
ViewSchedule.GetTableData() returns a TableData object that holds most of the data that describe the style and contents of the rows, columns,
and cells in a table. More information can be found under TableView and TableData.
Note: Adding rows and columns is only possible in the header section of a regular schedule.
Also note, in the code example above, it uses the properties FirstRowNumber and FirstColumnNumber. In some sections the row or column
numbers might start with 0, or they might start with 1. These properties should always be used in place of a hardcoded 0 or 1.
The style of rows, columns, or individual cells can be customized for schedules. This includes the ability to set the border line style for all four sides
of cells, as well as cell color and text appearance (i.e. color, font, size). For regular schedules, this can only be done in the header section of the
table.
In the example below, the font of the subtitle of a ViewSchedule (assumed to be the second row of the header section) is set to bold and the font
size is set to 10.
Code Region: Formatting cells
1. public void FormatSubtitle(ViewSchedule colSchedule)
2. {
3.
TableData colTableData = colSchedule.GetTableData();
4.
5.
TableSectionData tsd = colTableData.GetSectionData(SectionType.Header);
6.
// Subtitle is second row, first column
7.
if (tsd.AllowOverrideCellStyle(tsd.FirstRowNumber + 1, tsd.FirstColumnNumber))
8.
{
9.
TableCellStyle tcs = new TableCellStyle();
10.
TableCellStyleOverrideOptions options = new TableCellStyleOverrideOptions();
11.
options.FontSize = true;
12.
options.Bold = true;
13.
tcs.SetCellStyleOverrideOptions(options);
14.
tcs.IsFontBold = true;
15.
tcs.TextSize = 10;
16.
tsd.SetCellStyle(tsd.FirstRowNumber + 1, tsd.FirstColumnNumber, tcs);
17.
}
18. }
View Filters
Filters can be applied to Views using the ParameterFilterElement class. A ParameterFilterElement filters elements based on its category and a series of filter
rules. One or more categories can be specified as allowable for the filter.
Once a filter has been defined (with one or more categories and one or more filter rules), it can be applied to a View using one of several methods. The
View.AddFilter() method will apply the filter to the view, but with default overrides, meaning the view's display will not change. View.SetFilterOverrides() will
set graphical overrides associated with a filter. And View.SetFilterVisibility() will set whether the elements that pass the filter are visible in the view or not.
AddFilter() and SetFilterVisibility() will both apply the filter to the view if it is not already applied, making it unnecessary to call AddFilter() separately.
The following example creates a filter which includes all walls whose Comments property is set to "foo". The filter is then applied to the View so that any walls
meeting this criteria are outlined in red.
All filters applied to a view can be retrieved using the View.GetFilters() method which will return a list of filter ids. Filter visibility and graphic overrides can be
checked for a specific filter using the View.GetFilterVisibility() and View.GetFilterOverrides() methods respectively. View.RemoveFilter will remove a filter from
the view.
View Cropping
The crop region for some views may be modified using the Revit API. The ViewCropRegionShapeManager.Valid property indicates whether the view is allowed
to manage the crop region shape while the ShapeSet property indicates whether a shape has been set. The following example crops a view around the
boundary of a room.
Displaced Views
Create a displaced view using the DisplacementElement class. DisplacementElement is a view-specific element that can be used to cause elements to appear
displaced from their actual location. Displaced views are useful to illustrate the relationship model elements have to the model as a whole. The
DisplacementElement does not actually change the location of any model elements; it merely causes them to be displayed in a different location.
For a detailed example of creating displaced views, see the DisplacementElementAnimation sample in the Revit SDK.
The method ResetDisplacedElements() will set the translation of the DisplacementElement to (0, 0, 0). The DisplacementElement continues to
exist, but its elements are displayed in their actual location.
Creating a Displaced Path
DisplacementPath is a view-specific annotation related to a DisplacementElement. The DisplacementPath class creates an annotation that depicts
the movement of the element from its actual location to its displaced location. The DisplacementPath is anchored to the DisplacementElement by
a reference to a point on an edge of a displaced element of the DisplacementElement. It is represented by a single line, or a series of jogged lines,
originating at the specified point on the displaced element.
The static DisplacementPath.Create() method requires a document, id of the associated DisplacementElement, a reference that refers to an edge
or curve of one of the elements displaced by the DisplacementElement, and a value in the range [0,1] that is a parameter along the edge specified.
Once created, the path style of the DisplacementPath can get set using the PathStyle property. The anchor point can also be changed
using SetAnchorPoint().
The associated DisplacementElement may have a parent DisplacementElement and this parent may have its own parent DisplacementElement,
producing a series of ancestors. The terminal point may be the point's original (un-displaced) location, or the corresponding point on any of the
intermediate displaced locations corresponding to these ancestor DisplacementElements. The DisplacementPath.AncestorIdx property specifies
the end point of the path.
UIView
While the View class is the base class for all view types in Revit and keeps tracks of elements in the view, the UIView class contains data about the view
windows in the Revit user interface. A list of all open views can be retrieved from the UIDocument using the GetOpenUIViews() method. The UIView class has
methods to get information about the views drawing area as well as to pan and zoom the active view.
UIView.GetWindowRectangle() returns a rectangle that describes the size and placement of the UIView window. It does not include the window border or title
bar.
Zoom Operations
UIView has several methods related to zooming the active view. UIView.GetZoomCorners() gets the corners of the view's rectangle in model coordinates and
UIView.ZoomAndCenterRectangle() offers the ability to zoom and pan the active view to center on the input region of the model.
The ZoomToFit() and ZoomSheetSize() methods provide quick ways to adjust the zoom of the window, while the Zoom() method can be used to zoom in or out
by a specified factor.
Closing a View
UIView.Close() can close a visible window. However, it cannot be used to close the last active window. Attempting to close the last active window will throw an
exception.
Walls
There are four kinds of Walls represented by the WallType.WallKind enumeration:
Stacked
Curtain
Basic
Unknown
The Wall and WallType class work with the Basic wall type while providing limited function to the Stacked and Curtain walls. On occasion you
need to check a Wall to determine the wall type. For example, you cannot get sub-walls from a Stacked Wall using the API. WallKind is read
only and set by System Family.
The Wall.Flipped property and Wall.flip() method gain access to and control Wall orientation. In the following examples, a Wall is compared
before and after calling the flip() method.
The Orientation property before is (0.0, 1.0, 0.0).
The Orientation property after the flip call is (0.0, -1.0, 0.0).
The Wall Location Line (WALL_KEY_REF_PARAM) parameter is 3, which represents Finish Face: Interior in the following table.
Taking the line as reference, the Wall is moved but the Location is not changed.
Description
Wall Centerline
Core Centerline
There are five static override methods in the Wall class to create a Wall:
Table 25: Create() Overrides
Name
Description
Creates a new rectangular profile wall within the project using the specified wall type,
height, and offset.
Creates a non rectangular profile wall within the project using the default wall style.
Creates a new rectangular profile wall within the project on the level specified by ElementId
using the default wall style.
Creates a non rectangular profile wall within the project using the specified wall type.
Creates a non rectangular profile wall within the project using the specified wall type and
normal vector.
The WallType Wall Function (WALL_ATTR_EXTERIOR) parameter influences the created wall instance Room Bounding and Structural Usage
parameter. The WALL_ATTR_EXTERIOR value is an integer:
Table 26: Wall Function
Wall Function
Interior
Exterior
Foundation
Retaining
Soffit
Value
Element Type
ElementType Type
Element Creation
Other
Floor
Floor
FloorType
NewFloor()/NewSlab()
FloorType.IsFoundationSlab = false
Slab
Floor
FloorType
NewSlab()
FloorType.IsFoundationSlab = false
Ceiling
Ceiling
CeilingType
No
Category = OST_Ceilings
Wall Foundation
ContFooting
ContFootingType
No
Category = OST_StructuralFoundation
Isolated Foundation
FamilyInstance
FamilySymbol
NewFamilyInstance()
Category = OST_StructuralFoundation
Foundation Slab
Floor
FloorType
NewFloor()
Category = OST_StructuralFoundation
FloorType.IsFoundationSlab = true
When editing an Isolated Foundation in Revit, you can perform the following actions:
You can pick a host, such as a floor. However, the FamilyInstance object Host property always returns null.
When deleting the host floor, the Foundation is not deleted with it.
The Foundation host is available from the Host (INSTANCE_FREE_HOST_PARAM) parameter.
Use another related Offset (INSTANCE_FREE_HOST_OFFSET_PARAM) parameter to control the foundation offset from the host
Element.
Continuous footings are represented by the ContFooting class in the API. The API provides limited access to both ContFooting and ContFootingType except
when using the GetAnalyticalModel() method (refer to AnalyticalModel in the Revit Structure section). For example, the attached wall is not available in
Revit Architecture. In Revit Structure, the relationship between the Wall class and the ContFooting class is shown using the GetAnalyticalModelSupports()
method in the AnalyticalModel class. For more details, refer to AnalyticalModelSupport in the Revit Structure section.
Here's an example of reverting a selected modified floor back to its original shape:
For more detailed examples of using the SlabShapeEditor and related classes, see the SlabShapeEditing sample application included in the
Revit SDK.
Roofs
Roofs in the Revit Platform API all derive from the RoofBase object. There are two classes:
FootPrintRoof - represents a roof made from a building footprint
ExtrusionRoof - represents roof made from an extruded profile
Both have a RoofType property that gets or sets the type of roof. This example shows how you can create a footprint roof based on some
selected walls:
Curtains
Curtain walls, curtain systems, and curtain roofs are host elements for CurtainGrid objects. A curtain wall can have only one CurtainGrid,
while curtain systems and curtain roofs may contain one or more CurtainGrids. For an example of how to create a CurtainSystem, see the
CurtainSystem sample application included with the Revit SDK. For an example of creating a curtain wall and populating it with grid lines,
see the CurtainWallGrid sample application.
Other Elements
Some Elements are not HostObjects (and don't have a specific class), but are special cases that can host other objects. For example, ramp
and its associated element type, do not have specific classes in the API and instead are represented as Element and ElementType in the
OST_Ramps category.
CompoundStructure
Walls, floors, ceilings and roofs are all children of the API class HostObject. HostObject (and its related type class HostObjAttributes) provide read only access
to the CompoundStructure.
The CompoundStructure class offers read and write access to a set of layers consisting of different materials:
CompoundStructure.GetLayers()
CompoundStructure.SetLayers()
Normally these layers are parallel and extend the entire host object with a fixed layer width. However, for walls the structure can also be vertically
compound, where the layers vary at specified vertical distances from the top and bottom of the wall. Use CompoundStructure.IsVerticallyCompound to
identify these. For vertically compound structures, the structure describes a vertical section via a rectangle which is divided into polygonal regions whose sides
are all vertical or horizontal segments. A map associates each of these regions with the index of a layer in the CompoundStructure which determines the
properties of that region.
It is possible to use the compound structure to find the geometric location of different layer boundaries. The method
CompoundStructure.GetOffsetForLocationLine() provides the offset from the center location line to any of the location line options (core centerline, finish faces
on either side, or core sides).
With the offset to the location line available, you can obtain the location of each layer boundary by starting from a known location and obtaining the widths of
each bounding layer using CompoundStructure.GetLayerWidth().
Some notes about the use of CompoundStructure:
The total width of the element is the sum of each CompoundStructureLayer's widths. You cannot change the element's total width directly but you can change
it via changing the CompoundStructureLayer width. The index of the designated variable length layer (if assigned) can be obtained from
CompoundStructure.VariableLayerIndex.
You must set the CompoundStructure back to the HostObjAttributes instance (using the HostObjAttributes.SetCompoundStructure() method) in order for any
change to be stored.
Changes to the HostObjAttributes affects every instance in the current document. If you need a new combination of layers,you will need to create a new
HostObjAttributes (use ElementType.Duplicate()) and assign the new CompoundStructure to it.
The CompoundStructureLayer DeckProfileId, and DeckEmbeddingType, properties only work with Slab in Revit Structure. For more details, refer to Revit
Structure.
Material
Each CompoundStructureLayer in HostObjAttributes is typically displayed with some type of material. If CompoundStructureLayer.MaterialId returns -1, it
means the Material is Category-related. For more details, refer to Material. Getting the CompoundStructureLayer Material is illustrated in the following sample
code:
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66. }
switch (structLayer.Function)
{
case MaterialFunctionAssignment.Finish1:
layerMaterial =
allCategories.get_Item(BuiltInCategory.OST_WallsFinish1).Material;
break;
case MaterialFunctionAssignment.Finish2:
layerMaterial =
allCategories.get_Item(BuiltInCategory.OST_WallsFinish2).Material;
break;
case MaterialFunctionAssignment.Membrane:
layerMaterial =
allCategories.get_Item(BuiltInCategory.OST_WallsMembrane).Material;
break;
case MaterialFunctionAssignment.Structure:
layerMaterial =
allCategories.get_Item(BuiltInCategory.OST_WallsStructure).Material;
break;
case MaterialFunctionAssignment.Substrate:
layerMaterial =
allCategories.get_Item(BuiltInCategory.OST_WallsSubstrate).Material;
break;
case MaterialFunctionAssignment.Insulation:
layerMaterial =
allCategories.get_Item(BuiltInCategory.OST_WallsInsulation).Material;
break;
default:
// It is impossible to reach here
break;
}
if (null == layerMaterial)
{
// CompoundStructureLayer's default Material is its SubCategory
layerMaterial = wallMaterial;
}
}
TaskDialog.Show("Revit","Layer Material: " + layerMaterial);
Sometimes just the material from the "structural" layer is needed. Rather than looking at each layer for the one whose function is
MaterialFunctionAssignment.Structure, use the CompoundStructure.StructuralMaterialIndex property to find the index of the layer whose material defines the
structural properties of the type for the purposes of analysis.
Opening
In the Revit Platform API, the Opening object is derived from the Element object and contains all of the Element object properties and
methods. To retrieve all Openings in a project, use Document.ElementIterator to find the Elements.Opening objects.
General Properties
This section explains how to use the Opening properties.
IsRectBoundary - Identifies whether the opening has a rectangular boundary.
o
If true, it means the Opening has a rectangular boundary and you can get an IList<XYZ> collection from the Opening
BoundaryRect property. Otherwise, the property returns null.
If false, you can get a CurveArray object from the BoundaryCurves property.
BoundaryCurves - If the opening boundary is not a rectangle, this property retrieves geometry information; otherwise it returns null.
The property returns a CurveArray object containing the curves that represent the Opening object boundary.
For more details about Curve, refer to Geometry.
BoundaryRect - If the opening boundary is a rectangle, you can get the geometry information using this property; otherwise it returns
null.
o
The IList<XYZ> collection usually contains the rectangle boundary minimum (lower left) and the maximum (upper right)
coordinates.
Host - The host property retrieves the Opening host element. The host element is the element cut by the Opening object.
Note If the Opening object's category is Shaft Openings, the Opening host is null.
The following example illustrates how to retrieve the existing Opening properties.
}
else
{
message += "\nThe opening doesn't have a rectangular boundary.";
// Get curve number
int curves = opening.BoundaryCurves.Size;
message += "\nNumber of curves is : " + curves;
for (int i = 0; i < curves; i++)
{
Autodesk.Revit.DB.Curve curve = opening.BoundaryCurves.get_Item(i);
// Get curve start point
message += "\nCurve start point: " + XYZToString(curve.GetEndPoint(0));
// Get curve end point
message += "; Curve end point: " + XYZToString(curve.GetEndPoint(1));
}
}
TaskDialog.Show("Revit",message);
Create Opening
In the Revit Platform API, use the Document.NewOpening() method to create an opening in your project. There are four method overloads
you can use to create openings in different host elements:
profile);
Thermal Properties
Certain assembly types such as Wall, Floor, Ceiling, Roof and Building Pad have calculated and settable thermal properties which are represented by the
ThermalProperties class.
The ThermalProperties class has properties for the values shown above. Absorptance and Roughness are modifiable while HeatTransferCoefficient,
ThermalResistance, and ThermalMass are read-only. The units for these calculated values are shown in the table below.
Property
HeatTransferCoefficient
ThermalResistance
ThermalMass
Unit
Thermal properties can be retrieved using the ThermalProperties property on the following types:
WallType
FloorType
CeilingType
RoofType
BuildingPadType
Family Instances
In this section, you will learn about the following:
The relationship between family and family instance
Family and family instance features
How to load or create family and family instance features
The relationship between family instance and family symbol
Identifying Elements
In Revit, the easiest way to judge whether an element is a FamilyInstance or not is by using the properties dialog box.
If the family name starts with System Family and the Load button is disabled, it belongs to System Family.
The FamilySymbol object represents a specific set of family settings corresponding to a Type in the Revit UI, such as 34"80".
The FamilyInstance object represents an actual Type (FamilySymbol) instance in the Revit project. For example, in the following picture, the
FamilyInstance is a single door in the project.
Each FamilyInstance has one FamilySymbol. The door is an instance of a 34"80".
Each FamilySymbol belongs to one Family. The 34"80" symbol belongs to a Single-Flush family.
Each Family contains one or more FamilySymbols. The Single-Flush family contains a 34"80" symbol, a 34"84" symbol, a 36"84"
and so on.
Note that while most component elements are exposed through the API classes FamilySymbol and FamilyInstance, some have been wrapped
with specific API classes. For example, AnnotationSymbolType wraps FamilySymbol and AnnotationSymbol wraps FamilyInstance.
Family
The Family class represents an entire Revit family. It contains the FamilySymbols used by FamilyInstances.
Loading Families
The Document class contains the LoadFamily() and LoadFamilySymbol() methods.
LoadFamily() loads an entire family and all of its types or symbols into the project.
LoadFamilySymbol() loads only the specified family symbol from a family file into the project.
NoteTo improve the performance of your application and reduce memory usage, if possible load specific FamilySymbols instead of entire
Family objects.
The family file path is retrieved using the Options.Application object GetLibraryPaths() method.
The Options.Application object is retrieved using the Application object Options property.
In LoadFamilySymbol(), the input argument Name is the same string value returned by the FamilySymbol object Name property.
For more information, refer to Code Samples.
Categories
The FamilyBase.FamilyCategory property indicates the category of the Family such as Columns, Furniture, Structural Framing, or Windows.
FamilyInstances
Examples of categories of FamilyInstance objects in Revit are Beams, Braces, Columns, Furniture, Massing, and so on. The FamilyInstance
object provides more detailed properties so that the family instance type and appearance in the project can be changed.
Location-Related Properties
Location-related properties show the physical and geometric characteristics of FamilyInstance objects, such as orientation, rotation and
location.
Orientation
The face orientation or hand orientation can be changed for some FamilyInstance objects. For example, a door can face the outside or the
inside of a room or wall and it can be placed with the handle on the left side or the right side. The following table compares door, window,
and desk family instances.
Table 29: Compare Family Instances
Boolean Property
Door
Desk
CanFlipFacing
True
True
False
CanFlipHand
True
False
False
If CanFlipFacing or CanFlipHand is true, you can call the flipFacing() or flipHand() methods respectively. These methods can change the
facing orientation or hand orientation respectively. Otherwise, the methods do nothing and return False.
When changing orientation, remember that some types of windows can change both hand orientation and facing orientation, such as a
Casement 3x3 with Trim family.
There are four different facing orientation and hand orientation combinations for doors. See the following picture for the combinations and
the corresponding Boolean values are in the following table.
Door 1
Door 2
Door 3
Door 4
FacingFlipped
False
True
False
True
HandFlipped
False
True
True
False
Door 1
Door 2
Door 3
Door 4
Mirrored
False
False
True
True
In the previous door example, the Mirrored property for Door 1 and Door 2 is False, while for both Door 3 and Door 4 it is True. This is
because when you create a door in the Revit project, the default result is either Door 1 or Door 2. To create a door like Door 3 or Door 4,
you must flip the Door 1 and Door 2 hand orientation respectively. The flip operation is like a mirror transformation, which is why the Door 3
and Door 4 Mirrored property is True.
For more information about using the Mirror() method in Revit, refer to the Editing Elements chapter.
Rotation - CanRotate and rotate()
The family instance Boolean CanRotate property is used to test whether the family instance can be rotated 180 degrees. This depends on the
family to which the instance belongs. For example, in the following picture, the CanRotate properties for Window 1 (Casement 33 with
Trim: 36"72") and Door 1 (Double-Glass 2: 72"82") are true, while Window 2 (Fixed: 36"w 72"h) is false.
Other Properties
The properties in this section are specific to Revit Architecture and Revit Structure. They are covered thoroughly in their respective chapters.
Room Information
FamilyInstance properties include Room, FromRoom, and ToRoom. For more information about Room, refer to Revit Architecture.
Space Information
FamilyInstance has a Space property for identifying the space that holds an instance in MEP.
Revit Structure Related Analytical Model
The GetAnalyticalModel() method retrieves the family instance structural analytical model.
For more information about AnalyticalModel refer to Revit Structure.
Creating FamilyInstance Objects
Typically a FamilyInstance object is created using one of the twelve overload methods of Autodesk.Revit.Creation.Document called
NewFamilyInstance(). The choice of which overload to use depends not only on the category of the instance, but also other characteristics of
the placement like whether it should be hosted, placed relative to a reference level, or placed directly on a particular face. The details are
included in Table 32 - Options for creating instance with NewFamilyInstance() below.
Some FamilyInstance objects require more than one location to be created. In these cases, it is more appropriate to use the more detailed
creation method provided by this object (see Table 33 - Options for creating instances with other methods below). If the instance is not
created, an exception is thrown. The type/symbol used must be loaded into the project before the method is called.
NewFamilyInstance() parameters
Comments
Air Terminals
Creates the instance in an arbitrary location without reference to a level or host element.
Generic Models
Lighting Devices
If it is face-based and linear, but accepts a reference to a face, rather than a Face
Creates the column so that its base lies on the reference level. The column will extend to
the next available level in the model, or will extend the default column height if there are
no suitable levels above the reference level.
Doors and windows must be hosted by a wall. Use this method if they can be placed with
the default orientation.
Creates a level based brace or beam given its curve. This is the recommended method to
create Beams and Braces
Boundary Conditions
Casework
Communication Devices
Data Devices
Electrical Equipment
Electrical Fixtures
Entourage
Fire Alarm Devices
Furniture
Furniture Systems
Lighting Fixtures
Mass
Mechanical Equipment
Nurse Call Devices
Parking
Planting
Plumbing Fixtures
Security Devices
Site
Specialty Equipment
Sprinklers
Structural Connections
Structural Foundations
Structural Stiffeners
Telephone Devices
Columns
Structural Columns
Doors
Windows
Structural Framing
(Beams, Braces)
Detail Component
Generic Annotations
The structural instance will be of zero-length after creation. Extend it by setting its curve (FamilyInstance.Location as LocationCurve) using
LocationCurve.Curve property.
You can simplify your code and improve performance by creating more than one family instance at a time using
Document.NewFamilyInstances(). This method has a single parameter, which is a list of FamilyInstanceCreationData objects describing the
family instances to create.
Instances of some family types are better created through methods other than Autodesk.Revit.Creation.Document.NewFamilyInstance().
These are listed in the table below.
Creation method
Comments
Spinkler Tags
Stair Tags
Structural Area Reinforcement
Tags
Structural Beam System Tags
Structural Column Tags
Structural Connection Tags
Structural Foundation Tags
Structural Framing Tags
Structural Path Reinforcement
Tags
Structural Rebar Tags
Structural Stiffener Tags
Structural Truss Tags
Telephone Device Tags
Wall Tags
Window Tags
Wire Tag
Zone Tags
Material Tags
Multi-Category Tags
Title Blocks
NewViewSheet(FamilySymbol)
Families and family symbols are loaded using the Document.LoadFamily() or Document.LoadFamilySymbol() methods. Some families, such
as Beams, have more than one endpoint and are inserted in the same way as a single point instance. Once the linear family instances are
inserted, their endpoints can be changed using the Element.Location property. For more information, refer to Code Samples.
Code Samples
Review the following code samples for more information about working with Family Instances. Please note that in the NewFamilyInstance()
method, a StructuralType argument is required to specify the type of the family instance to be created. Here are some examples:
Table 34: The value of StructuralType argument in the NewFamilyInstance() method
Type of Family Instance
Value of StructuralType
NonStructural
Beams
Beam
Braces
Brace
Columns
Column
Footings
Footing
Create Tables
The following function demonstrates how to load a family of Tables into a Revit project and create instances from all symbols in this family.
The LoadFamily() method returns false if the specified family was previously loaded. Therefore, in the following case, do not load the family,
Table-Dining Round w Chairs.rfa, before this function is called. In this example, the tables are created at Level 1 by default.
Figure 47: Load family and create tables in the Revit project
Create a Beam
In this sample, a family symbol is loaded instead of a family, because loading a single FamilySymbol is faster than loading a Family that
contains many FamilySymbols.
Create Doors
Create a long wall about 180' in length and select it before running this sample. The host object must support inserting instances; otherwise
the NewFamilyInstance() method will fail. If a host element is not provided for an instance that must be created in a host, or the instance
cannot be inserted into the specified host element, the method NewFamilyInstance() does nothing.
FamilySymbol
The FamilySymbol class represents a single Type within a Family. Each family can contain one or more family symbols. Each FamilyInstance has an associated
FamilySymbol which can be accessed from its Symbol property.
Thermal Properties
Certain types of families (doors, windows, and curtain wall panels) contain thermal properties as shown in the Type Properties window below for a window.
The thermal properties for a FamilySymbol are represented by the FamilyThermalProperties class and are retrieved using the
FamilySymbol.GetThermalProperties() method. The FamilyThermalProperties for a FamilySymbol can be set using SetThermalProperties(). The properties of
the FamilyThermalProperties class itself are read-only.
The units for the calculated values are shown in the table below.
Property
Unit
HeatTransferCoefficient
ThermalResistance
The AnalyticConstructionTypeId property is the construction gbXML type and returns the value that corresponds to the 'id' property of a constructionType
node in Constructions.xml. The static FamilyThermalProperties.Find() method will find the FamilyThermalProperties by the 'id' property of a constructionType
node in Constructions.xml.
Family Documents
This section discusses families and how to:
Create and modify Family documents
Access family types and parameters
The FamilyCategory can also be set, allowing the category of a family that is being edited to be changed.
Parameters
Family parameters can be accessed from the OwnerFamily property of a Family Document as the following example shows.
The following sample shows how to create a new Sweep from a solid ovoid profile in a Family Document.
The following example shows how to create a new subcategory, assign it a material, and then assign the subcategory to a form.
Create an annotation
New annotations such as Dimensions and ModelText and TextNote objects can also be created in families, as well as curve annotation elements such as
SymbolicCurve, ModelCurve, and DetailCurve. See Annotation Elements for more information on Annotation elements.
Additionally, a new Alignment can be added, referencing a View that determines the orientation of the alignment, and two geometry references.
The following example demonstrates how to create a new arc length Dimension.
In the example below, the resulting family document will display the text "Hello World" with a line under it. When the family is loaded into a
Revit project document and an instance is placed, in plan view, only the line will be visible. In 3D view, both the line and text will be
displayed, unless the Detail Level is set to Course, in which case the line will disappear.
Editing FamilyTypes
FamilyManager provides the ability to iterate through existing types in a family, and add and modify types and their parameters.
The following example shows how to add a new type, set its parameters and then assign the new type to a FamilyInstance. Type editing is
done on the current type by using the Set() function. The current type is available from the CurrentType property. The CurrentType property
can be used to set the current type before editing, or use the NewType() function which creates a new type and sets it to the current type
for editing.
Note that once the new type is created and modified, Document.LoadFamily() is used to load the family back into the Revit project to make
the new type available.
Conceptual Design
This chapter discusses the conceptual design functionality of the Revit API for the creation of complex geometry in a family document. Formmaking is supported by the addition of new objects: points and spline curves that pass through these points. The resulting surfaces can be
divided, patterned, and panelized to create buildable forms with persistent parametric relationships.
Reference points can be created based on XYZ coordinates as in the example above, or they can be created relative to other geometry so
that the points will move when the referenced geometry changes. These points are created using the subclasses of the
PointElementReference class. The subclasses are:
PointOnEdge
PointOnEdgeEdgeIntersection
PointOnEdgeFaceIntersection
PointOnFace
PointOnPlane
For example, the last two lines of code in the previous example create a reference point in the middle of the CurveByPoints.
Forms can be created using model lines or reference lines. Model lines are "consumed" by the form during creation and no longer exist as
separate entities. Reference lines, on the other hand, persist after the form is created and can alter the form if they are moved. Although the
API does not have a ReferenceLine class, you can change a model line to a reference line using the ModelCurve.ChangeToReferenceLine()
method.
return revolveForms;
Forms
Creating Forms
Similar to family creation, the conceptual design environment provides the ability to create new forms. The following types of forms can be
created: extrusions, revolves, sweeps, swept blends, lofts, and surface forms. Rather than using the Blend, Extrusion, Revolution, Sweep,
and SweptBlend classes used in Family creation, Mass families use the Form class for all types of forms.
An extrusion form is created from a closed curve loop that is planar. A revolve form is created from a profile and a line in the same plane as
the profile which is the axis around which the shape is revolved to create a 3D form. A sweep form is created from a 2D profile that is swept
along a planar path. A swept blend is created from multiple profiles, each one planar, that is swept along a single curve. A loft form is
created from 2 or more profiles located on separate planes. A single surface form is created from a profile, similarly to an extrusion, but is
given no height.
The following example creates a simple extruded form. Note that since the ModelCurves used to create the form are not converted to
reference lines, they will be consumed by the resulting form.
return extrusionForm;
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69. }
ref_ar_ar.Append(ref_ar);
rpa.Clear();
ref_ar = new ReferenceArray();
// make third profile curve for loft
xyz = document.Application.Create.NewXYZ(75, 0, 0);
rp = document.FamilyCreate.NewReferencePoint(xyz);
rpa.Append(rp);
xyz = document.Application.Create.NewXYZ(75, 50, 5);
rp = document.FamilyCreate.NewReferencePoint(xyz);
rpa.Append(rp);
xyz = document.Application.Create.NewXYZ(75, 100, 0);
rp = document.FamilyCreate.NewReferencePoint(xyz);
rpa.Append(rp);
cbp = document.FamilyCreate.NewCurveByPoints(rpa);
ref_ar.Append(cbp.GeometryCurve.Reference);
ref_ar_ar.Append(ref_ar);
loftForm = document.FamilyCreate.NewLoftForm(true, ref_ar_ar);
return loftForm;
Additionally, you can modify a form by adding an edge or a profile, which can then be modified using the methods listed above.
The following example moves the first profile curve of the given form by a specified offset. The corresponding figure shows the result of
applying this code to the loft form from the previous example.
Rationalizing a Surface
Dividing a surface
Faces of forms can be divided with UV grids. You can access the data for a divided surface using the Form.GetDividedSurfaceData() method
(as is shown in a subsequent example) as well as create new divided surfaces on forms as shown below.
The following example demonstrates how to edit a massing panel family which can then be applied to a form in a conceptual mass
document. To run this example, first create a new family document using the "Curtain Panel Pattern Based.rft" template.
Adaptive Components
Adaptive Components are designed to handle cases where components need to flexibly adapt to many unique contextual conditions. For
example, adaptive components could be used in repeating systems generated by arraying multiple components that conform to user-defined
constraints.
The following code shows how to create an instance of an adaptive component family into a massing family and align the adaptive points in
the instance with points in the massing family.
For LoadBase, LoadCase, LoadCombination, LoadNature and LoadUsage, refer toRevit Structure
For ModelCurve, refer to Sketching
For Material and FillPattern, refer to Material
For EnergyDataSettings, refer to Revit Architecture
Levels
A level is a finite horizontal plane that acts as a reference for level-hosted elements, such as walls, roofs, floors, and ceilings. In the Revit
Platform API, the Level class is derived from the Element class. The inherited Name property is used to retrieve the user-visible level name
beside the level bubble in the Revit UI. To retrieve all levels in a project, use the ElementIterator iterator to search for Level objects.
Elevation
The Level class has the following properties:
The Elevation property (LEVEL_ELEV) is used to retrieve or change the elevation above or below ground level.
The ProjectElevation property is used to retrieve the elevation relative to the project origin regardless of the Elevation Base
parameter value.
Elevation Base is a Level type parameter.
o
Grids
Grids are represented by the Grid class which is derived from the Element class. It contains all grid properties and methods. The inherited
Name property is used to retrieve the content of the grid line's bubble.
Curve
The Grid class Curve property gets the object that represents the grid line geometry.
If the IsCurved property returns true, the Curve property will be an Arc class object.
If the IsCurved property returns false, the Curve property will be a Line class object.
For more information, refer to Geometry.
The following code is a simple example using the Grid class. The result appears in a message box after invoking the command.
Code Region 15-3: Using the Grid class
view plaincopy to clipboardprint?
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
TaskDialog.Show("Revit",message);
Creating a Grid
Two overloaded Document methods are available to create a new grid in the Revit Platform API. Using the following method with different
parameters, you can create a curved or straight grid:
The following code sample illustrates how to create a new grid with a line or an arc.
NoteIn Revit, the grids are named automatically in a numerical or alphabetical sequence when they are created.
You can also create several grids at once using the Document.NewGrids() method, which takes a CurveArray parameter.
Phase
Some architectural projects, such as renovations, proceed in phases. Phases have the following characteristics:
Phases represent distinct time periods in a project lifecycle.
The lifetime of an element within a building is controlled by phases.
Each element has a construction phase but only the elements with a finite lifetime have a destruction phase.
All phases in a project can be retrieved from the Document object. A Phase object contains three pieces of useful information: Name, ID and
UniqueId. The remaining properties always return null or an empty collection.
Each new modeling component added to a project has a Created Phase ID and a Demolished Phase ID property. The Element.AllowPhases()
method indicates whether its phase ID properties can be modified.
The Created Phase ID property has the following characteristics:
It identifies the phase in which the component was added.
The default value is the same ID as the current view Phase value.
Change the Created Phase ID parameter by selecting a new value corresponding to the drop-down list.
The Demolished Phase ID property has the following characteristics:
It identifies in which phase the component is demolished.
The default value is none.
Demolishing a component with the demolition tool updates the property to the current Phase ID value in the view where you
demolished the element.
You can demolish a component by setting the Demolished Phase ID property to a different value.
If you delete a phase using the Revit Platform API, all modeling components in the current phase still exist. The Created Phase ID
parameter value for these components is changed to the next item in the drop-down list in the Properties dialog box.
Design Options
Design options provide a way to explore alternative designs in a project. Design options provide the flexibility to adapt to changes in project
scope or to develop alternative designs for review. You can begin work with the main project model and then develop variations along the
way to present to a client. Most elements can be added into a design option. Elements that cannot be added into a design option are
considered part of the main model and have no design alternatives.
The main use for Design options is as a property of the Element class. See the following example.
The primary option is considered the default active DesignOption. For example, a design option set is named Wall and there
are two design options in this set named "brick wall" and "glass wall". If "brick wall" is the primary option, only this option
and elements that belong to it are retrieved by the Element Iterator. "Glass wall" is inactive.
Annotation Elements
This chapter introduces Revit Annotation Elements, including the following:
Dimension
DetailCurve
IndependentTag
TextNote
AnnotationSymbol
Note that:
Dimensions are view-specific elements that display sizes and distances in a project.
Detail curves are created for detailed drawings. They are visible only in the view in which they are drawn. Often they are drawn over
the model view.
Tags are an annotation used to identify elements in a drawing. Properties associated with a tag can appear in schedules.
AnnotationSymbol has multiple leader options when loaded into a project.
For more information about Revit Element classification, refer to Elements Essentials.
Dimensions
There are five kinds of permanent dimensions:
Linear dimension
Radial dimension
Diameter Dimension
Angular dimension
Arc length dimension
alignment constraint.
Spot Dimensions
Spot coordinates and spot elevations are represented by the SpotDimension class and are distinguished by category. Like the permanent
dimension, spot dimensions are view-specific. The type and category for each spot dimension are listed in the following table:
Table 35: Spot dimension Type and Category
Type
Category
Spot Coordinates
OST_SpotCoordinates
Spot Elevations
OST_SpotElevations
Comparison
The following table compares different kinds of dimensions and constraints in the API:
Table 36: Dimension Category Comparison
Dimension or Constraint
Permanent Dimension
Dimension Constraint
API Class
BuiltInCategory
Curve
Reference
View
Location
Dimension
OST_Dimensions
A Line
>=2
Specific view
null
radial dimension
Null
diameter dimension
Null
angular dimension
An Arc
An Arc
An Arc
An Arc
A Line
>=3
linear dimension
OST_Constraints
angular dimension
Equality Constraint
Create and Delete
The NewDimension() method is available in the Creation.Document class. This method can create a linear dimension only.
Using the NewDimension() method input parameters, you can define the visible View, dimension line, and References (two or more).
However, there is no easy way to distinguish a linear dimension DimensionType from other types. The overloaded NewDimension() method
with the DimensionType parameter is rarely used.
The following code illustrates how to use the NewDimension() method to duplicate a dimension.
Though only linear dimensions are created, you can delete all dimensions and constraints represented by Dimension and SpotDimension
using the Document.Delete() method.
Detail Curve
Detail curve is an important Detail component usually used in the detail or drafting view. Detail curves are accessible in the DetailCurve class
and its derived classes.
DetailCurve is view-specific as are other annotation elements. However, there is no DetailCurve.View property. When creating a detail curve,
you must compare the detail curve to the model curve view.
Tags
A tag is an annotation used to identify drawing elements. The API exposes the IndependentTag and RoomTag classes to cover most tags
used in the Revit application. For more details about RoomTag, see Room in the Revit Architecture section.
NoteThe IndependentTag class represents the tag element in Revit and other specific tags such as keynote, beam system tag, electronic
circuit symbol (Revit MEP), and so on. In Revit internal code, the specific tags have corresponding classes derived from IndependentTag. As
a result, specific features are not exposed by the API and cannot be created using the NewTag() method. They can be distinguished by the
following categories:
Table 37: Tag Name and Category
Tag Name
BuiltInCategory
Keynote Tag
OST_KeynoteTags
OST_BeamSystemTags
OST_ElectricalCircuitTags
OST_SpanDirectionSymbol
OST_PathReinSpanSymbol
OST_IOSRebarSystemSpanSymbolCtrl
In this section, the main focus is on the tag type represented in the following picture.
Note You can't change the text displayed in the IndependentTag directly. You need to change the parameter that is used to populate tag text
in the Family Type for the Element that's being tagged. In the example below, that parameter is "Type Mark", although this setting can be
changed in the Family Editor in the Revit UI.
ext
In the API, the TextNote class represents Text. Its general features are as follows:
Table 38: General Features of TextNote
Function
Document.Create.NewTextNote() Method
TextNote.Text Property
TextNote.Coord Property
TextNote.Width Property
TextNote.Leaders Property
TextNote.AddLeader() Method
TextNote.RemoveLeaders() Method
Revit supports two kinds of Leaders: straight leaders and arc leaders. Control the TextNote leader type using the TextNoteLeaderType
enumerated type:
Table 39: Leader Types
Function
Member Name
TNLT_ARC_R
-Add a right arc leader
TNLT_ARC_L
-Add a left arc leader
TNLT_STRAIGHT_R
-Add a right leader.
TNLT_STRAIGHT_L
-Add a left leader.
Note Straight leaders and arc leaders cannot be added to a Text type at the same time.
Annotation Symbol
An annotation symbol is a symbol applied to a family to uniquely identify that family in a project.
Geometry
The Autodesk.Revit.DB namespace contains many classes related to geometry and graphic-related types used to describe the graphical
representation in the API. The geometry-related classes include:
GeometryObject class - Includes classes derived from the GeometryObject class.
Geometry Helper classes - Includes classes derived from the APIObject class and value types
Geometry Utility classes - Includes classes to create non-element geometry and to find intersections of solids
Collection classes - Includes classes derived from the IEnumerable or IEnumerator interface.
In this section, you learn how to use various graphic-related types, how to retrieve geometry data from an element, how to transform an
element, and more.
Note Retrieving the geometry data from Element in this example is limited because Instance is not considered. For example, sweeps
included in the wall are not available in the sample code. The goal for this walkthrough is to give you a basic idea of how to retrieve
geometry data but not cover all conditions. For more information about retrieving geometry data from Element, refer to Example: Retrieving
Geometry Data from a Beam.
Create Geometry Options
In order to get the wall's geometry information, you must create a Geometry.Options object which provides detailed customized options. The
code is as follows:
GeometryObject Class
The indexed property Element.Geometry[] can be used to pull the geometry of any model element (3D element). This applies both to
system family instances such as walls, floors and roofs, and also to family instances of many categories, e.g. doors, windows, furniture, or
masses.
The extracted geometry is returned to you as Autodesk.Revit.DB.GeometryElement. You can iterate through the geometry members of that
element by using the GetEnumerator() method.
Typically, the objects returned at the top level of the extracted geometry will be one of:
Solid a boundary representation made up of faces and edges
Mesh a 3D array of triangles
Curve a bounded 3D curve
Point a visible point datum at a given 3D location
PolyLine a series of line segments defined by 3D points
GeometryInstance an instance of a geometric element positioned within the element
A curve represents a path in 2 or 3 dimensions in the Revit model. Curves may represent the entire extent of an elements geometry (e.g. CurveElements) or
may appear as a single piece of the geometry of an element (e.g. the centerline of a wall or duct). Curves and collections of curves are used as inputs in many
element creation methods in the API.
Curve parameterization
Curve analysis
Curve types
Mathematical representations of curve types
Curve creation
Curve collections
Curve analysis
There are several Curve members which are tools suitable for use in geometric analysis. In some cases, these APIs do more than you might expect by a quick
review of their names.
Intersect()
The Intersect method allows you compare two curves to find how they differ or how they are similar. It can be used in the manner you might expect, to obtain
the point or point(s) where two curves intersect one another, but it can also be used to identify:
Collinear lines
Overlapping lines
Identical curves
Totally distinct curves with no intersections
The return value identifies these different results, and the output IntersectionSetResult contains information on the intersection point(s).
Project()
The Project method projects a point onto the curve and returns information about the nearest point on the curve, its parameter, and the distance from the
projection point.
Tessellate()
This splits the curve into a series of linear segments, accurate within a default tolerance. For Curve.Tessellate(), the tolerance is slightly larger than 1/16. This
tolerance of approximation is the tolerance used internally by Revit as adequate for display purposes.
Note that only lines may be split into output of only two tessellation points; non-linear curves will always output more than two points even if the curve has an
extremely large radius which might mathematically equate to a straight line.
Curve collections
The Revit API uses different types of collections of curves as inputs:
CurveLoop this represents a specific chain of curves joined end-to-end. It can represent a closed loop or an open one. Create it using:
o CurveLoop.Create()
o CurveLoop.CreateViaCopy()
o CurveLoop.CreateViaThicken()
CurveArray this collection class represents an arbitrary collection of curves. Create it using its constructor.
CurveArrArray this collection class is a collection of CurveArrays. When this is used, the organization of the sub-elements of this array have meaning
for the method this is passed to; for example, in NewExtrusion() multiple CurveArrays should represent different closed loops.
Newer API methods use .NET collections of Curves in place of CurveArray and CurveArrArray.
Curve creation
Curves are often needed as inputs to Revit API methods. Curves can be created static methods on the associated classes:
Line.CreateBound()
Line.CreateUnbound()
Arc.Create()
Ellipse.Create()
NurbSpline.Create()
HermiteSpline.Create()
Curve.CreateTransformed()
Curve creation methods prevent creation of curves that are shorter than Revit's tolerance. This tolerance is exposed through the
Application.ShortCurveTolerance property.
Curve Parameterization
Curves in the Revit API can be described as mathematical functions of an input parameter u, where the location of the curve at any given point in XYZ space is
a function of u.
Curves can be bound or unbound. Unbound curves have no endpoints, representing either an infinite abstraction (an unbound line) or a cyclic curve (a circle or
ellipse).
In Revit, the parameter u can be represented in two ways:
A normalized parameter. The start value of the parameter is 0.0, and the end value is 1.0. For some curve types, this makes evaluation of the curve
along its extents very easy, for example, the midpoint of a line is at parameter 0.5. (Note that for more complex curve equations like Splines this
assumption cannot always be made).
A raw parameter. The start and end value of the parameter can be any value. For a given curve, the value of the minimum and maximum raw
parameter can be obtained through Curve.GetEndParameter(int) . Raw parameters are useful because their units are the same as the Revit default
units (feet). So to obtain a location 5 feet along the curve from the start point, you can take the raw parameter at the start and add 5 to it. Raw
parameters are also the only way to evaluate unbound curves.
The methods Curve.ComputeNormalizedParameter() and Curve.ComputeRawParameter() automatically scale between the two parameter types. The method
Curve.IsInside() evaluates a raw parameter to see if it lies within the bounds of the curve.
You can use the parameter to evaluate a variety of properties of the curve at any given location:
The XYZ location of the given curve. This is returned from Curve.Evaluate(). Either the raw or normalized parameter can be supplied. If you are also
calling ComputeDerivatives(), this is also the .Origin property of the Transform returned by that method.
The first derivative/tangent vector of the given curve. This is the .BasisX property of the Transform returned by Curve.ComputeDerivatives().
The second derivative/normal vector of the given curve. This is the .BasisY property of the Transform returned by Curve.ComputeDerivatives().
The binormal vector of the given curve, defined as the cross-product of the tangent and normal vector. This is the .BasisZ property of the Transform
returned by Curve.ComputeDerivatives().
All of the vectors returned are non-normalized (but you can normalize any vector in the Revit API with XYZ.Normalize()). Note that there will be no value set for
the normal and binormal vector when the curve is a straight line. You can calculate a normal vector to the straight line in a given plane using the tangent
vector.
The API sample DirectionCalculation uses the tangent vector to the wall location curve to find exterior walls that face south:
Curve types
Revit uses a variety of curve types to represent curve geometry in a document. These include:
Curve type
Definition
Notes
Bound line
Line
Arc
Arc
Circle
Arc
An unbound circle
Cylindrical
helix
CylindricalHelix
Elliptical arc
Ellipse
Ellipse
Ellipse
An unbound ellipse
NURBS
NurbSpline
HermiteSpline
Hermite
Mathematical representations of all of the Revit curve types can be found here.
Bound lines
Bound lines are defined by their endpoints. In the Revit API, obtain the endpoints of the line from the Curve-level GetEndPoint() method.
The equation for a point on a bound line in terms of the normalized parameter u and the line endpoints is
Unbound lines
Unbound lines are handled specially in the Revit API. Most curve properties cannot be used, however, Evaluate() and ComputeDerivatives() can be used to
obtain locations along the curve when a raw parameter is provided.
The equation for a point for an unbound line in terms of the raw parameter u and the line origin and normalized direction vector is
Arcs and Circles are represented in the Revit API by the Arc class. They are defined in terms of their radius, center and vector normal to the plane of the arc,
which are accessible in the Revit API directly from the Arc class as properties.
Circles have the IsBound property set to true. This means they can only be evaluated by using a raw parameter (range from 0 to 2), and the equation for a
point on the circle in terms of the raw parameter is
where the assumption is made that the circle lies in the XY plane.
Arcs begin and end at a certain angle. These angles can be obtained by the raw parameter values at each end of the arc, and angular values between these
values can be plugged into the same equation as above.
Cylindrical Helixes
Cylindrical helixes are represented in the Revit API by the CylindricalHelix class. They are defined in terms of the base point of the axis of the cylinder around
which the helix is wound, radius, x and y vectors, pitch, and start and end angles.
NurbSpline
NURBS (nonuniform rational B-splines) are used for spline segments sketched by the user as curves or portions of 3D object sketches. They are also used to
represent some types of imported geometry data.
The data for the NurbSpline include:
NurbSplines as used in Revits sketching tools can be generated from the control points and degree alone using an algorithm. The calculations performed by
Revits algorithm can be duplicated externally, see this sample below:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
prevKnot = knot;
HermiteSpline
Hermite splines are used for curves which are interpolated between a set of control points, like Curve by Points and flexible ducts and pipes in MEP. They are
also used to represent some types of imported geometry data. In the Revit API, the HermiteSpline class offers access to the arrays of points, tangent vectors
and parameters through the ControlPoints, Tangents, and Parameters properties.
The equation for the curve between two nodes in a Hermite spline is
where Pk and Pk+1 represent the points at each node, Mk and Mk+1 the tangent vectors, and uk and uk+1 the parameters at the nodes, and the basis functions are:
GeometryInstances
A GeometryInstance represents a set of geometry stored by Revit in a default configuration, and then transformed into the proper location as a result of the
properties of the element. The most common situation where GeometryInstances are encountered is in Family instances. Revit uses GeometryInstances to
allow it to store a single copy of the geometry for a given family and reuse it in multiple instances.
Note that not all Family instances will include GeometryInstances. When Revit needs to make a unique copy of the family geometry for a given instance
(because of the effect of local joins, intersections, and other factors related to the instance placement) no GeometryInstance will be encountered; instead the
Solid geometry will be found at the top level of the hierarchy.
A GeometryInstance offers the ability to read its geometry through the GetSymbolGeometry() and GetInstanceGeometry() methods. These methods return
another Autodesk.Revit.DB.GeometryElement which can be parsed just like the first level return.
GetSymbolGeometry() returns the geometry represented in the coordinate system of the family. Use this, for example, when you want a picture of the
generic table without regards to the orientation and placement location within the project. This is also the only overload which returns the actual Revit
geometry objects to you, and not copies. This is important because operations which use this geometry as input to creating other elements (for example,
dimensioning or placement of face-based families) require the reference to the original geometry.
GetInstanceGeometry() returns the geometry represented in the coordinate system of the project where the instance is placed. Use this, for example, when
you want a picture of the specific geometry of the instance in the project (for example, ensuring that tables are placed parallel to the walls of the room). This
always returns a copy of the element geometry, so while it would be suitable for implementation of an exporter or a geometric analysis tool, it would not be
appropriate to use this for the creation of other Revit elements referencing this geometry.
There are also overloads for both GetInstanceGeometry() and GetSymbolGeometry() that transform the geometry by any arbitrary coordinate system. These
methods always return copies similar to GetInstanceGeometry().
The GeometryInstance also stored a transformation from the symbol coordinate space to the instance coordinates. This transform is accessible as the
Transform property. It is also the transformation used when extracting a the copy of the geometry via GetInstanceGeometry(). For more details, refer to
Geometry.Transform.
2 family instances placed with different transforms - the same geometry will be acquired from both
Instances may be nested several levels deep for some families. If you encounter nested instances they may be parsed in a similar manner as the first level
instance.
Two samples are presented to explain how geometry of instances can be parsed.
In this sample, curves are extracted from the GeometryInstance method GetInstanceGeometry().
In this sample, the solids are obtained from an instance using GetSymbolGeometry(). The constituent points are then transformed into the project coordinate
system using the GeometryInstance.Transform.
Note
For more details about the retrieved geometry of family instances, refer to Example: Retrieving Geometry Data from a Beam.
Meshes
A mesh is a collection of triangular boundaries which collectively forms a 3D shape. Meshes are typically encountered inside Revit element geometry if those
elements were created from certain import operations and also are used in some native Revit elements such as TopographySurface. You can also obtain
Meshes as the result of calls to Face.Triangulate() for any given Revit face.
The following code sample illustrates how to get the geometry of a Revit face as a Mesh:
Note that the approximation tolerance used for Revit display purposes is used by the parameterless overload of the Triangulate() method (used above) when
constructing the Mesh. The overload of Triangulate() that takes a double allows a level of detail to be set between 0 (coarser) and 1 (finer).
Points
A point represents a visible coordinate in 3D space. These are typically encountered in mass family elements like ReferencePoint. The Point class provides read
access to its coordinates, and an ability to obtain a reference to the point for use as input to other functions.
PolyLines
A polyline is a collection of line segments defined by a set of coordinate points. These are typically encountered in imported geometry. The PolyLine class
offers the ability to read the coordinates:
Faces
Face analysis
Edge and face parameterization
Face types
Face Splitting
Mathematical representations of face types
Solid analysis
Solid and face creation
Edge direction
Direction is normally clockwise on the first face (first representing an arbitrary face which Revit has identified for a particular edge). But because two different
faces meet at one particular edge, and the edge has the same parametric direction regardless of which face you are concerned with, sometimes you need to
figure out the direction of the edge on a particular face.
The figure below illustrated how this works. For Face 0, the edges are all parameterized clockwise. For Face 1, the edge shared with Face 0 is not reparameterized; thus with respect to Face 1 the edge has a reversed direction, and some edges intersect where both edges parameters are 0 (or 1).
Edge parameterization
The API sample PanelEdgeLengthAngle shows how to recognize edges that are reversed for a given face. It uses the tangent vector at the edge endpoints to
calculate the angle between adjacent edges, and detect whether or not to flip the tangent vector at each intersection to calculate the proper angle.
PanelEdgeLengthAngle results
Faces
Faces in the Revit API can be described as mathematical functions of two input parameters u and v, where the location of the face at any given point in XYZ
space is a function of the parameters. The U and V directions are automatically determined based on the shape of the given face. Lines of constant U or V can
be represented as gridlines on the face, as shown in the example below:
You can use the UV parameters to evaluate a variety of properties of the face at any given location:
Whether the parameter is within the boundaries of the face, using Face.IsInside()
The XYZ location of the given face at the specified UV parameter value. This is returned from Face.Evaluate(). If you are also calling
ComputeDerivatives(), this is also the .Origin property of the Transform returned by that method.
The tangent vector of the given face in the U direction. This is the .BasisX property of the Transform returned by Face.ComputeDerivatives()
The tangent vector of the given face in the V direction. This is the .BasisY property of the Transform returned by Face.ComputeDerivatives().
The normal vector of the given face. This is the .BasisZ property of the Transform returned by Face.ComputeDerivatives().
Face analysis
There are several Face members which are tools suitable for use in geometric analysis.
Intersect()
The Intersect method computes the intersection between the face and a curve. It can be used in to identify:
Project()
The Project method projects a point on the input face, and returns information on the projection point, the distance to the face, and the nearest edge to the
projection point.
Triangulate()
The Triangulate method obtains a triangular mesh approximating the face. There are two overloads to this method. The parameterless method is similar to
Curve.Tessellate() in that the meshs points are accurate within the input tolerance used by Revit (slightly larger than 1/16). The second Triangulate method
accepts a level of detail as an argument ranging from 0 (coarse) to 1 (fine).
Face Splitting
A face may be split into regions by the Split Face command. The Face.HasRegions property will report if the face contains regions created with the Split Face
command, while the Face.GetRegions() method will return a list of faces, one for the main face of the object hosting the Split Face (such as wall of floor) and
one face for each Split Face region.
The FaceSplitter class represents an element that splits a face. The FaceSplitter.SplitElementId property provides the id of the element whose face is split by
this element. The FaceSplitter class can be used to filter and find these faces by type as shown below.
Face types
Revit uses a variety of curve types to represent face geometry in a document. These include:
Face type
Definition
Plane
PlanarFace
Cylinder
CylindricalFace
Cone
ConicalFace
RevolvedFace
Ruled surface
RuledFace
Hermite face
HermiteFace
Revolved face
Notes
Mathematical representations of all of the Revit face types can be found <<need link here>>.
PlanarFace
A plane defined by origin and unit vectors in U and V. Its parametric equation is
CylindricalFace
A face defined by extruding a circle along an axis. The Revit API provides the following properties:
ConicalFace
A face defined by rotation of a line about an axis. The Revit API provides the following properties:
RevolvedFace
A face defined by rotation of an arbitrary curve about an axis. The Revit API provides the following properties:
RuledFace
A ruled surface is created by sweeping a line between two profile curves or between a curve and a point. The Revit API provides the curve(s) and point(s) as
properties.
The parametric equation for this surface is:
if both curves are valid. If one of the curves is replaced with a point, the equations simplify to one of:
A ruled face with no curves and two points is degenerate and will not be returned.
HermiteFace
A cubic Hermite spline face. The Revit API provides:
The parametric representation of this surface, between nodes (u1, v1) and (u2, v2) is:
Where
And B is coefficient matrix obtained from the face properties at the interpolation points:
Solid analysis
Intersection between solid and curve
The method Solid.IntersectWithCurve() calculates the intersection between a closed volume solid and a curve. The SolidCurveIntersectionOptions class can
specify whether the results from the IntersectWithCurve() method will include curve segments inside the solid volume or outside. The curve segments inside
the solid will include curve segments coincident with the face(s) of the solid. Both the curve segments and the parameters of the segments are available in the
results.
The following example uses the IntersectWithCurve() method to calculate the length of rebar that lies within a column.
Transformed geometry
The method
GeometryElement.GetTransformed()
returns a copy of the input geometry element with a transformation applied. Because this geometry is a copy, its members cannot be used as input references
to other Revit elements, but it can be used geometric analysis and extraction.
Extrusion
Revolution
Sweep
Blend
SweptBlend
The resulting geometry is not added to the document as a part of any element. However, the created Solid can be used as inputs to other API functions,
including:
As the input face(s) to the methods in the Analysis Visualization framework (SpatialFieldManager.AddSpatialFieldPrimitive()) this allows the user to
visualize the created shape relative to other elements in the document
As the input solid to finding 3D elements by intersection
As one or more of the inputs to a Boolean operation
As a part of a geometric calculation (using, for example, Face.Project(), Face.Intersect(), or other Face, Solid, and Edge geometry methods)
The following example uses the GeometryCreationUtilities class to create cylindrical shapes based on a location and height. This might be used, for example, to
create volumes around the ends of a wall in order to find other walls within close proximity to the wall end points:
Boolean operations
The BooleanOperationsUtils class provides methods for combining a pair of solid geometry objects.
The ExecuteBooleanOperation() method takes a copy of the input solids and produces a new solid as a result. Its first argument can be any solid, either
obtained directly from a Revit element or created via another operation like GeometryCreationUtils.
The method ExecuteBooleanOperationModifyingOriginalSolid() performs the boolean operation directly on the first input solid. The first input must be a solid
which is not obtained directly from a Revit element. The property GeometryObject.IsElementGeometry can identify whether the solid is appropriate as input
for this method.
Options to both methods include the operations type: Union, Difference, or Intersect. The following example demonstrates how to get the intersection of two
solids and then find the volume.
The Transform OfPoint method implements the previous function. The following code is a sample of the same transformation process.
CreateReflection()
Reflect a specified plane.
Determinant
Transformation determinant.
HasReflection
This is a Boolean value that indicates whether the transformation produces a reflection.
Scale
A value that represents the transformation scale.
Inverse
An inverse transformation. Transformation matrix A is invertible if a transformation matrix B exists such that A*B = B*A = I (identity).
IsIdentity
Boolean value that indicates whether this transformation is an identity.
IsTranslation
Boolean value that indicates whether this transformation is a translation.
Geometry.Transform provides methods to perform basal matrix operations.
Multiply
Multiplies a transformation by a specified transformation and returns the result.
Operator* - Multiplies two specified transforms.
ScaleBasis
Scales the basis vectors and returns the result.
ScaleBasisAndOrigin
Scales the basis vectors and the transformation origin returns the result.
OfPoint
Applies the transformation to the point. The Origin property is used.
OfVector
Applies the transform to the vector. The Origin property is not used.
AlmostEqual
Compares two transformations. AlmostEqual is consistent with the computation mechanism and accuracy in the Revit core code. Additionally,
Equal and the == operator are not implemented in the Transform class.
The API provides several shortcuts to complete geometry transformation. The Transformed property in several geometry classes is used to
do the work, as shown in the following table.
Table 48: Transformed Methods
Class Name
Function Description
Curve.get_Transformed(Transform transform)
GeometryElement.GetTransformed(Transform transform)
Profile.get_Transformed(Transform transform)
Mesh.get_Transformed(Transform transform)
Note
The transformed method clones itself then returns the transformed cloned result.
In addition to these methods, the Instance class (which is the parent class for elements like family instances, link instances, and imported
CAD content) has two methods which provide the transform for a given Instance . The GetTransform() method obtains the basic transform
for the instance based on how the instance is placed, while GetTotalTransform() provides the transform modified with the true north
transform, for instances like import instances.
Reference
The Reference is very useful in element creation.
Dimension creation requires references.
The reference identifies a path within a geometric representation tree in a flexible manner.
The tree is used to view specific geometric representation creation.
The API exposes four types of references based on different Pick pointer types. They are retrieved from the API in different ways:
1. For Point - Curve.EndPointReference property
2. For Curve (Line, Arc, and etc.) - Curve.Reference property
3. For Face - Face.Reference property
4. For Cut Edge - Edge.Reference property
Different reference types cannot be used arbitrarily. For example:
The NewLineBoundaryConditions() method requires a reference for Line
The NewAreaBoundaryConditions() method requires a reference for Face
The NewPointBoundaryConditions() method requires a reference for Point.
The Reference.ConvertToStableRepresentation() method can be used to save a reference to a geometry object, for example a face, edge, or
curve, as a string, and later in the same Revit session (or even in a different session where the same document is present) use
ParseFromStableRepresentation() method to obtain an identical Reference using the string as input.
Options
Geometry is typically extracted from the indexed property Element.Geometry. The original geometry of a beam, column or brace, before the
instance is modified by
joins, cuts, coping, extensions, or other post-processing, can be extracted using the FamilyInstance.GetOriginalGeometry() method.
Both Element.Geometry and FamilyInstance.GetOriginalGeometry() accept an options class which you must supply. The options class
customizes the type of output you receive based on its properties:
ComputeReferences - Indicates whether to compute the geometry reference when retrieving geometry information. The default value
is false, so if this property is not set to true, the reference will not be accessible.
IncludeNonVisibleObjects - Indicates to also return geometry objects which are not visible in a default view.
View - Gets geometry information from a specific view. Note that if a view is assigned, the detail level for this view will be used in
place of "DetailLevel".
DetailLevel - Indicates the preferred detail level. The default is Medium.
ComputeReferences
If you set this property to false, the API does not compute a geometry reference. All Reference properties retrieved from the geometry tree
return nothing. For more details about references, refer to the Reference section. This option cannot be set to true when used with
FamilyInstance.GetOriginalGeometry().
IncludeNonVisibleObjects
Most of the non-visible geometry is construction and conditional geometry that the user sees when editing the element (i.e., the center plane
of a window family instance). The default for this property is false. However, some of this conditionally visible geometry represents realworld objects, such as insulation surrounding ducts in Revit MEP, and it should be extracted.
View
If users set the View property to a different view, the retrieved geometry information can be different. Review the following examples for
more information:
1. In Revit, draw a stair in 3D view then select the Crop Region, Crop Region Visible, and Section Box properties in the 3D view. In
the Crop Region, modify the section box in the 3D view to display a portion of the stair. If you get the geometry information for the
stair using the API and set the 3D view as the Options.View property, only a part of the stair geometry can be retrieved. The
following pictures show the stair in the Revit application (left) and one drawn with the API (right).
Draw a stair in Revit then draw a section as shown in the left picture. If you get the information for this stair using the API and set this
section view as the Options.View property, only a part of the stair geometry can be retrieved. The stair drawn with the API is shown in the
right picture.
The dash lines in the previous pictures show the section view boundary exposed as the CropBox property (a BoundingBoxXYZ instance).
The following table identifies the main uses for this class.
Table 49: BoundingBoxXYZ properties
Property Name
Usage
Max/Min
Maximum/Minimum coordinates. These two properties define a 3D box parallel to any coordinate axis. The Transform property
provides a transform matrix that can transform the box to the appropriate position.
Transform
Enabled
MaxEnabled/
MinEnabled
If the crop view is turned off, both MaxEnabled property and MinEnabled property return false.
This property indicates whether the view's crop box face can be used to clip the element's view.
If BoundingBoxXYZ is retrieved from the View3D.SectionBox property, the return value depends on whether the Section Box property is
selected in the 3D view Properties dialog box. If so, all Enabled properties return true.
If BoundingBoxXYZ is retrieved from the Element.BoundingBox property, all the Enabled properties are true.
Bounds
BoundEnabled
The following code sample illustrates how to rotate BoundingBoxXYZ to modify the 3D view section box.
BoundingBoxUV
BoundingBoxUV is a value class that defines a 2D rectangle parallel to the coordinate axes. It supports the Min and Max data members.
Together they define the BoundingBoxUV's boundary. BoundingBoxUV is retrieved from the View.Outline property which is the boundary
view in the paper space view.
Collection Classes
The API provides the following collection classes based on the items they contain:
Table 50: Geometry Collection Classes
Class/Type
Corresponding Iterators
Edge
EdgeArray,
EdgeArrayIterator,
EdgeArrayArray
EdgeArrayArrayIterator
Face
FaceArray
FaceArrayIterator
GeometryObject
GeometryObjectArray
GeometryObjectArrayIterator
Instance
InstanceArray
InstanceArrayIterator
Mesh
MeshArray
MeshArrayIterator
Reference
ReferenceArray
ReferenceArrayIterator
Solid
SolidArray
SolidArrayIterator
Double value
DoubleArray
DoubleArrayIterator
All of these classes use very similar methods and properties to do similar work. For more details, refer to Collection.
33.
34.
35.
36.
37.
38. }
The above example uses the FamilyInstance.Geometry property to access the true geometry of the beam. To obtain the original geometry
of a family instance before it is modified by joins, cuts, coping, extensions, or other post-processing, use the
FamilyInstance.GetOriginalGeometry() method.
Note For more information about how to retrieve the Geometry.Options type object, refer to Geometry.Options.
The GetExtrusionBase() method returns the calculated base profile of the extruded solid aligned to the input plane.
The CalculateFaceAlignment() method can be used to identify all faces from the original geometry which do and do not align with the faces of the
calculated extrusion. This could be useful to figure out if a wall, for example, has a slanted join at the top as would be the case if there is a join with a
roof. If a face is unaligned, something is joined to the geometry that is affecting it.
To determine the element that produced the non-aligned face, pass the face to Element.GetGeneratingElementIds(). For more details on this utility,
see the following section.
The ExtrusionAnalyzer utility works best for geometry which are at least somewhat extrusion-like, for example, the geometry of a wall which may or may not
be affected by end joins, floor joins, roof joins, openings cut by windows and doors, or other modifications. Rarely for specific shape and directional
combinations the analyzer may be unable to determine a coherent face to act as the base of the extrusion an InvalidOperationException will be thrown in
these situations.
In this example, the extrusion analyzer is used to calculate and outline a shadow formed from the input solid and the sun direction.
Code Region: Use Extrusion Analyzer to calculate and draw a shadow outline.
1. /// <summary>
2. /// Draw the shadow of the indicated solid with the sun direction specified.
3. /// </summary>
4. /// <remarks>The shadow will be outlined with model curves added to the document.
5. /// A transaction must be open in the document.</remarks>
6. /// <param name="document">The document.</param>
7. /// <param name="solid">The target solid.</param>
8. /// <param name="targetLevel">The target level where to measure and
9. /// draw the shadow.</param>
10. /// <param name="sunDirection">The direction from the sun (or light source).</param>
11. /// <returns>The curves created for the shadow.</returns>
12. /// <throws cref="Autodesk.Revit.Exceptions.InvalidOperationException">
13. /// Thrown by ExtrusionAnalyzer when the geometry and
14. /// direction combined do not permit a successful analysis.</throws>
15. private static ICollection<ElementId> DrawShadow(Document document, Solid solid,
16.
Level targetLevel, XYZ sunDirection)
17. {
18.
// Create target plane from level.
19.
Plane plane = document.Application.Create.NewPlane(XYZ.BasisZ,
20.
new XYZ(0, 0, targetLevel.ProjectElevation));
21.
22.
// Create extrusion analyzer.
23.
ExtrusionAnalyzer analyzer = ExtrusionAnalyzer.Create(solid, plane, sunDirection);
24.
25.
// Get the resulting face at the base of the calculated extrusion.
26.
Face result = analyzer.GetExtrusionBase();
27.
28.
// Convert edges of the face to curves.
29.
CurveArray curves = document.Application.Create.NewCurveArray();
30.
foreach (EdgeArray edgeLoop in result.EdgeLoops)
31.
{
32.
foreach (Edge edge in edgeLoop)
33.
{
34.
curves.Append(edge.AsCurve());
35.
}
Code Region: Use Extrusion Analyzer to calculate and draw a shadow outline.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61. }
Autodesk.Revit.Creation.ItemFactoryBase itemFactory;
if (document.IsFamilyDocument)
itemFactory = document.FamilyCreate;
else
itemFactory = document.Create;
SketchPlane sketchPlane =
itemFactory.NewSketchPlane(document.Application.Create.NewPlane(curves));
document.Regenerate();
The utility above above can be used to compute the shadow of a given mass with respect to the current sun and shadows settings for the view:
This class allows an application to use Revits picking tools to find elements and geometry. This class uses a ray from a point in a specified direction to find the
geometry that is hit by the ray.
The class intersects 3D geometry only and requires a 3D view on creation. It is possible to use a 3D view which has been cut by a section box, or which has
view-specific geometry and graphics options set, to find intersections which would not be found in the uncut and uncropped 3D model.
The ReferenceIntersector class supports filtering the output based on element or reference type. The output can be customized based on which constructor is
used or by using methods and properties of the class prior to calling a method to perform the ray projection.
Description
ReferenceIntersector(View3D)
Constructs a ReferenceIntersector which is set to return intersections from all elements and
representing all reference target types.
ReferenceIntersector(ElementFilter, FindReferenceTarget,
View3D)
ReferenceIntersector(ICollection<ElementId>,
FindReferenceTarget, View3D)
The FindReferenceTarget enumeration includes the options: Element, Mesh, Edge, Curve, Face or All.
There are two methods to project a ray, both of which take as input the origin of the ray and its direction. The Find() method returns a collection of
ReferenceWithContext objects which match the ReferenceIntersectors criteria. This object contains the intersected reference, which can be both the elements
and geometric references which intersect the ray. Some element references returned will have a corresponding geometric object which is also intersected (for
example, rays passing through openings in walls will intersect the wall and the opening element). If interested only in true physical intersections an application
should discard all references whose Reference is of type Element.
The FindNearest() method behaves similarly to the Find() method, but only returns the intersected reference nearest to the ray origin.
The ReferenceWithContext return includes a proximity parameter. This is the distance between the origin of the ray and the intersection point. An application
can use this distance to exclude items too far from the origin for a particular geometric analysis. An application can also use this distance to take on some
interesting problems involving analyzing the in place geometry of the model.
Notes:
This method finds both References will be found and returned only for elements that are in front of the ray.
This method will not return intersections in linked files.
This method will not return intersections with elements which are not in the active design option.
Measure distances
This class could also be used to measure the vertical distance from a skylight to the nearest floor.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80. }
if (skylight == null)
{
message = "Please select one skylight.";
return Result.Cancelled;
}
// Calculate the height
Line line = CalculateLineAboveFloor(doc, skylight);
// Create a model curve to show the distance
Plane plane = revit.Application.Application.Create.NewPlane(new XYZ(1, 0, 0), line.GetEndPoint(0));
SketchPlane sketchPlane = SketchPlane.Create(doc, plane);
ModelCurve curve = doc.Create.NewModelCurve(line, sketchPlane);
// Show a message with the length value
TaskDialog.Show("Distance", "Distance to floor: " + String.Format("{0:f2}", line.Length));
}
return Result.Succeeded;
/// <summary>
/// Determines the line segment that connects the skylight to the nearest floor.
/// </summary>
/// <returns>The line segment.</returns>
private Line CalculateLineAboveFloor(Document doc, FamilyInstance skylight)
{
// Find a 3D view to use for the ReferenceIntersector constructor
FilteredElementCollector collector = new FilteredElementCollector(doc);
Func<View3D, bool> isNotTemplate = v3 => !(v3.IsTemplate);
View3D view3D = collector.OfClass(typeof(View3D)).Cast<View3D>().First<View3D>(isNotTemplate);
// Use the center of the skylight bounding box as the start point.
BoundingBoxXYZ box = skylight.get_BoundingBox(view3D);
XYZ center = box.Min.Add(box.Max).Multiply(0.5);
// Project in the negative Z direction down to the floor.
XYZ rayDirection = new XYZ(0, 0, -1);
ElementClassFilter filter = new ElementClassFilter(typeof(Floor));
ReferenceIntersector refIntersector = new ReferenceIntersector(filter, FindReferenceTarget.Face, view3D);
ReferenceWithContext referenceWithContext = refIntersector.FindNearest(center, rayDirection);
Reference reference = referenceWithContext.GetReference();
XYZ intersection = reference.GlobalPoint;
// Create line segment from the start point and intersection point.
Line result = Line.CreateBound(center, intersection);
return result;
Ray bouncing/analysis
The references returned by ReferenceIntersector.Find() include the intersection point on the geometry. Knowing the intersection point on the face, the faces
material, and the ray direction allows an application to analyze reflection and refraction within the building. The following image demonstrates the use of the
intersection point to reflect rays intersected by model elements; model curves were added to represent the path of each ray.
Find intersections/collisions
Another use of the ReferenceIntersector class would be to detect intersections (such as beams or pipes) which intersect/interference with the centerline of a
given beam or pipe.
The HostObjectUtils class offers methods as a shortcut to locate certain faces of compound HostObjects. These utilities retrieve the faces which act as the
boundaries of the object's CompoundStructure:
HostObjectUtils.GetSideFaces() applicable to Walls and FaceWalls; you can obtain either the exterior or interior finish faces.
HostObjectUtils.GetTopFaces() and HostObjectUtils.GetBottomFaces() applicable to roofs, floors, and ceilings.
SolidUtils
SolidUtils.SplitVolumes() - takes a solid which includes disjoint enclosed volumes and returns newly created Solid objects representing each volume. If
no splitting is necessary, the input solid is returned.
SolidUtils.TessellateSolidOrShell() - triangulates a given input Solid (which can be one or more fully closed volumes, or an open shell). Returns a
TriangulatedSolidOrShell object which allows access to the stored triangulated boundary component of a solid or a triangulated connected component
of a shell.
JoinGeometryUtils
The JoinGeometryUtils class contains methods for joining and unjoining elements, and for managing the order in which elements are joined. These utilities are
not available for family documents.
FacetingUtils
This class is used to convert a triangulated structure into a structure in which some of the triangles have been consolidated into quadrilaterals.
FacetingUtils.ConvertTrianglesToQuads() - this method takes a TriangulationInterface (constructed from a TriangulatedSolidOrShell) as input and
returns a collection of triangles and quadrilaterals representing the original triangulated object.
SpatialElementBoundaryLocation whether to use finish faces or boundary element centerlines for calculation
StoredFreeBoundaryFaces whether to include faces which dont map directly to a boundary element in the results.
The results of calculating the geometry are contained in the class SpatialElementGeometryResults. From the SpatialElementGeometryResults class, you can
obtain:
The calculator maintains an internal cache for geometry it has already processed. If you intend to calculate geometry for several elements in the same
project you should use a single instance of this class. Note that the cache will be cleared when any change is made to the document.
Floors are almost never included in as boundary elements. Revit uses the 2D outline of the room to form the bottom faces and does not match them to
floor geometry.
Openings created by wall-cutting features such as doors and windows are not included in the returned faces.
The geometry calculations match the capabilities offered by Revit. In some cases where Revit makes assumptions about how to calculate the volumes
of boundaries of rooms and spaces, these assumptions will be present in the output of the utility.
The following example calculates a room's geometry and finds its boundary faces
The following example calculates a room's geometry and finds its the material of faces that belong to the elements that define the room.
Sketching
To create elements or edit their profiles in Revit, you must first create sketch objects. Examples of elements that require sketches include:
Roofs
Floors
Stairs
Railings.
Sketches are also required to define other types of geometry, such as:
Extrusions
Openings
Regions
In the Revit Platform API, sketch functions are represented by 2D and 3D sketch classes such as the following:
2D sketch:
o
SketchPlane
Sketch
ModelCurve
and more
3D sketch:
o
GenericForm
Path3D
In addition to Sketch Elements, ModelCurve is also described in this chapter. For more details about Element Classification, see Elements
Classification in the Elements Essential section.
When you specify a new work plane, you can select Pick a plane as illustrated in the previous picture. After you pick a plane, select a plane
on a particular element such as a wall as the following picture shows. In this case, the SketchPlane.Name property returns a string related to
that element. For example, in the following picture, the SketchPlane.Name property returns 'Generic - 8' the same as the Wall.Name
property.
current API, but is represented by the Element class. A work plane must be defined based on a specific SketchPlane. Both the work plane
and SketchPlane Category property return null. Although SketchPlane is always invisible, there is always a SketchPlane that corresponds to a
work plane. A work plane is used to express a SketchPlane in text and pictures.
The following information applies to SketchPlane members:
ID, UniqueId, Name, and Plane properties return a value;
Parameters property is empty
Location property returns a Location object
Other properties return null.
Plane contains the SketchPlane geometric information. SketchPlane sets up a plane coordinate system with Plane as the following picture
illustrates:
3D Sketch
3D Sketch is used to edit a family or create a 3D object. In the Revit Platform API, you can complete the 3D Sketch using the following
classes.
Extrusion
Revolution
Blend
Sweep
In other words, there are four operations through which a 2D model turns into a 3D model. For more details about sketching in 2D, refer to
2D Sketch.
Extrusion
Revit uses extrusions to define 3D geometry for families. You create an extrusion by defining a 2D sketch on a plane; Revit then extrudes
the sketch between a start and an end point.
Query the Extrusion Form object for a generic form to use in family modeling and massing. The Extrusion class has the following properties:
Table 40: Extrusion Properties
Property
Description
ExtrusionStart
ExtrusionEnd
Sketch
Returns the Extrusion Sketch. It contains a sketch plane and some curves.
The value of the ExtrusionStart and ExtrusionEnd properties is consistent with the parameters in the Revit UI. The following figure illustrates
the corresponding parameters and the Extrusion result.
Description
Axis
EndAngle
Sketch
EndAngle is consistent with the same parameter in the Revit UI. The following pictures illustrate the Revolution corresponding parameter,
the sketch, and the result.
The Start Angle is not accessible using the Revit Platform API.
If the End Angle is positive, the Rotation direction is clockwise. If it is negative, the Rotation direction is counterclockwise
Blend
The Blend command blends two profiles together. For example, if you sketch a large rectangle and a smaller rectangle on top of it, Revit
Architecture blends the two shapes together.
Query the Blend Form object for a generic form to use in family modeling and massing. The Blend class has the following properties:
Table 42: Blend Properties
Property
Description
BottomSketch
TopSketch
FirstEnd
SecondEnd
The FirstEnd and SecondEnd property values are consistent with the same parameters in the Revit UI. The following pictures illustrate the
Blend corresponding parameters, the sketches, and the result.
Description
Path3d
PathSketch
ProfileSketch
EnableTrajSegmentation
MaxSegmentAngle
Creating a 2D Path is similar to other forms. The 3D Path is fetched by picking the created 3D curves.
The Path3d property is available only when you use Pick Path to get the 3D path.
PathSketch is available whether the path is 3D or 2D.
Segmented sweeps are useful for creating mechanical duct work elbows. Create a segmented sweep by setting two sweep parameters and
sketching a path with arcs.
ModelCurve
ModelCurve represents model lines in the project. It exists in 3D space and is visible in all views.
The following pictures illustrate the four ModelCurve derived classes:
Creating a ModelCurve
The key to creating a ModelCurve is to create the Geometry.Curve and SketchPlane where the Curve is located. Based on the
Geometry.Curve type you input, the corresponding ModelCurve returned can be downcast to its correct type.
The following sample illustrates how to create a new model curve (ModelLine and ModelArc):
GeometryCurve
The GeometryCurve property is used to get or set the model curve's geometry curve. Except for ModelHermiteSpline, you can get different
Geometry.Curves from the four ModelCurves;
Line
Arc
Ellipse
Nurbspline.
The following code sample illustrates how to get a specific Curve from a ModelCurve.
if (geoCurve is Autodesk.Revit.DB.Line)
{
}
The GeometryCurve property return value is a general Geometry.Curve object, therefore, you must use an As operator to convert the object
type.
NoteThe following information applies to GeometryCurve:
In Revit you cannot create a Hermite curve but you can import it from other software such as AutoCAD. Geometry.Curve is the only
geometry class that represents the Hermite curve.
The SetPlaneAndCurve() method and the Curve and SketchPlane property setters are used in different situations.
o
When the new Curve lies in the same SketchPlane, or the new SketchPlane lies on the same planar face with the old
SketchPlane, use the Curve or SketchPlane property setters.
If new Curve does not lay in the same SketchPlane, or the new SketchPlane does not lay on the same planar face with the
old SketchPlane, you must simultaneously change the Curve value and the SketchPlane value using SetPlaneAndCurve() to
avoid internal data inconsistency.
Line Styles
Line styles are represented by the GraphicsStyle class. All line styles for a ModelCurve are available from the GetLineStyleIds() method
which returns a set of ElementIds of GraphicsStyle elements.
Material
In the Revit Platform API, material data is stored and managed as an Element. Just as in the Revit UI, a material can have several assets associated with it, but
only thermal and structural (referred to as Physical in the Revit UI) assets can be assigned using the API.
Some material features are represented by properties on the Material class itself, such as FillPattern, Color, or Render while others are available as properties
of either a structural or thermal asset associated with the material.
In this chapter, you learn how to access material elements and how to manage the Material objects in the document. Walkthrough: Get Materials of a Window
provides a walkthrough showing how to get a window material.
Classification
The material classification relevant to structural analysis (i.e. steel, concrete, wood) can be obtained from the StructuralAssetClass property
of the StructuralAsset associated with the material.
Note: The API does not provide access to the values of Concrete Type for Concrete material.
The material classification relevant to energy analysis (i.e. solid, liquid, gas) can be obtained from the ThermalMaterialType property of the
ThermalAsset associated with the material.
Other Properties
The material object properties identify a specific type of material including color, fill pattern, and more.
Properties and Parameter
Some Material properties are only available as a Parameter. A few, such as Color, are available as a property or as a Parameter using the
BuiltInParameter MATERIAL_PARAM_COLOR.
Rendering Information
Collections of rendering data are organized into objects called Assets, which are read-only. You can obtain all available Appearance-related
assets from the Application.Assets property. An appearance asset can be accessed from a material via the Material.RenderAppearance
property.
The following figure shows the Appearance Library section of the Asset Browser dialog box, which shows how some rendering assets are
displayed in the UI.
Material Management
You can use filtering to retrieve all materials in the document. Every Material object in the Document is identified by a unique name.
The following example illustrates how to use the material name to get material.
Note To run the sample code, make sure the material name exists in your document. All material names for the current document are located under the
Materials).
Creating Materials
There are two ways to create a new Material object in the API.
Duplicate an existing Material
Add a new Material.
When using the Duplicate() method, the returned Material object is the same type as the original.
Use the static method Material.Create() to add a new Material directly. No matter how it is applied, it is necessary to specify a unique name
for the material and any assets belonging to the material. The unique name is the Material object key.
Element Material
One element can have several elements and components. For example, FamilyInstance has SubComponents and Wall has
CompoundStructure which contain several CompoundStructureLayers. (For more details about SubComponents refer to the Family Instances
section and refer to Walls, Floors, Roofs and Openings for more information about CompoundStructure.)
In the Revit Platform API, get an element's materials using the following guidelines:
If the element contains elements, get the materials separately.
If the element contains components, get the material for each component from the parameters or in specific way (see Material
section in Walls, Floors, Roofs and Openings).
If the component's material returns null, get the material from the corresponding Element.Category sub Category.
Material in a Parameter
If the Element object has a Parameter where ParameterType is ParameterType.Material, you can get the element material from the
Parameter. For example, a structural column FamilySymbol (a FamilyInstance whose Category is BuiltInCategory.OST_StructuralColumns)
has the Structural Material parameter. Get the Material using the ElementId. The following code example illustrates how to get the structural
column Material that has one component.
Note If the material property is set to By Category in the UI, the ElementId for the material is ElementId.InvalidElementId and cannot be
used to retrieve the Material object as shown in the sample code. Try retrieving the Material from Category as described in the next section.
Some material properties contained in other compound parameters are not accessible from the API. As an example, in the following figure,
for System Family: Railing, the Rail Structure parameter's StorageType is StorageType.None. As a result, you cannot get material
information in this situation.
HostObject with CompoundStructure - Get the Material object from the CompoundStructureLayer class MaterialId property.
When you get a null Material object or an invalid ElementId with a value of ElementId.InvalidElementId, try the Material from the
corresponding category. Note that a FamilyInstance and its FamilySymbol usually have the same category.
The more you know about the Element object, the easier it is to get the material. For example:
o
If you know the Element is a beam, you can get the instance parameter Structural Material
If you know the element is a window, you can cast it to a FamilyInstance and get the FamilySymbol.
After that you can get the Parameters such as Frame Exterior Material or Frame Interior Material to get the Material object. If you get
null try to get the Material object from the FamilySymbol Category.
Not all Element Materials are available in the API.
Walkthrough: Get Window Materials
The following code illustrates how to get the Window Materials.
Material quantities
There are methods to directly obtain the material volumes and areas computed by Revit for material takeoff schedules:
The methods apply to categories of elements where Category.HasMaterialQuantities property is true. In practice, this is limited to elements that use
compound structure, like walls, roofs, floors, ceilings, a few other basic 3D elements like stairs, plus 3D families where materials can be assigned to geometry of
the family, like windows, doors, columns, MEP equipment and fixtures, and generic model families. Note that within these categories there are further
restrictions about how material quantities can be extracted. For example, curtain walls and curtain roofs will not report any material quantities themselves; the
materials used by these constructs can be extracted from the individual panel elements that make up the curtain system.
Note that the volumes and areas computed by Revit may be approximate in some cases. For example, for individual layers within a wall, minor discrepancies
might appear between the volumes visible in the model and those shown in the material takeoff schedule. These discrepancies tend to occur when you use the
wall sweep tool to add a sweep or a reveal to a wall, or under certain join conditions.
The SDK sample MaterialQuantities combines both the material quantity extraction tools and temporary suppression of cutting elements (opening, windows,
and doors) to extract both gross and net material quantities.
Classes in the Revit API in the Autodesk.Revit.DB.Architecture namespace allow access to stairs and related components such as landings and runs. Stairs can
be created or modified using the Revit API. The Stairs class represents stairs created "by component". Stair elements that were created by sketch cannot be
accessed as a Stair object in the API. The static method Stairs.IsByComponent() can be used to determine if an ElementId represents stairs that were created by
component.
As with other types of elements in the Revit document, a Transaction is necessary to edit stairs and stairs components. However, to create new components
such as runs and landings, or to create new stairs themselves, it is necessary to use an Autodesk.Revit.DB.StairsEditScope object which maintains a stairsediting session.
StairsEditScope acts like a TransactionGroup. After a StairsEditScope is started, you can start transactions and edit the stairs. Individual transactions created
inside StairsEditScope will not appear in the undo menu. All transactions committed during the edit mode will be merged into a single one which will bear the
name passed into the StairsEditScope constructor.
StairsEditScope has two Start methods. One takes the ElementId for an existing Stairs object for which it starts a stairs-editing session. The second Start
method takes the ElementIds for base and top levels and creates a new empty stairs element with a default stairs type in the specified levels and then starts a
stairs edit mode for the new stairs.
After runs and landings have been added to the Stairs and editing is complete, call StairsEditScope.Commit() to end the stairs-editing session.
Adding Runs
The StairsRun class has three static methods for creating new runs for a Stairs object:
CreateSketchedRun - Creates a sketched run by providing a group of boundary curves and riser curves.
CreateStraightRun - Creates a straight run.
CreateSpiralRun - Creates a spiral run by providing the center, start angle and included angle.
Adding Landings
Either automatic or sketched landings can be added between two runs. The static method StairsLanding.CanCreateAutomaticLanding() will check whether two
stairs runs meet restriction to create automatic landing(s). The static StairsLanding.CreateAutomaticLanding() method will return the Ids of all landings created
between the two stairs runs.
The static StairsLanding.CreateSketchedLanding method creates a customized landing between two runs by providing the closed boundary curves of the
landing. One of the inputs to the CreateSketchedLanding method is a double value for the base elevation. The elevation has following restriction:
Example
The following example creates a new Stairs object, two runs (one sketched, one straight) and a landing between them.
58.
59.
);
60.
61.
62.
63.
64.
65. }
landingLoop.Append(curve_4);
StairsLanding newLanding = StairsLanding.CreateSketchedLanding(document, newStairsId, landingLoop, newRun1.TopElevation
stairsTrans.Commit();
newStairsScope.Commit();
return newStairsId;
Railings
The Autodesk.Revit.DB.Architecture.Railing class represents a railing element in an Autodesk Revit project. Although railings are associated with stairs, they
can be associated with another host, such as a floor, or placed in space. Railings can be continuous or non-continuous. If they are non-continuous, only a
limited level of access is provided.
Railings associated with stairs can be retrieved from the Stairs class with the GetAssociatedRailings() method. There are only a few properties and methods
specific to railings such as the TopRail property which returns the ElementId of the top rail and Flipped which indicates if the Railing is flipped. The Railing.Flip()
method flips the railing, while the RemoveHost() method will remove the association between the railing and its host.
The following example retrieves all of the railings associated with a Stairs object and flips each railing that is the default railing that the system generates.
The Railing class has a Create method which automatically creates new railings with the specified railing type on all sides of a stairs element. Railing creation is
demonstrated in the Creating and Editing Stairs section.
The RailingType class represents the railing type used in the generation of a railing. It contains a number of properties about the railing, such as the height,
lateral offset and type of the primary and secondary handrails as well as the top rail.
Adding Railings
When new stairs are created using the StairsEditScope.Start(ElementId, ElementId) method, they have default railings associated with them. However, the
Railing.Create() method can be used to create new railings with the specified railing type on all sides of a stairs element for stairs without railings. Unlike run
and landing creation which require the use of StairsEditScope, railing creation cannot be performed inside an open stairs editing session.
Since railings cannot be created for Stairs that already have railings associated with them, the following example deletes the existing railings associated with a
Stairs object before creating new railings.
Stairs Annotations
The StairsPath class can be used to annotate the slope direction and walk line of a stair. The static StairsPath.Create() method will create a new stairs path for
the specified stairs with the specified stairs path type in a specific plan view in which the stairs must be visible.
The StairsPath class has the same properties that are available in the Properties window when editing a stairs path in the Revit UI, such as properties to set the
up and down text along or whether the text should be shown at all. Additionally offsets for the up and down text can be specified as can an offset for the stairs
path from the stairs centerline.
The following example finds a StairsPathType and a FloorPlan in the project and uses them to create a new StairsPath for a given Stairs.
A StairsPath has a StairsPathType. Stair path types are available from 2 predefined system families: Automatic Up/Down Direction and Fixed Up Direction. The
properties available for these two types are available as properties in the StairsPathType class, such as FullStepArrow and DistanceToCutMark.
The CutMarkType class represents a cut mark type in the Revit UI and it has properties to represent the same properties available when editing a cut mark type
in the UI, such as CutLineAngle and CutLineExtension . It is associated with a StairsType object and can be retrieved using the BuiltInParameter
STAIRSTYPE_CUTMARK_TYPE as shown below.
Stairs Components
The Stairs class represents a stairs element in Revit and contains properties that represent information about the treads, risers, number of stories, as well as
the height of the stairs and base and top elevation. Methods of the Stairs class can be used to get the stairs landing components, stairs run components and
stairs supports.
The following example finds all of the Stairs that are by component and outputs some information on each of the Stairs to a Task Dialog. Note that this
example uses a category filter with the BuiltInCategory.OST_Stairs which will return ElementIds for all stairs, therefore requiring a test to see if each ElementId
represents a Stairs By Component before being cast to a Stairs class when retrieved from the document.
The StairsType class represents the type for a Stairs element. It contains information about the Stairs, such as the type of all runs and landings in the stairs
object, types and offsets for supports on the left, right and middle of the stairs, and numerous other properties related to stair generation such as the
maximum height of each riser on the stair element. The following example gets the StairsType for a Stairs element and displays some information about it in a
TaskDialog.
Runs
Stairs by component are composed of runs, landings and supports. Each of these items can be retrieved from the Stairs class. A run is represented in the Revit
API by the StairsRun class. The following example gets each run for a Stairs object and makes sure that it begins and ends with a riser.
7.
8.
9.
10.
11.
12.
13.
14. }
The StairsRun class provides access to run properties such as the StairsRunStyle (straight, winder, etc.), BaseElevation, TopElevation, and properties about the
risers. There are also methods in the StairsRun class to access the supports hosted by the run, either all, or just those on the left or right side of the run
boundaries. The GetStairsPath() method will return the curves representing the stairs path on the run, which are projected onto the base level of the stairs.
The GetFootprintBoundary() method returns the run's boundary curves which are also projected onto the stairs' base level.
There are three static methods of the StairsRun class for creating new runs. These are covered in the Creating and Editing Stairs section.
The StairsRunType class represents the type of a StairsRun. It contains many properties about the treads and risers of the run as well as other information
about the run. The following example gets the StairsRunType for the first run in a Stairs element and displays the riser and tread thicknesses along with the
type's name.
Landings
Landings are represented by the StairsLanding class. The following example finds the thickness for each landing of a Stairs object.
Similar to StairsRun, StairsLanding has a GetStairsPath() method which returns the curves representing the stairs path on the landing projected onto the base
level of the stairs and a GetFootprintBoundary() method which returns the landing's boundary curves, also projected onto the stairs' base level. Also similar to
StairsRun, there is a method to get all of the supports hosted by the landing.
The StairsLanding class has a method to create a new landing between two runs. It is covered in the Creating and Editing Stairs section.
The StairsLandingType class represents a landing type in the Revit API. The StairsLandingType class has only a couple of properties specific to it, namely
IsMonolithic which is true if the stairs landing is monolithic, and Thickness, representing the thickness of the stairs landing.
StairsComponentConnection
Both StairsRun and StairsLanding have a GetConnections() method which provides information about connections among stairs components (run to run, or run
to landing). The method returns a collection of StairsComponentConnection objects which have properties about each connection, including the connection
type (to a landing, the start of a stairs run, or the end of a stairs run) and the Id of the connected stairs component.
Supports
The Revit API does not expose a class for stairs supports. When getting the supports for Stairs, StairsRun, or a StairsLanding, the supports will be generic Revit
Elements. The following example gets the names of all the supports for a Stairs object.
Discipline-Specific Functionality
Revit Architecture
This chapter covers API functionality that is specific to Revit Architecture, namely:
Functionality related to rooms (Element.Room, RoomTag, etc.)
Rooms
The following sections cover information about the room class, its parameters, and how to use the room class in the API.
Room, Area, and Tags
The Room class is used to represent rooms and elements such as room schedule and area plans. The properties and create function for
different rooms, areas, and their corresponding tags in the API are listed in the following table:
Table 55: Room, Area, and Tags relationship
Element
Class
Category
Boundary
Location
Can Create
Room
OST_Rooms
LocationPoint
Room
OST_Rooms
Null
Null
NewRoom(Phase)
Area
Room
OST_Areas
Always has
LocationPoint
No
Room Tag
RoomTag
OST_RoomTags
LocationPoint
Creation.Document.NewRoomTag()
Area Tag
FamilySymbol
OST_AreaTags
LocationPoint
No
Note
Room.Name is the combination of the room name and room number. Use the ROOM_NAME BuiltInParameter to get the room name. In the
following picture, the Room.Name returns "Master Bedroom 2".
Creating a room
The following code illustrates the simplest way to create a room at a certain point in a specific level:
Rooms can be created in a room schedule then inserted into a plan circuit.
The Document.NewRoom(Phase) method is used to create a new room, not associated with any specific location, and insert it into an
existing schedule. Make sure the room schedule exists or create a room schedule in the specified phase before you make the call.
The Document.NewRoom(Room room, PlanCircuit circuit) method is used to create a room from a room in a schedule and a
PlanCircuit.
o
The input room must exist only in the room schedule, meaning that it does not display in any plan view.
After invoking the method, a model room with the same name and number is created in the view where the PlanCircuit is
located.
Code Region 28-2: Creating and inserting a room into a plan circuit
1. Room InsertNewRoomInPlanCircuit(Autodesk.Revit.DB.Document document, Level level, Phase newConstructionPhase)
2. {
3.
// create room using Phase
4.
Room newScheduleRoom = document.Create.NewRoom(newConstructionPhase);
5.
6.
// set the Room Number and Name
7.
string newRoomNumber = "101";
8.
string newRoomName = "Class Room 1";
9.
newScheduleRoom.Name = newRoomName;
10.
newScheduleRoom.Number = newRoomNumber;
11.
12.
// Get a PlanCircuit
13.
PlanCircuit planCircuit = null;
14.
// first get the plan topology for given level
15.
PlanTopology planTopology = document.get_PlanTopology(level);
16.
17.
// Iterate circuits in this plan topology
18.
foreach (PlanCircuit circuit in planTopology.Circuits)
19.
{
20.
// get the first circuit we find
21.
if (null != circuit)
22.
{
23.
planCircuit = circuit;
24.
break;
25.
}
26.
}
27.
28.
Room newRoom2 = null;
29.
Transaction transaction = new Transaction(document, "Create Room");
30.
if (transaction.Start() == TransactionStatus.Started)
31.
{
32.
// The input room must exist only in the room schedule,
33.
// meaning that it does not display in any plan view.
34.
newRoom2 = document.Create.NewRoom(newScheduleRoom, planCircuit);
35.
// a model room with the same name and number is created in the
36.
// view where the PlanCircuit is located
37.
if (null != newRoom2)
38.
{
39.
// Give the user some information
40.
TaskDialog.Show("Revit", "Room placed in Plan Circuit successfully.");
41.
}
42.
transaction.Commit();
43.
}
44.
45.
return newRoom2;
46. }
Once a room has been created and added to a location, it can be removed from the location (but still remains in available in the project) by
using the Room.Unplace() method. It can then be placed in a new location.
Room Boundary
Rooms have boundaries that create an enclosed region where the room is located.
Boundaries include the following elements:
o
Walls
Model lines
Columns
Roofs
Room.GetBoundarySegments().Size
Room 1
Room 2
Room 3
Room 4
Room 5
Room 6
Note
Walls joined by model lines are considered continuous line segments. Single model lines are ignored.
After getting IList<IList<BoundarySegment>>, get the BoundarySegment by iterating the list.
BoundarySegment
The segments that make the region are represented by the BoundarySegment class; its Element property returns the corresponding element
with the following conditions:
For a ModelCurve element, the category must be BuiltInCategory.OST_AreaSeparationLines meaning that it represents a Room
Separator.
For other elements such as wall, column, and roof, if the element is a room boundary, the Room Bounding parameter
(BuiltInParameter.WALL_ATTR_ROOM_BOUNDING) must be true as in the following picture.
Notice how the roof forms the BoundarySegment for a room in the following pictures. The first picture shows Level 3 in the elevation view.
The room is created in the Level 3 floor view. The latter two pictures show the boundary of the room and the house in 3D view.
The area boundary can only be a ModelCurve with the category Area Boundary (BuiltInCategory.OST_AreaSchemeLines) while the boundary
of the displayed room can be walls and other elements.
To update the room boundary data, use the transaction mechanism in the following code:
Circuit.SideNum
Circuit 1
3 (Room1)
Circuit 2
4 +2 = 6
4 +3 = 7 (Room2)
Circuit 3
3 +2 = 5
3 +3 = 6 (Room3)
Circuit 4
3 (Room4)
Circuit 5
3 (Room5)
FromRoom
ToRoom
Room
Door 1
null
null
null
Door 2
Room 1
null
null
Door 3
Room 3
Room 2
Room 2
Door 4
Room 4
null
null
Door 5
null
Room 6
Room 6
All family instances have the Room property, which is the room where an instance is located in the last project phase. Windows and doors
face into a room. Change the room by flipping the door or window facing, or by calling FamilyInstance.FlipFromToRoom(). For other kinds of
instances, such as beams and columns, the Room is the room that has the same boundary as the instance.
The following code illustrates how to get the Room from the family instance. It is necessary to check if the result is null or not.
This example displays the dimension information for a selected room. Note that the volume calculations setting must be enabled, or the
room volume is returned as 0.
The ClosedShell property for a Room (or Space) is the geometry formed by the boundaries of the open space of the room (walls, floors,
ceilings, roofs, and boundary lines). This property is useful if you need to check for intersection with other physical element in the model
with the room, for example, to see if part or all of the element is located in the room. For an example, see the RoofsRooms sample
application, included with the Revit SDK, where ClosedShell is used to check whether a room is vertically unbounded.
In addition, you can get or set the base offset and limit offset for rooms with these properties:
BaseOffset
LimitOffset
You can get or set the level that defines the upper limit of the room with the UpperLimit property.
Revit Structure
Certain API features that only exist in Revit Structure products are discussed in the following sections:
Structural Model Elements - Discusses specific Elements and their properties that only exist in the Revit Structure product.
AnalyticalModel - Discusses analytical model-related classes such as AnalyticalModel, RigidLink, and AnalyticalModelSupport.
AnalyticalLink - Discusses creating new analytical links between analytical beams and columns.
Loads - Discusses Load Settings and three kinds of Loads.
Your Analysis Link - Provides suggestions for API users who want to link the Revit Structure product to certain Structural Analysis
applications.
This chapter contains some advanced topics. If you are not familiar with the Revit Platform API, read the basic sections first, such as Getting
Started, Elements Essentials, Parameter, and so on.
to indicate the FamilyInstance objects corresponding to structural columns, beams, and braces.
Though Structural column, beam, and brace are all FamilyInstance objects in the API, they are distinguished by the StructuralType property.
You can filter out FamilySymbol objects corresponding to structural columns, beams, and braces in using categories. The category for
Structural beams and braces is BuiltInCategory.OST_StructuralFraming.
You can get and set beam setback properties with the FamilyInstance.ExtensionUtility property. If this property returns null, the beam
setback can't be modified.
AreaReinforcement and PathReinforcement
Find the AreaReinforcementCurves for AreaReinforcement by calling the GetCurveElementIds() method which returns an IList of ElementIds
that represent AreaReinforcementCurves. In edit mode, AreaReinforcementCurves are the purple curves (red when selected) in the Revit UI.
From the Element Properties dialog box you can see AreaReinforcementCurve parameters. Parameters such as Hook Types and Orientation
are editable only if the Override Area Reinforcement Setting parameter is true.
Although the AreaReinforcement.GetCurveElementIds() method returns a set of ElementIds representing AreaReinforcementCurves, which
have a property that returns a Curve, the PathReinforcement.GetCurveElementIds() method returns a collection of ElementIds that
represent ModelCurves. There is no way to flip the PathReinforcement except by using the NewPathReinforcement() method (the last input
parameter).
Filter out the right face based on normal and origin. For example:
o
For a general vertical Wall, the face is located using the following factors:
Note that project-wide settings related to area and path reinforcement are accessible from the ReinforcementSettings class. Currently, the
only setting available is the HostStructuralRebar property.
BeamSystem
BeamSystem provides you with full access and edit ability. You can get and set all of its properties, such as BeamSystemType, BeamType,
Direction, and Level. BeamSystem.Direction is not limited to one line of edges. It can be set to any XYZ coordinate on the same plane with
the BeamSystem.
Note You cannot change the StructuralBeam AnalyticalModel after the Elevation property is changed in the UI or by the API. In the following
picture the analytical model lines stay in the original location after BeamSystem Elevation is changed to 10 feet.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61. }
if (null != trussType)
{
truss = Truss.Create(document, trussType.Id, sketchPlane.Id, baseLine);
transaction.Commit();
}
else
{
transaction.RollBack();
throw new Exception("No truss types found in document.");
}
return truss;
Rebar
The Rebar class represents rebar used to reinforce suitable elements, such as concrete beams, columns, slabs or foundations.
You can create rebar objects using one of three static Rebar methods.
Name
Description
Creates a new instance of a Rebar element within the project. All curves must
belong to the plane defined by the normal and origin.
Creates a new Rebar, as an instance of a RebarShape. The instance will have the
default shape parameters from the RebarShape, and its location is based on the
bounding box of the shape in the shape definition. Hooks are removed from the
shape before computing its bounding box. If appropriate hooks can be found in
the document, they will be assigned arbitrarily.
Creates a new instance of a Rebar element within the project. The instance will
have the default shape parameters from the RebarShape. All curves must
belong to the plane defined by the normal and origin.
The first version creates rebar from an array of curves describing the rebar, while the second creates a Rebar object based on a RebarShape
and position. The third version creates rebar from an array of curves and based on a RebarShape.
When using the CreateFromCurves() or CreateFromCurvesAndShape() method, the parameters RebarBarType and RebarHookType are
available in the RebarBarTypes and RebarHookTypes properties of the Document.
The following code illustrates how to create Rebar with a specific layout.
NoteFor more examples of creating rebar elements, see the Reinforcement and NewRebar sample applications included with the Revit SDK.
The following table lists the integer value for the Parameter REBAR_ELEM_LAYOUT_RULE:
Table 59: Rebar Layout Rule
Value
Description
None
Fixed Number
Maximum Spacing
The Rebar.ScaleToBox() method provides a way to simultaneously set all the shape parameters. The behavior is similar to the UI for placing
Rebar.
RebarHostData and RebarCoverType
Clear cover is associated with individual faces of valid rebar hosts. You can access the cover settings of a host through the
Autodesk.Revit.Elements.RebarHostData object. A simpler, less powerful mechanism for accessing the same settings is provided through
parameters.
Cover is defined by a named offset distance, modeled as an element Autodesk.Revit.DB.Structure.RebarCoverType.
BoundaryConditions
There are three types of BoundaryConditions:
Point
Curve
Area
The type and pertinent geometry information is retrieved using the following code:
When using NewSlab() to create a Slab, Span Directions are not automatically created. There is also no way to create them directly.
The Slab compound structure layer Structural Deck properties are exposed by the following properties:
CompoundStructuralLayer.DeckUsage
DeckProfile
The properties are outlined in the following dialog box:
Analytical Model
In Revit Structure, an analytical model is the engineering description of a structural physical model.
The following structural elements have structural member analytical models:
Structural Columns
Structural Framing elements (such as beams and braces)
Structural Floors
Structural Footings
Structural Walls
An Element's AnalyticalModel can be obtained using the GetAnalyticalModel() method. Note that the AnalyticalModel for a newly created
structural element is not available until a Regeneration occurs. Depending on the element's family, the AnalyticalModel may not exist. If the
AnalyticalModel value does not apply to an element's family, the GetAnalyticalModel() method returns null. Check the value before using this
class. AnalyticalModel is made up of the following information:
Location of the Element with respect to analysis
Parameter Information, including projection, hard points, approximation, and rigid links
Support Information
Adjustment Information, both Manual and Automatic
Analytical Offset
Analytical Location
Depending on the type of element that corresponds to the AnalyticalModel, the location of the element with respect to analysis can be
obtained by one of three methods: GetPoint(), GetCurve() or GetCurves().
Note that the curves retrieved from these methods do not have their Reference properties set. Therefore, they cannot be used for properties
such as Curve.EndPointReference. Instead, you can obtain References to the curves and their end points through construction of an
AnalyticalModelSelector object containing the necessary information, as the following example demonstrates.
The following example demonstrates how to get the analytical location for a structural footing.
The following example demonstrates the use of AnalyticalModel for structural walls.
Note that in addition to the correct values being set, the elements must also overlap for the rigid link to be created.
Manual Adjustment
The geometry of the structural member analytical model may also be adjusted in relation to those elements to which it joins (assuming the
SupportsManualAdjustment() method returns true). Use the AnalyticalModel.ManuallyAdjust() method to adjust the analytical model in
relation to another element.
Code Region 29-14: Adjusting the analytical model in relation to another element
// Pick the source analytical line to adjust to
Selection sel = app.ActiveUIDocument.Selection;
Reference refAnalytical = sel.PickObject(ObjectType.Element, "Please Pick the source analytical line to adjust to");
AnalyticalModel aModel = doc.GetElement(refAnalytical) as AnalyticalModel;
Curve aCurve = aModel.GetCurve();
// Get the reference of the start point
AnalyticalModelSelector aSelector = new AnalyticalModelSelector(aCurve);
aSelector.CurveSelector = AnalyticalCurveSelector.StartPoint;
Reference refSource = aModel.GetReference(aSelector);
// Pick the source analytical line to be adjusted
Reference refAnalytical2 = sel.PickObject(ObjectType.Element, "Please pick the source analytical line to be adjusted");
AnalyticalModel aModel2 = doc.GetElement(refAnalytical2) as AnalyticalModel;
// Get the reference of the start point
Curve aCurve2 = aModel2.GetCurve();
AnalyticalModelSelector aSelector2 = new AnalyticalModelSelector(aCurve2);
aSelector2.CurveSelector = AnalyticalCurveSelector.StartPoint;
// Can be adjusted to the middle of the line if WholeCurve is used
//aSelector2.CurveSelector = AnalyticalCurveSelector.WholeCurve;
Reference refTarget = aModel2.GetReference(aSelector2);
// Adjust the analytical line
aModel.ManuallyAdjust(refSource, refTarget, true);
AnalyticalModel also provides methods to determine if the analytical model has been manually adjusted and to reset it back to its original
location, relative to its corresponding physical model. Additionally, the GetManualAdjustmentMatchedElements() method retrieves a
collection of element Ids against which the Analytical Model has been adjusted.
Analytical Offset
Another way to adjust an analytical model is to use an offset. Setting the analytical offset is different than manually adjusting the analytical
model. The analytical offset is a basic offset applied to the entire analytical model and is independent of any other elements. AnalyticalModel
has methods to get and set the analytical offset as well as to determine if the analytical offset can be changed (CanSetAnalyticalOffset()).
AnalyticalModelSupport
AnalyticalModel provides the method IsElementFullySupported() to determine if the analytical model is fully supported. For additional
information about what is supporting the analytical model, the GetAnalyticalModelSupports() method retrieves a collection of
AnalyticalModelSupport objects that provide information on how the element is supported by other structural elements, including the priority
of each support (if multiple elements provide support) and the point, curve or face that provides the support. The following examples
illustrate how to use the AnalyticalModelSupport objects in different conditions.
Figure 165: Isolated Foundation (FamilyInstance) and Structural Column Support Information
Loads
The following sections identify load settings and discuss load limitation guidelines.
Load Settings
All functionality on the Setting dialog box Load Cases and Load Combinations tabs can be accessed by the API.
The following properties are available from the corresponding LoadCase BuiltInParameter:
Table 60 Load Case Properties and Parameters
Property
BuiltInParameter
Case Number
LOAD_CASE _NUMBER
Nature
LOAD_CASE_NATURE
Category
LOAD_CASE_CATEGORY
The LOAD_CASE_CATEGORY parameter returns an ElementId. The following table identifies the mapping between Category and ElementId
Value.
Table 61: Load Case Category
Load Case Category
BuiltInCategory
Dead Loads
OST_LoadCasesDead
Live Loads
OST_LoadCasesLive
Wind Loads
OST_LoadCasesWind
Snow Loads
OST_LoadCasesSnow
OST_LoadCasesRoofLive
Accidental Loads
OST_LoadCasesAccidental
Temperature Loads
OST_LoadCasesTemperature
Seismic Loads
OST_LoadCasesSeismic
Because they are all Element subclasses, they can be deleted using Document.Delete().
Analysis Link
With Revit Structure, an analytical model is automatically generated as you create the physical model. The analytical model is linked to
structural analysis applications and the physical model is automatically updated from the results through the Revit Structure API. Some
third-party software developers already provide bi-directional links to their structural analysis applications. These include the following:
ADAPT-Builder Suite from ADAPT Corporation (www.adaptsoft.com/revitstructure/)
Fastrak and S-Frame from CSC (www.cscworld.com)
ETABS from CSI (www.csiberkeley.com/)
RFEM from Dlubal (www.dlubal.com/FEA-Software-RFEM-integrates-with-Revit-Structure.aspx)
Advance Design, VisualDesign, Arche, Effel and SuperSTRESS from GRAITEC (www.graitec.com/En/revit.asp)
Scia Engineer from Nemetschek (www.scia-online.com/en/revit.html)
GSA from Oasys Software (Arup) (www.oasys-software.com/products)
ProDESK from Prokon Software Consultants (www.prokon.com/)
RAM Structural System from Bentley (www.bentley.com/en-US/Products/RAM+Structural+System/)
RISA-3D and RISAFloor from RISA Technologies (www.risatech.com/partner/revit_structure.asp)
SOFiSTiK Structural Desktop Suite from SOFiSTiK (http://www.sofistik.com/revit-to-sofistik)
SPACE GASS from SPACE GASS (www.spacegass.com/index.asp?resend=/revit.asp)
Revit Structure STAAD.Pro interface from Structural Integrators (structuralintegrators.com/products/si_xchange.php)
The key to linking Revit Structure to other analysis applications is to set up the mapping relationship between the objects in different object
models. That means the difficulty and level of the integration depends on the similarity between the two object models.
For example, during the product design process, design a table with at least the first two columns in the object mapping in the following
table: one for Revit Structure API and the other for the structural analysis application, shown as follows:
Table 62: Revit and Analysis Application Object Mapping
Revit Structural API
Analysis Application
Import to Revit
StructuralColumn
Column
NewStructuralColumn
Property:
Location
Read-only;
Parameter:
Analyze as
AnalyticalModel:
Editable;
Profile
Read-only;
RigidLink
Read-only;
Material:
Analytical Links
An analytical link is an element connecting 2 separate analytical nodes, which has properties such as fixity state. Analytical links can be created automatically
by Revit from analytical beams to analytical columns during modeling based on certain rules. And they can also be created manually, both in the Revit UI and
using the Revit API.
In the Revit API, an analytical link is represented by the AnalyticalLink class. Fixity values are available from its associated AnalyticalLinkType.
The example below demonstrates how to read all of the AnalyticalLinks in the document and displays a TaskDialog summarizing the number of automatically
generated and manually created AnalyticalLinks.
The static method AnalyticalLink.Create() creates a new analytical link. Rather than connecting the two elements directly, the connection is created between
two Hubs. The Hub class represents a connection between two or more Autodesk Revit Elements.
The following example creates a new analytical link between two selected FamilyInstance objects. It uses a filter to find all Hubs in the model and then the
GetHub() method searches the hubs to find one which references the Id of the AnalyticalModel of each FamilyInstance.
Revit MEP
The Revit MEP portion of the Revit API provides read and write access to HVAC and Piping data in a Revit model including:
Traversing ducts, pipes, fittings, and connectors in a system
Adding, removing, and changing ducts, pipes, and other equipment
Getting and setting system properties
Determining if the system is well-connected
Access to Mechanical Settings
Managing Routing Preferences
The code region below demonstrates how to create a FlexPipe using the static FlexPipe.Create() method. Pipes, ducts and flex ducts can all
be created between two points similarly.
After creating a pipe, you might want to change the diameter. The Diameter property of Pipe is read-only. To change the diameter, get the
RBS_PIPE_DIAMETER_PARAM built-in parameter.
Another common way to create a new duct or pipe is between two existing connectors, as the following example demonstrates. In this
example, it is assumed that 2 elements with connectors have been selected in Revit MEP, one being a piece of mechanical equipment and
the other a duct fitting with a connector that lines up with the SupplyAir connector on the equipment.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82. }
if (null != ductType)
{
duct = uiDocument.Document.Create.NewDuct(connector1, connector2, ductType);
}
return duct;
Below is the result of running this code after selecting a VAV Unit - Parallel Fan Powered and a rectangular elbow duct fitting.
Placeholders
Placeholder ducts and pipes
The Revit API provides the ability to put placeholder elements into a system when the exact design of the layout is not yet know. Using
placeholder ducts and pipes can allow for a well-connected system while the design is still unknown, and then which can then be elaborated
in the final design at a later stage.
The two static methods Duct.CreatePlaceholder() and Pipe.CreatePlaceholder() create placeholder elements. The IsPlaceholder property of
Duct and Pipe indicates whether they are a placeholder element or not.
When ready to create actual ducts and pipes from the placeholders, use the MechanicalUtils.ConvertDuctPlaceholders()
and PlumbingUtils.ConvertPipePlaceholders() methods to convert a set of placeholder elements to ducts and pipes. Once conversion
succeeds, the placeholder elements are deleted. The new duct, pipe and fitting elements are created and connections are established.
Systems
Creating a new system
New piping and mechanical systems can be created using the Revit API. NewPipingSystem() and NewMechanicalSystem() both take a
Connector that is the base equipment connector, such as a hot water heater for a piping system, or a fan for a mechanical system. They also
take a ConnectorSet of connectors that will be added to the system, such as faucets on sinks in a piping system. The last piece of
information required to create a new system is either a PipeSystemType for NewPipingSystem() or a DuctSystemType for
NewMechanicalSystem().
In the following sample, a new SupplyAir duct system is created from a selected piece of mechanical equipment (such as a fan) and all
selected Air Terminals.
Connectors
As shown in the previous section, new pipes and ducts can be created between two connectors. Connectors are associated with a domain ducts, piping or electrical - which is obtained from the Domain property of a Connector. Connectors are present on mechanical equipment as
well as on ducts and pipes.
To traverse a system, you can examine connectors on the base equipment of the system and determine what is attached to the connector by
checking the IsConnected property and then the AllRefs property. When looking for a physical connection, it is important to check the
ConnectionType of the connector. There are both physical and logical connectors in Revit, but only the physical connectors are visible in the
application. The following imagine shows the two types of physical connectors - end connections and curve connectors.
The following dialog box is the result of running this code example on the connector from a piece of mechanical equipment.
Family Creation
When creating mechanical equipment in a Revit family document, you will need to add connectors to allow the equipment to connect to a
system. Duct, electrical and pipe connectors can all be added similarly, using a reference plane where the connector will be placed and a
system type for the connector.
The overloaded static methods provided by the ConnectorElement class are:
CreateCableTrayConnector
CreateConduitConnector
CreateDuctConnector
CreateElectricalConnector
CreatePipeConnector
Each of the methods above has a second overload that takes an additional Edge parameter that allows creation of connector elements
centered on internal loops of a given face. The following code demonstrates how to add two pipe connectors to faces on an extrusion and set
some properties on them.
37.
38.
39.
40.
41.
42.
43.
44.
45. }
ConnectorElement connReturn =
ConnectorElement.CreatePipeConnector(uiDocument.Document,
PipeSystemType.ReturnHydronic,
planarFaces[1].Reference);
param = connReturn.get_Parameter(BuiltInParameter.CONNECTOR_RADIUS);
param.Set(0.5); // 6" radius
param = connReturn.get_Parameter(BuiltInParameter.RBS_PIPE_FLOW_DIRECTION_PARAM);
param.Set(1);
The following illustrates the result of running this example using in a new family document created using a Mechanical Equipment template
and passing in an extrusion 2'2'1'. Note that the connectors are placed at the centroid of the planar faces.
Mechanical Settings
Many of the settings available on the Manage tab under MEP Settings - Mechanical Settings are also available through the Revit API.
Pipe Settings
Pipe Settings
The PipeSettings class provides access to the settings shown above, such as Pipe Size Suffix and Pipe Connector Tolerance. There is one PipeSettings object per
document and it is accessible through the static method PipeSettings.GetPipeSettings().
Fitting Angles
Fitting angle usage settings for pipes are available from the following property and methods of the PipeSettings class:
PipeSettings.FittingAngleUsage
PipeSettings.GetSpecificFittingAngles()
PipeSettings.GetSpecificFittingAngleStatus()
PipeSettings.SetSpecificFittingAngleStatus()
The settings available in the UI under Pipe Settings - Segments and Sizes are available as well.
This information is available through the Segment and MEPSize classes. A Segment represents a length of MEPCurve that contains a material and set of
available sizes. The pipe sizes are represented by the MEPSize class. The Segments available can be found using a filter. The following example demonstrates
how to get some of the information in the dialog above.
To add new sizes to the list, use the Segment.AddSize() method. Use Segment.RemoveSize() to remove a size by nominal diameter.
Slopes
The PipeSettings class also provides access to the slope values available in the UI under Pipe Settings - Slopes. Use GetPipeSlopes() to retreive a list of slope
values. PipeSettings.SetPipeSlopes() provides the ability to set all the slope values at once, while PipeSettings.AddPipeSlope() adds a single pipe slope. Revit
stores the slope value as a percentage (0-100).
Duct Settings
The DuctSettings class provides access to the settings shown above, such as Duct Fitting Annotation Size and Air Density. There is one DuctSettings object per
document and it is accessible through the static method DuctSettings.GetDuctSettings().
Duct Fitting Angles
Fitting angle usage settings for ducts are available from the following property and methods of the DuctSettings class:
DuctSettings.FittingAngleUsage
DuctSettings.GetSpecificFittingAngles()
DuctSettings.GetSpecificFittingAngleStatus()
DuctSettings.SetSpecificFittingAngleStatus()
Electrical Settings
Some of the settings available on the Manage tab under MEP Settings - Electrical Settings are also available through the Revit API.
Electrical Settings
The ElectricalSetting class provides access to different electrical settings, such as fitting angles, wire types, and voltage types. There is one
ElectricalSetting object per document and it is accessible through the static method ElectricalSetting.GetElectricalSettings().
Fitting Angles
Fitting angle usage settings for cable trays and conduits are available from the following property and methods of the ElectricalSetting class:
ElectricalSetting.FittingAngleUsage
ElectricalSetting.GetSpecificFittingAngles()
ElectricalSetting.GetSpecificFittingAngleStatus()
ElectricalSetting.SetSpecificFittingAngleStatus()
Fitting Angles
Other Electrical Settings
Methods also are available to add or remove from the project distribution system types, voltate types, wire material types and wire types.
Routing Preferences
Routing prefences are accessible through the RoutingPreferenceManager class. An instance of this class is available from a property of the MEPCurveType
class. Currently, only PipeType and DuctType support routing preferences.
The RoutingPreferenceManager manages all rules for selecting segment types and sizes as well as fitting types based on user selection criteria. The
RoutingPreferenceRule class manages one segment or fitting preference and instances of this class can be added to the RoutingPreferenceManager. Each
routing preference rule is grouped according to what type of routing item in manages. The type is represented by the RoutingPreferenceRuleGroupType and
includes these options:
Member name
Description
Undefined
Segments
Elbows
Elbow types
Junctions
Crosses
Cross types
Transitions
Transition types (Note that the multi-shape transitions may have their own groups)
Unions
MechanicalJoints
Mechanical joint types that connect fitting to fitting, segment to fitting, or segment to segment
TransitionsRectangularToRound Multi-shape transition from the rectangular profile to the round profile
TransitionsRectangularToOval
TransitionsOvalToRound
Each routing preference rule can have one or more selection criteria, represented by the RoutingCriterionBase class, and the derived type PrimarySizeCriterion.
PrimarySizeCriterion selects fittings and segments based on minimum and maximum size constraints.
The RoutingConditions class holds a collection of RoutingCondition instances. The RoutingCondition class represents routing information that is used as input
when determining if a routing criterion, such as minimum or maximum diameter, is met. The RoutingPreferencesManager.GetMEPPartId() method gets a
fitting or segment id based on a RoutingPreferenceRuleGroupType and RoutingConditions.
The following example gets all the pipe types in the document, gets the routing preference manager for each one, then gets the sizes for each segment based
on the rules in the routing preference manager.
Advanced Topics
Storing Data in the Revit model
The Revit API provides two methods for storing data in the Revit model. The first is using shared parameters. The Revit API gives programmatic access to the
same shared parameters feature that is available through the Revit UI. Shared parameters, if defined as visible, will be viewable to the user in an element's
property window. Shared parameters can be assigned to many, but not all, categories of elements.
The other option is extensible storage, which allows you to create custom data structures and then assign instances of that data to elements in the model. This
data is never visible to the user in the Revit UI, but may be accessible to other third party applications via the Revit API depending on the read/write access
assigned to the schema when it is defined. Unlike Shared Parameters, extensible storage is not limited to certain categories of elements. Extensible storage
data can be assigned to any object that derives from the base class Element in the Revit model.
Shared Parameters
Shared Parameters are parameter definitions stored in an external text file. The definitions are identified by a unique identifier generated
when the definition is created and can be used in multiple projects.
This chapter introduces how to gain access to shared parameters through the Revit Platform API. The following overview shows how to get a
shared parameter and bind it to Elements in certain Categories:
Set SharedParametersFileName
Get the External Definition
Binding
Definition File
The DefinitionFile object represents a shared parameter file. The definition file is a common text file. Do not edit the definition file directly;
instead, edit it using the UI or the API.
Definition File Format
The shared parameter definition file is a text file (.txt) with two blocks: GROUP and PARAM.
GROUP
VISIBLE
MyParam TEXT
1 1
Price
INTEGER 2 1
areaTags FAMILYTYPE -2005020 1 1
The GROUP block contains group entries that associate every parameter definition with a group. The following fields appear in the
GROUP block:
o
ID - Uniquely identifies the group and associates the parameter definition with a group.
DATATYPE - Parameter type. This field can be a common type (TEXT, INTEGER, etc.), structural type (FORCE, MOMENT,
etc.) or common family type (Area Tags, etc). Common type and structural type parameters are specified in the text file
directly (e.g.: TEXT, FORCE). If the value of the DATATYPE field is FAMILYTYPE, an extra number is added. For example,
FAMILYTYPE followed by -2005020 represents Family type: Area Tags.
GROUP - A group ID used to identify the group that includes the current parameter definition.
VISIBLE - Identifies whether the parameter is visible. The value of this field is 0 or 1.
0 = invisible
1 = visible
Shared parameters are grouped for easy management and contain shared parameter definitions.
Autodesk.Revit.Parameters.ExternalDefinition Class - The ExternalDefinition class is derived from the Definition class.
o
The ExternalDefinition object is created by a DefinitionGroup object from a shared parameter file.
External parameter definitions must belong to a Group which is a collection of shared parameter definitions.
Autodesk.Revit.Options.Application.SharedParametersFilename Property - Get and set the shared parameter file path using the
Autodesk.Revit.Options.SharedParametersFilename property.
o
Autodesk.Revit.Application.OpenSharedParameterFile Method - This method returns an object representing a Revit shared parameter
file.
o
The file name for the shared parameter file is set in the Revit Application Options object. If the file does not exist, an
exception is thrown.
Create a Shared Parameter File
o
Because the shared parameter file is a text file, you can create it using code or create it manually.
Code Region 22-4: Getting the definition file from an external parameter file
private DefinitionFile SetAndOpenExternalSharedParamFile(
Autodesk.Revit.ApplicationServices.Application application, string sharedParameterFile)
{
// set the path of shared parameter file to current Revit
application.Options.SharedParametersFilename = sharedParameterFile;
// open the file
return application.OpenSharedParameterFile();
}
Note Consider the following points when you set the shared parameter path:
During each installation, Revit cannot detect whether the shared parameter file was set in other versions. You must bind the shared
parameter file for the new Revit installation again.
If Options.SharedParametersFilename is set to a wrong path, an exception is thrown only when OpenSharedParameterFile is called.
Revit can work with multiple shared parameter files. Even though only one parameter file is used when loading a parameter, the
current file can be changed freely.
Traverse All Parameter Entries
The following sample illustrates how to traverse the parameter entries and display the results in a message box.
Binding
In the add-in code, complete the following steps to bind a specific parameter:
1. Use an InstanceBinding or a TypeBinding object to create a new Binding object that includes the categories to which the parameter is
bound.
2. Add the binding and definition to the document using the Document.ParameterBindings object.
The following list provides more information about the classes and methods in the previous diagram.
Autodesk.Revit.Parameters.BindingMap Class - The BindingMap object is retrieved from the Document.ParameterBindings property.
o
Parameter binding connects a parameter definition to elements within one or more categories.
The map is used to interrogate existing bindings as well as generate new parameter bindings using the Insert method.
Parameters.BindingMap.Insert (Definition, Binding) Method - The binding object type dictates whether the parameter is bound to all
instances or just types.
o
o
Type Binding
The Autodesk.Revit.Parameters.TypeBinding objects are used to bind a property to a Revit type, such as a wall type. It differs from Instance
bindings in that the property is shared by all instances identified in type binding. Changing the parameter for one type affects all instances of
the same type.
The following code segment demonstrates how to add parameter definitions using a shared parameter file. The following code performs the
same actions as using the dialog box in the previous picture. Parameter definitions are created in the following order:
1. A shared parameter file is created.
2. A definition group and a parameter definition are created for the Walls type.
3. The definition is bound to the wall type parameter in the current document based on the wall category.
Code Region 22-7: Adding type parameter definitions using a shared parameter file
public bool SetNewParameterToTypeWall(UIApplication app, DefinitionFile myDefinitionFile)
{
// Create a new group in the shared parameters file
DefinitionGroups myGroups = myDefinitionFile.Groups;
DefinitionGroup myGroup = myGroups.Create("MyParameters");
// Create a type definition
Definition myDefinition_CompanyName =
myGroup.Definitions.Create("CompanyName", ParameterType.Text);
// Create a category set and insert category of wall to it
CategorySet myCategories = app.Application.Create.NewCategorySet();
// Use BuiltInCategory to get category of wall
Category myCategory = app.ActiveUIDocument.Document.Settings.Categories.get_Item(BuiltInCategory.OST_Walls);
myCategories.Insert(myCategory);
//Create an object of TypeBinding according to the Categories
TypeBinding typeBinding = app.Application.Create.NewTypeBinding(myCategories);
// Get the BingdingMap of current document.
BindingMap bindingMap = app.ActiveUIDocument.Document.ParameterBindings;
// Bind the definitions to the document
bool typeBindOK = bindingMap.Insert(myDefinition_CompanyName, typeBinding,
BuiltInParameterGroup.PG_TEXT);
return typeBindOK;
}
Instance Binding
The Autodesk.Revit.Parameters.InstanceBinding object indicates binding between a parameter definition and a parameter in certain category
instances. The following diagram illustrates Instance Binding in the Walls category.
Once bound, the parameter appears in all property dialog boxes for the instance. Changing the parameter in any one instance does not
change the value in any other instance.
The following code sample demonstrates how to add parameter definitions using a shared parameter file. Parameter definitions are added in
the following order:
1. A shared parameter file is created
2. A definition group and a definition for all Walls instances is created
3. Definitions are bound to each wall instance parameter in the current document based on the wall category.
Code Region 22-8: Adding instance parameter definitions using a shared parameter file
public bool SetNewParameterToInsanceWall(UIApplication app, DefinitionFile myDefinitionFile)
{
// create a new group in the shared parameters file
DefinitionGroups myGroups = myDefinitionFile.Groups;
DefinitionGroup myGroup = myGroups.Create("MyParameters1");
// create an instance definition in definition group MyParameters
Definition myDefinition_ProductDate =
myGroup.Definitions.Create("Instance_ProductDate", ParameterType.Text);
// create a category set and insert category of wall to it
CategorySet myCategories = app.Application.Create.NewCategorySet();
// use BuiltInCategory to get category of wall
Category myCategory = app.ActiveUIDocument.Document.Settings.Categories.get_Item(
BuiltInCategory.OST_Walls);
myCategories.Insert(myCategory);
//Create an instance of InstanceBinding
InstanceBinding instanceBinding =
app.Application.Create.NewInstanceBinding(myCategories);
// Get the BingdingMap of current document.
BindingMap bindingMap = app.ActiveUIDocument.Document.ParameterBindings;
// Bind the definitions to the document
bool instanceBindOK = bindingMap.Insert(myDefinition_ProductDate,
instanceBinding, BuiltInParameterGroup.PG_TEXT);
return instanceBindOK;
}
Extensible Storage
The Revit API allows you to create your own class-like Schema data structures and attach instances of them to any Element in a Revit
model. Schema-based data is saved with the Revit model and allows for higher-level, metadata-enhanced, object-oriented data structures.
Schema data can be configured to be readable and/or writable to all users, just a specific application vendor, or just a specific application
from a vendor.
The following steps are necessary to store data with Elements in Revit:
1. Create and name a new schema
2. Set the read/write access for the schema
3. Define one or more fields of data for the schema
4. Create an entity based on the schema
5. Assign values to the fields for the entity
6. Associate the entity with a Revit element
Schemas and SchemaBuilder
The first step to creating extensible storage is to define the schema. A schema is similar to a class in an object-oriented programming
language. Use the SchemaBuilder class constructor to create a new schema. SchemaBuilder is a helper class used to create schemas. Once a
schema is finalized using SchemaBuilder, the Schema class is used to access properties of the schema. At that stage, the schema is no
longer editable.
Although the SchemaBuilder constructor takes a GUID which is used to identify the schema, a schema name is also required. After creating
the schema, call SchemaBuilder.SetSchemaName() to assign a user-friendly identifier for the schema. The schema name is useful to identify
a schema in an error message.
The read and write access levels of entities associated with the schema can be set independently. The options are Public, Vendor, or
Application. If either the read or write access level is set to Vendor, the VendorId of the third-party vendor that may access entities of the
schema must be specified. If either access level is set to Application, the GUID of the application or add-in that may access entities of the
schema must be supplied.
Note that schemas are stored with the document and any Revit API add-in may read the available schemas in the document, as well as some
data of the schema. However, access to the fields of a schema is restricted based on the read access defined in the schema and the actual
data in the entities stored with specific elements is restricted based on the read and write access levels set in the schema when it is defined.
Fields and FieldBuilder
Once the schema has been created, fields may be defined. A field is similar to a property of a class. It contains a name, documentation,
value type and unit type. Fields can be a simple type, an array, or a map. The following simple data types are allowed:
Type
Default Value
int
short
byte
double
0.0
float
0.0
bool
false
string
GUID
Guid.Empty {00000000-0000-0000-0000-000000000000}
ElementId
ElementId.InvalidElementId
Autodesk.Revit.DB.XYZ
(0.0,0.0,0.0)
Autodesk.Revit.DB.UV
(0.0,0.0)
Additionally, a field may be of type Autodesk.Revit.DB.ExtensibleStorage.Entity. In other words, an instance of another Schema, also known
as a SubSchema or SubEntity. The default value for a field of this type is Entity with null schema, and guid of Guid.Empty.
A simple field can be created using the SchemaBuilder.AddSimpleField() method to specify a name and type for the field. AddSimpleField()
returns a FieldBuilder, which is a helper class for defining Fields. If the type of the field was specified as Entity, use
FieldBuilder.SetSubSchemaGUID() to specify the GUID of the schema of the Entities that are to be stored in this field.
Use the SchemaBuilder.AddArrayField() method to create a field containing an array of values in the Schema, with a given name and type of
contained values. Array fields can have all the same types as simple fields.
Use the SchemaBuilder.AddMapField() method to create a field containing an ordered key-value map in the Schema, with given name, type
of key and type of contained values. Supported types for values are the same as for simple fields. Supported types for keys are limited to
int, short, byte, string, bool, ElementId and GUID.
Once the schema is finalized using SchemaBuilder, fields can no longer be edited using FieldBuilder. At that stage, the Schema class provides
methods to get a Field by name, or a list of all Fields defined in the Schema.
Entities
After all fields have been defined for the schema, SchemaBuilder.Finish() will return the finished Schema. A new Entity can be created using
that schema. For each Field in the Schema, the value can be stored using Entity.Set(), which takes a Field and a value (whose type is
dependent on the field type). Once all applicable fields have been set for the entity, it can be assigned to an element using the
Element.SetEntity() method.
To retrieve the data later, call Element.GetEntity() passing in the corresponding Schema. If no entity based on that schema was saved with
the Element, an invalid Entity will be returned. To check that a valid Entity was returned, call the Entity.IsValid() method. Field values from
the entity can be obtained using the Entity.Get() method.
To determine Entities stored with an element, use the Element.GetEntitySchemaGuids() method, which returns the Schema guids of any
Entities for the Element. The Schema guids can be used with the static method Schema.Lookup() to retrieve the corresponding Schemas.
Transactions
Transactions are context-like objects that encapsulate any changes to a Revit model. Any change to a document can only be made while
there is an active transaction open for that document. Attempting to change the document outside of a transaction will throw an exception.
Changes do not become a part of the model until the active transaction is committed. Consequently, all changes made in a transaction can
be rolled back either explicitly or implicitly (by the destructor). Only one transaction per document can be open at any given time. A
transaction may consist of one or more operations.
There are three main classes in the Revit API related to transactions:
Transaction
SubTransaction
TransactionGroup
This section will discuss each of these classes in more depth. Only the Transaction class is required to make changes to a document. The
other classes can be used to better organize changes. Keep in mind that the TransactionMode attribute applied to the IExternalCommand
definition will affect how Revit expects transactions to be handled when the command is invoked. Review TransactionAttribute for more
information.
Note: An exception will be thrown if a transaction is started from an outside thread or outside modeless dialog. Transactions can only be
started from supported API workflows, such as part of an external command, event, updater, or call-back.
Transaction Classes
All three transaction objects share some common methods:
Table 51: Common Transaction Object Methods
Method
Description
Start
Commit
Rollback
GetStatus
In addition to the GetStatus() method returning the current status, the Start, Commit and RollBack methods also return a TransactionStatus
indicating whether or not the method was successful. Available TransactionStatus values include:
Table 52: TransactionStatus values
Status
Description
Uninitialized
The initial value after object is instantiated; the context has not started yet
Started
RolledBack
Committed
Pending
Transaction object was attempted to be either submitted or rolled back, but due to failures that process could not be finished yet and is
waiting for the end-user's response (in a modeless dialog). Once the failure processing is finished, the status will be automatically updated (to
either Committed or RolledBack status).
Transaction
A transaction is a context required in order to make any changes to a Revit model. Only one transaction can be open at a time; nesting is
not allowed. Each transaction must have a name, which will be listed on the Undo menu in Revit once a transaction is successfully
committed.
SubTransaction
A SubTransaction can be used to enclose a set of model-modifying operations. Sub-transactions are optional. They are not required in order
to modify the model. They are a convenience tool to allow logical splitting of larger tasks into smaller ones. Sub-transactions can only be
created within an already opened transaction and must be closed (either committed or rolled back) before the transaction is closed
(committed or rolled back). Unlike transactions, sub-transaction may be nested, but any nested sub-transaction must be closed before the
enclosing sub-transaction is closed. Sub-transactions do not have a name, for they do not appear on the Undo menu in Revit.
TransactionGroup
TransactionGroup allows grouping together several independent transactions, which gives the owner of a group an opportunity to address
many transactions at once. When a transaction group is to be closed, it can be rolled back, which means that all previously committed
transactions belonging to the group will be rolled back. If not rolled back, a group can be either committed or assimilated. In the former
case, all committed transactions (within the group) will be left as they were. In the later case, transactions within the group will be merged
together into one single transaction that will bear the group's name.
A transaction group can only be started when there is no transaction open yet, and must be closed only after all enclosed transactions are
closed (rolled back or committed). Transaction groups can be nested, but any nested group must be closed before the enclosing group is
closed. Transaction groups are optional. They are not required in order to make modifications to a model.
The following example shows the use of a TransactionGroup to combine two separate Transactions using the Assimilate() method. The
following code will result in a single Undo item added to the Undo menu with the name "Level and Grid".
52.
// For we were unable to create the level, we will roll the transaction back
53.
// (although on this simplified case we know there weren't any other changes)
54.
55.
transaction.RollBack();
56.
}
57.
}
58.
return false;
59. }
60.
61. public bool CreateGrid(Autodesk.Revit.DB.Document document, XYZ p1, XYZ p2)
62. {
63.
// All and any transaction should be enclosed in a 'using'
64.
// block or guarded within a try-catch-finally blocks
65.
// to guarantee that a transaction does not out-live its scope.
66.
using (Transaction transaction = new Transaction(document, "Creating Grid"))
67.
{
68.
// Must start a transaction to be able to modify a document
69.
if (TransactionStatus.Started == transaction.Start())
70.
{
71.
// We create a line and use it as an argument to create a grid
72.
Line gridLine = Line.CreateBound(p1, p2);
73.
74.
if ((null != gridLine) && (null != document.Create.NewGrid(gridLine)))
75.
{
76.
if (TransactionStatus.Committed == transaction.Commit())
77.
{
78.
return true;
79.
}
80.
}
81.
82.
// For we were unable to create the grid, we will roll the transaction back
83.
// (although on this simplified case we know there weren't any other changes)
84.
85.
transaction.RollBack();
86.
}
87.
}
88.
return false;
89. }
Transactions in Events
Modifying the document during an event
Events do not automatically open transactions. Therefore, the document will not be modified during an event unless one of the event's
handlers modifies it by making changes inside a transaction. If an event handler opens a transaction it is required that it will also close it
(commit it or roll it back), otherwise all changes will be discarded.
Please be aware that modifying the active document is not permitted during some events (e.g. the DocumentClosing event). If an event
handler attempts to make modifications during such an event, an exception will be thrown. The event documentation indicates whether or
not the event is read-only.
DocumentChanged Event
The DocumentChanged event is raised after every transaction gets committed, undone, or redone. This is a read-only event, designed to
allow you to keep external data in synch with the state of the Revit database. To update the Revit database in response to changes in
elements, use the Dynamic Model Update framework.
This option controls whether all warnings should be cleared after a transaction is rolled back. The default value is False.
DelayedMiniWarnings
This options controls whether mini-warnings, if any, are displayed at the end of the transaction currently being ended, or if they should be
postponed until the end of next transaction. This is typically used within a chain of transactions when it is not desirable to show intermediate
warnings at the end of each step, but rather to wait until the completion of the entire chain.
Warnings may be delayed for more than one transaction. The first transaction that does not have this option set to True will display all of its
own warnings, if any, as well as all warnings that might have accumulated from previous transactions. The default value is False.
Note that this option is ignored in modal mode (see ForcedModalHandling below).
ForcedModalHandling
This options controls whether eventual failures will be handled modally or modelessly. The default is True. Be aware that if the modeless
failure handling is set, processing the transaction may be done asynchronously, which means that upon returning from the Commit or
RollBack calls, the transaction will not be finished yet (the status will be 'Pending').
SetFailuresPreprocessor
This interface, if provided, is invoked when there are failures found at the end of a transaction. The preprocessor may examine current
failures and even try to resolve them. See Failure Posting and Handling for more information.
SetTransactionFinalizer
A finalizer is an interface, which, if provided, can be used to perform a custom action at the end of a transaction. Note that it is not invoked
when the Commit() or RollBack() methods are called, but only after the process of committing or rolling back is completed. Transaction
finalizers must implement the ITransactionFinalizer interface, which requires two functions to be defined:
OnCommitted - called at the end of committing a transaction
OnRolledBack - called at the end of rolling back a transaction
Note that since the finalizer is called after the transaction has finished, the document is not modifiable from the finalizer unless a new
transaction is started.
The following sample program demonstrates how a transaction populates these properties:
Temporary transactions
It is not always required to commit a transaction. The transaction framework also allows for Trasactions to be rolled back. This is useful when there is an error
during the processing of the transaction, but can also be leverage directly as a technique to create a temporary transaction.
Using a temporary transaction can be useful for certain types of analyses. For example, an application looking to extract geometric properties from a wall or
other object before it is cut by openings should use a temporary transaction in conjunction with Document.Delete(). When the application deletes the
elements that cut the target elements, the cut elements geometry is restored to its original state (after the document has been regenerated).
To use a temporary transaction:
1.
2.
3.
4.
5.
6.
Instantiate the Transaction using the Transaction constructor, and assign it a name.
Call Transaction.Start()
Make the temporary change(s) to the document (element modification, deletion or creation)
Regenerate the document
Extract the desired geometry and properties
Call Transaction.RollBack() to restore the document to the previous state.
Events
Events are notifications that are triggered on specific actions in the Revit user interface or API workflows. By subscribing to events, an add-in
application can be notified when an action is about to happen or has just happened and take some action related to that event. Some events
come in pairs around actions, one occurring before the action takes place ("pre" event) and the other happening after the action takes place
("post" event). Events that do not occur in these pre/post pairs are called "single" events.
Revit provides access to events at both the Application level (such as ApplicationClosing or DocumentOpened) and the Document level (such
as DocumentClosing and DocumentPrinting). The same application level events available from the Application class are also available from
the ControlledApplication class, which represents the Revit application with no access to documents. It is ControlledApplication that is
available to add-ins from the OnStartup() and OnShutdown() methods. In terms of subscribing and unsubscribing to events, these classes
are interchangeable; subscribing to an event from the ControlledApplication class is the same as subscribing from the Application class.
Events can also be categorized as database (DB) events or user interface (UI) events. DB events are available from the Application and
Document classes, while UI events are available from the UIApplication class. (Currently all UI events are at the application level only).
Some events are considered read-only, which means that during their execution the model may not be modified. The fact that an event is
read-only is documented in the API help file. It is important to know that even during regular events (i.e. not read-only events), the model
may be in a state in which it cannot be modified. The programmer should check the properties Document.IsModifiable and
Document.IsReadOnly to determine whether the model may be modified.
Database Events
The following table lists database events, their type and whether they are available at the application and/or document level:
Table 53: DB Event Types
Event
Type
Application
Document
DocumentChanged
single
DocumentClosing
pre
DocumentClosed
post
DocumentCreating
pre
DocumentCreated
post
DocumentOpening
pre
DocumentOpened
post
DocumentPrinting
pre
DocumentPrinted
post
DocumentSaving
pre
DocumentSaved
post
DocumentSavingAs
pre
DocumentSavedAs
post
DocumentSynchronizingWithCentral
pre
DocumentSynchronizedWithCentral
post
FailuresProcessing
single
FileExporting
pre
FileExported
post
FileImporting
pre
FileImported
post
ProgressChanged
single
ViewPrinting
pre
ViewPrinted
post
DocumentChanged event
The DocumentChanged event is triggered when the Revit document has changed. This event is raised whenever a Revit transaction is either committed,
undone or redone. This is a read-only event, designed to allow external data to be kept in synch with the state of the Revit database. To update the Revit
database in response to changes in elements, use the IUpdater framework.
The DocumentChangedEventArgs class is used by the DocumentChanged event. This class has several methods to get the element Ids of any newly added
elements (GetAddElementIds()), deleted elements (GetDeletedElementIds()) or elements that have been modified (GetModifiedElementIds()). The
GetAddElementIds() and GetModifiedElementIds() methods have overloads that take an ElementFilter, which makes it easy to detect only changes of interest.
Type
UIApplication
ApplicationClosing
pre
ApplicationInitialized
single
DialogBoxShowing
single
DisplayingOptionsDialog
single
Idling
single
ViewActivating
pre
ViewActivated
post
ControlledApplication
UIDocument
Registering Events
Using events is a two step process. First, you must have a function that will handle the event notification. This function must take two
parameters, the first is an Object that denotes the "sender" of the event notification, the second is an event-specific object that contains
event arguments specific to that event. For example, to register the DocumentSavingAs event, your event handler must take a second
parameter that is a DocumentSavingAsEventArgs object.
The second part of using an event is registering the event with Revit. This can be done as early as in the OnStartup() function through the
ControlledApplication parameter, or at any time after Revit starts up. Although events can be registered for External Commands as well as
External Applications, it is not recommended unless the External Command registers and unregisters the event in the same external
command.
The following example registers the DocumentOpened event, and when that event is triggered, this application will set the address of the
project.
Canceling Events
Events that are triggered before an action has taken place (i.e. DocumentSaving) are often cancellable. (Use the Cancellable property to
determine if the event can be cancelled.) For example, you may want to check some criteria are met in a model before it is saved. By
registering for the DocumentSaving or DocumentSavingAs event, for example, you can check for certain criteria in the document and cancel
the Save or Save As action. Once cancelled, an event cannot be un-cancelled.
Note that if a pre-event is cancelled, other event handlers that have subscribed to the event will not be notified. However, handlers that
have subscribed to a post-event related to the pre-event will be notified.
The following event handler for the DocumentSavingAs event checks if the ProjectInformation Status parameter is empty, and if it is, cancels
the SaveAs event. Note that if your application cancels an event, it should offer an explanation to the user.
Save is aborted.");
}
}
}
Note that although most event arguments have the Cancel and Cancellable properties, the DocumentChanged and FailuresProcessing events
have corresponding Cancel() and IsCancellable() methods.
External Events
The Revit API provides an External Events framework to accommodate the use of modeless dialogs. It is tailored for asynchronous processing and operates
similarly to the Idling event with default frequency.
To implement a modeless dialog using the External Events framework, follow these steps:
1.
2.
3.
4.
IExternalEventHandler
This is the interface to be implemented for an external event. An instance of a class implementing this interface is registered with Revit, and every time the
corresponding external event is raised, the Execute method of this interface is invoked.
The IExternalEventHandler has only two methods to implement, the Execute() method and GetName() which should return the name of the event. Below is a
basic implementation which will display a TaskDialog when the event is raised.
ExternalEvent
The ExternalEvent class is used to create an ExternalEvent. An instance of this class will be returned to an external event's owner upon the event's creation.
The event's owner will use this instance to signal that the event should be called by Revit. Revit will periodically check if any of the events have been signaled
(raised), and will execute all events that were raised by calling the Execute method on the events' respective handlers.
The following example shows the implementation of an IExternalApplication that has a method ShowForm() that is called from an ExternalCommand (shown at
the end of the code region). The ShowForm() method creates a new instance of the external events handler from the example above, creates a new
ExternalEvent and then displays the modeless dialog box which will later use the passed in ExternalEvent object to raise events.
Raise Event
Once the modeless dialog is displayed, the user may interact with it. Actions in the dialog may need to trigger some action in Revit. When this happens, the
ExternalEvent.Raise() method is called. The following example is the code for a simple modeless dialog with two buttons: one to raise our event and one to
close the dialog.
When the ExternalEvent.Raise() method is called, Revit will wait for an available Idling timecycle and then call the IExternalEventHandler.Execute() method. In
this simple example, it will display a TaskDialog with the text "Click Close to close." as shown in the first code region above.
For a more complex example of using the External Events framework, see the sample code in the SDK under the ModelessDialog\ModelessForm_ExternalEvent
folder. It uses a modeless dialog with numerous buttons and the IExternalEventHandler implementation has a public property to track which button was
pressed so it can switch on that value in the Execute() method.
Registering a dockable pane requires an instance of the IDockablePaneProvider interface. The SetupDockablePane() method of this interface is called during
initialization of the Revit user interface to gather information about add-in dockable pane windows. SetupDockablePane() has one parameter of type
DockablePaneProviderData, which is a container for information about the new dockable pane.
Implementations of the IDockablePaneProvider interface should set the FrameworkElement and InitialState properties of DockablePaneProviderData. The
FrameworkElement property is the Windows Presentation Framework object containing the pane's user interface.
Note: It is recommended that the dockable dialog in the add-in be the class that implements IDockablePaneProvider and that it be subclassed from
System.Windows.Controls.Page.
The InitialState property is the initial position and settings of the docking pane, indicated by the DockablePaneState class. The pane's DockPosition can be Top,
Bottom, Left, Right, Floating or Tabbed. If the position is Tabbed, the DockablePaneState.TabBehind property can be used to specify which pane the new pane
will appear behind. If the position is Floating, the DockablePaneState.FloatingRectangle property contains the rectangle that determines the size and position of
the pane.
DockablePane
To access a dockable pane during runtime, it needs to be registered by calling the UIApplication.RegisterDockablePane() method. This method requires a
unique identifier for the new pane (DockablePaneId), a string specifying the caption for the pane, and an implementation of the IDockablePaneProvider
interface.
Dockable panes can be accessed by calling UIApplication.GetDockablePane() and passing in the unique DockablePaneId.This method returns a DockablePane.
DockablePane.Show() will display the pane in the Revit user interface at its last docked location, if not currently visible. DockablePane.Hide() will hide a visible
dockable pane. However, it has no effect on built-in Revit dockable panes.
Implementing IUpdater
The IUpdater interface requires that the following 5 methods to be implemented:
GetUpdaterId() - This method should return a globally unique Id for the Updater consisting of the application Id plus a GUID for this
Updater. This method is called once during registration of the Updater.
GetUpdaterName() - This returns a name by which the Updater can be identified to the user, if there is a problem with the Updater at
runtime.
GetAdditionalInformation() - This method should return auxiliary text that Revit will use to inform the end user when the Updater is
not loaded.
GetChangePriority() - This method identifies the nature of the changes the Updater will be performing. It is used to identify the order
of execution of updaters. This method is called once during registration of the Updater.
Execute() - This is the method that Revit will invoke to perform an update. See the next section for more information on the
Execute() method.
If a document is modified by an Updater, the document will store the unique Id of the updater. If the user later opens the document and the
Updater is not present, Revit will warn the user that the 3rd party updater which previously edited the document is not available, unless the
Updater is flagged as optional. By default, updaters are non-optional and optional updaters should be used only when necessary.
The following code is a simple example of implementing the IUpdater interface (to change the WallType for newly added walls) and
registering the updater in the OnStartup() method. It demonstrates all the key aspects of creating and using an updater.
return Result.Succeeded;
}
}
public class WallUpdater : IUpdater
{
static AddInId m_appId;
static UpdaterId m_updaterId;
WallType m_wallType = null;
// constructor takes the AddInId for the add-in associated with this updater
public WallUpdater(AddInId id)
{
m_appId = id;
m_updaterId = new UpdaterId(m_appId, new Guid("FBFBF6B2-4C06-42d4-97C1-D1B4EB593EFF"));
}
public void Execute(UpdaterData data)
{
Document doc = data.GetDocument();
// Cache the wall type
if (m_wallType == null)
{
FilteredElementCollector collector = new FilteredElementCollector(doc);
collector.OfClass(typeof(WallType));
var wallTypes = from element in collector
where
element.Name == "Exterior - Brick on CMU"
select element;
if (wallTypes.Count<Element>() > 0)
{
m_wallType = wallTypes.Cast<WallType>().ElementAt<WallType>(0);
}
}
if (m_wallType != null)
{
// Change the wall to the cached wall type.
foreach (ElementId addedElemId in data.GetAddedElementIds())
{
Wall wall = doc.GetElement(addedElemId) as Wall;
if (wall != null)
{
wall.WallType = m_wallType;
}
}
}
}
public string GetAdditionalInformation()
{
return "Wall type updater example: updates all newly created walls to a special wall";
}
public ChangePriority GetChangePriority()
{
return ChangePriority.FloorsRoofsStructuralWalls;
}
public UpdaterId GetUpdaterId()
{
return m_updaterId;
}
public string GetUpdaterName()
{
return "Wall Type Updater";
}
}
It is also possible that the same element may be modified by another updater, possibly even within the same transaction. Although explicit
changes of exactly the same data is tracked and prohibited, indirect or propagated changes are still possible. Perhaps the most complex case
is that an element could be changed by the user and/or the same updater in different versions of the file. After the user reloads the latest or
saves to central, the modified target element will be brought from the other file and the updater will need to reconcile changes.
It is also important to realize that when a document synchs with the central file, the ElementId of elements may be affected. If new
elements have been added to two versions of the same file and the same ElementId is used in both places, this will be reconciled when the
files are synched to the central database. For this reason, when using updaters to cross-reference one element in another element, they
should use Element.UniqueId which is guaranteed to be unique.
Another issue to consider is if an updater attaches some data (i.e. as a parameter) to an element, it not only must be sure to maintain that
information in the element to which it was added, but also to reconcile data in cases when that element is duplicated via copy/paste or group
propagation. For example, if an updater adds a parameter "Total weight of rebar" to a rebar host, that parameter and its value will be copied
to the duplicated rebar host even though the rebar itself may be not copied with the host. In this case the updater needs to ensure the
parameter value is reset in the newly copied rebar host.
Registering Updaters
Updaters must be registered in order to be notified of changes to the model. The application level UpdaterRegistry class provides the ability
to register/unregister and manipulate the options set for Updaters. Updaters may be registered from any API callback and can be registered
as application-wide or document-specific, meaning they will only be triggered by changes made to the specified document. In order to use
the UpdaterRegistry functionality, the Revit add-in must be registered in a manifest file and the Id returned by UpdaterId.GetAddInId() for
any Updater (obtained from GetUpdaterId()) must match the AddInId field in the add-in's manifest file. An add-in cannot add, remove, or
modify Updaters that do not belong to it.
Triggers
In addition to calling the UpdaterRegistry.RegisterUpdater() method, Updaters should add one or more update triggers via the AddTrigger()
methods. These triggers indicate to the UpdaterRegistry what events should trigger the Updaters Execute() method to run. They can be set
application-wide, or can apply to changes made in a specific document. Update triggers are specified by pairing a change scope and a
change type.
The change scope is one of two things:
An explicit list of element Ids in a document - only changes happening to those elements will trigger the Updater
An implicit list of elements communicated via an ElementFilter - every changed element will be run against the filter, and if any pass,
the Updater is triggered
There are several options available for change type. ChangeTypes are obtained from static methods on the Element class.
Element addition - via Element.GetChangeTypeElementAddition()
Element deletion - via Element.GetChangeTypeElementDeletion()
Change of element geometry (shape or position) - via Element.GetChangeTypeGeometry()
Changing value of a specific parameter - via Element.GetChangeTypeParameter()
Any change of element - via Element.GetChangeTypeAny().
Note that geometry changes are triggered due to potentially many causes, like a change of element type, modification of properties and
parameters, move and rotate, or changes imposed on the element from other modified elements during regeneration.
Also note that the last option, any change of element, only triggers the Updater for modifications of pre-existing elements, and does not
trigger the Updater for newly added or deleted elements. Additionally, when using this trigger for an instance, only certain modifications to
its type will trigger the Updater. Changes that affect the instance itself, such as modification of the instance's geometry, will trigger the
Updater. However, changes that do not modify the instance directly and do not result in any discernable change to the instance, such as
changes to text parameters, will not trigger the Updater for the instance. To trigger based on these changes, the Type must also be included
in the trigger's change scope.
Order of Execution
The primary way that Revit sorts multiple Updaters to execute in the correct order is by looking at the ChangePriority returned by a given
Updater. An Updater reporting a priority for a more fundamental set of elements (e.g. GridsLevelsReferencePlanes) will execute prior to
Updaters reporting a priority for elements driven by these fundamental elements (e.g. Annotations). Reporting a proper change priority for
the elements which your Updater modifies benefits users of your application: Revit is less likely to have to execute the Updater a second
time due to changes made by another Updater.
For Updaters which report the same change priority, execution is ordered based on a sorting of UpdaterId. The method
UpdaterRegistry.SetExecutionOrder() allows you set the execution order between any two registered Updaters (even updaters registered by
other API add-ins) so long as your code knows the ids of the two Updaters.
Exposure to End-User
When updaters work as they should, they are transparent to the user. In some special cases though, Revit will display a warning to the user
concerning a 3rd party updater. Such messages will use the value of the GetUpdaterName() method to refer to the updater.
Updater not installed
If a document is modified by a non-optional updater and later loaded when that updater is not installed, a task dialog similar to the following
is displayed:
Commands
The Revit API provides access to existing Revit commands, either located on a tab, the application menu, or right-click menu. The main ways to work with Revit
commands using the API is to either replace the existing command implementation or to post a command.
Overriding a Revit command
The AddInCommandBinding class can be used to override an existing command in Revit. It has three events related to replacing the existing command
implementation.
BeforeExecuted- This read-only event occurs before the associated command executes. An application can react to this event but cannot make changes
to documents, or affect the invocation of the command.
CanExecute - Occurs when the associated command initiates a check to determine whether the command can be executed on the command target.
Executed - This event occurs when the associated command executes and is where any overriding implementation should be performed.
LookupCommandId - Retrieves the Revit command id with the given id string. To find the command id string, open a session of Revit, invoke the
desired command, close Revit, then look in the journal from that session. The "Jrn.Command" entry that was recorded
when it was selected will have the string needed for LookupCommandId() and will look something like "ID_EDIT_DESIGNOPTIONS".
LookupPostableCommandId - Retrieves the Revit command id using the PostableCommand enumeration. This only works for commands which are
postable (discussed in the following section).
The following example, taken from Revit 2014 SDK's DisableCommand sample, demonstrates how to create an AddInCommandBinding and override the
implementation to disable the command with a message to the user.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99. }
/// <summary>
/// Implements the OnShutdown event
/// </summary>
/// <param name="application"></param>
/// <returns></returns>
public Result OnShutdown(UIControlledApplication application)
{
// Remove the command binding on shutdown
if (s_commandId.HasBinding)
application.RemoveAddInCommandBinding(s_commandId);
return Result.Succeeded;
}
#endregion
/// <summary>
/// A command execution method which disables any command it is applied to (with a user-visible message).
/// </summary>
/// <param name="sender">Event sender.</param>
/// <param name="args">Arguments.</param>
private void DisableEvent(object sender, ExecutedEventArgs args)
{
ShowDialog("Disabled", "Use of this command has been disabled.");
}
/// <summary>
/// Show a task dialog with a message and title.
/// </summary>
/// <param name="title">The title.</param>
/// <param name="message">The message.</param>
private static void ShowDialog(string title, string message)
{
// Show the user a message.
TaskDialog td = new TaskDialog(title)
{
MainInstruction = message,
TitleAutoPrefix = false
};
td.Show();
}
/// <summary>
/// The string name of the command to disable. To lookup a command id string, open a session of Revit,
/// invoke the desired command, close Revit, then look to the journal from that session. The command
/// id string will be toward the end of the journal, look for the "Jrn.Command" entry that was recorded
/// when it was selected.
/// </summary>
static String s_commandToDisable = "ID_EDIT_DESIGNOPTIONS";
/// <summary>
/// The command id, stored statically to allow for removal of the command binding.
/// </summary>
static RevitCommandId s_commandId;
Posting a command
The method UIApplication.PostCommand() will post a command to the Revit message queue to be invoked when control returns from the current API
application. Only certain commands can be posted this way. They include all of the commands in the Autodesk.Revit.UI.PostableCommand enumerated type as
well as external commands created by any add-in.
Note that even a postable command may not execute when using PostCommand(). One reason this may happen is if another command has already been
posted. Only one command may be posted to Revit at a given time, so if a second command is posted, PostCommand() will throw an exception. Another
reason a posted command may not execute is if the command to be executed is not accessible at the time. Whether it is accessible is determined only at the
point where Revit returns from the API context, so a failure to execute for this reason will not be reported directly back to the application that posted the
command.
UIApplication.CanPostCommand() can be used to identify if the given command can be posted, meaning whether it is a member of PostableCommand or an
external command. It does not identify if the command is currently accessible.
Both PostCommand() and CanPostCommand() require a RevitCommandId which can be obtained as described in the "Overriding a Revit command" section
above.
Posting Failures
To use the failure posting mechanism to report problems, the following steps are required:
1. New failures not already defined in Revit must be defined and registered in the FailureDefinitionRegistry during the OnStartup() call of
the ExternalApplication.
2. Find the failure definition id, either from the BuiltInFailures classes or from the pre-registered custom failures using the class related
to FailureDefinition.
3. Post the failure to the document that has a problem using the classes related to FailureMessage to set options and details related to
the failure.
Defining and registering a failure
Each possible failure in Revit must be defined and registered during Revit application startup by creating a FailureDefinition object that
contains some persistent information about the failure such as identity, severity, basic description, types of resolution and default resolution.
The following example creates two new failures, a warning and an error, that can be used for walls that are too tall. In this example, they
are used in conjunction with an Updater that will do the failure posting (in a subsequent code sample in this chapter). The
FailureDefinitionIds are saved in the Updater class since they will be required when posting failures. The sections following explain the
FailureDefinition.CreateFailureDefinition() method parameters in more detail.
DocumentCorruption - Failure that forces the Transaction to be rolled back as soon as possible due to known corruption to a
document. When failure of this severity is posted, reading of information from a document is not allowed. The current transaction
must be rolled back first in order to work with the document. This severity is used only if there is known data corruption in the
document. This type of failure should generally be avoided unless there is no way to prevent corruption or to recover from it locally.
A fourth severity, None, cannot be specified when defining a new FailureDefinition.
Failure Resolutions
When a failure can be resolved, all possible resolutions should be predefined in the FailureDefinition class. This informs Revit what failure
resolutions can possibly be used with a given failure. The FailureDefinition contains a full list of resolution types applicable to the failure,
including a user-visible caption of the resolution.
The number of resolutions is not limited, however as of the 2011 Revit API, the only exposed failure resolution is DeleteElements. When
more than one resolution is specified, unless explicitly changed using the SetDefaultResolutionType() method, the first resolution added
becomes the default resolution. The default resolution is used by the Revit failure processing mechanism to resolve failures automatically
when applicable. The Revit UI only uses the default resolution, but Revit add-ins, via the Revit API, can use any applicable resolution, and
can provide an alternative UI for doing that (as described in the Handling Failures section later in this chapter).
In the case of a failure with a severity of DocumentCorruption, by the time failure resolution could occur, the transaction is already aborted,
so there is nothing to resolve. Therefore, FailureResolutions should not be added to API-defined Failures of severity DocumentCorruption.
Posting a failure
The Document.PostFailure() method is used to notify the document of a problem. Failures will be validated and possibly resolved at the end
of the transaction. Warnings posted via this method will not be stored in the document after they are resolved. Failure posting is used to
address a state of the document which may change before the end of the transaction or when it makes sense to defer resolution until the
end of the transaction. Not all failures encountered by an external command should post a failure. If the failure is unrelated to the document,
a task dialog should be used. For example, if the Revit UI is in an invalid state to perform the external command.
To post a failure, create a new FailureMessage using the FailureDefinitionId from when the custom failure was defined, or use a BuiltInFailure
provided by the Revit API. Set any additional information in the FailureMessage object, such as failing elements, and then call
Document.PostFailure() passing in the new FailureMessage. Note that the document must be modifiable in order to post a failure.
A unique FailureMessageKey returned by PostFailure() can be stored for the lifetime of transaction and used to remove a failure message if it
is no longer relevant. If the same FailureMessage is posted two or more times, the same FailureMessageKey is returned. If a posted failure
has a severity of DocumentCorruption, an invalid FailureMessageKey is returned. This is because a DocumentCorruption failure cannot be
unposted.
The following example shows an IUpdate class (referenced in the "Defining and registering a failure" code region above) that posts a new
failure based on information received in the Execute() method.
doc.PostFailure(failMessage);
}
else if (p.AsDouble() > 100)
{
FailureMessage failMessage = new FailureMessage(WarnId);
failMessage.SetFailingElement(id);
doc.PostFailure(failMessage);
}
}
}
}
public FailureDefinitionId FailureId
{
get { return m_failureId; }
set { m_failureId = value; }
}
public FailureDefinitionId WarnId
{
get { return m_warnId; }
set { m_warnId = value; }
}
public string GetAdditionalInformation()
{
return "Give warning and error if wall is too tall";
}
public ChangePriority GetChangePriority()
{
return ChangePriority.FloorsRoofsStructuralWalls;
}
public UpdaterId GetUpdaterId()
{
return m_updaterId;
}
public string GetUpdaterName()
{
return "Wall Height Check";
}
}
Removal of posted failures
Because there may be multiple changes to a document and multiple regenerations in the same transaction, it is possible that some failures
are no longer relevant and they may need to be removed to prevent "false alarms". Specific messages can be un-posted by calling the
Document.UnpostFailure() method and passing in the FailureMessageKey obtained when PostFailure() was called. UnpostFailure() will throw
an exception if the severity of the failure is DocumentCorruption.
It is also possible to automatically remove all posted failures when a transaction is about to be rolled back (so that the user is not bothered
to hit Cancel) by using the Transaction.SetFailureHandlingOptions() method.
Handling Failures
Normally posted failures are processed by Revit's standard failure resolution UI at the end of a transaction (specifically when
Transaction.Commit() or Transaction.Rollback() are invoked). The user is presented information and options to deal with the failures.
If an operation (or set of operations) on the document requires some special treatment from a Revit add-in for certain errors, failure
handling can be customized to carry out this resolution. Custom failure handling can be supplied:
For a given transaction using the interface IFailuresPreprocessor.
For all possible errors using the FailuresProcessing event.
Finally, the API offers the ability to completely replace the standard failure processing user interface using the interface IFailuresProcessor.
Although the first two methods for handling failures should be sufficient in most cases, this last option can be used in special cases, such as
to provide a better failure processing UI or when an application is used as a front-end on top of Revit.
Overview of Failure Processing
It is important to remember there are many things happening between the call to Transaction.Commit() and the actual processing of
failures. Auto-join, overlap checks, group checks and workset editability checks are just to name a few. These checks and changes may
make some failures disappear or, more likely, can post new failures. Therefore, conclusions cannot be drawn about the state of failures to be
processed when Transaction.Commit() is called. To process failures correctly, it is necessary to hook up to the actual failures processing
mechanism.
When failures processing begins, all changes to a document that are supposed to be made in the transaction are made, and all failures are
posted. Therefore, no uncontrolled changes to a document are allowed during failures processing. There is a limited ability to resolve failures
via the restricted interface provided by FailuresAccessor. If this has happened, all end of transaction checks and failures processing have to
be repeated. So there may be a few failure resolution cycles at the end of one transaction.
Each cycle of failures processing includes 3 steps:
1. Preprocessing of failures (FailuresPreprocessor)
2. Broadcasting of failures processing event (FailuresProcessing event)
3. Final processing (FailuresProcessor)
Each of these 3 steps can control what happens next by returning different FailureProcessingResults. The options are:
Continue - has no impact on execution flow. If FailuresProcessor returns "Continue" with unresolved failures, Revit will instead act as
if "ProceedWithRollBack" was returned.
ProceedWithCommit - interrupts failures processing and immediately triggers another loop of end-of-transaction checks followed by
another failures processing. Should be returned after an attempt to resolve failures. Can easily lead to an infinite loop if returned
without any successful failure resolution. Cannot be returned if transaction is already being rolled back and will be treated as
"ProceedWithRollBack" in this case.
ProceedWithRollback - continues execution of failure processing, but forces transaction to be rolled back, even if it was originally
requested to commit. If before ProceedWithRollBack is returned FailureHandlingOptions are set to clear errors after rollback, no
further error processing will take place, all failures will be deleted and transaction is rolled back silently. Otherwise default failure
processing will continue, failures may be delivered to the user, but transaction is guaranteed to be rolled back.
WaitForUserInput - Can be returned only by FailuresProcessor if it is waiting for an external event (typically user input) to complete
failures processing.
Depending on the severity of failures posted in the transaction and whether the transaction is being committed or rolled back, each of these
3 steps may have certain options to resolve errors. All information about failures posted in a document, information about ability to perform
certain operations to resolve failures and API to perform such operations are provided via the FailuresAccessor class. The Document can be
used to obtain additional information, but it cannot be changed other than via FailuresAccessor.
FailuresAccessor
A FailuresAccessor object is passed to each of failure processing steps as an argument and is the only available interface to fetch information
about failures in a document. While reading from a document during failure processing is allowed, the only way to modify a document during
failure resolution is via methods provided by this class. After returning from failure processing, the instance of the class is deactivated and
cannot be used any longer.
Information Available from FailuresAccessor
The FailuresAccessor object offers some generic information such as:
Document for which failures are being processed or preprocessed
Highest severity of failures posted in the document
Transaction name and failure handling options for transaction being finished
Whether transaction was requested to be committed or rolled back.
The FailuresAccessor object also offers information about specific failures via the GetFailuresMessages() method.
Options to resolve failures
The FailuresAccessor object provides a few ways to resolve failures:
Failure messages with a severity of Warning can be deleted with the DeleteWarning() or DeleteAllWarnings() methods.
ResolveFailure() or ResolveFailures() methods can be used to resolve one or more failures using the last failure resolution type set for
each failure.
DeleteElements() can resolve failures by deleting elements related to the failure.
Or delete all failure messages and replace them with one "generic" failure using the ReplaceFailures() method.
IFailuresPreprocessor
The IFailuresPreprocessor interface can be used to provide custom failure handling for a specific transaction only. IFailuresPreprocessor is an
interface that may be used to perform a preprocessing step to either filter out anticipated transaction failures or to post new failures.
Failures can be "filtered out" by:
silently removing warnings that are known to be posted for the transaction and are deemed as irrelevant for the user in the context of
a particular transaction
silently resolving certain failures that are known to be posted for the transaction and that should always be resolved in a context of a
given transaction
silently aborting the transaction in cases where "imperfect" transactions should not be committed or aborting the transaction is
preferable over user interaction for a given workflow.
The IFailuresPreprocessor interface gets control first during the failure resolution process. It is nearly equivalent to checking and resolving
failures before finishing a transaction, except that IFailuresPreprocessor gets control at the right time, after all failures guaranteed to be
posted and/or after all irrelevant ones are deleted.
There may be only one IFailuresPreprocessor per transaction and there is no default failure preprocessor. If one is not attached to the
transaction (via the failure handling options), this first step of failure resolution is simply omitted.
}
}
return FailureProcessingResult.Continue;
}
}
FailuresProcessing Event
The FailuresProcessing event is most suitable for applications that want to provide custom failure handling without a user interface, either for
the entire session or for many unrelated transactions. Some use cases for handling failures via this event are:
automatic removal of certain warnings and/or automatic resolving of certain errors based on office standards (or other criteria)
custom logging of failures
The FailuresProcessing event is raised after IFailuresPreprocessor (if any) has finished. It can have any number of handlers, and all of them
will be invoked. Since event handlers have no way to return a value, the SetProcessingResult() on the event argument should be used to
communicate status. Only Continue, ProceedWithRollback or ProceedWithCommit can be set.
The following example shows an event handler for the FailuresProcessing event.
The following example of implementing the IFailuresProcessor checks for a failure, deletes the failing elements and sets an appropriate
message for the user.
Performance Adviser
The performance adviser feature of the Revit API is designed to analyze a document and flag for the user any elements and/or settings that may cause
performance degradation. The Performance Adviser command executes a set of rules and displays their result in a standard review warnings dialog.
The API for performance adviser consists of 2 classes:
PerformanceAdviser - an application-wide object that has a dual role as a registry of rules to run in order to detect potential performance problems
and an engine to execute them
IPerformanceAdviserRule - an interface that allows you to define new rules for the Performance Adviser
Performance Adviser
PerformanceAdviser is used to add or delete rules to be checked, enable and disable rules, get information about rules in the list, and to execute some or all
rules in the list. Applications that create new rules are expected to use AddRule() to register the new rule during application startup and DeleteRule() to
deregister it during application shutdown. ExecuteAllRules() will execute all rules in the list on a given document, while ExecuteRules() can be used to execute
selected rules in a document. Both methods will return a list of failure messages explaining performance problems detected in the document.
The following example demonstrates looping through all performance adviser rules and executing all the rules for a document.
Code Region: Performance Adviser
view plaincopy to clipboardprint?
1.
2.
3.
4.
5.
6.
//Get the name of each registered PerformanceRule and then execute all of them.
foreach (PerformanceAdviserRuleId id in PerformanceAdviser.GetPerformanceAdviser().GetAllRuleIds())
{
string ruleName = PerformanceAdviser.GetPerformanceAdviser().GetRuleName(id);
}
PerformanceAdviser.GetPerformanceAdviser().ExecuteAllRules(document);
IPerformanceAdviserRule
Create an instance of the IPerformanceAdviserRule interface to create new rules for the Performance Adviser. Rules can be specific to elements or can be
document-wide rules. The following methods need to be implemented:
The following excerpt from the PerformanceAdviserControl sample in the Revit API SDK Samples folder demonstrates the implementation of a custom rule
used to identify any doors in the document that are face-flipped. (See the sample project for the complete class implementation.)
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
/// </summary>
/// <param name="document">The document being checked</param>
public void InitCheck(Autodesk.Revit.DB.Document document)
{
if (m_FlippedDoors == null)
m_FlippedDoors = new List<Autodesk.Revit.DB.ElementId>();
else
m_FlippedDoors.Clear();
return;
}
/// <summary>
/// This method does most of the work of the IPerformanceAdviserRule implementation.
/// It is called by PerformanceAdviser.
/// It examines the element passed to it (which was previously filtered by the filter
/// returned by GetElementFilter() (see below)). After checking to make sure that the
/// element is an instance, it checks the FacingFlipped property of the element.
///
/// If it is flipped, it adds the instance to a list to be used later.
/// </summary>
/// <param name="document">The active document</param>
/// <param name="element">The current element being checked</param>
public void ExecuteElementCheck(Autodesk.Revit.DB.Document document, Autodesk.Revit.DB.Element element)
{
if ((element is Autodesk.Revit.DB.FamilyInstance))
{
Autodesk.Revit.DB.FamilyInstance doorCurrent = element as Autodesk.Revit.DB.FamilyInstance;
if (doorCurrent.FacingFlipped)
m_FlippedDoors.Add(doorCurrent.Id);
}
}
/// <summary>
/// This method is called by PerformanceAdviser after all elements in document
/// matching the ElementFilter from GetElementFilter() are checked by ExecuteElementCheck().
///
/// This method checks to see if there are any elements (door instances, in this case) in the
/// m_FlippedDoor instance member. If there are, it iterates through that list and displays
/// the instance name and door tag of each item.
/// </summary>
/// <param name="document">The active document</param>
public void FinalizeCheck(Autodesk.Revit.DB.Document document)
{
if (m_FlippedDoors.Count == 0)
System.Diagnostics.Debug.WriteLine("No doors were flipped. Test passed.");
else
{
//Pass the element IDs of the flipped doors to the revit failure reporting APIs.
Autodesk.Revit.DB.FailureMessage fm = new Autodesk.Revit.DB.FailureMessage(m_doorWarningId);
fm.SetFailingElements(m_FlippedDoors);
Autodesk.Revit.DB.Transaction failureReportingTransaction = new Autodesk.Revit.DB.Transaction(document, "Failu
re reporting transaction");
72.
failureReportingTransaction.Start();
73.
document.PostFailure(fm);
74.
failureReportingTransaction.Commit();
75.
m_FlippedDoors.Clear();
76.
}
77.
}
78.
79.
/// <summary>
80.
/// Gets the description of the rule
81.
/// </summary>
82.
/// <returns>The rule description</returns>
83.
public string GetDescription()
84.
{
85.
return m_description;
86.
}
87.
88.
/// <summary>
89.
/// This method supplies an element filter to reduce the number of elements that PerformanceAdviser
90.
/// will pass to GetElementCheck(). In this case, we are filtering for door elements.
91.
/// </summary>
92.
/// <param name="document">The document being checked</param>
93.
/// <returns>A door element filter</returns>
94.
public Autodesk.Revit.DB.ElementFilter GetElementFilter(Autodesk.Revit.DB.Document document)
95.
{
96.
return new Autodesk.Revit.DB.ElementCategoryFilter(Autodesk.Revit.DB.BuiltInCategory.OST_Doors);
97.
}
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
/// <summary>
/// Gets the name of the rule
/// </summary>
/// <returns>The rule name</returns>
public string GetName()
{
return m_name;
}
/// <summary>
/// Returns true if this rule will iterate through elements and check them, false otherwise
/// </summary>
/// <returns>True</returns>
public bool WillCheckElements()
{
return true;
}
}
#endregion
Point Clouds
The Revit API provides 2 ways to work with point clouds. The first way allows you to create new point cloud instances, read and filter points, select sub-sets of
the overall points, and select points to be highlighted or isolated. The second way allows you to use your own point cloud engine and process unsupported file
formats (i.e. other than .pcg, .rcp or .rcs), providing points to Revit for the user to see.
Client API
o Create new Point Cloud instances
o Read & Filter Points
o Point Set Selection
o Control Point Cloud highlighting
Engine API
o Register Point Cloud file extension
o Provide points to Revit for rendering
PointCloudType - type of point cloud loaded into a Revit document. Each PointCloudType maps to a single file or identifier (depending upon the type
of Point Cloud Engine which governs it).
PointCloudInstance - an instance of a point cloud in a location in the Revit project.
PointCloudFilter - a filter determining the volume of interest when extracting points.
PointCollection - a collection of points obtained from an instance and a filter.
PointIterator - an iterator for the points in a PointCollection.
CloudPoint - an individual point cloud point, representing an X, Y, Z location in the coordinates of the cloud, and a color.
PointCloudOverrides - and its related settings classes specify graphic overrides that are stored by a view to be applied to a PointCloudInstance
element, or a scan within the element.
To create a new point cloud in a Revit document, create a PointCloudType and then use it to create a PointCloudInstance. The static PointCloudType.Create()
method requires the engine identifier, as it was registered with Revit by a third party, or the file extension of the point cloud file, if it is a supported file type. It
also requires a file name or the identification string for a non-file based engine. In the following sample, a pcg file is used to create a point cloud in a Revit
document.
Note that as a result of search algorithms used by Revit and the point cloud engine, the exact requested number of points may not be returned.
Although the second option involves dealing with pointers directly, there may be performance improvements when traversing large buffers of points.
However, this option is only possible from C# and C++/CLI.
The following two examples show how to iterate part of a point cloud using on one of these two methods.
6.
7.
8.
9.
10.
11.
12. }
Number of p
Filters
Filters are used both to limit the volume which is searched when reading points, and also to govern the display of point clouds. A PointCloudFilter can be
created based upon a collection of planar boundaries. The filter will check whether a point is located on the positive side of each input plane, as indicated by
the positive direction of the plane normal. Therefore, such filter implicitly defines a volume, which is the intersection of the positive half-spaces corresponding
to all the planes. This volume does not have to be closed, but it will always be convex.
The display of point clouds can be controlled by assigning a filter to:
PointCloudInstance.SetSelectionFilter()
Display of the filtered points will be based on the value of the property:
PointCloudInstance.FilterAction
If it is set to None, the selection filter is ignored. If it is set to Highlight, points that pass the filter are highlighted. If it is set to Isolate, only points that pass the
filter will be visible.
The following example will highlight a subset of the points in a point cloud based on its bounding box.
This is the result when the sample above is run on a small pipe point cloud:
An .rcp file can contain multiple scans. The method PointCloudInstance.GetScans() returns a list of scan names which can be used to set visibility and fixed color
overrides independently for each scan in the PointCloudInstance. PointCloudInstance.ContainsScan() indicates whether the given scan name is contained in the
point cloud instance while PointCloudInstance.GetScanOrigin() will return the origin of the given scan in model coordinates.
Overrides
Point cloud override settings assigned to a given view can be modified using the Revit API. These settings correspond to the settings on the Point Clouds tab of
the Visibility/Graphics Overrides task pane in the Revit UI. Overrides can be applied to an entire point cloud instance, or to specific scans within that instance.
Options for the overrides include setting visibility for scans in the point cloud instance, setting it to a fixed color, or to color gradients based on elevation,
normals, or intensity. The property PointCloudInstance.SupportsOverrides identifies point clouds which support override settings (clouds which are based on
.rcp or .rcs files).
The following classes are involved in setting the overrides for point clouds:
In order to supply the points of the point cloud to Revit, there are two ReadPoints() methods which must be implemented:
IPointCloudAccess.ReadPoints() - this provides a single set of points in a one-time call, either from Revit or the API. Revit uses this during some display
activities including selection pre-highlighting. It is also possible for API clients to call this method directly via PointCloudInstance.GetPoints().
IPointSetIterator.ReadPoints() - this provides a subset of points as a part of a larger iteration of points in the cloud. Revit uses this method during
normal display of the point cloud; quantities of points will be requested repeatedly until it obtains enough points or until something in the display
changes. The engine implementation must keep track of which points have been returned to Revit during any given point set iteration.
See the PointCloudEngine folder under the Samples directory included with the Revit API SDK for a complete example of registering and implementing both filebased and non-file-based point cloud engines.
Analysis
Energy Data
The EnergyDataSettings object represents the gbXML Parameters in the Revit project. To view the parameters, from the Revit UI, select
Project Information from the Project Settings panel on the Manage tab. The Project Information dialog box appears.
Analysis Visualization
The Revit API provides a mechanism for external analysis applications to easily display the results of their computation in the Revit model.
The SpatialFieldManager class is the main class for communicating analysis results back to Revit. It is used to create, delete, and modify the
"containers" in which the analysis results are stored. The AnalysisResultSchema class contains all information about one analysis result,
such as a description and the names and multipliers of all units for result visualization. Multiple AnalysisResultSchemas can be registered
with the SpatialFieldManager.
The AnalysisDisplayStyle class can then be used to control the appearance of the results. Creation and modification of AnalysisDisplayStyle
from a plug-in is optional; end users can have the same control over the presentation of the analysis results with the Revit UI.
The data model supported by Revit API requires that analysis results are specified at a certain set of points, and that at each point one or
more distinct numbers ("measurements") are computed. The number of measurements must be the same at all model points. The results
data is transient; it is stored only in the model until the document is closed. If the model is saved, closed, and reopened the analysis results
will not be present.
Once the AnalysisResultschema is configured, it needs to be registered using the SpatialFieldManager.RegisterResult() method, which will
return a unique index for the result. Use GetResultSchema() and SetResultSchema() using this unique index to get and change the result
after it has been registered.
The following example creates a simple set of analysis results on an element face selected by the user. The SDK sample SpatialFieldGradient
demonstrates a more complex use case where each point has multiple associated values.
The following example creates a new colored surface analysis display style (if not already found in the document) and then assigns it to the
current view.
MassEnergyAnalyticalModel - associates a mass instance with energy analytical model data and geometry.
MassLevelData - conceptual representation of an occupiable floor (Mass Floor) in a conceptual building model.
MassSurfaceData - holds properties and other data about a face in the MassEnergyAnalyticalModel element
MassZone - conceptual representations of individually heated and cooled sub-volumes of a building.
ConceptualConstructionType - describes the conceptual physical, construction and energy properties in a manner that can be understood by both the
Revit BIM model and Green Building Studio/Green Building XML.
ConceptualSurfaceType - represents a conceptual BIM object category to assign to faces in Mass geometries.
In addition to these classes, there is a Document.Export() overload that takes a MassGBXMLExportOptions parameter which exports a gBXML file containing
conceptual energy analysis elements (mass elements) only.
MassEnergyAnalyticalModel
The main class associated with conceptual energy analysis is MassEnergyAnalyticalModel. This class associates a mass instance with energy analytical model
data and geometry. The geometry begins as a copy of its associated mass instance geometry and is modified according to the requirements of the energy
analytical model. The static method MassEnergyAnalyticalModel. GetMassEnergyAnalyticalModelIdForMassInstance() will return the ElementId for the
MassEnergyAnalyticalModel for a given mass instance.
MassLevelData
A MassLevelData is defined by associating a particular level with a particular mass element in a Revit project. This can be done using the
MassInstanceUtils.AddMassLevelDataToMassInstance() method. MassLevelData reports metrics, such as floor areas, related to conceptual space planning.
MassLevelData contains information, such as ConceptualConstructionType, used as part of the Conceptual Energy Analytical model. The MassLevel data
geometry is determined by combining all the geometry of a mass into a single geometry, and then taking the area of intersection with the level of the
MassLevelData.
MassZones
MassZones are created by dividing a MassEnergyAnalyticalModel into pieces by intersecting MassLevelDatas associated with a Mass FamilyInstance with the
geometries of the MassEnergyAnalyticalModel associated with the same Mass FamilyInstance. ElementIds of the MassZones associated with a
MassEnergyAnalyticalModel can be retrieved using the GetMassZoneIds() method.
MassSurfaceData
From a MassEnergyAnalyticalModel, you can get References to all Faces which are meaningful for it. Using these references, you can get the MassSurfaceData
associated with each one using the GetMassSurfaceDataIdForReference() method. MassSurfaceData holds properties and other data about a face in the
MassEnergyAnalyticalModel element, such as the material value, and dimensions of auto-generated elements such as sill height, and skylight width.
MassSurfaceData also holds the id of the ConceptualConstructionType associated with the reference surface. ConceptualConstructionType describes the
conceptual physical, construction, and energy properties in a manner that can be understood by both the Revit BIM model and Green Building Studio/Green
Building XML. This class has numerous static methods to get the ElementId of the ConceptualConstructionType for different aspects of a building (such as walls
and windows) in a given document.
Another property of MassSurfaceData is CategoryIdForConceptualSurfaceType which provides the mass subcategory ElementId used for
its ConceptualSurfaceType. ConceptualSurfaceType represents a conceptual BIM object category to assign to faces in Mass geometries. There is one
ConceptualSurfaceType element for each of the Mass Surface Subcategories. Using the static method ConceptualSurfaceType.GetByMassSubCategoryId(), the
ConceptualSurfaceType for a MassSurfaceData can be obtained from the mass subcategory id.
When Conceptual Energy Analysis is enabled in a Revit Project, massing faces will be assigned to the subcategories of Mass category with which these
ConceptualSurfaceType's are associated. A default ConceptualConstructionType is associated with the ConceptualSurfaceType. This default
ConceptualConstructionType is assigned to Mass faces with the corresponding subcategory. Changing the default ConceptualConstructionType associated with
the ConceptualSurfaceType will update the ConceptualConstruction type for all Mass faces of that subcategory for which the user has not specifically provided
an override value.
MassInstanceUtils
The MassInstancesUtils utility class provides static methods to get information about a mass instance, such as the total occupiable floor area or total building
volume represented by a mass instance, as well as to create a MassLevelData (Mass Floor) to associate a Level with a mass instance as discussed above.
EnergyAnalysisDetailModel
EnergyAnalysisDetailModelOptions
EnergyAnalysisOpening
EnergyAnalysisSpace
EnergyAnalysisSurface
Polyloop
Use the static method EnergyAnalysisDetailModel.Create() to create and populate the energy analysis model. Set the appropriate options using the
EnergyAnalysisDetailModelOptions. The generated model is always returned in world coordinates, but the method TransformModel() transforms all surfaces in
the model according to ground plane, shared coordinates and true north.
The options available when creating the energy analysis detail model include:
The level of computation for energy analysis model - NotComputed, FirstLevelBoundaries, meaning analytical spaces and zones,
SecondLevelBoundaries, meaning analytical surfaces, or Final, meaning constructions, schedules, and non-graphical data
Whether mullions should be exported as shading surfaces
Whether shading surfaces will be included
Whether to simplify curtain systems - When true, a single large window/opening will be exported for a curtain wall/system regardless of the number of
panels in the system
The following example creates a new energy analysis detailed model from the physical model then displays the originating element for each surface of each
space in the model.
After creating the EnergyAnalysisDetailModel, the spaces, openings and surfaces associated with it can be retrieved with the GetAnalyticalOpenings(),
GetAnalyticalSpaces(), GetAnalyticalShadingSurfaces() and GetAnalyticalSurfaces() methods.
Be sure to call EnergyAnalysisDetailModel.Destroy() to clean up the Revit database after finishing with the analysis results.
EnergyAnalysisSpace
From an EnergyAnalysisSpace you can retrieve the collection of EnergyAnalysisSurfaces which define an enclosed volume bounded by the center plane of walls
and the top plane of roofs and floors. Alternatively, GetClosedShell() retrieves a collection of Polyloops, which are planar polygons, that define an enclosed
volume measured by interior bounding surfaces. For two-dimensions, use GetBoundary() which returns a collection of Polyloops representing the 2D
boundary of the space that defines an enclosed area measured by interior bounding surfaces.
The EnergyAnalysisSpace class also has a number of properties for accessing information about the analysis space, such as AnalyticalVolume, Name and Area.
EnergyAnalysisSurface
From an EnergyAnalysisSpace you can retrieve the primary analysis space associated with the surface as well as the secondary adjacent analytical space. The
GetAnalyticalOpenings() method will retrieve a collection of all analytical openings in the surface. The GetPolyloop() method obtains the planar polygon
describing the surface geometry as described in gbXML.
The EnergyAnalysisSpace class has numerous properties to provide more information about the analytical surface, such as Height, Width, Corner (lower-left
coordinate for the analytical rectangular geometry viewed from outside), and an originating element description.
The surface type is available either as an EnergyAnalysisSurfaceType or as a gbXMLSurfaceType. The gbXML surface type attribute is determined by the source
element and the number of space adjacencies. Possible types are:
Type
Shade
Air
ExteriorWall
InteriorWall
Source element is a Wall or a Curtain Wall and: there are two space adjacencies or the type Function parameter is set to "Interior"
or "CoreShaft"
UndergroundWall
Source element is a Wall or a Curtain Wall and there is one space adjacency and if it is below grade
SlabOnGrade
RaisedFloor
Source element is a Floor and there is one space adjacency and it is above grade
UndergroundSlab
Source element is a Floor and there is one space adjacency and it is below grade
InteriorFloor
Source element is a Floor and: there are two space adjacencies or the type Function parameter is set to "Interior
Roof
UndergroundCeiling
Source element is a Roof or a Ceiling and there is one space adjacency and it is below grade
Ceiling
Source element is a Roof or a Ceiling and there are two space adjacencies
EnergyAnalysisOpening
From an EnergyAnalysisOpening you can retrieve the associated parent analytical surface element. The GetPolyloop() method returns the opening geometry as
a planar polygon.
A number of properties are available to obtain information about the analytical opening, such as Height, Width, Corner and Name. Similar as for analytical
surfaces, the analytical opening type can be obtained as a simple EnergyAnalysisOpeningType enumeration or as a gbXMLOpeningType attribute. The type of
the opening is based on the family category for the opening and in what element it is contained, as shown in the following table:
Type
OperableWindow
Window
NonSlidingDoor
Door
FixedSkylight
FixedWindow
Air
Place
In the Revit Platform API, the SiteLocation class contains place information including Latitude, Longitude, and Time Zone. This information
identifies where the project is located in the world. When setting either the Latitude or Longitude, note that:
1. Revit will attempt to match the coordinates to a city it knows about, and if a match is found, will set the name accordingly.
2. Revit will attempt to automatically adjust the time zone value to match the new Longitude or Latitude value set using
SunAndShadowSettings.CalculateTimeZone(). For some boundary cases, the time zone calculated may not be correct and the
TimeZone property can be set directly if necessary.
City
City is an object that contains geographical location information for a known city in the world. It contains longitude, latitude, and time zone
information. The city list is retrieved by the Cities property in the Application object. New cities cannot be added to the existing list in Revit.
The city where the current project is located is not exposed by the Revit Platform API.
ProjectLocation
A project only has one site which is the absolute location on the earth. However, it can have different locations relative to the projects
around it. Depending on the coordinates and origins in use, there can be many ProjectLocation objects in one project.
By default each Revit project contains at least one named location, Internal. It is the active project location. You can retrieve it using the
Document.ActiveProjectLocation property. All existing ProjectLocation objects are retrieved using the Document.ProjectLocations property.
Project Position
Project position is an object that represents a geographical offset and rotation. It is usually used by the ProjectLocation object to get and set
geographical information. The following figure shows the results after changing the ProjectLocation geographical rotation and the coordinates
for the same point. However, you cannot see the result of changing the ProjectLocation geographical offset directly.
between 180 and 360 degrees, Revit transforms it automatically. For example, if you select East and type 200 degrees for Angle, Revit
transforms it to West 160 degrees
The following sample code illustrates how to retrieve the ProjectLocation object.
Note There is only one active project location at a time. To see the result after changing the ProjectLocation geographical offset and rotation,
change the Orientation property from Project North to True North in the plan view Properties dialog box.
Figure 127: Set orientation value in plan view Properties dialog box
Figure 128: Project is rotated 30 degrees from Project North to True North
The following code sample illustrates how to delete an existing project location from the current project.
The active project location cannot be deleted because there must be at least one project location in the project.
You cannot delete the project location if the ProjectLocationSet class instance is read-only.
Worksharing
Worksharing is a design method that allows multiple team members to work on the same project model at the same time. When worksharing is enabled, a
Revit document can be subdivided into worksets, which are collections of elements in the project.
Elements in Worksets
Each element in the document must belong to one and only one workset. Each element has a WorksetId which identifies the unique workset to which it
belongs. Additionally, given a WorksetId, it is possible to get all of the elements in the document belonging to that Workset using the ElementWorksetFilter as
shown below.
Worksharing information such as the current owner and checkout status of an element can be obtained using the WorksharingUtils class. It is a static class that
contains utility functions related to worksharing.
Element Ownership
The WorksharingUtils class can be used to modify element and workset ownership. The CheckoutElements() method obtains ownership for the current user of
as many specified elements as possible, while the CheckoutWorksets() method does the same for worksets. The RelinquishOwnership() method relinquishes
elements and worksets owned by the current user based on the specified RelinquishOptions.
For best performance, checkout all elements or worksets and relinquish items in one big call, rather than many small calls.
Note: When checking out an element, Revit may check out additional elements that are needed to make the requested element editable. For example, if an
element is in a group, Revit will checkout the entire group.
In the following example, all rooms in the document are checked out to the current user.
The next example demonstrates checking out all the view worksets.
The following example hides a workset in a given view and hides it by default in other views.
In addition to getting and setting information about the workset visibility, the View class also provides methods to access information on the worksharing
display mode and settings. The WorksharingDisplayMode enumeration indicates which mode a view is in, if any:
Member Name
Description
Off
CheckoutStatus
Owners
ModelUpdates
Worksets
The WorksharingDisplaySettings class controls how elements will appear when they are displayed in any of the worksharing display modes. The colors stored in
these settings are a common setting and are shared by all users in the model. Whether a given color is applied is specific to the current user and will not be
shared by other users. Note that these settings are available even in models that are not workshared. This is to allow pre-configuring the display settings
before enabling worksets so that they can be stored in template files.
The overloaded method WorksharingDisplaySettings.SetGraphicOverrides() sets the graphic overrides assigned to elements based on the given criteria.
displaySettings.SetGraphicOverrides(CheckoutStatus.NotOwned, graphicSettings);
// set a new graphicSettings for ModelUpdatesStatus - CurrentWithCentral
graphicSettings = new WorksharingDisplayGraphicSettings(true, new Color(128, 128, 0));
displaySettings.SetGraphicOverrides(ModelUpdatesStatus.CurrentWithCentral, graphicSettings);
// set a new graphicSettings by a given userName
graphicSettings = new WorksharingDisplayGraphicSettings(true, new Color(0, 255, 0));
displaySettings.SetGraphicOverrides(userName, graphicSettings);
// set a new graphicSettings by a given workset Id
graphicSettings = new WorksharingDisplayGraphicSettings(true, new Color(0, 0, 255));
displaySettings.SetGraphicOverrides(worksetId, graphicSettings);
The WorksharingDisplaySettings class can also be used to control which users are listed in the displayed users for the document. The RemoveUsers() method
removes users from the list of displayed users and permanently discards any customization of the graphics. Only users who do not own any elements in the
document can be removed. The RestoreUsers() method adds removed users back to the list of displayed users and permits customization of the graphics for
those users. Note that any restored users will be shown with default graphic overrides and any customizations that existed prior to removing the user will not
be restored.
Worksets
Worksets are a way to divide a set of elements in the Revit document into subsets for worksharing. There may be one or many worksets in a document.
The document contains a WorksetTable which is a table containing references to all the worksets contained in that document. There is one WorksetTable for
each document. There will be at least one default workset in the table, even if worksharing has not been enabled in the document. The
Document.IsWorkshared property can be used to determine if worksharing has been enabled in the document.
The FilteredWorksetCollector is used to search, filter and iterate through a set of worksets. Conditions can be assigned to filter the worksets that are returned.
If no condition is applied, this filter will access all of the worksets in the document. The WorksetKind enumerator is useful for filtering worksets as shown in
the following example:
As shown in the previous example, the Workset class provides many properties to get information about a given workset, such as the owner and whether or
not the workset is editable.
If a document is not already workshared, which can be determined from the Document.IsWorkshared property, worksharing can be enabled via the Revit API
using the Document.EnableWorksharing() method. The document's Undo history will be cleared by this command, therefore this command and others
executed before it cannot be undone. Additionally, all transaction phases (e.g. transactions, transaction groups and sub-transactions) that were explicitly
started must be finished prior to calling EnableWorksharing().
Reload Latest
The method Document.ReloadLatest() retrieves changes from the central model (due to one or more synchronizations with central) and merges them into the
current session.
The following examples uses ReloadLatest() to update the current session, and then calls Document.HasAllChangesFromCentral() to confirm that there were no
synchronizations with central performed during execution of ReloadLatest.
The method Document.SynchronizeWithCentral() reloads any changes from the central model so that the current session is up to date and then saves local
changes back to central. A save to central is performed even if no changes were made.
When using SynchronizeWithCentral(), options can be specified for accessing the central model as well as synchronizing with it. The main option for accessing
the central is to determine how the call should behave if the central model is locked. Since the synchronization requires a temporary lock on the central model,
it cannot be performed if the model is already locked. The default behavior is to wait and repeatedly try to lock the central model in order to proceed with the
synchronization. This behavior can be overridden using the TransactWithCentralOptions parameter of the SynchronizeWithCentral() method.
The SynchronizeWithCentralOptions parameter of the method is used to set options for the actual synchronization, such as whether elements or worksets
owned by the current user should be relinquished during synchronization.
In the following example, an attempt is made to synchronize with a central model. If the central model is locked, it will immediately give up.
The WorksharingUtils.CreateNewLocal() method copies a central model to a new local file. This method does not open the new file.
Construction Modeling
The Revit API allows elements to be divided into sub-parts or collected into assemblies to support construction modeling workflows, much the same way as can
be done with the Revit user interface. Both parts and assemblies can be independently scheduled, tagged, filtered, and exported. You can also divide a part
into smaller parts. After creating an assembly type, you can place additional instances in the project and generate isolated assembly views.
The main classes related to Construction Modeling are:
AssemblyInstance - This class combines multiple elements for tagging, filtering, scheduling and creating isolated assembly views.
AssemblyType - Represents a type for construction assembly elements. Each new unique assembly created in the project automatically creats a
corresponding AssemblyType. A new AssemblyInstance can be placed in the document from an existing AssemblyType.
PartUtils - This utility class contains general part utility methods, including the ability to create parts, divide parts, and to get information about parts.
AssemblyViewUtils - A utility class to create various types of assembly views.
The static Create() method of the AssemblyInstance class is used to create a new assembly instance in the project. The Create() method must be created inside
a transaction and the transaction must be committed before performing any action on the newly created assembly instance. The assembly type is assigned
after the transaction is complete.
The following example creates a new assembly instance, changes the name of its AssemblyType and then creates some views for the assembly instance.
Another way to create an AssemblyInstance is to use an existing AssemblyType. To create an AssemblyInstance using an AssemblyType, use the static method
AssemblyInstance.PlaceInstance() and specify the ElementId of the AssemblyType to use and a location at which to place the assembly.
Assembly Views
Various assembly views can be created for an assembly instance using the AssemblyViewUtils class, including an orthographic 3D assembly view, a detail
section assembly view, a material takeoff multicategory schedule assembly view, a part list multicategory schedule assembly view, and a sheet assembly view.
The document must be regenerated before using any of these newly created assembly views. You'll note in the example above that a transaction is committed
after creating two new assembly views. The Commit() method automatically regenerates the document.
Parts
Parts can be generated from elements with layered structures, such as:
In the Revit API, elements can be divided into parts using the PartUtils class. The static method PartUtils.CreateParts() is used to create parts from one or more
elements. Note that unlike most element creation methods in the API, CreateParts() does not actually create or return the parts, but rather instantiates an
element called a PartMaker. The PartMaker uses its embedded rules to drive creation of the needed parts during regeneration.
The API also offers an interface to subdivide parts. PartUtils.DivideParts() accepts as input a collection of part ids, a collection of intersecting element ids
(which can be layers and grids), and a collection of curves. The routine uses the intersecting elements and curves as boundaries from which to divide and
generate new parts.
The GetAssociatedParts() method can be called to find some or all of the parts associated with an element, or use HasAssociatedParts() to determine if an
element has parts.
You can delete parts through the API either by deleting the individual part elements, or by deleting the PartMaker associated to the parts (which will delete all
parts generated by this PartMaker after the next regeneration).
Parts can be manipulated in the Revit API much the same as they can in the Revit user interface. For example, the outer boundaries of parts may be offset with
PartUtils.SetFaceOffset().
The following example offsets all the faces of a part that can be offset.
Linked Files
The Revit API can determine which elements in Revit are references to external files ("linked files") and can make some modifications to how Revit loads
external files.
An Element which contains an ExternalFileReference is an element which refers to some file outside of the base .rvt file. Examples include Revit links, CAD
links, the element which stores the location of the keynote file, and rendering decals. Element.IsExternalFileReference() returns whether or not an element
represents an external file. And Element.GetExternalFileReference() returns the ExternalFileReference for a given Element which contains information
pertaining to the external file referenced by the element.
The following classes are associated with linked files in the Revit API:
ExternalFileReference - A non-Element class which contains path and type information for a single external file which a Revit project references.
ExternalFileUtils - A utility class which allows the user to find all external file references, get the external file reference from an element, or tell whether
an element is an external file reference.
RevitLinkType - An element representing a Revit file linked into a Revit project.
ModelPath - A non-Element class which contains path information for a file (not necessarily a .rvt file.) Paths can be to a location on a local or network
drive, or to a Revit Server location.
ModelPathUtils - A utility class which provides methods for converting between strings and ModelPaths.
TransmissionData - A class which stores information about all of the external file references in a document. The TransmissionData for a Revit
project can be read without opening the document.
ModelPath
ModelPaths are paths to another file. They can refer to Revit models, or to any of Revit's external file references such as DWG links. Paths can be relative or
absolute, but they must include an extension indicating the file type. Relative paths are generally relative to the currently opened document. If the current
document is workshared, paths will be treated as relative to the central model. To create a ModelPath, use one of the derived classes FilePath or ServerPath.
The class ModelPathUtils contains utility functions for converting ModelPaths to and from user-visible path strings, as well as to determine if a string is a valid
server path.
Revit Links
Revit documents can have links to various external files, including other Revit documents. These types of links in the Revit API are represented by the
RevitLinkType and RevitLinkInstance classes. The RevitLinkType class represents another Revit Document ("link") brought into the current one ("host"), while
the RevitLinkInstance class represents an instance of a RevitLinkType.
Creating New Links
To create a new Revit link, use the static RevitLinkType.Create() method which will create a new Revit link type and load the linked document and the static
RevitLinkInstance.Create() method to place an instance of the link in the model. The RevitLinkType.Create() method requires a document (which will be the
host), a ModelPath to the file to be linked, and a RevitLinkOptions object. The RevitLinkOptions class represents options for creating and loading a Revit link.
Options include whether or not Revit will store a relative or absolute path to the linked file and the workset configuration. The WorksetConfiguration class is
used to specify which, if any, worksets will be opened when creating the link. Note that the relative or absolute path determines how Revit will store the path,
but the ModelPath passed into the Create() method needs a complete path to find the linked document initially.
The following example demonstrates the use of RevitLinkType.Create(). The variable pathName is the full path to the file on disk to be linked.
Once the RevitLinkType is created, instances can be added to the document. In the following example, two instances of a RevitLinkType are added, offset by
100'. Until a RevitLinkInstance is created, the Revit link will show up in the Manage Links window, but the elements of the linked file will not be visible in any
views.
In the example below, the WorksetConfiguration is obtained, modified so that only one specified workset is opened and set back to the RevitLinkOptions prior
to creating the new link.
Whether creating or loading a link, a RevitLinkLoadResults is returned. This class has a property to determine if the link was loaded. It also has an ElementId
property that is the id of the created or loaded linked model.
Loading and Unloading Links
RevitLinkType has several methods related to loading links. Load(), LoadFrom() and Unload() allow a link to be loaded or unloaded, or to be loaded from a new
location. These methods regenerate the document. The document's Undo history will be cleared by these methods. All transaction phases (e.g. transactions,
transaction groups and sub-transactions) that were explicitly started must be finished prior to calling one of these methods.
The static method RevitLinkType.IsLoaded() will return whether or not the link is loaded.
Getting Link Information
Each RevitLinkType in a document can have one or more associated RevitLinkInstances. The RevitLinkInstance.GetLinkDocument() method returns a Document
associated with the Revit link. This document cannot be modified, meaning that operations that require a transaction or modify the document's status in
memory (such as Save and Close) cannot be performed.
The associated RevitLinkType for a RevitLinkInstance can be retrieved from the document using the ElementId obtained from the RevitLinkInstance.GetTypeId()
method. The RevitLinkType for a linked file has several methods and properties related to nested links. A document that is linked in to another document may
itself have links. The IsNested property returns true if the RevitLinkType is a nested link (i.e. it has some other link as a parent), or false if it is a top-level link.
The method GetParentId() will get the id of the immediate parent of this link, while GetRootId() will return the id of the top-level link which this link is
ultimately linked under. Both methods will return invalidElementId if this link is a top-level link. The method GetChildIds() will return the element ids of all links
which are linked directly into this one.
For example, if C is linked into document B and B in turn is linked into document A, calling GetParentId() for the C link will return the id of document B and
calling GetRootId() for the C link will return the id of document A. Calling GetChildIds() for document A will only return the id of B's link since C is not a direct
link under A.
RevitLinkType also has a PathType property which indicates if the path to the external file reference is relative to the host file's location (or to the central
model's location if the host is workshared), an absolute path to a location on disk or the network, or if the path is to a Revit Server location.
The AttachmentType property of RevitLinkType indicates if the link is an attachment or an overlay. "Attachment" links are considered to be part of their parent
link and will be brought along if their parent is linked into another document. "Overlay" links are only visible when their parent is opened directly.
The following example gets all RevitLinkInstances in the document and displays some information on them.
Link Geometry
Shared coordinates
The RevitLinkType methods SavePositions() and HasSaveablePositions() support saving shared coordinates changes back to the linked document.
Use HasSaveablePositions() to determine if the link has shared positioning changes which can be saved. Call SavePositions() to save shared coordinates changes
back to the linked document. SavePositions() requires an instance of the ISaveSharedCoordinatesCallback interface to resolve situations when Revit encounters
modified links. The interface's GetSaveModifiedLinksOption() method determines whether Revit should save the link, not save the link, or discard shared
positioning entirely.
While SavePositions() does not clear the document's undo history, it cannot be undone since it saves the link's shared coordinates changes to disk.
Conversion of geometric references
The Reference class has members related to linked files that allow conversion between Reference objects which reference only the contents of the link and
Reference objects which reference the host. This allows an application, for example, to look at the geometry in the link, find the needed face, and convert the
reference to that face into a reference in the host suitable for use to place a face-based instance. Also, these Reference members make it possible to obtain a
reference in the host (e.g. from a dimension or family) and convert it to a reference in the link suitable for use in Element.GetGeometryObjectFromReference().
The Reference.LinkedElementId property represents the id of the top-level element in the linked document that is referred to by this reference,
or InvalidElementId for references that do not refer to an element in a linked RVT file. The Reference.CreateLinkReference() method uses a RevitLinkInstance
to create a Reference from a Reference in a Revit link. And the Reference.CreateReferenceInLink() method creates a Reference in a Revit Link from a Reference
in the host file
Picking elements in links
The Selection methods PickObject() and PickObjects() allow the selection of objects in Revit links. To allow the user to select elements in linked files, use the
ObjectType.LinkedElement enumeration value for the first parameter of the PickObject() or PickObjects(). Note that this option allows for selection of elements
in links only, not in the host document.
In the example below, an ISelectionFilter is used to allow only walls to be selected in linked files.
As its name implies, this utility class provides information about external file references. TheExternalFileUtils.GetAllExternalFileReferences() method returns a
collection of ElementIds of all elements that are external file references in the document. (Note that it will not return the ids of nested Revit links; it only
returns top-level references.) This utility class has two other methods, IsExternalFileReference() and GetExternalFileReference() which perform the same
function as the similarly named methods of the Element class, but can be used when you have an ElementId rather than first obtaining the Element.
TransmissionData
TransmissionData stores information on both the previous state and requested state of an external file reference. This means that it stores the load state and
path of the reference from the most recent time this TransmissionData's document was opened. It also stores load state and path information for what Revit
should do the next time the document is opened.
As such, TransmissionData can be used to perform operations on external file references without having to open the entire associated Revit document. The
methods ReadTransmissionData and WriteTransmissionData can be used to obtain information about external references, or to change that information. For
example, calling WriteTransmissionData with a TransmissionData object which has had all references set to LinkedFileStatus.Unloaded would cause no
references to be loaded upon next opening the document.
TransmissionData cannot add or remove references to external files. If AddExternalFileReference is called using an ElementId which does not correspond to an
element which is an external file reference, the information will be ignored on file load.
The following example reads the TransmissionData for a file at the given location and sets all Revit links to be unloaded the next time the document is opened.
To read the TransmissionData object, you need to call the static method TransmissionData.ReadTransmissionData. It requires a ModelPath object.
There are two ways to construct a ModelPath object that refers to a central file. The first way involves using ModelPathUtils and the base ModelPath class. The
steps are as follows:
1. Compose the user-visible path string of the central file: ModelPathUtils.GetRevitServerPrefix() + relative path. (Note: The folder separator used in
the "relative path" is a forward slash(/). The correct separator is a forward slash.)
2. Create a ModelPath object via the ModelPathUtils.ConvertUserVisiblePathToModelPath() method. Pass in the string composed in the previous step.
3. Read the transmission data via the TransmissionData::ReadTransmissionData() method. Pass in the ModelPath obtained in the previous step.
The following example demonstrates this method assuming a central file testmodel.rvt is stored in the root folder of Revit Server, SHACNG035WQRP.
The second way to construct the ModelPath object that that refers to a central file is to use the child class ServerPath. This way can be used if the program
knows the local server name, however, it is not recommended as the server name may be changed by the Revit user from the Revit UI. The steps are as follows:
1. Create a ServerPath object using ServerPath constructor.
1. new ServerPath(ServerNameOrServerIp, relative path without the initial forward slash).
Note: The first parameter is the server name, not the string returned by the ModelPathUtils.GetRevitServerPrefix() and the second parameter does not include
the initial forward slash. See the following sample code. The folder separator is a forward slash(/) too.
2. Read the TransmissionData object via the TransmissionData.ReadTransmissionData() method.Pass in the ServerPath obtained in the previous step
Export
The Revit API allows for a Revit document, or a portion thereof, to be exported to various formats for use with other software. The Document class has an
overloaded Export() method that will initiate an export of a document using the built-in exporter in Revit (when available). For more advanced needs, some
types of exports can be customized with a Revit add-in, such as export to IFC and export to Navisworks. (Note, Navisworks export is only available as an add-in
exporter).
The Document.Export() method overloads are outlined in the table below.
Table: Document.Export() Methods
Format
Export() parameters
Comments
gbXML
gbXML
IFC
NWC
Exports a Revit project to the Navisworks .nwc format. Note that in order to use this function,you
must have a compatible Navisworks exporter add-in registered with your session of Revit.
DWF
DWFX
FBX
DGN
DWG
DXF
SAT
ADSK
Exporting to gbXML
There are two methods for exporting to the Green Building XML format. The one whose last parameter is MassGBXMLExportOptions is only available for
projects containing one or more instances of Conceptual Mass families. The MassGBXMLExportOptions object to pass into this method can be constructed with
just the ids of the mass zones to analyze in the exported gbXML, or with the mass zone ids and the ids of the masses to use as shading surfaces in the exported
gbXML. Whe using masses, they must not have mass floors or mass zones so as not to end up with duplicate surface information in the gbXML output.
The GBXMLExportOptions object used for the other gbXML export option has no settings to specify. It uses all default settings.
Exporting to IFC
Calling Document.Export() using the IFC option will either use the default Revit IFC export implementation or a custom IFC exporter, if one has been registered
with the current session of Revit. In either case, the IFCExportOptions class is used to set export options such as whether to export IFC standard quantities
currently supported by Revit or to allow division of multi-level walls and columns by levels.
Exporting to Navisworks
The Export method for Navisworks requires a compatible Navisworks exporter add-in registered with the current Revit session. If there is no compatible
exporter registered, the method will throw an exception. Use the OptionalFunctionalityUtils.IsNavisworksExporterAvailable() method to determine if a
Navisworks exporter is registered.
The NavisworksExportOptions object can be used to set numerous export settings for exporting to Navisworks, such as whether to divide the file into levels and
whether or not to export room geometry. Additionally, the NavisworksExportOptions.ExportScope property specifieds the export scope. The default is Model.
Other options include View and SelectedElements. When set to View, the NavisworksExportOptions.ViewId property should be set accordingly. This property is
only used when the export scope is set to View. When set to SelectedElements, the NavisworksExportOptions.SetSelectedElementIds() method should be called
with the ids of the elements to be exported.
Both DWF and DWFX files can be exported using the corresponding Document.Export() overloads. Both methods have a ViewSet parameter that represents the
views to be exported. All the views in the ViewSet must be printable in order for the export to succeed. This can be checked using the View.CanBePrinted
property of each view. The last parameter is either DWFExportOptions or DWFXExportOptions. DWFXExportOptions is derived from DWFExportOptions and has
all the same export settings. Options include whether or not to export the crop box, the image quality, and the paper format.
FBX Export requires the presence of certain modules that are optional and may not be part of the installed Revit, so
the OptionalFunctionalityUtils.IsFBXExportAvailable() method reports whether the FBX Export functionality is available. The Export() method for exporting to
3D-Studio Max has a ViewSet parameter representing the set of views to export. Only 3D views are allowed. The FBXExportOptions parameter can be used to
specify whether to export without boundary edges, wther to use levels of detail, and whether the export process should stop when a view fails to export.
Exporting to CAD Formats
Exporting to DGN , DWG and DXF format files have similar export methods and options.
DGN , DWG and DXF Export all require the presence of certain modules that are optional and may not be part of the installed version of Revit, so
the OptionalFunctionalityUtils class as corresponding methods to reports whether the each of these types of export functionality are available.
The Export() methods for exporting to DGN, DWG and DXF formats all have a parameter representing the views to be exported (as an ICollection of the
ElementIds of the views). At least one valid view must be present and it must be printable for the export to succeed. This can be checked using the
View.CanBePrinted property of each view.
The export options for each of these formats derives from BaseExportOptions, so there are many export settings in common, such as the color mode or
whether or not to hide the scope box. BaseExportOptions also has a static method called GetPredefinedSetupNames() which will return any predefined setups
for a document. The name of a predefined setup can then be passed into the static method GetPredefinedOptions() available from the corresponding options
class: DWGExportOptions, DGNExportOptions or DXFExportOptions. The export options for DWG and DXF files have even more options in common as they
share the base class ACADExportOptions.
The following example exports the active view (if it can be printed) to a DGN file using the first predefined setup name and the predefined options, without
making any changes.
For these file types it is possible to modify various mapping settings, such as layer mapping or text font mapping by creating the corresponding table and
passing it into the appropriate method of the BaseExportOptions class. For more information, see the Export Tables topic.
Exporting to SAT
The Export method for SAT has a parameter representing the views to be exported (as an ICollection of the ElementIds of the views). At least one valid view
must be present and it must be printable for the export to succeed. This can be checked using the View.CanBePrinted property of each view.
The SATExportOptions object has no settings to specify. It uses all default settings.
Exporting to Civil Engineering Design Applications
The last Export() method exports a 3D view of the document in the format of Civil Engineering design applications. One parameter of the method is a Viewplan
that specifies the gross area plan. All the areas on the view plan will be exported and it must be 'Gross Building' area plan. To check whether its area scheme is
Gross Building, use the AreaScheme.GrossBuildingArea property. The BuildingSiteExportOptions object allows custom values for settings such as gross area or
total occupancy.
Export Tables
The classes listed in the table below expose read and write access to the tables used for mapping on export to various formats such as DWG and DGN. Each
class contains (key, info) pairs of mapping data.
Class
Description
ExportLayerTable
Represents a table supporting a mapping of various layer properties (Category, name, color name) to layer name in the target
export format.
ExportLinetypeTable
Represents a table supporting a mapping of linetype names in the target export format.
ExportPatternTable
Represents a table supporting a mapping of FillPattern names and ids to FillPattern names in the target export format.
ExportFontTable
Represents a table supporting a mapping of font names in the target export format.
ExportLineweightTable
Represents a table supporting a mapping of lineweight names in the target export format.
Most of these tables are available through the BaseExportOptions class (the base class for options for DGN, DXF and DWG formats). The ExportLineweightTable
is available from the DGNExportOptions class. Each table has a corresponding Get and Set method. To modify the mappings, get the corresponding table, make
changes and then set it back to the options class.
The following example modifies the ExportLayerTable prior to exporting a DWG file.
31.
32.
33.
34.
35.
36. }
exported = document.Export(Path.GetDirectoryName(document.PathName),
Path.GetFileNameWithoutExtension(document.PathName), views, dwgOptions);
return exported;
IFC Export
The Revit API allows custom applications to override the default implementation for the IFC export process. To create a custom IFC Exporter, implement the
IExporterIFC interface and register it with the ExporterIFCRegistry class.
When an IExporterIFC object is registered with Revit, it will be used both when the user invokes an export to IFC from the UI as well as from the API method
Document.Export(String, String, IFCExportOptions). In both cases, if no custom IFC exporter if registered, the default Revit implementation for IFC export is
used.
When invoking an IFC export from the API, IFCExportOptions can be used to set the same export options as are available to the user from the Export IFC dialog
box.
ExporterIFCRegistry
The following example registers a custom IFC exporter in the OnStartup method.
Note that ExporterIFCRegistry is an application level singleton and only one IExporterIFC can be registered in a given session of Revit. Registration is on a first
come/first served basis. If RegisterIFCExporter() is called when there is already an IFC exporter registered, it will throw an InvalidOperationException. You can
check the journal file for the path of the DLL which was successfully registered as the IFC exporter for the session.
IExporterIFC
The interface IExporterIFC has only one method to implement, ExportIFC(). This method is invoked by Revit to perform an export to IFC. An ExporterIFC object
is passed to this method as one of its parameters. ExporterIFC is the main class provided by Revit to allow implementation of an IFC export. It contains
information on the options selected by the user for the export operation, as well as members used to access specific types of data needed to implement the
export properly.
The Autodesk.Revit.DB.IFC namespace contains numerous IFC related API classes that can be utilized by a custom implementation of the IFC export process.
For a complete sample of a custom IFC export application, see the Open Source example at http://sourceforge.net/projects/ifcexporter/.
Custom export
The Revit API provides a set of classes that make it possible to export 3D views via a custom export context. These classes provide access to the rendering
output pipeline through which Revit sends the graphical 3D representation of a model to an output device. In the case of a custom export, the "device" is
represented by a context object that could be any kind of a device. A file would be the most common case.
An implementation of a custom exporter provides a context and invokes rendering of a model, upon which Revit starts processing the model and sends graphic
data out via methods of the context. The data describes the model exactly as it would have appeared in Revit when the model is rendered. The data includes all
geometry and material properties.
CustomExporter class
The CustomExporter class allows exporting 3D views via a custom export context. The Export() method of this class triggers the standard rendering process in
Revit, but instead of displaying the result on screen or printer, the output is channeled through the given custom context that handles processing the geometric
as well as non-geometric information.
IExportContext
An instance of the IExportContext class is passed in as a parameter of the CustomExporter constructor. The methods of this interface are then called as the
entities of the model are exported.
RenderNode classes
RenderNode is the base class for all output nodes in a model-exporting process. A node can be either geometric (such as an element or light) or non-geometric
(such as material). Some types of nodes are container nodes, which include other render nodes.
CameraInfo
The CameraInfo class describes information about projection mapping of a 3D view to a rendered image. An instance of this class can be obtained via a
property of ViewNode. If it is null, an orthographic view should be assumed.
Appendices
Glossary
Array
Arrays hold a series of data elements, usually of the same size and data type. Individual elements are accessed by their position in the
array. The position is provided by an index, which is also called a subscript. The index usually uses a consecutive range of integers, but the
index can have any ordinal set of values.
BIM
Building Information Modeling is the creation and use of coordinated, internally consistent, computable information about a building project
in design and construction. In a BIM application the graphics are derived from the information and are not the original information itself like
in general CAD applications.
Class
In object-oriented programming (OOP), classes are used to group related Properties (variables) and Methods (functions) together. A typical
class describes how those methods operate upon and manipulate the properties. Classes can be standalone or inherited from other classes.
In the latter, a class from which others are derived is usually referred to as a Base Class.
Events
Events are messages or functions that are called when an event occurs within an application. For example when a model is saved or opened.
Iterator
An iterator is an object that allows a programmer to traverse through all elements in a collection (an array, a set, etc.), regardless of its
specific implementation.
Method
A method is a function or procedure that belongs to a class and operates or accesses the class data members. In procedural programming,
this is called a function.
Namespace
A namespace is an organizational unit used to group similar and/or functionally related classes together.
Overloading
Method overloading is when different methods (functions) of the same name are invoked with different types and/or numbers of parameters
passed.
Properties
Properties are data members of a class accessible to the class user. In procedural programming this is called a variable. Some properties are
read only (support Get() method) and some are modifiable (support Set() method).
Revit Families
A Family is a collection of objects called types. A family groups elements with a common set of parameters, identical use, and similar
graphical representation. Different types in a family can have different values of some or all parameters, but the set of parameters - their
names and their meaning - are the same.
Revit Parameters
There are a number of Revit parameter types.
Shared Parameters can be thought of as user-defined variables.
System Parameters are variables that are hard-coded in Revit.
Family parameters are variables that are defined when a family is created or modified.
Revit Types
A Type is a member of a Family. Each Type has specific parameters that are constant for all instances of the Type that exist in your model;
these are called Type Properties. Types have other parameters called Instance parameters, which can vary in your model.
Sets
A set is a collection (container) of values without a particular order and no repeated values. It corresponds with the mathematical concept of
set except for the restriction that it has to be finite.
Element ID
Each element has a corresponding ID. It is identified by an integer value. It provides a way of uniquely identifying an Element within an
Autodesk Revit project. It is only unique for one project, but not unique across separate Autodesk Revit projects.
Element UID
Each element has a corresponding UID. It is a string identifier that is universally unique. That means it is unique across separate Autodesk
Revit projects.
FAQ
General Questions
Table of contents
No headers
Q: How do I reference an element in Revit?
A: Each element has an ID. The ID that is unique in the model is used to make sure that you are referring to the same element across
multiple sessions of Revit.
Q: Can a model only use one shared parameter file?
A: Shared parameter files are used to hold bits of information about the parameter. The most important piece of information is the GUID
(Globally Unique Identifier) that is used to insure the uniqueness of a parameter in a single file and across multiple models.
Revit can work with multiple shared parameter files but you can only read parameters from one file at a time. It is then up to you to choose
the same shared parameter file for all models or a different one for each model.
In addition, your API application should avoid interfering with the user's parameter file. Ship your application with its own parameter file
containing your parameters. To load the parameter(s) into a Revit file:
The application must remember the user parameter file name.
Switch to the application's parameter file and load the parameter.
Then switch back to the user's file.
Q: Do I need to distribute the shared parameters file with the model so other programs can use the shared parameters?
A: No. The shared parameters file is only used to load shared parameters. After they are loaded the file is no longer needed for that model.
Q: Are shared parameter values copied when the corresponding element is copied?
A: Yes. If you have a shared parameter that holds the unique ID for an element in your database, append the Revit element Unique ID or
add another shared parameter with the Revit element unique ID. Do this so that you can check it and make sure you are working with the
original element ID and not a copy.
Q: Are element Unique IDs (UID) universally unique and can they ever change?
A: The element UIDs are universally unique, but element IDs are only unique within a model. For example, if you copy a wall from one Revit
project to another one, the UID of the wall is certain to change to maintain universal uniqueness, but the ID of the wall may not change.
Q: Revit takes a long time to update when my application sends data back to the model. What do I need to do to speed it up?
A: Make sure you only call Document.Regenerate() as often as necessary. Although this method is required to make sure the elements in
the Revit document reflect all changes, it can slow down your application. Keep in mind, too, that when a transaction is committed there is
an automatic call to regenerate the document.
Q: What do I do if I want to add shared parameters to elements that do not have the ability to have shared parameters bound to them? For
example, Grids or Materials.
A: If an element type does not have the ability to add shared parameters, you need to add a project parameter. This does make it a bit
more complicated when it is time to access the shared parameter associated with the element because it does not show up as part of the
element's parameter list. By using tricks like making the project shared parameter a string and including the element ID in the shared
parameter you can associate the data with an element by first parsing the string.
Q: How do I access the saved models and content BMP?
A: The Preview.dll is a shell plug-in which is an object that implements the IExtractImage interface. IExtractImage is an interface used by
the Windows Shell Folders to extract the images for a known file type.
For more information, review the information at WikiHelp
4.
There are two parameters called Moment Connection Start and Moment Connection End. If the value set for these two is not None then you should look
and see if there is a beam that is co-linear and also has the value set to something other than None. Also ask the user to make sure to select Cantilever
Project.
Add Code
When writing the code in VB.NET, you must pay attention to key letter capitalization.
Code Region 30-9: Hello World in VB.NET
Imports System
Imports Autodesk.Revit.UI
Imports Autodesk.Revit.DB
<Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Automatic)> _
Public Class Class1
Implements IExternalCommand
Public Function Execute(ByVal revit As ExternalCommandData, ByRef message As String, _
ByVal elements As ElementSet) As Autodesk.Revit.UI.Result _
Implements IExternalCommand.Execute
End Function
End Class
Code Region 30-10: Creating a .addin manifest file for an external command
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<RevitAddIns>
<AddIn Type="Command">
<Assembly>D:\Sample\HelloWorld\bin\Debug\HelloWorld.dll</Assembly>
<AddInId>239BD853-36E4-461f-9171-C5ACEDA4E721</AddInId>
<FullClassName>Class1</FullClassName>
<Text>HelloWorld</Text>
<VendorId>ADSK</VendorId>
<VendorDescription>Autodesk, www.autodesk.com</VendorDescription>
</AddIn>
</RevitAddIns>
3. Save the file as HelloWorld.addin and put it in the following location:
o
Press F5 to continue executing the program. The following system message appears.
Variable
Type
Internal Database
Units
Behavior
Behavior
bool
Isotropic,
Orthotropic
Young Modulus X
YoungModulusX
double
UT_Stress
Young Modulus Y
YoungModulusY
double
UT_Stress
Young Modulus Z
YoungModulusZ
double
UT_Stress
Poisson ratio X
PoissonModulusX
double
UT_Number
Poisson ratio Y
PoissonModulusY
double
UT_Number
Poisson ratio Z
PoissonModulusZ
double
UT_Number
Shear modulus X
ShearModulusX
double
UT_Stress
Shear modulus Y
ShearModulusY
double
UT_Stress
Shear modulus Z
ShearModulusZ
double
UT_Stress
Thermal
Expansion
coefficient X
ThermalExpansionCoefficientX
double
UT_TemperalExp
Thermal
Expansion
coefficient Y
ThermalExpansionCoefficientY
double
UT_TemperalExp
Thermal
Expansion
coefficient Z
ThermalExpansionCoefficientZ
double
UT_TemperalExp
Unit Weight
UnitWeight
double
UT_UnitWeight
Damping ratio
DampingRatio
double
UT_Number
Minimum Yield
Stress
MinimumYieldStress
double
UT_Stress
Minimum tensile
stress
MinimumTensileStrength
double
UT_Stress
Reduction factor
for shear
ReductionFactor
double
UT_Number
Description
Steel / Generic
Currently exposed for Generic Only
Concrete
Behavior
Behavior
bool
Isotropic,
Orthotropic
Young Modulus X
YoungModulusX
double
UT_Stress
Young Modulus Y
YoungModulusY
double
UT_Stress
Young Modulus Z
YoungModulusZ
double
UT_Stress
Poisson ratio X
PoissonModulusX
double
UT_Number
Poisson ratio Y
PoissonModulusY
double
UT_Number
Poisson ratio Z
PoissonModulusZ
double
UT_Number
Shear modulus X
ShearModulusX
double
UT_Stress
Shear modulus Y
ShearModulusY
double
UT_Stress
Shear modulus Z
ShearModulusZ
double
UT_Stress
Thermal
Expansion
coefficient X
ThermalExpansionCoefficientX
double
UT_TemperalExp
Thermal
Expansion
coefficient Y
ThermalExpansionCoefficientY
double
UT_TemperalExp
Thermal
Expansion
coefficient Z
ThermalExpansionCoefficientZ
double
UT_TemperalExp
Unit Weight
UnitWeight
double
UT_UnitWeight
Damping ratio
DampingRatio
double
UT_Number
Concrete
compression
ConcreteCompression
double
UT_Stress
Lightweight
LightWeight
Bool
Shear strength
modification
ShearStrengthReduction
double
UT_Number
Wood
Young Modulus
PoissonModulus
double
UT_Stress
Poisson ratio
ShearModulus
double
UT_Number
Shear modulus
ShearModulus
double
UT_Stress
Thermal
Expansion
coefficient
ThermalExpansionCoefficient
double
UT_TemperalExp
Unit Weight
UnitWeight
double
UT_UnitWeight
Species
Species
AString
Grade
Grade
AString
Bending
Bending
double
UT_Stress
Compression
parallel to grain
CompressionParallel
double
UT_Stress
Compression
perpendicular to
grain
CompressionPerpendicular
double
UT_Stress
Shear parallel to
grain
ShearParallel
double
UT_Stress
Tension
perpendicular to
grain
ShearPerpendicular
double
UT_Stress
Unit
Dimension
Internal Representation
1.
UT_Number
No dimension
Simple number.
2.
UT_Stress
(Mass)x(Length-1)x(Time-2)
Kg(mass)/(Foot*Sec2)
3.
UT_TemperalExp
(Temperature-1)
(1/C)
4.
UT_UnitWeight
(Mass)x(Length-2)x(Time-2)
Kg(mass)/(Foot2*Sec2)
Precast-Rectangular Beam
Precast-Single Tee
Precast-Inverted Tee
Precast-Double Tee
Consistency
It is important for applications based on the API to provide a user experience that is consistent with Revit. This will allow the users of your
application to leverage knowledge they developed while learning Revit. Consistency can be obtained by re-using certain dialog types, instead
of creating or re-creating dialogs. See the dialog types section for examples of dialogs you can leverage when creating your application.
Good Layout
A well-balanced layout of information can be achieved by following Gestalt Principles:
Proximity: items placed close together are perceived as being closely associated
Similarity: items that share similar appearance are perceived as being closely associated
Continuity: humans tend to prefer simple, unbroken contours over more complex, yet similarly plausible forms
Good Defaults
When a user needs to edit data or change a setting, the lack of any or obvious default can lead to errors and force users to re-edit and reenter information. Remember to:
Set the control value with a reasonable default value for the current context by consulting usage data or using the previously entered
values by the user. The appropriate default may be blank.
Where appropriate, remember the last used setting of the user instead of always presenting the same system default
A common example is pre-setting certain settings or options which would be the most often selected.
Progressive Disclosure
As an application's complexity increases, it becomes harder for the user to find what they need. To accommodate the complexity of a user
interface, it is common to separate the data or options into groupings. The concept of Progressive Disclosure shows the needed information
as necessary. Progressive Disclosure may be user-initiated, system initiated, or a hybrid of the two.
User initiated action
Examples here include a Show More button for launching a child dialog, Tabs for chunking interface elements into logical chunks, and a
Collection Search/ Filter for selectively displaying items in a collection by certain criteria.
System initiated action
These can either be:
Event based: An event within the product initiates the disclosure of more information, such as with a Task Dialog.
Time based: More information is disclosed after specified amount of time passes, such as in an automatic slide show.
PERCENTAGE
1-5 characters
100%
6-10 characters
40%
11-100 characters
30%
20%
Make the invisible control frame around text controls, frames etc. as large as possible to allow for longer translated text. These
frames should be at least 30% larger than the English text.
Refer to the User Interface Text Guidelines for Microsoft Windows User Experience Guidelines for additional information regarding localizing
text.
Dialog Guidelines
Introduction
A dialog is a separate controllable area of the application that contains information and/or controls for editing information. Dialogs are the
primary vehicle for obtaining input from and presenting information to the user. Use the following guidelines when deciding which dialog to
use.
Dialog
Type
Definition
Use When
Modal
Halts the rest of the application and waits for user input
Modeless
User can switch between the dialog and the rest of the application without closing
the dialog
Behavior Rules
A dialog can either be user initiated (prompted by clicking a control) or system initiated (a warning triggered by a system event)
The initial dialog location typically should be centered on the screen, but this rule may vary based on variation or on a particular
context of use, but should have an immediate focus
Dialogs should be resizable when the content is dynamic, please see Dynamic Layout section for more on this topic
Dialog Controls
Control
Use When
CHECK BOX
The choice being made (and its opposite) can be clearly expressed to the user with
a single label
Example
There are between 2 - 5 mutually exclusive but related choices and the user can
only make one selection per choice
TEXT BOX
DROP DOWN
LIST
COMBO BOX
Similar to a drop-down list box, but allows the user to enter information not prepopulated in the drop-down
SLIDER
Use when the expected input or existing data will be in a specific range.
Sliders can also be combined with text boxes to give additional level of user control
and give feedback as the slider is moved
SPINNER
Use this option if the data can be entered sequentially and has a logical limit. This
can be used in conjunction with an editable text box
Element
Requirements
Title bar
Help
button
Illustration
Controls
Commit
Buttons
Layout Flow
When viewing a dialog within a user interface, the user has multiple tasks to accomplish. How the information is designed and laid out must
support the user in accomplishing their task(s). Keeping this in mind, it is important to remember users:
Scan (not read) an interface and then stop when they get to what they were looking for and ignore anything beyond it
Focus on items that are different
Not scroll unless they need to
Lay out the window in such a way that suggests and prompts a "path" with a beginning, middle, and end. This path should be designed to be
easily scanned. The information and controls in the "middle" of the path must be designed to be well balanced and clearly delineate the
relationship between controls. Of course, not all users follow a strictly linear path when completing a task. The path is intended for a typical
task flow.
Variation A: Top-Down
Place UI items that:
1. Initiate a task in the upper-left corner or upper-center
2. User must interact with to complete the task(s) in the middle
3. Complete the task(s) in the lower-right corner
In this example (Materials dialog), the user does the following:
1. Searches/filters the list
2. Selects an item
3. Commits or Cancels
Variation B: Left-Right
Place UI items that:
1. Initiate a task or change between modes in the far left (see Tabs section)
2. User must interact with to complete the task(s) in the middle. This may be separated into
separate distinct sections
Variation C: Hybrid
As seen in Variation B, many windows that are laid out left to right are actually a hybrid of left-right and top-down.
For more information, see Walkthrough: Laying Out Windows Forms Controls with Padding, Margins, and the Auto Size Property.
Placement
Dialog units
Relative pixels
7 on all sides
11 on all sides
11
11
3 or no space
5 or no space
12
18
Grouping
Group boxes are the most common solution used to explicitly group related controls together in a dialog and give them a common grouping.
Figure 202 - Group box with no label and group box with one control and Group box with title that is redundant with dialog
title
Avoid "nesting" two of more group boxes within one another and placing Commit buttons inside a group box.
Horizontal Separator
An alternative to the traditional group box is a horizontal separator. Use this only when the groups are stacked vertically in a single column.
The following example is from Microsoft Outlook 2007:
Home Quadrant
Alignment
Multiple
Figure 204 - Four square grid applied to Revit View Templates dialog to demonstrate how it should be resized
In this example, the list box is located in all four quadrants. So, it is anchored to the top-left and expands to the right and to the bottom.
Implementation Notes
Here are the some steps to consider when implementing a dynamic layout:
Break the design on sections based on the structure of the content and flow you would like to achieve when container's size changes.
Define the minimum, maximum and other size constrains for the various sections and control used. This is usually driven by the
purpose of the data type we are presenting, images, supplemental information and controls.
Consider alignment, that is, how the content will flow when re-sized. Consider which items should be static and which dynamic and
how they are expandable - which should usually be for left-to-right languages, and dialogs should flow to the right and bottom,
being anchored and aligned to the top and left.
For guidelines on how different controls should handle resizing, see the table below:
Control
Content
Re-sizable
Moveable
Button
Static
No
Yes
Link
Static
No
Yes
Radio Button
Static
No
Yes
Spin Control
Static
No
Slider
Static
X Direction
Yes
Scroll Bar
Static
X Direction
Yes
Tab
Dynamic
X and Y Direction
Progressive Disclosure
Dynamic
X and Y Direction
Check Box
Static
No
Yes
Drop-Down List
Dynamic
X Direction
Combo Box
Dynamic
X and Y Direction
List View
Dynamic
X and Y Direction
Text Box
Dynamic
X and Y if multi-line
Yes
Dynamic
X Direction
Tree View
Dynamic
X and Y Direction
Canvas
Dynamic
X and Y Direction
Yes
Group Box
Dynamic
X and Y Direction
Progress Bar
Static
Yes
Status Bar
Dynamic
Yes
Dynamic
X and Y
Tip For more detail on using a FlowLayoutPanel to build a resizable dialog, see Walkthrough: Arranging Controls on Windows Forms Using a
FlowLayoutPanel
Dialog Types
There are a handful of dialog types that persist throughout the Revit products. Utilizing these standard types helps to drive consistency and
leverage users' existing learning and knowledge patterns.
Standard input dialog
This is the most basic dialog type. This should be used when the user needs to make a number of choices and then perform a discrete
operation based on those choices. Controls should follow rules for Grouping, Spacing and Margins, and Layout Flow.
The Revit Export 2D DWF Options dialog is a good example of a Standard Input dialog.
Supported Behaviors
ID
Behavior
Description
Required
Filter
No
Grouping
No
Each value cell can contain a control that can be edited (or disabled) depending on the context
Yes
Commit (Buttons)
No
Content Editor
If multiple action controls interoperate with the same content control (such as a list box), vertically stack them to the right of and topaligned with the content control, or horizontally place them left-aligned under the content control. This layout decision is at the developer's
discretion.
Figure 207 - Action controls to the right of content and action controls below content
Collection Viewer
In applications such as Revit, the user must view and manage collections of items to complete their tasks. The Collection View provides the
user a variety of ways of viewing the items (browsing, searching and filtering) in the collection. Provide a way for a user to easily browse
through a collection of items for the purpose of selecting an item to view or edit (see Collection Editor). Optionally provide the ability to
search and/or filter the collection.
Action
Description
Required
Filter
This provides options for filtering the list view. This can be represented as a:
No
Drop down - default criteria must be selected and should include "All" as an option
Check boxes - check box ON would refine the list. Default set by designer
Radio buttons - choosing between radio buttons refines the list. Default set by designer Once a choice is selected, the
collection will automatically update based on the selected criteria. Controls must follow the MICROSOFT WINDOWS
USER EXPERIENCE GUIDELINES
2
Search Box
A search box allows users to perform a keyword search on a collection. The search box must follow Microsoft Windows
User Experience Guidelines
No
Change
viewing mode
If the collection is viewed as list, the items can be optionally displayed with small or large icons instead of text
No
Collection
Manager
A separate UI will be provided to edit, rename, delete or add items to the collection. See Collection Editor
No
View the
collection
The collection itself can be viewed in the following ways: List View, Table View, Tree View, or as a Tree Table
Yes
Show More
This button hides/shows the additional data associated with the currently selected item. See Show More Button
No
List View
When the user needs to view and browse and optionally select, sort, group, filter, or search a flat collection of items. If the list is
hierarchical, use Tree View or Tree Table and if the data is grouped into two or more columns, use Table View instead.
Figure 209 - List View, showing different ways of presenting the data
There are four basic variations of this pattern that includes the following:
Drop down list
Use a drop down list box when you only need to present a flat list of names, only a single selection is required and space is limited. The
Microsoft Windows User Experience Guidelines should be followed when using a drop-down list.
Figure 211 - The font selector in Microsoft Office 2007 is an example of a combo box
List box
Use when you only need to present a - list of names, it benefits the user to see all items and when there is sufficient room on the UI to
display list box. Use also if selecting more than one option is required. The Microsoft Windows User Experience Guidelines should be followed
when using a list box.
List View
Use when the data includes the option of list, details and/or graphical thumbnail previews, such as a Windows Open Dialog.
many values
Columns containing numerical data
Right align the column headings for the data column
Right (decimal) align data in financial columns
Columns with a mix of positive and negative numeric data
Align the data so that decimals align
Tree View
Often a user may need to understand complex relationships within a hierarchy of items and this can often best displayed within a "tree
view." The user may also need to select one or more of the items. If the collection is a flat list, use the ListView and if the data is grouped
into two or more columns, use TableView or TreeTable instead.
A tree UI follows the principle of user initiated Progressive Disclosure. Using a tree allows complex hierarchical data to be presented in a
simple, yet progressively complex manner. If the data becomes too broad or deep, a search box should be considered.
Figure 218 - The Revit Project Browser is a good example of a tree view
Tree Table
As with a Tree View, the user may need to view and browse a hierarchically organized collection of items with the intent of selecting one or
more of the items. However, the user also needs to see more properties of the item than just the name. To accommodate this, present the
user with a tree embedded within a table. Each row presents additional attributes of the item. Expanding a node exposes another row.
Figure 219 - The Revit Visibility/Graphics dialog is a good example of a Tree Table Collection Search / Filter
When the user is viewing a collection with many items, they may need to filter the number of items. To accomplish this, provide a way for
the user choose between either a system-provided list of filter criteria and/or user-creatable criteria. Selecting the criteria automatically
filters the collection. The two most common ways are demonstrated in the Revit Materials dialog.
A search box allows the list to be filtered based on a keyword
A drop-down allows the list to be filtered based on a set of defined criteria
Collection Editor
In addition to viewing a collection of items, a user will also typically want to edit the collection. This can be accomplished by associating a
toolbar for editing, creating, duplicating, renaming, and deleting items.
The Edit Bar
The buttons should be ordered left to right in the following order and with the following as tooltip labels: Edit, New, Duplicate, Delete,
Rename. If a feature does not utilize one or more buttons, the rest move to the left.
Action
Context
Edit
Use If an item can be edited. Editing an item may launch a separate dialog if there are less than three properties to edit. See the Collection
Viewer section for more details on displaying collection items
New
Duplicate
Rename
Delete
To ensure that the primary UI element is placed first in the layout path, the following rules should be followed when placing the manage
controls:
Navigating list is primary task: place at the bottom-left of the list control
Managing list is primary task: place at top left of list control
When the main collection being managed is represented as a combo box: place to the right of the combo box
Add/Remove
A slight variation on the Edit Bar is the use of Add and Remove buttons, denoted by plus and minus icons, as shown below. Add and Remove
is used when data is being added to an existing item in the model.
The following is a good example of a Collection Editor dialog that uses both forms of the Edit Bar. The Add (+) and Remove (-) buttons are
used to add values to an already existing demand factor type.
List Builder
Use when there is a number of items that the user has to add/remove from one list to another. This is typically used when there is a list
(located on the right) that needs to have items added to it from an existing list (located on the left.) Provide a List Box View of the two lists
with button controls between, one for adding and the other for removing items.
Action
Description
Required
Yes
Yes
Collection Editor
No
Depending on the feature, the List Builder can act in one of two ways:
Item can only be added once items from List A can only be added to List B once. In this case, the Add button should be disabled when
a previously added item is selected in List A.
Item can be added multiple times. In this case, the Add button is not disabled, and the user can add an item from List A to List B
multiple times (the amount determined by the feature.) See Edit Label example below.
If the user needs to arbitrarily move an item up or down in a collection, provide up/down buttons next to the list.
Title (required)
All task dialogs require a title. Titles of task dialogs should be descriptive and as unique as possible. Task dialog titles should take the format
of the following:
<featureName> - <shortTitle>
Where <featureName> is the module from which the task dialog was triggered
And <shortTitle> is the action that resulted in the task dialog being shown
Examples:
o
Layer - Delete
Where possible, use verbs on the second <shortTitle> part of the title such as Create, Delete, Rename, Select, etc.
In cases where there is no obviously applicable feature name (or several) applying a short title alone is sufficient.
A task dialog title should never be the product name, such as AutoCAD Architecture.
Title bar Icon
The icon appearing in the far left to the title bar should be that of the host application - this includes third party plug-ins. Task dialogs may
contain plug-in names in the title to specify the source of the message, but the visual branding of all task dialogs should match the host
application; such as Revit Structure, Inventor, AutoCAD Electrical, etc.
Main Instructions (required)
This is the large primary text that appears at the top of a task dialog.
Every task dialog should have main instructions of some kind
Text should not exceed three lines
[English Language Versions] Main instructions should be written in sentence format - normal capitalization and punctuation
[English Language Versions] Address the user directly as "you"
[English Language Versions] When presented with multiple command link options the standard final line for the main instructions
should be, "What do you want to do?"
Figure 225 - A very simple task dialog with only main instructions for text
Figure 226 - A task dialog that uses both main instructions and main content
Expanded Content (optional - rarely used)
This text is hidden by default and will display at the bottom of the task dialog when the "Show" button is pressed.
Expanded content is optional, and should be rarely used. It is used for information that is not essential (advance or additional
information), or that doesn't apply to most situations
[English Language Versions] Expanded content should be written in sentence format (normal capitalization and punctuation)
[English Language Versions] Address the user directly as "you" when needed
Figure 227 - The Show Details button displays additional Main Content text
Figure 228 - Example of a task dialog using the DNSMA checkbox as an "Always" checkbox for one choice
Where multiple are choices possible:
The generic wording "Always perform my current choice" should be used
Command links should be used to show the available choices. If buttons are used and a Cancel button is included it looks as though
"cancel" is an option that could always be performed in future
Footer Text (optional)
Footer text is used to link to help. It replaces the Help or "?" button found on previous dialogs, and will link to the same location as an
existing help link. On English language versions the text in the footer should read:
"Click here to learn more"
The text should be written as a statement in sentence format, but with no final punctuation. See Figure 226 for an example of a Task Dialog
with footer text.
Figure 230 - Task Dialog with command links and a command button
Commit Buttons (optional - commonly used)
Commit buttons are simple buttons in the footer of the task dialog. Standard (English) terms include:
OK
Cancel
Yes
No
Retry
Close
It is possible to use custom text on commit buttons, but that is not recommended.
Notes on proper usage of each of the primary button types:
The OK button should only be used in situations where a task dialog poses a question that can be answered by OK.
The Cancel button should only be used when a task can truly be canceled, meaning the action that triggered the task dialog will be
aborted and no change will be committed. It can be used in combination with other commit buttons or command links.
The Yes & No button(s) should always be used in combination, and the text in the main instructions and / or main content should end
in a yes / no question.
The Retry button must appear with at least a Cancel button as an alternate option, so a user can choose not to retry.
The Close button is used on any purely informational task dialog; i.e. where the user has no action to choose, but can just read the
text and close the dialog.
Previously the OK button was often used on such dialogs. It should not be used in task dialogs for this purpose.
The following are some examples of how commit buttons should be used:
See Figure 226 for an example of a Cancel button with command links
See Figure 224 for an example of a purely informative task dialog with a close button
See Figure 227 for an example of a task dialog with OK and Cancel buttons
other, should not get assigned a default choice. All dialogs using only commit buttons must be assigned a default button.
Navigation
Tabs
Use when there are loosely related, yet distinct "chunks" of information need to exist within the same UI, but there is not enough room to
display it all in a clear manner.
Separate the UI into distinct modal zones, each one represented by a "tab" with a descriptive label. The entire dialog should be treated as a
single window with a single set of Commit buttons.
All of the tabs should be visible at the same time
Never have a single tab in a static UI such as dialog. Instead, use the tab's title for the page or dialog. Exception: if the number of
tabs grows dynamically and the default is one. e.g. Excel's open workbook tabs
Tabs are for navigation only. Selecting a tab should not perform any other action (such as a commit) besides simply switching to that
page in the window
Avoid nesting tabs within tabbed windows. In this case consider launching a child window
Do not change the label on a tab dynamically based on interaction within the parent window
Variations
Variation A: Horizontal Tabs
Keyboard Accessibility
Tab Order
Pressing the tab key cycles the focus between each editable control in the dialog. The general rule is left-to-right, top-to-bottom.
1. The default tab stop is at the control at the topmost, leftmost position in the dialog
2. Move right until there are no more controls in the current row
3. Move to the next row and start from the left-most control, moving right
4. Repeat step 2 until there are no more rows. Always end with the OK/Cancel/Apply row
Right and left arrow, down and up arrows, Tab and Shift-tab all have the same behavior, respectively. Except for when the focus is on
the following:
o
List control or combo box: The right/left, down/up arrows move the cursor down/up the list, respectively
Grid control: The right/left move the cursor right/left across columns, And down/up arrows move cursor down/up the list,
respectively
Slider: The right/left, down/up arrows move the slider right/left, respectively
Spinner: The right/left, down/up arrows move the spinner down/up, respectively
Treat each Group conceptually as a nested dialog, following the above rules within each Group first and moving from the top-left
Group, moving to the right until no more groups are encountered and then moving to the next row of Groups.
If dialog is tabbed, default tab stop should be the default tab.
Tip Visual Studio can assist with the creation and editing of tab order by toggling the Tab Order visual helper (accessed from the View
Tab
Order menu.)
Access Keys
Each editable control on a dialog should get a unique access key letter (which is represented by an underlined letter in the control's
label)
The user presses Alt key plus the assigned key and that control is activated as if it was clicked
The default button does not require an access key since Enter is mapped to it
The Cancel or Close button also does not need access key since Esc is mapped to it. See Committing Changes for more detail
Show More Button
Following the principle of Progressive Disclosure, users may need a way of showing more data than is presented as a default in the user
interface. The Show More button is typically implemented in one of two ways:
Expander Button: Provide a button with a label such as " << Preview " or "Show more >>" The double brackets >> should point towards
where the new information pane will be presented. When opened, the double brackets should switch to indicate how the additional pane will
be "closed."
See Figure 207 - Materials dialog from Revit for an example.
Dialog Launcher: A button with ellipses () that launches a separate dialog. This is typically used to provide a separate UI for editing a
selected item.
Figure 233 -Dialog launcher button, as implemented in the Revit View Filters dialog
Committing Changes
Modal dialogs are used to make changes to data within the project file. Use when there is an editor a series of edits have been queued up in
a modal dialog or form and need to be committed at once. If the dialog is purely informational in nature, use a Task Dialog, which has its
own committing rules.
Each modal dialog or web-form must have a set of commit buttons for committing the changes and/or canceling the task and/or closing the
dialog.
Sizing
Figure 234 - Commit Button sizes (taken from Microsoft Windows User Experience Guidelines)
Layout
A summary of commit button styles for different window types
Pattern
Modal Dialog
OK/Cancel or [Action]/Cancel
Modeless dialog
Progress Indicator
Use Cancel if returns the environment to its previous state (leaving no side effect); otherwise, use Stop
Button Type
Apply Button
Position the Default, Cancel, and Apply button(s) in this order and right aligned. The Dialog button(s) (if present) are aligned to the left, but
to the right of the help button (if present).
Default (OK and other Action) buttons
The dialog must have a default action button. This button should be closely mapped to the primary task of the dialog. This can either be
labeled OK or a more descriptive verb that describes the action.
Make the button with less destructive result to be the Default button
Enter key is the keyboard access point for the Default button
OK button
OK buttons can be used when saving a setting or series of settings. OK button rules:
OK button should be used when it is the ONLY action (besides cancel) that can be committed from the dialog. Do not mix OK with
other action buttons
In modal dialogs, clicking OK means apply the values, perform the task, and close the window Do not use OK buttons to respond to
questions
Label OK buttons correctly. The OK button should be labeled OK, not Ok or Okay
Do not use OK buttons in modeless dialog boxes. Use a action button or Close button
Action buttons
Action buttons have descriptive verbs that will be defined by the designer. Action button rules:
Action buttons can be used to describe more clearly the action that will be taken when clicked
One action button must be set as the default. This should be the action most closely mapped to the primary task of the dialog
There can be one or more action buttons, but do not mix OK button with action buttons
Use Cancel or Close button for negative commit buttons instead of specific responses to the main instruction
Otherwise, if user wants to cancel, the negative commit would require more thinking than needed for this particular small task
Cancel or Close Button
Verify the Close button on the title bar has the same effect as Close or Cancel
Esc is the keyboard shortcut for Cancel or Close
Cancel button
Cancel button should only be used when a task will be aborted and no change will be committed
Clicking the Cancel button means abandon all changes, cancel the task, close the window, and return the environment to its previous
state and leaving no side effect
For nested choice dialog boxes, clicking the Cancel button in the owner choice dialog typically means any changes made by owned
choice dialogs are also abandoned.
Don't use Cancel button in modeless dialog boxes. Use Close button instead
Close Button
Use Close button for modeless dialog boxes, as well as modal dialogs that cannot be canceled
Clicking Close button means close the dialog box window, leaving any existing side effects
Apply button (optional)
Apply button will commit any changes made within the dialog on all tabs, pages, or levels within a hierarchy without closing the dialog.
Optimally, the user will receive visual feedback of the applied changes. Here are some basic Apply Button rules:
In modal or modeless dialogs, clicking Apply means apply the values, perform the task, and do not close the window
In modeless dialog use Apply button only on those tasks that require significant or unknown upfront time to be performed, otherwise
data change should be applied immediately
The Apply button is disabled when no changes have been made. It becomes enabled when changes have been made
Clicking cancel will NOT undo any changes that have been already committed with the Apply button
Interacting with a child dialog (such as a confirmation) should not cause the Apply function to become enabled
Clicking the Apply button after committing a child dialog (such as a confirmation message) will apply all the changes made previous
to the action triggering the confirmation
Dialog Button (optional)
A dialog button performs an action on the dialog itself. Examples include: Reset and Tools for managing Favorites in an Open Dialog. They
should be aligned to the far left of the dialog (to the right of the help button if present) and should never be the default.
Implementation Notes
Keyboard Access - each commit button should have a keyboard access key mapped to it. The default button should be mapped to
Enter
The close button (whether it is Cancel or Close) should be mapped to Esc
If Apply exists, and is NOT the default button, it should be mapped to Alt-A
Ribbon Guidelines
The following are aspects of the ribbon UI that can be modified by individual API developers. These guidelines must be followed to make
your application's user interface (UI) compliant with standards used by Autodesk.
Ribbon Tab Placement
To make more room on the ribbon, third-party applications can now add ribbon controls to the Analyze tab as well as the Add-Ins tab.
Applications that add and/or modify elements within Revit should be added to the Add-Ins tab.
Applications that analyze existing data within the Revit model should be added to the Analyze tab.
Applications MUST NOT be added to both the Add-Ins and Analyze tabs.
Contextual Tab Focus User Option
The Revit 2012 product line contains a user option (located on the User Interface tab of the Options dialog) which allows users to choose
whether or not to automatically switch to a contextual tab upon selection. This option is set to automatically switch by default. For some API
applications, it may be favorable to have this option disabled, to prevent users from being switched away from the Add-ins or Analyze tab. In
these cases, it is best to inform users of this option in the documentation and/or as informational text in the installer user interface.
Number of Panels per Tab
Each API application SHOULD add only one panel to either the Add-Ins tab.
Panel Layout
The following guidelines define the proper way to lay out a panel on the Add-ins tab. The following panel under General Layout provides an
example to follow.
General layout
Figure 236 - Room & Area panel in the 2011 Revit products
A panel SHOULD have a large button as the left-most control. This button SHOULD be the most commonly accessed command in the
application. The left-most button icon will represent the entire panel when it collapses (see Panel Resizing and Collapsing below.) This button
MAY be the only button in the group, or this button MAY be followed by a large button and/or a small button stack.
Panels SHOULD NOT exceed three columns. If more controls are necessary, use a drop-down button.
Panels SHOULD only contain controls for launching commands and controlling the application. Controls for managing settings or launching
help and "about this application" should be located in a Slide-out Panel.
Ribbon Controls
Ribbon button
A Ribbon button is the most basic and most frequently-used control. Pressing a button invokes a command.
Ribbon buttons can be one of the three sizes:
Large: MUST have a text label
Medium: MAY have a text label
Small: MAY have a text label
Radio Buttons
A radio button group represents a set of controls that are mutually exclusive; only one can be chosen at a time. These groups can be
stacked horizontally (as seen in the justification buttons in the example below.)
Drop-down button
The top label SHOULD sufficiently describe the contents of the drop-down list.
Every item in the list SHOULD contain a large icon.
A horizontal separator can be optionally added between controls. This should be used if the items are logically grouped under one
button, but are separated into distinct groups.
Icons
For proper icon design, see the icon design guidelines.
Text Usage
Button Labels
These guidelines are for English language only.
MUST not have any punctuation (except hyphen, ampersand or forward slash)
MUST be no longer than three words
MUST be no longer than 36 characters
MUST be Title Case; e.g. Show Mass
The ampersand "&" MUST be used instead of "and". A space should appear before and after the ampersand
The forward slash "/" MUST be used instead of "or". No spaces should appear before and after the slash
Only large buttons MAY have two line labels but MUST NOT have more than two lines. Labels for all other controls MUST fit on a
single line
Button labels MUST NOT contain ellipses (
Every word MUST be in capital case except articles ("a," "an," and "the"), coordinating conjunctions (for example, "and," "or," "but,"
"so," "yet," "with," and "nor"), and prepositions with fewer than four letters (like "in"). The first and last words are always
capitalized
Panel Labels
These guidelines are English-only. All rules from the Command Labels section apply to Panel Labels in addition to the following:
The name of the panel SHOULD be specific. Vague, non-descriptive and unspecific terms used to describe panel content will reduce
the label's usefulness
Applications MUST NOT use panel names that use the abbreviations "misc." or "etc"
Panel labels SHOULD NOT include the term "add-ins" since it is redundant with the tab label
Panel labels MAY include the name of the third party product or provider
Tooltips
The following are guidelines for writing tooltip text. Write concisely. There is limited space to work with.
Localization Considerations
Make every word count. This is particularly important for localizing tooltip text to other languages
Do not use gerunds (verb forms used as nouns) because they can be confused with participles (verb forms used as adjectives). In the
example, "Drawing controls", drawing could be used as a verb or a noun. A better example is "Controls for drawing"
Do not include lengthy step-by-step procedures in tooltips. These belong in Help
Use terminology consistently
Make sure that your use of conjunctions does not introduce ambiguities in relationships. For example, instead of saying "replace and
tighten the hinges", it would be better to split the conjunction up into two simple (and redundant) sentences - "Replace the hinges.
Then tighten the hinges"
Be careful with "helping" verbs. Examples of helping verbs include shall, may, would have, should have, might have, and can. For
example, can and may could be translated as "capability" and "possibility" respectively
Watch for invisible plurals such as "object and attribute settings". Does this mean "the settings for one object and one attribute" or
"the settings for many objects and many attributes"?
Be cautious about words that can be either nouns or verbs. Use articles or rewrite phrases like "Model Display" where model can be a
noun or a verb in our software. Another example is "empty file". It can mean "to empty a file" or "a file with no content"
Be careful using metaphors. Metaphors can be subtle and are often discussed in the context of icons that are not culturally
appropriate or understood across cultures. Text metaphors (such as "places the computer in a hibernating state") can also be an
issue. Instead, you might say "places the computer in a low-power state"
Writing/Wording Considerations
Use simple sentences. The "Verb-Object-Adverb" format is recommended
Use strong and specific verbs that describe a specific action (such as "tile") rather than weak verbs (such as "use to")
Write in the active voice (for example, "Moves objects between model space and paper space")
Use the descriptive style instead of the imperative style ("Opens an existing drawing file" vs. "Open an existing drawing file")
Make the tooltip description easily recognizable by using the third person singular (for example - "Specifies the current color" instead
of "Specify the current color")
Don't use slang, jargon, or hard to understand acronyms
Formatting Considerations
Use only one space between sentences.
Avoid repetitive text. The content in the tooltip should be unique and add value.
Focus on the quality and understandability of the tooltip. Is the description clear? Is it helpful?
Unless it's a system variable or command, do not use bold. Although bold is supported in Asian languages, it is strongly
recommended to avoid using bold and italics, because of readability and stylistic issues.
Avoid Dabbreviations. For example, the word "Number" has many common abbreviations: No., Nbr, Num, Numb. It is best to spell
out terms.
Good Example:
An example of a more useful descriptive sentence might be "Adds a file such as a .bmp or .png". This provides more detailed information and
gives the user more insight into the feature.
Poor Example:
In this example, the tooltip content repeats the tooltip title verbatim and does not add value to the tooltip. Additionally, if the translator
cannot identify whether this string is a name/title or a descriptive sentence, it will be difficult for them to decide on the translation style.
As with other guideline issues, follow Microsoft Guidelines for title and sentence case (listed below):
Title Case
Capitalize all nouns, verbs (including is and other forms of to be), adverbs (including than and when), adjectives (including this and
that), and pronouns (including its)
Capitalize the first and last words, regardless of their parts of speech (for example, The Text to Look For)
Capitalize prepositions that are part of a verb phrase (for example, Backing Up Your Disk)
Do not capitalize articles (a, an, the), unless the article is the first word in the title
Do not capitalize coordinate conjunctions (and, but, for, nor, or), unless the conjunction is the first word in the title
Do not capitalize prepositions of four or fewer letters, unless the preposition is the first word in the title
Do not capitalize to in an infinitive phrase (for example, How to Format Your Hard Disk), unless the phrase is the first word in the title
Capitalize the second word in compound words if it is a noun or proper adjective, an "e-word," or the words have equal weight (for
example, E-Commerce, Cross-Reference, Pre-Microsoft Software, Read/Write Access, Run-Time). Do not capitalize the second word
if it is another part of speech, such as a preposition or other minor word (for example, Add-in, How-to, Take-off)
Capitalize user interface and application programming interface terms that you would not ordinarily capitalize, unless they are casesensitive (for example, The fdisk command)
Follow the traditional capitalization of keywords and other special terms in programming languages (for example, The printf function,
Using the EVEN and ALIGN Directives)
Capitalize only the first word of each column heading
Sentence Case
Always capitalize the first word of a new sentence
Do not capitalize the word following a colon unless the word is a proper noun, or the text following the colon is a complete sentence
Do not capitalize the word following an em-dash unless it is a proper noun, even if the text following the dash is a complete sentence
Always capitalize the first word of a new sentence following any end punctuation. Rewrite sentences that start with a case-sensitive
lowercase word
Common Definitions
Ribbon
The horizontally-tabbed user interface across the top of (the application frame in) Revit 2010 and later.
Ribbon Tab
The ribbon is separated into tabs. The Add-Ins ribbon tab, which only appears when at least one add-in is installed, is available for third
party developers to add a panel.
Ribbon Panel
A ribbon tab is separated into horizontal groupings of commands. An Add-In panel represents the commands available for a third party
developer's application. The Add-In panel is equivalent to the toolbar in Revit 2009.
Ribbon Button
The button is the mechanism for launching a command. They can either be large, medium or small (Both large and small buttons can either
be a simple push button or a drop-down button.
Menu button
The default first panel on the Add-Ins tab is the External Tools panel that contains one button titled "External Tools." The External Tools
menu-button is equivalent to the Tools > External Tools menu in Revit 2009. Any External Commands registered in a .addin manifest file will
appear in this menu button.
Terminology Definitions
Several words are used to signify the requirements of the standards. These words are capitalized. This section defines how these special
words should be interpreted. The interpretation has been copied from Internet Engineering Task Force RFC 2119.
WORD
DEFINITION
MUST
This word or the term "SHALL", mean that the item is an absolute requirement
MUST
NOT
This phrase, or the phrase "SHALL NOT", means that the item is an absolute prohibition
SHOULD
This word, or the adjective "RECOMMENDED", mean that there may exist valid reasons in particular circumstances to ignore the item, but the
full implications must be understood and carefully weighed before choosing a different course
SHOULD
NOT
This phrase, or the phrase "NOT RECOMMENDED", mean that there may exist valid reasons in particular circumstances when the particular
behavior is acceptable or even useful, but the full implications should be understood and the case carefully weighed before implementing any
behavior described with this label
MAY
This word, or the adjective "OPTIONAL", means that the item is truly optional. One product team may choose to include the item because a
particular type of user requires it or because the product team feels that it enhances the product while another product team may omit the
same item