Create Floor- Python

Hi All,

I am trying to create a floor within my python script using:

doc.Create.NewFloor(curveArray, FloorType, LevelType, Structural_Element)

I am passing in line and arc data which I have created in grasshopper- and because I manage arcs and lines as seperate opererations when I read the data- it is not ordered perfectly. when I read the the two geometries to make the curve array.

However, when I use the out of the dynamo nodes such as Polycurve.ByJoined curves it seems to be able to make a closed polyline no matter what the order.

Can someone tell me if I am correct in saying that the API comment I quote about needs them to be ordered in order for them to work, and secondly, is it poor practice if I use dynamo node commands within my script? Thirdly, I have also read that its not possible to send in two polyline to create floors, for example, if I have a void I want to have cut out etc.

Thanks, Sam

Hi Sam,

I don’t know how far you currently are, but the curves don’t need to be in order. It is just like making a floor in revit itself. You don’t have to draw the curves in a particular order.

So: doc.Create.NewFloor(curveArray, FloorType, LevelType, Structural_Element) doesn’t need the curves to be in order. What it does need is Revit curves and not Dynamo Curves! You have to parse the Dynamo curves to Revit curves. You can do that with the Extension methodes in the “RevitNodes” dll.

It is not a poor practice to use Dynamo Node Commands like PolyCurve.ByJoinedCurves in Python. The “Commands” are just Methodes in a Class.

I don’t know where you read about the “two polyline” thing, but you can put the curves of two polycurves in one curve array and it will create an “opening” in the floor, but it will not become an Opening in Revit. (I hope this is clear). If you really want an Opening element in Revit, you need the doc. NewOpening(Element, CurveArray, Boolean)

Let me know if something is unclear! :slight_smile:

Hi @Joelmick

Thankyou for your response.

To convert them from dynamo to revit I am doing the following (for both arcs and lines)

curveArray = ()
curveArray.Append(line.ToRevitType()) 

I then start transaction and pass them in to make floor and then add it to my output list from my script.
Does this seem to be the correct method?

Then If I was to create an inner boundary as you mentoned, so just say an area for a spiral stair, I could just pass the relevent lines, arcs in to the same curvearray and dynamo would be smart enough to see they are two closed shapes?

# Make within python

 >     >     >    TransactionManager.Instance.EnsureInTransaction(doc)
>     >     > 
>     >     NewFloor = doc.Create.NewFloor(curveArray, FloorType, LevelType, Structural_Element)
>     > 
>     >     #Append it to the new floor list which we output
>     > 
>     >     NewFloor_List.Add(NewFloor.ToDSType(False))
1 Like

The methode ToRevitType() is correct. only the curveArray should be:

curveArray = CurveArray()
#Floor lines is the list with all the dynamo curves for the floor (inner loops and outer loops
for line in floorLines: 
    curveArray.Append(line.ToRevitType())

For the last question, yes that would be right. keep in mind that “dynamo” is not this smart instance here, but “Revit” is, since NewFloor() is a Revit methode, not a dynamo one :wink:

Thankyou,

Could you just clarify, the code below:

I know I want to add this to my list of new floors.

  1. I could just as easilly use append right as opposed to add,
  2. .ToDSType(False)) what is this actually doing
  3. I am correct to put my end transaction outside of the loop where I make all my floors? for example I start a new transaction for every row of my loop (so could do this say 20 times) but i only ever end the transaction once- out of the loop. Given this works, I assume you dont need to always have then same number of transaction starts as you do ends?

And finally, I feel once my script runs and the floors build. if i try and re-run, it doesnt really work, I need to in effect break it (remove a link) then run it to where it fails, then fix it and run it again for it to work again. Is there a way around this?

Sorry for all the questions…

NewFloor_List.Add(NewFloor.ToDSType(False))

NewFloor_List.Add(NewFloor.ToDSType(False))

  1. Yes you can use Add() instead of append(), the difference between them is that Add is a method of a .Net List class and append is a methode of a Python list class. In Dynamo we use IronPython which can both talk to .Net (Revit API is a .Net library) and normal Python 2.7. Add won’t work if you don’t import the right modules in you boilerplate and append will always work since we are already writing in Python.

  2. .ToDSType() is saying To Designscript Type() which means that it shifts "ownership of the newly created object from Dynamo to Revit. When you use the Python script on another set of curves, the other floor will disappear if ToDSType(False), because you use it on other curves. If you set ToDSType(True) it will create a second floor, and a third if used on another. What is important here is that, when you test your script, you set this to False, otherwise it will create a Floor ontop of another Floor each time you run the script for a test.

  3. Yes you are correct to Start & End you Transaction outside the Loop. This way, you do 1 transaction in which you create an object. Lets say you want to create 10 floors. This way you Start 1 transaction, Create 10 floors and End the transaction. If you Start&End a Transaction each time you create a Floor in the loop, Revit will become slower.

And finally, I feel once my script runs and the floors build. if i try and re-run, it doesnt really work, I need to in effect break it (remove a link) then run it to where it fails, then fix it and run it again for it to work again. Is there a way around this?

This is probably due to the fact that ToDSType() is set to False. Dynamo is not going to create a new object, since he already has one. If you Set this to True it will create a Floor on each run, but it will be a Floor on top of another.

I hope this makes everything a bit clearer! Also, never apologize for asking alot of questions :wink:

1 Like

That all makes a lot of sense!

For the transaction,

I feel that I always start a new transaction before i do something within the loop, so I start as many transactions as I do loops, but always have only one end transcation.

How I read what you say- maybe I am better of starting the transaction just before my ‘action’ loop and ending it once I have finished in that loop?

The other descriptions are exactly what I needed to hear. Sam

Hi Sam, I owe you a rectification haha.

I am now testing everything myself and somethings I told you don’t apply on floors.

the ToDSType() appears to not do anything for methodes in the Autodesk.Revit.Creation.Document class, including NewFloor(). Revit just keeps on creating new Floors. It seems that the OOTB Node for Floors takes care of this in another way (if you update that one, It will update the floors and not make new ones)

Also the openings. I thought revit could figure out if it needed to create an “opening” of you provide 2 curveloops, but it seems Revit throws an error… So it seems that, if you want openings, you need to program that aswell… annoying…

For the Transactions. A Transaction is 1 thing. It tells Revit "Hey I am going to do some things (Delete, Create, move) " You Start a Transaction, Do loops, create stuff etc and you End the Transaction. In Dynamo Python they Have the TransactionManager for this. This Starts the Transaction for you and Closes it after you are done.

I have made a full example for you.
Floors.dyn (54.1 KB)