Skip to content

Commit

Permalink
Add support for deg, rad and grad in unitconvert (fixes #1052), and d…
Browse files Browse the repository at this point in the history
…ocument that it supports numeric factors (refs #1053)
  • Loading branch information
rouault committed Jun 21, 2018
1 parent 8ee389a commit e7626c0
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 35 deletions.
52 changes: 37 additions & 15 deletions docs/source/operations/conversions/unitconvert.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Unit conversion

.. versionadded:: 5.0.0

Convert between various distance and time units.
Convert between various distance, angular and time units.

+---------------------+--------------------------------------------------------+
| **Alias** | unitconvert |
Expand Down Expand Up @@ -41,25 +41,29 @@ expected to be in units of decimalyears. This can be fixed with `unitconvert`::
Parameters
################################################################################

.. option:: +xy_in=<unit>
.. option:: +xy_in=<unit> or <conversion_factor>

Horizontal input units. See :ref:`distance_units` for a list of available
units.
Horizontal input units. See :ref:`distance_units` and :ref:`angular_units`
for a list of available units. `<conversion_factor>` is the conversion factor
from the input unit to the International System unit.

.. option:: +xy_out=<unit>
.. option:: +xy_out=<unit> or <conversion_factor>

Horizontal output units. See :ref:`distance_units` for a list of available
units.
Horizontal output units. See :ref:`distance_units` and :ref:`angular_units`
for a list of available units. `<conversion_factor>` is the conversion factor
from the output unit to the International System unit.

.. option:: +z_in=<unit>
.. option:: +z_in=<unit> or <conversion_factor>

Vertical output units. See :ref:`distance_units` for a list of available
units.
Vertical output units. See :ref:`distance_units` and :ref:`angular_units`
for a list of available units. `<conversion_factor>` is the conversion factor
from the input unit to the International System unit.

.. option:: +z_out=<unit>
.. option:: +z_out=<unit> or <conversion_factor>

Vertical output units. See :ref:`distance_units` for a list of available
units.
Vertical output units. See :ref:`distance_units` and :ref:`angular_units`
for a list of available units. `<conversion_factor>` is the conversion factor
from the output unit to the International System unit.

.. option:: +t_in=<unit>

Expand All @@ -74,7 +78,7 @@ Parameters
Distance units
###############################################################################

In the table below all distance units supported by PROJ is listed.
In the table below all distance units supported by PROJ are listed.
The same list can also be produced on the command line with :program:`proj` or
:program:`cs2cs`, by adding the `-lu` flag when calling the utility.

Expand Down Expand Up @@ -124,12 +128,30 @@ The same list can also be produced on the command line with :program:`proj` or
| ind-ch | Indian Chain |
+----------+---------------------------------+

.. _angular_units:

Angular units
###############################################################################

In the table below all angular units supported by PROJ `unitconvert` are listed.
(since PROJ 5.2.0)

+----------+---------------------------------+
| **Label**| **Name** |
+----------+---------------------------------+
| deg | Degree |
+----------+---------------------------------+
| grad | Grad |
+----------+---------------------------------+
| rad | Radian |
+----------+---------------------------------+

.. _time_units:

Time units
###############################################################################

In the table below all time units supported by PROJ is listed.
In the table below all time units supported by PROJ are listed.

+--------------+-----------------------------+
| **label** | **Name** |
Expand Down
79 changes: 59 additions & 20 deletions src/PJ_unitconvert.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,49 @@ static PJ_COORD reverse_4d(PJ_COORD obs, PJ *P) {
return out;
}

/* M_PI / 200 */
#define GRAD_TO_RAD 0.015707963267948967

static const struct PJ_UNITS
pj_angular_units[] = {
{"rad", "1.0", "Radian", 1.0},
{"deg", "0.017453292519943296", "Degree", DEG_TO_RAD},
{"grad", "0.015707963267948967", "Grad", GRAD_TO_RAD},
{NULL, NULL, NULL, 0.0}
};


/***********************************************************************/
static double getUnitConversionFactor(const char* name,
const char** p_normalized_name) {
/***********************************************************************/
int i;
const char* s;

/* Try first with linear units */
for (i = 0; (s = pj_units[i].id) ; ++i) {
if ( strcmp(s, name) == 0 ) {
if( p_normalized_name ) {
*p_normalized_name = pj_units[i].name;
}
return pj_units[i].factor;
}
}

/* And then angular units */
for (i = 0; (s = pj_angular_units[i].id) ; ++i) {
if ( strcmp(s, name) == 0 ) {
if( p_normalized_name ) {
*p_normalized_name = pj_angular_units[i].name;
}
return pj_angular_units[i].factor;
}
}
if( p_normalized_name ) {
*p_normalized_name = NULL;
}
return 0.0;
}

/***********************************************************************/
PJ *CONVERSION(unitconvert,0) {
Expand Down Expand Up @@ -413,11 +456,10 @@ PJ *CONVERSION(unitconvert,0) {
Q->z_factor = 1.0;

if ((name = pj_param (P->ctx, P->params, "sxy_in").s) != NULL) {
for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i);

if (s) {
f = pj_units[i].factor;
proj_log_debug(P, "xy_in unit: %s", pj_units[i].name);
const char* normalized_name = NULL;
f = getUnitConversionFactor(name, &normalized_name);
if (f != 0.0) {
proj_log_debug(P, "xy_in unit: %s", normalized_name);
} else {
if ( (f = pj_param (P->ctx, P->params, "dxy_in").f) == 0.0)
return pj_default_destructor(P, PJD_ERR_UNKNOWN_UNIT_ID);
Expand All @@ -427,11 +469,10 @@ PJ *CONVERSION(unitconvert,0) {
}

if ((name = pj_param (P->ctx, P->params, "sxy_out").s) != NULL) {
for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i);

if (s) {
f = pj_units[i].factor;
proj_log_debug(P, "xy_out unit: %s", pj_units[i].name);
const char* normalized_name = NULL;
f = getUnitConversionFactor(name, &normalized_name);
if (f != 0.0) {
proj_log_debug(P, "xy_out unit: %s", normalized_name);
} else {
if ( (f = pj_param (P->ctx, P->params, "dxy_out").f) == 0.0)
return pj_default_destructor(P, PJD_ERR_UNKNOWN_UNIT_ID);
Expand All @@ -441,11 +482,10 @@ PJ *CONVERSION(unitconvert,0) {
}

if ((name = pj_param (P->ctx, P->params, "sz_in").s) != NULL) {
for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i);

if (s) {
f = pj_units[i].factor;
proj_log_debug(P, "z_in unit: %s", pj_units[i].name);
const char* normalized_name = NULL;
f = getUnitConversionFactor(name, &normalized_name);
if (f != 0.0) {
proj_log_debug(P, "z_in unit: %s", normalized_name);
} else {
if ( (f = pj_param (P->ctx, P->params, "dz_in").f) == 0.0)
return pj_default_destructor(P, PJD_ERR_UNKNOWN_UNIT_ID);
Expand All @@ -455,11 +495,10 @@ PJ *CONVERSION(unitconvert,0) {
}

if ((name = pj_param (P->ctx, P->params, "sz_out").s) != NULL) {
for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i);

if (s) {
f = pj_units[i].factor;
proj_log_debug(P, "z_out unit: %s", pj_units[i].name);
const char* normalized_name = NULL;
f = getUnitConversionFactor(name, &normalized_name);
if (f != 0.0) {
proj_log_debug(P, "z_out unit: %s", normalized_name);
} else {
if ( (f = pj_param (P->ctx, P->params, "dz_out").f) == 0.0)
return pj_default_destructor(P, PJD_ERR_UNKNOWN_UNIT_ID);
Expand Down
11 changes: 11 additions & 0 deletions test/gie/unitconvert.gie
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,15 @@ tolerance 0.1
accept 1 1 1 1
expect 0.5 0.5 1 1

operation proj=unitconvert xy_in=deg xy_out=rad
tolerance 0.000000000001
accept 1 1 1 1
expect 0.017453292519943296 0.017453292519943296 1 1

operation proj=unitconvert xy_in=grad xy_out=deg
tolerance 0.000000000001
accept 50 50 1 1
expect 45 45 1 1


</gie>

0 comments on commit e7626c0

Please sign in to comment.