zoukankan      html  css  js  c++  java
  • 图形学--(中点画线法+Bresenham画线算法)

       

         编程环境:codeblocks+EGE库

         用到的函数:putpixel(int x1,int y1,int color)  用某种颜色打亮一个坐标点。

     这俩种算法都是用来在计算机上画一条直线的,那么我们为什么不直接用直线方程分别带点再打亮呢,这是因为,计算机中每个坐标点都是整数,而直线是由一个个像素点组合而成的,那么,直接将坐标点再进行四舍五入整数化就好了啊,的确,这是一种方法,但计算机中进行浮点数的四舍五入会使运算效率变差,因此真正画直线时是用到上边这俩种方法的。

    1、中点画线法

      只考虑当直线的斜率|k|<1时的情况,假设现在有一条直线(x1,y1,x2,y2),那么第一个点一定是(x1,y1)无疑,下一个点的x坐标为x1+1,y坐标要么为y1要么为y1+。关键在于每次取下一个点时,是取前一个的y1呢,还是y1+1,这时一定是取直线上点最靠近的那个了,而判断取哪个点就用到了中点,我们将中点代入直线中 d=F(x1+1,y1+0.5)=a*(x1+1)+b*(y1+0.5)+c。

        (1)如果直线d>=0,则取下边的点也就是(x1+1,y1)。 (2)如果直线d<0,则取上边的点也就是(x1+1,y1+1)。

      它的实际过程就是这样每次根据前边的点判断下一个点在哪,然后进行打亮,但这样每次判断的时候都得代入直线方程计算太麻烦了,我们将这俩种情况分别代入直线方程中可以找出规律:

        (1)当直线>=0时,经过化解得d1=d+a;

       (2)当直线<0时,经过化解得d2=d+a+b;

        (3)初始值d0=a+0.5b。

    也就是说每次的增量要么为a,要么为a+b,那么这样判断的时候就简单多了,因为我们每次只是判断它的正负。所以给等式同时乘2,将其中浮点数0.5化为整数,这样硬件操作时无疑更快了。

    代码:

     1 #include <iostream>
     2 #include <graphics.h>
     3 using namespace std;
     4 //中点画线法
     5 void line1(int x1,int y1,int x2,int y2){
     6 
     7      int x,y,d0,d1,d2,a,b;
     8      y=y1;             
     9      a=y1-y2;          //直线方程中的a的算法
    10      b=x2-x1;          //直线方程中的b的算法
    11      d0=2*a+b;         //增量初始值
    12      d1=2*a;           //当>=0时的增量
    13      d2=2*(a+b);       //当<0时的增量
    14      for(x=x1;x<=x2;x++){
    15             putpixel(x,y,GREEN);   //打亮
    16         if(d0<0){
    17             y++;            
    18             d0+=d2;
    19         }else{
    20 
    21         d0+=d1;
    22         }
    23 
    24      }
    25 }
    26 //Bresenham画线算法
    27 void line2(int x1,int y1,int x2,int y2){
    28 
    29    int x,y,dx,dy,d;
    30    y=y1;               
    31    dx=x2-x1;         
    32    dy=y2-y1;     
    33    d=2*dy-dx;        //增量d的初始值
    34    for(x=x1;x<=x2;x++){
    35     putpixel(x,y,GREEN);   //打亮
    36     if(d<0){
    37         d+=2*dy;
    38     }else{
    39       y++;
    40       d+=2*dy-2*dx;
    41     }
    42 
    43 
    44 
    45    }
    46 
    47 }
    48 int main()
    49 {
    50     initgraph(640,480);       //打开EGE初始化
    51     line1(200,160,400,400);   //画线
    52     getch();                  //等待用户操作
    53     closegraph();             //关闭图形
    54     return 0;
    55 }

    2、Bresenham画线算法

      这种画线算法的思想和中点画线的一致,只是在判断取哪个点时,不是看它位于中点的上边还是下边,而是将这俩个点到直线上那个点的距离相减,判断其正负,如果下边的点到直线实际点距离远则的d1-d2>=0那么取上边的点y1+1,同样也是代入直线化解可以得出下面结论:

      (1)当d1-d2<0时,d=d+2*dy.

      (2)当d1-d2>=0时,d=d+2*dy-2*dx.

      (3)d的初始值为  d=2*dy-dx.

     其代码如上所示。运行截图如下:

  • 相关阅读:
    一个具体的例子学习Java volatile关键字
    JavaScript实现的水果忍者游戏,支持鼠标操作
    记录我开发工作中遇到HTTP跨域和OPTION请求的一个坑
    微信程序开发系列教程(四)使用微信API创建公众号自定义菜单
    微信程序开发系列教程(三)使用微信API给微信用户发文本消息
    Java实现 LeetCode 547 朋友圈(并查集?)
    Java实现 LeetCode 547 朋友圈(并查集?)
    Java实现 LeetCode 547 朋友圈(并查集?)
    Java实现 LeetCode 546 移除盒子(递归,vivo秋招)
    Java实现 LeetCode 546 移除盒子(递归,vivo秋招)
  • 原文地址:https://www.cnblogs.com/llsq/p/7506597.html
Copyright © 2011-2022 走看看