欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。
所谓多边形裁剪,就是在二维平面上有一堆多边,和一个矩形窗口。求出现在窗口里的部分是哪些。
蓝线为窗口
裁剪后如下
在这里我们规定矩形的边是平行于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
本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)