Python script to place Point Element on MEP Fabrication Pipework Centreline

Python script to place Point Element on MEP Fabrication Pipework Centreline

AndrewWalkerE33UZ
Explorer Explorer
649 Views
3 Replies
Message 1 of 4

Python script to place Point Element on MEP Fabrication Pipework Centreline

AndrewWalkerE33UZ
Explorer
Explorer

Hello, thank you for reading my post.

 

We have a pipe clip that we use and it can be hosted to lines or faces. I didn't create the family but it is nested in a what I think is an Adaptive family turned Structural Connection, and then uses Point Elements, to host to the centreline of the MEP Fabrication pipework we use.

I am trying to write some code that will place these clips on selected pipes but I cant for the life of me get it to host correctly. The closest I have come is to place the clip on the midpoint of the pipework.

 

Does anyone know how I do this through the API, attached is my code and the pipe clip.

 

AndrewWalkerE33UZ_0-1734051811385.png

 



Edit: Currently trying to get this to work in Revit 22/23

 

Much Appreciated,

Andy

0 Likes
Accepted solutions (1)
650 Views
3 Replies
Replies (3)
Message 2 of 4

harilalmnCBXDY
Enthusiast
Enthusiast

@AndrewWalkerE33UZ 
I would humbly suggest two things;


1. Keep that family simple. Too much of unnecessary nesting, I feel. 
2. Keep the model inside the family file oriented to the front, left or right view. It is now modelled on XY plane.

Then it becomes so easy to do the automation. Also, I don't think there is any need to make it adaptive.
Now, if you wish to make it Line Based, it is a good call but still, keep the family instance modelled on any plane other than XY, keeping it vertical. By the way, you can easily achieve this using Dynamo. I tried it and seemed working. Here is a screenshot.

harilalmnCBXDY_1-1734110593386.png

I am attaching;

1. The project file
2. The family file edited version as a representation without any parameters and constrains for the purpose of demonstration)

3. The Dynamo File

 

Message 3 of 4

harilalmnCBXDY
Enthusiast
Enthusiast

If you really want to use Python, after keeping the family file simple, as mentioned above, the following script should work. 

__title__ = "Support\nBracket"

import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import StructuralType
from Autodesk.Revit.UI import *
from Autodesk.Revit.UI.Selection import *
from System.Collections.Generic import List

doc = __revit__.ActiveUIDocument.Document
uidoc = __revit__.ActiveUIDocument

def get_adaptive_family_symbol():
    """Get the family symbol for the adaptive component"""
    collector = FilteredElementCollector(doc).OfClass(FamilySymbol)
    
    for symbol in collector:
        if symbol.Family.Name == "ClipBracket":
            if not symbol.IsActive:
                try:
                    with Transaction(doc, "Activate Symbol") as t:
                        t.Start()
                        symbol.Activate()
                        t.Commit()
                except Exception as e:
                    print("Error activating symbol: {}".format(str(e)))
                    return None
            return symbol
    return None

def create_family(point, angle):
    familySymbol = get_adaptive_family_symbol()
    if familySymbol is None:
        print("Could not find family symbol")
        return
    
    try:
        with Transaction(doc, "Activate Symbol") as t:
            t.Start()
            # Create a new instance of the family
            newFamily = doc.Create.NewFamilyInstance(point, familySymbol, Structure.StructuralType.NonStructural)
            ElementTransformUtils.RotateElement(doc, newFamily.Id, Line.CreateBound(point, point + XYZ.BasisZ), angle)
            t.Commit()
    except Exception as e:
        print("Error creating family: {}".format(str(e)))

pipe = doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element, "Pick object"))
location = pipe.Location
locationCurve = location.Curve
point = locationCurve.Evaluate(0.5, True)
rotationFactor = 1
if locationCurve.Direction.CrossProduct(XYZ.BasisZ).Z < 0:
    rotationFactor = 1
else:
    rotationFactor = -1
angle = locationCurve.Direction.AngleOnPlaneTo(XYZ.BasisY, XYZ.BasisZ) * rotationFactor

create_family(point, angle)


It is working for me. Kindly see the attached video. 
Note that, as I mentioned the family file has to be finetuned by setting the required parameters and comnstraints , like pipe diameter etc...

Message 4 of 4

AndrewWalkerE33UZ
Explorer
Explorer
Accepted solution

Hi @harilalmnCBXDY, thank you for your reply and efforts to fix my problem. I have given up on trying to host adaptive elements to pipework centrelines until I find evidence it is possible with the Revit API.

 

I went back to just placing the clip on the centreline and manipulating it based on the geometry, I kept the complex clip as this is a clip we have multiple variations of, is used across multiple offices in the UK and used in multiple offices in other counties so updating and pushing new clips to all these places would of been a huge hassle.

 

I cracked it in the end, you select all your clips and steelwork run the script and a clip is placed on each pipe inline with the steel, a bearer is extended to the face of the steelwork and my wood block / clip size update to match the size of the pipework. Pretty happy with it so far.

 

 

Thanks again for your support.

 

Andy