Python Help: IsPainted() takes exactly 3 arguments (2 given)

Hi All,

I’m preparing to write my first Python script in Dynamo, had some previous experience with Python in Grasshopper but it’s been a couple years. In doing so, I’m just trying to run a simple command from the Revit API, IsPainted, but am getting an error that is telling me this command takes 3 arguments. When looking on the RevitAPI Docs page it says it only takes two.

[http://www.revitapidocs.com/2016/638f398e-bb20-53c4-55a6-454d8a0a1029.htm]
image

Here is my code so far

# Enable Python support and load DesignScript library
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import Document

# The inputs to this node will be stored as a list in the IN variables.
elementID = IN[0]
face = IN[1]

# Place your code below this line
Result = Document.IsPainted(elementID,face)

# Assign your output to the OUT variable.
OUT = Result

To start out this Python project I have tried to get all the parameters for IsPainted within Dynamo and pass them into the Python node. I’m not sure I need to include the Revit file I’m working with here, as I had just opened up a new file drew a couple walls in 3D and painted random faces, then brought those walls into Dynamo via “Select Model Elements.”

Remove Paint Python.dyn (15.5 KB)

Any help would be much appreciated!! Thanks

Oh… I am using Revit 2018.3 and Dynamo 2.0.1

Hi @Jason.Wheeler,

I’m afraid your referencing of the document is not done properly.

Take a look in the primer to get started:

http://primer.dynamobim.org/10_Custom-Nodes/10-5_Python-Revit.html

Thank You @MartinSpence

I have added the following, but not exactly sure which I need and why. The examples from the primer page are using different combinations.

# Import RevitNodes
clr.AddReference("RevitNodes")
import Revit

# Import Revit elements
from Revit.Elements import *

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

import System

Also if I use the above then do I need still need to be adding the following

clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import Document

Lastly I have read some things about the wrapping and unwrapping of “Revit data types” via the following GitHub page. Is this an instance when I need to be unwrapping the faces I’m trying to use?

https://github.com/DynamoDS/Dynamo/wiki/Python-0.6.3-to-0.7.x-Migration

The Python script below is what I currently have. Still have the same issue with IsPainted() takes exactly 3 arguments (2 given)

# Enable Python support and load DesignScript library
import clr

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

clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import Document

# Import RevitNodes
clr.AddReference("RevitNodes")
import Revit

# Import Revit elements
from Revit.Elements import *

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

import System

# The inputs to this node will be stored as a list in the IN variables.
elementID = IN[0]
face = IN[1]

# Place your code below this line
Result = Document.IsPainted(elementID,face)

# Assign your output to the OUT variable.
OUT = Result

Again thanks for the help!

Hi @Jason.Wheeler

You don’t need to feed element.Id. You can directly get Element.Id’s from faces. Here is the modified code below:

# Import libraries
import clr

clr.AddReference("RevitAPI")
clr.AddReference("RevitServices")

import Autodesk
import RevitServices

# Import DocumentManager and TransactionManager
from Autodesk.Revit.DB import *
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc =  DocumentManager.Instance.CurrentDBDocument


#Functions for list handling
ProcessLists = lambda function, lists: [ProcessLists(function, item) if isinstance(item, list) else function(item) for item in lists]
ApplyFunction = lambda func, objs: ProcessLists(func, objs) if isinstance(objs, list) else [func(objs)]

def Unwrap(item):
    return UnwrapElement(item)
    
#Preparing input from dynamo to revit   
if isinstance(IN[0], list):
	surfaces = ProcessLists(Unwrap, IN[0])
else:
	surfaces = Unwrap(IN[0])

def PaintFace(surf):
	elemRef = surf.Tags.LookupTag('RevitFaceReference')
	elem = doc.GetElement(elemRef)
	face = elem.GetGeometryObjectFromReference(elemRef)
	task = doc.IsPainted(elem.Id,face)
	return task

 
# Assign your output to the OUT variable.
OUT = ApplyFunction(PaintFace,surfaces)

image

1 Like

Hey again, @Jason.Wheeler

Ok I’m at a computer now :slight_smile:

Firstly you need to pay attention to the data type you are inputting to the python node. If you for instance use a Select Faces node, you’ll be getting a Autodesk.DesignScript.Geometry.Face object, whereas the API call states that the input must be a Autodesk.Revit.DB.Face. You can use an Object.Type node to check stuff like this:

To use the IsPainted method, as you also stated, you’ll need the ElementId and the Face as parameters:
image

So regarding the imports, you’ll only need to reference the API and the document to get this specific call to work. This looks like this:

import clr

#Import the Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *

#Import DocumentManager and TransactionManager
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager

#Reference the active Document and application
doc = DocumentManager.Instance.CurrentDBDocument 

Figuring out exactly what you need to import can be quite tough in the beginning, but you’ll get the hang of it if you keep practicing :slight_smile:.

The entire scrip looks like this:

import clr

#Import the Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *

#Import DocumentManager and TransactionManager
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager

#Reference the active Document and application
doc = DocumentManager.Instance.CurrentDBDocument

#Start scripting here:

walls = UnwrapElement(IN[0]) #Unwrap the wall in order to expose the API object

opt = Options() #Geometry options object. Needed when extracting geometry from a Revit element. 

output = [] #output list

for i in walls: #Iterate the walls
	elemId = i.Id #Get the element id, which we need to use as a parameter in the IsPainted method
	solids = i.get_Geometry(opt) #use the overloaded property get_Geometry to get the wall solids
	temp = [] #Temp container
	for j in solids: #Iterate the solids  
		faces = j.Faces #use the Faces property to get the faces
		for f in faces: #Iterate the faces
			temp.append(doc.IsPainted(elemId, f)) #append the result to the temp container
			
	output.append(temp) #append the temp container to the out list

#Assign your output to the OUT variable.

OUT = output 

Links to the Classes, Methods and Properties I’ve used:
Options Class: https://apidocs.co/apps/revit/2018.2/64e4d76d-5cd4-6099-fbab-8f0fc6ab64b0.htm
Geometry Property: https://apidocs.co/apps/revit/2018.2/d8a55a5b-2a69-d5ab-3e1f-6cf1ee43c8ec.htm
Faces Property: https://apidocs.co/apps/revit/2018.2/b45fa881-3077-409c-0ef1-5d42744e7429.htm
IsPainted method: https://apidocs.co/apps/revit/2018.2/638f398e-bb20-53c4-55a6-454d8a0a1029.htm

2 Likes

Haha, @Kulkul beat me to it and came up with a different approach :slight_smile:

Now you just have to choose :smiley:

1 Like

@Kulkul is fast. You gotta being the A game to play with a super hero like him. :slight_smile:

1 Like

@Kulkul & @MartinSpence thanks so much! I’m going to need to take some time to digest this, but thanks for helping me out. I’m sure I will have questions after I have taken a deeper dive.