Floor Creation

I already presented examples on using the NewFloor method to

edit a floor profile
and

perform Boolean operations on two-dimensional polygons
.

Now Guming submitted a

simpler question
, on
how to use the NewFloor method to create a floor from scratch,

twice
in
fact, so let’s have a look at that:

Question: How can I use certain points to create a new floor?
The function NewFloor doesn’t work for me.

Answer: You create a new floor using the NewFloor method.
You need to provide the profile curves and specify whether it is structural or not.
Other optional arguments can determine the floor type, level and a normal vector in case it is not horizontal.
According to the help file, the profile curves must always be specified horizontally, regardless of the desired floor slope.
Here are the argument lists of the three NewFloor overloads:

  • CurveArray profile, Boolean structural: Creates a floor within the project with the given horizontal profile using the default floor style.
  • CurveArray profile, FloorType, Level, Boolean structural: Creates a floor within the project with the given horizontal profile and floor style on the specified level.
  • CurveArray profile, FloorType, Level, Boolean structural, XYZ normal: Creates a floor within the project with the given horizontal profile and floor style on the specified level with the specified normal vector.

Further documentation on the use of this method is provided in the developer guide section 11.2 ‘Floors and Foundations’.

The Building Coder samples include the command

CmdEditFloor
which
exercises the second one of the NewFloor overloads, and so does the Revit SDK sample application GenerateFloor.

CmdEditFloor reads a profile from an existing floor and modifies that, whereas GenerateFloor demonstrates how to generate a floor using the closed outline made by a selection of walls.

Guming, one problem with the input points that you list is that they are not horizontal.
Some have a Z coordinate of 0, others 10.
That might be causing the method to fail for you.

Here is another related issue and interesting sample from a case handled by my colleagues Saikat Bhattacharya and Harry Mattison:

Question: I wish to create a whole set of floors by automatically generating slabs in every level of a project based on profiles.

When creating a set of floors using profiles, all the floors seem to be created with a non-zero value for the ‘Height Offset from Level’ parameter.
Why is this parameter value being set to a non-zero value?

In spite of this parameter value being set and the Level property showing the correct information, all the floors are being created on the same level.
I can manually set this parameter value to zero to get the expected results, but I am not sure why it is being automatically set in the first place.

Answer: The floors are created at the position of the profile curves.
The floors are associated with the specified level, but the level does not set the floor’s height.

Therefore, all floors are created with the same set of profiles and each floor is associated with a different level.
All the profile curves have a Z coordinate equal to zero.
So when a floor is associated with a level at 28 feet and its curves are at 0, the offset will be -28.

You have two options:

  • Leave the Z value of all curve points at zero, create the floors, and set their FLOOR_HEIGHTABOVELEVEL_PARAM parameter value to zero.
  • Modify each and every curve Z coordinate before creating the floors to ensure that the parameter is set to zero to begin with.

Which method to choose depends on how you want your model built.
In some cases, you will want to associate with the nearest level and not use the offsets.
In other cases, you might not care about what level is related to the floor and position them using offsets only.

Presumably, if you set all the horizontal curve profile Z coordinates to the elevation of the level, the floor height above level parameter value will be automatically set to zero.

I implemented a sample application CreateFloors to demonstrate this.
It performs the following steps:

  • Create a list of all the levels in the project.
  • Determine the floor type to use, Generic – 12″.
  • Retrieve the first generic model named WP1 to use as a profile definition element.
  • Traverse the profile definition element geometry and collect all its curves.
  • Use these curves to generate a floor on each of the levels.
  • Set the height above level parameter on each floor to zero, to that it resides on the same height as its associated level.

Here is the source code to achieve these steps:


[Transaction( TransactionMode.Manual )]
public class Command : IExternalCommand
{
  public Result Execute(
    ExternalCommandData commandData,
    ref string message,
    ElementSet elements )
  {
    UIApplication uiapp = commandData.Application;
    UIDocument uidoc = uiapp.ActiveUIDocument;
    Application app = uiapp.Application;
    Document doc = uidoc.Document;
 
    FilteredElementCollector levels
      = new FilteredElementCollector( doc )
        .OfClass( typeof( Level ) );
 
    FloorType floorType
      = new FilteredElementCollector( doc )
        .OfClass( typeof( FloorType ) )
        .First<Element>(
          e => e.Name.Equals( "Generic - 12"" ) )
          as FloorType;
 
    Element profileElement
      = new FilteredElementCollector( doc )
        .OfClass( typeof( FamilyInstance ) )
        .OfCategory( BuiltInCategory.OST_GenericModel )
        .First<Element>(
          e => e.Name.Equals( "WP1" ) );
 
    CurveArray slabCurves = new CurveArray();
 
    GeometryElement geo = profileElement.get_Geometry( new Options() );
 
    foreach( GeometryInstance inst in geo.Objects )
    {
      foreach( GeometryObject obj in inst.SymbolGeometry.Objects )
      {
        if( obj is Curve )
        {
          slabCurves.Append( obj as Curve );
        }
      }
    }
 
    XYZ normal = XYZ.BasisZ;
 
    Transaction trans = new Transaction( doc );
    trans.Start( "Create Floors" );
 
    foreach( Level level in levels )
    {
      Floor newFloor = doc.Create.NewFloor( slabCurves,
        floorType, level, false, normal );
 
      newFloor.get_Parameter(
        BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM ).Set( 0 );
    }
 
    trans.Commit();
 
    return Result.Succeeded;
  }
}

These are some sample levels to use to create floors on:

Floor creation levels

This is the generic model that the floor profile is read from:

Floor creation generic model

Here are the resulting floors:

Floor creation result

Here is
CreateFloors.zip containing
the complete Visual Studio solution, C# source code, and add-in manifest file of the CreateFloors external command.


Comments

14 responses to “Floor Creation”

  1. Rudolf Honke Avatar
    Rudolf Honke

    Hi Jeremy,
    I’ve made the experience that creating new floors may fail if the FloorType is too complex. The thinner and simpler its CompoundStructure is, the more probably the method will do the job.
    Just search for the simpliest FloorType when using the NewFloor methods. You may apply the correct FloorType after Floor creation.
    Bye,
    Rudolf

  2. Dear Rudolf,
    Thank you for the interesting observation and good advice.
    If you ever run into such a situation again, please submit a DevHelp Online case with the sample code and model immediately, so that we can explore and fix the problem.
    Cheers, Jeremy.

  3. Rudolf Honke Avatar
    Rudolf Honke

    Hi Jeremy,
    I’ll do so.
    If there is some time for it…
    It may be that this behaviour occurred in a beta version, so it may already be fixed.
    Bye,
    Rudolf

  4. Dear Jeremy,
    Thank you so much!
    Guming.

  5. Jeremy,
    Is there any way to constrain a floor edge to a particular wall or reference similar to an align/lock in the main interface? Even better, can you associate a floor sketch line with a wall somehow? I’ve looked but can’t find anything…

  6. Dear Steve,
    The ItemFactoryBase.NewAlignment method might work in a project context as well as in a family one.
    I have only tested it in the family API myself.
    Cheers, Jeremy.

  7. Thanks for posting the source code to creating those floors, I appreciate it!

  8. Rolando Karlos Avatar
    Rolando Karlos

    Hi Jeremy. I´m trying to pick a Mass Face to create a floor, but always prompts me that an error happened and nothing happens. I´m using Revit 2011.

  9. Dear Rolando,
    I never had problems with that, so I would suggest that you look at some of the sample code implementing such a selection, e.g. using the Selection.PickObject method.
    It is unchanged between Revit 2011 and 2012, and there are numerous examples of calling it here on the blog.
    Cheers, Jeremy.

  10. Hi Jeremy,
    I know this is an old post so you may not see this but worth a try… I have a quandry regarding the CurveArray passed to the NewFloor method that I’m having trouble with. Basically it seems that when I pass the CurveArray, some lines ‘jump’ to different locations about 25% of the time and I can’t figure out why. I have created model lines from the CurveArray which come out correctly, then passed the CurveArray in the next line of code to the NewFloor method and experienced the jump.
    I posted a more thorough description on AUGI at http://forums.augi.com/showthread.php?p=1166825#post1166825 and it seems that someone else is having that issue with joining walls. Anyway, I was wondering if you knew of any ‘magic’ in the API that I may be missing that would cause this?
    Thanks for any help you can give,
    Steve Faust

  11. foreach (GeometryInstance inst in geo.Objects)
    In Revit 2014 error, “geo.Objects” What does it mean ?
    and ask how to fix it?
    Thank you ~

  12. Dear James,
    This modification has been documented about a million times, so you probably found a solution for it yourself by now.
    Still, for the sake of completeness, I’ll repeat once more that the geometry object itself was made iterable, so you can simply replace the ‘geo.Objects’ property by ‘geo’ itself.
    Cheers, Jeremy.

  13. David Martinez Avatar
    David Martinez

    Dear Jeremy:
    I’m trying to create floor in the view active, but do not know how. Please help me.
    Thanks very much.
    Cheers,
    David

  14. Dear David,
    Simply run the code above in the active view.
    Cheers, Jeremy.

Leave a Reply to Steve FaustCancel reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading