Modify CropBox of Elevation View


#1

Hi,

I’m hoping someone can give me some advice on manipulating the Cropbox of a view.

In essence from the View Class the CropBox can be obtained, and then from that the BoundingBoxXYZ class can be obtained which has Min and Max properties which define the extents of the views Crop.

Min is the Upper left corner in plan (lower level)
Max is the Lower right corner in plan (Upper level).

This screen grab shows two red lines which are what I want to set the Crop to, along with the Min and Max point coordinates:

My Python code which runs in Dynamo inputs the Crop coordinates as number nodes and runs a Python script:

Note that for the code to work the Elevation View created has to be called ‘TEST’.

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

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

from math import atan2, radians, cos, sin, degrees

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager

import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
adoc = doc.ActiveView

#The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN

##For this routine to work you need to create an Elevation view called 'TEST'

#Get all views and find the one called 'TEST'
allViews = FilteredElementCollector(doc).OfClass(View).ToElements()

viewtopick = "TEST"

for f in allViews:
    if f.Name == "TEST":
        viewtouse = f


#Change the Min value of the crop box of view 'TEST'
t = Transaction(doc, "Update cropbox")
t.Start()

#Get View cropbox
viewcropbox = viewtouse.CropBox

#Create a new Bounding Box
newbox = BoundingBoxXYZ()

wallstartx = IN[1]
wallstarty = IN[2]
wallstartz = IN[3]

wallendx = IN[4]
wallendy = IN[5]
wallendz = IN[6]

#Get the min and max values of existing view's Cropbox
exmincb = viewcropbox.Min
exmaxcb = viewcropbox.Max

newmincp = XYZ(wallstartx, wallstarty, wallstartz)
newmaxcp = XYZ(wallendx, wallendy, wallendz)

#Set the min and Max values of BoundingBox
newbox.Min = viewcropbox.Transform.Inverse.OfPoint(newmincp)
newbox.Max = viewcropbox.Transform.Inverse.OfPoint(newmaxcp)

viewtouse.CropBox = newbox


t.Commit()

#Assign your output to the OUT variable.
OUT = ["Cropbox existing:",exmincb, exmaxcb, "New Cropbox pre trans:", newmincp, newmaxcp, "New Cropbox post trans:", newbox.Min, newbox.Max]

The problem is that it doesn’t set the CropBox as expected, it reverses it flipping it the other way:

I can’t see whats going wrong, the coordinates I’m using are exactly the same when I manually move the CropBox to the position I want and report them.

Any help would be appreciated.


#2

Hi,
Should output look like this?


#3

Its easier to check the elevation marker to see if its lined up with the red lines, it should look like this:

I added the output to the watch node so that I could manually check the coordinates in Revit.

I’ve shared the Revit file on my Gdrive if you want to take a look.

https://drive.google.com/file/d/0Bw4srQjbibR0elVYY1JEbmtVLXc/view?usp=sharing

Thanks for your response.


#4

OK, something is definitely going wrong here.

I modified to code to simply obtain the Cropbox Min and Max values of the existing view, and then create a new Cropbox with the existing Min and Max values and assign it back to the same view.

In other words - I’m setting the view with the same settings and so nothing should change.

#For this to work you need an Elevation View called 'TEST;
#Get all views and find the one called 'TEST'
allViews = FilteredElementCollector(doc).OfClass(View).ToElements()

viewtopick = "TEST"

for f in allViews:
	if f.Name == "TEST":
		viewtouse = f


#Change the Min value of the crop box of view 'TEST'
t = Transaction(doc, "Update cropbox")
t.Start()

#Get View cropbox
viewcropbox = viewtouse.CropBox

#Create a new Bounding Box
newbox = BoundingBoxXYZ()

#Get the min and max values of existing view's Cropbox
exmincb = viewcropbox.Min
exmaxcb = viewcropbox.Max

#Set the min and Max values of BoundingBox to the same as the old values
newbox.Min = exmincb
newbox.Max = exmaxcb

viewtouse.CropBox = newbox

t.Commit()

#Assign your output to the OUT variable.
OUT = ["Cropbox existing:",exmincb, exmaxcb, newbox]

But it does!

If I run the code, the view box flips, when I run it again it flips back again:

Original:

Run once:

Run again:

I don’t understand why this is happening, Perhaps its a bug? I don’t see why setting the View crop with the same settings as its currently using is changing anything??


#5

I’ve found the answer to this.

Annoyingly, its a bug. This has only just been fixed in Revit 2017 (taken several years to do that).

Theres a write up on it here:

http://forums.autodesk.com/t5/revit-api/modify-cropbox-of-elevation-view/td-p/3604982

Really disappointing…


#6

Hi @Kevin_Bell

I’ve been messing around with your cropbox python code and it’s quite interesting. I’m using Revit 2017.2.

The “set crop box” code works fine when using it with a Plan view (I don’t know what the Z changes here!) and I can move the sliders and see the crop region changing in real time.

However, using an Elevation view always returns an Exception: box is empty in the Python “set cropbox” script . My guess is that maybe the XYZ axis are not the same in Plan and Elevation?

I’ve check the cropbox min and max points with revit LookUp addin and set the same numbers but still get an empty box (even if using the actual Revit values).

Don’t know if this helps…