【计算机图形学】【实验报告】DDA画线算法、Bresenham中点画线算法、多边形填充算法附代码

实 验 报 告

一、实验目的

  1. 了解光栅化图形学的主要理论和知识。
  2. 了解OpenGL图形库的构成,会设计OpenGL的程序。
  3. 掌握基本图形的生成原理,学会设计基本图形的生成算法。包括画线算法、画圆算法和多边形填充算法的原理和实现方法。
  4. 设计中点画线算法,对给定的任意起点和终点的线段,采用中点画线算法设计画线程序,并能保证程序的正确性。
  5. 掌握多边形填充算法的基本原理和方法,掌握有序边表法和扫描线种子填充算法的原理。根据给定的类设计实现有序边表法填充多边形的程序​​​​​​​ 

二、实验内容与实验步骤

中点画线算法:

  1. 完成中点画线算法的设计,调用OpenGL的画点的函数,采用中点画线算法完成二维线段的绘制算法。
  2. 补全了lineBres函数以及pointFun函数。
    1. lineBres函数:一共有四个参数,表示起始点和终止点的坐标信息。分四种情况实现中点画线算法,分别是:0<=m<=1,m>=1,-1<=m<=0以及m<=-1。在函数中调用glVertex2d(x,y)函数,对每个坐标点(x,y)进行绘制。
    2. pointFun函数:利用glColor3f(GLfloat,GLfloat,GLfloat)函数设置画线颜色,之后调用lineBres函数绘制每条线。
  3. 实现后调用OpenGL的画线函数画线对比自己的实验结果。

DDA画线算法:

  1. 完成DDA画线算法的设计,调用OpenGL的画点的函数,采用DDA画线算法完成二维线段的绘制算法。
  2. 调用文件里所给的lineDDA函数,并创建与pointFun函数具有相同功能的DDALine函数。
    1. lineDDA函数:一共有四个参数,表示起始点和终止点的坐标信息。
    2. DDALine函数:利用glColor3f(GLfloat,GLfloat)函数设置画线颜色,之后调用lineDDA函数绘制每条线。

多边形填充算法:       

  1. 根据给定的类设计实现有序边表法填充多边形的程序
  2. 创建drawFrame()函数,用以勾画填充图形的外轮廓。
  3. 导入参考文件里的myclass.h以及myclass.cpp文件,调用其中的类以及函数,在main.cpp文件内创建新函数scanFill()函数,实现多边形填充。
  4. 在main()函数内调用drawFrame()函数以及scanFill()函数,实现描边以及填充。

三、实验环境

  1. 操作系统:macOS Big Sur Version 11.6
  2. 调试软件:Xcode Version 13.0
  3. 上机地点:xxx
  4. 机器台号:xxx

四、实验过程与分析

中点画线算法:

lineBres函数:

 流程图

      修改:Build Settings --> Linking --> Other Linker Flags 添加 “-framework OpenGL”

  • 定义函数出错

​​​​​​​ 

修改:将函数改名为ro(猜测round和其他功能重名)

 坐标信息

原点位置:视口中央

X正方向:视口内右方向

Y正方向:视口内上方向

视口大小:600*600


DDA画线算法:

lineDDA函数:

 流程图

最开始文件中给的循环代码为:while (x <= x2),运行结果:

缺少斜率为负的情况。

修改:将循环判定部分修改为for (int i=1; i<=epsl; i++),即可绘制出正确图案。

坐标信息

 坐标原点位置:视口中央

X正方向:视口内右方向

Y正方向:视口内上方向

视口大小:600*600


多边形填充算法:

scanFill函数:

 流程图

 调试中的问题

  •  问题:输入的数据类型和定义不符

       修改:将point均改为引用类型。

 

  •   问题:指针应采用->样式调用 

       修改:把head.GetNextedge改为head->GetNextedge

  •  问题:运行函数后没有图形。

       修改:在myDisplay()函数末尾添加glFlush()函数调用。

 坐标信息

 坐标原点位置:视口中央

X正方向:视口内右方向

Y正方向:视口内上方向

视口大小:600*600


五、实验结果总结

中点画线算法:

DDA画线算法:

多边形填充算法:

代码:

// 画线算法

#define GL_SILENCE_DEPRECATION

#include<iostream>
#include<GLUT/glut.h> //windows改成<GL/glut.h>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>

using namespace std;


void init(void)
{
    glClearColor(1.0,1.0,0.0);  // Set display-window color to white.
    glMatrixMode(GL_PROJECTION);       // Set projection parameters.
    glPointSize(2.0f);
    gluOrtho2D(-200,200,-200,200);
    GLfloat sizes[2];
    GLfloat step;
        glGetFloatv(1.0f,sizes);
        glGetFloatv(1.0f,& step);
    
}


int ro(const float a)
{
    int b = int(a+0.5);
    return b;
}


void lineDDA(int x1,int y1,int x2,int y2);
void lineBres(int x1,int y2);

void myReshape(GLsizei w,GLsizei h) {
    glViewport(0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-w/2,w/2,-h/2,h/2,-10,10);
}

void myDisplay() {
    glClearColor(0.0,0.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0,1.0);
    //glRectf(100,100,20,20);
    lineDDA(10,10,150);
    lineBres(10,30,170);
    glFlush();
}


void lineDDA(int x1,int y2) {
    float dx,dy;
    int epsl;
    float xIncre,yIncre;
    dx = x2 - x1;
    dy = y2 - y1;
    float x = x1;
    float y = y1;
    if (abs(dx) > abs(dy))
        epsl = abs(dx);
    else
        epsl = abs(dy);
    xIncre = (float)dx / epsl;
    yIncre = (float)dy / epsl;
    glBegin(GL_POINTS);
    for (int i=1; i<=epsl; i++)
    {
        glVertex2i(int(x + 0.5),int(y + 0.5));
        x += xIncre;
        y += yIncre;
    }

}

void lineBres(int x1,int y2)
{
    int x = x1;
    int y = y1;
    if (x1 > x2)
    {
        x = x1; x1 = x2; x2 = x; x = x1;
        y = y1; y1 = y2; y2 = y; y = y1;
    }
    glBegin(GL_POINTS);
    int a = y1 - y2;
    int b = x2 - x1;
    float k = 0;
    int d;
    if (x1 != x2)
    {
        k = -1.0 * a / b;
    }
    else
    {
        if (y2 >= 0)
        {
            while (y < y2)
            {
                glVertex2i(x,y);
                y++;
            }
        }
        else
        {
            while (y > y2)
            {
                glVertex2i(x,y);
                y--;
            }
        }
    }

    if (k >= 0.0 && k < 1.0)
    {
        d = 2 * a + b;
        while (x <= x2)
        {
            glVertex2i(x,y);
            if (d >= 0)
            {
                d += 2 * a;
                x++;
            }
            else {
                d += 2 * a + 2 * b;
                x++;
                y++;
            }


        }



    }
    else if (k >= 1.0)
    {
        d = 2 * b + a;
        while (y <= y2)
        {
            glVertex2i(x,y);
            if (d >= 0)
            {
                d += 2 * b + 2 * a;
                x++;
                y++;
            }
            else {
                d += 2 * b;
                y++;
            }



        }


    }
    else if (k > -1.0 && k <= 0.0)
    {
        d = 2 * a - b;
        while (x <= x2)
        {
            glVertex2i(x,y);
            if (d >= 0)
            {
                d += 2 * a - 2 * b;
                x++;
                y--;
            }
            else {
                d += 2 * a;
                x++;

            }


        }

    }
    
    else
    {
        d = a - 2 * b;
        while (y >= y2)
        {
            glVertex2i(x,y);
            if (d >= 0)
            {
                d += -2 * b;
                y--;
            }
            else {
                d += 2 * a - 2 * b;
                x++;
                y--;
            }
        }

    }
    glEnd();


}


void pointFun(void)

{
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_POINTS);
    glColor3f(1.0,0.0);//红
    lineBres(1,1,50);//(1,1)    (100,50)
    glColor3f(1.0,0.5,0.0);//橙
    lineBres(1,50,100);//(1,1)    (50,100)
    glColor3f(1.0,0.0);//黄
    lineBres(-1,-100,50);//(-1,1)    (-100,50)
    glColor3f(0.0,0.0);//绿
    lineBres(-1,-50,100);//(-1,1)    (-50,100)
    glColor3f(0.0,1.0);//青
    lineBres(-1,-1,-50);//(-1,-1)    (-100,-50)
    glColor3f(0.0,1.0);//蓝
    lineBres(-1,-100);//(-1,-1)    (-50,-100)
    glColor3f(1.0,1.0);//紫
    lineBres(1,-50);//(1,-1)    (100,-50)
    glColor3f(0.0,0.0);//黑
    lineBres(1,-100);//(1,-1)    (50,-100)
    glColor3f(0.0,0.0);//黑
    lineBres(0,0);//(0,0)    (100,0)
    glColor3f(0.0,100);//(0,0)    (0,100)
    glEnd();
    glFlush();

        
}

void DDALine(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_POINTS);
    glColor3f(1.0,0.0);//红
    lineDDA(1,0.0);//橙
    lineDDA(1,0.0);//黄
    lineDDA(-1,0.0);//绿
    lineDDA(-1,1.0);//青
    lineDDA(-1,1.0);//蓝
    lineDDA(-1,1.0);//紫
    lineDDA(1,0.0);//黑
    lineDDA(1,0.0);//黑
    lineDDA(0,100)
    glEnd();
    glFlush();
}

void sysLine(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_LINES);
    glColor3f(1.0,0.0);//红
    glVertex2f(1,1);
    glVertex2f(100,50);
    glColor3f(1.0,0.0);//橙
    glVertex2f(1,1);
    glVertex2f(50,100);
    glColor3f(1.0,0.0);//黄
    glVertex2f(-1,1);
    glVertex2f(-100,50);
    glColor3f(0.0,0.0);//绿
    glVertex2f(-1,1);
    glVertex2f(-50,100);
    glColor3f(0.0,1.0);//青
    glVertex2f(-1,-1);
    glVertex2f(-100,-50);
    glColor3f(0.0,1.0);//蓝
    glVertex2f(-1,-1);
    glVertex2f(-50,-100);
    glColor3f(1.0,1.0);//紫
    glVertex2f(1,-1);
    glVertex2f(100,0.0);//黑
    glVertex2f(1,-1);
    glVertex2f(50,-100);
    glVertex2f(0,0);
    glVertex2f(100,0);
    glVertex2f(0,100);

    glEnd();
    glFlush();

    
}

int main(int argc,char** argv)
{

    glutInit(&argc,argv);                         // Initialize GLUT.
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);   // Set display mode.
    glutInitWindowPosition(50,100);   // Set top-left display-window position.
    glutInitWindowSize(600,600);      // Set display-window width and height.
    glutCreateWindow("DDA画线算法"); // Create display window.
    init();                           // Execute initialization procedure.
    glutDisplayFunc(DDALine);       // Send graphics to display window.
    glutMainLoop();// Send graphics to display window.                  // Display everything and wait.
    

    return 0;
}
// 多边形填充算法
#define GL_SILENCE_DEPRECATION

#include <iostream>
using namespace std;
#include <GLUT/glut.h> // windows改成<GL/glut.h>
#include "myclass.h"

void drawFrame();
void scanFill();

void myReshape(GLsizei w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-w / 2,w / 2,-h / 2,h / 2,10);
}

void myDisplay() {
    glClearColor(1.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(0.0,0.0);
    //glRectf(100,20);
    drawFrame();
    scanFill();
    glFlush();
}

int main(int argc,char* argv[]) {
    glutInit(&argc,argv);

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(600,600);
    glutCreateWindow("多边形填充");

    glutDisplayFunc(myDisplay);
    glutReshapeFunc(myReshape);
    glutMainLoop();
    
    return 0;
}

void drawFrame(){
    Point2D point_1(0,0);
    Point2D point_2(-100,100);
    Point2D point_3(100,100);
    Point2D point_4(0,200);
    
    glBegin(GL_LINE_LOOP);
    glVertex2i(point_1.GetX(),point_1.GetY());
    glVertex2i(point_2.GetX(),point_2.GetY());
    glVertex2i(point_3.GetX(),point_3.GetY());
    glVertex2i(point_4.GetX(),point_4.GetY());
    glEnd();
}


void scanFill(){
    NewEdgeTable NET;
    ActiveEdgeTable AET;
    ActiveEdge point1(0,100);
    NET.InsertNewEdge(&point1,0);
    ActiveEdge point2(0,100);
    point1.SetNext(&point2);
    ActiveEdge point3(-100,200);
    NET.InsertNewEdge(&point3,100);
    ActiveEdge point4(100,200);
    point3.SetNext(&point4);

    int i=0;
    //遍历新边表
    for (ActiveEdge* point : NET.rowTable){
        ActiveEdge * ptr = AET.head->GetNextedge();
        //遍历活性边表 删去非必要的边
        while (ptr != NULL) {
            if (ptr->GetMax()==i){
                ActiveEdge* ptr2 = ptr;
                ptr = ptr->GetNextedge();
                AET.DeleteActiveEdge(ptr2);
            }else{
                float x = ptr->GetCurrentX()+ptr->GetDX();
                ptr->SetCurrentX(x);
                ptr = ptr->GetNextedge();
            }
        }
        
        //放入活性边表
        while (point != NULL) {
            ActiveEdge* point2 = point;
            point = point->GetNextedge();
            AET.InsertActiveEdge(point2);
        }
        AET.sort();
        ptr = AET.head->GetNextedge();
        glBegin(GL_LINES);
        glColor3f(0.0,0.0);
        
        //遍历新的活性边表 填充
        while (ptr!=NULL){
            int x = ptr->GetCurrentX();
            glVertex2i(x,i);
            ptr = ptr->GetNextedge();
            x = ptr->GetCurrentX();
            glVertex2i(x,i);
            ptr = ptr->GetNextedge();
        }
        glEnd();
        i++;
        
    }
    
}

六、附录

  1. 设想:可以考虑用每一步都定格一小段时间看真实的扫描过程,但因能力不足未实现。
  2. 资料:
    1. 多边形的扫描转换算法——扫描线算法(计算机图形学)_八爪鱼的博客-CSDN博客
    2. 【区域填充】中的扫描线填充算法,活性边表AET,新边表NET_ZY_cat的博客-CSDN博客_活性边表
    3. 计算机图形学实验三:多边形填充算法之活性边表方法实现_孜迹的博客-CSDN博客_活性边表算法
    4. UniTHI/PolygonRasterer.java at 1669f5ede92db042919dad65c09fda71b0bd1fac · MobysDikk/UniTHI · GitHub
    5. 百度搜索、百度文库、课本等。
  3. 思考题:
    1. Q:对比DDA画线算法,Bresenham中点画线算法有哪些优点?A:D DA算法中的yk都必须用浮点数表示,并且每一步运算都要对y进行舍入取整,这不利于硬件实现。中点画线法只包含整数变量,并且不含乘除法,速度更快效率更高。
    2. Q:举例说明种子填充算法适合什么应用场景? A:如果要填充的区域是以图像元数据方式给出的,通常使用种子填充算法进行区域填充。种子填充算法需要给出图像数据的区域,以及区域内的一个点,这种算法比较适合人机交互方式进行的图像填充操作,不适合计算机自动处理和判断填色。​​​​​​​

// 大家随便看看,当初做实验真的是被整麻了……心态一整个没有hhh。

// 要是有错误欢迎指出,用到了麻烦点个赞点个关注~(没兴趣真的不要学数媒

原文地址:https://blog.csdn.net/Kqp12_27

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


在有效期内的苹果开发者账号(类型为个人或者公司账号)。还有一种情况,就是你的Apple ID被添加到公司开发者账号团队里面,这样也是可以的,但是需要叫管理员给你开通相应的账号权限,如下截图:这里可能有些同学会问,苹果开发者账号是什么?如何申请?那么可以看看我的上一篇文章:iOS苹果开发者账号(公司账号)申请流程详解能正常编译打包的iOS工程项目(都不能正常编译谈何出包上架
Appuploader官网--IOS ipa上传发布工具,证书制作工具跨平台版,windows,linux,mac系统都可用 (applicationloader.net)第一步:注册苹果开发者账号,访问以下网址,按照提示注册即可,因为不需要支付688认证苹果开发者,所以没什么好讲的。证书部分:主要是通过工具生成.p12证书文件,后面这个证书要导入mac系统。描述文件:这个文件主要包含了证书,公钥,设备信息等,具体可以百度了解详情。第三步:使用xcode打包导出ipa文件,供其他人内测。..........
苹果在9月13号凌晨(北京时间)发布 iOS 16,该系统的设备可能会因为各种原因,导致功能不可用和UI错乱等问题,我们需要做好适配iOS 16。
计算机图形学--OpenGL递归实现光线追踪
Xcode 14打出来的包在低版本系统运行时会崩溃,报错信息是Library not loaded: /usr/lib/swift/libswiftCoreGraphics.dylib,在苹果开发者论坛搜索报错信息,可以看到会闪退的最高版本是iOS12.1(不敢肯定,毕竟我没测过,不过肯定低于iOS 12.4
iOS16手机开启开发者模式 "developer mode disable"Pod工程中的Bundle target签名报错
【计算机图形学】【实验报告】DDA画线算法、Bresenham中点画线算法、多边形填充算法(附代码)
iOS 16 满载全新的个性化功能、更具深度的智能技术,以及更多无缝的沟通与共享方式,让 iPhone 的体验更进一步。13、隐私权限增强,如通过 UIDevice 获取设备名称时,无法获取用户的信息,只能获取设备对应的名称。
3、回到苹果开发者中心,如下图,点击certificates,点蓝色小加号,就可以开始创建证书,创建证书的时候无论测试还是上传app store打包,都要选ios distribution app store and adhoc,不要选apple和develpment类型的证书。2、如下图,点左边的profiles菜单,点击蓝色加号,创建描述文件,创建过程中会要求我们选择描述文件的类型,假如你想发布app到app store,则选择app store,假如你想真机测试,则选择ad hoc类型。
需要:Unity,IOS平台模块,Xcode,IOS_SDk,MAC电脑,Iphone手机
最近下载安装 xcode 并解压安装,遇到一些问题误以为是错误,记录在此。从百度和谷歌上搜了很多帖子,发现并没有靠谱的 xcode 国内的镜像,这里提供一个可以跳转到官网的下载方式。xcode 不同版本的列表,下载时注意不同 macOs 不同的系统和 Xcode 版本的对应关系。如 要求 及其以上版本。https://xcodereleases.com/注意点击后会跳到官方下载地址,需要登录苹果账号。xcode 文件很大,通常要 10G 以上,下载速度很慢。可以考虑使用 Free Downlo
使用苹果登录作为第三方登录
missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun解决方法
Xcode14 正式版编译报错' does not contain bitcode.You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. file 'xxx' for architecture arm64解决方案
那应该和升级Xcode 14有关系。但是官方还没有给出解决方案。应该后续会有兼容的cocoapods 新版本。
项目中需要用到Xcode将C++代码输出的Mac版本的DLL文件即DYLIB文件,并能够使用C#代码调用。Unity与 DLL文件 ☀️| 怎样使用VC++生成一个DLL文件并调用!这次来看一下在Mac使用Xcode生成的方法吧!本文介绍了在Mac中怎样使用 Xcode项目使用C++生成 .dylib文件的方法。相对于在Windows中使用AndroidStudio创建动态链接库的方法来说,使用Xcode创建.dylib文件确实简单了很多。