Create a 3D View with Section Box for each Level

In a comment on the Payette blog, it was asked how to make a 3D view showing a single floor of a building. This is done with the Section Box, and I thought it would make a good API sample to make a 3D view with Section Box for every level of a project.

Here are the set of 3D views that the macro creates, one for each of the 5 levels in the project.

3dSectionBox

To start, here is a small macro to create a 3d view.  It introduces the new concept of ViewFamilyType. If you click Edit Type when the Properties of a view are shown, the Type that is shown in the ViewFamilyType. Many Revit users probably ever have to deal with this Type, but to create a view with the API it needs to be specified.

ViewFamilyType

public void create3DView()
{
    Document doc = this.ActiveUIDocument.Document;

    // get a ViewFamilyType for a 3D View
    ViewFamilyType viewFamilyType = (from v in new FilteredElementCollector(doc).
                 OfClass(typeof(ViewFamilyType)).
                 Cast<ViewFamilyType>()
                 where v.ViewFamily == ViewFamily.ThreeDimensional
                 select v).First();

    using (Transaction t = new Transaction(doc,"Create view"))
    {    
        t.Start();
        View3D view = View3D.CreateIsometric(doc, viewFamilyType.Id);
        t.Commit();
    }
}

Building on that, here is the macro to create the set of views shown above and set the Section Boxes based on the height of each level.

public void create3DViewsWithSectionBox()
{
    Document doc = this.ActiveUIDocument.Document;
    UIDocument uidoc = new UIDocument(doc);

    // get list of all levels
    IList<Level> levels = new FilteredElementCollector(doc).OfClass(typeof(Level)).Cast<Level>().OrderBy(l => l.Elevation).ToList();

    // get a ViewFamilyType for a 3D View
    ViewFamilyType viewFamilyType = (from v in new FilteredElementCollector(doc).
                                     OfClass(typeof(ViewFamilyType)).
                                     Cast<ViewFamilyType>()
                                     where v.ViewFamily == ViewFamily.ThreeDimensional
                                     select v).First();

    using (Transaction t = new Transaction(doc,"Create view"))
    {
        int ctr = 0;
        // loop through all levels
        foreach (Level level in levels)
        {
            t.Start(); 

            // Create the 3d view
            View3D view = View3D.CreateIsometric(doc, viewFamilyType.Id);

            // Set the name of the view
            view.Name = level.Name + " Section Box";

            // Set the name of the transaction
            // A transaction can be renamed after it has been started
            t.SetName("Create view " + view.Name);

            // Create a new BoundingBoxXYZ to define a 3D rectangular space
            BoundingBoxXYZ boundingBoxXYZ = new BoundingBoxXYZ();

            // Set the lower left bottom corner of the box
            // Use the Z of the current level.
            // X & Y values have been hardcoded based on this RVT geometry
            boundingBoxXYZ.Min = new XYZ(-50, -100, level.Elevation);

            // Determine the height of the bounding box
            double zOffset = 0;
            // If there is another level above this one, use the elevation of that level
            if (levels.Count > ctr + 1)
                zOffset = levels.ElementAt(ctr+1).Elevation;
            // If this is the top level, use an offset of 10 feet
            else
                zOffset = level.Elevation + 10;
            boundingBoxXYZ.Max = new XYZ(200, 125, zOffset);

            // Apply this bouding box to the view's section box
            view.SectionBox = boundingBoxXYZ;

            t.Commit();

            // Open the just-created view
            // There cannot be an open transaction when the active view is set
            uidoc.ActiveView = view;

            ctr++;            
        }
    }
}

UPDATE: The list of levels is now sorted by Elevation with the addition of “OrderBy(l => l.Elevation)”

Advertisements

6 thoughts on “Create a 3D View with Section Box for each Level

  1. You probably want to sort the levels list by elevation. Using LINQ’s OrderBy – this is straight forward:

    IList levels = new FilteredElementCollector(doc).OfClass(typeof(Level)).Cast().OrderBy ( lvl => lvl.Elevation).ToList();

  2. Just what I was looking for, thanks.
    One thought though, you might want to filter the levels further to include only building story levels; some models have multi leveled stories and you don’t want to end up with a 2 feet high section box!

    Cheers,
    Sam

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s