Events, UV Coordinates and Rooms on Level

A lot of interesting solutions were shared in the Revit API discussion forum and private email messages during my absence last week, and several exciting events are looming:

Forge Accelerator in Gothenburg

We have two Forge accelerators coming up in Europe in the next couple of months:

I am planning to attend both and would love to see you there too.

In fact, the complete EMEA DevTech Team will be present to support you over the course of the week.

They take place in the Autodesk offices with lots of space and cool recreation areas.

Attendance is free of charge – all you pay for is your travel, accommodation and living expenses.

You can still apply to participate in either of these two events by sending your Forge App development project ideas to adn-training-worldwide@autodesk.com.

More information is available at autodeskcloudaccelerator.com.

Check out the videos on the landing page to hear what great results the attendees at previous accelerators achieved after just one week of intensive teamwork and training.

AEC Hackathon in Munich

Directly after the Gothenburg accelerator, March 31 - April 2, the AEC Hackathon Germany is taking off at the Technical University Munich.

It gives everyone designing, building, and maintaining our built environment the opportunity to collaborate with cutting edge technologies and its developers and designers.

It’s a weekend of geeking at its finest for improving the industries that affect all that live or work in a house or building.

Jaime is going, and unfortunately, I am not...

Autodesk University in London

As I mentioned, Autodesk University is coming to London, to Tobacco Dock, E1 on June 21-22, 2017; the first English speaking Autodesk University in Northern Europe!

Registration for Autodesk University London 2017 is now open. Number are limited and an early bird discount is available until April 14.

To get a taste of what we’ve got in store for you this year, check out the venue, view the agenda and timings and find out all you need to know, visit the AU London website.

AU London 2017

Retrieve and Map Texture UV Coordinates Exporting Geometry and Material

Question: I have a question looking at the rather outdated discussion on texture data UV coordinates and FBX:

I find that the API Mesh.UVs is not available in Revit 2014 or later.

How can I retrieve the mesh UVs now?

How can I map texture UV accurately when exporting Revit geometry and materials?

I already tried Edge.TessellateOnFace(Face) and Face.GetBoundBoxingUV; neither of them works as desired (not accurate).

  Mesh geomMesh = geomFace.Triangulate();
  XYZArray vertices = geomMesh.Vertices;
  UVArray uvs = geomMesh.UVs; // This API is not available

Answer: You should use the CustomExporter – the OnMaterial and OnPolymesh methods are designed for these sorts of export operations.

XYZArray is way obsolete, and most custom Revit API collections have been replaced by generic ones in the past few years, e.g., List<XYZ>, in this case.

Collect all Rooms on a Given Level

From the Revit API discussion forum thread on collecting all rooms in level xx:

Question: How can I collect all rooms on a given level?

Answer 1: You can't collect Rooms directly, you need to collect SpatialElement instead, its parent class, and then post-process the results:

  public List<Room> GetRoomFromLevel( 
    Document document, 
    Level level )
  {
    List<Element> Rooms 
      = new FilteredElementCollector( document )
        .OfClass( typeofSpatialElement ) )
        .WhereElementIsNotElementType()
        .Where( room => room.GetType() == typeofRoom ) )
        .ToList();

    return new List<Room>( Rooms.Where( room 
        => document.GetElement( room.LevelId ) == level )
      .Select( r => r as Room ) );
  }

The Where and List<> stuff comes from the System.Collections.Generic namespace.

Answer 2: Here is a new method GetRoomsOnLevel that I added to The Building Coder samples release 2017.0.132.8 sporting some small improvements:

  #region Retrieve all rooms on a given level
  /// <summary>
  /// Retrieve all rooms on a given level.
  /// </summary>
  public IEnumerable<Room> GetRoomsOnLevel( 
    Document doc,
    ElementId idLevel )
  {
    return new FilteredElementCollector( doc )
      .WhereElementIsNotElementType()
      .OfClass( typeofSpatialElement ) )
      .Where( e => e.GetType() == typeofRoom ) )
      .Where( e => e.LevelId.IntegerValue.Equals( 
        idLevel.IntegerValue ) )
      .Cast<Room>();
  }
  #endregion // Retrieve all rooms on a given level

This is more efficient than the first version due to:

The reason you cannot filter directly for Room elements is explained in the discussion on filtering for a non-native class and in the remarks on the ElementClassFilter class.