We already looked at some examples of confusion due to the interaction of phases with the room property on family instances. Here is a new aspect of this encountered and solved by Patrick Rosendahl of SOLAR-COMPUTER GmbH, who kindly explains the issue and its resolution like this:
Problem: I am having a problem with the FamilyInstance Room property. I looked at the discussion of issues with the Room property and its phase dependency but have not been able to solve it yet.
This is the situation:
These are the problems encountered:
Questions:
As a workaround, I thought of calling the get_Room method on the family instance in a loop over all available phases in the project, and making use of the document PointInRoom method if that fails.
Solution: Here is a promising start for a solution that I am currently exploring:
foreach(Phase p) { familyinstance.get_Room(p) }
foreach(Room r where r.DesignOption.IsPrimary) { r.IsPointInRoom( fi.Location ) }
foreach( Room r ) { r.IsPointInRoom( fi.Location ) }
Here is the actual method implementating this that I am currently working with, including some todo items left as an exercise for the reader ;)
public static Room DetermineRoom( Element el ) { FamilyInstance fi = el as FamilyInstance; if( fi == null ) { return null; } // As simple as that? try { if( fi.Room != null ) { //Debug.WriteLine("fi.Room != null"); return fi.Room; } } catch { } // Try phasing Room r = null; foreach( Phase p in el.Document.Phases ) { try { // TODO should check fi.GetPhaseStatus // instead of provoking an exception r = fi.get_Room( p ); if( r != null ) { //Debug.WriteLine("fi.get_Room( " // + p.Name + ") != null"); return r; } } catch { } } LocationPoint lp = el.Location as LocationPoint; if( lp != null ) { // Try design options List<Element> roomlst = get_Elements( el.Document, typeof( Room ) ); // Try rooms from primary design option foreach( Element roomel in roomlst ) { Room priroom = roomel as Room; if( priroom == null ) continue; if( priroom.DesignOption == null ) continue; if( priroom.DesignOption.IsPrimary ) { // TODO should check whether priroom // and el phasing overlaps if( priroom.IsPointInRoom( lp.Point ) ) { //Debug.WriteLine( // "priroom.IsPointInRoom != null"); return priroom; } } } // Emergency: try any room foreach( Element roomel in roomlst ) { Room room = roomel as Room; if( room == null ) continue; // TODO should check whether room // and el phasing overlaps if( room.IsPointInRoom( lp.Point ) ) { //Debug.WriteLine( // "room.IsPointInRoom != null"); return room; } } } // Nothing found return null; }
I think this approach provides is a good starting point. A more complete solution might possibly take the phase and design option as arguments. In my context, the function above rarely returns a non-primary design option room.
Many thanks to Patrick for his research and sharing this solution!