gnuastro-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnuastro-commits] master 1c045d8 1/2: Table: new atan2 operator, an arc


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 1c045d8 1/2: Table: new atan2 operator, an arc-tangent that preserves quadrant
Date: Thu, 14 Jan 2021 19:31:41 -0500 (EST)

branch: master
commit 1c045d81c72caa4f8394e2393a0faa73c4f9c460
Author: Mohammad Akhlaghi <mohammad@akhlaghi.org>
Commit: Mohammad Akhlaghi <mohammad@akhlaghi.org>

    Table: new atan2 operator, an arc-tangent that preserves quadrant
    
    Until now only the 'atan' operator was available, but that would only
    return angles in two quadrants!
    
    With this commit, a new 'atan2' operator has been added (directly calling
    the C library's 'atan2' function) for returning angles over all four
    quadrants.
---
 NEWS                   |  2 ++
 bin/table/arithmetic.c | 58 +++++++++++++++++++++++++++++++++-----------------
 bin/table/arithmetic.h |  1 +
 doc/gnuastro.texi      | 24 +++++++++++++++++++++
 4 files changed, 65 insertions(+), 20 deletions(-)

diff --git a/NEWS b/NEWS
index b05c09a..7dd5a49 100644
--- a/NEWS
+++ b/NEWS
@@ -124,6 +124,8 @@ See the end of the file for license conditions.
    - New trigonometric operators for column-arithmetic (inputs in units of
      degrees): 'sin', 'cos' and 'tan'. Their inverse trigonometric (outputs
      in units of degrees) have also been added: 'asin', 'acos' and 'atan'.
+     The 'atan2' operator (inverse tangent that preserves the quadrant, see
+     its description in the book) is also now available.
    - New hyperbolic operators for column-arithmetic: 'sinh', 'cosh' and
      'tanh'. Their inverse has also been added: 'asinh', 'acosh' and
      'atanh'.
diff --git a/bin/table/arithmetic.c b/bin/table/arithmetic.c
index fd448ca..764c06f 100644
--- a/bin/table/arithmetic.c
+++ b/bin/table/arithmetic.c
@@ -117,6 +117,7 @@ arithmetic_operator_name(int operator)
       case ARITHMETIC_TABLE_OP_ASINH: out="asinh"; break;
       case ARITHMETIC_TABLE_OP_ACOSH: out="acosh"; break;
       case ARITHMETIC_TABLE_OP_ATANH: out="atanh"; break;
+      case ARITHMETIC_TABLE_OP_ATAN2: out="atan2"; break;
       case ARITHMETIC_TABLE_OP_WCSTOIMG: out="wcstoimg"; break;
       case ARITHMETIC_TABLE_OP_IMGTOWCS: out="imgtowcs"; break;
       case ARITHMETIC_TABLE_OP_DISTANCEFLAT: out="distance-flat"; break;
@@ -179,6 +180,8 @@ arithmetic_set_operator(struct tableparams *p, char *string,
         { op=ARITHMETIC_TABLE_OP_ACOS; *num_operands=0; }
       else if( !strcmp(string, "atan"))
         { op=ARITHMETIC_TABLE_OP_ATAN; *num_operands=0; }
+      else if( !strcmp(string, "atan2"))
+        { op=ARITHMETIC_TABLE_OP_ATAN2; *num_operands=0; }
       else if( !strcmp(string, "sinh"))
         { op=ARITHMETIC_TABLE_OP_SINH; *num_operands=0; }
       else if( !strcmp(string, "cosh"))
@@ -576,33 +579,46 @@ arithmetic_trig_hyper(struct tableparams *p, gal_data_t 
**stack,
                       int operator)
 {
   size_t i;
-  gal_data_t *in;
-  double *d, pi=3.14159265358979323846264338327;
+  double *x, *y;
+  gal_data_t *in=NULL, *in2=NULL;
+  double pi=3.14159265358979323846264338327;
 
-  /* Read the input column as a 'double'. */
+  /* Read the input columns as a 'double'. */
   in=arithmetic_stack_pop(stack, operator, NULL);
   in=gal_data_copy_to_new_type_free(in, GAL_TYPE_FLOAT64);
 
-  /* Parse the array and do the calculation in place. r=pi*d/180
+  /* Set the array pointers. */
+  x=in->array;
+  if(operator==ARITHMETIC_TABLE_OP_ATAN2)
+    {
+      in2=arithmetic_stack_pop(stack, operator, NULL);
+      in2=gal_data_copy_to_new_type_free(in2, GAL_TYPE_FLOAT64);
+      y=in2->array;
+    }
 
-         d=r*180/pi
- */
-  d=in->array;
+  /* Parse the array and do the calculation in place. */
   for(i=0;i<in->size;++i)
     switch(operator)
       {
-      case ARITHMETIC_TABLE_OP_SIN:   d[i]=sin(   pi*d[i]/180.0f ); break;
-      case ARITHMETIC_TABLE_OP_COS:   d[i]=cos(   pi*d[i]/180.0f ); break;
-      case ARITHMETIC_TABLE_OP_TAN:   d[i]=tan(   pi*d[i]/180.0f ); break;
-      case ARITHMETIC_TABLE_OP_ASIN:  d[i]=asin(  d[i] )*180.0f/pi; break;
-      case ARITHMETIC_TABLE_OP_ACOS:  d[i]=acos(  d[i] )*180.0f/pi; break;
-      case ARITHMETIC_TABLE_OP_ATAN:  d[i]=atan(  d[i] )*180.0f/pi; break;
-      case ARITHMETIC_TABLE_OP_SINH:  d[i]=sinh(  d[i] );           break;
-      case ARITHMETIC_TABLE_OP_COSH:  d[i]=cosh(  d[i] );           break;
-      case ARITHMETIC_TABLE_OP_TANH:  d[i]=tanh(  d[i] );           break;
-      case ARITHMETIC_TABLE_OP_ASINH: d[i]=asinh( d[i] );           break;
-      case ARITHMETIC_TABLE_OP_ACOSH: d[i]=acosh( d[i] );           break;
-      case ARITHMETIC_TABLE_OP_ATANH: d[i]=atanh( d[i] );           break;
+      /* Single-operand operators. */
+      case ARITHMETIC_TABLE_OP_SIN:   x[i]=sin(   pi*x[i]/180.0f ); break;
+      case ARITHMETIC_TABLE_OP_COS:   x[i]=cos(   pi*x[i]/180.0f ); break;
+      case ARITHMETIC_TABLE_OP_TAN:   x[i]=tan(   pi*x[i]/180.0f ); break;
+      case ARITHMETIC_TABLE_OP_ASIN:  x[i]=asin(  x[i] )*180.0f/pi; break;
+      case ARITHMETIC_TABLE_OP_ACOS:  x[i]=acos(  x[i] )*180.0f/pi; break;
+      case ARITHMETIC_TABLE_OP_ATAN:  x[i]=atan(  x[i] )*180.0f/pi; break;
+      case ARITHMETIC_TABLE_OP_SINH:  x[i]=sinh(  x[i] );           break;
+      case ARITHMETIC_TABLE_OP_COSH:  x[i]=cosh(  x[i] );           break;
+      case ARITHMETIC_TABLE_OP_TANH:  x[i]=tanh(  x[i] );           break;
+      case ARITHMETIC_TABLE_OP_ASINH: x[i]=asinh( x[i] );           break;
+      case ARITHMETIC_TABLE_OP_ACOSH: x[i]=acosh( x[i] );           break;
+      case ARITHMETIC_TABLE_OP_ATANH: x[i]=atanh( x[i] );           break;
+
+      /* Two operand operators. */
+      case ARITHMETIC_TABLE_OP_ATAN2:
+        x[i]=atan2(y[i], x[i])*180.0f/pi; break;
+
+      /* Not recognized (a bug). */
       default:
         error(EXIT_FAILURE, 0, "%s: a bug! please contact us at %s to fix "
               "the problem. The code %d is not recognized as an operator "
@@ -610,7 +626,8 @@ arithmetic_trig_hyper(struct tableparams *p, gal_data_t 
**stack,
               operator);
       }
 
-  /* Put the resulting calculation back on the stack. */
+  /* Clean up and put the resulting calculation back on the stack. */
+  if(in2) gal_data_free(in2);
   gal_list_data_add(stack, in);
 }
 
@@ -740,6 +757,7 @@ arithmetic_operator_run(struct tableparams *p, gal_data_t 
**stack,
         case ARITHMETIC_TABLE_OP_ASINH:
         case ARITHMETIC_TABLE_OP_ACOSH:
         case ARITHMETIC_TABLE_OP_ATANH:
+        case ARITHMETIC_TABLE_OP_ATAN2:
           arithmetic_trig_hyper(p, stack, operator);
           break;
 
diff --git a/bin/table/arithmetic.h b/bin/table/arithmetic.h
index 232627e..8c3f2f1 100644
--- a/bin/table/arithmetic.h
+++ b/bin/table/arithmetic.h
@@ -41,6 +41,7 @@ enum arithmetic_operators
   ARITHMETIC_TABLE_OP_ASIN,
   ARITHMETIC_TABLE_OP_ACOS,
   ARITHMETIC_TABLE_OP_ATAN,
+  ARITHMETIC_TABLE_OP_ATAN2,
   ARITHMETIC_TABLE_OP_SINH,
   ARITHMETIC_TABLE_OP_COSH,
   ARITHMETIC_TABLE_OP_TANH,
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 3c1b614..18bbb7e 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -9854,6 +9854,30 @@ They take one operand, in units of degrees.
 Inverse trigonometric functions.
 They take one operand and the returned values are in units of degrees.
 
+@item atan2
+Inverse tangent (output in units of degrees) which uses the signs of the input 
coordinates to distinguish between the quadrants.
+This operator therefore needs two operands: the first popped operand is 
assumed to be the X axis position of the point, and the second popped operand 
is its Y axis coordinate.
+
+For example see the commands below for four points in the four quadrants (if 
you want to try them, you don't need to type/copy the parts after @key{#}).
+The first point (2,2) is in the first quadrant, therefore the returned angle 
is 45 degrees.
+But the second, third and fourth points are in the quadrants of the same 
order, and the returned angles reflect the quadrant.
+
+@example
+$ echo " 2  2" | asttable -c'arith $2 $1 atan2'   # -->   45
+$ echo " 2 -2" | asttable -c'arith $2 $1 atan2'   # -->  -45
+$ echo "-2 -2" | asttable -c'arith $2 $1 atan2'   # --> -135
+$ echo "-2  2" | asttable -c'arith $2 $1 atan2'   # -->  135
+@end example
+
+However, if you simply use the classic arc-tangent operator (@code{atan}) for 
the same points, the result will only be in two quadrants as you see below:
+
+@example
+echo " 2  2" | "$utility" -c'arith $2 $1 / atan'  # -->   45
+echo " 2 -2" | "$utility" -c'arith $2 $1 / atan'  # -->  -45
+echo "-2 -2" | "$utility" -c'arith $2 $1 / atan'  # -->   45
+echo "-2  2" | "$utility" -c'arith $2 $1 / atan'  # -->  -45
+@end example
+
 @item  sinh
 @itemx cosh
 @itemx tanh



reply via email to

[Prev in Thread] Current Thread [Next in Thread]