Вычислить среднее расстояние от точки до сегмента линии и от сегмента линии до сегмента линии

Я ищу алгоритм для вычисления среднего расстояния между точкой и отрезком линии в 3D. Итак, учитывая две точки A (x1, y1, z1) и B (x2, y2, z2), которые представляют отрезок AB, и третью точку C (x3, y3, z3), каково среднее расстояние между каждой точкой на AB? в точку C?

Меня также интересует среднее расстояние между двумя отрезками линии. Итак, учитывая отрезки AB и CD, каково среднее расстояние от каждой точки на AB до ближайшей точки на CD?

Мне не повезло с поиском в Интернете, поэтому я буду благодарен за любые предложения.

Спасибо.


person Fred    schedule 20.04.2010    source источник
comment
По какой причине вы пытаетесь это вычислить? Кажется, что это необычный расчет, и, боюсь, он не очень простой. Вы уверены, что ищете?   -  person brainjam    schedule 20.04.2010


Ответы (3)


Если вы имеете в виду то, что, по моему мнению, вы подразумеваете под «средним» (и «расстоянием», т. Е. Норму L2, упомянутую dreeves), вот процедура, которая, думаю, должна работать для определения среднего расстояния между точками. и отрезок линии. Вам понадобится функция dot(A,B), которая принимает скалярное произведение двух векторов.

// given vectors (points) A, B, C
K1 = dot(A-C,A-C)
K2 = 2*dot(B-A,A-C)
K3 = dot(B-A,B-A)
L1 = sqrt(K3*(K1+K2+K3))
L2 = sqrt(K3*K1)
N = 4*K3*L1 + 2*K2*(L1-L2) + (K2*K2-4*K1*K3)*log((K2+2*L2)/(2*K3+K2+2*L1))
D = N / (8*K3^1.5)

Если предположить, что я все правильно расшифровал, тогда D будет средним расстоянием.

По сути, это просто псевдокод для оценки результата интеграла, который я сделал в Mathematica. Для этого может быть какой-нибудь изящный вычислительный ярлык, но если он есть, я этого не знаю. (И если его нет, я бы спросил, сколько вам действительно нужно для этого вычисления)

Если вы хотите найти среднее расстояние от ближайшей точки на линейном сегменте CD до всех точек на AB, в большинстве случаев ближайшей точкой будет либо C, либо D, поэтому вы можете просто проверить оба из них, чтобы увидеть, какая из них ближе (возможно, используя некоторый расчет минимального расстояния, как указано в других ответах). Единственное исключение - когда CD и AB параллельны, и вы можете провести перпендикуляр от одного к другому, и в этом случае вам придется более точно определить свои требования.

Если бы вы хотели найти среднее расстояние между всеми точками на CD и всеми точками на AB ... это можно было бы сделать с помощью двойного интеграла, хотя я с содроганием представляю, насколько сложной будет полученная формула.

person David Z    schedule 20.04.2010
comment
Я впечатлен, Дэвид! Как вы заставили Mathematica вычислять интеграл с символическими A, B, C? К сожалению, один из нас допустил ошибку, потому что, когда я сравниваю ваш алгоритм с Интегрировать [Norm [(1-k) A + kB-C], {k, 0,1}] для конкретных A, B, C, они не т совпадение. Любые идеи? - person dreeves; 20.04.2010
comment
PS: теперь я уверен, что в алгоритме Дэвида есть ошибка, но я не понял, как воспроизвести то, что он сделал, чтобы определить, что это за ошибка! - person dreeves; 20.04.2010
comment
Вот что я сделал: отрезок линии можно параметризовать как A+k(B-A), поэтому я вручную оценил (A+k(B-A)-C)^2, получив (A-C)^2+2k(B-A).(A-C)+k^2(B-A)^2. Я установил _4 _, _ 5_ и K3=(B-A)^2 и попросил Mathematica установить Integrate[Sqrt[K1 + K2 k + K3 k^2],{k,0,1}]. - person David Z; 20.04.2010
comment
ааа, думаю, я понимаю, что произошло: я случайно переключил K1 и K3, когда набирал формулу. Это должно быть исправлено сейчас. - person David Z; 20.04.2010
comment
Спасибо, Дэвид! Я проверил вашу формулу через кучу случайных тестов, чтобы убедиться, что она верна. По крайней мере, сейчас я не чувствую себя так плохо из-за того, что не разобрался в этом самостоятельно. Думаю, я постараюсь найти более простую формулу, которая дает хорошее приближение, если возможно. - person Fred; 21.04.2010
comment
Вероятно, это неплохая идея, хотя виды приближений, которые вы можете использовать, будут зависеть от вашего конкретного приложения. Например, как минимальное расстояние от вашей точки до сегмента линии соотносится с длиной сегмента? Если один из них намного меньше другого, я могу придумать несколько быстрых формул, которые будут работать. Если вы внесете в этот вопрос более подробные сведения о своей программе, мы поможем вам найти подходящее приближение. - person David Z; 21.04.2010

Во-первых, расстояние между двумя точками - это квадратный корень из суммы квадратов попарных разностей координат. (Например, расстояние от (0,0,0) до (1,1,1) равно sqrt (3), но это работает для произвольных точек в любом количестве измерений.) Это расстояние известно как l2-norm (L в нижнем регистре) или евклидова норма. Напишите норму (A, B) для расстояния между точками A и B.

Что касается интересной проблемы средних расстояний ... (Обратите внимание, что определение минимального расстояния от точки до линии или между сегментами линии - гораздо более распространенная проблема. Здесь был ответ с хорошими указателями для этой проблемы, но, похоже, он был удален тем временем.)

Чтобы найти среднее расстояние от точки C до отрезка AB, рассмотрите расстояние до произвольной точки между A и B, а именно (1-k) A + kB, где k изменяется от 0 до 1. Это норма (C, ( 1-к) А + кБ). Таким образом, среднее расстояние - это интеграл от k = 0 до 1 нормы (C, (1-k) A + kB).

Mathematica может сделать этот интеграл для любых конкретных A, B и C.

Вот реализация Mathematica:

avgd[A_,B_,C_] :=  Integrate[Sqrt@Dot[(1-k)*A+k*B-C, (1-k)*A+k*B-C], {k, 0, 1}]

Подынтегральное выражение также можно записать Norm[(1-k)*A+k*B-C]. В любом случае, Mathematica может сделать это для определенных точек, но не может интегрировать это символически, хотя, очевидно, Дэвид каким-то образом добился этого. Вот пример Дэвида из комментариев:

> avgd[{0, 0, 0}, {4, 0, 0}, {4, 3, 0}] // N

3.73594

Теоретически я думаю, что для проблемы среднего расстояния между двумя отрезками линии это должно сработать:

avgd[A_,B_,C_,D_] := Integrate[Norm[(1-k)A+k*B - (1-j)C - j*D], {k,0,1}, {j,0,1}]

Но Mathematica, кажется, задыхается от этого даже для конкретных моментов, не говоря уже о символах.

person dreeves    schedule 20.04.2010
comment
Интересный метод, не могли бы вы указать мне объяснение / доказательство? (Мне просто интересно) - person David Z; 20.04.2010
comment
... и теперь, когда я думаю об этом, я считаю, что с этой формулой что-то не так. Рассмотрим A=(0,0,0), B=(4,0,0) и либо C=(3.99999999,3,0), либо C=(4.000000001,3,0). В первом случае ваша первая формула (когда D лежит на AB) дает среднее расстояние 3,5, но во втором случае ваша вторая формула дает расстояние 4, несмотря на то, что они должны быть почти идентичными. (Мой собственный аналитический расчет дает 3,7359) - person David Z; 20.04.2010
comment
Пока вы его редактируете, я не думаю, что вы хотели сказать: «Отбросьте перпендикуляр от A к линии, на которой лежит AB». - person Karl; 20.04.2010
comment
Теперь я почти уверен, что мой ответ верен, по крайней мере, для проблемы «точка-линия», хотя и не очень полезен, если вы не используете язык программирования, который может выполнять интегралы. - person dreeves; 20.04.2010
comment
В худшем случае вы всегда можете аппроксимировать интегрирование, используя числовую квадратуру, например формулы Ньютона-Котеса. - person user168715; 20.04.2010

Что ж, если анализ не удастся, возьмите компьютер и проделайте глупые вычисления, пока не почувствуете числа ...

У меня тоже есть копия Mathematica. Для простоты, поскольку треугольник должен лежать в плоскости, я проработал следующее в 2D-пространстве. Чтобы упростить задачу, я указываю точку в {0,0} и отрезок от {1,0} до {0,1}. Среднее расстояние от точки до линии должно быть, если это имеет смысл, средней длиной всех линий, которые могут быть проведены от {0,0} до любой точки сегмента линии. Конечно, таких строк очень много, поэтому давайте начнем, скажем, с 10. В системе Mathematica это можно вычислить как

Mean[Table[EuclideanDistance[{0, 0}, {1 - k, 0 + k}], {k, 0, 1, 10.0^-1}]]]

что дает 0.830255. Следующий шаг очевиден - увеличьте количество измеряемых линий. Фактически, давайте составим таблицу средних значений, когда показатель степени 10.0 станет меньше (они отрицательны!). В системе Mathematica:

Table[Mean[Table[EuclideanDistance[{0, 0}, {1 - k, 0 + k}], {k, 0, 1, 
10.0^-i}]], {i, 0, 6}]

который производит:

{1, 0.830255, 0.813494, 0.811801, 0.811631, 0.811615, 0.811613}

Следуя этому подходу, я переработал пример @Dave (забудьте о третьем измерении):

Table[Mean[Table[EuclideanDistance[{0, 0}, {4, 0 + 3 k}], {k, 0, 1, 
10.0^-i}]], {i, 0, 6}]

который дает:

{9/2, 4.36354, 4.34991, 4.34854, 4.34841, 4.34839, 4.34839}

Это не согласуется с тем, что, по словам @dreeves, вычисляет алгоритм @Dave.

РЕДАКТИРОВАТЬ: Хорошо, поэтому я потратил на это еще немного времени. Для простого примера, который я использовал в первую очередь, то есть с точкой в ​​{0,0} и отрезком линии, простирающимся от {0,1} до {1,0}, я определяю функцию в Mathematica (как всегда), например:

fun2[k_] := EuclideanDistance[{0, 0}, {0 + k, 1 - k}]

Теперь это интегрируемо. Mathematica дает:

   In[13]:= Integrate[fun2[k], {k, 0, 1}]

   Out[13]= 1/4 (2 + Sqrt[2] ArcSinh[1])

Или, если вы предпочитаете числа, это:

In[14]:= NIntegrate[fun2[k], {k, 0, 1}]
Out[14]= 0.811613

что дает чисто численный подход, который я использовал ранее.

Теперь я собираюсь вернуться к работе и предоставить вам возможность обобщить это на произвольный треугольник, определяемый точкой и конечными точками отрезка линии.

person High Performance Mark    schedule 20.04.2010
comment
В последнем примере, я думаю, мы вычисляем разные расстояния. В своих комментариях я говорил о среднем расстоянии между стороной длины 4 и противоположной ей вершиной, но похоже, что вы вычислили среднее расстояние между стороной длины 3 и противоположной ей вершиной. Вероятно, это объясняет, почему числа не совпадают. - person David Z; 20.04.2010
comment
@ Дэвид - да, когда я переделываю свои расчеты, я тоже получаю 3,73594. - person High Performance Mark; 20.04.2010