4

中点法画圆_2021秋季《计算机图形学》_基于《计算机图形学(第四版)》D.H.&M.P.B...

 2 years ago
source link: https://blog.csdn.net/rd142857/article/details/120519139
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

工具:vscode+glfw

自己写的非常丑陋的代码

// g++ circle.cpp -o test libglfw3dll.a libopengl32.a
// .\test

#include <bits/stdc++.h>
#include <GL/gl.h>
#include "glfw3.h"

#define N 1000

using namespace std;

void processInput(GLFWwindow *window)
{
    if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

void DrawBresenhamCircle(float r)
{
    float x0 = 0, y0 = r;
    float p = (3-2*r)/1000;
    float x = x0, y = y0;
    for(int i = 0; x<=y && i<1000; i++)
    {
        glBegin(GL_POINTS);
        glVertex2f(x, y);
        glVertex2f(y, x);
        glVertex2f(x, -y);
        glVertex2f(-y,x);
        glVertex2f(-x, y);
        glVertex2f(y, -x);
        glVertex2f(-x, -y);
        glVertex2f(-y, -x);
        if(p>=0)
        {
            p += (4000*(x-y) +10)/1000;
            x+=0.001;
            y-=0.001;
        }
        else
        {
            p += (4000*x+6)/1000;
            x += 0.001;
        }
        glEnd();
    }
}

int main()
{

    if (!glfwInit()) return -1;

    GLFWwindow* window;

    window = glfwCreateWindow(960, 960, "TestOpenGL", NULL ,NULL); //创建窗口对象

    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);

    while (!glfwWindowShouldClose(window))
    {
        processInput(window);

        //int r; cin>>r;
        DrawBresenhamCircle(1);

        glfwSwapBuffers(window);

        glfwPollEvents();
    }

    glfwTerminate();
    
    return 0;
}

从书上抄的漂亮代码

// g++ Circle_class.cpp -o test libglfw3dll.a libopengl32.a
// .\test

#include <bits/stdc++.h>
#include <GL/gl.h>
#include "glfw3.h"

using namespace std;


class screenPt
{
    private:
        GLint x, y;
    public:
        ScreenPt()
        {
            x = y = 0;  // 默认在原点
        }

        void setCoords(GLint xCoordValue, GLint yCoordValue)
        {
            x = xCoordValue;
            y = yCoordValue;
        }

        GLint getx() const
        {
            return x;
        }

        GLint gety() const
        {
            return y;
        }

        void incrementx()
        {
            x++;
        }

        void decrementy()
        {
            y--;
        }
};

void setPixel(GLint xCoord, GLint yCoord)  // 自定义画点函数
{
    glBegin(GL_POINTS);
        glVertex2f((float)(xCoord)/1000, (float)(yCoord)/1000);
    glEnd;
}

void circleMidpoint(GLint xc, GLint yc, GLint radius)  // 将圆心坐标和半径传入
{
    screenPt circPt;

    GLint p = 1-radius;

    circPt.setCoords(0, radius);  // 起始位置在圆的最上端

    void circlePlotPoints(GLint, GLint, screenPt);  // 在每个八分之一圆弧起点画一个点
    circlePlotPoints(xc, xc, circPt);

    while (circPt.getx()<=circPt.gety())
    {
        circPt.incrementx();
        if(p<0)
            p += 2*circPt.getx()+1;
        else
        {
            p += 2*(circPt.getx()-circPt.gety())+5;
            circPt.decrementy();
        }
        circlePlotPoints(xc, yc, circPt);
    }
}

void circlePlotPoints(GLint xc, GLint yc, screenPt circPt)
{
    setPixel(xc+circPt.getx(), yc+circPt.gety());
    setPixel(xc-circPt.getx(), yc+circPt.gety());
    setPixel(xc+circPt.getx(), yc-circPt.gety());
    setPixel(xc-circPt.getx(), yc-circPt.gety());
    setPixel(xc+circPt.gety(), yc+circPt.getx());
    setPixel(xc-circPt.gety(), yc+circPt.getx());
    setPixel(xc+circPt.gety(), yc-circPt.getx());
    setPixel(xc-circPt.gety(), yc-circPt.getx());
}

/********************************************************************/
void processInput(GLFWwindow *window)
{
    if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}


int main()
{
    if (!glfwInit()) return -1;

    GLFWwindow* window;

    window = glfwCreateWindow(960, 960, "MidPointCircle", NULL ,NULL); //创建窗口对象

    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);

    while (!glfwWindowShouldClose(window))
    {
        processInput(window);

        circleMidpoint(0, 0, 500);

        glfwSwapBuffers(window);

        glfwPollEvents();
    }

    glfwTerminate();
    
    return 0;
}

漂亮但是有一些小问题。由于glfw窗口坐标区间为(-1,1),所以画点时需要对数据进行/N的处理(可理解为归一化)。由于精度问题,连接处容易产生空缺,画出这样的赛博朋克圆
在这里插入图片描述
但在助教的电脑上跑出来就是完整的圆,很离谱,实验课解决。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK