Drafting View Crop adjust to elements in view

This might not he possible (But should be!!!) Trying to (re)Set drafting crop regions to tight in around elements in drafting view. The Python is intended for later introduction into PyRevit, so now everything is in one Python module.

Sometimes drafting views extents far exceed the actual contents.
(WARNING: Playing with the CropBoundary TRUE/FALSE is what “Blew out” the limits for the drafting views in the first place; hence the REVIT 22 source data attached : )

Sometimes like in this example there is “dead” space (RED FILL (5-7) Below)

image

Running the script doesn’t expand or contract the extent of the limits (RED DASHED LINES 1-4 above)

I wasn’t sure if min/max would take a “None” at the start - So the minPt and maxPt DEF() may not be needed.

The Limits of the bb crop are ‘stuck’ at (-100,-100,-100) and (100,100,100). Not sure but does the /BoundingBoxXYZ return the element or the view bounding???

[
  [
    (-100.000000000, -100.000000000, -100.000000000),
    (100.000000000, 100.000000000, 100.000000000),
    [
      [
        Detail Lines,
        Autodesk.Revit.DB.BoundingBoxXYZ,
        (-100.000000000, -100.000000000, -100.000000000),
        (100.000000000, 100.000000000, 100.000000000)
      ],
      [
....

PYTHON module:

import sys                                      ##Standard system input
import clr
##https://gist.github.com/gtalarico/e6be055472dfcb6f597e3dcd20d11f37
from Autodesk.Revit.DB import FilteredElementCollector

#import Revit
#clr.AddReference('RevitAPI')
#clr.ImportExtensions(Revit.GeometryConversion)

import RevitServices


from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
#  Drafting Views
from Autodesk.Revit.DB import BuiltInCategory, BuiltInParameter
from Autodesk.Revit.DB import ViewFamilyType, ViewDrafting, Element
from Autodesk.Revit.DB import ViewFamily
from Autodesk.Revit.DB import Transaction, TransactionGroup, BoundingBoxXYZ
###Creates a Drafting View###
from Autodesk.Revit.DB import Transaction, Element, ElementTransformUtils
##https://forum.dynamobim.com/t/collecting-all-elements-of-family-types-in-active-view/19838/2
from Autodesk.Revit.DB import BuiltInCategory, BuiltInParameter

# ViewFamilyTypes and Drafting views creation 
from Autodesk.Revit.DB import ViewFamilyType, ViewDrafting, Element
from Autodesk.Revit.DB import ViewFamily

import System                                   ##filterAnnot = System.Predicate  <<Work on removing         
from System.Collections.Generic import List     ##Not same as type() = List       <<Work on removing 

import math                                     ##For truncate to integer-RA
import re                                       ##Regular expressions for 'natural' sort

from itertools import groupby
#from Autodesk.Revit.DB import *
from Autodesk.Revit.DB import FamilySymbol, FamilyInstance, XYZ, AnnotationSymbol

doc = DocumentManager.Instance.CurrentDBDocument
uidoc=DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument

##Likely View Families for View Types REFERENCE
ViewTypeArray=["AreaPlan","CeilingPlan","CostReport","Detail","Drafting","Elevation","FloorPlan", "GraphicalColumnSchedule",
    "Legend", "LoadsReport", "PanelSchedule", "PressureLossReport", "Schedule", "Section", "Sheet", "StructuralPlan",
    "SystemsAnalysisReport", "ThreeDimensional","Walkthrough"
   ];

def GetDraftingViews():
    ##https://forums.autodesk.com/t5/revit-api-forum/view3d-collector/td-p/5277451
    DraftingViewsList = FilteredElementCollector(doc).OfClass(ViewDrafting).ToElements()
    ##DraftingViewTemplates = [v.Id for v in DraftingViewsList if v.IsTemplate == True]
    DraftingViewsList = [v for v in DraftingViewsList if v.IsTemplate == False]
    return DraftingViewsList

def GetElementsInView(oView):
    OUT=[]
    cats = doc.Settings.Categories       ##https://forum.dynamobim.com/t/get-all-elements-of-category/65314/4
    for cat in cats:
        bic = System.Enum.ToObject(BuiltInCategory, cat.Id.IntegerValue)
        filtered =FilteredElementCollector(doc,oView.Id).OfCategory(bic).ToElements()
        if filtered:
           OUT.extend(filtered)
    return OUT
 
def CropViews (views):
    ##Transaction tools https://forum.dynamobim.com/t/naming-dynamo-transactions-in-revit/21149/5
    tGroup = TransactionGroup(doc, 'Dynamo View Crop')
    
    tGroup.Start()
    
    for DV in dviews:
        trans1 = Transaction(doc, 'Crop View')
        
        trans1.Start()
        
        oView.CropBox = DV[1][55].BoundingBox(DV[0]) 
        
        trans1.Commit()
    
    tGroup.Commit()

def MinPt(pt1,pt2):              #############Return minimum of 2 points
    if pt1==None:
        return pt2
    if pt1[0] < pt2[0] or pt1[1] < pt2[1] or pt1[2] < pt2 [2]:
        return pt1
    else:
        return pt2
    ##If one is null- return non-null
    ##IF any X or Y or Z is LESS  than than pt1  X or Yor Z, return it
    
def MaxPt(pt1,pt2):              #############Return max of 2 points
    if pt1==None:
        return pt2
    if pt1[0] > pt2[0] or pt1[1]  >pt2[1] or pt1[2] > pt2[2]:
        return pt1
    else:
        return pt2
    ##If one is null- return non-null
    ##IF any X or Y or Z is LESS  than than pt1  X or Yor Z, return it
    ##If one is null- return non-null
    ##IF any X or Y or Z is GREATER than than pt1  X or Yor Z, return it

def Main():
    DraftingViews = GetDraftingViews()          ##Get drafting views
    
    dviews=[]                           ##Drafting Views lits
    aMin=None                           ##minimum point
    aMax=None                           ##Maximum point
    
    done=[]                             ##Successful
    failed=[]                           ##Failed
    
    for DV in GetDraftingViews():       ##Cycke through drafting views
        dviews.append([DV, GetElementsInView(DV)])  ##dviews DOUBL of Drafting view [elements in view]
    
    tgr=TransactionGroup(doc, 'TGR:DynamoSetDraftCrop') ##Transaction group start name
    tgr.Start()                         ##Start transaction overall wrapper name
    
    for DV in dviews:                   ##Pair of [[view][list of elements]]
   
        oView=None                      #Clear just in case
        oView=DV[0]                     ##Object View - drafting view
        elements=None                   ##clear elements just in case
        elements=DV[1]                  ##Elements portion of DV DOUBLE

        tgrtra=Transaction(doc,oView.Name)     
        tgrtra.Start()                  ##Start transactiongroup within transaction
        
        oView.CropBoxActive= False      ##Turn off crop box
        oView.CropBoxVisible = False    ##Turn off visibility
        
        for ele in elements:            ##Elements list as 2nd double in list
#            return dir(ele)            ##<<DEBUG CHECK FOR ELE TYPES
            try:                        ##TRY Set bounding box
                bb=None                 ##Set boundign box to none    
                bb=BoundingBoxXYZ(ele)  ##MIN MAX bounding- all these are the same 
                                        ##- is bounding ov vioew already In Lieu Of element?
                
                aMin=MinPt(aMin,bb.Min) ##Check MIN point and set     
                aMax=MaxPt(aMax,bb.Max) ##check MAX point and set   
                #return bb.Min
                #aMin=min(aMin,bb.Min)  ##MIN/MAX VIA Direct compare - even if aMin or aMax is nothing?   
                #aMax=max(aMax,bb.Max)  ##MIN/MAX VIA Direct compare - even if aMin or aMax is nothing?
                
                done.append([ele.Name,bb,aMin,aMax])   ##Append no-error element name, Bound box, min and max
            except:                     ##ON FAIL
 #               return type(ele),done  ##DEBUG<<<<<<<<<<<<<<<<<
                failed.append(ele.Name) ##Append to FAIL for element
                continue                ##CONTINUE with next element
        
        bb.Min=aMin                     ##Set min pt = min found
        bb.Max=aMax                     ##Sect max pt = max found
        
        #bb.Min = XYZ(-1/12,-1/12,-1/12) ##aMin test to override - DOES NOTHING<<<DEBUG
        #bb.Max = XYZ(2/12,2/12,2/12)   ###aMAX test to override - DOES NOTHING<<<DEBUG 
   
        oView.CropBox=bb                ##????<<<<CROP VIEW to BB??????
        oView.CropBoxActive= True       ##Set crop active HAS AN EFFECT
        oView.CropBoxVisible = True     ##Set visible- has no effect.
        
        tgrtra.Commit()                 ##Commit group transaction for current view : )
        
    return aMin,aMax,done,failed        ##RETURN FROM MAIN TO OUT BELOW...

############################################################
                                   ##Run Main
############################################################
#OUT=min((-1,-4,-1),(2,4,6))
OUT= Main () ##anElement.getBoundingBox(DV[0]).Min ##anElement.getBoundingBox(oView)
#

DYN Attached.
Views-Drafting-Reset-Unseen-Crop-0-60.dyn (11.7 KB)
TEST DATA REVIT attached (WARNING: Testing on actual files can “Blow out” the limits of the rafting views):
004-Test-Drafting_view_clipping.rvt (864 KB)

view.get_Parameter(BuiltInParameter.VIEWER_CROP_REGION).Set(0)

1 Like

Yeah - but no way to actually CROP the view like other views? OR “TIGHT-CROP” it?

And no effect:
[
2022-10-12(Revit) t134416 PY.GetDraftView.PY

[
DraftingView(Name = Drafting 1 ), <<OUTPUT
Autodesk.Revit.DB.Parameter <<PArameter
]
]

@jacob.small - any suggestions? Not in the API yet?

You have new Crop Region Size options once it has been turned on and placed on a sheet.

1 Like

Then you can adjust it all you want or match it to another view like this example.

1 Like

Yeah - this is going to get messy, but the ability to do this programmatically will be valuable.
2022-10-12(Revit) t142056 Crop_Region_Size

[
[
[
ByCorners,
ByCornersCoordinateSystem,
ByGeometry,
ByGeometryCoordinateSystem,
CheckArgsForAsmExtents,
ComputeHashCode,
Contains,
ContextCoordinateSystem,
Dispose,
DisposeDisplayable,
Equals,
Finalize,
GetHashCode,
GetType,
Intersection,
Intersects,
IsEmpty,
MaxPoint,
MemberwiseClone,
MinPoint,
Overloads,
ReferenceEquals,
Tags,
Tessellate,
ToCuboid,
ToPolySurface,
ToString,
call,
class,
delattr,
delitem,
dir,
doc,
enter,
eq,
exit,
format,
ge,
getattribute,
getitem,
gt,
hash,
init,
init_subclass,
iter,
le,
lt,
module,
ne,
new,
overloads,
reduce,
reduce_ex,
repr,
setattr,
setitem,
sizeof,
str,
subclasshook,
get_ContextCoordinateSystem,
get_MaxPoint,
get_MinPoint,
get_scaleFactor,
mConstructor,
scaleFactor
]
]
]

Hello @Ron_Allen probably something for crop annotation size…

2 Likes

So far this is what I have. It partly works but has issues - if anyone wants to move it forward we could all benefit.

It gathers the shapes and sets the bounding box.

bb sized right - setting the crop to bb does nothing : (

import sys                                      ##Standard system input
import clr
##https://gist.github.com/gtalarico/e6be055472dfcb6f597e3dcd20d11f37
from Autodesk.Revit.DB import FilteredElementCollector
import RevitServices

from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
#  Drafting Views
from Autodesk.Revit.DB import BuiltInCategory, BuiltInParameter
from Autodesk.Revit.DB import ViewFamilyType, ViewDrafting, Element
from Autodesk.Revit.DB import ViewFamily
from Autodesk.Revit.DB import Transaction, TransactionGroup, BoundingBoxXYZ

from Autodesk.Revit.DB import Transaction, Element, ElementTransformUtils
##https://forum.dynamobim.com/t/collecting-all-elements-of-family-types-in-active-view/19838/2
from Autodesk.Revit.DB import BuiltInCategory, BuiltInParameter

# ViewFamilyTypes and Drafting views creation 
from Autodesk.Revit.DB import ViewFamilyType, ViewDrafting, Element
from Autodesk.Revit.DB import ViewFamily

import System                                   ##filterAnnot = System.Predicate  <<Work on removing         
from System.Collections.Generic import List     ##Not same as type() = List       <<Work on removing 

import math                                     ##For truncate to integer-RA
import re                                       ##Regular expressions for 'natural' sort

from itertools import groupby
#from Autodesk.Revit.DB import *
from Autodesk.Revit.DB import FamilySymbol, FamilyInstance, XYZ, AnnotationSymbol
##############################################################################################
doc = DocumentManager.Instance.CurrentDBDocument
uidoc=DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
##############################################################################################
##Likely View Families for View Types REFERENCE
ViewTypeArray=["AreaPlan","CeilingPlan","CostReport","Detail","Drafting","Elevation","FloorPlan", "GraphicalColumnSchedule",
    "Legend", "LoadsReport", "PanelSchedule", "PressureLossReport", "Schedule", "Section", "Sheet", "StructuralPlan",
    "SystemsAnalysisReport", "ThreeDimensional","Walkthrough"
   ];
##############################################################################################
def TestBoundingBox(dviews):            ##RETURNS BOUNDING BOX
    
    oView=dviews[0][0]                  ##Object View - 1ST drafting view
    
    element=dviews[0][1][0]             ##oBJECT 1ST ELEMENT
    
    return element.get_BoundingBox(oView)
##############################################################################################
def GetDraftingViews():
    ##https://forums.autodesk.com/t5/revit-api-forum/view3d-collector/td-p/5277451
    DraftingViewsList = FilteredElementCollector(doc).OfClass(ViewDrafting).ToElements()
    ##DraftingViewTemplates = [v.Id for v in DraftingViewsList if v.IsTemplate == True] ##Retun IDs only fpr drafting view templates
    DraftingViewsList = [v for v in DraftingViewsList if v.IsTemplate == False]
    return DraftingViewsList
##############################################################################################
def GetElementsInView(oView):
    OUT=[]
    cats = doc.Settings.Categories       ##https://forum.dynamobim.com/t/get-all-elements-of-category/65314/4
    for cat in cats:
        bic = System.Enum.ToObject(BuiltInCategory, cat.Id.IntegerValue)
        filtered =FilteredElementCollector(doc,oView.Id).OfCategory(bic).ToElements()
        if filtered:
           OUT.extend(filtered)
    OUT=UnwrapElement(OUT)
    return OUT

def Get_BoundingBox_from_elements (oView,elements):                 ##Takes list pair of views and elements in views
                                            ##to set bounding
    done=["Pass"]                           ##Successful
    failed=["Fail"]                   	    ##Failed
    ele=None                                ##Revit DB Element
    
    ##dviews=UnwrapElement(dviews)          ##Unwrap - unnecessary.

    bbout = elements[0].get_BoundingBox(oView) ##Set initial bounding box

    for ele in elements:                    ##Elements list as 2nd double in list          
        try:                                ##TRY Set bounding box
            bb=None                         ##Set boundign box to none    
            bb=ele.Get_BoundingBox(None)
            
            if bbout.min > bb.Min:  
                bbout.min=bb.Min    ##Set smaller value
            if bbout.Max < bb.Max:  
                bbout.Max=bb.Max    ##Set larger value
             
            done.append([ele.Name,bb,aMin,aMax])   ##Append no-error element name, Bound box, min and max
        ##except Exception, e:        ##ON FAIL - Doesn't like tracking the exception for some reason
        except:        ##ON FAIL
            ##failed.append(type(ele))              ##DEBUG<<<<<<<<<<<<<<<<<
            failed.append(ele.Name) ##Append to FAIL for element
            continue                ##CONTINUE with next element

    return bbout                        ##REturn widest bounding box 
############################################################################################## 
#def CropViews (dviews):
#    ##Transaction tools https://forum.dynamobim.com/t/naming-dynamo-transactions-in-revit/21149/5
#    tGroup = TransactionGroup(doc, "Dynamo View Crop")
#    
#    tGroup.Start()
#    
#    for DV in dviews:
#        trans1 = Transaction(doc, "Crop View")
#        
#        trans1.Start()
#        
#        oView.CropBox = DV[1].BoundingBox(DV[0]) 
#        
#        trans1.Commit()
#    
#    tGroup.Commit()
##############################################################################################
def PMin(a,b):                          ##Return Lowest point
    if a[0] < b[0] or a[1] < b[1] or a[2] < b[2]:
        return a
    else:
        return b

def PMax(a,b):                          ##Return Highest Point
    if a[0] < b[0] or a[1] < b[1] or a[2] < b[2]:
        return b
    else:
        return a

##############################################################################################
def CropViews (dviews):                 ##Takes list pair of views and elements in views
										##to set bounding
    tgr=TransactionGroup(doc, 'TGR:DynamoSetDraftCrop') ##Transaction group start name
    tgr.Start()                         ##Start transaction overall wrapper name
            
    done=["Pass"]                    	##Successful
    fail=["Fail"]                   	##Failed
    ele=None                            ##Revit DB Element
    
    ##dviews=UnwrapElement(dviews)      ##Unwrap - may be unnecessary.
    
    for DV in dviews:                   ##Pair of [[view][list of elements]]
        
        oview=None                      ##Clear oview
        oView=DV[0]                     ##DRAFTING VIEW AT INDEX 0  IN dVIEWS
        
        elements=None                   ##clear elements just in case
        elements=DV[1]                  ##Elements portion of DV DOUBLE

        tgrtra=Transaction(doc, oView.Name)     
        tgrtra.Start()                  ##Start transactiongroup within transaction

        bo = None                       ##Set boundign box to none  
        
        if elements:
            bo = elements[0].get_BoundingBox(oView)  #<seed bounding original and output
                    
            for ele in elements:            ##Elements list as 2nd double in list
                bc = None                     ##Set boundign box to none    
                bc = ele.get_BoundingBox(oView) #BC Counding Comare
    
                bo.Min=PMin(bc.Min,bo.Min)  ##Get MIN point
                bo.Max=PMax(bc.Min,bo.Min)  ##Get max point
                
            try:        
                oView.CropBoxActivate=True
                oView.CropBoxActive= True      ##Turn off crop box
                oView.CropBoxVisible = False    ##Turn off visibility
              
                oView.SetCropBox=bo         ##Set crop box to bb setup
                done.append([oView.Name,["Boundary:",bo,bo.Max,bo.Min],oView])   ##Append no-error element name, Bound box, min and max
            except Exception as e:
                fail.append([e.ToString,["Boundary:",bo,bo.Max,bo.Min],oView])
        else:
            fail.append([oView.Name,bo,oView]) ##No elements
            
        tgrtra.Commit()                 ##Commit group transaction for current view : 
        
    tgr.Commit()                        ##Commint outer transaction
    
    return done,fail
##############################################################################################
def Main():  

    DraftingViews = GetDraftingViews()  ##Get drafting views
    
    dviews=[]                           ##Drafting Views lits

    for DV in GetDraftingViews():       ##Cycke through drafting views
        dviews.append([DV, GetElementsInView(DV)])  ##dviews + [elements in view]
 
    ##OUT=Get_BoundingBox_from_elements(dviews[0][0],dviews[0][1])
   
    ##return OUT                        ##DEBUG<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    #return dviews
    #return TestBoundingBox(dviews)     ##DEBUG<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

    OUT=CropViews (dviews)              ##RUN CROP on all views

    return OUT ##dviews ##aMin,aMax,done,failed        ##RETURN FROM MAIN TO OUT BELOW...

##############################################################################################
##Run Main
############################################################
OUT= Main () ##anElement.getBoundingBox(DV[0]).Min ##anElement.getBoundingBox(oView)
#

and after removing extraneous lines it doesn’t work (The bounding box should have contracted but didn’t):
image

1 Like

@sovitek - is that for a rectangle or does it start the irregular shape manager (For drafting views)? I want to stay away form whatever triggers the irregular (non-box) shaped views as it drags down plotting capabilities.