How to change python code to get floorplan view instead of area plan view?

Hi all,

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).

1 Like

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

Polycurve.ByJoinedCurves

Already tried that Node, but then i got this error.

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?

Yes you’re right I had to set Use levels to @L1.
Got it working now.

Thanks!