Place Fabrication hanger by points in Dynamo

Hello, I have multiple points and i need to place a fabrication hanger to those points. I couldn’t find any nodes to convert point to fabrication element.
Also need to change the size of the hanger too. But when i check the parameters in revit properties no option shown there.
Anybody tell me how can i do these in Dynamo. (I am a beginner in dynamo)

Hello @arukaroor and welcome
Please read the forum rules if you haven’t.

I’m not sure if there are custom nodes can do this, I know you are a beginner but you can do it with Python if you have some programming knowledge.
unfortunately the Fabrication Part is not the easiest part of the Revit API

here an example
hangers3

Python code

import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Fabrication import *

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

def getConnectors(elem):
	lstCon = []
	conectors = elem.ConnectorManager.Connectors
	lstCon = [con for con in conectors]
	return lstCon[0], lstCon[1]

def getServiceButton(lstServiceFab, famName):	
	for servicFab in lstServiceFab:
		countGroup = servicFab.GroupCount
		for x in range(countGroup):
			countButton = servicFab.GetButtonCount(x)
			for y in range(countButton):
				fabServiceButton = servicFab.GetButton(x,y)
				if fabServiceButton.Name == famName:
					return fabServiceButton


fabPart = UnwrapElement(IN[0])
lstPoints = IN[1]
famName = IN[2]
outHanger = []
error = []
fabConf = FilteredElementCollector(doc).OfClass(FabricationConfiguration).FirstElement()
lstServ = fabConf.GetAllLoadedServices()
button  = getServiceButton(lstServ, famName)
if button is not None:
	TransactionManager.Instance.EnsureInTransaction(doc)
	for pts in lstPoints:
		#convert dynamoPt to RevitPt
		rvtPt = pts.ToXyz()
		curveFabPart = fabPart.Location.Curve
		conectA,  conectB = getConnectors(fabPart)
		interResult = curveFabPart.Project(rvtPt)
		if interResult.Distance < 0.05 :
			distaceA = rvtPt.DistanceTo(conectA.Origin)
			distaceB = rvtPt.DistanceTo(conectB.Origin)
			try:
				newhanger = FabricationPart.CreateHanger(doc, button, fabPart.Id, conectA, distaceA, True)
				outHanger.append(newhanger)
			except:
				try:
					newhanger = FabricationPart.CreateHanger(doc, button, fabPart.Id, conectB, distaceB, True)
					outHanger.append(newhanger)
				except Exception as ex:	
					error.append([ex, distaceA, distaceB])
	
	TransactionManager.Instance.TransactionTaskDone()
else:
	error = "ERROR, No hanger has been loaded with this name : '{}'".format(famName)
OUT = fabConf, button, outHanger, error

the api doc

3 Likes

What do you mean by you have points to place hangers? You have coordinates? A model element that needs changed to a hanger?

As mentioned MEP Fab parts are hard to work with in revit but I’m guessing you have already figured that out.
Hanger size is not an available instance parameter in the revit properties. By Dynamo can pull it up.
Element.Parameters is a useful node to figure out what you have to work with.
Also Parameter.ParameterByName needs to be used with Fab parts a lot instead of Element.GetParameterValue ByName but not always.

Thank you Mr.c.poupin for your support. Sorry for late reply.

I am not familiar with any programing language. But I have copied this example code in Dynamo and run the script as you shown in the image.
In my understanding this code will place hanger at (given input) distance, and it will work with only one element at a time. Correct me if I am wrong.
When I connect multiple pipes, this script shows some warnings(see the attached image).
Actually my requirement is that I need to place hangers at a specific distance in a pipe/duct run (a pipe run may be contain multiple pipes/fittings/couplings/solder joints/welded joints etc).
Is there any way to update this script for placing the hangers at a distance of 5’-0" by selecting a long pipe run and considering start and end points (P1 & P2) as marked in the image.


Sorry for my poor English.

Thank you for your reply Mr.Evan.Pond
A model element that needs changed to a hanger? : Exactly.
I didn’t see a way place the hanger and change the size parameter for fabrication part in dynamo.

Here is a variant for multi conduit, nevertheless you will have to determine the points per conduits (list with sub list of points)

import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Fabrication import *

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

def getConnectors(elem):
	lstCon = []
	conectors = elem.ConnectorManager.Connectors
	lstCon = [con for con in conectors]
	return lstCon[0], lstCon[1]

def getServiceButton(lstServiceFab, famName):	
	for servicFab in lstServiceFab:
		countGroup = servicFab.GroupCount
		for x in range(countGroup):
			countButton = servicFab.GetButtonCount(x)
			for y in range(countButton):
				fabServiceButton = servicFab.GetButton(x,y)
				if fabServiceButton.Name == famName:
					return fabServiceButton

toList = lambda x : x if hasattr(x, '__iter__') else [x]


lst_fabPart = toList(UnwrapElement(IN[0]))
group_lst_Points = IN[1]
famName = IN[2]
outHanger = []
error = []
fabConf = FilteredElementCollector(doc).OfClass(FabricationConfiguration).FirstElement()
lstServ = fabConf.GetAllLoadedServices() #GetAllServices()
button  = getServiceButton(lstServ, famName)
if button is not None:
	TransactionManager.Instance.EnsureInTransaction(doc)
	for lstPoints, fabPart in zip(group_lst_Points, lst_fabPart):
		for pts in lstPoints:
			#convert dynamoPt to RevitPt
			rvtPt = pts.ToXyz()
			curveFabPart = fabPart.Location.Curve
			conectA,  conectB = getConnectors(fabPart)
			interResult = curveFabPart.Project(rvtPt)
			if interResult.Distance < 0.05 :
				distaceA = rvtPt.DistanceTo(conectA.Origin)
				distaceB = rvtPt.DistanceTo(conectB.Origin)
				try:
					newhanger = FabricationPart.CreateHanger(doc, button, fabPart.Id, conectA, distaceA, True)
					outHanger.append(newhanger)
				except:
					try:
						newhanger = FabricationPart.CreateHanger(doc, button, fabPart.Id, conectB, distaceB, True)
						outHanger.append(newhanger)
					except Exception as ex:	
						error.append([ex, distaceA, distaceB])
	
	TransactionManager.Instance.TransactionTaskDone()
else:
	error = "ERROR, No hanger has been loaded with this name : '{}'".format(famName)
OUT = fabConf, button, outHanger, error
2 Likes

When I to run the new script, its showing some waring in the python script. Am I doing anything wrong?
Please se the attached script.

Hanger-Python.dyn (16.5 KB)

Set the lacing of the Curve.PointAtParameter node to “Cross”

1 Like

I have tried the lacing already. Still it shows warning in python code. Also It would be better if we can provide hanger distance in code block as input. I mean, if the pipes total length is 10’ , the hangers should be placed at given input distance. Instead of providing the total number and steps in code block[0.2…0.7…0.2] a single input (hanger distance) would be work better.

Sorry to disturb you again.
Untitled

You have an error in your graph, show the graph in this post

2 Likes