I have been looking for a way to update a Revision Clouds sketch curves. I tried to get the sketch curves of the rev cloud and setting it to a new set of Revit lines, but I don’t think that’s how the method works. It lets me set the existing curves to the new list of curves but it doesn’t set them. Is it possible to update the cloud sketch curves?
This workflow is to make the cloud smaller on Revit Schedule rows by segmenting the existing curve so we don’t have to update the cloud size for the entire project. I have a process right now for making a new rev cloud with segmented curves, but I would like to update what is being used.
Screenshot of the Dynamo so far.
Hi
An example of modifying existing RevisionCloud geometry (each DetailLine)
Note : assuming that each RevisionCloud
instance corresponds to a single cloud
import clr
import sys
import System
#
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
#import net library
from System import Array
from System.Collections.Generic import List, IList, Dictionary
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
def toList(x):
if isinstance(x, (list, dict)) or \
(hasattr(x, "GetType") and x.GetType().GetInterface("ICollection") is not None):
return x
else : return [x]
#Preparing input from dynamo to revit
cloud_instances = toList(UnwrapElement(IN[0]))
offset = IN[1]
#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
for cloud_instance in cloud_instances:
# must be run twice to keep the cloud oriented
for i in range(2):
iList_type = List[System.Type]([clr.GetClrType(DB.CurveElement)])
class_filter = ElementMulticlassFilter(iList_type)
details_lines_Ids = cloud_instance.GetDependentElements(class_filter)
detail_lines = [doc.GetElement(xId) for xId in details_lines_Ids]
poly_curve = DS.PolyCurve.ByJoinedCurves([x.GeometryCurve.ToProtoType() for x in detail_lines], 0.001, False, 0)
# create offset only once
if i == 0 :
poly_curve = poly_curve.OffsetMany(offset, False, None)[0]
# set new curves
for idx, ds_line in enumerate(poly_curve.Curves()):
new_line = ds_line.ToRevitType()
rvt_detail_line = detail_lines[idx]
rvt_detail_line.GeometryCurve = new_line
doc.Regenerate()
TransactionManager.Instance.TransactionTaskDone()
OUT = cloud_instances
2 Likes
@c.poupin I appreciate this so much! I would like to ask if you could explain why it needs to be ran twice? I’m not totally clear on the cloud orientation piece.
1 Like
I haven’t totally demystified this workaroud yet
Just that during my tests I noticed that it took 2 runs for the cloud arcs to be in the same direction as the original, I’d have to look at it more closely (maybe it’s due to the clockwise or counter-clockwise direction of the detail lines, to be seen) .
I appreciate the response. The other thing I noticed is and I wasn’t aware you could do this, but you’re setting the exiting curves to the new curves and so does that mean you have the have the same number of new curves as there are existing? If so, is there a way to add new curves to the list existing geometry? The goal is the divide the length of the original curves so the cloud arcs are smaller. Is it as simple as adding new curves to that list of detail lines?
Unfortunately, it’s not possible
1 Like
is there a way to take the existing geometry and divide it?
The only solution in this case will be to re-create a RevisionCloud as you mentioned.
1 Like
Ahhhh darn. I do appreciate the help! Can I ask you questions about parts and pieces of the code you supplied still?
So these lines of code. [quote=“c.poupin, post:2, topic:105967”]
iList_type = List[System.Type]([clr.GetClrType(DB.CurveElement)])
class_filter = ElementMulticlassFilter(iList_type)
details_lines_Ids = cloud_instance.GetDependentElements(class_filter)
[/quote]
is this just to ensure you’re collecting the detail curves being used by the rev cloud?
yes, because a RevisionCloud depends on several types of elements
1 Like
That makes sense, if you did a plain cloud_instance.GetDependentElements()
you would collect all of those dependent items, right? So making an element multiclass filter ensures you only collect the detail lines.
Sorry, I have so many questions. Would you be able to also break down the line where you make your IList?
according to the documentation, need to set None
(null) as parameter
To sum up briefly, when working with CPython3 (PythonNet) you have 2 domains:
when you call a .Net method, you need to ensure that the types of objects passed as arguments are correct
ElementMulticlassFilter
needs an IList<Type>
as parameter, so we convert (or cast) a python list to List<Type>
(.Net)
conversion isn’t always compulsory, but it’s a good practice to have
2 Likes