2

Firstly I would like to say that the main principal of this question is not necessarily related to the revit API.

I am trying to create a "path of travel line" which has to go from the furthest point in a room following the shortest way along the wall, which means that there are 2 options the path can go(I added a picture for clarification)

I have an array of all the wall lines which are bordering this room, I have the index of the wall where the door is in and the index of the wall which has the furthest point in the room. However these indexes and the number of walls in the array vary from room to room.

How can I create 1 list that runs from doorIndex going up to furthestPointIndex and another list going from furthestPointIndex down to doorIndex considering that one of those 2 lists are going to just over from the end of a list(List.Count) to the beginning(List[0]) or the other way around.

From these 2 lists it would be easy for me to determine the shortest route

Clarification

            //this gets the walls in order in a list            
            List<Curve> edgeLoop = AbcRevitUtils.GeometryUtils.get_Curves(bottomFace);

            Curve doorCurve;
                        Curve furthestCurve;

                int index = edgeLoop.IndexOf(doorCurve);
                        int indexFar = edgeLoop.IndexOf(furthestCurve);

            XYZ furthestPoint = new XYZ(0, 0, 0);
                        int startOrEnd;
                        //determine furthest endpoint on the furthest curve, a curve has 2 points in this case, a start point(0) and endpoint(1)
                        if (dPoint.DistanceTo(edgeLoop[indexFar].GetEndPoint(0)) < dPoint.DistanceTo(edgeLoop[indexFar].GetEndPoint(1)))
                        {
                            furthestPoint = edgeLoop[indexFar].GetEndPoint(1);
                            startOrEnd = 1;
                        }
                        else
                        {
                            furthestPoint = edgeLoop[indexFar].GetEndPoint(0);
                            startOrEnd = 0;
                        }
                        
            //this creates the line
                        Autodesk.Revit.DB.Analysis.PathOfTravel route = Autodesk.Revit.DB.Analysis.PathOfTravel.Create(doc.ActiveView, furthestPoint, dPoint);
                        //calculate which route in the loop is the shortest
                        //...
                        double path1 = 0;
                        List<double> path2 = new List<double>();

                        for (int i = index; i < indexFar; i++)
                        {
                            path1 += edgeLoop[i].Length;
                        }
                        

                        if (index < indexFar)
                        {

                            for (int i = indexFar - 1; i > index - 1; i--)
                            {
                                int j = 0;
                                route.InsertWaypoint(edgeLoop[i].GetEndPoint(startOrEnd), j);
                                j++;
                                route.Update();
                            }
                        }
                        else
                        {
                            for (int i = indexFar + 1; i < index + 1; i++)
                            {
                                int j = 0;
                                route.InsertWaypoint(edgeLoop[i].GetEndPoint(startOrEnd), j);
                                j++;
                                route.Update();
                            }
                        }
                        
Dries
  • 33
  • 5
  • if you have the wall that is opposite to the door, then the furthest point is either the first or the last one of that wall. But basically it all reduces to see if the door is placed in the bottom half or the upper half. –  Sep 14 '22 at 08:29
  • I have that point of that wall, but Im trying to loop from the index of that wall to the index that the wall of the door is on to determine the shortest path along the walls – Dries Sep 14 '22 at 08:33
  • The shortest path is the bottom one if the door is in the bottom half of the wall or the top one i the door is in the top half. the distance value is the width of the room (horizontal wall length) + the distance from the door to the closest horizontal wall. –  Sep 14 '22 at 08:34
  • For example in this case I would have a list of 4 items which are the walls, [0,1,2,3] . Lets say the Door Wall is on index 1 and the furthestPointWall is on index 3 then I need 1 list that is [3,2,1] and another list that is [3,0,1] – Dries Sep 14 '22 at 08:37
  • just having the list of walls is not enough. you need somehow to relate one wall to another by sharing an edge. You also need at least two points for each wall in order to be placed in a drawing. You will also need the location of the door... It's better if you edit your question and put the relevant info as code. –  Sep 14 '22 at 08:39
  • I have the wall relation cause the walls are in order in the array, I added my code but it has some references and is quite messy – Dries Sep 14 '22 at 08:47
  • If you only consider square rooms, the problem is trivial. If you want a generic shortest path you should convert your drawing to a graph, and use A* or Djikstra to find the shortest path. But it is really difficult to separate the important code in your example from the revit fluff. I would suggest simplifying the example, you have one or more `List` and want to do what exactly? – JonasH Sep 14 '22 at 09:03
  • I updated the code and removed the non important things, It should work for non squared rooms as well but I dont think that should be a problem in this case – Dries Sep 14 '22 at 09:14
  • But my question is more a general problem so I dont think the context is that necessary, "For example in this case I would have a list of 4 items which are the walls, [0,1,2,3] . Lets say the Door Wall is on index 1 and the furthestPointWall is on index 3 then I need 1 list that is [3,2,1] and another list that is [3,0,1]" I this comment should explain it well. – Dries Sep 14 '22 at 09:18

1 Answers1

1

Based on the question title (at the time of writing this answer):

Trying to create 2 lists of an array based on 2 indexes

and your supplementary comment:

For example in this case I would have a list of 4 items which are the walls, [0,1,2,3] . Lets say the Door Wall is on index 1 and the furthestPointWall is on index 3 then I need 1 list that is [3,2,1] and another list that is [3,0,1]

, I believe you in fact do not need help finding the shortest path, as may be the interpretation based on the content of your question post (and the comments related to it).

I think you rather want to generate

  • one list of wall indices that are being traversed when "going left" from S to D, and
  • one list of wall indices that are being traversed when "going right" from S to D,

when S is the starting point wall index and D is the door wall index.

As an example: If our wall indices are 0--5, starting point wall index is 3 and door wall index is 1:

[ 0, 1, 2, 3, 4, 5 ]
     D     S

, the two ways of traversing the wall indices should be as follows:

[ 0, 1, 2, 3, 4, 5 ]
     D<----S         // "going left"

[ 0, 1, 2, 3, 4, 5 ]
  -->D     S------   // "going right"

, resulting in these two lists:

[ 3, 2, 1 ]       // "going left"

[ 3, 4, 5, 0, 1 ] // "going right"

( Is this a false interpretation? If so, please let me know, and I will delete this answer. )


One way to go about it could be:

  1. Find the count of wall indices for one of the paths (path A)
  2. Find the count of wall indices for the other path (path B)
  3. Create an empty list for the wall indices for each path, each having its calculated capacity
    (found in the two previous steps)
  4. Find out whether path A moves up or down (i.e. "left" or "right") the wall index list
  5. Populate list of walls (or wall indices) to traverse for path A and path B
    • Use the direction found in the previous step to ensure that path A and path B traverse the wall index list in opposite directions
    • Use the remainder operator % to enable "looping" the wall index list
      (i.e. "jumping" from the last element to the first, or vice versa)

Seeing as the items in your comment's example ([0, 1, 2, 3]) have identical values as their respective indices in the list, I am not sure whether you are actually looking for resulting lists containing indices or resulting lists containing values from the original list.

I will therefore provide an example implementation which displays both approaches:

var walls = new List<int> { 10, 11, 12, 13, 14, 15 };

var indexStart = 3;
var indexDoor = 1;

var indexDiff = indexDoor - indexStart;

// Steps 1, 2
var wallCountPathA = 1 + Math.Abs(indexDiff);
var wallCountPathB = 2 + walls.Count - wallCountPathA;

// Step 3

// Indices
var wallIndicesPathA = new List<int>(wallCountPathA);
var wallIndicesPathB = new List<int>(wallCountPathB);

// Walls
var wallsPathA = new List<int>(wallCountPathA);
var wallsPathB = new List<int>(wallCountPathB);

// Step 4
var directionA = Math.Sign(indexDiff);

// Step 5
for (var i = 0; i < Math.Max(wallCountPathA, wallCountPathB); i++)
{
    if (i < wallCountPathA)
    {
        var indexA = indexStart + (directionA * i);
        
        wallIndicesPathA.Add(indexA);  // Indices
        wallsPathA.Add(walls[indexA]); // Walls
    }
    
    if (i < wallCountPathB)
    {
        var indexB = (walls.Count + indexStart - (directionA * i)) % walls.Count;
        
        wallIndicesPathB.Add(indexB);  // Indices
        wallsPathB.Add(walls[indexB]); // Walls
    }
}

This code snippet will result in:

Wall indices in path A: [ 3, 2, 1 ]
Wall indices in path B: [ 3, 4, 5, 0, 1 ]

Walls in path A: [ 13, 12, 11 ]
Walls in path B: [ 13, 14, 15, 10, 11 ]


Example fiddle here.


Note:
This implementation will not suffice for D == S.
In such a scenario, Math.Sign() will return 0 (rather than -1 or 1); leading to no incrementation (or decrementation) of the value being added to wallIndicesPathB as the for loop is being iterated.

Astrid E.
  • 2,280
  • 2
  • 6
  • 17