Rotate crop box of multiple views

Hi

I’m trying to rotate a list of views based on a list of rotations (in degrees) by modifying the code in this post. @Konrad_K_Sobon @Mark.Ackerley @Dimitar_Venkov

This is what I have but I am getting an error “unexpected token ‘v’”

import clr

clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

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

rot = IN[0]
viewports = UnwrapElement(IN[1])

def GetViewCropBoxElement(view):
	doc = DocumentManager.Instance.CurrentDBDocument
	TransactionManager.Instance.ForceCloseTransaction()
	tGroup = TransactionGroup(doc, "Temp to find crop box element")
	tGroup.Start()
	trans1 = Transaction(doc, "Temp to find crop box element")
	trans1.Start()
	view.CropBoxVisible = False
	trans1.Commit()
	
	shownElems = FilteredElementCollector(doc, view.Id).ToElementIds()
	
	trans1.Start()
	view.CropBoxVisible = True
	trans1.Commit()
	
	cropBoxElement = FilteredElementCollector(doc, view.Id).Excluding(shownElems).FirstElement()
	tGroup.RollBack()
	return cropBoxElement
	
def RotateCropBox(view, cropBox, angle):
    doc = DocumentManager.Instance.CurrentDBDocument
    bbox = view.CropBox
    center = 0.5 * (bbox.Max + bbox.Min)
    axis = Line.CreateBound(center, center + XYZ.BasisZ)
    TransactionManager.Instance.EnsureInTransaction(doc)
    ElementTransformUtils.RotateElement(doc, cropBox.Id, axis, angle)
    TransactionManager.Instance.TransactionTaskDone()
    return view

For v in viewports:
   	crpbx = GetViewCropBoxElement(v)
    crpbxRt = RotateCropBox(v, crpbx, rot)

OUT = crpbxRt

Any ideas?

Thanks

503_View rotation.dyn (8.5 KB)

1 Like

Can you try instead ? for v in viewports:
(For in lowercase )

import clr

clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

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

rot = IN[0]
viewports = UnwrapElement(IN[1])

def GetViewCropBoxElement(view):
	doc = DocumentManager.Instance.CurrentDBDocument
	TransactionManager.Instance.ForceCloseTransaction()
	tGroup = TransactionGroup(doc, "Temp to find crop box element")
	tGroup.Start()
	trans1 = Transaction(doc, "Temp to find crop box element")
	trans1.Start()
	view.CropBoxVisible = False
	trans1.Commit()
	
	shownElems = FilteredElementCollector(doc, view.Id).ToElementIds()
	
	trans1.Start()
	view.CropBoxVisible = True
	trans1.Commit()
	
	cropBoxElement = FilteredElementCollector(doc, view.Id).Excluding(shownElems).FirstElement()
	tGroup.RollBack()
	return cropBoxElement
	
def RotateCropBox(view, cropBox, angle):
    doc = DocumentManager.Instance.CurrentDBDocument
    bbox = view.CropBox
    center = 0.5 * (bbox.Max + bbox.Min)
    axis = Line.CreateBound(center, center + XYZ.BasisZ)
    TransactionManager.Instance.EnsureInTransaction(doc)
    ElementTransformUtils.RotateElement(doc, cropBox.Id, axis, angle)
    TransactionManager.Instance.TransactionTaskDone()
    return view

for v in viewports:
   	crpbx = GetViewCropBoxElement(v)
    crpbxRt = RotateCropBox(v, crpbx, rot)

OUT = crpbxRt
2 Likes

Thanks. That fixed that error but now I get:

File “”, line 46, in
File “”, line 40, in RotateCropBox
TypeError: expected float, got list

Any ideas how to fix? I believe it is because I am feeding in a list of angles (which should actually be in radians).

Hey, sorry I can’t check it right now, but I would maybe try a zip rather than for…? So you’re iterating through both lists together? Something like…

for v, r in zip(viewports, rot):
   	crpbx = GetViewCropBoxElement(v)
    crpbxRt = RotateCropBox(v, crpbx, r)

Hopefully that is helpful :slight_smile:

Mark

2 Likes

Thanks @Mark.Ackerley. Yep that was pretty much it. Just had to append the output…

import clr

clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

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

#rotations to be in radians
rot = UnwrapElement(IN[0])
viewports = UnwrapElement(IN[1])
views = []

def GetViewCropBoxElement(view):
	doc = DocumentManager.Instance.CurrentDBDocument
	TransactionManager.Instance.ForceCloseTransaction()
	tGroup = TransactionGroup(doc, "Temp to find crop box element")
	tGroup.Start()
	trans1 = Transaction(doc, "Temp to find crop box element")
	trans1.Start()
	view.CropBoxVisible = False
	trans1.Commit()
	
	shownElems = FilteredElementCollector(doc, view.Id).ToElementIds()
	
	trans1.Start()
	view.CropBoxVisible = True
	trans1.Commit()
	
	cropBoxElement = FilteredElementCollector(doc, view.Id).Excluding(shownElems).FirstElement()
	tGroup.RollBack()
	return cropBoxElement
	
def RotateCropBox(view, cropBox, angle):
    doc = DocumentManager.Instance.CurrentDBDocument
    bbox = view.CropBox
    center = 0.5 * (bbox.Max + bbox.Min)
    axis = Line.CreateBound(center, center + XYZ.BasisZ)
    TransactionManager.Instance.EnsureInTransaction(doc)
    ElementTransformUtils.RotateElement(doc, cropBox.Id, axis, angle)
    TransactionManager.Instance.TransactionTaskDone()
    return view
    
for v, r in zip(viewports, rot):
	crpbx = GetViewCropBoxElement(v)
	crpbxRt = RotateCropBox(v, crpbx, r)
	views.append(crpbxRt)

OUT = views
5 Likes

Thanks for the Python @Paul_Wintour . But i don’t get the expected rotation.
Can you explain what i am missing?

EDIT
Solved! I totally missed

awesome, it works perfectly.
I am just wondering how to change “for” to make the list writing with same number of angles ?
like i want to rotate all my views for .26 radiant, but i dont have to create a list of the same number repeating itself.

Hey,

I guess you mean this bit?

for v, r in zip(viewports, rot):
    crpbx = GetViewCropBoxElement(v)
    crpbxRt = RotateCropBox(v, crpbx, r)
    views.append(crpbxRt)
    OUT = views

you can replace it with this… (untested!)

for r in (rot):
    crpbx=GetViewCropBoxElement(view)
    crpbxRt = RotateCropBox(view, crpbx, r)
    views.append(crpbxRt)
    OUT = views

Hopefully that’s right :wink:

Mark

I don’t think repeat r would be the case. I think we should repeat append views in the list with the same “rot”

Hey, yes you’re right, my bad, but you get the idea… ‘for’ instead of ‘zip’ :slight_smile:

Has anyone gotten this to work for rotating the section boxes? I came across this post and this one by Jeremy, but I have been unable to get the section box to actually rotate the way that I need it to.

What goes wrong?

Hi!
I’m trying to rotate a view and the crop box (by selecting a wall and getting the angle between this and a 0,1,0 vector) I’ve tried this python code but it gives me an error:

The code in this post works partially, rotates the view but not the crop box…

Any ideas?? Thanks!!

Anybody? Please!!
@Konrad_K_Sobon @Mark.Ackerley @Alban_de_Chasteigner

Any help will be much appreciated!!

Hi,

The warning is telling you that you can’t iterate over the view… This means it is expecting a list (mostly), so if you add a ‘create list’ before you feed into IN[1] it will help matters. If you could post your .dyn it would make it easier to debug :slight_smile:

I suspect the problem you are getting in other post is because you have a custom crop box, i’m not sure they obey the same commands. To test, if you click on it in Revit and ‘reset’ (a button on the top ribbon on the right), you can re-run the python. I don’t know if there is a way to edit the sketch lines of the crop box.

Hope that is useful,

Mark

RotaciónVistas0.1.dyn (34.9 KB)
Thanks Mark for replying! You are right, addind a List.Create before the python node worked (for both inputs), but the crop region is not rotating. I’m still very noob at python.

The crop region is created automatically with another script I created before, which creates a cropped view for each flat type present in the model. There are different buildings with different angles, so some flats are not north-orientated. So I need the view and the region rotates together to be vertical…

I think there must be a way to do this, because in the other script I said, I had a node (Rhythm or archilab Package) that creates the crop region…

Is there a way to do it without all the Transaction Starts and Commits, etc.? I am doing it to hundreds of views and want to optimize speed.

I tried to remove them in def GetViewCropBoxElement but it didn’t work. The script does work as is, thank you.