算法思路:
寻找图形的中心点或者给定一个点,将影响图形形状的关键点绕着这个点旋转,然后根据旋转后的新值重绘图形。这里旋转的角度,即为鼠标移动开始点与定点的向量,和移动结束点与定点的向量之间的夹角。
用到的数学公式:
部分函数实现:
//////////////////////////////////////////////////////////////////////////
struct POINTF
{
float x;
float y;
POINTF::POINTF(){}
POINTF::POINTF(float a,float b):x(a),y(b){}
};
//判断向量顺时针旋转还是逆时针旋转(两向量起点相同)
//向量a,旋转前的向量
//向量b,旋转后的向量
//返回值1-顺时针 0-平行 -1-逆时针
int vecCross(const POINTF& a,const POINTF& b)
{
float fValue = a.x*b.y - b.x*a.y;
if (fValue > 1e-6)//正
{
return 1;
}
else if(fValue < -1e-6)//负
{
return -1;
}
else//零
{
return 0;
}
}
//点pta绕ptCenter点旋转
int vecCross(const POINTF& ptCenter,const POINTF& pta,const POINTF& ptScreen)
{
POINTF a = POINTF(pta.x-ptCenter.x,pta.y-ptCenter.y);
POINTF b = POINTF(ptScreen.x-ptCenter.x,ptScreen.y-ptCenter.y);
int axb = vecCross(a,b);
return axb;
}
//计算向量旋转角度cos值
//点pta绕ptCenter点旋转
float rotCosAngle(const POINTF& ptCenter,const POINTF& pta,const POINTF& ptScreen)
{
POINTF a = POINTF(pta.x-ptCenter.x,pta.y-ptCenter.y);
POINTF b = POINTF(ptScreen.x-ptCenter.x,ptScreen.y-ptCenter.y);
POINTF c = POINTF(ptScreen.x-pta.x,ptScreen.y-pta.y);
float A = sqrtf(a.x*a.x+a.y*a.y);
float B = sqrtf(b.x*b.x+b.y*b.y);
float C = sqrtf(c.x*c.x+c.y*c.y);
float CosC = (A*A+B*B-C*C)/(2*A*B);//cosC = (a^2+b^2-c^2)/2ab 此处没有考虑除数为0的情况
return CosC;
}
//计算一个点绕另一个点旋转,得到的点
POINTF getRotationPoint(const POINTF& ptCenter,const POINTF& pta,const int& axb,const float& costheta)
{
POINTF pt(0.0,0.0);
POINTF a = POINTF(pta.x-ptCenter.x,pta.y-ptCenter.y);
//POINTF b = POINTF(ptScreen.x-ptCenter.x,ptScreen.y-ptCenter.y);
//int axb = vecCross(a,b);
//float costheta = rotCosAngle(ptCenter,pta,ptScreen);
float sintheta = sqrtf(1-costheta*costheta);//计算sin值,sinA^2+cosA^2 = 1
POINTF ptTemp;
switch(axb)
{
case 0:
pt = pta;
break;
case -1://逆时针
ptTemp = POINTF(a.x*costheta+a.y*sintheta+ptCenter.x,-a.x*sintheta+a.y*costheta+ptCenter.y);
pt = ptTemp;
break;
case 1://顺时针
ptTemp = POINTF(a.x*costheta-a.y*sintheta+ptCenter.x,a.x*sintheta+a.y*costheta+ptCenter.y);
pt = ptTemp;
break;
}
return pt;
}