Как найти расстояние между многоугольниками

I doubt there is better solution than calculating the distance between the red one and every blue one and sorting these by length.

Regarding sorting, usually QuickSort is hard to beat in performance (an optimized one, that cuts off recursion if size goes below 7 items and switches to something like InsertionSort, maybe ShellSort).

Thus I guess the question is how to quickly calculate the distance between two polygons, after all you need to make this computation 50 times.

The following approach will work for 3D as well, but is probably not the fastest one:

Minimum Polygon Distance in 2D Space

The question is, are you willing to trade accuracy for speed? E.g. you can pack all polygons into bounding boxes, where the sides of the boxes are parallel to the coordinate system axes. 3D games use this approach pretty often. Therefor you need to find the maximum and minimum values for every coordinate (x, y, z) to construct the virtual bounding box. Calculating the distances of these bounding boxes is then a pretty trivial task.

Here’s an example image of more advanced bounding boxes, that are not parallel to the coordinate system axes:

Oriented Bounding Boxes — OBB

However, this makes the distance calculation less trivial. It is used for collision detection, as you don’t need to know the distance for that, you only need to know if one edge of one bounding box lies within another bounding box.

The following image shows an axes aligned bounding box:

Axes Aligned Bounding Box — AABB

OOBs are more accurate, AABBs are faster. Maybe you’d like to read this article:

Advanced Collision Detection Techniques

This is always assuming, that you are willing to trade precision for speed. If precision is more important than speed, you may need a more advanced technique.


Re[3]: Расстояние между многоугольниками

От:

wvk

Россия

 
Дата:  01.07.03 15:55
Оценка:

3 (1)

Здравствуйте, Croc, Вы писали:

C>Здравствуйте, wvk.

C>Спасибо за отклик.

wvk>>Ты не упомянул об отбрасывании по минимальному расстоянию между охватывающими прямоугольниками.


C>Да, за истекшее время я уже нашел и реализовал такой критерий. Кстати, точнее — охватывающие параллелипипеды (у меня — 3D).

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

wvk>>И тест на пересечение, я надеюсь не порёберная проверка.

C>С этого места, пожалуйста, подробнее?
C>Единственный окончательный критерий того, что они пересекаются, который я на данный момент осознал, такой: какое-либо ребро пересекает внутренность другого многоугольника. Вы знаете лучше? Подскажите, пожалуйста.

Очевидно они могут пересекаться только по линии пересечения плоскостей
несложно для каждого найти пересечение с этой линией, и сравнивать уже их.


Расстояние между многоугольниками

От:

Croc

Россия

 
Дата:  09.06.03 16:04
Оценка:

Здравствуйте, уважаемые эксперты.

Есть задача определения расстояния* между двумя плоскими многоугольниками в пространстве . (плоскости произвольные).
Без потери интереса к реализации можно ограничиться выпуклыми многоугольниками.
Я пока не придумал ничего лучше, чем:
1) Измерить попарно расстояние между ребер.
2) Измерить расстояние от всех вершин до другого многоугольника.
3) Проверить, не пересекают ли ребра другой многоугольник (расстояние 0).
Соответственно, наименьшее из них и будет искомым.
Есть ли какие-то принуипиально более интересные алгоритмы?

Также интересны эффективные критерии грубой нижней оценки.
То есть, если меня интересуют только близкие расстояния (<D), при этом вероятность такого события < X (например, 5 %),
то я готов сначала провернуть нечто, в дальнейшем бесполезное, если оно, например, на 20% быстрее выяснит, что расстояние заведомо больше D.

Спасибо за Ваши ссылки и идеи.

*формально, речь о наименьшем расстоянии между произвольной парой точек, принаждлежащих этим мноугольникам.


Re: Расстояние между многоугольниками

От:

wvk

Россия

 
Дата:  27.06.03 12:55
Оценка:

Здравствуйте, Croc, Вы писали:

<skip>

Ты не упомянул об отбрасывании по минимальному расстоянию между охватывающими прямоугольниками.
И тест на пересечение, я надеюсь не порёберная проверка.
А так, для выпуклых, наверное только полным перебором пар вершин…


Re: Расстояние между многоугольниками

От:

Кодт

Россия

 
Дата:  30.06.03 18:04
Оценка:

Здравствуйте, Croc, Вы писали:

Грубейшая оценка расстояния снизу:
— вокруг многоугольника описываем окружность (как получится);
— находим расстояние между центрами окружностей искомых многоугольников, вычитаем радиусы (как бы имеем дело с описывающими сферами).
(для нахождения описывающей окружности можно, например, взять за ее диаметр отрезок между наиболее удаленными вершинами многоугольника)

Более тонкая оценка:
— вычитаем не радиус окружности, а проекцию его на линию, проходящую через центры (для каждого прямоугольника нужно знать нормаль плоскости)

Еще более тонкая:
— переходим в (ортонормированную) систему координат, в которой OXY совпадает с плоскостью первого многоугольника
— находим проекцию второго многоугольника на эту плоскость
— находим расстояние Df между проекцией и первым многоугольником на плоскости, а также наименьшее расстояние H до плоскости
— D >= sqrt(Df^2 + H^2)
(вместо многоугольника можно рассмотреть описывающую окружность)

http://files.rsdn.org/4783/catsmiley.gif Перекуём баги на фичи!


Re[2]: Расстояние между многоугольниками

От:

Croc

Россия

 
Дата:  01.07.03 13:20
Оценка:

Здравствуйте, wvk.
Спасибо за отклик.

wvk>Ты не упомянул об отбрасывании по минимальному расстоянию между охватывающими прямоугольниками.

Да, за истекшее время я уже нашел и реализовал такой критерий. Кстати, точнее — охватывающие параллелипипеды (у меня — 3D).

wvk>И тест на пересечение, я надеюсь не порёберная проверка.

С этого места, пожалуйста, подробнее?
Единственный окончательный критерий того, что они пересекаются, который я на данный момент осознал, такой: какое-либо ребро пересекает внутренность другого многоугольника. Вы знаете лучше? Подскажите, пожалуйста.
С другой стороны, я использую дополнительные проверки, которые во многих случаях «говорят», что они заведомо не пересекаются.

wvk>А так, для выпуклых, наверное только полным перебором пар вершин…

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


Re[2]: Расстояние между многоугольниками

От:

Croc

Россия

 
Дата:  01.07.03 13:30
Оценка:

Здравствуйте, Кодт, спасибо за идеи:

К>Грубейшая оценка расстояния снизу:

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

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

К>Более тонкая оценка:

К>- вычитаем не радиус окружности, а проекцию его на линию, проходящую через центры (для каждого прямоугольника нужно знать нормаль плоскости)

К>Еще более тонкая:

К>- переходим в (ортонормированную) систему координат, в которой OXY совпадает с плоскостью первого многоугольника
К>- находим проекцию второго многоугольника на эту плоскость
К>- находим расстояние Df между проекцией и первым многоугольником на плоскости, а также наименьшее расстояние H до плоскости
К>- D >= sqrt(Df^2 + H^2)
К>(вместо многоугольника можно рассмотреть описывающую окружность)

А вот это уже по выч. мощности близко к точному расчету расстояния.

Еще раз спасибо за мысли.


Re[3]: Расстояние между многоугольниками

От:

Кодт

Россия

 
Дата:  01.07.03 13:46
Оценка:

Здравствуйте, Croc, Вы писали:

К>>Грубейшая оценка расстояния снизу:

К>>- находим расстояние между центрами окружностей искомых многоугольников, вычитаем радиусы (как бы имеем дело с описывающими сферами).

C>Это, все же, на порядок сложней описывающего параллелипипида, при приблизительно той же эффективности.

Я исходил из того, что если нужно находить расстояния «каждый с каждым», то можно предварительно найти центры и радиусы (O(N*V), N — число многоугольников, V — число вершин), а затем быстро-быстро…

Хотя с параллелепипедами будет быстрее… Но искать расстояние между параллелепипедами — более сложная задача; впрочем, можно сделать объединение подходов:
— центр параллелепипеда находим элементарно
— радиус = половине макс.габарита

К>>Еще более тонкая:

К>>- переходим в (ортонормированную) систему координат, в которой OXY совпадает с плоскостью первого многоугольника
К>>- находим проекцию второго многоугольника на эту плоскость
К>>- находим расстояние Df между проекцией и первым многоугольником на плоскости, а также наименьшее расстояние H до плоскости
К>>- D >= sqrt(Df^2 + H^2)
К>>(вместо многоугольника можно рассмотреть описывающую окружность)

C>А вот это уже по выч. мощности близко к точному расчету расстояния.


Но опять же, если мы для каждого многоугольника проведем предварительную работу по нахождению нормали его плоскости…

Между прочим, гарантировать что многоугольник плоский можно только для треугольников.
Ты это как-то фиксируешь?

http://files.rsdn.org/4783/catsmiley.gif Перекуём баги на фичи!


Re[4]: Расстояние между многоугольниками

От:

Croc

Россия

 
Дата:  02.07.03 16:02
Оценка:

Здравствуйте, wvk, Вы писали:

wvk>>>И тест на пересечение, я надеюсь не порёберная проверка.


wvk>Очевидно они могут пересекаться только по линии пересечения плоскостей
wvk>несложно для каждого найти пересечение с этой линией, и сравнивать уже их.

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

В любом случае мысль хороша, спасибо.


Re[4]: Расстояние между многоугольниками

От:

Croc

Россия

 
Дата:  02.07.03 17:03
Оценка:

Здравствуйте, Кодт, Вы писали:

К>Я исходил из того, что если нужно находить расстояния «каждый с каждым», то можно предварительно найти центры и радиусы (O(N*V), N — число многоугольников, V — число вершин), а затем быстро-быстро…


К>Хотя с параллелепипедами будет быстрее… Но искать расстояние между параллелепипедами — более сложная задача;

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

К>Между прочим, гарантировать что многоугольник плоский можно только для треугольников.

К>Ты это как-то фиксируешь?

Ну это уже издержки

Подождите ...

Wait...

  • Переместить
  • Удалить
  • Выделить ветку

Пока на собственное сообщение не было ответов, его можно удалить.

Луогу P2742

Найти окружность выпуклой оболочки

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e4+1;
const double eps=1e-8;
struct point
{
    double x,y;
    point(){}
    point(double a,double b)
    {
        x=a;y=b;
    }
         оператор точки (const point & a) const // разность векторов
    {
        return point(x-a.x,y-a.y);
    }
         двойной оператор ^ (const point & a) const // Векторное перекрестное произведение
    {
        return x*a.y-y*a.x;
    }
         двойной оператор * (const point & a) const // Векторное произведение точек
    {
        return x*a.x+y*a.y;
    }
}p[MAX],b[MAX];
int top,n;
 двойное пересечение (точка a, точка b, точка c) // перекрестное произведение (площадь треугольника * 2
{
    return (b-a)^(c-a);
}
 double dis (точка a, точка b) // Расстояние между двумя точками sqrt (dis)
{
    return (a-b)*(a-b);
}
bool cmp(point a,point b)
{
    double tmp=cross(p[0],a,b);
    if(tmp>eps||(fabs(tmp)<eps&&dis(p[0],a)-dis(p[0],b)>eps)) return 1;
    return 0;
}
void graham()
{
    int u=0;top=0;
    for(int k=1;k<n;k++)
        if(p[u].y-p[k].y>eps||(fabs(p[u].y-p[k].y)<eps&&p[u].x-p[k].x>eps))
            u=k;
    swap(p[u],p[0]);
    sort(p+1,p+n,cmp);
    if(n>0) {b[0]=p[0];top++;}
    if(n>1) {b[1]=p[1];top++;}
    if(n<3) return ;
    for(int i=2;i<n;i++)
    {
        while(top>1&&cross(b[top-2],b[top-1],p[i])<eps) top--;
        b[top++]=p[i];
    }
}
int main()
{
    double sum=0;
    scanf("%d",&n);
    for(int k=0;k<n;k++)
        scanf("%lf%lf",&p[k].x,&p[k].y);
    graham();
    b[top]=b[0];
    for(int k=1;k<=top;k++)
        sum+=sqrt(dis(b[k],b[k-1]));
    printf("%.2fn",sum);
    return 0;
}

POJ3348 Cows

Найти площадь выпуклой оболочки

int main()
{
    double sum=0;
    scanf("%d",&n);
    for(int k=0;k<n;k++)
        scanf("%lf%lf",&p[k].x,&p[k].y);
    graham();
    for(int k=1;k<top-1;k++)
        sum + = fabs (cross (b [0], b [k], b [k + 1])); // Сумма произведений креста треугольника в выпуклой оболочке
    printf("%dn",(int)(sum/100));
    return 0;
}

POJ2187 Beauty Contest

Поверните держатель карты, чтобы найти самую дальнюю точку

double rotating()
{
    double ans=0;
    b[top]=b[0];
    for(int k=0,i=1;k<=top;k++)
    {
        while(fabs(cross(b[k],b[i+1],b[k+1]))-fabs(cross(b[k],b[i],b[k+1]))>eps)
            i=(i+1)%top;
        ans=max(ans,dis(b[i],b[k]));
    }
    return ans;
}

Поверните держатель карты, чтобы найти минимальную ширину выпуклой оболочки

double rotating()
{
    double ans=0x3f3f3f3f;
    b[top]=b[0];
    for(int k=0,i=1;k<=top;k++)
    {
        while(fabs(cross(b[k],b[i+1],b[k+1]))-fabs(cross(b[k],b[i],b[k+1]))>eps)
            i=(i+1)%top;
        ans=min(ans,fabs(cross(b[k],b[k+1],b[i])/sqrt(dis(b[k],b[k+1]))));
    }
    return ans;
}

HDU2202 самый большой треугольник

Поверните держатель карты, чтобы найти самый большой треугольник в плоскости

double rotating()
{
    double ans=0;
    for(int k=0;k<top;k++)
    {
        int i=(k+1)%top;
        int j=(i+1)%top;
        while(i!=k&&j!=k)
        {
            ans=max(ans,fabs(cross(b[k],b[i],b[j])));
            while(fabs(cross(b[k],b[i+1],b[j]))-fabs(cross(b[k],b[i],b[j]))>eps)
                i=(i+1)%top;
            j=(j+1)%top;
        }
    }
    return ans;
}

POJ3608 Bridge Across Islands

Поверните держатель карты, чтобы найти кратчайшее расстояние между двумя выпуклыми корпусами (мин) / наибольшее расстояние (макс.)

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
const int MAX=1e4+5;
const double eps=1e-8;
const double INF=1e99;
struct point
{
    double x,y;
    point(){}
    point(double a,double b)
    {
        x=a;y=b;
    }
         оператор точки (const point & a) const // разность векторов
    {
        return point(x-a.x,y-a.y);
    }
         двойной оператор ^ (const point & a) const // Векторное перекрестное произведение
    {
        return x*a.y-y*a.x;
    }
         двойной оператор * (const point & a) const // Векторное произведение точек
    {
        return x*a.x+y*a.y;
    }
}p[MAX],b1[MAX],b2[MAX];
int top1,top2;
double min(double a,double b)
{
    return a-b<-eps?a:b;
}
 двойное пересечение (точка a, точка b, точка c) // перекрестное произведение (площадь треугольника * 2
{
    return (b-a)^(c-a);
}
 двойное мульти (точка a, точка b, точка c) // точка произведения
{
    return (b-a)*(c-a);
}
 double dis (точка a, точка b) // Расстояние между двумя точками sqrt (dis)
{
    return (a-b)*(a-b);
}
 double dist (точка a, точка b, точка c) // Кратчайшее расстояние отрезка точечной линии a  bc
{
    point d;
    double t=multi(b,a,c)/dis(b,c);
    if(t>-eps&&t-1<eps) d=point(b.x+(c.x-b.x)*t,b.y+(c.y-b.y)*t);
    else
    {
        if(dis(a,b)-dis(a,c)<-eps) d=b;
        else d=c;
    }
    return dis(a,d);
}
 // двойное расстояние (точка a, точка b, точка c) // sqrt (dis)
//{
//    if(dis(b,c)<eps) return dis(a,c);
//    if(multi(b,c,a)<-eps) return dis(a,b);
//    if(multi(c,b,a)<-eps) return dis(a,c);
//    return fabs(cross(b,c,a)/dis(b,c));
//}
 двойное расстояние (точка a, точка b, точка c, точка d) // расстояние между двумя отрезками линии ab  cd
{
    return min(min(dist(a,c,d),dist(b,c,d)),min(dist(c,a,b),dist(d,a,b)));
}
bool cmp(point a,point b)
{
    double tmp=cross(p[0],a,b);
    if(tmp>eps||(fabs(tmp)<eps&&dis(p[0],a)-dis(p[0],b)>eps)) return 1;
    return 0;
}
void graham(point *b,int n,int &top)
{
    int u=0;top=0;
    for(int k=1;k<n;k++)
        if(p[u].y-p[k].y>eps||(fabs(p[u].y-p[k].y)<eps&&p[u].x-p[k].x>eps))
            u=k;
    swap(p[u],p[0]);
    sort(p+1,p+n,cmp);
    if(n>0) {b[0]=p[0];top++;}
    if(n>1) {b[1]=p[1];top++;}
    if(n<3) return ;
    for(int i=2;i<n;i++)
    {
        while(top>1&&cross(b[top-2],b[top-1],p[i])<eps) top--;
        b[top++]=p[i];
    }
}
double rotating(point *a,int n,point *b,int m)
{
    int i1=0,i2=0;
    for(int k=0;k<n;k++)
        if(a[k].y-a[i1].y<-eps) i1=k;
    for(int k=0;k<m;k++)
        if(b[k].y-b[i2].y>eps) i2=k;
    a[n]=a[0];b[m]=b[0];
    double tmp,ans=INF;
    for(int k=0;k<n;k++)
    {
        while((tmp=cross(a[i1+1],b[i2+1],a[i1])-cross(a[i1+1],b[i2],a[i1]))>eps)
            i2=(i2+1)%m;
        if(tmp<-eps) ans=min(ans,dist(b[i2],a[i1],a[i1+1]));
        else ans=min(ans,distence(a[i1],a[i1+1],b[i2],b[i2+1]));
        i1=(i1+1)%n;
    }
    return ans;
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m)&&(n||m))
    {
        for(int k=0;k<n;k++) scanf("%lf%lf",&p[k].x,&p[k].y);
        graham(b1,n,top1);
        for(int k=0;k<m;k++) scanf("%lf%lf",&p[k].x,&p[k].y);
        graham(b2,m,top2);
                 // Double и float могут выводиться только с% f, когда G ++ компилируется, float конвертируется в double, C ++ не влияет, обычно G ++ преобладает во время игры
        printf("%0.5fn",sqrt(min(rotating(b1,top1,b2,top2),rotating(b2,top2,b1,top1))));
    }
    return 0;
}

* Замечания по компиляции G ++ (ming32 / linux) C ++ в конкурсе ACM

HDU5251 прямоугольная зона

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

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
const int MAX=1e4+5;
const double eps=1e-8;
const double INF=1e99;
struct point
{
    double x,y;
    point(){}
    point(double a,double b)
    {
        x=a;y=b;
    }
         оператор точки (const point & a) const // разность векторов
    {
        return point(x-a.x,y-a.y);
    }
         двойной оператор ^ (const point & a) const // Векторное перекрестное произведение
    {
        return x*a.y-y*a.x;
    }
         двойной оператор * (const point & a) const // Векторное произведение точек
    {
        return x*a.x+y*a.y;
    }
}p[MAX],b[MAX];
int top,n;
double min(double a,double b)
{
    return a-b<-eps?a:b;
}
 двойное пересечение (точка a, точка b, точка c) // перекрестное произведение (площадь треугольника * 2
{
    return (b-a)^(c-a);
}
 двойное мульти (точка a, точка b, точка c) // точка произведения
{
    return (b-a)*(c-a);
}
 double dis (точка a, точка b) // Расстояние между двумя точками sqrt (dis)
{
    return (a-b)*(a-b);
}
bool cmp(point a,point b)
{
    double tmp=cross(p[0],a,b);
    if(tmp>eps||(fabs(tmp)<eps&&dis(p[0],a)-dis(p[0],b)>eps)) return 1;
    return 0;
}
void graham()
{
    int u=0;top=0;
    for(int k=1;k<n;k++)
        if(p[u].y-p[k].y>eps||(fabs(p[u].y-p[k].y)<eps&&p[u].x-p[k].x>eps))
            u=k;
    swap(p[u],p[0]);
    sort(p+1,p+n,cmp);
    if(n>0) {b[0]=p[0];top++;}
    if(n>1) {b[1]=p[1];top++;}
    if(n<3) return ;
    for(int i=2;i<n;i++)
    {
        while(top>1&&cross(b[top-2],b[top-1],p[i])<eps) top--;
        b[top++]=p[i];
    }
}
double rotating()
{
    int r=1,u=1,l;
    double ans=INF;
    b[top]=b[0];
    for(int k=0;k<top;k++)
    {
        while(cross(b[k],b[k+1],b[u+1])-cross(b[k],b[k+1],b[u])>-eps) u=(u+1)%top;
        while(multi(b[k],b[k+1],b[r+1])-multi(b[k],b[k+1],b[r])>eps) r=(r+1)%top;
        l=k==0?r:l;
        while(multi(b[k],b[k+1],b[l+1])-multi(b[k],b[k+1],b[l])<eps) l=(l+1)%top;
        ans=min(ans,fabs(cross(b[k],b[k+1],b[u]))*fabs(multi(b[k],b[k+1],b[r])-multi(b[k],b[k+1],b[l]))/dis(b[k],b[k+1]));
    }
    return ans;
}
int main()
{
    int t;
    scanf("%d",&t);
    for(int tc=1;tc<=t;tc++)
    {
        scanf("%d",&n);n*=4;
        for(int k=0;k<n;k++) scanf("%lf%lf",&p[k].x,&p[k].y);
        graham();
        printf("Case #%d:n%dn",tc,(int)(rotating()+0.5));
    }
    return 0;
}

Подробное объяснение выпуклой оболочки (переиздание)

1. Справочник

Немного истории:

В 1978 году докторская диссертация М.И. Шамоса «Вычислительная геометрия» ознаменовала зарождение этой области информатики. В то время он опубликовал очень простой алгоритм определения диаметра выпуклого многоугольника, который определялся по максимальному расстоянию между парой точек многоугольника.
Позже диаметр определялся парой точек противодействия пятке. Шамос предложил простой O (n) временной алгоритм для определения выпуклой пары контрапунктов. Поскольку они имеют не более 3n / 2 пар, диаметр можно рассчитать за время O (n).
Как позже предложил Туссен, алгоритм Шамоса похож на вращение пары заклинивающих оболочек вокруг многоугольника. Отсюда и термин «вращающийся джем». В 1983 году Туссен опубликовал статью, в которой использовался тот же метод для решения многих задач. С тех пор был создан новый алгоритм на основе этой модели, решающий многие проблемы.
Они включают в себя:

  • Рассчитать расстояние
    • Выпуклый диаметр многоугольника
    • Ширина выпуклого многоугольника
    • Максимальное расстояние между выпуклыми многоугольниками
    • Минимальное расстояние между выпуклыми полигонами
  • Ограничительный прямоугольник
    • Минимальная площадь прямоугольника
    • Минимальный периметр описанного прямоугольника
  • Триангуляция
    • Луковая триангуляция
    • Спиральная триангуляция
    • Четырехсторонний раскол
  • Свойства выпуклого многоугольника
    • Объединить выпуклый корпус
    • Найти котангенс
    • Выпуклое пересечение многоугольника
    • Критическая касательная
    • Выпуклая многоугольная векторная сумма
  • Самый тонкий раздел
    • Тончайшее поперечное сечение

Во-вторых, рассчитать расстояние

1. Выпуклый диаметр многоугольника

Мы определяем максимальное расстояние между любыми двумя точками на многоугольнике как диаметр многоугольника. Для определения этого диаметра может быть более одной пары точек. Фактически, для многоугольника с вершинами могут быть пары «точек диаметра».

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

Очевидно, что невозможно определить пару точек выпуклого многоугольника с диаметром внутри многоугольника. Поэтому поиск следует проводить на границе. На самом деле, поскольку диаметр определяется наибольшим расстоянием параллельных касательных многоугольника, нам нужно только запросить контрапункт. Shamos (1978) предлагает алгоритм сложности времени (O) для вычисления n точек пар выпуклой оболочки и пар пятки. Диаметр может быть получен путем обхода списка вершин, чтобы получить максимальное расстояние. Ниже приводится псевдокод алгоритма Шамоса, опубликованный в «Препарате и Шамосе» в 1985 году.
На входе используется многоугольник P = {p1, …, pn}.

begin
     p0:=pn;
     q:=NEXT[p];
     while (Area(p,NEXT[p],NEXT[q]) > Area(p,NEXT[p],q)) do
          q:=NEXT[q];
          q0:=q;
          while (q != p0) do
               begin
                    p:=NEXT[p];
                    Print(p,q);
                    while (Area(p,NEXT[p],NEXT[q]) > Area(p,NEXT[p],q) do
                         begin
                              q:=NEXT[q];
                              if ((p,q) != (q0,p0)) then Print(p,q)
                              else return
                         end;
                    if (Area(p,NEXT[p],NEXT[q]) = Area(p,NEXT[p],q)) then
                      if ((p,q) != (q0,p0)) then Print(p,NEXT[q])
                      else Print(NEXT[p],q)
               end
end.
 

ВотPrint(p,q)Указывает, что (p, q) выводится в качестве контрапункта,Area(p,q,r)Представляет направленную площадь треугольника pqr.
Хотя этот процесс интуитивно отличается от обычного алгоритма заклинивания с вращением, он, по сути, одинаков, и все вычисления углов исключаются.

Ниже приведен более интуитивный алгоритм:

  1. Рассчитать многоугольникyКонечная точка в направлении. Мы называем этоymin с ymax 。
  2. Проходитьymin с ymaxПостроить две горизонтальные касательные. Поскольку они уже являются парой контрапунктов, рассчитайте расстояние между ними и сохраните его как текущий максимум.
  3. Вращайте обе линии одновременно, пока одна из них не совпадет с одной стороной многоугольника.
  4. В это время генерируется новый контрапункт. Рассчитайте новое расстояние, сравните его с текущим максимальным значением и обновите его, если оно больше текущего максимального значения.
  5. Повторите процесс шага 3 и шага 4, пока пара контрпунктов не будет сгенерирована снова(ymin,ymax) 。
  6. Выход определяет максимальный диаметр пары пяточных точек.

Пока что описанный выше процесс (в псевдокоде) очень полезен. Мы можем получить другую информацию из пар контрапунктов, например, ширину многоугольника.

2. Ширина выпуклого многоугольника

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

Мы предполагаем, что есть отрезок [a, b] и две параллельные линии, проходящие через a и b. Вращая эти две линии вокруг этих двух точек, расстояние между ними увеличивается или уменьшается. В частности, всегда есть определенное направление вращения, которое уменьшает расстояние между двумя линиями при вращении.

Этот простой вывод можно применить к проблеме ширины: необходимо учитывать не все направления. Предположим, что для данного многоугольника существуют также две параллельные касательные. Если ни один из них не совпадает с краем, то мы всегда можем уменьшить расстояние между ними вращением. Следовательно, две параллельные касательные могут определять ширину многоугольника только в том случае, если хотя бы одна из них совпадает с ребром.

Это означает, что в процессе вычисления ширины необходимо учитывать пары «точка-к-пятке» и «край-к-краю».

Принципиальная схема ширины выпуклого многоугольника. Пары диаметра показаны в виде черных точек, пересекаемых параллельными касательными (красные линии). Диаметр показан светлой синей линией.

Алгоритм, очень похожий на задачу вычисления диаметра, можно получить, обойдя список пар пар пяток полигонов, определив пары вершин-ребер и ребер-ребер для вычисления ширины. Процесс выбора выглядит следующим образом:

  1. Рассчитать многоугольникyКонечная точка в направлении. Мы называем этоymin с ymax
  2. Проходитьymin с ymaxПостроить две горизонтальные касательные. Если линия (или две) линии совпадают с ребром, то создается пара «точка-точка-край» или пара «ребро-край». В это время расстояние между двумя линиями рассчитывается и сохраняется как текущее минимальное расстояние.
  3. Вращайте обе линии одновременно, пока одна из них не совпадет с одной стороной многоугольника.
  4. В это время генерируется новая пара «противоположная точка-кромка» (или пара «кромка-кромка», когда обе линии совпадают с кромкой). Рассчитайте новое расстояние, сравните его с текущим минимальным значением и обновите, если оно меньше текущего минимального значения.
  5. Повторяйте шаги 3 и 4 (застрявшие), пока начальная параллельная позиция края не будет достигнута снова.
  6. Пара полученного минимального значения выводится как пара определенной ширины.

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

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

Даны два выпуклых многоугольникаP с Q, Цель состоит в том, чтобы найти пару точек (p,q) (pПринадлежитPА такжеqПринадлежитQ) Максимизируйте расстояние между ними.

Интуитивно понятно, что эти точки не могут принадлежать соответствующим полигонам. Это условие на самом деле очень похоже на проблему диаметра:

Два выпуклых многоугольникаP с QМаксимальное расстояние между ними определяется парами контрапунктов между полигонами.
Хотя утверждение одно и то же, это определение отличается от пар контрапунктов данного выпуклого многоугольника.
Существенное различие между парами точек между и выпуклыми многоугольниками состоит в том, что касательная направлена ​​и обращена. На следующем рисунке показан пример:
 
Приведенный выше вывод подразумевает, что необходимо обнаруживать не только пары вершин, но и только конкретные пары вершин. Фактически, они только обнаруживают параллельную касательную, установленную алгоритмом на основе вращающегося шаблона заклинивания.
Рассмотрим следующий алгоритм, вход алгоритма — дваm с nВыпуклый многоугольник с заданной вершиной по часовой стрелкеP с Q

  1. расчетP yВершина с наименьшим значением координаты (называетсяyminP ) с Q yВершина с наибольшим значением координаты (называетсяymaxQ)。
  2. Для полигоновyminP с ymaxQДве касательные построеныLP с LQТак что соответствующие им полигоны находятся справа от них. на данный момент LPс LQЕсть разные направления, иyminP с ymaxQСтаньте контрапунктом между полигонами.
  3. Рассчитать расстояние (yminP,ymaxQ) И поддерживать его на текущем максимуме.
  4. Вращайте параллельные линии по часовой стрелке одновременно, пока одна из них не совпадет с краем многоугольника, на котором она находится.
  5. Создается новая пара контрапунктов. Новое расстояние вычисляется, сравнивается с текущим максимальным значением и обновляется, если оно больше текущего максимального значения. Если две линии совпадают с ребром в одно и то же время, необходимо рассмотреть в общей сложности три пары точек пятки (комбинацию предыдущей и новой вершин).
  6. Повторите шаги 4 и 5, пока новая пара точек не будет (yminP,ymaxQ)。
  7. Максимальное выходное расстояние.

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

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

4. Минимальное расстояние между выпуклыми многоугольниками

Для двух несвязных (например, непересекающихся) выпуклых многоугольников P и Q цель состоит в том, чтобы найти пару точек (p, q) с наименьшим расстоянием (p принадлежит P, а q принадлежит Q).

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

Возвращаясь к нашему основному вопросу: интуитивно, точка, определяющая минимальное расстояние, не может содержаться внутри многоугольника. Подобно проблеме максимального расстояния, мы имеем следующие выводы:

Минимальное расстояние между двумя выпуклыми многоугольниками P и Q устанавливается парами контрапунктов между многоугольниками. Существует три типа контрапунктов между выпуклыми многоугольниками, поэтому существует три возможных режима минимального расстояния:

  1. «Вертекс-Вертекс» ситуация
  2. Чехол «Vertex-edge»
  3. Ситуация «бок о бок»

Другими словами, пара точек, определяющая минимальное расстояние, не обязательно должна быть вершиной. Следующие три легенды иллюстрируют вышеприведенные выводы:
   
Учитывая результат, естественным образом возникает алгоритм, основанный на вращающихся заклинивших пластинах:
Рассмотрим следующий алгоритм: вход в алгоритм — два выпуклых многоугольника P и Q с m и n по заданным вершинам по часовой стрелке соответственно.

  1. расчетP yВершина с наименьшим значением координаты (называетсяyminP ) с Q yВершина с наибольшим значением координаты (называетсяymaxQ)。
  2. Для полигоновyminP с ymaxQДве касательные построеныLP с LQТак что соответствующие им полигоны находятся справа от них. на данный момент LPс LQЕсть разные направления, иyminP с ymaxQСтаньте контрапунктом между полигонами.
  3. Рассчитать расстояние (yminP,ymaxQ) И поддерживать его до текущего минимального значения.
  4. Вращайте параллельные линии по часовой стрелке одновременно, пока одна из них не совпадет с краем многоугольника, на котором она находится.
  5. Если с ребром совпадает только одна линия, то необходимо рассчитать только расстояние между парой точек пятки «вершина-край» и парой точек пятки «вершина-вершина». Оба сравнивают их с текущим минимальным значением, а также заменяют и обновляют, если оно меньше текущего минимального значения. Если обе касательные совпадают с ребрами, ситуация усложняется. Если ребра «перекрываются», то есть вы можете построить общую вертикальную линию, которая пересекает оба ребра (но не в вершине), а затем рассчитать расстояние «ребро-ребро». В противном случае вычислите расстояние между тремя новыми парами «вершина-вершина» точек пятки. Все эти расстояния сравниваются с текущим минимальным значением, и если оно меньше текущего минимального значения, замена обновляется.
  6. Повторите шаги 4 и 5, пока новая пара точек не будет (yminP,ymaxQ)。
  7. Максимальное выходное расстояние.

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

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

В-третьих, внешний прямоугольник

1. Выпуклый многоугольник, минимальная площадь описанного прямоугольника

Учитывая выпуклый многоугольникPНаименьшая площадь может быть установленаPЧто такое прямоугольник (с точки зрения периферии)? Технически, учитывая направление, его можно рассчитатьPКонечная точка и структура создают ограниченный прямоугольник. Но нам нужнотестовое заданиеПолучаете ли вы каждый прямоугольник для каждой ситуации, чтобы рассчитать минимальную площадь? Слава Богу, мы не должны это делать.

Для полигоновPОписанный прямоугольник имеет сторону, коллинеарную исходному многоугольнику.

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

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

Простой алгоритм — вычислять каждую сторону по очереди как сторону, которая совпадает с прямоугольником. Однако этот метод построения прямоугольника включает расчет конечных точек каждого ребра многоугольника, стоимостьO(n)Время (из-заnРасчет). Весь алгоритм будет иметь квадратичную сложность по времени.

Обнаружен более эффективный алгоритм. Используя вращающуюся пробку, мы можем обновлять в режиме реального времени в постоянное время вместо пересчета конечной точки.
На самом деле рассмотрим выпуклый многоугольник с двумя парами иx с yКасательная с четырьмя касательными точками в направлении. Четыре линии определили описанный прямоугольник многоугольника. Но если полигон не имеет горизонтальной или вертикальной стороны, площадь этого прямоугольника не может считаться минимальной площадью.
Однако вы можете поворачивать линию, пока не будет выполнено условие. Этот процесс является ядром подчиненного алгоритма. Предположим, вы вводите выпуклый многоугольник по часовой стрелкеnВершина.

  1. Рассчитайте конечные точки всех четырех полигонов и назовите этоxminP, xmaxP, yminP, ymaxP
  2. Построен через четыре точкиPЧетыре касательных. Они определили два набора «застрял».
  3. Если одна (или две) линии совпадают с ребром, то площадь прямоугольника, определяемая четырьмя линиями, вычисляется и сохраняется как текущее минимальное значение. В противном случае текущее минимальное значение определяется как бесконечность.
  4. Вращайте линию по часовой стрелке, пока один из них не совпадет с одной стороной многоугольника.
  5. Рассчитайте площадь нового прямоугольника и сравните его с текущим минимальным значением. Если оно меньше текущего минимального значения, оно обновляется, и информация о прямоугольнике, определяющая минимальное значение, сохраняется.
  6. Повторяйте шаги 4 и 5 до тех пор, пока угол поворота линии не станет больше 90 градусов.
  7. Минимальная площадь выходного прямоугольника.

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

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

2. Выпуклый многоугольник с минимальным периметром описанного прямоугольника

Эта проблема аналогична минимальной площади описанного прямоугольника. Наша цель — найти самый маленький прямоугольник (с точки зрения периметра) описанного многоугольника.P 。 

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

Теперь, учитывая направление, мы можем рассчитатьPКонечная точка используется для определения ограниченного прямоугольника. Однако, как и в случае с площадью, из-за следующих выводов нам не нужно проверять каждое состояние, чтобы получить прямоугольник с наименьшим периметром:

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

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

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

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

  1. Рассчитайте конечные точки всех четырех полигонов и назовите этоxminP, xmaxP, yminP, ymaxP
  2. Построен через четыре точкиPЧетыре касательных. Они определили два набора «застрял».
  3. Если одна (или две) линии совпадают с ребром, то площадь прямоугольника, определяемая четырьмя линиями, вычисляется и сохраняется как текущее минимальное значение. В противном случае текущее минимальное значение определяется как бесконечность.
  4. Вращайте линию по часовой стрелке, пока один из них не совпадет с одной стороной многоугольника.
  5. Рассчитайте периметр нового прямоугольника и сравните его с текущим минимальным значением. Если оно меньше текущего минимального значения, оно обновляется, и информация о прямоугольнике, определяющая минимальное значение, сохраняется.
  6. Повторяйте шаги 4 и 5 до тех пор, пока угол поворота линии не станет больше 90 градусов.
  7. Минимальный периметр выходного прямоугольника.

Поскольку две пары «застрял» определяют ограниченный прямоугольник, этот алгоритм учитывает все прямоугольники, которые могут рассчитать наименьший периметр. Кроме того, в дополнение к начальному значению, основной цикл алгоритма должен только выполнить общее количество вершин несколько раз. Следовательно, алгоритм имеет линейную сложность по времени.

Обработка проблем также включает треугольники. Существует два особых случая: подробности см. В разделе Триангуляция лука и Спиральная триангуляция.

4. Триангуляция

1. Луковая триангуляция

Учитывая набор точек на плоскости, цель состоит в том, чтобы построить триангуляцию множества точек.

От исходного алгоритма квадратичной сложности времени Ленна в 1911 году до алгоритма линейной сложности времени Чазеля 1991 года предшественники провели множество исследований по повышению эффективности алгоритмов триангуляции.

Основное внимание здесь уделяется специальному виду триангуляции, основанному на операции «очищение лука» от заданной точки.
Рассмотрим один на плоскостиnКоллекция очковS, расчетSВыпуклый корпус и дизайнS’Множество точек в выпуклой оболочке. Затем рассчитайтеS’Выпуклый корпус и повторите эту операцию, пока не осталось никаких точек. Наконец, есть выпуклая последовательность корпусов, покрытых как птичье гнездо, называемое луковой оболочкой.S, Благодаря алгоритму Шазеля эта структура можетO(n log n) В течение времени работы.

Набор луковых шкур. Обратите внимание, что в дополнение к выпуклому многоугольнику самая внутренняя структура может быть отрезком или одной точкой. На этом рисунке представлена ​​иерархическая информация о точках, например, какая из них находится относительно «глубже» между точками.

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

Алгоритм торической триангуляции очень прост. Алгоритм ввода выпуклой оболочкиPВыпуклая оболочка пакетаQИх вершины по часовой стрелке.

  1. Вставьте край выпуклой оболочки как треугольный край.
  2. расчетP с QизxТочки с наименьшими координатами называютсяxmin(P) с xmin(Q) 。
  3. Вxmin(P) с xmin(Q)Есть две вертикальные касательные линии, называемыеLP с LQ 。
  4. Будет (xmin(P)xmin(Q)) Вставьте как треугольный край.
  5. ТекущийLP с LQсоответствующийp с qОчкиxmin(P) с xmin(Q)
  6. Поверните нить по часовой стрелке, пока один из них не совпадет с ребром. Таким образом, новая вершина «вычеркивается» линией.
    • Если он принадлежитP(Известный как)p’), Вставить (p’q) В триангуляцию. Обновить текущую точку доp’ с p’ 。
    • Если он принадлежитQ(Называется q ‘), вставьте (pq’) В триангуляцию. Обновить текущую точку доp с q’ 。
    • Для случая параллельных ребер обе касательные совпадают с ребрами, и две новые вершины являются «хитами» (назовите их «p’ с q’). Затем вставьте (p’q’) , а также (pq’) с (p’q) В триангуляцию. Обновить текущую точку доp’ с q’ 。
  7. Повторите вышеуказанные шаги, пока не будет достигнута начальная минимальная точка.

Триангуляция изменения лица выглядит следующим образом:

Вышеприведенный алгоритм имеет линейную сложность по времени. При триангуляции набора точек выпуклая оболочка обходится (не более) дважды в течение всего процесса, а самая внутренняя и внешняя выпуклая оболочка пересекается только один раз. Так что дляnОбщее время работы триангуляции в одной точкеO(n) 。 

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

2. Спиральная триангуляция

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

  1. Начните с определенной конечной точки (например, минимальной точки в заданном направлении), где берется минимумxКоординатные точки.
  2. Постройте отвесную линию через эту точку.
  3. Вращайте линию в заданном направлении (всегда держите ее по часовой стрелке или против часовой стрелки), пока линия не «ударит» другую вершину.
  4. Соедините две точки отрезком.
  5. Повторите шаги 3 и 4, но всегда игнорируйте точки, которые были поражены.

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

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

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

Алгоритм построения спиральной триангуляции, хотя и основан на триангуляции тора, более сложен, поскольку спираль должна быть разделена на подходящие выпуклые цепи корпуса. Предположим, что вход представляет собой выпуклую спираль по часовой стрелке из набора точекCИ естьC = { p1 , … , pn } 。

  1. Вставьте край выпуклой спирали как треугольный край.
  2. От p1В начале ищите последнюю точку на выпуклой спирали множества точекph 。
  3. Расширить последний край выпуклой спирали [p(n-1),pn] Пока не пересекает выпуклую спираль. Отметить пересечение какq’ 。
  4. Структура иCВырезать в точкуq’Tangent. Поверните эту линию против часовой стрелки, пока он иCПересечь в одной точкеqИ параллельно с [p(n-1),pn] 。
  5. Будет [p(n-1), q] Вставьте в триангуляцию.
  6. После этой операции выпуклая спиральная цепь делится на две части: часть вне цепи и многоугольная область внутри цепи. Предполагать Co = { p1 , … , qА такжеCi = { ph , … , q , … , pn}. Процесс строительства показан ниже:  

    Верхний левый угол: процесс строительства. Верхний правый угол: многоугольная область снаружи и внутри спирали. Внизу: внешние и внутренние выпуклые цепиCo сCi 。

  7. Внешняя спиральная область может быть триангулирована как тор.Co с CiВ это время его можно рассматривать как вложенную выпуклую оболочку.
  8. Внутренняя многоугольная область может быть легкоpnЗвездные деления образуют триангуляцию.
  9. Комбинация этих двух триангуляций составляет всю структуру спиральной триангуляции.

Пример спиральной выпуклой оболочки и ее триангуляции показаны ниже:

Вышеупомянутый алгоритм имеет линейную временную сложность, и время алгоритма зависит от времени работы тора.

3. Четырехсторонний раскол

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

Четырехстороннее разбиение на самом деле является четырехугольным разбиением набора точек. Следует отметить некоторые существенные отличия от триангуляции (кроме тех, которые особенно очевидны):
Прежде всего, не все наборы точек имеют четырехугольные разбиения. Фактически доступен только набор четных точек. Для множества нечетных точек иногда необходимо добавить точки (называемые точками Штейнера) к исходному набору, чтобы построить четырехугольное разбиение.
В то же время люди часто ожидают, что структура четырехугольного разбиения будет иметь некоторые «хорошие» свойства, такие как выпуклые. Это отличается от триангуляции.

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

Бозе и Туссен предложили в 1997 году начать с треугольной триангуляции набора точек для построения о-четырехугольного деления.
Если набор точек четный, то любая другая диагональная линия (добавленная в алгоритм спиральной триангуляции) удаляется для построения четырехугольного разбиения. Если это нечетное количество точек, то любая другая диагональная линия (например, последняя, ​​предпоследняя третья и т. Д.) Удаляется из последней диагональной линии, а одна добавляется рядом со удаленной первой диагональю. Очки Штейнера. На рисунке ниже показан первый случай (набор точек с четным числом точек). Спиральная триангуляция (слева) и окончательное четырехугольное деление (справа).

Потому что процесс удаления диагонали (и необходимые обновления) стоитO(n) Время, этот четырехугольный алгоритм имеет ту же сложность времени, что и спиральная триангуляция. Преимущество этого алгоритма в том, что его легко понять и реализовать (после того как установлена ​​выпуклая спираль), и фактически он производит «лучший» алгоритм четырехугольного расщепления, чем многие конкуренты.

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

Пять выпуклых свойств многоугольника

1. Слияние выпуклых оболочек

Рассмотрим следующие вопросы. Что такое два выпуклых многоугольника, какой наименьший выпуклый многоугольник содержит их объединение? Ответ — выпуклый многоугольник, полученный объединением выпуклых оболочек.

Объединение выпуклых оболочек может быть достигнуто неэффективно: с учетом всех вершин двух многоугольников вычислите выпуклые оболочки, соответствующие этим точкам. Существуют более эффективные методы, и они основаны на поиске мостов между полигонами. Следующая диаграмма описывает эту концепцию:

Два выпуклых многоугольника, которые не пересекаются. Объединенная выпуклая оболочка содержит выпуклую цепь корпуса из двух многоугольников (толстая синяя сплошная линия на пути), соединенная мостом между многоугольниками (синяя пунктирная линия на пути)

Учитывая два непересекающихся многоугольника, между многоугольниками есть два моста. Когда полигоны пересекаются, они имеют такое же количество мостов, что и количество вершин, как показано на следующем рисунке:

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

Суть операции объединения — метод разделяй и властвуй. Он также используется в полигонах. Очень простой способ получить выпуклую оболочку состоит в том, чтобы разделить набор точек на две части, вычислить выпуклые оболочки двух меньших наборов точек по отдельности и объединить их. Каждый набор снова делится до тех пор, пока количество элементов не станет достаточно маленьким (скажем, три или меньше), чтобы можно было легко получить выпуклый корпус.
Туссен предложил использовать вращающуюся карточную оболочку, чтобы найти мост между двумя выпуклыми многоугольниками. Основным преимуществом этого метода является то, что он использует возвратный путь, и полигоны могут перекрываться (другие алгоритмы требуют, чтобы полигоны не пересекались). Следующий вывод является основным процессом его алгоритма:
Для заданного выпуклого многоугольника P = {{p (1), …, p (m)} и Q = = {q (1), …, q (n)}, Пара точек (p (i), q (j)) образует мост между P и Q тогда и только тогда, когда:

  1. (p(i), q(j)) Формируем пару параллельных точек.
  2. p(i-1), p(i+1), q(j-1), q(j+1) расположены (p(i), q(j)) Та же сторона составленной линии.

Предполагая, что многоугольники заданы в стандартной форме, а вершины расположены по часовой стрелке, алгоритм выглядит следующим образом:

  1. Рассчитать отдельноP с QИмеет самый большойyВершины координат. Если таких точек более одного, возьмитеxСамая большая координата.
  2. Построить плоскую касательную этих точек, с многоугольником на правой стороне в качестве положительного направления (поэтому они указывают наx(Ось положительное направление).
  3. Одновременно вращайте две касательные по часовой стрелке, пока одна из них не пересекает край. Получить новую пару параллельных точек (p(i), q(j)). Для случая параллельных сторон получаются три пары параллельных пяточных точек.
  4. Для всех действительных пар параллельных пяток (p(i), q(j)): Решениеp(i-1), p(i+1), q(j-1), q(j+1) все находятся в точке подключения (p(i), q(j)) На той же стороне образовалась линия. Если это так, эта пара параллельных каблуков образует мост и отмечает его.
  5. Повторяйте шаги 3 и 4, пока касательная не вернется в исходное положение.
  6. Все возможные мосты были определены в это время. Объединенная выпуклая оболочка создается путем непрерывного соединения соответствующих выпуклых цепочек корпусов между мостами.

Приведенные выше выводы определяют правильность алгоритма. Время работы ограничено шагами 1, 5 и 6. Все они имеют O (N) время выполнения (N — общее количество вершин). Следовательно, алгоритм имеет сложность текущего времени.
 

Мост между выпуклыми многоугольниками фактически определяет другую полезную концепцию: общую касательную между многоугольниками. В то же время мост является также ядром алгоритма для вычисления пересечения выпуклых многоугольников.

2. Найти котангенс

Общая касательная — это простая прямая линия, которая касается многоугольника одновременно, и оба многоугольника находятся на одной стороне линии. Другими словами, общая касательная — это линия, которая касается обоих многоугольников. Пример показан ниже:
 

Два непересекающихся выпуклых многоугольника и общая касательная

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

Другой «версией» общей касательной двух многоугольников является касательная ключа. В этом случае многоугольник отделен с обеих сторон линии.

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

3. Выпуклое пересечение многоугольника

Учитывая два многоугольника, наш первый вопрос для обсуждения должен быть: «Они пересекаются?». Chazelle и Dobkin опубликовали алгоритм логарифмического времени в своей статье под названием «Обнаружение легче, чем вычисление» в 1980 году (название статьи очень уместно). Для пересечения многоугольников многие алгоритмы могут вычислять пересечение. Что интересно, так это вывод (предложенный Guibas), который доказывает, что существует взаимно-однозначное соответствие между точками пересечения многоугольников и мостами между ними.

Два многоугольника (светло-красный и синий) и их пересечение (светло-фиолетовый). Пересечение отмечено красным. Каждое пересечение связано с мостом между полигонами (отмечен красной пунктирной линией).

Туссен использовал выводы Гибаса из литературы 1985 года, а также свой предыдущий алгоритм поиска мостов для вычисления множеств пересечений. Его алгоритм использует мосты для вычисления множеств пересечений. Как только они найдены, аналогично операции объединения выпуклых оболочек, выпуклые цепи и множества пересечений образуют пересечение многоугольников.

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

G.T. Toussaint. A simple linear algorithm for intersecting convex polygons. The Visual Computer. 1: 118-123. 1985. 

Следующая проблема — найти критическую касательную двух выпуклых многоугольников.

4. Критическая касательная

Критическая касательная между двумя выпуклыми многоугольниками (обычно называемая линией CS) — это касательная, которая разделяет два многоугольника на разных сторонах линии. Другими словами, они разделяют многоугольники.
Линия CS может использоваться для планирования движения, видимости и подбора диапазона.

На следующем рисунке изображены два многоугольника и их две критические касательные.

Здесь следует отметить, что при условии, что данные приведены в стандартной форме, линия CS будет пересекать только два многоугольника в двух вершинах. Следовательно, линия CS определяется парой вершин между полигонами.
Следующий вывод описывает эту пару точек:

Для двух выпуклых многоугольников P, Q и двух вершин p (i), q (j) (соответственно принадлежащих P и Q) определить линию CS тогда и только тогда, когда:

  1. p (i), q (j) составляют пары контрапунктов между полигонами.
  2. p (i-1), p (i + 1) находится на стороне линии (p (i), q (j)), а q (j-1), q (j + 1) на другой стороне.

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

  1. Вычислите вершину с наименьшим значением координаты на P (называемую yminP) и вершину с наибольшим значением координаты на Q (называемую yymaxQ).
  2. Постройте две касательные линии LP и LQ для многоугольников в yyminP и ymaxQ так, чтобы их соответствующие многоугольники были справа от них. В это время LP и LQ имеют разные направления, а yminP и ymaxQ становятся контрпунктом между полигонами.
  3. Пусть p (i) = yminP, q (j) = ymaxQ. (p (i), q (j)) образует пару точек пятки между полигонами. Проверьте, есть ли одна сторона p (i-1), p (i + 1) на линии (p (i), q (j)) и q (j-1), q (j + 1) на другой стороне , Если оно выполнено, (p (i), q (j)) определяет линию CS.
  4. Вращайте эти две линии, пока одна из них не совпадет с краем соответствующего многоугольника.
  5. Новый контрапункт подтвержден. Если обе линии совпадают с ребром, необходимо рассмотреть три пары точек пятки (комбинация исходной вершины и новой вершины). Для всех пар контрпунктов выполните вышеуказанный тест.
  6. Повторяйте шаги 4 и 5, пока новая пара точек не станет (yminP, ymaxQ).
  7. Выходная линия CS.

Этот алгоритм в основном находит пары контрапунктов между всеми многоугольниками, вращая касательную вокруг многоугольников. После определения каждой пары контрпунктов выполните все необходимые тесты. После выполнения описанного выше процесса все критические касательные были найдены.
Время выполнения алгоритма определяется на шаге 1 и шаге 6, все они тратят время O (n) (все обнаружения занимают постоянное время. Поскольку существует точка отсчета O (n) Да, общая стоимость O (n)).

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

5. Векторная сумма выпуклых многоугольников

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

P + + Q = {p + + q} Все принадлежат P и Q соответственно.

Полигональная векторная сумма также называется суммой Минковского при планировании движения.

Учитывая приведенное выше определение, можно задать много вопросов о составе множества P + Q, характере его владения и т. д. Подчиненные результаты помогают нам описать векторную сумму многоугольника.

  1. P + Q — выпуклый многоугольник.
  2. Множество вершин P + Q является суммой множеств вершин P и Q.
  3. Множество вершин P + Q является параллельной точкой, установленной между P и Q.
  4. Учитывая, что есть P и Q вершин, соответственно, нет больше вершин, чем P + Q.

Наконец, подчиненный вывод не только описывает проблему, но также предоставляет метод для постепенного вычисления векторной суммы вершин.
Учитывая, что k-й вектор z (k) множества P + Q удовлетворяет z (k) = p (i) + q (j). Построение Постройте две параллельные касательные линии в точках p (i) и q (j), чтобы многоугольник находился справа от соответствующей линии. Две линии определяют углы в тета (i) и фи (j) в p (i) и q (j) соответственно (как показано на рисунке ниже)

Таким образом, следующий вектор z (k + 1) равен:

  • p (i + 1) + q (j), если theta (i) <ph (j)
  • p (i) + q (j + 1), если тета (i)> фи (j)
  • p (i + 1) + q (j + 1), если theta (i) = phi (j)

Следующие полигоны и их векторные суммы служат примером.

Два выпуклых многоугольника. Край первого многоугольника отмечен красным, а второй — синим.

Векторная сумма вышеуказанных полигонов. Цвет его стороны такой же, как у оригинального многоугольника.

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

Правильность алгоритма вытекает из основного вывода: он имеет линейную сложность по времени, поскольку каждый шаг имеет только один требуемый вектор, и векторы в наборе определяются, и они имеют только m + n Следовательно, общее время работы составляет m + n.

6. Самый тонкий раздел

1. Самое тонкое сечение

Рассмотрим следующую проблему размещения оборудования: набор «групп потребления» дается семейством людей, которые выглядят как выпуклые многоугольники на плоскости. Наша цель — найти «устройство», прямую линию на плоскости, которая минимизирует максимальное расстояние от линии до потребителя.

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

Представленные здесь выводы были опубликованы Робертом и Туссеном в 1990 году.
Основная проблема эквивалентна поиску полосы с наименьшей шириной (область, ограниченная двумя параллельными линиями на плоскости), и все многоугольники членов семейства пересекаются. Следовательно, центр ремня (линия, которая равноудалена от границы ремня) — это линия, которая минимизирует максимальное расстояние.

Чтобы обсудить эту проблему, мы определим следующее:

Прямая линия на плоскости, уравнение которой равно + ax + + c = 0 (и b> 0 или a == -1), делит плоскость на две области: верхняя полуплоскость Hu Точка в (l) p = (px, py) удовлетворяет apx + apy ++ c> = 0, а точка в нижней полуплоскости Hl (l) = (px, py) удовлетворяет apx + apy + c << 0 ,
В соответствии с приведенным выше определением, если линия вертикальная, верхняя полуплоскость находится в отрицательном направлении оси x.

Кроме того, полоса может быть определена как пересечение верхней полуплоскости одной линии и нижней полуплоскости другой (параллельной) линии.

Учитывая выпуклый многоугольник, угол направления, нижняя касательная линия tl (P, theta) — это линия с положительной полуосью оси x в theta, которая пересекается с и P находится в верхней половине tl (P, тета). Точка пересечения (может быть больше одного) называется следующей вершиной.
Аналогично, определите верхнюю касательную и верхнюю вершину.
При заданном наборе полигонов семейства и фиксированном угле направления определяются набор нижних и набор верхних вершин.

Наконец, рассмотрим следующие выводы:
Набор полигонов данного семейства, а также угол направления, тета и полоса (полученные из пересечения Hu (l1) и Hl (l2) больше 0) — это F (в этом направлении Вверху) Минимальная ширина полосы, если и только если есть два многоугольника в F и Q

  • Пересечение P и Hu (l1) находится на l1.
  • Пересечение Q и Hl (l2) находится на l2.

Основной вывод: минимальная ширина полосы (в заданном направлении) множества выпуклых многоугольников семейства F определяется l1 и l2
l1 = tl (CH (UP (F, thethe)), thethe) и
l2 = tu (CH (LP (F, Thethe)), thethe) установлено.

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

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

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

  1. Найдите вершину с наименьшими и самыми большими координатами. Отметьте их как p и q и постройте горизонтальный касательный через них.
  2. Вращайте касательную против часовой стрелки через тета, пока один из них не будет параллелен стороне одного из многоугольников.
  3. Если вершина снимается после (в направлении против часовой стрелки), то p является следующей вершиной между углом 0 (включительно) и углом тета (не включено). Если вершина снимается после q, то q является верхней вершиной в том же диапазоне углов. Эти две ситуации могут также возникнуть, когда стороны параллельны.
  4. Обновите текущую точку до новой вершины и обновите текущий угол.
  5. Повторите шаги с 2 по 4 одновременно с новым угловым интервалом, зная, что новый угол равен 180 градусам (в какой момент вы сначала вернулись в исходное положение, но порядок изменился).

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

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

Полное описание алгоритма, обсуждение правильности и анализ времени выполнения см. в статье автора:

J.-M. Robert, G.T. Toussaint. Computational geometry and facility location. Proc. Internatioanl Conf. on Operations Research and Management Science, Manila, The Philippines, Dec. 11-15, 1990. pp B-1 to B-19.

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

У меня 1 красный многоугольник говорят и 50 случайно расположенных синих полигонов — они расположены в географическом 2D пространство. Какой самый быстрый / самый быстрый алгоритм для поиска кратчайшего расстояния между красным многоугольником и ближайшим к нему синим многоугольником?

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

Итак, в конце — ответ должен вернуть ближайший синий многоугольник к единственному красному.

Это сложнее, чем кажется!

Перейти к ответу
Данный вопрос помечен как решенный


Ответы
13

Может быть, расстояние Фреше — это то, что вы ищете?

Вычисление расстояния Фреше между двумя многоугольными кривыми
Вычисление расстояния Фреше между простыми многоугольниками

Наивный подход состоит в том, чтобы найти расстояние между красными и 50 синими объектами — так что вы смотрите на 50 трехмерных вычислений Пифагора + сортировку, чтобы найти ответ. Однако это действительно сработает только для определения расстояния между центральными точками.

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

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

Для многоугольников с разумным количеством граничных точек, например, в ГИС или игровом приложении, может быть проще провести серию тестов.

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

См. http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline3d/ (это просто для 2-го случая)

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

Что касается сортировки, обычно QuickSort трудно превзойти по производительности (оптимизированный, который отключает рекурсию, если размер становится меньше 7 элементов, и переключается на что-то вроде InsertionSort, может быть, ShellSort).

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

Следующий подход будет работать и для 3D, но, вероятно, не самый быстрый:

Минимальное расстояние до многоугольника в 2D-пространстве

Вопрос в том, готовы ли вы променять точность на скорость? Например. вы можете упаковать все полигоны в ограничивающие прямоугольники, где стороны прямоугольников параллельны осям системы координат. В 3D-играх этот подход используется довольно часто. Поэтому вам нужно найти максимальное и минимальное значения для каждой координаты (x, y, z), чтобы построить виртуальную ограничивающую рамку. В таком случае вычисление расстояний до этих ограничивающих рамок является довольно тривиальной задачей.

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

Ориентированные ограничивающие рамки — OBB

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

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

Граничная рамка с выравниванием по осям — AABB

OOB более точны, AABB быстрее. Может быть, вы хотите прочитать эту статью:

Расширенные методы обнаружения столкновений

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

Возможно, вы сможете уменьшить проблему, а затем провести интенсивный поиск на небольшом множестве.

Сначала обработайте каждый многоугольник, найдя:

  • Центр многоугольника
  • Максимальный радиус многоугольника (т.е. точка на краю / поверхности / вершине многоугольника, наиболее удаленная от заданного центра)

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

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

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

Я знаю, что вы сказали «кратчайшее расстояние», но вы действительно имели в виду оптимальное решение или «хорошее / очень хорошее» решение подходит для вашей проблемы?

Потому что, если вам нужно найти оптимальное решение, вы должны вычислить расстояние между всеми границами вашего исходного и целевого полигонов (а не только вершинами). Если вы находитесь в трехмерном пространстве, то каждая граница — это плоскость. Это может быть большой проблемой (O (n ^ 2)) в зависимости от того, сколько у вас вершин.

Так что, если у вас есть количество вершин, которое приводит к квадрату страшного числа, И вам подходит «хорошее / очень хорошее» решение, используйте эвристическое решение или приближение.

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

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

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

Вы можете посмотреть на Вороного Каллинга. Бумага и видео здесь:

Http://www.cs.unc.edu/~geom/DVD/

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

upper bound of min distance = min {distance(red's center, current blue's center) + current blue's radius}

for every blue polygon where distance(red's center, current blue's center) - current blue's radius < upper bound of min distance
    check distance of edges and vertices

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

Надеюсь, это поможет

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

  1. Выберите любой синий многоугольник и найдите расстояние от красного. Теперь выберите любой другой многоугольник. Если минимальное расстояние между ограничивающими областями больше, чем уже найденное расстояние, вы можете игнорировать этот многоугольник. Продолжайте для всех полигонов.
  2. Найдите минимальное расстояние / центроидное расстояние между красным многоугольником и всеми синими многоугольниками. Отсортируйте расстояния и сначала рассмотрите наименьшее расстояние. Вычислите фактическое минимальное расстояние и продолжайте просмотр отсортированного списка до тех пор, пока максимальное расстояние между полигонами не станет больше, чем минимальное расстояние, найденное на данный момент.

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

Для расчета фактического минимального расстояния вы можете использовать «Новый быстрый алгоритм вычисления расстояния между двумя непересекающимися выпуклыми многоугольниками на основе диаграммы Вороного» Янга и др., Который равен O (log n + log m).

Надо бежать на похороны через секунду, но если вы разбиваете полигоны на выпуклые субполиции, вы можете сделать некоторые оптимизации. Вы можете выполнить двоичный поиск на каждом поли, чтобы найти ближайшую вершину, а затем я полагать ближайшей точкой должна быть либо эта вершина, либо смежное ребро. Это означает, что вы должны иметь возможность сделать это в log(log m * n), где m — среднее количество вершин на полигоне, а n — количество полигонов. Это своего рода поспешность, поэтому это может быть неправильно. При желании я расскажу подробнее позже.

Я считаю, что вы ищете алгоритм A *, который используется при поиске пути.

Другие вопросы по теме

Уважаемый пользователь! Для получения полного доступа ко всем функциями сайта, пожалуйста, пополните счёт

690 руб.

+ 1 месяц

Получите 1 месяц полного доступа

Пополнить счёт

1400 руб.

+ 3 месяца

Вы экономите 625₽!

Получите 3 месяца полного доступа

Пополнить счёт

3890 руб.

+ 9 месяцев

Вы экономите 2119₽!

Получите 9 месяцев полного доступа

Пополнить счёт

Если вы хотите использовать платформу как репетитор или как учитель, пожалуйста, свяжитесь с нами

Понравилась статья? Поделить с друзьями:
  • Как найти среднее квадратическое отклонение по таблице
  • Как можно найти место по фотографии
  • Как найти высоту закон сохранения энергии
  • Как составить заявление на ликвидацию
  • Как найти минимальное значение в массиве php