I saw this youtube video from Aussie BIM Guru and was trying to make a variation of this script.
Instead of making plan views from Rooms my goal is to make new floorplan views from the area boundaries which I selected in my area plans.
I changed the python code from Rooms to Areas. But the outcomes are now Area plan views instead of floor plan views. I think this is because the script search for the active view and get’s the TypeId of this view.
But I have almoest no experience with Python codes, so is this the problem? And is there an (easy) way to set a floorplan viewtype instead of using the active view viewtype for the new views?
See my changed python code below:
> # Load the Python Standard and DesignScript Libraries
> import clr
>
> clr.AddReference('ProtoGeometry')
> from Autodesk.DesignScript.Geometry import *
>
> clr.AddReference("RevitNodes")
> import Revit
> clr.ImportExtensions(Revit.Elements)
> clr.ImportExtensions(Revit.GeometryConversion)
>
> clr.AddReference("RevitServices")
> import RevitServices
> from RevitServices.Persistence import DocumentManager
> from RevitServices.Transactions import TransactionManager
>
> clr.AddReference("RevitAPI")
> import Autodesk
> from Autodesk.Revit.DB import *
>
> # Current doc/app/ui
> doc = DocumentManager.Instance.CurrentDBDocument
>
> # Define list/unwrap list functions
> def tolist(input):
> result = input if isinstance(input, list) else [input]
> return result
>
> def uwlist(input):
> result = input if isinstance(input, list) else [input]
> return UnwrapElement(result)
>
> def createPlan(area, name, typeId):
> # Get level id of area
> levelId = area.LevelId
> # Create view
> view = ViewPlan.Create(doc, typeId, levelId)
> view.Name = name
> # Return view
> return view
>
> def cropPlanView(view, polycurve):
> # Get Crop manager
> region_man = view.GetCropRegionShapeManager()
> # Get Revit curves from pc
> curves_dyn = PolyCurve.Curves(polycurve)
> # Make a curveloop
> curveloop = CurveLoop()
> for c in curves_dyn:
> c_rvt = c.ToRevitType()
> curveloop.Append(c_rvt)
> # Make sure Crop is on
> view.CropBoxActive = True
> view.CropBoxVisible = True
> # Set the crop shape
> region_man.SetCropShape(curveloop)
>
> # The inputs to this node will be stored as a list in the IN variables.
> names = tolist(IN[0])
> areas = uwlist(IN[1])
> polyCurves = tolist(IN[2])
>
> # Get active view Id
> view_active = doc.ActiveView
> viewtype_id = view_active.GetTypeId()
>
> # Create and crop plan views per area
> views_out = []
>
> TransactionManager.Instance.EnsureInTransaction(doc)
>
> for a,n,p in zip(areas,names,polyCurves):
> # Create a plan
> view = createPlan(a, n, viewtype_id)
> # Crop the view
> cropPlanView(view, p)
> # Append the view
> views_out.append(view)
>
> TransactionManager.Instance.TransactionTaskDone()
>
> # Assign your output to the OUT variable.
> OUT = views_out
Nothing in the python code is specific to rooms. It creates a view based on the element’s level and then crops the view based on the supplied boundary curve. As you guessed, it does use the active view’s view type though. You can either change the code to specify a view type as a new input (recommended) or you could try making the area selection first and then changing to an active view with the correct view type before running the script (not really scalable).
Thanks for the suggestions. I’ve changed the script and now it seems to work well in Revit 2023.
Another problem is that we still have a project in Revit 2020, which we cannot update to a higher version, and for this dynamo version the Node Polycurve.OffsetMany does not exist. So here we have now an output of Curve instead of Polycurves and gives an error in the python script.
Is there a way to turn the curves into Polycurves?
# Load the Python Standard and DesignScript Libraries
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
# Current doc/app/ui
doc = DocumentManager.Instance.CurrentDBDocument
# Define list/unwrap list functions
def tolist(input):
result = input if isinstance(input, list) else [input]
return result
def uwlist(input):
result = input if isinstance(input, list) else [input]
return UnwrapElement(result)
def createPlan(area, name, typeId):
# Get level id of area
levelId = area.LevelId
# Create view
view = ViewPlan.Create(doc, floor_plan_type.Id, levelId)
view.Name = name
# Return view
return view
def cropPlanView(view, polycurve):
# Get Crop manager
region_man = view.GetCropRegionShapeManager()
# Get Revit curves from pc
curves_dyn = PolyCurve.Curves(polycurve)
# Make a curveloop
curveloop = CurveLoop()
for c in curves_dyn:
c_rvt = c.ToRevitType()
curveloop.Append(c_rvt)
# Make sure Crop is on
view.CropBoxActive = True
view.CropBoxVisible = True
# Set the crop shape
region_man.SetCropShape(curveloop)
# The inputs to this node will be stored as a list in the IN variables.
names = tolist(IN[0])
areas = uwlist(IN[1])
polyCurves = tolist(IN[2])
# Get active view Id
view_active = doc.ActiveView
# Get all view types
view_types = FilteredElementCollector(doc).OfClass(ViewFamilyType).ToElements()
# Filter view types
view_types_plans = [vt for vt in view_types if vt.ViewFamily == ViewFamily.FloorPlan]
floor_plan_type = view_types_plans[0]
# Create and crop plan views per area
views_out = []
TransactionManager.Instance.EnsureInTransaction(doc)
for a,n,p in zip(areas,names,polyCurves):
# Create a plan
view = createPlan(a, n, floor_plan_type.Id)
# Crop the view
cropPlanView(view, p)
# Append the view
views_out.append(view)
TransactionManager.Instance.TransactionTaskDone()
# Assign your output to the OUT variable.
OUT = views_out
The error is telling you that the curves provided to form an enclosed loop. The offset node is only showing 3 curves, which doesn’t seem right. Which curves are being returned there? Have you tried list levels to force each polycurve to be offset?