Set Crop View automatically

Hello everyone,

I have a script that creates a 3D model of a metallic structure, creates section views of certain areas (and duplicates the default 3D View) of the model, sets the scale according to the sheet size and inserts them into the created sheets. It then proceeds to export the sheets into a PDF file using PDFCreator.

However, a part of the 3D model ends up being cropped out of the viewport in the duplicate 3D View (as shown bellow - the Crop View is visible):

Is there a way of setting up the Crop View automatically in a way where the 3D model isn’t cropped?

All files are available bellow for your criticism and any improvement (even regarding other topics) is welcome:
bars.xlsx (57.5 KB)
nodes.xlsx (30.1 KB)
structureV24.dyn (2.4 MB)
Template.rvt (3.3 MB)

Hi,
an example using Python and Elements’s Boudingbox

crop 3D View

import clr
import sys
import System
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS

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

#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

def get_Global_Middle(all_bbx):
	"""
	# get middle point of global BBX
	"""
	minX = min([bbx.Min.X for bbx in all_bbx])
	minY = min([bbx.Min.Y for bbx in all_bbx])
	minZ = min([bbx.Min.Z for bbx in all_bbx])
	#
	maxX = max([bbx.Max.X for bbx in all_bbx])
	maxY = max([bbx.Max.Y for bbx in all_bbx])
	maxZ = max([bbx.Max.Z for bbx in all_bbx])
	return XYZ((minX + maxX) / 2, (minY + maxY) / 2, (minZ + maxZ) / 2 )
	
def toList(x):
	if isinstance(x, list):
		return x
	elif hasattr(x, "GetType") and x.GetType().GetInterface("IEnumerable") is not None:
		return x
	else :
		return [x]
#Preparing input from dynamo to revit
lstElems = toList(UnwrapElement(IN[0]))
view = UnwrapElement(IN[1])
margin = 8
lstTfPts = []
lstBBx = []

#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
tfView = view.CropBox.Transform.Inverse
for elem in lstElems:
	bbxElemB = elem.get_BoundingBox(view)
	lstBBx.append(bbxElemB)
	pt1 = tfView.OfPoint(bbxElemB.Min)
	pt2 = tfView.OfPoint(bbxElemB.Max)
	pt3 = tfView.OfPoint(XYZ(bbxElemB.Min.X, bbxElemB.Max.Y, 0))
	pt4 = tfView.OfPoint(XYZ(bbxElemB.Max.X, bbxElemB.Min.Y, 0))
	lstTfPts.extend([pt1, pt2, pt3, pt4])
	
# get min max coordinate from transform points
minX = min(lstTfPts, key = lambda p : p.X).X
minY = min(lstTfPts, key = lambda p : p.Y).Y
maxX = max(lstTfPts, key = lambda p : p.X).X
maxY = max(lstTfPts, key = lambda p : p.Y).Y
# set a new Transform
t = Transform.Identity
t.Origin = get_Global_Middle(lstBBx)
t.BasisX = tfView.BasisX
t.BasisY = tfView.BasisY
t.BasisZ = tfView.BasisZ
# set a new BBX
newBox = BoundingBoxXYZ()
newBox.Enabled = True
newBox.Min =  XYZ(minX - margin, minY - margin, -10000)
newBox.Max =  XYZ(maxX + margin, maxY + margin, -0.10)
newBox.Transform = t
view.CropBox = newBox

TransactionManager.Instance.TransactionTaskDone()

OUT = view
3 Likes

Hello and thank you for your reply,

I have tested your code and the following error message appears:

From what I understood, the Y value of the minimum point is not being retrieved or is a null value. What can be causing this?

Also, the updated .dyn file is attached bellow since the script is enormous. I’d upload a print of it but it would lose quality.

structureV24.dyn (2.4 MB)

Update:

I did some digging up and got to the cause of the issue:
I think that the toList function is returning null. Maybe the values in the list I tried to insert weren’t correct (picture bellow)

I have tried with all the elements in the active view but it returned the same warning. Any suggestions of what is the issue here?

Updated .dyn file:
structureV24.dyn (2.4 MB)

Hi,
try this one

import clr
import sys
import System
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS

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

#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

def get_Global_Middle(all_bbx):
	"""
	# get middle point of global BBX
	"""
	minX = min([bbx.Min.X for bbx in all_bbx])
	minY = min([bbx.Min.Y for bbx in all_bbx])
	minZ = min([bbx.Min.Z for bbx in all_bbx])
	#
	maxX = max([bbx.Max.X for bbx in all_bbx])
	maxY = max([bbx.Max.Y for bbx in all_bbx])
	maxZ = max([bbx.Max.Z for bbx in all_bbx])
	return XYZ((minX + maxX) / 2, (minY + maxY) / 2, (minZ + maxZ) / 2 )
	
def toList(x):
	if isinstance(x, list):
		return x
	elif hasattr(x, "GetType") and x.GetType().GetInterface("IEnumerable") is not None:
		return x
	else :
		return [x]
#Preparing input from dynamo to revit
lstElems = toList(UnwrapElement(IN[0]))
view = UnwrapElement(IN[1])
margin = 8
lstTfPts = []
lstBBx = []

#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
tfView = view.CropBox.Transform.Inverse
for elem in lstElems:
	bbxElemB = elem.get_BoundingBox(view)
	if bbxElemB is not None:
		lstBBx.append(bbxElemB)
		pt1 = tfView.OfPoint(bbxElemB.Min)
		pt2 = tfView.OfPoint(bbxElemB.Max)
		pt3 = tfView.OfPoint(XYZ(bbxElemB.Min.X, bbxElemB.Max.Y, 0))
		pt4 = tfView.OfPoint(XYZ(bbxElemB.Max.X, bbxElemB.Min.Y, 0))
		lstTfPts.extend([pt1, pt2, pt3, pt4])
	
# get min max coordinate from transform points
minX = min(lstTfPts, key = lambda p : p.X).X
minY = min(lstTfPts, key = lambda p : p.Y).Y
maxX = max(lstTfPts, key = lambda p : p.X).X
maxY = max(lstTfPts, key = lambda p : p.Y).Y
# set a new Transform
t = Transform.Identity
t.Origin = get_Global_Middle(lstBBx)
t.BasisX = tfView.BasisX
t.BasisY = tfView.BasisY
t.BasisZ = tfView.BasisZ
# set a new BBX
newBox = BoundingBoxXYZ()
newBox.Enabled = True
newBox.Min =  XYZ(minX - margin, minY - margin, -10000)
newBox.Max =  XYZ(maxX + margin, maxY + margin, -0.10)
newBox.Transform = t
view.CropBox = newBox

TransactionManager.Instance.TransactionTaskDone()

OUT = view

If bug persist, can you share a sample rvt file (here or in PM) ?

1 Like

Hello again,

I implemented your code and ran the script. There was a different error this time but I think it’s related to the same issue as before (picture bellow)

Also, in the original post, there’s the .rvt file I’m currently using for testing and the Excel sheets with the reference point coordinates and the material types used for the creation of the structure. The only different file is the .dyn file (which is attached bellow)
structureV24.dyn (2.4 MB)

your script does not work well for me, the script generates beams with a very very large distance

That’s strange. What version of Revit are you using? The version I am using is Revit 2020

Revit 2022 ENG

I think that the code you provided works on Revit 2020 since the script did run. Maybe the issue here lies in the reference points of the beams or in the material family type

Same in Revit 2020

hence my request for your rvt file with the structure made

Oh okay. I’m really sorry for my misunderstanding

Here’s the rvt file with the assembled structure:
Template.rvt (5.4 MB)

Hope this helps :slight_smile:

the error comes because there are no elements in the input IN[0]

try this way

set CropBox in 3DView.dyn (9.3 KB)

Hello again and thank you for your patience.

I’ve implemented the code you shared on your 2nd picture. However, the error remains the same (picture bellow)

What am I doing wrong? Do I need to create a custom node?
Again, thank you for your patience

Strange … works for me

Test CropView

Are you tried my dyn in my previous post ? (file attached)

1 Like

Hello again,

Yes, I have tried it and still the same error.
Can it be because it’s trying to do that inside the same transaction?

try to add a transaction End node

2 Likes

You are a life saver, thank you so much!

1 Like

I will try this! Getting back to you soon.