NEFU图形学课程实验

大二选修课计算机图形学
课程实验代码


实验一:直线、圆、椭圆的生成

实验目的:掌握基本图形的生成算法,包括直线段、圆、椭圆的扫描转换

实验原理: 直线段、圆、椭圆生成算法的基本原理。

1.直线段的生成

//直线段的生成:分别根据DDA画线法、中点画线法、Bresenham画线法的基本原理,编写绘制直线段的应用程序,并运行演示。
void DDALine (int x1, int y1, int x2, int y2, int color, CDC* pDC)
{
    
    
	int x;
	float k, y=y1;
	k=1.0*(y2-y1)/(x2-x1);
	for(x=x1; x<=x2; x++)
	{
    
    	pDC->SetPixel(x, (int)(y+0.5), color);
		y=y+k;	
	}
}


void MPLine (int x1, int y1, int x2, int y2, int color, CDC* pDC)
{
    
    
	int x, y, a,b, d, d1, d2;
	a=y1-y2;
	b=x2-x1;
	y=y1;
	d=2*a+b;
	d1=2*a;
	d2=2*(a+b);
	
	for(x=x1;x<=x2;x++)
	{
    
    
		pDC->SetPixel(x,y,color);
		if(d<0){
    
    
			y++; d+=d2;}
		else{
    
    d+=d1;}
		pDC->SetPixel(x,y,color);
	}
}

void BHLine (int x1, int y1, int x2, int y2, int color, CDC* pDC)
{
    
    
	int x,y,dx,dy,dk;
	dx=x2-x1;dy=y2-y1;
	dk=2*dy-dx; y=y1;
	for(x=x1;x<=x2;x++)
	{
    
    
		pDC->SetPixel(x,y,color);
			dk=dk+2*dy;
		if(dk>=0)
		{
    
    y++;dk=dk-2*dx;}
	}
}
void CCircleView::OnDraw(CDC* pDC)
{
    
    
	CCircleDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	int x1=100, y1=100, x2=600, y2=200, color=RGB(0,0,255);
		DDALine(x1,y1,x2,y2,color,pDC);
		MPLine(x1,y1,x2,y2+150,color,pDC);
		BHLine(x1,y1,x2,y2+300,color,pDC);
}

在这里插入图片描述

2.圆的生成

//在这里根据中点画圆算法的基本原理,编写绘制圆的应用程序,并运行演示。
void wholeCircle(int xc,int yc,int x,int y,int color,CDC* pDC)
{
    
    
	pDC->SetPixel(xc+x,yc+y,color);pDC->SetPixel(xc-x,yc+y,color);
	pDC->SetPixel(xc+x,yc-y,color);pDC->SetPixel(xc-x,yc-y,color);
	pDC->SetPixel(xc+y,yc+x,color);pDC->SetPixel(xc-y,yc+x,color);
	pDC->SetPixel(xc+y,yc-x,color);pDC->SetPixel(xc-y,yc-x,color);
}


void MidpointCircle(int xc, int yc, int r,int color,CDC* pDC)
{
    
    
		int x=0,y=r,d=1-r;
		wholeCircle(xc,yc,x,y,color,pDC);
		while(x<=y)
		{
    
    
			if(d<0){
    
    d+=2*x+3;x++;}
			else {
    
    d+=2*(x-y)+5;x++;y--;}
			wholeCircle(xc,yc,x,y,color,pDC);

		}
}
void CCircleView::OnDraw(CDC* pDC)
{
    
    
	CCircleDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
		int x0=300, y0=200, r=150, color=RGB(255,0,0);
	MidpointCircle(x0,y0,r,color,pDC);
}

在这里插入图片描述

3、椭圆的生成

//根据中点画椭圆算法的基本原理,编写绘制椭圆的应用程序,并运行演示。
void WholeEllipse(int xc, int yc, int x, int y,int color, CDC* pDC)
{
    
    
	pDC->SetPixel(xc + x, yc + y, color);
	pDC->SetPixel(xc - x, yc + y, color);
	pDC->SetPixel(xc + x, yc - y, color);
	pDC->SetPixel(xc - x, yc - y, color);
}

void MPEllipse(int xc, int yc, int a, int b, int color, CDC* pDC)
{
    
    
	int aa = a * a, bb = b * b;
	int x = 0, y = b;
	int d = (int)(bb + aa * (-b + 0.25) + 0.5);
	WholeEllipse(xc, yc, x, y, color, pDC);
	while(bb * x < aa * y)
	{
    
    
		if(d < 0)
		{
    
    
			d += bb * (2 * x + 3);
		}
		else
		{
    
    
			d += bb * (2 * x + 3) + aa * (-2 * y + 2);
			y --;
		}
		x ++;
		WholeEllipse(xc, yc, x, y, color, pDC);
	}
	d = (int)(bb * (x + 0.5) * (x + 0.5) + aa * (y - 1) * (y - 1) - aa * bb + 0.5);
	while(y > 0)
	{
    
    
		if(d > 0)
		{
    
    
			d += aa * (-2 * y + 3);
		}
		else
		{
    
    
			d += bb * (2 * x + 2) + aa * (-2 * y + 3);
			x ++;
		}
		y --;
		WholeEllipse(xc, yc, x, y, color, pDC);
	}
}

void CTestOneView::OnDraw(CDC* pDC)
{
    
    
	CTestOneDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	int xc = 500, yc = 320, x1, x2, y1, a = 120, b = 50, color = RGB(0, 0, 225);
	MPEllipse(xc - 170, yc, a, b, color, pDC);
	MPEllipse(xc + 170, yc, a, b, color, pDC);
	MPEllipse(xc, yc - 170, b, a, color, pDC);
	MPEllipse(xc, yc + 170, b, a, color, pDC);
	a = 30;
	b = 30;
	MPEllipse(xc, yc, a, b, color, pDC);
}

在这里插入图片描述

实验二:区域填充与图形裁剪

1、区域填充:


//根据种子填充算法的基本原理,编写图形填充的应用程序,并运行演示填充效果。
void boundaryfill4(int seedx,int seedy,int fcolor,int bcolor,CDC* pDC)
{
    
    
		int current = pDC->GetPixel(seedx,seedy);
		if((current !=bcolor)&&(current !=fcolor))
		{
    
    
			pDC->SetPixel(seedx,seedy,fcolor);
			boundaryfill4(seedx,seedy+1,fcolor,bcolor,pDC);
			boundaryfill4(seedx,seedy-1,fcolor,bcolor,pDC);
			boundaryfill4(seedx-1,seedy,fcolor,bcolor,pDC);
			boundaryfill4(seedx+1,seedy,fcolor,bcolor,pDC);
		}
}



void CMy1021View::OnDraw(CDC* pDC)
{
    
    
	CMy1021Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	int n=3,x0=150,y0=100,x1=x0+200,y1=y0;
	
	CPoint pIn[3]={
    
    CPoint(50,50),CPoint(250,80),CPoint(150,230)};
	int fcolor =RGB(0,255,0),bcolor=RGB(0,0,255);

	CPen pen1(PS_SOLID,1,bcolor);
	pDC->SelectObject(&pen1);
	pDC->Polygon(pIn,n);
	boundaryfill4(x0,y0,fcolor,bcolor,pDC);
	pDC->Ellipse(x1-60,y1-50,x1+60,y1+50);
	boundaryfill4(x1,y1,fcolor,bcolor,pDC);
}

在这里插入图片描述

2、直线段裁剪

//根据编码裁剪算法的基本原理,编写直线段裁剪的应用程序,并运行演示裁剪效果。
#define LEFT 1
#define RIGHT 2
#define BOTTOM 4
#define TOP 8

void Encode(int x,int y,int *code,int XL,int XR,int YB,int YT)
	{
    
    
		int c=0;
		if(x<XL)c=c|LEFT;
			else if(x>XR)c=c|RIGHT;
		if(y<YB)c=c|BOTTOM;
			else if(y>YT)c=c|TOP;
			(*code)=c;

	}

	void C_S_Line(POINT &p1,POINT &p2,int XL,int XR,int YB,int YT)
	{
    
    
		int x1,x2,y1,y2,x,y,code1,code2,code;
		x1=p1.x;x2=p2.x,y1=p1.y;y2=p2.y;
		Encode(x1,y1,&code1,XL,XR,YB,YT);
		Encode(x2,y2,&code2,XL,XR,YB,YT);
		while(code1!=0||code2!=0){
    
    
			if((code1&code2)!=0)return;
			code=code1;
			if(code1==0)
				code=code2;
			if((LEFT&code)!=0)
			{
    
    
				x=XL;y=y1+(y2-y1)*(XL-x1)/(x2-x1);
			}
			else if((code&RIGHT)!=0)
			{
    
    x=XR; y=y1+(y2-y1)*(XR-x1)/(x2-x1);}
			else if((code & BOTTOM)!=0)
			{
    
    y=YB; x=x1+(x2-x1)*(YB-y1)/(y2-y1);}
			else if((TOP & code)!=0)
			{
    
    	y=YT; x=x1+(x2-x1)*(YT-y1)/(y2-y1);}
			if(code==code1)
			{
    
    x1=x; y1=y; Encode(x,y,&code1,XL,XR,YB,YT);}
			else
			{
    
    x2=x; y2=y; Encode(x,y,&code2,XL,XR,YB,YT);}
		}
		p1.x=x1; p1.y=y1; p2.x= x2; p2.y=y2;
		
	}


void CMy1021View::OnDraw(CDC* pDC)
{
    
    
	CMy1021Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	int sig,XL,XR,YB,YT;
	float x1,y1,x2,y2;
	CPoint wMin(150,100),wMax(500,300),p1(50,80),p2(600,330);
	int color;
	x1=(float)p1.x;y1=p1.y;
	x2=p2.x;y2=p2.y;
	XL=wMin.x;XR=wMax.x;
	YB=wMin.y;YT=wMax.y;

	color=RGB(255,0,0);
	CPen pen1(PS_SOLID,1,color);
	pDC->SelectObject(&pen1);
	pDC->Rectangle(XL,YB,XR,YT);

	color=RGB(0,255,0);
	CPen pen2(PS_DOT,1,color);
	pDC->SelectObject(&pen2);
	pDC->MoveTo(x1,y1);
	pDC->LineTo(x2,y2);
	C_S_Line(p1,p2,XL,XR,YB,YT);

	color=RGB(0,0,255);
	CPen pen3(PS_SOLID,3,color);
	pDC->SelectObject(&pen3);
	pDC->MoveTo(p1.x,p1.y);
	pDC->LineTo(p2.x,p2.y);
	
}

在这里插入图片描述

3、多边形裁剪

//根据逐边裁剪算法的基本原理,编写多边形裁剪的应用程序,并运行演示裁剪效果。
void TestIntersect(int edge, int tyke, POINT p1, POINT p2, POINT &pout, int &yes, int &isIn, CDC* pDC)
{
    
    
	float dx, dy, m;
	isIn = 0;
	yes = 0;
	dy = p2.y - p1.y;
	dx = p2.x - p1.x;
	m = dy / dx;
	switch(tyke)
	{
    
    
	case 1:  /*right*/
		if(p2.x <= edge)
		{
    
    
			isIn = 1;
			if(p1.x > edge)
				yes = 1;
		}
		else if(p1.x <= edge)
			yes = 1;
		break;
	case 2:  /*bottom*/
		if(p2.y >= edge)
		{
    
    
			isIn = 1;
			if(p1.y < edge)
				yes = 1;
		}
		else if(p1.y >= edge)
			yes = 1;
		break;
	case 3:  /*left*/
		if(p2.x >= edge)
		{
    
    
			isIn = 1;
			if(p1.x < edge)
				yes = 1;
		}
		else if(p1.x >= edge)
			yes = 1;
		break;
	case 4:  /*top*/
		if(p2.y <= edge)
		{
    
    
			isIn = 1;
			if(p1.y > edge)
				yes = 1;
		}
		else if(p1.y <= edge)
			yes = 1;
		break;
	default: 
		break;
	}
	if(yes)
	{
    
    
		if((tyke == 1) || (tyke == 3))
		{
    
    
			pout.x = edge;
			pout.y = p1.y + m * (pout.x - p1.x);
		}
		if((tyke ==2) || (tyke == 4))
		{
    
    
			pout.y = edge;
			pout.x = p1.x + (pout.y - p1.y) / m;
		}
	}
}
void clipSingleEdge(int edge, int tyke, int nin, POINT pin[50], int &nout, POINT pout[50], CDC* pDC)
{
    
    
	int i, k = 0, yes, isIn;
	POINT p, tp, pinters;
	p.x = pin[nin - 1].x;
	p.y = pin[nin - 1].y;
	for(i = 0; i < nin; i ++)
	{
    
    
		TestIntersect(edge, tyke, p, pin[i], pinters, yes, isIn, pDC);
	    if(yes)
		{
    
    
			pout[k].x = pinters.x;
			pout[k].y = pinters.y;
			k ++;
		}
		if(isIn)
		{
    
    
			pout[k].x = pin[i].x;
			pout[k].y = pin[i].y;
			k ++;
		}
		p.x = pin[i].x;
		p.y = pin[i].y;
	}
    nout = k;
}
void ClipEdgePolygon(POINT ps[50], int &n, int XL, int XR, int YB, int YT, CDC* pDC)
{
    
    
	int n1 = 0;
	POINT pt[50];
	clipSingleEdge(XR, 1, n, ps, n1, pt, pDC);
	clipSingleEdge(YB, 2, n1, pt, n, ps, pDC);
	clipSingleEdge(XL, 3, n, ps, n1, pt, pDC);
	clipSingleEdge(YT, 4, n1, pt, n, ps, pDC);
}
void CDrjyView::OnDraw(CDC* pDC)
{
    
    
	CDrjyDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	int i, XL, XR, YB, YT, n = 3, nout = 0;
	int color;
	CPoint ply[50] = {
    
    CPoint(50, 50), CPoint(600, 250), CPoint(200, 400)};
	CPoint wMin(100, 100), wMax(500, 350);
	XL = wMin.x;
	YB = wMin.y;
	XR = wMax.x;
	YT = wMax.y;

	color = RGB(255, 0, 0);
	CPen pen1(PS_SOLID, 1, color);
	pDC->SelectObject(&pen1);
    pDC->Rectangle(XL, YB, XR, YT);

	color = RGB(0, 255, 0);
	CPen pen2(PS_DASHDOT, 1, color);
	pDC->SelectObject(&pen2);
	pDC->Polygon(ply, n);

	ClipEdgePolygon(ply, n, XL, XR, YB, YT, pDC);
	color = RGB(0, 0, 255);
	CPen pen3(PS_SOLID, 3, color);
	pDC->SelectObject(&pen3);
	pDC->Polygon(ply, n);
}

在这里插入图片描述

实验三:图形几何变换

5种基本几何变换

设计一个要进行图形变换的二维平面图形(比如一个多边形),编程实现5种基本几何变换(平移、比例缩放、旋转、对称、错切),运行程序,分别显示出变换前、后的图形。

代码如下(示例):

旋转

void RotateTransform(POINT p[20],int m,POINT Cen,float theta,CDC *pDC)
{
    
    
	int i;double a,b,c,d;
	POINT p1[20];
	double alfa=theta*PI/180;
	a=cos(alfa);b=sin(alfa);
	for(i=0;i<m;i++)
	{
    
    
		p1[i].x=p[i].x*a-p[i].y*b+Cen.x*(1-a)+Cen.y*b;
		p1[i].y=p[i].x*b+p[i].y*a-Cen.x*b+Cen.y*(1-a);
	}
	
	for(i=0;i<m;i++)
	{
    
    p[i].x=p1[i].x;p[i].y=p1[i].y;}

	//画出直角坐标系

	CPen pen(PS_DASHDOT,1,RGB(0,255,0));
	pDC->SelectObject(&pen);

	pDC->MoveTo(Cen.x-Cen.x/2,Cen.y);
	pDC->LineTo(Cen.x+Cen.x/2,Cen.y);
	pDC->MoveTo(Cen.x,Cen.y-Cen.y/2);
	pDC->LineTo(Cen.x,Cen.y+Cen.y/2);

}

void CSyView::OnDraw(CDC* pDC)
{
    
    
	CSyDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	int color,n=4;
	float th,x0,y0,SkewX,SkewY,ScaleX,ScaleY,MoveX,MoveY;
	POINT ply[4]={
    
    {
    
    50,100},{
    
    150,100},{
    
    150,300},{
    
    120,300}},p0={
    
    300,300},ps={
    
    200,20},pe={
    
    300,400};
	th=90;x0=p0.x;y0=p0.y;SkewX=0.6;SkewY=0;ScaleX=2.0;ScaleY=2.0;MoveX=400,MoveY=200;
	
	
	color=RGB(0,0,255);
	CPen pen1(PS_DASH,1,color);
	pDC->SelectObject(&pen1);
	pDC->Polygon(ply,n);

	RotateTransform(ply,n,p0,th,pDC);

	color=RGB(255,0,0);
	CPen pen2(PS_SOLID,2,color);
	pDC->SelectObject(&pen2);
	pDC->Polygon(ply,n);


}

在这里插入图片描述

错切

void SkewTransform(POINT p[20],int m,float SkewX,float SkewY)
{
    
    
	for(int i=0;i<m;i++)
	{
    
    	
		p[i].x=p[i].x+p[i].y*SkewX;  p[i].y=p[i].y+p[i].x*SkewY;
	}
}


void CSyView::OnDraw(CDC* pDC)
{
    
    
	CSyDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	int color,n=4;
	float th,x0,y0,SkewX,SkewY,ScaleX,ScaleY,MoveX,MoveY;
	POINT ply[4]={
    
    {
    
    50,100},{
    
    150,100},{
    
    150,300},{
    
    120,300}},p0={
    
    300,300},ps={
    
    200,20},pe={
    
    300,400};
	th=90;x0=p0.x;y0=p0.y;SkewX=0.6;SkewY=0;ScaleX=2.0;ScaleY=2.0;MoveX=400,MoveY=200;
	
	//
	color=RGB(0,0,255);
	CPen pen1(PS_DASH,1,color);
	pDC->SelectObject(&pen1);
	pDC->Polygon(ply,n);


	SkewTransform(ply,n,SkewX,SkewY);

	color=RGB(255,0,0);
	CPen pen2(PS_SOLID,2,color);
	pDC->SelectObject(&pen2);
	pDC->Polygon(ply,n);


}

在这里插入图片描述

对称

void MirrorTransform(POINT p[20],int m,POINT ps,POINT pe,CDC *pDC)
{
    
    
	int i;POINT p1[20];double A,B,C;
	A=pe.y-ps.y;B=ps.x-pe.x;C=-(A*ps.x+B*ps.y);
	for(i=0;i<m;i++)
	{
    
    
	p1[i].x=((B*B-A*A)*p[i].x-2*A*B*p[i].y-2*A*C)/(A*A+B*B);
	p1[i].y=((A*A-B*B)*p[i].y-2*A*B*p[i].x-2*B*C)/(A*A+B*B);
	}

	for(i=0;i<m;i++)
	{
    
    
		p[i].x=p1[i].x;	p[i].y=p1[i].y;
	}
	//画出对称直线
	CPen pen(PS_DASHDOT,1,RGB(0,255,0));
	pDC->SelectObject(&pen);

	pDC->MoveTo(ps.x,ps.y);
	pDC->LineTo(pe.x,pe.y);
	

}

void CSyView::OnDraw(CDC* pDC)
{
    
    
	CSyDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	int color,n=4;
	float th,x0,y0,SkewX,SkewY,ScaleX,ScaleY,MoveX,MoveY;
	POINT ply[4]={
    
    {
    
    50,100},{
    
    150,100},{
    
    150,300},{
    
    120,300}},p0={
    
    300,300},ps={
    
    200,20},pe={
    
    300,400};
	th=90;x0=p0.x;y0=p0.y;SkewX=0.6;SkewY=0;ScaleX=2.0;ScaleY=2.0;MoveX=400,MoveY=200;
	
	//
	color=RGB(0,0,255);
	CPen pen1(PS_DASH,1,color);
	pDC->SelectObject(&pen1);
	pDC->Polygon(ply,n);


	MirrorTransform(ply,n,ps,pe,pDC);

//
	color=RGB(255,0,0);
	CPen pen2(PS_SOLID,2,color);
	pDC->SelectObject(&pen2);
	pDC->Polygon(ply,n);


}

在这里插入图片描述

比例缩放

void ScaleTransform(POINT p[20],int m,float ScaleX,float ScaleY)
{
    
    
for(int i=0;i<m;i++)
{
    
    	p[i].x=p[i].x*ScaleX;
	p[i].y=p[i].y*ScaleY;
}

}

void CSyView::OnDraw(CDC* pDC)
{
    
    
	CSyDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	int color,n=4;
	float th,x0,y0,SkewX,SkewY,ScaleX,ScaleY,MoveX,MoveY;
	POINT ply[4]={
    
    {
    
    50,100},{
    
    150,100},{
    
    150,300},{
    
    120,300}},p0={
    
    300,300},ps={
    
    200,20},pe={
    
    300,400};
	th=90;x0=p0.x;y0=p0.y;SkewX=0.6;SkewY=0;ScaleX=2.0;ScaleY=2.0;MoveX=400,MoveY=200;
	
	//
	color=RGB(0,0,255);
	CPen pen1(PS_DASH,1,color);
	pDC->SelectObject(&pen1);
	pDC->Polygon(ply,n);

//	RotateTransform(ply,n,p0,th,pDC);
//	SkewTransform(ply,n,SkewX,SkewY);
//	MirrorTransform(ply,n,ps,pe,pDC);
	ScaleTransform(ply,n,ScaleX,ScaleY);
//	MoveTransform(ply,n,MoveX,MoveY);

//
	color=RGB(255,0,0);
	CPen pen2(PS_SOLID,2,color);
	pDC->SelectObject(&pen2);
	pDC->Polygon(ply,n);


}

在这里插入图片描述

平移

void MoveTransform(POINT p[20],int m,float MoveX,float MoveY)
{
    
    
	for(int i=0;i<m;i++)
	{
    
    p[i].x=p[i].x+MoveX;p[i].y=p[i].y+MoveY;}
	//画出直角坐标系


}


void CSyView::OnDraw(CDC* pDC)
{
    
    
	CSyDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	int color,n=4;
	float th,x0,y0,SkewX,SkewY,ScaleX,ScaleY,MoveX,MoveY;
	POINT ply[4]={
    
    {
    
    50,100},{
    
    150,100},{
    
    150,300},{
    
    120,300}},p0={
    
    300,300},ps={
    
    200,20},pe={
    
    300,400};
	th=90;x0=p0.x;y0=p0.y;SkewX=0.6;SkewY=0;ScaleX=2.0;ScaleY=2.0;MoveX=400,MoveY=200;
	
	//
	color=RGB(0,0,255);
	CPen pen1(PS_DASH,1,color);
	pDC->SelectObject(&pen1);
	pDC->Polygon(ply,n);

//	RotateTransform(ply,n,p0,th,pDC);
//	SkewTransform(ply,n,SkewX,SkewY);
//	MirrorTransform(ply,n,ps,pe,pDC);
//	ScaleTransform(ply,n,ScaleX,ScaleY);
	MoveTransform(ply,n,MoveX,MoveY);

//
	color=RGB(255,0,0);
	CPen pen2(PS_SOLID,2,color);
	pDC->SelectObject(&pen2);
	pDC->Polygon(ply,n);


}

结果
在这里插入图片描述

实验四:自由曲线的绘制

1、二次插值样条曲线

编写二次插值样条曲线生成函数,然后利用该函数根据自己设计的型值点绘制出相应的曲线图形。

void Paeabola(POINT *p,int n,CDC* pDC)
{
    
    
	int x,y,i,j,k=10;
	double t1,t2,t3,t,a,b,c,d;
	p[0].x=p[1].x;
	p[0].y=p[1].y;

	p[n+1].x=p[n].x;
	p[n+1].y=p[n].y;

	t=0.5/k;

	pDC->MoveTo(p[1].x,p[1].y);

	for(i=1;i<n;i++)//外层画段多少
	{
    
    
		for(j=1;j<k;j++)//画的每一段
		{
    
    
			t1=j*t;
			t2=t1*t1;
			t3=t1*t2;

			a=4.0*t2-t1-4.0*t3;		//Pi的系数
			b=1.0-10.0*t2+12.0*t3;	//P(i+1)的系数
			c=t1+8.0*t2-12.0*t3;	//P(i+2)的系数
			d=4.0*t3-2.0*t2;		//P(i+3)的系数

			x=(int)(a*p[i-1].x+b*p[i].x+c*p[i+1].x+d*p[i+2].x);
			y=(int)(a*p[i-1].y+b*p[i].y+c*p[i+1].y+d*p[i+2].y);
			pDC->LineTo(x,y);
		}
		pDC->LineTo(p[i+1].x,p[i+1].y);
	}
}

void CS441View::OnDraw(CDC* pDC)
{
    
    
	CS441Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	int n=4;
	POINT ps[6];

	ps[1].x=50;
	ps[1].y=300;

	ps[2].x=150;
	ps[2].y=50;

	ps[3].x=250;
	ps[3].y=300;
		
	ps[4].x=350;
	ps[4].y=50;
	
	Paeabola(ps,n,pDC);

}
    

在这里插入图片描述

2.Bezier曲线

编写任意阶次的Bezier曲线生成函数,然后利用该函数根据自己设计的控制点绘制出相应的曲线图形。

	double powi(double v,int k)//计算v的k次方
	{
    
    
		double temp=1.0;
		if(k==0||v==0)return 1;
		else {
    
    
			for(int i=1;i<=k;i++)
				temp=temp*v;}
			return temp;
		
	}

	long fac(int m)//计算阶乘
	{
    
    
		int i;long temp=1;
		if(m==1)return 1;
		else {
    
    
			for(i=2;i<=m;i++)
				temp=temp*i;}
			return temp;
		
	}

	void Bezier(POINT *p,int n,CDC *pDC)
	{
    
    
		int x,y,i,j,k=100;
		double t=1.0/k,t1,u,v;
		double temp,temp1,temp2,bi;
		pDC->MoveTo(p[0].x,p[0].y);
		for(j=1;j<k;j++)
		{
    
    
			t1=j*t;
			u=t1;v=1-u;
			x=0;y=0;
			for(i=0;i<=n;i++)
			{
    
    
				temp=double(fac(n)/fac(i)/fac(n-i));
				temp1=powi(u,i);
				temp2=powi(v,n-i);
				bi=temp*temp1*temp2;
				x=x+bi*p[i].x;
				y=y+bi*p[i].y;
			}
			pDC->LineTo(x,y);
		}
			pDC->LineTo(p[n].x,p[n].y);
	}



void CS441View::OnDraw(CDC* pDC)
{
    
    
	CS441Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	int n=5;
	CPoint ps[6]={
    
    CPoint(50,100),CPoint(150,250),CPoint(300,200),CPoint(400,50),CPoint(550,300),CPoint(350,400)};

	//画特征多边形,即多边折线
	CPen pen1(PS_DASHDOT,1,RGB(0,0,255));
	pDC->SelectObject(&pen1);
	pDC->Polyline(ps,6);

	//画出Bezier曲线(5次)
	CPen pen2(PS_DASHDOT,2,RGB(255,0,0));
	pDC->SelectObject(&pen2);
	Bezier(ps,n,pDC);
}

在这里插入图片描述

3.三次B样条曲线

编写三次B样条曲线生成函数,然后利用该函数根据自己设计的控制点绘制出相应的曲线图形。

void BSpLine(POINT *p,int n,CDC* pDC)
{
    
    
	int x,y,i,j,k=1000;
	double t,t1,t2,t3,a,b,c,d;
	t=1.0/k;
	//端点处理
	p[0].x=2*p[1].x-p[2].x;
	p[0].y=2*p[1].y-p[2].y;
	p[n].x=2*p[n-1].x-p[n-2].x;
	p[n].y=2*p[n-1].y-p[n-2].y;

	pDC->MoveTo(p[1].x,p[1].y);

	for(i=1;i<n-1;i++)
		for(j=1;j<=k;j++)
		{
    
    
			t1=j*t;
			t2=t1*t1;
			t3=t2*t1;
			a=(3*t2-t3-3*t1+1)/6;
			b=(3*t3-6*t2+4)/6;
			c=(3*t2-3*t3+3*t1+1)/6;
			d=t3/6;
			x=int(a*p[i-1].x+b*p[i].x+c*p[i+1].x+d*p[i+2].x);
			y=int(a*p[i-1].y+b*p[i].y+c*p[i+1].y+d*p[i+2].y);
			pDC->LineTo(x,y);
		}
}




void CQuxian3View::OnDraw(CDC* pDC)
{
    
    
	CQuxian3Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	int n=5;
	POINT ps[6];
	ps[1].x=350;
	ps[1].y=250;
	ps[2].x=500;
	ps[2].y=200;
	ps[3].x=600;
	ps[3].y=50;
	ps[4].x=750;
	ps[4].y=300;

	//绘制三次B样条曲线
	
	CPen pen1(PS_DASHDOT,2,RGB(255,0,0));
	pDC->SelectObject(&pen1);
	BSpLine(ps,n,pDC);



	//绘制特征多边形,即多边折线
	CPen pen2(PS_DASHDOT,1,RGB(0,0,255));
	pDC->SelectObject(&pen2);
	pDC->Polyline(ps,6);


}

在这里插入图片描述

注意:
本文代码块仅提供完整图形生成函数,而非可运行程序,需要建立绘图程序

猜你喜欢

转载自blog.csdn.net/weixin_51121822/article/details/118249990