diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2018-06-21 22:43:14 +0200 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2018-06-21 23:40:50 +0200 |
| commit | 4e36fd85b9bd9f80c83d7f262c5a8fb3ae44cde2 (patch) | |
| tree | c787ebfba75f36bc576934dde44a1964df94c3ae /src | |
| parent | 8ee389a6f44fb9ac0380ddbd3706b9354269d62f (diff) | |
| download | PROJ-4e36fd85b9bd9f80c83d7f262c5a8fb3ae44cde2.tar.gz PROJ-4e36fd85b9bd9f80c83d7f262c5a8fb3ae44cde2.zip | |
Add support for deg, rad and grad in unitconvert (fixes #1052), and document that it supports numeric factors (refs #1053)
Diffstat (limited to 'src')
| -rw-r--r-- | src/PJ_unitconvert.c | 79 | ||||
| -rw-r--r-- | src/pj_strerrno.c | 1 | ||||
| -rw-r--r-- | src/pj_transform.c | 27 | ||||
| -rw-r--r-- | src/projects.h | 3 |
4 files changed, 83 insertions, 27 deletions
diff --git a/src/PJ_unitconvert.c b/src/PJ_unitconvert.c index 25bdc2e7..59af201f 100644 --- a/src/PJ_unitconvert.c +++ b/src/PJ_unitconvert.c @@ -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 get_unit_conversion_factor(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) { @@ -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 = get_unit_conversion_factor(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); @@ -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 = get_unit_conversion_factor(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); @@ -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 = get_unit_conversion_factor(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); @@ -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 = get_unit_conversion_factor(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); diff --git a/src/pj_strerrno.c b/src/pj_strerrno.c index e06ea58b..d37e6d5f 100644 --- a/src/pj_strerrno.c +++ b/src/pj_strerrno.c @@ -67,6 +67,7 @@ pj_err_list[] = { "ellipsoidal usage unsupported", /* -56 */ "only one +init allowed for non-pipeline operations", /* -57 */ "argument not numerical or out of range", /* -58 */ + "inconsistent unit type between input and output", /* -59 */ /* When adding error messages, remember to update ID defines in projects.h, and transient_error array in pj_transform */ diff --git a/src/pj_transform.c b/src/pj_transform.c index e67cc525..b459e4a2 100644 --- a/src/pj_transform.c +++ b/src/pj_transform.c @@ -69,8 +69,8 @@ static int adjust_axis( projCtx ctx, const char *axis, int denormalize_flag, #define M_BF (defn->datum_params[6]) /* -** This table is intended to indicate for any given error code in -** the range 0 to -56, whether that error will occur for all locations (ie. +** This table is intended to indicate for any given error code +** whether that error will occur for all locations (ie. ** it is a problem with the coordinate system as a whole) in which case the ** value would be 0, or if the problem is with the point being transformed ** in which case the value is 1. @@ -98,6 +98,19 @@ static const int transient_error[60] = { /* 50 to 59 */ 1, 0, 1, 0, 1, 1, 1, 1, 0, 0 }; +/* -------------------------------------------------------------------- */ +/* Read transient_error[] in a safe way. */ +/* -------------------------------------------------------------------- */ +static int get_transient_error_value(int pos_index) +{ + const int array_size = + (int)(sizeof(transient_error) / sizeof(transient_error[0])); + if( pos_index < 0 || pos_index >= array_size ) { + return 0; + } + return transient_error[pos_index]; +} + /* -------------------------------------------------------------------- */ /* Transform unusual input coordinate axis orientation to */ @@ -211,7 +224,7 @@ static int geographic_to_projected (PJ *P, long n, int dist, double *x, double * && P->ctx->last_errno != ERANGE) && (P->ctx->last_errno > 0 || P->ctx->last_errno < -44 || n == 1 - || transient_error[-P->ctx->last_errno] == 0 ) ) + || get_transient_error_value(-P->ctx->last_errno) == 0 ) ) { return P->ctx->last_errno; } @@ -249,7 +262,7 @@ static int geographic_to_projected (PJ *P, long n, int dist, double *x, double * && P->ctx->last_errno != ERANGE) && (P->ctx->last_errno > 0 || P->ctx->last_errno < -44 || n == 1 - || transient_error[-P->ctx->last_errno] == 0 ) ) + || get_transient_error_value(-P->ctx->last_errno) == 0 ) ) { return P->ctx->last_errno; } @@ -319,7 +332,7 @@ static int projected_to_geographic (PJ *P, long n, int dist, double *x, double * && P->ctx->last_errno != ERANGE) && (P->ctx->last_errno > 0 || P->ctx->last_errno < -44 || n == 1 - || transient_error[-P->ctx->last_errno] == 0 ) ) + || get_transient_error_value(-P->ctx->last_errno) == 0 ) ) { return P->ctx->last_errno; } @@ -358,7 +371,7 @@ static int projected_to_geographic (PJ *P, long n, int dist, double *x, double * && P->ctx->last_errno != ERANGE) && (P->ctx->last_errno > 0 || P->ctx->last_errno < -44 || n == 1 - || transient_error[-P->ctx->last_errno] == 0 ) ) + || get_transient_error_value(-P->ctx->last_errno) == 0 ) ) { return P->ctx->last_errno; } @@ -850,7 +863,7 @@ int pj_datum_transform( PJ *src, PJ *dst, z_is_temp = TRUE; } -#define CHECK_RETURN(defn) {if( defn->ctx->last_errno != 0 && (defn->ctx->last_errno > 0 || transient_error[-defn->ctx->last_errno] == 0) ) { if( z_is_temp ) pj_dalloc(z); return defn->ctx->last_errno; }} +#define CHECK_RETURN(defn) {if( defn->ctx->last_errno != 0 && (defn->ctx->last_errno > 0 || get_transient_error_value(-defn->ctx->last_errno) == 0) ) { if( z_is_temp ) pj_dalloc(z); return defn->ctx->last_errno; }} /* -------------------------------------------------------------------- */ /* If this datum requires grid shifts, then apply it to geodetic */ diff --git a/src/projects.h b/src/projects.h index 5b923813..2dc073fa 100644 --- a/src/projects.h +++ b/src/projects.h @@ -583,6 +583,9 @@ enum deprecated_constants_for_now_dropped_analytical_factors { #define PJD_ERR_ELLIPSOIDAL_UNSUPPORTED -56 #define PJD_ERR_TOO_MANY_INITS -57 #define PJD_ERR_INVALID_ARG -58 +#define PJD_ERR_INCONSISTENT_UNIT -59 +/* NOTE: Remember to update pj_strerrno.c and transient_error in */ +/* pj_transform.c when adding new value */ struct projFileAPI_t; |
