Paint all conduit's faces at once

Hello everybody. I am new with all those dynamo things, but that is the challenge.
I want to apply different materials to different conduits. Applying filter settings will not work for what I need. The only way to actually apply material to conduits is using Paint tool, but I have thousands and thousands of conduit on the project and each segment has 4 faces. I mean it will be a really amount of time if i do it manually. I was wondering if there is a dynamo code or something to make it more automatically.

Thank you so much!

Hi @tiagob_etc !
Are those conduits regular families ? What is the rule to drive the painting ?
With dynamo you can do a lots of things, you can create your own script (with the help of the community :slightly_smiling_face:).
Could you share a scrennshot to show what you want to do ?

1 Like

Hi, thanks for answering.

The conduits are the standard Revit family. (I still don’t know why they keep avoiding put the material parameter in conduit families).

I have different kinds of conduits in my projects. And I would like to apply the materials for each kind. But, the family doesn’t have the parameter and I don’t know how you can add that parameter to that kind of family, the only way I know, so far, is using painting tool.
To better understand, at the screenshot, on the right, we have the conduits with a filter applied where shows the different types and each one with their colors. But I need to rendering some scenes of the project, and the filter parameter does not work for that. When I try to do, it goes like it is on the left. Everything gray, because filter is only a visualization thing, and I really need to apply the materials.

But I have thousands of conduits on the project, it would take so many hours if I do that manually. I was wondering if there is a way, in dynamo, you can select all conduits of one type, and paint all surfaces of the selection at once with one material…

They are systems families so no way to add a parameter.
Can’t you aplly a material by electrical system ?.(i know it is possible with mechanical systems).
But you want it by family type, isn’t it ?
I don’t think there is a node to use the paint tool. Maybe in a package…

1 Like

For pipes yes, I could apply by systems, but for electrical, I cannot do that, they don’t have systems properties like mechanical (at least I don’t think so).

But the problem about applying by systems is that it could overlay the material of all the system’s elements, including the ones that already have theirs set, like lightning switches and outlets, as it does for hydraulic systems, with the valves, for exemple.

I got it… I’ll keep looking in the packages if I can find anything. Thank you very much!

Hello @tiagob_etc
try this (just for Conduits, conduits must connected)

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

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

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

def getAllConnect(conduit):
	lstIds = [conduit.Id]
	lstconduit = [conduit]
	def findNext(lstconduitCheck):
		lstElemId = []
		for conduitCheck in lstconduitCheck:
			if hasattr(conduitCheck, 'ConnectorManager'):
				conManag = conduitCheck.ConnectorManager
			else:
				conManag = conduitCheck.MEPModel.ConnectorManager			
			for con in conManag.Connectors :
				for conRef in con.AllRefs:
					if conRef.Owner.Id not in lstIds:
						lstElemId.append(conRef.Owner.Id)
		return lstElemId
	flag = True
	while flag:
		newConnIds = findNext(lstconduit)
		if len(newConnIds) > 0:
			newConnElem = [doc.GetElement(x) for x in 	newConnIds]	
			lstconduit.extend(newConnElem)
			lstIds.extend(newConnIds)
		else:
			flag = False
			break
	return 	lstconduit	
	
conduit = UnwrapElement(IN[0])
material = UnwrapElement(IN[1])
opt = Options()
TransactionManager.Instance.EnsureInTransaction(doc)
for conduitToPaint in getAllConnect(conduit) :
	if isinstance(conduitToPaint, Conduit):
		instGeo = conduit.get_Geometry(opt)
		for ig in instGeo:
			if isinstance(ig, Solid):
				for face in ig.Faces:
					doc.Paint(conduitToPaint.Id, face, material.Id)						
						
TransactionManager.Instance.TransactionTaskDone()

OUT = getAllConnect(conduit)
5 Likes

hello c.poupin
do you can help me to change your code of python for cable tray ??

thanks

Hello @maikol.gonzalez and welcome :grinning:
please start a new topic

Hello C.poipin

I loved the script of python and I would like to ask you for a favour. I need to choose the elements to assign to each material as I have different types of materials in my channelling of conduit. I want select the conduit and asign the material, I hope you could help me with that. Thank you in advance!

Hello @maikol.gonzalez
here, an example based on Name of Type (pipe)
the goal is to create a dictionary with :

  • keys → name of PipeTypes
  • values → materials

paint_by_type


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

clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
from Autodesk.Revit.DB.Electrical import Conduit
from Autodesk.Revit.DB.Plumbing import Pipe

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

def getAllConnect(conduit):
	lstIds = [conduit.Id]
	lstconduit = [conduit]
	def findNext(lstconduitCheck):
		lstElemId = []
		for conduitCheck in lstconduitCheck:
			if hasattr(conduitCheck, 'ConnectorManager'):
				conManag = conduitCheck.ConnectorManager
			else:
				conManag = conduitCheck.MEPModel.ConnectorManager			
			for con in conManag.Connectors :
				for conRef in con.AllRefs:
					if conRef.Owner.Id not in lstIds:
						lstElemId.append(conRef.Owner.Id)
		return lstElemId
	flag = True
	while flag:
		newConnIds = findNext(lstconduit)
		if len(newConnIds) > 0:
			newConnElem = [doc.GetElement(x) for x in 	newConnIds]	
			lstconduit.extend(newConnElem)
			lstIds.extend(newConnIds)
		else:
			flag = False
			break
	return 	lstconduit	
	
def get_material_from_dict(elem):
	fullName = elem.get_Parameter(BuiltInParameter.ELEM_FAMILY_AND_TYPE_PARAM).AsValueString()
	for name, mat in dictmaterial.items():
		if name in fullName:
			return UnwrapElement(mat)
			
conduit = UnwrapElement(IN[0])
dictmaterial = dict(IN[1])

opt = Options()
TransactionManager.Instance.EnsureInTransaction(doc)
for conduitToPaint in getAllConnect(conduit) :
	material = get_material_from_dict(conduitToPaint)
	print(material)
	if isinstance(conduitToPaint, (Pipe, Conduit)):
		instGeo = conduit.get_Geometry(opt)
		for ig in instGeo:
			if isinstance(ig, Solid):
				for face in ig.Faces:
					#doc.Paint.Overloads[DB.ElementId, DB.Face, DB.ElementId](conduitToPaint.Id, face, material.Id)
					doc.Paint(conduitToPaint.Id, face, material.Id)
TransactionManager.Instance.TransactionTaskDone()

OUT = getAllConnect(conduit)
1 Like

@c.poupin
I’m starting to use python and your script helps me understand a little more, thanks for your help, time and dedication :smiley: