HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Get every information about the Reservation

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thereservationeverygetaboutinformation

Problem

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 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 => itemX.RoundCenter.DistanceTo(res.RoundCenter) < 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 = resLi

Solution

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 like so

List ductCurves = new List();
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 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 => itemX.RoundCenter.DistanceTo(res.RoundCenter) < 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 });
                }
            }
        }
    }
}

Code Snippets

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;
    }
}
List<DuctCurve> ductCurves = new List<DuctCurve>();
foreach (Duct d in ducts)
{
    ductCurves.Add(d, FindDuctCurve(d));
}
foreach (Wall w in walls)
{
    wallFaces = FindWallFace(w);
    foreach (DuctCurve dc in ductCurves)
    {
        foreach (Face f in wallFaces)
        {
            foreach (KeyValuePair<XYZ, Wall> 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 => itemX.RoundCenter.DistanceTo(res.RoundCenter) < 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 });
                }
            }
        }
    }
}

Context

StackExchange Code Review Q#132195, answer score: 3

Revisions (0)

No revisions yet.