[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