二维图形变换

                               二维图形变换

一.目的:

      1.了解不同的二维坐标变换公式。

      2.掌握二维坐标变换公式的使用方法。

      3.掌握二维图形的基本几何变换:平移、旋转和缩放。

 

二.要求:

      1.在屏幕上绘制出较简单的几何图形。

      2.对1的图形进行平移变换(每次平移一个单位),绘制出变换后的几何图形。

      3.对1的图形进行旋转变换(每次旋转角度为3.14/36),绘制出变换后的几何图形。

      4.对1的图形进行比例变换(横纵坐标变换比例为0.5或2),绘制出变换后的几何图形。

三.原理和关键算法:

     1.  编辑一个资源,并为其映射一个类cgTransControl。

     2.  在Doc下,定义空间变换矩阵

               float  m_LineTransMatria【3】【2】;

               float  m_PolyTransMatria【3】【2】.

     3.  定义一条空间线段和一个空间多边形,本例为三角形。

     4.  二维图形变换主要是基于齐次坐标方程,通过一些简单的矩阵运算来实现: 

      二维齐次坐标变换的矩阵形式是:  

      矩阵的每个元素都有特殊含义。其中可以对图形进行缩放,旋转等变换;是对图形进行平移变换; 

则是对图形整体进行缩放变换.

     5. 平移变换:

     将一个图形在X方向中平移tx个单位,在Y方向平移ty个单位.其实现过程如下:

     

     其中:x1,y1是变换后的坐标,x,y是变换前的坐标,通过上述变换,(x,y)被平移了P(tx,ty). 在二维平面上任何复杂的变换都可以通过上述基本变换的组合来实现.在计算机上主要体现在矩阵的乘法运算,即将各个简单变换的矩阵逆序相乘,就可以得到一个总的变换矩阵.利用这个总的变换矩阵就可以对图形进行复合变换.

    6. 旋转变化:

   

    7. 放缩变换:

   

四.关键代码:

   1. 绘制初始直线和多边形,并将变换后的图形绘出:

void CCg_WuPing2DtransView::pDrawScene(CDC* pDC)
{
	CCg_WuPing2DtransDoc* pDoc = GetDocument();
	
	// Draw coordinate
 	pDC->MoveTo(m_wndWidth/2,  0);
	pDC->LineTo(m_wndWidth/2,  m_wndHeight);
	
	pDC->MoveTo(         0,  m_wndHeight/2);
	pDC->LineTo(m_wndWidth,  m_wndHeight/2);
	
	if (pDoc->m_objSelect < 2) pCalTransMatrix();

	// Line Object trans and clip
	float tx1,ty1,tx2,ty2;
	int   itx1,ity1,itx2,ity2;
	tx1 = pDoc->x1;    ty1 = pDoc->y1;
	tx2 = pDoc->x2;    ty2 = pDoc->y2;
	
	pTrans2Dpoint(&tx1, &ty1);
    pTrans2Dpoint(&tx2, &ty2);
	pDC->MoveTo(m_wndWidth/2+tx1, m_wndHeight/2-ty1);
	pDC->LineTo(m_wndWidth/2+tx2, m_wndHeight/2-ty2); 

	pDoc->m_lineVisible = false;
	itx1 = tx1;   itx2 = tx2;
    ity1 = ty1;   ity2 = ty2;
	if (ClipLine(&itx1, &ity1, &itx2, &ity2)) {
		CPen newPen;
		CPen *oldPen;
		
		// Create new color pen to Draw Clipping Line
		newPen.CreatePen(PS_SOLID, 2,  RGB(255, 250, 0));
		oldPen = (CPen *)pDC->SelectObject(&newPen);
		
		pDC->MoveTo(itx1+m_wndWidth/2, m_wndHeight/2-ity1);
		pDC->LineTo(itx2+m_wndWidth/2, m_wndHeight/2-ity2);
		
		pDC->SelectObject(oldPen);
		newPen.DeleteObject();
		
		pDoc->cx1 = itx1;  pDoc->cx2 = itx2;
        pDoc->cy1 = ity1;  pDoc->cy2 = ity2;
		pDoc->m_lineVisible = true;
		
	}

	// polygon Object trans and clip
    float tx[16],ty[16];

	for (int i = 0; i < pDoc->m_polyPoints; i++)
	{
		tx[i] = pDoc->m_polyPointsX[i];
		ty[i] = pDoc->m_polyPointsY[i];
	}
	pTrans2Dpoints(pDoc->m_polyPoints, tx, ty);

    pDC->MoveTo(m_wndWidth/2+tx[0], m_wndHeight/2-ty[0]);
	for (i = 1; i < pDoc->m_polyPoints; i++)
		pDC->LineTo(m_wndWidth/2+tx[i], m_wndHeight/2-ty[i]);

	pDoc->m_polyVisible = false;

	int points = pDoc->m_polyPoints,xx[16],yy[16],cn,cx[16],cy[16];

	for (i = 0; i < pDoc->m_polyPoints; i++)
	{
		xx[i] = tx[i];
		yy[i] = ty[i];
	}

    if (ClipPolygon(pDoc->m_polyPoints, xx, yy, &cn, cx, cy))
	{
		CPen newPen;
		CPen *oldPen;
		
		// Create new color pen to Draw Clipping Line
		newPen.CreatePen(PS_SOLID, 2,  RGB(255, 0, 0));
		oldPen = (CPen *)pDC->SelectObject(&newPen);
		
		pDC->MoveTo(cx[0]+m_wndWidth/2, m_wndHeight/2-cy[0]);
		for (i = 0; i < cn; i++) 
			pDC->LineTo(cx[i]+m_wndWidth/2, m_wndHeight/2-cy[i]);

		pDC->LineTo(cx[0]+m_wndWidth/2, m_wndHeight/2-cy[0]);

		pDC->SelectObject(oldPen);
		newPen.DeleteObject();
		
		pDoc->m_clipPolyPoints = cn;

		for (i = 0; i < cn; i++ )
		{
			pDoc->m_polyClipPointsX[i] = cx[i];
            pDoc->m_polyClipPointsY[i] = cy[i]; 
		} 

		pDoc->m_polyVisible = true;
	}


    pDC->MoveTo(m_wndWidth/2+pDoc->m_wndRectangle[0], m_wndHeight/2-pDoc->m_wndRectangle[3]);
	pDC->LineTo(m_wndWidth/2+pDoc->m_wndRectangle[1], m_wndHeight/2-pDoc->m_wndRectangle[3]);
    pDC->LineTo(m_wndWidth/2+pDoc->m_wndRectangle[1], m_wndHeight/2-pDoc->m_wndRectangle[2]);
	pDC->LineTo(m_wndWidth/2+pDoc->m_wndRectangle[0], m_wndHeight/2-pDoc->m_wndRectangle[2]);
	pDC->LineTo(m_wndWidth/2+pDoc->m_wndRectangle[0], m_wndHeight/2-pDoc->m_wndRectangle[3]);

	// Tell CgTransControl the process finish now.
    pDoc->UpdateAllViews(this);
}

    2. 变换操作:分别实现四个方向的变换:(-X,+X,-Y,+Y)

void CCg_WuPing2DtransView::pCalTransMatrix()
{
	CCg_WuPing2DtransDoc* pDoc = GetDocument();

	switch (pDoc->m_transDir) {
	  case 0: // -X
          if (pDoc->m_transMode == 0)        pCal2DTranslateMatrix(-10.0, 0.0);
	      else if (pDoc->m_transMode == 1)   pCal2DRotateMatrix(sin(3.14/36), cos(3.14/36));
		  else                               pCal2DScaleMatrix(0.5, 1.0);
		  break;
	  case 1: // +X
		  if (pDoc->m_transMode == 0)        pCal2DTranslateMatrix(10.0, 0.0);
		  else if (pDoc->m_transMode == 1)   pCal2DRotateMatrix(-sin(3.14/36), cos(3.14/36));
		  else                               pCal2DScaleMatrix(2.0, 1.0);
		break;
	  case 2: // +Y
		  if (pDoc->m_transMode == 0)        pCal2DTranslateMatrix(0.0, +10.0);
		  else if (pDoc->m_transMode == 1)   pCal2DRotateMatrix(-sin(3.14/36), cos(3.14/36));
		  else                               pCal2DScaleMatrix(2.0, 1.0);
		  break;
	  case 3: // -Y
		  if (pDoc->m_transMode == 0)        pCal2DTranslateMatrix(0.0, -10.0);
		  else if (pDoc->m_transMode == 1)   pCal2DRotateMatrix(sin(3.14/36), cos(3.14/36));
		  else                               pCal2DScaleMatrix(0.5, 1.0);
		break;
	}
}

    3.平移变换:

void CCg_WuPing2DtransView::pCal2DTranslateMatrix(float Tx, float Ty)//平移变换
{
	CCg_WuPing2DtransDoc * pDoc = (CCg_WuPing2DtransDoc*)GetDocument();

    if(pDoc ->m_objSelect == 0)
	{
		pDoc->m_lineTransMatrix[2][0] = pDoc ->m_lineTransMatrix[2][0] + Tx;
	    pDoc ->m_lineTransMatrix[2][1] = pDoc ->m_lineTransMatrix[2][1] + Ty;
	}
    
    if(pDoc ->m_objSelect == 1)
	{
		pDoc->m_polyTransMatrix[2][0] = pDoc->m_polyTransMatrix[2][0] + Tx;
	    pDoc->m_polyTransMatrix[2][1] = pDoc->m_polyTransMatrix[2][1] + Ty;
}
}

    4. 旋转变换:

void CCg_WuPing2DtransView::pCal2DRotateMatrix(float S, float C)//旋转变换
{
	CCg_WuPing2DtransDoc* pDoc = (CCg_WuPing2DtransDoc*)GetDocument();
	

	if(pDoc ->m_objSelect == 0)
	{
	    float temp1,temp2;
		temp1 = pDoc ->m_lineTransMatrix[0][0];
		temp2 = pDoc ->m_lineTransMatrix[1][0];
        pDoc ->m_lineTransMatrix[0][0] = pDoc ->m_lineTransMatrix[0][0]*C-pDoc ->m_lineTransMatrix[0][1]*S;
        pDoc ->m_lineTransMatrix[0][1] = temp1*S + pDoc ->m_lineTransMatrix[0][1]*C;
		pDoc ->m_lineTransMatrix[1][0] = pDoc ->m_lineTransMatrix[1][0]*C-pDoc ->m_lineTransMatrix[1][1]*S;
		pDoc ->m_lineTransMatrix[1][1] = temp2*S+pDoc ->m_lineTransMatrix[1][1]*C;
	
	}

	if(pDoc ->m_objSelect == 1)
	{
		float temp1,temp2;
		temp1 = pDoc ->m_polyTransMatrix[0][0];
		temp2 = pDoc ->m_polyTransMatrix[1][0];
        pDoc ->m_polyTransMatrix[0][0] = pDoc ->m_polyTransMatrix[0][0]*C-pDoc ->m_polyTransMatrix[0][1]*S;
        pDoc ->m_polyTransMatrix[0][1] = temp1*S + pDoc ->m_polyTransMatrix[0][1]*C;
		pDoc ->m_polyTransMatrix[1][0] = pDoc ->m_polyTransMatrix[1][0]*C-pDoc ->m_polyTransMatrix[1][1]*S;
		pDoc ->m_polyTransMatrix[1][1] = temp2*S+pDoc ->m_polyTransMatrix[1][1]*C;
	}
 
}

     5. 比例变换:

void CCg_WuPing2DtransView::pCal2DScaleMatrix(float Sx, float Sy)// 比例变换
{
	CCg_WuPing2DtransDoc* pDoc = (CCg_WuPing2DtransDoc*)GetDocument();
	if(pDoc ->m_objSelect == 0)
	{
		pDoc ->m_lineTransMatrix[0][0] = pDoc ->m_lineTransMatrix[0][0] * Sx;
		pDoc ->m_lineTransMatrix[1][1] = pDoc ->m_lineTransMatrix[1][1] * Sy;
	}
	if(pDoc ->m_objSelect == 1)
	{
		pDoc ->m_polyTransMatrix[0][0] *= Sx;
		pDoc ->m_polyTransMatrix[1][1] *= Sy;
	}
}

    6. 实现自动变换操作:

       调用以下函数:

  void CCg_WuPing2DtransView::OnTimer(UINT nIDEvent)
  void CCg_WuPing2DtransView::OnOutoplay()
  void CCg_WuPing2DtransView::OnUpdateOutoplay(CCmdUI* pCmdUI)

五.结果及分析:

    1.  对话界面:

      

     2.  平移变换:

      

    3.   旋转变换:

      

     4.   比例变换:

       






  • 9
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值