如何在窗口中画直线

本文将介绍如何在Linux环境中利用编程技术在窗口上绘制直线。通过理解浮点数坐标系统,结合算法知识,你可以创建自己的图形应用。此外,我们还将涉及Makefile的使用来编译项目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 如何画直线,看起来似乎很简单,拿个直线方程,遍历X求出Y,再把对应点画出来不就行了么,嘿嘿,没那么简单~

    平时我们所说的直线是在实数域的,也就是说对应的Y可能是小数,而在屏幕上,所画直线是基于正整数域的,那么根据直线方程如何画直线呢?

    先考虑斜率 0 < k < 1的情况

    1.Bresenham算法

    该算法由Bresenham在1965年发明,它到底做了什么事呢?其实想法很简单,就是每X移动一个像素,则考虑Y应该是如何移动。

    由于由(x0,y0),(x1,y1)两点构成的直线方程为:

    y-y0 = (y1-y0)/(x1-x0) * (x-x0)

    对于每一点的x值其y为:

    (y1-y0)/(x1-x0) * (x-x0) + y0

    可见并非每一点x对应的y都为整数,所以没有必要去计算每一点x对应的y值,只需求出哪一点的x值导致y值+1,如果x尚未到此值,则这中间的x对应的y都不变。

    如何找到这个值则要依靠直线方程斜率k,x每增加1个单位,y值都增加k个单位,而每一个x的像素点都对应一个误差,为直线中根据x求得的y与x的像素点y的差,如果误差绝对值>0.5则表示其靠近下一个像素点的y,此时把y+1,误差值-1。

    2.伪代码

    drawline(x0,y0,x1,y1)

    {

      int dx = x1 - x0;

      int dy = y1 - y0;

      float k = (float)dy / dx;

      float error = 0;

      for(int x = x0,y = y0:x <= x1; ++x)

      {

        draw(x,y);

        error += k;

        if(fabs(error) >= 0.5)

        {

          y += 1;

          error -= 1;

        }

      }

    }

    3.在linux终端窗口中画直线

    主要思想:

    构造一个二维字符数组,以空格为其基本元素,以此在屏幕形成画布

    若要画点则将对应点赋值'*',画完后刷新画布,可见图形

    4.具体实现

    CCanvas类接口:

    CCanvas(int width = 40,int height = 40);    //构造函数,形成一定大小的画布

    Init();            //完成画布初始化工作

    void SetValue(int x,int y,char c);        //在(x,y)处"画"一个点

    void Refresh();        //刷新显示画布

     

    //CCanvas.h

    #include <vector>

    class CCanvas

    {

    public:

      CCanvas(int width = 40,int height = 40);

      ~CCanvas();

      void SetValue(int x,int y,char c);

      typedef std::vector<std::vector<char> >::iterator ITER;

    private:

      int m_width,m_height;

      std::vector<std::vector<char> >    m_info;

      void Init();

    };

     

    //CCanvas.cpp

    #include <iostream>

    #include "CCanvas.h"

    CCanvas::CCanvas(int width,int height)

    {

    m_width = width;

    m_height = height;

    Init();

    }

    CCanvas::~CCanvas()

    {

    }

    void CCanvas::Init()

    {

    m_info.resize(m_height);

    for(ITER it = m_info.begin();it != m_info.end(); ++it)

    {

    it->resize(m_width,' ');

    }

    void CCanvas::SetValue(int x,int y,char c)

    {

    if(x >= m_width || y >= m_height)

    {

    printf("bad args!");

    return;

    }

    m_info[y][x] = c;

    }

    void CCanvas::Refresh()

    {

      for(int i = 0;i != m_height; ++i)

      {

      for(int j = 0;j != m_width; ++j)

       {

        printf("%c",m_info[i][j]);

       }

      printf("/n");

      }

    }

     

    //主文件

    #include <iostream>

    #include <cmath>

    #include "CCanvas.h"

     

    CCanvas g_canvas;

    void DrawLine(int x0,int y0,int x1,int y1)

    {

      int dx = x1 - x0;

      int dy = y1 - y0;

      float k = (float)dy / dx;

      float error = 0;

      for(int x = x0,y = y0:x <= x1; ++x)

      {

        draw(x,y);

        error += k;

        if(fabs(error)  >=  0.5)

        {

          y += 1;

          error -= 1;

        }

      }

    }

     

    int main()

    {

    std::cout << "please enter the startpoint (x0,y0) and endpoint (x1,y1)..." << std::endl;

    int x0,y0,x1,y1;

    std::cin >> x0 >> y0 >> x1 >> y1;

    DrawLine(x0,y0,x1,y1);

    g_canvas.Refresh();

     

    return 0;

    }

     

    为了便于调试写一个Makefile文件

    Makefile

    objects = CCanvas.o DrawLine.o

    DrawLine : $(objects)

        g++ -g $(objects) -o DrawLine

    DrawLine.o : DrawLine.cpp CCanvas.h

        g++ -g -c CCanvas.h DrawLine.cpp

    CCanvas.o : CCanvas.h

        g++ -g -c CCanvas.h CCanvas.cpp

    .PHONY : clean

    clean :

        -rm DrawLine $(objects)

    //编译 运行

    make

    ./DrawLine


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值