Duplicate Plan and set crop box, view range, scale, view template, view type, etc

Hello,

I´m working on a new Dynamo Script and i`m pretty happy about how far i got, but now i need your help.

Target: Create plan views for multiple levels by using one plan view as template

Tasks:

  • Create multiple plan views for multiple levels
  • Get parameters from template plan view (crop box, view range, scale, view template, view type)
  • Set parameters
  • Copy 2D-Elements from template plan
  • Copy Dimensionings from template plan
  • Set Grid like in the template plan

Major Problems:

  • Set View Range. The python script by user kennyb6 is not working in plans with view direction “up”, as user pitern pointed out. All my plans have view direction up. I have no idea how to change the script and i don´t understand the error.
  • My script works only for creating one plan. If i add more levels it works for a specific amount of levels because in dynamo player i have to fill out all dropdowns. But i want my script to work for one plan or for 10 plans. I have no idea how to achiev this.
  • If the template plan view has a rotation on a sheet, the duplicated plan view doesn´t have the rotation. How can i copy and apply this rotation?
  • If the “get.active.view” node doen`t find anything (or finds a sheet) because i´m not in a view, the script will still create a plan, how can i stop that? I only want the sript to run with a ceiling plan or structural plan as input.

Would be happy about any advice, thank you very much in advance!

Here is what`s working right now:

And this is the error from the python code:

I got the python script working by erasing all if/else clauses that i don`t need. I think they were there for list inputs.

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import*
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument

v = UnwrapElement(IN[0])
tof = IN[1]
bof = IN[2]
cof = IN[3]
dof = IN[4]
count = 0

TransactionManager.Instance.EnsureInTransaction(doc)

#getting the viewrange of the view
viewrange = v.GetViewRange()
asslvl = v.GenLevel

#Setting top clip plane of the viewrange
#Setting level of topclip plane
viewrange.SetLevelId(PlanViewPlane.TopClipPlane,asslvl.Id)
#setting offset of top clip plane
viewrange.SetOffset(PlanViewPlane.TopClipPlane,tof)

#Setting bottom clip plane of the viewrange
#Setting level of bottom clip plane
viewrange.SetLevelId(PlanViewPlane.BottomClipPlane,asslvl.Id)
#setting offset of bottom clip plane
viewrange.SetOffset(PlanViewPlane.BottomClipPlane,bof)

#setting offset of cut plane
viewrange.SetOffset(PlanViewPlane.CutPlane,cof)

#Setting view depth plane of the viewrange
#Setting level of view depth plane
viewrange.SetLevelId(PlanViewPlane.ViewDepthPlane,asslvl.Id)
viewrange.SetOffset(PlanViewPlane.ViewDepthPlane,dof)


#Applying the viewrange to the view
v.SetViewRange(viewrange)
count = count +1
TransactionManager.Instance.TransactionTaskDone()

OUT = '%d view ranges altered' %(count)

But now i have trouble to add this python script to my dynamo script, it`s because of the View.
While it works fine if i put the view in with an select.views node:

It does not work in my script because the view has another name:

As you can see i receive the plan view as a ceiling plan when using a select.views node and the python code is working fine.
But when i take the view name from my StructuralPlanByLevel node i get the view as a StructuralPlanView and the python script does nothing.

I have no idea whats going on here… :astonished:

Here a comparison, its the same ID

Hi,

In your second picture, your view input is a list and the python script doesn’t work with list.
Use a GetItemAtIndex or a FirstItem node to remove the list.

Thank you very much Alban! You are right, i didnt see this. But there is another problem. I got it working but only by running the dynamo script a second time and switching the node where i get the view from. I cant explaine whats going on but i think i know the reason.

By creating the structural plan i get a plan with the view direction DOWN because that seems to be the default. Thats why i get the view range error on python because my parameters are for UP direction.
The Dynamo script changes the view type which changes the view direction to UP.

For some reason the python script gets the DOWN view that was created in first place, but i need to input the view after applying the new type.

Thats how i get it to work right now:

run dynamo script first time gives me an error:

running it a second time does nothing. But changing the input to another node and running it a second time:

does work…

how can i give the relevant view as input?

edit: i tried transition end and start, it didn´t work but i´m not quiet shure how to use it. Or do i need a pause? :man_shrugging:

I got it working, but still don`t know whats happening exactly.
As you can see, in the process of setting the parameters, the PlanView Type changes from StructuralPlan to CeilingPlan. I thought the SetParameterByName node is the reason, but now it happens at the SetCropBox node?! Would be glad if someone could explain why this is happening.

Edit: As you can see, dynamo recognizes a Structuralplan with viewdirection UP as a ceiling plan…

So let`s move on to the next step, adjusting the 2D-Grid like it is in the template plan view.
This is a built in Revit tool with the name Propagate Extents and i found a Python code for it, its from Dan Woodcock: https://danimosite.wordpress.com/2017/05/29/grids-propagate-extents/

My Problem ist now, that Propagate Extents only works if the CropRegion of the views is turned off. I Can turn them off with SetParameter nodes, but i have no idea how i can turn them on after the GridExtents.

There´s my script, would be glad about any help:

Edit:

I added the following transaction to the code:

#Open a new Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
view.CropBoxActive = True
TransactionManager.Instance.TransactionTaskDone() 

This successfully activates the cropbox for the view at Input 0 but not for the view in Input 1 :confused:

Here is the complete code:

import clr
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
 
# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
 
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
 
clr.AddReference("System.Core")
from System.Collections.Generic import HashSet

import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
 
#############   DEFINITIONS START  ###############
 
def tolist(obj1):
    if hasattr(obj1,"__iter__"): return obj1
    else: return [obj1]
 
#############   DEFINITIONS END  ###############
 
# declare IN-Variables 
view = tolist(UnwrapElement(IN[0]))[0]
targetViews = tolist(UnwrapElement(IN[1]))
 
# declare OUT-Variables
outList = []
 
#Collector - Get all grids in view...
grids = FilteredElementCollector(doc, view.Id).OfCategory(BuiltInCategory.OST_Grids)
 
# Get ISet of TargetViews ElementID's...
tViewIds = HashSet[ElementId]([tv.Id for tv in targetViews])
 
# Open a new Transaction to make changed to the Revit Document...
TransactionManager.Instance.EnsureInTransaction(doc)
# Loop through all the Grids in View...
for g in grids:
    try:
        g.PropagateToViews(view, tViewIds)
        outList.append("Grid " + g.Name + " - Propagation Succeeded")
    except Exception, e:
        outList.append("Grid " + g.Name + " - Propagation Failed" + "\n - " + e.message)
# Close Transaction and commit changes...
TransactionManager.Instance.TransactionTaskDone()

# Open a new Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
view.CropBoxActive = True
TransactionManager.Instance.TransactionTaskDone()

# Return the results...
OUT = outList

Edit 2:

I edited the Python script to give the views as output and did the rest with nodes. Everything working fine now :slightly_smiling_face: But still some problems to solve, more tomorrow. Would be great if someone could help me clean the “grid-group” up by adding the relevant lines to the python script.

On to the next task, i added an if-node that will only create a new Plan if the template Plan is a ceilingplan. Working fine, no idea if there is a better way to do this.

So now 3 Problems are left:

  • Allow variable amount of inputs in dynamo player. I have found something from Data-Shapes. Will try this.
  • Copy 2D-Elements
  • Copy Dimensioning

Cleaned up a little by adding some code to the Grid Script that will now do the following tasks:

  • Turn off CropBoxes of template view and target view
  • Propagate Extents
  • Turn on CropBoxes of template view and target view
import clr
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
 
# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
 
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
 
clr.AddReference("System.Core")
from System.Collections.Generic import HashSet

import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
 
#############   DEFINITIONS START  ###############
 
def tolist(obj1):
    if hasattr(obj1,"__iter__"): return obj1
    else: return [obj1]
 
#############   DEFINITIONS END  ###############
 
# declare IN-Variables 
view = tolist(UnwrapElement(IN[0]))[0]
targetViews = tolist(UnwrapElement(IN[1]))
targetViews2 = (UnwrapElement(IN[1]))
 
# declare OUT-Variables
outList = []
 
#Collector - Get all grids in view...
grids = FilteredElementCollector(doc, view.Id).OfCategory(BuiltInCategory.OST_Grids)
 
# Get ISet of TargetViews ElementID's...
tViewIds = HashSet[ElementId]([tv.Id for tv in targetViews])
# Open a new Transaction to make changed to the Revit Document... 
TransactionManager.Instance.EnsureInTransaction(doc)

# Turn off CropBox 
if view.CropBoxActive == True:
   view.CropBoxActive = False
# Turn off CropBox 
if targetViews2.CropBoxActive == True:
   targetViews2.CropBoxActive = False

# Loop through all the Grids in View...
for g in grids:
    try:
        g.PropagateToViews(view, tViewIds)
        outList.append("Grid " + g.Name + " - Propagation Succeeded")
    except Exception, e:
        outList.append("Grid " + g.Name + " - Propagation Failed" + "\n - " + e.message)
# Turn on CropBox              
view.CropBoxActive = True
targetViews2.CropBoxActive = True        
        
# Close Transaction and commit changes...
TransactionManager.Instance.TransactionTaskDone()

# Return the results...
OUT = outList

Still have no idea why the script only works if i connect the python node to the setcropboxnode.
Still have no idea why only the setcropbox node gives out a ceilingplan and the others structural plans.

Has someone please any suggestions for me? DYN file attached.
What DOES work is changing the lacing of the set.parameter.by.name node an run the script a second time…
only green is working

Duplicate_Formworkplan.dyn (49.2 KB)

Sorry, I do not have any great Ideas but I may have a solution for you. What if you set the crop boundary first before you changed the view type? This would then ensure that the view type is what you want it to be if View.SetCropBoxCurves is changing the type on you.

Again this is not an answer to why this is happening but it may allow your script to function properly.

Hey Steven, thanks for your reply. The “green wired” version above is working, i just wanted to solve the mystery bacause i dont understand whats going on. The version you suggested doesnt work, but don`t ask me why. It DOES work if i change the Set.Parameter lacing and run the script AGAIN…

Here is now the standalone version of the Get-Set PlanView parameter script:

We can see the following:

  • A Structural Plan with view direction UP is a CeilingPlanView in Dynamo
  • A Structural Plan with view direction DOWN is a StructuralPlanView in Dynamo
  • Changing view direction from DOWN to UP with this script was successfull.
  • The Structural Plan has now view direction UP but is still a StructuralPlanView in Dynamo.
  • That makes absolutely no sense at all^^

Can`t tell whats the reason that it doesnt work in the full script.

Maybe it`s a problem that there are 3 Type entries?

image