文章目录

  • 说明
  • Sutherland-Hodgeman
  • 代码

说明

在阅读此博客前,请访问2018级山东大学计算机学院图形学实验汇总。

原笔记通过latex编写,csdn只支持latex部分功能,所以下面主要是将pdf截屏上传。部分内容参考中国农业大学mooc。

Sutherland-Hodgeman

算法较为简单,直接看课本就可以。

代码

/** 项目名称:Sutherland-Hodgeman* 注意:polyPoint中存储的是多边形的所有顶点,每个顶点仅仅存一次* 问题:processInput中,有一个崩溃bug,已经避免,但是不知道为什么有bug*/
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "shader.h"
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
using namespace std;const unsigned int MAXN = 800*600*2;
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
const char* vertexShaderPath="/Users/longzhengtian/Desktop/代码/C++代码/ComputerGraphics/shader.vs";
const char* fragmentShaderPath="/Users/longzhengtian/Desktop/代码/C++代码/ComputerGraphics/shader.fs";struct Point{double x,y;Point(double _x=0,double _y=0):x(_x),y(_y){};Point&operator=(const Point &p){x=p.x; y=p.y;return *this;};bool operator ==(const Point &p){return (x==p.x&&y==p.y);}
}templine[2];
vector<Point> polyPoint;//多边形
vector<Point> cropPoint;//裁剪点
struct Rectangle{double xleft,xright,ytop,ybottom;
}rec;//裁剪窗口,注意,xleft<xright,ytop<ybottom,这是窗口坐标决定的,左上角坐标是(0, 0),左上角是(xleft,ytop),但是ytop比ybottom小bool DrawRec=false,DrawPoly=false;
bool DrawPolyEnd=false,DrawRecEnd=false;int clickwho=-1;
unsigned int VBO[4], VAO[4];void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
void SutherlandHodgeman(vector<Point> part_polyPoint,vector<Point> &part_cropPoint,const Rectangle &part_rec);float transX(double x){return (float)((float)(2*x)-SCR_WIDTH)/(SCR_WIDTH*1.0f);}
float transY(double y){return (float)(SCR_HEIGHT-2*(float)y)/(SCR_HEIGHT*1.0f);}bool distant(Point p1,Point p2){return (pow(fabs(p1.x-p2.x),2)+pow(fabs(p1.y-p2.y),2)<=25);}
bool IsItOnTheVisibleSide(const Point &p,const int &id,const Rectangle &part_rec);Point GetTheIntersection(const Point &p1,const Point &p2,const int &id,const Rectangle &part_rec);int main(){//实例化glfw函数glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif//创建glfw窗口GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Sutherland-Hodgeman", nullptr, nullptr);if (window == nullptr){cout << "Failed to create GLFW window" << endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window);//将window设置为接下来操作的主窗口glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);glfwSetKeyCallback(window, key_callback);glfwSetMouseButtonCallback(window, mouse_button_callback);if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){//使用glad加载glfw的所有函数指针cout << "Failed to initialize GLAD" << endl;return -1;}Shader ourShader(vertexShaderPath,fragmentShaderPath);//创建着色器程序float RecVertices[13];//裁剪窗口float Poly1Vertices[MAXN];//原始线float Poly2Vertices[MAXN];//裁剪窗口里面的线float TempLineVertices[7];//临时边glGenVertexArrays(4, VAO);glGenBuffers(4, VBO);glBindVertexArray(VAO[0]);glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);glBufferData(GL_ARRAY_BUFFER, sizeof(RecVertices), RecVertices, GL_DYNAMIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);glBindVertexArray(VAO[1]);glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);glBufferData(GL_ARRAY_BUFFER, sizeof(Poly1Vertices), Poly1Vertices, GL_DYNAMIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);glBindVertexArray(VAO[2]);glBindBuffer(GL_ARRAY_BUFFER, VBO[2]);glBufferData(GL_ARRAY_BUFFER, sizeof(Poly2Vertices), Poly2Vertices, GL_DYNAMIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);glBindVertexArray(VAO[3]);glBindBuffer(GL_ARRAY_BUFFER, VBO[3]);glBufferData(GL_ARRAY_BUFFER, sizeof(TempLineVertices), TempLineVertices, GL_DYNAMIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);glBindBuffer(GL_ARRAY_BUFFER, 0);glBindVertexArray(0);glEnable(GL_LINE_SMOOTH);//启用线宽glLineWidth(10);glEnable(GL_PROGRAM_POINT_SIZE);glPointSize(10);while (!glfwWindowShouldClose(window)){//输入processInput(window);//渲染命令glClearColor(0.7f, 0.7f, 0.7f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);//裁剪窗口//ourShader.setVec4("ourColor",greenValue,blueValue,redValue,1.0f);ourShader.setVec4("ourColor",1.0f,1.0f,1.0f,1.0f);ourShader.use();glBindVertexArray(VAO[0]);glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);//主多边形ourShader.setVec4("ourColor",1.0f,0.0f,0.0f,1.0f);ourShader.use();glBindVertexArray(VAO[1]);if(DrawPoly) glDrawArrays(GL_LINE_STRIP, 0, polyPoint.size());else glDrawArrays(GL_LINE_LOOP, 0, polyPoint.size());//裁剪多边形ourShader.setVec4("ourColor",0.0f,0.0f,0.0f,1.0f);ourShader.use();glBindVertexArray(VAO[2]);glDrawArrays(GL_LINE_LOOP, 0, cropPoint.size());//临时边ourShader.setVec4("ourColor",1.0f,0.0f,0.0f,1.0f);ourShader.use();glBindVertexArray(VAO[3]);glDrawArrays(GL_LINES, 0, 2);//检查并调用事件,交换缓冲glfwSwapBuffers(window);glfwPollEvents();}glDeleteVertexArrays(4, VAO);glDeleteBuffers(4, VBO);glfwTerminate();return 0;
}
Point GetTheIntersection(const Point &p1,const Point &p2,const int &id,const Rectangle &part_rec){//获得交点if(id==0) return {((part_rec.ybottom-p1.y)/(p2.y-p1.y))*(p2.x-p1.x)+p1.x,part_rec.ybottom};else if(id==1) return {part_rec.xright,((part_rec.xright-p1.x)/(p2.x-p1.x))*(p2.y-p1.y)+p1.y};else if(id==2) return {((part_rec.ytop-p1.y)/(p2.y-p1.y))*(p2.x-p1.x)+p1.x,part_rec.ytop};else return {part_rec.xleft,((part_rec.xleft-p1.x)/(p2.x-p1.x))*(p2.y-p1.y)+p1.y};
}
bool IsItOnTheVisibleSide(const Point &p,const int &id,const Rectangle &part_rec){//判断是否在可见侧if(id==0) return p.y>=part_rec.ybottom;else if(id==1) return p.x<=part_rec.xright;else if(id==2) return p.y<=part_rec.ytop;else return p.x>=part_rec.xleft;
}
void SutherlandHodgeman(vector<Point> part_polyPoint,vector<Point> &part_cropPoint,const Rectangle &part_rec){/* 按照这个顺序* Point windowPoint[4]={{part_rec.xleft,part_rec.ybottom},*                  {part_rec.xright,part_rec.ybottom},*                  {part_rec.xright,part_rec.ytop},*                  {part_rec.xleft,part_rec.ytop}};* double windowLine[4]={part_rec.ybottom,part_rec.xright,part_rec.ytop,part_rec.xleft};*/part_cropPoint.clear();vector<float> tempvToCrop;for (int i=0; i<4; i++){//对于四条边for (int j=0; j<part_polyPoint.size(); j++){//对于多边形的剩余顶点int nextpolyid=(j+1)%part_polyPoint.size();if(!IsItOnTheVisibleSide(part_polyPoint[j],i,part_rec) && IsItOnTheVisibleSide(part_polyPoint[nextpolyid],i,part_rec)){//p1不可见,p2可见Point tempIntersection=GetTheIntersection(part_polyPoint[j],part_polyPoint[nextpolyid],i,part_rec);//交点part_cropPoint.push_back(tempIntersection);part_cropPoint.push_back(part_polyPoint[nextpolyid]);}else if(IsItOnTheVisibleSide(part_polyPoint[j],i,part_rec) && IsItOnTheVisibleSide(part_polyPoint[nextpolyid],i,part_rec)){//p1可见,p2可见part_cropPoint.push_back(part_polyPoint[nextpolyid]);}else if(IsItOnTheVisibleSide(part_polyPoint[j],i,part_rec) && !IsItOnTheVisibleSide(part_polyPoint[nextpolyid],i,part_rec)){//p1可见,p2不可见Point tempIntersection=GetTheIntersection(part_polyPoint[j],part_polyPoint[nextpolyid],i,part_rec);//交点part_cropPoint.push_back(tempIntersection);}}if(i!=3){//剩余顶点作为新的多边形part_polyPoint.clear();for (auto it:part_cropPoint) part_polyPoint.push_back(it);part_cropPoint.clear();}}for (auto it:part_cropPoint){tempvToCrop.push_back(transX(it.x));tempvToCrop.push_back(transY(it.y));tempvToCrop.push_back(1.0f);}float* tempfToCrop=tempvToCrop.data();glBindBuffer(GL_ARRAY_BUFFER, VBO[2]);glBufferSubData(GL_ARRAY_BUFFER, 0, tempvToCrop.size() * sizeof(float), tempfToCrop);glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void processInput(GLFWwindow *window){if(DrawPoly){//如果此时已经开始画多边形,这里是画临时边double xpos,ypos;glfwGetCursorPos(window,&xpos,&ypos);templine[0]=polyPoint[polyPoint.size()-1];templine[1]=Point((int)xpos,(int)ypos);float tempvec[]={transX(templine[0].x),transY(templine[0].y),1.0f,transX(templine[1].x),transY(templine[1].y),1.0f};glBindBuffer(GL_ARRAY_BUFFER, VBO[3]);glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(tempvec), &tempvec);glBindBuffer(GL_ARRAY_BUFFER, 0);}else if(clickwho>=0 && clickwho<=3){//此时应该改变矩形double xpos,ypos;glfwGetCursorPos(window,&xpos,&ypos);if(clickwho==0){rec.xleft=xpos; rec.ybottom=ypos;}//"左下"else if(clickwho==1){rec.xright=xpos; rec.ytop=ypos;}//"右上"else if(clickwho==2){rec.xleft=xpos; rec.ytop=ypos;}//"左上"else if(clickwho==3){rec.xright=xpos; rec.ybottom=ypos;}//"右下"float tempvec[]={transX(rec.xleft),transY(rec.ybottom),1.0f,transX(rec.xleft),transY(rec.ytop),1.0f,transX(rec.xright),transY(rec.ybottom),1.0f,transX(rec.xright),transY(rec.ytop),1.0f};glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);glBufferSubData(GL_ARRAY_BUFFER,0,sizeof(tempvec),&tempvec);glBindBuffer(GL_ARRAY_BUFFER, 0);//裁剪if(DrawPolyEnd && DrawRecEnd) SutherlandHodgeman(polyPoint,cropPoint,rec);}else if(clickwho>=4){//移动多边形double xpos,ypos;glfwGetCursorPos(window,&xpos,&ypos);float tempvec[]={transX(xpos),transY(ypos),1.0f};glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);glBufferSubData(GL_ARRAY_BUFFER, (clickwho-4)*3*sizeof(float), sizeof(tempvec), &tempvec);glBindBuffer(GL_ARRAY_BUFFER, 0);polyPoint[clickwho-4]=Point(xpos,ypos);//裁剪if(DrawPolyEnd && DrawRecEnd) SutherlandHodgeman(polyPoint,cropPoint,rec);}
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height){glViewport(0, 0, width, height);
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods){if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)glfwSetWindowShouldClose(window, GL_TRUE);else if (key == GLFW_KEY_R && action == GLFW_PRESS) {//如果按下"R",画裁剪窗口if(!DrawPoly){//此时不是属于画多边形时刻if(!DrawRec){//开始画窗口cout<<"You press ‘R’ to start drawing the crop window"<<endl;double xpos,ypos;glfwGetCursorPos(window,&xpos,&ypos);rec.xleft=xpos; rec.ybottom=ypos;clickwho=1;//此时的状态和点击了"右下"是一样的DrawRec=true;}else {//结束画窗口cout<<"You press ‘R’, drawing the cropping window ends"<<endl;clickwho=-1;DrawRec=false; DrawRecEnd=true;//裁剪if(DrawPolyEnd && DrawRecEnd) SutherlandHodgeman(polyPoint,cropPoint,rec);}}}else if (key == GLFW_KEY_P && action == GLFW_PRESS) {//如果按下"P",画多边形if(!DrawRec){//此时不是属于画裁剪窗口时刻if(!DrawPoly){//开始画多边形polyPoint.clear(); cropPoint.clear();cout<<"You press ‘P’ to start drawing the polygon"<<endl;DrawPoly=true;double xpos,ypos;glfwGetCursorPos(window,&xpos,&ypos);float tempvec[]={transX(xpos),transY(ypos),1.0f};glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);glBufferSubData(GL_ARRAY_BUFFER, polyPoint.size()*3*sizeof(float), sizeof(tempvec), &tempvec);glBindBuffer(GL_ARRAY_BUFFER, 0);polyPoint.emplace_back(xpos,ypos);}else {//结束画多边形cout<<"You press ‘P’ and the polygon drawing ends"<<endl;//处理临时边templine[0]=Point(0,0);templine[1]=Point(0,0);float tempvec1[]={0.0f,0.0f,1.0f,0.0f,0.0f,1.0f};glBindBuffer(GL_ARRAY_BUFFER, VBO[3]);glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(tempvec1), &tempvec1);glBindBuffer(GL_ARRAY_BUFFER, 0);DrawPoly=false; DrawPolyEnd=true;//裁剪if(DrawPolyEnd && DrawRecEnd) SutherlandHodgeman(polyPoint,cropPoint,rec);}}}
}
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods){if(button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS){//鼠标点击了左键double xpos,ypos;glfwGetCursorPos(window,&xpos,&ypos);if(DrawPoly){//如果此时正在画多边形float tempvec[]={transX(xpos),transY(ypos),1.0f};glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);glBufferSubData(GL_ARRAY_BUFFER, polyPoint.size()*3*sizeof(float), sizeof(tempvec), &tempvec);glBindBuffer(GL_ARRAY_BUFFER, 0);polyPoint.emplace_back(xpos,ypos);}else if(!DrawRec){//如果此时没有画矩形if(clickwho!=-1) clickwho=-1;//移动中点击了鼠标,肯定是要结束了else if(distant({rec.xleft,rec.ybottom},{xpos,ypos})) clickwho=0;//点击矩形"左下"else if(distant({rec.xright,rec.ytop},{xpos,ypos})) clickwho=1;//点击矩形"右上"else if(distant({rec.xleft,rec.ytop},{xpos,ypos})) clickwho=2;//点击矩形"左上"else if(distant({rec.xright,rec.ybottom},{xpos,ypos})) clickwho=3;//点击矩形"右下"else {for (int i=0; i<polyPoint.size(); i++){//点击的点是多边形上的点if(distant({xpos,ypos},polyPoint[i])){clickwho=i+4; return;}}//没有点击到特殊的点,不进行任何操作}}}
}

Sutherland-Hodgeman 多边形裁剪算法相关推荐

  1. java实现线段裁剪算法,多边形裁剪算法java

    Weiler-Atherton 任意多边形裁剪 Sutherland-Hodgeman 算法解决了裁剪窗口为凸多边形窗口的问题,但一些应用需要涉及 任意多边形窗口(含凹多边形窗口)的裁剪.Weiler ...

  2. 图形学基础笔记III:图形管线中的多边形裁剪算法、Sutherland-Hodgman、Guard Band Clipping

    这个主要讲的是viewport 里的. 从 frustum (根据 fov 视场角 和 aspect ratio 纵横比决定 lrbt,front.near 是由摄像机距离和世界大小决定的)到 vie ...

  3. 【Weiler-Atherton算法】 计算机图形学多边形裁剪算法

    目录 什么是多边形裁剪 前置知识 算法步骤 程序框图 代码实现 源代码: https://github.com/ricar0/Weiler-Atherton-Alogrithm/tree/master ...

  4. weiler-atherton多边形裁剪算法_EAST算法超详细源码解析:数据预处理与标签生成...

    作者简介 CW,广东深圳人,毕业于中山大学(SYSU)数据科学与计算机学院,毕业后就业于腾讯计算机系统有限公司技术工程与事业群(TEG)从事Devops工作,期间在AI LAB实习过,实操过道路交通元 ...

  5. mfc 多边形裁剪算法

    多边形裁剪 效果截图: 1.头文件定义: enum Boundary{Left, Right, Bottom, Top}; int cj_line_x1;//裁剪直线时原直线的坐标     int c ...

  6. 多边形裁剪一:Sutherland-Hodgman算法

    Sutherland-Hodgman算法也叫逐边裁剪法,该算法是萨瑟兰德(I.E.Sutherland)和霍德曼(Hodgman)在1974年提出的.这种算法采用了分割处理.逐边裁剪的方法.一,基本思 ...

  7. 计算机图形学 多边形裁剪

    多边形裁剪 多边形裁剪 Sutherland Hodgeman多边形裁剪 新点的产生与旧点的保留及其二者的输出确定 第一点S在不可见侧,第二点P在可见侧 第一点S和第二点P都在可见侧 第一点S在可见侧 ...

  8. Sutherland-Hodgeman 逐次裁剪法(多边形裁剪)

    Sutherland-Hodgeman多边形裁剪算法思想: 每次用窗口的一条边界(包括延长线)对要裁剪的多边形进行裁剪,裁剪时,顺序地测试多边形各顶点,保留边界内侧的顶点,删除外侧的顶点,同时,适时地 ...

  9. 3.qt-图解Weiler-Atherton任意多边形剪裁算法

    1.Weiler-Atherton多边形剪裁算法 Weiler-Atherton剪裁算法是一个适用于凸的.凹的和带孔的多边形的裁剪算法. 裁剪窗口可以是矩形.任意凸多边形.任意凹多边形. 与 Suth ...

最新文章

  1. inotify结合rsync监控目录的实时变化
  2. 百度商品识别心得笔记
  3. httpclient帮助类
  4. ICCV 2019 开源论文 | ShapeMatchingGAN:打造炫酷动态的艺术字
  5. java8 camel_WildFly 8的Camel子系统集成了Java EE –入门
  6. mysql 数据库操作类_【数据库操作类】10个php操作数据库类下载
  7. 高数学习笔记:计算方向导数
  8. ssh:Permissions 0644 for ‘/root/.ssh/id_rsa’ are too open
  9. mysql判断范围0到10 11到20_SQL 如何查询日期在一定范围内的数据
  10. DZNEmptyDataSet,优秀的空白页或者出错页封装
  11. postgresql视图
  12. 同一个WiFi,电脑不能访问CSDN网站,手机却可以,换一个网络电脑就可以是什么原因?
  13. 深度学习怎么入门?零基础快速入门深度学习
  14. 电信dns服务器哪个稳定,电信宽带dns设置哪个最快? dns设置哪个最好最快
  15. CentOS7安装WPS中文字体问题
  16. 今天收到一封非常牛B的离职信
  17. 计算机网络自顶向下方法(第六版) 课后题答案 | 第三章
  18. 芯片的SD/MMC控制器以及SD卡介绍
  19. 容器云系列之Kubernetes基本架构介绍
  20. lammps案例:fix indent命令实现纳米摩擦及摩擦力计算

热门文章

  1. Android酷炫音乐律动动效部署到Maven仓库
  2. Flutter 自定义组件实战
  3. 摄影-曝光口诀(阳光16法则)
  4. freertos使用基础
  5. Java进阶04-动态代理、类加载
  6. VMware Workstation 虚拟机不兼容解决方法
  7. R语言在图上标出点坐标_R语言做图plot参数
  8. 计算机组装手机app,智能手机安装软件的
  9. MySQL 5.6.22绿色版安装
  10. 杭州考驾照-2017.4