【计算机图形学】扫面转换算法(DDA算法 中点画线算法 Bresenham画线算法)

模块1 扫描转换算法

一 实验目的

  1. 编写直线、弧线的光栅扫描转换算法,并对线宽与线形的算法加以探讨
  2. 用DDA算法、中点画线算法、Bresenham画线算法绘制直线(如果键盘输入数据,给出数据值;如果绘制图案,图案中应包含各种斜率;如果鼠标确定任意两点,给出操作说明)
  3. 意识到各类直线的光栅扫描转换算法的局限性,并尝试改进后实现任意斜率的直线的画法

二 实验理论分析

DDA法:

  1. 主要思想:主要采用增量算法思想,即当x每递增1时,y会递增k。而由于像素只能取整数,所以对(y+0.5)取整后标注该像素。
  2. 局限性:当k的绝对值小于1时,能够较好的描绘直线;但是当k的绝对值大于1时,光栅点分布较为稀疏,像素标注情况较差。
  3. 改进方法:当k的绝对值大于1时,将x和y的位置互换。即取x和y变化大的轴作为参考轴,来保证直线被光栅化后有足够多的像素。

中点画线法:

  1. 主要思想:采用直线的一般式方程,即ax+by+c=0。构造判别式为d=F(xi+1,yi+0.5)=a(xi+1)+b(yi+0.5)+c,当d<0时,取y+1,当d≥0时,取y。
  2. 局限性:计算量太太大,不如DDA算法;只能绘制斜率在0到1之间的正斜率直线。
  3. 改进方法:构造判别式为d0=F(x0+1,y0+0.5)=a+0.5b,重构在d的正负影响下dnew和dold之间的关系,并优化d为整数运算。根据dx和dy的大小关系,以跨步大的轴为步长方向,另一个轴为d的迭代方向。

Bresenham法:

  1. 主要思想:通过计算像素点之间的差值来决定下一个像素点的位置。一旦d≥1,就把它减去1,保证d在0、1之间,即始终有d∈[0,1)。
  2. 局限性:计算不方便;只能绘制斜率在0到1之间的正斜率直线。
  3. 改进方法:对于计算方便而言,第一种改进方法是令e=d-0.5,逐步迭代后判断e的正负并更改e;第二种改进方法是用e*2△x替换e,从而获得整数算法并避免除法。对于任意斜率而言,可以根据dx和dy的大小关系,以跨步大的轴为步长方向,另一个轴为e的迭代方向。

三 实验内容

1:用DDA算法绘制任意斜率的直线

实验结果如下图所示:

第一步:输入起点的坐标和终点的坐标(【100,100】为起点,【0,0】为终点)

第二步:程序自动连接上述两点

2:用中点画线和Bresenham画线算法绘制部分斜率的直线

2.1-Bresenham画线算法实验结果如下图所示:

第一行的操作分别为:水平从左向右画线、从左下向右上画线、从左上向右下画线(不超过45度);

第二行的操作分别为:从左上向右下画线(超过45度)、从右上向左下画线、从右下向左上画线;

2.2-中点画线算法实验结果如下图所示:

第一行的操作分别为:水平从左向右画线、从左下向右上画线、从左上向右下画线(不超过45度);

第二行的操作分别为:从左上向右下画线(超过45度)、从右上向左下画线、从右下向左上画线;

3:用中点画线和Bresenham画线算法绘制任意斜率的直线

3.1-Bresenham画线算法实验结果如下图所示:

第一行的操作分别为:水平方向画线(左->右,右->左)、从左上向右下画线(k的绝对值大于1,k的绝对值小于1)、从左下向右上画线(k的绝对值大于1,k的绝对值小于1);

第二行的操作分别为:从右上向左下画线(k的绝对值大于1,k的绝对值小于1)、从右下向左上画线(k的绝对值大于1,k的绝对值小于1)、竖直方向画线(上->下,下->上);

3.2-中点画线算法实验结果如下图所示:

从任一点出发,即当前点为起点,在四周画出其他的任意斜率的直线。最终结果为如下的辐射状的图形,即可证明该算法可以画出任意斜率的直线。

四 程序说明

Project中程序的调用:

将当前cpp文件的属性——常规——从生成中排除中选择否,其他文件选择是,即可运行当前的cpp文件

1

//

// 程序名称:DDA

// 功  能:用DDA算法绘制任意斜率的曲线

// 编译环境:VS2019,EasyX_20220116

// 最后修改:2022-3-3

#include <graphics.h>

#include <math.h>

#include <conio.h>

#include <iostream>

using namespace std;

void DDA_Line(int x0, int y0, int x1, int y1, int color){

    int dx = x1 - x0, dy = y1 - y0, step, k;

    float x = x0, y = y0, xIncre, yIncre;

    //斜率绝对值大于1的时候,以 y 的变化为基准

    if (abs(dx) > abs(dy)) {

        step = abs(dx);

    }

    else {

       step = abs(dy);

    }

    //x和y的增量计算

    xIncre = (float)dx / (float)step;

    yIncre = (float)dy / (float)step;

    for (k = 0; k < step; k++) {

       putpixel(int(x + 0.5f), (int)(y + 0.5f), color);

       x += xIncre;

       y += yIncre;

    }

}

int main(){

    int x1, y1, x2, y2;

    cout << "please input the start point:" << endl;

    cin >> x1 >> y1;

    cout << "please input the end point:" << endl;

    cin >> x2 >> y2;

   

    initgraph(640, 480);

    DDA_Line(x1, y1, x2, y2, WHITE);

    _getch();

    closegraph();

    return 0;

}

2题:中点画线

//

// 程序名称:中点画线

// 功  能:用中点画线算法绘制部分斜率的曲线

// 编译环境:VS2019,EasyX_20220116

// 最后修改:2022-3-3

#include <graphics.h>

#include <math.h>

#include <conio.h>

#include <iostream>

using namespace std;

void MidPointLine(int x0, int y0, int x1, int y1, int color) {

    int dx, dy, increE, increNE, d, x, y;

    dx = x1 - x0;

    dy = y1 - y0;

    d = dx - 2 * dy;

    increE = -2 * dy;

    increNE = 2 * (dx - dy);

    x = x0;

    y = y0;

    putpixel(x, y, color);

    while (x < x1) {

       if (d > 0) {

           d += increE;

           x++;

       }

       else {

           d += increNE;

           y++;

           x++;

       }

       putpixel(x, y, color);

    }

}

int main(){

    initgraph(640, 480);

    ExMessage m;

    int x0, y0, x1, y1;

    while (true) {

       m = getmessage(EX_MOUSE | EX_KEY);

       switch (m.message) {

       case WM_LBUTTONDOWN:

           x0 = m.x;

           y0 = m.y;

           setfillcolor(GREEN);

           fillrectangle(m.x - 3, m.y - 3, m.x + 3, m.y + 3);

       case WM_RBUTTONDOWN:

           x1 = m.x;

           y1 = m.y;

           MidPointLine(x0, y0, x1, y1, WHITE);

           setfillcolor(GREEN);

           fillrectangle(m.x - 3, m.y - 3, m.x + 3, m.y + 3);

       case WM_KEYDOWN:

           if (m.vkcode == VK_ESCAPE)

              return 0;  // 按 ESC 键退出程序

       }

    }

    closegraph();

    return 0;

}

2题:Bresenham画线

//

// 程序名称:bresenham画线

// 功  能:用bresenham画线算法绘制部分斜率的曲线

// 编译环境:VS2019,EasyX_20220116

// 最后修改:2022-3-3

#include <graphics.h>

#include <math.h>

#include <conio.h>

#include <iostream>

using namespace std;

void bresenham(int x0, int y0, int x1, int y1, int color) {

    int x, y, dx, dy, i, e;

    dx = x1 - x0;

    dy = y1 - y0;

    e = -dx;

    x = x0;

    y = y0;

    for (i = 0; i <= dx; i++) {

       putpixel(x, y, color);

       x++;

       e += 2 * dy;

       if (e >= 0) {

           y++;

           e -= 2 * dx;

       }

    }

}

int main() {

    initgraph(640, 480);

    ExMessage m;

    int x0, y0, x1, y1;

    while (true) {

       m = getmessage(EX_MOUSE | EX_KEY);

       switch (m.message) {

       case WM_LBUTTONDOWN:

           x0 = m.x;

           y0 = m.y;

           setfillcolor(GREEN);

           fillrectangle(m.x - 3, m.y - 3, m.x + 3, m.y + 3);

       case WM_RBUTTONDOWN:

           x1 = m.x;

           y1 = m.y;

           bresenham(x0, y0, x1, y1, WHITE);

           setfillcolor(GREEN);

           fillrectangle(m.x - 3, m.y - 3, m.x + 3, m.y + 3);

       case WM_KEYDOWN:

           if (m.vkcode == VK_ESCAPE)

              return 0;  // 按 ESC 键退出程序

       }

    }

    closegraph();

    return 0;

}

3题:中点画线

//

// 程序名称:中点画线:加强版

// 功  能:用中点画线算法绘制任意斜率的曲线

// 编译环境:VS2019,EasyX_20220116

// 最后修改:2022-3-3

#include <graphics.h>

#include <math.h>

#include <conio.h>

#include <iostream>

using namespace std;

void MidPointLine(int x0, int y0, int x1, int y1, int color)

{

    int a, b, d1, d2, d, x, y;

    float m;

    if (x1 < x0) {

       d = x0;

       x0 = x1;

       x1 = d;

       d = y0;

       y0 = y1;

       y1 = d;

    }

    a = y0 - y1; //y差值

    b = x1 - x0; //x差值

    if (b == 0) {

       m = -1 * a * 100;

    }

    else {

       m = (float) a / (x0 - x1);

    }

    x = x0;

    y = y0;

    putpixel(x, y, color);

    //斜率在0~1

    if (m >= 0 && m <= 1){

       d = 2 * a + b;

       d1 = 2 * a;

       d2 = 2 * (a + b);

       while (x < x1) {

           if (d <= 0) {

              x++;

              y++;

              d += d2;

           }

           else {

              x++;

              d += d1;

           }

           putpixel(x, y, color);

       }

    }

    //斜率在-1~0

    else if (m <= 0 && m >= -1) {

       d = 2 * a - b;

       d1 = 2 * a - 2 * b;

       d2 = 2 * a;

       while (x < x1) {

           if (d > 0) {

              x++;

              y--;

              d += d1;

           }

           else {

              x++;

              d += d2;

           }

           putpixel(x, y, color);

       }

    }

    //斜率在1~∞

    else if (m > 1) {

       d = a + 2 * b; d1 = 2 * (a + b), d2 = 2 * b;

       while (y < y1) {

           if (d > 0) {

              x++;

              y++;

              d += d1;

           }

           else {

              y++;

               d += d2;

           }

           putpixel(x, y, color);

       }

    }

    //斜率在∞~-1

    else {

       d = a - 2 * b; d1 = -2 * b, d2 = 2 * (a - b);

       while (y > y1) {

           if (d <= 0) {

              x++;

              y--;

              d += d2;

           }

           else {

              y--;

              d += d1;

           }

           putpixel(x, y, color);

       }

    }

}

int main() {

    initgraph(640, 480);

    ExMessage m;

    int x0, y0, x1, y1;

    while (true) {

       m = getmessage(EX_MOUSE | EX_KEY);

       switch (m.message) {

       case WM_LBUTTONDOWN:

           x0 = m.x;

           y0 = m.y;

           setfillcolor(GREEN);

           fillrectangle(m.x - 3, m.y - 3, m.x + 3, m.y + 3);

       case WM_RBUTTONDOWN:

           x1 = m.x;

           y1 = m.y;

           MidPointLine(x0, y0, x1, y1, WHITE);

           setfillcolor(GREEN);

           fillrectangle(m.x - 3, m.y - 3, m.x + 3, m.y + 3);

       case WM_KEYDOWN:

           if (m.vkcode == VK_ESCAPE)

              return 0;  // 按 ESC 键退出程序

       }

    }

    closegraph();

    return 0;

}

3题:Bresenham画线

//

// 程序名称:bresenham画线:加强版

// 功  能:用bresenham画线算法绘制任意斜率的曲线

// 编译环境:VS2019,EasyX_20220116

// 最后修改:2022-3-3

#include <graphics.h>

#include <math.h>

#include <conio.h>

#include <iostream>

using namespace std;

void bresenham(int x0, int y0, int x1, int y1, int color) {

    int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;

    int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;

    int erro = (dx > dy ? dx : -dy) / 2;

    while (putpixel(x0, y0, color), x0 != x1 || y0 != y1) {

       int e2 = erro;

       if (e2 > -dx) {

           erro -= dy;

           x0 += sx;

       }

        if (e2 < dy) {

           erro += dx;

           y0 += sy;

       }

    }

}

int main() {

    initgraph(640, 480);

    ExMessage m;

    int x0, y0, x1, y1;

    while (true) {

       m = getmessage(EX_MOUSE | EX_KEY);

       switch (m.message) {

       case WM_LBUTTONDOWN:

           x0 = m.x;

           y0 = m.y;

           setfillcolor(GREEN);

           fillrectangle(m.x - 3, m.y - 3, m.x + 3, m.y + 3);

       case WM_RBUTTONDOWN:

           x1 = m.x;

           y1 = m.y;

           bresenham(x0, y0, x1, y1, WHITE);

           setfillcolor(GREEN);

           fillrectangle(m.x - 3, m.y - 3, m.x + 3, m.y + 3);

       case WM_KEYDOWN:

           if (m.vkcode == VK_ESCAPE)

              return 0;  // 按 ESC 键退出程序

       }

    }

    closegraph();

    return 0;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/752.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

机器看世界

博主简介 博主是一名大二学生&#xff0c;主攻人工智能研究。感谢让我们在CSDN相遇&#xff0c;博主致力于在这里分享关于人工智能&#xff0c;c&#xff0c;Python&#xff0c;爬虫等方面知识的分享。 如果有需要的小伙伴可以关注博主&#xff0c;博主会继续更新的&#xff0c…

开源超级终端工具——WindTerm

1、下载和安装&#xff08;我的是win10&#xff0c;其他版本各位自选&#xff09; Releases kingToolbox/WindTerm GitHub 安装的话&#xff0c;相信大家不用我赘述了。 初始界面是这样的&#xff1a; 2、WindTerm使用 2.1 本地会话&#xff08;最下面那个框&#xff0c;发…

自动化测试实战篇(10),找不到合适接口测试怎么办?Postman中mock模拟接口帮你解决烦恼

一般想学习接口测试&#xff0c;找不到相应的接口进行测试也是比较麻烦的一件事情&#xff0c;尤其是找一些能够正常显示想要的相应的数据的接口更是相对来讲比较复杂&#xff0c;那么有没有简单点造接口数据的方式呢&#xff1f; 像是mock框架&#xff0c;以它为基础的apifox…

23.3.14打卡 2022年江西省大学生程序设计竞赛(正式赛)ABL

就写了签到, 其他题没写, 这场好像3题就银了 纪念一下3.14原粥率日 比赛链接:https://ac.nowcoder.com/acm/contest/43898 A题 Special Adjustment Method 题意 给出非负整数x, y, z 你可以让其中两个数字-1, 另外一个2, 使得x2y2z2x^2y^{2}z^{2}x2y2z2最大 题解 这题很容…

站上风口,文心一言任重道远

目录正式发布时机选择逻辑推理AI绘画用户选择总结自从OpenAI公司的chatGPT发布以来&#xff0c;吸引了全球目光&#xff0c;同时也引起了我们的羡慕&#xff0c;希望有国产的聊天机器人&#xff0c;盼星星盼月亮&#xff0c;终于等来了百度文心一言的发布。 正式发布 3月16日…

安全SaaS,在中国TO B中艰难成长

无论是一体化、还是以业务为中心专攻政企或金融客户&#xff0c;还是针对中小微企业市场推出免费产品&#xff0c;都可能成为未来安全SaaS规模化的发展路径。 作者|斗斗 编辑|皮爷 出品|产业家 5G、物联网、AI、云计算等技术的应用&#xff0c;让生产、服务过程加速数字化、…

Unity PS4/PS5开发环境搭建

首先&#xff0c;主机游戏PlayStation/Nintendo Switch都是比较闭塞的&#xff0c;开发者账号是必须的。 开发环境有两个部分&#xff0c;一是SDK Kit&#xff08;各种开发调试环境&#xff09;&#xff0c;二是Unity的支持库(安装后才能在Unity中切换到PS平台)&#xff1b; 需…

软件开发的权限系统功能模块设计,分享主流的九种常见权限模型

软件系统的权限控制几乎是非常常见且必备的&#xff0c;这篇文章整理下常见的九种模型&#xff0c;几乎基本够你用了&#xff0c;主流的权限模型主要有以下9种&#xff1a; 1、ACL模型 访问控制列表 2、DAC模型 自主访问控制 3、MAC模型 强制访问控制 4、ABAC模型 基于属性的访…

【数据结构】带头双向循环链表的实现

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;别人可以拷贝我的模式&#xff0c;但不能拷贝我不断往前的激情 &#x1f6f8;C语言专栏&#xff1a;https://blog.csdn.net/vhhhbb/category_12174730.html &#x1f680;数据结构专栏&#xff…

【JavaEE】前后端分离实现博客系统(后端实现)

写在前面 Hello&#xff0c;在上一篇中&#xff0c;我们已经实现了对于博客系统的页面构建任务。本次主要解决的问题就是针对这四个界面&#xff0c;实现后端的 servlet 程序&#xff0c;规范前后端交互的接口&#xff0c;编写客户端和服务端代码&#xff0c;处理请求并反馈。博…

响应式编程详解,带你熟悉Reactor响应式编程

文章目录一、什么是响应式编程1、Java的流和响应式流2、Java中响应式的使用3、Reactor中响应式流的基本接口4、Reactor中响应式接口的基本使用二、初始Reactor1、Flux和Mono的基本介绍2、引入Reactor依赖3、响应式类型的创建4、响应式类型的组合&#xff08;1&#xff09;使用m…

【C语言蓝桥杯每日一题】——数字三角形

【C语言蓝桥杯每日一题】—— 数字三角形&#x1f60e;前言&#x1f64c;数字三角形&#x1f64c;总结撒花&#x1f49e;&#x1f60e;博客昵称&#xff1a;博客小梦 &#x1f60a;最喜欢的座右铭&#xff1a;全神贯注的上吧&#xff01;&#xff01;&#xff01; &#x1f60a…

QEMU启动ARM32 Linux内核

目录前言前置知识ARM Versatile Express开发板简介ARM处理器家族简介安装qemu-system-arm安装交叉编译工具交叉编译ARM32 Linux内核交叉编译ARM32 Busybox使用busybox制作initramfs使用QEMU启动ARM32 Linux内核模拟vexpress-a9开发板模拟vexpress-a15开发板参考前言 本文介绍采…

编译原理

文章目录绪论第1章 绪论1.什么是编译2.编译系统的结构3.词法分析第2章 语言及其文法字母表 ∑\sum∑概念终结符非终结符产生式文法Chomsky文法分类体系0型文法 &#xff08;Type-0 Grammar&#xff09;1型文法&#xff08;Type-1 Grammar&#xff09;2型文法&#xff08;Type-2…

JAVA开发与JAVA(一文学会使用ElasticSearch)

在web网站的架设中特别是数据量大的网站或者APP小程序需要搜索或者全文检索的场景&#xff0c;几乎都需要借助ElasticSearch来作为全文检索引擎&#xff0c;以提高网站的搜索效率和性能。 这一节&#xff0c;我们通过一篇文章介绍&#xff0c;使大家通过一文就学会使用Elastic…

python 函数:定义、调用、参数、返回值、嵌套、变量的作用域(局部变量、全局变量)、global、匿名函数lambda

函数可以将我们的程序分解成最小的模块&#xff0c;避免重复使用。函数内部的代码&#xff0c;只有被调用的时候才会执行。 函数的定义&#xff08;def就是define&#xff09;&#xff1a; 格式&#xff1a;def 函数名(): 函数封装的代码 函数的调用&#xff1a; 格式&…

大学生考研的意义?

当我拿起笔头&#xff0c;准备写这个话题时&#xff0c;心里是非常难受的&#xff0c;因为看到太多的学生在最好的年华&#xff0c;在自由的大学本应该开拓知识&#xff0c;提升认知&#xff0c;动手实践&#xff0c;不断尝试和试错&#xff0c;不断历练自己跳出学生思维圈&…

15000 字的 SQL 语句大全 第一部分

一、基础 1、说明&#xff1a;创建数据库CREATE DATABASE database-name 2、说明&#xff1a;删除数据库drop database dbname 3、说明&#xff1a;备份sql server--- 创建 备份数据的 device USE master EXEC sp_addumpdevice disk, testBack, c:\mssql7backup\MyNwind_1.dat …

数据结构--二叉树

目录1.树概念及结构1.1数的概念1.2数的表示2.二叉树概念及结构2.1二叉树的概念2.2数据结构中的二叉树2.3特殊的二叉树2.4二叉树的存储结构2.4.1顺序存储2.4.2链式存储2.5二叉树的性质3.堆的概念及结构3.1堆的实现3.1.1堆的创建3.1.2堆的插入3.1.3堆顶的删除3.1.4堆的代码实现3.…

蓝桥杯刷题冲刺 | 倒计时26天

作者&#xff1a;指针不指南吗 专栏&#xff1a;蓝桥杯倒计时冲刺 &#x1f43e;马上就要蓝桥杯了&#xff0c;最后的这几天尤为重要&#xff0c;不可懈怠哦&#x1f43e; 文章目录1.路径2.特别数的和3.MP3储存4.求和1.路径 题目 链接&#xff1a; 路径 - 蓝桥云课 (lanqiao.cn…