Revit connect pipes


In this post, I will present the operation of a new function in my PYLAB add-in. This function is used to connect parallel pipes with a perpendicular section. Connect the pipes with one click!

In article “Revit connect pipes”:

revit connect pipes
Ikona funkcji z

Revit connect pipes – program idea

The pipe joining program will help you in your daily design work. No more manual connection of pipes, all you need to do is select the elements you are interested in. When will you use it?

  1. You draw new installations
  2. You coordinate designed installations
  3. You edit installations

Instruction how to install my extension you can find here.

How program work

You select the “Parallel pipe connect” function, then select two pipes and confirm with the “Finish” button.

connect pipes

After pressing this button, the program will insert a perpendicular segment to the selected pipes and connect them together.

auto connect revit pipes

Film with program use

Source code – Revit connect pipes

Below is the program code from the first version of the overlay. For more please visit mine GitHub, where new versions of the overlay will appear on a regular basis.

Copyright (C) 2023 Paweł Kińczyk
## Imports

import math

from Autodesk.Revit.UI.Selection import *
from Autodesk.Revit.DB import *
from Autodesk.Revit.Creation import *
from Autodesk.Revit.Exceptions import ArgumentException
from pyrevit import forms
from pyrevit import revit

import clr

# def / class
# Custom filter to allow picking only the mentioned category
class CustomISelectionFilter(ISelectionFilter):
    def __init__(self, nom_categorie):
        self.nom_categorie = nom_categorie

    def AllowElement(self, e):
        if e.Category.Name in self.nom_categorie:
            # if self.nom_categorie.Contains(e.Category.Name):
            # if e.Category.Name == self.nom_categorie:
            return True
            return False

    def AllowReference(self, ref, point):
        return True

# Pick object/objects with custom filter

def pick_objects(title="Pick", filter=""):
    with forms.WarningBar(title=title):
        return uidoc.Selection.PickObjects(ObjectType.Element, CustomISelectionFilter(filter))

# Mesure distance between two points

def distance(xyz1, xyz2):
    d = 0.0
    d = math.sqrt((xyz2[0] - xyz1[0])**2 + (xyz2[1] -
                  xyz1[1])**2 + (xyz2[2] - xyz1[2])**2)
    return d

# Pick right category and amount of pipes also write error when something is wrong

class PickElements:
    def __init__(self, title="", filter="", error_message="", max_pipes_number=100):
        self.title = title
        self.filter = filter
        self.error_message = error_message
        self.max_pipes_number = max_pipes_number

    def pick_pipes(self):
            self.pipes = pick_objects(title=self.title, filter=self.filter)
            if len(self.pipes) > self.max_pipes_number:
                forms.alert(title="Program Error", msg="You picked more than {} pipes".format(
                    self.max_pipes_number), exitscript=True)
            return self.pipes
            forms.alert(title="Program Error",
                        msg=self.error_message, exitscript=True)

# Loop over the pipes and collect all connectors

class GetPipeConnectors(object):
    def __init__(self, pipes_list):
        self.pipes_list = pipes_list
        self.connectors = {}
        self.connlist = []

    def get_connectors(self):

        for pipe in self.pipes_list:
            pipe = doc.GetElement(pipe)
            conns = pipe.ConnectorManager.Connectors
            for conn in conns:
                if conn.IsConnected:  # get only connected
                self.connectors[conn] = None
                # print(conn)
        return self.connlist, self.connectors

# Main function class that create new pipe and connect them together

class CreateParallelPipeAndConnect(GetPipeConnectors):
    def __init__(self, pipes_list, closest_distance=1000000):
        # Parent class is GetPipeConnectors
        super(CreateParallelPipeAndConnect, self).__init__(
        self.closest_distance = closest_distance

    # *** CODE FROM DYNAMO NODES WRITEEN BY Alban de Chasteigner ***
    # Search for two closest connectors to draw pipe between them
    def search_for_closest_connectors(self):
        self.closest_distance = 1000000
        self.closest_connectors = []
        for i in range(len(self.connectors.items())):
            for j in range(len(self.connectors.items())):
                if i != j:
                    xyz1 = self.connectors.items()[i]
                    xyz2 = self.connectors.items()[j]
                    a = distance(xyz1[0].Origin, xyz2[0].Origin)
                    # print(a)
                    if self.closest_distance > a:
                        self.closest_distance = a
                        self.closest_connectors = {
                            xyz1[0]: None, xyz2[0]: None}
        return self.closest_connectors
    # *** ***

    # *** CODE FROM PYREVIT FORUM MANY THANKS TO Nicholas Miles and Jean-Marc ***
    # Create pipe parallel to two picked pipes
    def create_parallel_pipe(self):
        # Get middle point
        p1 = self.closest_connectors.items()[0]
        p2 = self.closest_connectors.items()[1]

        # Create variable for connector to remove indexing and have more understandable code
        p1_connector = p1[0]
        p2_connector = p2[0]

        # This is the "Direction" of the connector
        p1_vector = p1_connector.CoordinateSystem.BasisZ
        p2_vector = p2_connector.CoordinateSystem.BasisZ

        vector_between_connectors = p1_connector.Origin.Subtract(

        # This will give us the scalar for the projected distance between connectors
        # Multiply 0.5 to get the midpoint of the distance between the vectors
        distance_between_connectors = p2_vector.DotProduct(
            vector_between_connectors) * 0.5

        # Now we add the distance to both of the pipes endpoints
        self.p1_point = p1_connector.Origin.Add(
        self.p2_point = p2_connector.Origin.Add(

        is_parallel = round(p1_vector.X * p2_vector.Y -
                            p1_vector.Y * p2_vector.X) == 0.0

        if (p1_connector.Origin.Z - p2_connector.Origin.Z) < 0.0000001 and is_parallel:

            transaction = Transaction(doc, 'Create parallel pipe')
                parent_pipe = doc.GetElement(self.pipes_list[0])

                self.new_pipe = Plumbing.Pipe.Create(doc, parent_pipe.MEPSystem.GetTypeId(
                ), parent_pipe.GetTypeId(), parent_pipe.ReferenceLevel.Id, self.p1_point, self.p2_point)
            except ArgumentException:
                forms.alert(title="Program Error",
                            msg="Please try to move pipes closer", exitscript=True)

            except Exception as e:

        for conn in self.new_pipe.ConnectorManager.Connectors:
            self.closest_connectors[conn] = None
    # *** ***

    # *** CODE FROM DYNAMO NODES WRITEEN BY Alban de Chasteigner ***
    # Connect all connectors together
    def connect_pipes(self):
        connlist = self.closest_connectors.keys()
        for k in self.closest_connectors.keys():
            mindist = 1000000
            closest = None
            for conn in connlist:
                if conn.Owner.Id.Equals(k.Owner.Id):
                dist = k.Origin.DistanceTo(conn.Origin)
                if dist < mindist:
                    mindist = dist
                    closest = conn
            if mindist > 1:
            self.closest_connectors[k] = closest
                del self.closest_connectors[closest]

        transaction = Transaction(doc, 'Connect pipes - PYLAB')

        for k, v in closest_connectors.items():
                fitting = doc.Create.NewElbowFitting(k, v)

    # *** ***

doc = revit.doc
uidoc = revit.uidoc

pick_pipes = PickElements(title="Pick pipes to be connected", filter="Pipes",
                          error_message="You didn't pick any pipe", max_pipes_number=2)

pipes = pick_pipes.pick_pipes()

get_pipe_connectors = CreateParallelPipeAndConnect(
    pipes_list=pipes, closest_distance=1000000)


closest_connectors = get_pipe_connectors.search_for_closest_connectors()



Please report any irregularities in the operation of the program that occur during use on my social accounts or account GitHub.

See also:

Paweł Kińczyk
Paweł Kińczyk
Articles: 84

Leave a Reply

Your email address will not be published. Required fields are marked *