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.
1 Like
thanks again, I’ll try it and see what happens
1 Like
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)