I’ve inherited some legacy python from a previous dev.
Fortunately, they have left a link to the original blog post that was used as a starting point.
But I think I’m hitting a syntax error in the parts they tried to modify.
Specifically at line 96 its saying index is occupied or out of range
https://learndynamo.com/mod2/
#Copyright(c) 2016 www.Learndynamo.com
#Please contact at jeremy@learndynamo.com
import clr
clr.AddReference('RevitAPI')
clr.AddReference("RevitServices")
clr.AddReference("RevitNodes")
import RevitServices
import Revit
import Autodesk
from Autodesk.Revit.DB import *
import math
from math import *
clr.ImportExtensions(Revit.GeometryConversion)
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
toggle = IN[0]
point = UnwrapElement(IN[1])
modelPoints = UnwrapElement(IN[2])
cropCurves = UnwrapElement(IN[3])
viewType = UnwrapElement(IN[4])
lst = []
#Get Family View Type
vft = 0
collector = FilteredElementCollector(doc).OfClass(ViewFamilyType).ToElements()
#eleViews = []
for i in collector:
if i.ViewFamily == ViewFamily.Elevation:
vft = i.Id
break
if toggle == True:
TransactionManager.Instance.EnsureInTransaction(doc)
#Retrieve the mid point of model lines and get X,Y.
index = 0
for modelpoint in modelPoints:
modelMP = modelpoint.ToXyz()
modelMPX = modelMP.X
modelMPY = modelMP.Y
#Retrieve individual lines of crop window.
cropLines = cropCurves[index]
l1 = cropLines[0].ToRevitType()
l2 = cropLines[1].ToRevitType()
l3 = cropLines[2].ToRevitType()
l4 = cropLines[3].ToRevitType()
# Create a line in the z-Axis for elevation marker to rotate around.
elevationPT = point[index].ToXyz()
elptRotate = XYZ(elevationPT.X, elevationPT.Y, elevationPT.Z+100)
ln = Line.CreateBound(elevationPT, elptRotate)
#Calculate the angle between Model Mid Point and Elevation Point.
elevationPTY = elevationPT.Y
elevationPTX = elevationPT.X
#combY = elevationPTY-modelMPY
#combX = elevationPTX-modelMPX
combY = modelMPY-elevationPTY
combX = modelMPX-elevationPTX
ang = -atan2(combX, combY)
comparisonAng = round(degrees(ang))
newAng = 90
arrowPos = 2
eleMarker = ElevationMarker.CreateElevationMarker(doc, viewType.Id, elevationPT, 100)
#left arrow
if comparisonAng >= 45 and comparisonAng <= 135:
arrowPos = 0
newAng = -90
#top arrow
#changed <= to < august 5th 2021
if comparisonAng <= 45 and comparisonAng > -45:
arrowPos = 1
newAng = 0
#bottom arrow
if comparisonAng > 135 or comparisonAng < -135:
arrowPos = 3
ang = ang + radians(90)
#default is right arrow
ele = eleMarker.CreateElevation(doc, doc.ActiveView.Id, arrowPos)
ElementTransformUtils.RotateElement(doc, eleMarker.Id, ln, ang)
ElementTransformUtils.RotateElement(doc, eleMarker.Id, ln, radians(newAng))
#ElementTransformUtils.RotateElement(doc, eleMarker.Id, ln, ang)
#Create elevation marker and elevation in position 0.
#Rotate elevation marker towars model line.
#ElementTransformUtils.RotateElement(doc, eleMarker.Id, ln, math.radians(90))
#
crManager = ele.GetCropRegionShapeManager()
#crShape = crManager.GetCropRegionShape()
newCurveLoop = []
newCurveLoop.Add(l1)
newCurveLoop.Add(l2)
newCurveLoop.Add(l3)
newCurveLoop.Add(l4)
cLoop = CurveLoop.Create(newCurveLoop)
index+=1
try:
crManager.SetCropShape(cLoop)
lst.append(ele)
#lst.append("Elevation Created")
except:
pass
lst.append("Missed Elevation")
TransactionManager.Instance.TransactionTaskDone()
#OUT = degrees(ang)
OUT = lst
else:
OUT = "Set toggle to TRUE"
Can you share a stripped down Revit model with the items need to run the script?
I’ve yet to try to create an Elevation via the API, but so far as I can tell this seems like it should be working. My best guess at the moment, is that ElevationMakers are built with a default direction, so the index value for that direction is inherently occupied. So when you try to create a new elevation using that index, it throws an error.
This is relatively easy to test for. Can you run this and tell me what the python node outputs?
#Copyright(c) 2016 www.Learndynamo.com
#Please contact at jeremy@learndynamo.com
import clr
clr.AddReference('RevitAPI')
clr.AddReference("RevitServices")
clr.AddReference("RevitNodes")
import RevitServices
import Revit
import Autodesk
from Autodesk.Revit.DB import *
import math
from math import *
clr.ImportExtensions(Revit.GeometryConversion)
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
toggle = IN[0]
point = UnwrapElement(IN[1])
modelPoints = UnwrapElement(IN[2])
cropCurves = UnwrapElement(IN[3])
viewType = UnwrapElement(IN[4])
lst = []
#Get Family View Type
vft = 0
collector = FilteredElementCollector(doc).OfClass(ViewFamilyType).ToElements()
#eleViews = []
for i in collector:
if i.ViewFamily == ViewFamily.Elevation:
vft = i.Id
break
if toggle == True:
TransactionManager.Instance.EnsureInTransaction(doc)
#Retrieve the mid point of model lines and get X,Y.
index = 0
for modelpoint in modelPoints:
modelMP = modelpoint.ToXyz()
modelMPX = modelMP.X
modelMPY = modelMP.Y
#Retrieve individual lines of crop window.
cropLines = cropCurves[index]
l1 = cropLines[0].ToRevitType()
l2 = cropLines[1].ToRevitType()
l3 = cropLines[2].ToRevitType()
l4 = cropLines[3].ToRevitType()
# Create a line in the z-Axis for elevation marker to rotate around.
elevationPT = point[index].ToXyz()
elptRotate = XYZ(elevationPT.X, elevationPT.Y, elevationPT.Z+100)
ln = Line.CreateBound(elevationPT, elptRotate)
#Calculate the angle between Model Mid Point and Elevation Point.
elevationPTY = elevationPT.Y
elevationPTX = elevationPT.X
#combY = elevationPTY-modelMPY
#combX = elevationPTX-modelMPX
combY = modelMPY-elevationPTY
combX = modelMPX-elevationPTX
ang = -atan2(combX, combY)
comparisonAng = round(degrees(ang))
newAng = 90
arrowPos = 2
eleMarker = ElevationMarker.CreateElevationMarker(doc, viewType.Id, elevationPT, 100)
OUT = eleMarker.HasElevations(), [eleMarker.IsAvailableIndex(x) for x in range(4)]
else:
OUT = "Set toggle to TRUE"
@stewart.skyler
I think that would support your hypothesis, no?
So I guess my next step is trying to figure out how to over write the default value of the elevation marker?
Huh. Yes and no, I was anticipating that first result to be true as well, if any of the items in the following list were. The thought being that it’s creating a default elevation and that’s why one of the indices is unavailable.
Taking another look, maybe ElevationMarkers can hold view types other than elevations, and your variable viewType holds a View Type other than an elevation. If you swap eleMarker.HasElevations() with eleMarker.CurrentViewCount does that come up with a number larger than 0?
If this is the case then yeah, I think the next step would be to check if the index is in use, and if so delete that view and create a new one.
I don’t see a convenient way to retrieve that via it’s members in the API docs.
But what might work is using a FilteredElementCollector with an ElementWorksetFilter.
fil = FilteredElementCollector(doc)
workset_filter = ElementWorksetFilter(eleMarker.WorksetId)
views = fil.OfClass(View).WherePasses(workset_filter).ToElements()
Note that I haven’t tested that bit of code, but I think it should work.
Edit:
Slight change to the FilterdElementCollector so that it only returns views.
thanks again, I’ll try it and see what happens
as far as minimal model, the original blog post just uses a loop of model lines. I’ve added a wall with some windows, because the elevations looked really bland. Then I added a loop of curtain walls, because I know in the end that’s what I’m working toward.
I’ll see if I can get a basic version of the core graph too
I’ve been digesting it by the sections from his original writing
ModuleTwo.rvt (5.0 MB)