How to Find if walls are intersecting at start and end points

How to Find if walls are intersecting at start and end points

arao6KKLC
Explorer Explorer
461 Views
6 Replies
Message 1 of 7

How to Find if walls are intersecting at start and end points

arao6KKLC
Explorer
Explorer

I'm trying to see if I can calculate the exposed surface area of a set of walls, (for example a set of 4 walls in a square), and I'm running a check to see if the walls intersect at both the start and end points, since the walls are joined together. 

By using the centerline xyz coordinates, i thought I could check and return a bool value if there is an intersection or not.

 

However, the code is constantly returning false and I'm not sure what I've done wrong. Hopefully someone here can help me see my errors? 

 private bool Wallintersect(ExternalCommandData commandData)

            {

                UIApplication uiApp = commandData.Application;

                UIDocument uiDoc = uiApp.ActiveUIDocument;

                Autodesk.Revit.DB.Document doc = uiDoc.Document;

                // Collect all walls in the document

                FilteredElementCollector wallCollector = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls) .WhereElementIsNotElementType();

                foreach (Wall selectedWall in wallCollector)

                {
                    bool intersectsAtStart = false;
                    bool intersectsAtEnd = false;
 
                    foreach (Wall otherWall in wallCollector)
                    {
                        if (otherWall.Id != selectedWall.Id)
                        {
                            LocationCurve selectedWallCurve = selectedWall.Location as LocationCurve;

                            LocationCurve otherWallCurve = otherWall.Location as LocationCurve;
                            // Check for intersection at start point

                            if (selectedWallCurve.Curve.GetEndPoint(0).IsAlmostEqualTo(otherWallCurve.Curve.GetEndPoint(0)))
                            {
                                intersectsAtStart = true;
                                Walls.Joined0 = intersectsAtStart; 
                            }
                            else
                            {
                                intersectsAtStart = false;
                                Walls.Joined0 = intersectsAtStart;
                            }
                            // Check for intersection at end point
                            if (selectedWallCurve.Curve.GetEndPoint(1).IsAlmostEqualTo(otherWallCurve.Curve.GetEndPoint(0)))
                            {
                                intersectsAtEnd = true;
                                Walls.Joined1 = intersectsAtEnd; 
                            }
                            else
                            {
                                intersectsAtEnd = false;
                                Walls.Joined1 = intersectsAtEnd;
                            }
                        }
                    }
                }
                return Joined0 && Joined1;
            }
    }

 

 

0 Likes
462 Views
6 Replies
Replies (6)
Message 2 of 7

GaryOrrMBI
Collaborator
Collaborator
at start:
LocationCurve.ElementsAtJoin(0)
At End:
LocationCurve.ElementsAtJoin(1)

returns an ElementArray of elements joined at the specified LocationCurve end
Gary J. Orr
GaryOrrMBI (MBI Companies 2014-Current)
aka (past user names):
Gary_J_Orr (GOMO Stuff 2008-2014);
OrrG (Forum Studio 2005-2008);
Gary J. Orr (LHB Inc 2002-2005);
Orr, Gary J. (Gossen Livingston 1997-2002)
0 Likes
Message 3 of 7

arao6KKLC
Explorer
Explorer

Would you be able to further explain what you mean? I'm not sure how you want the member to be called into the method.

 

Or are you saying I should separately create an array for each the start and end points and then use that? 

0 Likes
Message 4 of 7

GaryOrrMBI
Collaborator
Collaborator

@arao6KKLC wrote:

...

 

Or are you saying I should separately create an array for each the start and end points and then use that? 


yes, I'm suggesting trying a different approach using this method instead of the point nearly equals - end points to start points to start points to end points - cross referencing to try to determine who is connecting to whom.

 

-G

Gary J. Orr
GaryOrrMBI (MBI Companies 2014-Current)
aka (past user names):
Gary_J_Orr (GOMO Stuff 2008-2014);
OrrG (Forum Studio 2005-2008);
Gary J. Orr (LHB Inc 2002-2005);
Orr, Gary J. (Gossen Livingston 1997-2002)
0 Likes
Message 5 of 7

RPTHOMAS108
Mentor
Mentor

What @GaryOrrMBI has indicated is clear enough.

 

For 'selectedWallCurve' use the function ElementsAtJoin(End Index) to get a list of walls the location curve associated with 'selectedWallCurve' is joining with.

 

This is better than iterating all of the walls in the entire project for each wall in the entire project (or a single selected one).  You are also missing the end1 to end1 possibility and the fact the Z levels may not match.

 

The downside of such things is that Walls are 3D and location curves are set to a level i.e. it is a 3D problem that can't be solved in a 2D way. Since a wall on one side could be modelled through levels this means there may be many wall location curves occupying the same 2D profile connected to that multilevel wall. 

 

Generally when people look at surface areas of walls they consider Rooms with features such as Room.ClosedShell or Room.GetBoundarySegments. You have to be careful using geometry directly due to how the wall joins are dealt with in such.

 

Lastly Boolean is born negative, so you can halve your existing code already. However you should review your logic focussing on the possible combinations of 'true' that can lead to the final true.

 

0 Likes
Message 6 of 7

arao6KKLC
Explorer
Explorer

Thank you for calling out that I had missed some test cases, had found that myself after I posted my original prompt. 

 

And the bool false segments were just me double checking that it would return false, but you're right it's redundant since as you said bool starts as negative. 

 

However, even if my method is slow, by checking all the walls within the project, I know that when I make my buildings, I don't let it extend past the floor it was created on, and if the z levels don't match per end I can run a check to see if the wall is sloped. 

 

is there really no way to solve this in a 2D method? My usage of revit doesn't involve the rooms tool, so I was hoping that there would be a way like the one I had made that can piece together if there is a join/intersection, and I can calculate based on if it is or not. 

 

private bool Wallintersect(ExternalCommandData commandData )

            {
          

            UIApplication uiApp = commandData.Application;

                UIDocument uiDoc = uiApp.ActiveUIDocument;

                Autodesk.Revit.DB.Document doc = uiDoc.Document;
          


            // Collect all walls in the document

            FilteredElementCollector wallCollector = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls) .WhereElementIsNotElementType();

                foreach (Wall selectedWall in wallCollector)

                {
                    bool intersectsAtStart;
                    bool intersectsAtEnd;
 
                    foreach (Wall otherWall in wallCollector)
                    {
                        if (otherWall.Id != selectedWall.Id)
                        {
                            LocationCurve selectedWallCurve = selectedWall.Location as LocationCurve;
                            selectedWallCurve.get_ElementsAtJoin(0);
                            selectedWallCurve.get_ElementsAtJoin(1);
                            LocationCurve otherWallCurve = otherWall.Location as LocationCurve;
                            otherWallCurve.get_ElementsAtJoin(0);
                            otherWallCurve.get_ElementsAtJoin(1);
                        // Check for intersection at start point
                        
                        if (selectedWallCurve.Curve.GetEndPoint(0).IsAlmostEqualTo(otherWallCurve.Curve.GetEndPoint(0)) || (selectedWallCurve.Curve.GetEndPoint(0).IsAlmostEqualTo(otherWallCurve.Curve.GetEndPoint(1))))
                            {
                                
                                intersectsAtStart = true;
                                Walls.Joined0 = intersectsAtStart; 
                            }
                           
                            // Check for intersection at end point

                            if (selectedWallCurve.Curve.GetEndPoint(1).IsAlmostEqualTo(otherWallCurve.Curve.GetEndPoint(0)) || (selectedWallCurve.Curve.GetEndPoint(1).IsAlmostEqualTo(otherWallCurve.Curve.GetEndPoint(1))))
                            {
                                intersectsAtEnd = true;
                                Walls.Joined1 = intersectsAtEnd; 
                            }
                         }
                    }
                }
                return Joined0 && Joined1;
            }
0 Likes
Message 7 of 7

RPTHOMAS108
Mentor
Mentor

You have to filter by level then or group all walls on the same level by Z, it may be the case that the location line is not at the base of the wall. It depends how the wall was modelled and how the top and bottom constraints have been changed since.

 

A lot of it depends on model discipline i.e. if it is for you and you are certain of what you have done then you can check in 2d.

 

If you are checking a certain wall to see what it is connected to via LocationCurve.ElementsAtJoin or the 2d ends points of all other walls in the project, makes no difference to the result just one is slower.

 

Convert it to a 2d comparison by taking the Z out of it. Also better to check two points as being the same when they are within a certain tolerance distance of one another. This is often easier to imagine than the consequence of:

abs(A - B) < 0.0000001

Which is how AlmostEqualTo works

 

There permutations for your end checks are

End0 to End0
End0 to End1
End1 to End1

 

LocationCurve.ElementsAtJoin will also move generally check if a wall abuts another wall (forming T or cross junction). Depending on your exercise this could be better than just checking end points.

 

You can create rooms with the API to then analyse, they don't have to be a current feature of the model. If you knew nothing about the locations of rooms and started with a search grid of points across rectangular area encompassing all walls on a plan. You would find some points form rooms and some points fall within rooms you've created.

0 Likes