StackOverflow не поддерживает Latex, поэтому я собираюсь замять некоторые математические.Одно из решений заключается в том, что если ваша линия охватывает точки p
и q
, то каждая точка на этой линии может быть представлена как t*(p-q)+q
для некоторого действительного значения t
.Затем вы хотите минимизировать расстояние между вашей заданной точкой r
и любой точкой на этой линии, и расстояние обычно является функцией единственной переменной t
, поэтому стандартные методы исчисления работают нормально.Рассмотрим следующий пример, который вычисляет минимальное расстояние между r
и линией, охватываемой p
и q
.От руки мы знаем, что ответ должен быть 1
.
import numpy as np
p = np.array([0, 0, 0])
q = np.array([0, 0, 1])
r = np.array([0, 1, 1])
def t(p, q, r):
x = p-q
return np.dot(r-q, x)/np.dot(x, x)
def d(p, q, r):
return np.linalg.norm(t(p, q, r)*(p-q)+q-r)
print(d(p, q, r))
# Prints 1.0
. Это прекрасно работает в любом количестве измерений, включая 2, 3 и миллиард.Единственным реальным ограничением является то, что p
и q
должны быть разными точками, чтобы между ними была уникальная линия.
Я разбил код в приведенном выше примере, чтобы показать два разныхшаги, вытекающие из того, как я об этом думал математически (нахождение t
и затем вычисление расстояния).Это не обязательно самый эффективный подход, и, конечно, это не так, если вы хотите знать минимальное расстояние для множества точек и одной и той же линии - вдвойне, если число измерений мало.Для более эффективного подхода рассмотрим следующее:
import numpy as np
p = np.array([0, 0, 0]) # p and q can have shape (n,) for any
q = np.array([0, 0, 1]) # n>0, and rs can have shape (m,n)
rs = np.array([ # for any m,n>0.
[0, 1, 1],
[1, 0, 1],
[1, 1, 1],
[0, 2, 1],
])
def d(p, q, rs):
x = p-q
return np.linalg.norm(
np.outer(np.dot(rs-q, x)/np.dot(x, x), x)+q-rs,
axis=1)
print(d(p, q, rs))
# Prints array([1. , 1. , 1.41421356, 2. ])
Возможно, я упускаю некоторые упрощения или другие вещи, которые могут ускорить это, но, по крайней мере, это должно быть хорошим началом.