Improved MEP Element Shape and Mount Ararat

We recently talked about

distinguishing Revit MEP duct element shapes
,
and Max aka

Maciej Szlek
presented
a solution based on the analysis of the string value of the duct’s Size parameter.

I suggested that the algorithm might be improved, both to make it more general and robust and also to remove the dependency on the different string formats used for imperial and metric units.
It probably becomes more efficient as well, by the way.

Instead of looking at the duct size parameter, one can query it for its connectors and extract the shape from them directly, avoiding all string manipulations and language or unit dependencies.

Max went ahead and implemented this new algorithm.
Simultaneously, he demonstrates that some useful helper methods can be reused from the Revit SDK samples, in this case ExtractMechanicalOrPipingSystem and ExtractSystemFromConnectors from the TraverseSystem sample.
Here is the code of the new algorithm:


static public string GetElementShape(
  Element e,
  Element pe = null,
  Element ne = null )
{
  if( is_element_of_category( e,
    BuiltInCategory.OST_DuctCurves ) )
  {
    // assuming that transition is using to change shape..
 
    ConnectorManager cm = ( e as MEPCurve )
      .ConnectorManager;
 
    foreach( Connector c in cm.Connectors )
      return c.Shape.ToString()
        + " 2 " + c.Shape.ToString();
  }
  else if( is_element_of_category( e,
    BuiltInCategory.OST_DuctFitting ) )
  {
    MEPSystem system
      = ExtractMechanicalOrPipingSystem( e );
 
    FamilyInstance fi = e as FamilyInstance;
    MEPModel mm = fi.MEPModel;
 
    ConnectorSet connectors
      = mm.ConnectorManager.Connectors;
 
    if( fi != null && mm is MechanicalFitting )
    {
      PartType partType
        = ( mm as MechanicalFitting ).PartType;
 
      if( PartType.Elbow == partType )
      {
        // assuming that transition is using to change shape..
 
        foreach( Connector c in connectors )
        {
          return c.Shape.ToString()
            + " 2 " + c.Shape.ToString();
        }
      }
      else if( PartType.Transition == partType )
      {
        string[] tmp = new string[2];
 
        if( system != null )
        {
          foreach( Connector c in connectors )
          {
            if( c.Direction == FlowDirectionType.In )
              tmp[0] = c.Shape.ToString();
 
            if( c.Direction == FlowDirectionType.Out )
              tmp[1] = c.Shape.ToString();
          }
          return string.Join( " 2 ", tmp );
        }
        else
        {
          int i = 0;
 
          foreach( Connector c in connectors )
          {
            if( pe != null )
            {
              if( is_connected_to( c, pe ) )
                tmp[0] = c.Shape.ToString();
              else
                tmp[1] = c.Shape.ToString();
            }
            else
            {
              tmp[i] = c.Shape.ToString();
            }
            ++i;
          }
 
          if( pe != null )
            return string.Join( " 2 ", tmp );
 
          return string.Join( "-", tmp );
        }
      }
      else if( PartType.Tee == partType
        || PartType.Cross == partType
        || PartType.Pants == partType
        || PartType.Wye == partType )
      {
        string from, to;
        from = to = null;
        List<string> unk = new List<string>();
 
        if( system != null )
        {
          foreach( Connector c in connectors )
          {
            if( c.Direction == FlowDirectionType.In )
              from = c.Shape.ToString();
            else
              unk.Add( c.Shape.ToString() );
 
            if( ne != null && is_connected_to( c, ne ) )
              to = c.Shape.ToString();
          }
 
          if( to != null )
            return from + " 2 " + to;
 
          return from + " 2 " + string.Join( "-",
            unk.ToArray() );
        }
        else
        {
          foreach( Connector c in connectors )
          {
            if( ne != null && is_connected_to(
              c, ne ) )
            {
              to = c.Shape.ToString();
              continue;
            }
 
            if( pe != null && is_connected_to(
              c, pe ) )
            {
              from = c.Shape.ToString();
              continue;
            }
 
            unk.Add( c.Shape.ToString() );
          }
 
          if( to != null )
            return from + " 2 " + to;
 
          if( from != null )
            return from + " 2 "
              + string.Join( "-", unk.ToArray() );
 
          return string.Join( "-", unk.ToArray() );
        }
      }
    }
  }
  return "unknown";
}
 

It is encapsulated as a static method in the class MepElementShape.
I created a second wrapper class MepElementShapeV1 for the first implementation and call them both in The Building Coder sample CmdMepElementShape external command Execute method like this:


  Element e = <selected element>;
 
  Util.InfoMsg( string.Format(
    "{0} is {1} ({2})",
    Util.ElementDescription( e ),
    MepElementShape.GetElementShape( e ),
    MepElementShapeV1.GetElementShape( e ) ) );
 

This prints the following in the Visual Studio debug output window on selecting some of the elements generated by the AvoidObstruction SDK sample:


Mechanical Equipment Parallel Fan Powered VAV
 is unknown (unknown)
Duct Fittings Rectangular Duct Radius Elbow 
is RectProfile 2 RectProfile (rectangular2rectangular)
Ducts 
is RectProfile 2 RectProfile (rectangular)
Duct Fittings Rectangular Duct Tee 
is RectProfile 2 RectProfile-RectProfile (unknown)
Air Terminals Supply Diffuser
 is unknown (unknown)

As you see, the results are the same for the string-based first version as for the new connector-based one, except for the tee junction, which was not handled properly by the former.

Very many thanks to Max for implementing and sharing this!

Here is an updated
version 2012.0.87.3 of
The Building Coder sample code including this new classification method.

Climbing the Ararat

I am off for another break now, this time a bit more adventurous, to climb

Mount Ararat
in far Eastern Turkey.
The flight from Istanbul to

Van
, the closest city with an airport, is almost as long as the one from Switzerland to Istanbul!

Since I am also busy preparing my

Autodesk University proposals
,
which are due for submission today, as well as the upcoming Revit 2012 API webcast, I am pretty occupied and having difficulty finding time to even pack.
With skis and winter clothing and mountain equipment, that is a non-trivial task…
Still, I will make it, I am sure.

Mount Ararat


Comments

5 responses to “Improved MEP Element Shape and Mount Ararat”

  1. Pierre NAVARRA Avatar
    Pierre NAVARRA

    Hi Jeremy,
    I’ve got an other question.
    Here, we are working with the Revit2010 without subscription.
    Do you think I can use the RevitAPI.dll from the 2012 SDK?
    Even if I must adapt my code….
    Is it possible?
    Cheers.

  2. Dear Pierre,
    I do not believe that the Revit 2012 API assemblies will work with the Revit 2010 executable. No way.
    But, if you are really interested, please try it out and let us know what you find out :-)
    Cheers, Jeremy.

  3. Dear Pierre,
    Glad to have you back and hear from you. Ararat was great!
    I was unable to use the monstrous link you provide above, but the two following work:
    http://noahsarksearch.com/LeeElfred/21.JPG
    http://www.sommet.net/moto/arche.html
    Regarding the quantity extraction, have you looked at the MaterialQuantities SDK sample, and the following post?
    http://thebuildingcoder.typepad.com/blog/2010/02/material-quantity-extraction.html
    Cheers, Jeremy.

  4. Welcome to the Mount Ararat Safe Climbing Tours Company
    Always Safe Expedition with Qualty services!
    For more info Please Contact Us
    http://www.mountararatexpeditions.com/
    http://www.ararattrekking.com/
    E-mail: mountararat@hotmail.com
    E-mail: climbararat@hotmail.com
    Phone: +90 545 610 46 40
    Agri /Dogubayazit /Turkey

Leave a Reply

Discover more from Autodesk Developer Blog

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

Continue reading