1

I have an array that represents a series of points. For the purpose of this question the first two columns of the array do not pertain to the problem. The array in question is:

array([[1., 1., 4., 0., 0.],
       [1., 1., 8., 0., 0.],
       [1., 5., 4., 0., 0.],
       [1., 5., 4., 0., 8.],
       [1., 7., 4., 0., 8.],
       [1., 7., 8., 0., 8.],
       [1., 9., 8., 0., 0.],
       [1., 9., 8., 0., 8.]])

The last 3 columns correspond to X,Y,Z coordinates. What I would like to do is sort the list so that the 1st row and the 3rd row will match, then the 4th and 5th row will match. But every two rows in the array are a pair and have to be moved together. Effectively, if you draw a line through the points, the sequence of the points will create a closed region. In this case every two entries represents a line segment. The sorted array should be:

array([[1., 1., 4., 0., 0.],
       [1., 1., 8., 0., 0.],
       [1., 9., 8., 0., 0.],
       [1., 9., 8., 0., 8.],
       [1., 7., 8., 0., 8.],
       [1., 7., 4., 0., 8.],
       [1., 5., 4., 0., 8.],
       [1., 5., 4., 0., 0.]])

I can achieve this with a while loop, but I am wondering if there is numpy function that will replace an entry based on a selection from an array?

What I have done is to first create an array to represent where the coordinates are equal to each other by the use of numpy equal and numpy all/any. I then create two more arrays to serve as reference indexs. the 'new_index' is the working array and is the one that will be manipulated by the while loop. The 'ref_index' is referenced for keeping the pair values together. At the end of the code the sorted array is returned by taking a slice of original array with the rearranged index.

My code -->

points=np.array([[1., 1., 4., 0., 0.],
       [1., 1., 8., 0., 0.],
       [1., 5., 4., 0., 0.],
       [1., 5., 4., 0., 8.],
       [1., 7., 4., 0., 8.],
       [1., 7., 8., 0., 8.],
       [1., 9., 8., 0., 0.],
       [1., 9., 8., 0., 8.]])

compare2=np.equal(points[:,-3:],points[:,-3:].reshape(-1,1,3))
compare2=np.all(compare2,2)
values,index=np.where(compare2)
values2,index2=np.unique(index.reshape(-1,2),return_index=True,axis=0)

ref_index=np.arange(0,8).reshape(-1,2)
new_index=np.arange(0,8)
i = 1
while i <len(new_index)-1:
    if i%2==1:
        #Find Matching value
        np.any(values2==new_index[i])
        selected_entry=values2[np.any(values2==new_index[i],1)]
        # add to base(i+1)
        new_index[i+1]=int(selected_entry[selected_entry!=new_index[i]])
    else:
        np.any(ref_index==new_index[i])
        selected_entry=ref_index[np.any(ref_index==new_index[i],1)]
        # add to base(i+1)
        new_index[i+1]=int(selected_entry[selected_entry!=new_index[i]])
    i += 1  
points[new_index]

My ultimate goal is to replace the while loop with a numpy function or combination of numpy functions. Is this possible?

Sushi08
  • 11
  • 2
  • Might be of inspiration: [How to sort a path of a graph](https://stackoverflow.com/questions/72280606/how-to-sort-a-path-of-a-graph) – Stef Feb 23 '23 at 16:33

0 Answers0