MFC三角形三个顶点为红、绿、蓝,使用有效边表算法进行填充完整代码
时间: 2023-07-14 19:11:50 浏览: 132
以下是使用有效边表算法进行三角形填充的 MFC 代码:
```
void CMFCTrianglesView::OnDraw(CDC* pDC)
{
CMFCTrianglesDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// 设置三角形三个顶点的坐标和颜色
CPoint v1(100, 100);
CPoint v2(200, 200);
CPoint v3(300, 100);
COLORREF c1 = RGB(255, 0, 0);
COLORREF c2 = RGB(0, 255, 0);
COLORREF c3 = RGB(0, 0, 255);
// 确定三角形的最大和最小 Y 坐标
int minY = min(v1.y, min(v2.y, v3.y));
int maxY = max(v1.y, max(v2.y, v3.y));
// 初始化有效边表
vector<EDGE> ET(maxY - minY + 1);
// 初始化活性边表
vector<EDGE> AET;
// 将三角形的边插入到有效边表中
InsertEdge(ET, v1, v2, c1, c2);
InsertEdge(ET, v2, v3, c2, c3);
InsertEdge(ET, v3, v1, c3, c1);
// 从上往下扫描每一行像素
for (int y = minY; y <= maxY; y++)
{
// 将有效边表中的边插入到活性边表中
for (int i = 0; i < ET[y - minY].size(); i++)
{
AET.push_back(ET[y - minY][i]);
}
// 对活性边表按照 X 坐标排序
sort(AET.begin(), AET.end(), CompareEdgeX);
// 填充当前行像素的颜色
for (int i = 0; i < AET.size() - 1; i += 2)
{
int x1 = AET[i].x;
int x2 = AET[i + 1].x;
COLORREF c1 = AET[i].color;
COLORREF c2 = AET[i + 1].color;
for (int x = x1; x <= x2; x++)
{
pDC->SetPixel(x, y, MixColor(c1, c2, x - x1, x2 - x));
}
}
// 从活性边表中删除 Y 坐标等于当前行的边
for (int i = 0; i < AET.size(); i++)
{
if (AET[i].y == y)
{
AET.erase(AET.begin() + i);
i--;
}
}
// 更新活性边表中每条边的 X 坐标和 Y 坐标
for (int i = 0; i < AET.size(); i++)
{
AET[i].x += AET[i].dx;
AET[i].y += 1;
}
}
}
// 将一条线段插入到有效边表中
void CMFCTrianglesView::InsertEdge(vector<EDGE>& ET, CPoint v1, CPoint v2, COLORREF c1, COLORREF c2)
{
// 确定线段的最大和最小 Y 坐标
int minY = min(v1.y, v2.y);
int maxY = max(v1.y, v2.y);
// 计算线段的斜率和 X 增量
float dx = (float)(v2.x - v1.x) / (float)(v2.y - v1.y);
// 将线段插入到有效边表中
EDGE edge;
edge.y = minY;
edge.x = v1.x + dx * (minY - v1.y);
edge.dx = dx;
edge.color = c1;
while (ET[maxY - minY].size() <= maxY - minY)
{
ET[maxY - minY].push_back(EDGE());
}
ET[maxY - minY][minY - minY] = edge;
}
// 比较两条边的 X 坐标
bool CMFCTrianglesView::CompareEdgeX(EDGE edge1, EDGE edge2)
{
return edge1.x < edge2.x;
}
// 混合两种颜色
COLORREF CMFCTrianglesView::MixColor(COLORREF c1, COLORREF c2, int w1, int w2)
{
int r = (GetRValue(c1) * w2 + GetRValue(c2) * w1) / (w1 + w2);
int g = (GetGValue(c1) * w2 + GetGValue(c2) * w1) / (w1 + w2);
int b = (GetBValue(c1) * w2 + GetBValue(c2) * w1) / (w1 + w2);
return RGB(r, g, b);
}
```
其中,`EDGE` 结构体表示一条边,包含以下成员:
- `int y`:边的最小 Y 坐标;
- `float x`:边的当前 X 坐标;
- `float dx`:边的 X 增量;
- `COLORREF color`:边的颜色。
`InsertEdge` 函数将一条线段插入到有效边表中,该函数的参数包括三角形的两个顶点、两个顶点的颜色,以及有效边表 `ET`。该函数首先计算线段的最大和最小 Y 坐标,然后计算线段的斜率和 X 增量,并将线段插入到有效边表中。
`CompareEdgeX` 函数比较两条边的 X 坐标,用于对活性边表进行排序。
`MixColor` 函数混合两种颜色,用于在填充像素时计算每个像素的颜色。
在 `OnDraw` 函数中,首先设置三角形三个顶点的坐标和颜色,然后确定三角形的最大和最小 Y 坐标。接下来,初始化有效边表和活性边表,并将三角形的边插入到有效边表中。然后从上往下扫描每一行像素,将有效边表中的边插入到活性边表中,并按照 X 坐标排序。然后填充当前行像素的颜色,从活性边表中删除 Y 坐标等于当前行的边,并更新活性边表中每条边的 X 坐标和 Y 坐标。最终得到填充后的三角形。
相关推荐
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)