Using the Revit IFC Export in your own add-on

In September 2011, Autodesk make accessible the Industry Foundation Classes (IFC) exporter for Revit as open source code, licensed through a LGPL v. 2.1 licensing agreement. In 2014, this project evolved to include IFC import as well, and was named “IFC for Revit”.

This source code is available on Source Forge, and everyone can contribute to the part of Revit that deal with IFC.

This source code is now the built-in IFC engine for Revit, and I was told that this engine is also behind the conversion service available through Forge.

When the user clicks on Export to IFC, an even is triggered, and Revit catch this even to run the IFC exporter. This also works when the event is triggered by the Document.Export() used through the Revit API by a third-party add-on, like the one I built last week. This IFC Export engine will then read the Revit model, convert every element into its IFC counterpart, and write the resulting IFC file.

How Revit export to IFC

This IFC engine comes with a special UI, the IFCExporterUI, designed to tap into the capabilities of the open-source IFC exporter to give you more control over the configuration of your export.

There are different add-ons for each Revit version, and each new release of Revit is shipped with the most up-to-date IFC engine available at the time. However, the code for this engine evolve quickly, and you can always download the latest version as an add-on on the Autodesk App Store.

At the time of writing, the landscape looks like this:

Revit Version Built-in IFC Exporter version Latest IFC Exporter version (with the Revit IFC add-on)
2016 Exporter 16.0.490.0 – Default UI Exporter – Alternate UI
2017 Exporter 17.0.1081.0 – Alternate UI Exporter – Alternate UI
2018 Exporter – Alternate UI Exporter – Alternate UI

If you want to know witch version you have, you can check it by opening an IFC file with a text editor and look among the first lines, the FILE_NAME one:

Check you exporter version

I didn’t dig into the subtleties of the different flavors of each Revit version, like R2 and other exotic name, you get the picture.

Last week, I published a Revit add-on to send a model to bimsync. Under the hood, this add-on exports the Revit model to IFC before uploading it to bimsync. As I was building my add-on, I realized that I couldn’t just use the Document.Export() function with whatever IFC export settings Revit could provide me. To be useful, such an add-on must allow the user to set up his own IFC Export configuration.

I look into the code of the IFC Exporter UI to understand how this user interface communicate with the export engine. I found out that you need an IFCExportConfiguration class to use a specific IFC Export configuration. Below is an example of the code needed to export a Revit model to IFC:

//Create an instance of IFCExportOptions
IFCExportOptions IFCOptions = new IFCExportOptions();

//Get an instance of IFCExportConfiguration
IFCExportConfiguration selectedConfig = modelSelection.Configuration;

//Get the current view Id, or -1 if you want to export the entire model
ElementId activeViewId = GenerateActiveViewIdFromDocument(doc);
selectedConfig.ActiveViewId = 
        selectedConfig.UseActiveViewGeometry ? activeViewId.IntegerValue : -1;

//Update the IFCExportOptions
selectedConfig.UpdateOptions(IFCOptions, activeViewId);

string folder = "A path to a folder where you want to save your IFC file";
string name = "the name of your IFC file";

//Export the model to IFC
doc.Export(folder, name, IFCOptions);

You start by creating an instance of the IFCExportOptions found in the Autodesk.Revit.DB namespace. This is standard in all Revit flavors.

Then, you retrieve or create an instance of the IFCExportConfiguration class. This is a class provided by the IFC Export add-on that hold every aspect of your export configuration, from knowing if you want to export the BaseQuanties to the path to the IfcPropertySets mapping files.

You get the Id of the active view and use the UpdateOptions method of IFCExportConfiguration to pass it along with all other properties to the IFCExportOptions.

The IFC Export add-on also provide an IFCExportConfigurationsMap class to get the built-in configurations and store the new ones.

The existing export setups

But where find these IFCExportConfiguration and IFCExportConfigurationMaps classes ?

If the IFC for Revit add-on is installed, you can find these classes in the IFCExporterUIOverride.dll. This dll can be found in your ApplicationPlugins folder, in the IFC plugin install folder (C:\ProgramData\Autodesk\ApplicationPlugins\IFC 2018.bundle\Contents\2018)

Running this on a Revit equipped with the add-on will work nicely, but it will fail miserably when the user doesn’t have the IFC for Revit add-on. In this case, the add-on can’t find the IFCExporterUIOverride.dll containing the IFCExportConfiguration class:

Using IFCExportConfiguration without the add-on

If you have a Revit version with the IFC Exporter UI built in (Revit 2017 or 2018), the IFCExportConfiguration and IFCExportConfigurationMaps classes can be found in the IFCExportUI.dll, located in your Revit installation folder (C:\Program Files\Autodesk\Revit 2018\AddIns\IFCExporterUI). In this case, the features available are the same than our previous case, but are in a different dll.

If you don’t have the IFC Exporter UI at all (Revit 2016 and earlier versions), you must fall back to the basic export options.

In a nutshell, we have to manage these three cases:

Class DLL Revit version
IFCExportConfiguration IFCExporterUIOverride.dll

In C:\ProgramData\Autodesk\ ApplicationPlugins\IFC 2018.bundle\Contents\2018

All Revit version equipped with the IFC for Revit add-on
IFCExportConfiguration IFCExportUI.dll

In C:\Program Files\Autodesk\Revit 2018\AddIns\IFCExporterUI

Revit 2017 and 2018 without the IFC for Revit add-on
IFCExportOptions RevitAPI.dll

In C:\Program Files\Autodesk\Revit 2018

Revit 2016 and earlier without the IFC for Revit add-on

To manage these different cases, I created my own export configuration class, named IFCExportConfigurationCustom. This class handle the configuration of the export and is an interface between my code and the possible IFC export options.

I load in my Visual Studio solution the two dll containing the IFCExportConfiguration class, and using alias, I call a different version of it depending on the installation of the user:


I also handle the vanilla Revit 2016 in my IFCExportConfigurationCustom class, without using any version of the IFCExportConfiguration (which is not available in this version of Revit), using instead the plain old IFCExportOptions built-in into Revit.

By managing the different possibilities of the Revit installation, I am able to make use of the best configuration available to export IFC. I am also able to use directly the Setup configuration interface available in the custom UI, and retrieve these user-defined export setups in my add-on.

Edit IFC Export Setup

If you plan on building your own Revit add-on to upload IFC models to a cloud service, don’t hesitate to look into the source code behind this article, the solution can be found on Github.

By opening the source code of its IFC engine, Autodesk make an underrated effort toward interoperability. Even if it’s obviously not for every Revit user, I think that everyone who rely on the Revit IFC export for its own software should look at this engine to get a full understanding of the possibilities offered by this exporter


Revit plugins updates and new features

As usual during this time of the year, I published the new version of my plugins for Revit.


The big improvement this year is the ability to align any type of elements, annotations or tags. I must thank Deyan Nenov and his large contribution to the source code for this new feature.

From now on, you can select any kind of element and align or distribute them evenly. This feature use the bounding box of the element in the view as a reference.

Align or distribute all elements

The Align command is still view-dependent, so using it in section view or in a plan view will not have the same effect on the overall position of a given element. A word of caution however, the align function can be unreliable in a 3D view.

View-dependent align functions

Of course, you can still use it to align or distribute your tags and annotations, and it even works with viewports:

Align viewports

Along with these improvement, Align now fully support Area tags, and a few bugs have been eliminated. You can now use Align even if on tag without a leader, and multi-leader text are now fully supported, and some selection subtlety have been introduced.

Align tags and texts

I haven’t tested it with all categories, if you find something weird, please let me know, I would be happy to fix it.

You can find this new version on the Autodesk App Store.

Room Finishing

Along with the support for Revit 2018, I corrected an issue where a skirting board was created even if the room was not bound by a wall. From now on, Room Finishing will not create a skirting board along room bounding lines.

Support room with room boundary lines

Room Finishing is also available on the App Store.

Time Stamper

The Time Stamper plugin got a few improvements this year along with the usual bug smashing.

You can now choose between applying your time stamp to every element, or just the one visible in the view. This will give you the ability to filter on which element you want to apply a stamp.

You can also choose to keep or override an existing value, this should help you keep the history of a given element.

A few bugs where corrected, making the creation of the four shared parameters far more reliable. Groups are now supported.

Support for groups

Time Stamper is now available here.

These new versions are now available on the Autodesk App Store. Don’t hesitate to report any issue you might find in them or ask for improvement.

These plugins are open source, you can find the source code here, here and here. Feel free to use it on your own project or contribute to these projects.

Modeling a neighborhood with Flux Site Extractor, GIS data and Revit

Since my last post, I kept on working on urban development. I particularly think about importing GIS data into our usual authoring tools. My experience with Infraworks was interesting, but it is still difficult to use this data in a Revit model.

The most promising resource out there for creating a context in a Revit model is the Flux Site Extractor. You select an area, add some features to extract and send them to a Flux project.

The Flux Site Extractor interface

After retrieving this data in my Flux Site Project, I use the Flux Dynamo nodes to get the topography as a mesh, extract the vertices of this mesh as points and use these points to create a toposurface in Revit.

Creating a toposurface from the Flux Site Extractor

Building profiles and heights came from OpenStreetMap, and aren’t accurate enough to be used for site analysis. But I am using building profiles to draw on a plan view the footprint of every building retreived with Flux. This will help me futher down the road to align my buildings on the toposurface.

Buildings footprints drawn in a plan view

I found more accurate data on the parisian buildings on the APUR Open Data plateform. I download this data as a shapefile containing every building in Paris.

Obviously, this dataset is too large to be imported as it in Revit. I am using QGIS, an open source GIS application, to extract a subset of this file. To do so, I draw a polygon encompassing the few city blocks I want to retrieve and use the “Clip” function to create a new shapefile containing only the selected buildings.

Isolate the propers city blocks

I am using the DynamoGIS package to import this shapefile into Revit. These nodes allow me to read the file and extract the shapes of the buildings.

The most difficult thing here was to include inner boundaries in a building shape. These boundaries are not taken into account by the Surface.ByPatch node. I manage to split the first surface (the largest) using the inner curve. This allow me to create the hollowed surface.

Highlight of inner boundaries

The DynamoGIS include nodes to query any value associated with shapes. I am using them to retrieve building heights in the dataset and extrude my buildings at their proper height.

Since it is GIS data, I am using a nice tip from LandArch to move my geometry near the project base point, and make it usable in Revit.

I am using the FamilyInstance.ByGeometry node from the great Spring nodes of Dimitar Venkov to create the buildings as mass families.

This Dynamo definition create a mass family for every building in the shapefile, extruded up to its actual height. Combined with the toposurface created with Flux, this look like an actual neighborhood, where you can think about massing and site integration directly in Revit.

Site integration of a project

This process still has a few issues. The buildings aren’t adjusted at the toposurface and aligning them with the toposurface created with the Flux Site Extractor involve some manipulations. I still have some work to do on this process to streamline it, and get a more accurate representation of an existing site.

Another view of the project


Room Finishes Update

I keep on working on my Revit add-ins. After Align, it is now Room Finishes who have been updated to support Revit 2017. Along with this update, I also have integrated some new features.

First of all, Room Finishes now support all kind of units. You just have to type your dimension with its unit symbol, and the plugin will convert it in a floor height or a skirting board height. The plug-in will now also use the default length unit of your model.


I have to thanks Brian Winterscheidt for this update, who was kind enough to contribute to my plug-in on Github, and point me to the Revit unit conversion system available in the API.

The other major update is the ability to join skirting board with their supporting wall. You can now join both geometries automatically. This enable one of the most wanted feature, the ability to cut the skirting board around the door.

Just select “Join geometry” before running the command, and every skirting board will be joined with its host wall.


This feature could generate its fair share of warning, so I have remove every related error message. You will now be able to run this command without having to dismiss every warning that come up.

I also add some minor UI improvements, like the ability to resize the window, or sorting wall type names by alphabetical order to be able to quickly find the specific wall type you have created for your skirting board or your floor finish.

Of course, Room Finishes is still open source, the entire code can be found on Github.

This plug-in is already available on the Autodesk App Store. If you like it, don’t hesitate to write a nice comment or add a few stars, it always means so much to me!

Align Tags Update

This is a long overdue update, but I finally take the time to prepare my Align Tag plug-in for Revit 2016.

Along with the annual clean up and bug fixes, I also add a new feature called Arrange Tags. This will automatically arrange all tags with a leader all around the active view.


This function is slightly different from the previous ones since you don’t need to select any tags before running it. Just click on Arrange Tags, and every tag will be neatly placed on each side of the active view.


This function works great on small views, like local sections or callouts. Don’t expect too much on plan views, you will be disappointed.

How it work?

The main idea behind Arrange Tag is to find on the left or the right of the view the nearest available space to place a tag. Once every tags are neatly placed on each side of the view, a second subroutine check every tag leaders and uncross them.


This feature use an opinionated way to organize tags on a view, and it probably won’t please everybody. I created it specifically to place tags on section views, and it follows my own drafting rules. That being said, I hope you will find it useful.

The application is available on Autodesk App Exchange. If you don’t mind fumbling into my code, you will also find the entire solution on Bitbucket, fell free to use it for your own projects.

Model Timestamp

As we receive models from subcontractors or partners, we need to integrate them in a coordination model.

The coordination model files structure look like this.filestructure

In the coordination model, we use linked views and model specific overrides to fine tune model display. To keep these settings when a linked model is updated, we just override the previous liked file with its new version. This process implies to rename the file each time we receive a new version from a subcontractor. So when we receive a file named with a date or a version, we rename it along some quality control checks.


But we also have to follow which model version we are linking in our coordination model. Renaming files is great to keep the link alive, but we lost the original name in the process.

To keep track of the version of the linked file, I create some kind of timestamp on every object of a given model. This application writes version information on four shared parameters, common to every object.

Once in the coordination model, these shared parameters allows us to know from which version a given element came from.


They can also be used to create filters to highlight the origin of each element in a view.

I also find some very interesting side effects. For example, I create a linked models schedule with a multi-category schedule displaying only the four shared parameters.


My only concern is the performance of such an application. I run it on the Revit MEP example file, and it take 31 seconds, regeneration included. It could easily handle a larger model, but the user will then need some patience as the application run.

You will find below a piece of code I use to write values on every elements of the model. This code does not include any interface, but I hope to be able to publish a packaged version anytime soon.


public void ModelTimeStamp()
	Document doc = this.ActiveUIDocument.Document;
	using (Transaction tx = new Transaction(doc)) {

		tx.Start("Model TimeStamp");

		//Create a list of category
		CategorySet myCategories = CreateCategoryList(doc, this.Application);

		//Retrive all model elements
		FilteredElementCollector collector = new FilteredElementCollector(doc);
		IList<ElementFilter> categoryFilters = new List<ElementFilter>();

		foreach (Category category in myCategories)
			categoryFilters.Add(new ElementCategoryFilter(category.Id));

		ElementFilter filter = new LogicalOrFilter(categoryFilters);

		IList<Element> elementList = collector.WherePasses(filter).WhereElementIsNotElementType().ToElements();

		//Add the value to all element
		if (elementList.Count > 0)
			foreach (Element e in elementList)
				WriteOnParam("Date", e, DateTime.Now.ToShortDateString());
				WriteOnParam("Version", e, "First Release");
				WriteOnParam("FileName", e, "SubContractors Model");
				WriteOnParam("Trade", e, "HVAC");



private void WriteOnParam(string paramName, Element e, string value)
	IList<Parameter> parameters = e.GetParameters(paramName);
	if (parameters.Count != 0)
		Parameter p = parameters.FirstOrDefault();
		if (!p.IsReadOnly)

private CategorySet CreateCategoryList(Document doc, Autodesk.Revit.ApplicationServices.Application app)
	CategorySet myCategorySet = app.Create.NewCategorySet();
	Categories categories = doc.Settings.Categories;

	foreach (Category c in categories)
		if (c.AllowsBoundParameters && c.CategoryType == CategoryType.Model)

	return myCategorySet;

Revit Tracking

My previous post about Revit performance highlighted the need for precise feedback from user about starting and synchronizing time. This is important when dealing with many users, with potentially different configuration and performance. In this case, these loading times can alert you soon enough of a problem with a model.

Having feedback from every user is also important, since you need to detect quickly if any user is having more difficulty to open a file than the average.

You can also compare file size progression with loading time to establish and check your set of good practices for keeping Revit models powerful.

To be more accurate and systematic with these measures, I create a small piece of code to log every opening, synchronizing and closing of Revit model for multiples users.

On startup, the application subscribe to the events triggered on opening, synchronizing or closing a model.

         public RevitLogger( UIControlledApplication a)
            ControlledApplication app = a.ControlledApplication;

            //Subscribe to the opening event
            app.DocumentOpening += 
            app.DocumentOpened += 

            //Subscribe to the synchronizing event
            app.DocumentSynchronizingWithCentral += 
            app.DocumentSynchronizedWithCentral += 

            //Subscribe to the closing event
            app.DocumentClosing += 
            app.DocumentClosed += 

Subscribing to the starting event and the ending event allow me to track down the time taken by each task.

Afterward, each event handler measure the time taken to perform the task, along with other properties related to the Revit file like its name, its path, if it is workshared, and so on.

For example, to log the opening of a model:

         private void DocumentOpeningEventHandler(
                 object sender,
                 Autodesk.Revit.DB.Events.DocumentOpeningEventArgs args)
            //Retrive info about the file
            BasicFileInfo FileInfo = BasicFileInfo .Extract(args.PathName);

            _logReccord = new LogReccord(ReccordType .Open);
            _logReccord.ReccordStarting = DateTime.Now;

         private void DocumentOpenedEventHandler(
                 object sender,
                 Autodesk.Revit.DB.Events.DocumentOpenedEventArgs args)
            _logReccord.ReccordEnding = DateTime.Now;

Here, the LogReccord class allow us to store the information retrieved in the event handler. Once these information are stored, it is pretty easy to collect them and write them down to a csv file.

It is now possible to quickly create very precise graph displaying opening time of different model, compare them and show their evolution along time


The next step should be to send these information to a shared SQL database in order to retrive data from every users. We should have this way a company-wide tool for keeping track of Revit performance.


CASE Design, Inc. Add-Ins

As Case Inc update their set of tools for Revit 2015, I write a few words about them.

CASE Inc. is a Building Information Modeling consultancy based in New York City, which provide a very interesting set of tools for managing Revit models. I am using these tools on a daily basis to automate repetitive tasks, and extract data from my model.

These tools come with a nice installer, allowing us to add applications for Revit and Navisworks, in various version.


It load a new ribbon bar in Revit, displaying all the available tools:


I am not using all of them, so I will just present here my favorites.

View Duplicator:


This tool allows me to quickly duplicate a set a view, and create for example a set of view for publishing. You can add a prefix or a suffix on every one of them, and filter the existing view to quickly select which one you want to duplicate.

Param To Param:


Originally design to write down parameter values to be able to export them in schedules, I am also using it to refactor in a single place parameters values scattered in various locations. One of the most useful example is to write down the reference level name in a single shared parameter applied on multiple categories.

Door Mark renumbering:


This tools allow us to mark a door with its related room. This is a very fast solution for extracting Room-Door relation, for schedule or room plan.

 Export Famillies to RFA:


Autodesk provide with Revit a very comprehensive set of families. But most of these families need to be sorted and renamed to fit the practice of our office. To do so, we add all of them in a Revit file, sort and rename them in this model, and finally, export all of them in nicely ordered folders for every draftsmen to use.

Shared Parameter Loader:


Finally, the Shared Parameter Loader allow me to quickly add large set of shared parameters on specific categories. This is especially useful when dealing with sheets parameters which have to be added to ever model in order to produce drawings.

These tools ease largely my daily pain while dealing with Revit models, and deserve to be in the toolbox of every Revit BIM Manager.


Walls in Geometry Gym

A recent webinar about interoperability between Grasshopper and Revit make me look again on these tools, particularly for importing walls, In fact, I generally test these kinds of tools with a set a beams, more or less intricate, but never with walls, so I decide to generate a set of walls using the Geometry Gym IFC Importer for Revit.

Using Geometry Gym require at least some basic knowledge of the IFC structure. In fact, using this tool can be a really good starting point for studying the model behind Industry Foundation Classes.

Any IFC building object must be included in a (IFC) building, itself included in a (IFC) project, both of them must have a GUID and a name. So we start by placing these components on the Grasshopper’s caneva.

In order to have our NURBS path curve understood by Revit, we approximate it into a set of lines and arcs, using the specific Geometry Gym component.

We create an ggIFCElementParameter component to give a pretty name to our wall.

In order to create the multy-layer structure, we add two materials, both of them linked to a MaterialLayer component where we define the thickness of each layer. These component are merged into a MaterialLayerSet, itself link to a wall type.

The IFC class used by Revit for generating walls is the IFCWallStandardCase, so we use this component in our Grasshopper definition. We link all these components to our IFC Wall Standard Case, had a height parameter, and bake the whole think.

The resulting IFC file contains a pretty good wall, with every expected parameter. We check it in my favorite IFC viewer, the Solibri Model checker.

Once imported in Revit, using the embedded plugin, it creates a generic component looking like our wall. It appears in a schedule with the family name and type as set, but it’s still not an editable Revit wall.

I generally use the massing tool to create walls in Geometry Gym. I create a simple IFCExtrudedAreaSolid (for example) from a base NURBS curve, and then import it in Revit to generate a mass.


I can now use this mass to create my curved walls in Revit, along with the floors slabs. This method need an additional step (creating the wall from the Revit mass faces), but create native Revit walls.

As I write these lines, a new version of the IFC Import plugin for Revit have been posted on the Geometry Gym blog, I still have to review the improvement.

Parametric modeling in Revit

There is a trendy topic on the Grasshopper forum these days about links between Grasshopper and Revit, and this refers to a more general subject : How to generate parametric geometry in Revit.

Since embedded tools in Revit are mostly oriented toward classical design, workarounds have been developed to create a more complex geometry.

The Revit plug-in Dynamo, developed by Ian Keough, is one of these tools. Starting as an open source side project, it has been integrated into the Autodesk lab to became one of its most popular projects.

This tool is a graphical user interface (GUI) for parametring design directly into Revit. It looks pretty much like Grasshopper, with a canevas where we drag components link together to directly create native Revit elements.

WhiteFeet is also a Revit Plugin, which allow creating native Revit elements from an Excel datasheet. It can be used alone, but I rather use it with Hummingbird, a Grasshopper extension used to generate these Excel datasheets. There is a Grasshopper component for each major Revit command.

Designing these element in Grasshopper follow pretty much the same logic than in Revit, with family name and type, points and parameters, except of course for the possibilities offered by natives Grasshopper components.

Here is a little example for generating beams on a double-curved surface from LunchBox.

Make sure you have the correct Excel 2010 worksheet opened; I struggled for a while before realizing that my Excel version was outdated.

The Hummingbird component writes a few lines in our Excel file, something like that:

Then we go the Add-Ins panel of Revit and start the WhiteFeet Model Builder to import our datasheet. There are a few options to set, with everything quite self-explanatory.

The plugin generated smoothly these beams in Revit, with all the requested parameters:

Among Grasshopper plugins, Chameleon allows to create Revit adaptative components directly from Grasshopper. It also includes components to edit Revit parameters directly on the model.

All these plugins, among others, became a very interesting alternative to the average modeling in Revit, and fill the gap between parametric modeling and a more average BIM modelisation.