




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
图形学实验报告一.实验目的:1.理解并掌握中点画线算法的基本思想和算法实现在面板随意位置画线。2.理解并掌握中点画圆算法的基本思想和算法实现在面板以任意位置为圆心画半径任意的圆。3.理解并掌握裁剪直线的基本思想和算法实现在任意绘制的矩形中裁剪所画直线。实验内容:中点画线1.1基本原理:假定直线斜率|k|<=1,且已确定当前象素点P(Xp,Yp),然后确定下一个象素点,即T或B之一。M为T,B中点,Q为理想直线与栅格线的交点。若M在Q的下方,选T,否则选B。使用直线的正负划分性来判断M和Q的位置关系(即:F(x,y)=a*x+b*y+c=0)。然后构造判别式:d=F(M)=F(xp+1,yp+0.5)=a(xp+1)+b(yp+0.5)+c其中a=y0-y1,b=x1-x0,c=x0y1-x1y0当d<0,M在L(Q点)下方,取右上方T为下一个象素;当d>0,M在L(Q点)上方,取右方B为下一个象素;当d=0,选T或B均可,约定取B为下一个象素判断了M的位置之后则可以依次的画出各个点,从而得到一条直线。但是上面的这个算法存在浮点运算,所以将其乘以2去掉浮点运算,实现整数运算,提高效率。而对于|k|>1的情况,只需将x与y的位置对调考虑则很容易得到正确的算法实现。并且在本次的中点算法中可以绘制任意斜率的直线。1.2函数流程直线方程:a*x+b*y+c=0,p1(x1,y1),p2(x2,y2)==>a=y1-y2;b=x2-x1.点到直线的距离:distance=|a*x0-b*y0+c|/sqrt(a*a+b*b)
设directionX,directionY分别为从(x1,y1)==>(x2,y2)的单位变化量(+/-1)当直线偏向X轴时,当前象素为(xk,yk),下一个象素可能为:(xk+directionX,yk)或者(xk+directionX,yk+directionY)这两点到直线的距离分别为:
d1=|a*xk+b*yk+c+a*directionX|/sqrt(a*a+b*b);
d2=|a*xk+b*yk+c+a*directionX+b*directonY|/sqrt(a*a+b*b);
便于运算,定义:f(xk,yk)=d2*d2-d1*d1(将d1和d2的分母去掉了的)
=b*b+*b*directonY*(a*xk+b*yk+c+a*directionX);
当f(xk,yk)<0的时候,下一个点为(xk+directionX,yk+directionY):
f(xk+directionX,yk+directionY)=f(xk,yk)+2*b*b+2*a*b*directionX*directionY;
当f(xk,yk)>=0的时候,下一个点为(xk+directionX,yk):
f(xk+directionX,yk)=f(xk,yk)+2*a*b*directionX*directionY;当直线偏向Y轴时,当前象素为(xk,yk),下一个象素可能为:(xk,yk+directionY)或者(xk+directionX,yk+directionY)这两点到直线的距离分别为:d1=|a*xk+b*yk+c+b*directionY|/sqrt(a*a+b*b);
d2=|a*xk+b*yk+c+b*directionY+a*directonX|/sqrt(a*a+b*b);
便于运算,定义:f(xk,yk)=d2*d2-d1*d1(将d1和d2的分母去掉了的)
=a*a+*a*directonX*(a*xk+b*yk+c+b*directionY);
当f(xk,yk)<0的时候,下一个点为(xk+directionX,yk+directionY):
f(xk+directionX,yk+directionY)=f(xk,yk)+2*a*a+2*a*b*directionX*directionY;
当f(xk,yk)>=0的时候,下一个点为(xk+directionX,yk):
f(xk+directionX,yk)=f(xk,yk)+2*a*b*directionX*directionY;1.3截图中点画圆2.1基本原理:对于圆上的点,F(x,y)=0;对于圆外的点,F(x,y)>0;而对于圆内的点,F(x,y)<0。假设M是P1和P2的中点,即M=(xp+1,yp-0.5)。那么,当F(M)<0时,M在圆内,这说明P1距离圆弧更近,应取P1作为下一像素。而当F(M)>0时,P2离圆弧更近,应取P2。当F(M)=0时,在P1与P2之中随便取一个即可,我们约定取P2。与中点画线法一样,构造判别式d=F(M)=F(xp+1,yp-0.5)=(xp+1)2+(yp-0.5)2-R2若d<0,则应取P1为下一像素,而且再下一个像素的判别式为d=F(xp+2,yp-0.5)=(xp+2)2+(yp-0.5)2-R2=d+2xp+3所以,沿正右方向,d的增量为2xp+3。而若d≥0,则P2是下一像素,而且下一像素的判别式为d'=F(xp+2,yp–1.5)=(xp+2)2+(yp–1.5)2–R2=d+(2xp+3)+(–2yp+2)所以,沿右下方向,判别式d的增量为2(xp–yp)+5。由于我们这里讨论的是按顺时针方向生成第二个8分圆,因此,第一像素是(0,R),判别量d的初始值为:d0=F(l,R–0.5)=1+(R–0.5)2–R2=1.25–R设则判别量的初值为递推公式中其他与d有管的狮子可以直接换成所以圆心位于原点的圆有四条对称轴x=0、y=0、x=y和x=-y。从而若已知圆弧上一点P(x,y),就可以得到其关于四条对称轴的七个对称点,这种性质称为八分对称性。因此只要能画出八分之一的圆弧,就可以利用对称性的原理得到整个圆弧。2.2截图直线剪裁3.1基本原理:裁剪窗口:矩形区域若线段两端点均落在窗口内:线段可见;.若线段两端点分别落在窗口的内外两侧:计算线段与窗口边界的交点(1个),确定可见部分线段;.若线段两端点均落在窗口外:计算线段与窗口交点(0个或2个),若无交点,则线段不可见,否则线段部分可见。分别记线段端点P1,P2的编码为code1,code2,当P1,P2均在窗口内:code1=0000且code2=0000;P1,P2在同一边框线外:code1[i]=code2[i]=1,i=1,2,3,4;即code1&code2!=0000,其它code1&code2=0000;code1!=0000或code2!=0000利用中点分割法并采用迭代方法找到距端点最近的可见点进行剪裁3.2流程图3.3截图附录
:代码:MAINFRAMEimportjava.awt.*;importjavax.swing.*;importjava.awt.event.*;importjavax.swing.event.*;importjavax.swing.border.*;publicclassMainFrameextendsJFrame{ MainFrame(){ Containerc=getContentPane(); drawPanel=newPanelEX(this,730,540); mainPanel=newJPanel(); mainPanel.setLayout(newGridBagLayout()); ctrlPanel=newJPanel(); ctrlPanel.setLayout(newBoxLayout(ctrlPanel,BoxLayout.Y_AXIS)); initButtonPanel(); ctrlPanel.add(buttonPanel);gridBagConstraints=newGridBagConstraints();mainPanel.add(ctrlPanel,gridBagConstraints);gridBagConstraints.insets=newInsets(5,5,15,5);add(mainPanel,BorderLayout.WEST); add(drawPanel,BorderLayout.CENTER); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);setTitle("画线圆剪裁——ZXJ");setSize(885,572);show(); } voidinitButtonPanel(){ buttonPanel=newJPanel();JPanelt=newJPanel(newGridLayout(6,1,6,6)); ButtonGroupbg=newButtonGroup(); line=newJToggleButton(); line.setFont(newFont("Dialog",0,30)); line.setSelected(true); line.setText("画线"); line.addActionListener(newActionListener(){ publicvoidactionPerformed(ActionEvente){ drawPanel.setOperate(PanelEX.DrawLine); } }); bg.add(line); t.add(line);clip=newJToggleButton(); clip.setFont(newFont("Dialog",0,30)); clip.setText("裁剪"); clip.addActionListener(newActionListener(){ publicvoidactionPerformed(ActionEvente){ drawPanel.setOperate(PanelEX.SegmentClip); } }); bg.add(clip); t.add(clip);circle=newJToggleButton(); circle.setFont(newFont("Dialog",0,30)); circle.setText("画圆"); circle.addActionListener(newActionListener(){ publicvoidactionPerformed(ActionEvente){ drawPanel.setOperate(PanelEX.drawcircle); } }); bg.add(circle); t.add(circle); clear=newJButton(); clear.setFont(newFont("Dialog",0,30)); clear.setText("清屏"); clear.addActionListener(newActionListener(){ publicvoidactionPerformed(ActionEvente){ drawPanel.clear(); } }); t.add(clear);buttonPanel.add(t); } publicstaticvoidmain(Stringargs[]){ try{ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); }catch(Exceptione){ e.printStackTrace(); } newMainFrame(); } JPanelmainPanel; JPanelctrlPanel; JPanelbuttonPanel; JToggleButtonline; JToggleButtoncircle; JToggleButtonclip; JButtonclear; GridBagConstraintsgridBagConstraints; PanelEXdrawPanel;}PANELEX
:importjava.awt.*;importjava.awt.image.*;importjavax.swing.*;importjava.awt.event.*;importjavax.swing.event.*;importjavax.swing.border.*;importjava.math.*;publicclassPanelEXextendsJPanelimplementsMouseMotionListener,MouseListener{PanelEX(MainFramemf,intwidth,intheight)//绘制画图面板{this.mf=mf;xmin=ymin=0;xmax=width;ymax=height;resetSize(width,height);circle=newCircleOP(this);clip=newClipOP(this);clip.setClipRect(0,0,width,height);line=newLineOP(this,clip);addMouseListener(this);addMouseMotionListener(this);}publicvoidmousePressed(MouseEvente)//鼠标压下获取当前位置{if(e.getButton()==MouseEvent.BUTTON1){xstart=xcurrent=e.getX();ystart=ycurrent=e.getY();}}publicvoidmouseDragged(MouseEvente)//鼠表拖动,根据不同情况有不同处理方式{switch(currentOperate){caseDrawLine://画线鼠标拖动过程中获取坐标并且将拖动过程显示line.pushBack(xstart,ystart,xcurrent,ycurrent);xcurrent=e.getX();ycurrent=e.getY();line.pushForward(xstart,ystart,xcurrent,ycurrent);break;casedrawcircle://画圆鼠标拖动过程中获取坐标计算半径并且将拖动过程显示intradix=(int)Math.sqrt((xstart-xcurrent)*(xstart-xcurrent)+(ystart-ycurrent)*(ystart-ycurrent));circle.pushBack(xstart,ystart,radix);xcurrent=e.getX();ycurrent=e.getY();radix=(int)Math.sqrt((xstart-xcurrent)*(xstart-xcurrent)+(ystart-ycurrent)*(ystart-ycurrent));circle.pushForward(xstart,ystart,radix);break;caseSegmentClip://剪裁由于剪裁的为直线,所以类似直线clip.pushBack(xstart,ystart,xcurrent,ycurrent);xcurrent=e.getX();ycurrent=e.getY();clip.pushForward(xstart,ystart,xcurrent,ycurrent);break;}}publicvoidmouseReleased(MouseEvente)//松开鼠标{if(e.getButton()!=MouseEvent.BUTTON1){return;}if(currentOperate==DrawLine)//根据中点画线方法画线{line.pushBack(xstart,ystart,xcurrent,ycurrent);line.MidPoint(xstart,ystart,e.getX(),e.getY());}if(currentOperate==drawcircle)//根据中点画圆方法画圆{intradix=(int)Math.sqrt((xcurrent-xstart)*(xcurrent-xstart)+(ycurrent-ystart)*(ycurrent-ystart));circle.pushBack(xstart,ystart,radix);radix=(int)Math.sqrt((e.getX()-xstart)*(e.getX()-xstart)+(e.getY()-ystart)*(e.getY()-ystart));circle.MidPoint(xstart,ystart,radix);}if(currentOperate==SegmentClip)//剪裁{clip.pushBack(xstart,ystart,xcurrent,ycurrent);if(xstart>e.getX())//获取xmin,xmax,ymin,ymax绘制剪裁矩形{xmin=e.getX();xmax=xstart;}else{xmin=xstart;xmax=e.getX();}if(ystart>e.getY()){ymin=e.getY();ymax=ystart;}else{ymin=ystart;ymax=e.getY();}if(xmin<0){xmin=0;}if(xmax>width){xmax=width;}if(ymin<0){ymin=0;}if(ymax>height){ymax=height;}clip.drawRectBoth(xmin,ymin,xmax,ymax);clip.setClipRect(xmin,ymin,xmax,ymax);}}publicvoidmouseMoved(MouseEvente){}voidresetSize(intwidth,intheight){//绘图面板if(this.width==width&&this.height==height){return;}this.width=width;this.height=height;bi=newBufferedImage(width,height,BufferedImage.TYPE_INT_RGB);g2=(Graphics2D)bi.getGraphics();g2.setColor(Color.white);g2.fillRect(0,0,width,height);g2.dispose();setSize(width,height);}publicvoidclear()//清屏{g2=(Graphics2D)bi.getGraphics();g2.setColor(Color.white);g2.fillRect(0,0,width,height);g2.dispose();paint(getGraphics());}publicvoidpaint(Graphicsg){g.drawImage(bi,0,0,width,height,this);}publicvoidupdate(Graphicsg){paint(g);}publicvoidstop(){}publicvoidsetOperate(intop){currentOperate=op;needConnectPoint=false;}publicvoidmouseClicked(MouseEvente){}publicvoidmouseEntered(MouseEvente){}publicvoidmouseExited(MouseEvente){}MainFramemf;BufferedImagebi;LineOPline;ClipOPclip;CircleOPcircle;Graphics2Dg2;intxstart;intystart;intxcurrent;intycurrent;intxend;intyend;privateintxmin;privateintymin;privateintxmax;privateintymax;intwidth=0;intheight=0;intcurrentOperate=DrawLine;Colorcolor;booleanneedConnectPoint=false;publicstaticfinalintDrawLine=1;publicstaticfinalintdrawcircle=2;publicstaticfinalintSegmentClip=4;}DRAWOP
:importjava.awt.*;importjava.awt.image.*;importjavax.swing.*;importjava.awt.event.*;importjavax.swing.event.*;importjavax.swing.border.*;importjava.math.*;publicclassDrawOP{ PanelEXp; intDelayTime; booleanDelay; Colorcolor; Colort; BufferedImagebi; Graphicsg; booleanstop; Graphics2Dg2; intmask=0; intRGB; publicstaticfinalintPUSHBACK=1; publicstaticfinalintXOR=2; publicstaticfinalintONSCREEN=4; publicstaticfinalintBOTH=8; DrawOP(PanelEXp) {this.p=p; stop=false; DelayTime=0; color=Color.black;} publicvoidinitGraphics(){ g=p.getGraphics(); bi=p.bi; g2=(Graphics2D)bi.getGraphics(); g.setColor(color); g2.setColor(color); } publicintgetPixel(intx,inty){ returnbi.getRGB(x,y); } publicvoidsetMask(intm){ mask=m; } publicvoidsetDelay(){ Delay=true; } publicvoidclrDelay(){ Delay=false; } publicvoidsetColor(Colorc){ color=c; } publicvoidsetDelayTime(intt){ DelayTime=t; } publicvoidstop(){ stop=true; } publicvoidstart(){ stop=false; } voidsetPixel(intx,inty){ if(x>=p.width||x<=0||y>=p.height||y<=0)return; if(mask==ONSCREEN){ g.drawLine(x,y,x,y); } elseif(mask==PUSHBACK){ RGB=bi.getRGB(x,y); t=newColor(RGB); g.setColor(t); g.drawLine(x,y,x,y); } elseif(mask==XOR){ intti; RGB=bi.getRGB(x,y); ti=color.getRGB(); t=newColor(ti^RGB); g.setColor(t); g.drawLine(x,y,x,y); g2.setColor(t); g2.drawLine(x,y,x,y); } else{ g.drawLine(x,y,x,y) ; g2.drawLine(x,y,x,y); } if(Delay==false)return; try{ Thread.sleep(DelayTime); }catch(InterruptedExceptione){} }}LIENEX
:publicclassLineEX{ intys,ye; doublexs,ki;//ki为斜率 publicintx1,y1,x2,y2; LineEXnext; LineEX(){ } LineEX(intx1,inty1,intx2,inty2){ this.x1=x1; this.x2=x2; this.y1=y1; this.y2=y2; if(y1<y2) {ys=y1; ye=y2; xs=x1; ki=(double)(x1-x2)/(y1-y2);} elseif(y1>y2){ ys=y2; ye=y1; xs=x2; ki=(double)(x1-x2)/(y1-y2); } Else{ ys=-1; ki=0; } next=null; }}LINEOPimportjava.awt.*; importjava.awt.image.*; importjavax.swing.*;importjava.awt.event.*; importjavax.swing.event.*; importjavax.swing.border.*;importjava.math.*;publicclassLineOPextendsDrawOP{ ClipOPclip; LineEXclipSeg; LineEXl; LineOP(PanelEXp,ClipOPclip){ super(p); this.clip=clip; } publicvoidMidPoint(intx1,inty1,intx2,inty2){ l=clip.clip(x1,y1,x2,y2); if(l==null)return; else{ x1=l.x1; y1=l.y1; x2=l.x2; y2=l.y2; } setDelay(); setMask(LineOP.BOTH); initGraphics(); drawLineM(x1,y1,x2,y2); } publicvoidpushBack(intx1,inty1,intx2,inty2){ clrDelay(); setMask(LineOP.PUSHBACK); initGraphics(); drawLineM(x1,y1,x2,y2); } publicvoidpushForward(intx1,inty1,intx2,inty2){ clrDelay(); setMask(LineOP.ONSCREEN); initGraphics(); drawLineM(x1,y1,x2,y2); } publicvoiddrawLineM(intstartX,intstartY,intendX,intendY){inta,b; a=startY-endY; b=endX-startX; intiDirectionX,iDirectionY; iDirectionX=iDirectionY=1; if(b<0) iDirectionX=-1;//iDirectionX,iDirectionY分别为从(x1,y1)==>(x2,y2)的单位变化量(+/-1) if(a>0) iDirectionY=-1; intiDistance;//distance为点到直线的距离intiDeltaSmall,iDeltaBig,iCurrX,iCurrY; intiStep; iDeltaSmall=2*a*b*iDirectionX*iDirectionY;//2ab iCurrX=startX; iCurrY=startY; if(Math.abs(b)>Math.abs(a))//abs:求绝对值 { iDeltaBig=2*b*b+iDeltaSmall; iDistance=b*b+iDeltaSmall; iStep=Math.abs(b); while(iStep-->0) { setPixel(iCurrX,iCurrY); iCurrX+=iDirectionX; if(iDistance<0) {iCurrY+=iDirectionY; iDistance+=iDeltaBig; } else { iDistance+=iDeltaSmall; } } } else { iDeltaBig=2*a*a+iDeltaSmall; iDistance=a*a+iDeltaSmall; iStep=Math.abs(a); while(iStep-->0) { setPixel(iCurrX,iCurrY); iCurrY+=iDirectionY; if(iDistance<0) { iCurrX+=iDirectionX; iDistance+=iDeltaBig; } else { iDistance+=iDeltaSmall; } } } setPixel(iCurrX,iCurrY); }} CIRCLEOPimportjava.awt.*; importjava.awt.image.*; importjavax.swing.*;importjava.awt.event.*; importjavax.swing.event.*; importjavax.swing.border.*;importjava.math.*;publicclassCircleOPextendsDrawOP{ CircleOP(PanelEXp){ super(p); }publicvoidpushBack(intx,inty,intr){ clrDelay(); setMask(CircleOP.PUSHBACK); initGraphics();drawCircleM(x,y,r); }publicvoidpushForward(intx,inty,intr){ clrDelay(); setMask(CircleOP.ONSCREEN); initGraphics(); drawCircleM(x,y,r); } publicvoidMidPoint(intx,inty,intr){ setDelay(); setMask(CircleOP.BOTH); initGraphics(); drawCircleM(x,y,r); }publicvoiddrawCircleM(intox,intoy,intr){ doubled=1-r; intx=0,y=r; while(x<y){ setPixel(x+ox,y+oy);//用来显示P(x,y)及其七个对称点。 setPixel(x+ox,-y+oy); setPixel(-x+ox,y+oy); setPixel(-x+ox,-y+oy); setPixel(y+ox,x+oy); setPixel(y+ox,-x+oy); setPixel(-y+ox,x+oy); setPixel(-y+ox,-x+oy); if(d<0){ x++; d=d+2*x+1; } Else{ x++; y--; d=d+2*x+1-2*y; } }}}CLIPOPimportjava.awt.*; importjava.awt.image.*; importjavax.swing.*;importjava.awt.event.*; importjavax.swing.event.*; importjavax.swing.border.*;importjava.math.*;publicclassClipOPextendsDrawOP{ intxmin,ymin,xmax,ymax; privatefinalintxminmask=8; privatefinalintxmaxmask=2; privatefinalintyminmask=4; privatefinalintymaxmask=1;publicstaticfinalintMidPoint=3; ClipOP(PanelEXp){ super(p); } publicLineEXclip(intx1,inty1,intx2,inty2){ returnclipMidPoint(x1,y1,x2,y2); } privateintgetCode(intx,inty)//完成对线段端点的编码过程。{ intcode=0; if(x>xmax) code|=xmaxmask; elseif(x<xmin) code|=xminmask; if(y>ymax)code|=ymaxmask; elseif(y<ymin)code|=yminmask; returncode; } privateLineEXclipPart(intx1,inty1,intx2,inty2)//利用中点分割法并采用迭代方法找到距端点最近的可见点{ intxm,ym,codem; intxt=x1,yt=y1; xm=(x1+x2)/2;//m为线段的中点 ym=(y1+y2)/2; codem=getCode(xm,ym);//获取线段中点m的编码 while(true){ if(codem!=0)//线段中点m在剪裁区域外{ x2=xm;//把中点m赋为终点P2 y2=ym; xm=(x1+x2)/2;//再重新取终点m ym=(y1+y2)/2; codem=getCode(xm,ym);//获取线段中点m的编码 if((xm==x2)&&(ym==y2))returnnewLineEX(xt,yt,x1,y1); } else//线段中点m在剪裁区域内{ x1=xm;//把中点m赋为起点P1 y1=ym; xm=(x1+x2)/2;//再重新取终点m ym=(y1+y2)/2; codem=getCod
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030中国纸尿裤行业市场深度调研及前景趋势与投资研究报告
- 2025-2030中国纯聚酯短纤维行业市场发展趋势与前景展望战略研究报告
- 2025-2030中国纤维素涂料行业市场现状供需分析及投资评估规划分析研究报告
- 2025-2030中国红枣汁行业市场深度调研及发展趋势和投资前景预测研究报告
- 2025-2030中国紧凑型数字万用表行业市场发展趋势与前景展望战略研究报告
- 二年级数学(上)计算题专项练习
- 一年级数学(上)计算题专项练习汇编
- 井内排水施工方案
- 生命教育与生态保护结合的教学计划
- 素混凝土回填施工方案
- 2024年其他资格考试-注册可靠性工程师笔试历年真题荟萃含答案
- 《思想道德与法治(2023版)》课程标准
- 混凝土行业投资建议分析报告
- 小沈龙脱口秀台词
- 空调设备巡检报告
- 餐饮服务食品安全操作规范试题测试题库含答案
- 剪辑拍摄培训课件
- 小学科技小制作知识讲座
- 电子商务仓库管理培训课程培训课件
- 阿瑞匹坦注射液-临床用药解读
- 民事案例实例分析课件
评论
0/150
提交评论