Room and Wall Adjacency

Question:
How can I obtain the part of a wall that touches a room, especially its face area?
The wall can be adjacent to more than one room.

Answer:
You will probably find the Room object’s Boundary property useful.
It returns the boundary of the room in a BoundarySegmentArrayArray object, i.e. an array of boundaries or loops.
A room may have more than one boundary loop if its floor surface contains holes, which is why this returns an array of arrays.
Each boundary consists of a BoundarySegmentArray item, which is a list of BoundarySegment elements.
Each such element represents a segment of a room boundary and has a property Element, which provides access to the element that is responsible for producing this boundary segment.
That means that from the room, you can figure out what part of its boundary is generated by which wall.
If you then go to each of these bounding walls, you can ask it for further information to discover the surface area that it generates adjacent to the given room.

The use and analysis of the Room Boundary property is demonstrated by the RoomViewer SDK sample.

I implemented a new external command class CmdRoomWallAdjacency to demonstrate the principle.
It analyses the currently selected rooms in the model, or all rooms if none have been selected.
For each room, it iterates over all its boundary segments and lists the bounding elements and their adjacent length, i.e. the length of the curve that they generate which forms part of the room boundary.
This may well be less than the total length of the element.
For all wall elements, its total length and its total area are also listed.
The total area of a wall is queried from the built-in parameter HOST_AREA_COMPUTED, as discussed in our early post on

selecting all walls
.

We have already discussed more complex ways of calculating areas for

2D

and

3D

polygons and their

transformations

directly from the underlying wall geometry, instead of relying on the black box result provided by the built-in parameter.
The

plan topology

object provided by the Revit API may also be useful in this context.

Here is the implementation of the command mainline:


Application app = commandData.Application;
Document doc = app.ActiveDocument;
 
List<Element> rooms = new List<Element>();
if( !Util.GetSelectedElementsOrAll(
  rooms, doc, typeof( Room ) ) )
{
  Selection sel = doc.Selection;
  message = ( 0 < sel.Elements.Size )
    ? "Please select some room elements."
    : "No room elements found.";
  return CmdResult.Failed;
}
foreach( Room room in rooms )
{
  DetermineAdjacentElementLengthsAndWallAreas(
    room );
}
return CmdResult.Failed;

It retrieves the currently selected rooms in the model, or all rooms if none have been selected, using the utility method GetSelectedElementsOrAll, and then iterates over each wall, applying the worker method DetermineAdjacentElementLengthsAndWallAreas to it.
Here is the implementation of the worker method:


void DetermineAdjacentElementLengthsAndWallAreas(
  Room room )
{
  BoundarySegmentArrayArray boundaries
    = room.Boundary;
 
  int n = boundaries.Size;
 
  Debug.Print(
    "{0} has {1} boundar{2}{3}",
    Util.ElementDescription( room ),
    n, Util.PluralSuffixY( n ),
    Util.DotOrColon( n ) );
 
  int iBoundary = 0, iSegment;
 
  foreach( BoundarySegmentArray b in boundaries )
  {
    ++iBoundary;
    iSegment = 0;
    foreach( BoundarySegment s in b )
    {
      ++iSegment;
      Element neighbour = s.Element;
      Curve curve = s.Curve;
      double length = curve.Length;
 
      Debug.Print(
        "  Neighbour {0}:{1} {2} has {3}"
        + " feet adjacent to room.",
        iBoundary, iSegment,
        Util.ElementDescription( neighbour ),
        Util.RealString( length ) );
 
      if( neighbour is Wall )
      {
        Wall wall = neighbour as Wall;
 
        Parameter p = wall.get_Parameter(
          BuiltInParameter.HOST_AREA_COMPUTED );
 
        double area = p.AsDouble();
 
        LocationCurve lc
          = wall.Location as LocationCurve;
 
        double wallLength = lc.Curve.Length;
 
        Debug.Print(
          "    This wall has a total length"
          + " and area of {0} feet and {1}"
          + " square feet.",
          Util.RealString( wallLength ),
          Util.RealString( area ) );
      }
    }
  }
}

It retrieves the room boundaries, prints a report on their number and the room identity, iterates over the boundaries and their segments, and checks each segment for the adjacent generating elements.
If the neighbouring element is a wall, its total length and area are also listed.

Here is the result of running this command on a simple square house containing one single room:


Rooms  has 1 boundary:
Neighbour 1:1 Walls  has 22.31 feet adjacent to room.
This wall has a total length and area of 22.97 feet and 283.65 square feet.
Neighbour 1:2 Walls  has 12.47 feet adjacent to room.
This wall has a total length and area of 13.12 feet and 172.22 square feet.
Neighbour 1:3 Walls  has 22.31 feet adjacent to room.
This wall has a total length and area of 22.97 feet and 301.39 square feet.
Neighbour 1:4 Walls  has 12.47 feet adjacent to room.
This wall has a total length and area of 13.12 feet and 163.61 square feet.

The reason for the varying surfaces reported for the walls is due to the way their connections and intersections in the corners of the house have been generated by Revit.

Here is the output when a room is bounded by some walls that extend out beyond the room, so that only part of them are actually adjacent to it:


Rooms  has 1 boundary:
Neighbour 1:1 Walls  has 5.91 feet adjacent to room.
This wall has a total length and area of 42.65 feet and 1119.45 square feet.
Neighbour 1:2 Walls  has 4.27 feet adjacent to room.
This wall has a total length and area of 4.92 feet and 111.94 square feet.
Neighbour 1:3 Walls  has 5.91 feet adjacent to room.
This wall has a total length and area of 19.69 feet and 499.45 square feet.
Neighbour 1:4 Walls  has 4.27 feet adjacent to room.
This wall has a total length and area of 9.84 feet and 241.11 square feet.

As you can see, the room boundary curve only reports the adjacent length, whereas the total wall length for some of the walls is much larger.

To determine the adjacent surface area is trivial if the wall has a constant height, since in that case it is a constant factor multiplied by the wall length. If the height varies, it becomes more complex.

Many thanks to Massimiliano Revelli of

Informatica System srl

for raising this issue.


Comments

14 responses to “Room and Wall Adjacency”

  1. Howard Roman Avatar
    Howard Roman

    This is off of this topic but you might be able to help. Is there a way in the family editor to align to faces of a layer of a composite wall. For instance, if I want the inside of a sill to always align flush with the inside face of the brick exterior of the wall. If this isn’t in your realm, who might know. Thanks

  2. Hi Howard,
    It is possible through the API to determine the exact location of the internal layers of a composite wall. This is demonstrated in
    http://thebuildingcoder.typepad.com/blog/2008/11/wall-compound-layers.html
    Unfortunately, this will not help you at all inside the family editor, because the API is not active in that context. I do not know whether you have access to the data of the wall’s internal layer structure through other means in the family editor.
    Cheers, Jeremy.

  3. Jeremy,
    I love your blog, but i don’t have a clue about C#..
    But i like the posibilities it has.
    Is it posible to add a wall sweep to the walls of the room boundery. And to place the wall sweep only over the portion of the wall that is in the room.
    This way you would be able to apply a wall finish automaticly….

  4. Dear Arno,
    Wow, thank you very much for your appreciation! Sorry to hear that C# is not your thing. As I pointed out a few times, all .NET languages are equivalent and code can be automatically translated from one to the other.
    I don’t know off hand about your wall sweep issue. Is it possible to achieve what you wish through the user interface? If not, it is probably not possible through the API either.
    Cheers, Jeremy.

  5. Dawit Ghebrehiwet Avatar
    Dawit Ghebrehiwet

    Hello Jeremy,
    thank you for this wonderful site. I am currently working on my master thesis and your blog is a wonderful ressource for the BIM part with Revit. Currently i am facing a problem i have not been able to solve. I am trying to find out the ‘to room’ and ‘from room’ for a given set of doors. Working with VS 2008 and Autodesk Revit MEP 2010 in C# i am trying to find out if a door is connecting two rooms:
    ElementSetIterator elementsetiteratorBIMDoors = bimdoors.getBIMDoors().ForwardIterator();
    while (elementsetiteratorBIMDoors.MoveNext())
    {
    Autodesk.Revit.Element elementDoor = elementsetiteratorBIMDoors.Current as Autodesk.Revit.Element;
    if ((null != elementDoor.get_Parameter(BuiltInParameter.FROM_ROOM_ID)) && (null != elementDoor.get_Parameter(BuiltInParameter.FROM_ROOM_ID)))
    {
    string sDoorFromRoomID = elementDoor.get_Parameter(BuiltInParameter.FROM_ROOM_ID).ToString();
    string sDoorToRoomID = elementDoor.get_Parameter(BuiltInParameter.TO_ROOM_ID).ToString();
    graph.addLink(new Link(sDoorFromRoomID, sDoorToRoomID));
    }
    }
    This approach seem not work because the return value of elementDoor.get_Parameter(BuiltInParameter.FROM_ROOM_ID) is always null.
    I have read on http://thebuildingcoder.typepad.com/blog/2009/02/rvtmgddbg.html that “Built-in parameters are not an officially supported portion of API. In future we expect it will be replaced by data being properly exposed as a property.”
    Is that statement true?
    Can anyone point me to an efficient way to get the relation between doors and rooms.
    Thanks a lot,
    Dawit Ghebrehiwet

  6. Dear Dawit,
    Thank you for your appreciation, I am glad you like it and find it useful.
    The statement that you refer to was once made and has not been revoked, but on the other hand every single Revit application that I am aware of does make use of parameters after all, so it is to be taken with a large pinch of salt.
    On the ‘third’ hand, since a door is always a FamilyInstance object, you should be able to make use of the FamilyInstance FromRoom and ToRoom properties and not need to resort to any direct parameter access after all:
    – FromRoom: The room from which the door or window is opened.
    – ToRoom: The room to which the door or window is opened.
    If for some reason that does not work, you can always go back to basics and make use of the GetRoomAtPoint method. Simply take the insertion point of the door, use a perpendicular offset vector to define points in the two adjacent rooms, and feed them into that method to determine their identities.
    Another interesting method in this context is Room.IsPointInRoom, which determines whether a given point lies within the volume of a room. The similar Space.IsPointInSpace method is used to analyse space adjacencies, a problem similar to the one you describe, in
    http://thebuildingcoder.typepad.com/blog/2009/07/space-adjacency.html
    I hope this helps and wish you the best of luck!
    Cheers, Jeremy.

  7. Chris Eversole Avatar
    Chris Eversole

    JEREMY,
    Please help. I am new to coding and C# and I am trying to build a complete app based off of the sample code you showed above. Can you please complete the full code so a newbie like me can see and try to understand.

  8. Kenny Geyskens Avatar
    Kenny Geyskens

    Hi Jeremy, would this also work with walls in separate linked documents while the room is defined on the top-level doc?

  9. Dear Kenny,
    Interesting question. It would depend on whether the BoundarySegment.Element property returns the walls in linked documents. Please try it out and let us know. Thank you!
    Cheers, Jeremy.

  10. Arif Hanif Avatar
    Arif Hanif

    Jeremy,
    Love the website, I have recently started to learn C# and have started exploring the API to help with MEP Design. It has been frustrating dealing with gbXML. I am trying to get Wall Area and Orientation for Room to excel. Can you point me to some of your past postings that could help me.
    Arif

  11. Dear Arif,
    Thank you for your appreciation.
    I am glad you like The Building Coder.
    There are a lot of discussions on getting the wall area, e.g.
    Mass quantities: Revit SDK MaterialQuantities sample
    http://thebuildingcoder.typepad.com/blog/2010/02/material-quantity-extraction.html
    2D Polygon Areas and Outer Loop
    http://thebuildingcoder.typepad.com/blog/2008/12/2d-polygon-areas-and-outer-loop.html
    Here is a recent discussion on getting the wall net and gross surface:
    http://forums.autodesk.com/t5/revit-api/door-window-areas/td-p/5535565
    For the orientation, here are some starting points:
    Azimuth
    http://thebuildingcoder.typepad.com/blog/2008/10/azimuth.html
    Facing North
    http://thebuildingcoder.typepad.com/blog/2010/01/project-location.html
    Cheers, Jeremy.

  12. Dear Arif,
    I summarised our little conversation and added a few more pointers that might be of interest to you here:
    http://thebuildingcoder.typepad.com/blog/2015/03/calculating-gross-and-net-wall-areas.html#2
    I hope this helps.
    Cheers, Jeremy.

  13. Dear Jeremy,
    I’ve got some questions concerning above topic.
    1. We have found out that some walls are not recognized by the room, because these walls do not get to become room bounded. For example when you have two walls stacked up on each other, when the upper wall is smaller than the bottom wall, the bottom wall is room bounded and the upper wall is not. How can you find these missing (upper) walls?
    2. How can I get the wall adjacency for composite walls if the wall is separated into parts by using the “create parts” function? For example a separating composite wall with cavity does not see two room adjacencies, because the cavity has no room/space.
    3. Is there any way to get the building envelope data (construction areas of outer facade, roofs, ground floors) without having rooms/spaces defined? For example when a user only has modeled constructions such as walls, floors and roofs?
    4. What if some rooms (eg. ventilation shafts and spaces behind retention walls) don’t have room definitions? Will this become adjacent to outside? Can you ignore these unintended wall adjacencies?
    I may have missed already given answers to above questions. If so, can you please provide URL’s to further reading?
    Appreciate your answers very much!
    Regards,
    Geert

  14. Dear Geert,
    I hope and believe that the SpatialElementGeometryCalculator class can answer all of the questions you raise.
    Can you please take a look at the following much more recent discussion and let us know whether that helps solve them and addresses all your needs?
    http://thebuildingcoder.typepad.com/blog/2015/03/findinserts-retrieves-all-openings-in-all-wall-types.html
    e553e16897883301b7c7789a82970b
    Please also note the relevant additional questions raised and addressed there in the comment by Håkon Clausen.
    I hope this helps.
    Cheers, Jeremy.

Leave a Reply

Discover more from Autodesk Developer Blog

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

Continue reading