多边形扫描转换-扫描线算法

简介: 多边形扫描转换-扫描线算法
#include <graphics.h>
#include <vector>
#include <algorithm>
#include<iostream>
using namespace std;
 
struct EdgeNode {
    int ymin;  // 边的最小y坐标
    double x;  // 当前x坐标
    double dx; // △x
    int ymax;  // 边的最大y坐标
};
 
void polygon_fill(vector<vector<int>>& polygon) {//i*2矩阵
    int y_min = INT_MAX;
    int y_max = INT_MIN;
 
    // 找到多边形的最小和最大y坐标
    for (const auto& point : polygon) {
        y_min = min(y_min, point[1]);
        y_max = max(y_max, point[1]);
    }
 
    vector<vector<EdgeNode>> NET(y_max + 1); 
 
    // 构造NET
    for (int i = 0; i < polygon.size(); i++) {
        int next_idx = (i + 1) % polygon.size();
        int x1 = polygon[i][0];
        int y1 = polygon[i][1];
        int x2 = polygon[next_idx][0];
        int y2 = polygon[next_idx][1];
 
        int ymin = min(y1, y2);
        int ymax = max(y1, y2);
        double dx = (double)(x2 - x1) / (y2 - y1);// △x
 
        if (ymax != ymin) {
            if (ymin == y1) {
                NET[ymin].push_back({ ymin, (double) (x1), dx, ymax });
            }
            else if (ymin == y2) {
                NET[ymin].push_back({ ymin, (double)(x2), dx, ymax });
            }
        }
    }
 
    vector<EdgeNode> AET; 
    //int ynow = y_min; // 当前扫描线号
 
    for (int i = y_min; i <= y_max; i++) { // 对每一条扫描线
        for (auto& edge : NET[i]) { // 把ymin=i的边放入AET
            if (edge.ymin == i) {
                AET.push_back(edge);
            }
        }
    }
    for (int i = y_min; i <= y_max; i++) { // 对每一条扫描线
        // 使用插入排序法对AET按x坐标递增顺序排序
        for (int j = 1; j < AET.size(); j++) {
            int k = j - 1;
            EdgeNode key = AET[j];
            while (k >= 0 && AET[k].x > key.x) {
                AET[k + 1] = AET[k];
                k--;
            }
 
            AET[k + 1] = key;
        }
 
        // 若允许多边形的边自交,用冒泡排序法对AET重新排序
        for (int j = 0; j < AET.size() - 1; j++) {
            for (int k = 0; k < AET.size() - j - 1; k++) {
                if (AET[k].x > AET[k + 1].x) {
                    swap(AET[k], AET[k + 1]);
                }
            }
        }
        // 遍历AET,找到配对的交点并填色
        for (int j = 0; j < AET.size(); j += 2) {
            int x_start = (int)(ceil(AET[j].x));
            int x_end = (int)(ceil(AET[j + 1].x));
 
            for (int x = x_start; x < x_end; x++) {
                putpixel(x, i, WHITE);
            }
        }
 
        // 遍历AET,更新x值,删除ymax=i的边
        vector<EdgeNode> new_AET;
        for (const auto& edge : AET) {
            if (edge.ymax > i) {
                EdgeNode new_edge = edge;
                new_edge.x += new_edge.dx;
                new_AET.push_back(new_edge);
            }
        }
        AET = new_AET;
    }
}
 
int main() {
    initgraph(800, 480);
 
    vector<vector<int>> polygon = { {100,200}, {200,200}, {150,150} };//三角形
    polygon_fill(polygon);
 
   polygon = { {300,150},{300,200}, {500,200 },{500,150}};//矩形
    polygon_fill(polygon);
 
    polygon = { {600,150}, {630,200 },{600,200},{630,150} };//漏斗形
    polygon_fill(polygon);
    system("pause");
    closegraph();
    return 0;
}

运行结果:

0c2c69361516421a90e526c91a3b2392.jpg

相关文章
|
算法 测试技术 Android开发
LeetCode 周赛上分之旅 #45 精妙的 O(lgn) 扫描算法与树上 DP 问题
学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场 LeetCode 周赛的解题报告,一起体会上分之旅。
215 2
LeetCode 周赛上分之旅 #45 精妙的 O(lgn) 扫描算法与树上 DP 问题
|
11月前
|
监控 网络协议 算法
基于问题“如何监控局域网内的电脑”——Node.js 的 ARP 扫描算法实现局域网内计算机监控的技术探究
在网络管理与安全领域,监控局域网内计算机至关重要。本文探讨基于Node.js的ARP扫描算法,通过获取IP和MAC地址实现有效监控。使用`arp`库安装(`npm install arp`)并编写代码,可定期扫描并对比设备列表,判断设备上线和下线状态。此技术适用于企业网络管理和家庭网络安全防护,未来有望进一步提升效率与准确性。
425 8
|
算法 图形学
【头歌 计算机图形学 练习】多边形填充v1.0 (第1关:扫描线填充算法(活动边表AET法) 第2关:边缘填充法 第3关:区域四连通种子填充算法 第4关:区域扫描线种子填充算法)
【头歌 计算机图形学 练习】多边形填充v1.0 (第1关:扫描线填充算法(活动边表AET法) 第2关:边缘填充法 第3关:区域四连通种子填充算法 第4关:区域扫描线种子填充算法)
867 0
|
存储 算法 图形学
【计算机图形学】实验二 用扫描线算法实现多边形填充
【计算机图形学】实验二 用扫描线算法实现多边形填充
1079 2
|
存储 算法 Java
基于Y向连贯性算法的多边形扫描线生成(适用于凸多边形和凹多边形)【原理+java实现】
基于Y向连贯性算法的多边形扫描线生成(适用于凸多边形和凹多边形)【原理+java实现】
426 0
|
算法 索引
连通不规则多边形算法
多边形连通和最小生成树本质上是一样的,问题在于确定权值。 下面算法由js实现,演示由svg提供。 let shown='hidden'; //核心算法 let caculatePath=function(){ ...
1232 0
|
算法 索引
一种求任意多边形内部水平方向似最大矩形的算法
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景        在前一篇中,我们探讨了如何求凸多边形中的似最大圆,但是针对实际情况需求,我们并没有完全解决问题。
3141 0