Hi,
I’ve search all the forum and google, and I couldn’t find an example in Python to Set Slope to Roof. There are RevitAPI example but in C# and VB I can’t figure out how to code them in Python.
So the code to create the roof creates a roof as a slab with no slope
import clr
#Import Revit Nodes
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
# Import DocumentManager and TransactionManager
clr.AddReference("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.
lines = IN[0].ToRevitType()
level = UnwrapElement(IN[1])
type = UnwrapElement(IN[2])
output = []
doc = DocumentManager.Instance.CurrentDBDocument
#Create Curve Array
cArray = CurveArray()
mcArray = clr.StrongBox[ModelCurveArray](ModelCurveArray())
#Loop through lines
for line in lines:
cArray.Append(line)
#Start Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
#Create Roof
roof = doc.Create.NewFootPrintRoof(cArray, level, type, mcArray)
output.append(roof.ToDSType(False))
#End Transaction
TransactionManager.Instance.TransactionTaskDone()
#Assign your output to the OUT variable.
OUT = output
I know I have to do something with the mcArray to set the slope parameter to the sketch model line or to set a curve as a slope arrow for the Roof.
Perhaps there is something to do from Link with this part,
import clr
#Import Revit Nodes
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
# Import DocumentManager and TransactionManager
clr.AddReference("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.
lines = IN[0].ToRevitType()
level = UnwrapElement(IN[1])
type = UnwrapElement(IN[2])
output = []
doc = DocumentManager.Instance.CurrentDBDocument
#Create Curve Array
footprint = CurveArray()
footPrintToModelCurveMapping = ModelCurveArray()
#Loop through lines
for line in lines:
footprint.Append(line.Curve)
footPrintToModelCurveMapping.Append(line.GeometryCurve)
iterator = footPrintToModelCurveMapping.ForwardIterator()
iterator.Reset()
while( iterator.MoveNext() )
line = iterator.Current as ModelCurve
footprintRoof.set_DefinesSlope( line, true )
footprintRoof.set_SlopeAngle( line, 0.5 )
#Start Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
#Create Roof
roof = doc.Create.NewFootPrintRoof(footprint, level, type, out footPrintToModelCurveMapping)
output.append(roof.ToDSType(False))
#End Transaction
TransactionManager.Instance.TransactionTaskDone()
#Assign your output to the OUT variable.
OUT = output
but it gives a error:
Warning: IronPythonEvaluator.EvaluateIronPythonScript operation failed.
unexpected token ‘’
Can’t really help you with your script as it is not properly formatted. Can you try fixing it first? Especially the indenting within the for and while loops. Also make sure the clr.AddReference()‘s are using single quote (’) instead of double quote (")
Thank you kennib6 ,
please have a look as I tried to do what you said, unfortunately I’m not sure regarding while
import clr
#Import Revit Nodes
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
# Import RevitAPI
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
# Import DocumentManager and TransactionManager
clr.AddReference('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.
lines = IN[0].ToRevitType()
level = UnwrapElement(IN[1])
type = UnwrapElement(IN[2])
output = []
doc = DocumentManager.Instance.CurrentDBDocument
#Create Curve Array
footprint = CurveArray()
footPrintToModelCurveMapping = ModelCurveArray()
#Loop through lines
for line in lines:
footprint.Append(line.Curve)
footPrintToModelCurveMapping.Append(line.GeometryCurve)
iterator = footPrintToModelCurveMapping.ForwardIterator()
iterator.Reset()
while iterator.MoveNext()
line = iterator.Current as ModelCurve
footprintRoof.set_DefinesSlope( line, true )
footprintRoof.set_SlopeAngle( line, 0.5 )
#Start Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
#Create Roof
roof = doc.Create.NewFootPrintRoof(footprint, level, type, out footPrintToModelCurveMapping)
output.append(roof.ToDSType(False))
#End Transaction
TransactionManager.Instance.TransactionTaskDone()
#Assign your output to the OUT variable.
OUT = output
Unfortunately I am leaving the office for the night and I am pretty bad at C# to python. However, the footprint = CurveArray() is unneeded as you don’t need to initialize variables in python, except to make it a list. So replace that with footprint = [] and footPrintToModelCurveMapping = []
Inside the for loop, .append should be lowercase. Anything more would take me a bit to look at that I would rather go home
The reason why iterator.MoveNext() can be used in the while loop is that it will return a bool of false if it is not able to do so. So instead of explicitly stating when the loop ends, it will just continue iterating until it cannot anymore.
Edit: Also, as @Mark.Ackerley said, the as doesn’t work in Python.
Think I got lost along the way, but tried to show two approaches (both using the "while statement and the approach originally by @Dimitar_Venkov) in this post NewFootPrintRoof Troubles
import clr
#Import Revit Nodes
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
# Import RevitAPI
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
from clr import StrongBox
# Import DocumentManager and TransactionManager
clr.AddReference('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.
lines = IN[0].ToRevitType()
level = UnwrapElement(IN[1])
type = UnwrapElement(IN[2])
output = []
doc = DocumentManager.Instance.CurrentDBDocument
footprint = CurveArray()
for o in lines:
footprint.Append(o )
TransactionManager.Instance.EnsureInTransaction(doc)
roofCurves = StrongBox[ModelCurveArray](ModelCurveArray() )
type = UnwrapElement(IN[2])
footprintRoof = doc.Create.NewFootPrintRoof(footprint, level, type, roofCurves)
TransactionManager.Instance.TransactionTaskDone()
ftprintRoof = footprintRoof
iterator = roofCurves.ForwardIterator()
iterator.Reset()
while iterator.MoveNext():
line = iterator.Current
ftprintRoof.set_DefinesSlope( line, True )
ftprintRoof.set_SlopeAngle( line, 0.5 )
OUT = footprintRoof.ToDSType(False), roofCurves.Value, ftprintRoof
Jonathan, thanks for your help
I am trying to figure out what did you do with this script, if I replace it, still doesn’t work
could you please give some more details?
I wish I can make one or all with a slope value to understand how it works, than I can decide which I need to make as a slope. For instance, I would set all the foot print lines to have a slope value and later to modify the script if I want it to be only the last one
See if this gives a better idea of how you could change e.g. one angle:
import clr
#Import Revit Nodes
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
# Import RevitAPI
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
from clr import StrongBox
# Import DocumentManager and TransactionManager
clr.AddReference('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.
lines = IN[0].ToRevitType()
level = UnwrapElement(IN[1])
type = UnwrapElement(IN[2])
output = []
doc = DocumentManager.Instance.CurrentDBDocument
footprint = CurveArray()
for o in lines:
footprint.Append(o)
TransactionManager.Instance.EnsureInTransaction(doc)
roofCurves = StrongBox[ModelCurveArray](ModelCurveArray() )
type = UnwrapElement(IN[2])
footprintRoof = doc.Create.NewFootPrintRoof(footprint, level, type, roofCurves)
TransactionManager.Instance.TransactionTaskDone()
ftprintRoof = footprintRoof
alllines = []
iterator = roofCurves.ForwardIterator()
iterator.Reset()
i = 0
while iterator.MoveNext():
line = iterator.Current
ftprintRoof.set_DefinesSlope( line, True )
if i == 0:
ftprintRoof.set_SlopeAngle( line, 0.2 )
i = i + 1
else:
ftprintRoof.set_SlopeAngle( line, 0.6 )
i = i + 1
alllines.append(line)
#The value is a "slope" measurement. For example, 0.5 is one unit of rise for each 2 units of run.
#This creates a slope of 26.57 degrees (the arctangent of 0.5).
OUT = footprintRoof.ToDSType(False), roofCurves.Value, ftprintRoof,alllines
Mind that the SlopeAngle is actually powered as follows according to the API: The value is a “slope” measurement. For example, 0.5 is one unit of rise for each 2 units of run. This creates a slope of 26.57 degrees (the arctangent of 0.5). http://www.revitapidocs.com/2018.1/4d58f862-472b-0cc1-a250-5ed1100911d9.htm
@Jonathan.Olesen that’s fantastic, thank you… I just added an input so that @TeoBlack can work out a way of defining which he wants sloped…
Would you mind saying a little about why an iterator is required here? It somehow allows you to iterate over a ModelCurveArray? It would be easier if we could use an enumerator so we could get an index, but that fails? Google isn’t giving me any answers I’m afraid
i = 0
j = IN[3]
while iterator.MoveNext():
line = iterator.Current
ftprintRoof.set_DefinesSlope( line, True )
if i == j:
ftprintRoof.set_SlopeAngle( line, 0.2 )
i = i + 1
else:
ftprintRoof.set_SlopeAngle( line, 0.6 )
i = i + 1
alllines.append(line)
I’m not sure I can give you a concrete answer on the iterator method…
What I can say is that it has to do with working with the ModelCurveArray (Which is in fact model curves as can be seen in List 3 in my screenshot.) But for an in depth description I have to refer to @Dimitar_Venkov who might be able to better explain
(Mind this is the first time I have ever worked with RoofSlopes and generally not doing a lot atm with the Revit API )
I am going to try my best but I could be horribly wrong. Please someone with more knowledge can clarify any mistakes I made:
To understand why the iterator.MoveNext() is required, you have to go back through all of the commands, starting here: roofCurves = StrongBox[ModelCurveArray](ModelCurveArray() )
This gives you an object of class ModelCurveArray. With a Revit type of array, there is a built in class for moving through each item inside of it, better than a for loop. That class is called using the method .ForwardIterator(), which is called for in this line: iterator = roofCurves.ForwardIterator()
All this to say why use .MoveNext(): The method basically is a ‘if another item in the list is possible, continue with the function using the next item. If it is not possible, return false, thus ending the while loop’. In a way, it is like a built in while loop using try: #function, except IndexError: break.
It is better than a for loop because you do not need to specify a length nor an iteration variable, as the property .Current acts as the i in for i in array:
It is basically a Revit version of python commands built into the class, I think.
I was trying it in Revit 2016 and it were giving me errors and couldn’t run the script, now I’ve tried in 2019 and it works. thanks a lot Gentleman.
now I will try to make it work in 2016 with 1.3 dynamo.
Thanks again for help