Generating Graphics and Collecting Assets

As always, many important ongoing issues are being presented and resolved in the Revit API discussion forum.

I continue struggling to create time to pick out and highlight the most relevant topics here.

I ended up with quite a number today:

Can You Avoid Generating Graphics?

Several developers encountered performance problems filtering for elements based on the view containing them.

In order to determine which elements are displayed in a view, the view has to be regenerated.

The first time this happens, Revit may display a progress bar saying 'Generating graphics'.

This can be triggered by a filtered element collector as well.

In the following, I'll summarise a couple of discussions around this topic.

The most recent was is the StackOverflow question on Revit : get all ViewSheet is very slow:

Question: For a plugin, I need to get all the viewsheets in the RVT file and display information from them in a XAML dialog. This process is very, very slow the first time I use it: with the debugger, it takes 500 ms for 83 plan views, and it is very slow without the debugger too. If I execute the code again, the execution is instantaneous. This code is causing it:

protected IEnumerable<Element> GetAllEl( Document doc )
{
  return new FilteredElementCollector( doc )
    .OfCategory( BuiltInCategory.OST_Sheets )
    .WhereElementIsNotElementType()
    .OfClass( typeofViewSheet ) );
}

Answer: I do not think there is currently a known generic solution for that problem.

A similar issue was just discussed with the development team:

Question: For a given element id, we need to find the list of sheet ids displaying it. Current solution: we loop through all the sheets and views and use FilteredElementCollector( doc, sheet.Id ). With the results from that, we perform one more call to FilteredElementCollector( doc, view.Id ) and look for the element id. Issue: the current solution takes a lot of time and displays a Revit progress bar saying Generating graphics. Is there any better way to know if a given element id is available in the sheet or not? For example, some API methods like this would be very useful:

  getAllSheets( ElementId ) // returns array of sheet id
  hasGuid( ElementId, sheetId ) // return true/false

Does the API provide any such methods, to check whether a given ElementId is available in the sheet?

Answer: So. the goal is to find a view that displays a particular element on a sheet? Many model elements could be visible on multiple views, while most annotation elements are typically present only in one view. What type of elements are you checking for? And what will you do with that info?

Response: The goal is to find a view that displays a particular element on a sheet. It can be any type of element.

Answer: Here are some previous related discussions:

Response: The problem is that the first call to FilteredElementCollector( doc, viewId ) shows generating graphics in the progress bar. Only the first-time search does so. The second time, search on the same view has no issues with performance.

Answer: The first time is slow because in order to iterate on the elements visible in a view, the graphics for that view must be generated. I can't think of a workaround to get a precise answer. You might be able to skip sheets which don't have model views in their viewport list to save a bit of time. Some sheets may only have drafting views and schedules and annotations.

The development team provided a very helpful suggestion which helped work around the generating graphics call by avoiding that specific filtering operation completely in another case, to loop through sheets generating graphics.

The solution there consisted in analysing exactly what relationship you are trying to retrieve. In that specific case, the Revit API provided direct support for the inverse relationship, so you can retrieve that and invert it to access the required elements.

Maybe you can optimise in a similar manner for your needs?

Read all Thermal and Physical Assets

Question: Is there a way to get the list of all Thermal and Physical assets using Revit 2019 API?

Answer: Those are used in Materials. I think you'd want to iterate over all materials in the document and look at each for its StructuralAssetId and ThermalAssetId. You can then look at the PropertySetElements that use those ids. You could probably also iterate PropertySetElements directly, which would be fine if you don't need to know what materials are using them.

Response: Thanks, just now got them as you suggested from the discussion on material assets collector for appearance, structural (physical) and thermal:

We are trying to gather all the material assets loaded into a project file but ran into a roadblock. We can successfully do this for the appearance assets, but for the other assets the approach does not work.

The only way that we can gather the structural and thermal assets is by starting with materials and cycle through the assets that are assigned. This approach will omit assets that are not assigned to materials.

Please see C# code below for reference. Any insight into how this can be achieved will be much appreciated.

  FilteredElementCollector collector 
    = new FilteredElementCollector( doc );
  //code works for appearance assets
  ICollection<Element> appearanceAssets 
    = collector.OfClass( typeofAppearanceAssetElement ) ).ToElements();
  //code throws an error
  ICollection<Element> physicalAssets 
    = collector.OfClass( typeofStructuralAssetClass ) ).ToElements();
  //code throws an error
  ICollection<Element> physicalAssets2 
    = collector.OfClass( typeofStructuralAsset ) ).ToElements();
  //code returns zero elements
  ICollection<Element> propertySet 
    = collector.OfClass( typeofPropertySetElement ) ).ToElements();
  //code throws an error
  ICollection<Element> thermalAssets 
    = collector.OfClass( typeofThermalAsset ) ).ToElements();

Error:

Other observations:

The appearance asset also has a built-in category OST_AppearanceAsset, while the structural and thermal assets do not have any corresponding built-in category.

The links below are our references to date:

Answer: Structural and Thermal Assets are contained in PropertySetElement objects. So, the line you wrote filtering for that should work. I checked in one of our templates and found 62 elements matching the filter.

Response: Yes, thank you for your direction.

The reason zero elements were collected in our previous code sample was because we used the same collector instance several times over, both for the appearance assets and the property set.

As soon as we defined a new one collector2, it worked.

The propertySet element hosts thermal and structural assets. However, there can be two property sets that have the same name (Air, for example), and one property set is dedicated to the structural, while the other to the thermal. You cannot easily discern whether setting the property set element to a material will set the thermal or structural assets. Essentially, the property set is either thermal or structural when applied to a material.

It seems like the Revit UI categorizes property sets further into thermal and structural categories, while API access is limited.

Below is an attempt to try to categorize the propertyset elements. Some property sets return a null value when the thermal asset info is missing and vice-versa.

  // property set: thermal and structural
  FilteredElementCollector collector2 
    = new FilteredElementCollector( doc );

  ICollection<Element> propertySet 
    = collector2.OfClass( typeofPropertySetElement ) )
      .ToElements();

  // loop through property sets to gather 
  // structural and thermal assets
  foreachPropertySetElement psEle in propertySet )
  {
    try
    {
      // gather
      StructuralAsset structAsset = psEle.GetStructuralAsset();

      // process - currently add both aspects of 
      // property set if they exist. this method can 
      // have same p-set element id in both thermal 
      // and structural
      if( structAsset != null )
      {
        structuralAssets.Add( psEle );
      }
    }
    catch
    {
      // code
    }
    try
    {
      // gather
      ThermalAsset thermAsset = psEle.GetThermalAsset();

      // process - currently add both aspects of 
      // property set if they exist. this method can 
      // have same p-set element id in both thermal 
      // and structural
      if( thermAsset != null )
      {
        thermalAssets.Add( psEle );
      }
    }
    catch
    {
      // code
    }
  }

Here is the ThermalAsset data extracted from a propertySet originally assigned to a StructuralAssetID of a material:

Snooping property set element

If the property set elements that host primarily the structural assets can be separated from the ones that host the thermal assets, then we would have to lists of property sets that we can work with.

Is there any way to get all the list directly instead of checking the PropertySetElements?

Answer: Sorry, checking the elements is the only way to get into the document's database for these items.

Collection of Old Add-In Managers

An old thread requesting Add-in Manager 2018 compiled version came up again:

Question: Is there a place where I can find a compiled version of the Add-in Manager for Revit 2018? Previous versions also, if possible. In our company, we have administrator restriction rights, so we can't easily install the Revit SDK.

Answer by Jim Jia: Here is a zip file add_in_manager_2015_2018.zip containing multiple versions of the Add-in Manager from the Revit SDK, for Revit 2015, 2016, 2017 and 2018.

Please also note that the Revit 2020 SDK was lacking the add-in manager, but the version from the Revit 2019 SDK still works in Revit 2020 as well.

Compiling an Add-In Without Revit Installed

Question by Armand on multi-targeting Revit versions using TargetFrameworks:

Question: Is it possible to write/compile Revit add-ins without having the specific version of Revit installed on your development machine? I am currently supporting add-ins that I have written for Revit versions 2016 thru 2020. I am setting up a new development machine and do not want to install 2016, 2017, & 2018. Does this mean I can no longer maintain the code that targeted those versions? Is there a way to just reference copies of those specific DLL files?

Answer: I have good news for you. You do not need to install Revit on your development machine. All you need are the Revit API .NET assemblies. As a minimum, they include RevitAPI.dll and RevitAPIUI.dll. There are many more that are optional. You can even create a NuGet package to deploy them to your development machine, or possibly use an existing Revit API NuGet package.

Xeokit 3D BIM and CAD Viewer

The xeokit is a software development kit from xeolabs for viewing high-detail 3D BIM and CAD models in the web browser.

Check out all the details in the xeokit-sdk JavaScript SDK GitHub repository.

It can load multiple models into the same 3D scene, from source formats including glTF, OBJ, 3DXML, STL, 3DS and BIMServer.

Software Development Manager Job Opportunity

Let's close for today with a current job opportunity here in Switzerland that may be of interest, for a Software Development Manager in Rümligen, Bern, Switzerland, Job ID 19WD35458:

Position Overview

The Autodesk Construction Solutions group is seeking a Software Development Manager to lead one or more agile teams. You and your team will design, build and run full stack web, mobile and cloud applications. As the Software Development Manager, you have a critical role in setting direction and expectations for the team. You will oversee both process and technology and help teams to make the right decisions when needed. You will be part of the Preconstruction organization working on new BIM 360 products that enable our customers to work more efficiently and collaboratively. If you are a leader that enjoys working with highly talented individuals, latest technologies and the best tools available, we would love to hear from you!

Responsibilities

Minimum Qualifications

Preferred Qualifications

The Ideal Candidate

You are a strategic thinker with a strong desire to deliver results. You can see the big picture and help the team to deliver in a dynamic, agile environment with changing priorities. You are not afraid to ask critical questions and influence the decision-making process. You can work independently and manage multiple priorities. You’re an effective communicator and easily build collaborative relationships. You are experienced in adapting language and content to the type of conversation. You enjoy the daily collaboration with your team, other disciplines and senior management. You build collaborative relationships through open feedback in an environment of trust. You enjoy leading people. You have mastered various leadership styles and you enjoy leading talented people with diverse seniority in different project phases. You can sense unleashed potential and strive to work with individuals to maximize their performance and engagement.

How You’d Spend Your Day

If you are interested in other jobs and other locations, please take a look at the possibilities listed at www.autodesk.com/careers.

If you see an opportunity that you are interested in, you can send me the job id for it and I will provide you with a personal referral link for it.

Good luck!