Loading The Building Coder Samples

As I write these blog entries, I continuously add new commands to The Building Coder sample project. While doing so, I wish keep my list of external commands up to date with a minimum of effort. I have several important requirements:

The easiest way to achieve these goals is to make use of the Revit SDK sample external application RvtSamples, which I described in more detail in the post on Loading SDK Samples.

So far, however, I have actually been duplicating the information, because on one hand, I wanted to keep it in a separate file. On the other hand, I had to copy it into the RvtSamples input file, RvtSamples.txt.

For quite a while, I have been thinking that a simple solution to this problem would be for RvtSamples to support an #include mechanism, like the C and C++ pre-processors do. The C #include pragma allows one file to reference another one, and the reference behaves just as if the content of the referenced file were inserted into the referencing one at the #include pragma location.

Once I started looking at the implementation, it turned out to be very simple. The original RvtSamples module Application.cs reads in the contents of RvtSamples.txt in the line:

  string[] lines = File.ReadAllLines(filename);

I defined a new helper method ReadAllLinesWithInclude and replaced that call by:

  string[] lines = ReadAllLinesWithInclude( filename );

Here is the implementation of ReadAllLinesWithInclude:

char[] _trimChars = new char[] {
  ' ', '"', '\'', '<', '>' };
 
string[] ReadAllLinesWithInclude(
  string filename )
{
  if( !File.Exists( filename ) )
  {
    ErrorMsg( filename + " not found." );
    return new string[] { };
  }
  string[] lines = File.ReadAllLines(
    filename );
 
  int n = lines.GetLength(0);
  ArrayList all_lines = new ArrayList( n );
  foreach( string line in lines )
  {
    string s = line.TrimStart();
    if( s.ToLower().StartsWith( "#include" ) )
    {
      string filename2 = s.Substring( 8 );
      filename2 = filename2.Trim( _trimChars );
      all_lines.AddRange( ReadAllLinesWithInclude(
        filename2 ) );
    }
    else
    {
      all_lines.Add( line );
    }
  }
  return all_lines.ToArray( typeof( string ) )
    as string[];
}

Now, I have added only two lines to the end of RvtSamples.txt, one each for the ADN and The Building Coder samples, and these two lines will never need to be edited again:

  #include C:/a/j/adn/train/revit/2009/src/AdnSamples.txt
  #include C:/a/j/adn/train/revit/2009/src/bc/BcSamples.txt

Here are the entire contents of BcSamples.txt, with the header informational comments removed, and the binary path somewhat shortened for the sake of clarity:

  /&ADN/&Bc/List Walls
  List wall lengths and areas
  C:/bin/BuildingCoder.dll
  BuildingCoder.CmdListWalls

  /&ADN/&Bc/Wall Dimensions
  Extract wall solid and list all its dimensions
  C:/bin/BuildingCoder.dll
  BuildingCoder.CmdWallDimensions

  /&ADN/&Bc/Relationship Inverter
  Determine opening > wall host relationships and invert them to wall > opening
  C:/bin/BuildingCoder.dll
  BuildingCoder.CmdRelationshipInverter

  /&ADN/&Bc/Filter Performance
  Compare Type Filter versus using an anonymous method to filter elements
  C:/bin/BuildingCoder.dll
  BuildingCoder.CmdFilterPerformance

  /&ADN/&Bc/Element Materials
  Retrieve building element materials
  C:/bin/BuildingCoder.dll
  BuildingCoder.CmdGetMaterials

  /&ADN/&Bc/Azimuth
  Calculate azimuth
  C:/bin/BuildingCoder.dll
  BuildingCoder.CmdAzimuth

  /&ADN/&Bc/Bounding Box
  Retrieve Element Bounding Box
  C:/bin/BuildingCoder.dll
  BuildingCoder.CmdBoundingBox

  /&ADN/&Bc/Slab Boundaries
  Determine polygonal floor slab boundary loops
  C:/bin/BuildingCoder.dll
  BuildingCoder.CmdSlabBoundary

  /&ADN/&Bc/Slab Sides
  Determine floor slab side faces
  C:/bin/BuildingCoder.dll
  BuildingCoder.CmdSlabSides

By the way, note that you can use an ampersand sign '&' to define keyboard mnemonics to provide shortcut access to the menu items when defining them through an external application. I find this especially handy when I need to start a command repeatedly to debug an application.

Here is my updated version of RvtSamples 1.0.1.0 supporting #include. I incremented the version number from 1.0.0.0 to 1.0.1.0.