计算机图形学实验4实验报告.docx
《计算机图形学实验4实验报告.docx》由会员分享,可在线阅读,更多相关《计算机图形学实验4实验报告.docx(12页珍藏版)》请在冰豆网上搜索。
计算机图形学实验4实验报告
《计算机图形学》实验4实验报告
实验题目:
参数曲线绘制
实验内容:
1圆的参数曲线绘制。
2显式数学曲线描绘程序。
3贝赛尔曲线绘制。
编写程序调用验证之。
参考资料:
1circleParam.java
2explicitCurve.java
3BezierLine.java
4数学曲线绘制.ppt和实验3的参考ppt
基本概念:
1、圆的参数曲线绘制:
圆的参数曲线绘制就是按照圆的定义,利用步长,得在显示域上每一点的位置,然后绘制。
圆是图形中经常使用的元素,圆被定义为所有离一中心位置(xc,yc)距离为给定值R的点集。
2、显示数学曲线描绘程序:
显示曲线的绘制就是在已知的坐标系上,按照方程要求在固定的点画点,然后连接成一条线。
3、贝塞尔曲线的绘制:
贝赛尔曲线的每一个顶点都有两个控制点,用于控制在顶点两侧的曲线的弧度。
它是应用于二维图形应用程序的数学曲线。
曲线的定义有四个点:
起始点、终止点(也称锚点)以及两个相互分离的中间点。
滑动两个中间点,贝塞尔曲线的形状会发生变化。
算法设计:
1、圆的算法设计:
本例程体现的主要是圆的快速算法,这里的主要算法是:
X=Xc +Rcost
Y=Yc+Rsint 0 t是圆的某一点与X轴之间的夹角。
Xc和Yc分别是圆的中心,以上一个终点为下一个的起点。
改变t的值,就可以得到一个圆。
体现在代码中就是:
//圆的参数曲线x=f(t)
privatedoublefx(doublet){
returnMath.cos(t)+0.2;
}
//圆的参数曲线y=f(t)
privatedoublefy(doublet){
returnMath.sin(t)+0.2;
}
2、显示数学曲线绘制:
利用微分方法进行绘制,将曲线x轴分割成足够小的间距,利用绘制的公式计算出每一个x所对应的y的坐标,然后在该坐标上画点(本程序绘制函数y=x*x-x-2)数图像从x=-4.0开始绘制,分割间距为0.05,即从x=-4.0绘制到x=4.0要走过160步,在该程序中用变量x表示开始绘图的x坐标,用变量deltaX表示每次分割的最小长度,即步长,利用所绘制的公式计算出y轴坐标,然后利用循环绘制出函数图像,体现在代码中就是:
//描绘曲线y=x^2-x-2
privatedoublef(doublex){
return(x-2)*(x+1);
}
3、绘制:
绘制分为两部分,一部分是节点的绘制,一部分是曲线线段的绘制,在该程徐序中定义了8个节点坐标,然后在该节点上绘制一个实心圆(红色表示),再绘制直线连接每两个相邻节点,共计8个节点7条线段,再利用微分的思想,将该范围内的x轴切分,该程序中是以变量t表示,切分大小为0.01,利用公式求解出对应的y轴坐标,然后利用绘制短直线的方法绘制相邻两个点之间的线段(蓝色表示),最后从最左节点绘制到最右节点坐标后结束绘制。
体现在代码中就是:
for(t=0;t<=1;t+=0.01){//参数法求点坐标
for(i=0;ix1=x1+(int)(Bin(n-1,i,t)*p[i].x);
y1=y1+(int)(Bin(n-1,i,t)*p[i].y);
}//i循环
g.drawLine(x0,y0,x1,y1);//划短直线
x0=x1;//下一折线
y0=y1;
x1=0;
y1=0;
}//参数t循环
代码:
画圆:
//圆的参数曲线x=f(t)
privatedoublefx(doublet){
returnMath.cos(t)+0.2;
}
//圆的参数曲线y=f(t)
privatedoublefy(doublet){
returnMath.sin(t)+0.2;
}
//Applet程序的描绘方法paint
publicvoidpaint(Graphicsg){
m.setBackground(Color.white);//背景色
m.setColor(Color.black);//前景色
m.setWindow(xmin,xmax,ymin,ymax);//用户坐标系范围
//缺省的视图为m.setViewport(0,1,0,1)和JavaAWT窗口大小一样
/*画X轴*/
double[]x1={xmax-0.05,xmax,xmax-0.05};
double[]y1={-0.03,0,0.03};
m.fillPolygon(x1,y1,3);
m.drawString("X轴",1.05,-0.15);
m.drawLine(xmin,0,xmax,0);
/*画Y轴*/
double[]x2={-0.03,0,0.03};
double[]y2={ymax-0.05,ymax,ymax-0.05};
m.fillPolygon(x2,y2,3);
m.drawString("Y轴",-0.2,1.05);
m.drawLine(0,ymin,0,ymax);
/*画圆*/
doublet=0.0;
doublex=fx(t);
doubley=fy(t);
m.moveTo(x,y);//抬笔移到起点
doublex0=x,y0=y;//记住起点
intstep=100;
doubledeltat=2*Math.PI/step;
for(inti=0;it+=deltat;
x=fx(t);y=fy(t);
m.lineTo(x,y);//画直线到该点
}
m.lineTo(x0,y0);//画直线到起点,结束
}//描绘方法paint结束
}//参数曲线描绘类结束
画显示数学曲线
//描绘曲线y=x^2-x-2
privatedoublef(doublex){
return(x-2)*(x+1);
}
//Applet程序的描绘方法paint
publicvoidpaint(Graphicsg){
m.setBackground(Color.white);//背景色
m.setColor(Color.blue);//前景色
m.setWindow(xmin,xmax,ymin,ymax);//用户坐标系范围
//缺省的视图为m.setViewport(0,1,0,1)和JavaAWT窗口大小一样
m.drawLine(xmin,0,xmax,0);//画x轴及刻度线
for(inti=(int)xmin;i<=(int)xmax;i++){
m.drawLine((double)i,-gDelta,(double)i,gDelta);
m.drawString(String.valueOf(i),i-gDelta,-0.4);
}
m.drawLine(0,ymin,0,ymax);//画y轴及刻度线
for(intj=(int)ymin;j<=(int)ymax;j++){
m.drawLine(-gDelta,(double)j,gDelta,(double)j);
m.drawString(String.valueOf(j),-0.4,j-gDelta);
}
/*画曲线*/
doublex=-2.0;//曲线的起始点
doubley=f(x);
m.moveTo(x,y);//抬笔移动到xy点处
doubledeltaX=0.05;//x的步长
for(inti=0;i<100;i++){//x方向走10步
x+=deltaX;y=f(x);
m.lineTo(x,y);//落笔画直线到xy点处
}
}//描绘方法paint结束
}//显式曲线描绘类结束
画贝塞尔曲线:
privateNodep[]=newNode[8];//塞尔曲线8个节点
//贝赛尔曲线类构造方法
publicBezierLine(){
super("Bezier曲线");//调用父类Frame的构造方法,显示窗口标题
this.setSize(700,600);
this.setLayout(newFlowLayout());
button_start=newButton("划线");
button_start.addActionListener(this);
button_close=newButton("关闭");
button_close.addActionListener(this);
//测试数据:
4个节点赋值
/*p[0]=newNode(50,400);
p[1]=newNode(100,350);
p[2]=newNode(200,450);
p[3]=newNode(550,400);*/
p[0]=newNode(50,300);
p[1]=newNode(120,380);
p[2]=newNode(200,450);
p[3]=newNode(300,410);
p[4]=newNode(380,350);
p[5]=newNode(300,260);
p[6]=newNode(220,150);
p[7]=newNode(80,200);
//p[0]=newNode(100,260);
//p[1]=newNode(50,150);
//p[2]=newNode(250,120);
//p[3]=newNode(330,250);
this.add(button_start);
this.add(button_close);
this.setVisible(true);//显示窗口和界面
}//结束贝赛尔曲线类构造方法
//辅助函数:
求t的i次方
publicdoublepow(doublet,inti){
if(t==0&&i==0)return1;
elsereturnMath.pow(t,i);
}
//辅助函数:
递归求n的阶乘
publicintfactorial(intn){
if(n==0||n==1)return1;
elsereturnn*factorial(n-1);
}
//定义Beinstein函数
publicdoubleBin(intn,inti,doublet){
doubletm;
tm=factorial(n)/(factorial(i)*factorial(n-i))*pow(t,i)*pow(1-t,n-i);
returntm;
}
//定义paint函数
publicvoidpaint(Graphicsg){
inti,j,n,x1=0,y1=0,x0,y0;
doublet;
n=8;//贝赛尔8个节点
g.setColor(Color.red);
g.fillOval(p[0].x-5,p[0].y-5,10,10);//实心圆
for(j=1;jg.fillOval(p[j].x-5,p[j].y-5,10,10);
g.drawLine(p[j-1].x-1,p[j-1].y-1,p[j].x-1,p[j].y-1);
}
x0=p[0].x;//起点
y0=p[0].y;
g.setColor(Color.blue);
for(t=0;t<=1;t+=0.01){//参数法求点坐标
for(i=0;ix1=x1+(int)(Bin(n-1,i,t)*p[i].x);
y1=y1+(int)(Bin(n-1,i,t)*p[i].y);
}//i循环
g.drawLine(x0,y0,x1,y1);//划短直线
x0=x1;//下一折线
y0=y1;
x1=0;
y1=0;
}//参数t循环
}
运行结果:
圆心在(0,0)的元圆:
圆心在(0.2,0.2)的圆:
绘画y=x^3-x的图:
绘画y=x^2-x-2的图:
三种四个节点不同参数的视图:
八个节点的视图:
实验体会:
学习了圆的参数曲线的画法,知道了在视图上和数学上算法的不同,学习了数学曲线的画法,其方式是采用递推,步长可以由用户自定义设置,步数决定画出来图形的完整度,
学习了贝塞尔曲线的画法,我了解到了更多的算法,学习到了更多的编程知识。