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)
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
Solved! Go to Solution.
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)
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
Solved! Go to Solution.
Solved by Sean_Page. Go to Solution.
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.
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.
In VB:
If Typeof(neighbor) is Wall then
....
If that's the problem.
- Michel
In VB:
If Typeof(neighbor) is Wall then
....
If that's the problem.
- Michel
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)
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)
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.
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.
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?
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?
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.
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.
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....
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....
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
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
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.
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.