Create Pipes and Ducts

There are 3 ways to create new ducts, flex ducts, pipes and flex pipes. They can be created between two points, between two connectors, or between a point and a connector.

The following code creates a new pipe between two points using the Pipe.Create() method. New flex pipes, ducts and flex ducts can all be created similarly.

Code Region: Creating a new Pipe using static Create() method

public Pipe CreateNewPipe(Document document, ElementId systemTypeId, ElementId levelId)
{
    // find a pipe type
            
    FilteredElementCollector collector = new FilteredElementCollector(document);
    collector.OfClass(typeof(PipeType));
    PipeType pipeType = collector.FirstElement() as PipeType;
            
    Pipe pipe = null;
    if (null != pipeType)
    {
        // create pipe between 2 points
        XYZ p1 = new XYZ(0, 0, 0);
        XYZ p2 = new XYZ(10, 0, 0);

        pipe = Pipe.Create(document, systemTypeId, pipeType.Id, levelId, p1, p2);
    }

    return pipe;
}
The code region below demonstrates how to create a FlexPipe using the static FlexPipe.Create() method. Pipes, ducts and flex ducts can all be created between two points similarly.

Code Region: Creating a new FlexPipe using static Create() method

public FlexPipe CreateFlexPipe(Document document, Level level)
{
    // find a pipe type
    FilteredElementCollector collector = new FilteredElementCollector(document);
    collector.OfClass(typeof(FlexPipeType));
    ElementId pipeTypeId = collector.FirstElementId();

    // find a pipe system type
    FilteredElementCollector sysCollector = new FilteredElementCollector(document);
    sysCollector.OfClass(typeof(PipingSystemType));
    ElementId pipeSysTypeId = sysCollector.FirstElementId();

    FlexPipe pipe = null;
    if (pipeTypeId != ElementId.InvalidElementId && pipeSysTypeId != ElementId.InvalidElementId)
    {
        // create flex pipe with 3 points
        List<XYZ> points = new List<XYZ>();
        points.Add(new XYZ(0, 0, 0));
        points.Add(new XYZ(10, 10, 0));
        points.Add(new XYZ(10, 0, 0));

        pipe = FlexPipe.Create(document, pipeSysTypeId, pipeTypeId, level.Id, points);
    }

    return pipe;
}

After creating a pipe, you might want to change the diameter. The Diameter property of Pipe is read-only. To change the diameter, get the RBS_PIPE_DIAMETER_PARAM built-in parameter.

Code Region: Changing pipe diameter

public void ChangePipeSize(Pipe pipe)
{
        Parameter parameter = pipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM);
        
        string message = "Pipe diameter: " + parameter.AsValueString();
        
        parameter.Set(0.5); // set to 6"
        
        // Regenerate the docucment before trying to read a parameter that has been edited
        pipe.Document.Regenerate();

        message += "\nPipe diameter after set: " + parameter.AsValueString();
        
        MessageBox.Show(message, "Revit");
}

Another common way to create a new duct or pipe is between two existing connectors, as the following example demonstrates. In this example, it is assumed that 2 elements with connectors have been selected in Revit, one being a piece of mechanical equipment and the other a duct fitting with a connector that lines up with the SupplyAir connector on the equipment.

Code Region: Adding a duct between two connectors

public Duct CreateDuctBetweenConnectors(UIDocument uiDocument)
{
    // prior to running this example
    // select some mechanical equipment with a supply air connector
    // and an elbow duct fitting with a connector in line with that connector
    ElementId levelId = ElementId.InvalidElementId;
    Connector connector1 = null, connector2 = null;
    ConnectorSetIterator csi = null;
    ICollection<ElementId> selectedIds = uiDocument.Selection.GetElementIds();
    Document document = uiDocument.Document;
    // First find the selected equipment and get the correct connector
    foreach (ElementId id in selectedIds)
    {
        Element e = document.GetElement(id);
        if (e is FamilyInstance)
        {
            FamilyInstance fi = e as FamilyInstance;
            Family family = fi.Symbol.Family;
            if (family.FamilyCategory.Name == "Mechanical Equipment")
            {
                csi = fi.MEPModel.ConnectorManager.Connectors.ForwardIterator();
                while (csi.MoveNext())
                {
                    Connector conn = csi.Current as Connector;
                    if (conn.Direction == FlowDirectionType.Out && 
                        conn.DuctSystemType == DuctSystemType.SupplyAir)
                    {
                        connector1 = conn;
                        levelId = family.LevelId;
                        break;
                    }
                }
            }
        }
    }
    // next find the second selected item to connect to
    foreach (ElementId id in selectedIds)
    {
        Element e = document.GetElement(id);
        if (e is FamilyInstance)
        {
            FamilyInstance fi = e as FamilyInstance;
            Family family = fi.Symbol.Family;
            if (family.FamilyCategory.Name != "Mechanical Equipment")
            {
                csi = fi.MEPModel.ConnectorManager.Connectors.ForwardIterator();
                while (csi.MoveNext())
                {
                    if (null == connector2)
                    {
                        Connector conn = csi.Current as Connector;

                        // make sure to choose the connector in line with the first connector
                        if (Math.Abs(conn.Origin.Y - connector1.Origin.Y) < 0.001)
                        {
                            connector2 = conn;
                            break;
                        }
                    }
                }
            }
        }
    }

    Duct duct = null;
    if (null != connector1 && null != connector2 && levelId != ElementId.InvalidElementId)
    {
        // find a duct type
        FilteredElementCollector collector = new FilteredElementCollector(uiDocument.Document);
        collector.OfClass(typeof(DuctType));
                
        // Use Linq query to make sure it is one of the rectangular duct types
        var query = from element in collector
                    where element.Name.Contains("Mitered Elbows") == true
                    select element;

        // use extension methods to get first duct type
        DuctType ductType = collector.Cast<DuctType>().First<DuctType>();
                
        if (null != ductType)
        {
            duct = Duct.Create(document, ductType.Id, levelId, connector1, connector2);
        }
    }

    return duct;
}

Lining and Insulation

Pipe and duct insulation and lining can be added as separate objects associated with ducts and pipes. The ids of insulation elements associated with a duct or pipe can be retrieved using the static method InsulationLiningBase.GetInsulationIds() while the ids of lining elements can be retreived using the static method InsulationLiningBase.GetLiningIds().

To create new insulations associated with a given duct, pipe, fitting, accessory, or content use the corresponding static method: DuctInsulation.Create() or PipeInsulation.Create(). DuctLining.Create() can be used to create a new instance of a lining applied to the inside of a given duct, fitting or accessory.