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
//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();
}
}
CodePudding user response:
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
toD
, and - one list of wall indices that are being traversed when "going right" from
S
toD
,
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:
- Find the count of wall indices for one of the paths (path A)
- Find the count of wall indices for the other path (path B)
- Create an empty list for the wall indices for each path, each having its calculated capacity
(found in the two previous steps) - Find out whether path A moves up or down (i.e. "left" or "right") the wall index list
- 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.