Barcelona Questions

Thanks to Alex Vila Ortega of Autodesk Spain, I spent the last couple of days here in Barcelona giving a training class on the Revit API, with lots of professional and enthusiastic participants.
Here are some of the questions that we explored.

Question:
How can I retrieve all the windows hosted by a specific given wall?

Answer:
Well, one possibility is to make use of the

relationship inverter

that we already discussed.
This will provide a global dictionary mapping each wall in the entire model to a list of all the windows it hosts.
Here is an idea for a more direct and localised approach using API filtering:

We can make use of the fact that each window’s host id is available not only from the FamilyInstance Host property, but also through the built-in parameter HOST_ID_PARAM.
This means that we can build a filter checking for the following combination of properties:

  • Category Windows.
  • Type FamilyInstance.
  • Built-in parameter value for HOST_ID_PARAM equal to the given wall element id.

The resulting Boolean ‘and’ combination should return all the windows hosted by a specific wall.

Question:
I create new levels through the API and that works fine.
However, no views are generated for these levels.
How can I generate views for the new levels?

Answer:
You might get some ideas by searching globally in the SDKSamples2009 solution for the NewLevel method, which is used to create a new level.
One of the places it is used is the FrameBuilder SDK sample, in FrameData.cs:


Level newLevel
= createDoc.NewLevel( elevation );
createDoc.NewViewPlan( newLevel.Name,
newLevel, ViewType.FloorPlan );

This appears to be creating a level and immediately creating a new plan view for it as well, which seems to be just what you are looking for.

Question:
We need to update some parameter values on certain elements from the document closed and saved events on the application object.
To do so, we implemented an external application class App in order to hook up automatic synchronisation to document save and close events.
We created a method SynchroniseAreaParameters to update the appropriate element parameters, which is registered as an event handler for the OnDocumentClosed, OnDocumentSaved and OnDocumentSavedAs events:


public class App : IExternalApplication
{
  void SynchroniseAreaParameters(
    Document doc )
  {
    ElementIterator i = doc.get_Elements(
      typeof( Room ) );
 
    while( i.MoveNext() )
    {
      Command.UpdateAreaParameter(
        i.Current as Room );
    }
  }
 
  public IExternalApplication.Result OnStartup(
    ControlledApplication app )
  {
    app.OnDocumentClosed
      += new DocumentClosedEventHandler(
        SynchroniseAreaParameters );
 
    app.OnDocumentSaved
      += new DocumentSavedEventHandler(
        SynchroniseAreaParameters );
 
    app.OnDocumentSavedAs
      += new DocumentSavedAsEventHandler(
        SynchroniseAreaParameters );
 
    return IExternalApplication.Result.Succeeded;
  }
 
  public IExternalApplication.Result OnShutdown( ControlledApplication app )
  {
    app.OnDocumentClosed
      -= new DocumentClosedEventHandler(
        SynchroniseAreaParameters );
 
    app.OnDocumentSaved
      -= new DocumentSavedEventHandler(
        SynchroniseAreaParameters );
 
    app.OnDocumentSavedAs
      -= new DocumentSavedAsEventHandler(
        SynchroniseAreaParameters );
 
    return IExternalApplication.Result.Succeeded;
  }
}

Unfortunately, this does not work, although we can see in the debugger that the notifications are dispatched as expected and each step executes correctly with no error.
Why are the parameters not updated accordingly?

Answer:
The reason why no changes are applied to the document is that you need to encapsulate the modification in a transaction.
In the context of an external command, the Revit API will automatically begin a transaction for you.
Depending on the IExternalCommand.Result value returned from the external command’s Execute method, the transaction will be either closed or aborted.
Within the context of an event handler, however, no such transaction will be automatically opened for you, so you are responsible for doing so yourself.
Adding two lines to SynchroniseAreaParameters to begin and end a transaction solved the problem:


  void SynchroniseAreaParameters(
    Document doc )
  {
    if( doc.BeginTransaction() )
    {
      ElementIterator i = doc.get_Elements(
        typeof( Room ) );
 
      while( i.MoveNext() )
      {
        Command.UpdateAreaParameter(
          i.Current as Room );
      }
      doc.EndTransaction();
    }
  }

I am looking forward to more exciting topics to explore and things to learn in our remaining day together.


Comments

4 responses to “Barcelona Questions”

  1. Danny Polkinhorn Avatar
    Danny Polkinhorn

    The last one is VERY helpful. I’m sure I would have bumped up against that one in the very near future. In fact, it should probably be a DevNote if it isn’t already.

  2. Hi Danny,
    Thank you very much for the appreciation and your suggestion! I forwarded it to my ADN DevTech colleagues.
    Cheers, Jeremy.

  3. Dear Jeremy
    Thank you so much for the training at Barcelona. I will also include here the concept of joining API and AutoHotKey scripts (for reference from AUGI: http://forums.augi.com/showthread.php?t=84683 or http://forums.augi.com/showthread.php?t=65897&highlight=revit+local+file+autohotkey) to perform some tasks which are still not available through the API. The second thread at AUGI is a very useful tool.
    Thanks again. Please keep giving us this great support with your blog.
    Cheers, RJ.

  4. Dear Ramon,
    Thank you very much for the AutoHotKey pointers. I read them through and they really do look hot. Thank you also for your appreciation! I definitely do hope and expect to keep it up, Insha’Allah.
    Cheers, Jeremy.

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading