[转]C语言math.h库函数中atan与atan2的区别

来源:互联网 发布:逆战自动开枪脚本源码 编辑:程序博客网 时间:2024/05/16 11:15

今天做图像旋转练习的时候,要根据鼠标的移动轨迹来确定转过的角度,于是就很自然的想到通过三个点来确定这个转过的角度:图像的中心,鼠标按下的点,鼠标拖到的点。想到使用斜率来计算角度,于是联想到数学公式中的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()接受两个参数xy:

angel=Math.atan2(y,x)
指定两个点横坐标的差
指定两个点纵坐标的差

计算出来的结果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;


FROM:http://blog.csdn.net/tuyang120428941/article/details/5822041



0 0
原创粉丝点击