sutherland-hodgman 多边形裁剪算法

sutherland-hodgman 多边形裁剪算法,第1张

sutherland-hodgman 多边形裁剪算法

欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。

多边形剪裁作用

所谓多边形裁剪,就是在二维平面上有一堆多边,和一个矩形窗口。求出现在窗口里的部分是哪些。


蓝线为窗口

裁剪后如下


在这里我们规定矩形的边是平行于x轴和y轴的。

算法思想

一个多边形可以使用一个点序列表示,每两个连续的点可以组成一条多边形的边。可以对边进行裁剪,最终得到裁剪后多边形的点序列。

对裁剪窗口的一个边来说,有以上4种情况。
具体实现总结为2句话:

    有交点加交点。末端点在窗口内,加入到队列中。
    总体过程如下:

    具体实现的时候
算法实现
#include "glew/2.2.0_1/include/GL/glew.h"
#include "glfw/3.3.4/include/GLFW/glfw3.h"
#include 
#include "model.h"
#include 

using namespace std;

class wcPt2D {
public:
    double x, y;

    wcPt2D() {}

    wcPt2D(double a, double b) : x(a), y(b) {}

    void out() {
        printf("%.2f, %.2fn", x, y);
    }
};

typedef enum {
    Left = 0, Right = 1, Bottom = 2, Top = 3
} Boundary;

GLint inside(wcPt2D p, Boundary b, wcPt2D wMin, wcPt2D wMax) {
    switch (b) {
        case Left:
            if (p.x < wMin.x) return false;
            break;
        case Right:
            if (p.x > wMax.x) return false;
            break;
        case Bottom:
            if (p.y < wMin.y) return false;
            break;
        case Top:
            if (p.y > wMax.y) return false;
            break;
    }
    return true;
}

GLint cross(wcPt2D p1, wcPt2D p2, Boundary winEdge, wcPt2D wMin, wcPt2D wMax) {
    auto b1 = inside(p1, winEdge, wMin, wMax);
    auto b2 = inside(p2, winEdge, wMin, wMax);
    return b1!=b2;
}

wcPt2D intersect(wcPt2D p1, wcPt2D p2, Boundary winEdge, wcPt2D wMin, wcPt2D wMax) {
    wcPt2D iPt;
    GLfloat m;

    if (p1.x != p2.x) m = (p1.y - p2.y) / (p1.x - p2.x);

    switch (winEdge) {
        case Left:
            iPt.x = wMin.x;
            iPt.y = p2.y + (wMin.x - p2.x) * m;
            break;
        case Right:
            iPt.x = wMax.x;
            iPt.y = p2.y + (wMax.x - p2.x) * m;
            break;
        case Bottom:
            iPt.y = wMin.y;
            if (p1.x != p2.x) iPt.x = p2.x + (wMin.y - p2.y) / m;
            else iPt.x = p2.x;
            break;
        case Top:
            iPt.y = wMax.y;
            if (p1.x != p2.x) iPt.x = p2.x + (wMax.y - p2.y) / m;
            else iPt.x = p2.x;
            break;
    }

    return iPt;
}


vector clipBoundary(vector &pIn, Boundary b, wcPt2D wMin, wcPt2D wMax) {
    vector ans;

    for(int i=0;i polygonClipSutherlandHodgman(wcPt2D wMin, wcPt2D wMax, vector pIn) {
    for(Boundary b = Left; b<=Top; b=Boundary(b+1)) {
        pIn = clipBoundary(pIn, b, wMin, wMax);
    }

    return pIn;
}



void key_callback(GLFWwindow *window, int key, int scancode, int action, int mode) {
    //如果按下ESC,把windowShouldClose设置为True,外面的循环会关闭应用
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
        glfwSetWindowShouldClose(window, GL_TRUE);
        std::cout << "ESC" << mode;
    }

    if (action != GLFW_PRESS)return;
    switch (key) {
        case GLFW_KEY_ESCAPE:
            glfwSetWindowShouldClose(window, GL_TRUE);
            break;
        default:
            break;
    }

}

void mouse_click(GLFWwindow *window, int button, int action, int mods) {
    cout << button << "," << action << "," << mods << endl;
    double xpos, ypos;
    glfwGetCursorPos(window, &xpos, &ypos);
    cout << xpos / 300 - 1 << "," << 1 - ypos / 300 << endl;
    cout << xpos << "," << ypos << endl;
}

int main(void) {
    //初始化GLFW库
    if (!glfwInit())
        return -1;
    //创建窗口以及上下文
    GLFWwindow *window = glfwCreateWindow(600, 600, "hello world", NULL, NULL);
    if (!window) {
        //创建失败会返回NULL
        glfwTerminate();
    }

    //建立当前窗口的上下文
    glfwMakeContextCurrent(window);

    glfwSetKeyCallback(window, key_callback); //注册回调函数
    glfwSetMouseButtonCallback(window, mouse_click);
    //glViewport(0, 0, 400, 400);
    gluOrtho2D(-300, 300.0, -300, 300.0);
    //循环,直到用户关闭窗口
    cout << 123 << endl;
    int n = 4;
    wcPt2D pIn[10] = {
            {-100, 0},
            {0,    -100},
            {100,  0},
            {0,    100},
    };

    wcPt2D wMin = {-150, -150};
    wcPt2D wMax = {150, 150};

    auto pOut = polygonClipSutherlandHodgman({-75, -75}, {75,75}, vector(pIn, pIn+n));
    cout << pOut.size() << endl;
    for (auto p : pOut) {
        p.out();
    }

    vector pIn1 = {
            {-75, 175},
            {-160,    10},
            {20,  -20},
    };
    auto pOut1 = polygonClipSutherlandHodgman(wMin,wMax, pIn1);



    vector pIn2 = {
            {-160, 10},
            {-155,    -50},
            {-140,  -100},
            {-70,  -150},
            {0,  -200},
            {80,  -160},
            {160,  160},
    };
    auto pOut2 = polygonClipSutherlandHodgman(wMin,wMax, pIn2);





    while (!glfwWindowShouldClose(window)) {
        
        glfwPollEvents();
        // cout<<456< 
算法效果 
示例1 


示例2


示例3



本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5702302.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存