Есть ли что-то вроде np.linspace для 3D-линий?

У меня есть вектор точек 3x1, представляющий начальную точку некоторой строки, и вектор точек 3x1, представляющий конец некоторой строки. Я хотел бы выбрать произвольное количество точек вдоль линии, соединенной этими двумя точками.

np.linspace делает именно то, что мне нужно, но в 1 измерении. Есть ли аналогичная функциональность, которую можно расширить до 3-х измерений?

Спасибо


person Carpetfizz    schedule 15.03.2018    source источник
comment
Как насчет линейной функции для сопоставления массива 1d с трехмерным пространством — линейной интерполяцией?   -  person hpaulj    schedule 15.03.2018
comment
Вы можете сделать что-то с np.interp или np.repeat + np.cumsum, то есть np.repeat((b - a) / 10, [10, 10, 10]).reshape(3, -1), но это может потребовать гораздо больше работы, чем просто itertools.starmap.   -  person Brad Solomon    schedule 15.03.2018
comment
это отвечает на ваш вопрос? Дайте мне знать, согласны ли вы закрыть свой вопрос.   -  person Paul Panzer    schedule 15.03.2018
comment
Возможный дубликат Как я могу векторизовать linspace в numpy   -  person Brad Solomon    schedule 16.03.2018


Ответы (1)


Мое предложение по интерполяции:

In [664]: p1=np.array([0,1,2])
In [665]: p2=np.array([10,9,8])
In [666]: l1 = np.linspace(0,1,11)
In [667]: l1
Out[667]: array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
In [668]: p1+(p2-p1)*l1[:,None]
Out[668]: 
array([[ 0. ,  1. ,  2. ],
       [ 1. ,  1.8,  2.6],
       [ 2. ,  2.6,  3.2],
       [ 3. ,  3.4,  3.8],
       [ 4. ,  4.2,  4.4],
       [ 5. ,  5. ,  5. ],
       [ 6. ,  5.8,  5.6],
       [ 7. ,  6.6,  6.2],
       [ 8. ,  7.4,  6.8],
       [ 9. ,  8.2,  7.4],
       [10. ,  9. ,  8. ]])

Эквивалентно 3 вызовам linspace

In [671]: np.stack([np.linspace(i,j,11) for i,j in zip(p1,p2)],axis=1)
Out[671]: 
array([[ 0. ,  1. ,  2. ],
       [ 1. ,  1.8,  2.6],
       [ 2. ,  2.6,  3.2],
       [ 3. ,  3.4,  3.8],
       [ 4. ,  4.2,  4.4],
       [ 5. ,  5. ,  5. ],
       [ 6. ,  5.8,  5.6],
       [ 7. ,  6.6,  6.2],
       [ 8. ,  7.4,  6.8],
       [ 9. ,  8.2,  7.4],
       [10. ,  9. ,  8. ]])

Вариант этого:

np.c_[tuple(slice(i,j,11j) for i,j in zip(p1,p2))]

Действительно тот же расчет, просто другой синтаксис.


Вместо этого можно использовать outer:

p1+np.outer(l1,(p2-p1))

Но даже это использует широковещательную передачу. p1 равно (3,), а outer равно (11,3), результат равен (11,3).


Подход @Brad по-разному обрабатывает конечные точки

In [686]: np.append(p1[:, None], np.repeat((p2 - p1) / 10, [10, 10, 10]).reshape
     ...: (3, -1).cumsum(axis=1), axis=1)
Out[686]: 
array([[ 0. ,  1. ,  2. ,  3. ,  4. ,  5. ,  6. ,  7. ,  8. ,  9. , 10. ],
       [ 1. ,  0.8,  1.6,  2.4,  3.2,  4. ,  4.8,  5.6,  6.4,  7.2,  8. ],
       [ 2. ,  0.6,  1.2,  1.8,  2.4,  3. ,  3.6,  4.2,  4.8,  5.4,  6. ]])
In [687]: _.shape
Out[687]: (3, 11)
person hpaulj    schedule 15.03.2018
comment
Спасибо. Что делает *l1[:,None] в вашем примере? - person Carpetfizz; 15.03.2018
comment
Это широковещательное умножение, фактически внешнее произведение. - person hpaulj; 15.03.2018