Расстояние между двумя выпуклыми многоугольниками в 3D

У меня есть два выпуклых многоугольника в 3D. Они оба плоские в разных плоскостях, так что это пара лиц.

какой самый простой способ вычислить расстояние между этими двумя полигонами?

Edit: длина кратчайшей линии, которая имеет конечную точку в первом многоугольнике и другую конечную точку во втором многоугольнике. Расстояние, которое я ищу, - это длина этой кратчайшей линии.

5 ответов


Это простая ограниченная оптимизация с линейными ограничениями и квадратичной функцией цели. Существует множество алгоритмов, которые можно использовать, например градиентный спуск.


Ну, есть только несколько возможностей; самая короткая линия между двумя полигонами может быть:

  1. между двумя вершинами
  2. между ребром и вершиной
  3. между двумя ребрами (представьте себе два многоугольника на перпендикулярных плоскостях)
  4. между вершиной и внутренней частью многоугольника
  5. или полигоны пересекаются

случаи 1-3 все позаботились о том, чтобы рассматривать каждую ребро + вершинную пару как сегмент строки и перечисление расстояние между всеми парами отрезков.

для случая 4, Найдите расстояние между каждой вершиной и плоскостью другого полигона. Убедитесь, что линия (охватывающая от вершины до ближайшей точки на плоскости) находится внутри другого многоугольника; если это не так, то Кратчайшая линия к другому многоугольнику будет по его периметру, о котором уже позаботились в случае 1 или 2.
(обязательно сделайте это проверка на и полигоны)

для случая 5, по крайней мере, один отрезок линии должен пересекаться с областью другого многоугольника - если бы они пересеклись по их периметру, мы бы поймали его уже в случаях 1-3, и если бы вершина пересекла область, мы бы поймали ее в случае 4. Поэтому просто проверьте пересечение каждого ребра с плоскостью другого многоугольника и посмотреть, находится ли точка пересечения внутри другой полигон.
(убедитесь, что эта проверка для и полигоны)

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


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

однако, если вы хотите довольно простой и лучший метод. Используйте, как предложил Бен Фойт, метод квадратичной оптимизации (т. е. Квадратичного Программирования). В основном, ваши полигоны ваш набор линейных ограничений, т. е. ваша точка решения должна лежать к внутренней стороне каждого края вашего многоугольника (это ограничение неравенства). И ваша функция затрат для оптимизации-это просто евклидово расстояние, т. е. Q в стандартной формулировке-это просто матрица тождества. После приведения в качестве такой проблемы вы можете использовать библиотеку, которая решает эту проблему (есть много таких), или вы можете изучить ее из книги и свернуть свой собственный код для нее (это довольно простой алгоритм для кодирования).

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


неясно, что вы пробовали.

этой вероятно для сегментов как таковых.

Итак, все, что вам нужно сделать, это проверить все пары кромок. Я бы хотел сначала реализовать это, прежде чем пытаться оптимизировать.

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


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