Create Crop Region From Curves (2.13)

I’m trying to create apply a crop region for a given view based on a list of curves. This used to work fine in previous versions of Dynamo/Python I have installed (2.6 was the most recent I have experience with) but no longer works in Revit 2023 and associated Dynamo 2.13.

I have tried using the custom nodes from packages MEPover and Data-Shapes as well as Python from older threads on this forum but they all return a similar error:

import clr

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)

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

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument

#prepare input
view = UnwrapElement(IN[0])
curves = IN[1]
outputlist = []

#Create curveloop
loop = CurveLoop()
for c in curves:
        loop.Append(c.ToRevitType())

#Set cropregion in Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
view.CropBoxActive = True
view.GetCropRegionShapeManager().SetCropShape(loop)
outputlist.append(view)
TransactionManager.Instance.TransactionTaskDone()

OUT = outputlist

Where Line 27 in this instance is:
loop.Append(c.ToRevitType())

This is the simplest version of this operation I could find but, like I said, pulling the Python code out of the MEPover node and the Data-Shapes node generates the same error whereas they all used to work in prior versions of Python (yes, I have run the auto-update to CPython3).

Any help much appreciated as this node is a key part of our workflow, thanks.

Hello…for mepower crop view node you need to run with python 2…and should work :wink:


1 Like

Hi - thanks for your reply but that doesn’t help as I get the same issue:

have you tried downloading the python 2 package in the newer version?

Yes, python 2 package is installed.

how many curves are in your crop box? that seems like a lot. Is the listing correct?

Lots of curves :slight_smile: The crop follows the extents of an apartment outline. The graph worked perfectly on exactly the same group in Revit 2021 and 2.6 before the project was upgraded to Revit 2023.

Not worth a bounding box and squared? :upside_down_face: I wouldn’t know but I can give suggestions. Check with closed square if it works. Also is it from a room perimeter? If not maybe run the curves through a polycurve by closed curves to check there all joined? :face_with_diagonal_mouth: I’m sure one of the smarter dudes will help ya soon.

1 Like

I wish we built square apartments! :smiley: Feeding polycurves into the node still causes it to fail (just in a different way) even though that, too used to work, so hopefully someone has some ideas. :slight_smile:

Seems you cant create a closed loop with these lines…this one here have sometimes help me in that sitiution…Curve.ApproximateWithArcAndLineSegments…but not sure it help you…if you had multiple loops then try group them with archilabs groupcurves

Curve merge from spring sometimes help to

To verify - have you checked tthrough PolyCurve.ByJoinedCurves + Curve.IsClosed that the input creates a single, closed boundary, you don’t have multiple CurveLoops or open curves? I’ve been dealing with similar task recently and have had all sorts of issues.

The curves are 100% joined and closed. They come from the boundary of a surface. The graph verifies this:

FYI, here’s the MEPover code:

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

import clr
clr.AddReference('RevitAPI')
import Autodesk.Revit.DB

import clr
clr.AddReference("RevitNodes")
import Revit

clr.AddReference('DSCoreNodes')
import DSCore
from DSCore import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

# Import ToProtoType, ToRevitType geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

#The inputs to this node will be stored as a list in the IN variables.
if isinstance(IN[0], list):
	views = UnwrapElement(IN[0])
else:
	views = [UnwrapElement(IN[0])]
if isinstance(IN[1], list):
	if IN[1][0].GetType() == PolyCurve:
		curves = [PolyCurve.Curves(x) for x in IN[1]]
	elif IN[1][0].GetType() == Curve or IN[1][0].GetType() == Line:
		curves = List.OfRepeatedItem(IN[1],len(views))
	else:
		curves = IN[1]
else:
	if IN[1].GetType() == PolyCurve:
		curves = [PolyCurve.Curves(IN[1])]
	else:
		curves = [IN[1]]
	
listout = []
for view,curve in zip(views,curves):
	regionMan = view.GetCropRegionShapeManager()
	revit_curve = [c.ToRevitType() for c in curve]
	curveloop = Autodesk.Revit.DB.CurveLoop()
	for c in revit_curve:
		curveloop.Append(c)
	TransactionManager.Instance.EnsureInTransaction(doc)
	if view.CropBoxActive == False:
		view.CropBoxActive = True
		view.CropBoxVisible = True
	regionMan.SetCropShape(curveloop)
	TransactionManager.Instance.TransactionTaskDone()
	listout.append(view)


#Assign your output to the OUT variable.
OUT = listout

Okay, I finally have a solution thanks to inspiration from the PolyCurve.ByJoinedCurves node - I just grabbed the curves from the PolyCurve (although not strictly necessary for the MEPover node as it can be fed a PolyCurve, other nodes were failing too).

The Python still needs to be extracted from the MEPover node as the original custom node still fails with this method.

I’m not sure why grabbing the curves from the perimeter of a surface should result in failure for nodes that require a closed loop when Dynamo says the loop is indeed closed?

So I dug a little further back in the graph and the problem seems to stem from the Strings node Surface.OuterPerimeterCurves that I use to remove internal loops before generating the crop.

If I feed OOTB Surface.PerimeterCurves into the operation then no errors so I’m not sure what the Strings node is doing (apart from the obvious difference of Curves vs Lines). In any case, a couple of different ways to get around the problem. Thanks all for the suggestions.

1 Like

Just guessing, but could it be that the building of a valid curveloop requires all the curves to be sequenced and oriented consistently - you can’t have them out of order or facing the wrong direction (start to end) or the process fails along the way. After creating the polycurve, all the curves are arranged consistently, therefore breaking it back up into curves works to create a curveloop. I’ve experienced similar issues creating loops and the polycurve step along the way usually helps me as well.