Как эффективно определить нормаль к многоугольнику в трехмерном пространстве?

У меня есть куча копланарных точек, определяющих многоугольник в трехмерном пространстве. Они всегда наматываются одинаково (например, по часовой стрелке). Мне нужно определить нормаль со знаком к плоскости, содержащей этот многоугольник, т. е. знать, какой путь находится «вверху» для этого многоугольника.

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

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

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

Как выбрать два ребра (или три вершины) в невыпуклом многоугольнике, чтобы надежно определить, в какую сторону обращен многоугольник?


person Joe Strout    schedule 28.08.2015    source источник
comment
Не по теме. Не программный вопрос. Это больше геометрия/математика. Попробуйте math.stackexchange.com   -  person Marc B    schedule 28.08.2015
comment
Задается здесь, потому что математики часто дают ответ, который нелегко (или неясно, как) реализовать, например, вершина является ухом, если линия, соединяющая соседние точки, полностью находится внутри многоугольника... верное утверждение, но бесполезное для фактического кодирования. Я прошу алгоритм, который я могу закодировать.   -  person Joe Strout    schedule 28.08.2015
comment
@JoeStrout Я знаю, что у вас уже есть удовлетворительный ответ, поэтому просто хотел обратить ваше внимание на то, что я добавил другой (более простой?) подход, и я не был уверен, что вы придете искать другой ответ.   -  person Amit    schedule 29.08.2015


Ответы (3)


Если бы я был вами, я бы сделал это следующим образом:

  1. Выберите любую точку C рядом с многоугольником (любую вершину или центр масс).
  2. Сумма перекрестных произведений (P[i] – C) x (P[i+1] – C) для всех i (включая последнюю и первую пару точек).
  3. Нормируйте вектор суммы.

Обратите внимание, что после шага 2 у вас есть вектор, который имеет нормальное направление с правильной ориентацией, а его величина составляет 2 S, где S — площадь вашего многоугольника. Вот почему это должно работать, если только ваш многоугольник не имеет нулевой или почти нулевой площади.

Кстати, точка C здесь используется только для того, чтобы сделать расчет немного точнее для небольших полигонов, расположенных далеко от начала координат. Вы можете выбрать C = 0, эффективно исключив его из расчетов.

person stgatilov    schedule 28.08.2015
comment
Протестировано и подтверждено, что работает (по крайней мере, во всех моих тестах). Большое спасибо! - person Joe Strout; 28.08.2015
comment
@YvesDaoust: я уверен, что вы полностью прочитали вопрос. Ваше решение не дает правильной ориентации нормали. Более того, он может быть нестабильным (в зависимости от реализации). - person stgatilov; 28.08.2015

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

Надежное решение состоит в том, чтобы найти наибольшее векторное произведение (P[i] - C) x (P[j] - C) для всех i, j, (i ‹ j) и нормализовать его. Он будет соответствовать самому большому вписанному треугольнику многоугольника.

person kireevtf    schedule 05.03.2019
comment
не может ли это в конечном итоге указать неправильный путь для вогнутых многоугольников? Каков выбор С? - person Alec Jacobson; 22.12.2020

Вычислите три области со знаком трех многоугольников, полученные в результате проекции вашего трехмерного многоугольника на XY, Самолеты YZ и ZX, что дает вам желаемую нормаль.

person Yves Daoust    schedule 29.08.2015
comment
В необычных/патологических случаях, когда площадь многоугольника мала по сравнению с его диаметром (многоугольники с большими отверстиями, скрещенные многоугольники), ситуацию, вероятно, можно улучшить, используя выпуклые оболочки (полученные с помощью алгоритма Мелкмана) вместо исходных многоугольников. В большинстве ситуаций это будет излишним. - person Yves Daoust; 29.08.2015