Bart
March 31, 2026, 12:27pm
1
I’m trying to create a roof based on an existing ceiling using Dynamo and Python.
Below is the Python script. It feels like I’m on the right track, but I’m clearly missing something. When I run the script, I receive the following warning:
TypeError : No method matches given arguments for NewFootPrintRoof: (<class 'Autodesk.Revit.DB.CurveArray'>, <class 'Autodesk.Revit.DB.Level'>, <class 'Autodesk.Revit.DB.RoofType'>) [' File "<string>", line 85, in <module>\n']
Which is weird, because the NewFootPrintRoof method requires the inputs as given.
Even AI can’t figure this one out. So I’m hoping a human might have a brighter idea.
# INPUTS
ceilings = [doc.GetElement(ElementId(5683347))]
systeemplafond_type = get_rooftype_by_name("NLRS_45_RO_systeemplafond_GEN")
output = []
errors = []
# CODE
TransactionManager.Instance.EnsureInTransaction(doc)
for ceiling in ceilings:
ceiling_lvl = doc.GetElement(ceiling.LevelId)
ceiling_offset = ceiling.get_Parameter(BuiltInParameter.CEILING_HEIGHTABOVELEVEL_PARAM).AsDouble()
ceiling_profile = doc.GetElement(ceiling.SketchId).Profile
footprint = CurveArray()
loop = ceiling_profile[0] # first array as boundary
for c in loop:
footprint.Append(c)
roof = doc.Create.NewFootPrintRoof(footprint, ceiling_lvl, systeemplafond_type)
output.append(roof)
TransactionManager.Instance.TransactionTaskDone()
OUT = output
Has anyone encountered this before, or does anyone see what I’m doing wrong?
Any help or pointers would be greatly appreciated.
What imported modules are you using because if you have attached the full code then this is probably the avenue where you are having issues.
Also if the above is your full code suprised you dont have issues with “get_rooftype_by_name”
Bart
March 31, 2026, 12:59pm
3
For readability, I only included the part of the code that causes the issue. Below is the full script:
import sys
import clr
clr.AddReference("ProtoGeometry")
from Autodesk.DesignScript.Geometry import *
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
import System
from System.Collections.Generic import List
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
app = uiapp.Application
intVersion = int(app.VersionNumber)
# FUNCTIONS
def to_list(obj):
return obj if isinstance(obj, list) else [obj]
def get_rooftype_by_name(name):
"""Function to get a Roof Type by name."""
types = FilteredElementCollector(doc).OfClass(RoofType)
for type in types:
if type.get_Parameter(BuiltInParameter.ALL_MODEL_TYPE_NAME).AsString() == name:
return type
return None
# INPUTS
ceilings = [doc.GetElement(ElementId(5683347))]
systeemplafond_type = get_rooftype_by_name("NLRS_45_RO_systeemplafond_GEN")
output = []
errors = []
# CODE
TransactionManager.Instance.EnsureInTransaction(doc)
for ceiling in ceilings:
ceiling_lvl = doc.GetElement(ceiling.LevelId)
ceiling_offset = ceiling.get_Parameter(BuiltInParameter.CEILING_HEIGHTABOVELEVEL_PARAM).AsDouble()
ceiling_profile = doc.GetElement(ceiling.SketchId).Profile
footprint = CurveArray()
loop = ceiling_profile[0] # first array as boundary
for c in loop:
footprint.Append(c)
roof = doc.Create.NewFootPrintRoof(footprint, ceiling_lvl, systeemplafond_type)
output.append(roof)
TransactionManager.Instance.TransactionTaskDone()
OUT = output
By the looks of it you’re missing the ‘out’ parameter for the resulting curves (which I recall is a requirement in some conditions). How to manage that will depend on your Python engine.
Bart
March 31, 2026, 1:21pm
5
I am using the CPython3 engine. Running the python script in Dynamo 3.6 in Revit 2026
PythonNet3 is likely going to work out better here if you’re ok migrating. C# would be easiest and most maintainable.
Try the following though may be best to use PythonNet3 as Jacob indicated above
import sys
import clr
clr.AddReference("ProtoGeometry")
from Autodesk.DesignScript.Geometry import *
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
import System
from System.Collections.Generic import List
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
app = uiapp.Application
intVersion = int(app.VersionNumber)
# FUNCTIONS
def to_list(obj):
return obj if isinstance(obj, list) else [obj]
def get_rooftype_by_name(name):
"""Function to get a Roof Type by name."""
types = FilteredElementCollector(doc).OfClass(RoofType)
for type in types:
if type.get_Parameter(BuiltInParameter.ALL_MODEL_TYPE_NAME).AsString() == name:
return type
return None
# INPUTS
ceilings = [doc.GetElement(ElementId(5683347))]
systeemplafond_type = get_rooftype_by_name("NLRS_45_RO_systeemplafond_GEN")
output = []
errors = []
# CODE
TransactionManager.Instance.EnsureInTransaction(doc)
for ceiling in ceilings:
ceiling_lvl = doc.GetElement(ceiling.LevelId)
ceiling_offset = ceiling.get_Parameter(BuiltInParameter.CEILING_HEIGHTABOVELEVEL_PARAM).AsDouble()
ceiling_profile = doc.GetElement(ceiling.SketchId).Profile
footprint = CurveArray()
loop = ceiling_profile[0]# first array as boundary
for c in loop:
footprint.Append(c)
footPrintToModelCurveMapping = clr.StrongBox[ModelCurveArray](ModelCurveArray())
roof = doc.Create.NewFootPrintRoof(footprint, ceiling_lvl, systeemplafond_type,footPrintToModelCurveMapping)
output.append(roof)
TransactionManager.Instance.TransactionTaskDone()
OUT = output
here is the syntax for CPython3 or PythonNet3 (preferred)
import sys
import clr
clr.AddReference("ProtoGeometry")
from Autodesk.DesignScript.Geometry import *
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
import System
from System.Collections.Generic import List
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
app = uiapp.Application
intVersion = int(app.VersionNumber)
# FUNCTIONS
def to_list(obj):
return obj if isinstance(obj, list) else [obj]
def get_rooftype_by_name(name):
"""Function to get a Roof Type by name."""
types = FilteredElementCollector(doc).OfClass(RoofType)
for type in types:
if type.get_Parameter(BuiltInParameter.ALL_MODEL_TYPE_NAME).AsString() == name:
return type
return None
# INPUTS
ceilings = [UnwrapElement(IN[0])]
systeemplafond_type = get_rooftype_by_name("Toit - 200 mm")
output = []
errors = []
# CODE
TransactionManager.Instance.EnsureInTransaction(doc)
for ceiling in ceilings:
ceiling_lvl = doc.GetElement(ceiling.LevelId)
ceiling_offset = ceiling.get_Parameter(BuiltInParameter.CEILING_HEIGHTABOVELEVEL_PARAM).AsDouble()
ceiling_profile = doc.GetElement(ceiling.SketchId).Profile
footprint = ceiling_profile[0]
# NOT NECESSARY
# loop = ceiling_profile[0] # first array as boundary
# for c in loop:
# footprint.Append(c)
out_curveArr = ModelCurveArray()
roof, out_curveArr = doc.Create.NewFootPrintRoof(footprint, ceiling_lvl, systeemplafond_type, out_curveArr)
output.append(roof)
TransactionManager.Instance.TransactionTaskDone()
OUT = output
Bart
April 1, 2026, 6:47am
9
Thanks Cyril, that worked! Thanks as well to Jacob and Brendan for thinking along with me.