📜  使用极坐标方程和 Bresenham 方程绘制圆

📅  最后修改于: 2021-10-23 08:18:57             🧑  作者: Mango

在本文中,我们将讨论如何使用 Bresenham 方程和极坐标方程绘制圆。

画圆算法

由于我们的电脑屏幕是由以矩阵形式组织的像素组成的,因此在电脑屏幕上显示连续平滑的弧线并不容易。因此,要在计算机屏幕上绘制圆,它应该始终从打印的像素中选择最近的像素,以便它们可以形成弧

  • 考虑以原点为中心、半径为整数的圆。
  • 可以应用翻译来获得非原点中心圆。
  • 圆的方程由下式给出:
  • 给定的方程可以写成:
  • Symmetry的使用:只需要计算一个八分圆。一个人可以在其他 7 个八分圆中获得积分,如下所示:
    • 绘图点(x,y)
    • 绘图点(y,x)
    • 绘图点(x,-y)
    • 绘图点(-y,x)
    • 绘图点(-x,-y)
    • 绘图点(-y,-x)
    • 绘图点(-x,y)
    • 绘图点(-y,x)

使用 Bresenham 方程绘制圆

Bresenham 方程使用高度对称的圆的关键特征。因此,对于整个 360将其分成8 个部分,每个八分圆为 45。为此,我们的想法是使用Bresenham 圆算法计算 45 度第一个八分圆中像素的位置。它假设圆以原点为中心。因此,对于每个像素(x, y) ,在圆的 8 个八分圆中的每个八分圆中绘制一个像素,如下所示:

在 Bresenham 算法中的任意点(x, y) 中,我们有两种选择,要么选择东部的下一个像素,即(x + 1, y) ,要么选择东南的下一个像素,即(x + 1, y – 1) .这可以通过使用决策参数 d来决定:

  • 如果d > 0 ,那么(x + 1, y – 1)将被选为下一个像素,因为它会更靠近弧线。
  • 否则(x + 1, y)将被选为下一个像素。

下面是 Bresenham 方程的算法:

  • F(x, y) = x 2 + y 2 = 0 点在圆上。
  • F(x, y) > 0 点位于圆外。
  • F(x, y) < 0 点位于圆内。
  • 如果 d >= 0 然后将 x 更新为 (x + 1) 和 y = (y – 1) 这给出了新的 d
  • 如果 d < 0 然后将 x 更新为 (x + 1) 这给出了 d 的新值
C
// C program for the above approach
#include 
#include 
#include 
#include 
  
int xo, yo, r;
  
// Function to display the circle using
// the above algorithm
void Display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
  
    // Color of printing object
    glColor3f(1, 0, 0);
  
    // Giving the size of the point
    glPointSize(2);
  
    int x = 0;
    int y = r;
    float p = 5 / 4 - r;
  
    glColor3f(1, 0, 0);
  
    // Starting of drawing the circle
    glBegin(GL_POINTS);
  
    while (y > x) {
        if (p < 0) {
  
            // Increment x to x+1
            x++;
            p = p + 2 * x + 1;
        }
        else {
  
            // Increment x to x+1
            // and decrease y to y-1
            y--;
            x++;
            p = p + 2 * (x - y) + 1;
        }
  
        // Draw the coordinates
        glVertex2d(x + xo, y + yo);
        glVertex2d(-x + xo, y + yo);
        glVertex2d(x + xo, -y + yo);
        glVertex2d(-x + xo, -y + yo);
        glVertex2d(y + yo, x + xo);
        glVertex2d(-y + yo, x + xo);
        glVertex2d(y + yo, -x + xo);
        glVertex2d(-y + yo, -x + xo);
    }
  
    glEnd();
  
    // Its empties all the buffer
    // causing the issue
    glFlush();
}
  
// Driver Code
int main(int argc, char** argv)
{
    printf("X-coordinate Y-coordinate radius:");
    scanf("%d %d %d", &xo, &yo, &r);
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
  
    // Assigning the size of window
    glutInitWindowSize(1000, 1000);
  
    // Assign the position of window
    // to be appeared
    glutInitWindowPosition(100, 100);
  
    // Defining the heading of the window
    glutCreateWindow("GeeksforGeeks");
  
    // Backgronnd Color
    glClearColor(1, 1, 1, 1);
  
    // limit of the coordinate points
    gluOrtho2D(-500, 500, -500, 500);
  
    // Calling the function
    glutDisplayFunc(Display);
  
    glutMainLoop();
  
    return 0;
}


C
// C program to demonstrate circle
// drawing using polar equation
#include 
#include 
#include 
#include 
float xo, yo, rad;
  
// Function to display the circle
void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
  
    // Color of printing object
    glColor3f(1, 1, 1);
  
    float angle;
  
    // Start to drawing the circle
    glBegin(GL_POLYGON);
  
    for (int i = 0; i < 100; i++) {
  
        // Change the angle
        angle = i * 2 * (M_PI / 100);
        glVertex2f(xo + (cos(angle) * rad),
                   yo + (sin(angle) * rad));
    }
  
    glEnd();
  
    // Its empties all the buffer
    // causing the issue
    glFlush();
}
  
// Driver Code
int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    printf("Enter x y radius ");
    scanf("%f %f %f", &xo, &yo, &rad);
  
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
  
    // Assigning the size of window
    glutInitWindowSize(500, 500);
  
    // Assign the position of window
    // to be appeared
    glutInitWindowPosition(200, 200);
  
    // Defining the heading of the window
    glutCreateWindow("GeeksforGeeks");
  
    // Backgronnd Color
    glClearColor(0, 1, 0, 1);
  
    // limit of the coordinate points
    gluOrtho2D(-500, 500, -500, 500);
  
    // Calling the function
    glutDisplayFunc(Display);
  
    glutMainLoop();
  
    return 0;
}


输出:

时间复杂度: O(N)
辅助空间: O(1)

使用极坐标方程的圆

在极地方程系统中,这个想法是用一只手思考时钟。手一起从原点移出距离r ,有时称为模数然后将手向上(逆时针)旋转角度θ以到达该点。以下是极坐标方程的算法:

  1. 初始化变量rad、center(x0, y0) 、索引值或增量值i ,并使用极坐标θ_end = 100定义一个圆。
  2. 如果θ_end < θ ,则退出循环。
  3. 将 x的值作为rad*cos(angle)y作为rad*sin(angle)
  4. 绘制通过对称性找到的八个点,即当前 (x, y)坐标处的中心 (x0, y0)。
    • 绘制 (x + xo, y + yo)
    • 绘图 (-x + xo, -y + yo)
    • 绘制 (y + xo, x + yo)
    • 绘图 (-y + xo, -x + yo)
    • 绘制 (-y + xo, x + yo)
    • 绘制 (y + xo, -x + yo)
    • 绘制 (-x + xo, y + yo)
    • 绘制 (x + xo, -y + yo)
  5. 将角度增加i*2*(M_PI/100)

以下是实现上述方法的程序:

C

// C program to demonstrate circle
// drawing using polar equation
#include 
#include 
#include 
#include 
float xo, yo, rad;
  
// Function to display the circle
void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
  
    // Color of printing object
    glColor3f(1, 1, 1);
  
    float angle;
  
    // Start to drawing the circle
    glBegin(GL_POLYGON);
  
    for (int i = 0; i < 100; i++) {
  
        // Change the angle
        angle = i * 2 * (M_PI / 100);
        glVertex2f(xo + (cos(angle) * rad),
                   yo + (sin(angle) * rad));
    }
  
    glEnd();
  
    // Its empties all the buffer
    // causing the issue
    glFlush();
}
  
// Driver Code
int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    printf("Enter x y radius ");
    scanf("%f %f %f", &xo, &yo, &rad);
  
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
  
    // Assigning the size of window
    glutInitWindowSize(500, 500);
  
    // Assign the position of window
    // to be appeared
    glutInitWindowPosition(200, 200);
  
    // Defining the heading of the window
    glutCreateWindow("GeeksforGeeks");
  
    // Backgronnd Color
    glClearColor(0, 1, 0, 1);
  
    // limit of the coordinate points
    gluOrtho2D(-500, 500, -500, 500);
  
    // Calling the function
    glutDisplayFunc(Display);
  
    glutMainLoop();
  
    return 0;
}

输出:

时间复杂度: O(N)
辅助空间: O(1)