Hello everyone,
recently i have worked on a project to schedule wall finish material, but i have faced a problem. when i use room get boundry segments and loop through them, it doesn't retrieve all walls. i use the following code:
var boundarySegments = room.GetBoundarySegments(spatialBoundaryOption);
List<ElementId> roomWallsIds = new List<ElementId>();
foreach (var SegArr in boundarySegments)
{
foreach (var segment in SegArr)
{
Element neighbour = document.GetElement(segment.ElementId);
if (neighbour is Wall)
{
roomWallsIds.Add(neighbour.Id);
}
}
}
uidoc.Selection.SetElementIds(roomWallsIds);
the selection would be like the following picture
after a lot of trial i found that if there any wall with Base Offset property greater than zero it wouldn't be selected in room boundaries. so if i change the base offset to zero and re-run the code it works fine like the next image
i wanna to get these walls within room boundaries list without change base offset property. i had came with a work around idea to make a transaction and change the walls to zero base offset and select the walls and do some logic and redone the walls base offset to initial state but this is come in vain as many problems came up.
also i try use intersection to get room geometry intersect with wall, but it return always null.
Any one has an idea to solve this issue, Please? thanks in advance
Yes. You are using the room room boundary segments, which have a zero offset. So, if you use those to determine the walls, you only
> Retrieve the id of the element that produces this boundary segment.
See the remarks in the docs:
https://www.revitapidocs.com/2022/3661349e-41e4-b2d7-5c4a-21e002d6b762.htm
You non-zero-offset walls are located vertically above. Therefore, you cannot use a pure 2D approach that only operates on the zero offset XY plane. You need a 3D approach.
Your 2D approach is nice and simple and effective. I would try to stick with that for most walls, since that should hopefully cover the vast majority. Then, you could check whether any bits are missing in various ways.
There are a huge number of different ways you could enhance this to get the missing walls.
One way might be to ask the room for its closed shell:
https://www.revitapidocs.com/2022/1a510aef-63f6-4d32-c0ff-a8071f5e23b8.htm
You could go through all the geometry elements of the closed shell and ask each whether it is generated by an element: using the IsElementGeometry property:
https://www.revitapidocs.com/2022/be3ad18d-a9d3-25ed-6200-4f71d3cd4754.htm
If your walls are all vertical, then you can limit the bits of interest to vertical faces and ensure that you obtain the generating wall for each piece of vertical closed shell geometry. Most have already been obtained with offset zero. For the missing ones, you could maybe use a bounding box intersection filter to retrieve all walls within a pretty small volume defined by one individual closed shell facet.
I hope my ideas above are not too confused (for myself) and confusing (for you).
There may well be other, simpler, more effective approaches. There almost certainly are.
Good luck and looking forward to hearing how you end up solving this.
Hello jeremy,
I have tried the ideas you have present. but i have some tiny issues as i am a new comer to revit Api.
for room ClosedSell property it returns a bunch of surface planes with relative BoundingBoxUV that i can't do intersection filter with regular XYZ Bounding Box, also every face has a reference property of null so i can't get the reference Element Id, i have read many of your articles like
- https://thebuildingcoder.typepad.com/blog/2021/03/boundary-elements-and-stirrup-constraints.html#3
- https://thebuildingcoder.typepad.com/blog/2013/10/determining-a-room-boundary-segment-generating-ele...
and no one fits the problem most i came with bunch of ideas, i will mention some of them.
1- GetRoomAtPoint:
i have construct a wall mid point and calculate the normal vector of the wall direction, on the midPoint of the wall i have construct two points
For those two points i have check to get room at these points. unfortunately, for long walls the midpoint retrieves wrong rooms. and for thin walls like a thin film of glass it retrieves the both rooms together.
2-CloseShell
Also, I have tried with room closeshell and loop over them, I had come with idea that I have each face closed loop, I can generate a solid with very tiny height and check for this solid intersection with all wall, this solution is not accurate and also time killer though 😂
3- construct a solid a bit bigger than room geometry itself
This idea is about create a boundary curve loop scaled bigger than original room curve loop and create a solid from this new scaled curve loop and make a solid intersection filter, this method is the most accurate way so far, its difficulty when the room is not regular shape like a rectangular for example, so I have tried to get the centroid of the room polygon and scale the new curve loop about this centroid to give me a uniform scale from all room sides then create the solid, this one is more accurate as mention before but some times the original issue about the correct scale about correct centroid point of the room polygon
i have also a new question about solid intesection filter. that it doesn't get any model in place walls inside the intersection geometry, so how to get them?
these all the ideas i came with, if you have another guidance for the situation you are most welcome
I wonder if there is a viable alternative.
create temporary level add room to level using NewRoom(Level, UV) (UV being point in original Room).
Adjust level elevation to move Room up within height limits of original room.
Record boundary segments and wall ids at each level change to see what walls are on overall height boundary.
I've not tried this I just initially tested if a Room could be within a room.
As a side note:
When you look at the Room creation overloads you may start to wonder how do you get a PlanCircuit?
Document has the property PlanTopology which will start a Topology calculation and return the PlanTopology for a given level and optionally phase. PlanTopology.Circuits returns an API collection containing PlanCircuit.
The properties that may be useful in this are PlanCircuit.GetPointInside and PlanCircuit.IsRoomLocated. There is no property to tell you which Room or Rooms are inside which circuit however.
PlanTopology has useful method GetRoomIds
See also: SpatialElementGeometryCalculator Class (Rooms are a SpatialElement)
Can't find what you're looking for? Ask the community or share your knowledge.