图形学实验.docx

上传人:b****6 文档编号:6235225 上传时间:2023-01-04 格式:DOCX 页数:23 大小:97.44KB
下载 相关 举报
图形学实验.docx_第1页
第1页 / 共23页
图形学实验.docx_第2页
第2页 / 共23页
图形学实验.docx_第3页
第3页 / 共23页
图形学实验.docx_第4页
第4页 / 共23页
图形学实验.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

图形学实验.docx

《图形学实验.docx》由会员分享,可在线阅读,更多相关《图形学实验.docx(23页珍藏版)》请在冰豆网上搜索。

图形学实验.docx

图形学实验

 

院系:

计算机科学学院

专业:

计算机科学与技术

年级:

07

课程名称:

计算机图形学

指导教师:

高志荣

组号:

学号:

070612420606125007061231

姓名:

杜传虎马龙刘伟业

2010年6月19日

实验分项1

直线的生成

在实验是同学熟悉中点画线算法或者Bresenham算法,并对不同算法的性能有所认识;

●将象素网格表现出来,建立网格坐标系

●用橡皮筋的形式输入参数

●鼠标移动时,显示鼠标当前位置

●显示判别式的计算过程和下一点的选择策略

●记录生成点的坐标,建议用表的形式

1.首先是在面板上画代表像素的格子:

本程序对坐标进行了封装,只需改变参数的值就能显示不同大小的格子;

publicvoidpaint(finalGraphicsg)

{

g.setColor(Color.BLUE);

for(inti=0;i<=1000;i++)

{

g.drawLine(0,i*10,1000,i*10);

}

for(inti=0;i<=1000;i++)

{

g.drawLine(i*10,0,i*10,1000);

}

2.监听操作,获取直线的起点和终点记为x0,y0,x,y;

坐标点的获取可以通过输入的方式,也可以通过鼠标的拖拽来实现!

3.Bresenham算法:

a.接收参数sx,sy,ex,ey;

dx=ex-sx;dy=ey-sy;

修正获取直线起点和终点:

//对坐标取整!

(使点在坐标交点处)

for(intj=0;j

if(((x0-X_START)%SPACE)!

=0)

x0--;

if((y0-Y_START)%SPACE!

=0)

y0--;

if(((x1-X_START)%SPACE)!

=0)

x1--;

if((y1-Y_START)%SPACE!

=0)

y1--;}

b.获取直线斜率

if(dx!

=0)

slope=(float)dy/dx;//此直线的斜率

c.然后对不同的斜率采用不同的方式处理:

if(slope>=0&&slope<=1)

for(i=0;i

{e=2*dy-dx;

x=x0;

y=y0;

if(e>=0){

y+=SPACE;

e=e-2*dx;

}

x+=SPACE;

e=e+2*dy;

}

if(slope>1){

e=2*dx-dy;

x=x0;

y=y0;

for(i=0;i

if(e>=0){

x+=SPACE;

e=e-2*dy;

}

y+=SPACE;

e=e+2*dx;

}

}

if(slope>=-1&&slope<0){

e=2*dy-dx;

x=-x1;

y=y1;

for(i=0;i

if(e>=0){

y+=SPACE;

e=e-2*dx;

}

x+=SPACE;

e=e+2*dy;

}

else{//slope<-1

inte=2*dy-dx;

x=-x0;

y=y0;

for(i=0;i

if(e>=0){

y+=SPACE;

e=e-2*dx;

}

x+=SPACE;

e=e+2*dy;

}

d.每次循环中都要存入数据x,y,e;

MyCoordinatecoordinate=newMyCoordinate(y,-x,e);

coor.add(coordinate);

其中MyCoordinate是自建的一个类,用来存放坐标x,y和e;coor是该类的一个ArrayList;

e.输出坐标:

用publicvoidprintoval(ArrayListp,Graphicsg,intx_start,inty_start)方法实现;

 

(写不完时,可另加附页。

1.开始菜单:

2.直线生成:

结果分析:

1.在输入模式下,坐标的原点是左上角,x轴方向是向右的,y轴的方向是向下的,而且在坐标显示上还是以一个像素点为单位的,只是在描述上以一个格子为一个像素点。

第二个图像直接在面板上取点,不用考虑相对的位置。

2.在显示的过程中由于是在面板上画图,实际坐标的取值还要考虑边框所占用的空间,所以在代码实现时要进行一定的位置修正!

(在代码中有体现。

在实现这个问题之前已经学过了几种作直线的算法,在对比中发现了所用算法的优越性。

程序中没有小数的加减而且没有改变直线求解的精确度,所以在性能上会有所改善;在程序的调试过程中,对画直线中的repiant()的用法认识不是很深刻,还有需要改进的地方;

实验分项2

 圆弧的生成

 用中点画圆算法或者Bresenham算法画圆

●将象素网格表现出来,建立网格坐标系

●用橡皮筋的形式输入参数

●鼠标移动时,显示鼠标当前位置

●显示判别式的计算过程和下一点的选择策略

●记录生成点的坐标,建议用表的形式

1.首先是在面板上画代表像素的格子:

本程序对坐标进行了封装,只需改变参数的值就能显示不同大小的格子;

for(;i<=LINE-1;i++){

g.drawLine(SPACE*(i-1)+X_START,Y_START,SPACE*(i-1)+X_START,SPACE*(LINE-1)+Y_START);

g.drawLine(X_START,SPACE*(i-1)+Y_START,SPACE*(LINE-1)+X_START,SPACE*(i-1)+Y_START);}

g.drawLine(SPACE*(i-1)+X_START,Y_START,SPACE*(i-1)+X_START,SPACE*(LINE-1)+Y_START);

g.drawLine(X_START,SPACE*(i-1)+Y_START,SPACE*(LINE-1)+X_START,SPACE*(i-1)+Y_START);

}

2.监听操作,在输入模式下获取圆的圆心坐标和半径或在拖拽模式下获得起点和终点坐标,设置起点坐标为圆心,拖拽的距离为圆的半径;

3.用Bresenham算法获取1/8圆弧:

voidbresenham_arc(intcircular_Points_X,intcircular_Points_Y,intR)

其中参数依次是圆的圆心坐标circular_Points_X,circular_Points_Y和半径R;算法功能是是实现添加1/8部分圆坐标,其核心代码如下:

while(x

if(d<0)d=d+4*x*SPACE+6*SPACE;

else{

d=d+4*(x-y)*SPACE+10*SPACE;

y=y-SPACE;

}

x=x+SPACE;}

坐标点的转换方法:

publicMyCoordinateaxisChanges(intx,inty,intd);

核心代码:

mycoor.setPhysicx(x);

mycoor.setPhysicy(y);

mycoor.setX((x-cir_point_x)/SPACE);

mycoor.setY((cir_point_y-y)/SPACE);

存放了两个坐标点,分别是在面板中的真实坐标和在界面中呈现出的坐标点;

4.添加圆的其它点:

publicvoidaddOtherPoint(intn)

其中n是已经在画的1/8的圆的像素个数;

核心代码如下:

获取半径向量:

x=coor.get(i).getX()-CIRPOINT.x;

y=coor.get(i).getY()-CIRPOINT.y;

logicx=coor.get(i).getPhysicx()-PHSICCIRPOINT.x;

logicy=coor.get(i).getPhysicy()-PHSICCIRPOINT.y;

获取其它各点:

(x+CIRPOINT.x,-y+CIRPOINT.y);

(-x+CIRPOINT.x,-y+CIRPOINT.y);

(-x+CIRPOINT.x,y+CIRPOINT.y);

(y+CIRPOINT.x,x+CIRPOINT.y);

(y+CIRPOINT.x,-x+CIRPOINT.y);

(-y+CIRPOINT.x,x+CIRPOINT.y);

(-y+CIRPOINT.x,-x+CIRPOINT.y);

5.用所存坐标画圆

while(it.hasNext()){

cox=point.getX();//已经是逻辑的坐标点,以space为单位

coy=point.getY();

logicx=point.getPhysicx();

logicy=point.getPhysicy();

g.fillOval(logicx-(int)(SPACE/4)+9,logicy-

(int)(SPACE/4)+32,(int)SPACE/2,(int)SPACE/2);

g.setColor(Color.red);

g.fillRect(logicx+9,logicy+32,SPACE,SPACE);

}

其中程序中的+9+32操作时对边框的修正。

 

(写不完时,可另加附页。

1.在输入模式下的弧线显示结果:

结果分析:

1.在输入模式下,对坐标点进行了位置的处理,坐标的原点是左下角,x轴方向是向右的,y轴的方向是向上的,但是这只是在显示上的表现,在画圆弧的过程中还是用的坐标的真实坐标;

2.在只做点击的情况下,设置坐标的半径为5;

3.在显示的过程中由于是在面板上画图,实际坐标的取值还要考虑边框所占用的空间,所以在代码实现时要进行一定的位置修正!

(在代码中有体现。

在这次实验过程中,对坐标的点进行了相应的改变,设置了坐下角为原点,而且成功的把坐标点物理点和逻辑点分开了,这是比较好的地方吧。

在画圆用的bresenham算法,继续用整数的加减来代替真正的距离来找坐标点,提高了算法的效率和减少了算法的复杂度!

感受到了这个算法的优越性!

实验分项3

 线段裁剪

 用Cohen-SutherLand算法进行线段裁剪

1.将象素网格表现出来,建立网格坐标系

2.用橡皮筋的形式输入剪裁线段

3.对于线段裁剪,线段被窗口的四条边裁剪的过程要显示出来

 

1.直线的生成:

mouseClicked方法中获取点击点的位置,当点击“确定”的时候把两点取出,并画直线;

g.setColor(Color.BLUE);

g.drawLine(pointX[0],pointY[0],pointX[1],pointY[1]);

2.裁剪框的生成:

使用鼠标的拖拽实现生成裁剪框,代码显示如下:

publicvoidmouseDragged(MouseEvente){

//剪切框的终点坐标

xR=e.getX();

yB=e.getY();

Graphicsg=getGraphics();

paintComponent(g);

g.setColor(Color.black);

g.drawRect(xL,yT,xR-xL,yB-yT);

}

其中起点的坐标xL,yT在mousePressed方法中生成!

3.由于直线的起点,终点都有记录,所以在重新生成裁剪线之前,首先对面板进行清理,用g.clearRect(00,00,380,600)实现

4.利用梁友栋-Barsky算法裁剪直线:

直线的裁剪是在clipline方法中实现的,参数分别是直线的起点和终点坐标;

clipLine(pointX[0],pointY[0],pointX[1],pointY[1]);

(写不完时,可另加附页。

if(clipTest(-dx,x1-xL)){

intw=x1-xL;

if(clipTest(dx,xR-x1)){

inth=xR-x1;

if(clipTest(-dy,y1-yB)){

intl=y1-yB;

if(clipTest(dy,yT-y1)){

x2=(int)(x1+u2*dx);

y2=(int)(y1+u2*dy);

x1=(int)(x1+u1*dx);

y1=(int)(y1+u1*dy);

g.setColor(Color.red);

g.drawLine(x1,y1,x2,y2);

}

其中用到clipTest方法在此方法中主要是判断起点组,终点组以及找到ts和te,这些工作的实现过程是:

publicbooleanclipTest(doubler,floats){

doublet;

if(r<0)

{

t=s/r;

if(t>1)

returnfalse;

elseif(t>0)

u1=t;/*u1取"进入"点的最大参数值*/

elseif(r>0)

{

t=s/r;

if(t<0)

returnfalse;

elseif(t<1)

u2=t;/*u2取"离开"点的最小参数值*/

}

elseif(s<0)/*p=0,且q<0。

平行于边界,而且在界外的线*/

returnfalse;

returntrue;

}

 

(写不完时,可另加附页。

1:

在已有的框内化画直线然后剪切的效果:

结果分析:

首先直线是用蓝线生成的,裁剪操作中,首先是把直线进行清除,然后找到裁剪后的起点和终点并用红线画出,边框也是重画的,输入框中显示了直线的裁剪过程;在下面的输出框中显示了直线裁剪的过程!

首先在这次实验过程中用到了梁友栋-Barsky算法,这个方法的实质是用到了向量的点乘运算,所以只用了很少的除法运算,这体现了这个算法的优越性;其次在编程过程中由于设计上的问题所以直线的生成是用点击“确定”生成的,这是需要改进的地方!

实验分项1

 多边形裁剪

 用Sutherland-Hodgman算法进行多边形裁剪

1.将象素网格表现出来,建立网格坐标系

2.用橡皮筋的形式输入剪裁线段

3.裁剪过程需先输入一多边形,然后用窗口四边裁剪的过程中要显示顶点增删的过程。

 

1.面板的初始化及裁剪框的生成:

方法:

publicvoidpaintComponent(Graphicsg)

画裁剪框:

for(intj=0;j<200;){

g.setColor(Color.RED);

g.fillRect(stx+j,sty,5,5);

g.fillRect(edx-j,edy,5,5);

j=j+5;

}

for(intj=0;j<160;){

g.setColor(Color.RED);

g.fillRect(stx,sty+j,5,5);

g.fillRect(edx,edy-j,5,5);

j=j+5;

}

画像素格:

for(inti=1;i<=LINE-1;i++){

g.setColor(Color.BLACK);

g.drawLine(SPACE*(i-1)+X_START,Y_START,SPACE*(i-1)+X_START,SPACE*(LINE-1)+Y_START);

g.drawLine(X_START,SPACE*(i-1)+Y_START,SPACE*(LINE-1)+X_START,SPACE*(i-1)+Y_START);

2.多边形的生成:

mouseClicked方法中获取点击点的位置,当点击“确定”的时候把两点取出,并画直线;

for(inti=0;i

g.fillRect(coor.get(i).getX(),coor.get(i).getY()+35,5,5);g.drawLine(coor.get(i)).getX()+4,coor.get(i)).getY()+35,

coor.get((i+1))).getX()+4,coor.get((i+1)).getY()+35);

Barsky(stx,sty,edx,edy,coor.get(i).getX(),coor.get(i)).getY(),coor.get(i+1).getX(),coor.get(i+1).getY());

}

其中,Barsky方法的功能是:

Barsky是每次找和框架相交得点,就是相似三角相似的原理;而且每一次把得到的点存起来,当全部做完以后就再画出来;

3.裁剪过程:

if(arg0.getSource()==jbtCut){

Graphicsg=getGraphics();

changeLine(dinate,g);

}

所以整个裁剪过程就是调用了publicvoidchangeLine(ArrayListp,Graphicsg)方法;

此方法的功能是:

通过Barsky算法获得交点坐标,这个方法是画那些交点后形成的直线!

while(it.hasNext()){

Coordinatepoint=(Coordinate)it.next();

pointX[j]=point.getX();

pointY[j]=point.getY();

j++;

}

多边形的裁剪结果是通过一下代码实现的:

for(inti=0;i

g.drawLine(pointX[i]+8,pointY[i]+36,pointX[(i+1)%p.size()]+8,pointY[(i+1)%p.size()]+36);

g.drawLine(pointX[i]+6,pointY[i]+34,pointX[(i+1)%p.size()]+6,pointY[(i+1)%p.size()]+34);

g.drawLine(pointX[i]+6,pointY[i]+34,pointX[(i+1)%p.size()]+6,pointY[(i+1)%p.size()]+34);

g.drawLine(pointX[i]+4,pointY[i]+32,pointX[(i+1)%p.size()]+4,pointY[(i+1)%p.size()]+32);

g.drawLine(pointX[i]+4,pointY[i]+32,pointX[(i+1)%p.size()]+4,pointY[(i+1)%p.size()]+32);

}

在drawLine方法只能够对坐标点进行了修正!

(写不完时,可另加附页。

1.剪切框已经给出,画出一个多边形,点击剪切即可看到效果:

 

结果分析:

在这次实验中,首先是裁剪框是给定的,虽然对整个程序处理上有所帮助,但是这是一个限制的边框,所以这是可以改进的地方,只是代码要变得复杂。

其次直线的生成是经过先确定点,然后一次性画出的,这个方式不是很好,是可以通过每点击一次就重画来改进的;最后为了使多边形的裁剪过程清晰可见,并没有延续上一次的清屏的过程,直接在另一种颜色重新画了裁剪后的多边形;输出框中显示了整个多边形的裁剪过程!

这次的实验是对第三次实验直线的裁剪的扩展,而且整体的质量有所提高,首先了解了对多边形图形的裁剪过程,其次对算法有了一定的认识尤其是在通过不同方法的对比中评价算法的优越性!

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 英语学习

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1