#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;
}
运行结果: