Retrieving detailed wall layer geometry without physically generating parts in Revit

Hi Guys,

I need to retrieve a detailed position for all wall layers in my wall compound structure. I know that layers geometry can be retrieved by Element.MakeParts / Element.GetParts from Steam Nodes. The problem with this, however, is that it causes Dynamo to physically convert Revit walls into parts, and this is highly unwanted.

I tried to mix the method from Steam Nodes with a solution that was once developed by Marcelo Quevedo and described by @Jeremy_Tammik on his blog here (the method was not initially for Dynamo, so the code was provided in C#):
http://thebuildingcoder.typepad.com/blog/2011/10/retrieving-detailed-wall-layer-geometry.html

That is, I’m trying to force Dynamo to get information about wall parts, extract the information I need - for example part faces - and end it all with transaction rollback so that Revit keeps its walls geometry unchanged. The problem is that I cannot take any information from the transaction to the outside, so I could use a little help here.

Here is my development so far:

wallparts

Maybe someone can come up with a fix?
Thanks in advance!

Yes, you can take geometry and other information out of the transaction before it is rolled back.

1 Like

Hi Jeremy, thank you for your prompt reply.

I realize that it can be done. If I understand the Revit API correctly, for retrieving the newly created parts I have to iterate through my walls with GetAssociatedParts and from that I can take the whatever geometry I need for further manupulation. When try to do that, however, I keep receiving a warning that “starting a new transaction is not permitted (…)”.

I get a little confused here, since in the method you described in details everything was solved in one transaction and it seems to be a problem for Dynamo/Python. After all, I’m not trying to start any new transaction before rolling back the current one.

On the other hand, if I try to iterate directly through the parts received via CreateParts method, I get the TypeError: ‘NoneType’ object is unsubscriptable. As I understand, it means that wallParts is not a list of any kind and it cannot be iterated through?

parts-v03

What am I missing here?

Probably has something to do with the way Dynamo handles transactions. Check out this section: https://github.com/DynamoDS/Dynamo/wiki/Python-0.6.3-to-0.7.x-Migration#transactions

One thing you could try is paste a ‘TransactionManager.ForceCloseTransaction()’ on line 55 to ensure any other transactions are closed.

Another option would be to run your script and then use the Undo command in Revit.

2 Likes

It didn’t solve the problem - it expects me to provide and argument for this function and doesn’t work either way. The other option is not really an option as I need to perform this action frequently.

But thanks for your input, though! I’ll look further into this and see what I can come up with.

How accurate do you need the results? Perfect or is ‘cocktail napkin’ quality acceptable?

Very accurate - I need it to determine constraints for another geometry I generate from it further in the process (long story).

I’ve been able to achieve what I need in a different way - I constructed the position of each layer geometrically using data from Clockworks’s CompoundStructureLayers and it suits my needs. However, it’s not the answer to the initial question :slight_smile:

You can try to force the transaction to close before you start another transaction…

The clockwork way was why I was asking the accuracy question. Feels like that may fail to account for wall joins and such. May want to check that.

Short of that it feels like you’re on the right path. Do you have a sample dyn and rvt file so others can try to modify your situation and code rather than building it from scratch?

before creating wallparts you should check if parts are available for the wallelement!

> if PartUtils.AreElementsValidForCreateParts(doc, IDS):
>    wallParts = PartUtils.CreateParts(doc,IDS)
>    doc.Regenerate()

There is something that remains unclear: Is the code provided by Jeremy Tammik not creating temporary parts in Revit anyway? I read this at the end of the article: “Create the parts and regenerate the model so the part geometry becomes accessible.” If so, using a Passthrough node with a Delete node at the end of the process couldn’t possibly lead to the same result?

Good point, that might be an option - I tried it some time ago. But I gave up this method since it was more time consuming for Revit+Dynamo to actually produce the parts first and delete them later and if I tried that on a big project it was a killer for my computer. At the same time - I like to keep my definition minimal, so I always try to push as many operations into Python scripts instead of dealing with dozens of nodes.

Anyhow, my goal is to turn all this process into the Python script. I tried to simply translate the code from the original C# to Python and there the whole story begun.

For now I have actually found another way to achieve what I need, that is, I constructed the position of each layer geometrically using data from Clockworks’s CompoundStructureLayers.

However, it’s not the answer to the initial question :slight_smile: Therefore, as @jacob.small suggested, I’m posting a simplified sample file and my script so that anyone interested can try to solve this puzzle - it might still be useful for someone in the future :slight_smile:

170905-WallParts.dyn (3.6 KB)
170905-WallPartsSample.rvt (1.9 MB)

Thanks for all your insights so far!

Just wondering if you shouldn’t get the element geometry before querying the faces:

1 Like

@karolina.ostrowska
to create a layer based quantity takeoff the api offers basically an efficient option.

  1. create parts. the process should be clear now.
  2. if revit is slowing down best practice will be to first select all walls that are relavant for qto (filter).
  3. then check if it is possible to create parts from them (PartUtils.AreElementsValidForCreateParts).
  4. put the elements which can be converted in a new list.
  5. if you have a complete list convert them all in one transaction (from the IList).
  6. now you have to do just one refresh for all - which saves a lot of time.
  7. now you can extract the part’s quantities. if you like you can even extract their geometry - which is not necessary as you receive width height volume area of each part.
    but basically the parts can be deconstructed easily.
  8. this information is written in a new list.
  9. new rollback the transaction and refresh again.
    so that is just one refresh and that is really quick.
  10. if you have walls containing 0 width layers you will have to go with "wall.WallType.CompoundStructure"
    here you receive ALL layers even those with 0 width. you now have to compare the number of layers you get in parts. if there is a difference you know you have 0 width layers.

@Peter_Kompolschek thanks for your input! This is not the case here, however. I don’t need quantity takeoff - I need the part geometry as references for creating prefabricated elements. Also, as I wrote a few posts up I was able to achieve it with the Compound Structure node, similarly to what you suggest in point 10 - this is not a universal solution, though.

The problem which still remains unsolved is dealing with transactions within a Python script - I keep getting an error that Dynamo cannot start a new transaction if I try to make parts and get parts’ information in the same transaction. So for now it’s more of a coding issue and most certainly I’m missing something in my script. I wasn’t able to figure it out on my own, so I thought I’d give it a try and post this issue here.

@karolina.ostrowska
anything like that?
image

2 Likes

Hi karolina,
i have not downloaded your script but is that the version where you have the transaction error inside a transaction? If not can you also post it so i can try and fix that. This will save me time to replicate the problem. Thanks.

Yes @Peter_Kompolschek, thank you for your help!

@Peter_Kompolschek
I get 1200 points for 2 compound walls, do you know if I would need to change something in the code you provided?
There is something else that I have seen about RollBack at the end of this page:

“Sub-Transactions will give you the ability to rollback your changes. There is no way to rollback the main Dynamo Transaction.”
Here is the related API section:

I can not see any Sub-Transaction in your code, do I miss something?
Could anyone try to clarify a little? :slightly_smiling_face:

Edit: sub-transactions related posts