1、图形学实验院 系:计算机科学学院 专 业:计算机科学与技术年 级: 07 课程名称: 计算机图形学 指导教师: 高志荣 组 号: 学 号: 07061242 06061250 07061231 姓 名: 杜传虎 马龙 刘伟业 2010年 6 月 19 日实验分项1直线的生成实验目的在实验是同学熟悉中点画线算法或者Bresenham算法,并对不同算法的性能有所认识;实验要求 将象素网格表现出来,建立网格坐标系 用橡皮筋的形式输入参数 鼠标移动时,显示鼠标当前位置 显示判别式的计算过程和下一点的选择策略 记录生成点的坐标,建议用表的形式实验原理步骤(算法流程)1.首先是在面板上画代表像素的格子:
2、本程序对坐标进行了封装,只需改变参数的值就能显示不同大小的格子; public void paint(final Graphics g) g.setColor(Color.BLUE); for(int i=0;i=1000;i+) g.drawLine(0, i*10, 1000, i*10); for(int i=0;i=1000;i+) g.drawLine(i*10, 0, i*10, 1000); 2. 监听操作,获取直线的起点和终点记为x0,y0,x,y; 坐标点的获取可以通过输入的方式,也可以通过鼠标的拖拽来实现!3.Bresenham算法:a. 接收参数sx,sy,ex,ey;
3、dx = ex-sx; dy = ey - sy; 修正获取直线起点和终点: /对坐标取整!(使点在坐标交点处) for(int j=0;j= 0 & slope = 1) for(i=0;i= 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= 0) x+=SPACE; e = e - 2 * dy; y+=SPACE; e = e + 2 * dx; if (slope = -1 & slope 0) e = 2 *
4、dy - dx; x = -x1; y = y1; for( i=0;i= 0) y+=SPACE; e = e - 2 * dx; x+=SPACE; e = e + 2 * dy; else /slope -1 int e = 2 * dy - dx; x = -x0; y = y0; for( i=0;i= 0) y+=SPACE; e = e - 2 *dx; x+=SPACE; e = e + 2 * dy; d. 每次循环中都要存入数据x,y,e; MyCoordinate coordinate=new MyCoordinate(y,-x,e); coor.add(coordina
5、te);其中MyCoordinate是自建的一个类,用来存放坐标x,y和e;coor是该类的 一个ArrayList;e. 输出坐标:用 public void printoval(ArrayList p,Graphics g,int x_start,int y_start)方法实现; (写不完时,可另加附页。)实验结果及分析1.开始菜单 :2.直线生成:结果分析:1.在输入模式下,坐标的原点是左上角,x轴方向是向右的,y轴的方向是向下的,而且在坐标显示上还是以一个像素点为单位的,只是在描述上以一个格子为一个像素点。第二个图像直接在面板上取点,不用考虑相对的位置。2.在显示的过程中由于是在面板
6、上画图,实际坐标的取值还要考虑边框所占用的空间,所以在代码实现时要进行一定的位置修正!(在代码中有体现。)心得体会 在实现这个问题之前已经学过了几种作直线的算法,在对比中发现了所用算法的优越性。程序中没有小数的加减而且没有改变直线求解的精确度,所以在性能上会有所改善;在程序的调试过程中,对画直线中的repiant()的用法认识不是很深刻,还有需要改进的地方;实验分项2圆弧的生成 实验目的用中点画圆算法或者Bresenham算法画圆实验要求 将象素网格表现出来,建立网格坐标系 用橡皮筋的形式输入参数 鼠标移动时,显示鼠标当前位置 显示判别式的计算过程和下一点的选择策略 记录生成点的坐标,建议用表
7、的形式实验原理步骤(算法流程)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*(
8、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圆弧:void bresenham_arc(int circular_Points_X,int circular_Points_Y ,int R)其中参数依次是圆的圆心坐标circular
9、_Points_X,circular_Points_Y和半径R;算法功能是是实现添加1/8部分圆坐标,其核心代码如下:while(xy) if (d0) d=d+4*x*SPACE+6*SPACE; else d=d+4*(x-y)*SPACE+10*SPACE; y=y-SPACE; x=x+SPACE;实验原理步骤(算法流程)坐标点的转换方法: public MyCoordinate axisChanges(int x,int y,int d); 核心代码: mycoor.setPhysicx(x); mycoor.setPhysicy(y); mycoor.setX(x-cir_poin
10、t_x)/SPACE); mycoor.setY(cir_point_y-y)/SPACE);存放了两个坐标点,分别是在面板中的真实坐标和在界面中呈现出的坐标点;4. 添加圆的其它点:public void addOtherPoint(int n)其中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).getPhy
11、sicy()-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();/已经是逻辑
12、的坐标点,以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.在输入模式下的弧
13、线显示结果:结果分析:1.在输入模式下,对坐标点进行了位置的处理,坐标的原点是左下角,x轴方向是向右的,y轴的方向是向上的,但是这只是在显示上的表现,在画圆弧的过程中还是用的坐标的真实坐标;2.在只做点击的情况下,设置坐标的半径为5;3.在显示的过程中由于是在面板上画图,实际坐标的取值还要考虑边框所占用的空间,所以在代码实现时要进行一定的位置修正!(在代码中有体现。)心得体会 在这次实验过程中,对坐标的点进行了相应的改变,设置了坐下角为原点,而且成功的把坐标点物理点和逻辑点分开了,这是比较好的地方吧。在画圆用的bresenham算法,继续用整数的加减来代替真正的距离来找坐标点,提高了算法的效率
14、和减少了算法的复杂度!感受到了这个算法的优越性!实验分项3 线段裁剪实验目的用Cohen-SutherLand算法进行线段裁剪实验要求1.将象素网格表现出来,建立网格坐标系2.用橡皮筋的形式输入剪裁线段 3.对于线段裁剪,线段被窗口的四条边裁剪的过程要显示出来实验原理步骤(算法流程)1.直线的生成: mouseClicked方法中获取点击点的位置,当点击“确定”的时候把两点取出, 并画直线; g.setColor(Color.BLUE); g.drawLine(pointX0,pointY0,pointX1,pointY1); 2.裁剪框的生成: 使用鼠标的拖拽实现生成裁剪框,代码显示如下:
15、public void mouseDragged(MouseEvent e) /剪切框的终点坐标 xR = e.getX(); yB = e.getY(); Graphics g = 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.利用梁友栋-Bars
16、ky算法裁剪直线: 直线的裁剪是在clipline方法中实现的,参数分别是直线的起点和终点坐标; clipLine(pointX0,pointY0,pointX1,pointY1); (写不完时,可另加附页。)实验原理步骤(算法流程) if(clipTest(-dx,x1-xL) int w=x1-xL; if(clipTest(dx,xR-x1) int h=xR-x1; if(clipTest(-dy,y1-yB) int l=y1-yB; if(clipTest(dy,yT-y1) x2=(int) (x1+u2*dx); y2=(int) (y1+u2*dy); x1=(int) (x
17、1+u1*dx); y1=(int) (y1+u1*dy); g.setColor(Color.red); g.drawLine(x1,y1,x2,y2); 其中用到clipTest方法在此方法中主要是判断起点组,终点组以及找到ts和te,这些工作的实现过程是:public boolean clipTest(double r,float s) double t; if(r1) return false; else if(t0) u1=t; /*u1取进入点的最大参数值*/ else if(r0) t=s/r; if(t0) return false; else if(t1) u2=t; /*u
18、2取离开 点的最小参数值*/ else if(s0) /*p=0,且q0。平行于边界,而且在界外的线*/ return false; return true; (写不完时,可另加附页。)实验结果及分析1:在已有的框内化画直线然后剪切的效果:结果分析:首先直线是用蓝线生成的,裁剪操作中,首先是把直线进行清除,然后找到裁剪后的起点和终点并用红线画出,边框也是重画的,输入框中显示了直线的裁剪过程;在下面的输出框中显示了直线裁剪的过程!心得体会 首先在这次实验过程中用到了梁友栋-Barsky算法,这个方法的实质是用到了向量的点乘运算,所以只用了很少的除法运算,这体现了这个算法的优越性;其次在编程过程中
19、由于设计上的问题所以直线的生成是用点击“确定”生成的,这是需要改进的地方!实验分项1多边形裁剪实验目的用Sutherland-Hodgman算法进行多边形裁剪实验要求1.将象素网格表现出来,建立网格坐标系2.用橡皮筋的形式输入剪裁线段 3.裁剪过程需先输入一多边形,然后用窗口四边裁剪的过程中要显示顶点增删的过程。实验原理步骤(算法流程)1.面板的初始化及裁剪框的生成: 方法:public void paintComponent(Graphics g) 画裁剪框: for(int j=0;j200;) g.setColor(Color.RED); g.fillRect(stx+j, sty, 5
20、, 5); g.fillRect(edx-j, edy, 5, 5); j=j+5; for(int j=0;j160;) g.setColor(Color.RED); g.fillRect(stx, sty+j, 5, 5); g.fillRect(edx, edy-j, 5, 5); j=j+5; 画像素格: for(int i=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.drawLi
21、ne(X_START,SPACE*(i-1)+Y_START,SPACE*(LINE-1)+X_START,SPACE*(i-1)+Y_START); 2.多边形的生成: mouseClicked方法中获取点击点的位置,当点击“确定”的时候把两点取出, 并画直线;实验原理步骤(算法流程) for(int i=0;icoor.size();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
22、).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) Graphics g = getGraphics(); changeLine(dinate,g);
23、所以整个裁剪过程就是调用了public void changeLine(ArrayList p,Graphics g)方法; 此方法的功能是:通过Barsky算法获得交点坐标,这个方法是画那些交点后形成的直线! while(it.hasNext() Coordinate point=(Coordinate)it.next(); pointXj = point.getX(); pointYj = point.getY(); j+; 多边形的裁剪结果是通过一下代码实现的:for(int i=0;ipointX.length;i+) g.drawLine(pointXi+8,pointYi+36,p
24、ointX(i+1)%p.size()+8,pointY(i+1)%p.size()+36); g.drawLine(pointXi+8,pointYi+36,pointX(i+1)%p.size()+8,pointY(i+1)%p.size()+36); g.drawLine(pointXi+6,pointYi+34,pointX(i+1)%p.size()+6,pointY(i+1)%p.size()+34); g.drawLine(pointXi+6,pointYi+34,pointX(i+1)%p.size()+6,pointY(i+1)%p.size()+34); g.drawLin
25、e(pointXi+4,pointYi+32,pointX(i+1)%p.size()+4,pointY(i+1)%p.size()+32); g.drawLine(pointXi+4,pointYi+32,pointX(i+1)%p.size()+4,pointY(i+1)%p.size()+32); 在drawLine方法只能够对坐标点进行了修正! (写不完时,可另加附页。)实验结果及分析1.剪切框已经给出,画出一个多边形,点击剪切即可看到效果:结果分析:在这次实验中,首先是裁剪框是给定的,虽然对整个程序处理上有所帮助,但是这是一个限制的边框,所以这是可以改进的地方,只是代码要变得复杂。其次直线的生成是经过先确定点,然后一次性画出的,这个方式不是很好,是可以通过每点击一次就重画来改进的;最后为了使多边形的裁剪过程清晰可见,并没有延续上一次的清屏的过程,直接在另一种颜色重新画了裁剪后的多边形;输出框中显示了整个多边形的裁剪过程!心得体会 这次的实验是对第三次实验直线的裁剪的扩展,而且整体的质量有所提高,首先了解了对多边形图形的裁剪过程,其次对算法有了一定的认识尤其是在通过不同方法的对比中评价算法的优越性!
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1