多边形凹凸性的判断、自相交判断

说明


该博文参考 弱花3kou 的文章 [OpenGL] 绘制并且判断凹凸多边形、自相交多边形

分析


  • 凸多边形

多边形凹凸性的判断、自相交判断_第1张图片

  • 凹多边形

多边形凹凸性的判断、自相交判断_第2张图片

  • 自相交

多边形凹凸性的判断、自相交判断_第3张图片

代码


#include 
#include 
#include 
#include 

using namespace std;

// 定义点
struct Pos {
     
    int x;
    int y;
};

// 定义边
struct Edge {
     
    int x1, x2;
    int y1, y2;
    int vx;
    int vy;
    int a, b, c;
};

// 定义多边形
struct Poly {
     
    // 点集
    int xx[100];
    int yy[100];

    // 边集
    Edge Edges[100];

    int plotNums = 0; //点数量
    int edgeNums = 0; //边数量

    // 记录凹点
    int conv = 0;
};

Poly poly;


// 求交点坐标
Pos CrossPos(int p1, int p2) {
     
    Pos res;
    int A1 = poly.Edges[p1].a;
    int B1 = poly.Edges[p1].b;
    int A2 = poly.Edges[p2].a;
    int B2 = poly.Edges[p2].b;
    int C1 = poly.Edges[p1].c;
    int C2 = poly.Edges[p2].c;

    int m = A1 * B2 - A2 * B1;
    if (m == 0)
        cout << "第" << p1 << "边和第" << p2 << "边" << "无交点" << endl;
    else {
     
        res.x = (C2 * B1 - C1 * B2) / m;
        res.y = (C1 * A2 - C2 * A1) / m;
    }
    return res;

}

// 判断点是否在线段内
bool JudgeInLine(Pos pos, Edge edge) {
     
    int maxX = edge.x1 >= edge.x2 ? edge.x1 : edge.x2;
    int minX = edge.x1 <= edge.x2 ? edge.x1 : edge.x2;
    int maxY = edge.y1 >= edge.y2 ? edge.y1 : edge.y2;
    int minY = edge.y1 <= edge.y2 ? edge.y1 : edge.y2;
    if (pos.x <= maxX && pos.x >= minX && pos.y <= maxY && pos.y >= minY) {
     
        return true;
    }
    return false;
}

// 求叉积 返回正负值
int CrossProduct(int n) {
     
    n = n % poly.edgeNums;
    int np = (n + 1) % poly.edgeNums;
    return (poly.Edges[n].vx * poly.Edges[np].vy - poly.Edges[np].vx * poly.Edges[n].vy) >= 0 ? 1 : -1;
}


// 判断是什么多边形
bool Judge() {
     
    /*输出边信息*/
    for (int i = 0; i < poly.edgeNums; i++) {
     
        cout << "Vx:" << poly.Edges[i].vx << "  " << "Vy:" << poly.Edges[i].vy << "  " << "A:" << poly.Edges[i].a << "  " << "B:" << poly.Edges[i].b << "  " << "C:" << poly.Edges[i].c << endl;
    }

    /*判断自交*/
    Pos interPos;
    if (poly.edgeNums > 3)
        for (int i = 0; i < poly.edgeNums; i++) {
     
            interPos = CrossPos(i, (i + 2) % poly.edgeNums);
            if (JudgeInLine(interPos, poly.Edges[i]) && JudgeInLine(interPos, poly.Edges[(i + 2) % poly.edgeNums])) {
     
                cout << "该多边形为自相交多边形" << endl;
                return false;
            }
        }

    /*判断凹凸*/
    // 判断向量叉积 是否为同一正负
    int judge;
    if (CrossProduct(0) >= 0)
        judge = 1;
    else
        judge = -1;
    //判断每一个角,两边向量乘积是否同符号
    for (int i = 1; i <= poly.edgeNums; i++) {
     
        if (judge * CrossProduct(i) < 0) {
     
            poly.conv = i;
            ChangePoly();
            cout << "该多边形为凹多边形" << endl;
            return false;
        }
    }
    cout << "该多边形为凸多边形" << endl;
    return true;
}

关于自相交的理解


在原博客中,自相交判断利用的是点与线段的位置关系,也就是线段与 X 和 Y 轴形成的区域是否有交集来进行判断

原博客中,它是先求两条直线的交点,然后判断该交点是否同时位于两个线段所构成的矩形内

值得注意的是,这里是对与其不相邻的所有边进行比较,也就是说,假如一个复杂凸多边形一共有 N 条边,且当前边为 i,那么其要与 [0, i - 2] ∪ [i + 2, N] 的边进行比较判断

基于此,我绘制了以下两个图来说明情况

如下图所示,黄色点要么位于红色区域,要么位于蓝色区域,那么就不是自相交

多边形凹凸性的判断、自相交判断_第4张图片

但是对于下图,黄色点同时落在红色和蓝色区域,那么就形成了自相交
多边形凹凸性的判断、自相交判断_第5张图片

上面两个图描述的是局部情况,如果我们把多边形画的更复杂一些,就是这样的情况

在下面图形中,对于左上角的图形,我们依次进行判断,最终结果,其不是自相交图形,其中,红色的禁止圆圈为相临边,也就是不进行判断的边

多边形凹凸性的判断、自相交判断_第6张图片

对于下面这幅图,红边是当前边,其对应的红色区域和与其自身不相邻的紫色区域相交,该图形是自相交图形

多边形凹凸性的判断、自相交判断_第7张图片

over

你可能感兴趣的:(面试汇总-,C/C++,点云处理,-,PCL,拓扑学,算法,图论)