计算机图形学实验报告实验2裁剪算法实验

时间:2024.4.14

一、实验目的:

直线段的裁剪:编码裁剪算法,中点分割裁剪算法。

二、实验内容:

//BasicGraph.cpp

//请将下列裁剪程序补充完整,并用注释说明是何种裁剪算法

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((RIGHT&code)!=0)

         {x=XR;y=y1+(y2-y1)*(XR-x1)/(x2-x1);}

        if((BOTTOM&code)!=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;

}

int IsInArea(POINT point,int XL,int XR,int YB,int YT)

{

   //请将此程序补充完整

     if(point.x>=XL && point.x<=XR && point.y>YB && point.y<YT) return 1;

     else return 0;

}

int NotIntersect(POINT begin,POINT end,int XL,int XR,int YB,int YT)

{

    //请将此程序补充完整

      int maxx,maxy,minx,miny;

      maxx=(begin.x>end.x)?begin.x:end.x;

      minx=(begin.x<end.x)?begin.x:end.x;

      maxy=(begin.y>end.y)?begin.y:end.y;

      miny=(begin.y<end.y)?begin.y:end.y;

      if(maxx<XL|| minx>XR||maxy<YB||miny>YT) return 1;

      else return 0;

}

//中点裁剪算法:

POINT ClipMid(POINT begin,POINT end,int XL,int XR,int YB,int YT)

{

   //请将此程序补充完整

     POINT mid,temp;

   if(IsInArea(begin,XL,XR,YB,YT)) temp=begin;

     else if(NotIntersect(begin,end,XL,XR,YB,YT)) temp=begin;

   else

   {

    mid.x=(begin.x+end.x)/2;mid.y=(begin.y+end.y)/2;

    if(abs(mid.x-end.x)<=1&& abs(mid.y-end.y)<=1) temp=mid;

    else

    {

    if(NotIntersect(begin,mid,XL,XR,YB,YT))

       temp=ClipMid(mid,end,XL,XR,YB,YT);

    else

       temp=ClipMid(begin,mid,XL,XR,YB,YT);

    }

   }

   return temp;

  

}

//Liang-Barsky直线裁剪算法:

void ClipParameter(POINT &p1,POINT &p2,int XL,int XR,int YB,int YT)

{  

    float u1=0.0,u2=1.0;

    float dx=p2.x-p1.x,dy=p2.y-p1.y;

    if(clipTest(-dx,p1.x-XL,&u1,&u2))

       if(clipTest(dx,XR-p1.x,&u1,&u2))

          if(clipTest(-dy,p1.y-YB,&u1,&u2))

            if(clipTest(dy,YT-p1.y,&u1,&u2))

            {

              if(u2<1.0)

              {

                  p2.x=p1.x+u2*dx;

                  p2.y=p1.y+u2*dy;

              }

               if(u1>0.0)

              {

                  p1.x=p1.x+u1*dx;

                  p1.y=p1.y+u1*dy;

              }

            }

}

int clipTest(float p,float q,float *u1,float *u2)

{

    float r;

    int remainFlag=1;

    if(p<0.0)

    {

       r=q/p;

       if(r>*u2) remainFlag=0;

       else if(r>*u1) *u1=r;

    }

    else if(p>0.0)

    {

       r=q/p;

       if(r<*u1) remainFlag=0;

       else if(r<*u2) *u2=r;

    }

    else  //*p=0

       if(q<0.0) remainFlag=0;

    return remainFlag;

}

//逐边裁剪算法:

//typedef struct tRes { int yes,isIn; POINT pout;} Res;

Res TestIntersect(int edge,int type,POINT p1,POINT p2)

{//判断p2是否在所裁剪的窗边edge的内侧,是否与p1点分别在窗边edge的异侧

    float dx,dy,m;

    Res res;int isIn=0,yes=0;POINT pout;

    dy=p2.y-p1.y;dx=p2.x-p1.x;m=dy/dx;

    switch(type)

    {

    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;

    default: break;

    }

    if(yes)

    {

        if((type==1) || (type==3))

       {   pout.x=edge;pout.y=p1.y+m*(pout.x-p1.x);}

        if((type==2) || (type==4))

       {   pout.y=edge;pout.x=p1.x+(pout.y-p1.y)/m;}

    }

    res.isIn=isIn;res.yes=yes;res.pout=pout;

    return res;

}

int clipSingleEdge(int edge,int type,int nin,POINT pin[50],POINT pout[50])

/*对多边形pin与窗边edge进行裁剪,返回裁剪后的多边形pout及点数*/

{

    int i,k=0;POINT p;Res res;

    p.x=pin[nin-1].x;p.y=pin[nin-1].y;

    for(i=0;i<nin;i++)

    {

        res=TestIntersect(edge,type,p,pin[i]);

        if(res.yes)

       {   pout[k].x=res.pout.x;pout[k].y=res.pout.y;k++;}

        if(res.isIn)

       {   pout[k].x=pin[i].x;pout[k].y=pin[i].y;k++;}

        p.x=pin[i].x;p.y=pin[i].y;

    }

    return k;

}

void ClipEdgePolygon(POINT ps[50],int &n,int XL,int XR,int YB,int YT)

{  /*对多边形ps进行逐边裁剪*/

    int n1=0,n2=0;

    POINT pt[50];

    n1=clipSingleEdge(XR,1,n,ps,pt);

    n2=clipSingleEdge(YB,2,n1,pt,ps);

    n1=clipSingleEdge(XL,3,n2,ps,pt);

    n2=clipSingleEdge(YT,4,n1,pt,ps);

    n=n2;

}

//多边形编码裁剪算法:

void ClipEncodePolygon(POINT ps[50],int &n,int XL,int XR,int YB,int YT)

{

    POINT tp[50];

    int k=0,m;

    int code1,code2,code;

    int x,y;

    for(int i=0;i<n-1;i++)

    {

        Encode(ps[i].x,ps[i].y,&code1,XL,XR,YB,YT);

        Encode(ps[i+1].x,ps[i+1].y,&code2,XL,XR,YB,YT);

       code=code1;m=i;

        for(int j=0;j<2;j++)

       {

         if((code1 & code2)!=0)  //线段两端都在窗口外的同一侧

         {

             switch(code)

             {

             case 1:x=XL;y=ps[m].y;break;

              case 2:x=XR;y=ps[m].y;break;

             case 4:x=ps[m].x;y=YB;break;

             case 5:x=XL;y=YB;break;

             case 6:x=XR;y=YB;break;

             case 8:x=ps[m].x;y=YT;break;

             case 9:x=XL;y=YT;break;

             case 10:x=XR;y=YT;break;

             }

             tp[k].x=x;tp[k].y=y;k++;

         }

         else if((code1 & code2)==0)  //线段两端不在窗口的同一侧

         {

             if(code==0)

             {

                tp[k]=ps[m];k++;

             }

             else if ((LEFT & code) !=0)  //线段与左边界相交

             {

                x=XL;

                 y=ps[i].y+(ps[i+1].y-ps[i].y)*(XL-ps[i].x)/(ps[i+1].x-ps[i].x);

                 if(y>YB && y<YT){tp[k].x=x;tp[k].y=y;k++;}

             }

             else if((TOP & code)!=0)   //线段与上边界相交

             {

                 y=YT;

                 x=ps[i].x+(ps[i+1].x-ps[i].x)*(YT-ps[i].y)/(ps[i+1].y-ps[i].y);

                 if(x>XL && x<XR){tp[k].x=x;tp[k].y=y;k++;}

             }

             else if((RIGHT & code)!=0)   //线段与右边界相交

             {

                 x=XR;

                 y=ps[i].y+(ps[i+1].y-ps[i].y)*(XR-ps[i].x)/(ps[i+1].x-ps[i].x);

                 if(y>YB && y<YT){tp[k].x=x;tp[k].y=y;k++;}

             }

             else if((BOTTOM & code) != 0)  //线段与下边界相交

             {

                 y=YB;

                 x=ps[i].x+(ps[i+1].x-ps[i].x)*(YB-ps[i].y)/(ps[i+1].y-ps[i].y);

                 if(x>XL && x<XR){tp[k].x=x;tp[k].y=y;k++;}

             }

         }

         code=code2;m++;

       }//for(j)

    }//for(i)

    for(i=0;i<k;i++)

       ps[i]=tp[i];

    n=k;

}

//函数的调用,裁剪窗口的调整

//DrawView.cpp文件

//裁剪窗口的调整

CDrawView::CDrawView()

{

/************请在此函数中将裁剪窗口大小调整为长度100单位像素,宽度50单位像素的矩形********/

    // TODO: add construction code here

//

    m_pWidth=1;

    m_pStyle=PEN_STYLE_SOLID;

    m_pColor=RGB(0,0,0);

    m_FFlag=0;

    m_FColor=RGB(0,0,0);

    m_HFlag=0;

    CurrentDraw=DRAW_VCLINE;

    m_Num=0;

    m_Drag=0;

    m_HCursor=AfxGetApp()->LoadStandardCursor(IDC_CROSS);

//

    DrawType=0;

    ClipFlag=0;

    ClipType=-1;

    XL=200;XR=300;YB=150;YT=200;

//XL=200;XR=500;YB=150;YT=400;

    ClipWindowColor=RGB(192,192,50);

}

void CDrawView::OnDraw(CDC* pDC)

{

    CDrawDoc* pDoc = GetDocument();

    ASSERT_VALID(pDoc);

    // TODO: add draw code for native data here

    if(ClipFlag)

    {

       CPen NewPen,*pOldPen;

       NewPen.CreatePen(PS_DASH,1,ClipWindowColor);

       pOldPen=pDC->SelectObject(&NewPen);

       pDC->MoveTo(XL,YB);

       pDC->LineTo(XR,YB);

        pDC->LineTo(XR,YT);

        pDC->LineTo(XL,YT);

        pDC->LineTo(XL,YB);

    }

    int index;

    index=pDoc->GetShapeNumber();

    for(int i=0;i<index;i++)

       pDoc->GetShape(i)->Drawing(pDC);

}

void CDrawView::OnInitialUpdate()

{

    CSize sizeTotal;

    sizeTotal.cx = 640;  sizeTotal.cy = 480;

    SetScrollSizes(MM_TEXT, sizeTotal);

    // TODO: Add your specialized code here and/or call the base class

   

}

void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)

{

    // TODO: Add your message handler code here and/or call default

    CClientDC dc(this);

    OnPrepareDC(&dc);

    dc.DPtoLP(&point);

   

       m_pPrev=point;

        m_pOrigin=point;    //点击鼠标左键作为拖动绘图的第一点

        m_Drag=1;

    SetCapture();

    RECT rect;

    GetClientRect(&rect);

    ClientToScreen(&rect);

    ClipCursor(&rect);

   

    CScrollView::OnLButtonDown(nFlags, point);

}

//函数调用处

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{

    // TODO: Add your message handler code here and/or call default

    if(m_Drag)

    {

        m_Drag=0;

       ReleaseCapture();

       ClipCursor(NULL);

        CDrawDoc *pDoc=GetDocument();

        CShape *pShape;

       POINT p1,p2;

       if(CurrentDraw==DRAW_VCLINE || CurrentDraw==DRAW_DDALINE ||

          CurrentDraw==DRAW_MIDLINE || CurrentDraw==DRAW_BSHLINE)

       {

           if(ClipFlag)

           {

              switch(ClipType)

              {

/****************编码裁剪函数调用处*************/

case CLIP_ENCODE:C_S_Line(m_pOrigin,m_pPrev,XL,XR,YB,YT); break;

/****************中点分割裁剪函数调用处************/

case CLIP_MIDPOINT: ClipMid(m_pPrev,m_pOrigin,XL,XR,YB,YT);

                  p1=ClipMid(m_pPrev,m_pOrigin,XL,XR,YB,YT);

                  p2=ClipMid(m_pOrigin,m_pPrev,XL,XR,YB,YT);

                  m_pOrigin=p1;m_pPrev=p2;

                  break;

case CLIP_PARAMETER:ClipParameter(m_pOrigin,m_pPrev,XL,XR,YB,YT);

break;

              }

           }

              pShape=new CLine(m_pOrigin,m_pPrev,m_pWidth,m_pStyle,m_pColor,DrawType);

           pDoc->AddShape(pShape);

       }

       if(CurrentDraw==DRAW_RECTANGLE)

       {

           if(ClipType==CLIP_WINDOW)

           {

              XL=m_pOrigin.x;XR=m_pPrev.x;

                YB=m_pOrigin.y;YT=m_pPrev.y;

           }

           else

           {

               pShape=new CRectangle(m_pOrigin,m_pPrev,m_pWidth,m_pStyle,m_pColor,

                  m_FFlag,m_FColor,m_HFlag,m_Hatch);

               pDoc->AddShape(pShape);

           }

       }

       if( CurrentDraw==DRAW_VCCIRCLE || CurrentDraw==DRAW_MIDCIRCLE ||

               CurrentDraw==DRAW_BSHCIRCLE)

       {

           pShape=new CCircle(m_pOrigin,m_pPrev,m_pWidth,m_pStyle,m_pColor,

               m_FFlag,m_FColor,m_HFlag,m_Hatch,DrawType);

           pDoc->AddShape(pShape);

       }     

       if(CurrentDraw==DRAW_VCELLIPSE || CurrentDraw==DRAW_MIDELLIPSE)

       {

           pShape=new CEllipse(m_pOrigin,m_pPrev,m_pWidth,m_pStyle,m_pColor,

               m_FFlag,m_FColor,m_HFlag,m_Hatch,DrawType);

           pDoc->AddShape(pShape);

       }

       pDoc->UpdateAllViews(NULL);

    }

   

    CScrollView::OnLButtonUp(nFlags, point);

}

三实验结果:

四、实验总结

通过这次试验使我了解到如何运用计算机程序对窗口进行剪裁,了解到编码剪裁算法直观方便,速度较快,中点分割剪裁算法不用进行乘除运算,剪裁效率高,Liang-Barsky直线裁剪算法更快。

更多相关推荐:
计算机图形学实验报告

福建农林大学计算机与信息学院课程名称姓名系专业年级学号指导教师职称实验报告计算机图形学洪世玉计算机计算机科学与技术10级102260010072李小林20xx年11月19日实验项目列表福建农林大学计算机与信息学...

计算机图形学实验(全)

实验1直线的绘制实验目的1通过实验进一步理解和掌握DDA和Bresenham算法2掌握以上算法生成直线段的基本过程3通过编程会在TC环境下完成用DDA或中点算法实现直线段的绘制实验环境计算机TurboC或其他C...

计算机图形学实验报告及代码

第1章概述一教学目标通过本章的学习使学生能够了解计算机图形学的基本概念研究内容当前的发展概况本门课程的特点和应用二教学要求1了解计算机图形学的概念和研究内容2了解本门课程的发展概况三教学内容提要1计算机图形学的...

计算机图形学实验报告

计算机图形学实验报告河南理工大学测绘学院计算机图形学实验报告学号姓名成绩评语交报告日期20xx年6月25日计算机图形学实验报告实验项目一图形学光栅化算法验证实验实验日期20xx年6月5日一实验目的1加强对直线圆...

计算机图形学实验报告

实验报告实验课程计算机图形学学生姓名XXXX学号专业班级软件20xx年12月25日目录i实验一矩阵变换ii实验二图形绘制iii实验三曲线的生成算法实现iv实验四二维基本图形生成的算法v实验五二维填充图的生成算法...

计算机图形学实验报告

班级10计科姓名敖智挺学号20xx30457117实验一直线生成与二次曲线拟合实验内容应用Bresenham画线算法实现一程序完成直线生成实验目的了解掌握VC下D图元的扫描转换原理及VC实现掌握图元属性原理及V...

计算机图形学实验报告

计算机图形学实验报告学号20xx2115姓名班级计算机2班指导老师何太军20xx619实验一Windows图形程序设计基础1实验目的1学习理解Win32应用程序设计的基本知识SDK编程2掌握Win32应用程序的...

计算机图形学实验报告20xx

计算机图形学课程实验报告实验题目班级姓名学号指导教师日期信息与计算机工程学院20xx实验2基本图形生成算法21直线的绘制一实验目的1通过实验进一步理解和掌握DDA和Bresenham算法2掌握以上算法生成直线段...

计算机图形学实验_透视茶壶源代码

includeltwindowshgtincludeltglgluthgtincludeltglglhgtusingnamespacestdfloatfTranslatefloatfRotatefloatfSc...

计算机图形学 实验 利用OpenGL实现图形的平移、旋转、缩放

实验名称利用OpenGL实现图形的平移旋转缩放实验时间年月日专业姓名学号预习操作座位号教师签名总评一实验目的1了解OpenGL下简单图形的平移旋转缩放变换的编程的基本思想2掌握OpenGL下简单图形的平移旋转缩...

计算机图形学实验

simplecpp黑色背景下画白色矩形includequotstdlibhquotincludequotGLgluthquotvoidinitglClearColor00000010清除背景并设为黑色glCol...

湖北工业大学计算机图形学实验代码及截图

计算机图形学OpenGL实验指导书1目录实验一OpenGL基础知识1实验二OpenGL中的建模与变换2实验三OpenGL中的光照5实验四OpenGL中的拾取8实验五OpenGL中的纹理映射112实验一OpenG...

计算机图形学实验报告(45篇)