作者:朱金燦
來源:http://blog.csdn.net/clever101/
這裡講述的二維圖形是指諸如三角形、多邊形圍繞某一中心點進行指定角度的旋轉。二維圖形其實是由一系列的離散點組成的,離散點放在特定的座標系就是向量。因此二維圖形的旋轉的基礎就是向量的旋轉。
首先考慮一個向量 p = (x,y) , 那麼它寫成座標的形式就是x+iy,這個就是P點在複平面的座標.
問題: 假設現在有一個角度d,並且使向量p沿逆時針方向旋轉d角度並且不改變其模的大小.請問旋轉後 的向量p'是什麼呢?
問題分析:
簡單舉例.....
對於一個向量p (1,0),使它向逆時針旋轉90度,並且不改變其模的大小,我們會很清楚的畫出,這個變化後的向量就是p' (0,1),我們把它們都恢複的一般形式,原向量(1,0) --- 1 + i * 0, 新向量(0,1) --- 0 + i * 1,我們不難發現把原來的向量p的一般形式乘以一個i,然後整理就會得到新的向量p'的座標一般形式....進一步想象,i是什麼呢? i = cos(90) + i*sin(90);那也就是說可以得出這樣一個結論:
對於一個向量p : x + i * y 來說,如果向逆時針旋轉d角度的話,新的向量p'應該是向量p的一般運算式(x+i*y)乘以cos(d)+i*sin(d) ,然後整理得出一個結果,將i的係數看成p'的複數部分,將其他部分看成p'的整數部分,由於又要保證它的大小不改變,所以我們只要保證乘的向量的模大小要為1,恰巧cos(d)+i*sin(d)全部滿足.
所以說對於p = (x,y)這個向量向逆時針旋轉且大小不改變所得到的向量如下:
p: (x,y) --------> p': ( x*cos(d)-y*sin(d) , x*sin(d)+y*cos(d) )
如果是向順時針旋轉則:
p: (x,y) --------> p': ( x*cos(-d)-y*sin(-d) , x*sin(-d)+y*cos(-d) )
現在我們明白了向量旋轉的原理,你可以看到上面的向量旋轉是圍繞原點(0,0)進行得,我們現在要實現的是圍繞某一中心點進行旋轉,該怎麼做呢?很簡單,就是將要旋轉的點平移到以中心點位原點的座標系,旋轉完成之後再平移回來(為了方便繪製)。
明白了原理,於是編程實現。下面是主要實現代碼:
double const PI = 3.1415926;<br />/*! @struct<br />* @brief 二維點結構體<br />*<br />*<br />*/<br />struct stPoint<br />{<br /> stPoint(CPoint &point)<br /> {<br /> m_CoorX = static_cast<double>(point.x);<br />m_CoorY = static_cast<double>(point.y);<br /> }<br /> stPoint(double x,double y)<br /> {<br /> m_CoorX = x;<br /> m_CoorY = y;<br /> }</p><p> /*!<br /> * @brief 執行和MFC的CPoint類的轉換<br /> *<br /> * /return 轉換後的點<br /> */<br /> operator CPoint const ()<br /> {<br /> return CPoint(static_cast<long>(m_CoorX),static_cast<long>(m_CoorY));<br /> }<br /> stPoint operator - (stPoint &OtherPt)<br /> {<br /> return stPoint(m_CoorX-OtherPt.m_CoorX,m_CoorY-OtherPt.m_CoorY);<br /> }<br /> stPoint operator + (stPoint &OtherPt)<br /> {<br /> return stPoint(m_CoorX+OtherPt.m_CoorX,m_CoorY+OtherPt.m_CoorY);<br /> }<br /> double m_CoorX;<br /> double m_CoorY;<br />};<br />/*!<br />* @brief 計算x*sin(d)+y*cos(d)<br />*<br />* @param [in]Left 左點<br />* @param [in]Right 右點<br />* /return 計算結果<br />*/<br />double VectorMulti(stPoint &Left,stPoint &Right)<br />{<br />return (Left.m_CoorX*Right.m_CoorY+Left.m_CoorY*Right.m_CoorX);<br />}<br />/*!<br />* @brief 計算x*cos(d)-y*sin(d)<br />*<br />* @param [in]Left 左點<br />* @param [in]Right 右點<br />* /return 計算結果<br />*/<br />double CrossProduct(stPoint &Left,stPoint &Right)<br />{<br />return (Left.m_CoorX*Right.m_CoorX-Left.m_CoorY*Right.m_CoorY);<br />}<br />/*!<br />* @brief 計算( x*cos(d)-y*sin(d) , x*sin(d)+y*cos(d) )<br />*<br />* @param [in]point 待旋轉的點<br />* @param [in]Right 轉換點<br />* /return 旋轉後的點<br />*/<br />stPoint PointMulti(stPoint &point,stPoint &TranPt)<br />{<br />return stPoint(CrossProduct(point,TranPt),VectorMulti(point,TranPt));<br />}<br />/*!<br />* @brief 對二維圖形的單個點進行變換<br />*<br />* @param [in][out]point 待旋轉的點<br />* @param [in]nAngle 旋轉角度<br />* @param [in]RotateCenter 旋轉中心點<br />* /return<br />*/<br />void PointRotate(stPoint &point,int nAngle,stPoint &RotateCenter)<br />{<br /> // 平移到以中心點位原點的座標系<br /> point = point - RotateCenter;<br /> // 角度轉弧度<br /> double radian = static_cast<double>(nAngle)/180.0*PI;<br /> stPoint RotatePt(cos(radian),sin(radian));<br /> point = PointMulti(point,RotatePt);<br /> // 平移回來<br /> point = point + RotateCenter;<br />}<br />
:
旋轉前:
旋轉後:
相關源碼下載:
二維圖形旋轉實現的相關代碼
參考文獻:
1. 神奇的向量旋轉