最小闭环工程是指新建一个工程,保留能够复现问题的最少的代码,删除其他无关的因素,从而找到问题原因。
这是本次使用的最小工程,它只包括了tgaimage库函数(用于输出图片)、扫描线算法scanline 、两点画直线算法line_rough 和 一个main函数。
#include <vector>
#include "tgaimage.h"
#include <iostream>
using namespace std;
void line_rough(int x0, int y0, int x1, int y1, TGAImage& image, TGAColor& color){
int d_x = x1 - x0;
int d_y = y1 - y0;
float X, Y;
for (float q = 0.; q < 1; q += 0.01){
X = x0 + q * d_x;
Y = y0 + q * d_y;
image.set(X, Y, color);
}
}
float k_p0p2, b_p0p2, k_p0p1, b_p0p1, k_p1p2, b_p1p2;
int i, j;
#define UNEXIST -99999
void scanline(int p0[2], int p1[2], int p2[2], TGAImage& image, TGAColor color){
if (p1[1] > p0[1]) swap(p1, p0);
if (p2[1] > p0[1]) swap(p2, p0);
if (p2[1] > p1[1]) swap(p2, p1);
// 若p0p1在同一条垂直线
if (p0[0] == p1[0])
{
cout << "fmxs:p0p1是一条垂直线!" << endl;
k_p0p1 = UNEXIST;
b_p0p1 = UNEXIST;
}
else
{
k_p0p1 = 1.0 * (p0[1] - p1[1]) / (p0[0] - p1[0]);
b_p0p1 = p0[1] - k_p0p1 * p0[0];
}
k_p0p2 = 1.0 * (p0[1] - p2[1]) / (p0[0] - p2[0]);
b_p0p2 = p2[1] - k_p0p2 * p2[0];
k_p1p2 = 1.0 * (p1[1] - p2[1]) / (p1[0] - p2[0]);
b_p1p2 = p1[1] - k_p1p2 * p1[0];
vector<vector<float>> memo1, memo2;
if (k_p0p1 == UNEXIST) {
for (int Y = p0[1]; Y >= p1[1]; --Y) {
memo1.push_back({ 1.0f * p0[0] , 1.0f * Y });
}
}
else
{
for (int Y = p0[1]; Y >= p1[1]; --Y) {
memo1.push_back({ (Y - b_p0p1) / k_p0p1 , (Y - b_p0p2) / k_p0p2 });
}
}
i = 0;
for (int Y = p0[1]; Y >= p1[1]; --Y){
line_rough(memo1[i][0], Y, memo1[i][1], Y, image, color);
i++;
}
for (int Y = p1[1]; Y >= p2[1]; --Y){
memo2.push_back({ (Y - b_p1p2) / k_p1p2 , (Y - b_p0p2) / k_p0p2 });
}
j = 0;
for (int Y = p1[1]; Y >= p2[1]; --Y){
line_rough(memo2[j][0], Y, memo2[j][1], Y, image, color);
j++;
}
}
int main(){
TGAImage image(800, 800, TGAImage::RGB);
TGAColor red = TGAColor(255, 0, 0, 1);
TGAColor green = TGAColor(0, 255, 0, 1);
// Define a right triangle to determine if the algorithm can draw it
int p0[2] = { 0,0 }, p1[2] = { 0,300 }, p2[2] = { 300, 0 };
// Define a common triangle to determine if the algorithm can draw it
int p3[2] = { 300,90 }, p4[2] = { 400,50 }, p5[2] = { 500,60 };
scanline(p0, p1, p2, image, red);
scanline(p3, p4, p5, image, green);
image.write_tga_file("testRightTriangle.tga");
return 0;
}
上面代码的main函数中绘制了两个三角形,第一个为直角三角形,其直角边是一条垂直线;第二个为一个普通的三角形。
在输出图片后发现第一个三角形(红色)没有绘制,第二个三角形(绿色)绘制出了。

由此可以确定扫描线算法缺少了一个特殊情况的判断:垂直线。我们便可以根据此思路去优化代码。
本最小闭环工程的更多信息请看: