填充三角形算法
Filling a Triangle Algorithm
我目前正在尝试完成一个填充绘制三角形的算法。我一直在这样做的方法是遍历形状并绘制单线。我有一个几乎完美的算法,除了一个小问题。当我有水平面时,填充失败。
这是我目前的填充算法。我应该注意,称为 origin、coor2 和 coor3 的多维数组表示为我的三角形的顶点(origin[0][0] = x of origin, origin[ 0][1 ]= y of origin)。坐标是典型的窗口,(0,0) 位于左上角。此外,gc 只是我需要在窗口中绘制的内容。
void triangle::drawFilled(GraphicsContext* gc)
{
// color
gc->setColor(colorRGB);
// algorithm variables
double ax = origin[0][0];
double bx = coor2[0][0];
double cx = coor3[0][0];
double ay = origin[1][0];
double by = coor2[1][0];
double cy = coor3[1][0];
// sort vertices by y
if (ay > by)
{
std::swap(ay, by);
std::swap(ax, bx);
}
if (ay > cy)
{
std::swap(ay, cy);
std::swap(ax, cx);
}
if (by > cy)
{
std::swap(by, cy);
std::swap(bx, cx);
}
// define more algorithm variables
double dx1 = (cx-ax)/(cy-ay);
double dx2 = (bx-ax)/(by-ay);
double dx3 = (cx-bx)/(cy-by);
double x1 = ax;
double x2 = ax;
// loop through coordinates
for(int y = ay; y < by; y++)
{
gc->drawLine(x1,y,x2,y);
x1 += dx1;
x2 += dx2;
}
// loop through coordinates
for(int y = by; y < cy; y++)
{
gc->drawLine(x1,y,x2,y);
x1 += dx1;
x2 += dx3;
}
}
这是没有水平边时的结果示例
这是当有一个水平面时
请注意轮廓和填充如何不对齐。
我意识到问题可能在于 y 顶点的排序,因此不考虑 x。我可以蛮力处理水平和垂直边缘的所有情况,但这似乎效率很低。我宁愿学习如何解决我的困境,而不是试图解决它。
问题是您的代码取决于第一个循环设置的副作用,x2
bx
。 当dx2
是无穷大时,无论如何都行不通,甚至不尝试。
因此,在第一个循环之后,只需设置x2=bx;
大多数时候,额外的步骤是多余的,但它是微不足道的,当顶部是水平的时,它是必要的。
我相信你不再需要这个,但你的问题相对简单。 对于三角形顶部平坦而底部平坦的条件,您需要条件语句
if(TopIsFlat){
}else if(BottomIsFlat){
}else{
pre existing code
}
对于顶部和底部,您必须弄清楚您将从哪个 X 坐标开始。 并在必要时交换 如果您交换,您还必须切换斜坡。
还要打印点之间的坡度,以确保坡度正确;
使用结构的示例
struct Vector2D{
int x, y,
}
struct Triangle{
Vector2D p[3];
}
void Fill(Triangle ySwap){
if(ySwap.p[0].y > ySwap.p[1].y) std::swap(ySwap.p[0], ySwap.p[1]);
if(ySwap.p[1].y > ySwap.p[2].y) std::swap(ySwap.p[1], ySwap.p[2]);
if(ySwap.p[0].y > ySwap.p[1].y) std::swap(ySwap.p[0], ySwap.p[1]);
float slope1 = ((float)(ySwap.p[1].x-ySwap.p[0].x)/(ySwap.p[1].y-ySwap.p[0].y));
float slope2 = ((float)(ySwap.p[2].x-ySwap.p[1].x)/(ySwap.p[2].y-ySwap.p[1].y));
float slope3 = ((float)(ySwap.p[2].x-ySwap.p[0].x)/(ySwap.p[2].y-ySwap.p[0].y));
float x1; float x2;
if(ySwap.p[0].y == ySwap.p[1].y){
if(ySwap.p[1].x > ySwap.p[0].x){
x1 = ySwap.p[0].x;
x2 = ySwap.p[1].x;
}else{
x1 = ySwap.p[1].x;
x2 = ySwap.p[0].x;
std::swap(slope2, slope3);
}
for(int y = ySwap.p[0].y; y < ySwap.p[2].y; y++){
DrawLine(x1, y, x2, y, 'T');
x1 += slope3;
x2 += slope2;
}
}else if(ySwap.p[1].y == ySwap.p[2].y){
if(ySwap.p[2].x > ySwap.p[1].x){
x1 = ySwap.p[0].x;
x2 = ySwap.p[2].x;
}else{
x1 = ySwap.p[2].x;
x2 = ySwap.p[0].x;
std::swap(slope1, slope3);
}
for(int y = ySwap.p[0].y; y < ySwap.p[2].y; y++){
DrawLine(x1, y, x2, y, 'B');
x1 += slope3;
x2 += slope1;
}
}else{
x1 = ySwap.p[0].x;
x2 = ySwap.p[0].x;
for(int y = ySwap.p[0].y ; y < ySwap.p[1].y; y++){
DrawLine(x1, y, x2, y, '+');
x1 += slope3;
x2 += slope1;
}
for(int y = ySwap.p[1].y; y < ySwap.p[2].y; y++){
DrawLine(x1, y, x2, y, '-');
x1 += slope3;
x2 += slope2;
}
}
screen[ySwap.p[0].x][ySwap.p[0].y] = '*';
screen[ySwap.p[1].x][ySwap.p[1].y] = '*';
screen[ySwap.p[2].x][ySwap.p[2].y] = '*';
DrawTriangle(ySwap.p[0].x, ySwap.p[0].y, ySwap.p[1].x, ySwap.p[1].y, ySwap.p[2].x, ySwap.p[2].y, '*');
}
您的代码实际上允许我完成我的三角形绘制函数,该函数有一些错误,这应该可以更好地工作,并且此代码将允许您看到每个角边缘和不同的三角形拆分,尽管您必须将其连接到您自己的线条绘制函数以及打印的字符数组。
相关文章:
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 基于ELO的团队匹配算法
- C++选择排序算法中的逻辑错误
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- C++A*算法并不总是在路径中具有目标节点
- 排序算法c++
- 绘制旋转的三角形
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 算法问题:查找从堆栈中弹出的所有序列
- 下面是排序算法O(n)吗
- KMP算法和LPS表构造的运行时间
- 如何用for循环在c++中生成单词三角形
- 为什么我的排序算法会更改数组值
- 如何累积三维三角形网格的边?用c语言计算网格边的算法
- 确定给定数字 N 是否可以成为具有所有 3 个积分边的直角三角形的斜边的算法
- 填充三角形算法
- 将连通三角形分组的C++算法
- 路径笔画算法(转换为三角形/四边形)或其他建议
- C++:查找直角三角形算法没有得到预期的结果
- 使用 kinect 从点云生成三角形网格的算法