Automate placing Pipe Accessory (Valves)



I have been trying to put together a script to automate placing valves on pipework serving Mechanical Equipment.

We have some big projects with 1000s of Mechanical Equipment instances, and so placing 1000s of valves is quite laborious and dull task. So i decided I would try to write a script to automate this task.

My workflow idea is:

  1. Find Mechanical Equipment
  2. Create boundary around the Equipment (with specified distance)
  3. Find the Connected or Unconnected pipework intending to serve the Equipment
    3a. Do this by finding the intersection between the Equipment boundary and pipes.
  4. Use MEPOver fitting node to place Valve onto pipework at intersection point.

(Further checks will be needed eventually, e.g. check there is space for the valve on the pipe etc)

I have tried to use some methods from other threads (Placing fire damper on ducts intersecting rf walls & Insert pipe sleeve at wall intersection with rotation and size)

However, I am struggling to get my script to work. The Geometry Intersect node only outputs “Solid” instead of points, and i don’t know how to convert. Currently nothing is inserted into the model. (Note I have made the suggested change (by MEPover) to adjust the family to have both connectors as “Fitting” instead of Global.

(Also, a side point, the string leaves behind a shadow set of generic models of the pipes and equipment, which I would prefer to avoid)

Any suggestions or assistance would be greatly appreciated.

Thank you in advance for your continued help


@danielU3R39 I’m curious why do you want to make a sphere around mechanical equipment?
what I’d suggest is, try making a bounding box for all mechanical equipment, then use “BoundingBox.GetElementIntersect” (BimorphNodes) to get all the pipe element intersecting.
once you have pipe elements you can get curve & center point of the pipe to place valve.


@jalshu Thank you for this.

I incorporated your script, which shows a point to place the valve, but the valve is not placed. The family connectors are set to “fitting”.

In answer to you question, the reason i created a sphere, is because I need to find intersections where there aren’t actually any in the model (i.e. virtual expand the mechanical equipment). This is because at the moment, we do not always connect pipework to our mechanical equipment in our model (when using low LOD in the project)

However, i can assume that the bounding box intersect “tolerance” connector is doing something similar to this? If not, is there any way to expand a bounding box?

Thank you for your help. Below is the script with run results.


Here is a snapshot from my Revit test file. I have highlighted the points the script creates.


You might want to flatten the list after “List.Clean” and then Chop it to have one point in each list.

Please read the solution of this thread. It explains how MEPFitting.Bypoint works.

On the side note, are you still interested in find the the intersection point by sphere? But I’m worried that what if it finds more than one intersection point or cross contamination(nearby mechanical equipment also has intersection with a pipe,which is not associated with that)? so that’s why I suggested using Bounding Box and then find the unique elements.
Yes, you may change the size of BoundingBox.


@jalshu @T_Pover

Thank you. I have followed your advice, and used the list chop, giving a list per pipe. The script worked and added the fitting, but not quite how I had hoped (see below)… The pipes have moved around, and the fitting is not connected to the pipework nor inherit the system. I have attached the valve that I am using for the test.

Any suggestions would be greatly appreciated.

M_Check Valve_Fitting.rfa (396 KB)

The result:

The script


@danielU3R39 MEP curve should be filtered duct elements. Try this.


@jalshu Thank you very much for pointing out that silly error. Made the change, but note that I took a 2nd output from the intersect -> cleanup -> flatten. But now it works perfectly!


@jalshu & @T_Pover

Sorry to ask another question. I want to try to insert different fitting types depending on the size of the pipe.

The valve family has a Family Type for each diameter size of Valve.

I am able to select the correct Family Type for each pipe, but I haven’t worked out how the node accepts multiple family types. I have tried using a flat list, as well as a chopped list (like the pipes). The chopped list gives me the following error in Revit. It looks like its inserting multiple valves.

Is there are a way for the MEPFitting node to take multiple fitting family types?

Maybe the node cannot accept multiple family type inputs… I have checked the other threads, and it looks like they use an instance parameter (instead of type parameter) in the family to change the size of the fitting.



It is possible to input a list of FamilyTypes so that shouldn’t be the problem. I think it gives the error because the python code will also try to change the size of the connectors on the family and changing the size of the family when it’s a type parameter is probably the reason for the error.
If you are somewhat comfortable with Python then you could try removing the lines that set the Connector sizes and see if that works:


@danielU3R39 If different family type is based on just size of the pipe, I feel that it would be worth investing time to make a flexible/adaptive family which will update the size of family type based on host. something similar to Autodesk’s Ball valve family from 2" to 6". So depending on host pipe’s size, It will place accurate valve size.


Thank you both. I would like to understand how a list of FamilyTypes can be input into the node. See the image below, I have used both highlighted lists with no success.

However, if as you say @T_Pover there is a way this can work, I would prefer this, as it allows more functionality with use of different valve families, as most of the valves that I have seen are built with each size as a FamilyType. And to use multiple valve types (PICV, ball valve etc) I will only have the simpler task of changing the connector from “global” to “fitting”.

However, if this becomes over-complicated I will invest time in editing the family(s) to be parametric per instance.


If you take out the Python node and make the modifications as I suggested then it might work.

Depending on the setup, sizes and families I sometimes received some errors, so it depends on your project setup if this will work.