TypeError: expected Point, got builtin_function_or_method

OK, so I have been working through getting my dynamo graph into python because I would like to see if it solves faster than all the dynamo nodes. @colin.mccrone I am borrowing (with commented attribution) some of your work and I thank you very much for the sort and group nodes in Ampersand, I use them often.

My issue is when Trying to create a level plane the post subject is my error. I have tried many different ways of getting a point or XYZ although none seem to be working. Any assistance would be greatly appreciated.

I have tried .ToPoint() and no luck

import clr

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

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

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

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

doc = DocumentManager.Instance.CurrentDBDocument

rLevel = []
levelElev = []
roomGroups = []
levelGroups = []
levels = []
levelPlane = []

rooms = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Rooms).WhereElementIsNotElementType().ToElements()

for r in rooms:
	rLevel.append(r.Level)
	levelElev.append(r.Level.Elevation)

#from Colin McCrone's Ampersand Package
def ListGroupByKey(data,criteria,toSort):
	bins = []
	bins.append(criteria[0])
	sorted = []
	sorted.append([])

	for i in range(1,len(criteria)):
		if criteria[i] in bins:
			continue
		else:
			bins.append(criteria[i])
			sorted.append([]) #initialize an empty list
	if toSort:
		bins.sort()

	#Sort data into bins
	for i in range(len(criteria)):
		for j in range(len(bins)):
			if criteria[i] == bins[j]:
				temp = sorted[j]
				temp.append(data[i])
				sorted[j]=temp
				continue
	return sorted, bins

roomGroups = ListGroupByKey(rooms,levelElev,True)[0]
levelGroups = ListGroupByKey(rLevel,levelElev,True)[0]

#TransactionManager.Instance.EnsureInTransaction(doc)
for l in levelGroups:
    levels.append(l[0])
    lPoint = Autodesk.Revit.DB.XYZ(0,0,l[0].Elevation)
    levelPlane.append(Plane.ByOriginNormal(Vector.ZAxis,lPoint))
#TransactionManager.Instance.TransactionTaskDone()

# Assign your output to the OUT variable.
OUT = roomGroups[0],levelPlane,levels

I hope I am missing something obvious and I get to look like a donkey.

At the moment I will cut and run, use the Level.Plane node and get back into python after that.

1 Like

There may be a namespace conflict between the RevitAPI library and the ProtoGeometry library as both have a Plane class. Furthermore, you are mixing object types (lPoint is an XYZ from Revit and cannot be used as an argument in a DesignScript constructor).

1 Like

ok, hmmm. even with

for l in levelGroups:
    levels.append(l[0])
    lPoint = Autodesk.Revit.DB.XYZ(0,0,l[0].Elevation)
    levelPlane.append(Autodesk.Revit.DB.Plane.CreateByNormalAndOrigin(Vector.ZAxis,lPoint))

this still returns “TypeError: expected XYZ, got builtin_function_or_method”

When I change it to
for l in levelGroups:
levels.append(l[0])
levelPlane.append(l[0].GetPlaneReference)

It runs without Error but returns “IronPython.Runtime.Types.BuiltinFunction”

Think I should just move on. thanks @cgartland maybe I will update when/if I move forward with this topic.

A few things to unpack here…

I think ZAxis is the property of a DesignScript Vector object. Assuming you have a vector vec, it would be used like this:

z = vec.ZAxis

In this case, vec is an instance of the Vector class, however this is still from ProtoGeometry, not from the Revit API.

In your modified script, you are using Plane.CreateByNormalAndOrigin from the Revit API, which, according to the documentation, expects two XYZ objects as its arguments. The XYZ class is a bit confusing as it can be either a point or a vector. In this case, the first XYZ is a vector and the second is a point. To get the world’s Z axis you can use the BasisZ property of the XYZ class:

z = XYZ.BasisZ

In the context of your script, it would look like this:

# No need to call Autodesk.Revit.DB explicitly here
levelPlane.append(Plane.CreateByNormalAndOrigin(XYZ.BasisZ, lPoint))

Lastly, this line is missing a pair of parentheses:

levelPlane.append(l[0].GetPlaneReference)

GetPlaneReference is a method, so it should be written like this:

levelPlane.append(l[0].GetPlaneReference())

thank you for clearing that up for me!

This finally works for what I want, I didn’t realize the error was pointing to the Vector not the XYZ point. That’s why I was spinning in circles.

for l in levelGroups:
    levels.append(l[0])
    lPoint = XYZ(0,0,l[0].Elevation)
    levelPlane.append(Autodesk.Revit.DB.Plane.CreateByNormalAndOrigin(XYZ.BasisZ, lPoint).ToPlane())

many thanks for your time. I am going to keep this bookmarked along with this link: Dynamo DS to Revit in Python

revised the process a bit, only collect rooms over 10’ height (specific to my workflow). This runs Much faster than the dynamo node equivalent. Think I am hooked.

import clr

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

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

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

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

# The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN

# Place your code below this line

doc = DocumentManager.Instance.CurrentDBDocument

rLevel = []
levelElev = []
roomGroups = []
levelGroups = []
levels = []
levelPlane = []

#Start Collecting Roooms Over Height of 10'
heightMin = 10
param = BuiltInParameter.ROOM_HEIGHT
provider = (ParameterValueProvider(ElementId(param)))
eval = FilterNumericGreater()
rule = Autodesk.Revit.DB.FilterDoubleRule(provider, eval, heightMin, 0.01)
epf = Autodesk.Revit.DB.ElementParameterFilter(rule)
roomCollector = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Rooms).WherePasses(epf).WhereElementIsNotElementType().ToElements()

#Get Level and Level Elevation for Rooms over 10'
for r in roomCollector:
	rLevel.append(r.Level)
	levelElev.append(r.Level.Elevation)

#from Colin McCrone's Ampersand Package
def ListGroupByKey(data,criteria,toSort):
	bins = []
	bins.append(criteria[0])
	sorted = []
	sorted.append([])

	for i in range(1,len(criteria)):
		if criteria[i] in bins:
			continue
		else:
			bins.append(criteria[i])
			sorted.append([]) #initialize an empty list
	if toSort:
		bins.sort()

	#Sort data into bins
	for i in range(len(criteria)):
		for j in range(len(bins)):
			if criteria[i] == bins[j]:
				temp = sorted[j]
				temp.append(data[i])
				sorted[j]=temp
				continue
	return sorted, bins

#Group Rooms per Level Elevation
roomGroups = ListGroupByKey(roomCollector,levelElev,True)[0]
#Group Levels per Level Elevation
levelGroups = ListGroupByKey(rLevel,levelElev,True)[0]

for l in levelGroups:
	levels.append(l[0])
	lPoint = XYZ(0,0,l[0].Elevation)
	levelPlane.append(Autodesk.Revit.DB.Plane.CreateByNormalAndOrigin(XYZ.BasisZ,lPoint).ToPlane())

# Assign your output to the OUT variable.
OUT = roomGroups,levelPlane,levels