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: 

GetBoundarySegments doc.GetElement(segment.ElementId) doesn't work as expected

10 REPLIES 10
SOLVED
Reply
Message 1 of 11
AH_Yafim
1501 Views, 10 Replies

GetBoundarySegments doc.GetElement(segment.ElementId) doesn't work as expected

I'm using the following code to try to get all exterior Walls using GetBoundarySegments .

 

Specifically I'm creating a huge room at the model extents, then identifying walls inside that room. (see image)

roomBoundaryissue.JPG

 

def GetWallsFromRoomBoundaries(doc, room):
	ids = []
	loops = room.GetBoundarySegments( SpatialElementBoundaryOptions() )
	for loop in loops:
		for segment in loop:
			print(segment)
			neighbor= doc.GetElement(segment.ElementId)
            print(neighbor)

	        if neighbor.GetType().ToString() == "Autodesk.Revit.DB.Wall":
				ids.Add(neighbor.Id)

	return ids

 

 

print(segments) outputs 2 loops;

- the 4 outside room boundaries

- an array of all the boundary segments of the walls (image above)

 

But print(neighbor) outputs only 2 wall elements.

 

I'm confused as to why doc.GetElement(segment.ElementId) doesn't work as expected.

I'm using Revit 2019, and I understood from the Revit API Documentation that segment.Element is deprecated so I can't use that directly to get the element touching the room boundary.

 

Any ideas?

Thanks

10 REPLIES 10
Message 2 of 11
michael-coffey
in reply to: AH_Yafim

I don't typically work in VB, but my guess is that

if neighbor.GetType().ToString() == "Autodesk.Revit.DB.Wall":

is the problem.  In c# i would say

if (neighbor is Wall)

i think you are getting the wall's type and asking if the string is the class name heirarchy. 

Message 3 of 11

In VB:

 

If Typeof(neighbor) is Wall then
....

 

If that's the problem. 

 

- Michel

Message 4 of 11
Sean_Page
in reply to: AH_Yafim

Not really sure why it is doing that, but I had the same result where it only return one wall even though they were all walls. I got it to work by using a separate definition.

 

#Preparing input from dynamo to revit
element = UnwrapElement(IN[0])

#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)

def GetWallsFromRoomBoundaries(doc, room):
	ids = []
	loops = room.GetBoundarySegments(SpatialElementBoundaryOptions())
	for loop in loops:
		for segment in loop:
			neighbor = doc.GetElement(segment.ElementId)
	        #if neighbor.GetType() == Wall:
			ids.Add(doc.GetElement(neighbor.Id))
	return ids
	
def GetWalls(elems):
	walls = []
	for e in elems:
		if e.GetType() == Wall:
			walls.Add(e)
	return walls

TransactionManager.Instance.TransactionTaskDone()

boundaries = GetWallsFromRoomBoundaries(doc, element)

OUT = GetWalls(boundaries)
Message 5 of 11
AH_Yafim
in reply to: TripleM-Dev.net

Hi guys,

Thank you for the answers.

I think my question might have included code that was misleading to what I am asking.

 

The problem is NOT with the line:

if neighbor.GetType().ToString() == "Autodesk.Revit.DB.Wall":

 

The problem is with the code that comes just before that:

print(segment)
neighbor = doc.GetElement(segment.ElementId)
print(neighbor)

The first print gives me all the correct elements, but the second print only outputs 2 walls.

 

Regardless, I've tried also to play with your suggestions of the if statement and tried:

(BTW I'm writing in Python, not VB)

if neighbor.GetType() == Wall:

if type(neighbor) == Wall:

but both of these didn't improve any results.

 

Again, the if statement isn't the issue. The problem is with the code BEFORE that.

doc.GetElement(segment.ElementId)

The code doesn't retrieve all the elements from the segments,  so something is wrong here.

 

 

Hoping you can help.

Message 6 of 11
lukaskohout
in reply to: AH_Yafim

 

 

IList<IList<BoundarySegment>> loops = room.GetBoundarySegments(options);
List<Wall> walls = new List<Wall>();

foreach(var loop in loops)
{
   foreach(var segment in loops)
   {
      Element e = doc.GetElement(segment.ElementId);
      if (e is Wall)
         walls.Add(e as Wall);
   }                
}

 

Trying your approach in C# works fine.

I created some closed wall boundary and outer limits with Room Separator.

Collection walls return all walls that are boundary for the room.

Have you tried the code on new sample project? 


Hitting Accepted Answer is a Community Contribution from me as well as from you.
======================================================================
Message 7 of 11
AH_Yafim
in reply to: lukaskohout

Hi,

I tried it now on a new project, with 4 walls creating a closed boundary.

This is the code:

 

def RetrieveWallBoundaries(doc, room):
	wallElementIds = []
	loops = room.GetBoundarySegments( SpatialElementBoundaryOptions() )

	for loop in loops:
		for segment in loop:	
			print(segment)
			neighbor = doc.GetElement(segment.ElementId)
	        print(type(neighbor))
	        	        
	        if type(neighbor) == Wall:
				wallElementIds.Add(neighbor.Id)

	return wallElementIds

 

 

The output from the 2 print statements in the segment loop is:

 

<Autodesk.Revit.DB.BoundarySegment object at 0x0000000000001195 [Autodesk.Revit.DB.BoundarySegment]>
<Autodesk.Revit.DB.BoundarySegment object at 0x0000000000001196 [Autodesk.Revit.DB.BoundarySegment]>
<Autodesk.Revit.DB.BoundarySegment object at 0x0000000000001197 [Autodesk.Revit.DB.BoundarySegment]>
<Autodesk.Revit.DB.BoundarySegment object at 0x0000000000001198 [Autodesk.Revit.DB.BoundarySegment]>
<type 'ModelLine'>
<Autodesk.Revit.DB.BoundarySegment object at 0x0000000000001199 [Autodesk.Revit.DB.BoundarySegment]>
<Autodesk.Revit.DB.BoundarySegment object at 0x000000000000119A [Autodesk.Revit.DB.BoundarySegment]>
<Autodesk.Revit.DB.BoundarySegment object at 0x000000000000119B [Autodesk.Revit.DB.BoundarySegment]>
<Autodesk.Revit.DB.BoundarySegment object at 0x000000000000119C [Autodesk.Revit.DB.BoundarySegment]>
<type 'Wall'>

 

 

So as mentioned before, the code finds the large room boundary segments, which don't have walls generating them, and it also finds the 4 boundary segments which are defined by those simple 4 walls, but it only recognizes 1 of those walls in the  neighbor = doc.GetElement(segment.ElementId) line.

Message 8 of 11
Sean_Page
in reply to: AH_Yafim

Did you try using the additional definition like I showed above? Basically I couldn't get them do loop and "type" in the same def, but it worked fine when I split them up.

Message 9 of 11
AH_Yafim
in reply to: Sean_Page

Hi,

The definition you suggested was a bit confusing because you return a variable called ids but actually it contains wall elements.

 

In any case I tried to replicate it:

def RetrieveWallBoundaries(doc, room):
	wallElements = []
	loops = room.GetBoundarySegments( SpatialElementBoundaryOptions() )

	for loop in loops:
		for segment in loop:
			#print(segment)
			neighbor = doc.GetElement(segment.ElementId)
	        #print(type(neighbor))
	        wallElements.Add(neighbor)        
	return wallElements


def GetWallids(wallElements):
	wallids = []
	for w in wallElements:
		if w.GetType() == Wall:
			wallids.Add(w.Id)
			print(w)
	return wallids


# MAIN
walls = RetrieveWallBoundaries(doc, room)
ids = GetWallids(walls)

 

The print(w) line still only prints 1 wall.... 

Message 10 of 11
Sean_Page
in reply to: AH_Yafim

So, not sure why, but I think it has to do with the GetElement and then translating that back to .Id.

 

This works for me it just doesn't use the "neighbor" translation:

 

def RetrieveWallBoundaries(doc, room):
	wallElementIds = []
	loops = room.GetBoundarySegments(SpatialElementBoundaryOptions())
	for loop in loops:
		for i in range(len(loop)):
			if type(doc.GetElement(loop[i].ElementId)) == Wall:
				wallElementIds.Add(loop[i].ElementId)
	return wallElementIds

 

Message 11 of 11
AH_Yafim
in reply to: Sean_Page

Extremely strange that with a range iteration it works but not otherwise..

Thank you for the creative workaround!

 

Maybe someone will see this post later on and enlighten us why this behavior exists.

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

Post to forums  

Rail Community


Autodesk Design & Make Report