【计算机图形学】实验二 用扫描线算法实现多边形填充

简介: 【计算机图形学】实验二 用扫描线算法实现多边形填充

😘欢迎关注:👍点赞🙌收藏✍️留言

🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的很重要,有问题可在评论区提出,感谢支持!!!

实验二、用扫描线算法实现多边形填充

一、实验目的及要求

本实验旨在掌握扫描线算法的原理和实现方法,通过编写程序实现多边形的填充。

二、实验设备

  • Microsoft Visual Studio 2022


三、实验原理

扫描线算法是一种用于填充多边形的算法,其基本思想是将多边形分解成若干个梯形区域,然后对每个梯形区域进行填充。在填充时,扫描线从上往下扫描,逐个像素点地判断当前点是否位于多边形内部,并根据需要进行颜色填充。

四、实验方法与步骤

  1. 算法思想

扫描线填充算法是一种计算机图形学中用于实现多边形填充的算法。它基于对多边形的扫描线进行处理,将多边形分割成一系列水平线段,并确定每条线段覆盖的像素点是否在多边形内部,从而实现多边形的填充。

  1. 算法步骤
  • 定义多边形数据结构,存储多边形的顶点信息。
  • 根据多边形的顶点信息,计算出多边形每条边的斜率和截距等信息,并存储在一个表格中。
  • 从多边形最高点开始,以每行像素点为单位,向下扫描直到最低点。
  • 对于每个扫描线,遍历保存边信息的表格,计算出当前扫描线和各条边的交点,将这些交点按照x坐标大小排序并两两配对。
  • 对每一对交点之间的像素点进行填充。
  • 重复以上步骤,直到扫描线扫描完成。
  1. 代码
// 多边形数据结构
struct Polygon {
    int numVertices; // 多边形顶点数
    int vertices[100][2]; // 多边形顶点坐标
};

// 边数据结构
struct Edge {
    double x; // 边与扫描线的交点x坐标
    double slope; // 边斜率倒数
    int ymax; // 边在扫描线之上的端点y坐标
};

// 填充多边形
void FillPolygon(Polygon poly) {
    // 计算多边形顶点中的最大和最小y坐标
    int maxY = INT_MIN, minY = INT_MAX;
    for (int i = 0; i < poly.numVertices; i++) {
        if (poly.vertices[i][1] > maxY) {
            maxY = poly.vertices[i][1];
        }
        if (poly.vertices[i][1] < minY) {
            minY = poly.vertices[i][1];
        }
    }

    // 创建边表,存储所有的边信息
    vector<Edge> edgeTable;
    for (int i = 0; i < poly.numVertices; i++) {
        Edge e;
        // 获取当前边和下一个顶点的坐标
        int x1 = poly.vertices[i][0], y1 = poly.vertices[i][1];
        int x2 = poly.vertices[(i + 1) % poly.numVertices][0], y2 = poly.vertices[(i + 1) % poly.numVertices][1];

        // 如果y1 == y2,说明该边不需要加入边表
        if (y1 == y2) {
            continue;
        }

        // 如果y2 < y1,则交换两个顶点的坐标
        if (y2 < y1) {
            swap(x1, x2);
            swap(y1, y2);
        }

        // 计算出边与扫描线的交点x坐标和斜率倒数
        e.x = x1;
        e.slope = (double)(x2 - x1) / (y2 - y1);
        e.ymax = y2 - 1;

        // 将边加入边表中
        edgeTable.push_back(e);
    }

    // 对边表按照交点x坐标排序
    sort(edgeTable.begin(), edgeTable.end(), [](const Edge& a, const Edge& b) { return a.x < b.x; });

    // 创建活动边表,存储所有与当前扫描线有交点的边信息
    vector<Edge> activeEdgeTable;

    // 从多边形最高点开始,逐行扫描
    for (int y = maxY; y >= minY; y--) {
        // 将与当前扫描线有交点的边加入活动边表中
        for (int i = 0; i < edgeTable.size(); i++) {
            if (edgeTable[i].ymax >= y) {
                activeEdgeTable.push_back(edgeTable[i]);
            }
        }

        // 按照交点x坐标排序
        sort(activeEdgeTable.begin(), activeEdgeTable.end(), [](const Edge& a, const Edge& b) { return a.x < b.x; });

        // 填充扫描线
        int x1 = INT_MAX, x2 = INT_MIN;
        for (int i = 0; i < activeEdgeTable.size(); i += 2) {
            x1 = (int)ceil(activeEdgeTable[i].x);
            x2 = (int)floor(activeEdgeTable[i + 1].x);

            // 如果是偶数条边,则说明有完整的矩形区域需要填充
            if (i + 1 < activeEdgeTable.size()) {
                for (int x = x1; x <= x2; x++) {
                    SetPixel(x, y);
                }
            }
        }

        // 更新活动边表
        for (int i = 0; i < activeEdgeTable.size(); i++) {
            activeEdgeTable[i].x += activeEdgeTable[i].slope;
            activeEdgeTable[i].ymax--;
        }

        // 从活动边表中移除不再与扫描线相交的边
        activeEdgeTable.erase(remove_if(activeEdgeTable.begin(), activeEdgeTable.end(), [](const Edge& a) { return a.ymax <= 0; }), activeEdgeTable.end());
    }
}


五、实验结果

  1. 扫描填充算法运行结果

六、结论

本实验是通过扫描线算法来实现多边形的填充。首先定义了多边形和边的数据结构,并且根据多边形的顶点信息计算出每条边的斜率和截距等信息,存储在一个表格中。然后从多边形最高点开始,以每行像素点为单位,向下扫描直到最低点。对于每个扫描线,遍历保存边信息的表格,计算出当前扫描线和各条边的交点,将这些交点按照x坐标大小排序并两两配对,然后对每一对交点之间的像素点进行填充。最后重复以上步骤,直到扫描线扫描完成。这种算法的优势在于可以处理任意形状的多边形,而不仅限于凸多边形。算法的时间复杂度为O(nlogn),其中n为多边形的边数。本次实验的结果是成功实现了多边形的填充。

相关文章
|
1月前
|
算法 搜索推荐 Java
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
这篇文章介绍了如何使用Java后端技术,结合Graphics2D和Echarts等工具,生成包含个性化信息和图表的海报,并提供了详细的代码实现和GitHub项目链接。
104 0
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
|
1月前
|
算法
计科一二班算法数据结构实验9答案
计科一二班算法数据结构实验9答案
14 0
|
3月前
|
算法 Java 测试技术
算法分析(蛮力法与减治算法应用实验报告)
这篇文章是关于算法分析的实验报告,介绍了如何使用蛮力法解决背包问题,并通过伪代码和Java代码实现,同时分析了其时间效率;还介绍了基于减治法思想实现的二叉查找树的插入与查找,同样提供了伪代码、Java源代码实现和时间效率分析,最后展示了测试结果截图。
算法分析(蛮力法与减治算法应用实验报告)
|
3月前
|
机器学习/深度学习 算法 Java
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
这篇文章介绍了基于贪婪技术思想的Prim算法和Dijkstra算法,包括它们的伪代码描述、Java源代码实现、时间效率分析,并展示了算法的测试用例结果,使读者对贪婪技术及其应用有了更深入的理解。
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
|
3月前
|
算法 Java 测试技术
算法设计(动态规划实验报告) 基于动态规划的背包问题、Warshall算法和Floyd算法
这篇文章介绍了基于动态规划法的三种算法:解决背包问题的递归和自底向上实现、Warshall算法和Floyd算法,并提供了它们的伪代码、Java源代码实现以及时间效率分析。
算法设计(动态规划实验报告) 基于动态规划的背包问题、Warshall算法和Floyd算法
|
3月前
|
算法 搜索推荐
算法设计 (分治法应用实验报告)基于分治法的合并排序、快速排序、最近对问题
这篇文章是关于分治法应用的实验报告,详细介绍了如何利用分治法实现合并排序和快速排序算法,并探讨了使用分治法解决二维平面上的最近对问题的方法,包括伪代码、源代码实现及时间效率分析,并附有运行结果和小结。
多边形扫描转换-扫描线算法
多边形扫描转换-扫描线算法
|
6月前
|
算法 图形学
【计算机图形学】实验三 用Cohen-Sutherland裁剪算法实现直线段裁剪
【计算机图形学】实验三 用Cohen-Sutherland裁剪算法实现直线段裁剪
441 2
|
24天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
|
9天前
|
算法 数据挖掘 数据安全/隐私保护
基于FCM模糊聚类算法的图像分割matlab仿真
本项目展示了基于模糊C均值(FCM)算法的图像分割技术。算法运行效果良好,无水印。使用MATLAB 2022a开发,提供完整代码及中文注释,附带操作步骤视频。FCM算法通过隶属度矩阵和聚类中心矩阵实现图像分割,适用于灰度和彩色图像,广泛应用于医学影像、遥感图像等领域。