首页 > 编程知识 正文

直尺画圆的原理,光沿直线传播的实验方案

时间:2023-05-04 18:45:07 阅读:168335 作者:3500

目录实验内容代码介绍

实验内容

实现DDA和Bresenham的划线算法。 (80% ) ) ) )。

实现画圆的算法。 (90% ) ) ) )。

请不要直接调用OpenGL库中的绘制直线和圆的函数。 您需要手动模拟如何通过绘制像素来显示几何体。 效果请参照下图。 (界面显示“虚拟像素”。)

可以通过交互式操作确定线段的起点和终点。 (100% )

代码介绍相关算法在课上已经说过了,这里只介绍相关代码。

应当注意的是,教科书的Bresenham算法仅适用于角度为沿x轴正方向选择45的范围的直线,因此实现该算法需要处理其他角度的直线3358www.Sina.com/内。

在以下代码中按l键将进入绘制直线模式,按c键将进入绘制圆模式。 用鼠标左键单击取出第一个点,用鼠标按左键拖动时,鼠标读取某个坐标绘制直线,用鼠标释放左键时取出第二个点,在该调用中使用Bresenham函数绘制直线

# include ' shader.h ' usingnamespacestd; const unsigned int SCR_WIDTH=800; const unsigned int SCR_HEIGHT=600; const unsigned int maxn=800 * 600 * 2; float verticesLine[maxn]; unsigned int VAO; unsigned int VBO; unsigned int theSize; //坐标变换成标准化的装置坐标,[-1.0,1.0 ]平面传输x (intx )返回(float ) )2 * x )-SCR _ width (-SCR _ width ) }bool click1,click2; 布尔线性; struct Point { int x,y; } Line[2]; vectorfloat TheLine; //要绘制的像素的顶点void frame buffer _ size _ callback (glf window * window,int width,int height ) GLviewport ) 0,0,width, heeeth )的//0是左下角的位置,下面两个参数是窗口的高度和宽度}voiddrawpixel(intx,int y )//对要上色的点进行排队Theline.push_back ) transx theline.push_back(Transy(y ) ); theline.push_back(1.0f; //z轴) voidDDAline(intx0,int y0,int x1,int y1 ) {//DDA出图直线float d=0; if(ABS(x1-x0 )=ABS (y1-y0 ) ) d=ABS (float ) x1-x0 ) ); elsed=ABS(float ) y1-y0 ); floatdx=(float ) ) x1 - x0 )/d; floatdy=(float ) ) y1 - y0 )/d; float x=x0 0.5; float y=y0 0.5; float i=0; while(Id ) { draw pixel (int ) x,) int ) y ); x =dx; y =dy; I; }voidBresenhamline(intx0,int y0,int x1,int y1 ) {//Bresenham标绘直线int dx=x1 - x0,dy=y1 - y0; //控制符号int ux=1,uy=1; if(dx0 ) ux=-1; if(dy0 ) uy=-1; int x=x0,y=y0; dx=ABS(dx; dy=ABS(dy; //取绝对值,取第一象限if(dxdy ) { int e=-dx; for(x=x0; x!=x1; x=UX({drawpixel ) x,y ); e =2 * dy; if(e=0) { y =uy; e -=2 * dx; } } } else { int e=-dy; for(y=y0; y!=y1; y =uy ) {

drawPixel(x, y); e += 2 * dx; if (e >= 0) { x += ux; e -= 2 * dy; } } }}void MIdPointDrawCircle(int x0, int y0, int r) {//中点画圆法 int x = 0; int y = r; double d = 1.25 - r; drawPixel(x0, y0);//画圆心 drawPixel(x0 + x, y0 + y); while (x <= y) { if (d < 0) d += 2 * x + 3; else { d += 2 * (x - y) + 5; y--; } x++; //八个方向画圆 //在原点上计算,然后加上x0 y0作为偏移量 drawPixel(x + x0, y + y0); drawPixel(y + x0, x + y0); drawPixel(-x + x0, y + y0); drawPixel(y + x0, -x + y0); drawPixel(x + x0, -y + y0); drawPixel(-y + x0, x + y0); drawPixel(-x + x0, -y + y0); drawPixel(-y + x0, -x + y0); }}void processInput(GLFWwindow *window) { if (click1) { if (!LineORCircle) {//绘制直线 cout << "Drawing Line" << endl; TheLine.clear(); BresenhamLine(Line[0].x, Line[0].y, Line[1].x, Line[1].y); //DDALine(Line[0].x,Line[0].y,Line[1].x,Line[1].y); GLfloat *tempVec = TheLine.data(); theSize = TheLine.size(); glBindBuffer(GL_ARRAY_BUFFER, VBO);//绑定缓冲 glBufferSubData(GL_ARRAY_BUFFER, 0, theSize * sizeof(GLfloat), tempVec); } else {//绘制圆 cout << "Drawing Circlen"; TheLine.clear(); float r = sqrt(pow(Line[1].x - Line[0].x, 2) + pow(Line[1].y - Line[0].y, 2)); MIdPointDrawCircle(Line[0].x, Line[0].y, r); GLfloat *tempVec = TheLine.data(); theSize = TheLine.size(); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferSubData(GL_ARRAY_BUFFER, 0, theSize * sizeof(GLfloat), tempVec); } }}//设定按键相应void key_CallBack(GLFWwindow *window, int key, int scancode, int action, int mod) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {//ESC退出 glfwSetWindowShouldClose(window, true); return; } if (key == GLFW_KEY_L && action == GLFW_PRESS) {//L画直线 //直线模式 LineORCircle = false; } if (key == GLFW_KEY_C && action == GLFW_PRESS) {//C画圆 //画圆模式 LineORCircle = true; }}//设定鼠标点击响应void mouse_click_callBack(GLFWwindow *window, int button, int action, int mod) { if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {//按下鼠标 //第一个点 double xPos, yPos; glfwGetCursorPos(window, &xPos, &yPos); Line[0].x = static_cast<int>(xPos); Line[0].y = static_cast<int>(yPos); //初始化 Line[1].x = static_cast<int>(xPos); Line[1].y = static_cast<int>(yPos); click1 = true; click2 = false; cout << xPos << " " << yPos << endl; } if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) {//松开鼠标 //第二个点 double xPos, yPos; glfwGetCursorPos(window, &xPos, &yPos); cout << xPos << " " << yPos << endl; Line[1].x = static_cast<int>(xPos); Line[1].y = static_cast<int>(yPos); click2 = true; click1 = false; }}void cursePosCallBack(GLFWwindow *window, double x, double y) { if (!click2) { Line[1].x = static_cast<int>(x); Line[1].y = static_cast<int>(y); }}int main() { //初始化并配置 glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //窗口创建 GLFWwindow *window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Bresenham", nullptr, nullptr); if (window == nullptr) { cout << "Failed to create GLFW window" << endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwSetKeyCallback(window, key_CallBack);//设定按键功能 glfwSetMouseButtonCallback(window, mouse_click_callBack);//设置鼠标点击 glfwSetCursorPosCallback(window, cursePosCallBack); if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) {//使用glad加载函数指针 cout << "Filed initialize GLAD" << endl; } Shader ourShader("../shader.vs", "../shader.fs"); //着色器类,前者为顶点着色器,后者为片段着色器 //顶点缓冲对象 glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); //将创建的缓冲绑定 glBindBuffer(GL_ARRAY_BUFFER, VBO); //将数据复制到缓冲内存 glBufferData(GL_ARRAY_BUFFER, sizeof(verticesLine), verticesLine, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *) nullptr); glEnableVertexAttribArray(0); while (!glfwWindowShouldClose(window)) { //输入 processInput(window); //清空屏幕 glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); ourShader.use(); glBindVertexArray(VAO); glDrawArrays(GL_POINTS, 0, theSize / 3); //检查并调用事件,交换缓冲 glfwSwapBuffers(window); glfwPollEvents(); } glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glfwTerminate(); return 0;}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。