计算机图形学实验二
//定义span的起点与终点数组
SpanLeft = new CPoint2[nTotalScanLine];//跨度左边数组
SpanRight = new CPoint2[nTotalScanLine];//跨度右边数组
//判断三角形与P0P1边的位置关系,0-1-2为右手系
int nDeltz = (point1.x - point0.x) * (point2.y - point1.y) - (point1.y - point0.y) * (point2.x - point1.x);//点矢量叉积的z坐标
void CTriangle::Draw(CDC* pDC)//画出来一个三角形
{
pDC->MoveTo(point0.x,point0.y);
pDC->LineTo(point1.x,point1.y);
pDC->LineTo(point2.x,point2.y);
pDC->LineTo(point0.x,point0.y);
Arrow=FALSE;
Flag=TRUE;
Number=0;
MState=FALSE;
if(FALSE==Attach)
{
CClientDC dc(this);
Picture.CreateCompatibleDC(&dc);
MessageBox("请使用鼠标在屏幕上绘制多边形","提示", MB_ICONINFORMATION);
BOOL bInterChange = FALSE;//bInterChange为假,主位移方向为x方向
int e, s1, s2, temp;
s1 = (PEnd.x > PStart.x) ? 1 :((PEnd.x < PStart.x) ? -1 : 0);
s2 = (PEnd.y > PStart.y) ? 1 :((PEnd.y < PStart.y) ? -1 : 0);
}
}
Invalidate(FALSE);
CView::OnMouseMove(nFlags, point);
}
void CTestView::OnRButtonDown(UINT nFlags, CPoint point)//右键按下函数
{
// TODO: Add your message handler code here and/or call default
课程名称
班级
实验日期
姓 名
学号
实验成绩
实验名称
交互式绘制多边形
实 验 目 的
利用有效边表填充算法,编程实现多边形的填充。
实
验
环
境
VisualStudio2010
实
验
内
容
基本要求:
1. 了解有效边表和边表的数据结构;
2. 掌握边界像素的处理原则;
3. 掌握动态链表排序算法;
4. 使用鼠标绘制多边形,右键实现多边形的填充;
FColor=ccd.GetColor();
CPoint BPoint,EPoint;//边的起点和终点
long MaxX=p[0].x;//多边形的x坐标最大值
for(long Num=0;Num<Number;Num++)//求多边形的最大x值
{
BPoint.x=p[Num].x;
EPoint.x=p[(Num+1)%Number].x;
{
// TODO: Add your command handler code here
COLORREF FColor;//填充颜色
CColorDialog ccd(RGB(0,0,255));
if(ccd.DoModal()==IDOK)
{
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT));
}
void CTriangle::GouraudShader(CDC* pDC)
{
SortVertex();//point0点为y坐标最小的点,point1点为y坐标最大的点,point2点的y坐标位于二者之间。如果y值相同,取x最小的点
//定义三角形覆盖的扫描线条数
int nTotalScanLine = point1.y - point0.y + 1;
{
int n = y - point0.y;
for(int x = SpanLeft[n].x; x < SpanRight[n].x; x++)//左闭右开
{
clr = LinearInterp(x, SpanLeft[n].x, SpanRight[n].x, SpanLeft[n].c, SpanRight[n].c);
pDC->SetPixelV(x, y, RGB(clr.red * 255, clr.green * 255, clr.blue * 255));
}
}
if(SpanLeft)
{
delete []SpanLeft;
SpanLeft = NULL;
}
if(SpanRight)
{
delete []SpanRight;
EPoint.x=p[(Num+1)%Number].x,EPoint.y=p[(Num+1)%Number].y;
if(BPoint.y>EPoint.y)//确保起点的y值小于终点的y值
{
CPoint t;//临时对象
t=BPoint;
BPoint=EPoint;
EPoint=t;
}
double k=double(BPoint.x-EPoint.x)/(BPoint.y-EPoint.y);//计算1/k
for(long y=BPoint.y;y<EPoint.y;y++)//边缘填充算法
{
long x=ROUND(double(BPoint.x)+(double(y)-double(BPoint.y))*k);//处理一条边上各个点的x起始坐标
for(;x<MaxX;x++)
{
if(Picture.GetPixel(x,y)==FColor)
if(nDeltz > 0)//三角形位于P0P1边的左侧
{
nIndex = 0;
DDA(point0, point2, TRUE);
DDA(point2, point1, TRUE);
nIndex = 0;
DDA(point0, point1, FALSE);
}
else//三角形位于P0P1边的右侧
{
// TODO: Add your message handler code here and/or call default
if(Arrow)
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
else
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS));
SpanRight = NULL;
}
//}
}
void CTriangle::DDA(CPoint2 PStart, CPoint2 PEnd, BOOL bFeature)
{
CRGBA crColor = PStart.c;
int dx = abs(PEnd.x - PStart.x);
int dy = abs(PEnd.y - PStart.y);
实验拓展:绘制颜色渐变的三角形和四边形。
实
验
步
骤
问题分析和算法描述:
有效边表填充算法通过维护边表和有效边表,避开了扫描线与多边形所有边求交的复杂运算。填充原理是按照扫描线从小到大的移动顺序,计算当前扫描线与有效边的交点,然后把这些交点按x值递增的顺序进行排序、配对,以确定填充区间,最后用指定颜色填充区间内的所有像素,即完成填充工作。
if(Flag==TRUE)
{பைடு நூலகம்
if(Number<50)
{
LBDown=TRUE;
p[Number]=point;
if(!Number)
{
Number++;
}
Number++;
}
}
CView::OnLButtonDown(nFlags, point);
}
void CTestView::OnMouseMove(UINT nFlags, CPoint point)//鼠标移动函数
Arrow=TRUE;
LBDown=FALSE;
Flag=FALSE;
MState=TRUE;
CTestView::OnMENUFillPolygon();
CView::OnRButtonDown(nFlags, point);
}
(2)填充函数
void CTestView::OnMENUFillPolygon()//填充菜单操作函数
if(pStatus)
{
Str.Format("%d,%d",point.x,point.y);
pStatus->SetPaneText(2,Str);//状态栏显示鼠标光标位置值
}
if(LBDown)
{
p[Number-1]=point;
if(nFlags==MK_SHIFT)//约束:测试按下了Shift键