Ceiling thickness

Ceiling thickness

Anonymous
Not applicable
5,390 Views
10 Replies
Message 1 of 11

Ceiling thickness

Anonymous
Not applicable

I would greatly appreciate if someone could send me some information about Revit API 2011 ceiling thickness data collection.
I would like to share part of C# code how do I get information about wall layers thickness:

CompoundStructure comStruct = aWallType.CompoundStructure;
Categories allCategories = doc.Settings.Categories;
Category wallCategory = allCategories.get_Item(BuiltInCategory.OST_Walls);
Autodesk.Revit.DB.Material wallMaterial = wallCategory.Material;
foreach (CompoundStructureLayer structLayer in comStruct.Layers)
{
    double thickness = structLayer.Thickness;        // INFORMATION ABOUT WALL LAYER THICKNESS
    Autodesk.Revit.DB.Material layerMaterial = structLayer.Material;
    if (null == layerMaterial)
    {
        layerMaterial = wallMaterial;
    }
}

This part of code work perfectly for walls but it is impossible to use it in case of ceilings. I found some information about getting celing layer thickness in "Revit 2011 API Developer’s Guide" and it is as follows:
"11.5.2 Ceiling
Ceiling does not have a specific class, so you can‘t create it using the API. The Ceiling object is an Element in the OST_Ceilings category.
The Ceiling element type is HostObjAttributes using the OST_Ceilings category with its CompoundStructure available." [Revit 2011 API Developer’s Guide, page 124]
but I do not know how to impement it.

0 Likes
Accepted solutions (1)
5,391 Views
10 Replies
Replies (10)
Message 2 of 11

BobbyC.Jones
Advocate
Advocate

Section 11.6 states that the CompoundStructure property is on the HostObjAttrbutes object.  Section 11.5.2 that you posted states that Ceiling element types are HostObjAttrbutes objects in the OST_Ceilings category. 

 

So once you find an element type with the OST_Ceilings category set, then cast it to a HostObjAttributes object and then you'll have access to the CompoundStructure property.

 

Let me know if you need a code sample.

--
Bobby C. Jones
0 Likes
Message 3 of 11

Anonymous
Not applicable

First of all I would like to thank you for fast reply.
I am beginner in Revit API so I would appreciate if you send me some code sample.

0 Likes
Message 4 of 11

BobbyC.Jones
Advocate
Advocate

 


@Anonymous wrote:

First of all I would like to thank you for fast reply.
I am beginner in Revit API so I would appreciate if you send me some code sample.


The code formatting is foobar'd here, so I included an attachment that should read better.  But this little snippet is the crux of what I suggested.  This filter selects all element types, with the ceiling catagory, and casts them to HostObjAttributes.  In this quick example I also filter out the non-compound ceilings, which you may or may not need to do, and which there may or may not be better ways to do.  I would love to see your final code as this has exhausted my knowledge in this area of the API and I'm sure that you'll discover much more as you delve into it.

 

collector.WhereElementIsElementType()
         .OfCategoryId(ceilingCatagory.Id)
         .Cast<HostObjAttributes>()
         .Where(ceiling => ceiling.CompoundStructure != null);

 

 

    public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
    {
      Document activeDoc = commandData.Application.ActiveUIDocument.Document;
      Category ceilingCatagory = activeDoc.Settings.Categories.get_Item(BuiltInCategory.OST_Ceilings);

      FilteredElementCollector collector = new FilteredElementCollector(activeDoc);
      IEnumerable<HostObjAttributes> ceilings = collector.WhereElementIsElementType()
                                                         .OfCategoryId(ceilingCatagory.Id)
                                                         .Cast <HostObjAttributes>()
                                                         .Where(ceiling => ceiling.CompoundStructure != null);

      StringBuilder ceilingInfoText = new StringBuilder();

      foreach (HostObjAttributes ceiling in ceilings)
      {
        ceilingInfoText.AppendLine(ceiling.Name);

        double ceilingThickness = ceiling.CompoundStructure.Layers
                                                           .OfType<CompoundStructureLayer>()
                                                           .Sum(layer => layer.Thickness);

        ceilingInfoText.AppendLine(ceilingThickness.ToString());
        ceilingInfoText.AppendLine();
      }

      TaskDialog.Show("Ceiling Thickness Example", ceilingInfoText.ToString());

      return Result.Succeeded;
    }

 

--
Bobby C. Jones
0 Likes
Message 5 of 11

BobbyC.Jones
Advocate
Advocate


@BobbyC.Jones wrote:

 

The code formatting is foobar'd here 


I take that back, this looks good, it was only bad in preview pane.
--
Bobby C. Jones
0 Likes
Message 6 of 11

Anonymous
Not applicable

Thank you very much!

I will go through it today or tommorow...

0 Likes
Message 7 of 11

Anonymous
Not applicable

I have a time to go through the source code. Unfortunately, after debugging process I get two error messages:

......

IEnumerable<HostObjAttributes> ceilings = collector.WhereElementIsElementType()
                                                                   .OfCategoryId(ceilingCatagory.Id)
                                                                   .Cast<HostObjAttributes>()      //<---------Error 1
                                                                   .Where(ceiling => ceiling.CompoundStructure != null);

........

double ceilingThickness = ceiling.CompoundStructure.Layers
                                                                       .OfType<CompoundStructureLayer>() //<------Error2
                                                                       .Sum(layer => layer.Thickness);

.........

---------------------------------------------------------------------------------------------------------------------------------------------------

Description of Error 1:

 'Autodesk.Revit.DB.FilteredElementCollector' does not contain a definition for 'Cast' and no extension method 'Cast' accepting a first argument of type 'Autodesk.Revit.DB.FilteredElementCollector' could be found (are you missing a using directive or an assembly reference?)

Description of Error 2:

 'Autodesk.Revit.DB.CompoundStructureLayerArray' does not contain a definition for 'OfType' and no extension method 'OfType' accepting a first argument of type 'Autodesk.Revit.DB.CompoundStructureLayerArray' could be found (are you missing a using directive or an assembly reference?)
---------------------------------------------------------------------------------------------------------------------------------------------------

Should I add some extra references??

This is a list of references used by my program:

using System;
using System.IO;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Collections;
using Autodesk.Revit.DB;
using System.Text;

 

It will be great if you can help me to solve this problem.

 

0 Likes
Message 8 of 11

BobbyC.Jones
Advocate
Advocate

@Anonymous wrote:

---------------------------------------------------------------------------------------------------------------------------------------------------

Should I add some extra references??

This is a list of references used by my program:

using System;
using System.IO;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Collections;
using Autodesk.Revit.DB;
using System.Text;

 

It will be great if you can help me to solve this problem.

 


Jakub,  you just need to add this:

 

using System.Linq;

 

--
Bobby C. Jones
0 Likes
Message 9 of 11

Anonymous
Not applicable

Dear Mr Jones

 

Thank you very much for solving my problem. Now it works perfectly!

I had to change part of code to adjust it to my needs. Now it finds ceilings existing in document and  shows information about material and thicnness. I left some extra space for Genergic Ceiling

 

Source Code:

-----------------------------------------------------------------------------------------------------------------------------------------

Category ceilingCatagory = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Ceilings);
collector = new FilteredElementCollector(doc);

IEnumerable<HostObjAttributes> docceilings = collector.WhereElementIsElementType().

OfCategoryId(ceilingCatagory.Id).

Cast<HostObjAttributes>();
foreach (HostObjAttributes docceiling in docceilings)
   {
   ElementCategoryFilter filter = new ElementCategoryFilter(BuiltInCategory.OST_Ceilings);
    collector = new FilteredElementCollector(doc);
    IList<Element> ceilings = collector.WherePasses(filter).WhereElementIsNotElementType().ToElements();  
    foreach (Element ceiling in ceilings)
       {
       if (docceiling.Name == ceiling.Name)
          {
           Writer.WriteLine(GetElementFaces(ceiling));
           if (docceiling.CompoundStructure != null)
              {
               foreach (CompoundStructureLayer layer in docceiling.CompoundStructure.Layers)
                  {
                  double thickness = layer.Thickness;
                   Autodesk.Revit.DB.Material layerMaterial = layer.Material;
                   TaskDialog.Show("Ceiling Thickness","Ceiling layer Material: "+layerMaterial.Name +"  Thickness: " + thickness);
                   }
              }
           else
              {
                 //Code for Generic Celiling
             }
          }
       }
   }

----------------------------------------------------------------------------------------------------------------------------------------

I know that It is still not perfect. I will optimize it later.

 

One again thank you very much!!

Yours sincerely

               Jakub Ziółkowski

 

0 Likes
Message 10 of 11

BobbyC.Jones
Advocate
Advocate
Accepted solution

I'm glad that's working for you.  I know you're still working on your code, but I wanted to point out that what you've posted is doing much more work than it needs to.  This example will do the same

 

    public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
    {
      Document activeDoc = commandData.Application.ActiveUIDocument.Document;

      Category ceilingCatagory = activeDoc.Settings.Categories.get_Item(BuiltInCategory.OST_Ceilings);

      FilteredElementCollector collector = new FilteredElementCollector(activeDoc);
      IEnumerable<HostObjAttributes> ceilings = collector.WhereElementIsElementType()
                                                         .OfCategoryId(ceilingCatagory.Id)
                                                         .Cast<HostObjAttributes>()
                                                         .Where(ceiling => ceiling.CompoundStructure != null);

      foreach (HostObjAttributes ceiling in ceilings)
      {
        foreach (CompoundStructureLayer ceilingLayer in ceiling.CompoundStructure.Layers)
        {
          string msg = string.Format("Ceiling layer material: {0}\tThickness: {1}.", ceilingLayer.Material.Name, ceilingLayer.Thickness);
          TaskDialog.Show("Ceiling Thickness", msg);
        }
      }

      return Result.Succeeded;
    }

 

--
Bobby C. Jones
0 Likes
Message 11 of 11

Anonymous
Not applicable

Dear Mr Bobby C. Jones

 

Sorry I have not been replying for so long. Currently I am really busy.

As You wrote yours solution is faster. Than you for help.

 

Yours sincerely

         Jakub Ziółkowski

0 Likes