首页 > 编程语言 >(5)---【DDA画线算法】C语言-OpenGL库-计算机图形学

(5)---【DDA画线算法】C语言-OpenGL库-计算机图形学

时间:2024-11-10 18:49:38浏览次数:3  
标签:直线 1.0 OpenGL int 0.0 float 图形学 C语言 lineDDA

本次实验项目 

        DDA画线算法理解与运用。

算法介绍

        DDA(Digital Differential Analyzer)画线算法是一种基于数值微分原理的直线生成算法。它主要用于在光栅系统中绘制直线,即在像素点阵中生成直线。DDA算法的核心思想是从一个端点开始,通过增量,逐步迭代计算下一个端点的位置,直到达到另一个端点。

算法描述

        设直线为Ly=kx+b,已知过端点 P0(x0, y0)P1(xend, yend),若

---------------------------------------------------------------------------------------------------------------------------------

沿X轴步进,x_{i+1}=x_{i}+1

| k | <= 1即\left | xend-x0 \right |\geq\left | yend-y0 \right |时,直线L靠近X轴,直线斜率为  k=\frac{yend-y0}{xend-x0}

y_{i+1}=k(x_{i}+1)+b =kx_{i}+k+b=y_{i}+k

        所以x每递增1,y相应地递增k,每次计算点的坐标,我只需要x+1,y+k就行了,避免了乘除,而只有加减。通过增量得到下一个点后,可知此坐标肯定会与实际像素点有偏差(实际的直线并不是和像素点完全重合的)。所以采取四舍五入得方式来平衡差值,但是C/C++中取整是直接舍去小数值,所以采取加上0.5再取整,即int(a+0.5)。从而达到一个四舍五入的目的。

---------------------------------------------------------------------------------------------------------------------------------

沿Y轴步进,y_{i+1}=y_{i}+1

| k | >= 1即\left | xend-x0 \right |< \left | yend-y0 \right |时,直线L靠近Y轴,若仍然使 k=\frac{yend-y0}{xend-x0},则会导致斜率k大于1。从而在x递增1的时候y可能会出现递增大于1的数,使得像素点不相邻,直线不连续,出现断点的情况。此时应令直线斜率为  v=\frac{1}{k}=\frac{xend-x0}{yend-y0}

x_{i+1}=\frac{(y_{i}+1)+b}{k} =\frac{y_{i}+b}{k}+\frac{1}{k}=x_{i}+\frac{1}{k}

        y每递增1,x相应地递增v,每次计算点的坐标,我只需要y+1,x+v就行了,同样的通过增量得到下一个点后,可知此坐标肯定会与实际像素点有偏差(实际的直线并不是和像素点完全重合的)。所以采取四舍五入得方式来平衡差值,但是C/C++中取整是直接舍去小数值,所以采取加上0.5再取整,即int(a+0.5)。从而达到一个四舍五入的目的。

---------------------------------------------------------------------------------------------------------------------------------

        整合即可得到完整DDA画线算法。

功能简单介绍

  setPixel 函数用于在指定的x和y坐标绘制一个像素点。lineDDA 函数实现了DDA算法,它接受两个端点的坐标作为参数,并在这两个点之间绘制直线。算法通过计算x和y的增量,逐步逼近直线上的点,并使用setPixel函数绘制这些点。

代码

#include <windows.h>
#include <cmath>
#include <GL/glut.h>  

#define GLUT_DISABLE_ATEXIT_HACK

inline int round(const float a) {
    return (int)(a + 0.5); // 四舍五入
}

void init(void) {
    glClearColor(0.0, 0.0, 0.0, 0.0); // 设置背景色
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0.0, 1920.0, 0.0, 1080.0); // 设置坐标系
}

void setPixel(int x, int y) {
    glBegin(GL_POINTS);	
        glVertex2i(x, y);
    glEnd();
}

void lineDDA(int x0, int y0, int xEnd, int yEnd) {
    int dx = xEnd - x0;
    int dy = yEnd - y0;
    int steps = (fabs(dx) > fabs(dy)) ? fabs(dx) : fabs(dy);
    float xIncreament = float(dx) / float(steps);
    float yIncreament = float(dy) / float(steps);
    float x = x0;
    float y = y0;

    setPixel(round(x), round(y)); // 设置起点像素

    for (int k = 0; k < steps; k++) {
        x += xIncreament;
        y += yIncreament;
        setPixel(round(x), round(y)); // 绘制像素点
    }
}

void lineSegment(void) {
    glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓存
	
	//坐标轴 
    glColor3f(1.0, 1.0, 1.0); // 设置线条颜色为白色
	glPointSize(5);
	lineDDA(960, 0, 960, 1080);//y轴 
    lineDDA(940,1050,960,1080);
    lineDDA(980,1050,960,1080);
    lineDDA(990,1070,1005,1050);
    lineDDA(1020,1070,990,1000);
    
    lineDDA(0, 540, 1920, 540);//x轴
	lineDDA(1900,560,1920, 540); 
	lineDDA(1900,520,1920, 540);
	lineDDA(1860,510,1910, 460); 
	lineDDA(1910,510,1860, 460);
    
	//绘制直线-1
	glColor3f(1.0, 0.0, 1.0); // 设置线条颜色为紫色
	glPointSize(3);
	lineDDA(50, 50, 1850, 1000); 
	//绘制直线-2
	glColor3f(1.0, 1.0, 0.0); // 设置线条颜色为黄色
	glPointSize(3);
	lineDDA(400,1000,1880,300); 
	//绘制直线		 
	glColor3f(0.0, 1.0, 1.0); // 设置线条颜色为青色
	glPointSize(3);
	lineDDA(400,1000,400,20); 
	
	glFlush(); // 强制执行所有OpenGL命令
}

int main(int argc, char** argv) {
    glutInit(&argc, argv);  
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);  
    glutInitWindowPosition(600, 450);  
    glutInitWindowSize(1920, 1080);  
    glutCreateWindow("DDA-OpenGL");  
    init();
    glutDisplayFunc(lineSegment);  
    glutMainLoop(); 
    return 0; 
}

运行结果

上手实践

          各位学有余力的先生和女士,如有兴趣的话,不妨参考上面内容,动手绘制自己喜欢的图形吧!祝你成功。

标签:直线,1.0,OpenGL,int,0.0,float,图形学,C语言,lineDDA
From: https://blog.csdn.net/2303_77716250/article/details/143663452

相关文章

  • 实验4 C语言数组应用编程
    实验任务1:task1.c源代码:1#include<stdio.h>2#defineN43#defineM245voidtest1(){6intx[N]={1,9,8,4};7inti;89printf("sizeof(x)=%d\n",sizeof(x));1011for(i=0;i<N;++i)......
  • 【C语言】解决error C4996: 'fopen': This function or variable may be unsafe. Cons
    几天编译文件的时候报错,编译出错信息:错误1errorC4996:'fopen':Thisfunctionorvariablemaybeunsafe.Considerusingfopen_sinstead.Todisabledeprecation,use_CRT_SECURE_NO_WARNINGS.Seeonlinehelpfordetails.意思就是fopen不安全,推荐你用fopen_s,这个时......
  • 实验4 c语言数组应用编程
    task1:1#include<stdio.h>2#include<stdlib.h>3#defineN44#defineM2567voidtest1(){8intx[N]={1,9,8,4};9inti;1011printf("sizeof(x)=%d\n",sizeof(x));1213for(i=0;i<N;++i)14......
  • OpenGL 和 GLSL 在顶点着色器中动态调整裁剪平面参数的简单代码示例
    以下是一个使用OpenGL和GLSL在顶点着色器中动态调整裁剪平面参数的简单代码示例://OpenGL初始化代码#include<GL/glew.h>#include<GLFW/glfw3.h>#include<iostream>GLFWwindow*window;//初始化GLFWvoidinitGLFW(){if(!glfwInit()){std::cer......
  • GPU OpenGL 管线
    GPUOpenGL管线主要分为以下几个阶段:顶点数据输入:数据定义与准备:开发者定义要渲染的图形的顶点数据,这些数据包含了每个顶点的位置、颜色、纹理坐标、法线向量等信息。例如,对于一个简单的三角形,需要指定三个顶点的三维坐标以及相关属性。这些数据通常存储在内存中,可以通过数组......
  • 洛谷题单入门1顺序结构(C语言版)
    【入门1】顺序结构Hello,World!#include<stdio.h>intmain(){printf("Hello,World!");return0;}输出字符菱形#include<stdio.h>intmain(){printf("*\n");printf("***\n");printf("*****\n&q......
  • 在OpenGL中实现视角切换插值过渡动画
    在OpenGL中实现视角切换插值过渡动画可以通过以下步骤来完成:一、定义视角结构体首先,需要定义一个结构体来表示视角相关的信息,通常包括观察位置(EyePosition)、观察目标点(LookAtPoint)和上方向向量(UpVector)。例如:structCamera{glm::vec3eye;glm::vec3center;......
  • 超详细C语言函数栈帧的创建和销毁的过程讲解,细节满满
    目录一、ebp和esp二、main函数的函数栈帧(解释反汇编)(1)、push操作(2)、mov操作(3)、sub操作(4)、然后又是三个push操作(5)、lea操作:(6)、接着四步操作:三、如何创建的变量(创建变量的反汇编)(1)、第一个inta=10:此时如果没有给a变量赋值,那么该位置的值就是CCCCCCCC,这就是为什么未......
  • 华为OD机试2024年E卷-MVP争夺战[100分]( Java | Python3 | C++ | C语言 | JsNode | Go
    题目描述在星球争霸篮球赛对抗赛中,最大的宇宙战队希望每个人都能拿到MVP,MVP的条件是单场最高分得分获得者。可以并列所以宇宙战队决定在比赛中尽可能让更多队员上场,并且让所有得分的选手得分都相同,然而比赛过程中的每1分钟的得分都只能由某一个人包揽。输入描述输入第一行......
  • 华为OD机试2024年E卷-AI识别面板[100分]( Java | Python3 | C++ | C语言 | JsNode | Go
    题目描述AI识别到面板上有N(1≤N≤100)个指示灯,灯大小一样,任意两个之间无重叠。由于AI识别误差,每次别到的指示灯位置可能有差异,以4个坐标值描述AI识别的指示灯的大小和位置(左上角x1,y1,右下角x2,y2),请输出先行后列排序的指示灯的编号,排序规则:每次在尚未排序的灯中挑选最高的......