zoukankan      html  css  js  c++  java
  • OpenGL——使用Bresenham算法绘制圆

      Bresenham算法是计算机图形学中为了“显示器(屏幕或打印机)系由像素构成”的这个特性而设计出来的算法,使得在求直线各点的过程中全部以整数来运算,因而大幅度提升计算速度。——摘自 “百度百科”。

      Bresenham算法绘制直线就不赘述了,大家看一看算法简介就能很好理解与实践。

      稍稍麻烦一点的就是用该算法绘制圆了,算法思想其实是一样的,并没有太大改变。

      算法核心:

        

      

      

      

      组合以上式子,当Dupper-Dlower<0时,取上点;当Dupper-Dlower>0时,取下点;否则任意。

      实验过程中,我使用了两种方法:① 画点法 ② 连线法。

      一、 画点法:

        画点法就是仅仅用OpenGL绘制点。可以选择按照圆的轨迹画整个圆,当然这样的算法要比较慢,而且要注意分段函数的增减性。

           我使用的是对称法,利用圆的对称性质,仅仅计算1/8的圆弧的点(当然算1/4也可以),其余的点均用对称性直接绘制。如下图所示:

              

        代码如下:

     1 /*
     2  * Draw Circle by Bresenham Algorithm
     3  * @para < xc, yc - 圆心: (xc, yc) >
     4  * @para < r - 半径 >
     5  * @para < deltaX - 坐标系每个小格的间距,用于控制精细度 >
     6  */
     7 void drawCircle_Bresenham(GLfloat xc, GLfloat yc, GLfloat r, const GLfloat deltaX) {
     8     GLfloat xi = - r, yi = 0; /* 圆上点 (xi, yi) */
     9     GLfloat du_l; /* upper - lower */
    10     glBegin(GL_POINTS);    
    11     while (abs(xi) >= abs(yi)) {
    12         // 根据圆的八向对称,只计算其中八分之一的点,然后对称得出其他点
    13         // 假设圆心在原点,先求点,再平移
    14         glVertex2f(xc + xi, yc + yi);
    15         glVertex2f(xc - xi, yc + yi);
    16         glVertex2f(xc + xi, yc - yi);
    17         glVertex2f(xc - xi, yc - yi);
    18         glVertex2f(xc + yi, yc + xi);
    19         glVertex2f(xc - yi, yc + xi);
    20         glVertex2f(xc + yi, yc - xi);
    21         glVertex2f(xc - yi, yc - xi);
    22         
    23         xi += deltaX; // 下一个x
    24         float yi_1 = sqrt(pow((GLfloat)r, 2) - pow((GLfloat)xi, 2)); // yi+1
    25         du_l = 2 * (GLfloat)yi + deltaX - 2 * yi_1;
    26         yi = (du_l <= 0) ? (int)yi_1 + deltaX : (int)yi_1;
    27     }
    28     glEnd();
    29     glFlush();
    30 }

      结果如图(半径150,圆心在原点,横坐标间隔为0.001):

      二、 画线法:

      根据圆弧四个象限的增减性和凹凸性的不同,分别绘制四段曲线,组合成一个圆。核心算法和第一种方法相同。

      

     1 const GLint FIRST_QUA = 1; // 第一象限
     2 const GLint SECOND_QUA = 2; // 第二象限
     3 const GLint THIRD_QUA = 3;
     4 const GLint FOURTH_QUA = 4;
     5 
     6 /*
     7  * 根据起点和终点绘制弧(画线法)
     8  * @para < deltaX - 坐标系每个小格的间距,用于控制精细度 >
     9  * @para < Quadrant - 象限 >
    10  */
    11 void setPixel(GLfloat startX, GLfloat endX, GLfloat startY, GLfloat xc, GLfloat yc, GLfloat r, GLfloat deltaX, GLint Quadrant) {
    12     GLfloat du_l; /* upper - lower */
    13     int inc = (Quadrant % 2 == 1) ? -1 : 1;
    14     int nag = (Quadrant > 2) ? -1 : 1;
    15     glBegin(GL_LINE_STRIP);
    16     while (startX <= endX) {
    17         // 假设圆心在原点,先求点,再平移
    18         glVertex2f(startX + xc, startY + yc);
    19         startX += deltaX;
    20         float yi_1 = nag * sqrt(pow((GLfloat)r, 2) - pow((GLfloat)startX, 2)); // yi+1
    21         du_l = 2 * (GLfloat)startY + inc * deltaX - 2 * yi_1;
    22         startY = (du_l <= 0) ? (int)yi_1 + deltaX : (int)yi_1;
    23     }
    24     glEnd();
    25 }
    26 
    27 /*
    28  * Bresenham 算法(画线法)
    29  * @para < xc, yc - 圆心(xc, yc) >
    30  * @para < r - 半径 >
    31  */
    32 void drawCircle_Bresenham_line(GLfloat xc, GLfloat yc, GLfloat r, GLfloat deltaX) {
    33     setPixel(-r, 0, 0, xc, yc, r, deltaX, SECOND_QUA); // 左上半
    34     setPixel(0, r, r, xc, yc, r, deltaX, FIRST_QUA); // 右上半
    35     setPixel(0, r , -r, xc, yc, r, deltaX, FOURTH_QUA); // 右下半
    36     setPixel(-r, 0, 0, xc, yc, r, deltaX, THIRD_QUA); // 左下半
    37     glFlush();
    38 }

      结果如图(半径150,圆心在原点,横坐标间隔为0.001):

      

  • 相关阅读:
    7天入门JavaScript,第一天
    linux 下 启动web项目报 java.net.UnknownHostException
    HashMap 和 Hashtable
    Servlet 两种跳转方式
    SpringMVC
    把当前时间(NSDate)转为字符串
    写入数据到Plist文件中时,第一次要创建一个空的数组,否则写入文件失败
    实现多个UIView之间切换的动画效果
    missing required architecture x86_64 in file 不支持64位
    获取IOS bundle中的文件
  • 原文地址:https://www.cnblogs.com/xulf/p/4357875.html
Copyright © 2011-2022 走看看