c语言math.atan,C语言math.h库函数中atan与atan2的区别

本文探讨了在图像旋转应用中,如何使用atan2函数精确计算鼠标轨迹角度,并解释了atan与atan2的区别,着重于atan2在处理顺逆时针旋转判断中的优势。通过实例展示了如何正确使用atan2函数并优化图像旋转角度计算。
摘要由CSDN通过智能技术生成

今天做图像旋转练习的时候,要根据鼠标的移动轨迹来确定转过的角度,于是就很自然的想到通过三个点来确定这个转过的角度:图像的中心,鼠标按下的点,鼠标拖到的点。想到使用斜率来计算角度,于是联想到数学公式中的arctan反正切函数,通过搜索得知在math.h函数库中有2个函数:atan与atan2都可以求到角度,我最初使用的是atan函数,可是在使用的过程中,出现了很大的问题。

1.atan()接受一个参数:

angel=atan(slope)

angel为一个角度的弧度值,要换算成角度,必须乘以180/PI,slope为直线的斜率,是一个数字,这个数字可以是负的无穷大到正无穷大之间的任何一个值.不过,利用他进行计算比较复杂.由于三角函数的周期性,一个数字的反正切值不止一个.例如arctan(1)的值是pi/4 + k * pi.然而通过atan(1)只能得到PI/4,对于正切函数来说,他的周期是180度,所以两个相差180度的角具有相同的正切和斜率:

tanθ=tan(θ+180)然而,atan()只能返回一个角度值,因此确定他的角度非常的复杂。特别是用在处理图像旋转的问题的时候更是棘手,因为我们要通过这个角度来判断图像是顺时针旋转还是逆时针旋转,从而来确定图像的转动,然而这个函数很难做到。

2.atan2()接受两个参数x和y:

angel=Math.atan2(y,x)

x指定两个点横坐标的差y指定两个点纵坐标的差

计算出来的结果angel是一个弧度值,要换算成角度,也必须乘以180/PI。

double a = atan2(1,1);

double b = atan2(1,-1);

double c = atan2(-1,-1);

double d = atan2(-1,1);

double e = atan(1);

double f = atan(-1);

cout << a * 180/PI << endl;  45    //第一象限

cout << b * 180/PI << endl;  135   //第二象限

cout << c * 180/PI << endl;  -135  //第三象限

cout << d * 180/PI << endl;  -45   //第四象限

cout << e * 180/PI << endl;  45

cout << f * 180/PI << endl;  -45

以下是用于图像旋转的代码:与这两个函数的讨论无关......

由于计算机中坐标向右是正X轴方向,向下是正Y轴方向,所以计算机坐标中的4,3,2,1象限就对应数学课本中的1,2,3,4象限。于是得知atan2的取值是-PI到PI。

可以很轻易的通过这个角度来判断我们的鼠标轨迹是顺时针还是逆时针。

处理图像旋转时求夹角部分的代码(图像放整个客户区的中间):

CRect rect;

GetClientRect(&rect);

long lWidth =   rect.Width();

long lHeight =  rect.Height();

int x1 = m_ptorigin.x;

int y1 = m_ptorigin.y;

int x2 = m_ptend.x;

int y2 = m_ptend.y;

float centerx  = (float)(lWidth / 2);

float centery =  (float)(lHeight /2) ;

float a1 = (float)(atan2((y1 - centery) , (x1 - centerx)));

float a2 = (float)(atan2((y2 - centery) , (x2 - centerx)));

TRACE("%f/n",a1 * 180 / PI);

TRACE("%f",a2 * 180 / PI);

if(a2 - a1 > 0)  //顺时针转(所得到的角度会越来越小,-X轴是-180,顺时针一圈到-X轴后是180)

{

m_iRotateAngle = (float)(a2 * 180 / PI - a1 * 180 /PI) + m_iRotateAngle;

}

else        //逆时针转(所得到的角度会越来越大,-X轴是180,顺时针一圈后到-X轴是-180)

{

m_iRotateAngle = (float)(a2 * 180 / PI - a1 * 180 /PI + 360) + m_iRotateAngle;

}

if( m_iRotateAngle > 360)    m_iRotateAngle -= 360;   if( m_iRotateAngle < 0)    m_iRotateAngle += 360;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值