Get every information about the Reservation I'm developing a plugin for Revit (a software to make 3D buildings).

The goal is simple to understand. When there is an intersection between a Wall and a Duct I create an object called Reservation at this location. I need to extract the Curve of the Ducts and the Faces of the Walls in order to calculate this intersection.

My algorithm is working fine and fast with a small building (3 Ducts, 10 Walls and 8 intersections) But when I want to launch it on a real project (around 10 000 Ducts) the code is way too slow due to many ForEach loops. Here is the sample which cause the issue:

foreach (Duct d in ducts)
            {
                Curve ductCurve = FindDuctCurve(d);
                curves.Add(ductCurve);

                foreach (Wall w in walls)
                {
                    wallFaces = FindWallFace(w);
                    foreach (Curve c in curves)
                    {
                        foreach (Face f in wallFaces)
                        {
                            foreach (KeyValuePair&lt;XYZ, Wall&gt; pair in FindInterWalls(c, f, walls))
                            {
                                Reservation.Res res = new Reservation.Res();
                                res.RoundCenter = new XYZ(Math.Round(pair.Key.X), Math.Round(pair.Key.Y), Math.Round(pair.Key.Z));
                                res.WallWidth = pair.Value.Width;
                                bool containsItemX = resList.Any(itemX =&gt; itemX.RoundCenter.DistanceTo(res.RoundCenter) &lt; res.WallWidth + 1);

                                if (containsItemX == false)
                                {
                                    res.AssociatedWall = pair.Value;
                                    res.Radius = 1;
                                    res.AssociatedDuct = d;

                                    res.Center = pair.Key;
                                    resList.Add(res);
                                    model.Reservations.Add(new Reservation { ResList = resList });
                                }
                            }
                        }
                    }
                }
            }


The custom methods I'm using also contain loops. I wonder if a LINQ would be faster but I don't really know how to use it.

In a nutshell i want to get all the information about Reservations without loosing so much time stuck in so many foreach loops.

Here is my Reservation Class :

public sealed class Reservation
{

    public List&lt;Res&gt; ResList { get; set; }

    public class Res
    {
        public XYZ Center { get; set; }
        public XYZ RoundCenter { get; set; }
        public Duct AssociatedDuct { get; set; }
        public Wall AssociatedWall { get; set; }
        public double WallWidth { get; set; }
        public int Radius { get; set; }
    }

    public Reservation()
    {
        ResList = new List&lt;Res&gt;();

    }

}




A Curve is a right in the center of a Duct (each Duct contains one Curve). And a Face is a side of a Wall (each Wall contains 6 Faces)
I hope I have understood this now.

Instead of iterating over all the Duct items and adding each iteration the related Curve to curves you should create another class like  

public class DuctCurev
{
    public Duct TheDuct {get; private set; }
    public Curve TheCurve {get; private set; }
    public DuctCurve(Duct duct, Curve curve)
    {
        TheDuct = duct;
        TheCurve = curve;
    }
}


now we iterate once over all of the Duct's and find the related Curve which we will add to a List&lt;DuctCurve&gt; like so  

List&lt;DuctCurve&gt; ductCurves = new List&lt;DuctCurve&gt;();
foreach (Duct d in ducts)
{
    ductCurves.Add(d, FindDuctCurve(d));
}  


then we need to adjust the remaining code to use the ductCurves and use the ! operator instead of using containsItemX == false like so

foreach (Wall w in walls)
{
    wallFaces = FindWallFace(w);
    foreach (DuctCurve dc in ductCurves)
    {
        foreach (Face f in wallFaces)
        {
            foreach (KeyValuePair&lt;XYZ, Wall&gt; pair in FindInterWalls(dc.Curve, f, walls))
            {
                Reservation.Res res = new Reservation.Res();
                res.RoundCenter = new XYZ(Math.Round(pair.Key.X), Math.Round(pair.Key.Y), Math.Round(pair.Key.Z));
                res.WallWidth = pair.Value.Width;
                bool containsItemX = resList.Any(itemX =&gt; itemX.RoundCenter.DistanceTo(res.RoundCenter) &lt; res.WallWidth + 1);

                if (!containsItemX)
                {
                    res.AssociatedWall = pair.Value;
                    res.Radius = 1;
                    res.AssociatedDuct = dc.Duct;

                    res.Center = pair.Key;
                    resList.Add(res);
                    model.Reservations.Add(new Reservation { ResList = resList });
                }
            }
        }
    }
}