Announcements
Due to scheduled maintenance, the Autodesk Community will be inaccessible from 10:00PM PDT on Oct 16th for approximately 1 hour. We appreciate your patience during this time.
Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Extract the names of the rooms separated by a wall

5 REPLIES 5
SOLVED
Reply
Message 1 of 6
Anonymous
912 Views, 5 Replies

Extract the names of the rooms separated by a wall

Hello, 

 

I use Revit to model my projects, then I export the BOMs to an excel that creates my quotes for clients. However, I am running into a problem: 

 

When I need to demolish (or create) a wall, I would like to see its location, if any, appear in the BOM. 

For example, if I break a wall between the kitchen and the living room, I would like to see "kitchen" or "living room", or even both, next to the surfaces. But I can't find a way to implement this. 

 

Do you have any ideas to help me? 

 

Thank you!

Translated with www.DeepL.com/Translator (free version)

Labels (3)
5 REPLIES 5
Message 2 of 6
RPTHOMAS108
in reply to: Anonymous

Via the API you can use use Room.GetBoundarySegments

 

This will return a nested list of BoundarySegment from which you can get BoundarySegment.ElementId or BoundarySegment.LinkElementId

 

Then it is just a case or matching the ElementId up with the wall id and pairing with the room(s). 

Message 3 of 6
RPTHOMAS108
in reply to: RPTHOMAS108

Some walls will be part of more than two rooms.

 

 Private Function Obj_210629a(ByVal commandData As Autodesk.Revit.UI.ExternalCommandData,
ByRef message As String, ByVal elements As Autodesk.Revit.DB.ElementSet) As Result

        Dim UIDoc As UIDocument = commandData.Application.ActiveUIDocument
        If UIDoc Is Nothing Then Return Result.Cancelled Else
        Dim IntDoc As Document = UIDoc.Document

        Dim FEC As New FilteredElementCollector(IntDoc)
        Dim ECF As New ElementCategoryFilter(BuiltInCategory.OST_Rooms)
        Dim Els As List(Of ElementId) = FEC.WherePasses(ECF).WhereElementIsNotElementType.ToElementIds

        Dim WallRefs As New Dictionary(Of ElementId, List(Of String))
        For i = 0 To Els.Count - 1
            Dim Rm As Room = IntDoc.GetElement(Els(i))

            Dim BSegs As IList(Of IList(Of BoundarySegment)) = Rm.GetBoundarySegments(New SpatialElementBoundaryOptions)
            For x = 0 To BSegs.Count - 1
                Dim BSegs0 As IList(Of BoundarySegment) = BSegs(x)
                For y = 0 To BSegs0.Count - 1
                    Dim Bseg As BoundarySegment = BSegs0(y)
                    If Bseg.ElementId <> ElementId.InvalidElementId Then
                        Dim CurRef As List(Of String)
                        If WallRefs.ContainsKey(Bseg.ElementId) Then
                            CurRef = WallRefs(Bseg.ElementId)
                        Else
                            CurRef = New List(Of String)
                            WallRefs.Add(Bseg.ElementId, CurRef)
                        End If

                        Dim Rm_el As Element = Rm 'Name property of Room is WriteOnly but Name property of Element isn't.
                        Dim RoomName As String = Rm_el.Name
                        If CurRef.Contains(RoomName) = False Then
                            CurRef.Add(RoomName)
                        End If

                    End If

                Next
            Next
        Next

        Dim FECw As New FilteredElementCollector(IntDoc)
        Dim ECFw As New ElementClassFilter(GetType(Wall))
        Dim Elsw As List(Of ElementId) = FECw.WherePasses(ECFw).ToElementIds

        Using Tx As New Transaction(IntDoc, "Name walls based on rooms")
            If Tx.Start = TransactionStatus.Started Then

                For i = 0 To Elsw.Count - 1
                    'Some boundary segments will not relate to walls.
                    If WallRefs.ContainsKey(Elsw(i)) Then

                        Dim El As Element = IntDoc.GetElement(Elsw(i))

                        'Using instance comments parameter for convenience
                        Dim P As Parameter = El.Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS)
                        If P Is Nothing Then Continue For Else

                        Dim Refs As List(Of String) = WallRefs(Elsw(i))
                        Refs.Sort()
                        Dim V As New Text.StringBuilder
                        For j = 0 To Refs.Count - 1
                            If j = Refs.Count - 1 Then
                                V.Append(Refs(j))
                            Else
                                V.Append(Refs(j) & " / ")
                            End If
                        Next
                        P.Set(V.ToString)

                    End If
                Next
                Tx.Commit()
            End If
        End Using
        Return Result.Succeeded
    End Function
Message 4 of 6
jeremy_tammik
in reply to: RPTHOMAS108

Very nice sample code snippet indeed! Thank you very much for that.

 

To expand slightly on Richard's rather terse explanation: Richard's code does two things:

  

  • For all rooms, for each bounding wall, determine all the neighbouring rooms and create a dictionary mapping the wall element id to a list of the rooms it bounds
  • For each wall element id in the dictionary created above, add a list of the names of all the rooms it bounds to its comment field 

 

Cool.

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 5 of 6
jeremy_tammik
in reply to: RPTHOMAS108

Ported Richard's very nice VB.NET implementation to C# and The Building Coder samples:

 

https://github.com/jeremytammik/the_building_coder_samples/compare/2022.0.150.14...2022.0.150.15

 

    // Originally implemented by Richard @RPTHOMAS108 Thomas in VB.NET in
    // https://forums.autodesk.com/t5/revit-api-forum/extract-the-names-of-the-rooms-separated-by-a-wall/m-p/10428696

    /// <summary>
    /// For all rooms, determine all adjacent walls,
    /// create dictionary mapping walls to adjacent rooms,
    /// and tag the walls with the adjacent room names.
    /// </summary>
    void TagWallsWithAdjacentRooms( Document doc )
    {
      FilteredElementCollector rooms
        = new FilteredElementCollector( doc )
          .WhereElementIsNotElementType()
          .OfCategory( BuiltInCategory.OST_Rooms );

      Dictionary<ElementId, List<string>> map_wall_to_rooms
        = new Dictionary<ElementId, List<string>>();

      SpatialElementBoundaryOptions opts
        = new SpatialElementBoundaryOptions();

      foreach( Room room in rooms )
      {
        IList<IList<BoundarySegment>> loops 
          = room.GetBoundarySegments( opts );

        foreach (IList<BoundarySegment> loop in loops )
        {
          foreach( BoundarySegment seg in loop )
          {
            ElementId idWall = seg.ElementId;

            if( ElementId.InvalidElementId != idWall )
            {
              if(!map_wall_to_rooms.ContainsKey(idWall))
              {
                map_wall_to_rooms.Add( 
                  idWall, new List<string>() );
              }

              string room_name = room.Name;

              if(!map_wall_to_rooms[idWall].Contains( room_name ) )
              {
                map_wall_to_rooms[ idWall ].Add( room_name );
              }
            }
          }
        }
      }

      using( Transaction tx = new Transaction( doc ) )
      {
        tx.Start( "Add list of adjacent rooms to wall comments" );

        Dictionary<ElementId, List<string>>.KeyCollection ids
          = map_wall_to_rooms.Keys;

        foreach( ElementId id in ids )
        {
          Element wall = doc.GetElement( id );

          Parameter p = wall.get_Parameter(
            BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS );

          if( null != p )
          {
            string s = string.Join( " / ", 
              map_wall_to_rooms[ id ] );

            p.Set( s );
          }
        }
        tx.Commit();
      }
    }

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 6 of 6
jeremy_tammik
in reply to: Anonymous

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Rail Community


Autodesk Design & Make Report