Create a Pipe Cap

Things have been a bit hectic for me in the last few days, with several complex cases to solve.
I also suddenly and unexpectedly had to find out how to apply for a visa to Saudi Arabia, which is a kind of interesting process.
Apparently, you start out with the inviting company in Saudi Arabia, which has to issue an invitation letter. This has to include a reference number, for which a form needs to be filled in and submitted to the Ministry of Foreign Affairs.
With that in place, a letter from my company addressed to the embassy of Saudi Arabia in Bern can be submitted to request the visa. This letter must be legalised by the chamber of commerce in Switzerland.
So quite an impressive process before I can even get started applying…

Anyway, another thing that came up today that was immediately solvable is the following simple question on how to create a new cap on a pipe in the Revit MEP context:

Question: The Revit SDK samples do not include any example showing how to create a cap on as pipe.
Can you show me how to do it in C#?

Let’s say I create a pipe as follows:


  UIApplication uiapp = commandData.Application;
  Document rvtDoc = uiapp.ActiveUIDocument.Document;
 
  XYZ start = new XYZ( 0, 0, 0 );
  XYZ end = new XYZ( 6, 0, 4 );
 
  FilteredElementCollector collector
    = new FilteredElementCollector( rvtDoc );
 
  collector.OfClass( typeof( ElementType ) );
 
  PipeType pipeType = collector.FirstElement()
    as PipeType;
 
  Pipe pipe = rvtDoc.Create.NewPipe(
    start, end, pipeType );
 
  pipe.get_Parameter(
    BuiltInParameter.RBS_PIPE_DIAMETER_PARAM )
    .Set( 0.1667 ); // revise to 2" dia pipe

In the project browser I see the node Families > Pipe Fittings > M_Cap – Generic > Standard.

How can I use that family to create a 2″ dia cap at the start point of the 2″ dia pipe in C#?

Answer: The solution is simple, actually, in the following two steps:

  1. Insert a cap family instance.
  2. Connect it to the pipe.

By the way, in your code, you are selecting the pipe type from a collector returning all element types.
That seems a bit liberal to me.
I would suggest adding a filter for the built-in category as well.

Here is my code that does just that.
First, I need to define a few constants to identify and load the cap symbol:


  const string _libFolder = "C:/Documents and Settings"
    + "/All Users/Application Data/Autodesk/RME 2011"
    + "/Metric Library/Pipe/Fittings/Generic";
 
  const string _rfaExtension = ".rfa";
  const string _capFamilyName = "M_Cap - Generic";
  const string _capSymbolName = "Standard";

I then create the pipe like before, select the cap family symbol, and insert an instance of it at the end point of the pipe:


  UIApplication uiapp = commandData.Application;
  Document doc = uiapp.ActiveUIDocument.Document;
 
  PipeType pipeType
    = new FilteredElementCollector( doc )
    .OfClass( typeof( ElementType ) )
    .OfCategory( BuiltInCategory.OST_PipeCurves )
    .FirstElement() as PipeType;
 
  XYZ start = new XYZ( 0, 0, 0 );
  XYZ end = new XYZ( 6, 0, 4 );
 
  Transaction t = new Transaction( doc,
    "Create Pipe Cap" );
 
  t.Start();
 
  Pipe pipe = doc.Create.NewPipe(
    start, end, pipeType );
 
  pipe.get_Parameter(
    BuiltInParameter.RBS_PIPE_DIAMETER_PARAM )
    .Set( 0.1667 ); // revise to 2" dia pipe
 
  // get cap symbol:
 
  List<FamilySymbol> symbols = new List<FamilySymbol>(
    new FilteredElementCollector( doc )
      .OfCategory( BuiltInCategory.OST_PipeFitting )
      .OfClass( typeof( FamilySymbol ) )
      .OfType<FamilySymbol>()
      .Where<FamilySymbol>( s
        => s.Family.Name.Equals( _capFamilyName ) ) );
 
  FamilySymbol capSymbol = null;
 
  if( 0 < symbols.Count )
  {
    capSymbol = symbols[0];
  }
  else
  {
    string filename = Path.Combine( _libFolder,
      _capFamilyName + _rfaExtension );
 
    // requires a transaction, obviously:
 
    doc.LoadFamilySymbol( filename, _capSymbolName,
      out capSymbol );
  }
 
  Debug.Assert( capSymbol.Family.Name.Equals( _capFamilyName ),
    "expected cap pipe fitting to be of family " + _capFamilyName );
 
  FamilyInstance fi = doc.Create.NewFamilyInstance(
    end, capSymbol, StructuralType.NonStructural );

The result of running the code so far looks like this:

Pipe cap unconnected

This implements the first step above.
As you can see, the cap is not connected to the pipe, and it also has a wrong diameter.

To implement the second step, we need to pick the suitable connectors on the cap and the pipe and hook them up with each other.
On the cap, there is just one connector, so that is easy.

On the pipe, there are two, and it is more complex.
The order of connectors returned by the connector manager may change, so one should always use a location or some other criterion to select the right one.
In this case, we check the distance of the pipe connectors to the endpoint we are capping and pick the closest one.

Once the two connectors have been selected, we can connect them to each other:


  // pick connector on cap:
 
  ConnectorSet connectors
    = fi.MEPModel.ConnectorManager.Connectors;
 
  Debug.Assert( 1 == connectors.Size,
    "expected nly one connector on pipe cap element" );
 
  Connector cap_end = null;
 
  foreach( Connector c in connectors )
  {
    cap_end = c;
  }
 
  // pick closest connector on pipe:
 
  connectors = pipe.ConnectorManager.Connectors;
 
  Connector pipe_end = null;
 
  // the order of connectors returned by the 
  // connector manager may change, so we 
  // always use a location (or even more 
  // information if several connectors are 
  // at the same location) to get the right
  // connector!
 
  double dist = double.MaxValue;
 
  foreach( Connector c in connectors )
  {
    XYZ p = c.Origin;
    double d = p.DistanceTo( end );
 
    if( d < dist )
    {
      dist = d;
      pipe_end = c;
    }
    break;
  }
 
  cap_end.ConnectTo( pipe_end );
 
  t.Commit();
 
  return Result.Succeeded;

The result of running the complete code looks like this:

Pipe cap connected

As you can see, the cap is now automatically positioned and dimensioned correctly with no further input required from my side.

Here is
CreatePipeCap.zip
containing the entire source code and Visual Studio solution implementing this command.


Comments

98 responses to “Create a Pipe Cap”

  1. Kailash Kute Avatar
    Kailash Kute

    Hi sir,
    Greetings for the day
    Finally i have placed hanger’s on slanting pipe programmatically through pipe slope angle.
    now i want to call Add Insulation Window Programmatically if yes then how ?
    or what is the shortcut key for the Add Insulation for e.g. for Pipe it is PI like that i want for Add Insulation.
    Regards
    Kailash Kute

  2. Kailash Kute Avatar
    Kailash Kute

    Hi Sir,
    Greetings for the day
    By reading this link in your Blog
    http://thebuildingcoder.typepad.com/blog/element-relationships/page/9/
    i came to know about this parameter ELEMENT_LOCKED_PARAM
    by using the below code i am able to lock all my elements(hangers and pipe) together in my document.
    Parameter lockedorNot = fihanger.get_Parameter(BuiltInParameter.ELEMENT_LOCKED_PARAM);
    int yesornot = lockedorNot.AsInteger();
    lockedorNot.Set(1);
    Regards
    Kailash Kute

  3. Dear Kailash,
    Congratulations on placing the hangers on the slanting pipe!
    I entered “revit shortcut key” in Google and found lots of answers, so I hope you were able to solve that one yourself.
    There are a couple of posts on how to programmatically launch Revit commands that are not accessible through the API, either by simulating the user input of a shortcut key or using UI Automation.
    Cheers, Jeremy.

  4. Dear Kailash,
    Congratulations on finding a good solution for locking the elements together, and thank you very much for letting us know!
    Do you mean the discussion on Locked Dimensioning? Here is a quicker link than scrolling through to page 9 of the element relationships category:
    http://thebuildingcoder.typepad.com/blog/2009/02/locked-dimensioning.html
    Cheers, Jeremy.

  5. Kailash Kute Avatar
    Kailash Kute

    Hi sir,
    Greetings for the day
    Is this possible to hide/invisible a Family Parameter from Family Types ?. i don’t want to show users the formula i added dynamically in family types.
    Thanks and Regards,
    Kailash N Kute

  6. Dear Kailash,
    This sounds extremely similar to the question by Nitin, which I already answered:
    http://thebuildingcoder.typepad.com/blog/2009/08/shared-parameter-visibility.html#comment-6a00e553e16897883301539063554d970b
    Just out of curiosity, are you colleagues, or working together?
    Anyway, to answer your question, the API allows you to define visibility in exactly the same manner as the user interface, with the one single exception of additionally allowing the creation of invisible shared parameters.
    As regards family parameters, the visibility options are the same as in the user interface.
    So you probably cannot make the formula invisible to users, as far as I know.
    Cheers, Jeremy.

  7. Kailash Kute Avatar
    Kailash Kute

    Hi Sir,
    Greetings for the day.
    i have a pipe in horizontal direction and my structural floor is in slanting position.i want to place hangers on pipe but hanger’s vertical rod length should meet the floor.
    how i will be able to get the start point and end point of Floor.
    is it possible to get these point if yes then how.
    Regards
    Kailash Kute

  8. Dear Kailash,
    You have many possibilities.
    One is to query the floor for its geometry and determine its top and bottom face. I assume that they are roughly horizontal, even if the floor is slanted, so they should be easy to find. Then you can project your point onto them. Or calculate the intersection of a line with the planar face, which is easy.
    Another approach would be to use the FindReferencesWithContextByDirection method, which would do all the intersection calculation for you, and also work for non-planar faces, in case your floor is really weird. Hundertwasser would love it!
    Cheers, Jeremy.

  9. Kailash Kute Avatar
    Kailash Kute

    hi sir,
    greetings for the day
    i have pipe at offset of 9 now i change the offset of my pipe to 12
    in my application i am placing coupling besides of elbow
    now on my first elbow first connector i am able to place coupling but for send connecot i am not able to do that
    when i debug my application i am able to see that it is executing properly it shows that coupling gets created successfully but revit don’t show the couplings over that point.
    plz help any thing i am not digging
    Regards
    Kailash Kute

  10. Dear Kailash,
    Sounds tricky to me, and hard to say anything without reproducing and studying in depth. At this point, all I can do is wish you the best of luck with it…
    Cheers, Jeremy.

  11. Kailash Kute Avatar
    Kailash Kute

    hi sir,
    greetings for the day.
    i just played with some offset and done coding for points for z in connector direction and i solved it
    Thanks & Regards
    Kailash kute

  12. Dear Kailash,
    Congratulations! Wow, you are really clearing every obstacle, one by one! Great work.
    Cheers, Jeremy.

  13. Kailash Kute Avatar
    Kailash Kute

    hi sir,
    Greetings for the day
    i am connecting a coupling that is family instance with the Pipe but when i connect them i get the following message from Revit.
    The duct/pipe has been modified to be in the opposite direction causing the connections to be invalid.
    Regards
    Kailash Kute

  14. Dear Kailash Kute,
    Sorry, I have not encountered that so far. By now, you know much more than me in this area! I look forward to hearing how you resolve it. Good luck!
    Cheers, Jeremy.

  15. Kailash Kute Avatar
    Kailash Kute

    Hi Sir,
    Greetings for the day
    i want to know the pipe offset programatically ? so i used below line,
    Parameter paramOffset = newpipe.get_Parameter(BuiltInParameter.RBS_OFFSET_PARAM);
    PreviousPipeOffset = paramOffset.AsDouble();
    newpipe is the pipe drawn here.
    when my pipe is at 9 offset i get the Offset as -0.999 and when i changed my offset to 27 i get it as -17.0000
    how will i get the exact offset of the pipe that is 9 and 27.
    Regards
    Kailash Kute

  16. Dear Kailash,
    The RBS_OFFSET_PARAM is the offset the pipe is relative to the level the pipe is assigned to.
    In your case it might be that the pipe was set to the level above the current level causing the negative value.
    To get the actual value, get the associated level of the pipe and combine the two, or get the start or end points of the pipe looking at the Z value for the raw elevation, which is not associated to a level.
    Cheers, Jeremy.

  17. Kailash Kute Avatar
    Kailash Kute

    Hi sir,
    Greetings for the day
    well the offset which i was getting was right when i debugged my solution.There was error in my function due to which i was getting this error i rectified it now i am getting exact result with reference to level 2.
    Thanks
    Kailash Kute

  18. Dear Kailash,
    I am very glad to hear you got it sorted out! Congratulations!
    Cheers, Jeremy.

  19. Kailash Kute Avatar
    Kailash Kute

    hello sir
    Now i want to draw a slanted pipe programatically from pipe start point to end point. i did it but the pipe is coming in horizontal position only i tried to retrieve the slope and again i tried to set it but no success
    slope is a readonly property… how to do it ?
    some thing i am missing
    regards
    Kailash Kute

  20. Kailash Kute Avatar
    Kailash Kute

    hello sir,
    any idea regarding slanting pipe ?\
    Regards
    Kailash Kute

  21. Dear Kailash,
    That really does sound a bit confusing.
    Sorry, no, I do not have any idea regarding this nor any time right now to look at it in any depth.
    I would suggest exploring it in one of the public discussion groups:
    http://thebuildingcoder.typepad.com/blog/2009/10/revit-api-forums.html
    If nothing else helps, you should consider joining the Autodesk Developer Network ADN to receive better support:
    http://www.autodesk.com/joinadn
    Cheers, Jeremy.

  22. Kailash Kute Avatar
    Kailash Kute

    hi sir,
    well i got success and drawn pipe from start point to end point in slope of 30 degree but the logic behind it is we have to calculate angle from BasisZ direction and calculated points using this angle and completed it.
    regards
    Kailash Kute

  23. Dear Kailash,
    Congratulations! I am very glad you solved it!
    Sorry I was unable to help more.
    Merry Christmas!
    Cheers, Jeremy.

  24. Kailash Kute Avatar
    Kailash Kute

    Merry Christmas Sir.

  25. Kailash Kute Avatar
    Kailash Kute

    Greetings Sir,
    well is there the link for rotation of family instance
    around axis plz do send me in this reply i am not getting.
    Regards
    Kailash kute

  26. Kailash Kute Avatar
    Kailash Kute

    Hi Sir,
    Warm Greetings for the day.
    well i placed a coupling on sloped pipe successfully and now it is perpendicular to pipe axis and it is connected System.
    the logic is first rotate the coupling by pipe angle then again we have to rotate that coupling by creating new axis but this time the angle is 90 degree for coupling.
    Regards
    Kailash Kute

  27. Kailash Kute Avatar
    Kailash Kute

    Hi Sir,
    warm greetings for the day.
    i have a elbow of 45 degree. i want to place a coupling on both the ends of elbow
    i have place one coupling where coupling is exactly connected to elbow and it is at 90 degree
    now the second end of elbow is at 45 degree. where i am not able to place coupling it is getting created over
    there but it not perpendicular also not connected to elbow.
    what may be the logic for this ?
    Best Regards
    Kailash Kute

  28. Kailash Kute Avatar
    Kailash Kute

    hi sir,
    greetings for the day
    i tried to place coupling on second end of elbow which is at 45 degree but i get this following error message.
    The family is connected in a network and can no longer keep the connectivity. Disconnect the family from the network?
    what is the meaning of this message.
    Regards
    Kailash Kute

  29. kailash n kute Avatar
    kailash n kute

    Hi Sir,
    warm greetings for the day.
    i have a elbow of 45 degree. i want to place a coupling on both the ends of elbow
    i have place one coupling where coupling is exactly connected to elbow and it is at 90 degree
    now the second end of elbow is at 45 degree. where i am not able to place coupling it is getting created over
    there it is perpendicular but not properly aligned with the pipe direction.
    please any help appreciated.
    Regards
    Kailash Kute

  30. Dear Kailash,
    Thank you very much for your query.
    I have not done any more exploration in the realm of creating pipes and fitting beyond what I published already on the blog.
    I am very impressed that you have encountered and apparently also solved such a huge number of issues.
    I don’t know what to suggest regarding this new situation that you describe.
    I am sure that it would make an extremely interesting (and huge) blog post if you were to describe all the solutions that you have already developed.
    Would you be interested in picking a few of the more typical ones and documenting them for sharing here on the blog?
    Thank you!
    Cheers, Jeremy.

  31. kailash kute Avatar
    kailash kute

    Hi Jeremy,
    well i tried,tried and finally got the solution for my coupling at the second end of elbow which is at 45 degree.is getting oriented properly Now.
    well i moved my Elbow from its original XYZ to New XYZ and again back to Original XYZ that’s it and my Coupling got Oriented in Proper Direction Successfully.
    Regards
    Kailash Kute

  32. Dear Kailash,
    You are fantastic! You should write a book about all your solutions! Congratulations!
    Cheers, Jeremy.

  33. kailash kute Avatar
    kailash kute

    Thanks a Lot Sir.

  34. hi sir,
    warm greetings for the day.
    By the use of text file i am able to create SharedParameters Successfully Programmatically.
    but without use of text file i want to create SharedParameter Programmatically.is it posiible …
    i tried using ExternalDefinition but still no Success.
    Regards
    Kailash Kute

  35. kailash kute Avatar
    kailash kute

    hi jeremy,
    warm greetings for the day,
    well i have a one family instance,now i want to know whether this family instance is of which template,
    Imperial template or Metric template,rather than using its naming convention M_ for metric.
    are there ways we come to know this Family Instance is of Imperial or Metric.
    Regards
    Kailash Kute

  36. Dear Kailash,
    There are no completely reliable methods that I am aware of, since there are no fixed rules when creating families and every user is free to create her own as she likes.
    Maybe there is some parameter that is found in every family which you can use to check, some global scaling factor or something?
    Please let us know if you find a solution.
    Thank you!
    Cheers, Jeremy.

  37. Dear Kailash,
    Yes, sure you can create shared parameters programmatically. This is demonstrated by the FireRating SDK sample, and also by
    http://thebuildingcoder.typepad.com/blog/2009/06/model-group-shared-parameter.html
    A few more posts on shared parameters are mentioned here:
    http://thebuildingcoder.typepad.com/blog/2011/04/extensible-storage.html
    Cheers, Jeremy.

  38. Jayshree Avatar
    Jayshree

    hi jeremy sir,
    i m new in revit programming
    i want to place hanger on pipe programatically.I have calculated lenght of the pipe bt not able to proceed further what to do next.
    Can u please help m to proceed futher
    Thanks in Advance
    Jayshree

  39. Dear Jayshree,
    Here is the one an only post dealing explicitly with this issue, which I strongly suspect is completely out of date, unfortunately:
    http://thebuildingcoder.typepad.com/blog/2010/03/mep-hangers.html
    Kailash Kute has successfully solved this issue, as you can see from his comments below:
    http://thebuildingcoder.typepad.com/blog/2011/02/create-a-pipe-cap.html?cid=6a00e553e168978833015434151d8c970c#comment-6a00e553e168978833015434151d8c970c
    http://thebuildingcoder.typepad.com/blog/2011/02/create-a-pipe-cap.html?cid=6a00e553e1689788330153905f7600970b#comment-6a00e553e1689788330153905f7600970b
    All I can do is suggest that you find out how to do it as well and then provide a nice clean simple sample for me to publish for the edification of your peers.
    Cheers, Jeremy.

  40. Jayshree Avatar
    Jayshree

    Hello sir
    warm greetings for the day,
    Thank you.I successfully place hanger on pipe bt i cant place hanger on slanting pipe.Please provide some idea what to do?
    Thanks in advance
    Jayshree

  41. Dear Jayshree,
    Congratulations on solving your task!
    I can only repeat what I answered to your last comment: I do not have the solution, it is possible, and Kailash Kute reports that he solved it, as you can see from his comments below, where he says “Finally i have placed hanger’s on slanting pipe programmatically through pipe slope angle”.
    All I can do is wish you success on finding out how to do it as well and then hope you provide a nice clean simple sample to publish for the edification of your peers.
    Cheers, Jeremy.

  42. Jayshree Avatar
    Jayshree

    Hello sir
    warm greetings for the day,
    I successfully place hanger on slanting pipe.Please provide some idea what to do? Now i started placing coupling on pipe i can place it but its not connected to pipe.whenever pipe is moved the coupling remains there only and pipe gets moved.Can You provide some idea
    Thanks in advance
    Jayshree

  43. kailash kute Avatar
    kailash kute

    Dear Jeremy,
    i would like to inform you that since i have changed my current company to another where there is no Revit,but till this whole time which i used to blog post on building coder,was very good and fantastic journey,your blog was most useful stuff for me ,i liked the coding,the posts,the information provided on this.i will miss but i also like to appreciate the work you are doing for revit stuff.
    Really it was a wonderful journey till this day on BuildingCoder.
    Regards and cheers
    Kailash kute

  44. Dear Kailash,
    Congratulations on your new position!
    I also congratulate you on solving so very many tricky Revit MEP API challenges, most of them on your own.
    Sorry I was not able to provide more help. You probably know a lot more about it now than I do, or almost anybody else in the world either, for that matter.
    I bid you farewell most officially in today’s blog post, and wish you much success and all the best in your new role:
    http://thebuildingcoder.typepad.com/blog/2012/05/devblog-devcamp-element-and-project-wide-data.html#3
    Cheers, Jeremy.

  45. Dear Jayshree,
    Congratulations on placing the hanger on the slanting pipe!
    It sounds as if you have to explicitly iterate over the family instance connector objects, find the corresponding ones, and explicitly connect them with each other.
    Good luck!
    Cheers, Jeremy.

  46. Jitendra Dhande Avatar
    Jitendra Dhande

    hi sir,
    I want to know about how to get instance parameter after loading family without placing it in document.
    Regards
    Jitendra dhande

  47. Dear Jitendra,
    I do not believe this is possible. Sorry.
    You could always place a dummy instance within a temporary transaction and roll it back afterwards.
    Cheers, Jeremy.

  48. Jayshree Avatar
    Jayshree

    Hello Sir,
    Warm greetings for the day,
    I want to ratoate Coupling on pipe in different View (Example: East Mech,West Mech,North Mech,South Mech) programatically.
    Is there any Method or property in revit to find out rotation angle and Axis.. for different Mech
    Thanks & regards
    Jayshree

Leave a Reply to Kailash KuteCancel reply

Discover more from Autodesk Developer Blog

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

Continue reading