大二选修课计算机图形学
课程实验代码
文章目录
实验一:直线、圆、椭圆的生成
实验目的:掌握基本图形的生成算法,包括直线段、圆、椭圆的扫描转换
实验原理: 直线段、圆、椭圆生成算法的基本原理。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);
}
注意:
本文代码块仅提供完整图形生成函数,而非可运行程序,需要建立绘图程序