【代码】使用C++实现改进的有效边表算法。

2023-05-16

算法的解释和一些细节晚一些再上传,先直接上代码:

如果有错误可以在评论区指出。

//由于opengl使用实数的坐标,所以,本程序将使用画线代替画点

#include<GL/glut.h>
#include<Windows.h>
#include<cmath>
#include<vector>
#include<list>
#include <iostream>


using namespace std;

class point2f {
public:
    float x;
    float y;
    point2f(float x, float y) : x(x),y(y){}
};

class line4bucket {
public:
    float x_st;//会变化
    int ymax;
    float dx;
    int ymin; // 由于有效边表算法,这个使用整数
    float x_ed;
    line4bucket(point2f p1,point2f p2) 
    {
        if (p1.y > p2.y)
        {
            ymax = p1.y;
            x_st = p2.x;
            ymin = p2.y;
            x_ed = p1.x;
        }
        else
        {
            ymax = p2.y;
            x_st = p1.x;
            ymin = p1.y;
            x_ed = p2.x;
        }
        dx=(p1.x - p2.x) / (p1.y - p2.y);
    };

    bool operator<(line4bucket p2)
    {
        return x_st < p2.x_st;
    }
    bool operator>(line4bucket p2)
    {
        return x_st > p2.x_st;
    }
};



void reshape(int x, int y)
{
    int dis = x > y ? y : x; //取小的
    glViewport(0, 0, dis, dis);
}

list<line4bucket> *bucket;
vector<point2f> point_list;
int maxY = -10086;

void initbucket() {
    int flag;
    int n;
    cout << "测试/按顺序输入顶点坐标/手动输入线段(0/1/2):\n";
    cin >> flag;
    switch (flag)
    {
    case 0:
        n = 7;
        point_list.push_back(point2f(3, 1));
        point_list.push_back(point2f(1, 7));
        point_list.push_back(point2f(3, 12));
        point_list.push_back(point2f(7, 8));
        point_list.push_back(point2f(12, 9));
        point_list.push_back(point2f(8, 1));
        point_list.push_back(point2f(6, 5));
        break;
    case 1:
        
        cout << "请输入顶点个数:\n";
        cin >> n;
        cout << "请输入顶点(x和y之间用空格或者逗号隔开):\n";
        for (int i = 0; i < n; i++)
        {
            float x, y;
            cin >> x >> y;
            point_list.push_back(point2f(x, y));
        }
        break;
    case 2:
        cout << "请输入线段个数:\n";
        cin >> n;
        cout << "请输入顶点坐标中y的最大值:\n";
        cin >> maxY;
        bucket = new list<line4bucket>[maxY + 1];
        cout << "请输入顶点(两个一组,x和y之间用空格或者逗号隔开):\n";
        for (int i = 0; i < n; i++)
        {
            float x1, y1,x2,y2;
            cin >> x1 >> y1 >> x2 >> y2;
            point2f p1 = point2f(x1, y1);
            point2f p2 = point2f(x2, y2);
            line4bucket tmpline = line4bucket(p1, p2);
            bucket[tmpline.ymin].push_back(tmpline);
        }
        return;
    default:
        n = 7;
        point_list.push_back(point2f(3, 1));
        point_list.push_back(point2f(1, 7));
        point_list.push_back(point2f(3, 12));
        point_list.push_back(point2f(7, 8));
        point_list.push_back(point2f(12, 9));
        point_list.push_back(point2f(8, 1));
        point_list.push_back(point2f(6, 5));
        break;
    }



    

    maxY=point_list[0].y;
    for (int i=1;i<n;i++)
    {
        if (point_list[i].y > maxY)
        {
            maxY = point_list[i].y;
        }
    }
    
    bucket = new list<line4bucket>[maxY+1];
    
    for (int i = 0; i < n; i++)
    {
        line4bucket tmpline = line4bucket(point_list[i], point_list[(i + 1)%n]);
        bucket[tmpline.ymin].push_back(tmpline);
    }
}



void draw()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    
    

    list<line4bucket> tmplst;
    for (int i = 0; i <= maxY; i++)
    {
        //删除到达最高点的线
        auto jtr = tmplst.begin();
        while (jtr != tmplst.end())
        {

            if (i > (*jtr).ymax)
            {
                if (jtr == tmplst.begin())
                {
                    tmplst.erase(jtr);
                    jtr = tmplst.begin();
                    continue;
                }
                else
                {
                    auto tmpjtr = jtr;
                    jtr--;
                    tmplst.erase(tmpjtr);
                }
                
            }

            jtr++;
        }
        //加入
        auto itr = bucket[i].begin();
        while (itr != bucket[i].end())
        {
            //删除旧线段末尾与新线段起点重合的旧线段
            auto jtr = tmplst.begin();
            while (jtr != tmplst.end())
            {

                if (((*itr).x_st - (*jtr).x_ed) <= 1e-7 && (*itr).ymin == (*jtr).ymax && !isinf((*itr).dx))
                {
                    if (jtr == tmplst.begin())
                    {
                        tmplst.erase(jtr);
                        jtr = tmplst.begin();
                        continue;
                    }
                    else
                    {
                        auto tmpjtr = jtr;
                        jtr--;
                        tmplst.erase(tmpjtr);
                    }

                }

                jtr++;
            }
            
            if(!isinf((*itr).dx))
            tmplst.push_back((*itr));
            itr++;
        }
        
        //排序
        tmplst.sort();

        //绘制
        //先检查一下
        if (tmplst.size() % 2 != 0)
        {
            cerr << "出现错误!";
            exit(10);
        }
        //绘制
        glColor3f(1.0, 1.0, 1.0);//白色点
        glBegin(GL_LINES);
        list<line4bucket>::iterator jtr_last;
        list<line4bucket>::iterator jtrt;
        if (tmplst.empty())goto STEP;
        
        jtr_last = tmplst.begin();
        jtrt = tmplst.begin();
        jtrt++;
        cout << "y = " << i << endl;
        while (true)
        {
            //opengl窗口的坐标范围是(-1,1),需要变换一下
            cout << "Draw(" << (*jtr_last).x_st << "," << (*jtrt).x_st << ")\n";
            glVertex2f(((*jtr_last).x_st) / ((float)20)-0.5, (((float)i) / ((float)20))-0.5);
            glVertex2f(((*jtrt).x_st) / ((float)20)-0.5, (((float)i) / ((float)20))-0.5);
            
            jtr_last++;
            jtr_last++;
            if (jtrt == tmplst.end())break;
            jtrt++;
            if (jtrt == tmplst.end())break;
            jtrt++;
            
        }
        cout << endl;
        
        STEP:
        //迭代
        for (auto jtr = tmplst.begin(); jtr != tmplst.end(); jtr++)
        {
            (*jtr).x_st += (*jtr).dx;
        }

    }

    glEnd();

    glFlush();
}

int main(int argc, char** argv)
{
    initbucket();
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
    glutInitWindowPosition(0, 0);
    glutInitWindowSize(500, 500);
    glutCreateWindow("多边形的扫描转换");
    glutDisplayFunc(draw);
    glutReshapeFunc(reshape);
    glutMainLoop();
    return 0;
}

/*

0 0 5 0
5 0 5 5
5 5 0 5
0 5 0 0
1 1 4 1
4 1 4 4
4 4 1 4
1 4 1 1
这是回字形线段输入

*/
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【代码】使用C++实现改进的有效边表算法。 的相关文章

  • INSERT INTO 表名 SELECT 语句

    Connected to Oracle Database 11g Enterprise Edition Release 11 2 0 1 0 Connected as scott CREATE TABLE 表名 AS SELECT 语句 S
  • Windows 去除快捷方式小箭头真正无任何副作用的方法!

    前几天写过 Windows7去除快捷方式小箭头后会导致左侧收藏夹中的桌面图标消失 xff0c 以为那种方法已经很完美 xff0c 然而我错了 xff0c 当我右击 计算机 想打开 管理 时 xff0c 弹出了错误提示 xff1a 该文件没有
  • 在 KDE 下不能正常使用 fcitx 以及翻页问题

    在 kde 下使用 fcitx 的时候 xff0c 不能在某些地方使用 xff0c 如kate xff0c 但有些地方可以使用 xff0c 如 chrome 使用 Ctrl 43 Space 时无法激活 Fcitx 1 检查你所输入的程序
  • IDM 激活

    打开 C WINDOWS system32 drivers etc 这个文件夹中有个 hosts 文件 大家用 记事本 打开 在最后一行加入 127 0 0 1 registeridm com 127 0 0 1 www registeri
  • Linux 挂载 exFat

    在Linux的学习中为方便大家学习了解更多的Linux方面的内容 xff0c 达内培训 技术小编本文将为大家详解关于Linux方面的技术内容 xff0c 提供给大家作为学习的参考 先说挂载exFAT格式的移动硬盘 xff0c 最近刚刚做了个
  • HTML中meta标签的作用

    HTML中meta标签的作用 首先 xff0c meta标签是一个自结束标签 xff0c 其格式为 lt meta gt xff0c 下面介绍meta标签的作用 xff1a 1 规定字符集 lt meta charset 61 34 utf
  • 多个浏览器窗口中间不同的Session

    关于多个窗口不同Session的作用就不说了 xff0c 直接说步骤 Firefox xff1a 编辑快捷方式的目标 xff0c 后面加上 p no remote Chrome xff1a 打开新的隐身窗口 IE xff1a 文件 gt 新
  • Nginx 开启对 PHP 的解析(转)

    安装 PHP 和 nginx 后 xff0c 无法解析 PHP 文件 其中 xff0c PHP 和 nginx 的编译安装 configure 如下 xff1a PHP 5 3 9 configure prefix 61 usr local
  • JDK 对应数字版本号

    J2SE 7 61 51 0x33 hex J2SE 6 0 61 50 0x32 hex J2SE 5 0 61 49 0x31 hex JDK 1 4 61 48 0x30 hex JDK 1 3 61 47 0x2F hex JDK
  • 打印控件

    Lodop
  • 二进制最大公约数算法

    求最大公约数的Euclid算法需要用到大量的取模运算 xff0c 这在大多数计算机上是一项复杂的工作 xff0c 相比之下减法运算 测试数的奇偶性 折半运算的执行速度都要更快些 二进制最大公约数算法避免了Euclid算法的取余数过程 二进制
  • 1、docker+k8s+kubesphere:准备(20200802更新免密)

    1 准备 docker 43 k8s 43 kubesphere准 环境准备 角色IP地址主机名docker版本硬件操作系统主192 168 5 151node151docker18 09 96核10GCentOS7 8节点192 168
  • 2、docker+k8s+kubesphere:docker安装

    2 docker安装 docker 43 k8s 43 kubesphere 卸载以前的docker yum remove y docker docker client docker client latest docker common
  • 7、docker+k8s+kubesphere:helm与tiller安装

    7 docker 43 k8s 43 kubesphere helm安装 官网地址 https kubesphere io docs zh CN installation install on k8s 官网虽然说低配置可以使用 xff0c
  • 8、docker+k8s+kubesphere:nfs安装(2020-08-02更新)

    8 docker 43 k8s 43 kubesphere nfs安装 server端安装在node151 yum y span class token function install span nfs utils rpcbind 配置文
  • 9、docker+k8s+kubesphere:Kubernetes安装(2020-08-02更新)

    9 docker 43 k8s 43 kubesphere Kubernetes安装 官网说明一定详细查看 span class token punctuation span 本文用的是2 1 1 span class token punc
  • Linux修改进程名称(setproctitle())

    每一个c程序都有个main函数 xff0c 作为程序启动入口函数 main函数的原型是int main int argc char argv 其中argc表示命令行参数的个数 xff1b argv是一个指针数组 xff0c 保存所有命令行字
  • 转载一篇文章:别人做毕业设计的思路

    发信人 zyzyis 小菜 十年一觉扬州梦 信区 SCU CS 标 题 我来谈谈毕业设计 xff08 准备篇 xff09 发信站 四川大学蓝色星空站 Sat Jan 15 11 15 53 2005 转信 很早就想写篇帖子来讲述自己做了近半
  • bash实现的回收站程序

    好久没写博了 哈哈 xff0c 最近在学习Linux 这是偶写的第一个shell脚本 xff0c 是一个实现类似windows里的回收站的程序 xff0c 可以避免误删文件 xff0c 希望能够对大家有所帮助 xff0c 当然自己练手是最重
  • 程序的格式

    一 格式 注 xff1a 比算法还重要 1 该注意的问题 xff1a xff08 1 xff09 大括号对齐 xff08 2 xff09 遇到 要缩进 xff1a Tab或Shift 43 Tab xff08 3 xff09 程序块之间加空

随机推荐