Help Converting C# code to Python

I wrote a script in C# to go through and optimize fabrication part lengths in Revit and am very interested in what Dynamo has to offer. I’ve tried with no success moving what I have in C# to a custom Dynamo node. I hoping some python coders here can help me move what I have into python. Here is what I have in C#. Thanks in advance.

Document doc = commandData.Application.ActiveUIDocument.Document;

UIDocument uidoc = commandData.Application.ActiveUIDocument;

FilteredElementCollector col

= newFilteredElementCollector(doc);

ICollection<ElementId> collection = col.WhereElementIsNotElementType().OfCategory(BuiltInCategory.OST_FabricationParts).ToElementIds();

if (collection.Count > 0)

{

ISet<ElementId> selIds = newHashSet<ElementId>();

foreach (ElementId id in collection)

selIds.Add(id);

using (Transaction tr = newTransaction(doc, “Optimize Straights”))

{

tr.Start();

// optimize lengths method will take a set of elements and any fabrication straight parts

// within this set that have been optimized will be returned.

ISet<ElementId> affectedPartIds = FabricationPart.OptimizeLengths(doc, selIds);

if (affectedPartIds.Count ==

Sorry here was my python node that did not work.

Capture

Hi Nathan,

I believe there’s already a few examples of FECs on the forum. If you do a search for those, you might see some more options. I don’t have the fabrications add-in installed to test this out, but I believe the code should look something like this:

2015-09-24_10-13-28

Can you compile your C# code into a dll library? If so, next time you could try importing your dll through File > Import Library and have it available as a canvas node.

You can find more info here:

Thanks for the reply Dimitar. I tried your code and am receiving the same warning as the code I created. I also tried importing the dll using zero touch with no success.

Python Error

according to the message you will have to create a IList.

the code will look something like:

elemIds=[]

for i in elements:

elemIds.append(i.Id) # creates a list of element Ids

selIds = ListElementId # this will create an IList. that should solve the problem

 

btw this corresponds with your c# code:

ISet<ElementId> affectedPartIds = FabricationPart.OptimizeLengths(doc, selIds);

I am having an issue with ISet vs IList. See attached image. I am using DatumPlane.PropagateToViews, which requires an ISet. I tried making an IList and it give me an error. Is there no way to create an ISet?

 

Hi Ben,

ISet doesn’t have a constructor and needs to be sub-classed to be used. You could use the SortedSet class instead because it already inherits the ISet class.

2016-02-11_13-57-51

Dimitar- I saw your answer and got excited that I would have a solution, but Sorted Set is not working for me…see attached image. It says that it “failed to compare two elements in the array”. I cannot even try the Propagate View part because it won’t get past the creation of the SortedSet. The array is simply two view ids (coming from an input list of two views).

Ha, I should have warned you about that. You might have guessed by the name that this class tries to sort its items. The problem is that it doesn’t know how to compare Revit IDs.

The only other class that uses the ISet interface is “HashSet” but unfortunately that doesn’t seem to be exposed to the iron python interpreter in Dynamo. So your only other alternative is to recreate the set for every view - not very efficient but hey, it works.

Thanks Dimitar- it works as intended now even if it’s not efficient. Who needs efficient code, right?

Dimitar,

HashSet works fine in Python/Dynamo:

Try this:

# Import Element wrapper extension methods
import clr
import System

# Load System.Core assembly that contains HashSet
clr.AddReference("System.Core")
from System.Collections.Generic import HashSet

# Create HashSet
myHashSet = HashSet[Autodesk.Revit.DB.ElementId]()

Then you can add items to it using the Add() method:
myHashSet.Add(someElementId)
3 Likes

Thanks, Konrad! My mistake was not referencing the system core dll. For some reason, I assumed that its path would be added to the interpreter by default.

The way this was explained to me once, it always depends on what functionality you need. So for example parts of System.Collections.Generic are located in couple different assemblies. HashSet stuff is specifically located in System.Core so its important to reference that specifically when importing HashSet. I asked around for this, as I wasn’t sure why I couldn’t get it to work the first time. Always learning…

2 Likes

Thanks Konrad! I used HashSet and its working great.

Nate

can not see HashSet keyword in python manual. where we need to look to get it.
image

# Load System.Core assembly that contains HashSet 
clr.AddReference("System.Core") from System.Collections.Generic import HashSet
2 Likes

what about ISet

What Revit API method uses that? What are you trying to call?

1 Like

i was trying to create a dynamo to convert design part o fab part. I need to know two things. How to create Iset and how can retrieve ServiceId
image

image

Hey,

If you read through all the threads I think it explains itself…

ISet doesn’t have a constructor and needs to be sub-classed to be used. You could use the SortedSet class instead because it already inherits the ISet class.

The only other class that uses the ISet interface is “HashSet”

Did you try a HashSet?

Hope that helps,

Mark

1 Like