Simple Code to Insert Revit Pipe/Duct Fittings and Accessory's at the End of Pipes

Simple Code to Insert Revit Pipe/Duct Fittings and Accessory's at the End of Pipes

Chris-VC_Studio
Advocate Advocate
2,217 Views
5 Replies
Message 1 of 6

Simple Code to Insert Revit Pipe/Duct Fittings and Accessory's at the End of Pipes

Chris-VC_Studio
Advocate
Advocate

Hello API community, I am a total noob and still learning to code, and I have some big ideas for Plugins but want to start simple.


My first C# plugin was how to place a vertical piece of pipe, something I've been wanting to do for ten years now and just accomplished it. Next, I'd like to have a button on my tool panel that will just place a simple union as specified from my routing preference at the end of a pipe or fitting to act as a mechanical coupling. After that, I would like to have another button for adding elbows and pipe accessories (like Valves and such) which should be very similar to the union thing, then ramp up to hangers and my Flow Arrows. So if someone can help get me started in this community and steer me in the right direction or post some simple code for adding a pipe fitting to the end of a pipe and not reducing the pipe length, it would be greatly appreciated. And please, for the love of God, don't steer to Jermey's rolling offset, there is a lot of information within it, but I would like to keep things super simple for now.

 

Thank you in advance for your support,
And like I learned in the Army, "Slow is smooth, and smooth is fast."

2,218 Views
5 Replies
Replies (5)
Message 2 of 6

jeremy_tammik
Alumni
Alumni

Welcome to the Revit API and congratulations on successfully completing your first add-in. That sounds great, and I love your approach and philosophy! Absolutely perfect, I think. I also like your army proverb. My favourite is KISS, which also originated there. Afaik, there are two possible approaches to take: either make use of a Revit built-in command functionality by using the PostCommand API to launch an appropriate built-in command, or place the fitting programmatically yourself using an appropriate overload of NewFamilyInstance. PostCommand may be the simpler way to go if the existing Revit functionality happens to do exactly what you need right out of the box:

  

https://thebuildingcoder.typepad.com/blog/about-the-author.html#5.3

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 3 of 6

Chris-VC_Studio
Advocate
Advocate

Thanks Jeremy , 

I was going to start off with the newFamilyInstance, but I think the PostCommands will be easier to get started with and may prove to be a simpler solution, but won't it just place any pipe fitting instead of the default elbow/union/tee in my routing preferences for the pipe type I am attaching to? 

0 Likes
Message 4 of 6

jeremy_tammik
Alumni
Alumni

It will behave exactly the same as whatever built-in Revit command you would launch manually through the end user interface. So, you can test it upfront. What command would you use? Does it adapt to your routing preferences in the desired manner? If not, can you set up your routing preferences to achieve what you need? If not, PostCommand will not work. If it does work, you can analyse the journal file to find the internal id of the command you used.

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 5 of 6

Chris-VC_Studio
Advocate
Advocate

Thanks again, Jeremy; I tried the PostCommand but discovered it was no different than just hitting the pipe fitting button on the Ribbon and having to sort thru ever pipe fitting in the Project. Not sure I want to continue down this path, so I am shifting back to the newFamilyInstance. So far, I have successfully made a specified Pipe Fitting (union) appear in the middle of the screen at XYZ 0,0,0. Next, I am looking into pipe or pipe fitting selection and acquiring the closest connection point. Then, I plan to try to find a way select the default fitting type by having it selected thru the routing preferences be it an Elbow, Union, or Tee button on my ribbon panel. 

 

Below is the code I have so far, I think I am about half way there, so if anyone from the community wants to follow my progress and/or contribute to it would be greatly appreciated. I find there is a lack of easy MEP code examples to follow for baby steps out there when compared to the how create walls and architectural objects out there. I know principles are roughly the same but MEP objects seem to require additional parameters on the due to them being part of a connect system and all. I will try to post regular updates and try keep this tread alive long as I can.

 

using Autodesk.Revit.ApplicationServices;

using Autodesk.Revit.Attributes;

using Autodesk.Revit.DB;

using Autodesk.Revit.DB.Plumbing;

using Autodesk.Revit.UI;

using Autodesk.Revit.UI.Selection;

using System;

using System.Collections.Generic;

using System.Linq;

 

namespace PipeTools

{

    [TransactionAttribute(TransactionMode.Manual)]

    public class PlaceUnion : IExternalCommand

    {

        Result IExternalCommand.Execute(ExternalCommandData revit, ref string message, ElementSet elements)

        {

            UIApplication uiapp = commandData.Application;

            UIDocument uidoc = uiapp.ActiveUIDocument;

            Document doc = uidoc.Document;

 

 

            // Need to add code to select the pipe, pipe fitting, or mech equipment closest pipe connection point for our pipe fitting to attach to

 

 

            //Need to change the get family Symbol code below to select union by routing preference default union?

            FamilySymbol symbol = new FilteredElementCollector(doc)

                .OfClass(typeof(FamilySymbol))

                .OfCategory(BuiltInCategory.OST_PipeFitting)

                .Cast<FamilySymbol>()

                .Where<FamilySymbol>(e => e.Family.Name.Contains("Coupling - Generic"))

                .FirstOrDefault<FamilySymbol>();

 

            

            try

            {

                using (Transaction trans = new Transaction(doc, "Place Family"))

                {

                    trans.Start();

                    if (!symbol.IsActive)

                    {

                        symbol.Activate();

                    }

 

                    //Somehow I know I need to change the "XYZ to closetest connection point?

                    doc.Create.NewFamilyInstance(new XYZ(0, 0, 0), symbol, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);

 

                    trans.Commit();

                }

 

 

                return Result.Succeeded;

            }

 

            catch (Exception e)

            {

                message = e.Message;

                return Result.Failed;

            }

        }

    }

}

0 Likes
Message 6 of 6

jeremy_tammik
Alumni
Alumni

That sounds and looks great so far! Congratulations on making good progress and identifying a good path forward.

 

I know you specifically asked not to be pointed to the rolling offset samples, but I'm afraid I still feel compelled to point out that some pipe selection and endpoint identification functionality that you might be able to use or adapt is presented there:

  

https://thebuildingcoder.typepad.com/blog/2014/01/calculating-a-rolling-offset-between-two-pipes.htm...

  

Check out the PipeElementSelectionFilter and how it is used...

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes