Пересечение полигонов

дано два многоугольника. как определить, находится ли один многоугольник внутри, снаружи или пересекает другой многоугольник? Полигоны могут быть вогнутыми или выпуклыми.

4 ответов


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

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

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


Как правило, такие проблемы легко решаются алгоритмом развертки. Тем не менее, основная цель и преимущество использования подхода sweep-line заключается в том, что он может эффективно решить проблему, когда вход состоит из двух относительно большие наборы полигонов. Как только решение линии развертки будет реализовано, оно также может быть эффективно применено к паре полигонов, если возникнет необходимость. Возможно, вам стоит подумать о том, чтобы двигаться в этом направлении, если вам нужно будет решить массивную проблемы в будущем.

однако, если вы уверены , что вам нужно решение для двух и только двух полигонов, то его можно решить с помощью последовательных тестов point-vs-polygon и segment-vs-polygon.


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

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

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

затем вы можете использовать этот метод так, как Томас описано в его ответе, чтобы проверить, пересекаются ли два полигона. Это должно дать вам O(NM) алгоритм, где два полигона имеют N и M вершин соответственно.


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

bool isInside(point a, polygon B)
{
    double angle = 0;
    for(int i = 0; i < B.nbVertices(); i++)
    {
        angle += angle(B[i],a,B[i+1]);
    }
    return (abs(angle) > pi);
}
  • если отрезок линии A пересекает отрезок линии B, то два полигона пересекаются друг с другом.
  • Else если все точки многоугольника A находятся внутри многоугольника B, то A находится внутри B.
  • Else если все точки многоугольника B находятся внутри многоугольника A, то B находится внутри A.
  • Else если все точки многоугольника A находятся вне многоугольника B, то A на улице Б.
  • еще два полигона пересекаются друг с другом.