From 186c6e3303ccef8e833026e4e9dbaa76be6cb93b Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Fri, 1 Apr 2016 23:10:44 +0200 Subject: First steps toward simplified macros/internals The brief version:: In an attempt to make proj.4 code slightly more secure and much easier to read and maintain, I'm trying to eliminate a few unfortunate design decisions from the early days of proj.4 The work will be *very* intrusive, especially in the PJ_xxx segment of the code tree, but great care has been taken to design a process that can be implemented stepwise and localized, one projection at a time, then finalized with a relatively small and concentrated work package. The (very) long version: See the comments in PJ_minimal.c --- src/PJ_cass.c | 165 ++++++++++++++++++++++++++++---------------- src/PJ_merc.c | 57 ++++++++++++---- src/PJ_minimal.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/pj_init.c | 96 ++++++++++++++++---------- src/pj_malloc.c | 57 ++++++++++++++-- src/proj_api.h | 2 + src/projects.h | 78 ++++++++++++++------- 7 files changed, 519 insertions(+), 139 deletions(-) create mode 100644 src/PJ_minimal.c (limited to 'src') diff --git a/src/PJ_cass.c b/src/PJ_cass.c index 38fa9db5..5d7aea3c 100644 --- a/src/PJ_cass.c +++ b/src/PJ_cass.c @@ -1,79 +1,126 @@ -#define PROJ_PARMS__ \ - double m0; \ - double n; \ - double t; \ - double a1; \ - double c; \ - double r; \ - double dd; \ - double d2; \ - double a2; \ - double tn; \ - double *en; #define PJ_LIB__ # include PROJ_HEAD(cass, "Cassini") "\n\tCyl, Sph&Ell"; + + # define EPS10 1e-10 # define C1 .16666666666666666666 # define C2 .00833333333333333333 # define C3 .04166666666666666666 # define C4 .33333333333333333333 # define C5 .06666666666666666666 -FORWARD(e_forward); /* ellipsoid */ - xy.y = pj_mlfn(lp.phi, P->n = sin(lp.phi), P->c = cos(lp.phi), P->en); - P->n = 1./sqrt(1. - P->es * P->n * P->n); - P->tn = tan(lp.phi); P->t = P->tn * P->tn; - P->a1 = lp.lam * P->c; - P->c *= P->es * P->c / (1 - P->es); - P->a2 = P->a1 * P->a1; - xy.x = P->n * P->a1 * (1. - P->a2 * P->t * - (C1 - (8. - P->t + 8. * P->c) * P->a2 * C2)); - xy.y -= P->m0 - P->n * P->tn * P->a2 * - (.5 + (5. - P->t + 6. * P->c) * P->a2 * C3); - return (xy); + + +struct opaque { + /* These are the only opaque members actually initialized */ + double *en; + double m0; + + /* Apparently this group of opaque members should be demoted to local variables in e_forward and e_inverse */ + double n; + double t; + double a1; + double c; + double r; + double dd; + double d2; + double a2; + double tn; +}; + + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct opaque *O = P->opaq; + xy.y = pj_mlfn(lp.phi, O->n = sin(lp.phi), O->c = cos(lp.phi), O->en); + O->n = 1./sqrt(1. - P->es * O->n * O->n); + O->tn = tan(lp.phi); O->t = O->tn * O->tn; + O->a1 = lp.lam * O->c; + O->c *= P->es * O->c / (1 - P->es); + O->a2 = O->a1 * O->a1; + xy.x = O->n * O->a1 * (1. - O->a2 * O->t * + (C1 - (8. - O->t + 8. * O->c) * O->a2 * C2)); + xy.y -= O->m0 - O->n * O->tn * O->a2 * + (.5 + (5. - O->t + 6. * O->c) * O->a2 * C3); + return xy; } -FORWARD(s_forward); /* spheroid */ + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; xy.x = asin(cos(lp.phi) * sin(lp.lam)); xy.y = atan2(tan(lp.phi) , cos(lp.lam)) - P->phi0; - return (xy); + return xy; } -INVERSE(e_inverse); /* ellipsoid */ + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct opaque *O = P->opaq; double ph1; - ph1 = pj_inv_mlfn(P->ctx, P->m0 + xy.y, P->es, P->en); - P->tn = tan(ph1); P->t = P->tn * P->tn; - P->n = sin(ph1); - P->r = 1. / (1. - P->es * P->n * P->n); - P->n = sqrt(P->r); - P->r *= (1. - P->es) * P->n; - P->dd = xy.x / P->n; - P->d2 = P->dd * P->dd; - lp.phi = ph1 - (P->n * P->tn / P->r) * P->d2 * - (.5 - (1. + 3. * P->t) * P->d2 * C3); - lp.lam = P->dd * (1. + P->t * P->d2 * - (-C4 + (1. + 3. * P->t) * P->d2 * C5)) / cos(ph1); - return (lp); + ph1 = pj_inv_mlfn(P->ctx, O->m0 + xy.y, P->es, O->en); + O->tn = tan(ph1); O->t = O->tn * O->tn; + O->n = sin(ph1); + O->r = 1. / (1. - P->es * O->n * O->n); + O->n = sqrt(O->r); + O->r *= (1. - P->es) * O->n; + O->dd = xy.x / O->n; + O->d2 = O->dd * O->dd; + lp.phi = ph1 - (O->n * O->tn / O->r) * O->d2 * + (.5 - (1. + 3. * O->t) * O->d2 * C3); + lp.lam = O->dd * (1. + O->t * O->d2 * + (-C4 + (1. + 3. * O->t) * O->d2 * C5)) / cos(ph1); + return lp; } -INVERSE(s_inverse); /* spheroid */ - lp.phi = asin(sin(P->dd = xy.y + P->phi0) * cos(xy.x)); - lp.lam = atan2(tan(xy.x), cos(P->dd)); - return (lp); + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + lp.phi = asin(sin(P->opaq->dd = xy.y + P->phi0) * cos(xy.x)); + lp.lam = atan2(tan(xy.x), cos(P->opaq->dd)); + return lp; } -FREEUP; - if (P) { - if (P->en) - pj_dalloc(P->en); - pj_dalloc(P); - } + + +static void freeup(PJ *P) { /* Destructor */ + if (0==P) + return; + if (0==P->opaq) { + pj_dealloc (P); + return; + } + pj_dealloc(P->opaq->en); + pj_dealloc(P->opaq); + pj_dealloc(P); } -ENTRY1(cass, en) - if (P->es) { - if (!(P->en = pj_enfn(P->es))) E_ERROR_0; - P->m0 = pj_mlfn(P->phi0, sin(P->phi0), cos(P->phi0), P->en); - P->inv = e_inverse; - P->fwd = e_forward; - } else { + + +PJ *PROJECTION(cass) { + + /* Spheroidal? */ + if (0==P->es) { P->inv = s_inverse; P->fwd = s_forward; - } -ENDENTRY(P) + } + + /* Otherwise it's ellipsoidal */ + P->opaq = pj_calloc (1, sizeof (struct opaque)); + if (0==P->opaq) { + freeup (P); + return 0; + } + + P->opaq->en = pj_enfn(P->es); + if (0==P->opaq->en) { + freeup (P); + return 0; + } + + P->opaq->m0 = pj_mlfn(P->phi0, sin(P->phi0), cos(P->phi0), P->opaq->en); + P->inv = e_inverse; + P->fwd = e_forward; + + return P; +} diff --git a/src/PJ_merc.c b/src/PJ_merc.c index 4b991c1c..89913e50 100644 --- a/src/PJ_merc.c +++ b/src/PJ_merc.c @@ -1,31 +1,53 @@ #define PJ_LIB__ #include PROJ_HEAD(merc, "Mercator") "\n\tCyl, Sph&Ell\n\tlat_ts="; + #define EPS10 1.e-10 -FORWARD(e_forward); /* ellipsoid */ - if (fabs(fabs(lp.phi) - HALFPI) <= EPS10) F_ERROR; + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + if (fabs(fabs(lp.phi) - HALFPI) <= EPS10) + F_ERROR; xy.x = P->k0 * lp.lam; xy.y = - P->k0 * log(pj_tsfn(lp.phi, sin(lp.phi), P->e)); - return (xy); + return xy; } -FORWARD(s_forward); /* spheroid */ - if (fabs(fabs(lp.phi) - HALFPI) <= EPS10) F_ERROR; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + if (fabs(fabs(lp.phi) - HALFPI) <= EPS10) + F_ERROR; xy.x = P->k0 * lp.lam; xy.y = P->k0 * log(tan(FORTPI + .5 * lp.phi)); - return (xy); + return xy; } -INVERSE(e_inverse); /* ellipsoid */ - if ((lp.phi = pj_phi2(P->ctx, exp(- xy.y / P->k0), P->e)) == HUGE_VAL) I_ERROR; + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + if ((lp.phi = pj_phi2(P->ctx, exp(- xy.y / P->k0), P->e)) == HUGE_VAL) + I_ERROR; lp.lam = xy.x / P->k0; - return (lp); + return lp; } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; lp.phi = HALFPI - 2. * atan(exp(-xy.y / P->k0)); lp.lam = xy.x / P->k0; - return (lp); + return lp; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(merc) + + +static void freeup(PJ *P) { /* Destructor */ + pj_dealloc(P); +} + + +PJ *PROJECTION(merc) { double phits=0.0; int is_phits; @@ -33,15 +55,20 @@ ENTRY0(merc) phits = fabs(pj_param(P->ctx, P->params, "rlat_ts").f); if (phits >= HALFPI) E_ERROR(-24); } + if (P->es) { /* ellipsoid */ if (is_phits) P->k0 = pj_msfn(sin(phits), cos(phits), P->es); P->inv = e_inverse; P->fwd = e_forward; - } else { /* sphere */ + } + + else { /* sphere */ if (is_phits) P->k0 = cos(phits); P->inv = s_inverse; P->fwd = s_forward; } -ENDENTRY(P) + + return P; +} diff --git a/src/PJ_minimal.c b/src/PJ_minimal.c new file mode 100644 index 00000000..210d25d3 --- /dev/null +++ b/src/PJ_minimal.c @@ -0,0 +1,203 @@ +/*********************************************************************** + + A minimal example of a new proj.4 projection implementation + + ...and a verbose justification for some highly intrusive code + surgery + +************************************************************************ + +**The brief version:** + +In an attempt to make proj.4 code slightly more secure and much easier +to read and maintain, I'm trying to eliminate a few unfortunate design +decisions from the early days of proj.4 + +The work will be *very* intrusive, especially in the PJ_xxx segment of +the code tree, but great care has been taken to design a process that +can be implemented stepwise and localized, one projection at a time, +then finalized with a relatively small and concentrated work package. + +**The (very) long version:** + +Gerald I. Evenden's original design for the proj.4 projection system +is a beautiful example of software architecture, where a very limited +set of policy rules leads to a well defined hierarchical structure and +a high degree of both encapsulation and internal interoperability. + +In the proj.4 code, the policy rules are *enforced* by a system of +preprocessor macros for building the scaffolding for implementation +of a new projection. + +While this system of macros undeniably possesses the property of both +reducing repetitive code and enforcing policy, unfortunately it also +possesses two much less desirable properties: + +First, while enforcing policy, it also *hides* policy: The "beauty in +simplicity" of Gerald's design is hidden behind layers of macros, +whose architectural clarity do not match that of proj.4 in general. + +Second (and related), the macros make the source code look like +something only vaguely related to C, making it hard to read (an effect +that gets amplified to the tune of syntax highlighters getting confused +by the macros). + +While the policy rule enforcement macros can be eliminated in relatively +non-intrusive ways, a more fundamental flaw in the proj.4 use of macros +is found in the PJ_xxx.c files implementing the individual projections: +The use of internal redefinition of PJ, the fundamental proj data object, +through the use of the PROJ_PARMS__ macro, makes the sizeof (PJ) +fundamentally unknown to the calling pj_init function. + +This leads to code that is probably not in full conformance with the +C standard. + +It is also a memory management catastrophe waiting to happen. + +But first and foremost, it leads to some very clumsy initialization code, +where pj_init (the constructor function), needs to start the constsruction +process by asking the PJ_xxx function to do the memory allocation (because +pj_init does not know the size of the PROJ_PARMS-mangled PJ object being +instantiated). + +Then, after doing some initialization work, pj_init returns control to +PJ_xxx, asking it to finalize the initialization with the projection +specific parameters specified by the PROJ_PARMS__ macro. + +Behind the scenes, hidden by two layers of macros, what happens is even +worse, as a lot of the initialization code is duplicated in every PJ_xxx +file, rather than being centralized in the pj_init function. + +**Solution procedure:** + +Evidently, the way to eliminate this clumsyness will be to introduce an +opaque object, that is managed by tne individual PJ_xxx projection code, +and represented as a simple void-pointer in the PJ object. + +This can be done one projection code file at a time, working through the +code base as time permits (it will take at least a month). + +When a PJ_xxx file is on the surgical bench, it will also have its +ENTRYA/ENTRY0/ENTRY1/ENTRY2/ENDENTRY/etc. etc. macro-guts torn out and +replaced by the PROJECTION macro (introduced in projects.h). + +This leads to code that looks a lot more like real C, and hence is much +less confusing to both syntax higlighters and humans. It also leads +to code that, after all projections have been processed, with a final +sweep over the code base can be brought into the style of the code in +PJ_minimal.c + +In my humble opinion the result wil be a code base that is not only easier +to maintain, but also more welcoming to new contributors. + +And if proj is to expand its strong basis in projections into the fields +of geodetic transformations and general geometric geodesy, we will need +to be able to attract quite a few expert geodesist contributors. + +And since expert geodesists are not necessarily expert coders, a welcoming +code base is a real asset (to put the icing on the cake of the already +welcoming user- and developer community). + +Note that the entire process does not touch the algorithmic/mathematical +parts of the code at all - it is actuallly an attempt to make this part +stand out more clearly. + +--- + +The attached material is an attempt to show what happens if we remove +the layers of macros, and introduce a more centralized approach to +memory allocation and initialization. + +Please note, however, that the level of cantralization achieved here +is not yet fully supported by the proj.4 infrastructure: It is an +example, intended to show what can be achieved through a smooth, +gradual and safe refactoring of the existing layered macro system. + +In my humble opinion, this version makes the beauty of Gerald's design +much more evident than the current layered-macro-version. + +Thomas Knudsen, thokn@sdfe.dk, 2016-03-31 + +***********************************************************************/ + +#define PJ_LIB__ +#include +#include +PROJ_HEAD(minimal, "Minimal example (brief description goes here)"); + + +/* Projection specific elements for the PJ object */ +struct opaque { + double a; + int b; +}; + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + /* Actual ellipsoidal forward code goes here */ + xy.y = lp.lam + P->es; + xy.x = lp.phi + 42; + return xy; +} + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + /* Actual spheroidal forward code goes here */ + xy.y = lp.lam + P->es; + xy.x = lp.phi + 42; + return xy; +} + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + /* Actual ellipsoidal forward code goes here */ + lp.lam = xy.x - P->es; + lp.phi = xy.y - P->opaq->b; + return lp; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + /* Actual spheroidal forward code goes here */ + lp.lam = xy.x - P->es; + lp.phi = xy.y - P->opaq->b; + return lp; +} + + +static void freeup(PJ *P) { /* Destructor */ + if (P==0) + return; + /* Projection specific deallocation goes here */ + pj_dealloc (P->opaq); + pj_dealloc (P); + return; +} + + +PJ *pj_projection_specific_setup_minimal (PJ *P) { + pj_prepare (P, des_minimal, freeup, sizeof (struct opaque)); + if (0==P->opaq) { + freeup (P); + return 0; + } + + P->opaq->a = 42.42; + P->opaq->b = 42; + + /* Spheroidal? */ + if (0==P->es) { + P->fwd = s_forward; + P->inv = s_inverse; + } + + /* Otherwise it's ellipsoidal */ + P->fwd = e_forward; + P->inv = e_inverse; + + return P; +} diff --git a/src/pj_init.c b/src/pj_init.c index 13d469da..ca7b9e4a 100644 --- a/src/pj_init.c +++ b/src/pj_init.c @@ -110,7 +110,7 @@ get_opt(projCtx ctx, paralist **start, PAFile fid, char *name, paralist *next, *sword = 't'; /* loop till we find our target keyword */ - while (*next_char) + while (*next_char) { next_char = fill_buffer(state, next_char); @@ -119,9 +119,9 @@ get_opt(projCtx ctx, paralist **start, PAFile fid, char *name, paralist *next, next_char++; next_char = fill_buffer(state, next_char); - + /* for comments, skip past end of line. */ - if( *next_char == '#' ) + if( *next_char == '#' ) { while( *next_char && *next_char != '\n' ) next_char++; @@ -131,11 +131,11 @@ get_opt(projCtx ctx, paralist **start, PAFile fid, char *name, paralist *next, next_char++; if (*next_char == '\r') next_char++; - - } + + } /* Is this our target? */ - else if( *next_char == '<' ) + else if( *next_char == '<' ) { /* terminate processing target on the next block definition */ if (in_target) @@ -143,7 +143,7 @@ get_opt(projCtx ctx, paralist **start, PAFile fid, char *name, paralist *next, next_char++; if (strncmp(name, next_char, len) == 0 - && next_char[len] == '>') + && next_char[len] == '>') { /* skip past target word */ next_char += len + 1; @@ -151,14 +151,14 @@ get_opt(projCtx ctx, paralist **start, PAFile fid, char *name, paralist *next, if(found_def) *found_def = 1; } - else + else { /* skip past end of line */ while( *next_char && *next_char != '\n' ) next_char++; } } - else if (in_target) + else if (in_target) { const char *start_of_word = next_char; int word_len = 0; @@ -183,27 +183,27 @@ get_opt(projCtx ctx, paralist **start, PAFile fid, char *name, paralist *next, if (!pj_param(ctx, *start, sword).i) { /* don't default ellipse if datum, ellps or any earth model information is set. */ - if( strncmp(sword+1,"ellps=",6) != 0 - || (!pj_param(ctx, *start, "tdatum").i - && !pj_param(ctx, *start, "tellps").i - && !pj_param(ctx, *start, "ta").i - && !pj_param(ctx, *start, "tb").i - && !pj_param(ctx, *start, "trf").i + if( strncmp(sword+1,"ellps=",6) != 0 + || (!pj_param(ctx, *start, "tdatum").i + && !pj_param(ctx, *start, "tellps").i + && !pj_param(ctx, *start, "ta").i + && !pj_param(ctx, *start, "tb").i + && !pj_param(ctx, *start, "trf").i && !pj_param(ctx, *start, "tf").i) ) { next = next->next = pj_mkparam(sword+1); } } - + } - else + else { /* skip past word */ while( *next_char && !isspace(*next_char) ) next_char++; - + } - } + } if (errno == 25) errno = 0; @@ -229,7 +229,7 @@ get_defaults(projCtx ctx, paralist **start, paralist *next, char *name) { if (errno) errno = 0; /* don't care if can't open file */ ctx->last_errno = 0; - + return next; } @@ -245,11 +245,11 @@ get_init(projCtx ctx, paralist **start, paralist *next, char *name, const paralist *orig_next = next; (void)strncpy(fname, name, MAX_PATH_FILENAME + ID_TAG_MAX + 1); - - /* - ** Search for file/key pair in cache + + /* + ** Search for file/key pair in cache */ - + init_items = pj_search_initcache( name ); if( init_items != NULL ) { @@ -275,8 +275,8 @@ get_init(projCtx ctx, paralist **start, paralist *next, char *name, if (errno == 25) errno = 0; /* unknown problem with some sys errno<-25 */ - /* - ** If we seem to have gotten a result, insert it into the + /* + ** If we seem to have gotten a result, insert it into the ** init file cache. */ if( next != NULL && next != orig_next ) @@ -308,7 +308,7 @@ pj_init_plus_ctx( projCtx ctx, const char *definition ) char *defn_copy; int argc = 0, i, blank_count = 0; PJ *result = NULL; - + /* make a copy that we can manipulate */ defn_copy = (char *) pj_malloc( strlen(definition)+1 ); strcpy( defn_copy, definition ); @@ -328,13 +328,13 @@ pj_init_plus_ctx( projCtx ctx, const char *definition ) defn_copy[i - blank_count] = '\0'; blank_count = 0; } - + if( argc+1 == MAX_ARG ) { pj_ctx_set_errno( ctx, -44 ); goto bum_call; } - + argv[argc++] = defn_copy + i + 1; } break; @@ -455,7 +455,7 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { PIN->rone_es = 1./PIN->one_es; /* Now that we have ellipse information check for WGS84 datum */ - if( PIN->datum_type == PJD_3PARAM + if( PIN->datum_type == PJD_3PARAM && PIN->datum_params[0] == 0.0 && PIN->datum_params[1] == 0.0 && PIN->datum_params[2] == 0.0 @@ -464,7 +464,7 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { { PIN->datum_type = PJD_WGS84; } - + /* set PIN->geoc coordinate system */ PIN->geoc = (PIN->es && pj_param(ctx, start, "bgeoc").i); @@ -532,7 +532,7 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { /* set units */ s = 0; - if ((name = pj_param(ctx, start, "sunits").s) != NULL) { + if ((name = pj_param(ctx, start, "sunits").s) != NULL) { for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i) ; if (!s) { pj_ctx_set_errno( ctx, -7 ); goto bum_call; } s = pj_units[i].to_meter; @@ -547,7 +547,7 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { /* set vertical units */ s = 0; - if ((name = pj_param(ctx, start, "svunits").s) != NULL) { + if ((name = pj_param(ctx, start, "svunits").s) != NULL) { for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i) ; if (!s) { pj_ctx_set_errno( ctx, -7 ); goto bum_call; } s = pj_units[i].to_meter; @@ -564,7 +564,7 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { /* prime meridian */ s = 0; - if ((name = pj_param(ctx, start, "spm").s) != NULL) { + if ((name = pj_param(ctx, start, "spm").s) != NULL) { const char *value = NULL; char *next_str = NULL; @@ -576,8 +576,8 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { break; } } - - if( value == NULL + + if( value == NULL && (dmstor_ctx(ctx,name,&next_str) != 0.0 || *name == '0') && *next_str == '\0' ) value = name; @@ -639,3 +639,27 @@ pj_free(PJ *P) { P->pfree(P); } } + + + + + + + + +/************************************************************************/ +/* pj_prepare() */ +/* */ +/* Helper function for the PJ_xxxx functions providing the */ +/* projection specific setup for each projection type. */ +/* */ +/* Currently not used, but placed here as part of the material */ +/* Demonstrating the idea for a future PJ_xxx architecture */ +/* (cf. pj_minimal.c) */ +/* */ +/************************************************************************/ +void pj_prepare (PJ *P, const char *description, void (*freeup)(struct PJconsts *), size_t sizeof_struct_opaque) { + P->descr = description; + P->pfree = freeup; + P->opaq = pj_calloc (1, sizeof_struct_opaque); +} diff --git a/src/pj_malloc.c b/src/pj_malloc.c index 80443a2b..aab69e99 100644 --- a/src/pj_malloc.c +++ b/src/pj_malloc.c @@ -9,19 +9,64 @@ pj_malloc(size_t size) { /* / Currently, pj_malloc is a hack to solve an errno problem. -/ The problem is described in more details at -/ https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=86420. -/ It seems, that pj_init and similar functions incorrectly -/ (under debian/glibs-2.3.2) assume that pj_malloc resets +/ The problem is described in more details at +/ https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=86420. +/ It seems, that pj_init and similar functions incorrectly +/ (under debian/glibs-2.3.2) assume that pj_malloc resets / errno after success. pj_malloc tries to mimic this. */ int old_errno = errno; - void *res = malloc(size); + void *res = malloc(size); if ( res && !old_errno ) - errno = 0; + errno = 0; return res; } void pj_dalloc(void *ptr) { free(ptr); } + + +/**********************************************************************/ +void *pj_calloc (size_t n, size_t size) { +/*********************************************************************** + +pj_calloc is the pj-equivalent of calloc(). + +It allocates space for an array of elements of size . +The array is initialized to zeros. + +***********************************************************************/ + void *res = pj_malloc (n*size); + if (0==res) + return 0; + memset (res, 0, n*size); + return res; +} + + +/**********************************************************************/ +void *pj_dealloc (void *ptr) { +/*********************************************************************** + +pj_dealloc supports the common use case of "clean up and return a null +pointer" to signal an error in a multi level allocation: + + struct foo { int bar; int *baz; }; + + struct foo *p = pj_calloc (1, sizeof (struct foo)); + if (0==p) + return 0; + + p->baz = pj_calloc (10, sizeof(int)); + if (0==p->baz) + return pj_dealloc (p); // clean up + signal error by 0-return + + return p; // success + +***********************************************************************/ + if (0==ptr) + return 0; + pj_dalloc (ptr); + return 0; +} diff --git a/src/proj_api.h b/src/proj_api.h index b482c0f5..dd25d61a 100644 --- a/src/proj_api.h +++ b/src/proj_api.h @@ -130,6 +130,8 @@ char *pj_get_def(projPJ, int); projPJ pj_latlong_from_proj( projPJ ); void *pj_malloc(size_t); void pj_dalloc(void *); +void *pj_calloc (size_t n, size_t size); +void *pj_dealloc (void *ptr); char *pj_strerrno(int); int *pj_get_errno_ref(void); const char *pj_get_release(void); diff --git a/src/projects.h b/src/projects.h index 411a3403..3106eb76 100644 --- a/src/projects.h +++ b/src/projects.h @@ -48,7 +48,7 @@ #define C_NAMESPACE extern "C" #define C_NAMESPACE_VAR extern "C" extern "C" { -#else +#else #define C_NAMESPACE extern #define C_NAMESPACE_VAR #endif @@ -132,8 +132,8 @@ typedef struct { /* datum_type values */ #define PJD_UNKNOWN 0 -#define PJD_3PARAM 1 -#define PJD_7PARAM 2 +#define PJD_3PARAM 1 +#define PJD_7PARAM 2 #define PJD_GRIDSHIFT 3 #define PJD_WGS84 4 /* WGS84 (or anything considered equivelent) */ @@ -143,7 +143,7 @@ typedef struct { #define PJD_ERR_GRID_AREA -48 #define PJD_ERR_CATALOG -49 -#define USE_PROJUV +#define USE_PROJUV typedef struct { double u, v; } projUV; typedef struct { double r, i; } COMPLEX; @@ -163,7 +163,7 @@ typedef struct { double lam, phi, z; } LPZ; typedef union { double f; int i; char *s; } PROJVALUE; struct PJconsts; - + struct PJ_LIST { char *id; /* projection keyword */ struct PJconsts *(*proj)(struct PJconsts*);/* projection entry point */ @@ -197,14 +197,14 @@ typedef struct { double ll_long; /* lower left corner coordinates (radians) */ double ll_lat; double ur_long; /* upper right corner coordinates (radians) */ - double ur_lat; + double ur_lat; } PJ_Region; struct DERIVS { double x_l, x_p; /* derivatives of x for lambda-phi */ double y_l, y_p; /* derivatives of y for lambda-phi */ }; - + struct FACTORS { struct DERIVS der; double h, k; /* meridinal, parallel scales */ @@ -226,12 +226,18 @@ typedef struct ARG_list { /* base projection data structure */ +#ifdef PJ_LIB__ + /* we need this forward declaration in order to be able to add a + pointer to struct opaque to the typedef struct PJconsts below */ + struct opaque; +#endif + typedef struct PJconsts { projCtx_t *ctx; XY (*fwd)(LP, struct PJconsts *); LP (*inv)(XY, struct PJconsts *); XYZ (*fwd3d)(LPZ, struct PJconsts *); - LPZ (*inv3d)(XYZ, struct PJconsts *); + LPZ (*inv3d)(XYZ, struct PJconsts *); void (*spc)(LP, struct PJconsts *, struct FACTORS *); void (*pfree)(struct PJconsts *); const char *descr; @@ -253,7 +259,7 @@ typedef struct PJconsts { x0, y0, /* easting and northing */ k0, /* general scaling factor */ to_meter, fr_meter; /* cartesian scaling */ - + int datum_type; /* PJD_UNKNOWN/3PARAM/7PARAM/GRIDSHIFT/WGS84 */ double datum_params[7]; struct _pj_gi **gridlist; @@ -272,9 +278,9 @@ typedef struct PJconsts { /* New Datum Shift Grid Catalogs */ char *catalog_name; struct _PJ_GridCatalog *catalog; - + double datum_date; - + struct _pj_gi *last_before_grid; PJ_Region last_before_region; double last_before_date; @@ -283,6 +289,10 @@ typedef struct PJconsts { PJ_Region last_after_region; double last_after_date; +#ifdef PJ_LIB__ + struct opaque *opaq; +#endif + #ifdef PROJ_PARMS__ PROJ_PARMS__ #endif /* end of optional extensions */ @@ -297,7 +307,7 @@ extern struct PJ_LIST pj_list[]; #else #define PROJ_HEAD(id, name) \ struct PJconsts *pj_##id(struct PJconsts*); extern char * const pj_s_##id; - + #include "pj_list.h" #undef PROJ_HEAD #define PROJ_HEAD(id, name) {#id, pj_##id, &pj_s_##id}, @@ -350,7 +360,27 @@ extern struct PJ_PRIME_MERIDIANS pj_prime_meridians[]; #define INVERSE3D(name) static LPZ name(XYZ xyz, PJ *P) {LPZ lpz = {0.0, 0.0, 0.0} #define FREEUP static void freeup(PJ *P) { #define SPECIAL(name) static void name(LP lp, PJ *P, struct FACTORS *fac) + + +/* cleaned up alternative to most of the "repetitive projection code" macros */ +#define PROJECTION(name) \ +pj_projection_specific_setup_##name (PJ *P); \ +C_NAMESPACE_VAR const char * const pj_s_##name = des_##name; \ +C_NAMESPACE PJ *pj_##name (PJ *P) { \ + if (P) \ + return pj_projection_specific_setup_##name (P); \ + P = (PJ*) pj_calloc (1, sizeof(PJ)); \ + if (0==P) \ + return 0; \ + P->pfree = freeup; \ + P->descr = des_##name; \ + return P; \ +} \ +PJ *pj_projection_specific_setup_##name (PJ *P) + #endif + + #define MAX_TAB_ID 80 typedef struct { float lam, phi; } FLP; typedef struct { int lam, phi; } ILP; @@ -366,8 +396,8 @@ struct CTABLE { typedef struct _pj_gi { char *gridname; /* identifying name of grid, eg "conus" or ntv2_0.gsb */ char *filename; /* full path to filename */ - - const char *format; /* format of this grid, ie "ctable", "ntv1", + + const char *format; /* format of this grid, ie "ctable", "ntv1", "ntv2" or "missing". */ int grid_offset; /* offset in file, for delayed loading */ @@ -414,6 +444,7 @@ int pj_ell_set(projCtx ctx, paralist *, double *, double *); int pj_datum_set(projCtx,paralist *, PJ *); int pj_prime_meridian_set(paralist *, PJ *); int pj_angular_units_set(paralist *, PJ *); +void pj_prepare (PJ *P, const char *description, void (*freeup)(struct PJconsts *), size_t sizeof_struct_opaque); paralist *pj_clone_paralist( const paralist* ); paralist*pj_search_initcache( const char *filekey ); @@ -439,7 +470,7 @@ struct PW_COEF {/* row coefficient structure */ int m; /* number of c coefficients (=0 for none) */ double *c; /* power coefficients */ }; - + /* Approximation structures and procedures */ typedef struct { /* Chebyshev or Power series structure */ projUV a, b; /* power series range for evaluation */ @@ -457,6 +488,7 @@ void **vector2(int, int, int); void freev2(void **v, int nrows); int bchgen(projUV, projUV, int, int, projUV **, projUV(*)(projUV)); int bch2bps(projUV, projUV, projUV **, int, int); + /* nadcon related protos */ LP nad_intr(LP, struct CTABLE *); LP nad_cvt(LP, int, struct CTABLE *); @@ -470,15 +502,15 @@ void nad_free(struct CTABLE *); /* higher level handling of datum grid shift files */ int pj_apply_vgridshift( PJ *defn, const char *listname, - PJ_GRIDINFO ***gridlist_p, + PJ_GRIDINFO ***gridlist_p, int *gridlist_count_p, - int inverse, + int inverse, long point_count, int point_offset, double *x, double *y, double *z ); -int pj_apply_gridshift_2( PJ *defn, int inverse, +int pj_apply_gridshift_2( PJ *defn, int inverse, long point_count, int point_offset, double *x, double *y, double *z ); -int pj_apply_gridshift_3( projCtx ctx, +int pj_apply_gridshift_3( projCtx ctx, PJ_GRIDINFO **gridlist, int gridlist_count, int inverse, long point_count, int point_offset, double *x, double *y, double *z ); @@ -493,15 +525,15 @@ void pj_gridinfo_free( projCtx, PJ_GRIDINFO * ); PJ_GridCatalog *pj_gc_findcatalog( projCtx, const char * ); PJ_GridCatalog *pj_gc_readcatalog( projCtx, const char * ); void pj_gc_unloadall( projCtx ); -int pj_gc_apply_gridshift( PJ *defn, int inverse, +int pj_gc_apply_gridshift( PJ *defn, int inverse, long point_count, int point_offset, double *x, double *y, double *z ); -int pj_gc_apply_gridshift( PJ *defn, int inverse, +int pj_gc_apply_gridshift( PJ *defn, int inverse, long point_count, int point_offset, double *x, double *y, double *z ); -PJ_GRIDINFO *pj_gc_findgrid( projCtx ctx, - PJ_GridCatalog *catalog, int after, +PJ_GRIDINFO *pj_gc_findgrid( projCtx ctx, + PJ_GridCatalog *catalog, int after, LP location, double date, PJ_Region *optional_region, double *grid_date ); -- cgit v1.2.3 From 83cdf16f019c7612192ff68504e5c20b7ef59d01 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Fri, 1 Apr 2016 23:52:00 +0200 Subject: Added missing return to cass, spherical case Correcting a blunder! --- src/PJ_cass.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/PJ_cass.c b/src/PJ_cass.c index 5d7aea3c..9e26ad8f 100644 --- a/src/PJ_cass.c +++ b/src/PJ_cass.c @@ -103,6 +103,7 @@ PJ *PROJECTION(cass) { if (0==P->es) { P->inv = s_inverse; P->fwd = s_forward; + return P; } /* Otherwise it's ellipsoidal */ -- cgit v1.2.3 From afebe65cb503e40f9a89b5f931a1f94fb545e067 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Sat, 2 Apr 2016 00:06:15 +0200 Subject: ... and correcting the same blunder in the pj_minimal case --- src/PJ_minimal.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/PJ_minimal.c b/src/PJ_minimal.c index 210d25d3..824d8b99 100644 --- a/src/PJ_minimal.c +++ b/src/PJ_minimal.c @@ -193,6 +193,7 @@ PJ *pj_projection_specific_setup_minimal (PJ *P) { if (0==P->es) { P->fwd = s_forward; P->inv = s_inverse; + return P; } /* Otherwise it's ellipsoidal */ -- cgit v1.2.3 From eeea65526dfd0301a7759a978a5b8fcbcf5baecd Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Tue, 5 Apr 2016 19:05:06 +0200 Subject: Some initial work on internal regression tests Need these to reduce the chance I'm screwing up something during this rather intrusive code surgery --- src/PJ_aea.c | 316 ++++++++++++++++++++++++++++++++++++---------- src/PJ_cass.c | 85 +++++++------ src/lib_proj.cmake | 2 + src/pj_generic_selftest.c | 200 +++++++++++++++++++++++++++++ src/pj_init.c | 2 +- src/pj_run_selftests.c | 63 +++++++++ src/proj.c | 15 ++- src/proj_api.h | 3 + src/projects.h | 22 +++- 9 files changed, 589 insertions(+), 119 deletions(-) create mode 100644 src/pj_generic_selftest.c create mode 100644 src/pj_run_selftests.c (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 0881ba78..8285e68f 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -1,7 +1,9 @@ /****************************************************************************** * Project: PROJ.4 * Purpose: Implementation of the aea (Albers Equal Area) projection. - * Author: Gerald Evenden + * and the leac (Lambert Equal Area Conic) projection + * Author: Gerald Evenden (1995) + * Thomas Knudsen (2016) - revise/add regression tests * ****************************************************************************** * Copyright (c) 1995, Gerald Evenden @@ -25,35 +27,21 @@ * DEALINGS IN THE SOFTWARE. *****************************************************************************/ -#define PROJ_PARMS__ \ - double ec; \ - double n; \ - double c; \ - double dd; \ - double n2; \ - double rho0; \ - double rho; \ - double phi1; \ - double phi2; \ - double *en; \ - int ellips; - #define PJ_LIB__ #include # define EPS10 1.e-10 # define TOL7 1.e-7 -PROJ_HEAD(aea, "Albers Equal Area") - "\n\tConic Sph&Ell\n\tlat_1= lat_2="; -PROJ_HEAD(leac, "Lambert Equal Area Conic") - "\n\tConic, Sph&Ell\n\tlat_1= south"; +PROJ_HEAD(aea, "Albers Equal Area") "\n\tConic Sph&Ell\n\tlat_1= lat_2="; +PROJ_HEAD(leac, "Lambert Equal Area Conic") "\n\tConic, Sph&Ell\n\tlat_1= south"; + + /* determine latitude angle phi-1 */ # define N_ITER 15 # define EPSILON 1.0e-7 # define TOL 1.0e-10 - static double -phi1_(double qs, double Te, double Tone_es) { +static double phi1_(double qs, double Te, double Tone_es) { int i; double Phi, sinpi, cospi, con, com, dphi; @@ -73,86 +61,276 @@ phi1_(double qs, double Te, double Tone_es) { } while (fabs(dphi) > TOL && --i); return( i ? Phi : HUGE_VAL ); } -FORWARD(e_forward); /* ellipsoid & spheroid */ - if ((P->rho = P->c - (P->ellips ? P->n * pj_qsfn(sin(lp.phi), - P->e, P->one_es) : P->n2 * sin(lp.phi))) < 0.) F_ERROR - P->rho = P->dd * sqrt(P->rho); - xy.x = P->rho * sin( lp.lam *= P->n ); - xy.y = P->rho0 - P->rho * cos(lp.lam); - return (xy); + + +struct pj_opaque { + double ec; + double n; + double c; + double dd; + double n2; + double rho0; + double rho; + double phi1; + double phi2; + double *en; + int ellips; +}; + + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoid/spheroid, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + if ((Q->rho = Q->c - (Q->ellips ? Q->n * pj_qsfn(sin(lp.phi), + P->e, P->one_es) : Q->n2 * sin(lp.phi))) < 0.) F_ERROR + Q->rho = Q->dd * sqrt(Q->rho); + xy.x = Q->rho * sin( lp.lam *= Q->n ); + xy.y = Q->rho0 - Q->rho * cos(lp.lam); + return xy; } -INVERSE(e_inverse) /* ellipsoid & spheroid */; - if( (P->rho = hypot(xy.x, xy.y = P->rho0 - xy.y)) != 0.0 ) { - if (P->n < 0.) { - P->rho = -P->rho; + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoid/spheroid, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + if( (Q->rho = hypot(xy.x, xy.y = Q->rho0 - xy.y)) != 0.0 ) { + if (Q->n < 0.) { + Q->rho = -Q->rho; xy.x = -xy.x; xy.y = -xy.y; } - lp.phi = P->rho / P->dd; - if (P->ellips) { - lp.phi = (P->c - lp.phi * lp.phi) / P->n; - if (fabs(P->ec - fabs(lp.phi)) > TOL7) { + lp.phi = Q->rho / Q->dd; + if (Q->ellips) { + lp.phi = (Q->c - lp.phi * lp.phi) / Q->n; + if (fabs(Q->ec - fabs(lp.phi)) > TOL7) { if ((lp.phi = phi1_(lp.phi, P->e, P->one_es)) == HUGE_VAL) I_ERROR } else lp.phi = lp.phi < 0. ? -HALFPI : HALFPI; - } else if (fabs(lp.phi = (P->c - lp.phi * lp.phi) / P->n2) <= 1.) + } else if (fabs(lp.phi = (Q->c - lp.phi * lp.phi) / Q->n2) <= 1.) lp.phi = asin(lp.phi); else lp.phi = lp.phi < 0. ? -HALFPI : HALFPI; - lp.lam = atan2(xy.x, xy.y) / P->n; + lp.lam = atan2(xy.x, xy.y) / Q->n; } else { lp.lam = 0.; - lp.phi = P->n > 0. ? HALFPI : - HALFPI; + lp.phi = Q->n > 0. ? HALFPI : - HALFPI; } - return (lp); + return lp; } -FREEUP; if (P) { if (P->en) pj_dalloc(P->en); pj_dalloc(P); } } - static PJ * -setup(PJ *P) { + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque->en); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +static PJ *setup(PJ *P) { double cosphi, sinphi; int secant; + struct pj_opaque *Q = P->opaque; - if (fabs(P->phi1 + P->phi2) < EPS10) E_ERROR(-21); - P->n = sinphi = sin(P->phi1); - cosphi = cos(P->phi1); - secant = fabs(P->phi1 - P->phi2) >= EPS10; - if( (P->ellips = (P->es > 0.))) { + P->inv = e_inverse; + P->fwd = e_forward; + + if (fabs(Q->phi1 + Q->phi2) < EPS10) E_ERROR(-21); + Q->n = sinphi = sin(Q->phi1); + cosphi = cos(Q->phi1); + secant = fabs(Q->phi1 - Q->phi2) >= EPS10; + if( (Q->ellips = (P->es > 0.))) { double ml1, m1; - if (!(P->en = pj_enfn(P->es))) E_ERROR_0; + if (!(Q->en = pj_enfn(P->es))) E_ERROR_0; m1 = pj_msfn(sinphi, cosphi, P->es); ml1 = pj_qsfn(sinphi, P->e, P->one_es); if (secant) { /* secant cone */ double ml2, m2; - sinphi = sin(P->phi2); - cosphi = cos(P->phi2); + sinphi = sin(Q->phi2); + cosphi = cos(Q->phi2); m2 = pj_msfn(sinphi, cosphi, P->es); ml2 = pj_qsfn(sinphi, P->e, P->one_es); - P->n = (m1 * m1 - m2 * m2) / (ml2 - ml1); + Q->n = (m1 * m1 - m2 * m2) / (ml2 - ml1); } - P->ec = 1. - .5 * P->one_es * log((1. - P->e) / + Q->ec = 1. - .5 * P->one_es * log((1. - P->e) / (1. + P->e)) / P->e; - P->c = m1 * m1 + P->n * ml1; - P->dd = 1. / P->n; - P->rho0 = P->dd * sqrt(P->c - P->n * pj_qsfn(sin(P->phi0), + Q->c = m1 * m1 + Q->n * ml1; + Q->dd = 1. / Q->n; + Q->rho0 = Q->dd * sqrt(Q->c - Q->n * pj_qsfn(sin(P->phi0), P->e, P->one_es)); } else { - if (secant) P->n = .5 * (P->n + sin(P->phi2)); - P->n2 = P->n + P->n; - P->c = cosphi * cosphi + P->n2 * sinphi; - P->dd = 1. / P->n; - P->rho0 = P->dd * sqrt(P->c - P->n2 * sin(P->phi0)); + if (secant) Q->n = .5 * (Q->n + sin(Q->phi2)); + Q->n2 = Q->n + Q->n; + Q->c = cosphi * cosphi + Q->n2 * sinphi; + Q->dd = 1. / Q->n; + Q->rho0 = Q->dd * sqrt(Q->c - Q->n2 * sin(P->phi0)); } - P->inv = e_inverse; P->fwd = e_forward; + return P; } -ENTRY1(aea,en) - P->phi1 = pj_param(P->ctx, P->params, "rlat_1").f; - P->phi2 = pj_param(P->ctx, P->params, "rlat_2").f; -ENDENTRY(setup(P)) -ENTRY1(leac,en) - P->phi2 = pj_param(P->ctx, P->params, "rlat_1").f; - P->phi1 = pj_param(P->ctx, P->params, "bsouth").i ? - HALFPI: HALFPI; -ENDENTRY(setup(P)) + + +PJ *PROJECTION(aea) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_aea; + + Q->phi1 = pj_param(P->ctx, P->params, "rlat_1").f; + Q->phi2 = pj_param(P->ctx, P->params, "rlat_2").f; + setup(P); + return P; +} + + +PJ *PROJECTION(leac) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_leac; + Q->phi2 = pj_param(P->ctx, P->params, "rlat_1").f; + Q->phi1 = pj_param(P->ctx, P->params, "bsouth").i ? - HALFPI: HALFPI; + setup(P); + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_aea_selftest (void) {return 0;} +#else + +int pj_aea_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=aea +ellps=GRS80 +lat_1=0 +lat_2=2"}; + char s_args[] = {"+proj=aea +ellps=GRS80 +lat_1=0 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {222571.60875710563, 110653.32674302977}, + {222706.30650839131, -110484.26714439997}, + {-222571.60875710563, 110653.32674302977}, + {-222706.30650839131, -110484.26714439997}, + }; + + XY s_fwd_expect[] = { + {223334.08517088494, 111780.43188447191}, + {223470.15499168713, -111610.33943099028}, + {-223334.08517088494, 111780.43188447191}, + {-223470.15499168713, -111610.33943099028}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0017966310597749514, 0.00090436885862202158}, + {0.0017966300767030448, -0.00090437009538581453}, + {-0.0017966310597749514, 0.00090436885862202158}, + {-0.0017966300767030448, -0.00090437009538581453}, + }; + + LP s_inv_expect[] = { + {0.0017904935979658752, 0.00089524594491375306}, + {0.0017904926216016812, -0.00089524716502493225}, + {-0.0017904935979658752, 0.00089524594491375306}, + {-0.0017904926216016812, -0.00089524716502493225}, + }; + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif + + + +#ifdef PJ_OMIT_SELFTEST +int pj_leac_selftest (void) {return 0;} +#else + +int pj_leac_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=leac +ellps=GRS80 +lat_1=0 +lat_2=2"}; + char s_args[] = {"+proj=leac +ellps=GRS80 +lat_1=0 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {220685.14054297868, 112983.50088939646}, + {224553.31227982609, -108128.63674487274}, + {-220685.14054297868, 112983.50088939646}, + {-224553.31227982609, -108128.63674487274}, + }; + + XY s_fwd_expect[] = { + {221432.86859285168, 114119.45452653214}, + {225331.72412711097, -109245.82943505641}, + {-221432.86859285168, 114119.45452653214}, + {-225331.72412711097, -109245.82943505641}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0017966446840328458, 0.00090435171340223211}, + {0.0017966164523713021, -0.00090438724081843625}, + {-0.0017966446840328458, 0.00090435171340223211}, + {-0.0017966164523713021, -0.00090438724081843625}, + }; + + LP s_inv_expect[] = { + {0.0017905070979748127, 0.00089522906964877795}, + {0.001790479121519977, -0.00089526404022281043}, + {-0.0017905070979748127, 0.00089522906964877795}, + {-0.001790479121519977, -0.00089526404022281043}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif diff --git a/src/PJ_cass.c b/src/PJ_cass.c index 9e26ad8f..5f885376 100644 --- a/src/PJ_cass.c +++ b/src/PJ_cass.c @@ -11,7 +11,7 @@ PROJ_HEAD(cass, "Cassini") "\n\tCyl, Sph&Ell"; # define C5 .06666666666666666666 -struct opaque { +struct pj_opaque { /* These are the only opaque members actually initialized */ double *en; double m0; @@ -32,17 +32,17 @@ struct opaque { static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ XY xy = {0.0,0.0}; - struct opaque *O = P->opaq; - xy.y = pj_mlfn(lp.phi, O->n = sin(lp.phi), O->c = cos(lp.phi), O->en); - O->n = 1./sqrt(1. - P->es * O->n * O->n); - O->tn = tan(lp.phi); O->t = O->tn * O->tn; - O->a1 = lp.lam * O->c; - O->c *= P->es * O->c / (1 - P->es); - O->a2 = O->a1 * O->a1; - xy.x = O->n * O->a1 * (1. - O->a2 * O->t * - (C1 - (8. - O->t + 8. * O->c) * O->a2 * C2)); - xy.y -= O->m0 - O->n * O->tn * O->a2 * - (.5 + (5. - O->t + 6. * O->c) * O->a2 * C3); + struct pj_opaque *Q = P->opaque; + xy.y = pj_mlfn(lp.phi, Q->n = sin(lp.phi), Q->c = cos(lp.phi), Q->en); + Q->n = 1./sqrt(1. - P->es * Q->n * Q->n); + Q->tn = tan(lp.phi); Q->t = Q->tn * Q->tn; + Q->a1 = lp.lam * Q->c; + Q->c *= P->es * Q->c / (1 - P->es); + Q->a2 = Q->a1 * Q->a1; + xy.x = Q->n * Q->a1 * (1. - Q->a2 * Q->t * + (C1 - (8. - Q->t + 8. * Q->c) * Q->a2 * C2)); + xy.y -= Q->m0 - Q->n * Q->tn * Q->a2 * + (.5 + (5. - Q->t + 6. * Q->c) * Q->a2 * C3); return xy; } @@ -57,45 +57,48 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ LP lp = {0.0,0.0}; - struct opaque *O = P->opaq; + struct pj_opaque *Q = P->opaque; double ph1; - ph1 = pj_inv_mlfn(P->ctx, O->m0 + xy.y, P->es, O->en); - O->tn = tan(ph1); O->t = O->tn * O->tn; - O->n = sin(ph1); - O->r = 1. / (1. - P->es * O->n * O->n); - O->n = sqrt(O->r); - O->r *= (1. - P->es) * O->n; - O->dd = xy.x / O->n; - O->d2 = O->dd * O->dd; - lp.phi = ph1 - (O->n * O->tn / O->r) * O->d2 * - (.5 - (1. + 3. * O->t) * O->d2 * C3); - lp.lam = O->dd * (1. + O->t * O->d2 * - (-C4 + (1. + 3. * O->t) * O->d2 * C5)) / cos(ph1); + ph1 = pj_inv_mlfn(P->ctx, Q->m0 + xy.y, P->es, Q->en); + Q->tn = tan(ph1); Q->t = Q->tn * Q->tn; + Q->n = sin(ph1); + Q->r = 1. / (1. - P->es * Q->n * Q->n); + Q->n = sqrt(Q->r); + Q->r *= (1. - P->es) * Q->n; + Q->dd = xy.x / Q->n; + Q->d2 = Q->dd * Q->dd; + lp.phi = ph1 - (Q->n * Q->tn / Q->r) * Q->d2 * + (.5 - (1. + 3. * Q->t) * Q->d2 * C3); + lp.lam = Q->dd * (1. + Q->t * Q->d2 * + (-C4 + (1. + 3. * Q->t) * Q->d2 * C5)) / cos(ph1); return lp; } static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ LP lp = {0.0,0.0}; - lp.phi = asin(sin(P->opaq->dd = xy.y + P->phi0) * cos(xy.x)); - lp.lam = atan2(tan(xy.x), cos(P->opaq->dd)); + lp.phi = asin(sin(P->opaque->dd = xy.y + P->phi0) * cos(xy.x)); + lp.lam = atan2(tan(xy.x), cos(P->opaque->dd)); return lp; } -static void freeup(PJ *P) { /* Destructor */ +static void *freeup_new(PJ *P) { /* Destructor */ if (0==P) - return; - if (0==P->opaq) { - pj_dealloc (P); - return; - } - pj_dealloc(P->opaq->en); - pj_dealloc(P->opaq); - pj_dealloc(P); + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc(P->opaque->en); + pj_dealloc(P->opaque); + return pj_dealloc(P); } +static void freeup(PJ *P) { /* Destructor */ + freeup_new (P); + return; +} PJ *PROJECTION(cass) { @@ -107,19 +110,19 @@ PJ *PROJECTION(cass) { } /* Otherwise it's ellipsoidal */ - P->opaq = pj_calloc (1, sizeof (struct opaque)); - if (0==P->opaq) { + P->opaque = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==P->opaque) { freeup (P); return 0; } - P->opaq->en = pj_enfn(P->es); - if (0==P->opaq->en) { + P->opaque->en = pj_enfn(P->es); + if (0==P->opaque->en) { freeup (P); return 0; } - P->opaq->m0 = pj_mlfn(P->phi0, sin(P->phi0), cos(P->phi0), P->opaq->en); + P->opaque->m0 = pj_mlfn(P->phi0, sin(P->phi0), cos(P->phi0), P->opaque->en); P->inv = e_inverse; P->fwd = e_forward; diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake index a8797a74..eeb0582d 100644 --- a/src/lib_proj.cmake +++ b/src/lib_proj.cmake @@ -172,6 +172,7 @@ SET(SRC_LIBPROJ_CORE pj_fwd3d.c pj_gauss.c pj_gc_reader.c + pj_generic_selftest.c pj_geocent.c pj_gridcatalog.c pj_gridinfo.c @@ -195,6 +196,7 @@ SET(SRC_LIBPROJ_CORE pj_pr_list.c pj_qsfn.c pj_release.c + pj_run_selftests.c pj_strerrno.c pj_transform.c pj_tsfn.c diff --git a/src/pj_generic_selftest.c b/src/pj_generic_selftest.c new file mode 100644 index 00000000..e2d24baf --- /dev/null +++ b/src/pj_generic_selftest.c @@ -0,0 +1,200 @@ +/****************************************************************************** + * Project: PROJ.4 + * Purpose: Generic regression test for PROJ.4 projection algorithms. + * Author: Thomas Knudsen + * + ****************************************************************************** + * Copyright (c) 2016, Thomas Knudsen + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + *****************************************************************************/ + + +#include +#define PJ_LIB__ +#include + + +static int deviates_xy (XY expected, XY got, double tolerance); +static int deviates_lp (LP expected, LP got, double tolerance); +static XY pj_fwd_deg (LP in, PJ *P); + + +/**********************************************************************/ +int pj_generic_selftest ( +/**********************************************************************/ + char *e_args, + char *s_args, + double tolerance_xy, + double tolerance_lp, + int n_fwd, + int n_inv, + LP *fwd_in, + XY *e_fwd_expect, + XY *s_fwd_expect, + XY *inv_in, + LP *e_inv_expect, + LP *s_inv_expect +) { +/*********************************************************************** + +Generic regression test for PROJ.4 projection algorithms, testing both +ellipsoidal ("e_") and spheroidal ("s_") versions of the projection +algorithms in both forward ("_fwd_") and inverse ("_inv_") mode. + +Compares the "known good" results in and +with the actual results obtained by transforming the forward input data +set in with pj_fwd() using setup arguments and +, respectively. + +Then + +Compares the "known good" results in and +with the actual results obtained by transforming the inverse input data +set in with pj_inv() using setup arguments and +, respectively. + +Any of the pointers passed may be set to 0, indicating "don't test this +part". + +Returns 0 if all data agree to within the accuracy specified in + and . Non-zero otherwise. + +***********************************************************************/ + int i; + + PJ *P; + +puts ("testing"); + if (e_args) { + + puts ("e_args"); + puts (e_args); + + P = pj_init_plus(e_args); + if (0==P) + return 2; + + /* Test forward ellipsoidal */ + if (e_fwd_expect) { puts ("e_fwd"); + for (i = 0; i < n_fwd; i++) + if (deviates_xy (e_fwd_expect[i], pj_fwd_deg ( fwd_in[i], P ), tolerance_xy)) + break; + if ( i != n_fwd ) + return 100 + i; + } + + /* Test inverse ellipsoidal */ + if (e_inv_expect) { puts ("e_inv"); + for (i = 0; i < n_inv; i++) + if (deviates_lp (e_inv_expect[i], pj_inv ( inv_in[i], P ), tolerance_lp)) + break; + if ( i != n_inv ) + return 200 + i; + } + + pj_free (P); + } + + + if (s_args) { + puts ("s_args"); + puts (s_args); + P = pj_init_plus(s_args); + if (0==P) + return 3; + + /* Test forward spherical */ + if (s_fwd_expect) { puts ("s_fwd"); + for (i = 0; i < n_fwd; i++) + if (deviates_xy (s_fwd_expect[i], pj_fwd_deg ( fwd_in[i], P ), tolerance_xy)) + break; + if ( i != n_fwd ) + return 300 + i; + } + + /* Test inverse spherical */ + if (s_inv_expect) { puts ("s_inv"); + for (i = 0; i < n_inv; i++) + if (deviates_lp (s_inv_expect[i], pj_inv ( inv_in[i], P ), tolerance_lp)) + break; + if ( i != n_inv ) + return 400 + i; + } + + pj_free (P); + } + + return 0; +} + + + +/**********************************************************************/ +static int deviates_xy (XY expected, XY got, double tolerance) { +/*********************************************************************** + + Determine whether two XYs deviate by more than . + +***********************************************************************/ + if (HUGE_VAL== expected.x) + return 0; + if (HUGE_VAL== expected.y) + return 0; + if (hypot ( expected.x - got.x, expected.y - got.y ) > tolerance) + return 1; + return 0; +} + + +/**********************************************************************/ +static int deviates_lp (LP expected, LP got, double tolerance) { +/*********************************************************************** + + Determine whether two LPs deviate by more than . + + This one is slightly tricky, since the LP is + supposed to be represented as degrees (since it was at some + time written down by a real human), whereas the LP is + represented in radians (since it is supposed to be the result + output from pj_inv) + +***********************************************************************/ + if (HUGE_VAL== expected.lam) + return 0; + if (HUGE_VAL== expected.phi) + return 0; + if (hypot ( DEG_TO_RAD * expected.lam - got.lam, DEG_TO_RAD * expected.phi - got.phi ) > tolerance) + return 1; + return 0; +} + + +/**********************************************************************/ +static XY pj_fwd_deg (LP in, PJ *P) { +/*********************************************************************** + + Wrapper for pj_fwd, accepting input in degrees. + +***********************************************************************/ + LP in_rad; + in_rad.lam = DEG_TO_RAD * in.lam; + in_rad.phi = DEG_TO_RAD * in.phi; + return pj_fwd (in_rad, P); +} diff --git a/src/pj_init.c b/src/pj_init.c index ca7b9e4a..79b64bb3 100644 --- a/src/pj_init.c +++ b/src/pj_init.c @@ -661,5 +661,5 @@ pj_free(PJ *P) { void pj_prepare (PJ *P, const char *description, void (*freeup)(struct PJconsts *), size_t sizeof_struct_opaque) { P->descr = description; P->pfree = freeup; - P->opaq = pj_calloc (1, sizeof_struct_opaque); + P->opaque = pj_calloc (1, sizeof_struct_opaque); } diff --git a/src/pj_run_selftests.c b/src/pj_run_selftests.c new file mode 100644 index 00000000..44573b2b --- /dev/null +++ b/src/pj_run_selftests.c @@ -0,0 +1,63 @@ +/****************************************************************************** + * Project: PROJ.4 + * Purpose: Generic regression test for PROJ.4 projection algorithms. + * Author: Thomas Knudsen + * + ****************************************************************************** + * Copyright (c) 2016, Thomas Knudsen + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + *****************************************************************************/ + + +#include +#define PJ_LIB__ +#include + + +extern int pj_aea_selftest(void); +extern int pj_leac_selftest(void); + + + +static void run_one_test (const char *mnemonic, int (testfunc)(void), int verbosity, int *n_ok, int *n_ko) { + int ret = testfunc (); + if (ret) + (*n_ko)++; + else + (*n_ok)++; + + if (verbosity) + printf ("Testing: %8s - return code: %d\n", mnemonic, ret); +} + + +int pj_run_selftests (int verbosity) { + int n_ok = 0, n_ko = 0; + + if (verbosity) + printf ("Running internal regression tests\n"); + run_one_test ("aea", pj_aea_selftest, verbosity, &n_ok, &n_ko); + run_one_test ("leac", pj_leac_selftest, verbosity, &n_ok, &n_ko); + + if (0==verbosity) + printf ("Internal regression tests done. "); + printf ("Total: %d, Failure: %d, Success: %d\n", n_ok+n_ko, n_ko, n_ok); + return n_ko; +} diff --git a/src/proj.c b/src/proj.c index 23f9cca9..40c6df94 100644 --- a/src/proj.c +++ b/src/proj.c @@ -42,7 +42,7 @@ postscale = 0; *oform = (char *)0, /* output format for x-y or decimal degrees */ *oterr = "*\t*", /* output line for unprojectable input */ *usage = -"%s\nusage: %s [ -beEfiIlormsStTvVwW [args] ] [ +opts[=arg] ] [ files ]\n"; +"%s\nusage: %s [ -bCeEfiIlormsStTvVwW [args] ] [ +opts[=arg] ] [ files ]\n"; static struct FACTORS facs; static double @@ -158,7 +158,7 @@ vprocess(FILE *fid) { if (!oform) oform = "%.3f"; if (bin_in || bin_out) - emess(1,"binary I/O not available in -V option"); + emess(1,"binary I/O not available in -V option"); for (;;) { ++emess_dat.File_line; if (!(s = fgets(line, MAX_LINE, fid))) @@ -267,6 +267,9 @@ int main(int argc, char **argv) { case 'b': /* binary I/O */ bin_in = bin_out = 1; continue; + case 'C': /* Check - run internal regression tests */ + pj_run_selftests (very_verby); + continue; case 'v': /* monitor dump of initialization */ mon = 1; continue; @@ -300,8 +303,8 @@ int main(int argc, char **argv) { char *str; for (lp = pj_get_list_ref() ; lp->id ; ++lp) { - if( strcmp(lp->id,"latlong") == 0 - || strcmp(lp->id,"longlat") == 0 + if( strcmp(lp->id,"latlong") == 0 + || strcmp(lp->id,"longlat") == 0 || strcmp(lp->id,"geocent") == 0 ) continue; @@ -353,7 +356,7 @@ int main(int argc, char **argv) { continue; /* artificial */ case 'e': /* error line alternative */ if (--argc <= 0) - noargument: + noargument: emess(1,"missing argument for -%c",*arg); oterr = *++argv; continue; @@ -364,7 +367,7 @@ int main(int argc, char **argv) { case 'm': /* cartesian multiplier */ if (--argc <= 0) goto noargument; postscale = 1; - if (!strncmp("1/",*++argv,2) || + if (!strncmp("1/",*++argv,2) || !strncmp("1:",*argv,2)) { if((fscale = atof((*argv)+2)) == 0.) goto badscale; diff --git a/src/proj_api.h b/src/proj_api.h index dd25d61a..24a6f053 100644 --- a/src/proj_api.h +++ b/src/proj_api.h @@ -168,6 +168,9 @@ char *pj_ctx_fgets(projCtx ctx, char *line, int size, PAFile file); PAFile pj_open_lib(projCtx, const char *, const char *); +int pj_run_selftests (int verbosity); + + #define PJ_LOG_NONE 0 #define PJ_LOG_ERROR 1 #define PJ_LOG_DEBUG_MAJOR 2 diff --git a/src/projects.h b/src/projects.h index 3106eb76..2b638e94 100644 --- a/src/projects.h +++ b/src/projects.h @@ -229,7 +229,7 @@ typedef struct ARG_list { #ifdef PJ_LIB__ /* we need this forward declaration in order to be able to add a pointer to struct opaque to the typedef struct PJconsts below */ - struct opaque; + struct pj_opaque; #endif typedef struct PJconsts { @@ -290,7 +290,7 @@ typedef struct PJconsts { double last_after_date; #ifdef PJ_LIB__ - struct opaque *opaq; + struct pj_opaque *opaque; #endif #ifdef PROJ_PARMS__ @@ -381,6 +381,24 @@ PJ *pj_projection_specific_setup_##name (PJ *P) #endif +int pj_generic_selftest ( + char *e_args, + char *s_args, + double tolerance_xy, + double tolerance_lp, + int n_fwd, + int n_inv, + LP *fwd_in, + XY *e_fwd_expect, + XY *s_fwd_expect, + XY *inv_in, + LP *e_inv_expect, + LP *s_inv_expect +); + + + + #define MAX_TAB_ID 80 typedef struct { float lam, phi; } FLP; typedef struct { int lam, phi; } ILP; -- cgit v1.2.3 From 2cd5e4f988e7f2d89f259ad2f3ac69be825acb75 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Tue, 5 Apr 2016 19:36:04 +0200 Subject: Minor corrections Removed som debugging leftovers, and corrected the behaviour of new proj option -C / -VC, for checking internal regression tests. --- src/PJ_aea.c | 4 ++-- src/pj_generic_selftest.c | 15 ++++----------- src/proj.c | 1 + 3 files changed, 7 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 8285e68f..0ebbb82f 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -225,7 +225,7 @@ int pj_aea_selftest (void) { double tolerance_xy = 1e-7; char e_args[] = {"+proj=aea +ellps=GRS80 +lat_1=0 +lat_2=2"}; - char s_args[] = {"+proj=aea +ellps=GRS80 +lat_1=0 +lat_2=2"}; + char s_args[] = {"+proj=aea +a=6400000 +lat_1=0 +lat_2=2"}; LP fwd_in[] = { { 2, 1}, @@ -285,7 +285,7 @@ int pj_leac_selftest (void) { double tolerance_xy = 1e-7; char e_args[] = {"+proj=leac +ellps=GRS80 +lat_1=0 +lat_2=2"}; - char s_args[] = {"+proj=leac +ellps=GRS80 +lat_1=0 +lat_2=2"}; + char s_args[] = {"+proj=leac +a=6400000 +lat_1=0 +lat_2=2"}; LP fwd_in[] = { { 2, 1}, diff --git a/src/pj_generic_selftest.c b/src/pj_generic_selftest.c index e2d24baf..5ac239e2 100644 --- a/src/pj_generic_selftest.c +++ b/src/pj_generic_selftest.c @@ -81,18 +81,13 @@ Returns 0 if all data agree to within the accuracy specified in PJ *P; -puts ("testing"); if (e_args) { - - puts ("e_args"); - puts (e_args); - P = pj_init_plus(e_args); if (0==P) return 2; /* Test forward ellipsoidal */ - if (e_fwd_expect) { puts ("e_fwd"); + if (e_fwd_expect) { for (i = 0; i < n_fwd; i++) if (deviates_xy (e_fwd_expect[i], pj_fwd_deg ( fwd_in[i], P ), tolerance_xy)) break; @@ -101,7 +96,7 @@ puts ("testing"); } /* Test inverse ellipsoidal */ - if (e_inv_expect) { puts ("e_inv"); + if (e_inv_expect) { for (i = 0; i < n_inv; i++) if (deviates_lp (e_inv_expect[i], pj_inv ( inv_in[i], P ), tolerance_lp)) break; @@ -114,14 +109,12 @@ puts ("testing"); if (s_args) { - puts ("s_args"); - puts (s_args); P = pj_init_plus(s_args); if (0==P) return 3; /* Test forward spherical */ - if (s_fwd_expect) { puts ("s_fwd"); + if (s_fwd_expect) { for (i = 0; i < n_fwd; i++) if (deviates_xy (s_fwd_expect[i], pj_fwd_deg ( fwd_in[i], P ), tolerance_xy)) break; @@ -130,7 +123,7 @@ puts ("testing"); } /* Test inverse spherical */ - if (s_inv_expect) { puts ("s_inv"); + if (s_inv_expect) { for (i = 0; i < n_inv; i++) if (deviates_lp (s_inv_expect[i], pj_inv ( inv_in[i], P ), tolerance_lp)) break; diff --git a/src/proj.c b/src/proj.c index 40c6df94..00853994 100644 --- a/src/proj.c +++ b/src/proj.c @@ -269,6 +269,7 @@ int main(int argc, char **argv) { continue; case 'C': /* Check - run internal regression tests */ pj_run_selftests (very_verby); + return 0; continue; case 'v': /* monitor dump of initialization */ mon = 1; -- cgit v1.2.3 From 77f8c2947b934d64293da614bf7b8b8e0f90031b Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Tue, 5 Apr 2016 23:56:01 +0200 Subject: Added regression tests for projections beginning with a and b Continuing alphabetically, with a few detours due to the occasional case of more than one projection in one source file. --- src/PJ_airy.c | 144 ++++++++++++++------ src/PJ_aitoff.c | 223 +++++++++++++++++++++++++------ src/PJ_august.c | 60 ++++++++- src/PJ_bacon.c | 186 +++++++++++++++++++++++--- src/PJ_bipc.c | 350 +++++++++++++++++++++++++++++++------------------ src/PJ_boggs.c | 53 +++++++- src/PJ_bonne.c | 176 +++++++++++++++++++------ src/pj_run_selftests.c | 31 ++++- 8 files changed, 949 insertions(+), 274 deletions(-) (limited to 'src') diff --git a/src/PJ_airy.c b/src/PJ_airy.c index 73a51e5b..0addf2b8 100644 --- a/src/PJ_airy.c +++ b/src/PJ_airy.c @@ -1,7 +1,8 @@ /****************************************************************************** * Project: PROJ.4 * Purpose: Implementation of the airy (Airy) projection. - * Author: Gerald Evenden + * Author: Gerald Evenden (1995) + * Thomas Knudsen (2016) - revise/add regression tests * ****************************************************************************** * Copyright (c) 1995, Gerald Evenden @@ -25,96 +26,163 @@ * DEALINGS IN THE SOFTWARE. *****************************************************************************/ -#define PROJ_PARMS__ \ - double p_halfpi; \ - double sinph0; \ - double cosph0; \ - double Cb; \ - int mode; \ - int no_cut; /* do not cut at hemisphere limit */ #define PJ_LIB__ #include PROJ_HEAD(airy, "Airy") "\n\tMisc Sph, no inv.\n\tno_cut lat_b="; + +struct pj_opaque { + double p_halfpi; + double sinph0; + double cosph0; + double Cb; + int mode; + int no_cut; /* do not cut at hemisphere limit */ +}; + + # define EPS 1.e-10 # define N_POLE 0 # define S_POLE 1 # define EQUIT 2 # define OBLIQ 3 -FORWARD(s_forward); /* spheroid */ + + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double sinlam, coslam, cosphi, sinphi, t, s, Krho, cosz; sinlam = sin(lp.lam); coslam = cos(lp.lam); - switch (P->mode) { + switch (Q->mode) { case EQUIT: case OBLIQ: sinphi = sin(lp.phi); cosphi = cos(lp.phi); cosz = cosphi * coslam; - if (P->mode == OBLIQ) - cosz = P->sinph0 * sinphi + P->cosph0 * cosz; - if (!P->no_cut && cosz < -EPS) + if (Q->mode == OBLIQ) + cosz = Q->sinph0 * sinphi + Q->cosph0 * cosz; + if (!Q->no_cut && cosz < -EPS) F_ERROR; if (fabs(s = 1. - cosz) > EPS) { t = 0.5 * (1. + cosz); - Krho = -log(t)/s - P->Cb / t; + Krho = -log(t)/s - Q->Cb / t; } else - Krho = 0.5 - P->Cb; + Krho = 0.5 - Q->Cb; xy.x = Krho * cosphi * sinlam; - if (P->mode == OBLIQ) - xy.y = Krho * (P->cosph0 * sinphi - - P->sinph0 * cosphi * coslam); + if (Q->mode == OBLIQ) + xy.y = Krho * (Q->cosph0 * sinphi - + Q->sinph0 * cosphi * coslam); else xy.y = Krho * sinphi; break; case S_POLE: case N_POLE: - lp.phi = fabs(P->p_halfpi - lp.phi); - if (!P->no_cut && (lp.phi - EPS) > HALFPI) + lp.phi = fabs(Q->p_halfpi - lp.phi); + if (!Q->no_cut && (lp.phi - EPS) > HALFPI) F_ERROR; if ((lp.phi *= 0.5) > EPS) { t = tan(lp.phi); - Krho = -2.*(log(cos(lp.phi)) / t + t * P->Cb); + Krho = -2.*(log(cos(lp.phi)) / t + t * Q->Cb); xy.x = Krho * sinlam; xy.y = Krho * coslam; - if (P->mode == N_POLE) + if (Q->mode == N_POLE) xy.y = -xy.y; } else xy.x = xy.y = 0.; } - return (xy); + return xy; +} + + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(airy) + + +PJ *PROJECTION(airy) { double beta; - P->no_cut = pj_param(P->ctx, P->params, "bno_cut").i; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + + P->opaque = Q; + P->pfree = freeup; + P->descr = des_airy; + + Q->no_cut = pj_param(P->ctx, P->params, "bno_cut").i; beta = 0.5 * (HALFPI - pj_param(P->ctx, P->params, "rlat_b").f); if (fabs(beta) < EPS) - P->Cb = -0.5; + Q->Cb = -0.5; else { - P->Cb = 1./tan(beta); - P->Cb *= P->Cb * log(cos(beta)); + Q->Cb = 1./tan(beta); + Q->Cb *= Q->Cb * log(cos(beta)); } + if (fabs(fabs(P->phi0) - HALFPI) < EPS) if (P->phi0 < 0.) { - P->p_halfpi = -HALFPI; - P->mode = S_POLE; + Q->p_halfpi = -HALFPI; + Q->mode = S_POLE; } else { - P->p_halfpi = HALFPI; - P->mode = N_POLE; + Q->p_halfpi = HALFPI; + Q->mode = N_POLE; } else { if (fabs(P->phi0) < EPS) - P->mode = EQUIT; + Q->mode = EQUIT; else { - P->mode = OBLIQ; - P->sinph0 = sin(P->phi0); - P->cosph0 = cos(P->phi0); + Q->mode = OBLIQ; + Q->sinph0 = sin(P->phi0); + Q->cosph0 = cos(P->phi0); } } P->fwd = s_forward; P->es = 0.; -ENDENTRY(P) + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_airy_selftest (void) {return 0;} +#else + +int pj_airy_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=airy +a=6400000 +lat_1=0 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 189109.88690862127, 94583.752387504152}, + { 189109.88690862127, -94583.752387504152}, + {-189109.88690862127, 94583.752387504152}, + {-189109.88690862127, -94583.752387504152}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 0, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} + +#endif diff --git a/src/PJ_aitoff.c b/src/PJ_aitoff.c index d5350f2c..6c766e5a 100644 --- a/src/PJ_aitoff.c +++ b/src/PJ_aitoff.c @@ -2,7 +2,9 @@ * Project: PROJ.4 * Purpose: Implementation of the aitoff (Aitoff) and wintri (Winkel Tripel) * projections. - * Author: Gerald Evenden + * Author: Gerald Evenden (1995) + * Drazen Tutic, Lovro Gradiser (2015) - add inverse + * Thomas Knudsen (2016) - revise/add regression tests * ****************************************************************************** * Copyright (c) 1995, Gerald Evenden @@ -26,12 +28,15 @@ * DEALINGS IN THE SOFTWARE. *****************************************************************************/ -#define PROJ_PARMS__ \ - double cosphi1; \ - int mode; #define PJ_LIB__ #include + +struct pj_opaque { + double cosphi1; + int mode; +}; + #ifndef M_PI # define M_PI 3.14159265358979323846 #endif @@ -42,7 +47,16 @@ PROJ_HEAD(aitoff, "Aitoff") "\n\tMisc Sph"; PROJ_HEAD(wintri, "Winkel Tripel") "\n\tMisc Sph\n\tlat_1"; + + +#if 0 FORWARD(s_forward); /* spheroid */ +#endif + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double c, d; if((d = acos(cos(lp.phi) * cos(c = 0.5 * lp.lam)))) {/* basic Aitoff */ @@ -50,8 +64,8 @@ FORWARD(s_forward); /* spheroid */ xy.y *= d * sin(lp.phi); } else xy.x = xy.y = 0.; - if (P->mode) { /* Winkel Tripel */ - xy.x = (xy.x + lp.lam * P->cosphi1) * 0.5; + if (Q->mode) { /* Winkel Tripel */ + xy.x = (xy.x + lp.lam * Q->cosphi1) * 0.5; xy.y = (xy.y + lp.phi) * 0.5; } return (xy); @@ -60,13 +74,13 @@ FORWARD(s_forward); /* spheroid */ /*********************************************************************************** * * Inverse functions added by Drazen Tutic and Lovro Gradiser based on paper: -* -* I.Özbug Biklirici and Cengizhan Ipbüker. A General Algorithm for the Inverse +* +* I.Özbug Biklirici and Cengizhan Ipbüker. A General Algorithm for the Inverse * Transformation of Map Projections Using Jacobian Matrices. In Proceedings of the * Third International Symposium Mathematical & Computational Applications, * pages 175{182, Turkey, September 2002. * -* Expected accuracy is defined by EPSILON = 1e-12. Should be appropriate for +* Expected accuracy is defined by EPSILON = 1e-12. Should be appropriate for * most applications of Aitoff and Winkel Tripel projections. * * Longitudes of 180W and 180E can be mixed in solution obtained. @@ -78,19 +92,21 @@ FORWARD(s_forward); /* spheroid */ * ************************************************************************************/ -INVERSE(s_inverse); /* sphere */ - int iter, MAXITER = 10, round = 0, MAXROUND = 20; +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + int iter, MAXITER = 10, round = 0, MAXROUND = 20; double EPSILON = 1e-12, D, C, f1, f2, f1p, f1l, f2p, f2l, dp, dl, sl, sp, cp, cl, x, y; - if ((fabs(xy.x) < EPSILON) && (fabs(xy.y) < EPSILON )) { lp.phi = 0.; lp.lam = 0.; return (lp); } + if ((fabs(xy.x) < EPSILON) && (fabs(xy.y) < EPSILON )) { lp.phi = 0.; lp.lam = 0.; return lp; } /* intial values for Newton-Raphson method */ - lp.phi = xy.y; lp.lam = xy.x; + lp.phi = xy.y; lp.lam = xy.x; do { - iter = 0; - do { - sl = sin(lp.lam * 0.5); cl = cos(lp.lam * 0.5); - sp = sin(lp.phi); cp = cos(lp.phi); + iter = 0; + do { + sl = sin(lp.lam * 0.5); cl = cos(lp.lam * 0.5); + sp = sin(lp.phi); cp = cos(lp.phi); D = cp * cl; C = 1. - D * D; D = acos(D) / pow(C, 1.5); @@ -100,11 +116,11 @@ INVERSE(s_inverse); /* sphere */ f1l = cp * cp * sl * sl / C + D * cp * cl * sp * sp; f2p = sp * sp * cl / C + D * sl * sl * cp; f2l = 0.5 * (sp * cp * sl / C - D * sp * cp * cp * sl * cl); - if (P->mode) { /* Winkel Tripel */ - f1 = 0.5 * (f1 + lp.lam * P->cosphi1); + if (Q->mode) { /* Winkel Tripel */ + f1 = 0.5 * (f1 + lp.lam * Q->cosphi1); f2 = 0.5 * (f2 + lp.phi); f1p *= 0.5; - f1l = 0.5 * (f1l + P->cosphi1); + f1l = 0.5 * (f1l + Q->cosphi1); f2p = 0.5 * (f2p + 1.); f2l *= 0.5; } @@ -115,9 +131,9 @@ INVERSE(s_inverse); /* sphere */ while (dl < -M_PI) dl += M_PI; /* set to interval [-M_PI, M_PI] */ lp.phi -= dp; lp.lam -= dl; } while ((fabs(dp) > EPSILON || fabs(dl) > EPSILON) && (iter++ < MAXITER)); - if (lp.phi > M_PI_2) lp.phi -= 2.*(lp.phi-M_PI_2); /* correct if symmetrical solution for Aitoff */ - if (lp.phi < -M_PI_2) lp.phi -= 2.*(lp.phi+M_PI_2); /* correct if symmetrical solution for Aitoff */ - if ((fabs(fabs(lp.phi) - M_PI_2) < EPSILON) && (!P->mode)) lp.lam = 0.; /* if pole in Aitoff, return longitude of 0 */ + if (lp.phi > M_PI_2) lp.phi -= 2.*(lp.phi-M_PI_2); /* correct if symmetrical solution for Aitoff */ + if (lp.phi < -M_PI_2) lp.phi -= 2.*(lp.phi+M_PI_2); /* correct if symmetrical solution for Aitoff */ + if ((fabs(fabs(lp.phi) - M_PI_2) < EPSILON) && (!Q->mode)) lp.lam = 0.; /* if pole in Aitoff, return longitude of 0 */ /* calculate x,y coordinates with solution obtained */ if((D = acos(cos(lp.phi) * cos(C = 0.5 * lp.lam)))) {/* Aitoff */ @@ -125,8 +141,8 @@ INVERSE(s_inverse); /* sphere */ y *= D * sin(lp.phi); } else x = y = 0.; - if (P->mode) { /* Winkel Tripel */ - x = (x + lp.lam * P->cosphi1) * 0.5; + if (Q->mode) { /* Winkel Tripel */ + x = (x + lp.lam * Q->cosphi1) * 0.5; y = (y + lp.phi) * 0.5; } /* if too far from given values of x,y, repeat with better approximation of phi,lam */ @@ -134,27 +150,154 @@ INVERSE(s_inverse); /* sphere */ if (iter == MAXITER && round == MAXROUND) fprintf(stderr, "Warning: Accuracy of 1e-12 not reached. Last increments: dlat=%e and dlon=%e\n", dp, dl); - return (lp); + return lp; } -FREEUP; if (P) pj_dalloc(P); } - static PJ * -setup(PJ *P) { + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + +static PJ *setup(PJ *P) { P->inv = s_inverse; P->fwd = s_forward; P->es = 0.; return P; } -ENTRY0(aitoff) - P->mode = 0; -ENDENTRY(setup(P)) -ENTRY0(wintri) - P->mode = 1; - if (pj_param(P->ctx, P->params, "tlat_1").i) - { - if ((P->cosphi1 = cos(pj_param(P->ctx, P->params, "rlat_1").f)) == 0.) + + +PJ *PROJECTION(aitoff) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_aitoff; + Q->mode = 0; + return setup(P); +} + + +PJ *PROJECTION(wintri) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_wintri; + Q->mode = 1; + if (pj_param(P->ctx, P->params, "tlat_1").i) { + if ((Q->cosphi1 = cos(pj_param(P->ctx, P->params, "rlat_1").f)) == 0.) E_ERROR(-22) - } + } else /* 50d28' or acos(2/pi) */ - P->cosphi1 = 0.636619772367581343; -ENDENTRY(setup(P)) + Q->cosphi1 = 0.636619772367581343; + return setup(P); +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_aitoff_selftest (void) {return 0;} +#else + +int pj_aitoff_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=aitoff +a=6400000 +lat_1=0 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + + XY s_fwd_expect[] = { + {223379.45881169615, 111706.74288385305}, + {223379.45881169615, -111706.74288385305}, + {-223379.45881169615, 111706.74288385305}, + {-223379.45881169615, -111706.74288385305}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + + LP s_inv_expect[] = { + {0.0017904931100388164, 0.00089524655491012516}, + {0.0017904931100388164, -0.00089524655491012516}, + {-0.0017904931100388164, 0.00089524655491012516}, + {-0.0017904931100388164, -0.00089524655491012516}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif + + + +#ifdef PJ_OMIT_SELFTEST +int pj_wintri_selftest (void) {return 0;} +#else + +int pj_wintri_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=wintri +a=6400000 +lat_1=0 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {223390.80153348515, 111703.90750574505}, + {223390.80153348515, -111703.90750574505}, + {-223390.80153348515, 111703.90750574505}, + {-223390.80153348515, -111703.90750574505}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + {0.0017904931099113196, 0.00089524655490101819}, + {0.0017904931099113196, -0.00089524655490101819}, + {-0.0017904931099113196, 0.00089524655490101819}, + {-0.0017904931099113196, -0.00089524655490101819}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif diff --git a/src/PJ_august.c b/src/PJ_august.c index 496fc3c3..4d4ecf6e 100644 --- a/src/PJ_august.c +++ b/src/PJ_august.c @@ -1,8 +1,13 @@ #define PJ_LIB__ #include + + PROJ_HEAD(august, "August Epicycloidal") "\n\tMisc Sph, no inv."; #define M 1.333333333333333 -FORWARD(s_forward); /* spheroid */ + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; double t, c1, c, x1, x12, y1, y12; (void) P; @@ -15,5 +20,54 @@ FORWARD(s_forward); /* spheroid */ xy.y = M * y1 * (3. + 3. * x12 - y12); return (xy); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(august) P->inv = 0; P->fwd = s_forward; P->es = 0.; ENDENTRY(P) + + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(august) { + P->inv = 0; + P->fwd = s_forward; + P->es = 0.; + P->pfree = freeup; + P->descr = des_august; + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_august_selftest (void) {return 0;} +#else + +int pj_august_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=august +a=6400000 +lat_1=0 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {223404.97818097242, 111722.34028976287}, + {223404.97818097242, -111722.34028976287}, + {-223404.97818097242, 111722.34028976287}, + {-223404.97818097242, -111722.34028976287}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} + + +#endif diff --git a/src/PJ_bacon.c b/src/PJ_bacon.c index dfc559b8..b71fae28 100644 --- a/src/PJ_bacon.c +++ b/src/PJ_bacon.c @@ -1,19 +1,27 @@ # define HLFPI2 2.46740110027233965467 # define EPS 1e-10 -#define PROJ_PARMS__ \ - int bacn; \ - int ortl; #define PJ_LIB__ #include + + +struct pj_opaque { + int bacn; + int ortl; +}; + PROJ_HEAD(apian, "Apian Globular I") "\n\tMisc Sph, no inv."; PROJ_HEAD(ortel, "Ortelius Oval") "\n\tMisc Sph, no inv."; PROJ_HEAD(bacon, "Bacon Globular") "\n\tMisc Sph, no inv."; -FORWARD(s_forward); /* spheroid */ + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double ax, f; - xy.y = P->bacn ? HALFPI * sin(lp.phi) : lp.phi; + xy.y = Q->bacn ? HALFPI * sin(lp.phi) : lp.phi; if ((ax = fabs(lp.lam)) >= EPS) { - if (P->ortl && ax >= HALFPI) + if (Q->ortl && ax >= HALFPI) xy.x = sqrt(HLFPI2 - lp.phi * lp.phi + EPS) + ax - HALFPI; else { f = 0.5 * (HLFPI2 / ax + ax); @@ -24,18 +32,154 @@ FORWARD(s_forward); /* spheroid */ xy.x = 0.; return (xy); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(bacon) - P->bacn = 1; - P->ortl = 0; - P->es = 0.; P->fwd = s_forward; -ENDENTRY(P) -ENTRY0(apian) - P->bacn = P->ortl = 0; - P->es = 0.; P->fwd = s_forward; -ENDENTRY(P) -ENTRY0(ortel) - P->bacn = 0; - P->ortl = 1; - P->es = 0.; P->fwd = s_forward; -ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(bacon) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_bacon; + Q->bacn = 1; + Q->ortl = 0; + P->es = 0.; + P->fwd = s_forward; + return P; +} + + +PJ *PROJECTION(apian) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_apian; + Q->bacn = Q->ortl = 0; + P->es = 0.; + P->fwd = s_forward; + return P; +} + + +PJ *PROJECTION(ortel) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_ortel; + Q->bacn = 0; + Q->ortl = 1; + P->es = 0.; + P->fwd = s_forward; + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_bacon_selftest (void) {return 0;} +#else +int pj_bacon_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=bacon +a=6400000 +lat_1=0 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {223334.13255596498, 175450.72592266591}, + {223334.13255596498, -175450.72592266591}, + {-223334.13255596498, 175450.72592266591}, + {-223334.13255596498, -175450.72592266591}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 0, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} +#endif + + + + +#ifdef PJ_OMIT_SELFTEST +int pj_apian_selftest (void) {return 0;} +#else +int pj_apian_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=apian +a=6400000 +lat_1=0 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223374.57735525275, 111701.07212763709}, + { 223374.57735525275, -111701.07212763709}, + {-223374.57735525275, 111701.07212763709}, + {-223374.57735525275, -111701.07212763709}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 0, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} +#endif + + + + +#ifdef PJ_OMIT_SELFTEST +int pj_ortel_selftest (void) {return 0;} +#else +int pj_ortel_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=ortel +a=6400000 +lat_1=0 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223374.57735525275, 111701.07212763709}, + { 223374.57735525275, -111701.07212763709}, + {-223374.57735525275, 111701.07212763709}, + {-223374.57735525275, -111701.07212763709}, + }; + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 0, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} +#endif + diff --git a/src/PJ_bipc.c b/src/PJ_bipc.c index 471e7266..5616b817 100644 --- a/src/PJ_bipc.c +++ b/src/PJ_bipc.c @@ -1,132 +1,226 @@ -#define PROJ_PARMS__ \ - int noskew; #define PJ_LIB__ -# include -PROJ_HEAD(bipc, "Bipolar conic of western hemisphere") - "\n\tConic Sph."; -# define EPS 1e-10 -# define EPS10 1e-10 +#include + +PROJ_HEAD(bipc, "Bipolar conic of western hemisphere") "\n\tConic Sph."; + +# define EPS 1e-10 +# define EPS10 1e-10 # define ONEEPS 1.000000001 -# define NITER 10 -# define lamB -.34894976726250681539 -# define n .63055844881274687180 -# define F 1.89724742567461030582 -# define Azab .81650043674686363166 -# define Azba 1.82261843856185925133 -# define T 1.27246578267089012270 -# define rhoc 1.20709121521568721927 -# define cAzc .69691523038678375519 -# define sAzc .71715351331143607555 -# define C45 .70710678118654752469 -# define S45 .70710678118654752410 -# define C20 .93969262078590838411 -# define S20 -.34202014332566873287 -# define R110 1.91986217719376253360 -# define R104 1.81514242207410275904 -FORWARD(s_forward); /* spheroid */ - double cphi, sphi, tphi, t, al, Az, z, Av, cdlam, sdlam, r; - int tag; - - cphi = cos(lp.phi); - sphi = sin(lp.phi); - cdlam = cos(sdlam = lamB - lp.lam); - sdlam = sin(sdlam); - if (fabs(fabs(lp.phi) - HALFPI) < EPS10) { - Az = lp.phi < 0. ? PI : 0.; - tphi = HUGE_VAL; - } else { - tphi = sphi / cphi; - Az = atan2(sdlam , C45 * (tphi - cdlam)); - } - if( (tag = (Az > Azba)) ) { - cdlam = cos(sdlam = lp.lam + R110); - sdlam = sin(sdlam); - z = S20 * sphi + C20 * cphi * cdlam; - if (fabs(z) > 1.) { - if (fabs(z) > ONEEPS) F_ERROR - else z = z < 0. ? -1. : 1.; - } else - z = acos(z); - if (tphi != HUGE_VAL) - Az = atan2(sdlam, (C20 * tphi - S20 * cdlam)); - Av = Azab; - xy.y = rhoc; - } else { - z = S45 * (sphi + cphi * cdlam); - if (fabs(z) > 1.) { - if (fabs(z) > ONEEPS) F_ERROR - else z = z < 0. ? -1. : 1.; - } else - z = acos(z); - Av = Azba; - xy.y = -rhoc; - } - if (z < 0.) F_ERROR; - r = F * (t = pow(tan(.5 * z), n)); - if ((al = .5 * (R104 - z)) < 0.) F_ERROR; - al = (t + pow(al, n)) / T; - if (fabs(al) > 1.) { - if (fabs(al) > ONEEPS) F_ERROR - else al = al < 0. ? -1. : 1.; - } else - al = acos(al); - if (fabs(t = n * (Av - Az)) < al) - r /= cos(al + (tag ? t : -t)); - xy.x = r * sin(t); - xy.y += (tag ? -r : r) * cos(t); - if (P->noskew) { - t = xy.x; - xy.x = -xy.x * cAzc - xy.y * sAzc; - xy.y = -xy.y * cAzc + t * sAzc; - } - return (xy); +# define NITER 10 +# define lamB -.34894976726250681539 +# define n .63055844881274687180 +# define F 1.89724742567461030582 +# define Azab .81650043674686363166 +# define Azba 1.82261843856185925133 +# define T 1.27246578267089012270 +# define rhoc 1.20709121521568721927 +# define cAzc .69691523038678375519 +# define sAzc .71715351331143607555 +# define C45 .70710678118654752469 +# define S45 .70710678118654752410 +# define C20 .93969262078590838411 +# define S20 -.34202014332566873287 +# define R110 1.91986217719376253360 +# define R104 1.81514242207410275904 + + +struct pj_opaque { + int noskew; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double cphi, sphi, tphi, t, al, Az, z, Av, cdlam, sdlam, r; + int tag; + + cphi = cos(lp.phi); + sphi = sin(lp.phi); + cdlam = cos(sdlam = lamB - lp.lam); + sdlam = sin(sdlam); + if (fabs(fabs(lp.phi) - HALFPI) < EPS10) { + Az = lp.phi < 0. ? PI : 0.; + tphi = HUGE_VAL; + } else { + tphi = sphi / cphi; + Az = atan2(sdlam , C45 * (tphi - cdlam)); + } + if( (tag = (Az > Azba)) ) { + cdlam = cos(sdlam = lp.lam + R110); + sdlam = sin(sdlam); + z = S20 * sphi + C20 * cphi * cdlam; + if (fabs(z) > 1.) { + if (fabs(z) > ONEEPS) F_ERROR + else z = z < 0. ? -1. : 1.; + } else + z = acos(z); + if (tphi != HUGE_VAL) + Az = atan2(sdlam, (C20 * tphi - S20 * cdlam)); + Av = Azab; + xy.y = rhoc; + } else { + z = S45 * (sphi + cphi * cdlam); + if (fabs(z) > 1.) { + if (fabs(z) > ONEEPS) F_ERROR + else z = z < 0. ? -1. : 1.; + } else + z = acos(z); + Av = Azba; + xy.y = -rhoc; + } + if (z < 0.) F_ERROR; + r = F * (t = pow(tan(.5 * z), n)); + if ((al = .5 * (R104 - z)) < 0.) F_ERROR; + al = (t + pow(al, n)) / T; + if (fabs(al) > 1.) { + if (fabs(al) > ONEEPS) F_ERROR + else al = al < 0. ? -1. : 1.; + } else + al = acos(al); + if (fabs(t = n * (Av - Az)) < al) + r /= cos(al + (tag ? t : -t)); + xy.x = r * sin(t); + xy.y += (tag ? -r : r) * cos(t); + if (Q->noskew) { + t = xy.x; + xy.x = -xy.x * cAzc - xy.y * sAzc; + xy.y = -xy.y * cAzc + t * sAzc; + } + return (xy); } -INVERSE(s_inverse); /* spheroid */ - double t, r, rp, rl, al, z, fAz, Az, s, c, Av; - int neg, i; - - if (P->noskew) { - t = xy.x; - xy.x = -xy.x * cAzc + xy.y * sAzc; - xy.y = -xy.y * cAzc - t * sAzc; - } - if( (neg = (xy.x < 0.)) ) { - xy.y = rhoc - xy.y; - s = S20; - c = C20; - Av = Azab; - } else { - xy.y += rhoc; - s = S45; - c = C45; - Av = Azba; - } - rl = rp = r = hypot(xy.x, xy.y); - fAz = fabs(Az = atan2(xy.x, xy.y)); - for (i = NITER; i ; --i) { - z = 2. * atan(pow(r / F,1 / n)); - al = acos((pow(tan(.5 * z), n) + - pow(tan(.5 * (R104 - z)), n)) / T); - if (fAz < al) - r = rp * cos(al + (neg ? Az : -Az)); - if (fabs(rl - r) < EPS) - break; - rl = r; - } - if (! i) I_ERROR; - Az = Av - Az / n; - lp.phi = asin(s * cos(z) + c * sin(z) * cos(Az)); - lp.lam = atan2(sin(Az), c / tan(z) - s * cos(Az)); - if (neg) - lp.lam -= R110; - else - lp.lam = lamB - lp.lam; - return (lp); + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double t, r, rp, rl, al, z, fAz, Az, s, c, Av; + int neg, i; + + if (Q->noskew) { + t = xy.x; + xy.x = -xy.x * cAzc + xy.y * sAzc; + xy.y = -xy.y * cAzc - t * sAzc; + } + if( (neg = (xy.x < 0.)) ) { + xy.y = rhoc - xy.y; + s = S20; + c = C20; + Av = Azab; + } else { + xy.y += rhoc; + s = S45; + c = C45; + Av = Azba; + } + rl = rp = r = hypot(xy.x, xy.y); + fAz = fabs(Az = atan2(xy.x, xy.y)); + for (i = NITER; i ; --i) { + z = 2. * atan(pow(r / F,1 / n)); + al = acos((pow(tan(.5 * z), n) + + pow(tan(.5 * (R104 - z)), n)) / T); + if (fAz < al) + r = rp * cos(al + (neg ? Az : -Az)); + if (fabs(rl - r) < EPS) + break; + rl = r; + } + if (! i) I_ERROR; + Az = Av - Az / n; + lp.phi = asin(s * cos(z) + c * sin(z) * cos(Az)); + lp.lam = atan2(sin(Az), c / tan(z) - s * cos(Az)); + if (neg) + lp.lam -= R110; + else + lp.lam = lamB - lp.lam; + return (lp); +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + pj_dealloc (P->opaque); + return pj_dealloc(P); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(bipc) - P->noskew = pj_param(P->ctx, P->params, "bns").i; - P->inv = s_inverse; - P->fwd = s_forward; - P->es = 0.; -ENDENTRY(P) + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(bipc) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->noskew = pj_param(P->ctx, P->params, "bns").i; + P->pfree = freeup; + P->descr = des_bipc; + P->inv = s_inverse; + P->fwd = s_forward; + P->es = 0.; + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_bipc_selftest (void) {return 0;} +#else + +int pj_bipc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=bipc +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=bipc +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {2452160.2177257561, -14548450.759654747}, + {2447915.213725341, -14763427.21279873}, + {2021695.5229349085, -14540413.695283702}, + {2018090.5030046992, -14755620.651414108}, + }; + + XY s_fwd_expect[] = { + {2460565.7409749646, -14598319.9893308}, + {2456306.1859352002, -14814033.339502094}, + {2028625.4978190989, -14590255.375482792}, + {2025008.1205891429, -14806200.018759441}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {-73.038700284978702, 17.248118466239116}, + {-73.03730373933017, 17.249414978178777}, + {-73.03589317304332, 17.245536403008771}, + {-73.034496627213585, 17.246832895573739}, + }; + + LP s_inv_expect[] = { + {-73.038693104942126, 17.248116270440242}, + {-73.037301330021322, 17.24940835333777}, + {-73.035895582251086, 17.245543027866539}, + {-73.034503807150301, 17.246835091521532}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif diff --git a/src/PJ_boggs.c b/src/PJ_boggs.c index b22a25ff..dc4d781f 100644 --- a/src/PJ_boggs.c +++ b/src/PJ_boggs.c @@ -8,7 +8,10 @@ PROJ_HEAD(boggs, "Boggs Eumorphic") "\n\tPCyl., no inv., Sph."; # define FXC2 1.11072 # define FYC 0.49931 # define FYC2 1.41421356237309504880 -FORWARD(s_forward); /* spheroid */ + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; double theta, th1, c; int i; (void) P; @@ -29,5 +32,49 @@ FORWARD(s_forward); /* spheroid */ xy.y = FYC * (lp.phi + FYC2 * sin(theta)); return (xy); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(boggs) P->es = 0.; P->fwd = s_forward; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(boggs) { + P->es = 0.; + P->fwd = s_forward; + P->pfree = freeup; + P->descr = des_boggs; + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_boggs_selftest (void) {return 0;} +#else +int pj_boggs_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=boggs +a=6400000 +lat_1=0 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 211949.70080818201, 117720.99830541089}, + { 211949.70080818201, -117720.99830541089}, + {-211949.70080818201, 117720.99830541089}, + {-211949.70080818201, -117720.99830541089}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 0, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} +#endif diff --git a/src/PJ_bonne.c b/src/PJ_bonne.c index 4b1e7866..cb17104a 100644 --- a/src/PJ_bonne.c +++ b/src/PJ_bonne.c @@ -1,51 +1,70 @@ -#define PROJ_PARMS__ \ - double phi1; \ - double cphi1; \ - double am1; \ - double m1; \ - double *en; #define PJ_LIB__ #include + PROJ_HEAD(bonne, "Bonne (Werner lat_1=90)") "\n\tConic Sph&Ell\n\tlat_1="; #define EPS10 1e-10 -FORWARD(e_forward); /* ellipsoid */ + +struct pj_opaque { + double phi1; + double cphi1; + double am1; + double m1; + double *en; +}; + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double rh, E, c; - rh = P->am1 + P->m1 - pj_mlfn(lp.phi, E = sin(lp.phi), c = cos(lp.phi), P->en); + rh = Q->am1 + Q->m1 - pj_mlfn(lp.phi, E = sin(lp.phi), c = cos(lp.phi), Q->en); E = c * lp.lam / (rh * sqrt(1. - P->es * E * E)); xy.x = rh * sin(E); - xy.y = P->am1 - rh * cos(E); - return (xy); + xy.y = Q->am1 - rh * cos(E); + return xy; } -FORWARD(s_forward); /* spheroid */ + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double E, rh; - rh = P->cphi1 + P->phi1 - lp.phi; + rh = Q->cphi1 + Q->phi1 - lp.phi; if (fabs(rh) > EPS10) { xy.x = rh * sin(E = lp.lam * cos(lp.phi) / rh); - xy.y = P->cphi1 - rh * cos(E); + xy.y = Q->cphi1 - rh * cos(E); } else xy.x = xy.y = 0.; - return (xy); + return xy; } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double rh; - rh = hypot(xy.x, xy.y = P->cphi1 - xy.y); - lp.phi = P->cphi1 + P->phi1 - rh; + rh = hypot(xy.x, xy.y = Q->cphi1 - xy.y); + lp.phi = Q->cphi1 + Q->phi1 - rh; if (fabs(lp.phi) > HALFPI) I_ERROR; if (fabs(fabs(lp.phi) - HALFPI) <= EPS10) lp.lam = 0.; else lp.lam = rh * atan2(xy.x, xy.y) / cos(lp.phi); - return (lp); + return lp; } -INVERSE(e_inverse); /* ellipsoid */ + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double s, rh; - rh = hypot(xy.x, xy.y = P->am1 - xy.y); - lp.phi = pj_inv_mlfn(P->ctx, P->am1 + P->m1 - rh, P->es, P->en); + rh = hypot(xy.x, xy.y = Q->am1 - xy.y); + lp.phi = pj_inv_mlfn(P->ctx, Q->am1 + Q->m1 - rh, P->es, Q->en); if ((s = fabs(lp.phi)) < HALFPI) { s = sin(lp.phi); lp.lam = rh * atan2(xy.x, xy.y) * @@ -53,33 +72,112 @@ INVERSE(e_inverse); /* ellipsoid */ } else if (fabs(s - HALFPI) <= EPS10) lp.lam = 0.; else I_ERROR; - return (lp); + return lp; } -FREEUP; - if (P) { - if (P->en) - pj_dalloc(P->en); - pj_dalloc(P); - } + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque->en); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; } -ENTRY1(bonne, en) + + +PJ *PROJECTION(bonne) { double c; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_bonne; - P->phi1 = pj_param(P->ctx, P->params, "rlat_1").f; - if (fabs(P->phi1) < EPS10) E_ERROR(-23); + Q->phi1 = pj_param(P->ctx, P->params, "rlat_1").f; + if (fabs(Q->phi1) < EPS10) E_ERROR(-23); if (P->es) { - P->en = pj_enfn(P->es); - P->m1 = pj_mlfn(P->phi1, P->am1 = sin(P->phi1), - c = cos(P->phi1), P->en); - P->am1 = c / (sqrt(1. - P->es * P->am1 * P->am1) * P->am1); + Q->en = pj_enfn(P->es); + Q->m1 = pj_mlfn(Q->phi1, Q->am1 = sin(Q->phi1), + c = cos(Q->phi1), Q->en); + Q->am1 = c / (sqrt(1. - P->es * Q->am1 * Q->am1) * Q->am1); P->inv = e_inverse; P->fwd = e_forward; } else { - if (fabs(P->phi1) + EPS10 >= HALFPI) - P->cphi1 = 0.; + if (fabs(Q->phi1) + EPS10 >= HALFPI) + Q->cphi1 = 0.; else - P->cphi1 = 1. / tan(P->phi1); + Q->cphi1 = 1. / tan(Q->phi1); P->inv = s_inverse; P->fwd = s_forward; } -ENDENTRY(P) + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_bonne_selftest (void) {return 0;} +#else +int pj_bonne_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=bonne +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=bonne +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222605.29609715697, 55321.139565494814}, + { 222605.29609923941, -165827.64779905154}, + {-222605.29609715697, 55321.139565494814}, + {-222605.29609923941, -165827.64779905154}, + }; + + XY s_fwd_expect[] = { + { 223368.11557252839, 55884.555246393575}, + { 223368.11557463196, -167517.59936969393}, + {-223368.11557252839, 55884.555246393575}, + {-223368.11557463196, -167517.59936969393}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.0017966987691132891, 0.50090436853737497}, + { 0.0017966982774478867, 0.4990956309655612}, + {-0.0017966987691132891, 0.50090436853737497}, + {-0.0017966982774478867, 0.4990956309655612}, + }; + + LP s_inv_expect[] = { + { 0.0017905615332457991, 0.50089524631087834}, + { 0.0017905610449335603, 0.49910475320072978}, + {-0.0017905615332457991, 0.50089524631087834}, + {-0.0017905610449335603, 0.49910475320072978}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif diff --git a/src/pj_run_selftests.c b/src/pj_run_selftests.c index 44573b2b..45aa7203 100644 --- a/src/pj_run_selftests.c +++ b/src/pj_run_selftests.c @@ -33,6 +33,16 @@ extern int pj_aea_selftest(void); extern int pj_leac_selftest(void); +extern int pj_airy_selftest(void); +extern int pj_aitoff_selftest(void); +extern int pj_wintri_selftest(void); +extern int pj_august_selftest(void); +extern int pj_bacon_selftest(void); +extern int pj_apian_selftest(void); +extern int pj_ortel_selftest(void); +extern int pj_boggs_selftest(void); +extern int pj_bonne_selftest(void); +extern int pj_bipc_selftest(void); @@ -48,16 +58,33 @@ static void run_one_test (const char *mnemonic, int (testfunc)(void), int verbos } +#ifdef PJ_OMIT_SELFTEST +int pj_run_selftests (int verbosity) { + printf ("This version of libproj is not configured for internal regression tests.\n"); + return 0; +} +#else int pj_run_selftests (int verbosity) { int n_ok = 0, n_ko = 0; if (verbosity) printf ("Running internal regression tests\n"); - run_one_test ("aea", pj_aea_selftest, verbosity, &n_ok, &n_ko); - run_one_test ("leac", pj_leac_selftest, verbosity, &n_ok, &n_ko); + run_one_test ("aea", pj_aea_selftest, verbosity, &n_ok, &n_ko); + run_one_test ("leac", pj_leac_selftest, verbosity, &n_ok, &n_ko); + run_one_test ("airy", pj_airy_selftest, verbosity, &n_ok, &n_ko); + run_one_test ("aitoff", pj_aitoff_selftest, verbosity, &n_ok, &n_ko); + run_one_test ("wintri", pj_wintri_selftest, verbosity, &n_ok, &n_ko); + run_one_test ("august", pj_august_selftest, verbosity, &n_ok, &n_ko); + run_one_test ("bacon", pj_bacon_selftest, verbosity, &n_ok, &n_ko); + run_one_test ("apian", pj_apian_selftest, verbosity, &n_ok, &n_ko); + run_one_test ("ortel", pj_ortel_selftest, verbosity, &n_ok, &n_ko); + run_one_test ("boggs", pj_boggs_selftest, verbosity, &n_ok, &n_ko); + run_one_test ("bonne", pj_bonne_selftest, verbosity, &n_ok, &n_ko); + run_one_test ("bipc", pj_bipc_selftest, verbosity, &n_ok, &n_ko); if (0==verbosity) printf ("Internal regression tests done. "); printf ("Total: %d, Failure: %d, Success: %d\n", n_ok+n_ko, n_ko, n_ok); return n_ko; } +#endif -- cgit v1.2.3 From 267c852a74c2f76241966ab6701313a810e83751 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Wed, 6 Apr 2016 00:30:41 +0200 Subject: Updating VS and Autotools build systems --- src/Makefile.am | 5 +++-- src/makefile.vc | 14 +++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index d59e3fde..b961c930 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -62,8 +62,9 @@ libproj_la_SOURCES = \ pj_factors.c pj_fwd.c pj_init.c pj_inv.c pj_fwd3d.c pj_inv3d.c\ pj_list.c pj_malloc.c pj_mlfn.c pj_msfn.c proj_mdist.c \ pj_open_lib.c pj_param.c pj_phi2.c pj_pr_list.c \ - pj_qsfn.c pj_strerrno.c pj_tsfn.c pj_units.c pj_ctx.c pj_log.c \ - pj_zpoly1.c rtodms.c vector1.c pj_release.c pj_gauss.c \ + pj_qsfn.c pj_generic_selftest.c pj_run_selftests.c pj_strerrno.c \ + pj_tsfn.c pj_units.c pj_ctx.c pj_log.c pj_zpoly1.c rtodms.c \ + vector1.c pj_release.c pj_gauss.c \ PJ_healpix.c PJ_natearth.c PJ_natearth2.c PJ_calcofi.c pj_fileapi.c \ \ pj_gc_reader.c pj_gridcatalog.c \ diff --git a/src/makefile.vc b/src/makefile.vc index 6989519d..ffffc153 100644 --- a/src/makefile.vc +++ b/src/makefile.vc @@ -18,7 +18,7 @@ cylinder = \ PJ_gall.obj PJ_labrd.obj PJ_lsat.obj PJ_misrsom.obj PJ_merc.obj \ PJ_mill.obj PJ_ocea.obj PJ_omerc.obj PJ_patterson.obj PJ_somerc.obj \ PJ_tcc.obj PJ_tcea.obj PJ_tmerc.obj PJ_geos.obj \ - PJ_gstmerc.obj proj_etmerc.obj + PJ_gstmerc.obj proj_etmerc.obj misc = \ PJ_airy.obj PJ_aitoff.obj PJ_august.obj PJ_bacon.obj \ @@ -38,18 +38,18 @@ pseudo = \ PJ_putp4p.obj PJ_putp5.obj PJ_putp6.obj PJ_robin.obj \ PJ_sts.obj PJ_urm5.obj PJ_urmfps.obj PJ_wag2.obj \ PJ_wag3.obj PJ_wink1.obj PJ_wink2.obj PJ_isea.obj \ - PJ_calcofi.obj + PJ_calcofi.obj support = \ aasincos.obj adjlon.obj bch2bps.obj bchgen.obj pj_gauss.obj \ biveval.obj dmstor.obj mk_cheby.obj pj_auth.obj \ pj_deriv.obj pj_ell_set.obj pj_ellps.obj pj_errno.obj \ - pj_factors.obj pj_fwd.obj pj_init.obj pj_inv.obj \ - pj_fwd3d.obj pj_inv3d.obj \ + pj_factors.obj pj_fwd.obj pj_generic_selftest.obj pj_init.obj \ + pj_inv.obj pj_fwd3d.obj pj_inv3d.obj \ pj_list.obj pj_malloc.obj pj_mlfn.obj pj_msfn.obj \ pj_open_lib.obj pj_param.obj pj_phi2.obj pj_pr_list.obj \ - pj_qsfn.obj pj_strerrno.obj pj_tsfn.obj pj_units.obj \ - pj_zpoly1.obj rtodms.obj vector1.obj pj_release.obj \ + pj_qsfn.obj pj_run_selftests.obj pj_strerrno.obj pj_tsfn.obj \ + pj_units.obj pj_zpoly1.obj rtodms.obj vector1.obj pj_release.obj \ geocent.obj pj_transform.obj pj_datum_set.obj pj_datums.obj \ pj_apply_gridshift.obj pj_gc_reader.obj pj_gridcatalog.obj \ nad_cvt.obj nad_init.obj nad_intr.obj \ @@ -146,4 +146,4 @@ install: all copy proj_api.h $(INSTDIR)\include copy projects.h $(INSTDIR)\include copy geodesic.h $(INSTDIR)\include - + -- cgit v1.2.3 From 383e7d18de64f36d8043a7a4c3be857364abddaf Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Thu, 7 Apr 2016 11:19:43 +0200 Subject: selftest function stubs Added stubs for selftest functions for all projections supported. For now, the stub collection has been addad at the bottom of PJ_aea.c Each time a real selftest function is added to a projection source file, the stub should be removed. Stubbing the stuff makes sure a selftest function exists for all projections, and hence allows us to build a list of all selftest functions using the X-macro trick (with PROJ_HEAD as X-macro) used for building pj_list[] in pj_init.c. Actually, the plan is to add a selftest entry directly in the struct PJ_LIST, and let pj_init build the list directly as a part of pj_list[] --- src/PJ_aea.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++++ src/pj_run_selftests.c | 2 +- 2 files changed, 147 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 0ebbb82f..eb35072f 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -333,4 +333,150 @@ int pj_leac_selftest (void) { } + + + + + + + + + +/*********************************************************************** + SELFTEST STUBS +************************************************************************ + +Preliminary selftest stubs temporarily placed here, and removed as real +selftest functions are added to the projection source files + +***********************************************************************/ + +int pj_aeqd_selftest (void) {return 0;} +int pj_alsk_selftest (void) {return 0;} + +int pj_calcofi_selftest (void) {return 0;} +int pj_cass_selftest (void) {return 0;} +int pj_cc_selftest (void) {return 0;} +int pj_cea_selftest (void) {return 0;} +int pj_chamb_selftest (void) {return 0;} +int pj_collg_selftest (void) {return 0;} +int pj_crast_selftest (void) {return 0;} +int pj_denoy_selftest (void) {return 0;} +int pj_eck1_selftest (void) {return 0;} +int pj_eck2_selftest (void) {return 0;} +int pj_eck3_selftest (void) {return 0;} +int pj_eck4_selftest (void) {return 0;} +int pj_eck5_selftest (void) {return 0;} +int pj_eck6_selftest (void) {return 0;} +int pj_eqc_selftest (void) {return 0;} +int pj_eqdc_selftest (void) {return 0;} +int pj_euler_selftest (void) {return 0;} +int pj_etmerc_selftest (void) {return 0;} +int pj_fahey_selftest (void) {return 0;} +int pj_fouc_selftest (void) {return 0;} +int pj_fouc_s_selftest (void) {return 0;} +int pj_gall_selftest (void) {return 0;} +int pj_geos_selftest (void) {return 0;} +int pj_gins8_selftest (void) {return 0;} +int pj_gn_sinu_selftest (void) {return 0;} +int pj_gnom_selftest (void) {return 0;} +int pj_goode_selftest (void) {return 0;} +int pj_gs48_selftest (void) {return 0;} +int pj_gs50_selftest (void) {return 0;} +int pj_hammer_selftest (void) {return 0;} +int pj_hatano_selftest (void) {return 0;} +int pj_healpix_selftest (void) {return 0;} +int pj_rhealpix_selftest (void) {return 0;} +int pj_igh_selftest (void) {return 0;} +int pj_imw_p_selftest (void) {return 0;} +int pj_isea_selftest (void) {return 0;} +int pj_kav5_selftest (void) {return 0;} +int pj_kav7_selftest (void) {return 0;} +int pj_krovak_selftest (void) {return 0;} +int pj_labrd_selftest (void) {return 0;} +int pj_laea_selftest (void) {return 0;} +int pj_lagrng_selftest (void) {return 0;} +int pj_larr_selftest (void) {return 0;} +int pj_lask_selftest (void) {return 0;} +int pj_lonlat_selftest (void) {return 0;} +int pj_latlon_selftest (void) {return 0;} +int pj_lcc_selftest (void) {return 0;} +int pj_lcca_selftest (void) {return 0;} + +int pj_lee_os_selftest (void) {return 0;} +int pj_loxim_selftest (void) {return 0;} +int pj_lsat_selftest (void) {return 0;} +int pj_mbt_s_selftest (void) {return 0;} +int pj_mbt_fps_selftest (void) {return 0;} +int pj_mbtfpp_selftest (void) {return 0;} +int pj_mbtfpq_selftest (void) {return 0;} +int pj_mbtfps_selftest (void) {return 0;} +int pj_merc_selftest (void) {return 0;} +int pj_mil_os_selftest (void) {return 0;} +int pj_mill_selftest (void) {return 0;} +int pj_moll_selftest (void) {return 0;} +int pj_murd1_selftest (void) {return 0;} +int pj_murd2_selftest (void) {return 0;} +int pj_murd3_selftest (void) {return 0;} +int pj_natearth_selftest (void) {return 0;} +int pj_nell_selftest (void) {return 0;} +int pj_nell_h_selftest (void) {return 0;} +int pj_nicol_selftest (void) {return 0;} +int pj_nsper_selftest (void) {return 0;} +int pj_nzmg_selftest (void) {return 0;} +int pj_ob_tran_selftest (void) {return 0;} +int pj_ocea_selftest (void) {return 0;} +int pj_oea_selftest (void) {return 0;} +int pj_omerc_selftest (void) {return 0;} +int pj_ortel_selftest (void) {return 0;} +int pj_ortho_selftest (void) {return 0;} +int pj_pconic_selftest (void) {return 0;} +int pj_poly_selftest (void) {return 0;} +int pj_putp1_selftest (void) {return 0;} +int pj_putp2_selftest (void) {return 0;} +int pj_putp3_selftest (void) {return 0;} +int pj_putp3p_selftest (void) {return 0;} +int pj_putp4p_selftest (void) {return 0;} +int pj_putp5_selftest (void) {return 0;} +int pj_putp5p_selftest (void) {return 0;} +int pj_putp6_selftest (void) {return 0;} +int pj_putp6p_selftest (void) {return 0;} +int pj_qua_aut_selftest (void) {return 0;} +int pj_qsc_selftest (void) {return 0;} +int pj_robin_selftest (void) {return 0;} +int pj_rouss_selftest (void) {return 0;} +int pj_rpoly_selftest (void) {return 0;} +int pj_sch_selftest (void) {return 0;} +int pj_sinu_selftest (void) {return 0;} +int pj_somerc_selftest (void) {return 0;} +int pj_stere_selftest (void) {return 0;} +int pj_sterea_selftest (void) {return 0;} +int pj_gstmerc_selftest (void) {return 0;} +int pj_tcc_selftest (void) {return 0;} +int pj_tcea_selftest (void) {return 0;} +int pj_tissot_selftest (void) {return 0;} +int pj_tmerc_selftest (void) {return 0;} +int pj_tpeqd_selftest (void) {return 0;} +int pj_tpers_selftest (void) {return 0;} +int pj_ups_selftest (void) {return 0;} +int pj_urm5_selftest (void) {return 0;} +int pj_urmfps_selftest (void) {return 0;} +int pj_utm_selftest (void) {return 0;} +int pj_vandg_selftest (void) {return 0;} +int pj_vandg2_selftest (void) {return 0;} +int pj_vandg3_selftest (void) {return 0;} +int pj_vandg4_selftest (void) {return 0;} +int pj_vitk1_selftest (void) {return 0;} +int pj_wag1_selftest (void) {return 0;} +int pj_wag2_selftest (void) {return 0;} +int pj_wag3_selftest (void) {return 0;} +int pj_wag4_selftest (void) {return 0;} +int pj_wag5_selftest (void) {return 0;} +int pj_wag6_selftest (void) {return 0;} +int pj_wag7_selftest (void) {return 0;} +int pj_weren_selftest (void) {return 0;} +int pj_wink1_selftest (void) {return 0;} +int pj_wink2_selftest (void) {return 0;} + + #endif diff --git a/src/pj_run_selftests.c b/src/pj_run_selftests.c index 45aa7203..34a514f0 100644 --- a/src/pj_run_selftests.c +++ b/src/pj_run_selftests.c @@ -80,7 +80,7 @@ int pj_run_selftests (int verbosity) { run_one_test ("ortel", pj_ortel_selftest, verbosity, &n_ok, &n_ko); run_one_test ("boggs", pj_boggs_selftest, verbosity, &n_ok, &n_ko); run_one_test ("bonne", pj_bonne_selftest, verbosity, &n_ok, &n_ko); - run_one_test ("bipc", pj_bipc_selftest, verbosity, &n_ok, &n_ko); + run_one_test ("bipc", pj_bipc_selftest, verbosity, &n_ok, &n_ko); if (0==verbosity) printf ("Internal regression tests done. "); -- cgit v1.2.3 From 0450ac5396660c5d2ca105846f943347de19e120 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Thu, 7 Apr 2016 12:53:26 +0200 Subject: Removed definition of pj_ortel_selftest as it already defined in PJ_bacon.c --- src/PJ_aea.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index eb35072f..e1aa7109 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -428,7 +428,6 @@ int pj_ob_tran_selftest (void) {return 0;} int pj_ocea_selftest (void) {return 0;} int pj_oea_selftest (void) {return 0;} int pj_omerc_selftest (void) {return 0;} -int pj_ortel_selftest (void) {return 0;} int pj_ortho_selftest (void) {return 0;} int pj_pconic_selftest (void) {return 0;} int pj_poly_selftest (void) {return 0;} -- cgit v1.2.3 From 775f9b56ac293ec717a6deac49b33d1e3bfd81b2 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Thu, 7 Apr 2016 12:57:45 +0200 Subject: Fixing windows build with regards to pj_run_selftests. Also adding new projections natearth2 and comill to dll-build. --- src/makefile.vc | 18 +++--- src/proj.def | 179 ++++++++++++++++++++++++++++---------------------------- 2 files changed, 99 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/makefile.vc b/src/makefile.vc index ffffc153..cd63dfdb 100644 --- a/src/makefile.vc +++ b/src/makefile.vc @@ -14,11 +14,11 @@ conic = \ PJ_rpoly.obj PJ_sconics.obj PJ_lcca.obj cylinder = \ - PJ_cass.obj PJ_cc.obj PJ_cea.obj PJ_comill.obj PJ_eqc.obj \ + PJ_cass.obj PJ_cc.obj PJ_cea.obj PJ_eqc.obj \ PJ_gall.obj PJ_labrd.obj PJ_lsat.obj PJ_misrsom.obj PJ_merc.obj \ PJ_mill.obj PJ_ocea.obj PJ_omerc.obj PJ_patterson.obj PJ_somerc.obj \ PJ_tcc.obj PJ_tcea.obj PJ_tmerc.obj PJ_geos.obj \ - PJ_gstmerc.obj proj_etmerc.obj + PJ_gstmerc.obj proj_etmerc.obj PJ_comill.obj misc = \ PJ_airy.obj PJ_aitoff.obj PJ_august.obj PJ_bacon.obj \ @@ -26,7 +26,7 @@ misc = \ PJ_lask.obj PJ_nocol.obj PJ_ob_tran.obj PJ_oea.obj \ PJ_sch.obj PJ_tpeqd.obj PJ_vandg.obj PJ_vandg2.obj \ PJ_vandg4.obj PJ_wag7.obj pj_latlong.obj PJ_krovak.obj \ - pj_geocent.obj PJ_healpix.obj PJ_natearth.obj PJ_natearth2.obj PJ_qsc.obj + pj_geocent.obj PJ_healpix.obj PJ_qsc.obj pseudo = \ PJ_boggs.obj PJ_collg.obj PJ_crast.obj PJ_denoy.obj \ @@ -38,18 +38,18 @@ pseudo = \ PJ_putp4p.obj PJ_putp5.obj PJ_putp6.obj PJ_robin.obj \ PJ_sts.obj PJ_urm5.obj PJ_urmfps.obj PJ_wag2.obj \ PJ_wag3.obj PJ_wink1.obj PJ_wink2.obj PJ_isea.obj \ - PJ_calcofi.obj + PJ_calcofi.obj PJ_natearth.obj PJ_natearth2.obj support = \ aasincos.obj adjlon.obj bch2bps.obj bchgen.obj pj_gauss.obj \ biveval.obj dmstor.obj mk_cheby.obj pj_auth.obj \ pj_deriv.obj pj_ell_set.obj pj_ellps.obj pj_errno.obj \ - pj_factors.obj pj_fwd.obj pj_generic_selftest.obj pj_init.obj \ - pj_inv.obj pj_fwd3d.obj pj_inv3d.obj \ + pj_factors.obj pj_fwd.obj pj_init.obj pj_inv.obj \ + pj_fwd3d.obj pj_inv3d.obj \ pj_list.obj pj_malloc.obj pj_mlfn.obj pj_msfn.obj \ pj_open_lib.obj pj_param.obj pj_phi2.obj pj_pr_list.obj \ - pj_qsfn.obj pj_run_selftests.obj pj_strerrno.obj pj_tsfn.obj \ - pj_units.obj pj_zpoly1.obj rtodms.obj vector1.obj pj_release.obj \ + pj_qsfn.obj pj_strerrno.obj pj_tsfn.obj pj_units.obj \ + pj_zpoly1.obj rtodms.obj vector1.obj pj_release.obj \ geocent.obj pj_transform.obj pj_datum_set.obj pj_datums.obj \ pj_apply_gridshift.obj pj_gc_reader.obj pj_gridcatalog.obj \ nad_cvt.obj nad_init.obj nad_intr.obj \ @@ -60,7 +60,7 @@ support = \ geodesic = geodesic.obj LIBOBJ = $(support) $(pseudo) $(azimuthal) $(conic) $(cylinder) $(misc) \ - $(geodesic) + $(geodesic) pj_run_selftests.obj pj_generic_selftest.obj PROJEXE_OBJ = proj.obj gen_cheb.obj p_series.obj emess.obj CS2CSEXE_OBJ = cs2cs.obj gen_cheb.obj p_series.obj emess.obj GEODEXE_OBJ = geod.obj geod_set.obj geod_interface.obj emess.obj diff --git a/src/proj.def b/src/proj.def index c7708cc5..1f228a6c 100644 --- a/src/proj.def +++ b/src/proj.def @@ -1,90 +1,91 @@ -VERSION 1.2 +VERSION 1.2 EXPORTS - pj_init @1 - pj_fwd @2 - pj_inv @3 - pj_free @4 - pj_transform @5 - pj_geocentric_to_geodetic @6 - pj_geodetic_to_geocentric @7 - pj_deallocate_grids @8 - pj_init_plus @9 - pj_latlong_from_proj @10 - pj_is_latlong @11 - pj_get_errno_ref @12 - pj_set_finder @13 - pj_strerrno @14 - pj_errno @15 - pj_get_def @16 - pj_dalloc @17 - pj_is_geocent @18 - pj_get_release @19 - pj_malloc @20 - pj_pr_list @21 - pj_compare_datums @22 - pj_apply_gridshift @23 - pj_datum_transform @24 - pj_set_searchpath @25 - dmstor @26 - pj_get_ellps_ref @27 - pj_get_datums_ref @28 - pj_get_units_ref @29 - pj_get_list_ref @30 - pj_get_prime_meridians_ref @31 - rtodms @32 - set_rtodms @33 - pj_factors @34 - mk_cheby @35 - adjlon @36 - pj_param @37 - pj_ell_set @38 - pj_mkparam @39 - pj_init_ctx @40 - pj_init_plus_ctx @41 - pj_get_default_ctx @42 - pj_get_ctx @43 - pj_set_ctx @44 - pj_ctx_alloc @45 - pj_ctx_free @46 - pj_ctx_get_errno @47 - pj_ctx_set_errno @48 - pj_ctx_set_debug @49 - pj_ctx_set_logger @50 - pj_ctx_set_app_data @51 - pj_ctx_get_app_data @52 - pj_log @53 - pj_clear_initcache @54 - geod_init @55 - geod_lineinit @56 - geod_genposition @57 - geod_position @58 - geod_gendirect @59 - geod_direct @60 - geod_geninverse @61 - geod_inverse @62 - geod_polygonarea @63 - pj_get_spheroid_defn @64 - pj_get_default_fileapi @65 - pj_ctx_set_fileapi @66 - pj_ctx_get_fileapi @67 - pj_ctx_fopen @68 - pj_ctx_fread @69 - pj_ctx_ftell @70 - pj_ctx_fclose @71 - pj_open_lib @72 - pj_atof @73 - pj_strtod @74 - pj_fwd3d @75 - pj_inv3d @76 - geod_gensetdistance @77 - geod_setdistance @78 - geod_gendirectline @79 - geod_directline @80 - geod_inverseline @81 - geod_polygon_init @82 - geod_polygon_addedge @83 - geod_polygon_addpoint @84 - geod_polygon_compute @85 - geod_polygon_testedge @86 - geod_polygon_testpoint @87 - geod_polygon_clear @88 + pj_init @1 + pj_fwd @2 + pj_inv @3 + pj_free @4 + pj_transform @5 + pj_geocentric_to_geodetic @6 + pj_geodetic_to_geocentric @7 + pj_deallocate_grids @8 + pj_init_plus @9 + pj_latlong_from_proj @10 + pj_is_latlong @11 + pj_get_errno_ref @12 + pj_set_finder @13 + pj_strerrno @14 + pj_errno @15 + pj_get_def @16 + pj_dalloc @17 + pj_is_geocent @18 + pj_get_release @19 + pj_malloc @20 + pj_pr_list @21 + pj_compare_datums @22 + pj_apply_gridshift @23 + pj_datum_transform @24 + pj_set_searchpath @25 + dmstor @26 + pj_get_ellps_ref @27 + pj_get_datums_ref @28 + pj_get_units_ref @29 + pj_get_list_ref @30 + pj_get_prime_meridians_ref @31 + rtodms @32 + set_rtodms @33 + pj_factors @34 + mk_cheby @35 + adjlon @36 + pj_param @37 + pj_ell_set @38 + pj_mkparam @39 + pj_init_ctx @40 + pj_init_plus_ctx @41 + pj_get_default_ctx @42 + pj_get_ctx @43 + pj_set_ctx @44 + pj_ctx_alloc @45 + pj_ctx_free @46 + pj_ctx_get_errno @47 + pj_ctx_set_errno @48 + pj_ctx_set_debug @49 + pj_ctx_set_logger @50 + pj_ctx_set_app_data @51 + pj_ctx_get_app_data @52 + pj_log @53 + pj_clear_initcache @54 + geod_init @55 + geod_lineinit @56 + geod_genposition @57 + geod_position @58 + geod_gendirect @59 + geod_direct @60 + geod_geninverse @61 + geod_inverse @62 + geod_polygonarea @63 + pj_get_spheroid_defn @64 + pj_get_default_fileapi @65 + pj_ctx_set_fileapi @66 + pj_ctx_get_fileapi @67 + pj_ctx_fopen @68 + pj_ctx_fread @69 + pj_ctx_ftell @70 + pj_ctx_fclose @71 + pj_open_lib @72 + pj_atof @73 + pj_strtod @74 + pj_fwd3d @75 + pj_inv3d @76 + geod_gensetdistance @77 + geod_setdistance @78 + geod_gendirectline @79 + geod_directline @80 + geod_inverseline @81 + geod_polygon_init @82 + geod_polygon_addedge @83 + geod_polygon_addpoint @84 + geod_polygon_compute @85 + geod_polygon_testedge @86 + geod_polygon_testpoint @87 + geod_polygon_clear @88 + pj_run_selftests @89 -- cgit v1.2.3 From bb88f71369d9266d322e72e9d51b4d820baf4492 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Thu, 7 Apr 2016 13:02:17 +0200 Subject: moved test obj's to support section of makefile --- src/makefile.vc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/makefile.vc b/src/makefile.vc index cd63dfdb..2efad1f0 100644 --- a/src/makefile.vc +++ b/src/makefile.vc @@ -25,8 +25,8 @@ misc = \ PJ_chamb.obj PJ_hammer.obj PJ_lagrng.obj PJ_larr.obj \ PJ_lask.obj PJ_nocol.obj PJ_ob_tran.obj PJ_oea.obj \ PJ_sch.obj PJ_tpeqd.obj PJ_vandg.obj PJ_vandg2.obj \ - PJ_vandg4.obj PJ_wag7.obj pj_latlong.obj PJ_krovak.obj \ - pj_geocent.obj PJ_healpix.obj PJ_qsc.obj + PJ_vandg4.obj PJ_wag7.obj pj_latlong.obj PJ_krovak.obj \ + pj_geocent.obj PJ_healpix.obj PJ_qsc.obj pseudo = \ PJ_boggs.obj PJ_collg.obj PJ_crast.obj PJ_denoy.obj \ @@ -45,7 +45,7 @@ support = \ biveval.obj dmstor.obj mk_cheby.obj pj_auth.obj \ pj_deriv.obj pj_ell_set.obj pj_ellps.obj pj_errno.obj \ pj_factors.obj pj_fwd.obj pj_init.obj pj_inv.obj \ - pj_fwd3d.obj pj_inv3d.obj \ + pj_fwd3d.obj pj_inv3d.obj \ pj_list.obj pj_malloc.obj pj_mlfn.obj pj_msfn.obj \ pj_open_lib.obj pj_param.obj pj_phi2.obj pj_pr_list.obj \ pj_qsfn.obj pj_strerrno.obj pj_tsfn.obj pj_units.obj \ @@ -56,11 +56,11 @@ support = \ pj_utils.obj pj_gridlist.obj pj_gridinfo.obj \ proj_mdist.obj pj_mutex.obj pj_initcache.obj \ pj_ctx.obj pj_fileapi.obj pj_log.obj pj_apply_vgridshift.obj \ - pj_strtod.obj + pj_strtod.obj pj_run_selftests.obj pj_generic_selftest.obj geodesic = geodesic.obj LIBOBJ = $(support) $(pseudo) $(azimuthal) $(conic) $(cylinder) $(misc) \ - $(geodesic) pj_run_selftests.obj pj_generic_selftest.obj + $(geodesic) PROJEXE_OBJ = proj.obj gen_cheb.obj p_series.obj emess.obj CS2CSEXE_OBJ = cs2cs.obj gen_cheb.obj p_series.obj emess.obj GEODEXE_OBJ = geod.obj geod_set.obj geod_interface.obj emess.obj -- cgit v1.2.3 From 2d111097d76ce52fb0ba019b20e02b33abe842ed Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Thu, 7 Apr 2016 22:21:21 +0200 Subject: pj_list cleanup + added selftest stubs for all projections The projection list maintained by code in pj_list.c depended on stuff in projects.h. This stuff is non-obvious and since it is only used in pj_list.c, it has been moved from projects.h to pj_list.c (The material moved is based on some really clever X-macro techniques implemented by numerous redefinitions of the PROJ_HEAD macro, followed by immediate re-inclusion of te pj_list.h file). Also, the self test runner pj_run_selftests has been remodelled, now depending on a list of self test functions, generated in a similar way to the projection list, and like the projection list generated by X-macro techniques in pj_list.c. For this to work, self test functions need to be available for all projections. To fulfill this, stubs for all projections not having self tests already, have been added to PJ_aea.c Along with the recent build system patches by @kbevers, this first part of the macro-refactoring project is considered close to finished. --- src/PJ_aea.c | 271 +++++++++++++++++++++++++------------------------ src/pj_list.c | 49 ++++++++- src/pj_run_selftests.c | 62 +++++------ src/projects.h | 26 ++--- 4 files changed, 224 insertions(+), 184 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index e1aa7109..59f3e7bd 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -211,13 +211,13 @@ PJ *PROJECTION(leac) { P->descr = des_leac; Q->phi2 = pj_param(P->ctx, P->params, "rlat_1").f; Q->phi1 = pj_param(P->ctx, P->params, "bsouth").i ? - HALFPI: HALFPI; - setup(P); + setup (P); return P; } #ifdef PJ_OMIT_SELFTEST -int pj_aea_selftest (void) {return 0;} +int pj_aea_selftest (void) {return 10000;} #else int pj_aea_selftest (void) { @@ -277,7 +277,7 @@ int pj_aea_selftest (void) { #ifdef PJ_OMIT_SELFTEST -int pj_leac_selftest (void) {return 0;} +int pj_leac_selftest (void) {return 10000;} #else int pj_leac_selftest (void) { @@ -346,136 +346,143 @@ int pj_leac_selftest (void) { SELFTEST STUBS ************************************************************************ -Preliminary selftest stubs temporarily placed here, and removed as real -selftest functions are added to the projection source files - -***********************************************************************/ +Selftest stubs temporarily placed here. -int pj_aeqd_selftest (void) {return 0;} -int pj_alsk_selftest (void) {return 0;} - -int pj_calcofi_selftest (void) {return 0;} -int pj_cass_selftest (void) {return 0;} -int pj_cc_selftest (void) {return 0;} -int pj_cea_selftest (void) {return 0;} -int pj_chamb_selftest (void) {return 0;} -int pj_collg_selftest (void) {return 0;} -int pj_crast_selftest (void) {return 0;} -int pj_denoy_selftest (void) {return 0;} -int pj_eck1_selftest (void) {return 0;} -int pj_eck2_selftest (void) {return 0;} -int pj_eck3_selftest (void) {return 0;} -int pj_eck4_selftest (void) {return 0;} -int pj_eck5_selftest (void) {return 0;} -int pj_eck6_selftest (void) {return 0;} -int pj_eqc_selftest (void) {return 0;} -int pj_eqdc_selftest (void) {return 0;} -int pj_euler_selftest (void) {return 0;} -int pj_etmerc_selftest (void) {return 0;} -int pj_fahey_selftest (void) {return 0;} -int pj_fouc_selftest (void) {return 0;} -int pj_fouc_s_selftest (void) {return 0;} -int pj_gall_selftest (void) {return 0;} -int pj_geos_selftest (void) {return 0;} -int pj_gins8_selftest (void) {return 0;} -int pj_gn_sinu_selftest (void) {return 0;} -int pj_gnom_selftest (void) {return 0;} -int pj_goode_selftest (void) {return 0;} -int pj_gs48_selftest (void) {return 0;} -int pj_gs50_selftest (void) {return 0;} -int pj_hammer_selftest (void) {return 0;} -int pj_hatano_selftest (void) {return 0;} -int pj_healpix_selftest (void) {return 0;} -int pj_rhealpix_selftest (void) {return 0;} -int pj_igh_selftest (void) {return 0;} -int pj_imw_p_selftest (void) {return 0;} -int pj_isea_selftest (void) {return 0;} -int pj_kav5_selftest (void) {return 0;} -int pj_kav7_selftest (void) {return 0;} -int pj_krovak_selftest (void) {return 0;} -int pj_labrd_selftest (void) {return 0;} -int pj_laea_selftest (void) {return 0;} -int pj_lagrng_selftest (void) {return 0;} -int pj_larr_selftest (void) {return 0;} -int pj_lask_selftest (void) {return 0;} -int pj_lonlat_selftest (void) {return 0;} -int pj_latlon_selftest (void) {return 0;} -int pj_lcc_selftest (void) {return 0;} -int pj_lcca_selftest (void) {return 0;} - -int pj_lee_os_selftest (void) {return 0;} -int pj_loxim_selftest (void) {return 0;} -int pj_lsat_selftest (void) {return 0;} -int pj_mbt_s_selftest (void) {return 0;} -int pj_mbt_fps_selftest (void) {return 0;} -int pj_mbtfpp_selftest (void) {return 0;} -int pj_mbtfpq_selftest (void) {return 0;} -int pj_mbtfps_selftest (void) {return 0;} -int pj_merc_selftest (void) {return 0;} -int pj_mil_os_selftest (void) {return 0;} -int pj_mill_selftest (void) {return 0;} -int pj_moll_selftest (void) {return 0;} -int pj_murd1_selftest (void) {return 0;} -int pj_murd2_selftest (void) {return 0;} -int pj_murd3_selftest (void) {return 0;} -int pj_natearth_selftest (void) {return 0;} -int pj_nell_selftest (void) {return 0;} -int pj_nell_h_selftest (void) {return 0;} -int pj_nicol_selftest (void) {return 0;} -int pj_nsper_selftest (void) {return 0;} -int pj_nzmg_selftest (void) {return 0;} -int pj_ob_tran_selftest (void) {return 0;} -int pj_ocea_selftest (void) {return 0;} -int pj_oea_selftest (void) {return 0;} -int pj_omerc_selftest (void) {return 0;} -int pj_ortho_selftest (void) {return 0;} -int pj_pconic_selftest (void) {return 0;} -int pj_poly_selftest (void) {return 0;} -int pj_putp1_selftest (void) {return 0;} -int pj_putp2_selftest (void) {return 0;} -int pj_putp3_selftest (void) {return 0;} -int pj_putp3p_selftest (void) {return 0;} -int pj_putp4p_selftest (void) {return 0;} -int pj_putp5_selftest (void) {return 0;} -int pj_putp5p_selftest (void) {return 0;} -int pj_putp6_selftest (void) {return 0;} -int pj_putp6p_selftest (void) {return 0;} -int pj_qua_aut_selftest (void) {return 0;} -int pj_qsc_selftest (void) {return 0;} -int pj_robin_selftest (void) {return 0;} -int pj_rouss_selftest (void) {return 0;} -int pj_rpoly_selftest (void) {return 0;} -int pj_sch_selftest (void) {return 0;} -int pj_sinu_selftest (void) {return 0;} -int pj_somerc_selftest (void) {return 0;} -int pj_stere_selftest (void) {return 0;} -int pj_sterea_selftest (void) {return 0;} -int pj_gstmerc_selftest (void) {return 0;} -int pj_tcc_selftest (void) {return 0;} -int pj_tcea_selftest (void) {return 0;} -int pj_tissot_selftest (void) {return 0;} -int pj_tmerc_selftest (void) {return 0;} -int pj_tpeqd_selftest (void) {return 0;} -int pj_tpers_selftest (void) {return 0;} -int pj_ups_selftest (void) {return 0;} -int pj_urm5_selftest (void) {return 0;} -int pj_urmfps_selftest (void) {return 0;} -int pj_utm_selftest (void) {return 0;} -int pj_vandg_selftest (void) {return 0;} -int pj_vandg2_selftest (void) {return 0;} -int pj_vandg3_selftest (void) {return 0;} -int pj_vandg4_selftest (void) {return 0;} -int pj_vitk1_selftest (void) {return 0;} -int pj_wag1_selftest (void) {return 0;} -int pj_wag2_selftest (void) {return 0;} -int pj_wag3_selftest (void) {return 0;} -int pj_wag4_selftest (void) {return 0;} -int pj_wag5_selftest (void) {return 0;} -int pj_wag6_selftest (void) {return 0;} -int pj_wag7_selftest (void) {return 0;} -int pj_weren_selftest (void) {return 0;} -int pj_wink1_selftest (void) {return 0;} -int pj_wink2_selftest (void) {return 0;} +To be removed as real selftest functions are added to the projection +source files +***********************************************************************/ +int pj_aeqd_selftest (void) {return 10000;} +int pj_alsk_selftest (void) {return 10000;} + +int pj_calcofi_selftest (void) {return 10000;} +int pj_cass_selftest (void) {return 10000;} +int pj_cc_selftest (void) {return 10000;} +int pj_cea_selftest (void) {return 10000;} +int pj_chamb_selftest (void) {return 10000;} +int pj_collg_selftest (void) {return 10000;} +int pj_comill_selftest (void) {return 10000;} +int pj_crast_selftest (void) {return 10000;} +int pj_denoy_selftest (void) {return 10000;} +int pj_eck1_selftest (void) {return 10000;} +int pj_eck2_selftest (void) {return 10000;} +int pj_eck3_selftest (void) {return 10000;} +int pj_eck4_selftest (void) {return 10000;} +int pj_eck5_selftest (void) {return 10000;} +int pj_eck6_selftest (void) {return 10000;} +int pj_eqc_selftest (void) {return 10000;} +int pj_eqdc_selftest (void) {return 10000;} +int pj_euler_selftest (void) {return 10000;} +int pj_etmerc_selftest (void) {return 10000;} +int pj_fahey_selftest (void) {return 10000;} +int pj_fouc_selftest (void) {return 10000;} +int pj_fouc_s_selftest (void) {return 10000;} +int pj_gall_selftest (void) {return 10000;} +int pj_geos_selftest (void) {return 10000;} +int pj_geocent_selftest (void) {return 10000;} +int pj_gins8_selftest (void) {return 10000;} +int pj_gn_sinu_selftest (void) {return 10000;} +int pj_gnom_selftest (void) {return 10000;} +int pj_goode_selftest (void) {return 10000;} +int pj_gs48_selftest (void) {return 10000;} +int pj_gs50_selftest (void) {return 10000;} +int pj_hammer_selftest (void) {return 10000;} +int pj_hatano_selftest (void) {return 10000;} +int pj_healpix_selftest (void) {return 10000;} +int pj_rhealpix_selftest (void) {return 10000;} +int pj_igh_selftest (void) {return 10000;} +int pj_imw_p_selftest (void) {return 10000;} +int pj_isea_selftest (void) {return 10000;} +int pj_kav5_selftest (void) {return 10000;} +int pj_kav7_selftest (void) {return 10000;} +int pj_krovak_selftest (void) {return 10000;} +int pj_labrd_selftest (void) {return 10000;} +int pj_laea_selftest (void) {return 10000;} +int pj_lagrng_selftest (void) {return 10000;} +int pj_larr_selftest (void) {return 10000;} +int pj_lask_selftest (void) {return 10000;} +int pj_latlon_selftest (void) {return 10000;} +int pj_latlong_selftest (void) {return 10000;} +int pj_lonlat_selftest (void) {return 10000;} +int pj_longlat_selftest (void) {return 10000;} +int pj_lcc_selftest (void) {return 10000;} +int pj_lcca_selftest (void) {return 10000;} + +int pj_lee_os_selftest (void) {return 10000;} +int pj_loxim_selftest (void) {return 10000;} +int pj_lsat_selftest (void) {return 10000;} +int pj_mbt_s_selftest (void) {return 10000;} +int pj_mbt_fps_selftest (void) {return 10000;} +int pj_mbtfpp_selftest (void) {return 10000;} +int pj_mbtfpq_selftest (void) {return 10000;} +int pj_mbtfps_selftest (void) {return 10000;} +int pj_merc_selftest (void) {return 10000;} +int pj_mil_os_selftest (void) {return 10000;} +int pj_mill_selftest (void) {return 10000;} +int pj_misrsom_selftest (void) {return 10000;} +int pj_moll_selftest (void) {return 10000;} +int pj_murd1_selftest (void) {return 10000;} +int pj_murd2_selftest (void) {return 10000;} +int pj_murd3_selftest (void) {return 10000;} +int pj_natearth_selftest (void) {return 10000;} +int pj_natearth2_selftest (void) {return 10000;} +int pj_nell_selftest (void) {return 10000;} +int pj_nell_h_selftest (void) {return 10000;} +int pj_nicol_selftest (void) {return 10000;} +int pj_nsper_selftest (void) {return 10000;} +int pj_nzmg_selftest (void) {return 10000;} +int pj_ob_tran_selftest (void) {return 10000;} +int pj_ocea_selftest (void) {return 10000;} +int pj_oea_selftest (void) {return 10000;} +int pj_omerc_selftest (void) {return 10000;} +int pj_ortho_selftest (void) {return 10000;} +int pj_patterson_selftest (void) {return 10000;} +int pj_pconic_selftest (void) {return 10000;} +int pj_poly_selftest (void) {return 10000;} +int pj_putp1_selftest (void) {return 10000;} +int pj_putp2_selftest (void) {return 10000;} +int pj_putp3_selftest (void) {return 10000;} +int pj_putp3p_selftest (void) {return 10000;} +int pj_putp4p_selftest (void) {return 10000;} +int pj_putp5_selftest (void) {return 10000;} +int pj_putp5p_selftest (void) {return 10000;} +int pj_putp6_selftest (void) {return 10000;} +int pj_putp6p_selftest (void) {return 10000;} +int pj_qua_aut_selftest (void) {return 10000;} +int pj_qsc_selftest (void) {return 10000;} +int pj_robin_selftest (void) {return 10000;} +int pj_rouss_selftest (void) {return 10000;} +int pj_rpoly_selftest (void) {return 10000;} +int pj_sch_selftest (void) {return 10000;} +int pj_sinu_selftest (void) {return 10000;} +int pj_somerc_selftest (void) {return 10000;} +int pj_stere_selftest (void) {return 10000;} +int pj_sterea_selftest (void) {return 10000;} +int pj_gstmerc_selftest (void) {return 10000;} +int pj_tcc_selftest (void) {return 10000;} +int pj_tcea_selftest (void) {return 10000;} +int pj_tissot_selftest (void) {return 10000;} +int pj_tmerc_selftest (void) {return 10000;} +int pj_tpeqd_selftest (void) {return 10000;} +int pj_tpers_selftest (void) {return 10000;} +int pj_ups_selftest (void) {return 10000;} +int pj_urm5_selftest (void) {return 10000;} +int pj_urmfps_selftest (void) {return 10000;} +int pj_utm_selftest (void) {return 10000;} +int pj_vandg_selftest (void) {return 10000;} +int pj_vandg2_selftest (void) {return 10000;} +int pj_vandg3_selftest (void) {return 10000;} +int pj_vandg4_selftest (void) {return 10000;} +int pj_vitk1_selftest (void) {return 10000;} +int pj_wag1_selftest (void) {return 10000;} +int pj_wag2_selftest (void) {return 10000;} +int pj_wag3_selftest (void) {return 10000;} +int pj_wag4_selftest (void) {return 10000;} +int pj_wag5_selftest (void) {return 10000;} +int pj_wag6_selftest (void) {return 10000;} +int pj_wag7_selftest (void) {return 10000;} +int pj_weren_selftest (void) {return 10000;} +int pj_wink1_selftest (void) {return 10000;} +int pj_wink2_selftest (void) {return 10000;} #endif diff --git a/src/pj_list.c b/src/pj_list.c index bb56ade9..a8f171ab 100644 --- a/src/pj_list.c +++ b/src/pj_list.c @@ -1,11 +1,56 @@ /* Projection System: default list of projections ** Use local definition of PJ_LIST_H for subset. */ + #define USE_PJ_LIST_H 1 #include "projects.h" -struct PJ_LIST *pj_get_list_ref() -{ + +#define PASTE(a,b) a##b + +/* Generate prototypes for projection functions */ +#define PROJ_HEAD(id, name) struct PJconsts *pj_##id(struct PJconsts*); +#include "pj_list.h" +#undef PROJ_HEAD + +/* Generate prototypes for projection selftest functions */ +#define PROJ_HEAD(id, name) int PASTE(pj_##id, _selftest) (void); +#include "pj_list.h" +#undef PROJ_HEAD + + +/* Generate extern declarations for description strings */ +#define PROJ_HEAD(id, name) extern char * const pj_s_##id; +#include "pj_list.h" +#undef PROJ_HEAD + + +/* Generate the null-terminated list of projection functions with associated mnemonics and descriptions */ +#define PROJ_HEAD(id, name) {#id, pj_##id, &pj_s_##id}, +struct PJ_LIST pj_list[] = { +#include "pj_list.h" + {0, 0, 0}, + }; +#undef PROJ_HEAD + + +/* Generate the null-terminated list of projection selftest functions with associated mnemonics */ +#define PROJ_HEAD(id, name) {#id, PASTE(pj_##id, _selftest)}, +struct PJ_SELFTEST_LIST pj_selftest_list[] = { +#include "pj_list.h" + {0, 0}, + }; +#undef PROJ_HEAD +#undef PASTE + + +struct PJ_LIST *pj_get_list_ref (void) { return pj_list; } + + +struct PJ_SELFTEST_LIST *pj_get_selftest_list_ref (void) { + return pj_selftest_list; +} + diff --git a/src/pj_run_selftests.c b/src/pj_run_selftests.c index 34a514f0..cede4961 100644 --- a/src/pj_run_selftests.c +++ b/src/pj_run_selftests.c @@ -25,36 +25,26 @@ * DEALINGS IN THE SOFTWARE. *****************************************************************************/ - #include #define PJ_LIB__ #include -extern int pj_aea_selftest(void); -extern int pj_leac_selftest(void); -extern int pj_airy_selftest(void); -extern int pj_aitoff_selftest(void); -extern int pj_wintri_selftest(void); -extern int pj_august_selftest(void); -extern int pj_bacon_selftest(void); -extern int pj_apian_selftest(void); -extern int pj_ortel_selftest(void); -extern int pj_boggs_selftest(void); -extern int pj_bonne_selftest(void); -extern int pj_bipc_selftest(void); - - - -static void run_one_test (const char *mnemonic, int (testfunc)(void), int verbosity, int *n_ok, int *n_ko) { +static void run_one_test (const char *mnemonic, int (testfunc)(void), int verbosity, int *n_ok, int *n_ko, int *n_stubs) { int ret = testfunc (); - if (ret) - (*n_ko)++; - else - (*n_ok)++; + switch (ret) { + case 0: (*n_ok)++; break; + case 10000: (*n_stubs)++; break; + default: (*n_ko)++; + } - if (verbosity) - printf ("Testing: %8s - return code: %d\n", mnemonic, ret); + if (verbosity) { + if (ret==10000) + printf ("Testing: %10s - [stub]\n", mnemonic); + else + printf ("Testing: %10s - return code: %d\n", mnemonic, ret); + } + return; } @@ -64,27 +54,25 @@ int pj_run_selftests (int verbosity) { return 0; } #else + + int pj_run_selftests (int verbosity) { - int n_ok = 0, n_ko = 0; + int n_ok = 0, n_ko = 0, n_stubs = 0, i = 0; + + struct PJ_SELFTEST_LIST *tests = pj_get_selftest_list_ref (); + + if (0==tests) + printf ("This version of libproj is not configured for internal regression tests.\n"); if (verbosity) printf ("Running internal regression tests\n"); - run_one_test ("aea", pj_aea_selftest, verbosity, &n_ok, &n_ko); - run_one_test ("leac", pj_leac_selftest, verbosity, &n_ok, &n_ko); - run_one_test ("airy", pj_airy_selftest, verbosity, &n_ok, &n_ko); - run_one_test ("aitoff", pj_aitoff_selftest, verbosity, &n_ok, &n_ko); - run_one_test ("wintri", pj_wintri_selftest, verbosity, &n_ok, &n_ko); - run_one_test ("august", pj_august_selftest, verbosity, &n_ok, &n_ko); - run_one_test ("bacon", pj_bacon_selftest, verbosity, &n_ok, &n_ko); - run_one_test ("apian", pj_apian_selftest, verbosity, &n_ok, &n_ko); - run_one_test ("ortel", pj_ortel_selftest, verbosity, &n_ok, &n_ko); - run_one_test ("boggs", pj_boggs_selftest, verbosity, &n_ok, &n_ko); - run_one_test ("bonne", pj_bonne_selftest, verbosity, &n_ok, &n_ko); - run_one_test ("bipc", pj_bipc_selftest, verbosity, &n_ok, &n_ko); + + for (i = 0; tests[i].testfunc != 0; i++) + run_one_test (tests[i].id, tests[i].testfunc, verbosity, &n_ok, &n_ko, &n_stubs); if (0==verbosity) printf ("Internal regression tests done. "); - printf ("Total: %d, Failure: %d, Success: %d\n", n_ok+n_ko, n_ko, n_ok); + printf ("[Stubs: %d] Total: %d. Failure: %d. Success: %d\n", n_stubs, n_ok+n_ko, n_ko, n_ok); return n_ko; } #endif diff --git a/src/projects.h b/src/projects.h index 2b638e94..307b69bd 100644 --- a/src/projects.h +++ b/src/projects.h @@ -169,6 +169,13 @@ struct PJ_LIST { struct PJconsts *(*proj)(struct PJconsts*);/* projection entry point */ char * const *descr; /* description text */ }; + +/* Merging this into the PJ_LIST infrastructure is tempting, but may imply ABI breakage. Perhaps at next major version? */ +struct PJ_SELFTEST_LIST { + char *id; /* projection keyword */ + int (* testfunc)(void); /* projection entry point */ +}; + struct PJ_ELLPS { char *id; /* ellipse keyword name */ char *major; /* a= value */ @@ -301,24 +308,16 @@ PROJ_PARMS__ /* public API */ #include "proj_api.h" + /* Generate pj_list external or make list from include file */ + #ifndef USE_PJ_LIST_H extern struct PJ_LIST pj_list[]; -#else -#define PROJ_HEAD(id, name) \ - struct PJconsts *pj_##id(struct PJconsts*); extern char * const pj_s_##id; - -#include "pj_list.h" -#undef PROJ_HEAD -#define PROJ_HEAD(id, name) {#id, pj_##id, &pj_s_##id}, - struct PJ_LIST -pj_list[] = { -#include "pj_list.h" - {0, 0, 0}, - }; -#undef PROJ_HEAD +extern struct PJ_SELFTEST_LIST pj_selftest_list[]; #endif + + #ifndef PJ_ELLPS__ extern struct PJ_ELLPS pj_ellps[]; #endif @@ -571,6 +570,7 @@ struct PJ_ELLPS *pj_get_ellps_ref( void ); struct PJ_DATUMS *pj_get_datums_ref( void ); struct PJ_UNITS *pj_get_units_ref( void ); struct PJ_LIST *pj_get_list_ref( void ); +struct PJ_SELFTEST_LIST *pj_get_selftest_list_ref ( void ); struct PJ_PRIME_MERIDIANS *pj_get_prime_meridians_ref( void ); double pj_atof( const char* nptr ); -- cgit v1.2.3 From 86a3221bdc26ea2cdbe85fcf270263ce02fef0e6 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Tue, 12 Apr 2016 17:25:22 +0200 Subject: refactoring + added selftest for 8 more projections calcofi, cass,cc,wag2, wag3, wag7, wink1, wink2 --- src/PJ_aea.c | 8 --- src/PJ_calcofi.c | 154 ++++++++++++++++++++++++++++++++++--------- src/PJ_cass.c | 196 ++++++++++++++++++++++++++++++++++--------------------- src/PJ_cc.c | 87 +++++++++++++++++++++--- src/PJ_wag2.c | 81 +++++++++++++++++++++-- src/PJ_wag3.c | 103 +++++++++++++++++++++++++---- src/PJ_wag7.c | 66 +++++++++++++++++-- src/PJ_wink1.c | 104 +++++++++++++++++++++++++---- src/PJ_wink2.c | 89 ++++++++++++++++++++----- src/projects.h | 2 +- 10 files changed, 712 insertions(+), 178 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 59f3e7bd..6de8f00d 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -356,9 +356,6 @@ source files int pj_aeqd_selftest (void) {return 10000;} int pj_alsk_selftest (void) {return 10000;} -int pj_calcofi_selftest (void) {return 10000;} -int pj_cass_selftest (void) {return 10000;} -int pj_cc_selftest (void) {return 10000;} int pj_cea_selftest (void) {return 10000;} int pj_chamb_selftest (void) {return 10000;} int pj_collg_selftest (void) {return 10000;} @@ -476,13 +473,8 @@ int pj_vandg3_selftest (void) {return 10000;} int pj_vandg4_selftest (void) {return 10000;} int pj_vitk1_selftest (void) {return 10000;} int pj_wag1_selftest (void) {return 10000;} -int pj_wag2_selftest (void) {return 10000;} -int pj_wag3_selftest (void) {return 10000;} int pj_wag4_selftest (void) {return 10000;} int pj_wag5_selftest (void) {return 10000;} int pj_wag6_selftest (void) {return 10000;} -int pj_wag7_selftest (void) {return 10000;} int pj_weren_selftest (void) {return 10000;} -int pj_wink1_selftest (void) {return 10000;} -int pj_wink2_selftest (void) {return 10000;} #endif diff --git a/src/PJ_calcofi.c b/src/PJ_calcofi.c index 2d142938..62749a93 100644 --- a/src/PJ_calcofi.c +++ b/src/PJ_calcofi.c @@ -1,25 +1,27 @@ #define PJ_LIB__ #include + +PROJ_HEAD(calcofi, + "Cal Coop Ocean Fish Invest Lines/Stations") "\n\tCyl, Sph&Ell"; + #include #include #include #include #include -/* Conversions for the California Cooperative Oceanic Fisheries Investigations +/* Conversions for the California Cooperative Oceanic Fisheries Investigations Line/Station coordinate system following the algorithm of: -Eber, L.E., and R.P. Hewitt. 1979. Conversion algorithms for the CALCOFI -station grid. California Cooperative Oceanic Fisheries Investigations Reports -20:135-137. (corrected for typographical errors). +Eber, L.E., and R.P. Hewitt. 1979. Conversion algorithms for the CALCOFI +station grid. California Cooperative Oceanic Fisheries Investigations Reports +20:135-137. (corrected for typographical errors). http://www.calcofi.org/publications/calcofireports/v20/Vol_20_Eber___Hewitt.pdf -They assume 1 unit of CalCOFI Line == 1/5 degree in longitude or -meridional units at reference point O, and similarly 1 unit of CalCOFI -Station == 1/15 of a degree at O. -By convention, CalCOFI Line/Station conversions use Clarke 1866 but we use +They assume 1 unit of CalCOFI Line == 1/5 degree in longitude or +meridional units at reference point O, and similarly 1 unit of CalCOFI +Station == 1/15 of a degree at O. +By convention, CalCOFI Line/Station conversions use Clarke 1866 but we use whatever ellipsoid is provided. */ -PROJ_HEAD(calcofi, - "Cal Coop Ocean Fish Invest Lines/Stations") "\n\tCyl, Sph&Ell"; #define EPS10 1.e-10 #define DEG_TO_LINE 5 @@ -31,14 +33,17 @@ PROJ_HEAD(calcofi, #define PT_O_LAMBDA -2.1144663887911301 /* lon -121.15 and */ #define PT_O_PHI 0.59602993955606354 /* lat 34.15 */ #define ROTATION_ANGLE 0.52359877559829882 /*CalCOFI angle of 30 deg in rad */ -FORWARD(e_forward); /* ellipsoid */ + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; double oy; /* pt O y value in Mercator */ double l1; /* l1 and l2 are distances calculated using trig that sum to the east/west distance between point O and point xy */ double l2; - double ry; /* r is the point on the same station as o (60) and the same + double ry; /* r is the point on the same station as o (60) and the same line as xy xy, r, o form a right triangle */ - /* if the user has specified +lon_0 or +k0 for some reason, + /* if the user has specified +lon_0 or +k0 for some reason, we're going to ignore it so that xy is consistent with point O */ lp.lam = lp.lam + P->lam0; if (fabs(fabs(lp.phi) - HALFPI) <= EPS10) F_ERROR; @@ -49,18 +54,21 @@ FORWARD(e_forward); /* ellipsoid */ l2 = -xy.x - l1 + PT_O_LAMBDA; ry = l2 * cos(ROTATION_ANGLE) * sin(ROTATION_ANGLE) + xy.y; ry = pj_phi2(P->ctx, exp(-ry), P->e); /*inverse Mercator*/ - xy.x = PT_O_LINE - RAD_TO_DEG * - (ry - PT_O_PHI) * DEG_TO_LINE / cos(ROTATION_ANGLE); - xy.y = PT_O_STATION + RAD_TO_DEG * + xy.x = PT_O_LINE - RAD_TO_DEG * + (ry - PT_O_PHI) * DEG_TO_LINE / cos(ROTATION_ANGLE); + xy.y = PT_O_STATION + RAD_TO_DEG * (ry - lp.phi) * DEG_TO_STATION / sin(ROTATION_ANGLE); /* set a = 1, x0 = 0, and y0 = 0 so that no further unit adjustments are done */ P->a = 1; P->x0 = 0; P->y0 = 0; - return (xy); + return xy; } -FORWARD(s_forward); /* spheroid */ + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; double oy; double l1; double l2; @@ -73,17 +81,20 @@ FORWARD(s_forward); /* spheroid */ l1 = (xy.y - oy) * tan(ROTATION_ANGLE); l2 = -xy.x - l1 + PT_O_LAMBDA; ry = l2 * cos(ROTATION_ANGLE) * sin(ROTATION_ANGLE) + xy.y; - ry = HALFPI - 2. * atan(exp(-ry)); - xy.x = PT_O_LINE - RAD_TO_DEG * - (ry - PT_O_PHI) * DEG_TO_LINE / cos(ROTATION_ANGLE); - xy.y = PT_O_STATION + RAD_TO_DEG * + ry = HALFPI - 2. * atan(exp(-ry)); + xy.x = PT_O_LINE - RAD_TO_DEG * + (ry - PT_O_PHI) * DEG_TO_LINE / cos(ROTATION_ANGLE); + xy.y = PT_O_STATION + RAD_TO_DEG * (ry - lp.phi) * DEG_TO_STATION / sin(ROTATION_ANGLE); P->a = 1; P->x0 = 0; P->y0 = 0; - return (xy); + return xy; } -INVERSE(e_inverse); /* ellipsoid */ + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; double ry; /* y value of point r */ double oymctr; /* Mercator-transformed y value of point O */ double rymctr; /* Mercator-transformed ry */ @@ -93,7 +104,7 @@ INVERSE(e_inverse); /* ellipsoid */ /* turn x and y back into Line/Station */ xy.x /= P->ra; xy.y /= P->ra; - ry = PT_O_PHI - LINE_TO_RAD * (xy.x - PT_O_LINE) * + ry = PT_O_PHI - LINE_TO_RAD * (xy.x - PT_O_LINE) * cos(ROTATION_ANGLE); lp.phi = ry - STATION_TO_RAD * (xy.y - PT_O_STATION) * sin(ROTATION_ANGLE); oymctr = -log(pj_tsfn(PT_O_PHI, sin(PT_O_PHI), P->e)); @@ -103,9 +114,12 @@ INVERSE(e_inverse); /* ellipsoid */ l2 = (rymctr - xymctr) / (cos(ROTATION_ANGLE) * sin(ROTATION_ANGLE)); lp.lam = PT_O_LAMBDA - (l1 + l2); P->over = 1; - return (lp); + return lp; } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; double ry; double oymctr; double rymctr; @@ -114,7 +128,7 @@ INVERSE(s_inverse); /* spheroid */ double l2; xy.x /= P->ra; xy.y /= P->ra; - ry = PT_O_PHI - LINE_TO_RAD * (xy.x - PT_O_LINE) * + ry = PT_O_PHI - LINE_TO_RAD * (xy.x - PT_O_LINE) * cos(ROTATION_ANGLE); lp.phi = ry - STATION_TO_RAD * (xy.y - PT_O_STATION) * sin(ROTATION_ANGLE); oymctr = log(tan(FORTPI + .5 * PT_O_PHI)); @@ -124,10 +138,25 @@ INVERSE(s_inverse); /* spheroid */ l2 = (rymctr - xymctr) / (cos(ROTATION_ANGLE) * sin(ROTATION_ANGLE)); lp.lam = PT_O_LAMBDA - (l1 + l2); P->over = 1; - return (lp); + return lp; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(calcofi) + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc (P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(calcofi) { + P->opaque = 0; + + P->pfree = freeup; + P->descr = des_calcofi; if (P->es) { /* ellipsoid */ P->inv = e_inverse; P->fwd = e_forward; @@ -135,4 +164,65 @@ ENTRY0(calcofi) P->inv = s_inverse; P->fwd = s_forward; } -ENDENTRY(P) + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_calcofi_selftest (void) {return 0;} +#else + +int pj_calcofi_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=calcofi +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=calcofi +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {508.44487214981905, -1171.7648604175156}, + {514.99916815188112, -1145.8219814677668}, + {500.68538412539851, -1131.4453779204598}, + {507.36971913666355, -1106.1782014834275}, + }; + + XY s_fwd_expect[] = { + {507.09050748781806, -1164.7273751978314}, + {513.68613637462886, -1138.9992682173072}, + {499.33626147591531, -1124.4351309968195}, + {506.0605703929898, -1099.3756650673038}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {-110.36330792469906, 12.032056975840137}, + {-98.455008863288782, 18.698723642506803}, + {-207.4470245036909, 81.314089278595247}, + {-62.486322854481287, 87.980755945261919}, + }; + + LP s_inv_expect[] = { + {-110.30519040955151, 12.032056975840137}, + {-98.322360950234085, 18.698723642506803}, + {-207.54490681381429, 81.314089278595247}, + {-62.576950371885275, 87.980755945261919}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif diff --git a/src/PJ_cass.c b/src/PJ_cass.c index 5f885376..28d35b91 100644 --- a/src/PJ_cass.c +++ b/src/PJ_cass.c @@ -1,96 +1,90 @@ #define PJ_LIB__ -# include +# include PROJ_HEAD(cass, "Cassini") "\n\tCyl, Sph&Ell"; -# define EPS10 1e-10 -# define C1 .16666666666666666666 -# define C2 .00833333333333333333 -# define C3 .04166666666666666666 -# define C4 .33333333333333333333 -# define C5 .06666666666666666666 +# define EPS10 1e-10 +# define C1 .16666666666666666666 +# define C2 .00833333333333333333 +# define C3 .04166666666666666666 +# define C4 .33333333333333333333 +# define C5 .06666666666666666666 struct pj_opaque { - /* These are the only opaque members actually initialized */ - double *en; - double m0; - - /* Apparently this group of opaque members should be demoted to local variables in e_forward and e_inverse */ - double n; - double t; - double a1; - double c; - double r; - double dd; - double d2; - double a2; - double tn; + double *en; + double m0; }; static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ - XY xy = {0.0,0.0}; + double n, t, a1, c, a2, tn; + XY xy = {0.0, 0.0}; struct pj_opaque *Q = P->opaque; - xy.y = pj_mlfn(lp.phi, Q->n = sin(lp.phi), Q->c = cos(lp.phi), Q->en); - Q->n = 1./sqrt(1. - P->es * Q->n * Q->n); - Q->tn = tan(lp.phi); Q->t = Q->tn * Q->tn; - Q->a1 = lp.lam * Q->c; - Q->c *= P->es * Q->c / (1 - P->es); - Q->a2 = Q->a1 * Q->a1; - xy.x = Q->n * Q->a1 * (1. - Q->a2 * Q->t * - (C1 - (8. - Q->t + 8. * Q->c) * Q->a2 * C2)); - xy.y -= Q->m0 - Q->n * Q->tn * Q->a2 * - (.5 + (5. - Q->t + 6. * Q->c) * Q->a2 * C3); - return xy; + + xy.y = pj_mlfn (lp.phi, n = sin (lp.phi), c = cos (lp.phi), Q->en); + + n = 1./sqrt(1. - P->es * n*n); + tn = tan(lp.phi); t = tn * tn; + a1 = lp.lam * c; + c *= P->es * c / (1 - P->es); + a2 = a1 * a1; + + xy.x = n * a1 * (1. - a2 * t * + (C1 - (8. - t + 8. * c) * a2 * C2)); + xy.y -= Q->m0 - n * tn * a2 * + (.5 + (5. - t + 6. * c) * a2 * C3); + + return xy; } static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ - XY xy = {0.0,0.0}; - xy.x = asin(cos(lp.phi) * sin(lp.lam)); - xy.y = atan2(tan(lp.phi) , cos(lp.lam)) - P->phi0; - return xy; + XY xy = {0.0, 0.0}; + xy.x = asin (cos (lp.phi) * sin (lp.lam)); + xy.y = atan2 (tan (lp.phi), cos (lp.lam)) - P->phi0; + return xy; } static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ - LP lp = {0.0,0.0}; + double n, t, r, dd, d2, tn, ph1; + LP lp = {0.0, 0.0}; struct pj_opaque *Q = P->opaque; - double ph1; - - ph1 = pj_inv_mlfn(P->ctx, Q->m0 + xy.y, P->es, Q->en); - Q->tn = tan(ph1); Q->t = Q->tn * Q->tn; - Q->n = sin(ph1); - Q->r = 1. / (1. - P->es * Q->n * Q->n); - Q->n = sqrt(Q->r); - Q->r *= (1. - P->es) * Q->n; - Q->dd = xy.x / Q->n; - Q->d2 = Q->dd * Q->dd; - lp.phi = ph1 - (Q->n * Q->tn / Q->r) * Q->d2 * - (.5 - (1. + 3. * Q->t) * Q->d2 * C3); - lp.lam = Q->dd * (1. + Q->t * Q->d2 * - (-C4 + (1. + 3. * Q->t) * Q->d2 * C5)) / cos(ph1); - return lp; + + ph1 = pj_inv_mlfn (P->ctx, Q->m0 + xy.y, P->es, Q->en); + tn = tan (ph1); t = tn*tn; + n = sin (ph1); + r = 1. / (1. - P->es * n * n); + n = sqrt (r); + r *= (1. - P->es) * n; + dd = xy.x / n; + d2 = dd * dd; + lp.phi = ph1 - (n * tn / r) * d2 * + (.5 - (1. + 3. * t) * d2 * C3); + lp.lam = dd * (1. + t * d2 * + (-C4 + (1. + 3. * t) * d2 * C5)) / cos (ph1); + return lp; } static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ LP lp = {0.0,0.0}; - lp.phi = asin(sin(P->opaque->dd = xy.y + P->phi0) * cos(xy.x)); - lp.lam = atan2(tan(xy.x), cos(P->opaque->dd)); - return lp; + double dd; + lp.phi = asin(sin(dd = xy.y + P->phi0) * cos(xy.x)); + lp.lam = atan2(tan(xy.x), cos(dd)); + return lp; } static void *freeup_new(PJ *P) { /* Destructor */ - if (0==P) + if (0==P) return 0; if (0==P->opaque) return pj_dealloc (P); - pj_dealloc(P->opaque->en); + pj_dealloc(P->opaque->en); pj_dealloc(P->opaque); return pj_dealloc(P); } @@ -103,28 +97,82 @@ static void freeup(PJ *P) { /* Destructor */ PJ *PROJECTION(cass) { /* Spheroidal? */ - if (0==P->es) { - P->inv = s_inverse; - P->fwd = s_forward; + if (0==P->es) { + P->inv = s_inverse; + P->fwd = s_forward; return P; } - /* Otherwise it's ellipsoidal */ + /* otherwise it's ellipsoidal */ P->opaque = pj_calloc (1, sizeof (struct pj_opaque)); - if (0==P->opaque) { - freeup (P); - return 0; - } + if (0==P->opaque) + return freeup_new (P); - P->opaque->en = pj_enfn(P->es); - if (0==P->opaque->en) { - freeup (P); - return 0; - } + P->opaque->en = pj_enfn (P->es); + if (0==P->opaque->en) + return freeup_new (P); - P->opaque->m0 = pj_mlfn(P->phi0, sin(P->phi0), cos(P->phi0), P->opaque->en); - P->inv = e_inverse; - P->fwd = e_forward; + P->opaque->m0 = pj_mlfn (P->phi0, sin (P->phi0), cos (P->phi0), P->opaque->en); + P->inv = e_inverse; + P->fwd = e_forward; return P; } + + +#ifdef PJ_OMIT_SELFTEST +int pj_cass_selftest (void) {return 0;} +#else + +int pj_cass_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=cass +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=cass +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222605.28577699114, 110642.22925399939}, + { 222605.28577699114, -110642.22925399939}, + {-222605.28577699114, 110642.22925399939}, + {-222605.28577699114, -110642.22925399939}, + }; + + XY s_fwd_expect[] = { + { 223368.10520348375, 111769.14504058579}, + { 223368.10520348375, -111769.14504058579}, + {-223368.10520348375, 111769.14504058579}, + {-223368.10520348375, -111769.14504058579}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.0017966305684613522, 0.00090436947663183841}, + { 0.0017966305684613522, -0.00090436947663183841}, + {-0.0017966305684613522, 0.00090436947663183841}, + {-0.0017966305684613522, -0.00090436947663183841}, + }; + + LP s_inv_expect[] = { + { 0.0017904931100023887, 0.00089524655445477922}, + { 0.0017904931100023887, -0.00089524655445477922}, + {-0.0017904931100023887, 0.00089524655445477922}, + {-0.0017904931100023887, -0.00089524655445477922}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} +#endif diff --git a/src/PJ_cc.c b/src/PJ_cc.c index 0f573929..475fbae4 100644 --- a/src/PJ_cc.c +++ b/src/PJ_cc.c @@ -1,20 +1,89 @@ -#define PROJ_PARMS__ \ - double ap; #define PJ_LIB__ #include + PROJ_HEAD(cc, "Central Cylindrical") "\n\tCyl, Sph"; #define EPS10 1.e-10 -FORWARD(s_forward); /* spheroid */ - if (fabs(fabs(lp.phi) - HALFPI) <= EPS10) F_ERROR; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + if (fabs (fabs(lp.phi) - HALFPI) <= EPS10) F_ERROR; xy.x = lp.lam; xy.y = tan(lp.phi); - return (xy); + return xy; } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; (void) P; lp.phi = atan(xy.y); lp.lam = xy.x; - return (lp); + return lp; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(cc) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(cc) { + P->es = 0.; + + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_cc_selftest (void) {return 0;} +#else + +int pj_cc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=cc +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {223402.14425527418, 111712.41554059254}, + {223402.14425527418, -111712.41554059254}, + {-223402.14425527418, 111712.41554059254}, + {-223402.14425527418, -111712.41554059254}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + {0.0017904931097838226, 0.00089524655481905597}, + {0.0017904931097838226, -0.00089524655481905597}, + {-0.0017904931097838226, 0.00089524655481905597}, + {-0.0017904931097838226, -0.00089524655481905597}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif diff --git a/src/PJ_wag2.c b/src/PJ_wag2.c index f4942bb2..b70dcd4f 100644 --- a/src/PJ_wag2.c +++ b/src/PJ_wag2.c @@ -5,17 +5,84 @@ PROJ_HEAD(wag2, "Wagner II") "\n\tPCyl., Sph."; #define C_y 1.38725 #define C_p1 0.88022 #define C_p2 0.88550 -FORWARD(s_forward); /* spheroid */ - lp.phi = aasin(P->ctx,C_p1 * sin(C_p2 * lp.phi)); - xy.x = C_x * lp.lam * cos(lp.phi); + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + lp.phi = aasin (P->ctx,C_p1 * sin (C_p2 * lp.phi)); + xy.x = C_x * lp.lam * cos (lp.phi); xy.y = C_y * lp.phi; return (xy); } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; lp.phi = xy.y / C_y; lp.lam = xy.x / (C_x * cos(lp.phi)); - lp.phi = aasin(P->ctx,sin(lp.phi) / C_p1) / C_p2; + lp.phi = aasin (P->ctx,sin(lp.phi) / C_p1) / C_p2; return (lp); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(wag2) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(wag2) { + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_wag2_selftest (void) {return 0;} +#else + +int pj_wag2_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=wag2 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 206589.88809996162, 120778.04035754716}, + { 206589.88809996162, -120778.04035754716}, + {-206589.88809996162, 120778.04035754716}, + {-206589.88809996162, -120778.04035754716}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0019360240367390709, 0.00082795765763814082}, + { 0.0019360240367390709, -0.00082795765763814082}, + {-0.0019360240367390709, 0.00082795765763814082}, + {-0.0019360240367390709, -0.00082795765763814082}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif diff --git a/src/PJ_wag3.c b/src/PJ_wag3.c index 482e389c..0539f4a1 100644 --- a/src/PJ_wag3.c +++ b/src/PJ_wag3.c @@ -1,24 +1,101 @@ -#define PROJ_PARMS__ \ - double C_x; #define PJ_LIB__ # include PROJ_HEAD(wag3, "Wagner III") "\n\tPCyl., Sph.\n\tlat_ts="; #define TWOTHIRD 0.6666666666666666666667 -FORWARD(s_forward); /* spheroid */ - xy.x = P->C_x * lp.lam * cos(TWOTHIRD * lp.phi); + +struct pj_opaque { + double C_x; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + xy.x = P->opaque->C_x * lp.lam * cos(TWOTHIRD * lp.phi); xy.y = lp.phi; - return (xy); + return xy; } + + +#if 0 INVERSE(s_inverse); /* spheroid */ +#endif + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; lp.phi = xy.y; - lp.lam = xy.x / (P->C_x * cos(TWOTHIRD * lp.phi)); - return (lp); + lp.lam = xy.x / (P->opaque->C_x * cos(TWOTHIRD * lp.phi)); + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(wag3) + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(wag3) { double ts; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + ts = pj_param (P->ctx, P->params, "rlat_ts").f; + P->opaque->C_x = cos (ts) / cos (2.*ts/3.); + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_wag3_selftest (void) {return 0;} +#else + +int pj_wag3_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=wag3 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {223387.02171816575, 111701.07212763709}, + {223387.02171816575, -111701.07212763709}, + {-223387.02171816575, 111701.07212763709}, + {-223387.02171816575, -111701.07212763709}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + {0.001790493109880963, 0.00089524655489191132}, + {0.001790493109880963, -0.00089524655489191132}, + {-0.001790493109880963, 0.00089524655489191132}, + {-0.001790493109880963, -0.00089524655489191132}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + - ts = pj_param(P->ctx, P->params, "rlat_ts").f; - P->C_x = cos(ts) / cos(2.*ts/3.); - P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; -ENDENTRY(P) +#endif diff --git a/src/PJ_wag7.c b/src/PJ_wag7.c index db29ffb1..847566d8 100644 --- a/src/PJ_wag7.c +++ b/src/PJ_wag7.c @@ -1,15 +1,67 @@ #define PJ_LIB__ #include + PROJ_HEAD(wag7, "Wagner VII") "\n\tMisc Sph, no inv."; -FORWARD(s_forward); /* sphere */ + + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0, 0.0}; double theta, ct, D; - (void) P; - theta = asin(xy.y = 0.90630778703664996 * sin(lp.phi)); - xy.x = 2.66723 * (ct = cos(theta)) * sin(lp.lam /= 3.); - xy.y *= 1.24104 * (D = 1/(sqrt(0.5 * (1 + ct * cos(lp.lam))))); + (void) P; /* Shut up compiler warnnings about unused P */ + + theta = asin (xy.y = 0.90630778703664996 * sin(lp.phi)); + xy.x = 2.66723 * (ct = cos (theta)) * sin (lp.lam /= 3.); + xy.y *= 1.24104 * (D = 1/(sqrt (0.5 * (1 + ct * cos (lp.lam))))); xy.x *= D; return (xy); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(wag7) P->fwd = s_forward; P->inv = 0; P->es = 0.; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + + +PJ *PROJECTION(wag7) { + P->fwd = s_forward; + P->inv = 0; + P->es = 0.; + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_wag7_selftest (void) {return 0;} +#else + +int pj_wag7_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=wag7 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 198601.87695731167, 125637.0457141714}, + { 198601.87695731167, -125637.0457141714}, + {-198601.87695731167, 125637.0457141714}, + {-198601.87695731167, -125637.0457141714}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} +#endif diff --git a/src/PJ_wink1.c b/src/PJ_wink1.c index dfb455e0..f9d127c0 100644 --- a/src/PJ_wink1.c +++ b/src/PJ_wink1.c @@ -1,20 +1,100 @@ -#define PROJ_PARMS__ \ - double cosphi1; #define PJ_LIB__ -# include +#include PROJ_HEAD(wink1, "Winkel I") "\n\tPCyl., Sph.\n\tlat_ts="; -FORWARD(s_forward); /* spheroid */ - xy.x = .5 * lp.lam * (P->cosphi1 + cos(lp.phi)); + + +struct pj_opaque { + double cosphi1; +}; + + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + xy.x = .5 * lp.lam * (P->opaque->cosphi1 + cos(lp.phi)); xy.y = lp.phi; return (xy); } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; lp.phi = xy.y; - lp.lam = 2. * xy.x / (P->cosphi1 + cos(lp.phi)); + lp.lam = 2. * xy.x / (P->opaque->cosphi1 + cos(lp.phi)); return (lp); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(wink1) - P->cosphi1 = cos(pj_param(P->ctx, P->params, "rlat_ts").f); - P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; -ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(wink1) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->opaque->cosphi1 = cos (pj_param(P->ctx, P->params, "rlat_ts").f); + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_wink1_selftest (void) {return 0;} +#else + +int pj_wink1_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=wink1 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223385.13164095284, 111701.07212763709}, + { 223385.13164095284, -111701.07212763709}, + {-223385.13164095284, 111701.07212763709}, + {-223385.13164095284, -111701.07212763709}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0017904931098931057, 0.00089524655489191132}, + { 0.0017904931098931057, -0.00089524655489191132}, + {-0.0017904931098931057, 0.00089524655489191132}, + {-0.0017904931098931057, -0.00089524655489191132}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif diff --git a/src/PJ_wink2.c b/src/PJ_wink2.c index 388c790a..f31ba5a5 100644 --- a/src/PJ_wink2.c +++ b/src/PJ_wink2.c @@ -1,34 +1,93 @@ -#define PROJ_PARMS__ \ - double cosphi1; #define PJ_LIB__ # include + PROJ_HEAD(wink2, "Winkel II") "\n\tPCyl., Sph., no inv.\n\tlat_1="; + +struct pj_opaque { double cosphi1; }; + #define MAX_ITER 10 #define LOOP_TOL 1e-7 #define TWO_D_PI 0.636619772367581343 -FORWARD(s_forward); /* spheroid */ + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0, 0.0}; double k, V; int i; xy.y = lp.phi * TWO_D_PI; - k = PI * sin(lp.phi); + k = PI * sin (lp.phi); lp.phi *= 1.8; for (i = MAX_ITER; i ; --i) { - lp.phi -= V = (lp.phi + sin(lp.phi) - k) / - (1. + cos(lp.phi)); - if (fabs(V) < LOOP_TOL) + lp.phi -= V = (lp.phi + sin (lp.phi) - k) / + (1. + cos (lp.phi)); + if (fabs (V) < LOOP_TOL) break; } if (!i) lp.phi = (lp.phi < 0.) ? -HALFPI : HALFPI; else lp.phi *= 0.5; - xy.x = 0.5 * lp.lam * (cos(lp.phi) + P->cosphi1); - xy.y = FORTPI * (sin(lp.phi) + xy.y); - return (xy); + xy.x = 0.5 * lp.lam * (cos (lp.phi) + P->opaque->cosphi1); + xy.y = FORTPI * (sin (lp.phi) + xy.y); + return xy; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(wink2) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->opaque->cosphi1 = cos(pj_param(P->ctx, P->params, "rlat_1").f); + P->es = 0.; + P->inv = 0; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_wink2_selftest (void) {return 0;} +#else + +int pj_wink2_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=wink2 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223387.39643378611, 124752.03279744535}, + { 223387.39643378611, -124752.03279744535}, + {-223387.39643378611, 124752.03279744535}, + {-223387.39643378611, -124752.03279744535}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(wink2) - P->cosphi1 = cos(pj_param(P->ctx, P->params, "rlat_1").f); - P->es = 0.; P->inv = 0; P->fwd = s_forward; -ENDENTRY(P) +#endif diff --git a/src/projects.h b/src/projects.h index 307b69bd..2957f848 100644 --- a/src/projects.h +++ b/src/projects.h @@ -359,7 +359,7 @@ extern struct PJ_PRIME_MERIDIANS pj_prime_meridians[]; #define INVERSE3D(name) static LPZ name(XYZ xyz, PJ *P) {LPZ lpz = {0.0, 0.0, 0.0} #define FREEUP static void freeup(PJ *P) { #define SPECIAL(name) static void name(LP lp, PJ *P, struct FACTORS *fac) - +#define ELLIPSOIDAL(P) ((P->es==0)? (FALSE): (TRUE)) /* cleaned up alternative to most of the "repetitive projection code" macros */ #define PROJECTION(name) \ -- cgit v1.2.3 From c8f040f1d6b52f89825c9a1060545a97bf799487 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Tue, 12 Apr 2016 21:55:29 +0200 Subject: refactoring + added selftest for 7 more projections tcc, tcea, tmerc, tpeqd, urm5, urmfps, wag1 --- src/PJ_aea.c | 7 - src/PJ_tcc.c | 76 ++++++++-- src/PJ_tcea.c | 104 ++++++++++--- src/PJ_tmerc.c | 373 +++++++++++++++++++++++++++++----------------- src/PJ_tpeqd.c | 193 ++++++++++++++++++------ src/PJ_urm5.c | 103 +++++++++---- src/PJ_urmfps.c | 176 ++++++++++++++++++---- src/pj_generic_selftest.c | 20 ++- 8 files changed, 767 insertions(+), 285 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 6de8f00d..7a507460 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -457,22 +457,15 @@ int pj_somerc_selftest (void) {return 10000;} int pj_stere_selftest (void) {return 10000;} int pj_sterea_selftest (void) {return 10000;} int pj_gstmerc_selftest (void) {return 10000;} -int pj_tcc_selftest (void) {return 10000;} -int pj_tcea_selftest (void) {return 10000;} int pj_tissot_selftest (void) {return 10000;} -int pj_tmerc_selftest (void) {return 10000;} -int pj_tpeqd_selftest (void) {return 10000;} int pj_tpers_selftest (void) {return 10000;} int pj_ups_selftest (void) {return 10000;} -int pj_urm5_selftest (void) {return 10000;} -int pj_urmfps_selftest (void) {return 10000;} int pj_utm_selftest (void) {return 10000;} int pj_vandg_selftest (void) {return 10000;} int pj_vandg2_selftest (void) {return 10000;} int pj_vandg3_selftest (void) {return 10000;} int pj_vandg4_selftest (void) {return 10000;} int pj_vitk1_selftest (void) {return 10000;} -int pj_wag1_selftest (void) {return 10000;} int pj_wag4_selftest (void) {return 10000;} int pj_wag5_selftest (void) {return 10000;} int pj_wag6_selftest (void) {return 10000;} diff --git a/src/PJ_tcc.c b/src/PJ_tcc.c index 00cdb556..457924c0 100644 --- a/src/PJ_tcc.c +++ b/src/PJ_tcc.c @@ -1,17 +1,65 @@ -#define PROJ_PARMS__ \ - double ap; -#define EPS10 1.e-10 #define PJ_LIB__ -#include +#include + PROJ_HEAD(tcc, "Transverse Central Cylindrical") "\n\tCyl, Sph, no inv."; -FORWARD(s_forward); /* spheroid */ - double b, bt; - - b = cos(lp.phi) * sin(lp.lam); - if ((bt = 1. - b * b) < EPS10) F_ERROR; - xy.x = b / sqrt(bt); - xy.y = atan2(tan(lp.phi) , cos(lp.lam)); - return (xy); + +#define EPS10 1.e-10 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0, 0.0}; + double b, bt; + + b = cos (lp.phi) * sin (lp.lam); + if ((bt = 1. - b * b) < EPS10) F_ERROR; + xy.x = b / sqrt(bt); + xy.y = atan2 (tan (lp.phi) , cos (lp.lam)); + return xy; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(tcc) { + P->es = 0.; + P->fwd = s_forward; + P->inv = 0; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_tcc_selftest (void) {return 0;} +#else +int pj_tcc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=tcc +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {223458.84419245756, 111769.14504058579}, + {223458.84419245756, -111769.14504058579}, + {-223458.84419245756, 111769.14504058579}, + {-223458.84419245756, -111769.14504058579}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(tcc) P->es = 0.; P->fwd = s_forward; ENDENTRY(P) +#endif diff --git a/src/PJ_tcea.c b/src/PJ_tcea.c index 3626fa17..7b469d0e 100644 --- a/src/PJ_tcea.c +++ b/src/PJ_tcea.c @@ -1,27 +1,85 @@ -#define PROJ_PARMS__ \ - double rk0; #define PJ_LIB__ -#include +#include + PROJ_HEAD(tcea, "Transverse Cylindrical Equal Area") "\n\tCyl, Sph"; -FORWARD(s_forward); /* spheroid */ - xy.x = P->rk0 * cos(lp.phi) * sin(lp.lam); - xy.y = P->k0 * (atan2(tan(lp.phi), cos(lp.lam)) - P->phi0); - return (xy); + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + xy.x = cos (lp.phi) * sin (lp.lam) / P->k0; + xy.y = P->k0 * (atan2 (tan (lp.phi), cos (lp.lam)) - P->phi0); + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0, 0.0}; + double t; + + xy.y = xy.y / P->k0 + P->phi0; + xy.x *= P->k0; + t = sqrt (1. - xy.x * xy.x); + lp.phi = asin (t * sin (xy.y)); + lp.lam = atan2 (xy.x, t * cos (xy.y)); + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; } -INVERSE(s_inverse); /* spheroid */ - double t; - - xy.y = xy.y * P->rk0 + P->phi0; - xy.x *= P->k0; - t = sqrt(1. - xy.x * xy.x); - lp.phi = asin(t * sin(xy.y)); - lp.lam = atan2(xy.x, t * cos(xy.y)); - return (lp); + + +PJ *PROJECTION(tcea) { + P->inv = s_inverse; + P->fwd = s_forward; + P->es = 0.; + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_tcea_selftest (void) {return 0;} +#else +int pj_tcea_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=tcea +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223322.76057672748, 111769.14504058579}, + { 223322.76057672748, -111769.14504058579}, + {-223322.76057672748, 111769.14504058579}, + {-223322.76057672748, -111769.14504058579}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0017904931102938101, 0.00089524655445477922}, + { 0.0017904931102938101, -0.00089524655445477922}, + {-0.0017904931102938101, 0.00089524655445477922}, + {-0.0017904931102938101, -0.00089524655445477922}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(tcea) - P->rk0 = 1 / P->k0; - P->inv = s_inverse; - P->fwd = s_forward; - P->es = 0.; -ENDENTRY(P) +#endif diff --git a/src/PJ_tmerc.c b/src/PJ_tmerc.c index 70e8e72f..35203261 100644 --- a/src/PJ_tmerc.c +++ b/src/PJ_tmerc.c @@ -1,13 +1,16 @@ -#define PROJ_PARMS__ \ - double esp; \ - double ml0; \ - double *en; #define PJ_LIB__ -#include +#include + PROJ_HEAD(tmerc, "Transverse Mercator") "\n\tCyl, Sph&Ell"; -#define EPS10 1.e-10 -#define aks0 P->esp -#define aks5 P->ml0 + + +struct pj_opaque { + double esp; \ + double ml0; \ + double *en; +}; + +#define EPS10 1.e-10 #define FC1 1. #define FC2 .5 #define FC3 .16666666666666666666 @@ -16,138 +19,234 @@ PROJ_HEAD(tmerc, "Transverse Mercator") "\n\tCyl, Sph&Ell"; #define FC6 .03333333333333333333 #define FC7 .02380952380952380952 #define FC8 .01785714285714285714 -FORWARD(e_forward); /* ellipse */ - double al, als, n, cosphi, sinphi, t; - - /* - * Fail if our longitude is more than 90 degrees from the - * central meridian since the results are essentially garbage. - * Is error -20 really an appropriate return value? - * - * http://trac.osgeo.org/proj/ticket/5 - */ - if( lp.lam < -HALFPI || lp.lam > HALFPI ) - { - xy.x = HUGE_VAL; - xy.y = HUGE_VAL; - pj_ctx_set_errno( P->ctx, -14 ); - return xy; - } - - sinphi = sin(lp.phi); cosphi = cos(lp.phi); - t = fabs(cosphi) > 1e-10 ? sinphi/cosphi : 0.; - t *= t; - al = cosphi * lp.lam; - als = al * al; - al /= sqrt(1. - P->es * sinphi * sinphi); - n = P->esp * cosphi * cosphi; - xy.x = P->k0 * al * (FC1 + - FC3 * als * (1. - t + n + - FC5 * als * (5. + t * (t - 18.) + n * (14. - 58. * t) - + FC7 * als * (61. + t * ( t * (179. - t) - 479. ) ) - ))); - xy.y = P->k0 * (pj_mlfn(lp.phi, sinphi, cosphi, P->en) - P->ml0 + - sinphi * al * lp.lam * FC2 * ( 1. + - FC4 * als * (5. - t + n * (9. + 4. * n) + - FC6 * als * (61. + t * (t - 58.) + n * (270. - 330 * t) - + FC8 * als * (1385. + t * ( t * (543. - t) - 3111.) ) - )))); - return (xy); + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0, 0.0}; + struct pj_opaque *Q = P->opaque; + double al, als, n, cosphi, sinphi, t; + + /* + * Fail if our longitude is more than 90 degrees from the + * central meridian since the results are essentially garbage. + * Is error -20 really an appropriate return value? + * + * http://trac.osgeo.org/proj/ticket/5 + */ + if( lp.lam < -HALFPI || lp.lam > HALFPI ) { + xy.x = HUGE_VAL; + xy.y = HUGE_VAL; + pj_ctx_set_errno( P->ctx, -14 ); + return xy; + } + + sinphi = sin (lp.phi); + cosphi = cos (lp.phi); + t = fabs (cosphi) > 1e-10 ? sinphi/cosphi : 0.; + t *= t; + al = cosphi * lp.lam; + als = al * al; + al /= sqrt (1. - P->es * sinphi * sinphi); + n = Q->esp * cosphi * cosphi; + xy.x = P->k0 * al * (FC1 + + FC3 * als * (1. - t + n + + FC5 * als * (5. + t * (t - 18.) + n * (14. - 58. * t) + + FC7 * als * (61. + t * ( t * (179. - t) - 479. ) ) + ))); + xy.y = P->k0 * (pj_mlfn(lp.phi, sinphi, cosphi, Q->en) - Q->ml0 + + sinphi * al * lp.lam * FC2 * ( 1. + + FC4 * als * (5. - t + n * (9. + 4. * n) + + FC6 * als * (61. + t * (t - 58.) + n * (270. - 330 * t) + + FC8 * als * (1385. + t * ( t * (543. - t) - 3111.) ) + )))); + return (xy); +} + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + double b, cosphi; + + /* + * Fail if our longitude is more than 90 degrees from the + * central meridian since the results are essentially garbage. + * Is error -20 really an appropriate return value? + * + * http://trac.osgeo.org/proj/ticket/5 + */ + if( lp.lam < -HALFPI || lp.lam > HALFPI ) { + xy.x = HUGE_VAL; + xy.y = HUGE_VAL; + pj_ctx_set_errno( P->ctx, -14 ); + return xy; + } + + cosphi = cos(lp.phi); + b = cosphi * sin (lp.lam); + if (fabs (fabs (b) - 1.) <= EPS10) + F_ERROR; + + xy.x = P->opaque->ml0 * log ((1. + b) / (1. - b)); + xy.y = cosphi * cos (lp.lam) / sqrt (1. - b * b); + + b = fabs ( xy.y ); + if (b >= 1.) { + if ((b - 1.) > EPS10) + F_ERROR + else xy.y = 0.; + } else + xy.y = acos (xy.y); + + if (lp.phi < 0.) + xy.y = -xy.y; + xy.y = P->opaque->esp * (xy.y - P->phi0); + return xy; +} + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double n, con, cosphi, d, ds, sinphi, t; + + lp.phi = pj_inv_mlfn(P->ctx, Q->ml0 + xy.y / P->k0, P->es, Q->en); + if (fabs(lp.phi) >= HALFPI) { + lp.phi = xy.y < 0. ? -HALFPI : HALFPI; + lp.lam = 0.; + } else { + sinphi = sin(lp.phi); + cosphi = cos(lp.phi); + t = fabs (cosphi) > 1e-10 ? sinphi/cosphi : 0.; + n = Q->esp * cosphi * cosphi; + d = xy.x * sqrt (con = 1. - P->es * sinphi * sinphi) / P->k0; + con *= t; + t *= t; + ds = d * d; + lp.phi -= (con * ds / (1.-P->es)) * FC2 * (1. - + ds * FC4 * (5. + t * (3. - 9. * n) + n * (1. - 4 * n) - + ds * FC6 * (61. + t * (90. - 252. * n + + 45. * t) + 46. * n + - ds * FC8 * (1385. + t * (3633. + t * (4095. + 1574. * t)) ) + ))); + lp.lam = d*(FC1 - + ds*FC3*( 1. + 2.*t + n - + ds*FC5*(5. + t*(28. + 24.*t + 8.*n) + 6.*n + - ds * FC7 * (61. + t * (662. + t * (1320. + 720. * t)) ) + ))) / cosphi; + } + return lp; } -FORWARD(s_forward); /* sphere */ - double b, cosphi; - - /* - * Fail if our longitude is more than 90 degrees from the - * central meridian since the results are essentially garbage. - * Is error -20 really an appropriate return value? - * - * http://trac.osgeo.org/proj/ticket/5 - */ - if( lp.lam < -HALFPI || lp.lam > HALFPI ) - { - xy.x = HUGE_VAL; - xy.y = HUGE_VAL; - pj_ctx_set_errno( P->ctx, -14 ); - return xy; - } - - b = (cosphi = cos(lp.phi)) * sin(lp.lam); - if (fabs(fabs(b) - 1.) <= EPS10) F_ERROR; - xy.x = aks5 * log((1. + b) / (1. - b)); - if ((b = fabs( xy.y = cosphi * cos(lp.lam) / sqrt(1. - b * b) )) >= 1.) { - if ((b - 1.) > EPS10) F_ERROR - else xy.y = 0.; - } else - xy.y = acos(xy.y); - if (lp.phi < 0.) xy.y = -xy.y; - xy.y = aks0 * (xy.y - P->phi0); - return (xy); + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0, 0.0}; + double h, g; + + h = exp(xy.x / P->opaque->esp); + g = .5 * (h - 1. / h); + h = cos (P->phi0 + xy.y / P->opaque->esp); + lp.phi = asin(sqrt((1. - h * h) / (1. + g * g))); + if (xy.y < 0.) lp.phi = -lp.phi; + lp.lam = (g || h) ? atan2 (g, h) : 0.; + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + pj_dealloc (P->opaque->en); + pj_dealloc (P->opaque); + return pj_dealloc(P); } -INVERSE(e_inverse); /* ellipsoid */ - double n, con, cosphi, d, ds, sinphi, t; - - lp.phi = pj_inv_mlfn(P->ctx, P->ml0 + xy.y / P->k0, P->es, P->en); - if (fabs(lp.phi) >= HALFPI) { - lp.phi = xy.y < 0. ? -HALFPI : HALFPI; - lp.lam = 0.; - } else { - sinphi = sin(lp.phi); - cosphi = cos(lp.phi); - t = fabs(cosphi) > 1e-10 ? sinphi/cosphi : 0.; - n = P->esp * cosphi * cosphi; - d = xy.x * sqrt(con = 1. - P->es * sinphi * sinphi) / P->k0; - con *= t; - t *= t; - ds = d * d; - lp.phi -= (con * ds / (1.-P->es)) * FC2 * (1. - - ds * FC4 * (5. + t * (3. - 9. * n) + n * (1. - 4 * n) - - ds * FC6 * (61. + t * (90. - 252. * n + - 45. * t) + 46. * n - - ds * FC8 * (1385. + t * (3633. + t * (4095. + 1574. * t)) ) - ))); - lp.lam = d*(FC1 - - ds*FC3*( 1. + 2.*t + n - - ds*FC5*(5. + t*(28. + 24.*t + 8.*n) + 6.*n - - ds * FC7 * (61. + t * (662. + t * (1320. + 720. * t)) ) - ))) / cosphi; - } - return (lp); + +static void freeup (PJ *P) { + freeup_new (P); + return; } -INVERSE(s_inverse); /* sphere */ - double h, g; - - h = exp(xy.x / aks0); - g = .5 * (h - 1. / h); - h = cos(P->phi0 + xy.y / aks0); - lp.phi = asin(sqrt((1. - h * h) / (1. + g * g))); - if (xy.y < 0.) lp.phi = -lp.phi; - lp.lam = (g || h) ? atan2(g, h) : 0.; - return (lp); + +static PJ *setup(PJ *P) { /* general initialization */ + struct pj_opaque *Q = P->opaque; + if (P->es) { + if (!(Q->en = pj_enfn(P->es))) + E_ERROR_0; + Q->ml0 = pj_mlfn(P->phi0, sin(P->phi0), cos(P->phi0), Q->en); + Q->esp = P->es / (1. - P->es); + P->inv = e_inverse; + P->fwd = e_forward; + } else { + Q->esp = P->k0; + Q->ml0 = .5 * Q->esp; + P->inv = s_inverse; + P->fwd = s_forward; + } + return P; } -FREEUP; - if (P) { - if (P->en) - pj_dalloc(P->en); - pj_dalloc(P); - } + + +PJ *PROJECTION(tmerc) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + return setup(P); } - static PJ * -setup(PJ *P) { /* general initialization */ - if (P->es) { - if (!(P->en = pj_enfn(P->es))) - E_ERROR_0; - P->ml0 = pj_mlfn(P->phi0, sin(P->phi0), cos(P->phi0), P->en); - P->esp = P->es / (1. - P->es); - P->inv = e_inverse; - P->fwd = e_forward; - } else { - aks0 = P->k0; - aks5 = .5 * aks0; - P->inv = s_inverse; - P->fwd = s_forward; - } - return P; + + +#ifdef PJ_OMIT_SELFTEST +int pj_tmerc_selftest (void) {return 0;} +#else +int pj_tmerc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=tmerc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=tmerc +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222650.79679577847, 110642.22941192707}, + { 222650.79679577847, -110642.22941192707}, + {-222650.79679577847, 110642.22941192707}, + {-222650.79679577847, -110642.22941192707}, + }; + + XY s_fwd_expect[] = { + { 223413.46640632232, 111769.14504059685}, + { 223413.46640632232, -111769.14504059685}, + {-223413.46640632208, 111769.14504059685}, + {-223413.46640632208, -111769.14504059685}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.0017966305681649396, 0.00090436947663183841}, + { 0.0017966305681649396, -0.00090436947663183841}, + {-0.0017966305681649396, 0.00090436947663183841}, + {-0.0017966305681649396, -0.00090436947663183841}, + }; + + LP s_inv_expect[] = { + { 0.0017904931097048034, 0.00089524670602767842}, + { 0.0017904931097048034, -0.00089524670602767842}, + {-0.001790493109714345, 0.00089524670602767842}, + {-0.001790493109714345, -0.00089524670602767842}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); } -ENTRY1(tmerc, en) -ENDENTRY(setup(P)) +#endif diff --git a/src/PJ_tpeqd.c b/src/PJ_tpeqd.c index 4ab5cf4e..182f23a5 100644 --- a/src/PJ_tpeqd.c +++ b/src/PJ_tpeqd.c @@ -1,76 +1,177 @@ -#define PROJ_PARMS__ \ - double cp1, sp1, cp2, sp2, ccs, cs, sc, r2z0, z02, dlam2; \ - double hz0, thz0, rhshz0, ca, sa, lp, lamc; #define PJ_LIB__ #include + + PROJ_HEAD(tpeqd, "Two Point Equidistant") "\n\tMisc Sph\n\tlat_1= lon_1= lat_2= lon_2="; -FORWARD(s_forward); /* sphere */ + +struct pj_opaque { + double cp1, sp1, cp2, sp2, ccs, cs, sc, r2z0, z02, dlam2; \ + double hz0, thz0, rhshz0, ca, sa, lp, lamc; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0, 0.0}; + struct pj_opaque *Q = P->opaque; double t, z1, z2, dl1, dl2, sp, cp; sp = sin(lp.phi); cp = cos(lp.phi); - z1 = aacos(P->ctx,P->sp1 * sp + P->cp1 * cp * cos(dl1 = lp.lam + P->dlam2)); - z2 = aacos(P->ctx,P->sp2 * sp + P->cp2 * cp * cos(dl2 = lp.lam - P->dlam2)); + z1 = aacos(P->ctx, Q->sp1 * sp + Q->cp1 * cp * cos (dl1 = lp.lam + Q->dlam2)); + z2 = aacos(P->ctx, Q->sp2 * sp + Q->cp2 * cp * cos (dl2 = lp.lam - Q->dlam2)); z1 *= z1; z2 *= z2; - xy.x = P->r2z0 * (t = z1 - z2); - t = P->z02 - t; - xy.y = P->r2z0 * asqrt(4. * P->z02 * z2 - t * t); - if ((P->ccs * sp - cp * (P->cs * sin(dl1) - P->sc * sin(dl2))) < 0.) + + xy.x = Q->r2z0 * (t = z1 - z2); + t = Q->z02 - t; + xy.y = Q->r2z0 * asqrt (4. * Q->z02 * z2 - t * t); + if ((Q->ccs * sp - cp * (Q->cs * sin(dl1) - Q->sc * sin(dl2))) < 0.) xy.y = -xy.y; return xy; } -INVERSE(s_inverse); /* sphere */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double cz1, cz2, s, d, cp, sp; - cz1 = cos(hypot(xy.y, xy.x + P->hz0)); - cz2 = cos(hypot(xy.y, xy.x - P->hz0)); + cz1 = cos (hypot(xy.y, xy.x + Q->hz0)); + cz2 = cos (hypot(xy.y, xy.x - Q->hz0)); s = cz1 + cz2; d = cz1 - cz2; - lp.lam = - atan2(d, (s * P->thz0)); - lp.phi = aacos(P->ctx,hypot(P->thz0 * s, d) * P->rhshz0); + lp.lam = - atan2(d, (s * Q->thz0)); + lp.phi = aacos(P->ctx, hypot (Q->thz0 * s, d) * Q->rhshz0); if ( xy.y < 0. ) lp.phi = - lp.phi; /* lam--phi now in system relative to P1--P2 base equator */ - sp = sin(lp.phi); - cp = cos(lp.phi); - lp.phi = aasin(P->ctx,P->sa * sp + P->ca * cp * (s = cos(lp.lam -= P->lp))); - lp.lam = atan2(cp * sin(lp.lam), P->sa * cp * s - P->ca * sp) + P->lamc; + sp = sin (lp.phi); + cp = cos (lp.phi); + lp.phi = aasin (P->ctx, Q->sa * sp + Q->ca * cp * (s = cos(lp.lam -= Q->lp))); + lp.lam = atan2 (cp * sin(lp.lam), Q->sa * cp * s - Q->ca * sp) + Q->lamc; return lp; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(tpeqd) + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(tpeqd) { double lam_1, lam_2, phi_1, phi_2, A12, pp; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + /* get control point locations */ phi_1 = pj_param(P->ctx, P->params, "rlat_1").f; lam_1 = pj_param(P->ctx, P->params, "rlon_1").f; phi_2 = pj_param(P->ctx, P->params, "rlat_2").f; lam_2 = pj_param(P->ctx, P->params, "rlon_2").f; - if (phi_1 == phi_2 && lam_1 == lam_2) E_ERROR(-25); - P->lam0 = adjlon(0.5 * (lam_1 + lam_2)); - P->dlam2 = adjlon(lam_2 - lam_1); - P->cp1 = cos(phi_1); - P->cp2 = cos(phi_2); - P->sp1 = sin(phi_1); - P->sp2 = sin(phi_2); - P->cs = P->cp1 * P->sp2; - P->sc = P->sp1 * P->cp2; - P->ccs = P->cp1 * P->cp2 * sin(P->dlam2); - P->z02 = aacos(P->ctx,P->sp1 * P->sp2 + P->cp1 * P->cp2 * cos(P->dlam2)); - P->hz0 = .5 * P->z02; - A12 = atan2(P->cp2 * sin(P->dlam2), - P->cp1 * P->sp2 - P->sp1 * P->cp2 * cos(P->dlam2)); - P->ca = cos(pp = aasin(P->ctx,P->cp1 * sin(A12))); - P->sa = sin(pp); - P->lp = adjlon(atan2(P->cp1 * cos(A12), P->sp1) - P->hz0); - P->dlam2 *= .5; - P->lamc = HALFPI - atan2(sin(A12) * P->sp1, cos(A12)) - P->dlam2; - P->thz0 = tan(P->hz0); - P->rhshz0 = .5 / sin(P->hz0); - P->r2z0 = 0.5 / P->z02; - P->z02 *= P->z02; - P->inv = s_inverse; P->fwd = s_forward; + + if (phi_1 == phi_2 && lam_1 == lam_2) + E_ERROR(-25); + P->lam0 = adjlon (0.5 * (lam_1 + lam_2)); + Q->dlam2 = adjlon (lam_2 - lam_1); + + Q->cp1 = cos (phi_1); + Q->cp2 = cos (phi_2); + Q->sp1 = sin (phi_1); + Q->sp2 = sin (phi_2); + Q->cs = Q->cp1 * Q->sp2; + Q->sc = Q->sp1 * Q->cp2; + Q->ccs = Q->cp1 * Q->cp2 * sin(Q->dlam2); + Q->z02 = aacos(P->ctx, Q->sp1 * Q->sp2 + Q->cp1 * Q->cp2 * cos (Q->dlam2)); + Q->hz0 = .5 * Q->z02; + A12 = atan2(Q->cp2 * sin (Q->dlam2), + Q->cp1 * Q->sp2 - Q->sp1 * Q->cp2 * cos (Q->dlam2)); + Q->ca = cos(pp = aasin(P->ctx, Q->cp1 * sin(A12))); + Q->sa = sin(pp); + Q->lp = adjlon ( atan2 (Q->cp1 * cos(A12), Q->sp1) - Q->hz0); + Q->dlam2 *= .5; + Q->lamc = HALFPI - atan2(sin(A12) * Q->sp1, cos(A12)) - Q->dlam2; + Q->thz0 = tan (Q->hz0); + Q->rhshz0 = .5 / sin (Q->hz0); + Q->r2z0 = 0.5 / Q->z02; + Q->z02 *= Q->z02; + + P->inv = s_inverse; + P->fwd = s_forward; P->es = 0.; -ENDENTRY(P) + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_tpeqd_selftest (void) {return 0;} +#else + +int pj_tpeqd_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=tpeqd +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=tpeqd +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {-27750.758831679042, -222599.40369177726}, + {-250434.93702403645, -222655.93819326628}, + {-27750.758831679042, 222599.40369177726}, + {-250434.93702403645, 222655.93819326628}, + }; + + XY s_fwd_expect[] = { + {-27845.882978485075, -223362.43069526015}, + {-251293.37876465076, -223419.15898590829}, + {-27845.882978485075, 223362.43069526015}, + {-251293.37876465076, 223419.15898590829}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {-0.00089855554821257374, 1.2517966304145272}, + {0.0008985555481998515, 1.2517966304145272}, + {-0.00089855431859741167, 1.2482033692781642}, + {0.00089855431859741167, 1.2482033692781642}, + }; + + LP s_inv_expect[] = { + {-0.00089548606640108474, 1.2517904929571837}, + {0.0008954860663883625, 1.2517904929571837}, + {-0.000895484845182587, 1.248209506737604}, + {0.00089548484516986475, 1.248209506737604}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif diff --git a/src/PJ_urm5.c b/src/PJ_urm5.c index 9159df65..7a759b07 100644 --- a/src/PJ_urm5.c +++ b/src/PJ_urm5.c @@ -1,28 +1,81 @@ -#define PROJ_PARMS__ \ - double m, rmn, q3, n; #define PJ_LIB__ -# include +#include + PROJ_HEAD(urm5, "Urmaev V") "\n\tPCyl., Sph., no inv.\n\tn= q= alpha="; -FORWARD(s_forward); /* spheroid */ - double t; - - t = lp.phi = aasin(P->ctx,P->n * sin(lp.phi)); - xy.x = P->m * lp.lam * cos(lp.phi); - t *= t; - xy.y = lp.phi * (1. + t * P->q3) * P->rmn; - return xy; + +struct pj_opaque { + double m, rmn, q3, n; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0, 0.0}; + struct pj_opaque *Q = P->opaque; + double t; + + t = lp.phi = aasin (P->ctx, Q->n * sin (lp.phi)); + xy.x = Q->m * lp.lam * cos (lp.phi); + t *= t; + xy.y = lp.phi * (1. + t * Q->q3) * Q->rmn; + return xy; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(urm5) { + double alpha, t; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->n = pj_param(P->ctx, P->params, "dn").f; + Q->q3 = pj_param(P->ctx, P->params, "dq").f / 3.; + alpha = pj_param(P->ctx, P->params, "ralpha").f; + t = Q->n * sin (alpha); + Q->m = cos (alpha) / sqrt (1. - t * t); + Q->rmn = 1. / (Q->m * Q->n); + + P->es = 0.; + P->inv = 0; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_urm5_selftest (void) {return 0;} +#else +int pj_urm5_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=urm5 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223393.6384339639, 111696.81878511712}, + { 223393.6384339639, -111696.81878511712}, + {-223393.6384339639, 111696.81878511712}, + {-223393.6384339639, -111696.81878511712}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(urm5) - double alpha, t; - - P->n = pj_param(P->ctx, P->params, "dn").f; - P->q3 = pj_param(P->ctx, P->params, "dq").f / 3.; - alpha = pj_param(P->ctx, P->params, "ralpha").f; - t = P->n * sin(alpha); - P->m = cos(alpha) / sqrt(1. - t * t); - P->rmn = 1. / (P->m * P->n); - P->es = 0.; - P->inv = 0; - P->fwd = s_forward; -ENDENTRY(P) +#endif diff --git a/src/PJ_urmfps.c b/src/PJ_urmfps.c index 5c5918ae..2322aa04 100644 --- a/src/PJ_urmfps.c +++ b/src/PJ_urmfps.c @@ -1,40 +1,166 @@ -#define PROJ_PARMS__ \ - double n, C_y; #define PJ_LIB__ #include + PROJ_HEAD(urmfps, "Urmaev Flat-Polar Sinusoidal") "\n\tPCyl, Sph.\n\tn="; PROJ_HEAD(wag1, "Wagner I (Kavraisky VI)") "\n\tPCyl, Sph."; + +struct pj_opaque { + double n, C_y; +}; + #define C_x 0.8773826753 #define Cy 1.139753528477 -FORWARD(s_forward); /* sphere */ - lp.phi = aasin(P->ctx,P->n * sin(lp.phi)); - xy.x = C_x * lp.lam * cos(lp.phi); - xy.y = P->C_y * lp.phi; - return (xy); -} -INVERSE(s_inverse); /* sphere */ - xy.y /= P->C_y; - lp.phi = aasin(P->ctx,sin(xy.y) / P->n); - lp.lam = xy.x / (C_x * cos(xy.y)); - return (lp); -} -FREEUP; if (P) pj_dalloc(P); } - static PJ * -setup(PJ *P) { - P->C_y = Cy / P->n; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0, 0.0}; + lp.phi = aasin (P->ctx,P->opaque->n * sin (lp.phi)); + xy.x = C_x * lp.lam * cos (lp.phi); + xy.y = P->opaque->C_y * lp.phi; + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0, 0.0}; + xy.y /= P->opaque->C_y; + lp.phi = aasin(P->ctx, sin (xy.y) / P->opaque->n); + lp.lam = xy.x / (C_x * cos (xy.y)); + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + +static PJ *setup(PJ *P) { + P->opaque->C_y = Cy / P->opaque->n; P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; return P; } -ENTRY0(urmfps) + + +PJ *PROJECTION(urmfps) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + if (pj_param(P->ctx, P->params, "tn").i) { - P->n = pj_param(P->ctx, P->params, "dn").f; - if (P->n <= 0. || P->n > 1.) + P->opaque->n = pj_param(P->ctx, P->params, "dn").f; + if (P->opaque->n <= 0. || P->opaque->n > 1.) E_ERROR(-40) } else E_ERROR(-40) -ENDENTRY(setup(P)) -ENTRY0(wag1) - P->n = 0.8660254037844386467637231707; -ENDENTRY(setup(P)) + + return setup(P); +} + + +PJ *PROJECTION(wag1) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->opaque->n = 0.8660254037844386467637231707; + return setup(P); +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_urmfps_selftest (void) {return 0;} +#else +int pj_urmfps_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=urmfps +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 196001.70813419219, 127306.84332999329}, + { 196001.70813419219, -127306.84332999329}, + {-196001.70813419219, 127306.84332999329}, + {-196001.70813419219, -127306.84332999329}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.002040720839642371, 0.00078547381740438178}, + { 0.002040720839642371, -0.00078547381740438178}, + {-0.002040720839642371, 0.00078547381740438178}, + {-0.002040720839642371, -0.00078547381740438178}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} +#endif + + +#ifdef PJ_OMIT_SELFTEST +int pj_wag1_selftest (void) {return 0;} +#else +int pj_wag1_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=wag1 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 195986.78156115755, 127310.07506065986}, + { 195986.78156115755, -127310.07506065986}, + {-195986.78156115755, 127310.07506065986}, + {-195986.78156115755, -127310.07506065986}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.002040720839738254, 0.00078547381739207999}, + { 0.002040720839738254, -0.00078547381739207999}, + {-0.002040720839738254, 0.00078547381739207999}, + {-0.002040720839738254, -0.00078547381739207999}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} +#endif + diff --git a/src/pj_generic_selftest.c b/src/pj_generic_selftest.c index 5ac239e2..2af3f3b9 100644 --- a/src/pj_generic_selftest.c +++ b/src/pj_generic_selftest.c @@ -145,11 +145,15 @@ static int deviates_xy (XY expected, XY got, double tolerance) { Determine whether two XYs deviate by more than . + The test material ("expected" values) may contain coordinates that + are indeterminate. For those cases, we test the other coordinate + only by forcing expected and actual ("got") coordinates to 0. + ***********************************************************************/ - if (HUGE_VAL== expected.x) - return 0; - if (HUGE_VAL== expected.y) - return 0; + if ((HUGE_VAL== expected.x) || (isnan (expected.x))) + expected.x = got.x = 0; + if ((HUGE_VAL== expected.y) || (isnan (expected.y))) + expected.y = got.y = 0; if (hypot ( expected.x - got.x, expected.y - got.y ) > tolerance) return 1; return 0; @@ -169,10 +173,10 @@ static int deviates_lp (LP expected, LP got, double tolerance) { output from pj_inv) ***********************************************************************/ - if (HUGE_VAL== expected.lam) - return 0; - if (HUGE_VAL== expected.phi) - return 0; + if ((HUGE_VAL== expected.lam) || (isnan (expected.lam))) + expected.lam = got.lam = 0; + if ((HUGE_VAL== expected.phi) || (isnan (expected.phi))) + expected.phi = got.phi = 0; if (hypot ( DEG_TO_RAD * expected.lam - got.lam, DEG_TO_RAD * expected.phi - got.phi ) > tolerance) return 1; return 0; -- cgit v1.2.3 From 240b3cdd740630be906a99c1325f8aa7d3c91b71 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Tue, 12 Apr 2016 23:14:02 +0200 Subject: refactoring + added selftest for 7 more more projections euler, murd1, murd2, murd3, pconic, tissot, vitk1 (7 projections in one file - PJ_sconics.c) --- src/PJ_aea.c | 7 - src/PJ_sconics.c | 827 +++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 684 insertions(+), 150 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 7a507460..bd6c90ac 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -370,7 +370,6 @@ int pj_eck5_selftest (void) {return 10000;} int pj_eck6_selftest (void) {return 10000;} int pj_eqc_selftest (void) {return 10000;} int pj_eqdc_selftest (void) {return 10000;} -int pj_euler_selftest (void) {return 10000;} int pj_etmerc_selftest (void) {return 10000;} int pj_fahey_selftest (void) {return 10000;} int pj_fouc_selftest (void) {return 10000;} @@ -419,9 +418,6 @@ int pj_mil_os_selftest (void) {return 10000;} int pj_mill_selftest (void) {return 10000;} int pj_misrsom_selftest (void) {return 10000;} int pj_moll_selftest (void) {return 10000;} -int pj_murd1_selftest (void) {return 10000;} -int pj_murd2_selftest (void) {return 10000;} -int pj_murd3_selftest (void) {return 10000;} int pj_natearth_selftest (void) {return 10000;} int pj_natearth2_selftest (void) {return 10000;} int pj_nell_selftest (void) {return 10000;} @@ -435,7 +431,6 @@ int pj_oea_selftest (void) {return 10000;} int pj_omerc_selftest (void) {return 10000;} int pj_ortho_selftest (void) {return 10000;} int pj_patterson_selftest (void) {return 10000;} -int pj_pconic_selftest (void) {return 10000;} int pj_poly_selftest (void) {return 10000;} int pj_putp1_selftest (void) {return 10000;} int pj_putp2_selftest (void) {return 10000;} @@ -457,7 +452,6 @@ int pj_somerc_selftest (void) {return 10000;} int pj_stere_selftest (void) {return 10000;} int pj_sterea_selftest (void) {return 10000;} int pj_gstmerc_selftest (void) {return 10000;} -int pj_tissot_selftest (void) {return 10000;} int pj_tpers_selftest (void) {return 10000;} int pj_ups_selftest (void) {return 10000;} int pj_utm_selftest (void) {return 10000;} @@ -465,7 +459,6 @@ int pj_vandg_selftest (void) {return 10000;} int pj_vandg2_selftest (void) {return 10000;} int pj_vandg3_selftest (void) {return 10000;} int pj_vandg4_selftest (void) {return 10000;} -int pj_vitk1_selftest (void) {return 10000;} int pj_wag4_selftest (void) {return 10000;} int pj_wag5_selftest (void) {return 10000;} int pj_wag6_selftest (void) {return 10000;} diff --git a/src/PJ_sconics.c b/src/PJ_sconics.c index 8c17533d..2bf2213b 100644 --- a/src/PJ_sconics.c +++ b/src/PJ_sconics.c @@ -1,12 +1,17 @@ -#define PROJ_PARMS__ \ - double n; \ - double rho_c; \ - double rho_0; \ - double sig; \ - double c1, c2; \ - int type; #define PJ_LIB__ -#include +#include + + +struct pj_opaque { + double n; + double rho_c; + double rho_0; + double sig; + double c1, c2; + int type; +}; + + #define EULER 0 #define MURD1 1 #define MURD2 2 @@ -14,141 +19,677 @@ #define PCONIC 4 #define TISSOT 5 #define VITK1 6 -#define EPS10 1.e-10 +#define EPS10 1.e-10 #define EPS 1e-10 #define LINE2 "\n\tConic, Sph\n\tlat_1= and lat_2=" -PROJ_HEAD(tissot, "Tissot") - LINE2; -PROJ_HEAD(murd1, "Murdoch I") - LINE2; -PROJ_HEAD(murd2, "Murdoch II") - LINE2; -PROJ_HEAD(murd3, "Murdoch III") - LINE2; -PROJ_HEAD(euler, "Euler") - LINE2; -PROJ_HEAD(pconic, "Perspective Conic") - LINE2; -PROJ_HEAD(vitk1, "Vitkovsky I") - LINE2; + +PROJ_HEAD(euler, "Euler") LINE2; +PROJ_HEAD(murd1, "Murdoch I") LINE2; +PROJ_HEAD(murd2, "Murdoch II") LINE2; +PROJ_HEAD(murd3, "Murdoch III") LINE2; +PROJ_HEAD(pconic, "Perspective Conic") LINE2; +PROJ_HEAD(tissot, "Tissot") LINE2; +PROJ_HEAD(vitk1, "Vitkovsky I") LINE2; + + + /* get common factors for simple conics */ - static int -phi12(PJ *P, double *del) { - double p1, p2; - int err = 0; - - if (!pj_param(P->ctx, P->params, "tlat_1").i || - !pj_param(P->ctx, P->params, "tlat_2").i) { - err = -41; - } else { - p1 = pj_param(P->ctx, P->params, "rlat_1").f; - p2 = pj_param(P->ctx, P->params, "rlat_2").f; - *del = 0.5 * (p2 - p1); - P->sig = 0.5 * (p2 + p1); - err = (fabs(*del) < EPS || fabs(P->sig) < EPS) ? -42 : 0; - *del = *del; - } - return err; -} -FORWARD(s_forward); /* spheroid */ - double rho; - - switch (P->type) { - case MURD2: - rho = P->rho_c + tan(P->sig - lp.phi); - break; - case PCONIC: - rho = P->c2 * (P->c1 - tan(lp.phi - P->sig)); - break; - default: - rho = P->rho_c - lp.phi; - break; - } - xy.x = rho * sin( lp.lam *= P->n ); - xy.y = P->rho_0 - rho * cos(lp.lam); - return (xy); -} -INVERSE(s_inverse); /* ellipsoid & spheroid */ - double rho; - - rho = hypot(xy.x, xy.y = P->rho_0 - xy.y); - if (P->n < 0.) { - rho = - rho; - xy.x = - xy.x; - xy.y = - xy.y; - } - lp.lam = atan2(xy.x, xy.y) / P->n; - switch (P->type) { - case PCONIC: - lp.phi = atan(P->c1 - rho / P->c2) + P->sig; - break; - case MURD2: - lp.phi = P->sig - atan(rho - P->rho_c); - break; - default: - lp.phi = P->rho_c - rho; - } - return (lp); -} -FREEUP; if (P) pj_dalloc(P); } - static PJ * -setup(PJ *P) { - double del, cs; - int i; - - if( (i = phi12(P, &del)) ) - E_ERROR(i); - switch (P->type) { - case TISSOT: - P->n = sin(P->sig); - cs = cos(del); - P->rho_c = P->n / cs + cs / P->n; - P->rho_0 = sqrt((P->rho_c - 2 * sin(P->phi0))/P->n); - break; - case MURD1: - P->rho_c = sin(del)/(del * tan(P->sig)) + P->sig; - P->rho_0 = P->rho_c - P->phi0; - P->n = sin(P->sig); - break; - case MURD2: - P->rho_c = (cs = sqrt(cos(del))) / tan(P->sig); - P->rho_0 = P->rho_c + tan(P->sig - P->phi0); - P->n = sin(P->sig) * cs; - break; - case MURD3: - P->rho_c = del / (tan(P->sig) * tan(del)) + P->sig; - P->rho_0 = P->rho_c - P->phi0; - P->n = sin(P->sig) * sin(del) * tan(del) / (del * del); - break; - case EULER: - P->n = sin(P->sig) * sin(del) / del; - del *= 0.5; - P->rho_c = del / (tan(del) * tan(P->sig)) + P->sig; - P->rho_0 = P->rho_c - P->phi0; - break; - case PCONIC: - P->n = sin(P->sig); - P->c2 = cos(del); - P->c1 = 1./tan(P->sig); - if (fabs(del = P->phi0 - P->sig) - EPS10 >= HALFPI) - E_ERROR(-43); - P->rho_0 = P->c2 * (P->c1 - tan(del)); - break; - case VITK1: - P->n = (cs = tan(del)) * sin(P->sig) / del; - P->rho_c = del / (cs * tan(P->sig)) + P->sig; - P->rho_0 = P->rho_c - P->phi0; - break; - } - P->inv = s_inverse; - P->fwd = s_forward; - P->es = 0; - return (P); -} -ENTRY0(euler) P->type = EULER; ENDENTRY(setup(P)) -ENTRY0(tissot) P->type = TISSOT; ENDENTRY(setup(P)) -ENTRY0(murd1) P->type = MURD1; ENDENTRY(setup(P)) -ENTRY0(murd2) P->type = MURD2; ENDENTRY(setup(P)) -ENTRY0(murd3) P->type = MURD3; ENDENTRY(setup(P)) -ENTRY0(pconic) P->type = PCONIC; ENDENTRY(setup(P)) -ENTRY0(vitk1) P->type = VITK1; ENDENTRY(setup(P)) +static int phi12(PJ *P, double *del) { + double p1, p2; + int err = 0; + + if (!pj_param(P->ctx, P->params, "tlat_1").i || + !pj_param(P->ctx, P->params, "tlat_2").i) { + err = -41; + } else { + p1 = pj_param(P->ctx, P->params, "rlat_1").f; + p2 = pj_param(P->ctx, P->params, "rlat_2").f; + *del = 0.5 * (p2 - p1); + P->opaque->sig = 0.5 * (p2 + p1); + err = (fabs(*del) < EPS || fabs(P->opaque->sig) < EPS) ? -42 : 0; + *del = *del; + } + return err; +} + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0, 0.0}; + struct pj_opaque *Q = P->opaque; + double rho; + + switch (Q->type) { + case MURD2: + rho = Q->rho_c + tan (Q->sig - lp.phi); + break; + case PCONIC: + rho = Q->c2 * (Q->c1 - tan (lp.phi - Q->sig)); + break; + default: + rho = Q->rho_c - lp.phi; + break; + } + + xy.x = rho * sin ( lp.lam *= Q->n ); + xy.y = Q->rho_0 - rho * cos (lp.lam); + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, (and ellipsoidal?) inverse */ + LP lp = {0.0, 0.0}; + struct pj_opaque *Q = P->opaque; + double rho; + + rho = hypot (xy.x, xy.y = Q->rho_0 - xy.y); + if (Q->n < 0.) { + rho = - rho; + xy.x = - xy.x; + xy.y = - xy.y; + } + + lp.lam = atan2 (xy.x, xy.y) / Q->n; + + switch (Q->type) { + case PCONIC: + lp.phi = atan (Q->c1 - rho / Q->c2) + Q->sig; + break; + case MURD2: + lp.phi = Q->sig - atan(rho - Q->rho_c); + break; + default: + lp.phi = Q->rho_c - rho; + } + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +static PJ *setup(PJ *P, int type) { + double del, cs; + int i; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + Q->type = type; + + i = phi12 (P, &del); + if(i) + E_ERROR(i); + switch (Q->type) { + + case TISSOT: + Q->n = sin (Q->sig); + cs = cos (del); + Q->rho_c = Q->n / cs + cs / Q->n; + Q->rho_0 = sqrt ((Q->rho_c - 2 * sin (P->phi0)) / Q->n); + break; + + case MURD1: + Q->rho_c = sin(del)/(del * tan(Q->sig)) + Q->sig; + Q->rho_0 = Q->rho_c - P->phi0; + Q->n = sin(Q->sig); + break; + + case MURD2: + Q->rho_c = (cs = sqrt (cos (del))) / tan (Q->sig); + Q->rho_0 = Q->rho_c + tan (Q->sig - P->phi0); + Q->n = sin (Q->sig) * cs; + break; + + case MURD3: + Q->rho_c = del / (tan(Q->sig) * tan(del)) + Q->sig; + Q->rho_0 = Q->rho_c - P->phi0; + Q->n = sin (Q->sig) * sin (del) * tan (del) / (del * del); + break; + + case EULER: + Q->n = sin (Q->sig) * sin (del) / del; + del *= 0.5; + Q->rho_c = del / (tan (del) * tan (Q->sig)) + Q->sig; + Q->rho_0 = Q->rho_c - P->phi0; + break; + + case PCONIC: + Q->n = sin (Q->sig); + Q->c2 = cos (del); + Q->c1 = 1./tan (Q->sig); + if (fabs (del = P->phi0 - Q->sig) - EPS10 >= HALFPI) + E_ERROR(-43); + Q->rho_0 = Q->c2 * (Q->c1 - tan (del)); + break; + + case VITK1: + Q->n = (cs = tan (del)) * sin (Q->sig) / del; + Q->rho_c = del / (cs * tan (Q->sig)) + Q->sig; + Q->rho_0 = Q->rho_c - P->phi0; + break; + } + + P->inv = s_inverse; + P->fwd = s_forward; + P->es = 0; + return (P); +} + + +PJ *PROJECTION(euler) { + return setup(P, EULER); +} + + +PJ *PROJECTION(tissot) { + return setup(P, TISSOT); +} + + +PJ *PROJECTION(murd1) { + return setup(P, MURD1); +} + + +PJ *PROJECTION(murd2) { + return setup(P, MURD2); +} + + +PJ *PROJECTION(murd3) { + return setup(P, MURD3); +} + + +PJ *PROJECTION(pconic) { + return setup(P, PCONIC); +} + + +PJ *PROJECTION(vitk1) { + return setup(P, VITK1); +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_euler_selftest (void) {return 0;} +#else + +int pj_euler_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=euler +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=euler +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {222597.63465910763, 111404.24054991946}, + {222767.16563187627, -111234.6764910177}, + {-222597.63465910763, 111404.24054991946}, + {-222767.16563187627, -111234.6764910177}, + }; + + XY s_fwd_expect[] = { + {223360.65559869423, 111786.11238979101}, + {223530.76769031584, -111615.96709862351}, + {-223360.65559869423, 111786.11238979101}, + {-223530.76769031584, -111615.96709862351}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0017962807023075235, 0.0008983146697688839}, + {0.0017962794738334226, -0.00089831589842987965}, + {-0.0017962807023075235, 0.0008983146697688839}, + {-0.0017962794738334226, -0.00089831589842987965}, + }; + + LP s_inv_expect[] = { + {0.0017901444369360026, 0.00089524594522202015}, + {0.001790143216840731, -0.00089524716533368484}, + {-0.0017901444369360026, 0.00089524594522202015}, + {-0.001790143216840731, -0.00089524716533368484}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif + + + + + + +#ifdef PJ_OMIT_SELFTEST +int pj_murd1_selftest (void) {return 0;} +#else + +int pj_murd1_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=murd1 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=murd1 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {222600.81347355421, 111404.24418054636}, + {222770.3492878644, -111234.6728566746}, + {-222600.81347355421, 111404.24418054636}, + {-222770.3492878644, -111234.6728566746}, + }; + + XY s_fwd_expect[] = { + {223363.84530949194, 111786.11603286299}, + {223533.96225925098, -111615.96345182261}, + {-223363.84530949194, 111786.11603286299}, + {-223533.96225925098, -111615.96345182261}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0017962550410516366, 0.0008983146697688839}, + {0.0017962538125775522, -0.00089831589842987965}, + {-0.0017962550410516366, 0.0008983146697688839}, + {-0.0017962538125775522, -0.00089831589842987965}, + }; + + LP s_inv_expect[] = { + {0.0017901188633413715, 0.00089524594522202015}, + {0.0017901176432461162, -0.00089524716492657387}, + {-0.0017901188633413715, 0.00089524594522202015}, + {-0.0017901176432461162, -0.00089524716492657387}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif + + + + + + + + + + + + + + +#ifdef PJ_OMIT_SELFTEST +int pj_murd2_selftest (void) {return 0;} +#else + +int pj_murd2_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=murd2 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=murd2 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {222588.09975123021, 111426.14002741246}, + {222757.72626701824, -111341.43131750476}, + {-222588.09975123021, 111426.14002741246}, + {-222757.72626701824, -111341.43131750476}, + }; + + XY s_fwd_expect[] = { + {223351.08800702673, 111808.08693438848}, + {223521.2959691704, -111723.08785967289}, + {-223351.08800702673, 111808.08693438848}, + {-223521.2959691704, -111723.08785967289}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0017963574947305447, 0.00089788747830845382}, + {0.0017963562661689487, -0.00089788809264252983}, + {-0.0017963574947305447, 0.00089788747830845382}, + {-0.0017963562661689487, -0.00089788809264252983}, + }; + + LP s_inv_expect[] = { + {0.0017902209670287586, 0.00089482021163422854}, + {0.0017902197468465887, -0.00089482082161134206}, + {-0.0017902209670287586, 0.00089482021163422854}, + {-0.0017902197468465887, -0.00089482082161134206}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif + + + + + + + + + + +#ifdef PJ_OMIT_SELFTEST +int pj_murd3_selftest (void) {return 0;} +#else + +int pj_murd3_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=murd3 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=murd3 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {222600.81407757697, 111404.24660137216}, + {222770.35473389886, -111234.67043217793}, + {-222600.81407757697, 111404.24660137216}, + {-222770.35473389886, -111234.67043217793}, + }; + + XY s_fwd_expect[] = { + {223363.84591558515, 111786.11846198692}, + {223533.96772395336, -111615.96101901523}, + {-223363.84591558515, 111786.11846198692}, + {-223533.96772395336, -111615.96101901523}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0017962550166583809, 0.0008983146697688839}, + {0.0017962537881492445, -0.00089831589842987965}, + {-0.0017962550166583809, 0.0008983146697688839}, + {-0.0017962537881492445, -0.00089831589842987965}, + }; + + LP s_inv_expect[] = { + {0.0017901188390313859, 0.00089524594522202015}, + {0.0017901176189013177, -0.00089524716533368484}, + {-0.0017901188390313859, 0.00089524594522202015}, + {-0.0017901176189013177, -0.00089524716533368484}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif + + + + + + + + + + + +#ifdef PJ_OMIT_SELFTEST +int pj_pconic_selftest (void) {return 0;} +#else + +int pj_pconic_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=pconic +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=pconic +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {222588.09884161691, 111416.60477006658}, + {222757.71809109033, -111331.88153107995}, + {-222588.09884161691, 111416.60477006658}, + {-222757.71809109033, -111331.88153107995}, + }; + + XY s_fwd_expect[] = { + {223351.08709429545, 111798.5189920546}, + {223521.28776521701, -111713.50533845725}, + {-223351.08709429545, 111798.5189920546}, + {-223521.28776521701, -111713.50533845725}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0017963575313784969, 0.0008979644089172499}, + {0.0017963563027642206, -0.00089796502355327969}, + {-0.0017963575313784969, 0.0008979644089172499}, + {-0.0017963563027642206, -0.00089796502355327969}, + }; + + LP s_inv_expect[] = { + {0.0017902210035514285, 0.0008948968793741558}, + {0.0017902197833169374, -0.00089489748965381963}, + {-0.0017902210035514285, 0.0008948968793741558}, + {-0.0017902197833169374, -0.00089489748965381963}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif + + + + + + + + + + + + + + + +#ifdef PJ_OMIT_SELFTEST +int pj_tissot_selftest (void) {return 0;} +#else + +int pj_tissot_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=tissot +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=tissot +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {222641.07869963095, 54347.828487281469}, + {222810.61451394114, -168291.08854993948}, + {-222641.07869963095, 54347.828487281469}, + {-222810.61451394114, -168291.08854993948}, + }; + + XY s_fwd_expect[] = { + {223404.24855684943, 54534.122161157939}, + {223574.36550660848, -168867.95732352766}, + {-223404.24855684943, 54534.122161157939}, + {-223574.36550660848, -168867.95732352766}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0017962807107425871, 0.51344495513064536}, + {0.0017962794822333915, 0.51164832456244658}, + {-0.0017962807107425871, 0.51344495513064536}, + {-0.0017962794822333915, 0.51164832456244658}, + }; + + LP s_inv_expect[] = { + {0.0017901444453421915, 0.51344188640609856}, + {0.001790143225212064, 0.51165139329554277}, + {-0.0017901444453421915, 0.51344188640609856}, + {-0.001790143225212064, 0.51165139329554277}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif + + + + + + + + +#ifdef PJ_OMIT_SELFTEST +int pj_vitk1_selftest (void) {return 0;} +#else + +int pj_vitk1_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=vitk1 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=vitk1 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {222607.17121145778, 111404.25144243463}, + {222776.71670959776, -111234.66558744459}, + {-222607.17121145778, 111404.25144243463}, + {-222776.71670959776, -111234.66558744459}, + }; + + XY s_fwd_expect[] = { + {223370.22484047143, 111786.12331964359}, + {223540.3515072545, -111615.9561576751}, + {-223370.22484047143, 111786.12331964359}, + {-223540.3515072545, -111615.9561576751}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0017962037198570686, 0.0008983146697688839}, + {0.0017962024913830157, -0.00089831589842987965}, + {-0.0017962037198570686, 0.0008983146697688839}, + {-0.0017962024913830157, -0.00089831589842987965}, + }; + + LP s_inv_expect[] = { + {0.0017900677174648159, 0.00089524594522202015}, + {0.0017900664973695916, -0.00089524716533368484}, + {-0.0017900677174648159, 0.00089524594522202015}, + {-0.0017900664973695916, -0.00089524716533368484}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 2f5893fa96213d5ef77328471918d2bd25645a9c Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Tue, 12 Apr 2016 23:24:43 +0200 Subject: Reverting isnan check since MSVC needs a NaNny MSVC, in some versions has _isnan(), rather than isnan()... but why? --- src/pj_generic_selftest.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/pj_generic_selftest.c b/src/pj_generic_selftest.c index 2af3f3b9..88b5c308 100644 --- a/src/pj_generic_selftest.c +++ b/src/pj_generic_selftest.c @@ -150,10 +150,10 @@ static int deviates_xy (XY expected, XY got, double tolerance) { only by forcing expected and actual ("got") coordinates to 0. ***********************************************************************/ - if ((HUGE_VAL== expected.x) || (isnan (expected.x))) - expected.x = got.x = 0; - if ((HUGE_VAL== expected.y) || (isnan (expected.y))) - expected.y = got.y = 0; + if (HUGE_VAL== expected.x) + return 0; + if (HUGE_VAL== expected.y) + return 0; if (hypot ( expected.x - got.x, expected.y - got.y ) > tolerance) return 1; return 0; @@ -173,10 +173,10 @@ static int deviates_lp (LP expected, LP got, double tolerance) { output from pj_inv) ***********************************************************************/ - if ((HUGE_VAL== expected.lam) || (isnan (expected.lam))) - expected.lam = got.lam = 0; - if ((HUGE_VAL== expected.phi) || (isnan (expected.phi))) - expected.phi = got.phi = 0; + if (HUGE_VAL== expected.lam) + return 0; + if (HUGE_VAL== expected.phi) + return 0; if (hypot ( DEG_TO_RAD * expected.lam - got.lam, DEG_TO_RAD * expected.phi - got.phi ) > tolerance) return 1; return 0; -- cgit v1.2.3 From b62b21c363e436b8260279623cd2e4ebf7faccdf Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 13 Apr 2016 21:31:57 +0200 Subject: Converted Cylindrical Equal Area (cea) projection --- src/PJ_aea.c | 1 - src/PJ_cea.c | 218 ++++++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 157 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index bd6c90ac..2e441beb 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -356,7 +356,6 @@ source files int pj_aeqd_selftest (void) {return 10000;} int pj_alsk_selftest (void) {return 10000;} -int pj_cea_selftest (void) {return 10000;} int pj_chamb_selftest (void) {return 10000;} int pj_collg_selftest (void) {return 10000;} int pj_comill_selftest (void) {return 10000;} diff --git a/src/PJ_cea.c b/src/PJ_cea.c index 44c0a887..f4ff21f3 100644 --- a/src/PJ_cea.c +++ b/src/PJ_cea.c @@ -1,63 +1,159 @@ -#define PROJ_PARMS__ \ - double qp; \ - double *apa; #define PJ_LIB__ -# include +#include + +struct pj_opaque { + double qp; + double *apa; +}; + PROJ_HEAD(cea, "Equal Area Cylindrical") "\n\tCyl, Sph&Ell\n\tlat_ts="; -# define EPS 1e-10 -FORWARD(e_forward); /* spheroid */ - xy.x = P->k0 * lp.lam; - xy.y = .5 * pj_qsfn(sin(lp.phi), P->e, P->one_es) / P->k0; - return (xy); -} -FORWARD(s_forward); /* spheroid */ - xy.x = P->k0 * lp.lam; - xy.y = sin(lp.phi) / P->k0; - return (xy); -} -INVERSE(e_inverse); /* spheroid */ - lp.phi = pj_authlat(asin( 2. * xy.y * P->k0 / P->qp), P->apa); - lp.lam = xy.x / P->k0; - return (lp); -} -INVERSE(s_inverse); /* spheroid */ - double t; - - if ((t = fabs(xy.y *= P->k0)) - EPS <= 1.) { - if (t >= 1.) - lp.phi = xy.y < 0. ? -HALFPI : HALFPI; - else - lp.phi = asin(xy.y); - lp.lam = xy.x / P->k0; - } else I_ERROR; - return (lp); -} -FREEUP; - if (P) { - if (P->apa) - pj_dalloc(P->apa); - pj_dalloc(P); - } -} -ENTRY1(cea, apa) - double t = 0.0; - - if (pj_param(P->ctx, P->params, "tlat_ts").i) { - P->k0 = cos(t = pj_param(P->ctx, P->params, "rlat_ts").f); - if (P->k0 < 0.) { - E_ERROR(-24); - } - } - if (P->es) { - t = sin(t); - P->k0 /= sqrt(1. - P->es * t * t); - P->e = sqrt(P->es); - if (!(P->apa = pj_authset(P->es))) E_ERROR_0; - P->qp = pj_qsfn(1., P->e, P->one_es); - P->inv = e_inverse; - P->fwd = e_forward; - } else { - P->inv = s_inverse; - P->fwd = s_forward; - } -ENDENTRY(P) +# define EPS 1e-10 + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + xy.x = P->k0 * lp.lam; + xy.y = 0.5 * pj_qsfn(sin(lp.phi), P->e, P->one_es) / P->k0; + return xy; +} + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + xy.x = P->k0 * lp.lam; + xy.y = sin(lp.phi) / P->k0; + return xy; +} + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + lp.phi = pj_authlat(asin( 2. * xy.y * P->k0 / Q->qp), Q->apa); + lp.lam = xy.x / P->k0; + return lp; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + double t; + + if ((t = fabs(xy.y *= P->k0)) - EPS <= 1.) { + if (t >= 1.) + lp.phi = xy.y < 0. ? -HALFPI : HALFPI; + else + lp.phi = asin(xy.y); + lp.lam = xy.x / P->k0; + } else I_ERROR; + return (lp); +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dalloc (P->opaque->apa); + pj_dealloc (P->opaque); + return pj_dealloc (P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + +PJ *PROJECTION(cea) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_cea; + double t = 0.0; + + if (pj_param(P->ctx, P->params, "tlat_ts").i) { + P->k0 = cos(t = pj_param(P->ctx, P->params, "rlat_ts").f); + if (P->k0 < 0.) { + E_ERROR(-24); + } + } + if (P->es) { + t = sin(t); + P->k0 /= sqrt(1. - P->es * t * t); + P->e = sqrt(P->es); + if (!(Q->apa = pj_authset(P->es))) E_ERROR_0; + Q->qp = pj_qsfn(1., P->e, P->one_es); + P->inv = e_inverse; + P->fwd = e_forward; + } else { + P->inv = s_inverse; + P->fwd = s_forward; + } + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_cea_selftest (void) {return 0;} +#else + +int pj_cea_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=cea +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=cea +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {222638.981586547132, 110568.812396267356}, + {222638.981586547132, -110568.812396265886}, + {-222638.981586547132, 110568.812396267356}, + {-222638.981586547132, -110568.812396265886}, + }; + + XY s_fwd_expect[] = { + {223402.144255274179, 111695.401198614476}, + {223402.144255274179, -111695.401198614476}, + {-223402.144255274179, 111695.401198614476}, + {-223402.144255274179, -111695.401198614476}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.00179663056823904264, 0.000904369476105564289}, + {0.00179663056823904264, -0.000904369476105564289}, + {-0.00179663056823904264, 0.000904369476105564289}, + {-0.00179663056823904264, -0.000904369476105564289}, + }; + + LP s_inv_expect[] = { + {0.00179049310978382265, 0.000895246554928338998}, + {0.00179049310978382265, -0.000895246554928338998}, + {-0.00179049310978382265, 0.000895246554928338998}, + {-0.00179049310978382265, -0.000895246554928338998}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From a98e366f1e91202d576cecb2015dfa8db6a42bc3 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 13 Apr 2016 21:56:03 +0200 Subject: Converted Collignon projection --- src/PJ_aea.c | 1 - src/PJ_collg.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 72 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 2e441beb..52510360 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -357,7 +357,6 @@ int pj_aeqd_selftest (void) {return 10000;} int pj_alsk_selftest (void) {return 10000;} int pj_chamb_selftest (void) {return 10000;} -int pj_collg_selftest (void) {return 10000;} int pj_comill_selftest (void) {return 10000;} int pj_crast_selftest (void) {return 10000;} int pj_denoy_selftest (void) {return 10000;} diff --git a/src/PJ_collg.c b/src/PJ_collg.c index 871dfc97..80029a3a 100644 --- a/src/PJ_collg.c +++ b/src/PJ_collg.c @@ -1,10 +1,14 @@ #define PJ_LIB__ # include + PROJ_HEAD(collg, "Collignon") "\n\tPCyl, Sph."; #define FXC 1.12837916709551257390 #define FYC 1.77245385090551602729 #define ONEEPS 1.0000001 -FORWARD(s_forward); /* spheroid */ + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; (void) P; if ((xy.y = 1. - sin(lp.phi)) <= 0.) xy.y = 0.; @@ -14,7 +18,10 @@ FORWARD(s_forward); /* spheroid */ xy.y = FYC * (1. - xy.y); return (xy); } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; lp.phi = xy.y / FYC - 1.; if (fabs(lp.phi = 1. - lp.phi * lp.phi) < 1.) lp.phi = asin(lp.phi); @@ -26,5 +33,66 @@ INVERSE(s_inverse); /* spheroid */ lp.lam = xy.x / (FXC * sqrt(lp.lam)); return (lp); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(collg) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(collg) { + P->es = 0.0; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_collg_selftest (void) {return 0;} +#else + +int pj_collg_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=collg +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {249872.921577929839, 99423.1747884602082}, + {254272.532301245432, -98559.3077607425657}, + {-249872.921577929839, 99423.1747884602082}, + {-254272.532301245432, -98559.3077607425657}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + {0.00158679719207879865, 0.00101017310941749921}, + {0.001586769215623956, -0.00101018201458258111}, + {-0.00158679719207879865, 0.00101017310941749921}, + {-0.001586769215623956, -0.00101018201458258111}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 613baf982c3d14ab4ebce2e754043f193f0c56fa Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 13 Apr 2016 22:54:36 +0200 Subject: Converted Compact Miller projection --- src/PJ_aea.c | 1 - src/PJ_comill.c | 133 +++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 102 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 52510360..65b001b4 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -357,7 +357,6 @@ int pj_aeqd_selftest (void) {return 10000;} int pj_alsk_selftest (void) {return 10000;} int pj_chamb_selftest (void) {return 10000;} -int pj_comill_selftest (void) {return 10000;} int pj_crast_selftest (void) {return 10000;} int pj_denoy_selftest (void) {return 10000;} int pj_eck1_selftest (void) {return 10000;} diff --git a/src/PJ_comill.c b/src/PJ_comill.c index ad9914d4..f84f4eb0 100644 --- a/src/PJ_comill.c +++ b/src/PJ_comill.c @@ -1,13 +1,14 @@ /* -The Compact Miller projection was designed by Tom Patterson, US National -Park Service, in 2014. The polynomial equation was developed by Bojan -Savric and Bernhard Jenny, College of Earth, Ocean, and Atmospheric +The Compact Miller projection was designed by Tom Patterson, US National +Park Service, in 2014. The polynomial equation was developed by Bojan +Savric and Bernhard Jenny, College of Earth, Ocean, and Atmospheric Sciences, Oregon State University. Port to PROJ.4 by Bojan Savric, 4 April 2016 */ #define PJ_LIB__ -#include +#include + PROJ_HEAD(comill, "Compact Miller") "\n\tCyl., Sph."; #define K1 0.9902 @@ -19,41 +20,111 @@ PROJ_HEAD(comill, "Compact Miller") "\n\tCyl., Sph."; #define EPS 1e-11 #define MAX_Y (0.6000207669862655 * PI) -FORWARD(s_forward); /* spheroid */ - double lat_sq; - lat_sq = lp.phi * lp.phi; - xy.x = lp.lam; - xy.y = lp.phi * (K1 + lat_sq * (K2 + K3 * lat_sq)); - return (xy); +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + double lat_sq; + + lat_sq = lp.phi * lp.phi; + xy.x = lp.lam; + xy.y = lp.phi * (K1 + lat_sq * (K2 + K3 * lat_sq)); + return xy; } -INVERSE(s_inverse); /* spheroid */ - double yc, tol, y2, y4, f, fder; + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + double yc, tol, y2, y4, f, fder; /* make sure y is inside valid range */ - if (xy.y > MAX_Y) { - xy.y = MAX_Y; - } else if (xy.y < -MAX_Y) { - xy.y = -MAX_Y; - } + if (xy.y > MAX_Y) { + xy.y = MAX_Y; + } else if (xy.y < -MAX_Y) { + xy.y = -MAX_Y; + } /* latitude */ - yc = xy.y; + yc = xy.y; for (;;) { /* Newton-Raphson */ - y2 = yc * yc; - f = (yc * (K1 + y2 * (K2 + K3 * y2))) - xy.y; - fder = C1 + y2 * (C2 + C3 * y2); - yc -= tol = f / fder; - if (fabs(tol) < EPS) { - break; - } - } - lp.phi = yc; + y2 = yc * yc; + f = (yc * (K1 + y2 * (K2 + K3 * y2))) - xy.y; + fder = C1 + y2 * (C2 + C3 * y2); + yc -= tol = f / fder; + if (fabs(tol) < EPS) { + break; + } + } + lp.phi = yc; /* longitude */ - lp.lam = xy.x; + lp.lam = xy.x; + + return lp; +} + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(comill) { + P->es = 0; + + P->inv = s_inverse; + P->fwd = s_forward; - return (lp); + P->pfree = freeup; + P->descr = des_comill; + + return P; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(comill) P->es = 0; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +#ifdef PJ_OMIT_SELFTEST +int pj_comill_selftest (void) {return 0;} +#else + +int pj_comill_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=comill +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {223402.144255274179, 110611.859089458536}, + {223402.144255274179, -110611.859089458536}, + {-223402.144255274179, 110611.859089458536}, + {-223402.144255274179, -110611.859089458536}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + {0.00179049310978382265, 0.000904106801510605831}, + {0.00179049310978382265, -0.000904106801510605831}, + {-0.00179049310978382265, 0.000904106801510605831}, + {-0.00179049310978382265, -0.000904106801510605831}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 9f0c963ffff90f7d62b5e25dea3db4e3f1cbd897 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 13 Apr 2016 23:05:00 +0200 Subject: Converted Craster Parabolic (Putnins P4) projection --- src/PJ_aea.c | 1 - src/PJ_crast.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 82 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 65b001b4..2cbb4cc3 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -357,7 +357,6 @@ int pj_aeqd_selftest (void) {return 10000;} int pj_alsk_selftest (void) {return 10000;} int pj_chamb_selftest (void) {return 10000;} -int pj_crast_selftest (void) {return 10000;} int pj_denoy_selftest (void) {return 10000;} int pj_eck1_selftest (void) {return 10000;} int pj_eck2_selftest (void) {return 10000;} diff --git a/src/PJ_crast.c b/src/PJ_crast.c index 3f251ac6..9a896459 100644 --- a/src/PJ_crast.c +++ b/src/PJ_crast.c @@ -1,24 +1,98 @@ #define PJ_LIB__ # include -PROJ_HEAD(crast, "Craster Parabolic (Putnins P4)") -"\n\tPCyl., Sph."; + +PROJ_HEAD(crast, "Craster Parabolic (Putnins P4)") "\n\tPCyl., Sph."; + #define XM 0.97720502380583984317 #define RXM 1.02332670794648848847 #define YM 3.06998012383946546542 #define RYM 0.32573500793527994772 #define THIRD 0.333333333333333333 -FORWARD(s_forward); /* spheroid */ + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; (void) P; lp.phi *= THIRD; xy.x = XM * lp.lam * (2. * cos(lp.phi + lp.phi) - 1.); xy.y = YM * sin(lp.phi); - return (xy); + return xy; } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; (void) P; lp.phi = 3. * asin(xy.y * RYM); lp.lam = xy.x * RXM / (2. * cos((lp.phi + lp.phi) * THIRD) - 1); - return (lp); + return lp; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(crast) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(crast) { + P->es = 0.0; + P->inv = s_inverse; + P->fwd = s_forward; + + P->pfree = freeup; + P->descr = des_crast; + + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_crast_selftest (void) {return 0;} +#else + +int pj_crast_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=crast +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=crast +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + + XY s_fwd_expect[] = { + {218280.142056780722, 114306.045604279774}, + {218280.142056780722, -114306.045604279774}, + {-218280.142056780722, 114306.045604279774}, + {-218280.142056780722, -114306.045604279774}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + {0.00183225941982580187, 0.00087483943098902331}, + {0.00183225941982580187, -0.00087483943098902331}, + {-0.00183225941982580187, 0.00087483943098902331}, + {-0.00183225941982580187, -0.00087483943098902331}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From ba4406f472fae0ca22d79a6fb75e2720c5a7a776 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 13 Apr 2016 23:26:29 +0200 Subject: Converted Chamberlin Trimetric (chamb) projection --- src/PJ_aea.c | 2 - src/PJ_chamb.c | 277 +++++++++++++++++++++++++++++++++++---------------------- 2 files changed, 173 insertions(+), 106 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 2cbb4cc3..0822efd6 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -355,8 +355,6 @@ source files int pj_aeqd_selftest (void) {return 10000;} int pj_alsk_selftest (void) {return 10000;} - -int pj_chamb_selftest (void) {return 10000;} int pj_denoy_selftest (void) {return 10000;} int pj_eck1_selftest (void) {return 10000;} int pj_eck2_selftest (void) {return 10000;} diff --git a/src/PJ_chamb.c b/src/PJ_chamb.c index 65f21129..091408b7 100644 --- a/src/PJ_chamb.c +++ b/src/PJ_chamb.c @@ -1,112 +1,181 @@ -typedef struct { double r, Az; } VECT; -#define PROJ_PARMS__ \ - struct { /* control point data */ \ - double phi, lam; \ - double cosphi, sinphi; \ - VECT v; \ - XY p; \ - double Az; \ - } c[3]; \ - XY p; \ - double beta_0, beta_1, beta_2; #define PJ_LIB__ -#include +#include + +typedef struct { double r, Az; } VECT; +struct pj_opaque { + struct { /* control point data */ + double phi, lam; + double cosphi, sinphi; + VECT v; + XY p; + double Az; + } c[3]; + XY p; + double beta_0, beta_1, beta_2; +}; + PROJ_HEAD(chamb, "Chamberlin Trimetric") "\n\tMisc Sph, no inv." "\n\tlat_1= lon_1= lat_2= lon_2= lat_3= lon_3="; -#include + +#include #define THIRD 0.333333333333333333 #define TOL 1e-9 - static VECT /* distance and azimuth from point 1 to point 2 */ -vect(projCtx ctx, double dphi, double c1, double s1, double c2, double s2, double dlam) { - VECT v; - double cdl, dp, dl; - - cdl = cos(dlam); - if (fabs(dphi) > 1. || fabs(dlam) > 1.) - v.r = aacos(ctx, s1 * s2 + c1 * c2 * cdl); - else { /* more accurate for smaller distances */ - dp = sin(.5 * dphi); - dl = sin(.5 * dlam); - v.r = 2. * aasin(ctx,sqrt(dp * dp + c1 * c2 * dl * dl)); - } - if (fabs(v.r) > TOL) - v.Az = atan2(c2 * sin(dlam), c1 * s2 - s1 * c2 * cdl); - else - v.r = v.Az = 0.; - return v; + +/* distance and azimuth from point 1 to point 2 */ +static VECT vect(projCtx ctx, double dphi, double c1, double s1, double c2, double s2, double dlam) { + VECT v; + double cdl, dp, dl; + + cdl = cos(dlam); + if (fabs(dphi) > 1. || fabs(dlam) > 1.) + v.r = aacos(ctx, s1 * s2 + c1 * c2 * cdl); + else { /* more accurate for smaller distances */ + dp = sin(.5 * dphi); + dl = sin(.5 * dlam); + v.r = 2. * aasin(ctx,sqrt(dp * dp + c1 * c2 * dl * dl)); + } + if (fabs(v.r) > TOL) + v.Az = atan2(c2 * sin(dlam), c1 * s2 - s1 * c2 * cdl); + else + v.r = v.Az = 0.; + return v; +} + +/* law of cosines */ +static double lc(projCtx ctx, double b,double c,double a) { + return aacos(ctx, .5 * (b * b + c * c - a * a) / (b * c)); +} + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double sinphi, cosphi, a; + VECT v[3]; + int i, j; + + sinphi = sin(lp.phi); + cosphi = cos(lp.phi); + for (i = 0; i < 3; ++i) { /* dist/azimiths from control */ + v[i] = vect(P->ctx, lp.phi - Q->c[i].phi, Q->c[i].cosphi, Q->c[i].sinphi, + cosphi, sinphi, lp.lam - Q->c[i].lam); + if ( ! v[i].r) + break; + v[i].Az = adjlon(v[i].Az - Q->c[i].v.Az); + } + if (i < 3) /* current point at control point */ + xy = Q->c[i].p; + else { /* point mean of intersepts */ + xy = Q->p; + for (i = 0; i < 3; ++i) { + j = i == 2 ? 0 : i + 1; + a = lc(P->ctx,Q->c[i].v.r, v[i].r, v[j].r); + if (v[i].Az < 0.) + a = -a; + if (! i) { /* coord comp unique to each arc */ + xy.x += v[i].r * cos(a); + xy.y -= v[i].r * sin(a); + } else if (i == 1) { + a = Q->beta_1 - a; + xy.x -= v[i].r * cos(a); + xy.y -= v[i].r * sin(a); + } else { + a = Q->beta_2 - a; + xy.x += v[i].r * cos(a); + xy.y += v[i].r * sin(a); + } + } + xy.x *= THIRD; /* mean of arc intercepts */ + xy.y *= THIRD; + } + return xy; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); } - static double /* law of cosines */ -lc(projCtx ctx, double b,double c,double a) { - return aacos(ctx, .5 * (b * b + c * c - a * a) / (b * c)); + +static void freeup (PJ *P) { + freeup_new (P); + return; } -FORWARD(s_forward); /* spheroid */ - double sinphi, cosphi, a; - VECT v[3]; - int i, j; - - sinphi = sin(lp.phi); - cosphi = cos(lp.phi); - for (i = 0; i < 3; ++i) { /* dist/azimiths from control */ - v[i] = vect(P->ctx, lp.phi - P->c[i].phi, P->c[i].cosphi, P->c[i].sinphi, - cosphi, sinphi, lp.lam - P->c[i].lam); - if ( ! v[i].r) - break; - v[i].Az = adjlon(v[i].Az - P->c[i].v.Az); - } - if (i < 3) /* current point at control point */ - xy = P->c[i].p; - else { /* point mean of intersepts */ - xy = P->p; - for (i = 0; i < 3; ++i) { - j = i == 2 ? 0 : i + 1; - a = lc(P->ctx,P->c[i].v.r, v[i].r, v[j].r); - if (v[i].Az < 0.) - a = -a; - if (! i) { /* coord comp unique to each arc */ - xy.x += v[i].r * cos(a); - xy.y -= v[i].r * sin(a); - } else if (i == 1) { - a = P->beta_1 - a; - xy.x -= v[i].r * cos(a); - xy.y -= v[i].r * sin(a); - } else { - a = P->beta_2 - a; - xy.x += v[i].r * cos(a); - xy.y += v[i].r * sin(a); - } - } - xy.x *= THIRD; /* mean of arc intercepts */ - xy.y *= THIRD; - } - return xy; + + +PJ *PROJECTION(chamb) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_chamb; + int i, j; + char line[10]; + + for (i = 0; i < 3; ++i) { /* get control point locations */ + (void)sprintf(line, "rlat_%d", i+1); + Q->c[i].phi = pj_param(P->ctx, P->params, line).f; + (void)sprintf(line, "rlon_%d", i+1); + Q->c[i].lam = pj_param(P->ctx, P->params, line).f; + Q->c[i].lam = adjlon(Q->c[i].lam - P->lam0); + Q->c[i].cosphi = cos(Q->c[i].phi); + Q->c[i].sinphi = sin(Q->c[i].phi); + } + for (i = 0; i < 3; ++i) { /* inter ctl pt. distances and azimuths */ + j = i == 2 ? 0 : i + 1; + Q->c[i].v = vect(P->ctx,Q->c[j].phi - Q->c[i].phi, Q->c[i].cosphi, Q->c[i].sinphi, + Q->c[j].cosphi, Q->c[j].sinphi, Q->c[j].lam - Q->c[i].lam); + if (! Q->c[i].v.r) E_ERROR(-25); + /* co-linearity problem ignored for now */ + } + Q->beta_0 = lc(P->ctx,Q->c[0].v.r, Q->c[2].v.r, Q->c[1].v.r); + Q->beta_1 = lc(P->ctx,Q->c[0].v.r, Q->c[1].v.r, Q->c[2].v.r); + Q->beta_2 = PI - Q->beta_0; + Q->p.y = 2. * (Q->c[0].p.y = Q->c[1].p.y = Q->c[2].v.r * sin(Q->beta_0)); + Q->c[2].p.y = 0.; + Q->c[0].p.x = - (Q->c[1].p.x = 0.5 * Q->c[0].v.r); + Q->p.x = Q->c[2].p.x = Q->c[0].p.x + Q->c[2].v.r * cos(Q->beta_0); + + P->es = 0.; + P->fwd = s_forward; + + return P; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(chamb) - int i, j; - char line[10]; - - for (i = 0; i < 3; ++i) { /* get control point locations */ - (void)sprintf(line, "rlat_%d", i+1); - P->c[i].phi = pj_param(P->ctx, P->params, line).f; - (void)sprintf(line, "rlon_%d", i+1); - P->c[i].lam = pj_param(P->ctx, P->params, line).f; - P->c[i].lam = adjlon(P->c[i].lam - P->lam0); - P->c[i].cosphi = cos(P->c[i].phi); - P->c[i].sinphi = sin(P->c[i].phi); - } - for (i = 0; i < 3; ++i) { /* inter ctl pt. distances and azimuths */ - j = i == 2 ? 0 : i + 1; - P->c[i].v = vect(P->ctx,P->c[j].phi - P->c[i].phi, P->c[i].cosphi, P->c[i].sinphi, - P->c[j].cosphi, P->c[j].sinphi, P->c[j].lam - P->c[i].lam); - if (! P->c[i].v.r) E_ERROR(-25); - /* co-linearity problem ignored for now */ - } - P->beta_0 = lc(P->ctx,P->c[0].v.r, P->c[2].v.r, P->c[1].v.r); - P->beta_1 = lc(P->ctx,P->c[0].v.r, P->c[1].v.r, P->c[2].v.r); - P->beta_2 = PI - P->beta_0; - P->p.y = 2. * (P->c[0].p.y = P->c[1].p.y = P->c[2].v.r * sin(P->beta_0)); - P->c[2].p.y = 0.; - P->c[0].p.x = - (P->c[1].p.x = 0.5 * P->c[0].v.r); - P->p.x = P->c[2].p.x = P->c[0].p.x + P->c[2].v.r * cos(P->beta_0); - P->es = 0.; P->fwd = s_forward; -ENDENTRY(P) + + +#ifdef PJ_OMIT_SELFTEST +int pj_chamb_selftest (void) {return 0;} +#else + +int pj_chamb_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=chamb +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {-27864.7795868005815, -223364.324593274243}, + {-251312.283053493476, -223402.145526208304}, + {-27864.7856491046077, 223364.327328827145}, + {-251312.289116443484, 223402.142197287147}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} + + +#endif -- cgit v1.2.3 From 2d14c6a55bbc69560d71a42aec44e5cbd597ca7f Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Thu, 14 Apr 2016 20:38:26 +0200 Subject: Removed superfluous declarations in PROJECTION --- src/PJ_cea.c | 2 -- src/PJ_chamb.c | 2 -- src/PJ_comill.c | 3 --- src/PJ_crast.c | 33 +++++++++++++++------------------ 4 files changed, 15 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/PJ_cea.c b/src/PJ_cea.c index f4ff21f3..87c0da07 100644 --- a/src/PJ_cea.c +++ b/src/PJ_cea.c @@ -72,8 +72,6 @@ PJ *PROJECTION(cea) { return freeup_new (P); P->opaque = Q; - P->pfree = freeup; - P->descr = des_cea; double t = 0.0; if (pj_param(P->ctx, P->params, "tlat_ts").i) { diff --git a/src/PJ_chamb.c b/src/PJ_chamb.c index 091408b7..c35061f3 100644 --- a/src/PJ_chamb.c +++ b/src/PJ_chamb.c @@ -114,8 +114,6 @@ PJ *PROJECTION(chamb) { return freeup_new (P); P->opaque = Q; - P->pfree = freeup; - P->descr = des_chamb; int i, j; char line[10]; diff --git a/src/PJ_comill.c b/src/PJ_comill.c index f84f4eb0..1d88dbd5 100644 --- a/src/PJ_comill.c +++ b/src/PJ_comill.c @@ -78,9 +78,6 @@ PJ *PROJECTION(comill) { P->inv = s_inverse; P->fwd = s_forward; - P->pfree = freeup; - P->descr = des_comill; - return P; } diff --git a/src/PJ_crast.c b/src/PJ_crast.c index 9a896459..0c5b706a 100644 --- a/src/PJ_crast.c +++ b/src/PJ_crast.c @@ -1,31 +1,31 @@ #define PJ_LIB__ -# include +# include PROJ_HEAD(crast, "Craster Parabolic (Putnins P4)") "\n\tPCyl., Sph."; -#define XM 0.97720502380583984317 -#define RXM 1.02332670794648848847 -#define YM 3.06998012383946546542 -#define RYM 0.32573500793527994772 -#define THIRD 0.333333333333333333 +#define XM 0.97720502380583984317 +#define RXM 1.02332670794648848847 +#define YM 3.06998012383946546542 +#define RYM 0.32573500793527994772 +#define THIRD 0.333333333333333333 static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ XY xy = {0.0,0.0}; - (void) P; - lp.phi *= THIRD; - xy.x = XM * lp.lam * (2. * cos(lp.phi + lp.phi) - 1.); - xy.y = YM * sin(lp.phi); - return xy; + (void) P; + lp.phi *= THIRD; + xy.x = XM * lp.lam * (2. * cos(lp.phi + lp.phi) - 1.); + xy.y = YM * sin(lp.phi); + return xy; } static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ LP lp = {0.0,0.0}; - (void) P; - lp.phi = 3. * asin(xy.y * RYM); - lp.lam = xy.x * RXM / (2. * cos((lp.phi + lp.phi) * THIRD) - 1); - return lp; + (void) P; + lp.phi = 3. * asin(xy.y * RYM); + lp.lam = xy.x * RXM / (2. * cos((lp.phi + lp.phi) * THIRD) - 1); + return lp; } @@ -45,9 +45,6 @@ PJ *PROJECTION(crast) { P->inv = s_inverse; P->fwd = s_forward; - P->pfree = freeup; - P->descr = des_crast; - return P; } -- cgit v1.2.3 From 147885200d7c0474a59b03224848a87b77bef917 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Thu, 14 Apr 2016 21:07:50 +0200 Subject: Minor cleanups of PJ_c... A few cases of mixed declarations and code cleaned up, a few unused parameter warnings eliminated --- src/PJ_cea.c | 34 ++++++++++++++++------------------ src/PJ_chamb.c | 4 ++-- src/PJ_comill.c | 6 +++++- src/PJ_crast.c | 1 - 4 files changed, 23 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/PJ_cea.c b/src/PJ_cea.c index 87c0da07..e1bcb0af 100644 --- a/src/PJ_cea.c +++ b/src/PJ_cea.c @@ -13,7 +13,7 @@ PROJ_HEAD(cea, "Equal Area Cylindrical") "\n\tCyl, Sph&Ell\n\tlat_ts="; static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ XY xy = {0.0,0.0}; xy.x = P->k0 * lp.lam; - xy.y = 0.5 * pj_qsfn(sin(lp.phi), P->e, P->one_es) / P->k0; + xy.y = 0.5 * pj_qsfn (sin (lp.phi), P->e, P->one_es) / P->k0; return xy; } @@ -28,8 +28,7 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ LP lp = {0.0,0.0}; - struct pj_opaque *Q = P->opaque; - lp.phi = pj_authlat(asin( 2. * xy.y * P->k0 / Q->qp), Q->apa); + lp.phi = pj_authlat(asin( 2. * xy.y * P->k0 / P->opaque->qp), P->opaque->apa); lp.lam = xy.x / P->k0; return lp; } @@ -56,7 +55,7 @@ static void *freeup_new (PJ *P) { /* Destructor */ if (0==P->opaque) return pj_dealloc (P); - pj_dalloc (P->opaque->apa); + pj_dealloc (P->opaque->apa); pj_dealloc (P->opaque); return pj_dealloc (P); } @@ -67,12 +66,12 @@ static void freeup (PJ *P) { } PJ *PROJECTION(cea) { + double t = 0.0; struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - double t = 0.0; if (pj_param(P->ctx, P->params, "tlat_ts").i) { P->k0 = cos(t = pj_param(P->ctx, P->params, "rlat_ts").f); @@ -116,17 +115,17 @@ int pj_cea_selftest (void) { }; XY e_fwd_expect[] = { - {222638.981586547132, 110568.812396267356}, - {222638.981586547132, -110568.812396265886}, + { 222638.981586547132, 110568.812396267356}, + { 222638.981586547132, -110568.812396265886}, {-222638.981586547132, 110568.812396267356}, - {-222638.981586547132, -110568.812396265886}, + {-222638.981586547132, -110568.812396265886}, }; XY s_fwd_expect[] = { - {223402.144255274179, 111695.401198614476}, - {223402.144255274179, -111695.401198614476}, + { 223402.144255274179, 111695.401198614476}, + { 223402.144255274179, -111695.401198614476}, {-223402.144255274179, 111695.401198614476}, - {-223402.144255274179, -111695.401198614476}, + {-223402.144255274179, -111695.401198614476}, }; XY inv_in[] = { @@ -137,21 +136,20 @@ int pj_cea_selftest (void) { }; LP e_inv_expect[] = { - {0.00179663056823904264, 0.000904369476105564289}, - {0.00179663056823904264, -0.000904369476105564289}, + { 0.00179663056823904264, 0.000904369476105564289}, + { 0.00179663056823904264, -0.000904369476105564289}, {-0.00179663056823904264, 0.000904369476105564289}, - {-0.00179663056823904264, -0.000904369476105564289}, + {-0.00179663056823904264, -0.000904369476105564289}, }; LP s_inv_expect[] = { - {0.00179049310978382265, 0.000895246554928338998}, - {0.00179049310978382265, -0.000895246554928338998}, + { 0.00179049310978382265, 0.000895246554928338998}, + { 0.00179049310978382265, -0.000895246554928338998}, {-0.00179049310978382265, 0.000895246554928338998}, - {-0.00179049310978382265, -0.000895246554928338998}, + {-0.00179049310978382265, -0.000895246554928338998}, }; return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); } - #endif diff --git a/src/PJ_chamb.c b/src/PJ_chamb.c index c35061f3..68d99f26 100644 --- a/src/PJ_chamb.c +++ b/src/PJ_chamb.c @@ -109,13 +109,13 @@ static void freeup (PJ *P) { PJ *PROJECTION(chamb) { + int i, j; + char line[10]; struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - int i, j; - char line[10]; for (i = 0; i < 3; ++i) { /* get control point locations */ (void)sprintf(line, "rlat_%d", i+1); diff --git a/src/PJ_comill.c b/src/PJ_comill.c index 1d88dbd5..6bccb264 100644 --- a/src/PJ_comill.c +++ b/src/PJ_comill.c @@ -25,6 +25,8 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ XY xy = {0.0,0.0}; double lat_sq; + (void) P; /* silence unused parameter warnings */ + lat_sq = lp.phi * lp.phi; xy.x = lp.lam; xy.y = lp.phi * (K1 + lat_sq * (K2 + K3 * lat_sq)); @@ -34,7 +36,9 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ LP lp = {0.0,0.0}; - double yc, tol, y2, y4, f, fder; + double yc, tol, y2, f, fder; + + (void) P; /* silence unused parameter warnings */ /* make sure y is inside valid range */ if (xy.y > MAX_Y) { diff --git a/src/PJ_crast.c b/src/PJ_crast.c index 0c5b706a..4773ee7c 100644 --- a/src/PJ_crast.c +++ b/src/PJ_crast.c @@ -56,7 +56,6 @@ int pj_crast_selftest (void) { double tolerance_lp = 1e-10; double tolerance_xy = 1e-7; - char e_args[] = {"+proj=crast +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; char s_args[] = {"+proj=crast +a=6400000 +lat_1=0.5 +lat_2=2"}; LP fwd_in[] = { -- cgit v1.2.3 From e172c753d5486726b50186bb2e6f8aa2731daf7f Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Thu, 14 Apr 2016 23:32:33 +0200 Subject: Convert somerc, stere, ups, sterea, kav5, fouc, mbt_s,, qua_aut i.e. the files PJ_somerc.c, PJ_stere.c, PJ_sterea.c, PJ_sts.c 47 projections converted so far - 95 to go... --- src/PJ_aea.c | 14 +- src/PJ_somerc.c | 219 ++++++++++++++------ src/PJ_stere.c | 610 ++++++++++++++++++++++++++++++++++++-------------------- src/PJ_sterea.c | 204 ++++++++++++++----- src/PJ_sts.c | 369 ++++++++++++++++++++++++++++++---- 5 files changed, 1038 insertions(+), 378 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 0822efd6..8cca2386 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -366,7 +366,7 @@ int pj_eqc_selftest (void) {return 10000;} int pj_eqdc_selftest (void) {return 10000;} int pj_etmerc_selftest (void) {return 10000;} int pj_fahey_selftest (void) {return 10000;} -int pj_fouc_selftest (void) {return 10000;} + int pj_fouc_s_selftest (void) {return 10000;} int pj_gall_selftest (void) {return 10000;} int pj_geos_selftest (void) {return 10000;} @@ -384,7 +384,7 @@ int pj_rhealpix_selftest (void) {return 10000;} int pj_igh_selftest (void) {return 10000;} int pj_imw_p_selftest (void) {return 10000;} int pj_isea_selftest (void) {return 10000;} -int pj_kav5_selftest (void) {return 10000;} + int pj_kav7_selftest (void) {return 10000;} int pj_krovak_selftest (void) {return 10000;} int pj_labrd_selftest (void) {return 10000;} @@ -402,7 +402,7 @@ int pj_lcca_selftest (void) {return 10000;} int pj_lee_os_selftest (void) {return 10000;} int pj_loxim_selftest (void) {return 10000;} int pj_lsat_selftest (void) {return 10000;} -int pj_mbt_s_selftest (void) {return 10000;} + int pj_mbt_fps_selftest (void) {return 10000;} int pj_mbtfpp_selftest (void) {return 10000;} int pj_mbtfpq_selftest (void) {return 10000;} @@ -435,19 +435,17 @@ int pj_putp5_selftest (void) {return 10000;} int pj_putp5p_selftest (void) {return 10000;} int pj_putp6_selftest (void) {return 10000;} int pj_putp6p_selftest (void) {return 10000;} -int pj_qua_aut_selftest (void) {return 10000;} + int pj_qsc_selftest (void) {return 10000;} int pj_robin_selftest (void) {return 10000;} int pj_rouss_selftest (void) {return 10000;} int pj_rpoly_selftest (void) {return 10000;} int pj_sch_selftest (void) {return 10000;} int pj_sinu_selftest (void) {return 10000;} -int pj_somerc_selftest (void) {return 10000;} -int pj_stere_selftest (void) {return 10000;} -int pj_sterea_selftest (void) {return 10000;} + int pj_gstmerc_selftest (void) {return 10000;} int pj_tpers_selftest (void) {return 10000;} -int pj_ups_selftest (void) {return 10000;} + int pj_utm_selftest (void) {return 10000;} int pj_vandg_selftest (void) {return 10000;} int pj_vandg2_selftest (void) {return 10000;} diff --git a/src/PJ_somerc.c b/src/PJ_somerc.c index f7d1f119..e7659876 100644 --- a/src/PJ_somerc.c +++ b/src/PJ_somerc.c @@ -1,66 +1,165 @@ -#define PROJ_PARMS__ \ - double K, c, hlf_e, kR, cosp0, sinp0; #define PJ_LIB__ -#include +#include + PROJ_HEAD(somerc, "Swiss. Obl. Mercator") "\n\tCyl, Ell\n\tFor CH1903"; -#define EPS 1.e-10 + +struct pj_opaque { + double K, c, hlf_e, kR, cosp0, sinp0; +}; + +#define EPS 1.e-10 #define NITER 6 -FORWARD(e_forward); - double phip, lamp, phipp, lampp, sp, cp; - - sp = P->e * sin(lp.phi); - phip = 2.* atan( exp( P->c * ( - log(tan(FORTPI + 0.5 * lp.phi)) - P->hlf_e * log((1. + sp)/(1. - sp))) - + P->K)) - HALFPI; - lamp = P->c * lp.lam; - cp = cos(phip); - phipp = aasin(P->ctx,P->cosp0 * sin(phip) - P->sinp0 * cp * cos(lamp)); - lampp = aasin(P->ctx,cp * sin(lamp) / cos(phipp)); - xy.x = P->kR * lampp; - xy.y = P->kR * log(tan(FORTPI + 0.5 * phipp)); - return (xy); + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0, 0.0}; + double phip, lamp, phipp, lampp, sp, cp; + struct pj_opaque *Q = P->opaque; + + sp = P->e * sin (lp.phi); + phip = 2.* atan ( exp ( Q->c * ( + log (tan (FORTPI + 0.5 * lp.phi)) - Q->hlf_e * log ((1. + sp)/(1. - sp))) + + Q->K)) - HALFPI; + lamp = Q->c * lp.lam; + cp = cos(phip); + phipp = aasin (P->ctx, Q->cosp0 * sin (phip) - Q->sinp0 * cp * cos (lamp)); + lampp = aasin (P->ctx, cp * sin (lamp) / cos (phipp)); + xy.x = Q->kR * lampp; + xy.y = Q->kR * log (tan (FORTPI + 0.5 * phipp)); + return xy; } -INVERSE(e_inverse); /* ellipsoid & spheroid */ - double phip, lamp, phipp, lampp, cp, esp, con, delp; - int i; - - phipp = 2. * (atan(exp(xy.y / P->kR)) - FORTPI); - lampp = xy.x / P->kR; - cp = cos(phipp); - phip = aasin(P->ctx,P->cosp0 * sin(phipp) + P->sinp0 * cp * cos(lampp)); - lamp = aasin(P->ctx,cp * sin(lampp) / cos(phip)); - con = (P->K - log(tan(FORTPI + 0.5 * phip)))/P->c; - for (i = NITER; i ; --i) { - esp = P->e * sin(phip); - delp = (con + log(tan(FORTPI + 0.5 * phip)) - P->hlf_e * - log((1. + esp)/(1. - esp)) ) * - (1. - esp * esp) * cos(phip) * P->rone_es; - phip -= delp; - if (fabs(delp) < EPS) - break; - } - if (i) { - lp.phi = phip; - lp.lam = lamp / P->c; - } else - I_ERROR - return (lp); + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double phip, lamp, phipp, lampp, cp, esp, con, delp; + int i; + + phipp = 2. * (atan (exp (xy.y / Q->kR)) - FORTPI); + lampp = xy.x / Q->kR; + cp = cos (phipp); + phip = aasin (P->ctx, Q->cosp0 * sin (phipp) + Q->sinp0 * cp * cos (lampp)); + lamp = aasin (P->ctx, cp * sin (lampp) / cos (phip)); + con = (Q->K - log (tan (FORTPI + 0.5 * phip)))/Q->c; + for (i = NITER; i ; --i) { + esp = P->e * sin(phip); + delp = (con + log(tan(FORTPI + 0.5 * phip)) - Q->hlf_e * + log((1. + esp)/(1. - esp)) ) * + (1. - esp * esp) * cos(phip) * P->rone_es; + phip -= delp; + if (fabs(delp) < EPS) + break; + } + if (i) { + lp.phi = phip; + lp.lam = lamp / Q->c; + } else + I_ERROR + return (lp); } + + +#if 0 FREEUP; if (P) pj_dalloc(P); } -ENTRY0(somerc) - double cp, phip0, sp; - - P->hlf_e = 0.5 * P->e; - cp = cos(P->phi0); - cp *= cp; - P->c = sqrt(1 + P->es * cp * cp * P->rone_es); - sp = sin(P->phi0); - P->cosp0 = cos( phip0 = aasin(P->ctx, P->sinp0 = sp / P->c) ); - sp *= P->e; - P->K = log(tan(FORTPI + 0.5 * phip0)) - P->c * ( - log(tan(FORTPI + 0.5 * P->phi0)) - P->hlf_e * - log((1. + sp) / (1. - sp))); - P->kR = P->k0 * sqrt(P->one_es) / (1. - sp * sp); - P->inv = e_inverse; - P->fwd = e_forward; -ENDENTRY(P) +#endif + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(somerc) { + double cp, phip0, sp; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + + Q->hlf_e = 0.5 * P->e; + cp = cos (P->phi0); + cp *= cp; + Q->c = sqrt (1 + P->es * cp * cp * P->rone_es); + sp = sin (P->phi0); + Q->cosp0 = cos( phip0 = aasin (P->ctx, Q->sinp0 = sp / Q->c) ); + sp *= P->e; + Q->K = log (tan (FORTPI + 0.5 * phip0)) - Q->c * ( + log (tan (FORTPI + 0.5 * P->phi0)) - Q->hlf_e * + log ((1. + sp) / (1. - sp))); + Q->kR = P->k0 * sqrt(P->one_es) / (1. - sp * sp); + P->inv = e_inverse; + P->fwd = e_forward; + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_somerc_selftest (void) {return 0;} +#else + +int pj_somerc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=somerc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=somerc +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {222638.98158654713, 110579.96521824898}, + {222638.98158654713, -110579.96521825089}, + {-222638.98158654713, 110579.96521824898}, + {-222638.98158654713, -110579.96521825089}, + }; + + XY s_fwd_expect[] = { + {223402.14425527418, 111706.74357494408}, + {223402.14425527418, -111706.74357494518}, + {-223402.14425527418, 111706.74357494408}, + {-223402.14425527418, -111706.74357494518}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0017966305682390426, 0.00090436947704129484}, + {0.0017966305682390426, -0.00090436947704377105}, + {-0.0017966305682390426, 0.00090436947704129484}, + {-0.0017966305682390426, -0.00090436947704377105}, + }; + + LP s_inv_expect[] = { + {0.0017904931097838226, 0.00089524655485801927}, + {0.0017904931097838226, -0.00089524655484529714}, + {-0.0017904931097838226, 0.00089524655485801927}, + {-0.0017904931097838226, -0.00089524655484529714}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif diff --git a/src/PJ_stere.c b/src/PJ_stere.c index a0524627..fbca195f 100644 --- a/src/PJ_stere.c +++ b/src/PJ_stere.c @@ -1,239 +1,409 @@ -#define PROJ_PARMS__ \ - double phits; \ - double sinX1; \ - double cosX1; \ - double akm1; \ - int mode; #define PJ_LIB__ -#include +#include + PROJ_HEAD(stere, "Stereographic") "\n\tAzi, Sph&Ell\n\tlat_ts="; PROJ_HEAD(ups, "Universal Polar Stereographic") "\n\tAzi, Sph&Ell\n\tsouth"; -#define sinph0 P->sinX1 -#define cosph0 P->cosX1 -#define EPS10 1.e-10 -#define TOL 1.e-8 -#define NITER 8 -#define CONV 1.e-10 -#define S_POLE 0 -#define N_POLE 1 -#define OBLIQ 2 -#define EQUIT 3 - static double -ssfn_(double phit, double sinphi, double eccen) { - sinphi *= eccen; - return (tan (.5 * (HALFPI + phit)) * - pow((1. - sinphi) / (1. + sinphi), .5 * eccen)); + + +struct pj_opaque { + double phits; + double sinX1; + double cosX1; + double akm1; + int mode; +}; + +#define sinph0 P->opaque->sinX1 +#define cosph0 P->opaque->cosX1 +#define EPS10 1.e-10 +#define TOL 1.e-8 +#define NITER 8 +#define CONV 1.e-10 +#define S_POLE 0 +#define N_POLE 1 +#define OBLIQ 2 +#define EQUIT 3 + +static double ssfn_ (double phit, double sinphi, double eccen) { + sinphi *= eccen; + return (tan (.5 * (HALFPI + phit)) * + pow ((1. - sinphi) / (1. + sinphi), .5 * eccen)); } -FORWARD(e_forward); /* ellipsoid */ - double coslam, sinlam, sinX=0.0, cosX=0.0, X, A, sinphi; - - coslam = cos(lp.lam); - sinlam = sin(lp.lam); - sinphi = sin(lp.phi); - if (P->mode == OBLIQ || P->mode == EQUIT) { - sinX = sin(X = 2. * atan(ssfn_(lp.phi, sinphi, P->e)) - HALFPI); - cosX = cos(X); - } - switch (P->mode) { - case OBLIQ: - A = P->akm1 / (P->cosX1 * (1. + P->sinX1 * sinX + - P->cosX1 * cosX * coslam)); - xy.y = A * (P->cosX1 * sinX - P->sinX1 * cosX * coslam); - goto xmul; - case EQUIT: - A = 2. * P->akm1 / (1. + cosX * coslam); - xy.y = A * sinX; + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double coslam, sinlam, sinX = 0.0, cosX = 0.0, X, A, sinphi; + + coslam = cos (lp.lam); + sinlam = sin (lp.lam); + sinphi = sin (lp.phi); + if (Q->mode == OBLIQ || Q->mode == EQUIT) { + sinX = sin (X = 2. * atan(ssfn_(lp.phi, sinphi, P->e)) - HALFPI); + cosX = cos (X); + } + + switch (Q->mode) { + case OBLIQ: + A = Q->akm1 / (Q->cosX1 * (1. + Q->sinX1 * sinX + + Q->cosX1 * cosX * coslam)); + xy.y = A * (Q->cosX1 * sinX - Q->sinX1 * cosX * coslam); + goto xmul; /* but why not just xy.x = A * cosX; break; ? */ + + case EQUIT: + A = 2. * Q->akm1 / (1. + cosX * coslam); + xy.y = A * sinX; xmul: - xy.x = A * cosX; - break; - case S_POLE: - lp.phi = -lp.phi; - coslam = - coslam; - sinphi = -sinphi; - case N_POLE: - xy.x = P->akm1 * pj_tsfn(lp.phi, sinphi, P->e); - xy.y = - xy.x * coslam; - break; - } - xy.x = xy.x * sinlam; - return (xy); + xy.x = A * cosX; + break; + + case S_POLE: + lp.phi = -lp.phi; + coslam = - coslam; + sinphi = -sinphi; + case N_POLE: + xy.x = Q->akm1 * pj_tsfn (lp.phi, sinphi, P->e); + xy.y = - xy.x * coslam; + break; + } + + xy.x = xy.x * sinlam; + return xy; } -FORWARD(s_forward); /* spheroid */ - double sinphi, cosphi, coslam, sinlam; - - sinphi = sin(lp.phi); - cosphi = cos(lp.phi); - coslam = cos(lp.lam); - sinlam = sin(lp.lam); - switch (P->mode) { - case EQUIT: - xy.y = 1. + cosphi * coslam; - goto oblcon; - case OBLIQ: - xy.y = 1. + sinph0 * sinphi + cosph0 * cosphi * coslam; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double sinphi, cosphi, coslam, sinlam; + + sinphi = sin(lp.phi); + cosphi = cos(lp.phi); + coslam = cos(lp.lam); + sinlam = sin(lp.lam); + + switch (Q->mode) { + case EQUIT: + xy.y = 1. + cosphi * coslam; + goto oblcon; + case OBLIQ: + xy.y = 1. + sinph0 * sinphi + cosph0 * cosphi * coslam; oblcon: - if (xy.y <= EPS10) F_ERROR; - xy.x = (xy.y = P->akm1 / xy.y) * cosphi * sinlam; - xy.y *= (P->mode == EQUIT) ? sinphi : - cosph0 * sinphi - sinph0 * cosphi * coslam; - break; - case N_POLE: - coslam = - coslam; - lp.phi = - lp.phi; - case S_POLE: - if (fabs(lp.phi - HALFPI) < TOL) F_ERROR; - xy.x = sinlam * ( xy.y = P->akm1 * tan(FORTPI + .5 * lp.phi) ); - xy.y *= coslam; - break; - } - return (xy); + if (xy.y <= EPS10) F_ERROR; + xy.x = (xy.y = Q->akm1 / xy.y) * cosphi * sinlam; + xy.y *= (Q->mode == EQUIT) ? sinphi : + cosph0 * sinphi - sinph0 * cosphi * coslam; + break; + case N_POLE: + coslam = - coslam; + lp.phi = - lp.phi; + case S_POLE: + if (fabs (lp.phi - HALFPI) < TOL) F_ERROR; + xy.x = sinlam * ( xy.y = Q->akm1 * tan (FORTPI + .5 * lp.phi) ); + xy.y *= coslam; + break; + } + return xy; } -INVERSE(e_inverse); /* ellipsoid */ - double cosphi, sinphi, tp=0.0, phi_l=0.0, rho, halfe=0.0, halfpi=0.0; - int i; - - rho = hypot(xy.x, xy.y); - switch (P->mode) { - case OBLIQ: - case EQUIT: - cosphi = cos( tp = 2. * atan2(rho * P->cosX1 , P->akm1) ); - sinphi = sin(tp); - if( rho == 0.0 ) - phi_l = asin(cosphi * P->sinX1); + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double cosphi, sinphi, tp=0.0, phi_l=0.0, rho, halfe=0.0, halfpi=0.0; + int i; + + rho = hypot (xy.x, xy.y); + + switch (Q->mode) { + case OBLIQ: + case EQUIT: + cosphi = cos ( tp = 2. * atan2 (rho * Q->cosX1 , Q->akm1) ); + sinphi = sin (tp); + if ( rho == 0.0 ) + phi_l = asin (cosphi * Q->sinX1); else - phi_l = asin(cosphi * P->sinX1 + (xy.y * sinphi * P->cosX1 / rho)); - - tp = tan(.5 * (HALFPI + phi_l)); - xy.x *= sinphi; - xy.y = rho * P->cosX1 * cosphi - xy.y * P->sinX1* sinphi; - halfpi = HALFPI; - halfe = .5 * P->e; - break; - case N_POLE: - xy.y = -xy.y; - case S_POLE: - phi_l = HALFPI - 2. * atan(tp = - rho / P->akm1); - halfpi = -HALFPI; - halfe = -.5 * P->e; - break; - } - for (i = NITER; i--; phi_l = lp.phi) { - sinphi = P->e * sin(phi_l); - lp.phi = 2. * atan(tp * pow((1.+sinphi)/(1.-sinphi), - halfe)) - halfpi; - if (fabs(phi_l - lp.phi) < CONV) { - if (P->mode == S_POLE) - lp.phi = -lp.phi; - lp.lam = (xy.x == 0. && xy.y == 0.) ? 0. : atan2(xy.x, xy.y); - return (lp); - } - } - I_ERROR; + phi_l = asin (cosphi * Q->sinX1 + (xy.y * sinphi * Q->cosX1 / rho)); + + tp = tan (.5 * (HALFPI + phi_l)); + xy.x *= sinphi; + xy.y = rho * Q->cosX1 * cosphi - xy.y * Q->sinX1* sinphi; + halfpi = HALFPI; + halfe = .5 * P->e; + break; + case N_POLE: + xy.y = -xy.y; + case S_POLE: + phi_l = HALFPI - 2. * atan (tp = - rho / Q->akm1); + halfpi = -HALFPI; + halfe = -.5 * P->e; + break; + } + + for (i = NITER; i--; phi_l = lp.phi) { + sinphi = P->e * sin(phi_l); + lp.phi = 2. * atan (tp * pow ((1.+sinphi)/(1.-sinphi), halfe)) - halfpi; + if (fabs (phi_l - lp.phi) < CONV) { + if (Q->mode == S_POLE) + lp.phi = -lp.phi; + lp.lam = (xy.x == 0. && xy.y == 0.) ? 0. : atan2 (xy.x, xy.y); + return lp; + } + } + I_ERROR; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double c, rh, sinc, cosc; + + sinc = sin (c = 2. * atan ((rh = hypot (xy.x, xy.y)) / Q->akm1)); + cosc = cos (c); + lp.lam = 0.; + + switch (Q->mode) { + case EQUIT: + if (fabs (rh) <= EPS10) + lp.phi = 0.; + else + lp.phi = asin (xy.y * sinc / rh); + if (cosc != 0. || xy.x != 0.) + lp.lam = atan2 (xy.x * sinc, cosc * rh); + break; + case OBLIQ: + if (fabs (rh) <= EPS10) + lp.phi = P->phi0; + else + lp.phi = asin (cosc * sinph0 + xy.y * sinc * cosph0 / rh); + if ((c = cosc - sinph0 * sin (lp.phi)) != 0. || xy.x != 0.) + lp.lam = atan2 (xy.x * sinc * cosph0, c * rh); + break; + case N_POLE: + xy.y = -xy.y; + case S_POLE: + if (fabs (rh) <= EPS10) + lp.phi = P->phi0; + else + lp.phi = asin (Q->mode == S_POLE ? - cosc : cosc); + lp.lam = (xy.x == 0. && xy.y == 0.) ? 0. : atan2 (xy.x, xy.y); + break; + } + return lp; } -INVERSE(s_inverse); /* spheroid */ - double c, rh, sinc, cosc; - - sinc = sin(c = 2. * atan((rh = hypot(xy.x, xy.y)) / P->akm1)); - cosc = cos(c); - lp.lam = 0.; - switch (P->mode) { - case EQUIT: - if (fabs(rh) <= EPS10) - lp.phi = 0.; - else - lp.phi = asin(xy.y * sinc / rh); - if (cosc != 0. || xy.x != 0.) - lp.lam = atan2(xy.x * sinc, cosc * rh); - break; - case OBLIQ: - if (fabs(rh) <= EPS10) - lp.phi = P->phi0; - else - lp.phi = asin(cosc * sinph0 + xy.y * sinc * cosph0 / rh); - if ((c = cosc - sinph0 * sin(lp.phi)) != 0. || xy.x != 0.) - lp.lam = atan2(xy.x * sinc * cosph0, c * rh); - break; - case N_POLE: - xy.y = -xy.y; - case S_POLE: - if (fabs(rh) <= EPS10) - lp.phi = P->phi0; - else - lp.phi = asin(P->mode == S_POLE ? - cosc : cosc); - lp.lam = (xy.x == 0. && xy.y == 0.) ? 0. : atan2(xy.x, xy.y); - break; - } - return (lp); + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +static PJ *setup(PJ *P) { /* general initialization */ + double t; + struct pj_opaque *Q = P->opaque; + + if (fabs ((t = fabs (P->phi0)) - HALFPI) < EPS10) + Q->mode = P->phi0 < 0. ? S_POLE : N_POLE; + else + Q->mode = t > EPS10 ? OBLIQ : EQUIT; + Q->phits = fabs (Q->phits); + + if (P->es) { + double X; + + switch (Q->mode) { + case N_POLE: + case S_POLE: + if (fabs (Q->phits - HALFPI) < EPS10) + Q->akm1 = 2. * P->k0 / + sqrt (pow (1+P->e,1+P->e) * pow (1-P->e,1-P->e)); + else { + Q->akm1 = cos (Q->phits) / + pj_tsfn (Q->phits, t = sin (Q->phits), P->e); + t *= P->e; + Q->akm1 /= sqrt(1. - t * t); + } + break; + case EQUIT: + case OBLIQ: + t = sin (P->phi0); + X = 2. * atan (ssfn_(P->phi0, t, P->e)) - HALFPI; + t *= P->e; + Q->akm1 = 2. * P->k0 * cos (P->phi0) / sqrt(1. - t * t); + Q->sinX1 = sin (X); + Q->cosX1 = cos (X); + break; + } + P->inv = e_inverse; + P->fwd = e_forward; + } else { + switch (Q->mode) { + case OBLIQ: + sinph0 = sin (P->phi0); + cosph0 = cos (P->phi0); + case EQUIT: + Q->akm1 = 2. * P->k0; + break; + case S_POLE: + case N_POLE: + Q->akm1 = fabs (Q->phits - HALFPI) >= EPS10 ? + cos (Q->phits) / tan (FORTPI - .5 * Q->phits) : + 2. * P->k0 ; + break; + } + + P->inv = s_inverse; + P->fwd = s_forward; + } + return P; } -FREEUP; if (P) pj_dalloc(P); } - static PJ * -setup(PJ *P) { /* general initialization */ - double t; - - if (fabs((t = fabs(P->phi0)) - HALFPI) < EPS10) - P->mode = P->phi0 < 0. ? S_POLE : N_POLE; - else - P->mode = t > EPS10 ? OBLIQ : EQUIT; - P->phits = fabs(P->phits); - if (P->es) { - double X; - - switch (P->mode) { - case N_POLE: - case S_POLE: - if (fabs(P->phits - HALFPI) < EPS10) - P->akm1 = 2. * P->k0 / - sqrt(pow(1+P->e,1+P->e)*pow(1-P->e,1-P->e)); - else { - P->akm1 = cos(P->phits) / - pj_tsfn(P->phits, t = sin(P->phits), P->e); - t *= P->e; - P->akm1 /= sqrt(1. - t * t); - } - break; - case EQUIT: - case OBLIQ: - t = sin(P->phi0); - X = 2. * atan(ssfn_(P->phi0, t, P->e)) - HALFPI; - t *= P->e; - P->akm1 = 2. * P->k0 * cos(P->phi0) / sqrt(1. - t * t); - P->sinX1 = sin(X); - P->cosX1 = cos(X); - break; - } - P->inv = e_inverse; - P->fwd = e_forward; - } else { - switch (P->mode) { - case OBLIQ: - sinph0 = sin(P->phi0); - cosph0 = cos(P->phi0); - case EQUIT: - P->akm1 = 2. * P->k0; - break; - case S_POLE: - case N_POLE: - P->akm1 = fabs(P->phits - HALFPI) >= EPS10 ? - cos(P->phits) / tan(FORTPI - .5 * P->phits) : - 2. * P->k0 ; - break; - } - P->inv = s_inverse; - P->fwd = s_forward; - } - return P; + + +PJ *PROJECTION(stere) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->phits = pj_param (P->ctx, P->params, "tlat_ts").i ? + pj_param (P->ctx, P->params, "rlat_ts").f : HALFPI; + + return setup(P); } -ENTRY0(stere) - P->phits = pj_param(P->ctx, P->params, "tlat_ts").i ? - pj_param(P->ctx, P->params, "rlat_ts").f : HALFPI; -ENDENTRY(setup(P)) -ENTRY0(ups) + + +PJ *PROJECTION(ups) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + /* International Ellipsoid */ P->phi0 = pj_param(P->ctx, P->params, "bsouth").i ? - HALFPI: HALFPI; if (!P->es) E_ERROR(-34); P->k0 = .994; P->x0 = 2000000.; P->y0 = 2000000.; - P->phits = HALFPI; + Q->phits = HALFPI; P->lam0 = 0.; -ENDENTRY(setup(P)) + + return setup(P); +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_stere_selftest (void) {return 0;} +#else + +int pj_stere_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=stere +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=stere +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 445289.70910023432, 221221.76694834774}, + { 445289.70910023432, -221221.76694835056}, + {-445289.70910023432, 221221.76694834774}, + {-445289.70910023432, -221221.76694835056}, + }; + + XY s_fwd_expect[] = { + { 223407.81025950745, 111737.938996443}, + { 223407.81025950745, -111737.938996443}, + {-223407.81025950745, 111737.938996443}, + {-223407.81025950745, -111737.938996443}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.0017966305682022392, 0.00090436947502443507}, + { 0.0017966305682022392, -0.00090436947502443507}, + {-0.0017966305682022392, 0.00090436947502443507}, + {-0.0017966305682022392, -0.00090436947502443507}, + }; + + LP s_inv_expect[] = { + { 0.001790493109747395, 0.00089524655465513144}, + { 0.001790493109747395, -0.00089524655465513144}, + {-0.001790493109747395, 0.00089524655465513144}, + {-0.001790493109747395, -0.00089524655465513144}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif + + + + + +#ifdef PJ_OMIT_SELFTEST +int pj_ups_selftest (void) {return 0;} +#else + +int pj_ups_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=ups +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {2433455.5634384668, -10412543.301512826}, + {2448749.1185681992, -10850493.419804076}, + {1566544.4365615332, -10412543.301512826}, + {1551250.8814318008, -10850493.419804076}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {-44.998567498074834, 64.9182362867341}, + {-44.995702709112308, 64.917020250675748}, + {-45.004297076028529, 64.915804280954518}, + {-45.001432287066002, 64.914588377560719}, + }; + + return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); +} + + +#endif diff --git a/src/PJ_sterea.c b/src/PJ_sterea.c index fff2e952..cbfb8fb4 100644 --- a/src/PJ_sterea.c +++ b/src/PJ_sterea.c @@ -23,61 +23,155 @@ ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#define PROJ_PARMS__ \ - double phic0; \ - double cosc0, sinc0; \ - double R2; \ - void *en; - #define PJ_LIB__ -#include - -PROJ_HEAD(sterea, "Oblique Stereographic Alternative") - "\n\tAzimuthal, Sph&Ell"; -# define DEL_TOL 1.e-14 -# define MAX_ITER 10 - -FORWARD(e_forward); /* ellipsoid */ - double cosc, sinc, cosl, k; - - lp = pj_gauss(P->ctx, lp, P->en); - sinc = sin(lp.phi); - cosc = cos(lp.phi); - cosl = cos(lp.lam); - k = P->k0 * P->R2 / (1. + P->sinc0 * sinc + P->cosc0 * cosc * cosl); - xy.x = k * cosc * sin(lp.lam); - xy.y = k * (P->cosc0 * sinc - P->sinc0 * cosc * cosl); - return (xy); +#include + + +struct pj_opaque { + double phic0; + double cosc0, sinc0; + double R2; + void *en; +}; + + +PROJ_HEAD(sterea, "Oblique Stereographic Alternative") "\n\tAzimuthal, Sph&Ell"; +# define DEL_TOL 1.e-14 +# define MAX_ITER 10 + + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double cosc, sinc, cosl, k; + + lp = pj_gauss(P->ctx, lp, Q->en); + sinc = sin(lp.phi); + cosc = cos(lp.phi); + cosl = cos(lp.lam); + k = P->k0 * Q->R2 / (1. + Q->sinc0 * sinc + Q->cosc0 * cosc * cosl); + xy.x = k * cosc * sin(lp.lam); + xy.y = k * (Q->cosc0 * sinc - Q->sinc0 * cosc * cosl); + return xy; +} + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double rho, c, sinc, cosc; + + xy.x /= P->k0; + xy.y /= P->k0; + if ( (rho = hypot (xy.x, xy.y)) ) { + c = 2. * atan2 (rho, Q->R2); + sinc = sin (c); + cosc = cos (c); + lp.phi = asin (cosc * Q->sinc0 + xy.y * sinc * Q->cosc0 / rho); + lp.lam = atan2 (xy.x * sinc, rho * Q->cosc0 * cosc - xy.y * Q->sinc0 * sinc); + } else { + lp.phi = Q->phic0; + lp.lam = 0.; + } + return pj_inv_gauss(P->ctx, lp, Q->en); +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque->en); + pj_dealloc (P->opaque); + return pj_dealloc(P); } -INVERSE(e_inverse); /* ellipsoid */ - double rho, c, sinc, cosc; - - xy.x /= P->k0; - xy.y /= P->k0; - if((rho = hypot(xy.x, xy.y))) { - c = 2. * atan2(rho, P->R2); - sinc = sin(c); - cosc = cos(c); - lp.phi = asin(cosc * P->sinc0 + xy.y * sinc * P->cosc0 / rho); - lp.lam = atan2(xy.x * sinc, rho * P->cosc0 * cosc - - xy.y * P->sinc0 * sinc); - } else { - lp.phi = P->phic0; - lp.lam = 0.; - } - return(pj_inv_gauss(P->ctx, lp, P->en)); + + +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; if (P) { if (P->en) free(P->en); free(P); } } -ENTRYA(sterea) - - P->en=0; -ENTRYX - double R; - - if (!(P->en = pj_gauss_ini(P->e, P->phi0, &(P->phic0), &R))) E_ERROR_0; - P->sinc0 = sin(P->phic0); - P->cosc0 = cos(P->phic0); - P->R2 = 2. * R; - P->inv = e_inverse; - P->fwd = e_forward; -ENDENTRY(P) + + +PJ *PROJECTION(sterea) { + double R; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->en = pj_gauss_ini(P->e, P->phi0, &(Q->phic0), &R); + if (0==P) + E_ERROR_0; + + Q->sinc0 = sin (Q->phic0); + Q->cosc0 = cos (Q->phic0); + Q->R2 = 2. * R; + + P->inv = e_inverse; + P->fwd = e_forward; + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_sterea_selftest (void) {return 0;} +#else + +int pj_sterea_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=sterea +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=sterea +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222644.89410919772, 110611.09187173686}, + { 222644.89410919772, -110611.09187173827}, + {-222644.89410919772, 110611.09187173686}, + {-222644.89410919772, -110611.09187173827}, + }; + + XY s_fwd_expect[] = { + { 223407.81025950745, 111737.93899644315}, + { 223407.81025950745, -111737.93899644315}, + {-223407.81025950745, 111737.93899644315}, + {-223407.81025950745, -111737.93899644315}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.0017966305682019911, 0.00090436947683099009}, + { 0.0017966305682019911, -0.00090436947684371233}, + {-0.0017966305682019911, 0.00090436947683099009}, + {-0.0017966305682019911, -0.00090436947684371233}, + }; + + LP s_inv_expect[] = { + { 0.001790493109747395, 0.00089524655465446378}, + { 0.001790493109747395, -0.00089524655465446378}, + {-0.001790493109747395, 0.00089524655465446378}, + {-0.001790493109747395, -0.00089524655465446378}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif diff --git a/src/PJ_sts.c b/src/PJ_sts.c index c35d5cfc..689c0489 100644 --- a/src/PJ_sts.c +++ b/src/PJ_sts.c @@ -1,54 +1,353 @@ -#define PROJ_PARMS__ \ - double C_x, C_y, C_p; \ - int tan_mode; #define PJ_LIB__ # include -PROJ_HEAD(kav5, "Kavraisky V") "\n\tPCyl., Sph."; -PROJ_HEAD(qua_aut, "Quartic Authalic") "\n\tPCyl., Sph."; -PROJ_HEAD(mbt_s, "McBryde-Thomas Flat-Polar Sine (No. 1)") "\n\tPCyl., Sph."; -PROJ_HEAD(fouc, "Foucaut") "\n\tPCyl., Sph."; -FORWARD(s_forward); /* spheroid */ + +PROJ_HEAD(kav5, "Kavraisky V") "\n\tPCyl., Sph."; +PROJ_HEAD(qua_aut, "Quartic Authalic") "\n\tPCyl., Sph."; +PROJ_HEAD(fouc, "Foucaut") "\n\tPCyl., Sph."; +PROJ_HEAD(mbt_s, "McBryde-Thomas Flat-Polar Sine (No. 1)") "\n\tPCyl., Sph."; + + +struct pj_opaque { + double C_x, C_y, C_p; \ + int tan_mode; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double c; - xy.x = P->C_x * lp.lam * cos(lp.phi); - xy.y = P->C_y; - lp.phi *= P->C_p; + xy.x = Q->C_x * lp.lam * cos(lp.phi); + xy.y = Q->C_y; + lp.phi *= Q->C_p; c = cos(lp.phi); - if (P->tan_mode) { + if (Q->tan_mode) { xy.x *= c * c; - xy.y *= tan(lp.phi); + xy.y *= tan (lp.phi); } else { xy.x /= c; - xy.y *= sin(lp.phi); + xy.y *= sin (lp.phi); } - return (xy); + return xy; } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double c; - - xy.y /= P->C_y; - c = cos(lp.phi = P->tan_mode ? atan(xy.y) : aasin(P->ctx,xy.y)); - lp.phi /= P->C_p; - lp.lam = xy.x / (P->C_x * cos(lp.phi)); - if (P->tan_mode) + + xy.y /= Q->C_y; + c = cos (lp.phi = Q->tan_mode ? atan (xy.y) : aasin (P->ctx, xy.y)); + lp.phi /= Q->C_p; + lp.lam = xy.x / (Q->C_x * cos(lp.phi)); + if (Q->tan_mode) lp.lam /= c * c; else lp.lam *= c; - return (lp); + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; if (P) pj_dalloc(P); } - static PJ * -setup(PJ *P, double p, double q, int mode) { - P->es = 0.; + + +static PJ *setup(PJ *P, double p, double q, int mode) { + P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; - P->C_x = q / p; - P->C_y = p; - P->C_p = 1/ q; - P->tan_mode = mode; + P->opaque->C_x = q / p; + P->opaque->C_y = p; + P->opaque->C_p = 1/ q; + P->opaque->tan_mode = mode; return P; } -ENTRY0(kav5) ENDENTRY(setup(P, 1.50488, 1.35439, 0)) -ENTRY0(qua_aut) ENDENTRY(setup(P, 2., 2., 0)) -ENTRY0(mbt_s) ENDENTRY(setup(P, 1.48875, 1.36509, 0)) -ENTRY0(fouc) ENDENTRY(setup(P, 2., 2., 1)) + + + + + +PJ *PROJECTION(fouc) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + return setup(P, 2., 2., 1); +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_fouc_selftest (void) {return 0;} +#else +int pj_fouc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=fouc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=fouc +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {222588.12067589167, 111322.31670069379}, + {222588.12067589167, -111322.31670069379}, + {-222588.12067589167, 111322.31670069379}, + {-222588.12067589167, -111322.31670069379}, + }; + + XY s_fwd_expect[] = { + {223351.10900341379, 111703.9077217125}, + {223351.10900341379, -111703.9077217125}, + {-223351.10900341379, 111703.9077217125}, + {-223351.10900341379, -111703.9077217125}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0017966305685702751, 0.00089831528410111959}, + {0.0017966305685702751, -0.00089831528410111959}, + {-0.0017966305685702751, 0.00089831528410111959}, + {-0.0017966305685702751, -0.00089831528410111959}, + }; + + LP s_inv_expect[] = { + {0.0017904931101116717, 0.00089524655487369749}, + {0.0017904931101116717, -0.00089524655487369749}, + {-0.0017904931101116717, 0.00089524655487369749}, + {-0.0017904931101116717, -0.00089524655487369749}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} +#endif + + + + + + +PJ *PROJECTION(kav5) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_kav5; + return setup(P, 1.50488, 1.35439, 0); +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_kav5_selftest (void) {return 0;} +#else +int pj_kav5_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=kav5 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=kav5 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {200360.90530882866, 123685.08247699818}, + {200360.90530882866, -123685.08247699818}, + {-200360.90530882866, 123685.08247699818}, + {-200360.90530882866, -123685.08247699818}, + }; + + XY s_fwd_expect[] = { + {201047.7031108776, 124109.05062917093}, + {201047.7031108776, -124109.05062917093}, + {-201047.7031108776, 124109.05062917093}, + {-201047.7031108776, -124109.05062917093}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0019962591348533314, 0.00080848256185253912}, + {0.0019962591348533314, -0.00080848256185253912}, + {-0.0019962591348533314, 0.00080848256185253912}, + {-0.0019962591348533314, -0.00080848256185253912}, + }; + + LP s_inv_expect[] = { + {0.0019894397264987643, 0.00080572070962591153}, + {0.0019894397264987643, -0.00080572070962591153}, + {-0.0019894397264987643, 0.00080572070962591153}, + {-0.0019894397264987643, -0.00080572070962591153}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} +#endif + + + + + +PJ *PROJECTION(qua_aut) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + return setup(P, 2., 2., 0); +} + +#ifdef PJ_OMIT_SELFTEST +int pj_qua_aut_selftest (void) {return 0;} +#else +int pj_qua_aut_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=qua_aut +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=qua_aut +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {222613.54903309655, 111318.07788798446}, + {222613.54903309655, -111318.07788798446}, + {-222613.54903309655, 111318.07788798446}, + {-222613.54903309655, -111318.07788798446}, + }; + + XY s_fwd_expect[] = { + {223376.62452402918, 111699.65437918637}, + {223376.62452402918, -111699.65437918637}, + {-223376.62452402918, 111699.65437918637}, + {-223376.62452402918, -111699.65437918637}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0017966305684046586, 0.00089831528412872229}, + {0.0017966305684046586, -0.00089831528412872229}, + {-0.0017966305684046586, 0.00089831528412872229}, + {-0.0017966305684046586, -0.00089831528412872229}, + }; + + LP s_inv_expect[] = { + {0.0017904931099477471, 0.00089524655490101819}, + {0.0017904931099477471, -0.00089524655490101819}, + {-0.0017904931099477471, 0.00089524655490101819}, + {-0.0017904931099477471, -0.00089524655490101819}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} +#endif + + + + + +PJ *PROJECTION(mbt_s) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + return setup(P, 1.48875, 1.36509, 0); +} + +#ifdef PJ_OMIT_SELFTEST +int pj_mbt_s_selftest (void) {return 0;} +#else +int pj_mbt_s_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=mbt_s +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; + char s_args[] = {"+proj=mbt_s +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {204131.51785027285, 121400.33022550763}, + {204131.51785027285, -121400.33022550763}, + {-204131.51785027285, 121400.33022550763}, + {-204131.51785027285, -121400.33022550763}, + }; + + XY s_fwd_expect[] = { + {204831.24057099217, 121816.46669603503}, + {204831.24057099217, -121816.46669603503}, + {-204831.24057099217, 121816.46669603503}, + {-204831.24057099217, -121816.46669603503}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0019593827209883237, 0.00082369854658027549}, + {0.0019593827209883237, -0.00082369854658027549}, + {-0.0019593827209883237, 0.00082369854658027549}, + {-0.0019593827209883237, -0.00082369854658027549}, + }; + + LP s_inv_expect[] = { + {0.0019526892859206603, 0.00082088471512331508}, + {0.0019526892859206603, -0.00082088471512331508}, + {-0.0019526892859206603, 0.00082088471512331508}, + {-0.0019526892859206603, -0.00082088471512331508}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} +#endif -- cgit v1.2.3 From dde7b1573748d8a4a73f6632953837379b1c6591 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Fri, 15 Apr 2016 07:06:53 +0200 Subject: Converted denoy projection --- src/PJ_aea.c | 1 - src/PJ_denoy.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 8cca2386..84b070f1 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -355,7 +355,6 @@ source files int pj_aeqd_selftest (void) {return 10000;} int pj_alsk_selftest (void) {return 10000;} -int pj_denoy_selftest (void) {return 10000;} int pj_eck1_selftest (void) {return 10000;} int pj_eck2_selftest (void) {return 10000;} int pj_eck3_selftest (void) {return 10000;} diff --git a/src/PJ_denoy.c b/src/PJ_denoy.c index b1a6fe80..10005a31 100644 --- a/src/PJ_denoy.c +++ b/src/PJ_denoy.c @@ -1,19 +1,69 @@ #define PJ_LIB__ -#include +#include + PROJ_HEAD(denoy, "Denoyer Semi-Elliptical") "\n\tPCyl., no inv., Sph."; -#define C0 0.95 -#define C1 -.08333333333333333333 -#define C3 .00166666666666666666 -#define D1 0.9 -#define D5 0.03 -FORWARD(s_forward); /* spheroid */ - (void) P; - xy.y = lp.phi; - xy.x = lp.lam; - lp.lam = fabs(lp.lam); - xy.x *= cos((C0 + lp.lam * (C1 + lp.lam * lp.lam * C3)) * - (lp.phi * (D1 + D5 * lp.phi * lp.phi * lp.phi * lp.phi))); - return (xy); + +#define C0 0.95 +#define C1 -0.08333333333333333333 +#define C3 0.00166666666666666666 +#define D1 0.9 +#define D5 0.03 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0, 0.0}; + (void) P; + xy.y = lp.phi; + xy.x = lp.lam; + lp.lam = fabs(lp.lam); + xy.x *= cos((C0 + lp.lam * (C1 + lp.lam * lp.lam * C3)) * + (lp.phi * (D1 + D5 * lp.phi * lp.phi * lp.phi * lp.phi))); + return xy; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(denoy) P->es = 0.; P->fwd = s_forward; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(denoy) { + P->es = 0.0; + P->fwd = s_forward; + + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_denoy_selftest (void) {return 0;} +#else + +int pj_denoy_selftest (void) { + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=denoy +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223377.422876954137, 111701.07212763709}, + { 223377.422876954137, -111701.07212763709}, + {-223377.422876954137, 111701.07212763709}, + {-223377.422876954137, -111701.07212763709}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, 0, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} + + +#endif -- cgit v1.2.3 From 0f53bac54b31564d611c0c4d5d9453f0fb414456 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Fri, 15 Apr 2016 15:00:19 +0200 Subject: Converted eck1. Expanded tabs. --- src/PJ_aea.c | 1 - src/PJ_eck1.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 92 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 84b070f1..caf4efd5 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -355,7 +355,6 @@ source files int pj_aeqd_selftest (void) {return 10000;} int pj_alsk_selftest (void) {return 10000;} -int pj_eck1_selftest (void) {return 10000;} int pj_eck2_selftest (void) {return 10000;} int pj_eck3_selftest (void) {return 10000;} int pj_eck4_selftest (void) {return 10000;} diff --git a/src/PJ_eck1.c b/src/PJ_eck1.c index b0b43da5..da2c8685 100644 --- a/src/PJ_eck1.c +++ b/src/PJ_eck1.c @@ -1,21 +1,92 @@ -#define PJ_LIB__ -#include -PROJ_HEAD(eck1, "Eckert I") "\n\tPCyl., Sph."; -#define FC .92131773192356127802 -#define RP .31830988618379067154 -FORWARD(s_forward); /* spheroid */ - (void) P; - xy.x = FC * lp.lam * (1. - RP * fabs(lp.phi)); - xy.y = FC * lp.phi; - return (xy); -} -INVERSE(s_inverse); /* spheroid */ - (void) P; - lp.phi = xy.y / FC; - lp.lam = xy.x / (FC * (1. - RP * fabs(lp.phi))); - return (lp); -} -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(eck1) - P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; -ENDENTRY(P) +#define PJ_LIB__ +#include + +PROJ_HEAD(eck1, "Eckert I") "\n\tPCyl., Sph."; +#define FC 0.92131773192356127802 +#define RP 0.31830988618379067154 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + (void) P; + + xy.x = FC * lp.lam * (1. - RP * fabs(lp.phi)); + xy.y = FC * lp.phi; + + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + (void) P; + + lp.phi = xy.y / FC; + lp.lam = xy.x / (FC * (1. - RP * fabs(lp.phi))); + + return (lp); +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(eck1) { + P->es = 0.0; + P->inv = s_inverse; + P->fwd = s_forward; + + return P ; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_eck1_selftest (void) {return 0;} +#else + +int pj_eck1_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=eck1 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + XY s_fwd_expect[] = { + { 204680.88820295094, 102912.17842606473}, + { 204680.88820295094, -102912.17842606473}, + {-204680.88820295094, 102912.17842606473}, + {-204680.88820295094, -102912.17842606473}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0019434150820034624, 0.00097170229538813102}, + { 0.0019434150820034624, -0.00097170229538813102}, + {-0.0019434150820034624, 0.00097170229538813102}, + {-0.0019434150820034624, -0.00097170229538813102}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 8ec40ec09591e60a5b45179654fbda2ebab5d4a4 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Fri, 15 Apr 2016 15:02:21 +0200 Subject: Converted eck2. Expanded tabs. --- src/PJ_aea.c | 1 - src/PJ_eck2.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 100 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index caf4efd5..a94518dc 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -355,7 +355,6 @@ source files int pj_aeqd_selftest (void) {return 10000;} int pj_alsk_selftest (void) {return 10000;} -int pj_eck2_selftest (void) {return 10000;} int pj_eck3_selftest (void) {return 10000;} int pj_eck4_selftest (void) {return 10000;} int pj_eck5_selftest (void) {return 10000;} diff --git a/src/PJ_eck2.c b/src/PJ_eck2.c index 08b65595..6d73b88a 100644 --- a/src/PJ_eck2.c +++ b/src/PJ_eck2.c @@ -1,29 +1,104 @@ #define PJ_LIB__ -# include +# include + PROJ_HEAD(eck2, "Eckert II") "\n\tPCyl. Sph."; -#define FXC 0.46065886596178063902 -#define FYC 1.44720250911653531871 -#define C13 0.33333333333333333333 -#define ONEEPS 1.0000001 -FORWARD(s_forward); /* spheroid */ - (void) P; - xy.x = FXC * lp.lam * (xy.y = sqrt(4. - 3. * sin(fabs(lp.phi)))); - xy.y = FYC * (2. - xy.y); - if ( lp.phi < 0.) xy.y = -xy.y; - return (xy); + +#define FXC 0.46065886596178063902 +#define FYC 1.44720250911653531871 +#define C13 0.33333333333333333333 +#define ONEEPS 1.0000001 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + (void) P; + + xy.x = FXC * lp.lam * (xy.y = sqrt(4. - 3. * sin(fabs(lp.phi)))); + xy.y = FYC * (2. - xy.y); + if ( lp.phi < 0.) xy.y = -xy.y; + + return (xy); } -INVERSE(s_inverse); /* spheroid */ - lp.lam = xy.x / (FXC * ( lp.phi = 2. - fabs(xy.y) / FYC) ); - lp.phi = (4. - lp.phi * lp.phi) * C13; - if (fabs(lp.phi) >= 1.) { - if (fabs(lp.phi) > ONEEPS) I_ERROR - else - lp.phi = lp.phi < 0. ? -HALFPI : HALFPI; - } else - lp.phi = asin(lp.phi); - if (xy.y < 0) - lp.phi = -lp.phi; - return (lp); + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + (void) P; + + lp.lam = xy.x / (FXC * ( lp.phi = 2. - fabs(xy.y) / FYC) ); + lp.phi = (4. - lp.phi * lp.phi) * C13; + if (fabs(lp.phi) >= 1.) { + if (fabs(lp.phi) > ONEEPS) I_ERROR + else + lp.phi = lp.phi < 0. ? -HALFPI : HALFPI; + } else + lp.phi = asin(lp.phi); + if (xy.y < 0) + lp.phi = -lp.phi; + return (lp); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(eck2); P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + return pj_dealloc (P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(eck2) { + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_eck2_selftest (void) {return 0;} +#else + +int pj_eck2_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=eck2 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 204472.87090796008, 121633.73497524235}, + { 204472.87090796008, -121633.73497524235}, + {-204472.87090796008, 121633.73497524235}, + {-204472.87090796008, -121633.73497524235}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0019434150820034624, 0.00082480429919795412}, + { 0.0019434150820034624, -0.00082480429919795412}, + {-0.0019434150820034624, 0.00082480429919795412}, + {-0.0019434150820034624, -0.00082480429919795412}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From f38c90e53179c743809a128f08d8bffa6b636cd0 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Fri, 15 Apr 2016 15:06:43 +0200 Subject: Converted eck3, putp1, wag6 and kav7. Expanded tabs. --- src/PJ_aea.c | 4 - src/PJ_eck3.c | 335 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 290 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index a94518dc..2ad6d4f4 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -355,7 +355,6 @@ source files int pj_aeqd_selftest (void) {return 10000;} int pj_alsk_selftest (void) {return 10000;} -int pj_eck3_selftest (void) {return 10000;} int pj_eck4_selftest (void) {return 10000;} int pj_eck5_selftest (void) {return 10000;} int pj_eck6_selftest (void) {return 10000;} @@ -382,7 +381,6 @@ int pj_igh_selftest (void) {return 10000;} int pj_imw_p_selftest (void) {return 10000;} int pj_isea_selftest (void) {return 10000;} -int pj_kav7_selftest (void) {return 10000;} int pj_krovak_selftest (void) {return 10000;} int pj_labrd_selftest (void) {return 10000;} int pj_laea_selftest (void) {return 10000;} @@ -423,7 +421,6 @@ int pj_omerc_selftest (void) {return 10000;} int pj_ortho_selftest (void) {return 10000;} int pj_patterson_selftest (void) {return 10000;} int pj_poly_selftest (void) {return 10000;} -int pj_putp1_selftest (void) {return 10000;} int pj_putp2_selftest (void) {return 10000;} int pj_putp3_selftest (void) {return 10000;} int pj_putp3p_selftest (void) {return 10000;} @@ -450,6 +447,5 @@ int pj_vandg3_selftest (void) {return 10000;} int pj_vandg4_selftest (void) {return 10000;} int pj_wag4_selftest (void) {return 10000;} int pj_wag5_selftest (void) {return 10000;} -int pj_wag6_selftest (void) {return 10000;} int pj_weren_selftest (void) {return 10000;} #endif diff --git a/src/PJ_eck3.c b/src/PJ_eck3.c index d7755f0c..3eb7f8f9 100644 --- a/src/PJ_eck3.c +++ b/src/PJ_eck3.c @@ -1,50 +1,295 @@ -#define PROJ_PARMS__ \ - double C_x, C_y, A, B; #define PJ_LIB__ -#include +#include + PROJ_HEAD(eck3, "Eckert III") "\n\tPCyl, Sph."; PROJ_HEAD(putp1, "Putnins P1") "\n\tPCyl, Sph."; PROJ_HEAD(wag6, "Wagner VI") "\n\tPCyl, Sph."; PROJ_HEAD(kav7, "Kavraisky VII") "\n\tPCyl, Sph."; -FORWARD(s_forward); /* spheroid */ - xy.y = P->C_y * lp.phi; - xy.x = P->C_x * lp.lam * (P->A + asqrt(1. - P->B * lp.phi * lp.phi)); - return (xy); -} -INVERSE(s_inverse); /* spheroid */ - lp.phi = xy.y / P->C_y; - lp.lam = xy.x / (P->C_x * (P->A + asqrt(1. - P->B * lp.phi * lp.phi))); - return (lp); -} -FREEUP; if (P) pj_dalloc(P); } - static PJ * -setup(PJ *P) { - P->es = 0.; - P->inv = s_inverse; - P->fwd = s_forward; - return P; -} -ENTRY0(eck3) - P->C_x = .42223820031577120149; - P->C_y = .84447640063154240298; - P->A = 1.; - P->B = 0.4052847345693510857755; -ENDENTRY(setup(P)) -ENTRY0(kav7) - P->C_x = 0.2632401569273184856851; - P->C_x = 0.8660254037844; - P->C_y = 1.; - P->A = 0.; - P->B = 0.30396355092701331433; -ENDENTRY(setup(P)) -ENTRY0(wag6); - P->C_x = P->C_y = 0.94745; - P->A = 0.; - P->B = 0.30396355092701331433; -ENDENTRY(setup(P)) -ENTRY0(putp1); - P->C_x = 1.89490; - P->C_y = 0.94745; - P->A = -0.5; - P->B = 0.30396355092701331433; -ENDENTRY(setup(P)) + +struct pj_opaque { + double C_x, C_y, A, B; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + xy.y = Q->C_y * lp.phi; + xy.x = Q->C_x * lp.lam * (Q->A + asqrt(1. - Q->B * lp.phi * lp.phi)); + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + lp.phi = xy.y / Q->C_y; + lp.lam = xy.x / (Q->C_x * (Q->A + asqrt(1. - Q->B * lp.phi * lp.phi))); + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +static PJ *setup(PJ *P) { + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + return P; +} + + +PJ *PROJECTION(eck3) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->C_x = 0.42223820031577120149; + Q->C_y = 0.84447640063154240298; + Q->A = 1.0; + Q->B = 0.4052847345693510857755; + + return setup(P); +} + + +PJ *PROJECTION(kav7) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + /* Defined twice in original code - Using 0.866..., + * but leaving the other one here as a safety measure. + * Q->C_x = 0.2632401569273184856851; */ + Q->C_x = 0.8660254037844; + Q->C_y = 1.; + Q->A = 0.; + Q->B = 0.30396355092701331433; + + return setup(P); +} + + +PJ *PROJECTION(wag6) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->C_x = Q->C_y = 0.94745; + Q->A = 0.0; + Q->B = 0.30396355092701331433; + + return setup(P); +} + + +PJ *PROJECTION(putp1) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->C_x = 1.89490; + Q->C_y = 0.94745; + Q->A = -0.5; + Q->B = 0.30396355092701331433; + + return setup(P); +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_eck3_selftest (void) {return 0;} +#else + +int pj_eck3_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=eck3 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 188652.01572153764, 94328.919337031271}, + { 188652.01572153764, -94328.919337031271}, + {-188652.01572153764, 94328.919337031271}, + {-188652.01572153764, -94328.919337031271}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0021202405520236059, 0.0010601202759750307}, + { 0.0021202405520236059, -0.0010601202759750307}, + {-0.0021202405520236059, 0.0010601202759750307}, + {-0.0021202405520236059, -0.0010601202759750307}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif + +#ifdef PJ_OMIT_SELFTEST +int pj_kav7_selftest (void) {return 0;} +#else + +int pj_kav7_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=kav7 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 193462.9749437288, 111701.07212763709}, + { 193462.9749437288, -111701.07212763709}, + {-193462.9749437288, 111701.07212763709}, + {-193462.9749437288, -111701.07212763709} + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0020674833579085268, 0.00089524655489191132}, + { 0.0020674833579085268, -0.00089524655489191132}, + {-0.0020674833579085268, 0.00089524655489191132}, + {-0.0020674833579085268, -0.00089524655489191132} + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif + +#ifdef PJ_OMIT_SELFTEST +int pj_wag6_selftest (void) {return 0;} +#else + +int pj_wag6_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=wag6 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 211652.56216440981, 105831.18078732977}, + { 211652.56216440981, -105831.18078732977}, + {-211652.56216440981, 105831.18078732977}, + {-211652.56216440981, -105831.18078732977} + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0018898022163257513, 0.000944901108123818}, + { 0.0018898022163257513, -0.000944901108123818}, + {-0.0018898022163257513, 0.000944901108123818}, + {-0.0018898022163257513, -0.000944901108123818} + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif + + +#ifdef PJ_OMIT_SELFTEST +int pj_putp1_selftest (void) {return 0;} +#else + +int pj_putp1_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=putp1 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 211642.76275416015, 105831.18078732977}, + { 211642.76275416015, -105831.18078732977}, + {-211642.76275416015, 105831.18078732977}, + {-211642.76275416015, -105831.18078732977} + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0018898022164038663, 0.000944901108123818}, + { 0.0018898022164038663, -0.000944901108123818}, + {-0.0018898022164038663, 0.000944901108123818}, + {-0.0018898022164038663, -0.000944901108123818} + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From e83114c35547825a4665c19868ee898907b3810f Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Fri, 15 Apr 2016 15:14:50 +0200 Subject: Converted eck4. Expanded tabs. --- src/PJ_aea.c | 1 - src/PJ_eck4.c | 162 ++++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 117 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 2ad6d4f4..bea5d6e6 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -355,7 +355,6 @@ source files int pj_aeqd_selftest (void) {return 10000;} int pj_alsk_selftest (void) {return 10000;} -int pj_eck4_selftest (void) {return 10000;} int pj_eck5_selftest (void) {return 10000;} int pj_eck6_selftest (void) {return 10000;} int pj_eqc_selftest (void) {return 10000;} diff --git a/src/PJ_eck4.c b/src/PJ_eck4.c index 0bedbbc9..06998ad4 100644 --- a/src/PJ_eck4.c +++ b/src/PJ_eck4.c @@ -1,45 +1,117 @@ -#define PJ_LIB__ -#include -PROJ_HEAD(eck4, "Eckert IV") "\n\tPCyl, Sph."; -#define C_x .42223820031577120149 -#define C_y 1.32650042817700232218 -#define RC_y .75386330736002178205 -#define C_p 3.57079632679489661922 -#define RC_p .28004957675577868795 -#define EPS 1e-7 -#define NITER 6 -FORWARD(s_forward); /* spheroid */ - double p, V, s, c; - int i; - (void) P; - - p = C_p * sin(lp.phi); - V = lp.phi * lp.phi; - lp.phi *= 0.895168 + V * ( 0.0218849 + V * 0.00826809 ); - for (i = NITER; i ; --i) { - c = cos(lp.phi); - s = sin(lp.phi); - lp.phi -= V = (lp.phi + s * (c + 2.) - p) / - (1. + c * (c + 2.) - s * s); - if (fabs(V) < EPS) - break; - } - if (!i) { - xy.x = C_x * lp.lam; - xy.y = lp.phi < 0. ? -C_y : C_y; - } else { - xy.x = C_x * lp.lam * (1. + cos(lp.phi)); - xy.y = C_y * sin(lp.phi); - } - return (xy); -} -INVERSE(s_inverse); /* spheroid */ - double c; - - lp.phi = aasin(P->ctx,xy.y / C_y); - lp.lam = xy.x / (C_x * (1. + (c = cos(lp.phi)))); - lp.phi = aasin(P->ctx,(lp.phi + sin(lp.phi) * (c + 2.)) / C_p); - return (lp); -} -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(eck4); P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) +#define PJ_LIB__ +#include + +PROJ_HEAD(eck4, "Eckert IV") "\n\tPCyl, Sph."; + +#define C_x .42223820031577120149 +#define C_y 1.32650042817700232218 +#define RC_y .75386330736002178205 +#define C_p 3.57079632679489661922 +#define RC_p .28004957675577868795 +#define EPS 1e-7 +#define NITER 6 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + double p, V, s, c; + int i; + (void) P; + + p = C_p * sin(lp.phi); + V = lp.phi * lp.phi; + lp.phi *= 0.895168 + V * ( 0.0218849 + V * 0.00826809 ); + for (i = NITER; i ; --i) { + c = cos(lp.phi); + s = sin(lp.phi); + lp.phi -= V = (lp.phi + s * (c + 2.) - p) / + (1. + c * (c + 2.) - s * s); + if (fabs(V) < EPS) + break; + } + if (!i) { + xy.x = C_x * lp.lam; + xy.y = lp.phi < 0. ? -C_y : C_y; + } else { + xy.x = C_x * lp.lam * (1. + cos(lp.phi)); + xy.y = C_y * sin(lp.phi); + } + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + double c; + + lp.phi = aasin(P->ctx,xy.y / C_y); + lp.lam = xy.x / (C_x * (1. + (c = cos(lp.phi)))); + lp.phi = aasin(P->ctx,(lp.phi + sin(lp.phi) * (c + 2.)) / C_p); + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(eck4) { + P->es = 0.0; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_eck4_selftest (void) {return 0;} +#else + +int pj_eck4_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=eck4 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 188646.38935641639, 132268.54017406539 }, + { 188646.38935641639, -132268.54017406539 }, + {-188646.38935641639, 132268.54017406539 }, + {-188646.38935641639, -132268.54017406539 }, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0021202405520236059, 0.00075601458836610643 }, + { 0.0021202405520236059, -0.00075601458836610643 }, + {-0.0021202405520236059, 0.00075601458836610643 }, + {-0.0021202405520236059, -0.00075601458836610643 }, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 439b43ce5652aacdda386edda62b02d9e6ed1b95 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Fri, 15 Apr 2016 15:21:06 +0200 Subject: Converted eck5. Expanded tabs. --- src/PJ_aea.c | 1 - src/PJ_eck4.c | 16 ++++---- src/PJ_eck5.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 116 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index bea5d6e6..8b96b5a9 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -355,7 +355,6 @@ source files int pj_aeqd_selftest (void) {return 10000;} int pj_alsk_selftest (void) {return 10000;} -int pj_eck5_selftest (void) {return 10000;} int pj_eck6_selftest (void) {return 10000;} int pj_eqc_selftest (void) {return 10000;} int pj_eqdc_selftest (void) {return 10000;} diff --git a/src/PJ_eck4.c b/src/PJ_eck4.c index 06998ad4..8a56f019 100644 --- a/src/PJ_eck4.c +++ b/src/PJ_eck4.c @@ -90,10 +90,10 @@ int pj_eck4_selftest (void) { }; XY s_fwd_expect[] = { - { 188646.38935641639, 132268.54017406539 }, - { 188646.38935641639, -132268.54017406539 }, - {-188646.38935641639, 132268.54017406539 }, - {-188646.38935641639, -132268.54017406539 }, + { 188646.38935641639, 132268.54017406539}, + { 188646.38935641639, -132268.54017406539}, + {-188646.38935641639, 132268.54017406539}, + {-188646.38935641639, -132268.54017406539}, }; XY inv_in[] = { @@ -104,10 +104,10 @@ int pj_eck4_selftest (void) { }; LP s_inv_expect[] = { - { 0.0021202405520236059, 0.00075601458836610643 }, - { 0.0021202405520236059, -0.00075601458836610643 }, - {-0.0021202405520236059, 0.00075601458836610643 }, - {-0.0021202405520236059, -0.00075601458836610643 }, + { 0.0021202405520236059, 0.00075601458836610643}, + { 0.0021202405520236059, -0.00075601458836610643}, + {-0.0021202405520236059, 0.00075601458836610643}, + {-0.0021202405520236059, -0.00075601458836610643}, }; return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); diff --git a/src/PJ_eck5.c b/src/PJ_eck5.c index 029c18e0..ccfcb88f 100644 --- a/src/PJ_eck5.c +++ b/src/PJ_eck5.c @@ -1,20 +1,108 @@ -#define PJ_LIB__ -# include -PROJ_HEAD(eck5, "Eckert V") "\n\tPCyl, Sph."; -#define XF 0.44101277172455148219 -#define RXF 2.26750802723822639137 -#define YF 0.88202554344910296438 -#define RYF 1.13375401361911319568 -FORWARD(s_forward); /* spheroid */ - (void) P; - xy.x = XF * (1. + cos(lp.phi)) * lp.lam; - xy.y = YF * lp.phi; - return (xy); -} -INVERSE(s_inverse); /* spheroid */ - (void) P; - lp.lam = RXF * xy.x / (1. + cos( lp.phi = RYF * xy.y)); - return (lp); -} -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(eck5); P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) +#define PJ_LIB__ +#include + +PROJ_HEAD(eck5, "Eckert V") "\n\tPCyl, Sph."; + +#define XF 0.44101277172455148219 +#define RXF 2.26750802723822639137 +#define YF 0.88202554344910296438 +#define RYF 1.13375401361911319568 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + (void) P; + xy.x = XF * (1. + cos(lp.phi)) * lp.lam; + xy.y = YF * lp.phi; + + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + (void) P; + lp.lam = RXF * xy.x / (1. + cos( lp.phi = RYF * xy.y)); + + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(eck5) { + P->es = 0.0; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_eck5_selftest (void) {return 0;} +#else + +int pj_eck5_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=eck5 +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=eck5 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 196358.31442683787, 98186.634363414545 }, + { 196358.31442683787, -98186.634363414545 }, + {-196358.31442683787, 98186.634363414545 }, + {-196358.31442683787, -98186.634363414545 }, + }; + + XY s_fwd_expect[] = { + { 197031.39213406085, 98523.198847226551 }, + { 197031.39213406085, -98523.198847226551 }, + {-197031.39213406085, 98523.198847226551 }, + {-197031.39213406085, -98523.198847226551 }, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0020369371178927064, 0.0010184685588659013 }, + {0.0020369371178927064, -0.0010184685588659013 }, + {-0.0020369371178927064, 0.0010184685588659013 }, + {-0.0020369371178927064, -0.0010184685588659013 }, + }; + + LP s_inv_expect[] = { + {0.002029978749734037, 0.001014989374787388 }, + {0.002029978749734037, -0.001014989374787388 }, + {-0.002029978749734037, 0.001014989374787388 }, + {-0.002029978749734037, -0.001014989374787388 }, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 4e112d2e44b9855404bfe05bf2586a3e2682f653 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Fri, 15 Apr 2016 15:41:38 +0200 Subject: Converted fahey. Expanded tabs. --- src/PJ_aea.c | 2 - src/PJ_fahey.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 96 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 8b96b5a9..69240842 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -359,8 +359,6 @@ int pj_eck6_selftest (void) {return 10000;} int pj_eqc_selftest (void) {return 10000;} int pj_eqdc_selftest (void) {return 10000;} int pj_etmerc_selftest (void) {return 10000;} -int pj_fahey_selftest (void) {return 10000;} - int pj_fouc_s_selftest (void) {return 10000;} int pj_gall_selftest (void) {return 10000;} int pj_geos_selftest (void) {return 10000;} diff --git a/src/PJ_fahey.c b/src/PJ_fahey.c index 007fc906..864225f4 100644 --- a/src/PJ_fahey.c +++ b/src/PJ_fahey.c @@ -1,19 +1,96 @@ -#define PJ_LIB__ -# include -PROJ_HEAD(fahey, "Fahey") "\n\tPcyl, Sph."; -#define TOL 1e-6 -FORWARD(s_forward); /* spheroid */ - (void) P; - xy.y = 1.819152 * ( xy.x = tan(0.5 * lp.phi) ); - xy.x = 0.819152 * lp.lam * asqrt(1 - xy.x * xy.x); - return (xy); -} -INVERSE(s_inverse); /* spheroid */ - (void) P; - lp.phi = 2. * atan(xy.y /= 1.819152); - lp.lam = fabs(xy.y = 1. - xy.y * xy.y) < TOL ? 0. : - xy.x / (0.819152 * sqrt(xy.y)); - return (lp); -} -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(fahey) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) +#define PJ_LIB__ +# include + +PROJ_HEAD(fahey, "Fahey") "\n\tPcyl, Sph."; + +#define TOL 1e-6 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + (void) P; + + xy.x = tan(0.5 * lp.phi); + xy.y = 1.819152 * xy.x; + xy.x = 0.819152 * lp.lam * asqrt(1 - xy.x * xy.x); + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + (void) P; + + xy.y /= 1.819152; + lp.phi = 2. * atan(xy.y); + xy.y = 1. - xy.y * xy.y; + lp.lam = fabs(xy.y) < TOL ? 0. : xy.x / (0.819152 * sqrt(xy.y)); + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(fahey) { + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_fahey_selftest (void) {return 0;} +#else + +int pj_fahey_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=fahey +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=fahey +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 182993.34464912376, 101603.19356988439 }, + { 182993.34464912376, -101603.19356988439 }, + {-182993.34464912376, 101603.19356988439 }, + {-182993.34464912376, -101603.19356988439 }, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + {0.0021857886080359551, 0.00098424601668238403 }, + {0.0021857886080359551, -0.00098424601668238403 }, + {-0.0021857886080359551, 0.00098424601668238403 }, + {-0.0021857886080359551, -0.00098424601668238403 }, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From fb804cc8d0df7c0c56284ce22731249386202f84 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sat, 16 Apr 2016 21:33:50 +0200 Subject: Converted fouc_s. Expanded tabs. --- src/PJ_aea.c | 1 - src/PJ_fouc_s.c | 157 ++++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 119 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 69240842..fd697f14 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -359,7 +359,6 @@ int pj_eck6_selftest (void) {return 10000;} int pj_eqc_selftest (void) {return 10000;} int pj_eqdc_selftest (void) {return 10000;} int pj_etmerc_selftest (void) {return 10000;} -int pj_fouc_s_selftest (void) {return 10000;} int pj_gall_selftest (void) {return 10000;} int pj_geos_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} diff --git a/src/PJ_fouc_s.c b/src/PJ_fouc_s.c index b84b3f82..4123497c 100644 --- a/src/PJ_fouc_s.c +++ b/src/PJ_fouc_s.c @@ -1,45 +1,126 @@ -#define PROJ_PARMS__ \ - double n, n1; #define PJ_LIB__ -#include +#include + PROJ_HEAD(fouc_s, "Foucaut Sinusoidal") "\n\tPCyl., Sph."; + #define MAX_ITER 10 #define LOOP_TOL 1e-7 -FORWARD(s_forward); /* spheroid */ - double t; - t = cos(lp.phi); - xy.x = lp.lam * t / (P->n + P->n1 * t); - xy.y = P->n * lp.phi + P->n1 * sin(lp.phi); - return (xy); +struct pj_opaque { + double n, n1; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double t; + + t = cos(lp.phi); + xy.x = lp.lam * t / (Q->n + Q->n1 * t); + xy.y = Q->n * lp.phi + Q->n1 * sin(lp.phi); + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double V; + int i; + + if (Q->n) { + lp.phi = xy.y; + for (i = MAX_ITER; i ; --i) { + lp.phi -= V = (Q->n * lp.phi + Q->n1 * sin(lp.phi) - xy.y ) / + (Q->n + Q->n1 * cos(lp.phi)); + if (fabs(V) < LOOP_TOL) + break; + } + if (!i) + lp.phi = xy.y < 0. ? -HALFPI : HALFPI; + } else + lp.phi = aasin(P->ctx,xy.y); + V = cos(lp.phi); + lp.lam = xy.x * (Q->n + Q->n1 * V) / V; + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); } -INVERSE(s_inverse); /* spheroid */ - double V; - int i; - - if (P->n) { - lp.phi = xy.y; - for (i = MAX_ITER; i ; --i) { - lp.phi -= V = (P->n * lp.phi + P->n1 * sin(lp.phi) - xy.y ) / - (P->n + P->n1 * cos(lp.phi)); - if (fabs(V) < LOOP_TOL) - break; - } - if (!i) - lp.phi = xy.y < 0. ? -HALFPI : HALFPI; - } else - lp.phi = aasin(P->ctx,xy.y); - V = cos(lp.phi); - lp.lam = xy.x * (P->n + P->n1 * V) / V; - return (lp); + + +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(fouc_s) - P->n = pj_param(P->ctx, P->params, "dn").f; - if (P->n < 0. || P->n > 1.) - E_ERROR(-99) - P->n1 = 1. - P->n; - P->es = 0; - P->inv = s_inverse; - P->fwd = s_forward; -ENDENTRY(P) + + +PJ *PROJECTION(fouc_s) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->n = pj_param(P->ctx, P->params, "dn").f; + if (Q->n < 0. || Q->n > 1.) + E_ERROR(-99) + Q->n1 = 1. - Q->n; + P->es = 0; + P->inv = s_inverse; + P->fwd = s_forward; + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_fouc_s_selftest (void) {return 0;} +#else + +int pj_fouc_s_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=fouc_s +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223402.14425527424, 111695.40119861449}, + { 223402.14425527424, -111695.40119861449}, + {-223402.14425527424, 111695.40119861449}, + {-223402.14425527424, -111695.40119861449}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0017904931097838226, 0.000895246554928339}, + { 0.0017904931097838226, -0.000895246554928339}, + {-0.0017904931097838226, 0.000895246554928339}, + {-0.0017904931097838226, -0.000895246554928339}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 68c66715f20deb45f2743f252507ed7813e19ff7 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Mon, 18 Apr 2016 10:53:38 +0200 Subject: Converted gall. Expanded tabs. --- src/PJ_aea.c | 1 - src/PJ_gall.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 96 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index fd697f14..c20a0bef 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -359,7 +359,6 @@ int pj_eck6_selftest (void) {return 10000;} int pj_eqc_selftest (void) {return 10000;} int pj_eqdc_selftest (void) {return 10000;} int pj_etmerc_selftest (void) {return 10000;} -int pj_gall_selftest (void) {return 10000;} int pj_geos_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} int pj_gins8_selftest (void) {return 10000;} diff --git a/src/PJ_gall.c b/src/PJ_gall.c index 1acd7d09..b3d7cc6c 100644 --- a/src/PJ_gall.c +++ b/src/PJ_gall.c @@ -1,21 +1,100 @@ #define PJ_LIB__ -#include +#include + PROJ_HEAD(gall, "Gall (Gall Stereographic)") "\n\tCyl, Sph"; -#define YF 1.70710678118654752440 -#define XF 0.70710678118654752440 -#define RYF 0.58578643762690495119 -#define RXF 1.41421356237309504880 -FORWARD(s_forward); /* spheroid */ - (void) P; - xy.x = XF * lp.lam; - xy.y = YF * tan(.5 * lp.phi); - return (xy); + +#define YF 1.70710678118654752440 +#define XF 0.70710678118654752440 +#define RYF 0.58578643762690495119 +#define RXF 1.41421356237309504880 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + (void) P; + + xy.x = XF * lp.lam; + xy.y = YF * tan(.5 * lp.phi); + + return xy; } -INVERSE(s_inverse); /* spheroid */ - (void) P; - lp.lam = RXF * xy.x; - lp.phi = 2. * atan(xy.y * RYF); - return (lp); + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + (void) P; + + lp.lam = RXF * xy.x; + lp.phi = 2. * atan(xy.y * RYF); + + return lp; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(gall) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(gall) { + P->es = 0.0; + + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_gall_selftest (void) {return 0;} +#else + +int pj_gall_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=gall +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 157969.17113451968, 95345.249178385886}, + { 157969.17113451968, -95345.249178385886}, + {-157969.17113451968, 95345.249178385886}, + {-157969.17113451968, -95345.249178385886}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0025321396391918614, 0.001048846580346495}, + { 0.0025321396391918614, -0.001048846580346495}, + {-0.0025321396391918614, 0.001048846580346495}, + {-0.0025321396391918614, -0.001048846580346495}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From dbba67bd749d6cf8080658fecc51fde90502f4d1 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Mon, 18 Apr 2016 11:44:15 +0200 Subject: Converted geos. Expanded tabs. --- src/PJ_aea.c | 1 - src/PJ_geos.c | 417 ++++++++++++++++++++++++++++++++++++---------------------- 2 files changed, 263 insertions(+), 155 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index c20a0bef..c5f808a5 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -359,7 +359,6 @@ int pj_eck6_selftest (void) {return 10000;} int pj_eqc_selftest (void) {return 10000;} int pj_eqdc_selftest (void) {return 10000;} int pj_etmerc_selftest (void) {return 10000;} -int pj_geos_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} int pj_gins8_selftest (void) {return 10000;} int pj_gn_sinu_selftest (void) {return 10000;} diff --git a/src/PJ_geos.c b/src/PJ_geos.c index 09393adf..578608c9 100644 --- a/src/PJ_geos.c +++ b/src/PJ_geos.c @@ -3,8 +3,7 @@ ** ** Copyright (c) 2004 Gerald I. Evenden ** Copyright (c) 2012 Martin Raspaud -*/ -/* +** ** See also (section 4.4.3.2): ** http://www.eumetsat.int/en/area4/msg/news/us_doc/cgms_03_26.pdf ** @@ -27,164 +26,274 @@ ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#define PROJ_PARMS__ \ - double h; \ - double radius_p; \ - double radius_p2; \ - double radius_p_inv2; \ - double radius_g; \ - double radius_g_1; \ - double C; \ - char * sweep_axis; \ - int flip_axis; + #define PJ_LIB__ -#include +#include + +struct pj_opaque { + double h; + double radius_p; + double radius_p2; + double radius_p_inv2; + double radius_g; + double radius_g_1; + double C; + char *sweep_axis; + int flip_axis; +}; PROJ_HEAD(geos, "Geostationary Satellite View") "\n\tAzi, Sph&Ell\n\th="; -FORWARD(s_forward); /* spheroid */ - double Vx, Vy, Vz, tmp; - -/* Calculation of the three components of the vector from satellite to -** position on earth surface (lon,lat).*/ - tmp = cos(lp.phi); - Vx = cos (lp.lam) * tmp; - Vy = sin (lp.lam) * tmp; - Vz = sin (lp.phi); -/* Check visibility.*/ - if (((P->radius_g - Vx) * Vx - Vy * Vy - Vz * Vz) < 0.) F_ERROR; -/* Calculation based on view angles from satellite.*/ - tmp = P->radius_g - Vx; - if(P->flip_axis) - { - xy.x = P->radius_g_1 * atan(Vy / hypot(Vz, tmp)); - xy.y = P->radius_g_1 * atan(Vz / tmp); - } - else - { - xy.x = P->radius_g_1 * atan(Vy / tmp); - xy.y = P->radius_g_1 * atan(Vz / hypot(Vy, tmp)); - } - return (xy); + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double Vx, Vy, Vz, tmp; + + /* Calculation of the three components of the vector from satellite to + ** position on earth surface (lon,lat).*/ + tmp = cos(lp.phi); + Vx = cos (lp.lam) * tmp; + Vy = sin (lp.lam) * tmp; + Vz = sin (lp.phi); + + /* Check visibility*/ + + + /* Calculation based on view angles from satellite.*/ + tmp = Q->radius_g - Vx; + + if(Q->flip_axis) { + xy.x = Q->radius_g_1 * atan(Vy / hypot(Vz, tmp)); + xy.y = Q->radius_g_1 * atan(Vz / tmp); + } else { + xy.x = Q->radius_g_1 * atan(Vy / tmp); + xy.y = Q->radius_g_1 * atan(Vz / hypot(Vy, tmp)); + } + + return xy; } -FORWARD(e_forward); /* ellipsoid */ - double r, Vx, Vy, Vz, tmp; - -/* Calculation of geocentric latitude. */ - lp.phi = atan (P->radius_p2 * tan (lp.phi)); -/* Calculation of the three components of the vector from satellite to -** position on earth surface (lon,lat).*/ - r = (P->radius_p) / hypot(P->radius_p * cos (lp.phi), sin (lp.phi)); - Vx = r * cos (lp.lam) * cos (lp.phi); - Vy = r * sin (lp.lam) * cos (lp.phi); - Vz = r * sin (lp.phi); -/* Check visibility. */ - if (((P->radius_g - Vx) * Vx - Vy * Vy - Vz * Vz * P->radius_p_inv2) < 0.) - F_ERROR; -/* Calculation based on view angles from satellite. */ - tmp = P->radius_g - Vx; - if(P->flip_axis) - { - xy.x = P->radius_g_1 * atan (Vy / hypot (Vz, tmp)); - xy.y = P->radius_g_1 * atan (Vz / tmp); - } - else - { - xy.x = P->radius_g_1 * atan (Vy / tmp); - xy.y = P->radius_g_1 * atan (Vz / hypot (Vy, tmp)); - } - return (xy); + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double r, Vx, Vy, Vz, tmp; + + /* Calculation of geocentric latitude. */ + lp.phi = atan (Q->radius_p2 * tan (lp.phi)); + + /* Calculation of the three components of the vector from satellite to + ** position on earth surface (lon,lat).*/ + r = (Q->radius_p) / hypot(Q->radius_p * cos (lp.phi), sin (lp.phi)); + Vx = r * cos (lp.lam) * cos (lp.phi); + Vy = r * sin (lp.lam) * cos (lp.phi); + Vz = r * sin (lp.phi); + + /* Check visibility. */ + if (((Q->radius_g - Vx) * Vx - Vy * Vy - Vz * Vz * Q->radius_p_inv2) < 0.) + F_ERROR; + + /* Calculation based on view angles from satellite. */ + tmp = Q->radius_g - Vx; + + if(Q->flip_axis) { + xy.x = Q->radius_g_1 * atan (Vy / hypot (Vz, tmp)); + xy.y = Q->radius_g_1 * atan (Vz / tmp); + } else { + xy.x = Q->radius_g_1 * atan (Vy / tmp); + xy.y = Q->radius_g_1 * atan (Vz / hypot (Vy, tmp)); + } + + return xy; } -INVERSE(s_inverse); /* spheroid */ - double Vx, Vy, Vz, a, b, det, k; - -/* Setting three components of vector from satellite to position.*/ - Vx = -1.0; - if(P->flip_axis) - { - Vz = tan (xy.y / (P->radius_g - 1.0)); - Vy = tan (xy.x / (P->radius_g - 1.0)) * sqrt (1.0 + Vz * Vz); - } - else - { - Vy = tan (xy.x / (P->radius_g - 1.0)); - Vz = tan (xy.y / (P->radius_g - 1.0)) * sqrt (1.0 + Vy * Vy); - } -/* Calculation of terms in cubic equation and determinant.*/ - a = Vy * Vy + Vz * Vz + Vx * Vx; - b = 2 * P->radius_g * Vx; - if ((det = (b * b) - 4 * a * P->C) < 0.) I_ERROR; -/* Calculation of three components of vector from satellite to position.*/ - k = (-b - sqrt(det)) / (2 * a); - Vx = P->radius_g + k * Vx; - Vy *= k; - Vz *= k; -/* Calculation of longitude and latitude.*/ - lp.lam = atan2 (Vy, Vx); - lp.phi = atan (Vz * cos (lp.lam) / Vx); - return (lp); + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double Vx, Vy, Vz, a, b, det, k; + + /* Setting three components of vector from satellite to position.*/ + Vx = -1.0; + if(Q->flip_axis) { + Vz = tan (xy.y / (Q->radius_g - 1.0)); + Vy = tan (xy.x / (Q->radius_g - 1.0)) * sqrt (1.0 + Vz * Vz); + } else { + Vy = tan (xy.x / (Q->radius_g - 1.0)); + Vz = tan (xy.y / (Q->radius_g - 1.0)) * sqrt (1.0 + Vy * Vy); + } + + /* Calculation of terms in cubic equation and determinant.*/ + a = Vy * Vy + Vz * Vz + Vx * Vx; + b = 2 * Q->radius_g * Vx; + if ((det = (b * b) - 4 * a * Q->C) < 0.) I_ERROR; + + /* Calculation of three components of vector from satellite to position.*/ + k = (-b - sqrt(det)) / (2 * a); + Vx = Q->radius_g + k * Vx; + Vy *= k; + Vz *= k; + + /* Calculation of longitude and latitude.*/ + lp.lam = atan2 (Vy, Vx); + lp.phi = atan (Vz * cos (lp.lam) / Vx); + + return lp; } -INVERSE(e_inverse); /* ellipsoid */ - double Vx, Vy, Vz, a, b, det, k; - -/* Setting three components of vector from satellite to position.*/ - Vx = -1.0; - if(P->flip_axis) - { - Vz = tan (xy.y / P->radius_g_1); - Vy = tan (xy.x / P->radius_g_1) * hypot(1.0, Vz); - } - else - { - Vy = tan (xy.x / P->radius_g_1); - Vz = tan (xy.y / P->radius_g_1) * hypot(1.0, Vy); - } -/* Calculation of terms in cubic equation and determinant.*/ - a = Vz / P->radius_p; - a = Vy * Vy + a * a + Vx * Vx; - b = 2 * P->radius_g * Vx; - if ((det = (b * b) - 4 * a * P->C) < 0.) I_ERROR; -/* Calculation of three components of vector from satellite to position.*/ - k = (-b - sqrt(det)) / (2. * a); - Vx = P->radius_g + k * Vx; - Vy *= k; - Vz *= k; -/* Calculation of longitude and latitude.*/ - lp.lam = atan2 (Vy, Vx); - lp.phi = atan (Vz * cos (lp.lam) / Vx); - lp.phi = atan (P->radius_p_inv2 * tan (lp.phi)); - return (lp); + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double Vx, Vy, Vz, a, b, det, k; + + /* Setting three components of vector from satellite to position.*/ + Vx = -1.0; + + if(Q->flip_axis) { + Vz = tan (xy.y / Q->radius_g_1); + Vy = tan (xy.x / Q->radius_g_1) * hypot(1.0, Vz); + } else { + Vy = tan (xy.x / Q->radius_g_1); + Vz = tan (xy.y / Q->radius_g_1) * hypot(1.0, Vy); + } + + /* Calculation of terms in cubic equation and determinant.*/ + a = Vz / Q->radius_p; + a = Vy * Vy + a * a + Vx * Vx; + b = 2 * Q->radius_g * Vx; + if ((det = (b * b) - 4 * a * Q->C) < 0.) I_ERROR; + + /* Calculation of three components of vector from satellite to position.*/ + k = (-b - sqrt(det)) / (2. * a); + Vx = Q->radius_g + k * Vx; + Vy *= k; + Vz *= k; + + /* Calculation of longitude and latitude.*/ + lp.lam = atan2 (Vy, Vx); + lp.phi = atan (Vz * cos (lp.lam) / Vx); + lp.phi = atan (Q->radius_p_inv2 * tan (lp.phi)); + + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); } -FREEUP; if (P) free(P); } -ENTRY0(geos) - if ((P->h = pj_param(P->ctx, P->params, "dh").f) <= 0.) E_ERROR(-30); - if (P->phi0) E_ERROR(-46); - P->sweep_axis = pj_param(P->ctx, P->params, "ssweep").s; - if (P->sweep_axis == NULL) - P->flip_axis = 0; + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(geos) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + if ((Q->h = pj_param(P->ctx, P->params, "dh").f) <= 0.) E_ERROR(-30); + + if (P->phi0) E_ERROR(-46); + + Q->sweep_axis = pj_param(P->ctx, P->params, "ssweep").s; + if (Q->sweep_axis == NULL) + Q->flip_axis = 0; + else { + if (Q->sweep_axis[1] != '\0' || + (Q->sweep_axis[0] != 'x' && + Q->sweep_axis[0] != 'y')) + E_ERROR(-49); + if (Q->sweep_axis[0] == 'x') + Q->flip_axis = 1; else - { - if (P->sweep_axis[1] != '\0' || - (P->sweep_axis[0] != 'x' && - P->sweep_axis[0] != 'y')) - E_ERROR(-49); - if (P->sweep_axis[0] == 'x') - P->flip_axis = 1; - else - P->flip_axis = 0; - } - P->radius_g_1 = P->h / P->a; - P->radius_g = 1. + P->radius_g_1; - P->C = P->radius_g * P->radius_g - 1.0; - if (P->es) { - P->radius_p = sqrt (P->one_es); - P->radius_p2 = P->one_es; - P->radius_p_inv2 = P->rone_es; - P->inv = e_inverse; - P->fwd = e_forward; - } else { - P->radius_p = P->radius_p2 = P->radius_p_inv2 = 1.0; - P->inv = s_inverse; - P->fwd = s_forward; - } -ENDENTRY(P) + Q->flip_axis = 0; + } + + Q->radius_g_1 = Q->h / P->a; + Q->radius_g = 1. + Q->radius_g_1; + Q->C = Q->radius_g * Q->radius_g - 1.0; + if (P->es) { + Q->radius_p = sqrt (P->one_es); + Q->radius_p2 = P->one_es; + Q->radius_p_inv2 = P->rone_es; + P->inv = e_inverse; + P->fwd = e_forward; + } else { + Q->radius_p = Q->radius_p2 = Q->radius_p_inv2 = 1.0; + P->inv = s_inverse; + P->fwd = s_forward; + } + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_geos_selftest (void) {return 0;} +#else + +int pj_geos_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=geos +ellps=GRS80 +lat_1=0.5 +lat_2=2 +h=35785831"}; + char s_args[] = {"+proj=geos +a=6400000 +lat_1=0.5 +lat_2=2 +h=35785831"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222527.07036580026, 110551.30341332949}, + { 222527.07036580026, -110551.30341332949}, + {-222527.07036580026, 110551.30341332949}, + {-222527.07036580026, -110551.30341332949}, + }; + + XY s_fwd_expect[] = { + { 223289.45763579503, 111677.65745653701}, + { 223289.45763579503, -111677.65745653701}, + {-223289.45763579503, 111677.65745653701}, + {-223289.45763579503, -111677.65745653701}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.0017966305689715385, 0.00090436947723267452}, + { 0.0017966305689715385, -0.00090436947723267452}, + {-0.0017966305689715385, 0.00090436947723267452}, + {-0.0017966305689715385, -0.00090436947723267452}, + }; + + LP s_inv_expect[] = { + { 0.0017904931105078943, 0.00089524655504237148}, + { 0.0017904931105078943, -0.00089524655504237148}, + {-0.0017904931105078943, 0.00089524655504237148}, + {-0.0017904931105078943, -0.00089524655504237148}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 8531aac07f11691fafa2704d357373459b6e9075 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Mon, 18 Apr 2016 12:32:21 +0200 Subject: Converted gins8. Expanded tabs. --- src/PJ_aea.c | 1 - src/PJ_gins8.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 72 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index c5f808a5..d99217bb 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -360,7 +360,6 @@ int pj_eqc_selftest (void) {return 10000;} int pj_eqdc_selftest (void) {return 10000;} int pj_etmerc_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} -int pj_gins8_selftest (void) {return 10000;} int pj_gn_sinu_selftest (void) {return 10000;} int pj_gnom_selftest (void) {return 10000;} int pj_goode_selftest (void) {return 10000;} diff --git a/src/PJ_gins8.c b/src/PJ_gins8.c index b7f38ad9..3eae7efa 100644 --- a/src/PJ_gins8.c +++ b/src/PJ_gins8.c @@ -1,18 +1,75 @@ #define PJ_LIB__ -# include +#include + PROJ_HEAD(gins8, "Ginsburg VIII (TsNIIGAiK)") "\n\tPCyl, Sph., no inv."; -#define Cl 0.000952426 -#define Cp 0.162388 -#define C12 0.08333333333333333 -FORWARD(s_forward); /* spheroid */ - double t = lp.phi * lp.phi; - (void) P; - - xy.y = lp.phi * (1. + t * C12); - xy.x = lp.lam * (1. - Cp * t); - t = lp.lam * lp.lam; - xy.x *= (0.87 - Cl * t * t); - return (xy); + +#define Cl 0.000952426 +#define Cp 0.162388 +#define C12 0.08333333333333333 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + double t = lp.phi * lp.phi; + (void) P; + + xy.y = lp.phi * (1. + t * C12); + xy.x = lp.lam * (1. - Cp * t); + t = lp.lam * lp.lam; + xy.x *= (0.87 - Cl * t * t); + + return xy; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(gins8) { + P->es = 0.0; + P->inv = 0; + P->fwd = s_forward; + + return P; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(gins8) P->es = 0.; P->inv = 0; P->fwd = s_forward; ENDENTRY(P) + + +#ifdef PJ_OMIT_SELFTEST +int pj_gins8_selftest (void) {return 0;} +#else + +int pj_gins8_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=gins8 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 194350.25093959007, 111703.90763533533}, + { 194350.25093959007, -111703.90763533533}, + {-194350.25093959007, 111703.90763533533}, + {-194350.25093959007, -111703.90763533533}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} + + +#endif -- cgit v1.2.3 From efffe811ed95d6e34f3eff1e2010d50d6f81682e Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Mon, 18 Apr 2016 13:10:48 +0200 Subject: Converted gnom. Expanded tabs. --- src/PJ_aea.c | 1 - src/PJ_gnom.c | 287 ++++++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 187 insertions(+), 101 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index d99217bb..4db5e386 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -361,7 +361,6 @@ int pj_eqdc_selftest (void) {return 10000;} int pj_etmerc_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} int pj_gn_sinu_selftest (void) {return 10000;} -int pj_gnom_selftest (void) {return 10000;} int pj_goode_selftest (void) {return 10000;} int pj_gs48_selftest (void) {return 10000;} int pj_gs50_selftest (void) {return 10000;} diff --git a/src/PJ_gnom.c b/src/PJ_gnom.c index 11deb86c..151f718e 100644 --- a/src/PJ_gnom.c +++ b/src/PJ_gnom.c @@ -1,105 +1,192 @@ -#define PROJ_PARMS__ \ - double sinph0; \ - double cosph0; \ - int mode; #define PJ_LIB__ -#include +#include + PROJ_HEAD(gnom, "Gnomonic") "\n\tAzi, Sph."; -#define EPS10 1.e-10 -#define N_POLE 0 + +#define EPS10 1.e-10 +#define N_POLE 0 #define S_POLE 1 -#define EQUIT 2 -#define OBLIQ 3 -FORWARD(s_forward); /* spheroid */ - double coslam, cosphi, sinphi; - - sinphi = sin(lp.phi); - cosphi = cos(lp.phi); - coslam = cos(lp.lam); - switch (P->mode) { - case EQUIT: - xy.y = cosphi * coslam; - break; - case OBLIQ: - xy.y = P->sinph0 * sinphi + P->cosph0 * cosphi * coslam; - break; - case S_POLE: - xy.y = - sinphi; - break; - case N_POLE: - xy.y = sinphi; - break; - } - if (xy.y <= EPS10) F_ERROR; - xy.x = (xy.y = 1. / xy.y) * cosphi * sin(lp.lam); - switch (P->mode) { - case EQUIT: - xy.y *= sinphi; - break; - case OBLIQ: - xy.y *= P->cosph0 * sinphi - P->sinph0 * cosphi * coslam; - break; - case N_POLE: - coslam = - coslam; - case S_POLE: - xy.y *= cosphi * coslam; - break; - } - return (xy); +#define EQUIT 2 +#define OBLIQ 3 + +struct pj_opaque { + double sinph0; + double cosph0; + int mode; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double coslam, cosphi, sinphi; + + sinphi = sin(lp.phi); + cosphi = cos(lp.phi); + coslam = cos(lp.lam); + + switch (Q->mode) { + case EQUIT: + xy.y = cosphi * coslam; + break; + case OBLIQ: + xy.y = Q->sinph0 * sinphi + Q->cosph0 * cosphi * coslam; + break; + case S_POLE: + xy.y = - sinphi; + break; + case N_POLE: + xy.y = sinphi; + break; + } + + if (xy.y <= EPS10) F_ERROR; + + xy.x = (xy.y = 1. / xy.y) * cosphi * sin(lp.lam); + switch (Q->mode) { + case EQUIT: + xy.y *= sinphi; + break; + case OBLIQ: + xy.y *= Q->cosph0 * sinphi - Q->sinph0 * cosphi * coslam; + break; + case N_POLE: + coslam = - coslam; + case S_POLE: + xy.y *= cosphi * coslam; + break; + } + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double rh, cosz, sinz; + + rh = hypot(xy.x, xy.y); + sinz = sin(lp.phi = atan(rh)); + cosz = sqrt(1. - sinz * sinz); + + if (fabs(rh) <= EPS10) { + lp.phi = P->phi0; + lp.lam = 0.; + } else { + switch (Q->mode) { + case OBLIQ: + lp.phi = cosz * Q->sinph0 + xy.y * sinz * Q->cosph0 / rh; + if (fabs(lp.phi) >= 1.) + lp.phi = lp.phi > 0. ? HALFPI : - HALFPI; + else + lp.phi = asin(lp.phi); + xy.y = (cosz - Q->sinph0 * sin(lp.phi)) * rh; + xy.x *= sinz * Q->cosph0; + break; + case EQUIT: + lp.phi = xy.y * sinz / rh; + if (fabs(lp.phi) >= 1.) + lp.phi = lp.phi > 0. ? HALFPI : - HALFPI; + else + lp.phi = asin(lp.phi); + xy.y = cosz * rh; + xy.x *= sinz; + break; + case S_POLE: + lp.phi -= HALFPI; + break; + case N_POLE: + lp.phi = HALFPI - lp.phi; + xy.y = -xy.y; + break; + } + lp.lam = atan2(xy.x, xy.y); + } + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; } -INVERSE(s_inverse); /* spheroid */ - double rh, cosz, sinz; - - rh = hypot(xy.x, xy.y); - sinz = sin(lp.phi = atan(rh)); - cosz = sqrt(1. - sinz * sinz); - if (fabs(rh) <= EPS10) { - lp.phi = P->phi0; - lp.lam = 0.; - } else { - switch (P->mode) { - case OBLIQ: - lp.phi = cosz * P->sinph0 + xy.y * sinz * P->cosph0 / rh; - if (fabs(lp.phi) >= 1.) - lp.phi = lp.phi > 0. ? HALFPI : - HALFPI; - else - lp.phi = asin(lp.phi); - xy.y = (cosz - P->sinph0 * sin(lp.phi)) * rh; - xy.x *= sinz * P->cosph0; - break; - case EQUIT: - lp.phi = xy.y * sinz / rh; - if (fabs(lp.phi) >= 1.) - lp.phi = lp.phi > 0. ? HALFPI : - HALFPI; - else - lp.phi = asin(lp.phi); - xy.y = cosz * rh; - xy.x *= sinz; - break; - case S_POLE: - lp.phi -= HALFPI; - break; - case N_POLE: - lp.phi = HALFPI - lp.phi; - xy.y = -xy.y; - break; - } - lp.lam = atan2(xy.x, xy.y); - } - return (lp); + + +PJ *PROJECTION(gnom) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + if (fabs(fabs(P->phi0) - HALFPI) < EPS10) { + Q->mode = P->phi0 < 0. ? S_POLE : N_POLE; + } else if (fabs(P->phi0) < EPS10) { + Q->mode = EQUIT; + } else { + Q->mode = OBLIQ; + Q->sinph0 = sin(P->phi0); + Q->cosph0 = cos(P->phi0); + } + + P->inv = s_inverse; + P->fwd = s_forward; + P->es = 0.; + + return P; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(gnom) - if (fabs(fabs(P->phi0) - HALFPI) < EPS10) - P->mode = P->phi0 < 0. ? S_POLE : N_POLE; - else if (fabs(P->phi0) < EPS10) - P->mode = EQUIT; - else { - P->mode = OBLIQ; - P->sinph0 = sin(P->phi0); - P->cosph0 = cos(P->phi0); - } - P->inv = s_inverse; - P->fwd = s_forward; - P->es = 0.; -ENDENTRY(P) + + +#ifdef PJ_OMIT_SELFTEST +int pj_gnom_selftest (void) {return 0;} +#else + +int pj_gnom_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=gnom +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223492.92474718543, 111780.50920659291}, + { 223492.92474718543, -111780.50920659291}, + {-223492.92474718543, 111780.50920659291}, + {-223492.92474718543, -111780.50920659291}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0017904931092009798, 0.00089524655438192376}, + { 0.0017904931092009798, -0.00089524655438192376}, + {-0.0017904931092009798, 0.00089524655438192376}, + {-0.0017904931092009798, -0.00089524655438192376}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From d96ad04833f4c857d4dda2560387b8e8053d821b Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Mon, 18 Apr 2016 14:02:19 +0200 Subject: Expanded tabs and removed trailing whitespace in an attempt at getting cleaner diffs for upcomming commits. --- src/PJ_gn_sinu.c | 132 ++--- src/PJ_goode.c | 70 +-- src/PJ_gstmerc.c | 30 +- src/PJ_hammer.c | 62 +-- src/PJ_hatano.c | 80 +-- src/PJ_healpix.c | 532 +++++++++--------- src/PJ_igh.c | 12 +- src/PJ_imw_p.c | 254 ++++----- src/PJ_isea.c | 1612 +++++++++++++++++++++++++++--------------------------- src/PJ_krovak.c | 192 +++---- 10 files changed, 1488 insertions(+), 1488 deletions(-) (limited to 'src') diff --git a/src/PJ_gn_sinu.c b/src/PJ_gn_sinu.c index bfd8bc2d..1ab43826 100644 --- a/src/PJ_gn_sinu.c +++ b/src/PJ_gn_sinu.c @@ -1,98 +1,98 @@ #define PROJ_PARMS__ \ - double *en; \ - double m, n, C_x, C_y; + double *en; \ + double m, n, C_x, C_y; #define PJ_LIB__ -#include +#include PROJ_HEAD(gn_sinu, "General Sinusoidal Series") "\n\tPCyl, Sph.\n\tm= n="; PROJ_HEAD(sinu, "Sinusoidal (Sanson-Flamsteed)") "\n\tPCyl, Sph&Ell"; PROJ_HEAD(eck6, "Eckert VI") "\n\tPCyl, Sph."; PROJ_HEAD(mbtfps, "McBryde-Thomas Flat-Polar Sinusoidal") "\n\tPCyl, Sph."; -#define EPS10 1e-10 +#define EPS10 1e-10 #define MAX_ITER 8 #define LOOP_TOL 1e-7 /* Ellipsoidal Sinusoidal only */ FORWARD(e_forward); /* ellipsoid */ - double s, c; + double s, c; - xy.y = pj_mlfn(lp.phi, s = sin(lp.phi), c = cos(lp.phi), P->en); - xy.x = lp.lam * c / sqrt(1. - P->es * s * s); - return (xy); + xy.y = pj_mlfn(lp.phi, s = sin(lp.phi), c = cos(lp.phi), P->en); + xy.x = lp.lam * c / sqrt(1. - P->es * s * s); + return (xy); } INVERSE(e_inverse); /* ellipsoid */ - double s; + double s; - if ((s = fabs(lp.phi = pj_inv_mlfn(P->ctx, xy.y, P->es, P->en))) < HALFPI) { - s = sin(lp.phi); - lp.lam = xy.x * sqrt(1. - P->es * s * s) / cos(lp.phi); - } else if ((s - EPS10) < HALFPI) - lp.lam = 0.; - else I_ERROR; - return (lp); + if ((s = fabs(lp.phi = pj_inv_mlfn(P->ctx, xy.y, P->es, P->en))) < HALFPI) { + s = sin(lp.phi); + lp.lam = xy.x * sqrt(1. - P->es * s * s) / cos(lp.phi); + } else if ((s - EPS10) < HALFPI) + lp.lam = 0.; + else I_ERROR; + return (lp); } /* General spherical sinusoidals */ FORWARD(s_forward); /* sphere */ - if (!P->m) - lp.phi = P->n != 1. ? aasin(P->ctx,P->n * sin(lp.phi)): lp.phi; - else { - double k, V; - int i; + if (!P->m) + lp.phi = P->n != 1. ? aasin(P->ctx,P->n * sin(lp.phi)): lp.phi; + else { + double k, V; + int i; - k = P->n * sin(lp.phi); - for (i = MAX_ITER; i ; --i) { - lp.phi -= V = (P->m * lp.phi + sin(lp.phi) - k) / - (P->m + cos(lp.phi)); - if (fabs(V) < LOOP_TOL) - break; - } - if (!i) - F_ERROR - } - xy.x = P->C_x * lp.lam * (P->m + cos(lp.phi)); - xy.y = P->C_y * lp.phi; - return (xy); + k = P->n * sin(lp.phi); + for (i = MAX_ITER; i ; --i) { + lp.phi -= V = (P->m * lp.phi + sin(lp.phi) - k) / + (P->m + cos(lp.phi)); + if (fabs(V) < LOOP_TOL) + break; + } + if (!i) + F_ERROR + } + xy.x = P->C_x * lp.lam * (P->m + cos(lp.phi)); + xy.y = P->C_y * lp.phi; + return (xy); } INVERSE(s_inverse); /* sphere */ - xy.y /= P->C_y; - lp.phi = P->m ? aasin(P->ctx,(P->m * xy.y + sin(xy.y)) / P->n) : - ( P->n != 1. ? aasin(P->ctx,sin(xy.y) / P->n) : xy.y ); - lp.lam = xy.x / (P->C_x * (P->m + cos(xy.y))); - return (lp); + xy.y /= P->C_y; + lp.phi = P->m ? aasin(P->ctx,(P->m * xy.y + sin(xy.y)) / P->n) : + ( P->n != 1. ? aasin(P->ctx,sin(xy.y) / P->n) : xy.y ); + lp.lam = xy.x / (P->C_x * (P->m + cos(xy.y))); + return (lp); } FREEUP; if (P) { if (P->en) pj_dalloc(P->en); pj_dalloc(P); } } - static void /* for spheres, only */ + static void /* for spheres, only */ setup(PJ *P) { - P->es = 0; - P->C_x = (P->C_y = sqrt((P->m + 1.) / P->n))/(P->m + 1.); - P->inv = s_inverse; - P->fwd = s_forward; + P->es = 0; + P->C_x = (P->C_y = sqrt((P->m + 1.) / P->n))/(P->m + 1.); + P->inv = s_inverse; + P->fwd = s_forward; } ENTRY1(sinu, en) - if (!(P->en = pj_enfn(P->es))) - E_ERROR_0; - if (P->es) { - P->inv = e_inverse; - P->fwd = e_forward; - } else { - P->n = 1.; - P->m = 0.; - setup(P); - } + if (!(P->en = pj_enfn(P->es))) + E_ERROR_0; + if (P->es) { + P->inv = e_inverse; + P->fwd = e_forward; + } else { + P->n = 1.; + P->m = 0.; + setup(P); + } ENDENTRY(P) ENTRY1(eck6, en) - P->m = 1.; - P->n = 2.570796326794896619231321691; - setup(P); + P->m = 1.; + P->n = 2.570796326794896619231321691; + setup(P); ENDENTRY(P) ENTRY1(mbtfps, en) - P->m = 0.5; - P->n = 1.785398163397448309615660845; - setup(P); + P->m = 0.5; + P->n = 1.785398163397448309615660845; + setup(P); ENDENTRY(P) ENTRY1(gn_sinu, en) - if (pj_param(P->ctx, P->params, "tn").i && pj_param(P->ctx, P->params, "tm").i) { - P->n = pj_param(P->ctx, P->params, "dn").f; - P->m = pj_param(P->ctx, P->params, "dm").f; - } else - E_ERROR(-99) - setup(P); + if (pj_param(P->ctx, P->params, "tn").i && pj_param(P->ctx, P->params, "tm").i) { + P->n = pj_param(P->ctx, P->params, "dn").f; + P->m = pj_param(P->ctx, P->params, "dm").f; + } else + E_ERROR(-99) + setup(P); ENDENTRY(P) diff --git a/src/PJ_goode.c b/src/PJ_goode.c index 387557e6..b03e15d1 100644 --- a/src/PJ_goode.c +++ b/src/PJ_goode.c @@ -1,49 +1,49 @@ #define PROJ_PARMS__ \ - struct PJconsts *sinu; \ - struct PJconsts *moll; + struct PJconsts *sinu; \ + struct PJconsts *moll; #define PJ_LIB__ -#include +#include PROJ_HEAD(goode, "Goode Homolosine") "\n\tPCyl, Sph."; - C_NAMESPACE PJ + C_NAMESPACE PJ *pj_sinu(PJ *), *pj_moll(PJ *); -#define Y_COR 0.05280 -#define PHI_LIM .71093078197902358062 +#define Y_COR 0.05280 +#define PHI_LIM .71093078197902358062 FORWARD(s_forward); /* spheroid */ - if (fabs(lp.phi) <= PHI_LIM) - xy = P->sinu->fwd(lp, P->sinu); - else { - xy = P->moll->fwd(lp, P->moll); - xy.y -= lp.phi >= 0.0 ? Y_COR : -Y_COR; - } - return (xy); + if (fabs(lp.phi) <= PHI_LIM) + xy = P->sinu->fwd(lp, P->sinu); + else { + xy = P->moll->fwd(lp, P->moll); + xy.y -= lp.phi >= 0.0 ? Y_COR : -Y_COR; + } + return (xy); } INVERSE(s_inverse); /* spheroid */ - if (fabs(xy.y) <= PHI_LIM) - lp = P->sinu->inv(xy, P->sinu); - else { - xy.y += xy.y >= 0.0 ? Y_COR : -Y_COR; - lp = P->moll->inv(xy, P->moll); - } - return (lp); + if (fabs(xy.y) <= PHI_LIM) + lp = P->sinu->inv(xy, P->sinu); + else { + xy.y += xy.y >= 0.0 ? Y_COR : -Y_COR; + lp = P->moll->inv(xy, P->moll); + } + return (lp); } FREEUP; - if (P) { - if (P->sinu) - (*(P->sinu->pfree))(P->sinu); - if (P->moll) - (*(P->moll->pfree))(P->moll); - pj_dalloc(P); - } + if (P) { + if (P->sinu) + (*(P->sinu->pfree))(P->sinu); + if (P->moll) + (*(P->moll->pfree))(P->moll); + pj_dalloc(P); + } } ENTRY2(goode, sinu, moll) - P->es = 0.; - if (!(P->sinu = pj_sinu(0)) || !(P->moll = pj_moll(0))) - E_ERROR_0; - P->sinu->es = 0.; + P->es = 0.; + if (!(P->sinu = pj_sinu(0)) || !(P->moll = pj_moll(0))) + E_ERROR_0; + P->sinu->es = 0.; P->sinu->ctx = P->ctx; P->moll->ctx = P->ctx; - if (!(P->sinu = pj_sinu(P->sinu)) || !(P->moll = pj_moll(P->moll))) - E_ERROR_0; - P->fwd = s_forward; - P->inv = s_inverse; + if (!(P->sinu = pj_sinu(P->sinu)) || !(P->moll = pj_moll(P->moll))) + E_ERROR_0; + P->fwd = s_forward; + P->inv = s_inverse; ENDENTRY(P) diff --git a/src/PJ_gstmerc.c b/src/PJ_gstmerc.c index bffe0b26..da67389f 100644 --- a/src/PJ_gstmerc.c +++ b/src/PJ_gstmerc.c @@ -1,36 +1,36 @@ #define PROJ_PARMS__ \ - double lamc;\ - double phic;\ - double c;\ - double n1;\ - double n2;\ + double lamc;\ + double phic;\ + double c;\ + double n1;\ + double n2;\ double XS;\ double YS; #define PJ_LIB__ -# include +# include PROJ_HEAD(gstmerc, "Gauss-Schreiber Transverse Mercator (aka Gauss-Laborde Reunion)") - "\n\tCyl, Sph&Ell\n\tlat_0= lon_0= k_0="; + "\n\tCyl, Sph&Ell\n\tlat_0= lon_0= k_0="; FORWARD(s_forward); /* spheroid */ - double L, Ls, sinLs1, Ls1; - L= P->n1*lp.lam; + double L, Ls, sinLs1, Ls1; + L= P->n1*lp.lam; Ls= P->c+P->n1*log(pj_tsfn(-1.0*lp.phi,-1.0*sin(lp.phi),P->e)); sinLs1= sin(L)/cosh(Ls); Ls1= log(pj_tsfn(-1.0*asin(sinLs1),0.0,0.0)); xy.x= (P->XS + P->n2*Ls1)*P->ra; xy.y= (P->YS + P->n2*atan(sinh(Ls)/cos(L)))*P->ra; /*fprintf(stderr,"fwd:\nL =%16.13f\nLs =%16.13f\nLs1 =%16.13f\nLP(%16.13f,%16.13f)=XY(%16.4f,%16.4f)\n",L,Ls,Ls1,lp.lam+P->lam0,lp.phi,(xy.x*P->a + P->x0)*P->to_meter,(xy.y*P->a + P->y0)*P->to_meter);*/ - return (xy); + return (xy); } INVERSE(s_inverse); /* spheroid */ - double L, LC, sinC; - L= atan(sinh((xy.x*P->a - P->XS)/P->n2)/cos((xy.y*P->a - P->YS)/P->n2)); + double L, LC, sinC; + L= atan(sinh((xy.x*P->a - P->XS)/P->n2)/cos((xy.y*P->a - P->YS)/P->n2)); sinC= sin((xy.y*P->a - P->YS)/P->n2)/cosh((xy.x*P->a - P->XS)/P->n2); LC= log(pj_tsfn(-1.0*asin(sinC),0.0,0.0)); lp.lam= L/P->n1; lp.phi= -1.0*pj_phi2(P->ctx, exp((LC-P->c)/P->n1),P->e); /*fprintf(stderr,"inv:\nL =%16.13f\nsinC =%16.13f\nLC =%16.13f\nXY(%16.4f,%16.4f)=LP(%16.13f,%16.13f)\n",L,sinC,LC,((xy.x/P->ra)+P->x0)/P->to_meter,((xy.y/P->ra)+P->y0)/P->to_meter,lp.lam+P->lam0,lp.phi);*/ - return (lp); + return (lp); } FREEUP; if (P) pj_dalloc(P); } ENTRY0(gstmerc) @@ -42,7 +42,7 @@ ENTRY0(gstmerc) P->n2= P->k0*P->a*sqrt(1.0-P->es)/(1.0-P->es*sin(P->phi0)*sin(P->phi0)); P->XS= 0;/* -P->x0 */ P->YS= -1.0*P->n2*P->phic;/* -P->y0 */ - P->inv= s_inverse; - P->fwd= s_forward; + P->inv= s_inverse; + P->fwd= s_forward; /*fprintf(stderr,"a (m) =%16.4f\ne =%16.13f\nl0(rad)=%16.13f\np0(rad)=%16.13f\nk0 =%16.4f\nX0 (m)=%16.4f\nY0 (m)=%16.4f\n\nlC(rad)=%16.13f\npC(rad)=%16.13f\nc =%16.13f\nn1 =%16.13f\nn2 (m) =%16.4f\nXS (m) =%16.4f\nYS (m) =%16.4f\n", P->a, P->e, P->lam0, P->phi0, P->k0, P->x0, P->y0, P->lamc, P->phic, P->c, P->n1, P->n2, P->XS +P->x0, P->YS + P->y0);*/ ENDENTRY(P) diff --git a/src/PJ_hammer.c b/src/PJ_hammer.c index 31e7a127..8b15fe50 100644 --- a/src/PJ_hammer.c +++ b/src/PJ_hammer.c @@ -1,43 +1,43 @@ #define PROJ_PARMS__ \ - double w; \ - double m, rm; + double w; \ + double m, rm; #define PJ_LIB__ #define EPS 1.0e-10 -# include +# include PROJ_HEAD(hammer, "Hammer & Eckert-Greifendorff") - "\n\tMisc Sph, \n\tW= M="; + "\n\tMisc Sph, \n\tW= M="; FORWARD(s_forward); /* spheroid */ - double cosphi, d; + double cosphi, d; - d = sqrt(2./(1. + (cosphi = cos(lp.phi)) * cos(lp.lam *= P->w))); - xy.x = P->m * d * cosphi * sin(lp.lam); - xy.y = P->rm * d * sin(lp.phi); - return (xy); + d = sqrt(2./(1. + (cosphi = cos(lp.phi)) * cos(lp.lam *= P->w))); + xy.x = P->m * d * cosphi * sin(lp.lam); + xy.y = P->rm * d * sin(lp.phi); + return (xy); } INVERSE(s_inverse); /* spheroid */ - double z; - z = sqrt(1. - 0.25*P->w*P->w*xy.x*xy.x - 0.25*xy.y*xy.y); - if (fabs(2.*z*z-1.) < EPS) { - lp.lam = HUGE_VAL; - lp.phi = HUGE_VAL; - pj_errno = -14; - } else { - lp.lam = aatan2(P->w * xy.x * z,2. * z * z - 1)/P->w; - lp.phi = aasin(P->ctx,z * xy.y); - } - return (lp); + double z; + z = sqrt(1. - 0.25*P->w*P->w*xy.x*xy.x - 0.25*xy.y*xy.y); + if (fabs(2.*z*z-1.) < EPS) { + lp.lam = HUGE_VAL; + lp.phi = HUGE_VAL; + pj_errno = -14; + } else { + lp.lam = aatan2(P->w * xy.x * z,2. * z * z - 1)/P->w; + lp.phi = aasin(P->ctx,z * xy.y); + } + return (lp); } FREEUP; if (P) pj_dalloc(P); } ENTRY0(hammer) - if (pj_param(P->ctx, P->params, "tW").i) { - if ((P->w = fabs(pj_param(P->ctx, P->params, "dW").f)) <= 0.) E_ERROR(-27); - } else - P->w = .5; - if (pj_param(P->ctx, P->params, "tM").i) { - if ((P->m = fabs(pj_param(P->ctx, P->params, "dM").f)) <= 0.) E_ERROR(-27); - } else - P->m = 1.; - P->rm = 1. / P->m; - P->m /= P->w; - P->es = 0.; P->fwd = s_forward; P->inv = s_inverse; + if (pj_param(P->ctx, P->params, "tW").i) { + if ((P->w = fabs(pj_param(P->ctx, P->params, "dW").f)) <= 0.) E_ERROR(-27); + } else + P->w = .5; + if (pj_param(P->ctx, P->params, "tM").i) { + if ((P->m = fabs(pj_param(P->ctx, P->params, "dM").f)) <= 0.) E_ERROR(-27); + } else + P->m = 1.; + P->rm = 1. / P->m; + P->m /= P->w; + P->es = 0.; P->fwd = s_forward; P->inv = s_inverse; ENDENTRY(P) diff --git a/src/PJ_hatano.c b/src/PJ_hatano.c index 7516ba6e..4ba9d6e8 100644 --- a/src/PJ_hatano.c +++ b/src/PJ_hatano.c @@ -1,51 +1,51 @@ #define PJ_LIB__ -#include +#include PROJ_HEAD(hatano, "Hatano Asymmetrical Equal Area") "\n\tPCyl, Sph."; -#define NITER 20 -#define EPS 1e-7 +#define NITER 20 +#define EPS 1e-7 #define ONETOL 1.000001 -#define CN 2.67595 -#define CS 2.43763 -#define RCN 0.37369906014686373063 -#define RCS 0.41023453108141924738 -#define FYCN 1.75859 -#define FYCS 1.93052 -#define RYCN 0.56863737426006061674 -#define RYCS 0.51799515156538134803 -#define FXC 0.85 -#define RXC 1.17647058823529411764 +#define CN 2.67595 +#define CS 2.43763 +#define RCN 0.37369906014686373063 +#define RCS 0.41023453108141924738 +#define FYCN 1.75859 +#define FYCS 1.93052 +#define RYCN 0.56863737426006061674 +#define RYCS 0.51799515156538134803 +#define FXC 0.85 +#define RXC 1.17647058823529411764 FORWARD(s_forward); /* spheroid */ - double th1, c; - int i; - (void) P; + double th1, c; + int i; + (void) P; - c = sin(lp.phi) * (lp.phi < 0. ? CS : CN); - for (i = NITER; i; --i) { - lp.phi -= th1 = (lp.phi + sin(lp.phi) - c) / (1. + cos(lp.phi)); - if (fabs(th1) < EPS) break; - } - xy.x = FXC * lp.lam * cos(lp.phi *= .5); - xy.y = sin(lp.phi) * (lp.phi < 0. ? FYCS : FYCN); - return (xy); + c = sin(lp.phi) * (lp.phi < 0. ? CS : CN); + for (i = NITER; i; --i) { + lp.phi -= th1 = (lp.phi + sin(lp.phi) - c) / (1. + cos(lp.phi)); + if (fabs(th1) < EPS) break; + } + xy.x = FXC * lp.lam * cos(lp.phi *= .5); + xy.y = sin(lp.phi) * (lp.phi < 0. ? FYCS : FYCN); + return (xy); } INVERSE(s_inverse); /* spheroid */ - double th; + double th; - th = xy.y * ( xy.y < 0. ? RYCS : RYCN); - if (fabs(th) > 1.) - if (fabs(th) > ONETOL) I_ERROR - else th = th > 0. ? HALFPI : - HALFPI; - else - th = asin(th); - lp.lam = RXC * xy.x / cos(th); - th += th; - lp.phi = (th + sin(th)) * (xy.y < 0. ? RCS : RCN); - if (fabs(lp.phi) > 1.) - if (fabs(lp.phi) > ONETOL) I_ERROR - else lp.phi = lp.phi > 0. ? HALFPI : - HALFPI; - else - lp.phi = asin(lp.phi); - return (lp); + th = xy.y * ( xy.y < 0. ? RYCS : RYCN); + if (fabs(th) > 1.) + if (fabs(th) > ONETOL) I_ERROR + else th = th > 0. ? HALFPI : - HALFPI; + else + th = asin(th); + lp.lam = RXC * xy.x / cos(th); + th += th; + lp.phi = (th + sin(th)) * (xy.y < 0. ? RCS : RCN); + if (fabs(lp.phi) > 1.) + if (fabs(lp.phi) > ONETOL) I_ERROR + else lp.phi = lp.phi > 0. ? HALFPI : - HALFPI; + else + lp.phi = asin(lp.phi); + return (lp); } FREEUP; if (P) pj_dalloc(P); } ENTRY0(hatano) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) diff --git a/src/PJ_healpix.c b/src/PJ_healpix.c index 12d57ff2..a645ba34 100644 --- a/src/PJ_healpix.c +++ b/src/PJ_healpix.c @@ -2,10 +2,10 @@ * Project: PROJ.4 * Purpose: Implementation of the HEALPix and rHEALPix projections. * For background see . - * Authors: Alex Raichev (raichev@cs.auckland.ac.nz) + * Authors: Alex Raichev (raichev@cs.auckland.ac.nz) * Michael Speth (spethm@landcareresearch.co.nz) - * Notes: Raichev implemented these projections in Python and - * Speth translated them into C here. + * Notes: Raichev implemented these projections in Python and + * Speth translated them into C here. ****************************************************************************** * Copyright (c) 2001, Thomas Flemming, tf@ttqv.com * @@ -33,17 +33,17 @@ int south_square; \ double qp; \ double *apa; -# define PJ_LIB__ -# include +# define PJ_LIB__ +# include PROJ_HEAD(healpix, "HEALPix") "\n\tSph., Ellps."; PROJ_HEAD(rhealpix, "rHEALPix") "\n\tSph., Ellps.\n\tnorth_square= south_square="; -# include +# include /* Matrix for counterclockwise rotation by pi/2: */ -# define R1 {{ 0,-1},{ 1, 0}} +# define R1 {{ 0,-1},{ 1, 0}} /* Matrix for counterclockwise rotation by pi: */ -# define R2 {{-1, 0},{ 0,-1}} +# define R2 {{-1, 0},{ 0,-1}} /* Matrix for counterclockwise rotation by 3*pi/2: */ -# define R3 {{ 0, 1},{-1, 0}} +# define R3 {{ 0, 1},{-1, 0}} /* Identity matrix */ # define IDENT {{1, 0},{0, 1}} /* IDENT, R1, R2, R3, R1 inverse, R2 inverse, R3 inverse:*/ @@ -74,25 +74,25 @@ double pj_sign (double v) { */ static int get_rotate_index(int index) { switch(index) { - case 0: - return 0; - case 1: - return 1; - case 2: - return 2; - case 3: - return 3; - case -1: - return 4; - case -2: - return 5; - case -3: - return 6; + case 0: + return 0; + case 1: + return 1; + case 2: + return 2; + case 3: + return 3; + case -1: + return 4; + case -2: + return 5; + case -3: + return 6; } return 0; } /** - * Return 1 if point (testx, testy) lies in the interior of the polygon + * Return 1 if point (testx, testy) lies in the interior of the polygon * determined by the vertices in vert, and return 0 otherwise. * See http://paulbourke.net/geometry/polygonmesh/ for more details. * @param nvert the number of vertices in the polygon. @@ -137,69 +137,69 @@ static int pnpoly(int nvert, double vert[][2], double testx, double testy) { } /** * Return 1 if (x, y) lies in (the interior or boundary of) the image of the - * HEALPix projection (in case proj=0) or in the image the rHEALPix projection + * HEALPix projection (in case proj=0) or in the image the rHEALPix projection * (in case proj=1), and return 0 otherwise. - * @param north_square the position of the north polar square (rHEALPix only) - * @param south_square the position of the south polar square (rHEALPix only) + * @param north_square the position of the north polar square (rHEALPix only) + * @param south_square the position of the south polar square (rHEALPix only) **/ int in_image(double x, double y, int proj, int north_square, int south_square) { if (proj == 0) { - double healpixVertsJit[][2] = { - {-1.0*PI- EPS, PI/4.0}, - {-3.0*PI/4.0, PI/2.0 + EPS}, - {-1.0*PI/2.0, PI/4.0 + EPS}, - {-1.0*PI/4.0, PI/2.0 + EPS}, - {0.0, PI/4.0 + EPS}, - {PI/4.0, PI/2.0 + EPS}, - {PI/2.0, PI/4.0 + EPS}, - {3.0*PI/4.0, PI/2.0 + EPS}, - {PI+ EPS, PI/4.0}, - {PI+ EPS, -1.0*PI/4.0}, - {3.0*PI/4.0, -1.0*PI/2.0 - EPS}, - {PI/2.0, -1.0*PI/4.0 - EPS}, - {PI/4.0, -1.0*PI/2.0 - EPS}, - {0.0, -1.0*PI/4.0 - EPS}, - {-1.0*PI/4.0, -1.0*PI/2.0 - EPS}, - {-1.0*PI/2.0, -1.0*PI/4.0 - EPS}, - {-3.0*PI/4.0, -1.0*PI/2.0 - EPS}, - {-1.0*PI - EPS, -1.0*PI/4.0} - }; - return pnpoly((int)sizeof(healpixVertsJit)/ - sizeof(healpixVertsJit[0]), healpixVertsJit, x, y); + double healpixVertsJit[][2] = { + {-1.0*PI- EPS, PI/4.0}, + {-3.0*PI/4.0, PI/2.0 + EPS}, + {-1.0*PI/2.0, PI/4.0 + EPS}, + {-1.0*PI/4.0, PI/2.0 + EPS}, + {0.0, PI/4.0 + EPS}, + {PI/4.0, PI/2.0 + EPS}, + {PI/2.0, PI/4.0 + EPS}, + {3.0*PI/4.0, PI/2.0 + EPS}, + {PI+ EPS, PI/4.0}, + {PI+ EPS, -1.0*PI/4.0}, + {3.0*PI/4.0, -1.0*PI/2.0 - EPS}, + {PI/2.0, -1.0*PI/4.0 - EPS}, + {PI/4.0, -1.0*PI/2.0 - EPS}, + {0.0, -1.0*PI/4.0 - EPS}, + {-1.0*PI/4.0, -1.0*PI/2.0 - EPS}, + {-1.0*PI/2.0, -1.0*PI/4.0 - EPS}, + {-3.0*PI/4.0, -1.0*PI/2.0 - EPS}, + {-1.0*PI - EPS, -1.0*PI/4.0} + }; + return pnpoly((int)sizeof(healpixVertsJit)/ + sizeof(healpixVertsJit[0]), healpixVertsJit, x, y); } else { - double rhealpixVertsJit[][2] = { - {-1.0*PI - EPS, PI/4.0 + EPS}, - {-1.0*PI + north_square*PI/2.0- EPS, PI/4.0 + EPS}, - {-1.0*PI + north_square*PI/2.0- EPS, 3*PI/4.0 + EPS}, - {-1.0*PI + (north_square + 1.0)*PI/2.0 + EPS, 3*PI/4.0 + EPS}, - {-1.0*PI + (north_square + 1.0)*PI/2.0 + EPS, PI/4.0 + EPS}, - {PI + EPS, PI/4.0 + EPS}, - {PI + EPS, -1.0*PI/4.0 - EPS}, - {-1.0*PI + (south_square + 1.0)*PI/2.0 + EPS, -1.0*PI/4.0 - EPS}, - {-1.0*PI + (south_square + 1.0)*PI/2.0 + EPS, -3.0*PI/4.0 - EPS}, - {-1.0*PI + south_square*PI/2.0 - EPS, -3.0*PI/4.0 - EPS}, - {-1.0*PI + south_square*PI/2.0 - EPS, -1.0*PI/4.0 - EPS}, - {-1.0*PI - EPS, -1.0*PI/4.0 - EPS}}; - return pnpoly((int)sizeof(rhealpixVertsJit)/ - sizeof(rhealpixVertsJit[0]), rhealpixVertsJit, x, y); + double rhealpixVertsJit[][2] = { + {-1.0*PI - EPS, PI/4.0 + EPS}, + {-1.0*PI + north_square*PI/2.0- EPS, PI/4.0 + EPS}, + {-1.0*PI + north_square*PI/2.0- EPS, 3*PI/4.0 + EPS}, + {-1.0*PI + (north_square + 1.0)*PI/2.0 + EPS, 3*PI/4.0 + EPS}, + {-1.0*PI + (north_square + 1.0)*PI/2.0 + EPS, PI/4.0 + EPS}, + {PI + EPS, PI/4.0 + EPS}, + {PI + EPS, -1.0*PI/4.0 - EPS}, + {-1.0*PI + (south_square + 1.0)*PI/2.0 + EPS, -1.0*PI/4.0 - EPS}, + {-1.0*PI + (south_square + 1.0)*PI/2.0 + EPS, -3.0*PI/4.0 - EPS}, + {-1.0*PI + south_square*PI/2.0 - EPS, -3.0*PI/4.0 - EPS}, + {-1.0*PI + south_square*PI/2.0 - EPS, -1.0*PI/4.0 - EPS}, + {-1.0*PI - EPS, -1.0*PI/4.0 - EPS}}; + return pnpoly((int)sizeof(rhealpixVertsJit)/ + sizeof(rhealpixVertsJit[0]), rhealpixVertsJit, x, y); } } /** * Return the authalic latitude of latitude alpha (if inverse=0) or - * return the approximate latitude of authalic latitude alpha (if inverse=1). - * P contains the relavent ellipsoid parameters. + * return the approximate latitude of authalic latitude alpha (if inverse=1). + * P contains the relavent ellipsoid parameters. **/ double auth_lat(PJ *P, double alpha, int inverse) { if (inverse == 0) { /* Authalic latitude. */ double q = pj_qsfn(sin(alpha), P->e, 1.0 - P->es); - double qp = P->qp; - double ratio = q/qp; - if (fabsl(ratio) > 1) { - /* Rounding error. */ - ratio = pj_sign(ratio); - } - return asin(ratio); + double qp = P->qp; + double ratio = q/qp; + if (fabsl(ratio) > 1) { + /* Rounding error. */ + ratio = pj_sign(ratio); + } + return asin(ratio); } else { /* Approximation to inverse authalic latitude. */ return pj_authlat(alpha, P->apa); @@ -216,46 +216,46 @@ XY healpix_sphere(LP lp) { XY xy; /* equatorial region */ if ( fabsl(phi) <= phi0) { - xy.x = lam; - xy.y = 3.0*PI/8.0*sin(phi); + xy.x = lam; + xy.y = 3.0*PI/8.0*sin(phi); } else { - double lamc; - double sigma = sqrt(3.0*(1 - fabsl(sin(phi)))); - double cn = floor(2*lam / PI + 2); - if (cn >= 4) { - cn = 3; - } - lamc = -3*PI/4 + (PI/2)*cn; - xy.x = lamc + (lam - lamc)*sigma; - xy.y = pj_sign(phi)*PI/4*(2 - sigma); + double lamc; + double sigma = sqrt(3.0*(1 - fabsl(sin(phi)))); + double cn = floor(2*lam / PI + 2); + if (cn >= 4) { + cn = 3; + } + lamc = -3*PI/4 + (PI/2)*cn; + xy.x = lamc + (lam - lamc)*sigma; + xy.y = pj_sign(phi)*PI/4*(2 - sigma); } return xy; } /** - * Return the inverse of healpix_sphere(). + * Return the inverse of healpix_sphere(). **/ LP healpix_sphere_inverse(XY xy) { - LP lp; + LP lp; double x = xy.x; double y = xy.y; double y0 = PI/4.0; /* Equatorial region. */ if (fabsl(y) <= y0) { - lp.lam = x; - lp.phi = asin(8.0*y/(3.0*PI)); + lp.lam = x; + lp.phi = asin(8.0*y/(3.0*PI)); } else if (fabsl(y) < PI/2.0) { - double cn = floor(2.0*x/PI + 2.0); + double cn = floor(2.0*x/PI + 2.0); double xc, tau; - if (cn >= 4) { - cn = 3; - } - xc = -3.0*PI/4.0 + (PI/2.0)*cn; - tau = 2.0 - 4.0*fabsl(y)/PI; - lp.lam = xc + (x - xc)/tau; - lp.phi = pj_sign(y)*asin(1.0 - pow(tau , 2.0)/3.0); + if (cn >= 4) { + cn = 3; + } + xc = -3.0*PI/4.0 + (PI/2.0)*cn; + tau = 2.0 - 4.0*fabsl(y)/PI; + lp.lam = xc + (x - xc)/tau; + lp.phi = pj_sign(y)*asin(1.0 - pow(tau , 2.0)/3.0); } else { - lp.lam = -1.0*PI; - lp.phi = pj_sign(y)*PI/2.0; + lp.lam = -1.0*PI; + lp.phi = pj_sign(y)*PI/2.0; } return (lp); } @@ -266,7 +266,7 @@ LP healpix_sphere_inverse(XY xy) { static void vector_add(double a[2], double b[2], double *ret) { int i; for(i = 0; i < 2; i++) { - ret[i] = a[i] + b[i]; + ret[i] = a[i] + b[i]; } } /** @@ -275,12 +275,12 @@ static void vector_add(double a[2], double b[2], double *ret) { **/ static void vector_sub(double a[2], double b[2], double*ret) { int i; - for(i = 0; i < 2; i++) { - ret[i] = a[i] - b[i]; + for(i = 0; i < 2; i++) { + ret[i] = a[i] - b[i]; } } /** - * Return the 2 x 1 matrix product a*b, where a is a 2 x 2 matrix and + * Return the 2 x 1 matrix product a*b, where a is a 2 x 2 matrix and * b is a 2 x 1 matrix. * @param ret holds a*b. **/ @@ -288,18 +288,18 @@ static void dot_product(double a[2][2], double b[2], double *ret) { int i, j; int length = 2; for(i = 0; i < length; i++) { - ret[i] = 0; - for(j = 0; j < length; j++) { - ret[i] += a[i][j]*b[j]; - } + ret[i] = 0; + for(j = 0; j < length; j++) { + ret[i] += a[i][j]*b[j]; + } } } /** - * Return the number of the polar cap, the pole point coordinates, and + * Return the number of the polar cap, the pole point coordinates, and * the region that (x, y) lies in. - * If inverse=0, then assume (x,y) lies in the image of the HEALPix + * If inverse=0, then assume (x,y) lies in the image of the HEALPix * projection of the unit sphere. - * If inverse=1, then assume (x,y) lies in the image of the + * If inverse=1, then assume (x,y) lies in the image of the * (north_square, south_square)-rHEALPix projection of the unit sphere. **/ static CapMap get_cap(double x, double y, int north_square, int south_square, @@ -309,84 +309,84 @@ static CapMap get_cap(double x, double y, int north_square, int south_square, capmap.x = x; capmap.y = y; if (inverse == 0) { - if (y > PI/4.0) { - capmap.region = north; - c = PI/2.0; - } else if (y < -1*PI/4.0) { - capmap.region = south; - c = -1*PI/2.0; - } else { - capmap.region = equatorial; - capmap.cn = 0; - return capmap; - } - /* polar region */ - if (x < -1*PI/2.0) { - capmap.cn = 0; - capmap.x = (-1*3.0*PI/4.0); - capmap.y = c; - } else if (x >= -1*PI/2.0 && x < 0) { - capmap.cn = 1; - capmap.x = -1*PI/4.0; - capmap.y = c; - } else if (x >= 0 && x < PI/2.0) { - capmap.cn = 2; - capmap.x = PI/4.0; - capmap.y = c; - } else { - capmap.cn = 3; - capmap.x = 3.0*PI/4.0; - capmap.y = c; - } - return capmap; + if (y > PI/4.0) { + capmap.region = north; + c = PI/2.0; + } else if (y < -1*PI/4.0) { + capmap.region = south; + c = -1*PI/2.0; + } else { + capmap.region = equatorial; + capmap.cn = 0; + return capmap; + } + /* polar region */ + if (x < -1*PI/2.0) { + capmap.cn = 0; + capmap.x = (-1*3.0*PI/4.0); + capmap.y = c; + } else if (x >= -1*PI/2.0 && x < 0) { + capmap.cn = 1; + capmap.x = -1*PI/4.0; + capmap.y = c; + } else if (x >= 0 && x < PI/2.0) { + capmap.cn = 2; + capmap.x = PI/4.0; + capmap.y = c; + } else { + capmap.cn = 3; + capmap.x = 3.0*PI/4.0; + capmap.y = c; + } + return capmap; } else { - double eps; - if (y > PI/4.0) { - capmap.region = north; - capmap.x = (-3.0*PI/4.0 + north_square*PI/2.0); - capmap.y = PI/2.0; - x = x - north_square*PI/2.0; - } else if (y < -1*PI/4.0) { - capmap.region = south; - capmap.x = (-3.0*PI/4.0 + south_square*PI/2); - capmap.y = -1*PI/2.0; - x = x - south_square*PI/2.0; - } else { - capmap.region = equatorial; - capmap.cn = 0; - return capmap; - } - /* Polar Region, find the HEALPix polar cap number that - x, y moves to when rHEALPix polar square is disassembled. */ - eps = 1e-15; /* Kludge. Fuzz to avoid some rounding errors. */ - if (capmap.region == north) { - if (y >= -1*x - PI/4.0 - eps && y < x + 5.0*PI/4.0 - eps) { - capmap.cn = (north_square + 1) % 4; - } else if (y > -1*x -1*PI/4.0 + eps && y >= x + 5.0*PI/4.0 - eps) { - capmap.cn = (north_square + 2) % 4; - } else if (y <= -1*x -1*PI/4.0 + eps && y > x + 5.0*PI/4.0 + eps) { - capmap.cn = (north_square + 3) % 4; - } else { - capmap.cn = north_square; - } - } else if (capmap.region == south) { - if (y <= x + PI/4.0 + eps && y > -1*x - 5.0*PI/4 + eps) { - capmap.cn = (south_square + 1) % 4; - } else if (y < x + PI/4.0 - eps && y <= -1*x - 5.0*PI/4.0 + eps) { - capmap.cn = (south_square + 2) % 4; - } else if (y >= x + PI/4.0 - eps && y < -1*x - 5.0*PI/4.0 - eps) { - capmap.cn = (south_square + 3) % 4; - } else { - capmap.cn = south_square; - } - } - return capmap; + double eps; + if (y > PI/4.0) { + capmap.region = north; + capmap.x = (-3.0*PI/4.0 + north_square*PI/2.0); + capmap.y = PI/2.0; + x = x - north_square*PI/2.0; + } else if (y < -1*PI/4.0) { + capmap.region = south; + capmap.x = (-3.0*PI/4.0 + south_square*PI/2); + capmap.y = -1*PI/2.0; + x = x - south_square*PI/2.0; + } else { + capmap.region = equatorial; + capmap.cn = 0; + return capmap; + } + /* Polar Region, find the HEALPix polar cap number that + x, y moves to when rHEALPix polar square is disassembled. */ + eps = 1e-15; /* Kludge. Fuzz to avoid some rounding errors. */ + if (capmap.region == north) { + if (y >= -1*x - PI/4.0 - eps && y < x + 5.0*PI/4.0 - eps) { + capmap.cn = (north_square + 1) % 4; + } else if (y > -1*x -1*PI/4.0 + eps && y >= x + 5.0*PI/4.0 - eps) { + capmap.cn = (north_square + 2) % 4; + } else if (y <= -1*x -1*PI/4.0 + eps && y > x + 5.0*PI/4.0 + eps) { + capmap.cn = (north_square + 3) % 4; + } else { + capmap.cn = north_square; + } + } else if (capmap.region == south) { + if (y <= x + PI/4.0 + eps && y > -1*x - 5.0*PI/4 + eps) { + capmap.cn = (south_square + 1) % 4; + } else if (y < x + PI/4.0 - eps && y <= -1*x - 5.0*PI/4.0 + eps) { + capmap.cn = (south_square + 2) % 4; + } else if (y >= x + PI/4.0 - eps && y < -1*x - 5.0*PI/4.0 - eps) { + capmap.cn = (south_square + 3) % 4; + } else { + capmap.cn = south_square; + } + } + return capmap; } } /** - * Rearrange point (x, y) in the HEALPix projection by + * Rearrange point (x, y) in the HEALPix projection by * combining the polar caps into two polar squares. - * Put the north polar square in position north_square and + * Put the north polar square in position north_square and * the south polar square in position south_square. * If inverse=1, then uncombine the polar caps. * @param north_square integer between 0 and 3. @@ -402,65 +402,65 @@ static XY combine_caps(double x, double y, int north_square, int south_square, double ret_dot[2]; CapMap capmap = get_cap(x, y, north_square, south_square, inverse); if (capmap.region == equatorial) { - xy.x = capmap.x; - xy.y = capmap.y; - return xy; + xy.x = capmap.x; + xy.y = capmap.y; + return xy; } v[0] = x; v[1] = y; if (inverse == 0) { - /* Rotate (x, y) about its polar cap tip and then translate it to + /* Rotate (x, y) about its polar cap tip and then translate it to north_square or south_square. */ - int pole = 0; - double (*tmpRot)[2]; - double c[2] = {capmap.x, capmap.y}; - if (capmap.region == north) { - pole = north_square; - a[0] = (-3.0*PI/4.0 + pole*PI/2); - a[1] = (PI/2.0 + pole*0); - tmpRot = rot[get_rotate_index(capmap.cn - pole)]; - vector_sub(v, c, v_min_c); - dot_product(tmpRot, v_min_c, ret_dot); - vector_add(ret_dot, a, vector); - } else { - pole = south_square; - a[0] = (-3.0*PI/4.0 + pole*PI/2); - a[1] = (PI/-2.0 + pole*0); - tmpRot = rot[get_rotate_index(-1*(capmap.cn - pole))]; - vector_sub(v, c, v_min_c); - dot_product(tmpRot, v_min_c, ret_dot); - vector_add(ret_dot, a, vector); - } - xy.x = vector[0]; - xy.y = vector[1]; - return xy; + int pole = 0; + double (*tmpRot)[2]; + double c[2] = {capmap.x, capmap.y}; + if (capmap.region == north) { + pole = north_square; + a[0] = (-3.0*PI/4.0 + pole*PI/2); + a[1] = (PI/2.0 + pole*0); + tmpRot = rot[get_rotate_index(capmap.cn - pole)]; + vector_sub(v, c, v_min_c); + dot_product(tmpRot, v_min_c, ret_dot); + vector_add(ret_dot, a, vector); + } else { + pole = south_square; + a[0] = (-3.0*PI/4.0 + pole*PI/2); + a[1] = (PI/-2.0 + pole*0); + tmpRot = rot[get_rotate_index(-1*(capmap.cn - pole))]; + vector_sub(v, c, v_min_c); + dot_product(tmpRot, v_min_c, ret_dot); + vector_add(ret_dot, a, vector); + } + xy.x = vector[0]; + xy.y = vector[1]; + return xy; } else { /* Inverse function. Unrotate (x, y) and then translate it back. */ - int pole = 0; - double (*tmpRot)[2]; - double c[2] = {capmap.x, capmap.y}; - /* disassemble */ - if (capmap.region == north) { - pole = north_square; - a[0] = (-3.0*PI/4.0 + capmap.cn*PI/2); - a[1] = (PI/2.0 + capmap.cn*0); - tmpRot = rot[get_rotate_index(-1*(capmap.cn - pole))]; - vector_sub(v, c, v_min_c); - dot_product(tmpRot, v_min_c, ret_dot); - vector_add(ret_dot, a, vector); - } else { - pole = south_square; - a[0] = (-3.0*PI/4.0 + capmap.cn*PI/2); - a[1] = (PI/-2.0 + capmap.cn*0); - tmpRot = rot[get_rotate_index(capmap.cn - pole)]; - vector_sub(v, c, v_min_c); - dot_product(tmpRot, v_min_c, ret_dot); - vector_add(ret_dot, a, vector); - } - xy.x = vector[0]; - xy.y = vector[1]; - return xy; + int pole = 0; + double (*tmpRot)[2]; + double c[2] = {capmap.x, capmap.y}; + /* disassemble */ + if (capmap.region == north) { + pole = north_square; + a[0] = (-3.0*PI/4.0 + capmap.cn*PI/2); + a[1] = (PI/2.0 + capmap.cn*0); + tmpRot = rot[get_rotate_index(-1*(capmap.cn - pole))]; + vector_sub(v, c, v_min_c); + dot_product(tmpRot, v_min_c, ret_dot); + vector_add(ret_dot, a, vector); + } else { + pole = south_square; + a[0] = (-3.0*PI/4.0 + capmap.cn*PI/2); + a[1] = (PI/-2.0 + capmap.cn*0); + tmpRot = rot[get_rotate_index(capmap.cn - pole)]; + vector_sub(v, c, v_min_c); + dot_product(tmpRot, v_min_c, ret_dot); + vector_add(ret_dot, a, vector); + } + xy.x = vector[0]; + xy.y = vector[1]; + return xy; } } FORWARD(s_healpix_forward); /* sphere */ @@ -476,20 +476,20 @@ FORWARD(e_healpix_forward); /* ellipsoid */ INVERSE(s_healpix_inverse); /* sphere */ /* Check whether (x, y) lies in the HEALPix image */ if (in_image(xy.x, xy.y, 0, 0, 0) == 0) { - lp.lam = HUGE_VAL; - lp.phi = HUGE_VAL; - pj_ctx_set_errno(P->ctx, -15); - return lp; + lp.lam = HUGE_VAL; + lp.phi = HUGE_VAL; + pj_ctx_set_errno(P->ctx, -15); + return lp; } return healpix_sphere_inverse(xy); } INVERSE(e_healpix_inverse); /* ellipsoid */ /* Check whether (x, y) lies in the HEALPix image. */ if (in_image(xy.x, xy.y, 0, 0, 0) == 0) { - lp.lam = HUGE_VAL; - lp.phi = HUGE_VAL; - pj_ctx_set_errno(P->ctx, -15); - return lp; + lp.lam = HUGE_VAL; + lp.phi = HUGE_VAL; + pj_ctx_set_errno(P->ctx, -15); + return lp; } lp = healpix_sphere_inverse(xy); lp.phi = auth_lat(P, lp.phi, 1); @@ -507,10 +507,10 @@ FORWARD(e_rhealpix_forward); /* ellipsoid */ INVERSE(s_rhealpix_inverse); /* sphere */ /* Check whether (x, y) lies in the rHEALPix image. */ if (in_image(xy.x, xy.y, 1, P->north_square, P->south_square) == 0) { - lp.lam = HUGE_VAL; - lp.phi = HUGE_VAL; - pj_ctx_set_errno(P->ctx, -15); - return lp; + lp.lam = HUGE_VAL; + lp.phi = HUGE_VAL; + pj_ctx_set_errno(P->ctx, -15); + return lp; } xy = combine_caps(xy.x, xy.y, P->north_square, P->south_square, 1); return healpix_sphere_inverse(xy); @@ -518,10 +518,10 @@ INVERSE(s_rhealpix_inverse); /* sphere */ INVERSE(e_rhealpix_inverse); /* ellipsoid */ /* Check whether (x, y) lies in the rHEALPix image. */ if (in_image(xy.x, xy.y, 1, P->north_square, P->south_square) == 0) { - lp.lam = HUGE_VAL; - lp.phi = HUGE_VAL; - pj_ctx_set_errno(P->ctx, -15); - return lp; + lp.lam = HUGE_VAL; + lp.phi = HUGE_VAL; + pj_ctx_set_errno(P->ctx, -15); + return lp; } xy = combine_caps(xy.x, xy.y, P->north_square, P->south_square, 1); lp = healpix_sphere_inverse(xy); @@ -529,23 +529,23 @@ INVERSE(e_rhealpix_inverse); /* ellipsoid */ return lp; } FREEUP; - if (P) { - if (P->apa) - pj_dalloc(P->apa); - pj_dalloc(P); - } + if (P) { + if (P->apa) + pj_dalloc(P->apa); + pj_dalloc(P); + } } ENTRY1(healpix, apa) if (P->es) { P->apa = pj_authset(P->es); /* For auth_lat(). */ P->qp = pj_qsfn(1.0, P->e, P->one_es); /* For auth_lat(). */ - P->a = P->a*sqrt(0.5*P->qp); /* Set P->a to authalic radius. */ + P->a = P->a*sqrt(0.5*P->qp); /* Set P->a to authalic radius. */ P->ra = 1.0/P->a; - P->fwd = e_healpix_forward; - P->inv = e_healpix_inverse; + P->fwd = e_healpix_forward; + P->inv = e_healpix_inverse; } else { - P->fwd = s_healpix_forward; - P->inv = s_healpix_inverse; + P->fwd = s_healpix_forward; + P->inv = s_healpix_inverse; } ENDENTRY(P) ENTRY1(rhealpix, apa) @@ -553,20 +553,20 @@ ENTRY1(rhealpix, apa) P->south_square = pj_param(P->ctx, P->params,"isouth_square").i; /* Check for valid north_square and south_square inputs. */ if (P->north_square < 0 || P->north_square > 3) { - E_ERROR(-47); + E_ERROR(-47); } if (P->south_square < 0 || P->south_square > 3) { - E_ERROR(-47); + E_ERROR(-47); } if (P->es) { P->apa = pj_authset(P->es); /* For auth_lat(). */ P->qp = pj_qsfn(1.0, P->e, P->one_es); /* For auth_lat(). */ - P->a = P->a*sqrt(0.5*P->qp); /* Set P->a to authalic radius. */ + P->a = P->a*sqrt(0.5*P->qp); /* Set P->a to authalic radius. */ P->ra = 1.0/P->a; - P->fwd = e_rhealpix_forward; - P->inv = e_rhealpix_inverse; + P->fwd = e_rhealpix_forward; + P->inv = e_rhealpix_inverse; } else { - P->fwd = s_rhealpix_forward; - P->inv = s_rhealpix_inverse; + P->fwd = s_rhealpix_forward; + P->inv = s_rhealpix_inverse; } ENDENTRY(P) diff --git a/src/PJ_igh.c b/src/PJ_igh.c index 4155c856..deca75b4 100644 --- a/src/PJ_igh.c +++ b/src/PJ_igh.c @@ -2,9 +2,9 @@ struct PJconsts* pj[12]; \ double dy0; #define PJ_LIB__ -#include +#include PROJ_HEAD(igh, "Interrupted Goode Homolosine") "\n\tPCyl, Sph."; - C_NAMESPACE PJ + C_NAMESPACE PJ *pj_sinu(PJ *), *pj_moll(PJ *); static const double d4044118 = (40 + 44/60. + 11.8/3600.) * DEG_TO_RAD; // 40d 44' 11.8" [degrees] @@ -116,9 +116,9 @@ FREEUP; if (P) { int i; for (i = 0; i < 12; ++i) - { - if (P->pj[i]) - (*(P->pj[i]->pfree))(P->pj[i]); + { + if (P->pj[i]) + (*(P->pj[i]->pfree))(P->pj[i]); } pj_dalloc(P); } @@ -149,7 +149,7 @@ ENTRY0(igh) if (!(P->pj[n-1] = pj_##proj(P->pj[n-1]))) E_ERROR_0; \ P->pj[n-1]->x0 = x_0; \ P->pj[n-1]->y0 = y_0; \ - P->pj[n-1]->lam0 = lon_0; + P->pj[n-1]->lam0 = lon_0; LP lp = { 0, d4044118 }; XY xy1; diff --git a/src/PJ_imw_p.c b/src/PJ_imw_p.c index ae411116..1f209172 100644 --- a/src/PJ_imw_p.c +++ b/src/PJ_imw_p.c @@ -1,151 +1,151 @@ #define PROJ_PARMS__ \ - double P, Pp, Q, Qp, R_1, R_2, sphi_1, sphi_2, C2; \ - double phi_1, phi_2, lam_1; \ - double *en; \ - int mode; /* = 0, phi_1 and phi_2 != 0, = 1, phi_1 = 0, = -1 phi_2 = 0 */ + double P, Pp, Q, Qp, R_1, R_2, sphi_1, sphi_2, C2; \ + double phi_1, phi_2, lam_1; \ + double *en; \ + int mode; /* = 0, phi_1 and phi_2 != 0, = 1, phi_1 = 0, = -1 phi_2 = 0 */ #define PJ_LIB__ -#include +#include PROJ_HEAD(imw_p, "International Map of the World Polyconic") - "\n\tMod. Polyconic, Ell\n\tlat_1= and lat_2= [lon_1=]"; + "\n\tMod. Polyconic, Ell\n\tlat_1= and lat_2= [lon_1=]"; #define TOL 1e-10 #define EPS 1e-10 - static int + static int phi12(PJ *P, double *del, double *sig) { - int err = 0; + int err = 0; - if (!pj_param(P->ctx, P->params, "tlat_1").i || - !pj_param(P->ctx, P->params, "tlat_2").i) { - err = -41; - } else { - P->phi_1 = pj_param(P->ctx, P->params, "rlat_1").f; - P->phi_2 = pj_param(P->ctx, P->params, "rlat_2").f; - *del = 0.5 * (P->phi_2 - P->phi_1); - *sig = 0.5 * (P->phi_2 + P->phi_1); - err = (fabs(*del) < EPS || fabs(*sig) < EPS) ? -42 : 0; - } - return err; + if (!pj_param(P->ctx, P->params, "tlat_1").i || + !pj_param(P->ctx, P->params, "tlat_2").i) { + err = -41; + } else { + P->phi_1 = pj_param(P->ctx, P->params, "rlat_1").f; + P->phi_2 = pj_param(P->ctx, P->params, "rlat_2").f; + *del = 0.5 * (P->phi_2 - P->phi_1); + *sig = 0.5 * (P->phi_2 + P->phi_1); + err = (fabs(*del) < EPS || fabs(*sig) < EPS) ? -42 : 0; + } + return err; } - static XY + static XY loc_for(LP lp, PJ *P, double *yc) { - XY xy; + XY xy; - if (! lp.phi) { - xy.x = lp.lam; - xy.y = 0.; - } else { - double xa, ya, xb, yb, xc, D, B, m, sp, t, R, C; + if (! lp.phi) { + xy.x = lp.lam; + xy.y = 0.; + } else { + double xa, ya, xb, yb, xc, D, B, m, sp, t, R, C; - sp = sin(lp.phi); - m = pj_mlfn(lp.phi, sp, cos(lp.phi), P->en); - xa = P->Pp + P->Qp * m; - ya = P->P + P->Q * m; - R = 1. / (tan(lp.phi) * sqrt(1. - P->es * sp * sp)); - C = sqrt(R * R - xa * xa); - if (lp.phi < 0.) C = - C; - C += ya - R; - if (P->mode < 0) { - xb = lp.lam; - yb = P->C2; - } else { - t = lp.lam * P->sphi_2; - xb = P->R_2 * sin(t); - yb = P->C2 + P->R_2 * (1. - cos(t)); - } - if (P->mode > 0) { - xc = lp.lam; - *yc = 0.; - } else { - t = lp.lam * P->sphi_1; - xc = P->R_1 * sin(t); - *yc = P->R_1 * (1. - cos(t)); - } - D = (xb - xc)/(yb - *yc); - B = xc + D * (C + R - *yc); - xy.x = D * sqrt(R * R * (1 + D * D) - B * B); - if (lp.phi > 0) - xy.x = - xy.x; - xy.x = (B + xy.x) / (1. + D * D); - xy.y = sqrt(R * R - xy.x * xy.x); - if (lp.phi > 0) - xy.y = - xy.y; - xy.y += C + R; - } - return (xy); + sp = sin(lp.phi); + m = pj_mlfn(lp.phi, sp, cos(lp.phi), P->en); + xa = P->Pp + P->Qp * m; + ya = P->P + P->Q * m; + R = 1. / (tan(lp.phi) * sqrt(1. - P->es * sp * sp)); + C = sqrt(R * R - xa * xa); + if (lp.phi < 0.) C = - C; + C += ya - R; + if (P->mode < 0) { + xb = lp.lam; + yb = P->C2; + } else { + t = lp.lam * P->sphi_2; + xb = P->R_2 * sin(t); + yb = P->C2 + P->R_2 * (1. - cos(t)); + } + if (P->mode > 0) { + xc = lp.lam; + *yc = 0.; + } else { + t = lp.lam * P->sphi_1; + xc = P->R_1 * sin(t); + *yc = P->R_1 * (1. - cos(t)); + } + D = (xb - xc)/(yb - *yc); + B = xc + D * (C + R - *yc); + xy.x = D * sqrt(R * R * (1 + D * D) - B * B); + if (lp.phi > 0) + xy.x = - xy.x; + xy.x = (B + xy.x) / (1. + D * D); + xy.y = sqrt(R * R - xy.x * xy.x); + if (lp.phi > 0) + xy.y = - xy.y; + xy.y += C + R; + } + return (xy); } FORWARD(e_forward); /* ellipsoid */ - double yc; - xy = loc_for(lp, P, &yc); - return (xy); + double yc; + xy = loc_for(lp, P, &yc); + return (xy); } INVERSE(e_inverse); /* ellipsoid */ - XY t; - double yc; + XY t; + double yc; - lp.phi = P->phi_2; - lp.lam = xy.x / cos(lp.phi); - do { - t = loc_for(lp, P, &yc); - lp.phi = ((lp.phi - P->phi_1) * (xy.y - yc) / (t.y - yc)) + P->phi_1; - lp.lam = lp.lam * xy.x / t.x; - } while (fabs(t.x - xy.x) > TOL || fabs(t.y - xy.y) > TOL); - return (lp); + lp.phi = P->phi_2; + lp.lam = xy.x / cos(lp.phi); + do { + t = loc_for(lp, P, &yc); + lp.phi = ((lp.phi - P->phi_1) * (xy.y - yc) / (t.y - yc)) + P->phi_1; + lp.lam = lp.lam * xy.x / t.x; + } while (fabs(t.x - xy.x) > TOL || fabs(t.y - xy.y) > TOL); + return (lp); } - static void + static void xy(PJ *P, double phi, double *x, double *y, double *sp, double *R) { - double F; + double F; - *sp = sin(phi); - *R = 1./(tan(phi) * sqrt(1. - P->es * *sp * *sp )); - F = P->lam_1 * *sp; - *y = *R * (1 - cos(F)); - *x = *R * sin(F); + *sp = sin(phi); + *R = 1./(tan(phi) * sqrt(1. - P->es * *sp * *sp )); + F = P->lam_1 * *sp; + *y = *R * (1 - cos(F)); + *x = *R * sin(F); } FREEUP; if (P) { if (P->en) pj_dalloc(P->en); pj_dalloc(P); } } ENTRY1(imw_p, en) - double del, sig, s, t, x1, x2, T2, y1, m1, m2, y2; - int i; + double del, sig, s, t, x1, x2, T2, y1, m1, m2, y2; + int i; - if (!(P->en = pj_enfn(P->es))) E_ERROR_0; - if( (i = phi12(P, &del, &sig)) != 0) - E_ERROR(i); - if (P->phi_2 < P->phi_1) { /* make sure P->phi_1 most southerly */ - del = P->phi_1; - P->phi_1 = P->phi_2; - P->phi_2 = del; - } - if (pj_param(P->ctx, P->params, "tlon_1").i) - P->lam_1 = pj_param(P->ctx, P->params, "rlon_1").f; - else { /* use predefined based upon latitude */ - sig = fabs(sig * RAD_TO_DEG); - if (sig <= 60) sig = 2.; - else if (sig <= 76) sig = 4.; - else sig = 8.; - P->lam_1 = sig * DEG_TO_RAD; - } - P->mode = 0; - if (P->phi_1) xy(P, P->phi_1, &x1, &y1, &P->sphi_1, &P->R_1); - else { - P->mode = 1; - y1 = 0.; - x1 = P->lam_1; - } - if (P->phi_2) xy(P, P->phi_2, &x2, &T2, &P->sphi_2, &P->R_2); - else { - P->mode = -1; - T2 = 0.; - x2 = P->lam_1; - } - m1 = pj_mlfn(P->phi_1, P->sphi_1, cos(P->phi_1), P->en); - m2 = pj_mlfn(P->phi_2, P->sphi_2, cos(P->phi_2), P->en); - t = m2 - m1; - s = x2 - x1; - y2 = sqrt(t * t - s * s) + y1; - P->C2 = y2 - T2; - t = 1. / t; - P->P = (m2 * y1 - m1 * y2) * t; - P->Q = (y2 - y1) * t; - P->Pp = (m2 * x1 - m1 * x2) * t; - P->Qp = (x2 - x1) * t; - P->fwd = e_forward; - P->inv = e_inverse; + if (!(P->en = pj_enfn(P->es))) E_ERROR_0; + if( (i = phi12(P, &del, &sig)) != 0) + E_ERROR(i); + if (P->phi_2 < P->phi_1) { /* make sure P->phi_1 most southerly */ + del = P->phi_1; + P->phi_1 = P->phi_2; + P->phi_2 = del; + } + if (pj_param(P->ctx, P->params, "tlon_1").i) + P->lam_1 = pj_param(P->ctx, P->params, "rlon_1").f; + else { /* use predefined based upon latitude */ + sig = fabs(sig * RAD_TO_DEG); + if (sig <= 60) sig = 2.; + else if (sig <= 76) sig = 4.; + else sig = 8.; + P->lam_1 = sig * DEG_TO_RAD; + } + P->mode = 0; + if (P->phi_1) xy(P, P->phi_1, &x1, &y1, &P->sphi_1, &P->R_1); + else { + P->mode = 1; + y1 = 0.; + x1 = P->lam_1; + } + if (P->phi_2) xy(P, P->phi_2, &x2, &T2, &P->sphi_2, &P->R_2); + else { + P->mode = -1; + T2 = 0.; + x2 = P->lam_1; + } + m1 = pj_mlfn(P->phi_1, P->sphi_1, cos(P->phi_1), P->en); + m2 = pj_mlfn(P->phi_2, P->sphi_2, cos(P->phi_2), P->en); + t = m2 - m1; + s = x2 - x1; + y2 = sqrt(t * t - s * s) + y1; + P->C2 = y2 - T2; + t = 1. / t; + P->P = (m2 * y1 - m1 * y2) * t; + P->Q = (y2 - y1) * t; + P->Pp = (m2 * x1 - m1 * x2) * t; + P->Qp = (x2 - x1) * t; + P->fwd = e_forward; + P->inv = e_inverse; ENDENTRY(P) diff --git a/src/PJ_isea.c b/src/PJ_isea.c index 7c09189c..0ba17807 100644 --- a/src/PJ_isea.c +++ b/src/PJ_isea.c @@ -30,78 +30,78 @@ struct hex { /* y *must* be positive down as the xy /iso conversion assumes this */ ISEA_STATIC int hex_xy(struct hex *h) { - if (!h->iso) return 1; - if (h->x >= 0) { - h->y = -h->y - (h->x+1)/2; - } else { - /* need to round toward -inf, not toward zero, so x-1 */ - h->y = -h->y - h->x/2; - } - h->iso = 0; - - return 1; + if (!h->iso) return 1; + if (h->x >= 0) { + h->y = -h->y - (h->x+1)/2; + } else { + /* need to round toward -inf, not toward zero, so x-1 */ + h->y = -h->y - h->x/2; + } + h->iso = 0; + + return 1; } ISEA_STATIC int hex_iso(struct hex *h) { - if (h->iso) return 1; - - if (h->x >= 0) { - h->y = (-h->y - (h->x+1)/2); - } else { - /* need to round toward -inf, not toward zero, so x-1 */ - h->y = (-h->y - (h->x)/2); - } - - h->z = -h->x - h->y; - h->iso = 1; - return 1; + if (h->iso) return 1; + + if (h->x >= 0) { + h->y = (-h->y - (h->x+1)/2); + } else { + /* need to round toward -inf, not toward zero, so x-1 */ + h->y = (-h->y - (h->x)/2); + } + + h->z = -h->x - h->y; + h->iso = 1; + return 1; } ISEA_STATIC int hexbin2(double width, double x, double y, int *i, int *j) { - double z, rx, ry, rz; - double abs_dx, abs_dy, abs_dz; - int ix, iy, iz, s; - struct hex h; - - x = x / cos(30 * M_PI / 180.0); /* rotated X coord */ - y = y - x / 2.0; /* adjustment for rotated X */ - - /* adjust for actual hexwidth */ - x /= width; - y /= width; - - z = -x - y; - - ix = rx = floor(x + 0.5); - iy = ry = floor(y + 0.5); - iz = rz = floor(z + 0.5); - - s = ix + iy + iz; - - if (s) { - abs_dx = fabs(rx - x); - abs_dy = fabs(ry - y); - abs_dz = fabs(rz - z); - - if (abs_dx >= abs_dy && abs_dx >= abs_dz) { - ix -= s; - } else if (abs_dy >= abs_dx && abs_dy >= abs_dz) { - iy -= s; - } else { - iz -= s; - } - } - h.x = ix; - h.y = iy; - h.z = iz; - h.iso = 1; - - hex_xy(&h); - *i = h.x; - *j = h.y; + double z, rx, ry, rz; + double abs_dx, abs_dy, abs_dz; + int ix, iy, iz, s; + struct hex h; + + x = x / cos(30 * M_PI / 180.0); /* rotated X coord */ + y = y - x / 2.0; /* adjustment for rotated X */ + + /* adjust for actual hexwidth */ + x /= width; + y /= width; + + z = -x - y; + + ix = rx = floor(x + 0.5); + iy = ry = floor(y + 0.5); + iz = rz = floor(z + 0.5); + + s = ix + iy + iz; + + if (s) { + abs_dx = fabs(rx - x); + abs_dy = fabs(ry - y); + abs_dz = fabs(rz - z); + + if (abs_dx >= abs_dy && abs_dx >= abs_dz) { + ix -= s; + } else if (abs_dy >= abs_dx && abs_dy >= abs_dz) { + iy -= s; + } else { + iz -= s; + } + } + h.x = ix; + h.y = iy; + h.z = iz; + h.iso = 1; + + hex_xy(&h); + *i = h.x; + *j = h.y; return ix * 100 + iy; } #ifndef ISEA_STATIC @@ -111,60 +111,60 @@ int hexbin2(double width, double x, double y, enum isea_poly { ISEA_NONE, ISEA_ICOSAHEDRON = 20 }; enum isea_topology { ISEA_HEXAGON=6, ISEA_TRIANGLE=3, ISEA_DIAMOND=4 }; enum isea_address_form { ISEA_GEO, ISEA_Q2DI, ISEA_SEQNUM, ISEA_INTERLEAVE, - ISEA_PLANE, ISEA_Q2DD, ISEA_PROJTRI, ISEA_VERTEX2DD, ISEA_HEX + ISEA_PLANE, ISEA_Q2DD, ISEA_PROJTRI, ISEA_VERTEX2DD, ISEA_HEX }; struct isea_dgg { - int polyhedron; /* ignored, icosahedron */ - double o_lat, o_lon, o_az; /* orientation, radians */ - int pole; /* true if standard snyder */ - int topology; /* ignored, hexagon */ - int aperture; /* valid values depend on partitioning method */ - int resolution; - double radius; /* radius of the earth in meters, ignored 1.0 */ - int output; /* an isea_address_form */ - int triangle; /* triangle of last transformed point */ - int quad; /* quad of last transformed point */ - unsigned long serial; + int polyhedron; /* ignored, icosahedron */ + double o_lat, o_lon, o_az; /* orientation, radians */ + int pole; /* true if standard snyder */ + int topology; /* ignored, hexagon */ + int aperture; /* valid values depend on partitioning method */ + int resolution; + double radius; /* radius of the earth in meters, ignored 1.0 */ + int output; /* an isea_address_form */ + int triangle; /* triangle of last transformed point */ + int quad; /* quad of last transformed point */ + unsigned long serial; }; struct isea_pt { - double x, y; + double x, y; }; struct isea_geo { - double lon, lat; + double lon, lat; }; struct isea_address { - int type; /* enum isea_address_form */ - int number; - double x,y; /* or i,j or lon,lat depending on type */ + int type; /* enum isea_address_form */ + int number; + double x,y; /* or i,j or lon,lat depending on type */ }; /* ENDINC */ enum snyder_polyhedron { - SNYDER_POLY_HEXAGON, SNYDER_POLY_PENTAGON, - SNYDER_POLY_TETRAHEDRON, SNYDER_POLY_CUBE, - SNYDER_POLY_OCTAHEDRON, SNYDER_POLY_DODECAHEDRON, - SNYDER_POLY_ICOSAHEDRON + SNYDER_POLY_HEXAGON, SNYDER_POLY_PENTAGON, + SNYDER_POLY_TETRAHEDRON, SNYDER_POLY_CUBE, + SNYDER_POLY_OCTAHEDRON, SNYDER_POLY_DODECAHEDRON, + SNYDER_POLY_ICOSAHEDRON }; struct snyder_constants { - double g, G, theta, ea_w, ea_a, ea_b, g_w, g_a, g_b; + double g, G, theta, ea_w, ea_a, ea_b, g_w, g_a, g_b; }; /* TODO put these in radians to avoid a later conversion */ ISEA_STATIC struct snyder_constants constants[] = { - {23.80018260, 62.15458023, 60.0, 3.75, 1.033, 0.968, 5.09, 1.195, 1.0}, - {20.07675127, 55.69063953, 54.0, 2.65, 1.030, 0.983, 3.59, 1.141, 1.027}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {37.37736814, 36.0, 30.0, 17.27, 1.163, 0.860, 13.14, 1.584, 1.0}, + {23.80018260, 62.15458023, 60.0, 3.75, 1.033, 0.968, 5.09, 1.195, 1.0}, + {20.07675127, 55.69063953, 54.0, 2.65, 1.030, 0.983, 3.59, 1.141, 1.027}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, + {37.37736814, 36.0, 30.0, 17.27, 1.163, 0.860, 13.14, 1.584, 1.0}, }; #define E 52.62263186 @@ -189,18 +189,18 @@ struct snyder_constants constants[] = { ISEA_STATIC struct isea_geo vertex[] = { - {0.0, DEG90}, - {DEG180, V_LAT}, - {-DEG108, V_LAT}, - {-DEG36, V_LAT}, - {DEG36, V_LAT}, - {DEG108, V_LAT}, - {-DEG144, -V_LAT}, - {-DEG72, -V_LAT}, - {0.0, -V_LAT}, - {DEG72, -V_LAT}, - {DEG144, -V_LAT}, - {0.0, -DEG90} + {0.0, DEG90}, + {DEG180, V_LAT}, + {-DEG108, V_LAT}, + {-DEG36, V_LAT}, + {DEG36, V_LAT}, + {DEG108, V_LAT}, + {-DEG144, -V_LAT}, + {-DEG72, -V_LAT}, + {0.0, -V_LAT}, + {DEG72, -V_LAT}, + {DEG144, -V_LAT}, + {0.0, -DEG90} }; /* TODO make an isea_pt array of the vertices as well */ @@ -215,46 +215,46 @@ static int tri_v1[] = {0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 2, 3, 4, 5, 1, 11, /* triangle Centers */ struct isea_geo icostriangles[] = { - {0.0, 0.0}, - {-DEG144, E_RAD}, - {-DEG72, E_RAD}, - {0.0, E_RAD}, - {DEG72, E_RAD}, - {DEG144, E_RAD}, - {-DEG144, F_RAD}, - {-DEG72, F_RAD}, - {0.0, F_RAD}, - {DEG72, F_RAD}, - {DEG144, F_RAD}, - {-DEG108, -F_RAD}, - {-DEG36, -F_RAD}, - {DEG36, -F_RAD}, - {DEG108, -F_RAD}, - {DEG180, -F_RAD}, - {-DEG108, -E_RAD}, - {-DEG36, -E_RAD}, - {DEG36, -E_RAD}, - {DEG108, -E_RAD}, - {DEG180, -E_RAD}, + {0.0, 0.0}, + {-DEG144, E_RAD}, + {-DEG72, E_RAD}, + {0.0, E_RAD}, + {DEG72, E_RAD}, + {DEG144, E_RAD}, + {-DEG144, F_RAD}, + {-DEG72, F_RAD}, + {0.0, F_RAD}, + {DEG72, F_RAD}, + {DEG144, F_RAD}, + {-DEG108, -F_RAD}, + {-DEG36, -F_RAD}, + {DEG36, -F_RAD}, + {DEG108, -F_RAD}, + {DEG180, -F_RAD}, + {-DEG108, -E_RAD}, + {-DEG36, -E_RAD}, + {DEG36, -E_RAD}, + {DEG108, -E_RAD}, + {DEG180, -E_RAD}, }; static double az_adjustment(int triangle) { - double adj; + double adj; - struct isea_geo v; - struct isea_geo c; + struct isea_geo v; + struct isea_geo c; - v = vertex[tri_v1[triangle]]; - c = icostriangles[triangle]; + v = vertex[tri_v1[triangle]]; + c = icostriangles[triangle]; - /* TODO looks like the adjustment is always either 0 or 180 */ - /* at least if you pick your vertex carefully */ - adj = atan2(cos(v.lat) * sin(v.lon - c.lon), - cos(c.lat) * sin(v.lat) - - sin(c.lat) * cos(v.lat) * cos(v.lon - c.lon)); - return adj; + /* TODO looks like the adjustment is always either 0 or 180 */ + /* at least if you pick your vertex carefully */ + adj = atan2(cos(v.lat) * sin(v.lon - c.lon), + cos(c.lat) * sin(v.lat) + - sin(c.lat) * cos(v.lat) * cos(v.lon - c.lon)); + return adj; } /* R tan(g) sin(60) */ @@ -269,49 +269,49 @@ ISEA_STATIC struct isea_pt isea_triangle_xy(int triangle) { - struct isea_pt c; - double Rprime = 0.91038328153090290025; - - triangle = (triangle - 1) % 20; - - c.x = TABLE_G * ((triangle % 5) - 2) * 2.0; - if (triangle > 9) { - c.x += TABLE_G; - } - switch (triangle / 5) { - case 0: - c.y = 5.0 * TABLE_H; - break; - case 1: - c.y = TABLE_H; - break; - case 2: - c.y = -TABLE_H; - break; - case 3: - c.y = -5.0 * TABLE_H; - break; - default: - /* should be impossible */ - exit(EXIT_FAILURE); - }; - c.x *= Rprime; - c.y *= Rprime; - - return c; + struct isea_pt c; + double Rprime = 0.91038328153090290025; + + triangle = (triangle - 1) % 20; + + c.x = TABLE_G * ((triangle % 5) - 2) * 2.0; + if (triangle > 9) { + c.x += TABLE_G; + } + switch (triangle / 5) { + case 0: + c.y = 5.0 * TABLE_H; + break; + case 1: + c.y = TABLE_H; + break; + case 2: + c.y = -TABLE_H; + break; + case 3: + c.y = -5.0 * TABLE_H; + break; + default: + /* should be impossible */ + exit(EXIT_FAILURE); + }; + c.x *= Rprime; + c.y *= Rprime; + + return c; } /* snyder eq 14 */ static double sph_azimuth(double f_lon, double f_lat, double t_lon, double t_lat) { - double az; + double az; - az = atan2(cos(t_lat) * sin(t_lon - f_lon), - cos(f_lat) * sin(t_lat) - - sin(f_lat) * cos(t_lat) * cos(t_lon - f_lon) - ); - return az; + az = atan2(cos(t_lat) * sin(t_lon - f_lon), + cos(f_lat) * sin(t_lat) + - sin(f_lat) * cos(t_lat) * cos(t_lon - f_lon) + ); + return az; } /* coord needs to be in radians */ @@ -319,173 +319,173 @@ ISEA_STATIC int isea_snyder_forward(struct isea_geo * ll, struct isea_pt * out) { - int i; - - /* - * spherical distance from center of polygon face to any of its - * vertexes on the globe - */ - double g; - - /* - * spherical angle between radius vector to center and adjacent edge - * of spherical polygon on the globe - */ - double G; - - /* - * plane angle between radius vector to center and adjacent edge of - * plane polygon - */ - double theta; - - /* additional variables from snyder */ - double q, Rprime, H, Ag, Azprime, Az, dprime, f, rho, - x, y; - - /* variables used to store intermediate results */ - double cot_theta, tan_g, az_offset; - - /* how many multiples of 60 degrees we adjust the azimuth */ - int Az_adjust_multiples; - - struct snyder_constants c; - - /* - * TODO by locality of reference, start by trying the same triangle - * as last time - */ - - /* TODO put these constants in as radians to begin with */ - c = constants[SNYDER_POLY_ICOSAHEDRON]; - theta = c.theta * DEG2RAD; - g = c.g * DEG2RAD; - G = c.G * DEG2RAD; - - for (i = 1; i <= 20; i++) { - double z; - struct isea_geo center; - - center = icostriangles[i]; - - /* step 1 */ - z = acos(sin(center.lat) * sin(ll->lat) - + cos(center.lat) * cos(ll->lat) * cos(ll->lon - center.lon)); - /* not on this triangle */ - if (z > g + 0.000005) { /* TODO DBL_EPSILON */ - continue; - } - - Az = sph_azimuth(center.lon, center.lat, ll->lon, ll->lat); - - /* step 2 */ - - /* This calculates "some" vertex coordinate */ - az_offset = az_adjustment(i); - - Az -= az_offset; - - /* TODO I don't know why we do this. It's not in snyder */ - /* maybe because we should have picked a better vertex */ - if (Az < 0.0) { - Az += 2.0 * M_PI; - } - /* - * adjust Az for the point to fall within the range of 0 to - * 2(90 - theta) or 60 degrees for the hexagon, by - * and therefore 120 degrees for the triangle - * of the icosahedron - * subtracting or adding multiples of 60 degrees to Az and - * recording the amount of adjustment - */ - - Az_adjust_multiples = 0; - while (Az < 0.0) { - Az += DEG120; - Az_adjust_multiples--; - } - while (Az > DEG120 + DBL_EPSILON) { - Az -= DEG120; - Az_adjust_multiples++; - } - - /* step 3 */ - cot_theta = 1.0 / tan(theta); - tan_g = tan(g); /* TODO this is a constant */ - - /* Calculate q from eq 9. */ - /* TODO cot_theta is cot(30) */ - q = atan2(tan_g, cos(Az) + sin(Az) * cot_theta); - - /* not in this triangle */ - if (z > q + 0.000005) { - continue; - } - /* step 4 */ - - /* Apply equations 5-8 and 10-12 in order */ - - /* eq 5 */ - /* Rprime = 0.9449322893 * R; */ - /* R' in the paper is for the truncated */ - Rprime = 0.91038328153090290025; - - /* eq 6 */ - H = acos(sin(Az) * sin(G) * cos(g) - cos(Az) * cos(G)); + int i; + + /* + * spherical distance from center of polygon face to any of its + * vertexes on the globe + */ + double g; + + /* + * spherical angle between radius vector to center and adjacent edge + * of spherical polygon on the globe + */ + double G; + + /* + * plane angle between radius vector to center and adjacent edge of + * plane polygon + */ + double theta; + + /* additional variables from snyder */ + double q, Rprime, H, Ag, Azprime, Az, dprime, f, rho, + x, y; + + /* variables used to store intermediate results */ + double cot_theta, tan_g, az_offset; + + /* how many multiples of 60 degrees we adjust the azimuth */ + int Az_adjust_multiples; + + struct snyder_constants c; + + /* + * TODO by locality of reference, start by trying the same triangle + * as last time + */ + + /* TODO put these constants in as radians to begin with */ + c = constants[SNYDER_POLY_ICOSAHEDRON]; + theta = c.theta * DEG2RAD; + g = c.g * DEG2RAD; + G = c.G * DEG2RAD; + + for (i = 1; i <= 20; i++) { + double z; + struct isea_geo center; + + center = icostriangles[i]; + + /* step 1 */ + z = acos(sin(center.lat) * sin(ll->lat) + + cos(center.lat) * cos(ll->lat) * cos(ll->lon - center.lon)); + /* not on this triangle */ + if (z > g + 0.000005) { /* TODO DBL_EPSILON */ + continue; + } + + Az = sph_azimuth(center.lon, center.lat, ll->lon, ll->lat); + + /* step 2 */ + + /* This calculates "some" vertex coordinate */ + az_offset = az_adjustment(i); + + Az -= az_offset; + + /* TODO I don't know why we do this. It's not in snyder */ + /* maybe because we should have picked a better vertex */ + if (Az < 0.0) { + Az += 2.0 * M_PI; + } + /* + * adjust Az for the point to fall within the range of 0 to + * 2(90 - theta) or 60 degrees for the hexagon, by + * and therefore 120 degrees for the triangle + * of the icosahedron + * subtracting or adding multiples of 60 degrees to Az and + * recording the amount of adjustment + */ + + Az_adjust_multiples = 0; + while (Az < 0.0) { + Az += DEG120; + Az_adjust_multiples--; + } + while (Az > DEG120 + DBL_EPSILON) { + Az -= DEG120; + Az_adjust_multiples++; + } + + /* step 3 */ + cot_theta = 1.0 / tan(theta); + tan_g = tan(g); /* TODO this is a constant */ + + /* Calculate q from eq 9. */ + /* TODO cot_theta is cot(30) */ + q = atan2(tan_g, cos(Az) + sin(Az) * cot_theta); + + /* not in this triangle */ + if (z > q + 0.000005) { + continue; + } + /* step 4 */ + + /* Apply equations 5-8 and 10-12 in order */ + + /* eq 5 */ + /* Rprime = 0.9449322893 * R; */ + /* R' in the paper is for the truncated */ + Rprime = 0.91038328153090290025; + + /* eq 6 */ + H = acos(sin(Az) * sin(G) * cos(g) - cos(Az) * cos(G)); - /* eq 7 */ - /* Ag = (Az + G + H - DEG180) * M_PI * R * R / DEG180; */ - Ag = Az + G + H - DEG180; + /* eq 7 */ + /* Ag = (Az + G + H - DEG180) * M_PI * R * R / DEG180; */ + Ag = Az + G + H - DEG180; - /* eq 8 */ - Azprime = atan2(2.0 * Ag, Rprime * Rprime * tan_g * tan_g - 2.0 * Ag * cot_theta); + /* eq 8 */ + Azprime = atan2(2.0 * Ag, Rprime * Rprime * tan_g * tan_g - 2.0 * Ag * cot_theta); - /* eq 10 */ - /* cot(theta) = 1.73205080756887729355 */ - dprime = Rprime * tan_g / (cos(Azprime) + sin(Azprime) * cot_theta); + /* eq 10 */ + /* cot(theta) = 1.73205080756887729355 */ + dprime = Rprime * tan_g / (cos(Azprime) + sin(Azprime) * cot_theta); - /* eq 11 */ - f = dprime / (2.0 * Rprime * sin(q / 2.0)); - - /* eq 12 */ - rho = 2.0 * Rprime * f * sin(z / 2.0); - - /* - * add back the same 60 degree multiple adjustment from step - * 2 to Azprime - */ - - Azprime += DEG120 * Az_adjust_multiples; - - /* calculate rectangular coordinates */ - - x = rho * sin(Azprime); - y = rho * cos(Azprime); + /* eq 11 */ + f = dprime / (2.0 * Rprime * sin(q / 2.0)); + + /* eq 12 */ + rho = 2.0 * Rprime * f * sin(z / 2.0); + + /* + * add back the same 60 degree multiple adjustment from step + * 2 to Azprime + */ + + Azprime += DEG120 * Az_adjust_multiples; + + /* calculate rectangular coordinates */ + + x = rho * sin(Azprime); + y = rho * cos(Azprime); - /* - * TODO - * translate coordinates to the origin for the particular - * hexagon on the flattened polyhedral map plot - */ + /* + * TODO + * translate coordinates to the origin for the particular + * hexagon on the flattened polyhedral map plot + */ - out->x = x; - out->y = y; - - return i; - } + out->x = x; + out->y = y; + + return i; + } - /* - * should be impossible, this implies that the coordinate is not on - * any triangle - */ - - fprintf(stderr, "impossible transform: %f %f is not on any triangle\n", - ll->lon * RAD2DEG, ll->lat * RAD2DEG); - - exit(EXIT_FAILURE); - - /* not reached */ - return 0; /* supresses a warning */ + /* + * should be impossible, this implies that the coordinate is not on + * any triangle + */ + + fprintf(stderr, "impossible transform: %f %f is not on any triangle\n", + ll->lon * RAD2DEG, ll->lat * RAD2DEG); + + exit(EXIT_FAILURE); + + /* not reached */ + return 0; /* supresses a warning */ } /* @@ -509,73 +509,73 @@ ISEA_STATIC struct isea_geo snyder_ctran(struct isea_geo * np, struct isea_geo * pt) { - struct isea_geo npt; - double alpha, phi, lambda, lambda0, beta, lambdap, phip; - double sin_phip; - double lp_b; /* lambda prime minus beta */ - double cos_p, sin_a; + struct isea_geo npt; + double alpha, phi, lambda, lambda0, beta, lambdap, phip; + double sin_phip; + double lp_b; /* lambda prime minus beta */ + double cos_p, sin_a; - phi = pt->lat; - lambda = pt->lon; - alpha = np->lat; - beta = np->lon; - lambda0 = beta; + phi = pt->lat; + lambda = pt->lon; + alpha = np->lat; + beta = np->lon; + lambda0 = beta; - cos_p = cos(phi); - sin_a = sin(alpha); + cos_p = cos(phi); + sin_a = sin(alpha); - /* mpawm 5-7 */ - sin_phip = sin_a * sin(phi) - cos(alpha) * cos_p * cos(lambda - lambda0); + /* mpawm 5-7 */ + sin_phip = sin_a * sin(phi) - cos(alpha) * cos_p * cos(lambda - lambda0); - /* mpawm 5-8b */ + /* mpawm 5-8b */ - /* use the two argument form so we end up in the right quadrant */ - lp_b = atan2(cos_p * sin(lambda - lambda0), - (sin_a * cos_p * cos(lambda - lambda0) + cos(alpha) * sin(phi))); + /* use the two argument form so we end up in the right quadrant */ + lp_b = atan2(cos_p * sin(lambda - lambda0), + (sin_a * cos_p * cos(lambda - lambda0) + cos(alpha) * sin(phi))); - lambdap = lp_b + beta; + lambdap = lp_b + beta; - /* normalize longitude */ - /* TODO can we just do a modulus ? */ - lambdap = fmod(lambdap, 2 * M_PI); - while (lambdap > M_PI) - lambdap -= 2 * M_PI; - while (lambdap < -M_PI) - lambdap += 2 * M_PI; + /* normalize longitude */ + /* TODO can we just do a modulus ? */ + lambdap = fmod(lambdap, 2 * M_PI); + while (lambdap > M_PI) + lambdap -= 2 * M_PI; + while (lambdap < -M_PI) + lambdap += 2 * M_PI; - phip = asin(sin_phip); + phip = asin(sin_phip); - npt.lat = phip; - npt.lon = lambdap; + npt.lat = phip; + npt.lon = lambdap; - return npt; + return npt; } ISEA_STATIC struct isea_geo isea_ctran(struct isea_geo * np, struct isea_geo * pt, double lon0) { - struct isea_geo npt; - - np->lon += M_PI; - npt = snyder_ctran(np, pt); - np->lon -= M_PI; - - npt.lon -= (M_PI - lon0 + np->lon); - - /* - * snyder is down tri 3, isea is along side of tri1 from vertex 0 to - * vertex 1 these are 180 degrees apart - */ - npt.lon += M_PI; - /* normalize longitude */ - npt.lon = fmod(npt.lon, 2 * M_PI); - while (npt.lon > M_PI) - npt.lon -= 2 * M_PI; - while (npt.lon < -M_PI) - npt.lon += 2 * M_PI; - - return npt; + struct isea_geo npt; + + np->lon += M_PI; + npt = snyder_ctran(np, pt); + np->lon -= M_PI; + + npt.lon -= (M_PI - lon0 + np->lon); + + /* + * snyder is down tri 3, isea is along side of tri1 from vertex 0 to + * vertex 1 these are 180 degrees apart + */ + npt.lon += M_PI; + /* normalize longitude */ + npt.lon = fmod(npt.lon, 2 * M_PI); + while (npt.lon > M_PI) + npt.lon -= 2 * M_PI; + while (npt.lon < -M_PI) + npt.lon += 2 * M_PI; + + return npt; } /* in radians */ @@ -588,64 +588,64 @@ ISEA_STATIC int isea_grid_init(struct isea_dgg * g) { - if (!g) - return 0; - - g->polyhedron = 20; - g->o_lat = ISEA_STD_LAT; - g->o_lon = ISEA_STD_LON; - g->o_az = 0.0; - g->aperture = 4; - g->resolution = 6; - g->radius = 1.0; - g->topology = 6; - - return 1; + if (!g) + return 0; + + g->polyhedron = 20; + g->o_lat = ISEA_STD_LAT; + g->o_lon = ISEA_STD_LON; + g->o_az = 0.0; + g->aperture = 4; + g->resolution = 6; + g->radius = 1.0; + g->topology = 6; + + return 1; } ISEA_STATIC int isea_orient_isea(struct isea_dgg * g) { - if (!g) - return 0; - g->o_lat = ISEA_STD_LAT; - g->o_lon = ISEA_STD_LON; - g->o_az = 0.0; - return 1; + if (!g) + return 0; + g->o_lat = ISEA_STD_LAT; + g->o_lon = ISEA_STD_LON; + g->o_az = 0.0; + return 1; } ISEA_STATIC int isea_orient_pole(struct isea_dgg * g) { - if (!g) - return 0; - g->o_lat = M_PI / 2.0; - g->o_lon = 0.0; - g->o_az = 0; - return 1; + if (!g) + return 0; + g->o_lat = M_PI / 2.0; + g->o_lon = 0.0; + g->o_az = 0; + return 1; } ISEA_STATIC int isea_transform(struct isea_dgg * g, struct isea_geo * in, - struct isea_pt * out) + struct isea_pt * out) { - struct isea_geo i, pole; - int tri; + struct isea_geo i, pole; + int tri; - pole.lat = g->o_lat; - pole.lon = g->o_lon; + pole.lat = g->o_lat; + pole.lon = g->o_lon; - i = isea_ctran(&pole, in, g->o_az); + i = isea_ctran(&pole, in, g->o_az); - tri = isea_snyder_forward(&i, out); - out->x *= g->radius; - out->y *= g->radius; - g->triangle = tri; + tri = isea_snyder_forward(&i, out); + out->x *= g->radius; + out->y *= g->radius; + g->triangle = tri; - return tri; + return tri; } #define DOWNTRI(tri) (((tri - 1) / 5) % 2 == 1) @@ -654,249 +654,249 @@ ISEA_STATIC void isea_rotate(struct isea_pt * pt, double degrees) { - double rad; + double rad; - double x, y; + double x, y; - rad = -degrees * M_PI / 180.0; - while (rad >= 2.0 * M_PI) rad -= 2.0 * M_PI; - while (rad <= -2.0 * M_PI) rad += 2.0 * M_PI; + rad = -degrees * M_PI / 180.0; + while (rad >= 2.0 * M_PI) rad -= 2.0 * M_PI; + while (rad <= -2.0 * M_PI) rad += 2.0 * M_PI; - x = pt->x * cos(rad) + pt->y * sin(rad); - y = -pt->x * sin(rad) + pt->y * cos(rad); + x = pt->x * cos(rad) + pt->y * sin(rad); + y = -pt->x * sin(rad) + pt->y * cos(rad); - pt->x = x; - pt->y = y; + pt->x = x; + pt->y = y; } ISEA_STATIC int isea_tri_plane(int tri, struct isea_pt *pt, double radius) { - struct isea_pt tc; /* center of triangle */ - - if (DOWNTRI(tri)) { - isea_rotate(pt, 180.0); - } - tc = isea_triangle_xy(tri); - tc.x *= radius; - tc.y *= radius; - pt->x += tc.x; - pt->y += tc.y; - - return tri; + struct isea_pt tc; /* center of triangle */ + + if (DOWNTRI(tri)) { + isea_rotate(pt, 180.0); + } + tc = isea_triangle_xy(tri); + tc.x *= radius; + tc.y *= radius; + pt->x += tc.x; + pt->y += tc.y; + + return tri; } /* convert projected triangle coords to quad xy coords, return quad number */ ISEA_STATIC int isea_ptdd(int tri, struct isea_pt *pt) { - int downtri, quad; - - downtri = (((tri - 1) / 5) % 2 == 1); - quad = ((tri - 1) % 5) + ((tri - 1) / 10) * 5 + 1; - - isea_rotate(pt, downtri ? 240.0 : 60.0); - if (downtri) { - pt->x += 0.5; - /* pt->y += cos(30.0 * M_PI / 180.0); */ - pt->y += .86602540378443864672; - } - return quad; + int downtri, quad; + + downtri = (((tri - 1) / 5) % 2 == 1); + quad = ((tri - 1) % 5) + ((tri - 1) / 10) * 5 + 1; + + isea_rotate(pt, downtri ? 240.0 : 60.0); + if (downtri) { + pt->x += 0.5; + /* pt->y += cos(30.0 * M_PI / 180.0); */ + pt->y += .86602540378443864672; + } + return quad; } ISEA_STATIC int isea_dddi_ap3odd(struct isea_dgg *g, int quad, struct isea_pt *pt, struct isea_pt *di) { - struct isea_pt v; - double hexwidth; - double sidelength; /* in hexes */ - int d, i; - int maxcoord; - struct hex h; - - /* This is the number of hexes from apex to base of a triangle */ - sidelength = (pow(2.0, g->resolution) + 1.0) / 2.0; - - /* apex to base is cos(30deg) */ - hexwidth = cos(M_PI / 6.0) / sidelength; - - /* TODO I think sidelength is always x.5, so - * (int)sidelength * 2 + 1 might be just as good - */ - maxcoord = (int) (sidelength * 2.0 + 0.5); - - v = *pt; - hexbin2(hexwidth, v.x, v.y, &h.x, &h.y); - h.iso = 0; - hex_iso(&h); - - d = h.x - h.z; - i = h.x + h.y + h.y; - - /* - * you want to test for max coords for the next quad in the same - * "row" first to get the case where both are max - */ - if (quad <= 5) { - if (d == 0 && i == maxcoord) { - /* north pole */ - quad = 0; - d = 0; - i = 0; - } else if (i == maxcoord) { - /* upper right in next quad */ - quad += 1; - if (quad == 6) - quad = 1; - i = maxcoord - d; - d = 0; - } else if (d == maxcoord) { - /* lower right in quad to lower right */ - quad += 5; - d = 0; - } - } else if (quad >= 6) { - if (i == 0 && d == maxcoord) { - /* south pole */ - quad = 11; - d = 0; - i = 0; - } else if (d == maxcoord) { - /* lower right in next quad */ - quad += 1; - if (quad == 11) - quad = 6; - d = maxcoord - i; - i = 0; - } else if (i == maxcoord) { - /* upper right in quad to upper right */ - quad = (quad - 4) % 5; - i = 0; - } - } - - di->x = d; - di->y = i; - - g->quad = quad; - return quad; + struct isea_pt v; + double hexwidth; + double sidelength; /* in hexes */ + int d, i; + int maxcoord; + struct hex h; + + /* This is the number of hexes from apex to base of a triangle */ + sidelength = (pow(2.0, g->resolution) + 1.0) / 2.0; + + /* apex to base is cos(30deg) */ + hexwidth = cos(M_PI / 6.0) / sidelength; + + /* TODO I think sidelength is always x.5, so + * (int)sidelength * 2 + 1 might be just as good + */ + maxcoord = (int) (sidelength * 2.0 + 0.5); + + v = *pt; + hexbin2(hexwidth, v.x, v.y, &h.x, &h.y); + h.iso = 0; + hex_iso(&h); + + d = h.x - h.z; + i = h.x + h.y + h.y; + + /* + * you want to test for max coords for the next quad in the same + * "row" first to get the case where both are max + */ + if (quad <= 5) { + if (d == 0 && i == maxcoord) { + /* north pole */ + quad = 0; + d = 0; + i = 0; + } else if (i == maxcoord) { + /* upper right in next quad */ + quad += 1; + if (quad == 6) + quad = 1; + i = maxcoord - d; + d = 0; + } else if (d == maxcoord) { + /* lower right in quad to lower right */ + quad += 5; + d = 0; + } + } else if (quad >= 6) { + if (i == 0 && d == maxcoord) { + /* south pole */ + quad = 11; + d = 0; + i = 0; + } else if (d == maxcoord) { + /* lower right in next quad */ + quad += 1; + if (quad == 11) + quad = 6; + d = maxcoord - i; + i = 0; + } else if (i == maxcoord) { + /* upper right in quad to upper right */ + quad = (quad - 4) % 5; + i = 0; + } + } + + di->x = d; + di->y = i; + + g->quad = quad; + return quad; } ISEA_STATIC int isea_dddi(struct isea_dgg *g, int quad, struct isea_pt *pt, struct isea_pt *di) { - struct isea_pt v; - double hexwidth; - int sidelength; /* in hexes */ - struct hex h; - - if (g->aperture == 3 && g->resolution % 2 != 0) { - return isea_dddi_ap3odd(g, quad, pt, di); - } - /* todo might want to do this as an iterated loop */ - if (g->aperture >0) { - sidelength = (int) (pow(g->aperture, g->resolution / 2.0) + 0.5); - } else { - sidelength = g->resolution; - } - - hexwidth = 1.0 / sidelength; - - v = *pt; - isea_rotate(&v, -30.0); - hexbin2(hexwidth, v.x, v.y, &h.x, &h.y); - h.iso = 0; - hex_iso(&h); - - /* we may actually be on another quad */ - if (quad <= 5) { - if (h.x == 0 && h.z == -sidelength) { - /* north pole */ - quad = 0; - h.z = 0; - h.y = 0; - h.x = 0; - } else if (h.z == -sidelength) { - quad = quad + 1; - if (quad == 6) - quad = 1; - h.y = sidelength - h.x; - h.z = h.x - sidelength; - h.x = 0; - } else if (h.x == sidelength) { - quad += 5; - h.y = -h.z; - h.x = 0; - } - } else if (quad >= 6) { - if (h.z == 0 && h.x == sidelength) { - /* south pole */ - quad = 11; - h.x = 0; - h.y = 0; - h.z = 0; - } else if (h.x == sidelength) { - quad = quad + 1; - if (quad == 11) - quad = 6; - h.x = h.y + sidelength; - h.y = 0; - h.z = -h.x; - } else if (h.y == -sidelength) { - quad -= 4; - h.y = 0; - h.z = -h.x; - } - } - di->x = h.x; - di->y = -h.z; - - g->quad = quad; - return quad; + struct isea_pt v; + double hexwidth; + int sidelength; /* in hexes */ + struct hex h; + + if (g->aperture == 3 && g->resolution % 2 != 0) { + return isea_dddi_ap3odd(g, quad, pt, di); + } + /* todo might want to do this as an iterated loop */ + if (g->aperture >0) { + sidelength = (int) (pow(g->aperture, g->resolution / 2.0) + 0.5); + } else { + sidelength = g->resolution; + } + + hexwidth = 1.0 / sidelength; + + v = *pt; + isea_rotate(&v, -30.0); + hexbin2(hexwidth, v.x, v.y, &h.x, &h.y); + h.iso = 0; + hex_iso(&h); + + /* we may actually be on another quad */ + if (quad <= 5) { + if (h.x == 0 && h.z == -sidelength) { + /* north pole */ + quad = 0; + h.z = 0; + h.y = 0; + h.x = 0; + } else if (h.z == -sidelength) { + quad = quad + 1; + if (quad == 6) + quad = 1; + h.y = sidelength - h.x; + h.z = h.x - sidelength; + h.x = 0; + } else if (h.x == sidelength) { + quad += 5; + h.y = -h.z; + h.x = 0; + } + } else if (quad >= 6) { + if (h.z == 0 && h.x == sidelength) { + /* south pole */ + quad = 11; + h.x = 0; + h.y = 0; + h.z = 0; + } else if (h.x == sidelength) { + quad = quad + 1; + if (quad == 11) + quad = 6; + h.x = h.y + sidelength; + h.y = 0; + h.z = -h.x; + } else if (h.y == -sidelength) { + quad -= 4; + h.y = 0; + h.z = -h.x; + } + } + di->x = h.x; + di->y = -h.z; + + g->quad = quad; + return quad; } ISEA_STATIC int isea_ptdi(struct isea_dgg *g, int tri, struct isea_pt *pt, - struct isea_pt *di) { - struct isea_pt v; - int quad; - - v = *pt; - quad = isea_ptdd(tri, &v); - quad = isea_dddi(g, quad, &v, di); - return quad; + struct isea_pt *di) { + struct isea_pt v; + int quad; + + v = *pt; + quad = isea_ptdd(tri, &v); + quad = isea_dddi(g, quad, &v, di); + return quad; } /* q2di to seqnum */ ISEA_STATIC int isea_disn(struct isea_dgg *g, int quad, struct isea_pt *di) { - int sidelength; - int sn, height; - int hexes; - - if (quad == 0) { - g->serial = 1; - return g->serial; - } - /* hexes in a quad */ - hexes = (int) (pow(g->aperture, g->resolution) + 0.5); - if (quad == 11) { - g->serial = 1 + 10 * hexes + 1; - return g->serial; - } - if (g->aperture == 3 && g->resolution % 2 == 1) { - height = (int) (pow(g->aperture, (g->resolution - 1) / 2.0)); - sn = ((int) di->x) * height; - sn += ((int) di->y) / height; - sn += (quad - 1) * hexes; - sn += 2; - } else { - sidelength = (int) (pow(g->aperture, g->resolution / 2.0) + 0.5); - sn = (quad - 1) * hexes + sidelength * di->x + di->y + 2; - } - - g->serial = sn; - return sn; + int sidelength; + int sn, height; + int hexes; + + if (quad == 0) { + g->serial = 1; + return g->serial; + } + /* hexes in a quad */ + hexes = (int) (pow(g->aperture, g->resolution) + 0.5); + if (quad == 11) { + g->serial = 1 + 10 * hexes + 1; + return g->serial; + } + if (g->aperture == 3 && g->resolution % 2 == 1) { + height = (int) (pow(g->aperture, (g->resolution - 1) / 2.0)); + sn = ((int) di->x) * height; + sn += ((int) di->y) / height; + sn += (quad - 1) * hexes; + sn += 2; + } else { + sidelength = (int) (pow(g->aperture, g->resolution / 2.0) + 0.5); + sn = (quad - 1) * hexes + sidelength * di->x + di->y + 2; + } + + g->serial = sn; + return sn; } /* TODO just encode the quad in the d or i coordinate @@ -906,118 +906,118 @@ int isea_disn(struct isea_dgg *g, int quad, struct isea_pt *di) { /* convert a q2di to global hex coord */ ISEA_STATIC int isea_hex(struct isea_dgg *g, int tri, - struct isea_pt *pt, struct isea_pt *hex) { - struct isea_pt v; - int sidelength; - int d, i, x, y, quad; - - quad = isea_ptdi(g, tri, pt, &v); - - hex->x = ((int)v.x << 4) + quad; - hex->y = v.y; - - return 1; - - d = v.x; - i = v.y; - - /* Aperture 3 odd resolutions */ - if (g->aperture == 3 && g->resolution % 2 != 0) { - int offset = (int)(pow(3.0, g->resolution - 1) + 0.5); - - d += offset * ((g->quad-1) % 5); - i += offset * ((g->quad-1) % 5); - - if (quad == 0) { - d = 0; - i = offset; - } else if (quad == 11) { - d = 2 * offset; - i = 0; - } else if (quad > 5) { - d += offset; - } - - x = (2*d - i) /3; - y = (2*i - d) /3; - - hex->x = x + offset / 3; - hex->y = y + 2 * offset / 3; - return 1; - } - - /* aperture 3 even resolutions and aperture 4 */ - sidelength = (int) (pow(g->aperture, g->resolution / 2.0) + 0.5); - if (g->quad == 0) { - hex->x = 0; - hex->y = sidelength; - } else if (g->quad == 11) { - hex->x = sidelength * 2; - hex->y = 0; - } else { - hex->x = d + sidelength * ((g->quad-1) % 5); - if (g->quad > 5) hex->x += sidelength; - hex->y = i + sidelength * ((g->quad-1) % 5); - } - - return 1; + struct isea_pt *pt, struct isea_pt *hex) { + struct isea_pt v; + int sidelength; + int d, i, x, y, quad; + + quad = isea_ptdi(g, tri, pt, &v); + + hex->x = ((int)v.x << 4) + quad; + hex->y = v.y; + + return 1; + + d = v.x; + i = v.y; + + /* Aperture 3 odd resolutions */ + if (g->aperture == 3 && g->resolution % 2 != 0) { + int offset = (int)(pow(3.0, g->resolution - 1) + 0.5); + + d += offset * ((g->quad-1) % 5); + i += offset * ((g->quad-1) % 5); + + if (quad == 0) { + d = 0; + i = offset; + } else if (quad == 11) { + d = 2 * offset; + i = 0; + } else if (quad > 5) { + d += offset; + } + + x = (2*d - i) /3; + y = (2*i - d) /3; + + hex->x = x + offset / 3; + hex->y = y + 2 * offset / 3; + return 1; + } + + /* aperture 3 even resolutions and aperture 4 */ + sidelength = (int) (pow(g->aperture, g->resolution / 2.0) + 0.5); + if (g->quad == 0) { + hex->x = 0; + hex->y = sidelength; + } else if (g->quad == 11) { + hex->x = sidelength * 2; + hex->y = 0; + } else { + hex->x = d + sidelength * ((g->quad-1) % 5); + if (g->quad > 5) hex->x += sidelength; + hex->y = i + sidelength * ((g->quad-1) % 5); + } + + return 1; } ISEA_STATIC struct isea_pt isea_forward(struct isea_dgg *g, struct isea_geo *in) { - int tri; - struct isea_pt out, coord; - - tri = isea_transform(g, in, &out); - - if (g->output == ISEA_PLANE) { - isea_tri_plane(tri, &out, g->radius); - return out; - } - - /* convert to isea standard triangle size */ - out.x = out.x / g->radius * ISEA_SCALE; - out.y = out.y / g->radius * ISEA_SCALE; - out.x += 0.5; - out.y += 2.0 * .14433756729740644112; - - switch (g->output) { - case ISEA_PROJTRI: - /* nothing to do, already in projected triangle */ - break; - case ISEA_VERTEX2DD: - g->quad = isea_ptdd(tri, &out); - break; - case ISEA_Q2DD: - /* Same as above, we just don't print as much */ - g->quad = isea_ptdd(tri, &out); - break; - case ISEA_Q2DI: - g->quad = isea_ptdi(g, tri, &out, &coord); - return coord; - break; - case ISEA_SEQNUM: - isea_ptdi(g, tri, &out, &coord); - /* disn will set g->serial */ - isea_disn(g, g->quad, &coord); - return coord; - break; - case ISEA_HEX: - isea_hex(g, tri, &out, &coord); - return coord; - break; - } - - return out; + int tri; + struct isea_pt out, coord; + + tri = isea_transform(g, in, &out); + + if (g->output == ISEA_PLANE) { + isea_tri_plane(tri, &out, g->radius); + return out; + } + + /* convert to isea standard triangle size */ + out.x = out.x / g->radius * ISEA_SCALE; + out.y = out.y / g->radius * ISEA_SCALE; + out.x += 0.5; + out.y += 2.0 * .14433756729740644112; + + switch (g->output) { + case ISEA_PROJTRI: + /* nothing to do, already in projected triangle */ + break; + case ISEA_VERTEX2DD: + g->quad = isea_ptdd(tri, &out); + break; + case ISEA_Q2DD: + /* Same as above, we just don't print as much */ + g->quad = isea_ptdd(tri, &out); + break; + case ISEA_Q2DI: + g->quad = isea_ptdi(g, tri, &out, &coord); + return coord; + break; + case ISEA_SEQNUM: + isea_ptdi(g, tri, &out, &coord); + /* disn will set g->serial */ + isea_disn(g, g->quad, &coord); + return coord; + break; + case ISEA_HEX: + isea_hex(g, tri, &out, &coord); + return coord; + break; + } + + return out; } /* * Proj 4 integration code follows */ #define PROJ_PARMS__ \ - struct isea_dgg dgg; + struct isea_dgg dgg; #define PJ_LIB__ #include @@ -1025,95 +1025,95 @@ isea_forward(struct isea_dgg *g, struct isea_geo *in) PROJ_HEAD(isea, "Icosahedral Snyder Equal Area") "\n\tSph"; FORWARD(s_forward); - struct isea_pt out; - struct isea_geo in; + struct isea_pt out; + struct isea_geo in; - in.lon = lp.lam; - in.lat = lp.phi; + in.lon = lp.lam; + in.lat = lp.phi; - out = isea_forward(&P->dgg, &in); - - xy.x = out.x; - xy.y = out.y; + out = isea_forward(&P->dgg, &in); - return xy; + xy.x = out.x; + xy.y = out.y; + + return xy; } FREEUP; if (P) pj_dalloc(P); } ENTRY0(isea) - char *opt; + char *opt; P->fwd = s_forward; isea_grid_init(&P->dgg); P->dgg.output = ISEA_PLANE; -/* P->dgg.radius = P->a; / * otherwise defaults to 1 */ - /* calling library will scale, I think */ - - opt = pj_param(P->ctx,P->params, "sorient").s; - if (opt) { - if (!strcmp(opt, "isea")) { - isea_orient_isea(&P->dgg); - } else if (!strcmp(opt, "pole")) { - isea_orient_pole(&P->dgg); - } else { - E_ERROR(-34); - } - } - - if (pj_param(P->ctx,P->params, "tazi").i) { - P->dgg.o_az = pj_param(P->ctx,P->params, "razi").f; - } - - if (pj_param(P->ctx,P->params, "tlon_0").i) { - P->dgg.o_lon = pj_param(P->ctx,P->params, "rlon_0").f; - } - - if (pj_param(P->ctx,P->params, "tlat_0").i) { - P->dgg.o_lat = pj_param(P->ctx,P->params, "rlat_0").f; - } - - if (pj_param(P->ctx,P->params, "taperture").i) { - P->dgg.aperture = pj_param(P->ctx,P->params, "iaperture").i; - } - - if (pj_param(P->ctx,P->params, "tresolution").i) { - P->dgg.resolution = pj_param(P->ctx,P->params, "iresolution").i; - } - - opt = pj_param(P->ctx,P->params, "smode").s; - if (opt) { - if (!strcmp(opt, "plane")) { - P->dgg.output = ISEA_PLANE; - } else if (!strcmp(opt, "di")) { - P->dgg.output = ISEA_Q2DI; - } - else if (!strcmp(opt, "dd")) { - P->dgg.output = ISEA_Q2DD; - } - else if (!strcmp(opt, "hex")) { - P->dgg.output = ISEA_HEX; - } - else { - /* TODO verify error code. Possibly eliminate magic */ - E_ERROR(-34); - } - } - - if (pj_param(P->ctx,P->params, "trescale").i) { - P->dgg.radius = ISEA_SCALE; - } - - if (pj_param(P->ctx,P->params, "tresolution").i) { - P->dgg.resolution = pj_param(P->ctx,P->params, "iresolution").i; - } else { - P->dgg.resolution = 4; - } - - if (pj_param(P->ctx,P->params, "taperture").i) { - P->dgg.aperture = pj_param(P->ctx,P->params, "iaperture").i; - } else { - P->dgg.aperture = 3; - } +/* P->dgg.radius = P->a; / * otherwise defaults to 1 */ + /* calling library will scale, I think */ + + opt = pj_param(P->ctx,P->params, "sorient").s; + if (opt) { + if (!strcmp(opt, "isea")) { + isea_orient_isea(&P->dgg); + } else if (!strcmp(opt, "pole")) { + isea_orient_pole(&P->dgg); + } else { + E_ERROR(-34); + } + } + + if (pj_param(P->ctx,P->params, "tazi").i) { + P->dgg.o_az = pj_param(P->ctx,P->params, "razi").f; + } + + if (pj_param(P->ctx,P->params, "tlon_0").i) { + P->dgg.o_lon = pj_param(P->ctx,P->params, "rlon_0").f; + } + + if (pj_param(P->ctx,P->params, "tlat_0").i) { + P->dgg.o_lat = pj_param(P->ctx,P->params, "rlat_0").f; + } + + if (pj_param(P->ctx,P->params, "taperture").i) { + P->dgg.aperture = pj_param(P->ctx,P->params, "iaperture").i; + } + + if (pj_param(P->ctx,P->params, "tresolution").i) { + P->dgg.resolution = pj_param(P->ctx,P->params, "iresolution").i; + } + + opt = pj_param(P->ctx,P->params, "smode").s; + if (opt) { + if (!strcmp(opt, "plane")) { + P->dgg.output = ISEA_PLANE; + } else if (!strcmp(opt, "di")) { + P->dgg.output = ISEA_Q2DI; + } + else if (!strcmp(opt, "dd")) { + P->dgg.output = ISEA_Q2DD; + } + else if (!strcmp(opt, "hex")) { + P->dgg.output = ISEA_HEX; + } + else { + /* TODO verify error code. Possibly eliminate magic */ + E_ERROR(-34); + } + } + + if (pj_param(P->ctx,P->params, "trescale").i) { + P->dgg.radius = ISEA_SCALE; + } + + if (pj_param(P->ctx,P->params, "tresolution").i) { + P->dgg.resolution = pj_param(P->ctx,P->params, "iresolution").i; + } else { + P->dgg.resolution = 4; + } + + if (pj_param(P->ctx,P->params, "taperture").i) { + P->dgg.aperture = pj_param(P->ctx,P->params, "iaperture").i; + } else { + P->dgg.aperture = 3; + } ENDENTRY(P) diff --git a/src/PJ_krovak.c b/src/PJ_krovak.c index dd250134..09a8311e 100644 --- a/src/PJ_krovak.c +++ b/src/PJ_krovak.c @@ -30,7 +30,7 @@ *****************************************************************************/ #define PROJ_PARMS__ \ - double C_x; + double C_x; #define PJ_LIB__ #include @@ -42,22 +42,22 @@ PROJ_HEAD(krovak, "Krovak") "\n\tPCyl., Ellps."; /** NOTES: According to EPSG the full Krovak projection method should have the following parameters. Within PROJ.4 the azimuth, and pseudo - standard parallel are hardcoded in the algorithm and can't be + standard parallel are hardcoded in the algorithm and can't be altered from outside. The others all have defaults to match the common usage with Krovak projection. lat_0 = latitude of centre of the projection - + lon_0 = longitude of centre of the projection - + ** = azimuth (true) of the centre line passing through the centre of the projection ** = latitude of pseudo standard parallel - + k = scale factor on the pseudo standard parallel - + x_0 = False Easting of the centre of the projection at the apex of the cone - + y_0 = False Northing of the centre of the projection at the apex of the cone **/ @@ -68,127 +68,127 @@ FORWARD(e_forward); /* ellipsoid */ /* calculate xy from lat/lon */ /* Constants, identical to inverse transform function */ - double s45, s90, e2, e, alfa, uq, u0, g, k, k1, n0, ro0, ad, a, s0, n; - double gfi, u, fi0, deltav, s, d, eps, ro; + double s45, s90, e2, e, alfa, uq, u0, g, k, k1, n0, ro0, ad, a, s0, n; + double gfi, u, fi0, deltav, s, d, eps, ro; - s45 = 0.785398163397448; /* 45deg */ - s90 = 2 * s45; - fi0 = P->phi0; /* Latitude of projection centre 49deg 30' */ + s45 = 0.785398163397448; /* 45deg */ + s90 = 2 * s45; + fi0 = P->phi0; /* Latitude of projection centre 49deg 30' */ - /* Ellipsoid is used as Parameter in for.c and inv.c, therefore a must + /* Ellipsoid is used as Parameter in for.c and inv.c, therefore a must be set to 1 here. Ellipsoid Bessel 1841 a = 6377397.155m 1/f = 299.1528128, e2=0.006674372230614; */ - a = 1; /* 6377397.155; */ - /* e2 = P->es;*/ /* 0.006674372230614; */ - e2 = 0.006674372230614; - e = sqrt(e2); + a = 1; /* 6377397.155; */ + /* e2 = P->es;*/ /* 0.006674372230614; */ + e2 = 0.006674372230614; + e = sqrt(e2); - alfa = sqrt(1. + (e2 * pow(cos(fi0), 4)) / (1. - e2)); + alfa = sqrt(1. + (e2 * pow(cos(fi0), 4)) / (1. - e2)); - uq = 1.04216856380474; /* DU(2, 59, 42, 42.69689) */ - u0 = asin(sin(fi0) / alfa); - g = pow( (1. + e * sin(fi0)) / (1. - e * sin(fi0)) , alfa * e / 2. ); + uq = 1.04216856380474; /* DU(2, 59, 42, 42.69689) */ + u0 = asin(sin(fi0) / alfa); + g = pow( (1. + e * sin(fi0)) / (1. - e * sin(fi0)) , alfa * e / 2. ); - k = tan( u0 / 2. + s45) / pow (tan(fi0 / 2. + s45) , alfa) * g; + k = tan( u0 / 2. + s45) / pow (tan(fi0 / 2. + s45) , alfa) * g; - k1 = P->k0; - n0 = a * sqrt(1. - e2) / (1. - e2 * pow(sin(fi0), 2)); - s0 = 1.37008346281555; /* Latitude of pseudo standard parallel 78deg 30'00" N */ - n = sin(s0); - ro0 = k1 * n0 / tan(s0); - ad = s90 - uq; + k1 = P->k0; + n0 = a * sqrt(1. - e2) / (1. - e2 * pow(sin(fi0), 2)); + s0 = 1.37008346281555; /* Latitude of pseudo standard parallel 78deg 30'00" N */ + n = sin(s0); + ro0 = k1 * n0 / tan(s0); + ad = s90 - uq; /* Transformation */ - gfi =pow ( ((1. + e * sin(lp.phi)) / + gfi =pow ( ((1. + e * sin(lp.phi)) / (1. - e * sin(lp.phi))) , (alfa * e / 2.)); - u= 2. * (atan(k * pow( tan(lp.phi / 2. + s45), alfa) / gfi)-s45); + u= 2. * (atan(k * pow( tan(lp.phi / 2. + s45), alfa) / gfi)-s45); - deltav = - lp.lam * alfa; + deltav = - lp.lam * alfa; - s = asin(cos(ad) * sin(u) + sin(ad) * cos(u) * cos(deltav)); - d = asin(cos(u) * sin(deltav) / cos(s)); - eps = n * d; - ro = ro0 * pow(tan(s0 / 2. + s45) , n) / pow(tan(s / 2. + s45) , n) ; + s = asin(cos(ad) * sin(u) + sin(ad) * cos(u) * cos(deltav)); + d = asin(cos(u) * sin(deltav) / cos(s)); + eps = n * d; + ro = ro0 * pow(tan(s0 / 2. + s45) , n) / pow(tan(s / 2. + s45) , n) ; /* x and y are reverted! */ - xy.y = ro * cos(eps) / a; - xy.x = ro * sin(eps) / a; + xy.y = ro * cos(eps) / a; + xy.x = ro * sin(eps) / a; if( !pj_param(P->ctx, P->params, "tczech").i ) - { - xy.y *= -1.0; - xy.x *= -1.0; - } + { + xy.y *= -1.0; + xy.x *= -1.0; + } - return (xy); + return (xy); } INVERSE(e_inverse); /* ellipsoid */ - /* calculate lat/lon from xy */ + /* calculate lat/lon from xy */ /* Constants, identisch wie in der Umkehrfunktion */ - double s45, s90, fi0, e2, e, alfa, uq, u0, g, k, k1, n0, ro0, ad, a, s0, n; - double u, deltav, s, d, eps, ro, fi1, xy0; - int ok; + double s45, s90, fi0, e2, e, alfa, uq, u0, g, k, k1, n0, ro0, ad, a, s0, n; + double u, deltav, s, d, eps, ro, fi1, xy0; + int ok; - s45 = 0.785398163397448; /* 45deg */ - s90 = 2 * s45; - fi0 = P->phi0; /* Latitude of projection centre 49deg 30' */ + s45 = 0.785398163397448; /* 45deg */ + s90 = 2 * s45; + fi0 = P->phi0; /* Latitude of projection centre 49deg 30' */ - /* Ellipsoid is used as Parameter in for.c and inv.c, therefore a must + /* Ellipsoid is used as Parameter in for.c and inv.c, therefore a must be set to 1 here. Ellipsoid Bessel 1841 a = 6377397.155m 1/f = 299.1528128, e2=0.006674372230614; */ - a = 1; /* 6377397.155; */ - /* e2 = P->es; */ /* 0.006674372230614; */ - e2 = 0.006674372230614; - e = sqrt(e2); + a = 1; /* 6377397.155; */ + /* e2 = P->es; */ /* 0.006674372230614; */ + e2 = 0.006674372230614; + e = sqrt(e2); - alfa = sqrt(1. + (e2 * pow(cos(fi0), 4)) / (1. - e2)); - uq = 1.04216856380474; /* DU(2, 59, 42, 42.69689) */ - u0 = asin(sin(fi0) / alfa); - g = pow( (1. + e * sin(fi0)) / (1. - e * sin(fi0)) , alfa * e / 2. ); + alfa = sqrt(1. + (e2 * pow(cos(fi0), 4)) / (1. - e2)); + uq = 1.04216856380474; /* DU(2, 59, 42, 42.69689) */ + u0 = asin(sin(fi0) / alfa); + g = pow( (1. + e * sin(fi0)) / (1. - e * sin(fi0)) , alfa * e / 2. ); - k = tan( u0 / 2. + s45) / pow (tan(fi0 / 2. + s45) , alfa) * g; + k = tan( u0 / 2. + s45) / pow (tan(fi0 / 2. + s45) , alfa) * g; - k1 = P->k0; - n0 = a * sqrt(1. - e2) / (1. - e2 * pow(sin(fi0), 2)); - s0 = 1.37008346281555; /* Latitude of pseudo standard parallel 78deg 30'00" N */ - n = sin(s0); - ro0 = k1 * n0 / tan(s0); - ad = s90 - uq; + k1 = P->k0; + n0 = a * sqrt(1. - e2) / (1. - e2 * pow(sin(fi0), 2)); + s0 = 1.37008346281555; /* Latitude of pseudo standard parallel 78deg 30'00" N */ + n = sin(s0); + ro0 = k1 * n0 / tan(s0); + ad = s90 - uq; /* Transformation */ /* revert y, x*/ - xy0=xy.x; - xy.x=xy.y; - xy.y=xy0; + xy0=xy.x; + xy.x=xy.y; + xy.y=xy0; if( !pj_param(P->ctx, P->params, "tczech").i ) - { - xy.x *= -1.0; - xy.y *= -1.0; - } + { + xy.x *= -1.0; + xy.y *= -1.0; + } - ro = sqrt(xy.x * xy.x + xy.y * xy.y); - eps = atan2(xy.y, xy.x); - d = eps / sin(s0); - s = 2. * (atan( pow(ro0 / ro, 1. / n) * tan(s0 / 2. + s45)) - s45); + ro = sqrt(xy.x * xy.x + xy.y * xy.y); + eps = atan2(xy.y, xy.x); + d = eps / sin(s0); + s = 2. * (atan( pow(ro0 / ro, 1. / n) * tan(s0 / 2. + s45)) - s45); - u = asin(cos(ad) * sin(s) - sin(ad) * cos(s) * cos(d)); - deltav = asin(cos(s) * sin(d) / cos(u)); + u = asin(cos(ad) * sin(s) - sin(ad) * cos(s) * cos(d)); + deltav = asin(cos(s) * sin(d) / cos(u)); - lp.lam = P->lam0 - deltav / alfa; + lp.lam = P->lam0 - deltav / alfa; /* ITERATION FOR lp.phi */ fi1 = u; @@ -196,7 +196,7 @@ INVERSE(e_inverse); /* ellipsoid */ ok = 0; do { - lp.phi = 2. * ( atan( pow( k, -1. / alfa) * + lp.phi = 2. * ( atan( pow( k, -1. / alfa) * pow( tan(u / 2. + s45) , 1. / alfa) * pow( (1. + e * sin(fi1)) / (1. - e * sin(fi1)) , e / 2.) ) - s45); @@ -215,34 +215,34 @@ INVERSE(e_inverse); /* ellipsoid */ FREEUP; if (P) pj_dalloc(P); } ENTRY0(krovak) - double ts; - /* read some Parameters, - * here Latitude Truescale */ + double ts; + /* read some Parameters, + * here Latitude Truescale */ + + ts = pj_param(P->ctx, P->params, "rlat_ts").f; + P->C_x = ts; - ts = pj_param(P->ctx, P->params, "rlat_ts").f; - P->C_x = ts; - - /* we want Bessel as fixed ellipsoid */ - P->a = 6377397.155; - P->e = sqrt(P->es = 0.006674372230614); + /* we want Bessel as fixed ellipsoid */ + P->a = 6377397.155; + P->e = sqrt(P->es = 0.006674372230614); /* if latitude of projection center is not set, use 49d30'N */ - if (!pj_param(P->ctx, P->params, "tlat_0").i) - P->phi0 = 0.863937979737193; + if (!pj_param(P->ctx, P->params, "tlat_0").i) + P->phi0 = 0.863937979737193; /* if center long is not set use 42d30'E of Ferro - 17d40' for Ferro */ /* that will correspond to using longitudes relative to greenwich */ /* as input and output, instead of lat/long relative to Ferro */ - if (!pj_param(P->ctx, P->params, "tlon_0").i) + if (!pj_param(P->ctx, P->params, "tlon_0").i) P->lam0 = 0.7417649320975901 - 0.308341501185665; /* if scale not set default to 0.9999 */ - if (!pj_param(P->ctx, P->params, "tk").i) + if (!pj_param(P->ctx, P->params, "tk").i) P->k0 = 0.9999; - /* always the same */ - P->inv = e_inverse; - P->fwd = e_forward; + /* always the same */ + P->inv = e_inverse; + P->fwd = e_forward; ENDENTRY(P) -- cgit v1.2.3 From 0d0f7dbc29d464d555ac37000e80f17476bcce84 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Mon, 18 Apr 2016 14:52:12 +0200 Subject: Converted gn_sinu, sinu, eck6 and mbtfps --- src/PJ_aea.c | 4 - src/PJ_gn_sinu.c | 377 +++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 326 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 4db5e386..539f829a 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -355,12 +355,10 @@ source files int pj_aeqd_selftest (void) {return 10000;} int pj_alsk_selftest (void) {return 10000;} -int pj_eck6_selftest (void) {return 10000;} int pj_eqc_selftest (void) {return 10000;} int pj_eqdc_selftest (void) {return 10000;} int pj_etmerc_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} -int pj_gn_sinu_selftest (void) {return 10000;} int pj_goode_selftest (void) {return 10000;} int pj_gs48_selftest (void) {return 10000;} int pj_gs50_selftest (void) {return 10000;} @@ -392,7 +390,6 @@ int pj_lsat_selftest (void) {return 10000;} int pj_mbt_fps_selftest (void) {return 10000;} int pj_mbtfpp_selftest (void) {return 10000;} int pj_mbtfpq_selftest (void) {return 10000;} -int pj_mbtfps_selftest (void) {return 10000;} int pj_merc_selftest (void) {return 10000;} int pj_mil_os_selftest (void) {return 10000;} int pj_mill_selftest (void) {return 10000;} @@ -426,7 +423,6 @@ int pj_robin_selftest (void) {return 10000;} int pj_rouss_selftest (void) {return 10000;} int pj_rpoly_selftest (void) {return 10000;} int pj_sch_selftest (void) {return 10000;} -int pj_sinu_selftest (void) {return 10000;} int pj_gstmerc_selftest (void) {return 10000;} int pj_tpers_selftest (void) {return 10000;} diff --git a/src/PJ_gn_sinu.c b/src/PJ_gn_sinu.c index 1ab43826..4b33b185 100644 --- a/src/PJ_gn_sinu.c +++ b/src/PJ_gn_sinu.c @@ -1,98 +1,373 @@ -#define PROJ_PARMS__ \ - double *en; \ - double m, n, C_x, C_y; #define PJ_LIB__ -#include +#include + PROJ_HEAD(gn_sinu, "General Sinusoidal Series") "\n\tPCyl, Sph.\n\tm= n="; PROJ_HEAD(sinu, "Sinusoidal (Sanson-Flamsteed)") "\n\tPCyl, Sph&Ell"; PROJ_HEAD(eck6, "Eckert VI") "\n\tPCyl, Sph."; PROJ_HEAD(mbtfps, "McBryde-Thomas Flat-Polar Sinusoidal") "\n\tPCyl, Sph."; -#define EPS10 1e-10 + +#define EPS10 1e-10 #define MAX_ITER 8 #define LOOP_TOL 1e-7 -/* Ellipsoidal Sinusoidal only */ -FORWARD(e_forward); /* ellipsoid */ + +struct pj_opaque { + double *en; + double m, n, C_x, C_y; +}; + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; double s, c; - xy.y = pj_mlfn(lp.phi, s = sin(lp.phi), c = cos(lp.phi), P->en); + xy.y = pj_mlfn(lp.phi, s = sin(lp.phi), c = cos(lp.phi), P->opaque->en); xy.x = lp.lam * c / sqrt(1. - P->es * s * s); - return (xy); + return xy; } -INVERSE(e_inverse); /* ellipsoid */ + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; double s; - if ((s = fabs(lp.phi = pj_inv_mlfn(P->ctx, xy.y, P->es, P->en))) < HALFPI) { + if ((s = fabs(lp.phi = pj_inv_mlfn(P->ctx, xy.y, P->es, P->opaque->en))) < HALFPI) { s = sin(lp.phi); lp.lam = xy.x * sqrt(1. - P->es * s * s) / cos(lp.phi); - } else if ((s - EPS10) < HALFPI) + } else if ((s - EPS10) < HALFPI) { lp.lam = 0.; - else I_ERROR; - return (lp); + } else { + I_ERROR; + } + + return lp; } -/* General spherical sinusoidals */ -FORWARD(s_forward); /* sphere */ - if (!P->m) - lp.phi = P->n != 1. ? aasin(P->ctx,P->n * sin(lp.phi)): lp.phi; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + if (!Q->m) + lp.phi = Q->n != 1. ? aasin(P->ctx,Q->n * sin(lp.phi)): lp.phi; else { double k, V; int i; - k = P->n * sin(lp.phi); + k = Q->n * sin(lp.phi); for (i = MAX_ITER; i ; --i) { - lp.phi -= V = (P->m * lp.phi + sin(lp.phi) - k) / - (P->m + cos(lp.phi)); + lp.phi -= V = (Q->m * lp.phi + sin(lp.phi) - k) / + (Q->m + cos(lp.phi)); if (fabs(V) < LOOP_TOL) break; } if (!i) F_ERROR } - xy.x = P->C_x * lp.lam * (P->m + cos(lp.phi)); - xy.y = P->C_y * lp.phi; - return (xy); + xy.x = Q->C_x * lp.lam * (Q->m + cos(lp.phi)); + xy.y = Q->C_y * lp.phi; + + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + xy.y /= Q->C_y; + lp.phi = Q->m ? aasin(P->ctx,(Q->m * xy.y + sin(xy.y)) / Q->n) : + ( Q->n != 1. ? aasin(P->ctx,sin(xy.y) / Q->n) : xy.y ); + lp.lam = xy.x / (Q->C_x * (Q->m + cos(xy.y))); + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + if (P->opaque->en) + pj_dalloc(P->opaque->en); + + pj_dealloc (P->opaque); + return pj_dealloc(P); } -INVERSE(s_inverse); /* sphere */ - xy.y /= P->C_y; - lp.phi = P->m ? aasin(P->ctx,(P->m * xy.y + sin(xy.y)) / P->n) : - ( P->n != 1. ? aasin(P->ctx,sin(xy.y) / P->n) : xy.y ); - lp.lam = xy.x / (P->C_x * (P->m + cos(xy.y))); - return (lp); + + +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; if (P) { if (P->en) pj_dalloc(P->en); pj_dalloc(P); } } - static void /* for spheres, only */ -setup(PJ *P) { + + +/* for spheres, only */ +static void setup(PJ *P) { + struct pj_opaque *Q = P->opaque; P->es = 0; - P->C_x = (P->C_y = sqrt((P->m + 1.) / P->n))/(P->m + 1.); P->inv = s_inverse; P->fwd = s_forward; + + Q->C_x = (Q->C_y = sqrt((Q->m + 1.) / Q->n))/(Q->m + 1.); } -ENTRY1(sinu, en) - if (!(P->en = pj_enfn(P->es))) + + +PJ *PROJECTION(sinu) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + if (!(Q->en = pj_enfn(P->es))) E_ERROR_0; + if (P->es) { P->inv = e_inverse; P->fwd = e_forward; } else { - P->n = 1.; - P->m = 0.; + Q->n = 1.; + Q->m = 0.; setup(P); } -ENDENTRY(P) -ENTRY1(eck6, en) - P->m = 1.; - P->n = 2.570796326794896619231321691; + return P; +} + + +PJ *PROJECTION(eck6) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->m = 1.; + Q->n = 2.570796326794896619231321691; setup(P); -ENDENTRY(P) -ENTRY1(mbtfps, en) - P->m = 0.5; - P->n = 1.785398163397448309615660845; + + return P; +} + + +PJ *PROJECTION(mbtfps) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->m = 0.5; + Q->n = 1.785398163397448309615660845; setup(P); -ENDENTRY(P) -ENTRY1(gn_sinu, en) + + return P; +} + + +PJ *PROJECTION(gn_sinu) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + if (pj_param(P->ctx, P->params, "tn").i && pj_param(P->ctx, P->params, "tm").i) { - P->n = pj_param(P->ctx, P->params, "dn").f; - P->m = pj_param(P->ctx, P->params, "dm").f; + Q->n = pj_param(P->ctx, P->params, "dn").f; + Q->m = pj_param(P->ctx, P->params, "dm").f; } else E_ERROR(-99) + setup(P); -ENDENTRY(P) + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_sinu_selftest (void) {return 0;} +#else + +int pj_sinu_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=sinu +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=sinu +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222605.29953946592, 110574.38855415257}, + { 222605.29953946592, -110574.38855415257}, + {-222605.29953946592, 110574.38855415257}, + {-222605.29953946592, -110574.38855415257}, + }; + + XY s_fwd_expect[] = { + { 223368.11902663155, 111701.07212763709}, + { 223368.11902663155, -111701.07212763709}, + {-223368.11902663155, 111701.07212763709}, + {-223368.11902663155, -111701.07212763709}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.0017966305684613522, 0.00090436947707945409}, + { 0.0017966305684613522, -0.00090436947707945409}, + {-0.0017966305684613522, 0.00090436947707945409}, + {-0.0017966305684613522, -0.00090436947707945409}, + }; + + LP s_inv_expect[] = { + { 0.0017904931100023887, 0.00089524655489191132}, + { 0.0017904931100023887, -0.00089524655489191132}, + {-0.0017904931100023887, 0.00089524655489191132}, + {-0.0017904931100023887, -0.00089524655489191132}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif + +#ifdef PJ_OMIT_SELFTEST +int pj_eck6_selftest (void) {return 0;} +#else + +int pj_eck6_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=eck6 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 197021.60562899226, 126640.42073317352}, + { 197021.60562899226, -126640.42073317352}, + {-197021.60562899226, 126640.42073317352}, + {-197021.60562899226, -126640.42073317352}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.002029978749734037, 0.00078963032910382171}, + { 0.002029978749734037, -0.00078963032910382171}, + {-0.002029978749734037, 0.00078963032910382171}, + {-0.002029978749734037, -0.00078963032910382171}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif + +#ifdef PJ_OMIT_SELFTEST +int pj_mbtfps_selftest (void) {return 0;} +#else + +int pj_mbtfps_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=mbtfps +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 204740.11747857218, 121864.72971934026}, + { 204740.11747857218, -121864.72971934026}, + {-204740.11747857218, 121864.72971934026}, + {-204740.11747857218, -121864.72971934026}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0019534152166442065, 0.00082057965689633387}, + { 0.0019534152166442065, -0.00082057965689633387}, + {-0.0019534152166442065, 0.00082057965689633387}, + {-0.0019534152166442065, -0.00082057965689633387}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif + + +#ifdef PJ_OMIT_SELFTEST +int pj_gn_sinu_selftest (void) {return 0;} +#else + +int pj_gn_sinu_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=gn_sinu +a=6400000 +lat_1=0.5 +lat_2=2 +m=1 +n=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223385.13250469571, 111698.23644718733}, + { 223385.13250469571, -111698.23644718733}, + {-223385.13250469571, 111698.23644718733}, + {-223385.13250469571, -111698.23644718733}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0017904931098931057, 0.00089524655491012516}, + { 0.0017904931098931057, -0.00089524655491012516}, + {-0.0017904931098931057, 0.00089524655491012516}, + {-0.0017904931098931057, -0.00089524655491012516}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From eca42acae89ad5892cb14a29ae7be46891e5c059 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 19 Apr 2016 09:37:35 +0200 Subject: Converted goode --- src/PJ_aea.c | 1 - src/PJ_goode.c | 177 +++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 128 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 539f829a..de3d6c03 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -359,7 +359,6 @@ int pj_eqc_selftest (void) {return 10000;} int pj_eqdc_selftest (void) {return 10000;} int pj_etmerc_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} -int pj_goode_selftest (void) {return 10000;} int pj_gs48_selftest (void) {return 10000;} int pj_gs50_selftest (void) {return 10000;} int pj_hammer_selftest (void) {return 10000;} diff --git a/src/PJ_goode.c b/src/PJ_goode.c index b03e15d1..d577f901 100644 --- a/src/PJ_goode.c +++ b/src/PJ_goode.c @@ -1,49 +1,128 @@ -#define PROJ_PARMS__ \ - struct PJconsts *sinu; \ - struct PJconsts *moll; -#define PJ_LIB__ -#include -PROJ_HEAD(goode, "Goode Homolosine") "\n\tPCyl, Sph."; - C_NAMESPACE PJ -*pj_sinu(PJ *), *pj_moll(PJ *); -#define Y_COR 0.05280 -#define PHI_LIM .71093078197902358062 -FORWARD(s_forward); /* spheroid */ - if (fabs(lp.phi) <= PHI_LIM) - xy = P->sinu->fwd(lp, P->sinu); - else { - xy = P->moll->fwd(lp, P->moll); - xy.y -= lp.phi >= 0.0 ? Y_COR : -Y_COR; - } - return (xy); -} -INVERSE(s_inverse); /* spheroid */ - if (fabs(xy.y) <= PHI_LIM) - lp = P->sinu->inv(xy, P->sinu); - else { - xy.y += xy.y >= 0.0 ? Y_COR : -Y_COR; - lp = P->moll->inv(xy, P->moll); - } - return (lp); -} -FREEUP; - if (P) { - if (P->sinu) - (*(P->sinu->pfree))(P->sinu); - if (P->moll) - (*(P->moll->pfree))(P->moll); - pj_dalloc(P); - } -} -ENTRY2(goode, sinu, moll) - P->es = 0.; - if (!(P->sinu = pj_sinu(0)) || !(P->moll = pj_moll(0))) - E_ERROR_0; - P->sinu->es = 0.; - P->sinu->ctx = P->ctx; - P->moll->ctx = P->ctx; - if (!(P->sinu = pj_sinu(P->sinu)) || !(P->moll = pj_moll(P->moll))) - E_ERROR_0; - P->fwd = s_forward; - P->inv = s_inverse; -ENDENTRY(P) +#define PJ_LIB__ +#include + +PROJ_HEAD(goode, "Goode Homolosine") "\n\tPCyl, Sph."; + +#define Y_COR 0.05280 +#define PHI_LIM 0.71093078197902358062 + +struct pj_opaque { + struct PJconsts *sinu; \ + struct PJconsts *moll; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + if (fabs(lp.phi) <= PHI_LIM) + xy = Q->sinu->fwd(lp, Q->sinu); + else { + xy = Q->moll->fwd(lp, Q->moll); + xy.y -= lp.phi >= 0.0 ? Y_COR : -Y_COR; + } + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + if (fabs(xy.y) <= PHI_LIM) + lp = Q->sinu->inv(xy, Q->sinu); + else { + xy.y += xy.y >= 0.0 ? Y_COR : -Y_COR; + lp = Q->moll->inv(xy, Q->moll); + } + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc(P); + if (P->opaque->sinu) + pj_dealloc(P->opaque->sinu); + if (P->opaque->moll) + pj_dealloc(P->opaque->moll); + pj_dealloc (P->opaque); + return pj_dealloc(P); + +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(goode) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->es = 0.; + if (!(Q->sinu = pj_sinu(0)) || !(Q->moll = pj_moll(0))) + E_ERROR_0; + Q->sinu->es = 0.; + Q->sinu->ctx = P->ctx; + Q->moll->ctx = P->ctx; + if (!(Q->sinu = pj_sinu(Q->sinu)) || !(Q->moll = pj_moll(Q->moll))) + E_ERROR_0; + + P->fwd = s_forward; + P->inv = s_inverse; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_goode_selftest (void) {return 0;} +#else + +int pj_goode_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=goode +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223368.11902663155, 111701.07212763709 }, + { 223368.11902663155, -111701.07212763709 }, + {-223368.11902663155, 111701.07212763709 }, + {-223368.11902663155, -111701.07212763709 }, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0017904931100023887, 0.00089524655489191132 }, + { 0.0017904931100023887, -0.00089524655489191132 }, + {-0.0017904931100023887, 0.00089524655489191132 }, + {-0.0017904931100023887, -0.00089524655489191132 }, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 774f90d415769f951fa738d0b39bcd66b670d76c Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 19 Apr 2016 09:58:50 +0200 Subject: Converted gstmerc --- src/PJ_aea.c | 1 - src/PJ_gstmerc.c | 165 +++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 124 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index de3d6c03..fd9ee4dd 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -423,7 +423,6 @@ int pj_rouss_selftest (void) {return 10000;} int pj_rpoly_selftest (void) {return 10000;} int pj_sch_selftest (void) {return 10000;} -int pj_gstmerc_selftest (void) {return 10000;} int pj_tpers_selftest (void) {return 10000;} int pj_utm_selftest (void) {return 10000;} diff --git a/src/PJ_gstmerc.c b/src/PJ_gstmerc.c index da67389f..2720c945 100644 --- a/src/PJ_gstmerc.c +++ b/src/PJ_gstmerc.c @@ -1,48 +1,131 @@ -#define PROJ_PARMS__ \ - double lamc;\ - double phic;\ - double c;\ - double n1;\ - double n2;\ - double XS;\ - double YS; - #define PJ_LIB__ -# include +#include + PROJ_HEAD(gstmerc, "Gauss-Schreiber Transverse Mercator (aka Gauss-Laborde Reunion)") "\n\tCyl, Sph&Ell\n\tlat_0= lon_0= k_0="; -FORWARD(s_forward); /* spheroid */ + +struct pj_opaque { + double lamc; + double phic; + double c; + double n1; + double n2; + double XS; + double YS; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double L, Ls, sinLs1, Ls1; - L= P->n1*lp.lam; - Ls= P->c+P->n1*log(pj_tsfn(-1.0*lp.phi,-1.0*sin(lp.phi),P->e)); - sinLs1= sin(L)/cosh(Ls); - Ls1= log(pj_tsfn(-1.0*asin(sinLs1),0.0,0.0)); - xy.x= (P->XS + P->n2*Ls1)*P->ra; - xy.y= (P->YS + P->n2*atan(sinh(Ls)/cos(L)))*P->ra; - /*fprintf(stderr,"fwd:\nL =%16.13f\nLs =%16.13f\nLs1 =%16.13f\nLP(%16.13f,%16.13f)=XY(%16.4f,%16.4f)\n",L,Ls,Ls1,lp.lam+P->lam0,lp.phi,(xy.x*P->a + P->x0)*P->to_meter,(xy.y*P->a + P->y0)*P->to_meter);*/ - return (xy); + + L = Q->n1*lp.lam; + Ls = Q->c + Q->n1 * log(pj_tsfn(-1.0 * lp.phi, -1.0 * sin(lp.phi), P->e)); + sinLs1 = sin(L) / cosh(Ls); + Ls1 = log(pj_tsfn(-1.0 * asin(sinLs1), 0.0, 0.0)); + xy.x = (Q->XS + Q->n2*Ls1) * P->ra; + xy.y = (Q->YS + Q->n2*atan(sinh(Ls) / cos(L))) * P->ra; + + return xy; } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double L, LC, sinC; - L= atan(sinh((xy.x*P->a - P->XS)/P->n2)/cos((xy.y*P->a - P->YS)/P->n2)); - sinC= sin((xy.y*P->a - P->YS)/P->n2)/cosh((xy.x*P->a - P->XS)/P->n2); - LC= log(pj_tsfn(-1.0*asin(sinC),0.0,0.0)); - lp.lam= L/P->n1; - lp.phi= -1.0*pj_phi2(P->ctx, exp((LC-P->c)/P->n1),P->e); - /*fprintf(stderr,"inv:\nL =%16.13f\nsinC =%16.13f\nLC =%16.13f\nXY(%16.4f,%16.4f)=LP(%16.13f,%16.13f)\n",L,sinC,LC,((xy.x/P->ra)+P->x0)/P->to_meter,((xy.y/P->ra)+P->y0)/P->to_meter,lp.lam+P->lam0,lp.phi);*/ - return (lp); + + L = atan(sinh((xy.x * P->a - Q->XS) / Q->n2) / cos((xy.y * P->a - Q->YS) / Q->n2)); + sinC = sin((xy.y * P->a - Q->YS) / Q->n2) / cosh((xy.x * P->a - Q->XS) / Q->n2); + LC = log(pj_tsfn(-1.0 * asin(sinC), 0.0, 0.0)); + lp.lam = L / Q->n1; + lp.phi = -1.0 * pj_phi2(P->ctx, exp((LC - Q->c) / Q->n1), P->e); + + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(gstmerc) - P->lamc= P->lam0; - P->n1= sqrt(1.0+P->es*pow(cos(P->phi0),4.0)/(1.0-P->es)); - P->phic= asin(sin(P->phi0)/P->n1); - P->c= log(pj_tsfn(-1.0*P->phic,0.0,0.0)) - -P->n1*log(pj_tsfn(-1.0*P->phi0,-1.0*sin(P->phi0),P->e)); - P->n2= P->k0*P->a*sqrt(1.0-P->es)/(1.0-P->es*sin(P->phi0)*sin(P->phi0)); - P->XS= 0;/* -P->x0 */ - P->YS= -1.0*P->n2*P->phic;/* -P->y0 */ - P->inv= s_inverse; - P->fwd= s_forward; - /*fprintf(stderr,"a (m) =%16.4f\ne =%16.13f\nl0(rad)=%16.13f\np0(rad)=%16.13f\nk0 =%16.4f\nX0 (m)=%16.4f\nY0 (m)=%16.4f\n\nlC(rad)=%16.13f\npC(rad)=%16.13f\nc =%16.13f\nn1 =%16.13f\nn2 (m) =%16.4f\nXS (m) =%16.4f\nYS (m) =%16.4f\n", P->a, P->e, P->lam0, P->phi0, P->k0, P->x0, P->y0, P->lamc, P->phic, P->c, P->n1, P->n2, P->XS +P->x0, P->YS + P->y0);*/ -ENDENTRY(P) + + +PJ *PROJECTION(gstmerc) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->lamc = P->lam0; + Q->n1 = sqrt(1.0 + P->es * pow(cos(P->phi0), 4.0) / (1.0 - P->es)); + Q->phic = asin(sin(P->phi0) / Q->n1); + Q->c = log(pj_tsfn(-1.0 * Q->phic, 0.0, 0.0)) + - Q->n1 * log(pj_tsfn(-1.0 * P->phi0, -1.0 * sin(P->phi0), P->e)); + Q->n2 = P->k0 * P->a * sqrt(1.0 - P->es) / (1.0 - P->es * sin(P->phi0) * sin(P->phi0)); + Q->XS = 0; + Q->YS = -1.0 * Q->n2 * Q->phic; + + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_gstmerc_selftest (void) {return 0;} +#else + +int pj_gstmerc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=gstmerc +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + + XY s_fwd_expect[] = { + { 223413.46640632182, 111769.14504058557}, + { 223413.46640632182, -111769.14504058668}, + {-223413.46640632302, 111769.14504058557}, + {-223413.46640632302, -111769.14504058668}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0017904931097109673, 0.0008952465544509083}, + { 0.0017904931097109673, -0.0008952465544509083}, + {-0.0017904931097109673, 0.0008952465544509083}, + {-0.0017904931097109673, -0.0008952465544509083}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 6559b20bf3554e3d24b0b21a42fdb9be4e8771fb Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 19 Apr 2016 10:06:47 +0200 Subject: Converted hammer --- src/PJ_aea.c | 1 - src/PJ_hammer.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 110 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index fd9ee4dd..63f2c54e 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -361,7 +361,6 @@ int pj_etmerc_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} int pj_gs48_selftest (void) {return 10000;} int pj_gs50_selftest (void) {return 10000;} -int pj_hammer_selftest (void) {return 10000;} int pj_hatano_selftest (void) {return 10000;} int pj_healpix_selftest (void) {return 10000;} int pj_rhealpix_selftest (void) {return 10000;} diff --git a/src/PJ_hammer.c b/src/PJ_hammer.c index 8b15fe50..3118640b 100644 --- a/src/PJ_hammer.c +++ b/src/PJ_hammer.c @@ -1,43 +1,129 @@ -#define PROJ_PARMS__ \ - double w; \ - double m, rm; #define PJ_LIB__ -#define EPS 1.0e-10 -# include +#include + PROJ_HEAD(hammer, "Hammer & Eckert-Greifendorff") "\n\tMisc Sph, \n\tW= M="; -FORWARD(s_forward); /* spheroid */ + +#define EPS 1.0e-10 + +struct pj_opaque { + double w; \ + double m, rm; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double cosphi, d; - d = sqrt(2./(1. + (cosphi = cos(lp.phi)) * cos(lp.lam *= P->w))); - xy.x = P->m * d * cosphi * sin(lp.lam); - xy.y = P->rm * d * sin(lp.phi); - return (xy); + d = sqrt(2./(1. + (cosphi = cos(lp.phi)) * cos(lp.lam *= Q->w))); + xy.x = Q->m * d * cosphi * sin(lp.lam); + xy.y = Q->rm * d * sin(lp.phi); + return xy; } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double z; - z = sqrt(1. - 0.25*P->w*P->w*xy.x*xy.x - 0.25*xy.y*xy.y); + + z = sqrt(1. - 0.25*Q->w*Q->w*xy.x*xy.x - 0.25*xy.y*xy.y); if (fabs(2.*z*z-1.) < EPS) { lp.lam = HUGE_VAL; lp.phi = HUGE_VAL; pj_errno = -14; } else { - lp.lam = aatan2(P->w * xy.x * z,2. * z * z - 1)/P->w; + lp.lam = aatan2(Q->w * xy.x * z,2. * z * z - 1)/Q->w; lp.phi = aasin(P->ctx,z * xy.y); } - return (lp); + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(hammer) + + +PJ *PROJECTION(hammer) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + if (pj_param(P->ctx, P->params, "tW").i) { - if ((P->w = fabs(pj_param(P->ctx, P->params, "dW").f)) <= 0.) E_ERROR(-27); + if ((Q->w = fabs(pj_param(P->ctx, P->params, "dW").f)) <= 0.) E_ERROR(-27); } else - P->w = .5; + Q->w = .5; if (pj_param(P->ctx, P->params, "tM").i) { - if ((P->m = fabs(pj_param(P->ctx, P->params, "dM").f)) <= 0.) E_ERROR(-27); + if ((Q->m = fabs(pj_param(P->ctx, P->params, "dM").f)) <= 0.) E_ERROR(-27); } else - P->m = 1.; - P->rm = 1. / P->m; - P->m /= P->w; - P->es = 0.; P->fwd = s_forward; P->inv = s_inverse; -ENDENTRY(P) + Q->m = 1.; + + Q->rm = 1. / Q->m; + Q->m /= Q->w; + + P->es = 0.; + P->fwd = s_forward; + P->inv = s_inverse; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_hammer_selftest (void) {return 0;} +#else + +int pj_hammer_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=hammer +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223373.78870324057, 111703.90739776699}, + { 223373.78870324057, -111703.90739776699}, + {-223373.78870324057, 111703.90739776699}, + {-223373.78870324057, -111703.90739776699}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.001790493109965961, 0.00089524655487369749}, + { 0.001790493109965961, -0.00089524655487369749}, + {-0.001790493109965961, 0.00089524655487369749}, + {-0.001790493109965961, -0.00089524655487369749}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From f541a9ac036494c8df374ebb4e328e1e2987b385 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 19 Apr 2016 10:24:03 +0200 Subject: Converted hatano --- src/PJ_aea.c | 1 - src/PJ_hatano.c | 185 ++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 134 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 63f2c54e..31f524c7 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -361,7 +361,6 @@ int pj_etmerc_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} int pj_gs48_selftest (void) {return 10000;} int pj_gs50_selftest (void) {return 10000;} -int pj_hatano_selftest (void) {return 10000;} int pj_healpix_selftest (void) {return 10000;} int pj_rhealpix_selftest (void) {return 10000;} int pj_igh_selftest (void) {return 10000;} diff --git a/src/PJ_hatano.c b/src/PJ_hatano.c index 4ba9d6e8..ca97849b 100644 --- a/src/PJ_hatano.c +++ b/src/PJ_hatano.c @@ -1,51 +1,134 @@ -#define PJ_LIB__ -#include -PROJ_HEAD(hatano, "Hatano Asymmetrical Equal Area") "\n\tPCyl, Sph."; -#define NITER 20 -#define EPS 1e-7 -#define ONETOL 1.000001 -#define CN 2.67595 -#define CS 2.43763 -#define RCN 0.37369906014686373063 -#define RCS 0.41023453108141924738 -#define FYCN 1.75859 -#define FYCS 1.93052 -#define RYCN 0.56863737426006061674 -#define RYCS 0.51799515156538134803 -#define FXC 0.85 -#define RXC 1.17647058823529411764 -FORWARD(s_forward); /* spheroid */ - double th1, c; - int i; - (void) P; - - c = sin(lp.phi) * (lp.phi < 0. ? CS : CN); - for (i = NITER; i; --i) { - lp.phi -= th1 = (lp.phi + sin(lp.phi) - c) / (1. + cos(lp.phi)); - if (fabs(th1) < EPS) break; - } - xy.x = FXC * lp.lam * cos(lp.phi *= .5); - xy.y = sin(lp.phi) * (lp.phi < 0. ? FYCS : FYCN); - return (xy); -} -INVERSE(s_inverse); /* spheroid */ - double th; - - th = xy.y * ( xy.y < 0. ? RYCS : RYCN); - if (fabs(th) > 1.) - if (fabs(th) > ONETOL) I_ERROR - else th = th > 0. ? HALFPI : - HALFPI; - else - th = asin(th); - lp.lam = RXC * xy.x / cos(th); - th += th; - lp.phi = (th + sin(th)) * (xy.y < 0. ? RCS : RCN); - if (fabs(lp.phi) > 1.) - if (fabs(lp.phi) > ONETOL) I_ERROR - else lp.phi = lp.phi > 0. ? HALFPI : - HALFPI; - else - lp.phi = asin(lp.phi); - return (lp); -} -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(hatano) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) +#define PJ_LIB__ +#include + +PROJ_HEAD(hatano, "Hatano Asymmetrical Equal Area") "\n\tPCyl, Sph."; + +#define NITER 20 +#define EPS 1e-7 +#define ONETOL 1.000001 +#define CN 2.67595 +#define CS 2.43763 +#define RCN 0.37369906014686373063 +#define RCS 0.41023453108141924738 +#define FYCN 1.75859 +#define FYCS 1.93052 +#define RYCN 0.56863737426006061674 +#define RYCS 0.51799515156538134803 +#define FXC 0.85 +#define RXC 1.17647058823529411764 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + double th1, c; + int i; + (void) P; + + c = sin(lp.phi) * (lp.phi < 0. ? CS : CN); + for (i = NITER; i; --i) { + lp.phi -= th1 = (lp.phi + sin(lp.phi) - c) / (1. + cos(lp.phi)); + if (fabs(th1) < EPS) break; + } + xy.x = FXC * lp.lam * cos(lp.phi *= .5); + xy.y = sin(lp.phi) * (lp.phi < 0. ? FYCS : FYCN); + + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + double th; + + th = xy.y * ( xy.y < 0. ? RYCS : RYCN); + if (fabs(th) > 1.) { + if (fabs(th) > ONETOL) { + I_ERROR; + } else { + th = th > 0. ? HALFPI : - HALFPI; + } + } else { + th = asin(th); + } + + lp.lam = RXC * xy.x / cos(th); + th += th; + lp.phi = (th + sin(th)) * (xy.y < 0. ? RCS : RCN); + if (fabs(lp.phi) > 1.) { + if (fabs(lp.phi) > ONETOL) { + I_ERROR; + } else { + lp.phi = lp.phi > 0. ? HALFPI : - HALFPI; + } + } else { + lp.phi = asin(lp.phi); + } + + return (lp); +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(hatano) { + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_hatano_selftest (void) {return 0;} +#else + +int pj_hatano_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=hatano +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 189878.87894652804, 131409.8024406255 }, + { 189881.08195244463, -131409.14227607418 }, + {-189878.87894652804, 131409.8024406255 }, + {-189881.08195244463, -131409.14227607418 }, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0021064624821817597, 0.00076095689425791926 }, + { 0.0021064624821676096, -0.00076095777439265377 }, + {-0.0021064624821817597, 0.00076095689425791926 }, + {-0.0021064624821676096, -0.00076095777439265377 }, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 5ae5f2368ad4a1d75827297a4c9e0ddb6e33b0c4 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 19 Apr 2016 11:45:06 +0200 Subject: Converted healpix and rhealpix --- src/PJ_aea.c | 2 - src/PJ_healpix.c | 311 ++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 263 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 31f524c7..1d7b8e7d 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -361,8 +361,6 @@ int pj_etmerc_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} int pj_gs48_selftest (void) {return 10000;} int pj_gs50_selftest (void) {return 10000;} -int pj_healpix_selftest (void) {return 10000;} -int pj_rhealpix_selftest (void) {return 10000;} int pj_igh_selftest (void) {return 10000;} int pj_imw_p_selftest (void) {return 10000;} int pj_isea_selftest (void) {return 10000;} diff --git a/src/PJ_healpix.c b/src/PJ_healpix.c index a645ba34..ae5aa5be 100644 --- a/src/PJ_healpix.c +++ b/src/PJ_healpix.c @@ -28,16 +28,13 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. *****************************************************************************/ -# define PROJ_PARMS__ \ - int north_square; \ - int south_square; \ - double qp; \ - double *apa; # define PJ_LIB__ -# include +# include + PROJ_HEAD(healpix, "HEALPix") "\n\tSph., Ellps."; PROJ_HEAD(rhealpix, "rHEALPix") "\n\tSph., Ellps.\n\tnorth_square= south_square="; -# include + +# include /* Matrix for counterclockwise rotation by pi/2: */ # define R1 {{ 0,-1},{ 1, 0}} /* Matrix for counterclockwise rotation by pi: */ @@ -50,16 +47,27 @@ PROJ_HEAD(rhealpix, "rHEALPix") "\n\tSph., Ellps.\n\tnorth_square= south_square= # define ROT {IDENT, R1, R2, R3, R3, R2, R1} /* Fuzz to handle rounding errors: */ # define EPS 1e-15 + +struct pj_opaque { + int north_square; \ + int south_square; \ + double qp; \ + double *apa; +}; + typedef struct { int cn; /* An integer 0--3 indicating the position of the polar cap. */ double x, y; /* Coordinates of the pole point (point of most extreme latitude on the polar caps). */ enum Region {north, south, equatorial} region; } CapMap; + typedef struct { double x, y; } Point; + double rot[7][2][2] = ROT; + /** * Returns the sign of the double. * @param v the parameter whose sign is returned. @@ -68,6 +76,8 @@ double rot[7][2][2] = ROT; double pj_sign (double v) { return v > 0 ? 1 : (v < 0 ? -1 : 0); } + + /** * Return the index of the matrix in ROT. * @param index ranges from -3 to 3. @@ -91,6 +101,8 @@ static int get_rotate_index(int index) { } return 0; } + + /** * Return 1 if point (testx, testy) lies in the interior of the polygon * determined by the vertices in vert, and return 0 otherwise. @@ -103,6 +115,7 @@ static int pnpoly(int nvert, double vert[][2], double testx, double testy) { int counter = 0; double xinters; Point p1, p2; + /* Check for boundrary cases */ for (i = 0; i < nvert; i++) { if (testx == vert[i][0] && testy == vert[i][1]) { @@ -135,6 +148,8 @@ static int pnpoly(int nvert, double vert[][2], double testx, double testy) { } return c; } + + /** * Return 1 if (x, y) lies in (the interior or boundary of) the image of the * HEALPix projection (in case proj=0) or in the image the rHEALPix projection @@ -184,17 +199,21 @@ int in_image(double x, double y, int proj, int north_square, int south_square) { sizeof(rhealpixVertsJit[0]), rhealpixVertsJit, x, y); } } + + /** * Return the authalic latitude of latitude alpha (if inverse=0) or * return the approximate latitude of authalic latitude alpha (if inverse=1). * P contains the relavent ellipsoid parameters. **/ double auth_lat(PJ *P, double alpha, int inverse) { + struct pj_opaque *Q = P->opaque; if (inverse == 0) { /* Authalic latitude. */ double q = pj_qsfn(sin(alpha), P->e, 1.0 - P->es); - double qp = P->qp; + double qp = Q->qp; double ratio = q/qp; + if (fabsl(ratio) > 1) { /* Rounding error. */ ratio = pj_sign(ratio); @@ -202,9 +221,11 @@ double auth_lat(PJ *P, double alpha, int inverse) { return asin(ratio); } else { /* Approximation to inverse authalic latitude. */ - return pj_authlat(alpha, P->apa); + return pj_authlat(alpha, Q->apa); } } + + /** * Return the HEALPix projection of the longitude-latitude point lp on * the unit sphere. @@ -214,6 +235,7 @@ XY healpix_sphere(LP lp) { double phi = lp.phi; double phi0 = asin(2.0/3.0); XY xy; + /* equatorial region */ if ( fabsl(phi) <= phi0) { xy.x = lam; @@ -231,6 +253,8 @@ XY healpix_sphere(LP lp) { } return xy; } + + /** * Return the inverse of healpix_sphere(). **/ @@ -239,6 +263,7 @@ LP healpix_sphere_inverse(XY xy) { double x = xy.x; double y = xy.y; double y0 = PI/4.0; + /* Equatorial region. */ if (fabsl(y) <= y0) { lp.lam = x; @@ -259,6 +284,8 @@ LP healpix_sphere_inverse(XY xy) { } return (lp); } + + /** * Return the vector sum a + b, where a and b are 2-dimensional vectors. * @param ret holds a + b. @@ -269,6 +296,8 @@ static void vector_add(double a[2], double b[2], double *ret) { ret[i] = a[i] + b[i]; } } + + /** * Return the vector difference a - b, where a and b are 2-dimensional vectors. * @param ret holds a - b. @@ -279,6 +308,8 @@ static void vector_sub(double a[2], double b[2], double*ret) { ret[i] = a[i] - b[i]; } } + + /** * Return the 2 x 1 matrix product a*b, where a is a 2 x 2 matrix and * b is a 2 x 1 matrix. @@ -294,6 +325,8 @@ static void dot_product(double a[2][2], double b[2], double *ret) { } } } + + /** * Return the number of the polar cap, the pole point coordinates, and * the region that (x, y) lies in. @@ -306,6 +339,7 @@ static CapMap get_cap(double x, double y, int north_square, int south_square, int inverse) { CapMap capmap; double c; + capmap.x = x; capmap.y = y; if (inverse == 0) { @@ -383,6 +417,8 @@ static CapMap get_cap(double x, double y, int north_square, int south_square, return capmap; } } + + /** * Rearrange point (x, y) in the HEALPix projection by * combining the polar caps into two polar squares. @@ -400,6 +436,7 @@ static XY combine_caps(double x, double y, int north_square, int south_square, double vector[2]; double v_min_c[2]; double ret_dot[2]; + CapMap capmap = get_cap(x, y, north_square, south_square, inverse); if (capmap.region == equatorial) { xy.x = capmap.x; @@ -463,17 +500,23 @@ static XY combine_caps(double x, double y, int north_square, int south_square, return xy; } } -FORWARD(s_healpix_forward); /* sphere */ + + +static XY s_healpix_forward(LP lp, PJ *P) { /* sphere */ (void) P; - (void) xy; return healpix_sphere(lp); } -FORWARD(e_healpix_forward); /* ellipsoid */ - (void) xy; + + +static XY e_healpix_forward(LP lp, PJ *P) { /* ellipsoid */ lp.phi = auth_lat(P, lp.phi, 0); return healpix_sphere(lp); } -INVERSE(s_healpix_inverse); /* sphere */ + + +static LP s_healpix_inverse(XY xy, PJ *P) { /* sphere */ + LP lp = {0.0,0.0}; + /* Check whether (x, y) lies in the HEALPix image */ if (in_image(xy.x, xy.y, 0, 0, 0) == 0) { lp.lam = HUGE_VAL; @@ -483,7 +526,11 @@ INVERSE(s_healpix_inverse); /* sphere */ } return healpix_sphere_inverse(xy); } -INVERSE(e_healpix_inverse); /* ellipsoid */ + + +static LP e_healpix_inverse(XY xy, PJ *P) { /* ellipsoid */ + LP lp = {0.0,0.0}; + /* Check whether (x, y) lies in the HEALPix image. */ if (in_image(xy.x, xy.y, 0, 0, 0) == 0) { lp.lam = HUGE_VAL; @@ -493,53 +540,90 @@ INVERSE(e_healpix_inverse); /* ellipsoid */ } lp = healpix_sphere_inverse(xy); lp.phi = auth_lat(P, lp.phi, 1); - return (lp); + return lp; } -FORWARD(s_rhealpix_forward); /* sphere */ - xy = healpix_sphere(lp); - return combine_caps(xy.x, xy.y, P->north_square, P->south_square, 0); + + +static XY s_rhealpix_forward(LP lp, PJ *P) { /* sphere */ + struct pj_opaque *Q = P->opaque; + + XY xy = healpix_sphere(lp); + return combine_caps(xy.x, xy.y, Q->north_square, Q->south_square, 0); } -FORWARD(e_rhealpix_forward); /* ellipsoid */ + + +static XY e_rhealpix_forward(LP lp, PJ *P) { /* ellipsoid */ + struct pj_opaque *Q = P->opaque; + lp.phi = auth_lat(P, lp.phi, 0); - xy = healpix_sphere(lp); - return combine_caps(xy.x, xy.y, P->north_square, P->south_square, 0); + XY xy = healpix_sphere(lp); + return combine_caps(xy.x, xy.y, Q->north_square, Q->south_square, 0); } -INVERSE(s_rhealpix_inverse); /* sphere */ + + +static LP s_rhealpix_inverse(XY xy, PJ *P) { /* sphere */ + struct pj_opaque *Q = P->opaque; + LP lp = {0.0,0.0}; + /* Check whether (x, y) lies in the rHEALPix image. */ - if (in_image(xy.x, xy.y, 1, P->north_square, P->south_square) == 0) { + if (in_image(xy.x, xy.y, 1, Q->north_square, Q->south_square) == 0) { lp.lam = HUGE_VAL; lp.phi = HUGE_VAL; pj_ctx_set_errno(P->ctx, -15); return lp; } - xy = combine_caps(xy.x, xy.y, P->north_square, P->south_square, 1); + xy = combine_caps(xy.x, xy.y, Q->north_square, Q->south_square, 1); return healpix_sphere_inverse(xy); } -INVERSE(e_rhealpix_inverse); /* ellipsoid */ + + +static LP e_rhealpix_inverse(XY xy, PJ *P) { /* ellipsoid */ + struct pj_opaque *Q = P->opaque; + LP lp = {0.0,0.0}; + /* Check whether (x, y) lies in the rHEALPix image. */ - if (in_image(xy.x, xy.y, 1, P->north_square, P->south_square) == 0) { + if (in_image(xy.x, xy.y, 1, Q->north_square, Q->south_square) == 0) { lp.lam = HUGE_VAL; lp.phi = HUGE_VAL; pj_ctx_set_errno(P->ctx, -15); return lp; } - xy = combine_caps(xy.x, xy.y, P->north_square, P->south_square, 1); + xy = combine_caps(xy.x, xy.y, Q->north_square, Q->south_square, 1); lp = healpix_sphere_inverse(xy); lp.phi = auth_lat(P, lp.phi, 1); return lp; } -FREEUP; - if (P) { - if (P->apa) - pj_dalloc(P->apa); - pj_dalloc(P); - } + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + if (P->opaque->apa) + pj_dealloc(P->opaque->apa); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; } -ENTRY1(healpix, apa) + + +PJ *PROJECTION(healpix) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + if (P->es) { - P->apa = pj_authset(P->es); /* For auth_lat(). */ - P->qp = pj_qsfn(1.0, P->e, P->one_es); /* For auth_lat(). */ - P->a = P->a*sqrt(0.5*P->qp); /* Set P->a to authalic radius. */ + Q->apa = pj_authset(P->es); /* For auth_lat(). */ + Q->qp = pj_qsfn(1.0, P->e, P->one_es); /* For auth_lat(). */ + P->a = P->a*sqrt(0.5*Q->qp); /* Set P->a to authalic radius. */ P->ra = 1.0/P->a; P->fwd = e_healpix_forward; P->inv = e_healpix_inverse; @@ -547,21 +631,31 @@ ENTRY1(healpix, apa) P->fwd = s_healpix_forward; P->inv = s_healpix_inverse; } -ENDENTRY(P) -ENTRY1(rhealpix, apa) - P->north_square = pj_param(P->ctx, P->params,"inorth_square").i; - P->south_square = pj_param(P->ctx, P->params,"isouth_square").i; + + return P; +} + + +PJ *PROJECTION(rhealpix) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->north_square = pj_param(P->ctx, P->params,"inorth_square").i; + Q->south_square = pj_param(P->ctx, P->params,"isouth_square").i; + /* Check for valid north_square and south_square inputs. */ - if (P->north_square < 0 || P->north_square > 3) { + if (Q->north_square < 0 || Q->north_square > 3) { E_ERROR(-47); } - if (P->south_square < 0 || P->south_square > 3) { + if (Q->south_square < 0 || Q->south_square > 3) { E_ERROR(-47); } if (P->es) { - P->apa = pj_authset(P->es); /* For auth_lat(). */ - P->qp = pj_qsfn(1.0, P->e, P->one_es); /* For auth_lat(). */ - P->a = P->a*sqrt(0.5*P->qp); /* Set P->a to authalic radius. */ + Q->apa = pj_authset(P->es); /* For auth_lat(). */ + Q->qp = pj_qsfn(1.0, P->e, P->one_es); /* For auth_lat(). */ + P->a = P->a*sqrt(0.5*Q->qp); /* Set P->a to authalic radius. */ P->ra = 1.0/P->a; P->fwd = e_rhealpix_forward; P->inv = e_rhealpix_inverse; @@ -569,4 +663,125 @@ ENTRY1(rhealpix, apa) P->fwd = s_rhealpix_forward; P->inv = s_rhealpix_inverse; } -ENDENTRY(P) + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_healpix_selftest (void) {return 0;} +#else + +int pj_healpix_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=healpix +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=healpix +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222390.10394923863, 130406.58866448226}, + { 222390.10394923863, -130406.58866448054}, + {-222390.10394923863, 130406.58866448226}, + {-222390.10394923863, -130406.58866448054}, + }; + + XY s_fwd_expect[] = { + { 223402.14425527418, 131588.04444199943}, + { 223402.14425527418, -131588.04444199943}, + {-223402.14425527418, 131588.04444199943}, + {-223402.14425527418, -131588.04444199943}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.0017986411845524453, 0.00076679453057823619}, + { 0.0017986411845524453, -0.00076679453057823619}, + {-0.0017986411845524453, 0.00076679453057823619}, + {-0.0017986411845524453, -0.00076679453057823619}, + }; + + LP s_inv_expect[] = { + { 0.0017904931097838226, 0.00075990887733981202}, + { 0.0017904931097838226, -0.00075990887733981202}, + {-0.0017904931097838226, 0.00075990887733981202}, + {-0.0017904931097838226, -0.00075990887733981202}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif + +#ifdef PJ_OMIT_SELFTEST +int pj_rhealpix_selftest (void) {return 0;} +#else + +int pj_rhealpix_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=rhealpix +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=rhealpix +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222390.10394923863, 130406.58866448226}, + { 222390.10394923863, -130406.58866448054}, + {-222390.10394923863, 130406.58866448226}, + {-222390.10394923863, -130406.58866448054}, + }; + + XY s_fwd_expect[] = { + { 223402.14425527418, 131588.04444199943}, + { 223402.14425527418, -131588.04444199943}, + {-223402.14425527418, 131588.04444199943}, + {-223402.14425527418, -131588.04444199943}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.0017986411845524453, 0.00076679453057823619}, + { 0.0017986411845524453, -0.00076679453057823619}, + {-0.0017986411845524453, 0.00076679453057823619}, + {-0.0017986411845524453, -0.00076679453057823619}, + }; + + LP s_inv_expect[] = { + { 0.0017904931097838226, 0.00075990887733981202}, + { 0.0017904931097838226, -0.00075990887733981202}, + {-0.0017904931097838226, 0.00075990887733981202}, + {-0.0017904931097838226, -0.00075990887733981202}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 1edecf4bed0863a2fe44db6d53024c6b090a8b80 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 19 Apr 2016 12:41:37 +0200 Subject: Converted igh --- src/PJ_aea.c | 1 - src/PJ_igh.c | 336 ++++++++++++++++++++++++++++++++++++----------------------- 2 files changed, 204 insertions(+), 133 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 1d7b8e7d..648838c1 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -361,7 +361,6 @@ int pj_etmerc_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} int pj_gs48_selftest (void) {return 10000;} int pj_gs50_selftest (void) {return 10000;} -int pj_igh_selftest (void) {return 10000;} int pj_imw_p_selftest (void) {return 10000;} int pj_isea_selftest (void) {return 10000;} diff --git a/src/PJ_igh.c b/src/PJ_igh.c index deca75b4..f82f4f3f 100644 --- a/src/PJ_igh.c +++ b/src/PJ_igh.c @@ -1,12 +1,9 @@ -#define PROJ_PARMS__ \ - struct PJconsts* pj[12]; \ - double dy0; #define PJ_LIB__ -#include +#include + PROJ_HEAD(igh, "Interrupted Goode Homolosine") "\n\tPCyl, Sph."; - C_NAMESPACE PJ -*pj_sinu(PJ *), *pj_moll(PJ *); +C_NAMESPACE PJ *pj_sinu(PJ *), *pj_moll(PJ *); static const double d4044118 = (40 + 44/60. + 11.8/3600.) * DEG_TO_RAD; // 40d 44' 11.8" [degrees] static const double d10 = 10 * DEG_TO_RAD; @@ -24,106 +21,137 @@ static const double d180 = 180 * DEG_TO_RAD; static const double EPSLN = 1.e-10; // allow a little 'slack' on zone edge positions -FORWARD(s_forward); /* spheroid */ - int z; - if (lp.phi >= d4044118) { // 1|2 - z = (lp.lam <= -d40 ? 1: 2); - } - else if (lp.phi >= 0) { // 3|4 - z = (lp.lam <= -d40 ? 3: 4); - } - else if (lp.phi >= -d4044118) { // 5|6|7|8 - if (lp.lam <= -d100) z = 5; // 5 - else if (lp.lam <= -d20) z = 6; // 6 - else if (lp.lam <= d80) z = 7; // 7 - else z = 8; // 8 - } - else { // 9|10|11|12 - if (lp.lam <= -d100) z = 9; // 9 - else if (lp.lam <= -d20) z = 10; // 10 - else if (lp.lam <= d80) z = 11; // 11 - else z = 12; // 12 - } +struct pj_opaque { + struct PJconsts* pj[12]; \ + double dy0; +}; - lp.lam -= P->pj[z-1]->lam0; - xy = P->pj[z-1]->fwd(lp, P->pj[z-1]); - xy.x += P->pj[z-1]->x0; - xy.y += P->pj[z-1]->y0; - return (xy); +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + int z; + + if (lp.phi >= d4044118) { // 1|2 + z = (lp.lam <= -d40 ? 1: 2); + } + else if (lp.phi >= 0) { // 3|4 + z = (lp.lam <= -d40 ? 3: 4); + } + else if (lp.phi >= -d4044118) { // 5|6|7|8 + if (lp.lam <= -d100) z = 5; // 5 + else if (lp.lam <= -d20) z = 6; // 6 + else if (lp.lam <= d80) z = 7; // 7 + else z = 8; // 8 + } + else { // 9|10|11|12 + if (lp.lam <= -d100) z = 9; // 9 + else if (lp.lam <= -d20) z = 10; // 10 + else if (lp.lam <= d80) z = 11; // 11 + else z = 12; // 12 + } + + lp.lam -= Q->pj[z-1]->lam0; + xy = Q->pj[z-1]->fwd(lp, Q->pj[z-1]); + xy.x += Q->pj[z-1]->x0; + xy.y += Q->pj[z-1]->y0; + + return xy; } -INVERSE(s_inverse); /* spheroid */ - const double y90 = P->dy0 + sqrt(2); // lt=90 corresponds to y=y0+sqrt(2) - - int z = 0; - if (xy.y > y90+EPSLN || xy.y < -y90+EPSLN) // 0 - z = 0; - else if (xy.y >= d4044118) // 1|2 - z = (xy.x <= -d40? 1: 2); - else if (xy.y >= 0) // 3|4 - z = (xy.x <= -d40? 3: 4); - else if (xy.y >= -d4044118) { // 5|6|7|8 - if (xy.x <= -d100) z = 5; // 5 - else if (xy.x <= -d20) z = 6; // 6 - else if (xy.x <= d80) z = 7; // 7 - else z = 8; // 8 - } - else { // 9|10|11|12 - if (xy.x <= -d100) z = 9; // 9 - else if (xy.x <= -d20) z = 10; // 10 - else if (xy.x <= d80) z = 11; // 11 - else z = 12; // 12 - } - if (z) - { - int ok = 0; - - xy.x -= P->pj[z-1]->x0; - xy.y -= P->pj[z-1]->y0; - lp = P->pj[z-1]->inv(xy, P->pj[z-1]); - lp.lam += P->pj[z-1]->lam0; - - switch (z) { - case 1: ok = (lp.lam >= -d180-EPSLN && lp.lam <= -d40+EPSLN) || - ((lp.lam >= -d40-EPSLN && lp.lam <= -d10+EPSLN) && - (lp.phi >= d60-EPSLN && lp.phi <= d90+EPSLN)); break; - case 2: ok = (lp.lam >= -d40-EPSLN && lp.lam <= d180+EPSLN) || - ((lp.lam >= -d180-EPSLN && lp.lam <= -d160+EPSLN) && - (lp.phi >= d50-EPSLN && lp.phi <= d90+EPSLN)) || - ((lp.lam >= -d50-EPSLN && lp.lam <= -d40+EPSLN) && - (lp.phi >= d60-EPSLN && lp.phi <= d90+EPSLN)); break; - case 3: ok = (lp.lam >= -d180-EPSLN && lp.lam <= -d40+EPSLN); break; - case 4: ok = (lp.lam >= -d40-EPSLN && lp.lam <= d180+EPSLN); break; - case 5: ok = (lp.lam >= -d180-EPSLN && lp.lam <= -d100+EPSLN); break; - case 6: ok = (lp.lam >= -d100-EPSLN && lp.lam <= -d20+EPSLN); break; - case 7: ok = (lp.lam >= -d20-EPSLN && lp.lam <= d80+EPSLN); break; - case 8: ok = (lp.lam >= d80-EPSLN && lp.lam <= d180+EPSLN); break; - case 9: ok = (lp.lam >= -d180-EPSLN && lp.lam <= -d100+EPSLN); break; - case 10: ok = (lp.lam >= -d100-EPSLN && lp.lam <= -d20+EPSLN); break; - case 11: ok = (lp.lam >= -d20-EPSLN && lp.lam <= d80+EPSLN); break; - case 12: ok = (lp.lam >= d80-EPSLN && lp.lam <= d180+EPSLN); break; - } - - z = (!ok? 0: z); // projectable? + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + const double y90 = Q->dy0 + sqrt(2); // lt=90 corresponds to y=y0+sqrt(2) + + int z = 0; + if (xy.y > y90+EPSLN || xy.y < -y90+EPSLN) // 0 + z = 0; + else if (xy.y >= d4044118) // 1|2 + z = (xy.x <= -d40? 1: 2); + else if (xy.y >= 0) // 3|4 + z = (xy.x <= -d40? 3: 4); + else if (xy.y >= -d4044118) { // 5|6|7|8 + if (xy.x <= -d100) z = 5; // 5 + else if (xy.x <= -d20) z = 6; // 6 + else if (xy.x <= d80) z = 7; // 7 + else z = 8; // 8 + } + else { // 9|10|11|12 + if (xy.x <= -d100) z = 9; // 9 + else if (xy.x <= -d20) z = 10; // 10 + else if (xy.x <= d80) z = 11; // 11 + else z = 12; // 12 + } + + if (z) { + int ok = 0; + + xy.x -= Q->pj[z-1]->x0; + xy.y -= Q->pj[z-1]->y0; + lp = Q->pj[z-1]->inv(xy, Q->pj[z-1]); + lp.lam += Q->pj[z-1]->lam0; + + switch (z) { + case 1: ok = (lp.lam >= -d180-EPSLN && lp.lam <= -d40+EPSLN) || + ((lp.lam >= -d40-EPSLN && lp.lam <= -d10+EPSLN) && + (lp.phi >= d60-EPSLN && lp.phi <= d90+EPSLN)); break; + case 2: ok = (lp.lam >= -d40-EPSLN && lp.lam <= d180+EPSLN) || + ((lp.lam >= -d180-EPSLN && lp.lam <= -d160+EPSLN) && + (lp.phi >= d50-EPSLN && lp.phi <= d90+EPSLN)) || + ((lp.lam >= -d50-EPSLN && lp.lam <= -d40+EPSLN) && + (lp.phi >= d60-EPSLN && lp.phi <= d90+EPSLN)); break; + case 3: ok = (lp.lam >= -d180-EPSLN && lp.lam <= -d40+EPSLN); break; + case 4: ok = (lp.lam >= -d40-EPSLN && lp.lam <= d180+EPSLN); break; + case 5: ok = (lp.lam >= -d180-EPSLN && lp.lam <= -d100+EPSLN); break; + case 6: ok = (lp.lam >= -d100-EPSLN && lp.lam <= -d20+EPSLN); break; + case 7: ok = (lp.lam >= -d20-EPSLN && lp.lam <= d80+EPSLN); break; + case 8: ok = (lp.lam >= d80-EPSLN && lp.lam <= d180+EPSLN); break; + case 9: ok = (lp.lam >= -d180-EPSLN && lp.lam <= -d100+EPSLN); break; + case 10: ok = (lp.lam >= -d100-EPSLN && lp.lam <= -d20+EPSLN); break; + case 11: ok = (lp.lam >= -d20-EPSLN && lp.lam <= d80+EPSLN); break; + case 12: ok = (lp.lam >= d80-EPSLN && lp.lam <= d180+EPSLN); break; } - // if (!z) pj_errno = -15; // invalid x or y - if (!z) lp.lam = HUGE_VAL; - if (!z) lp.phi = HUGE_VAL; - return (lp); + z = (!ok? 0: z); // projectable? + } + + if (!z) lp.lam = HUGE_VAL; + if (!z) lp.phi = HUGE_VAL; + + return lp; } -FREEUP; - if (P) { - int i; - for (i = 0; i < 12; ++i) - { - if (P->pj[i]) - (*(P->pj[i]->pfree))(P->pj[i]); - } - pj_dalloc(P); - } + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + int i; + for (i = 0; i < 12; ++i) { + if (P->opaque->pj[i]) + pj_dealloc(P->opaque->pj[i]); + } + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; } -ENTRY0(igh) + + +PJ *PROJECTION(igh) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + /* Zones: @@ -145,46 +173,90 @@ ENTRY0(igh) */ #define SETUP(n, proj, x_0, y_0, lon_0) \ - if (!(P->pj[n-1] = pj_##proj(0))) E_ERROR_0; \ - if (!(P->pj[n-1] = pj_##proj(P->pj[n-1]))) E_ERROR_0; \ - P->pj[n-1]->x0 = x_0; \ - P->pj[n-1]->y0 = y_0; \ - P->pj[n-1]->lam0 = lon_0; + if (!(Q->pj[n-1] = pj_##proj(0))) E_ERROR_0; \ + if (!(Q->pj[n-1] = pj_##proj(Q->pj[n-1]))) E_ERROR_0; \ + Q->pj[n-1]->x0 = x_0; \ + Q->pj[n-1]->y0 = y_0; \ + Q->pj[n-1]->lam0 = lon_0; - LP lp = { 0, d4044118 }; - XY xy1; - XY xy3; + LP lp = { 0, d4044118 }; + XY xy1; + XY xy3; - // sinusoidal zones - SETUP(3, sinu, -d100, 0, -d100); - SETUP(4, sinu, d30, 0, d30); - SETUP(5, sinu, -d160, 0, -d160); - SETUP(6, sinu, -d60, 0, -d60); - SETUP(7, sinu, d20, 0, d20); - SETUP(8, sinu, d140, 0, d140); + // sinusoidal zones + SETUP(3, sinu, -d100, 0, -d100); + SETUP(4, sinu, d30, 0, d30); + SETUP(5, sinu, -d160, 0, -d160); + SETUP(6, sinu, -d60, 0, -d60); + SETUP(7, sinu, d20, 0, d20); + SETUP(8, sinu, d140, 0, d140); - // mollweide zones - SETUP(1, moll, -d100, 0, -d100); + // mollweide zones + SETUP(1, moll, -d100, 0, -d100); - // y0 ? - xy1 = P->pj[0]->fwd(lp, P->pj[0]); // zone 1 - xy3 = P->pj[2]->fwd(lp, P->pj[2]); // zone 3 - // y0 + xy1.y = xy3.y for lt = 40d44'11.8" - P->dy0 = xy3.y - xy1.y; + // y0 ? + xy1 = Q->pj[0]->fwd(lp, Q->pj[0]); // zone 1 + xy3 = Q->pj[2]->fwd(lp, Q->pj[2]); // zone 3 + // y0 + xy1.y = xy3.y for lt = 40d44'11.8" + Q->dy0 = xy3.y - xy1.y; - P->pj[0]->y0 = P->dy0; + Q->pj[0]->y0 = Q->dy0; - // mollweide zones (cont'd) - SETUP( 2, moll, d30, P->dy0, d30); - SETUP( 9, moll, -d160, -P->dy0, -d160); - SETUP(10, moll, -d60, -P->dy0, -d60); - SETUP(11, moll, d20, -P->dy0, d20); - SETUP(12, moll, d140, -P->dy0, d140); + // mollweide zones (cont'd) + SETUP( 2, moll, d30, Q->dy0, d30); + SETUP( 9, moll, -d160, -Q->dy0, -d160); + SETUP(10, moll, -d60, -Q->dy0, -d60); + SETUP(11, moll, d20, -Q->dy0, d20); + SETUP(12, moll, d140, -Q->dy0, d140); - P->inv = s_inverse; - P->fwd = s_forward; - P->es = 0.; -ENDENTRY(P) + P->inv = s_inverse; + P->fwd = s_forward; + P->es = 0.; + + return P; +} +#ifdef PJ_OMIT_SELFTEST +int pj_igh_selftest (void) {return 0;} +#else + +int pj_igh_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=igh +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223878.49745627123, 111701.07212763709}, + { 223708.37131305804, -111701.07212763709}, + {-222857.74059699223, 111701.07212763709}, + {-223027.86674020503, -111701.07212763709}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.001790489447892545, 0.00089524655489191132}, + { 0.0017904906685957927, -0.00089524655489191132}, + {-0.001790496772112032, 0.00089524655489191132}, + {-0.0017904955514087843, -0.00089524655489191132}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + +#endif -- cgit v1.2.3 From 597e1669a442f1a8c953b90aad315d64cacaa8e5 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 19 Apr 2016 14:51:47 +0200 Subject: Converted imw_p --- src/PJ_aea.c | 1 - src/PJ_imw_p.c | 206 ++++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 147 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 648838c1..7d666dc0 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -361,7 +361,6 @@ int pj_etmerc_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} int pj_gs48_selftest (void) {return 10000;} int pj_gs50_selftest (void) {return 10000;} -int pj_imw_p_selftest (void) {return 10000;} int pj_isea_selftest (void) {return 10000;} int pj_krovak_selftest (void) {return 10000;} diff --git a/src/PJ_imw_p.c b/src/PJ_imw_p.c index 1f209172..10a06a44 100644 --- a/src/PJ_imw_p.c +++ b/src/PJ_imw_p.c @@ -1,32 +1,40 @@ -#define PROJ_PARMS__ \ - double P, Pp, Q, Qp, R_1, R_2, sphi_1, sphi_2, C2; \ - double phi_1, phi_2, lam_1; \ - double *en; \ - int mode; /* = 0, phi_1 and phi_2 != 0, = 1, phi_1 = 0, = -1 phi_2 = 0 */ #define PJ_LIB__ -#include +#include + PROJ_HEAD(imw_p, "International Map of the World Polyconic") "\n\tMod. Polyconic, Ell\n\tlat_1= and lat_2= [lon_1=]"; + #define TOL 1e-10 #define EPS 1e-10 - static int -phi12(PJ *P, double *del, double *sig) { + +struct pj_opaque { + double P, Pp, Q, Qp, R_1, R_2, sphi_1, sphi_2, C2; \ + double phi_1, phi_2, lam_1; \ + double *en; \ + int mode; /* = 0, phi_1 and phi_2 != 0, = 1, phi_1 = 0, = -1 phi_2 = 0 */ +}; + + +static int phi12(PJ *P, double *del, double *sig) { + struct pj_opaque *Q = P->opaque; int err = 0; if (!pj_param(P->ctx, P->params, "tlat_1").i || !pj_param(P->ctx, P->params, "tlat_2").i) { err = -41; } else { - P->phi_1 = pj_param(P->ctx, P->params, "rlat_1").f; - P->phi_2 = pj_param(P->ctx, P->params, "rlat_2").f; - *del = 0.5 * (P->phi_2 - P->phi_1); - *sig = 0.5 * (P->phi_2 + P->phi_1); + Q->phi_1 = pj_param(P->ctx, P->params, "rlat_1").f; + Q->phi_2 = pj_param(P->ctx, P->params, "rlat_2").f; + *del = 0.5 * (Q->phi_2 - Q->phi_1); + *sig = 0.5 * (Q->phi_2 + Q->phi_1); err = (fabs(*del) < EPS || fabs(*sig) < EPS) ? -42 : 0; } return err; } - static XY -loc_for(LP lp, PJ *P, double *yc) { + + +static XY loc_for(LP lp, PJ *P, double *yc) { + struct pj_opaque *Q = P->opaque; XY xy; if (! lp.phi) { @@ -36,28 +44,28 @@ loc_for(LP lp, PJ *P, double *yc) { double xa, ya, xb, yb, xc, D, B, m, sp, t, R, C; sp = sin(lp.phi); - m = pj_mlfn(lp.phi, sp, cos(lp.phi), P->en); - xa = P->Pp + P->Qp * m; - ya = P->P + P->Q * m; + m = pj_mlfn(lp.phi, sp, cos(lp.phi), Q->en); + xa = Q->Pp + Q->Qp * m; + ya = Q->P + Q->Q * m; R = 1. / (tan(lp.phi) * sqrt(1. - P->es * sp * sp)); C = sqrt(R * R - xa * xa); if (lp.phi < 0.) C = - C; C += ya - R; - if (P->mode < 0) { + if (Q->mode < 0) { xb = lp.lam; - yb = P->C2; + yb = Q->C2; } else { - t = lp.lam * P->sphi_2; - xb = P->R_2 * sin(t); - yb = P->C2 + P->R_2 * (1. - cos(t)); + t = lp.lam * Q->sphi_2; + xb = Q->R_2 * sin(t); + yb = Q->C2 + Q->R_2 * (1. - cos(t)); } - if (P->mode > 0) { + if (Q->mode > 0) { xc = lp.lam; *yc = 0.; } else { - t = lp.lam * P->sphi_1; - xc = P->R_1 * sin(t); - *yc = P->R_1 * (1. - cos(t)); + t = lp.lam * Q->sphi_1; + xc = Q->R_1 * sin(t); + *yc = Q->R_1 * (1. - cos(t)); } D = (xb - xc)/(yb - *yc); B = xc + D * (C + R - *yc); @@ -70,82 +78,162 @@ loc_for(LP lp, PJ *P, double *yc) { xy.y = - xy.y; xy.y += C + R; } - return (xy); + return xy; } -FORWARD(e_forward); /* ellipsoid */ + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; double yc; + xy = loc_for(lp, P, &yc); return (xy); } -INVERSE(e_inverse); /* ellipsoid */ + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; XY t; double yc; - lp.phi = P->phi_2; + lp.phi = Q->phi_2; lp.lam = xy.x / cos(lp.phi); do { t = loc_for(lp, P, &yc); - lp.phi = ((lp.phi - P->phi_1) * (xy.y - yc) / (t.y - yc)) + P->phi_1; + lp.phi = ((lp.phi - Q->phi_1) * (xy.y - yc) / (t.y - yc)) + Q->phi_1; lp.lam = lp.lam * xy.x / t.x; } while (fabs(t.x - xy.x) > TOL || fabs(t.y - xy.y) > TOL); - return (lp); + + return lp; } - static void -xy(PJ *P, double phi, double *x, double *y, double *sp, double *R) { + + +static void xy(PJ *P, double phi, double *x, double *y, double *sp, double *R) { double F; *sp = sin(phi); *R = 1./(tan(phi) * sqrt(1. - P->es * *sp * *sp )); - F = P->lam_1 * *sp; + F = P->opaque->lam_1 * *sp; *y = *R * (1 - cos(F)); *x = *R * sin(F); } -FREEUP; if (P) { if (P->en) pj_dalloc(P->en); pj_dalloc(P); } } -ENTRY1(imw_p, en) + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(imw_p) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + double del, sig, s, t, x1, x2, T2, y1, m1, m2, y2; int i; - if (!(P->en = pj_enfn(P->es))) E_ERROR_0; + if (!(Q->en = pj_enfn(P->es))) E_ERROR_0; if( (i = phi12(P, &del, &sig)) != 0) E_ERROR(i); - if (P->phi_2 < P->phi_1) { /* make sure P->phi_1 most southerly */ - del = P->phi_1; - P->phi_1 = P->phi_2; - P->phi_2 = del; + if (Q->phi_2 < Q->phi_1) { /* make sure P->phi_1 most southerly */ + del = Q->phi_1; + Q->phi_1 = Q->phi_2; + Q->phi_2 = del; } if (pj_param(P->ctx, P->params, "tlon_1").i) - P->lam_1 = pj_param(P->ctx, P->params, "rlon_1").f; + Q->lam_1 = pj_param(P->ctx, P->params, "rlon_1").f; else { /* use predefined based upon latitude */ sig = fabs(sig * RAD_TO_DEG); if (sig <= 60) sig = 2.; else if (sig <= 76) sig = 4.; else sig = 8.; - P->lam_1 = sig * DEG_TO_RAD; + Q->lam_1 = sig * DEG_TO_RAD; } - P->mode = 0; - if (P->phi_1) xy(P, P->phi_1, &x1, &y1, &P->sphi_1, &P->R_1); + Q->mode = 0; + if (Q->phi_1) xy(P, Q->phi_1, &x1, &y1, &Q->sphi_1, &Q->R_1); else { - P->mode = 1; + Q->mode = 1; y1 = 0.; - x1 = P->lam_1; + x1 = Q->lam_1; } - if (P->phi_2) xy(P, P->phi_2, &x2, &T2, &P->sphi_2, &P->R_2); + if (Q->phi_2) xy(P, Q->phi_2, &x2, &T2, &Q->sphi_2, &Q->R_2); else { - P->mode = -1; + Q->mode = -1; T2 = 0.; - x2 = P->lam_1; + x2 = Q->lam_1; } - m1 = pj_mlfn(P->phi_1, P->sphi_1, cos(P->phi_1), P->en); - m2 = pj_mlfn(P->phi_2, P->sphi_2, cos(P->phi_2), P->en); + m1 = pj_mlfn(Q->phi_1, Q->sphi_1, cos(Q->phi_1), Q->en); + m2 = pj_mlfn(Q->phi_2, Q->sphi_2, cos(Q->phi_2), Q->en); t = m2 - m1; s = x2 - x1; y2 = sqrt(t * t - s * s) + y1; - P->C2 = y2 - T2; + Q->C2 = y2 - T2; t = 1. / t; - P->P = (m2 * y1 - m1 * y2) * t; - P->Q = (y2 - y1) * t; - P->Pp = (m2 * x1 - m1 * x2) * t; - P->Qp = (x2 - x1) * t; + Q->P = (m2 * y1 - m1 * y2) * t; + Q->Q = (y2 - y1) * t; + Q->Pp = (m2 * x1 - m1 * x2) * t; + Q->Qp = (x2 - x1) * t; + P->fwd = e_forward; P->inv = e_inverse; -ENDENTRY(P) + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_imw_p_selftest (void) {return 0;} +#else + +int pj_imw_p_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=imw_p +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222588.4411393762, 55321.128653809537}, + { 222756.90637768712, -165827.58428832365}, + {-222588.4411393762, 55321.128653809537}, + {-222756.90637768712, -165827.58428832365}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.0017966991379592214, 0.50090492361427374}, + { 0.0017966979081574697, 0.49909507588689922}, + {-0.0017966991379592214, 0.50090492361427374}, + {-0.0017966979081574697, 0.49909507588689922}, + }; + + return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); +} + + +#endif -- cgit v1.2.3 From af38b27ae62208c8000547ca763b0ba536124b1a Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 19 Apr 2016 15:25:24 +0200 Subject: Converted isea --- src/PJ_aea.c | 1 - src/PJ_isea.c | 2295 +++++++++++++++++++++++++++++---------------------------- 2 files changed, 1176 insertions(+), 1120 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 7d666dc0..f57c1161 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -361,7 +361,6 @@ int pj_etmerc_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} int pj_gs48_selftest (void) {return 10000;} int pj_gs50_selftest (void) {return 10000;} -int pj_isea_selftest (void) {return 10000;} int pj_krovak_selftest (void) {return 10000;} int pj_labrd_selftest (void) {return 10000;} diff --git a/src/PJ_isea.c b/src/PJ_isea.c index 0ba17807..f1bc89a7 100644 --- a/src/PJ_isea.c +++ b/src/PJ_isea.c @@ -1,1119 +1,1176 @@ -/* - * This code was entirely written by Nathan Wagner - * and is in the public domain. - */ - -#include -#include -#include -#include - -#ifndef M_PI -# define M_PI 3.14159265358979323846 -#endif - -/* - * Proj 4 provides its own entry points into - * the code, so none of the library functions - * need to be global - */ -#define ISEA_STATIC static -#ifndef ISEA_STATIC -#define ISEA_STATIC -#endif - -struct hex { - int iso; - int x, y, z; -}; - -/* y *must* be positive down as the xy /iso conversion assumes this */ -ISEA_STATIC -int hex_xy(struct hex *h) { - if (!h->iso) return 1; - if (h->x >= 0) { - h->y = -h->y - (h->x+1)/2; - } else { - /* need to round toward -inf, not toward zero, so x-1 */ - h->y = -h->y - h->x/2; - } - h->iso = 0; - - return 1; -} - -ISEA_STATIC -int hex_iso(struct hex *h) { - if (h->iso) return 1; - - if (h->x >= 0) { - h->y = (-h->y - (h->x+1)/2); - } else { - /* need to round toward -inf, not toward zero, so x-1 */ - h->y = (-h->y - (h->x)/2); - } - - h->z = -h->x - h->y; - h->iso = 1; - return 1; -} - -ISEA_STATIC -int hexbin2(double width, double x, double y, - int *i, int *j) { - double z, rx, ry, rz; - double abs_dx, abs_dy, abs_dz; - int ix, iy, iz, s; - struct hex h; - - x = x / cos(30 * M_PI / 180.0); /* rotated X coord */ - y = y - x / 2.0; /* adjustment for rotated X */ - - /* adjust for actual hexwidth */ - x /= width; - y /= width; - - z = -x - y; - - ix = rx = floor(x + 0.5); - iy = ry = floor(y + 0.5); - iz = rz = floor(z + 0.5); - - s = ix + iy + iz; - - if (s) { - abs_dx = fabs(rx - x); - abs_dy = fabs(ry - y); - abs_dz = fabs(rz - z); - - if (abs_dx >= abs_dy && abs_dx >= abs_dz) { - ix -= s; - } else if (abs_dy >= abs_dx && abs_dy >= abs_dz) { - iy -= s; - } else { - iz -= s; - } - } - h.x = ix; - h.y = iy; - h.z = iz; - h.iso = 1; - - hex_xy(&h); - *i = h.x; - *j = h.y; - return ix * 100 + iy; -} -#ifndef ISEA_STATIC -#define ISEA_STATIC -#endif - -enum isea_poly { ISEA_NONE, ISEA_ICOSAHEDRON = 20 }; -enum isea_topology { ISEA_HEXAGON=6, ISEA_TRIANGLE=3, ISEA_DIAMOND=4 }; -enum isea_address_form { ISEA_GEO, ISEA_Q2DI, ISEA_SEQNUM, ISEA_INTERLEAVE, - ISEA_PLANE, ISEA_Q2DD, ISEA_PROJTRI, ISEA_VERTEX2DD, ISEA_HEX -}; - -struct isea_dgg { - int polyhedron; /* ignored, icosahedron */ - double o_lat, o_lon, o_az; /* orientation, radians */ - int pole; /* true if standard snyder */ - int topology; /* ignored, hexagon */ - int aperture; /* valid values depend on partitioning method */ - int resolution; - double radius; /* radius of the earth in meters, ignored 1.0 */ - int output; /* an isea_address_form */ - int triangle; /* triangle of last transformed point */ - int quad; /* quad of last transformed point */ - unsigned long serial; -}; - -struct isea_pt { - double x, y; -}; - -struct isea_geo { - double lon, lat; -}; - -struct isea_address { - int type; /* enum isea_address_form */ - int number; - double x,y; /* or i,j or lon,lat depending on type */ -}; - -/* ENDINC */ - -enum snyder_polyhedron { - SNYDER_POLY_HEXAGON, SNYDER_POLY_PENTAGON, - SNYDER_POLY_TETRAHEDRON, SNYDER_POLY_CUBE, - SNYDER_POLY_OCTAHEDRON, SNYDER_POLY_DODECAHEDRON, - SNYDER_POLY_ICOSAHEDRON -}; - -struct snyder_constants { - double g, G, theta, ea_w, ea_a, ea_b, g_w, g_a, g_b; -}; - -/* TODO put these in radians to avoid a later conversion */ -ISEA_STATIC -struct snyder_constants constants[] = { - {23.80018260, 62.15458023, 60.0, 3.75, 1.033, 0.968, 5.09, 1.195, 1.0}, - {20.07675127, 55.69063953, 54.0, 2.65, 1.030, 0.983, 3.59, 1.141, 1.027}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {37.37736814, 36.0, 30.0, 17.27, 1.163, 0.860, 13.14, 1.584, 1.0}, -}; - -#define E 52.62263186 -#define F 10.81231696 - -#define DEG60 1.04719755119659774614 -#define DEG120 2.09439510239319549229 -#define DEG72 1.25663706143591729537 -#define DEG90 1.57079632679489661922 -#define DEG144 2.51327412287183459075 -#define DEG36 0.62831853071795864768 -#define DEG108 1.88495559215387594306 -#define DEG180 M_PI -/* sqrt(5)/M_PI */ -#define ISEA_SCALE 0.8301572857837594396028083 - -/* 26.565051177 degrees */ -#define V_LAT 0.46364760899944494524 - -#define RAD2DEG (180.0/M_PI) -#define DEG2RAD (M_PI/180.0) - -ISEA_STATIC -struct isea_geo vertex[] = { - {0.0, DEG90}, - {DEG180, V_LAT}, - {-DEG108, V_LAT}, - {-DEG36, V_LAT}, - {DEG36, V_LAT}, - {DEG108, V_LAT}, - {-DEG144, -V_LAT}, - {-DEG72, -V_LAT}, - {0.0, -V_LAT}, - {DEG72, -V_LAT}, - {DEG144, -V_LAT}, - {0.0, -DEG90} -}; - -/* TODO make an isea_pt array of the vertices as well */ - -static int tri_v1[] = {0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 2, 3, 4, 5, 1, 11, 11, 11, 11, 11}; - -/* 52.62263186 */ -#define E_RAD 0.91843818702186776133 - -/* 10.81231696 */ -#define F_RAD 0.18871053072122403508 - -/* triangle Centers */ -struct isea_geo icostriangles[] = { - {0.0, 0.0}, - {-DEG144, E_RAD}, - {-DEG72, E_RAD}, - {0.0, E_RAD}, - {DEG72, E_RAD}, - {DEG144, E_RAD}, - {-DEG144, F_RAD}, - {-DEG72, F_RAD}, - {0.0, F_RAD}, - {DEG72, F_RAD}, - {DEG144, F_RAD}, - {-DEG108, -F_RAD}, - {-DEG36, -F_RAD}, - {DEG36, -F_RAD}, - {DEG108, -F_RAD}, - {DEG180, -F_RAD}, - {-DEG108, -E_RAD}, - {-DEG36, -E_RAD}, - {DEG36, -E_RAD}, - {DEG108, -E_RAD}, - {DEG180, -E_RAD}, -}; - -static double -az_adjustment(int triangle) -{ - double adj; - - struct isea_geo v; - struct isea_geo c; - - v = vertex[tri_v1[triangle]]; - c = icostriangles[triangle]; - - /* TODO looks like the adjustment is always either 0 or 180 */ - /* at least if you pick your vertex carefully */ - adj = atan2(cos(v.lat) * sin(v.lon - c.lon), - cos(c.lat) * sin(v.lat) - - sin(c.lat) * cos(v.lat) * cos(v.lon - c.lon)); - return adj; -} - -/* R tan(g) sin(60) */ -#define TABLE_G 0.6615845383 - -/* H = 0.25 R tan g = */ -#define TABLE_H 0.1909830056 - -#define RPRIME 0.91038328153090290025 - -ISEA_STATIC -struct isea_pt -isea_triangle_xy(int triangle) -{ - struct isea_pt c; - double Rprime = 0.91038328153090290025; - - triangle = (triangle - 1) % 20; - - c.x = TABLE_G * ((triangle % 5) - 2) * 2.0; - if (triangle > 9) { - c.x += TABLE_G; - } - switch (triangle / 5) { - case 0: - c.y = 5.0 * TABLE_H; - break; - case 1: - c.y = TABLE_H; - break; - case 2: - c.y = -TABLE_H; - break; - case 3: - c.y = -5.0 * TABLE_H; - break; - default: - /* should be impossible */ - exit(EXIT_FAILURE); - }; - c.x *= Rprime; - c.y *= Rprime; - - return c; -} - -/* snyder eq 14 */ -static double -sph_azimuth(double f_lon, double f_lat, double t_lon, double t_lat) -{ - double az; - - az = atan2(cos(t_lat) * sin(t_lon - f_lon), - cos(f_lat) * sin(t_lat) - - sin(f_lat) * cos(t_lat) * cos(t_lon - f_lon) - ); - return az; -} - -/* coord needs to be in radians */ -ISEA_STATIC -int -isea_snyder_forward(struct isea_geo * ll, struct isea_pt * out) -{ - int i; - - /* - * spherical distance from center of polygon face to any of its - * vertexes on the globe - */ - double g; - - /* - * spherical angle between radius vector to center and adjacent edge - * of spherical polygon on the globe - */ - double G; - - /* - * plane angle between radius vector to center and adjacent edge of - * plane polygon - */ - double theta; - - /* additional variables from snyder */ - double q, Rprime, H, Ag, Azprime, Az, dprime, f, rho, - x, y; - - /* variables used to store intermediate results */ - double cot_theta, tan_g, az_offset; - - /* how many multiples of 60 degrees we adjust the azimuth */ - int Az_adjust_multiples; - - struct snyder_constants c; - - /* - * TODO by locality of reference, start by trying the same triangle - * as last time - */ - - /* TODO put these constants in as radians to begin with */ - c = constants[SNYDER_POLY_ICOSAHEDRON]; - theta = c.theta * DEG2RAD; - g = c.g * DEG2RAD; - G = c.G * DEG2RAD; - - for (i = 1; i <= 20; i++) { - double z; - struct isea_geo center; - - center = icostriangles[i]; - - /* step 1 */ - z = acos(sin(center.lat) * sin(ll->lat) - + cos(center.lat) * cos(ll->lat) * cos(ll->lon - center.lon)); - /* not on this triangle */ - if (z > g + 0.000005) { /* TODO DBL_EPSILON */ - continue; - } - - Az = sph_azimuth(center.lon, center.lat, ll->lon, ll->lat); - - /* step 2 */ - - /* This calculates "some" vertex coordinate */ - az_offset = az_adjustment(i); - - Az -= az_offset; - - /* TODO I don't know why we do this. It's not in snyder */ - /* maybe because we should have picked a better vertex */ - if (Az < 0.0) { - Az += 2.0 * M_PI; - } - /* - * adjust Az for the point to fall within the range of 0 to - * 2(90 - theta) or 60 degrees for the hexagon, by - * and therefore 120 degrees for the triangle - * of the icosahedron - * subtracting or adding multiples of 60 degrees to Az and - * recording the amount of adjustment - */ - - Az_adjust_multiples = 0; - while (Az < 0.0) { - Az += DEG120; - Az_adjust_multiples--; - } - while (Az > DEG120 + DBL_EPSILON) { - Az -= DEG120; - Az_adjust_multiples++; - } - - /* step 3 */ - cot_theta = 1.0 / tan(theta); - tan_g = tan(g); /* TODO this is a constant */ - - /* Calculate q from eq 9. */ - /* TODO cot_theta is cot(30) */ - q = atan2(tan_g, cos(Az) + sin(Az) * cot_theta); - - /* not in this triangle */ - if (z > q + 0.000005) { - continue; - } - /* step 4 */ - - /* Apply equations 5-8 and 10-12 in order */ - - /* eq 5 */ - /* Rprime = 0.9449322893 * R; */ - /* R' in the paper is for the truncated */ - Rprime = 0.91038328153090290025; - - /* eq 6 */ - H = acos(sin(Az) * sin(G) * cos(g) - cos(Az) * cos(G)); - - /* eq 7 */ - /* Ag = (Az + G + H - DEG180) * M_PI * R * R / DEG180; */ - Ag = Az + G + H - DEG180; - - /* eq 8 */ - Azprime = atan2(2.0 * Ag, Rprime * Rprime * tan_g * tan_g - 2.0 * Ag * cot_theta); - - /* eq 10 */ - /* cot(theta) = 1.73205080756887729355 */ - dprime = Rprime * tan_g / (cos(Azprime) + sin(Azprime) * cot_theta); - - /* eq 11 */ - f = dprime / (2.0 * Rprime * sin(q / 2.0)); - - /* eq 12 */ - rho = 2.0 * Rprime * f * sin(z / 2.0); - - /* - * add back the same 60 degree multiple adjustment from step - * 2 to Azprime - */ - - Azprime += DEG120 * Az_adjust_multiples; - - /* calculate rectangular coordinates */ - - x = rho * sin(Azprime); - y = rho * cos(Azprime); - - /* - * TODO - * translate coordinates to the origin for the particular - * hexagon on the flattened polyhedral map plot - */ - - out->x = x; - out->y = y; - - return i; - } - - /* - * should be impossible, this implies that the coordinate is not on - * any triangle - */ - - fprintf(stderr, "impossible transform: %f %f is not on any triangle\n", - ll->lon * RAD2DEG, ll->lat * RAD2DEG); - - exit(EXIT_FAILURE); - - /* not reached */ - return 0; /* supresses a warning */ -} - -/* - * return the new coordinates of any point in orginal coordinate system. - * Define a point (newNPold) in orginal coordinate system as the North Pole in - * new coordinate system, and the great circle connect the original and new - * North Pole as the lon0 longitude in new coordinate system, given any point - * in orginal coordinate system, this function return the new coordinates. - */ - -#define PRECISION 0.0000000000005 - -/* formula from Snyder, Map Projections: A working manual, p31 */ -/* - * old north pole at np in new coordinates - * could be simplified a bit with fewer intermediates - * - * TODO take a result pointer - */ -ISEA_STATIC -struct isea_geo -snyder_ctran(struct isea_geo * np, struct isea_geo * pt) -{ - struct isea_geo npt; - double alpha, phi, lambda, lambda0, beta, lambdap, phip; - double sin_phip; - double lp_b; /* lambda prime minus beta */ - double cos_p, sin_a; - - phi = pt->lat; - lambda = pt->lon; - alpha = np->lat; - beta = np->lon; - lambda0 = beta; - - cos_p = cos(phi); - sin_a = sin(alpha); - - /* mpawm 5-7 */ - sin_phip = sin_a * sin(phi) - cos(alpha) * cos_p * cos(lambda - lambda0); - - /* mpawm 5-8b */ - - /* use the two argument form so we end up in the right quadrant */ - lp_b = atan2(cos_p * sin(lambda - lambda0), - (sin_a * cos_p * cos(lambda - lambda0) + cos(alpha) * sin(phi))); - - lambdap = lp_b + beta; - - /* normalize longitude */ - /* TODO can we just do a modulus ? */ - lambdap = fmod(lambdap, 2 * M_PI); - while (lambdap > M_PI) - lambdap -= 2 * M_PI; - while (lambdap < -M_PI) - lambdap += 2 * M_PI; - - phip = asin(sin_phip); - - npt.lat = phip; - npt.lon = lambdap; - - return npt; -} - -ISEA_STATIC -struct isea_geo -isea_ctran(struct isea_geo * np, struct isea_geo * pt, double lon0) -{ - struct isea_geo npt; - - np->lon += M_PI; - npt = snyder_ctran(np, pt); - np->lon -= M_PI; - - npt.lon -= (M_PI - lon0 + np->lon); - - /* - * snyder is down tri 3, isea is along side of tri1 from vertex 0 to - * vertex 1 these are 180 degrees apart - */ - npt.lon += M_PI; - /* normalize longitude */ - npt.lon = fmod(npt.lon, 2 * M_PI); - while (npt.lon > M_PI) - npt.lon -= 2 * M_PI; - while (npt.lon < -M_PI) - npt.lon += 2 * M_PI; - - return npt; -} - -/* in radians */ -#define ISEA_STD_LAT 1.01722196792335072101 -#define ISEA_STD_LON .19634954084936207740 - -/* fuller's at 5.2454 west, 2.3009 N, adjacent at 7.46658 deg */ - -ISEA_STATIC -int -isea_grid_init(struct isea_dgg * g) -{ - if (!g) - return 0; - - g->polyhedron = 20; - g->o_lat = ISEA_STD_LAT; - g->o_lon = ISEA_STD_LON; - g->o_az = 0.0; - g->aperture = 4; - g->resolution = 6; - g->radius = 1.0; - g->topology = 6; - - return 1; -} - -ISEA_STATIC -int -isea_orient_isea(struct isea_dgg * g) -{ - if (!g) - return 0; - g->o_lat = ISEA_STD_LAT; - g->o_lon = ISEA_STD_LON; - g->o_az = 0.0; - return 1; -} - -ISEA_STATIC -int -isea_orient_pole(struct isea_dgg * g) -{ - if (!g) - return 0; - g->o_lat = M_PI / 2.0; - g->o_lon = 0.0; - g->o_az = 0; - return 1; -} - -ISEA_STATIC -int -isea_transform(struct isea_dgg * g, struct isea_geo * in, - struct isea_pt * out) -{ - struct isea_geo i, pole; - int tri; - - pole.lat = g->o_lat; - pole.lon = g->o_lon; - - i = isea_ctran(&pole, in, g->o_az); - - tri = isea_snyder_forward(&i, out); - out->x *= g->radius; - out->y *= g->radius; - g->triangle = tri; - - return tri; -} - -#define DOWNTRI(tri) (((tri - 1) / 5) % 2 == 1) - -ISEA_STATIC -void -isea_rotate(struct isea_pt * pt, double degrees) -{ - double rad; - - double x, y; - - rad = -degrees * M_PI / 180.0; - while (rad >= 2.0 * M_PI) rad -= 2.0 * M_PI; - while (rad <= -2.0 * M_PI) rad += 2.0 * M_PI; - - x = pt->x * cos(rad) + pt->y * sin(rad); - y = -pt->x * sin(rad) + pt->y * cos(rad); - - pt->x = x; - pt->y = y; -} - -ISEA_STATIC -int isea_tri_plane(int tri, struct isea_pt *pt, double radius) { - struct isea_pt tc; /* center of triangle */ - - if (DOWNTRI(tri)) { - isea_rotate(pt, 180.0); - } - tc = isea_triangle_xy(tri); - tc.x *= radius; - tc.y *= radius; - pt->x += tc.x; - pt->y += tc.y; - - return tri; -} - -/* convert projected triangle coords to quad xy coords, return quad number */ -ISEA_STATIC -int -isea_ptdd(int tri, struct isea_pt *pt) { - int downtri, quad; - - downtri = (((tri - 1) / 5) % 2 == 1); - quad = ((tri - 1) % 5) + ((tri - 1) / 10) * 5 + 1; - - isea_rotate(pt, downtri ? 240.0 : 60.0); - if (downtri) { - pt->x += 0.5; - /* pt->y += cos(30.0 * M_PI / 180.0); */ - pt->y += .86602540378443864672; - } - return quad; -} - -ISEA_STATIC -int -isea_dddi_ap3odd(struct isea_dgg *g, int quad, struct isea_pt *pt, struct isea_pt *di) -{ - struct isea_pt v; - double hexwidth; - double sidelength; /* in hexes */ - int d, i; - int maxcoord; - struct hex h; - - /* This is the number of hexes from apex to base of a triangle */ - sidelength = (pow(2.0, g->resolution) + 1.0) / 2.0; - - /* apex to base is cos(30deg) */ - hexwidth = cos(M_PI / 6.0) / sidelength; - - /* TODO I think sidelength is always x.5, so - * (int)sidelength * 2 + 1 might be just as good - */ - maxcoord = (int) (sidelength * 2.0 + 0.5); - - v = *pt; - hexbin2(hexwidth, v.x, v.y, &h.x, &h.y); - h.iso = 0; - hex_iso(&h); - - d = h.x - h.z; - i = h.x + h.y + h.y; - - /* - * you want to test for max coords for the next quad in the same - * "row" first to get the case where both are max - */ - if (quad <= 5) { - if (d == 0 && i == maxcoord) { - /* north pole */ - quad = 0; - d = 0; - i = 0; - } else if (i == maxcoord) { - /* upper right in next quad */ - quad += 1; - if (quad == 6) - quad = 1; - i = maxcoord - d; - d = 0; - } else if (d == maxcoord) { - /* lower right in quad to lower right */ - quad += 5; - d = 0; - } - } else if (quad >= 6) { - if (i == 0 && d == maxcoord) { - /* south pole */ - quad = 11; - d = 0; - i = 0; - } else if (d == maxcoord) { - /* lower right in next quad */ - quad += 1; - if (quad == 11) - quad = 6; - d = maxcoord - i; - i = 0; - } else if (i == maxcoord) { - /* upper right in quad to upper right */ - quad = (quad - 4) % 5; - i = 0; - } - } - - di->x = d; - di->y = i; - - g->quad = quad; - return quad; -} - -ISEA_STATIC -int -isea_dddi(struct isea_dgg *g, int quad, struct isea_pt *pt, struct isea_pt *di) { - struct isea_pt v; - double hexwidth; - int sidelength; /* in hexes */ - struct hex h; - - if (g->aperture == 3 && g->resolution % 2 != 0) { - return isea_dddi_ap3odd(g, quad, pt, di); - } - /* todo might want to do this as an iterated loop */ - if (g->aperture >0) { - sidelength = (int) (pow(g->aperture, g->resolution / 2.0) + 0.5); - } else { - sidelength = g->resolution; - } - - hexwidth = 1.0 / sidelength; - - v = *pt; - isea_rotate(&v, -30.0); - hexbin2(hexwidth, v.x, v.y, &h.x, &h.y); - h.iso = 0; - hex_iso(&h); - - /* we may actually be on another quad */ - if (quad <= 5) { - if (h.x == 0 && h.z == -sidelength) { - /* north pole */ - quad = 0; - h.z = 0; - h.y = 0; - h.x = 0; - } else if (h.z == -sidelength) { - quad = quad + 1; - if (quad == 6) - quad = 1; - h.y = sidelength - h.x; - h.z = h.x - sidelength; - h.x = 0; - } else if (h.x == sidelength) { - quad += 5; - h.y = -h.z; - h.x = 0; - } - } else if (quad >= 6) { - if (h.z == 0 && h.x == sidelength) { - /* south pole */ - quad = 11; - h.x = 0; - h.y = 0; - h.z = 0; - } else if (h.x == sidelength) { - quad = quad + 1; - if (quad == 11) - quad = 6; - h.x = h.y + sidelength; - h.y = 0; - h.z = -h.x; - } else if (h.y == -sidelength) { - quad -= 4; - h.y = 0; - h.z = -h.x; - } - } - di->x = h.x; - di->y = -h.z; - - g->quad = quad; - return quad; -} - -ISEA_STATIC -int isea_ptdi(struct isea_dgg *g, int tri, struct isea_pt *pt, - struct isea_pt *di) { - struct isea_pt v; - int quad; - - v = *pt; - quad = isea_ptdd(tri, &v); - quad = isea_dddi(g, quad, &v, di); - return quad; -} - -/* q2di to seqnum */ -ISEA_STATIC -int isea_disn(struct isea_dgg *g, int quad, struct isea_pt *di) { - int sidelength; - int sn, height; - int hexes; - - if (quad == 0) { - g->serial = 1; - return g->serial; - } - /* hexes in a quad */ - hexes = (int) (pow(g->aperture, g->resolution) + 0.5); - if (quad == 11) { - g->serial = 1 + 10 * hexes + 1; - return g->serial; - } - if (g->aperture == 3 && g->resolution % 2 == 1) { - height = (int) (pow(g->aperture, (g->resolution - 1) / 2.0)); - sn = ((int) di->x) * height; - sn += ((int) di->y) / height; - sn += (quad - 1) * hexes; - sn += 2; - } else { - sidelength = (int) (pow(g->aperture, g->resolution / 2.0) + 0.5); - sn = (quad - 1) * hexes + sidelength * di->x + di->y + 2; - } - - g->serial = sn; - return sn; -} - -/* TODO just encode the quad in the d or i coordinate - * quad is 0-11, which can be four bits. - * d' = d << 4 + q, d = d' >> 4, q = d' & 0xf - */ -/* convert a q2di to global hex coord */ -ISEA_STATIC -int isea_hex(struct isea_dgg *g, int tri, - struct isea_pt *pt, struct isea_pt *hex) { - struct isea_pt v; - int sidelength; - int d, i, x, y, quad; - - quad = isea_ptdi(g, tri, pt, &v); - - hex->x = ((int)v.x << 4) + quad; - hex->y = v.y; - - return 1; - - d = v.x; - i = v.y; - - /* Aperture 3 odd resolutions */ - if (g->aperture == 3 && g->resolution % 2 != 0) { - int offset = (int)(pow(3.0, g->resolution - 1) + 0.5); - - d += offset * ((g->quad-1) % 5); - i += offset * ((g->quad-1) % 5); - - if (quad == 0) { - d = 0; - i = offset; - } else if (quad == 11) { - d = 2 * offset; - i = 0; - } else if (quad > 5) { - d += offset; - } - - x = (2*d - i) /3; - y = (2*i - d) /3; - - hex->x = x + offset / 3; - hex->y = y + 2 * offset / 3; - return 1; - } - - /* aperture 3 even resolutions and aperture 4 */ - sidelength = (int) (pow(g->aperture, g->resolution / 2.0) + 0.5); - if (g->quad == 0) { - hex->x = 0; - hex->y = sidelength; - } else if (g->quad == 11) { - hex->x = sidelength * 2; - hex->y = 0; - } else { - hex->x = d + sidelength * ((g->quad-1) % 5); - if (g->quad > 5) hex->x += sidelength; - hex->y = i + sidelength * ((g->quad-1) % 5); - } - - return 1; -} - -ISEA_STATIC -struct isea_pt -isea_forward(struct isea_dgg *g, struct isea_geo *in) -{ - int tri; - struct isea_pt out, coord; - - tri = isea_transform(g, in, &out); - - if (g->output == ISEA_PLANE) { - isea_tri_plane(tri, &out, g->radius); - return out; - } - - /* convert to isea standard triangle size */ - out.x = out.x / g->radius * ISEA_SCALE; - out.y = out.y / g->radius * ISEA_SCALE; - out.x += 0.5; - out.y += 2.0 * .14433756729740644112; - - switch (g->output) { - case ISEA_PROJTRI: - /* nothing to do, already in projected triangle */ - break; - case ISEA_VERTEX2DD: - g->quad = isea_ptdd(tri, &out); - break; - case ISEA_Q2DD: - /* Same as above, we just don't print as much */ - g->quad = isea_ptdd(tri, &out); - break; - case ISEA_Q2DI: - g->quad = isea_ptdi(g, tri, &out, &coord); - return coord; - break; - case ISEA_SEQNUM: - isea_ptdi(g, tri, &out, &coord); - /* disn will set g->serial */ - isea_disn(g, g->quad, &coord); - return coord; - break; - case ISEA_HEX: - isea_hex(g, tri, &out, &coord); - return coord; - break; - } - - return out; -} -/* - * Proj 4 integration code follows - */ - -#define PROJ_PARMS__ \ - struct isea_dgg dgg; - -#define PJ_LIB__ -#include - -PROJ_HEAD(isea, "Icosahedral Snyder Equal Area") "\n\tSph"; - -FORWARD(s_forward); - struct isea_pt out; - struct isea_geo in; - - in.lon = lp.lam; - in.lat = lp.phi; - - out = isea_forward(&P->dgg, &in); - - xy.x = out.x; - xy.y = out.y; - - return xy; -} -FREEUP; if (P) pj_dalloc(P); } - -ENTRY0(isea) - char *opt; - - P->fwd = s_forward; - isea_grid_init(&P->dgg); - - P->dgg.output = ISEA_PLANE; -/* P->dgg.radius = P->a; / * otherwise defaults to 1 */ - /* calling library will scale, I think */ - - opt = pj_param(P->ctx,P->params, "sorient").s; - if (opt) { - if (!strcmp(opt, "isea")) { - isea_orient_isea(&P->dgg); - } else if (!strcmp(opt, "pole")) { - isea_orient_pole(&P->dgg); - } else { - E_ERROR(-34); - } - } - - if (pj_param(P->ctx,P->params, "tazi").i) { - P->dgg.o_az = pj_param(P->ctx,P->params, "razi").f; - } - - if (pj_param(P->ctx,P->params, "tlon_0").i) { - P->dgg.o_lon = pj_param(P->ctx,P->params, "rlon_0").f; - } - - if (pj_param(P->ctx,P->params, "tlat_0").i) { - P->dgg.o_lat = pj_param(P->ctx,P->params, "rlat_0").f; - } - - if (pj_param(P->ctx,P->params, "taperture").i) { - P->dgg.aperture = pj_param(P->ctx,P->params, "iaperture").i; - } - - if (pj_param(P->ctx,P->params, "tresolution").i) { - P->dgg.resolution = pj_param(P->ctx,P->params, "iresolution").i; - } - - opt = pj_param(P->ctx,P->params, "smode").s; - if (opt) { - if (!strcmp(opt, "plane")) { - P->dgg.output = ISEA_PLANE; - } else if (!strcmp(opt, "di")) { - P->dgg.output = ISEA_Q2DI; - } - else if (!strcmp(opt, "dd")) { - P->dgg.output = ISEA_Q2DD; - } - else if (!strcmp(opt, "hex")) { - P->dgg.output = ISEA_HEX; - } - else { - /* TODO verify error code. Possibly eliminate magic */ - E_ERROR(-34); - } - } - - if (pj_param(P->ctx,P->params, "trescale").i) { - P->dgg.radius = ISEA_SCALE; - } - - if (pj_param(P->ctx,P->params, "tresolution").i) { - P->dgg.resolution = pj_param(P->ctx,P->params, "iresolution").i; - } else { - P->dgg.resolution = 4; - } - - if (pj_param(P->ctx,P->params, "taperture").i) { - P->dgg.aperture = pj_param(P->ctx,P->params, "iaperture").i; - } else { - P->dgg.aperture = 3; - } - -ENDENTRY(P) +/* + * This code was entirely written by Nathan Wagner + * and is in the public domain. + */ + +#include +#include +#include +#include + +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +/* + * Proj 4 provides its own entry points into + * the code, so none of the library functions + * need to be global + */ +#define ISEA_STATIC static +#ifndef ISEA_STATIC +#define ISEA_STATIC +#endif + +struct hex { + int iso; + int x, y, z; +}; + +/* y *must* be positive down as the xy /iso conversion assumes this */ +ISEA_STATIC +int hex_xy(struct hex *h) { + if (!h->iso) return 1; + if (h->x >= 0) { + h->y = -h->y - (h->x+1)/2; + } else { + /* need to round toward -inf, not toward zero, so x-1 */ + h->y = -h->y - h->x/2; + } + h->iso = 0; + + return 1; +} + +ISEA_STATIC +int hex_iso(struct hex *h) { + if (h->iso) return 1; + + if (h->x >= 0) { + h->y = (-h->y - (h->x+1)/2); + } else { + /* need to round toward -inf, not toward zero, so x-1 */ + h->y = (-h->y - (h->x)/2); + } + + h->z = -h->x - h->y; + h->iso = 1; + return 1; +} + +ISEA_STATIC +int hexbin2(double width, double x, double y, + int *i, int *j) { + double z, rx, ry, rz; + double abs_dx, abs_dy, abs_dz; + int ix, iy, iz, s; + struct hex h; + + x = x / cos(30 * M_PI / 180.0); /* rotated X coord */ + y = y - x / 2.0; /* adjustment for rotated X */ + + /* adjust for actual hexwidth */ + x /= width; + y /= width; + + z = -x - y; + + ix = rx = floor(x + 0.5); + iy = ry = floor(y + 0.5); + iz = rz = floor(z + 0.5); + + s = ix + iy + iz; + + if (s) { + abs_dx = fabs(rx - x); + abs_dy = fabs(ry - y); + abs_dz = fabs(rz - z); + + if (abs_dx >= abs_dy && abs_dx >= abs_dz) { + ix -= s; + } else if (abs_dy >= abs_dx && abs_dy >= abs_dz) { + iy -= s; + } else { + iz -= s; + } + } + h.x = ix; + h.y = iy; + h.z = iz; + h.iso = 1; + + hex_xy(&h); + *i = h.x; + *j = h.y; + return ix * 100 + iy; +} +#ifndef ISEA_STATIC +#define ISEA_STATIC +#endif + +enum isea_poly { ISEA_NONE, ISEA_ICOSAHEDRON = 20 }; +enum isea_topology { ISEA_HEXAGON=6, ISEA_TRIANGLE=3, ISEA_DIAMOND=4 }; +enum isea_address_form { ISEA_GEO, ISEA_Q2DI, ISEA_SEQNUM, ISEA_INTERLEAVE, + ISEA_PLANE, ISEA_Q2DD, ISEA_PROJTRI, ISEA_VERTEX2DD, ISEA_HEX +}; + +struct isea_dgg { + int polyhedron; /* ignored, icosahedron */ + double o_lat, o_lon, o_az; /* orientation, radians */ + int pole; /* true if standard snyder */ + int topology; /* ignored, hexagon */ + int aperture; /* valid values depend on partitioning method */ + int resolution; + double radius; /* radius of the earth in meters, ignored 1.0 */ + int output; /* an isea_address_form */ + int triangle; /* triangle of last transformed point */ + int quad; /* quad of last transformed point */ + unsigned long serial; +}; + +struct isea_pt { + double x, y; +}; + +struct isea_geo { + double lon, lat; +}; + +struct isea_address { + int type; /* enum isea_address_form */ + int number; + double x,y; /* or i,j or lon,lat depending on type */ +}; + +/* ENDINC */ + +enum snyder_polyhedron { + SNYDER_POLY_HEXAGON, SNYDER_POLY_PENTAGON, + SNYDER_POLY_TETRAHEDRON, SNYDER_POLY_CUBE, + SNYDER_POLY_OCTAHEDRON, SNYDER_POLY_DODECAHEDRON, + SNYDER_POLY_ICOSAHEDRON +}; + +struct snyder_constants { + double g, G, theta, ea_w, ea_a, ea_b, g_w, g_a, g_b; +}; + +/* TODO put these in radians to avoid a later conversion */ +ISEA_STATIC +struct snyder_constants constants[] = { + {23.80018260, 62.15458023, 60.0, 3.75, 1.033, 0.968, 5.09, 1.195, 1.0}, + {20.07675127, 55.69063953, 54.0, 2.65, 1.030, 0.983, 3.59, 1.141, 1.027}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, + {37.37736814, 36.0, 30.0, 17.27, 1.163, 0.860, 13.14, 1.584, 1.0}, +}; + +#define E 52.62263186 +#define F 10.81231696 + +#define DEG60 1.04719755119659774614 +#define DEG120 2.09439510239319549229 +#define DEG72 1.25663706143591729537 +#define DEG90 1.57079632679489661922 +#define DEG144 2.51327412287183459075 +#define DEG36 0.62831853071795864768 +#define DEG108 1.88495559215387594306 +#define DEG180 M_PI +/* sqrt(5)/M_PI */ +#define ISEA_SCALE 0.8301572857837594396028083 + +/* 26.565051177 degrees */ +#define V_LAT 0.46364760899944494524 + +#define RAD2DEG (180.0/M_PI) +#define DEG2RAD (M_PI/180.0) + +ISEA_STATIC +struct isea_geo vertex[] = { + {0.0, DEG90}, + {DEG180, V_LAT}, + {-DEG108, V_LAT}, + {-DEG36, V_LAT}, + {DEG36, V_LAT}, + {DEG108, V_LAT}, + {-DEG144, -V_LAT}, + {-DEG72, -V_LAT}, + {0.0, -V_LAT}, + {DEG72, -V_LAT}, + {DEG144, -V_LAT}, + {0.0, -DEG90} +}; + +/* TODO make an isea_pt array of the vertices as well */ + +static int tri_v1[] = {0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 2, 3, 4, 5, 1, 11, 11, 11, 11, 11}; + +/* 52.62263186 */ +#define E_RAD 0.91843818702186776133 + +/* 10.81231696 */ +#define F_RAD 0.18871053072122403508 + +/* triangle Centers */ +struct isea_geo icostriangles[] = { + {0.0, 0.0}, + {-DEG144, E_RAD}, + {-DEG72, E_RAD}, + {0.0, E_RAD}, + {DEG72, E_RAD}, + {DEG144, E_RAD}, + {-DEG144, F_RAD}, + {-DEG72, F_RAD}, + {0.0, F_RAD}, + {DEG72, F_RAD}, + {DEG144, F_RAD}, + {-DEG108, -F_RAD}, + {-DEG36, -F_RAD}, + {DEG36, -F_RAD}, + {DEG108, -F_RAD}, + {DEG180, -F_RAD}, + {-DEG108, -E_RAD}, + {-DEG36, -E_RAD}, + {DEG36, -E_RAD}, + {DEG108, -E_RAD}, + {DEG180, -E_RAD}, +}; + +static double +az_adjustment(int triangle) +{ + double adj; + + struct isea_geo v; + struct isea_geo c; + + v = vertex[tri_v1[triangle]]; + c = icostriangles[triangle]; + + /* TODO looks like the adjustment is always either 0 or 180 */ + /* at least if you pick your vertex carefully */ + adj = atan2(cos(v.lat) * sin(v.lon - c.lon), + cos(c.lat) * sin(v.lat) + - sin(c.lat) * cos(v.lat) * cos(v.lon - c.lon)); + return adj; +} + +/* R tan(g) sin(60) */ +#define TABLE_G 0.6615845383 + +/* H = 0.25 R tan g = */ +#define TABLE_H 0.1909830056 + +#define RPRIME 0.91038328153090290025 + +ISEA_STATIC +struct isea_pt +isea_triangle_xy(int triangle) +{ + struct isea_pt c; + double Rprime = 0.91038328153090290025; + + triangle = (triangle - 1) % 20; + + c.x = TABLE_G * ((triangle % 5) - 2) * 2.0; + if (triangle > 9) { + c.x += TABLE_G; + } + switch (triangle / 5) { + case 0: + c.y = 5.0 * TABLE_H; + break; + case 1: + c.y = TABLE_H; + break; + case 2: + c.y = -TABLE_H; + break; + case 3: + c.y = -5.0 * TABLE_H; + break; + default: + /* should be impossible */ + exit(EXIT_FAILURE); + }; + c.x *= Rprime; + c.y *= Rprime; + + return c; +} + +/* snyder eq 14 */ +static double +sph_azimuth(double f_lon, double f_lat, double t_lon, double t_lat) +{ + double az; + + az = atan2(cos(t_lat) * sin(t_lon - f_lon), + cos(f_lat) * sin(t_lat) + - sin(f_lat) * cos(t_lat) * cos(t_lon - f_lon) + ); + return az; +} + +/* coord needs to be in radians */ +ISEA_STATIC +int +isea_snyder_forward(struct isea_geo * ll, struct isea_pt * out) +{ + int i; + + /* + * spherical distance from center of polygon face to any of its + * vertexes on the globe + */ + double g; + + /* + * spherical angle between radius vector to center and adjacent edge + * of spherical polygon on the globe + */ + double G; + + /* + * plane angle between radius vector to center and adjacent edge of + * plane polygon + */ + double theta; + + /* additional variables from snyder */ + double q, Rprime, H, Ag, Azprime, Az, dprime, f, rho, + x, y; + + /* variables used to store intermediate results */ + double cot_theta, tan_g, az_offset; + + /* how many multiples of 60 degrees we adjust the azimuth */ + int Az_adjust_multiples; + + struct snyder_constants c; + + /* + * TODO by locality of reference, start by trying the same triangle + * as last time + */ + + /* TODO put these constants in as radians to begin with */ + c = constants[SNYDER_POLY_ICOSAHEDRON]; + theta = c.theta * DEG2RAD; + g = c.g * DEG2RAD; + G = c.G * DEG2RAD; + + for (i = 1; i <= 20; i++) { + double z; + struct isea_geo center; + + center = icostriangles[i]; + + /* step 1 */ + z = acos(sin(center.lat) * sin(ll->lat) + + cos(center.lat) * cos(ll->lat) * cos(ll->lon - center.lon)); + /* not on this triangle */ + if (z > g + 0.000005) { /* TODO DBL_EPSILON */ + continue; + } + + Az = sph_azimuth(center.lon, center.lat, ll->lon, ll->lat); + + /* step 2 */ + + /* This calculates "some" vertex coordinate */ + az_offset = az_adjustment(i); + + Az -= az_offset; + + /* TODO I don't know why we do this. It's not in snyder */ + /* maybe because we should have picked a better vertex */ + if (Az < 0.0) { + Az += 2.0 * M_PI; + } + /* + * adjust Az for the point to fall within the range of 0 to + * 2(90 - theta) or 60 degrees for the hexagon, by + * and therefore 120 degrees for the triangle + * of the icosahedron + * subtracting or adding multiples of 60 degrees to Az and + * recording the amount of adjustment + */ + + Az_adjust_multiples = 0; + while (Az < 0.0) { + Az += DEG120; + Az_adjust_multiples--; + } + while (Az > DEG120 + DBL_EPSILON) { + Az -= DEG120; + Az_adjust_multiples++; + } + + /* step 3 */ + cot_theta = 1.0 / tan(theta); + tan_g = tan(g); /* TODO this is a constant */ + + /* Calculate q from eq 9. */ + /* TODO cot_theta is cot(30) */ + q = atan2(tan_g, cos(Az) + sin(Az) * cot_theta); + + /* not in this triangle */ + if (z > q + 0.000005) { + continue; + } + /* step 4 */ + + /* Apply equations 5-8 and 10-12 in order */ + + /* eq 5 */ + /* Rprime = 0.9449322893 * R; */ + /* R' in the paper is for the truncated */ + Rprime = 0.91038328153090290025; + + /* eq 6 */ + H = acos(sin(Az) * sin(G) * cos(g) - cos(Az) * cos(G)); + + /* eq 7 */ + /* Ag = (Az + G + H - DEG180) * M_PI * R * R / DEG180; */ + Ag = Az + G + H - DEG180; + + /* eq 8 */ + Azprime = atan2(2.0 * Ag, Rprime * Rprime * tan_g * tan_g - 2.0 * Ag * cot_theta); + + /* eq 10 */ + /* cot(theta) = 1.73205080756887729355 */ + dprime = Rprime * tan_g / (cos(Azprime) + sin(Azprime) * cot_theta); + + /* eq 11 */ + f = dprime / (2.0 * Rprime * sin(q / 2.0)); + + /* eq 12 */ + rho = 2.0 * Rprime * f * sin(z / 2.0); + + /* + * add back the same 60 degree multiple adjustment from step + * 2 to Azprime + */ + + Azprime += DEG120 * Az_adjust_multiples; + + /* calculate rectangular coordinates */ + + x = rho * sin(Azprime); + y = rho * cos(Azprime); + + /* + * TODO + * translate coordinates to the origin for the particular + * hexagon on the flattened polyhedral map plot + */ + + out->x = x; + out->y = y; + + return i; + } + + /* + * should be impossible, this implies that the coordinate is not on + * any triangle + */ + + fprintf(stderr, "impossible transform: %f %f is not on any triangle\n", + ll->lon * RAD2DEG, ll->lat * RAD2DEG); + + exit(EXIT_FAILURE); + + /* not reached */ + return 0; /* supresses a warning */ +} + +/* + * return the new coordinates of any point in orginal coordinate system. + * Define a point (newNPold) in orginal coordinate system as the North Pole in + * new coordinate system, and the great circle connect the original and new + * North Pole as the lon0 longitude in new coordinate system, given any point + * in orginal coordinate system, this function return the new coordinates. + */ + +#define PRECISION 0.0000000000005 + +/* formula from Snyder, Map Projections: A working manual, p31 */ +/* + * old north pole at np in new coordinates + * could be simplified a bit with fewer intermediates + * + * TODO take a result pointer + */ +ISEA_STATIC +struct isea_geo +snyder_ctran(struct isea_geo * np, struct isea_geo * pt) +{ + struct isea_geo npt; + double alpha, phi, lambda, lambda0, beta, lambdap, phip; + double sin_phip; + double lp_b; /* lambda prime minus beta */ + double cos_p, sin_a; + + phi = pt->lat; + lambda = pt->lon; + alpha = np->lat; + beta = np->lon; + lambda0 = beta; + + cos_p = cos(phi); + sin_a = sin(alpha); + + /* mpawm 5-7 */ + sin_phip = sin_a * sin(phi) - cos(alpha) * cos_p * cos(lambda - lambda0); + + /* mpawm 5-8b */ + + /* use the two argument form so we end up in the right quadrant */ + lp_b = atan2(cos_p * sin(lambda - lambda0), + (sin_a * cos_p * cos(lambda - lambda0) + cos(alpha) * sin(phi))); + + lambdap = lp_b + beta; + + /* normalize longitude */ + /* TODO can we just do a modulus ? */ + lambdap = fmod(lambdap, 2 * M_PI); + while (lambdap > M_PI) + lambdap -= 2 * M_PI; + while (lambdap < -M_PI) + lambdap += 2 * M_PI; + + phip = asin(sin_phip); + + npt.lat = phip; + npt.lon = lambdap; + + return npt; +} + +ISEA_STATIC +struct isea_geo +isea_ctran(struct isea_geo * np, struct isea_geo * pt, double lon0) +{ + struct isea_geo npt; + + np->lon += M_PI; + npt = snyder_ctran(np, pt); + np->lon -= M_PI; + + npt.lon -= (M_PI - lon0 + np->lon); + + /* + * snyder is down tri 3, isea is along side of tri1 from vertex 0 to + * vertex 1 these are 180 degrees apart + */ + npt.lon += M_PI; + /* normalize longitude */ + npt.lon = fmod(npt.lon, 2 * M_PI); + while (npt.lon > M_PI) + npt.lon -= 2 * M_PI; + while (npt.lon < -M_PI) + npt.lon += 2 * M_PI; + + return npt; +} + +/* in radians */ +#define ISEA_STD_LAT 1.01722196792335072101 +#define ISEA_STD_LON .19634954084936207740 + +/* fuller's at 5.2454 west, 2.3009 N, adjacent at 7.46658 deg */ + +ISEA_STATIC +int +isea_grid_init(struct isea_dgg * g) +{ + if (!g) + return 0; + + g->polyhedron = 20; + g->o_lat = ISEA_STD_LAT; + g->o_lon = ISEA_STD_LON; + g->o_az = 0.0; + g->aperture = 4; + g->resolution = 6; + g->radius = 1.0; + g->topology = 6; + + return 1; +} + +ISEA_STATIC +int +isea_orient_isea(struct isea_dgg * g) +{ + if (!g) + return 0; + g->o_lat = ISEA_STD_LAT; + g->o_lon = ISEA_STD_LON; + g->o_az = 0.0; + return 1; +} + +ISEA_STATIC +int +isea_orient_pole(struct isea_dgg * g) +{ + if (!g) + return 0; + g->o_lat = M_PI / 2.0; + g->o_lon = 0.0; + g->o_az = 0; + return 1; +} + +ISEA_STATIC +int +isea_transform(struct isea_dgg * g, struct isea_geo * in, + struct isea_pt * out) +{ + struct isea_geo i, pole; + int tri; + + pole.lat = g->o_lat; + pole.lon = g->o_lon; + + i = isea_ctran(&pole, in, g->o_az); + + tri = isea_snyder_forward(&i, out); + out->x *= g->radius; + out->y *= g->radius; + g->triangle = tri; + + return tri; +} + +#define DOWNTRI(tri) (((tri - 1) / 5) % 2 == 1) + +ISEA_STATIC +void +isea_rotate(struct isea_pt * pt, double degrees) +{ + double rad; + + double x, y; + + rad = -degrees * M_PI / 180.0; + while (rad >= 2.0 * M_PI) rad -= 2.0 * M_PI; + while (rad <= -2.0 * M_PI) rad += 2.0 * M_PI; + + x = pt->x * cos(rad) + pt->y * sin(rad); + y = -pt->x * sin(rad) + pt->y * cos(rad); + + pt->x = x; + pt->y = y; +} + +ISEA_STATIC +int isea_tri_plane(int tri, struct isea_pt *pt, double radius) { + struct isea_pt tc; /* center of triangle */ + + if (DOWNTRI(tri)) { + isea_rotate(pt, 180.0); + } + tc = isea_triangle_xy(tri); + tc.x *= radius; + tc.y *= radius; + pt->x += tc.x; + pt->y += tc.y; + + return tri; +} + +/* convert projected triangle coords to quad xy coords, return quad number */ +ISEA_STATIC +int +isea_ptdd(int tri, struct isea_pt *pt) { + int downtri, quad; + + downtri = (((tri - 1) / 5) % 2 == 1); + quad = ((tri - 1) % 5) + ((tri - 1) / 10) * 5 + 1; + + isea_rotate(pt, downtri ? 240.0 : 60.0); + if (downtri) { + pt->x += 0.5; + /* pt->y += cos(30.0 * M_PI / 180.0); */ + pt->y += .86602540378443864672; + } + return quad; +} + +ISEA_STATIC +int +isea_dddi_ap3odd(struct isea_dgg *g, int quad, struct isea_pt *pt, struct isea_pt *di) +{ + struct isea_pt v; + double hexwidth; + double sidelength; /* in hexes */ + int d, i; + int maxcoord; + struct hex h; + + /* This is the number of hexes from apex to base of a triangle */ + sidelength = (pow(2.0, g->resolution) + 1.0) / 2.0; + + /* apex to base is cos(30deg) */ + hexwidth = cos(M_PI / 6.0) / sidelength; + + /* TODO I think sidelength is always x.5, so + * (int)sidelength * 2 + 1 might be just as good + */ + maxcoord = (int) (sidelength * 2.0 + 0.5); + + v = *pt; + hexbin2(hexwidth, v.x, v.y, &h.x, &h.y); + h.iso = 0; + hex_iso(&h); + + d = h.x - h.z; + i = h.x + h.y + h.y; + + /* + * you want to test for max coords for the next quad in the same + * "row" first to get the case where both are max + */ + if (quad <= 5) { + if (d == 0 && i == maxcoord) { + /* north pole */ + quad = 0; + d = 0; + i = 0; + } else if (i == maxcoord) { + /* upper right in next quad */ + quad += 1; + if (quad == 6) + quad = 1; + i = maxcoord - d; + d = 0; + } else if (d == maxcoord) { + /* lower right in quad to lower right */ + quad += 5; + d = 0; + } + } else if (quad >= 6) { + if (i == 0 && d == maxcoord) { + /* south pole */ + quad = 11; + d = 0; + i = 0; + } else if (d == maxcoord) { + /* lower right in next quad */ + quad += 1; + if (quad == 11) + quad = 6; + d = maxcoord - i; + i = 0; + } else if (i == maxcoord) { + /* upper right in quad to upper right */ + quad = (quad - 4) % 5; + i = 0; + } + } + + di->x = d; + di->y = i; + + g->quad = quad; + return quad; +} + +ISEA_STATIC +int +isea_dddi(struct isea_dgg *g, int quad, struct isea_pt *pt, struct isea_pt *di) { + struct isea_pt v; + double hexwidth; + int sidelength; /* in hexes */ + struct hex h; + + if (g->aperture == 3 && g->resolution % 2 != 0) { + return isea_dddi_ap3odd(g, quad, pt, di); + } + /* todo might want to do this as an iterated loop */ + if (g->aperture >0) { + sidelength = (int) (pow(g->aperture, g->resolution / 2.0) + 0.5); + } else { + sidelength = g->resolution; + } + + hexwidth = 1.0 / sidelength; + + v = *pt; + isea_rotate(&v, -30.0); + hexbin2(hexwidth, v.x, v.y, &h.x, &h.y); + h.iso = 0; + hex_iso(&h); + + /* we may actually be on another quad */ + if (quad <= 5) { + if (h.x == 0 && h.z == -sidelength) { + /* north pole */ + quad = 0; + h.z = 0; + h.y = 0; + h.x = 0; + } else if (h.z == -sidelength) { + quad = quad + 1; + if (quad == 6) + quad = 1; + h.y = sidelength - h.x; + h.z = h.x - sidelength; + h.x = 0; + } else if (h.x == sidelength) { + quad += 5; + h.y = -h.z; + h.x = 0; + } + } else if (quad >= 6) { + if (h.z == 0 && h.x == sidelength) { + /* south pole */ + quad = 11; + h.x = 0; + h.y = 0; + h.z = 0; + } else if (h.x == sidelength) { + quad = quad + 1; + if (quad == 11) + quad = 6; + h.x = h.y + sidelength; + h.y = 0; + h.z = -h.x; + } else if (h.y == -sidelength) { + quad -= 4; + h.y = 0; + h.z = -h.x; + } + } + di->x = h.x; + di->y = -h.z; + + g->quad = quad; + return quad; +} + +ISEA_STATIC +int isea_ptdi(struct isea_dgg *g, int tri, struct isea_pt *pt, + struct isea_pt *di) { + struct isea_pt v; + int quad; + + v = *pt; + quad = isea_ptdd(tri, &v); + quad = isea_dddi(g, quad, &v, di); + return quad; +} + +/* q2di to seqnum */ +ISEA_STATIC +int isea_disn(struct isea_dgg *g, int quad, struct isea_pt *di) { + int sidelength; + int sn, height; + int hexes; + + if (quad == 0) { + g->serial = 1; + return g->serial; + } + /* hexes in a quad */ + hexes = (int) (pow(g->aperture, g->resolution) + 0.5); + if (quad == 11) { + g->serial = 1 + 10 * hexes + 1; + return g->serial; + } + if (g->aperture == 3 && g->resolution % 2 == 1) { + height = (int) (pow(g->aperture, (g->resolution - 1) / 2.0)); + sn = ((int) di->x) * height; + sn += ((int) di->y) / height; + sn += (quad - 1) * hexes; + sn += 2; + } else { + sidelength = (int) (pow(g->aperture, g->resolution / 2.0) + 0.5); + sn = (quad - 1) * hexes + sidelength * di->x + di->y + 2; + } + + g->serial = sn; + return sn; +} + +/* TODO just encode the quad in the d or i coordinate + * quad is 0-11, which can be four bits. + * d' = d << 4 + q, d = d' >> 4, q = d' & 0xf + */ +/* convert a q2di to global hex coord */ +ISEA_STATIC +int isea_hex(struct isea_dgg *g, int tri, + struct isea_pt *pt, struct isea_pt *hex) { + struct isea_pt v; + int sidelength; + int d, i, x, y, quad; + + quad = isea_ptdi(g, tri, pt, &v); + + hex->x = ((int)v.x << 4) + quad; + hex->y = v.y; + + return 1; + + d = v.x; + i = v.y; + + /* Aperture 3 odd resolutions */ + if (g->aperture == 3 && g->resolution % 2 != 0) { + int offset = (int)(pow(3.0, g->resolution - 1) + 0.5); + + d += offset * ((g->quad-1) % 5); + i += offset * ((g->quad-1) % 5); + + if (quad == 0) { + d = 0; + i = offset; + } else if (quad == 11) { + d = 2 * offset; + i = 0; + } else if (quad > 5) { + d += offset; + } + + x = (2*d - i) /3; + y = (2*i - d) /3; + + hex->x = x + offset / 3; + hex->y = y + 2 * offset / 3; + return 1; + } + + /* aperture 3 even resolutions and aperture 4 */ + sidelength = (int) (pow(g->aperture, g->resolution / 2.0) + 0.5); + if (g->quad == 0) { + hex->x = 0; + hex->y = sidelength; + } else if (g->quad == 11) { + hex->x = sidelength * 2; + hex->y = 0; + } else { + hex->x = d + sidelength * ((g->quad-1) % 5); + if (g->quad > 5) hex->x += sidelength; + hex->y = i + sidelength * ((g->quad-1) % 5); + } + + return 1; +} + +ISEA_STATIC +struct isea_pt +isea_forward(struct isea_dgg *g, struct isea_geo *in) +{ + int tri; + struct isea_pt out, coord; + + tri = isea_transform(g, in, &out); + + if (g->output == ISEA_PLANE) { + isea_tri_plane(tri, &out, g->radius); + return out; + } + + /* convert to isea standard triangle size */ + out.x = out.x / g->radius * ISEA_SCALE; + out.y = out.y / g->radius * ISEA_SCALE; + out.x += 0.5; + out.y += 2.0 * .14433756729740644112; + + switch (g->output) { + case ISEA_PROJTRI: + /* nothing to do, already in projected triangle */ + break; + case ISEA_VERTEX2DD: + g->quad = isea_ptdd(tri, &out); + break; + case ISEA_Q2DD: + /* Same as above, we just don't print as much */ + g->quad = isea_ptdd(tri, &out); + break; + case ISEA_Q2DI: + g->quad = isea_ptdi(g, tri, &out, &coord); + return coord; + break; + case ISEA_SEQNUM: + isea_ptdi(g, tri, &out, &coord); + /* disn will set g->serial */ + isea_disn(g, g->quad, &coord); + return coord; + break; + case ISEA_HEX: + isea_hex(g, tri, &out, &coord); + return coord; + break; + } + + return out; +} +/* + * Proj 4 integration code follows + */ + +#define PJ_LIB__ +#include + +PROJ_HEAD(isea, "Icosahedral Snyder Equal Area") "\n\tSph"; + +struct pj_opaque { + struct isea_dgg dgg; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + struct isea_pt out; + struct isea_geo in; + + in.lon = lp.lam; + in.lat = lp.phi; + + out = isea_forward(&Q->dgg, &in); + + xy.x = out.x; + xy.y = out.y; + + return xy; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(isea) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + char *opt; + + P->fwd = s_forward; + isea_grid_init(&Q->dgg); + + Q->dgg.output = ISEA_PLANE; +/* P->dgg.radius = P->a; / * otherwise defaults to 1 */ + /* calling library will scale, I think */ + + opt = pj_param(P->ctx,P->params, "sorient").s; + if (opt) { + if (!strcmp(opt, "isea")) { + isea_orient_isea(&Q->dgg); + } else if (!strcmp(opt, "pole")) { + isea_orient_pole(&Q->dgg); + } else { + E_ERROR(-34); + } + } + + if (pj_param(P->ctx,P->params, "tazi").i) { + Q->dgg.o_az = pj_param(P->ctx,P->params, "razi").f; + } + + if (pj_param(P->ctx,P->params, "tlon_0").i) { + Q->dgg.o_lon = pj_param(P->ctx,P->params, "rlon_0").f; + } + + if (pj_param(P->ctx,P->params, "tlat_0").i) { + Q->dgg.o_lat = pj_param(P->ctx,P->params, "rlat_0").f; + } + + if (pj_param(P->ctx,P->params, "taperture").i) { + Q->dgg.aperture = pj_param(P->ctx,P->params, "iaperture").i; + } + + if (pj_param(P->ctx,P->params, "tresolution").i) { + Q->dgg.resolution = pj_param(P->ctx,P->params, "iresolution").i; + } + + opt = pj_param(P->ctx,P->params, "smode").s; + if (opt) { + if (!strcmp(opt, "plane")) { + Q->dgg.output = ISEA_PLANE; + } else if (!strcmp(opt, "di")) { + Q->dgg.output = ISEA_Q2DI; + } + else if (!strcmp(opt, "dd")) { + Q->dgg.output = ISEA_Q2DD; + } + else if (!strcmp(opt, "hex")) { + Q->dgg.output = ISEA_HEX; + } + else { + /* TODO verify error code. Possibly eliminate magic */ + E_ERROR(-34); + } + } + + if (pj_param(P->ctx,P->params, "trescale").i) { + Q->dgg.radius = ISEA_SCALE; + } + + if (pj_param(P->ctx,P->params, "tresolution").i) { + Q->dgg.resolution = pj_param(P->ctx,P->params, "iresolution").i; + } else { + Q->dgg.resolution = 4; + } + + if (pj_param(P->ctx,P->params, "taperture").i) { + Q->dgg.aperture = pj_param(P->ctx,P->params, "iaperture").i; + } else { + Q->dgg.aperture = 3; + } + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_isea_selftest (void) {return 0;} +#else + +int pj_isea_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=isea +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {-1097074.9480224741, 3442909.3090371834}, + {-1097074.9482647954, 3233611.7285857084}, + {-1575486.3536415542, 3442168.3420281881}, + {-1575486.353880283, 3234352.6955947056}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} + + +#endif -- cgit v1.2.3 From f9192bdb014d69393e93df20f789a3afb4e1218a Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 19 Apr 2016 15:37:17 +0200 Subject: Converted krovak --- src/PJ_aea.c | 1 - src/PJ_krovak.c | 162 +++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 113 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index f57c1161..72091132 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -362,7 +362,6 @@ int pj_geocent_selftest (void) {return 10000;} int pj_gs48_selftest (void) {return 10000;} int pj_gs50_selftest (void) {return 10000;} -int pj_krovak_selftest (void) {return 10000;} int pj_labrd_selftest (void) {return 10000;} int pj_laea_selftest (void) {return 10000;} int pj_lagrng_selftest (void) {return 10000;} diff --git a/src/PJ_krovak.c b/src/PJ_krovak.c index 09a8311e..bb714189 100644 --- a/src/PJ_krovak.c +++ b/src/PJ_krovak.c @@ -29,16 +29,17 @@ * SOFTWARE. *****************************************************************************/ -#define PROJ_PARMS__ \ - double C_x; #define PJ_LIB__ - #include #include #include PROJ_HEAD(krovak, "Krovak") "\n\tPCyl., Ellps."; +struct pj_opaque { + double C_x; +}; + /** NOTES: According to EPSG the full Krovak projection method should have the following parameters. Within PROJ.4 the azimuth, and pseudo @@ -63,11 +64,12 @@ PROJ_HEAD(krovak, "Krovak") "\n\tPCyl., Ellps."; **/ +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + /* calculate xy from lat/lon */ -FORWARD(e_forward); /* ellipsoid */ -/* calculate xy from lat/lon */ - -/* Constants, identical to inverse transform function */ + /* Constants, identical to inverse transform function */ double s45, s90, e2, e, alfa, uq, u0, g, k, k1, n0, ro0, ad, a, s0, n; double gfi, u, fi0, deltav, s, d, eps, ro; @@ -76,11 +78,11 @@ FORWARD(e_forward); /* ellipsoid */ s90 = 2 * s45; fi0 = P->phi0; /* Latitude of projection centre 49deg 30' */ - /* Ellipsoid is used as Parameter in for.c and inv.c, therefore a must + /* Ellipsoid is used as Parameter in for.c and inv.c, therefore a must be set to 1 here. Ellipsoid Bessel 1841 a = 6377397.155m 1/f = 299.1528128, e2=0.006674372230614; - */ + */ a = 1; /* 6377397.155; */ /* e2 = P->es;*/ /* 0.006674372230614; */ e2 = 0.006674372230614; @@ -101,39 +103,38 @@ FORWARD(e_forward); /* ellipsoid */ ro0 = k1 * n0 / tan(s0); ad = s90 - uq; -/* Transformation */ - - gfi =pow ( ((1. + e * sin(lp.phi)) / - (1. - e * sin(lp.phi))) , (alfa * e / 2.)); + /* Transformation */ + gfi = pow ( ((1. + e * sin(lp.phi)) / + (1. - e * sin(lp.phi))) , (alfa * e / 2.)); - u= 2. * (atan(k * pow( tan(lp.phi / 2. + s45), alfa) / gfi)-s45); + u = 2. * (atan(k * pow( tan(lp.phi / 2. + s45), alfa) / gfi)-s45); deltav = - lp.lam * alfa; s = asin(cos(ad) * sin(u) + sin(ad) * cos(u) * cos(deltav)); d = asin(cos(u) * sin(deltav) / cos(s)); eps = n * d; - ro = ro0 * pow(tan(s0 / 2. + s45) , n) / pow(tan(s / 2. + s45) , n) ; + ro = ro0 * pow(tan(s0 / 2. + s45) , n) / pow(tan(s / 2. + s45) , n); /* x and y are reverted! */ xy.y = ro * cos(eps) / a; xy.x = ro * sin(eps) / a; - if( !pj_param(P->ctx, P->params, "tczech").i ) - { + if( !pj_param(P->ctx, P->params, "tczech").i ) { xy.y *= -1.0; xy.x *= -1.0; - } + } - return (xy); + return xy; } - -INVERSE(e_inverse); /* ellipsoid */ +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; /* calculate lat/lon from xy */ -/* Constants, identisch wie in der Umkehrfunktion */ + /* Constants, identisch wie in der Umkehrfunktion */ double s45, s90, fi0, e2, e, alfa, uq, u0, g, k, k1, n0, ro0, ad, a, s0, n; double u, deltav, s, d, eps, ro, fi1, xy0; int ok; @@ -168,17 +169,16 @@ INVERSE(e_inverse); /* ellipsoid */ ad = s90 - uq; -/* Transformation */ + /* Transformation */ /* revert y, x*/ - xy0=xy.x; - xy.x=xy.y; - xy.y=xy0; + xy0 = xy.x; + xy.x = xy.y; + xy.y = xy0; - if( !pj_param(P->ctx, P->params, "tczech").i ) - { + if( !pj_param(P->ctx, P->params, "tczech").i ) { xy.x *= -1.0; xy.y *= -1.0; - } + } ro = sqrt(xy.x * xy.x + xy.y * xy.y); eps = atan2(xy.y, xy.x); @@ -190,37 +190,56 @@ INVERSE(e_inverse); /* ellipsoid */ lp.lam = P->lam0 - deltav / alfa; -/* ITERATION FOR lp.phi */ - fi1 = u; + /* ITERATION FOR lp.phi */ + fi1 = u; - ok = 0; - do - { - lp.phi = 2. * ( atan( pow( k, -1. / alfa) * - pow( tan(u / 2. + s45) , 1. / alfa) * - pow( (1. + e * sin(fi1)) / (1. - e * sin(fi1)) , e / 2.) - ) - s45); + ok = 0; + do { + lp.phi = 2. * ( atan( pow( k, -1. / alfa) * + pow( tan(u / 2. + s45) , 1. / alfa) * + pow( (1. + e * sin(fi1)) / (1. - e * sin(fi1)) , e / 2.) + ) - s45); - if (fabs(fi1 - lp.phi) < 0.000000000000001) ok=1; - fi1 = lp.phi; - - } - while (ok==0); + if (fabs(fi1 - lp.phi) < 0.000000000000001) ok=1; + fi1 = lp.phi; + } while (ok==0); lp.lam -= P->lam0; - return (lp); + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); } -FREEUP; if (P) pj_dalloc(P); } +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(krovak) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; -ENTRY0(krovak) + P->pfree = freeup; + P->descr = des_krovak; double ts; /* read some Parameters, * here Latitude Truescale */ ts = pj_param(P->ctx, P->params, "rlat_ts").f; - P->C_x = ts; + Q->C_x = ts; /* we want Bessel as fixed ellipsoid */ P->a = 6377397.155; @@ -241,8 +260,53 @@ ENTRY0(krovak) P->k0 = 0.9999; /* always the same */ - P->inv = e_inverse; + P->inv = e_inverse; P->fwd = e_forward; -ENDENTRY(P) + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_krovak_selftest (void) {return 0;} +#else + +int pj_krovak_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=krovak +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {-3196535.2325636409, -6617878.8675514441}, + {-3260035.4405521089, -6898873.6148780314}, + {-3756305.3288691747, -6478142.5615715114}, + {-3831703.6585019818, -6759107.1701553948}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {24.836218918719162, 59.758403933233858}, + {24.836315484509566, 59.756888425730189}, + {24.830447747947495, 59.758403933233858}, + {24.830351182157091, 59.756888425730189}, + }; + + return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); +} + +#endif -- cgit v1.2.3 From 7a4841d9424e259f6cba2f173ebfb8225e21bb88 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Wed, 20 Apr 2016 17:12:48 +0200 Subject: Minor bug in pj_sterea Added missing check for actual allocation of gauss object. --- src/PJ_sterea.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/PJ_sterea.c b/src/PJ_sterea.c index cbfb8fb4..93799011 100644 --- a/src/PJ_sterea.c +++ b/src/PJ_sterea.c @@ -99,13 +99,14 @@ static void freeup (PJ *P) { PJ *PROJECTION(sterea) { double R; struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) return freeup_new (P); P->opaque = Q; Q->en = pj_gauss_ini(P->e, P->phi0, &(Q->phic0), &R); - if (0==P) - E_ERROR_0; + if (0==Q->en) + return freeup_new (P); Q->sinc0 = sin (Q->phic0); Q->cosc0 = cos (Q->phic0); -- cgit v1.2.3 From 9687e69b177933c2894adc842f6aa507fc70ca16 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Wed, 20 Apr 2016 18:10:00 +0200 Subject: Portability cleanups for the code in PR #5 Eliminated load time non-constant initializers, mixed code/declarations and C++ style comments. A lot of non-constant initializers remain in PJ_healpix. Should probably be handled before next release. --- src/PJ_goode.c | 18 ++++------- src/PJ_healpix.c | 4 +-- src/PJ_igh.c | 96 ++++++++++++++++++++++++++++++-------------------------- src/PJ_imw_p.c | 5 ++- src/PJ_isea.c | 2 +- src/PJ_krovak.c | 7 +++-- 6 files changed, 67 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/PJ_goode.c b/src/PJ_goode.c index d577f901..48fc9ad5 100644 --- a/src/PJ_goode.c +++ b/src/PJ_goode.c @@ -6,9 +6,11 @@ PROJ_HEAD(goode, "Goode Homolosine") "\n\tPCyl, Sph."; #define Y_COR 0.05280 #define PHI_LIM 0.71093078197902358062 +C_NAMESPACE PJ *pj_sinu(PJ *), *pj_moll(PJ *); + struct pj_opaque { - struct PJconsts *sinu; \ - struct PJconsts *moll; + PJ *sinu; + PJ *moll; }; @@ -101,11 +103,7 @@ int pj_goode_selftest (void) { }; XY s_fwd_expect[] = { - { 223368.11902663155, 111701.07212763709 }, - { 223368.11902663155, -111701.07212763709 }, - {-223368.11902663155, 111701.07212763709 }, - {-223368.11902663155, -111701.07212763709 }, - }; + { 223368.11902663155, 111701.07212763709}, { 223368.11902663155, -111701.07212763709}, {-223368.11902663155, 111701.07212763709}, {-223368.11902663155, -111701.07212763709}, }; XY inv_in[] = { { 200, 100}, @@ -115,11 +113,7 @@ int pj_goode_selftest (void) { }; LP s_inv_expect[] = { - { 0.0017904931100023887, 0.00089524655489191132 }, - { 0.0017904931100023887, -0.00089524655489191132 }, - {-0.0017904931100023887, 0.00089524655489191132 }, - {-0.0017904931100023887, -0.00089524655489191132 }, - }; + { 0.0017904931100023887, 0.00089524655489191132}, { 0.0017904931100023887, -0.00089524655489191132}, {-0.0017904931100023887, 0.00089524655489191132}, {-0.0017904931100023887, -0.00089524655489191132}, }; return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); } diff --git a/src/PJ_healpix.c b/src/PJ_healpix.c index ae5aa5be..f6fe624b 100644 --- a/src/PJ_healpix.c +++ b/src/PJ_healpix.c @@ -554,9 +554,9 @@ static XY s_rhealpix_forward(LP lp, PJ *P) { /* sphere */ static XY e_rhealpix_forward(LP lp, PJ *P) { /* ellipsoid */ struct pj_opaque *Q = P->opaque; - + XY xy; lp.phi = auth_lat(P, lp.phi, 0); - XY xy = healpix_sphere(lp); + xy = healpix_sphere(lp); return combine_caps(xy.x, xy.y, Q->north_square, Q->south_square, 0); } diff --git a/src/PJ_igh.c b/src/PJ_igh.c index f82f4f3f..533c3aa0 100644 --- a/src/PJ_igh.c +++ b/src/PJ_igh.c @@ -4,7 +4,14 @@ PROJ_HEAD(igh, "Interrupted Goode Homolosine") "\n\tPCyl, Sph."; C_NAMESPACE PJ *pj_sinu(PJ *), *pj_moll(PJ *); -static const double d4044118 = (40 + 44/60. + 11.8/3600.) * DEG_TO_RAD; // 40d 44' 11.8" [degrees] + +/* 40d 44' 11.8" [degrees] */ +/* +static const double d4044118 = (40 + 44/60. + 11.8/3600.) * DEG_TO_RAD; +has been replaced by this define, to eliminate portability issue: +Initializer element not computable at load time +*/ +#define d4044118 ((40 + 44/60. + 11.8/3600.) * DEG_TO_RAD) static const double d10 = 10 * DEG_TO_RAD; static const double d20 = 20 * DEG_TO_RAD; @@ -19,7 +26,7 @@ static const double d140 = 140 * DEG_TO_RAD; static const double d160 = 160 * DEG_TO_RAD; static const double d180 = 180 * DEG_TO_RAD; -static const double EPSLN = 1.e-10; // allow a little 'slack' on zone edge positions +static const double EPSLN = 1.e-10; /* allow a little 'slack' on zone edge positions */ struct pj_opaque { struct PJconsts* pj[12]; \ @@ -32,23 +39,23 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ struct pj_opaque *Q = P->opaque; int z; - if (lp.phi >= d4044118) { // 1|2 + if (lp.phi >= d4044118) { /* 1|2 */ z = (lp.lam <= -d40 ? 1: 2); } - else if (lp.phi >= 0) { // 3|4 + else if (lp.phi >= 0) { /* 3|4 */ z = (lp.lam <= -d40 ? 3: 4); } - else if (lp.phi >= -d4044118) { // 5|6|7|8 - if (lp.lam <= -d100) z = 5; // 5 - else if (lp.lam <= -d20) z = 6; // 6 - else if (lp.lam <= d80) z = 7; // 7 - else z = 8; // 8 + else if (lp.phi >= -d4044118) { /* 5|6|7|8 */ + if (lp.lam <= -d100) z = 5; /* 5 */ + else if (lp.lam <= -d20) z = 6; /* 6 */ + else if (lp.lam <= d80) z = 7; /* 7 */ + else z = 8; /* 8 */ } - else { // 9|10|11|12 - if (lp.lam <= -d100) z = 9; // 9 - else if (lp.lam <= -d20) z = 10; // 10 - else if (lp.lam <= d80) z = 11; // 11 - else z = 12; // 12 + else { /* 9|10|11|12 */ + if (lp.lam <= -d100) z = 9; /* 9 */ + else if (lp.lam <= -d20) z = 10; /* 10 */ + else if (lp.lam <= d80) z = 11; /* 11 */ + else z = 12; /* 12 */ } lp.lam -= Q->pj[z-1]->lam0; @@ -63,26 +70,26 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ LP lp = {0.0,0.0}; struct pj_opaque *Q = P->opaque; - const double y90 = Q->dy0 + sqrt(2); // lt=90 corresponds to y=y0+sqrt(2) + const double y90 = Q->dy0 + sqrt(2); /* lt=90 corresponds to y=y0+sqrt(2) */ int z = 0; - if (xy.y > y90+EPSLN || xy.y < -y90+EPSLN) // 0 + if (xy.y > y90+EPSLN || xy.y < -y90+EPSLN) /* 0 */ z = 0; - else if (xy.y >= d4044118) // 1|2 + else if (xy.y >= d4044118) /* 1|2 */ z = (xy.x <= -d40? 1: 2); - else if (xy.y >= 0) // 3|4 + else if (xy.y >= 0) /* 3|4 */ z = (xy.x <= -d40? 3: 4); - else if (xy.y >= -d4044118) { // 5|6|7|8 - if (xy.x <= -d100) z = 5; // 5 - else if (xy.x <= -d20) z = 6; // 6 - else if (xy.x <= d80) z = 7; // 7 - else z = 8; // 8 + else if (xy.y >= -d4044118) { /* 5|6|7|8 */ + if (xy.x <= -d100) z = 5; /* 5 */ + else if (xy.x <= -d20) z = 6; /* 6 */ + else if (xy.x <= d80) z = 7; /* 7 */ + else z = 8; /* 8 */ } - else { // 9|10|11|12 - if (xy.x <= -d100) z = 9; // 9 - else if (xy.x <= -d20) z = 10; // 10 - else if (xy.x <= d80) z = 11; // 11 - else z = 12; // 12 + else { /* 9|10|11|12 */ + if (xy.x <= -d100) z = 9; /* 9 */ + else if (xy.x <= -d20) z = 10; /* 10 */ + else if (xy.x <= d80) z = 11; /* 11 */ + else z = 12; /* 12 */ } if (z) { @@ -113,7 +120,7 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ case 11: ok = (lp.lam >= -d20-EPSLN && lp.lam <= d80+EPSLN); break; case 12: ok = (lp.lam >= d80-EPSLN && lp.lam <= d180+EPSLN); break; } - z = (!ok? 0: z); // projectable? + z = (!ok? 0: z); /* projectable? */ } if (!z) lp.lam = HUGE_VAL; @@ -124,12 +131,12 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ static void *freeup_new (PJ *P) { /* Destructor */ + int i; if (0==P) return 0; if (0==P->opaque) return pj_dealloc (P); - int i; for (i = 0; i < 12; ++i) { if (P->opaque->pj[i]) pj_dealloc(P->opaque->pj[i]); @@ -146,11 +153,6 @@ static void freeup (PJ *P) { } -PJ *PROJECTION(igh) { - struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); - if (0==Q) - return freeup_new (P); - P->opaque = Q; /* Zones: @@ -179,11 +181,17 @@ PJ *PROJECTION(igh) { Q->pj[n-1]->y0 = y_0; \ Q->pj[n-1]->lam0 = lon_0; + +PJ *PROJECTION(igh) { + XY xy1, xy3; LP lp = { 0, d4044118 }; - XY xy1; - XY xy3; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + - // sinusoidal zones + /* sinusoidal zones */ SETUP(3, sinu, -d100, 0, -d100); SETUP(4, sinu, d30, 0, d30); SETUP(5, sinu, -d160, 0, -d160); @@ -191,18 +199,18 @@ PJ *PROJECTION(igh) { SETUP(7, sinu, d20, 0, d20); SETUP(8, sinu, d140, 0, d140); - // mollweide zones + /* mollweide zones */ SETUP(1, moll, -d100, 0, -d100); - // y0 ? - xy1 = Q->pj[0]->fwd(lp, Q->pj[0]); // zone 1 - xy3 = Q->pj[2]->fwd(lp, Q->pj[2]); // zone 3 - // y0 + xy1.y = xy3.y for lt = 40d44'11.8" + /* y0 ? */ + xy1 = Q->pj[0]->fwd(lp, Q->pj[0]); /* zone 1 */ + xy3 = Q->pj[2]->fwd(lp, Q->pj[2]); /* zone 3 */ + /* y0 + xy1.y = xy3.y for lt = 40d44'11.8" */ Q->dy0 = xy3.y - xy1.y; Q->pj[0]->y0 = Q->dy0; - // mollweide zones (cont'd) + /* mollweide zones (cont'd) */ SETUP( 2, moll, d30, Q->dy0, d30); SETUP( 9, moll, -d160, -Q->dy0, -d160); SETUP(10, moll, -d60, -Q->dy0, -d60); diff --git a/src/PJ_imw_p.c b/src/PJ_imw_p.c index 10a06a44..a1675a90 100644 --- a/src/PJ_imw_p.c +++ b/src/PJ_imw_p.c @@ -137,14 +137,13 @@ static void freeup (PJ *P) { PJ *PROJECTION(imw_p) { + double del, sig, s, t, x1, x2, T2, y1, m1, m2, y2; + int i; struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - double del, sig, s, t, x1, x2, T2, y1, m1, m2, y2; - int i; - if (!(Q->en = pj_enfn(P->es))) E_ERROR_0; if( (i = phi12(P, &del, &sig)) != 0) E_ERROR(i); diff --git a/src/PJ_isea.c b/src/PJ_isea.c index f1bc89a7..ba9d3c62 100644 --- a/src/PJ_isea.c +++ b/src/PJ_isea.c @@ -1061,12 +1061,12 @@ static void freeup (PJ *P) { PJ *PROJECTION(isea) { + char *opt; struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - char *opt; P->fwd = s_forward; isea_grid_init(&Q->dgg); diff --git a/src/PJ_krovak.c b/src/PJ_krovak.c index bb714189..86616b4c 100644 --- a/src/PJ_krovak.c +++ b/src/PJ_krovak.c @@ -66,7 +66,7 @@ struct pj_opaque { static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ XY xy = {0.0,0.0}; - struct pj_opaque *Q = P->opaque; + /* calculate xy from lat/lon */ /* Constants, identical to inverse transform function */ @@ -131,7 +131,7 @@ static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ LP lp = {0.0,0.0}; - struct pj_opaque *Q = P->opaque; + /* calculate lat/lon from xy */ /* Constants, identisch wie in der Umkehrfunktion */ @@ -227,6 +227,7 @@ static void freeup (PJ *P) { PJ *PROJECTION(krovak) { + double ts; struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); @@ -234,7 +235,7 @@ PJ *PROJECTION(krovak) { P->pfree = freeup; P->descr = des_krovak; - double ts; + /* read some Parameters, * here Latitude Truescale */ -- cgit v1.2.3 From e1924c9dd5d9732da86852bdc81c3f00f50afd59 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 27 Apr 2016 21:21:01 +0200 Subject: Converted labrd --- src/PJ_aea.c | 1 - src/PJ_labrd.c | 290 ++++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 185 insertions(+), 106 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 72091132..53a3d49c 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -362,7 +362,6 @@ int pj_geocent_selftest (void) {return 10000;} int pj_gs48_selftest (void) {return 10000;} int pj_gs50_selftest (void) {return 10000;} -int pj_labrd_selftest (void) {return 10000;} int pj_laea_selftest (void) {return 10000;} int pj_lagrng_selftest (void) {return 10000;} int pj_larr_selftest (void) {return 10000;} diff --git a/src/PJ_labrd.c b/src/PJ_labrd.c index 4cb39ec8..9c44e569 100644 --- a/src/PJ_labrd.c +++ b/src/PJ_labrd.c @@ -1,109 +1,189 @@ -#define PROJ_PARMS__ \ - double Az, kRg, p0s, A, C, Ca, Cb, Cc, Cd; \ - int rot; #define PJ_LIB__ -#include +#include + PROJ_HEAD(labrd, "Laborde") "\n\tCyl, Sph\n\tSpecial for Madagascar"; -#define EPS 1.e-10 -FORWARD(e_forward); - double V1, V2, ps, sinps, cosps, sinps2, cosps2, I1, I2, I3, I4, I5, I6, - x2, y2, t; - - V1 = P->A * log( tan(FORTPI + .5 * lp.phi) ); - t = P->e * sin(lp.phi); - V2 = .5 * P->e * P->A * log ((1. + t)/(1. - t)); - ps = 2. * (atan(exp(V1 - V2 + P->C)) - FORTPI); - I1 = ps - P->p0s; - cosps = cos(ps); cosps2 = cosps * cosps; - sinps = sin(ps); sinps2 = sinps * sinps; - I4 = P->A * cosps; - I2 = .5 * P->A * I4 * sinps; - I3 = I2 * P->A * P->A * (5. * cosps2 - sinps2) / 12.; - I6 = I4 * P->A * P->A; - I5 = I6 * (cosps2 - sinps2) / 6.; - I6 *= P->A * P->A * - (5. * cosps2 * cosps2 + sinps2 * (sinps2 - 18. * cosps2)) / 120.; - t = lp.lam * lp.lam; - xy.x = P->kRg * lp.lam * (I4 + t * (I5 + t * I6)); - xy.y = P->kRg * (I1 + t * (I2 + t * I3)); - x2 = xy.x * xy.x; - y2 = xy.y * xy.y; - V1 = 3. * xy.x * y2 - xy.x * x2; - V2 = xy.y * y2 - 3. * x2 * xy.y; - xy.x += P->Ca * V1 + P->Cb * V2; - xy.y += P->Ca * V2 - P->Cb * V1; - return (xy); +#define EPS 1.e-10 + +struct pj_opaque { + double kRg, p0s, A, C, Ca, Cb, Cc, Cd; \ + int rot; +}; + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double V1, V2, ps, sinps, cosps, sinps2, cosps2; + double I1, I2, I3, I4, I5, I6, x2, y2, t; + + V1 = Q->A * log( tan(FORTPI + .5 * lp.phi) ); + t = P->e * sin(lp.phi); + V2 = .5 * P->e * Q->A * log ((1. + t)/(1. - t)); + ps = 2. * (atan(exp(V1 - V2 + Q->C)) - FORTPI); + I1 = ps - Q->p0s; + cosps = cos(ps); cosps2 = cosps * cosps; + sinps = sin(ps); sinps2 = sinps * sinps; + I4 = Q->A * cosps; + I2 = .5 * Q->A * I4 * sinps; + I3 = I2 * Q->A * Q->A * (5. * cosps2 - sinps2) / 12.; + I6 = I4 * Q->A * Q->A; + I5 = I6 * (cosps2 - sinps2) / 6.; + I6 *= Q->A * Q->A * + (5. * cosps2 * cosps2 + sinps2 * (sinps2 - 18. * cosps2)) / 120.; + t = lp.lam * lp.lam; + xy.x = Q->kRg * lp.lam * (I4 + t * (I5 + t * I6)); + xy.y = Q->kRg * (I1 + t * (I2 + t * I3)); + x2 = xy.x * xy.x; + y2 = xy.y * xy.y; + V1 = 3. * xy.x * y2 - xy.x * x2; + V2 = xy.y * y2 - 3. * x2 * xy.y; + xy.x += Q->Ca * V1 + Q->Cb * V2; + xy.y += Q->Ca * V2 - Q->Cb * V1; + return xy; +} + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double x2, y2, V1, V2, V3, V4, t, t2, ps, pe, tpe, s; + double I7, I8, I9, I10, I11, d, Re; + int i; + + x2 = xy.x * xy.x; + y2 = xy.y * xy.y; + V1 = 3. * xy.x * y2 - xy.x * x2; + V2 = xy.y * y2 - 3. * x2 * xy.y; + V3 = xy.x * (5. * y2 * y2 + x2 * (-10. * y2 + x2 )); + V4 = xy.y * (5. * x2 * x2 + y2 * (-10. * x2 + y2 )); + xy.x += - Q->Ca * V1 - Q->Cb * V2 + Q->Cc * V3 + Q->Cd * V4; + xy.y += Q->Cb * V1 - Q->Ca * V2 - Q->Cd * V3 + Q->Cc * V4; + ps = Q->p0s + xy.y / Q->kRg; + pe = ps + P->phi0 - Q->p0s; + for ( i = 20; i; --i) { + V1 = Q->A * log(tan(FORTPI + .5 * pe)); + tpe = P->e * sin(pe); + V2 = .5 * P->e * Q->A * log((1. + tpe)/(1. - tpe)); + t = ps - 2. * (atan(exp(V1 - V2 + Q->C)) - FORTPI); + pe += t; + if (fabs(t) < EPS) + break; + } + + t = P->e * sin(pe); + t = 1. - t * t; + Re = P->one_es / ( t * sqrt(t) ); + t = tan(ps); + t2 = t * t; + s = Q->kRg * Q->kRg; + d = Re * P->k0 * Q->kRg; + I7 = t / (2. * d); + I8 = t * (5. + 3. * t2) / (24. * d * s); + d = cos(ps) * Q->kRg * Q->A; + I9 = 1. / d; + d *= s; + I10 = (1. + 2. * t2) / (6. * d); + I11 = (5. + t2 * (28. + 24. * t2)) / (120. * d * s); + x2 = xy.x * xy.x; + lp.phi = pe + x2 * (-I7 + I8 * x2); + lp.lam = xy.x * (I9 + x2 * (-I10 + x2 * I11)); + return lp; } -INVERSE(e_inverse); /* ellipsoid & spheroid */ - double x2, y2, V1, V2, V3, V4, t, t2, ps, pe, tpe, s, - I7, I8, I9, I10, I11, d, Re; - int i; - - x2 = xy.x * xy.x; - y2 = xy.y * xy.y; - V1 = 3. * xy.x * y2 - xy.x * x2; - V2 = xy.y * y2 - 3. * x2 * xy.y; - V3 = xy.x * (5. * y2 * y2 + x2 * (-10. * y2 + x2 )); - V4 = xy.y * (5. * x2 * x2 + y2 * (-10. * x2 + y2 )); - xy.x += - P->Ca * V1 - P->Cb * V2 + P->Cc * V3 + P->Cd * V4; - xy.y += P->Cb * V1 - P->Ca * V2 - P->Cd * V3 + P->Cc * V4; - ps = P->p0s + xy.y / P->kRg; - pe = ps + P->phi0 - P->p0s; - for ( i = 20; i; --i) { - V1 = P->A * log(tan(FORTPI + .5 * pe)); - tpe = P->e * sin(pe); - V2 = .5 * P->e * P->A * log((1. + tpe)/(1. - tpe)); - t = ps - 2. * (atan(exp(V1 - V2 + P->C)) - FORTPI); - pe += t; - if (fabs(t) < EPS) - break; - } -/* - if (!i) { - } else { - } -*/ - t = P->e * sin(pe); - t = 1. - t * t; - Re = P->one_es / ( t * sqrt(t) ); - t = tan(ps); - t2 = t * t; - s = P->kRg * P->kRg; - d = Re * P->k0 * P->kRg; - I7 = t / (2. * d); - I8 = t * (5. + 3. * t2) / (24. * d * s); - d = cos(ps) * P->kRg * P->A; - I9 = 1. / d; - d *= s; - I10 = (1. + 2. * t2) / (6. * d); - I11 = (5. + t2 * (28. + 24. * t2)) / (120. * d * s); - x2 = xy.x * xy.x; - lp.phi = pe + x2 * (-I7 + I8 * x2); - lp.lam = xy.x * (I9 + x2 * (-I10 + x2 * I11)); - return (lp); + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(labrd) - double Az, sinp, R, N, t; - - P->rot = pj_param(P->ctx, P->params, "bno_rot").i == 0; - Az = pj_param(P->ctx, P->params, "razi").f; - sinp = sin(P->phi0); - t = 1. - P->es * sinp * sinp; - N = 1. / sqrt(t); - R = P->one_es * N / t; - P->kRg = P->k0 * sqrt( N * R ); - P->p0s = atan( sqrt(R / N) * tan(P->phi0) ); - P->A = sinp / sin(P->p0s); - t = P->e * sinp; - P->C = .5 * P->e * P->A * log((1. + t)/(1. - t)) + - - P->A * log( tan(FORTPI + .5 * P->phi0)) - + log( tan(FORTPI + .5 * P->p0s)); - t = Az + Az; - P->Ca = (1. - cos(t)) * ( P->Cb = 1. / (12. * P->kRg * P->kRg) ); - P->Cb *= sin(t); - P->Cc = 3. * (P->Ca * P->Ca - P->Cb * P->Cb); - P->Cd = 6. * P->Ca * P->Cb; - P->inv = e_inverse; - P->fwd = e_forward; -ENDENTRY(P) + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(labrd) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_labrd; + double Az, sinp, R, N, t; + + Q->rot = pj_param(P->ctx, P->params, "bno_rot").i == 0; + Az = pj_param(P->ctx, P->params, "razi").f; + sinp = sin(P->phi0); + t = 1. - P->es * sinp * sinp; + N = 1. / sqrt(t); + R = P->one_es * N / t; + Q->kRg = P->k0 * sqrt( N * R ); + Q->p0s = atan( sqrt(R / N) * tan(P->phi0) ); + Q->A = sinp / sin(Q->p0s); + t = P->e * sinp; + Q->C = .5 * P->e * Q->A * log((1. + t)/(1. - t)) + + - Q->A * log( tan(FORTPI + .5 * P->phi0)) + + log( tan(FORTPI + .5 * Q->p0s)); + t = Az + Az; + Q->Ca = (1. - cos(t)) * ( Q->Cb = 1. / (12. * Q->kRg * Q->kRg) ); + Q->Cb *= sin(t); + Q->Cc = 3. * (Q->Ca * Q->Ca - Q->Cb * Q->Cb); + Q->Cd = 6. * Q->Ca * Q->Cb; + + P->inv = e_inverse; + P->fwd = e_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_labrd_selftest (void) {return 0;} +#else + +int pj_labrd_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=labrd +ellps=GRS80 +lon_0=0.5 +lat_0=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 166973.166090228391, -110536.912730266107}, + { 166973.168287157256, -331761.993650884193}, + {-278345.500519976194, -110469.032642031714}, + {-278345.504185269645, -331829.870790275279}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.501797719349373672, 2.00090435742047923}, + {0.501797717380853658, 1.99909564058898681}, + {0.498202280650626328, 2.00090435742047923}, + {0.498202282619146342, 1.99909564058898681}, + }; + + return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); +} + + +#endif -- cgit v1.2.3 From ba69dbac4355c92328de73edc0ac3cb1f1dd4a64 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 27 Apr 2016 22:08:46 +0200 Subject: Converted laea --- src/PJ_aea.c | 1 - src/PJ_laea.c | 555 ++++++++++++++++++++++++++++++++++------------------------ 2 files changed, 331 insertions(+), 225 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 53a3d49c..382116b2 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -362,7 +362,6 @@ int pj_geocent_selftest (void) {return 10000;} int pj_gs48_selftest (void) {return 10000;} int pj_gs50_selftest (void) {return 10000;} -int pj_laea_selftest (void) {return 10000;} int pj_lagrng_selftest (void) {return 10000;} int pj_larr_selftest (void) {return 10000;} int pj_lask_selftest (void) {return 10000;} diff --git a/src/PJ_laea.c b/src/PJ_laea.c index 445e39c3..b58b07e2 100644 --- a/src/PJ_laea.c +++ b/src/PJ_laea.c @@ -1,233 +1,340 @@ -#define PROJ_PARMS__ \ - double sinb1; \ - double cosb1; \ - double xmf; \ - double ymf; \ - double mmf; \ - double qp; \ - double dd; \ - double rq; \ - double *apa; \ - int mode; #define PJ_LIB__ -#include +#include + PROJ_HEAD(laea, "Lambert Azimuthal Equal Area") "\n\tAzi, Sph&Ell"; -#define sinph0 P->sinb1 -#define cosph0 P->cosb1 -#define EPS10 1.e-10 -#define NITER 20 -#define CONV 1.e-10 -#define N_POLE 0 -#define S_POLE 1 -#define EQUIT 2 -#define OBLIQ 3 -FORWARD(e_forward); /* ellipsoid */ - double coslam, sinlam, sinphi, q, sinb=0.0, cosb=0.0, b=0.0; - - coslam = cos(lp.lam); - sinlam = sin(lp.lam); - sinphi = sin(lp.phi); - q = pj_qsfn(sinphi, P->e, P->one_es); - if (P->mode == OBLIQ || P->mode == EQUIT) { - sinb = q / P->qp; - cosb = sqrt(1. - sinb * sinb); - } - switch (P->mode) { - case OBLIQ: - b = 1. + P->sinb1 * sinb + P->cosb1 * cosb * coslam; - break; - case EQUIT: - b = 1. + cosb * coslam; - break; - case N_POLE: - b = HALFPI + lp.phi; - q = P->qp - q; - break; - case S_POLE: - b = lp.phi - HALFPI; - q = P->qp + q; - break; - } - if (fabs(b) < EPS10) F_ERROR; - switch (P->mode) { - case OBLIQ: - xy.y = P->ymf * ( b = sqrt(2. / b) ) - * (P->cosb1 * sinb - P->sinb1 * cosb * coslam); - goto eqcon; - break; - case EQUIT: - xy.y = (b = sqrt(2. / (1. + cosb * coslam))) * sinb * P->ymf; + +struct pj_opaque { + double sinb1; + double cosb1; + double xmf; + double ymf; + double mmf; + double qp; + double dd; + double rq; + double *apa; + int mode; +}; + +#define EPS10 1.e-10 +#define NITER 20 +#define CONV 1.e-10 +#define N_POLE 0 +#define S_POLE 1 +#define EQUIT 2 +#define OBLIQ 3 + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double coslam, sinlam, sinphi, q, sinb=0.0, cosb=0.0, b=0.0; + + coslam = cos(lp.lam); + sinlam = sin(lp.lam); + sinphi = sin(lp.phi); + q = pj_qsfn(sinphi, P->e, P->one_es); + + if (Q->mode == OBLIQ || Q->mode == EQUIT) { + sinb = q / Q->qp; + cosb = sqrt(1. - sinb * sinb); + } + + switch (Q->mode) { + case OBLIQ: + b = 1. + Q->sinb1 * sinb + Q->cosb1 * cosb * coslam; + break; + case EQUIT: + b = 1. + cosb * coslam; + break; + case N_POLE: + b = HALFPI + lp.phi; + q = Q->qp - q; + break; + case S_POLE: + b = lp.phi - HALFPI; + q = Q->qp + q; + break; + } + if (fabs(b) < EPS10) F_ERROR; + + switch (Q->mode) { + case OBLIQ: + b = sqrt(2. / b); + xy.y = Q->ymf * b * (Q->cosb1 * sinb - Q->sinb1 * cosb * coslam); + goto eqcon; + break; + case EQUIT: + b = sqrt(2. / (1. + cosb * coslam)); + xy.y = b * sinb * Q->ymf; eqcon: - xy.x = P->xmf * b * cosb * sinlam; - break; - case N_POLE: - case S_POLE: - if (q >= 0.) { - xy.x = (b = sqrt(q)) * sinlam; - xy.y = coslam * (P->mode == S_POLE ? b : -b); - } else - xy.x = xy.y = 0.; - break; - } - return (xy); + xy.x = Q->xmf * b * cosb * sinlam; + break; + case N_POLE: + case S_POLE: + if (q >= 0.) { + b = sqrt(q); + xy.x = b * sinlam; + xy.y = coslam * (Q->mode == S_POLE ? b : -b); + } else + xy.x = xy.y = 0.; + break; + } + return xy; } -FORWARD(s_forward); /* spheroid */ - double coslam, cosphi, sinphi; - - sinphi = sin(lp.phi); - cosphi = cos(lp.phi); - coslam = cos(lp.lam); - switch (P->mode) { - case EQUIT: - xy.y = 1. + cosphi * coslam; - goto oblcon; - case OBLIQ: - xy.y = 1. + sinph0 * sinphi + cosph0 * cosphi * coslam; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double coslam, cosphi, sinphi; + + sinphi = sin(lp.phi); + cosphi = cos(lp.phi); + coslam = cos(lp.lam); + switch (Q->mode) { + case EQUIT: + xy.y = 1. + cosphi * coslam; + goto oblcon; + case OBLIQ: + xy.y = 1. + Q->sinb1 * sinphi + Q->cosb1 * cosphi * coslam; oblcon: - if (xy.y <= EPS10) F_ERROR; - xy.x = (xy.y = sqrt(2. / xy.y)) * cosphi * sin(lp.lam); - xy.y *= P->mode == EQUIT ? sinphi : - cosph0 * sinphi - sinph0 * cosphi * coslam; - break; - case N_POLE: - coslam = -coslam; - case S_POLE: - if (fabs(lp.phi + P->phi0) < EPS10) F_ERROR; - xy.y = FORTPI - lp.phi * .5; - xy.y = 2. * (P->mode == S_POLE ? cos(xy.y) : sin(xy.y)); - xy.x = xy.y * sin(lp.lam); - xy.y *= coslam; - break; - } - return (xy); + if (xy.y <= EPS10) F_ERROR; + xy.y = sqrt(2. / xy.y); + xy.x = xy.y * cosphi * sin(lp.lam); + xy.y *= Q->mode == EQUIT ? sinphi : + Q->cosb1 * sinphi - Q->sinb1 * cosphi * coslam; + break; + case N_POLE: + coslam = -coslam; + case S_POLE: + if (fabs(lp.phi + P->phi0) < EPS10) F_ERROR; + xy.y = FORTPI - lp.phi * .5; + xy.y = 2. * (Q->mode == S_POLE ? cos(xy.y) : sin(xy.y)); + xy.x = xy.y * sin(lp.lam); + xy.y *= coslam; + break; + } + return xy; +} + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double cCe, sCe, q, rho, ab=0.0; + + switch (Q->mode) { + case EQUIT: + case OBLIQ: + xy.x /= Q->dd; + xy.y *= Q->dd; + rho = hypot(xy.x, xy.y); + if (rho < EPS10) { + lp.lam = 0.; + lp.phi = P->phi0; + return lp; + } + sCe = 2. * asin(.5 * rho / Q->rq); + cCe = cos(sCe); + sCe = sin(sCe); + xy.x *= sCe; + if (Q->mode == OBLIQ) { + ab = cCe * Q->sinb1 + xy.y * sCe * Q->cosb1 / rho; + xy.y = rho * Q->cosb1 * cCe - xy.y * Q->sinb1 * sCe; + } else { + ab = xy.y * sCe / rho; + xy.y = rho * cCe; + } + break; + case N_POLE: + xy.y = -xy.y; + case S_POLE: + q = (xy.x * xy.x + xy.y * xy.y); + if (!q) { + lp.lam = 0.; + lp.phi = P->phi0; + return (lp); + } + ab = 1. - q / Q->qp; + if (Q->mode == S_POLE) + ab = - ab; + break; + } + lp.lam = atan2(xy.x, xy.y); + lp.phi = pj_authlat(asin(ab), Q->apa); + return lp; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double cosz=0.0, rh, sinz=0.0; + + rh = hypot(xy.x, xy.y); + if ((lp.phi = rh * .5 ) > 1.) I_ERROR; + lp.phi = 2. * asin(lp.phi); + if (Q->mode == OBLIQ || Q->mode == EQUIT) { + sinz = sin(lp.phi); + cosz = cos(lp.phi); + } + switch (Q->mode) { + case EQUIT: + lp.phi = fabs(rh) <= EPS10 ? 0. : asin(xy.y * sinz / rh); + xy.x *= sinz; + xy.y = cosz * rh; + break; + case OBLIQ: + lp.phi = fabs(rh) <= EPS10 ? P->phi0 : + asin(cosz * Q->sinb1 + xy.y * sinz * Q->cosb1 / rh); + xy.x *= sinz * Q->cosb1; + xy.y = (cosz - sin(lp.phi) * Q->sinb1) * rh; + break; + case N_POLE: + xy.y = -xy.y; + lp.phi = HALFPI - lp.phi; + break; + case S_POLE: + lp.phi -= HALFPI; + break; + } + lp.lam = (xy.y == 0. && (Q->mode == EQUIT || Q->mode == OBLIQ)) ? + 0. : atan2(xy.x, xy.y); + return (lp); +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque->apa); + pj_dealloc (P->opaque); + return pj_dealloc(P); } -INVERSE(e_inverse); /* ellipsoid */ - double cCe, sCe, q, rho, ab=0.0; - - switch (P->mode) { - case EQUIT: - case OBLIQ: - if ((rho = hypot(xy.x /= P->dd, xy.y *= P->dd)) < EPS10) { - lp.lam = 0.; - lp.phi = P->phi0; - return (lp); - } - cCe = cos(sCe = 2. * asin(.5 * rho / P->rq)); - xy.x *= (sCe = sin(sCe)); - if (P->mode == OBLIQ) { - ab = cCe * P->sinb1 + xy.y * sCe * P->cosb1 / rho; - xy.y = rho * P->cosb1 * cCe - xy.y * P->sinb1 * sCe; - } else { - ab = xy.y * sCe / rho; - xy.y = rho * cCe; - } - break; - case N_POLE: - xy.y = -xy.y; - case S_POLE: - if (!(q = (xy.x * xy.x + xy.y * xy.y)) ) { - lp.lam = 0.; - lp.phi = P->phi0; - return (lp); - } - /* - q = P->qp - q; - */ - ab = 1. - q / P->qp; - if (P->mode == S_POLE) - ab = - ab; - break; - } - lp.lam = atan2(xy.x, xy.y); - lp.phi = pj_authlat(asin(ab), P->apa); - return (lp); + +static void freeup (PJ *P) { + freeup_new (P); + return; } -INVERSE(s_inverse); /* spheroid */ - double cosz=0.0, rh, sinz=0.0; - - rh = hypot(xy.x, xy.y); - if ((lp.phi = rh * .5 ) > 1.) I_ERROR; - lp.phi = 2. * asin(lp.phi); - if (P->mode == OBLIQ || P->mode == EQUIT) { - sinz = sin(lp.phi); - cosz = cos(lp.phi); - } - switch (P->mode) { - case EQUIT: - lp.phi = fabs(rh) <= EPS10 ? 0. : asin(xy.y * sinz / rh); - xy.x *= sinz; - xy.y = cosz * rh; - break; - case OBLIQ: - lp.phi = fabs(rh) <= EPS10 ? P->phi0 : - asin(cosz * sinph0 + xy.y * sinz * cosph0 / rh); - xy.x *= sinz * cosph0; - xy.y = (cosz - sin(lp.phi) * sinph0) * rh; - break; - case N_POLE: - xy.y = -xy.y; - lp.phi = HALFPI - lp.phi; - break; - case S_POLE: - lp.phi -= HALFPI; - break; - } - lp.lam = (xy.y == 0. && (P->mode == EQUIT || P->mode == OBLIQ)) ? - 0. : atan2(xy.x, xy.y); - return (lp); + + +PJ *PROJECTION(laea) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_laea; + double t; + t = fabs(P->phi0); + if (fabs(t - HALFPI) < EPS10) + Q->mode = P->phi0 < 0. ? S_POLE : N_POLE; + else if (fabs(t) < EPS10) + Q->mode = EQUIT; + else + Q->mode = OBLIQ; + if (P->es) { + double sinphi; + + P->e = sqrt(P->es); + Q->qp = pj_qsfn(1., P->e, P->one_es); + Q->mmf = .5 / (1. - P->es); + Q->apa = pj_authset(P->es); + switch (Q->mode) { + case N_POLE: + case S_POLE: + Q->dd = 1.; + break; + case EQUIT: + Q->dd = 1. / (Q->rq = sqrt(.5 * Q->qp)); + Q->xmf = 1.; + Q->ymf = .5 * Q->qp; + break; + case OBLIQ: + Q->rq = sqrt(.5 * Q->qp); + sinphi = sin(P->phi0); + Q->sinb1 = pj_qsfn(sinphi, P->e, P->one_es) / Q->qp; + Q->cosb1 = sqrt(1. - Q->sinb1 * Q->sinb1); + Q->dd = cos(P->phi0) / (sqrt(1. - P->es * sinphi * sinphi) * + Q->rq * Q->cosb1); + Q->ymf = (Q->xmf = Q->rq) / Q->dd; + Q->xmf *= Q->dd; + break; + } + P->inv = e_inverse; + P->fwd = e_forward; + } else { + if (Q->mode == OBLIQ) { + Q->sinb1 = sin(P->phi0); + Q->cosb1 = cos(P->phi0); + } + P->inv = s_inverse; + P->fwd = s_forward; + } + + return P; } -FREEUP; - if (P) { - if (P->apa) - pj_dalloc(P->apa); - pj_dalloc(P); - } + + +#ifdef PJ_OMIT_SELFTEST +int pj_laea_selftest (void) {return 0;} +#else + +int pj_laea_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=laea +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=laea +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222602.471450095181, 110589.82722441027}, + { 222602.471450095181, -110589.827224408786}, + {-222602.471450095181, 110589.82722441027}, + {-222602.471450095181, -110589.827224408786}, + }; + + XY s_fwd_expect[] = { + { 223365.281370124663, 111716.668072915665}, + { 223365.281370124663, -111716.668072915665}, + {-223365.281370124663, 111716.668072915665}, + {-223365.281370124663, -111716.668072915665}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.00179663056847900867, 0.000904369475966495845}, + { 0.00179663056847900867, -0.000904369475966495845}, + {-0.00179663056847900867, 0.000904369475966495845}, + {-0.00179663056847900867, -0.000904369475966495845}, + }; + + LP s_inv_expect[] = { + { 0.00179049311002060264, 0.000895246554791735271}, + { 0.00179049311002060264, -0.000895246554791735271}, + {-0.00179049311002060264, 0.000895246554791735271}, + {-0.00179049311002060264, -0.000895246554791735271}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); } -ENTRY1(laea,apa) - double t; - - if (fabs((t = fabs(P->phi0)) - HALFPI) < EPS10) - P->mode = P->phi0 < 0. ? S_POLE : N_POLE; - else if (fabs(t) < EPS10) - P->mode = EQUIT; - else - P->mode = OBLIQ; - if (P->es) { - double sinphi; - - P->e = sqrt(P->es); - P->qp = pj_qsfn(1., P->e, P->one_es); - P->mmf = .5 / (1. - P->es); - P->apa = pj_authset(P->es); - switch (P->mode) { - case N_POLE: - case S_POLE: - P->dd = 1.; - break; - case EQUIT: - P->dd = 1. / (P->rq = sqrt(.5 * P->qp)); - P->xmf = 1.; - P->ymf = .5 * P->qp; - break; - case OBLIQ: - P->rq = sqrt(.5 * P->qp); - sinphi = sin(P->phi0); - P->sinb1 = pj_qsfn(sinphi, P->e, P->one_es) / P->qp; - P->cosb1 = sqrt(1. - P->sinb1 * P->sinb1); - P->dd = cos(P->phi0) / (sqrt(1. - P->es * sinphi * sinphi) * - P->rq * P->cosb1); - P->ymf = (P->xmf = P->rq) / P->dd; - P->xmf *= P->dd; - break; - } - P->inv = e_inverse; - P->fwd = e_forward; - } else { - if (P->mode == OBLIQ) { - sinph0 = sin(P->phi0); - cosph0 = cos(P->phi0); - } - P->inv = s_inverse; - P->fwd = s_forward; - } -ENDENTRY(P) + + +#endif -- cgit v1.2.3 From f4b7823cb88c9f49d6f8eea74418f7661c950806 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 27 Apr 2016 22:19:10 +0200 Subject: Forgot to remove P->free and P->descr assignments --- src/PJ_labrd.c | 3 --- src/PJ_laea.c | 4 +--- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'src') diff --git a/src/PJ_labrd.c b/src/PJ_labrd.c index 9c44e569..e7bca390 100644 --- a/src/PJ_labrd.c +++ b/src/PJ_labrd.c @@ -113,9 +113,6 @@ PJ *PROJECTION(labrd) { if (0==Q) return freeup_new (P); P->opaque = Q; - - P->pfree = freeup; - P->descr = des_labrd; double Az, sinp, R, N, t; Q->rot = pj_param(P->ctx, P->params, "bno_rot").i == 0; diff --git a/src/PJ_laea.c b/src/PJ_laea.c index b58b07e2..02b281a4 100644 --- a/src/PJ_laea.c +++ b/src/PJ_laea.c @@ -226,10 +226,8 @@ PJ *PROJECTION(laea) { if (0==Q) return freeup_new (P); P->opaque = Q; - - P->pfree = freeup; - P->descr = des_laea; double t; + t = fabs(P->phi0); if (fabs(t - HALFPI) < EPS10) Q->mode = P->phi0 < 0. ? S_POLE : N_POLE; -- cgit v1.2.3 From 59e147128033c6c2d859b948af7859e13e0f1bc1 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 27 Apr 2016 22:29:54 +0200 Subject: Converted lagrng --- src/PJ_aea.c | 1 - src/PJ_lagrng.c | 132 ++++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 100 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 382116b2..fb9cc1d0 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -362,7 +362,6 @@ int pj_geocent_selftest (void) {return 10000;} int pj_gs48_selftest (void) {return 10000;} int pj_gs50_selftest (void) {return 10000;} -int pj_lagrng_selftest (void) {return 10000;} int pj_larr_selftest (void) {return 10000;} int pj_lask_selftest (void) {return 10000;} int pj_latlon_selftest (void) {return 10000;} diff --git a/src/PJ_lagrng.c b/src/PJ_lagrng.c index 8a13b3da..9a018808 100644 --- a/src/PJ_lagrng.c +++ b/src/PJ_lagrng.c @@ -1,35 +1,103 @@ -#define PROJ_PARMS__ \ - double hrw; \ - double rw; \ - double a1; -#define TOL 1e-10 #define PJ_LIB__ -#include +#include + PROJ_HEAD(lagrng, "Lagrange") "\n\tMisc Sph, no inv.\n\tW="; -FORWARD(s_forward); /* spheroid */ - double v, c; - - if (fabs(fabs(lp.phi) - HALFPI) < TOL) { - xy.x = 0; - xy.y = lp.phi < 0 ? -2. : 2.; - } else { - lp.phi = sin(lp.phi); - v = P->a1 * pow((1. + lp.phi)/(1. - lp.phi), P->hrw); - if ((c = 0.5 * (v + 1./v) + cos(lp.lam *= P->rw)) < TOL) - F_ERROR; - xy.x = 2. * sin(lp.lam) / c; - xy.y = (v - 1./v) / c; - } - return (xy); + +#define TOL 1e-10 + +struct pj_opaque { + double a1; + double hrw; + double rw; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double v, c; + + if (fabs(fabs(lp.phi) - HALFPI) < TOL) { + xy.x = 0; + xy.y = lp.phi < 0 ? -2. : 2.; + } else { + lp.phi = sin(lp.phi); + v = Q->a1 * pow((1. + lp.phi)/(1. - lp.phi), Q->hrw); + if ((c = 0.5 * (v + 1./v) + cos(lp.lam *= Q->rw)) < TOL) + F_ERROR; + xy.x = 2. * sin(lp.lam) / c; + xy.y = (v - 1./v) / c; + } + return xy; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(lagrng) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + double phi1; + + Q->rw = pj_param(P->ctx, P->params, "dW").f; + if (Q->rw <= 0) E_ERROR(-27); + + Q->rw = 1. / Q->rw; + Q->hrw = 0.5 * Q->rw; + phi1 = sin(pj_param(P->ctx, P->params, "rlat_1").f); + if (fabs(fabs(phi1) - 1.) < TOL) E_ERROR(-22); + + Q->a1 = pow((1. - phi1)/(1. + phi1), Q->hrw); + + P->es = 0.; + P->fwd = s_forward; + + return P; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(lagrng) - double phi1; - - if ((P->rw = pj_param(P->ctx, P->params, "dW").f) <= 0) E_ERROR(-27); - P->hrw = 0.5 * (P->rw = 1. / P->rw); - phi1 = pj_param(P->ctx, P->params, "rlat_1").f; - if (fabs(fabs(phi1 = sin(phi1)) - 1.) < TOL) E_ERROR(-22); - P->a1 = pow((1. - phi1)/(1. + phi1), P->hrw); - P->es = 0.; P->fwd = s_forward; -ENDENTRY(P) + + +#ifdef PJ_OMIT_SELFTEST +int pj_lagrng_selftest (void) {return 0;} +#else + +int pj_lagrng_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=lagrng +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 111703.37591722561, 27929.8319080333386}, + { 111699.122088816002, -83784.1780133577704}, + {-111703.37591722561, 27929.8319080333386}, + {-111699.122088816002, -83784.1780133577704}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} + + +#endif -- cgit v1.2.3 From b9cb845c8f9e552406bc28207211e32937487905 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 27 Apr 2016 23:06:12 +0200 Subject: Converted larr --- src/PJ_aea.c | 1 - src/PJ_larr.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 67 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index fb9cc1d0..7e68de93 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -362,7 +362,6 @@ int pj_geocent_selftest (void) {return 10000;} int pj_gs48_selftest (void) {return 10000;} int pj_gs50_selftest (void) {return 10000;} -int pj_larr_selftest (void) {return 10000;} int pj_lask_selftest (void) {return 10000;} int pj_latlon_selftest (void) {return 10000;} int pj_latlong_selftest (void) {return 10000;} diff --git a/src/PJ_larr.c b/src/PJ_larr.c index 118bef00..f55289b1 100644 --- a/src/PJ_larr.c +++ b/src/PJ_larr.c @@ -1,13 +1,70 @@ -#define PROJ_PARMS__ #define PJ_LIB__ -#include +#include + PROJ_HEAD(larr, "Larrivee") "\n\tMisc Sph, no inv."; + #define SIXTH .16666666666666666 -FORWARD(s_forward); /* sphere */ - (void) P; - xy.x = 0.5 * lp.lam * (1. + sqrt(cos(lp.phi))); - xy.y = lp.phi / (cos(0.5 * lp.phi) * cos(SIXTH * lp.lam)); - return (xy); -} -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(larr) P->fwd = s_forward; P->inv = 0; P->es = 0.; ENDENTRY(P) + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + (void) P; + + xy.x = 0.5 * lp.lam * (1. + sqrt(cos(lp.phi))); + xy.y = lp.phi / (cos(0.5 * lp.phi) * cos(SIXTH * lp.lam)); + return xy; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(larr) { + + P->es = 0; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_larr_selftest (void) {return 0;} +#else + +int pj_larr_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=larr +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {223393.637624200899, 111707.215961255497}, + {223393.637624200899, -111707.215961255497}, + {-223393.637624200899, 111707.215961255497}, + {-223393.637624200899, -111707.215961255497}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} + + +#endif -- cgit v1.2.3 From e1915ab381bc4e731178f457e56695d5f08004cb Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 27 Apr 2016 23:11:35 +0200 Subject: Converted lask --- src/PJ_aea.c | 1 - src/PJ_lask.c | 102 ++++++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 78 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 7e68de93..ddcb401e 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -362,7 +362,6 @@ int pj_geocent_selftest (void) {return 10000;} int pj_gs48_selftest (void) {return 10000;} int pj_gs50_selftest (void) {return 10000;} -int pj_lask_selftest (void) {return 10000;} int pj_latlon_selftest (void) {return 10000;} int pj_latlong_selftest (void) {return 10000;} int pj_lonlat_selftest (void) {return 10000;} diff --git a/src/PJ_lask.c b/src/PJ_lask.c index 797b580d..38e7045c 100644 --- a/src/PJ_lask.c +++ b/src/PJ_lask.c @@ -1,27 +1,81 @@ -#define PROJ_PARMS__ #define PJ_LIB__ -#include +#include + PROJ_HEAD(lask, "Laskowski") "\n\tMisc Sph, no inv."; -#define a10 0.975534 -#define a12 -0.119161 -#define a32 -0.0143059 -#define a14 -0.0547009 -#define b01 1.00384 -#define b21 0.0802894 -#define b03 0.0998909 -#define b41 0.000199025 -#define b23 -0.0285500 -#define b05 -0.0491032 -FORWARD(s_forward); /* sphere */ - double l2, p2; - (void) P; - - l2 = lp.lam * lp.lam; - p2 = lp.phi * lp.phi; - xy.x = lp.lam * (a10 + p2 * (a12 + l2 * a32 + p2 * a14)); - xy.y = lp.phi * (b01 + l2 * (b21 + p2 * b23 + l2 * b41) + - p2 * (b03 + p2 * b05)); - return (xy); + +#define a10 0.975534 +#define a12 -0.119161 +#define a32 -0.0143059 +#define a14 -0.0547009 +#define b01 1.00384 +#define b21 0.0802894 +#define b03 0.0998909 +#define b41 0.000199025 +#define b23 -0.0285500 +#define b05 -0.0491032 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + double l2, p2; + (void) P; + + l2 = lp.lam * lp.lam; + p2 = lp.phi * lp.phi; + xy.x = lp.lam * (a10 + p2 * (a12 + l2 * a32 + p2 * a14)); + xy.y = lp.phi * (b01 + l2 * (b21 + p2 * b23 + l2 * b41) + + p2 * (b03 + p2 * b05)); + return xy; +} + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(lask) { + + P->fwd = s_forward; + P->es = 0.; + + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_lask_selftest (void) {return 0;} +#else + +int pj_lask_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=lask +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 217928.275907355128, 112144.32922014239}, + { 217928.275907355128, -112144.32922014239}, + {-217928.275907355128, 112144.32922014239}, + {-217928.275907355128, -112144.32922014239}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(lask) P->fwd = s_forward; P->inv = 0; P->es = 0.; ENDENTRY(P) + + +#endif -- cgit v1.2.3 From b04e68b6e4bc2f111ab0c6b1e2828747140e10e8 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 27 Apr 2016 23:32:46 +0200 Subject: Converted lcc --- src/PJ_aea.c | 1 - src/PJ_lcc.c | 288 +++++++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 189 insertions(+), 100 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index ddcb401e..fb26487c 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -366,7 +366,6 @@ int pj_latlon_selftest (void) {return 10000;} int pj_latlong_selftest (void) {return 10000;} int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} -int pj_lcc_selftest (void) {return 10000;} int pj_lcca_selftest (void) {return 10000;} int pj_lee_os_selftest (void) {return 10000;} diff --git a/src/PJ_lcc.c b/src/PJ_lcc.c index 9d3494bf..3a5d3485 100644 --- a/src/PJ_lcc.c +++ b/src/PJ_lcc.c @@ -1,105 +1,195 @@ -#define PROJ_PARMS__ \ - double phi1; \ - double phi2; \ - double n; \ - double rho0; \ - double c; \ - int ellips; #define PJ_LIB__ -#include +#include + PROJ_HEAD(lcc, "Lambert Conformal Conic") - "\n\tConic, Sph&Ell\n\tlat_1= and lat_2= or lat_0"; -# define EPS10 1.e-10 -FORWARD(e_forward); /* ellipsoid & spheroid */ - double rho; - if (fabs(fabs(lp.phi) - HALFPI) < EPS10) { - if ((lp.phi * P->n) <= 0.) F_ERROR; - rho = 0.; - } - else - rho = P->c * (P->ellips ? pow(pj_tsfn(lp.phi, sin(lp.phi), - P->e), P->n) : pow(tan(FORTPI + .5 * lp.phi), -P->n)); - xy.x = P->k0 * (rho * sin( lp.lam *= P->n ) ); - xy.y = P->k0 * (P->rho0 - rho * cos(lp.lam) ); - return (xy); + "\n\tConic, Sph&Ell\n\tlat_1= and lat_2= or lat_0"; + +# define EPS10 1.e-10 + +struct pj_opaque { + double phi1; + double phi2; + double n; + double rho0; + double c; + int ellips; +}; + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double rho; + + if (fabs(fabs(lp.phi) - HALFPI) < EPS10) { + if ((lp.phi * Q->n) <= 0.) F_ERROR; + rho = 0.; + } else { + rho = Q->c * (Q->ellips ? pow(pj_tsfn(lp.phi, sin(lp.phi), + P->e), Q->n) : pow(tan(FORTPI + .5 * lp.phi), -Q->n)); + } + lp.lam *= Q->n; + xy.x = P->k0 * (rho * sin( lp.lam) ); + xy.y = P->k0 * (Q->rho0 - rho * cos(lp.lam) ); + return xy; } -INVERSE(e_inverse); /* ellipsoid & spheroid */ - double rho; - xy.x /= P->k0; - xy.y /= P->k0; - if( (rho = hypot(xy.x, xy.y = P->rho0 - xy.y)) != 0.0) { - if (P->n < 0.) { - rho = -rho; - xy.x = -xy.x; - xy.y = -xy.y; - } - if (P->ellips) { - if ((lp.phi = pj_phi2(P->ctx, pow(rho / P->c, 1./P->n), P->e)) - == HUGE_VAL) - I_ERROR; - } else - lp.phi = 2. * atan(pow(P->c / rho, 1./P->n)) - HALFPI; - lp.lam = atan2(xy.x, xy.y) / P->n; - } else { - lp.lam = 0.; - lp.phi = P->n > 0. ? HALFPI : - HALFPI; - } - return (lp); + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double rho; + + xy.x /= P->k0; + xy.y /= P->k0; + + xy.y = Q->rho0 - xy.y; + rho = hypot(xy.x, xy.y); + if (rho != 0.0) { + if (Q->n < 0.) { + rho = -rho; + xy.x = -xy.x; + xy.y = -xy.y; + } + if (Q->ellips) { + lp.phi = pj_phi2(P->ctx, pow(rho / Q->c, 1./Q->n), P->e); + if (lp.phi == HUGE_VAL) + I_ERROR; + } else + lp.phi = 2. * atan(pow(Q->c / rho, 1./Q->n)) - HALFPI; + lp.lam = atan2(xy.x, xy.y) / Q->n; + } else { + lp.lam = 0.; + lp.phi = Q->n > 0. ? HALFPI : - HALFPI; + } + return lp; } + SPECIAL(fac) { - double rho; - if (fabs(fabs(lp.phi) - HALFPI) < EPS10) { - if ((lp.phi * P->n) <= 0.) return; - rho = 0.; - } else - rho = P->c * (P->ellips ? pow(pj_tsfn(lp.phi, sin(lp.phi), - P->e), P->n) : pow(tan(FORTPI + .5 * lp.phi), -P->n)); - fac->code |= IS_ANAL_HK + IS_ANAL_CONV; - fac->k = fac->h = P->k0 * P->n * rho / - pj_msfn(sin(lp.phi), cos(lp.phi), P->es); - fac->conv = - P->n * lp.lam; + struct pj_opaque *Q = P->opaque; + double rho; + if (fabs(fabs(lp.phi) - HALFPI) < EPS10) { + if ((lp.phi * Q->n) <= 0.) return; + rho = 0.; + } else + rho = Q->c * (Q->ellips ? pow(pj_tsfn(lp.phi, sin(lp.phi), + P->e), Q->n) : pow(tan(FORTPI + .5 * lp.phi), -Q->n)); + fac->code |= IS_ANAL_HK + IS_ANAL_CONV; + fac->k = fac->h = P->k0 * Q->n * rho / + pj_msfn(sin(lp.phi), cos(lp.phi), P->es); + fac->conv = - Q->n * lp.lam; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(lcc) - double cosphi, sinphi; - int secant; - - P->phi1 = pj_param(P->ctx, P->params, "rlat_1").f; - if (pj_param(P->ctx, P->params, "tlat_2").i) - P->phi2 = pj_param(P->ctx, P->params, "rlat_2").f; - else { - P->phi2 = P->phi1; - if (!pj_param(P->ctx, P->params, "tlat_0").i) - P->phi0 = P->phi1; - } - if (fabs(P->phi1 + P->phi2) < EPS10) E_ERROR(-21); - P->n = sinphi = sin(P->phi1); - cosphi = cos(P->phi1); - secant = fabs(P->phi1 - P->phi2) >= EPS10; - if( (P->ellips = (P->es != 0.)) ) { - double ml1, m1; - - P->e = sqrt(P->es); - m1 = pj_msfn(sinphi, cosphi, P->es); - ml1 = pj_tsfn(P->phi1, sinphi, P->e); - if (secant) { /* secant cone */ - P->n = log(m1 / - pj_msfn(sinphi = sin(P->phi2), cos(P->phi2), P->es)); - P->n /= log(ml1 / pj_tsfn(P->phi2, sinphi, P->e)); - } - P->c = (P->rho0 = m1 * pow(ml1, -P->n) / P->n); - P->rho0 *= (fabs(fabs(P->phi0) - HALFPI) < EPS10) ? 0. : - pow(pj_tsfn(P->phi0, sin(P->phi0), P->e), P->n); - } else { - if (secant) - P->n = log(cosphi / cos(P->phi2)) / - log(tan(FORTPI + .5 * P->phi2) / - tan(FORTPI + .5 * P->phi1)); - P->c = cosphi * pow(tan(FORTPI + .5 * P->phi1), P->n) / P->n; - P->rho0 = (fabs(fabs(P->phi0) - HALFPI) < EPS10) ? 0. : - P->c * pow(tan(FORTPI + .5 * P->phi0), -P->n); - } - P->inv = e_inverse; - P->fwd = e_forward; - P->spc = fac; -ENDENTRY(P) + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(lcc) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + double cosphi, sinphi; + int secant; + + Q->phi1 = pj_param(P->ctx, P->params, "rlat_1").f; + if (pj_param(P->ctx, P->params, "tlat_2").i) + Q->phi2 = pj_param(P->ctx, P->params, "rlat_2").f; + else { + Q->phi2 = Q->phi1; + if (!pj_param(P->ctx, P->params, "tlat_0").i) + P->phi0 = Q->phi1; + } + if (fabs(Q->phi1 + Q->phi2) < EPS10) E_ERROR(-21); + Q->n = sinphi = sin(Q->phi1); + cosphi = cos(Q->phi1); + secant = fabs(Q->phi1 - Q->phi2) >= EPS10; + if( (Q->ellips = (P->es != 0.)) ) { + double ml1, m1; + + P->e = sqrt(P->es); + m1 = pj_msfn(sinphi, cosphi, P->es); + ml1 = pj_tsfn(Q->phi1, sinphi, P->e); + if (secant) { /* secant cone */ + sinphi = sin(Q->phi2); + Q->n = log(m1 / pj_msfn(sinphi, cos(Q->phi2), P->es)); + Q->n /= log(ml1 / pj_tsfn(Q->phi2, sinphi, P->e)); + } + Q->c = (Q->rho0 = m1 * pow(ml1, -Q->n) / Q->n); + Q->rho0 *= (fabs(fabs(P->phi0) - HALFPI) < EPS10) ? 0. : + pow(pj_tsfn(P->phi0, sin(P->phi0), P->e), Q->n); + } else { + if (secant) + Q->n = log(cosphi / cos(Q->phi2)) / + log(tan(FORTPI + .5 * Q->phi2) / + tan(FORTPI + .5 * Q->phi1)); + Q->c = cosphi * pow(tan(FORTPI + .5 * Q->phi1), Q->n) / Q->n; + Q->rho0 = (fabs(fabs(P->phi0) - HALFPI) < EPS10) ? 0. : + Q->c * pow(tan(FORTPI + .5 * P->phi0), -Q->n); + } + + P->inv = e_inverse; + P->fwd = e_forward; + P->spc = fac; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_lcc_selftest (void) {return 0;} +#else + +int pj_lcc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=lcc +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222588.439735968423, 110660.533870799671}, + { 222756.879700278747, -110532.797660827026}, + {-222588.439735968423, 110660.533870799671}, + {-222756.879700278747, -110532.797660827026}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.00179635940600536667, 0.000904232207322381741}, + { 0.00179635817735249777, -0.000904233135128348995}, + {-0.00179635940600536667, 0.000904232207322381741}, + {-0.00179635817735249777, -0.000904233135128348995}, + }; + + return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); +} + + +#endif -- cgit v1.2.3 From 547454fab9e54a3812dc0d10c51f89f7cffcf901 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Thu, 28 Apr 2016 00:04:30 +0200 Subject: Converted lcca --- src/PJ_aea.c | 1 - src/PJ_lcca.c | 206 +++++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 146 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index fb26487c..78021a0e 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -366,7 +366,6 @@ int pj_latlon_selftest (void) {return 10000;} int pj_latlong_selftest (void) {return 10000;} int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} -int pj_lcca_selftest (void) {return 10000;} int pj_lee_os_selftest (void) {return 10000;} int pj_loxim_selftest (void) {return 10000;} diff --git a/src/PJ_lcca.c b/src/PJ_lcca.c index 320d52db..eef46110 100644 --- a/src/PJ_lcca.c +++ b/src/PJ_lcca.c @@ -1,70 +1,156 @@ -/* PROJ.4 Cartographic Projection System +/* PROJ.4 Cartographic Projection System */ -#define MAX_ITER 10 -#define DEL_TOL 1e-12 -#define PROJ_PARMS__ \ - double *en; \ - double r0, l, M0; \ - double C; #define PJ_LIB__ -#include +#include PROJ_HEAD(lcca, "Lambert Conformal Conic Alternative") - "\n\tConic, Sph&Ell\n\tlat_0="; + "\n\tConic, Sph&Ell\n\tlat_0="; + +#define MAX_ITER 10 +#define DEL_TOL 1e-12 + +struct pj_opaque { + double *en; + double r0, l, M0; + double C; +}; + + +static double fS(double S, double C) { /* func to compute dr */ + + return S * ( 1. + S * S * C); +} + + +static double fSp(double S, double C) { /* deriv of fs */ + + return 1. + 3.* S * S * C; +} + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double S, r, dr; + + S = pj_mlfn(lp.phi, sin(lp.phi), cos(lp.phi), Q->en) - Q->M0; + dr = fS(S, Q->C); + r = Q->r0 - dr; + xy.x = P->k0 * (r * sin( lp.lam *= Q->l ) ); + xy.y = P->k0 * (Q->r0 - r * cos(lp.lam) ); + return xy; +} + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double theta, dr, S, dif; + int i; + + xy.x /= P->k0; + xy.y /= P->k0; + theta = atan2(xy.x , Q->r0 - xy.y); + dr = xy.y - xy.x * tan(0.5 * theta); + lp.lam = theta / Q->l; + S = dr; + for (i = MAX_ITER; i ; --i) { + S -= (dif = (fS(S, Q->C) - dr) / fSp(S, Q->C)); + if (fabs(dif) < DEL_TOL) break; + } + if (!i) I_ERROR + lp.phi = pj_inv_mlfn(P->ctx, S + Q->M0, P->es, Q->en); - static double /* func to compute dr */ -fS(double S, double C) { - return(S * ( 1. + S * S * C)); + return lp; } - static double /* deriv of fs */ -fSp(double S, double C) { - return(1. + 3.* S * S * C); + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque->en); + pj_dealloc (P->opaque); + return pj_dealloc(P); } -FORWARD(e_forward); /* ellipsoid */ - double S, r, dr; - - S = pj_mlfn(lp.phi, sin(lp.phi), cos(lp.phi), P->en) - P->M0; - dr = fS(S, P->C); - r = P->r0 - dr; - xy.x = P->k0 * (r * sin( lp.lam *= P->l ) ); - xy.y = P->k0 * (P->r0 - r * cos(lp.lam) ); - return (xy); + +static void freeup (PJ *P) { + freeup_new (P); + return; } -INVERSE(e_inverse); /* ellipsoid & spheroid */ - double theta, dr, S, dif; - int i; - - xy.x /= P->k0; - xy.y /= P->k0; - theta = atan2(xy.x , P->r0 - xy.y); - dr = xy.y - xy.x * tan(0.5 * theta); - lp.lam = theta / P->l; - S = dr; - for (i = MAX_ITER; i ; --i) { - S -= (dif = (fS(S, P->C) - dr) / fSp(S, P->C)); - if (fabs(dif) < DEL_TOL) break; - } - if (!i) I_ERROR - lp.phi = pj_inv_mlfn(P->ctx, S + P->M0, P->es, P->en); - return (lp); + + +PJ *PROJECTION(lcca) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + double s2p0, N0, R0, tan0; + + (Q->en = pj_enfn(P->es)); + if (!Q->en) E_ERROR_0; + if (!pj_param(P->ctx, P->params, "tlat_0").i) E_ERROR(50); + if (P->phi0 == 0.) E_ERROR(51); + Q->l = sin(P->phi0); + Q->M0 = pj_mlfn(P->phi0, Q->l, cos(P->phi0), Q->en); + s2p0 = Q->l * Q->l; + R0 = 1. / (1. - P->es * s2p0); + N0 = sqrt(R0); + R0 *= P->one_es * N0; + tan0 = tan(P->phi0); + Q->r0 = N0 / tan0; + Q->C = 1. / (6. * R0 * N0); + + P->inv = e_inverse; + P->fwd = e_forward; + + return P; } -FREEUP; if (P) { if (P->en) pj_dalloc(P->en); pj_dalloc(P); } } -ENTRY0(lcca) - double s2p0, N0, R0, tan0; - - if (!(P->en = pj_enfn(P->es))) E_ERROR_0; - if (!pj_param(P->ctx, P->params, "tlat_0").i) E_ERROR(50); - if (P->phi0 == 0.) E_ERROR(51); - P->l = sin(P->phi0); - P->M0 = pj_mlfn(P->phi0, P->l, cos(P->phi0), P->en); - s2p0 = P->l * P->l; - R0 = 1. / (1. - P->es * s2p0); - N0 = sqrt(R0); - R0 *= P->one_es * N0; - tan0 = tan(P->phi0); - P->r0 = N0 / tan0; - P->C = 1. / (6. * R0 * N0); - P->inv = e_inverse; - P->fwd = e_forward; -ENDENTRY(P) + + +#ifdef PJ_OMIT_SELFTEST +int pj_lcca_selftest (void) {return 0;} +#else + +int pj_lcca_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=lcca +ellps=GRS80 +lat_0=1 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222605.285770237417, 67.8060072715846616}, + { 222740.037637936533, -221125.539829601563}, + {-222605.285770237417, 67.8060072715846616}, + {-222740.037637936533, -221125.539829601563}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.00179690290525662526, 1.00090436621350798}, + { 0.00179690192174008037, 0.999095632791497268}, + {-0.00179690290525662526, 1.00090436621350798}, + {-0.00179690192174008037, 0.999095632791497268}, + }; + + return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); +} + + +#endif -- cgit v1.2.3 From c00d175ddb11c0190347c4606f6dfdf68bd7a8c0 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Thu, 28 Apr 2016 08:23:37 +0200 Subject: Converted loxim --- src/PJ_aea.c | 1 - src/PJ_loxim.c | 163 ++++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 126 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 78021a0e..428bcec1 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -368,7 +368,6 @@ int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} int pj_lee_os_selftest (void) {return 10000;} -int pj_loxim_selftest (void) {return 10000;} int pj_lsat_selftest (void) {return 10000;} int pj_mbt_fps_selftest (void) {return 10000;} diff --git a/src/PJ_loxim.c b/src/PJ_loxim.c index 595423f7..9ddfd51c 100644 --- a/src/PJ_loxim.c +++ b/src/PJ_loxim.c @@ -1,41 +1,130 @@ -#define PROJ_PARMS__ \ - double phi1; \ - double cosphi1; \ - double tanphi1; #define PJ_LIB__ -#include +#include + PROJ_HEAD(loxim, "Loximuthal") "\n\tPCyl Sph"; -#define EPS 1e-8 -FORWARD(s_forward); /* spheroid */ - xy.y = lp.phi - P->phi1; - if (fabs(xy.y) < EPS) - xy.x = lp.lam * P->cosphi1; - else { - xy.x = FORTPI + 0.5 * lp.phi; - if (fabs(xy.x) < EPS || fabs(fabs(xy.x) - HALFPI) < EPS) - xy.x = 0.; - else - xy.x = lp.lam * xy.y / log( tan(xy.x) / P->tanphi1 ); - } - return (xy); + +#define EPS 1e-8 + +struct pj_opaque { + double phi1; + double cosphi1; + double tanphi1; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + xy.y = lp.phi - Q->phi1; + if (fabs(xy.y) < EPS) + xy.x = lp.lam * Q->cosphi1; + else { + xy.x = FORTPI + 0.5 * lp.phi; + if (fabs(xy.x) < EPS || fabs(fabs(xy.x) - HALFPI) < EPS) + xy.x = 0.; + else + xy.x = lp.lam * xy.y / log( tan(xy.x) / Q->tanphi1 ); + } + return xy; } -INVERSE(s_inverse); /* spheroid */ - lp.phi = xy.y + P->phi1; - if (fabs(xy.y) < EPS) - lp.lam = xy.x / P->cosphi1; - else - if (fabs( lp.lam = FORTPI + 0.5 * lp.phi ) < EPS || - fabs(fabs(lp.lam) - HALFPI) < EPS) - lp.lam = 0.; - else - lp.lam = xy.x * log( tan(lp.lam) / P->tanphi1 ) / xy.y ; - return (lp); + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + lp.phi = xy.y + Q->phi1; + if (fabs(xy.y) < EPS) { + lp.lam = xy.x / Q->cosphi1; + } else { + lp.lam = FORTPI + 0.5 * lp.phi; + if (fabs(lp.lam) < EPS || fabs(fabs(lp.lam) - HALFPI) < EPS) + lp.lam = 0.; + else + lp.lam = xy.x * log( tan(lp.lam) / Q->tanphi1 ) / xy.y ; + } + return lp; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(loxim); - P->phi1 = pj_param(P->ctx, P->params, "rlat_1").f; - if ((P->cosphi1 = cos(P->phi1)) < EPS) E_ERROR(-22); - P->tanphi1 = tan(FORTPI + 0.5 * P->phi1); - P->inv = s_inverse; P->fwd = s_forward; - P->es = 0.; -ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(loxim) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->phi1 = pj_param(P->ctx, P->params, "rlat_1").f; + Q->cosphi1 = cos(Q->phi1); + if (Q->cosphi1 < EPS) + E_ERROR(-22); + + Q->tanphi1 = tan(FORTPI + 0.5 * Q->phi1); + + P->inv = s_inverse; + P->fwd = s_forward; + P->es = 0.; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_loxim_selftest (void) {return 0;} +#else + +int pj_loxim_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=loxim +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223382.295791338867, 55850.5360638185448}, + { 223393.637462243292, -167551.608191455656}, + {-223382.295791338867, 55850.5360638185448}, + {-223393.637462243292, -167551.608191455656}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00179056141104335601, 0.500895246554891926}, + { 0.00179056116683692576, 0.499104753445108074}, + {-0.00179056141104335601, 0.500895246554891926}, + {-0.00179056116683692576, 0.499104753445108074}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From c9f12e0033474518fa460444b9948f36ce47d51f Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Thu, 28 Apr 2016 08:48:20 +0200 Subject: Converted lsat --- src/PJ_aea.c | 1 - src/PJ_lsat.c | 389 +++++++++++++++++++++++++++++++++++----------------------- 2 files changed, 238 insertions(+), 152 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 428bcec1..84ad5c4c 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -368,7 +368,6 @@ int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} int pj_lee_os_selftest (void) {return 10000;} -int pj_lsat_selftest (void) {return 10000;} int pj_mbt_fps_selftest (void) {return 10000;} int pj_mbtfpp_selftest (void) {return 10000;} diff --git a/src/PJ_lsat.c b/src/PJ_lsat.c index d11a5c14..2dcdb000 100644 --- a/src/PJ_lsat.c +++ b/src/PJ_lsat.c @@ -1,171 +1,258 @@ /* based upon Snyder and Linck, USGS-NMD */ -#define PROJ_PARMS__ \ - double a2, a4, b, c1, c3; \ - double q, t, u, w, p22, sa, ca, xj, rlm, rlm2; #define PJ_LIB__ -#include +#include + PROJ_HEAD(lsat, "Space oblique for LANDSAT") - "\n\tCyl, Sph&Ell\n\tlsat= path="; + "\n\tCyl, Sph&Ell\n\tlsat= path="; + #define TOL 1e-7 #define PI_HALFPI 4.71238898038468985766 #define TWOPI_HALFPI 7.85398163397448309610 - static void -seraz0(double lam, double mult, PJ *P) { - double sdsq, h, s, fc, sd, sq, d__1; + +struct pj_opaque { + double a2, a4, b, c1, c3; + double q, t, u, w, p22, sa, ca, xj, rlm, rlm2; +}; + +static void seraz0(double lam, double mult, PJ *P) { + struct pj_opaque *Q = P->opaque; + double sdsq, h, s, fc, sd, sq, d__1 = 0; lam *= DEG_TO_RAD; sd = sin(lam); sdsq = sd * sd; - s = P->p22 * P->sa * cos(lam) * sqrt((1. + P->t * sdsq) / (( - 1. + P->w * sdsq) * (1. + P->q * sdsq))); - d__1 = 1. + P->q * sdsq; - h = sqrt((1. + P->q * sdsq) / (1. + P->w * sdsq)) * ((1. + - P->w * sdsq) / (d__1 * d__1) - P->p22 * P->ca); - sq = sqrt(P->xj * P->xj + s * s); - P->b += fc = mult * (h * P->xj - s * s) / sq; - P->a2 += fc * cos(lam + lam); - P->a4 += fc * cos(lam * 4.); - fc = mult * s * (h + P->xj) / sq; - P->c1 += fc * cos(lam); - P->c3 += fc * cos(lam * 3.); + s = Q->p22 * Q->sa * cos(lam) * sqrt((1. + Q->t * sdsq) + / ((1. + Q->w * sdsq) * (1. + Q->q * sdsq))); + + h = sqrt((1. + Q->q * sdsq) / (1. + Q->w * sdsq)) * ((1. + Q->w * sdsq) + / (d__1 * d__1) - Q->p22 * Q->ca); + + sq = sqrt(Q->xj * Q->xj + s * s); + fc = mult * (h * Q->xj - s * s) / sq; + Q->b += fc; + Q->a2 += fc * cos(lam + lam); + Q->a4 += fc * cos(lam * 4.); + fc = mult * s * (h + Q->xj) / sq; + Q->c1 += fc * cos(lam); + Q->c3 += fc * cos(lam * 3.); } -FORWARD(e_forward); /* ellipsoid */ + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; int l, nn; - double lamt, xlam, sdsq, c, d, s, lamdp, phidp, lampp, tanph, - lamtp, cl, sd, sp, fac, sav, tanphi; - - if (lp.phi > HALFPI) - lp.phi = HALFPI; - else if (lp.phi < -HALFPI) - lp.phi = -HALFPI; - lampp = lp.phi >= 0. ? HALFPI : PI_HALFPI; - tanphi = tan(lp.phi); - for (nn = 0;;) { - sav = lampp; - lamtp = lp.lam + P->p22 * lampp; - cl = cos(lamtp); - if (fabs(cl) < TOL) - lamtp -= TOL; - fac = lampp - sin(lampp) * (cl < 0. ? -HALFPI : HALFPI); - for (l = 50; l; --l) { - lamt = lp.lam + P->p22 * sav; - if (fabs(c = cos(lamt)) < TOL) - lamt -= TOL; - xlam = (P->one_es * tanphi * P->sa + sin(lamt) * P->ca) / c; - lamdp = atan(xlam) + fac; - if (fabs(fabs(sav) - fabs(lamdp)) < TOL) - break; - sav = lamdp; - } - if (!l || ++nn >= 3 || (lamdp > P->rlm && lamdp < P->rlm2)) - break; - if (lamdp <= P->rlm) - lampp = TWOPI_HALFPI; - else if (lamdp >= P->rlm2) - lampp = HALFPI; - } - if (l) { - sp = sin(lp.phi); - phidp = aasin(P->ctx,(P->one_es * P->ca * sp - P->sa * cos(lp.phi) * - sin(lamt)) / sqrt(1. - P->es * sp * sp)); - tanph = log(tan(FORTPI + .5 * phidp)); - sd = sin(lamdp); - sdsq = sd * sd; - s = P->p22 * P->sa * cos(lamdp) * sqrt((1. + P->t * sdsq) - / ((1. + P->w * sdsq) * (1. + P->q * sdsq))); - d = sqrt(P->xj * P->xj + s * s); - xy.x = P->b * lamdp + P->a2 * sin(2. * lamdp) + P->a4 * - sin(lamdp * 4.) - tanph * s / d; - xy.y = P->c1 * sd + P->c3 * sin(lamdp * 3.) + tanph * P->xj / d; - } else - xy.x = xy.y = HUGE_VAL; - return xy; + double lamt, xlam, sdsq, c, d, s, lamdp, phidp, lampp, tanph; + double lamtp, cl, sd, sp, fac, sav, tanphi; + + if (lp.phi > HALFPI) + lp.phi = HALFPI; + else if (lp.phi < -HALFPI) + lp.phi = -HALFPI; + + lampp = lp.phi >= 0. ? HALFPI : PI_HALFPI; + tanphi = tan(lp.phi); + for (nn = 0;;) { + sav = lampp; + lamtp = lp.lam + Q->p22 * lampp; + cl = cos(lamtp); + if (fabs(cl) < TOL) + lamtp -= TOL; + fac = lampp - sin(lampp) * (cl < 0. ? -HALFPI : HALFPI); + for (l = 50; l; --l) { + lamt = lp.lam + Q->p22 * sav; + c = cos(lamt); + if (fabs(c) < TOL) + lamt -= TOL; + xlam = (P->one_es * tanphi * Q->sa + sin(lamt) * Q->ca) / c; + lamdp = atan(xlam) + fac; + if (fabs(fabs(sav) - fabs(lamdp)) < TOL) + break; + sav = lamdp; + } + if (!l || ++nn >= 3 || (lamdp > Q->rlm && lamdp < Q->rlm2)) + break; + if (lamdp <= Q->rlm) + lampp = TWOPI_HALFPI; + else if (lamdp >= Q->rlm2) + lampp = HALFPI; + } + if (l) { + sp = sin(lp.phi); + phidp = aasin(P->ctx,(P->one_es * Q->ca * sp - Q->sa * cos(lp.phi) * + sin(lamt)) / sqrt(1. - P->es * sp * sp)); + tanph = log(tan(FORTPI + .5 * phidp)); + sd = sin(lamdp); + sdsq = sd * sd; + s = Q->p22 * Q->sa * cos(lamdp) * sqrt((1. + Q->t * sdsq) + / ((1. + Q->w * sdsq) * (1. + Q->q * sdsq))); + d = sqrt(Q->xj * Q->xj + s * s); + xy.x = Q->b * lamdp + Q->a2 * sin(2. * lamdp) + Q->a4 * + sin(lamdp * 4.) - tanph * s / d; + xy.y = Q->c1 * sd + Q->c3 * sin(lamdp * 3.) + tanph * Q->xj / d; + } else + xy.x = xy.y = HUGE_VAL; + return xy; } -INVERSE(e_inverse); /* ellipsoid */ + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; int nn; double lamt, sdsq, s, lamdp, phidp, sppsq, dd, sd, sl, fac, scl, sav, spp; - lamdp = xy.x / P->b; - nn = 50; - do { - sav = lamdp; - sd = sin(lamdp); - sdsq = sd * sd; - s = P->p22 * P->sa * cos(lamdp) * sqrt((1. + P->t * sdsq) - / ((1. + P->w * sdsq) * (1. + P->q * sdsq))); - lamdp = xy.x + xy.y * s / P->xj - P->a2 * sin( - 2. * lamdp) - P->a4 * sin(lamdp * 4.) - s / P->xj * ( - P->c1 * sin(lamdp) + P->c3 * sin(lamdp * 3.)); - lamdp /= P->b; - } while (fabs(lamdp - sav) >= TOL && --nn); - sl = sin(lamdp); - fac = exp(sqrt(1. + s * s / P->xj / P->xj) * (xy.y - - P->c1 * sl - P->c3 * sin(lamdp * 3.))); - phidp = 2. * (atan(fac) - FORTPI); - dd = sl * sl; - if (fabs(cos(lamdp)) < TOL) - lamdp -= TOL; - spp = sin(phidp); - sppsq = spp * spp; - lamt = atan(((1. - sppsq * P->rone_es) * tan(lamdp) * - P->ca - spp * P->sa * sqrt((1. + P->q * dd) * ( - 1. - sppsq) - sppsq * P->u) / cos(lamdp)) / (1. - sppsq - * (1. + P->u))); - sl = lamt >= 0. ? 1. : -1.; - scl = cos(lamdp) >= 0. ? 1. : -1; - lamt -= HALFPI * (1. - scl) * sl; - lp.lam = lamt - P->p22 * lamdp; - if (fabs(P->sa) < TOL) - lp.phi = aasin(P->ctx,spp / sqrt(P->one_es * P->one_es + P->es * sppsq)); - else - lp.phi = atan((tan(lamdp) * cos(lamt) - P->ca * sin(lamt)) / - (P->one_es * P->sa)); - return lp; + lamdp = xy.x / Q->b; + nn = 50; + do { + sav = lamdp; + sd = sin(lamdp); + sdsq = sd * sd; + s = Q->p22 * Q->sa * cos(lamdp) * sqrt((1. + Q->t * sdsq) + / ((1. + Q->w * sdsq) * (1. + Q->q * sdsq))); + lamdp = xy.x + xy.y * s / Q->xj - Q->a2 * sin( + 2. * lamdp) - Q->a4 * sin(lamdp * 4.) - s / Q->xj * ( + Q->c1 * sin(lamdp) + Q->c3 * sin(lamdp * 3.)); + lamdp /= Q->b; + } while (fabs(lamdp - sav) >= TOL && --nn); + sl = sin(lamdp); + fac = exp(sqrt(1. + s * s / Q->xj / Q->xj) * (xy.y - + Q->c1 * sl - Q->c3 * sin(lamdp * 3.))); + phidp = 2. * (atan(fac) - FORTPI); + dd = sl * sl; + if (fabs(cos(lamdp)) < TOL) + lamdp -= TOL; + spp = sin(phidp); + sppsq = spp * spp; + lamt = atan(((1. - sppsq * P->rone_es) * tan(lamdp) * + Q->ca - spp * Q->sa * sqrt((1. + Q->q * dd) * ( + 1. - sppsq) - sppsq * Q->u) / cos(lamdp)) / (1. - sppsq + * (1. + Q->u))); + sl = lamt >= 0. ? 1. : -1.; + scl = cos(lamdp) >= 0. ? 1. : -1; + lamt -= HALFPI * (1. - scl) * sl; + lp.lam = lamt - Q->p22 * lamdp; + if (fabs(Q->sa) < TOL) + lp.phi = aasin(P->ctx,spp / sqrt(P->one_es * P->one_es + P->es * sppsq)); + else + lp.phi = atan((tan(lamdp) * cos(lamt) - Q->ca * sin(lamt)) / + (P->one_es * Q->sa)); + return lp; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(lsat) + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(lsat) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; int land, path; double lam, alf, esc, ess; - land = pj_param(P->ctx, P->params, "ilsat").i; - if (land <= 0 || land > 5) E_ERROR(-28); - path = pj_param(P->ctx, P->params, "ipath").i; - if (path <= 0 || path > (land <= 3 ? 251 : 233)) E_ERROR(-29); - if (land <= 3) { - P->lam0 = DEG_TO_RAD * 128.87 - TWOPI / 251. * path; - P->p22 = 103.2669323; - alf = DEG_TO_RAD * 99.092; - } else { - P->lam0 = DEG_TO_RAD * 129.3 - TWOPI / 233. * path; - P->p22 = 98.8841202; - alf = DEG_TO_RAD * 98.2; - } - P->p22 /= 1440.; - P->sa = sin(alf); - P->ca = cos(alf); - if (fabs(P->ca) < 1e-9) - P->ca = 1e-9; - esc = P->es * P->ca * P->ca; - ess = P->es * P->sa * P->sa; - P->w = (1. - esc) * P->rone_es; - P->w = P->w * P->w - 1.; - P->q = ess * P->rone_es; - P->t = ess * (2. - P->es) * P->rone_es * P->rone_es; - P->u = esc * P->rone_es; - P->xj = P->one_es * P->one_es * P->one_es; - P->rlm = PI * (1. / 248. + .5161290322580645); - P->rlm2 = P->rlm + TWOPI; - P->a2 = P->a4 = P->b = P->c1 = P->c3 = 0.; - seraz0(0., 1., P); - for (lam = 9.; lam <= 81.0001; lam += 18.) - seraz0(lam, 4., P); - for (lam = 18; lam <= 72.0001; lam += 18.) - seraz0(lam, 2., P); - seraz0(90., 1., P); - P->a2 /= 30.; - P->a4 /= 60.; - P->b /= 30.; - P->c1 /= 15.; - P->c3 /= 45.; - P->inv = e_inverse; P->fwd = e_forward; -ENDENTRY(P) + land = pj_param(P->ctx, P->params, "ilsat").i; + if (land <= 0 || land > 5) E_ERROR(-28); + path = pj_param(P->ctx, P->params, "ipath").i; + if (path <= 0 || path > (land <= 3 ? 251 : 233)) E_ERROR(-29); + if (land <= 3) { + P->lam0 = DEG_TO_RAD * 128.87 - TWOPI / 251. * path; + Q->p22 = 103.2669323; + alf = DEG_TO_RAD * 99.092; + } else { + P->lam0 = DEG_TO_RAD * 129.3 - TWOPI / 233. * path; + Q->p22 = 98.8841202; + alf = DEG_TO_RAD * 98.2; + } + Q->p22 /= 1440.; + Q->sa = sin(alf); + Q->ca = cos(alf); + if (fabs(Q->ca) < 1e-9) + Q->ca = 1e-9; + esc = P->es * Q->ca * Q->ca; + ess = P->es * Q->sa * Q->sa; + Q->w = (1. - esc) * P->rone_es; + Q->w = Q->w * Q->w - 1.; + Q->q = ess * P->rone_es; + Q->t = ess * (2. - P->es) * P->rone_es * P->rone_es; + Q->u = esc * P->rone_es; + Q->xj = P->one_es * P->one_es * P->one_es; + Q->rlm = PI * (1. / 248. + .5161290322580645); + Q->rlm2 = Q->rlm + TWOPI; + Q->a2 = Q->a4 = Q->b = Q->c1 = Q->c3 = 0.; + seraz0(0., 1., P); + for (lam = 9.; lam <= 81.0001; lam += 18.) + seraz0(lam, 4., P); + for (lam = 18; lam <= 72.0001; lam += 18.) + seraz0(lam, 2., P); + seraz0(90., 1., P); + Q->a2 /= 30.; + Q->a4 /= 60.; + Q->b /= 30.; + Q->c1 /= 15.; + Q->c3 /= 45.; + + P->inv = e_inverse; + P->fwd = e_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_lsat_selftest (void) {return 0;} +#else + +int pj_lsat_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=lsat +ellps=GRS80 +lat_1=0.5 +lat_2=2 +lsat=1 +path=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {18241950.01455855, 9998256.83982293494}, + {18746856.2533194572, 10215761.669925211}, + {18565503.6836331636, 9085039.14672705345}, + {19019696.9020289108, 9247763.0394328218}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {126.000423834530011, 0.00172378224025701425}, + {126.002213738256714, 0.00188015467480917966}, + {126.000734468914601, -0.00188015467480917966}, + {126.002524372641304, -0.00172378224025701425}, + }; + + return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); +} + + +#endif -- cgit v1.2.3 From 66b9152c5339cdc699c93d8954078e1a81f84e38 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Thu, 28 Apr 2016 21:04:35 +0200 Subject: Converted mbt_fps --- src/PJ_aea.c | 1 - src/PJ_mbt_fps.c | 129 +++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 101 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 84ad5c4c..4198d2b3 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -369,7 +369,6 @@ int pj_longlat_selftest (void) {return 10000;} int pj_lee_os_selftest (void) {return 10000;} -int pj_mbt_fps_selftest (void) {return 10000;} int pj_mbtfpp_selftest (void) {return 10000;} int pj_mbtfpq_selftest (void) {return 10000;} int pj_merc_selftest (void) {return 10000;} diff --git a/src/PJ_mbt_fps.c b/src/PJ_mbt_fps.c index 3cd5e674..daa1555c 100644 --- a/src/PJ_mbt_fps.c +++ b/src/PJ_mbt_fps.c @@ -1,39 +1,112 @@ #define PJ_LIB__ -#include +#include + PROJ_HEAD(mbt_fps, "McBryde-Thomas Flat-Pole Sine (No. 2)") "\n\tCyl., Sph."; -#define MAX_ITER 10 -#define LOOP_TOL 1e-7 + +#define MAX_ITER 10 +#define LOOP_TOL 1e-7 #define C1 0.45503 #define C2 1.36509 #define C3 1.41546 #define C_x 0.22248 #define C_y 1.44492 #define C1_2 0.33333333333333333333333333 -FORWARD(s_forward); /* spheroid */ - double k, V, t; - int i; - (void) P; - - k = C3 * sin(lp.phi); - for (i = MAX_ITER; i ; --i) { - t = lp.phi / C2; - lp.phi -= V = (C1 * sin(t) + sin(lp.phi) - k) / - (C1_2 * cos(t) + cos(lp.phi)); - if (fabs(V) < LOOP_TOL) - break; - } - t = lp.phi / C2; - xy.x = C_x * lp.lam * (1. + 3. * cos(lp.phi)/cos(t) ); - xy.y = C_y * sin(t); - return (xy); + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + double k, V, t; + int i; + (void) P; + + k = C3 * sin(lp.phi); + for (i = MAX_ITER; i ; --i) { + t = lp.phi / C2; + lp.phi -= V = (C1 * sin(t) + sin(lp.phi) - k) / + (C1_2 * cos(t) + cos(lp.phi)); + if (fabs(V) < LOOP_TOL) + break; + } + t = lp.phi / C2; + xy.x = C_x * lp.lam * (1. + 3. * cos(lp.phi)/cos(t) ); + xy.y = C_y * sin(t); + return xy; } -INVERSE(s_inverse); /* spheroid */ - double t; - lp.phi = C2 * (t = aasin(P->ctx,xy.y / C_y)); - lp.lam = xy.x / (C_x * (1. + 3. * cos(lp.phi)/cos(t))); - lp.phi = aasin(P->ctx,(C1 * sin(t) + sin(lp.phi)) / C3); - return (lp); + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + double t; + + lp.phi = C2 * (t = aasin(P->ctx,xy.y / C_y)); + lp.lam = xy.x / (C_x * (1. + 3. * cos(lp.phi)/cos(t))); + lp.phi = aasin(P->ctx,(C1 * sin(t) + sin(lp.phi)) / C3); + return (lp); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(mbt_fps) P->es = 0; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(mbt_fps) { + + P->es = 0; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_mbt_fps_selftest (void) {return 0;} +#else + +int pj_mbt_fps_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=mbt_fps +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 198798.176129849948, 125512.017254530627}, + { 198798.176129849948, -125512.017254530627}, + {-198798.176129849948, 125512.017254530627}, + {-198798.176129849948, -125512.017254530627}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00201197086238270742, 0.000796711850174446003}, + { 0.00201197086238270742, -0.000796711850174446003}, + {-0.00201197086238270742, 0.000796711850174446003}, + {-0.00201197086238270742, -0.000796711850174446003}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 47a7800d0396d36dbb099e9a4a86378f5bb4a1dd Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Thu, 28 Apr 2016 21:13:47 +0200 Subject: Converted mbtfpp --- src/PJ_aea.c | 1 - src/PJ_mbtfpp.c | 139 ++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 110 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 4198d2b3..863d9025 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -369,7 +369,6 @@ int pj_longlat_selftest (void) {return 10000;} int pj_lee_os_selftest (void) {return 10000;} -int pj_mbtfpp_selftest (void) {return 10000;} int pj_mbtfpq_selftest (void) {return 10000;} int pj_merc_selftest (void) {return 10000;} int pj_mil_os_selftest (void) {return 10000;} diff --git a/src/PJ_mbtfpp.c b/src/PJ_mbtfpp.c index 433d3c8f..688150fe 100644 --- a/src/PJ_mbtfpp.c +++ b/src/PJ_mbtfpp.c @@ -1,33 +1,114 @@ #define PJ_LIB__ -#include +#include + PROJ_HEAD(mbtfpp, "McBride-Thomas Flat-Polar Parabolic") "\n\tCyl., Sph."; -#define CS .95257934441568037152 -#define FXC .92582009977255146156 -#define FYC 3.40168025708304504493 -#define C23 .66666666666666666666 -#define C13 .33333333333333333333 -#define ONEEPS 1.0000001 -FORWARD(s_forward); /* spheroid */ - (void) P; - lp.phi = asin(CS * sin(lp.phi)); - xy.x = FXC * lp.lam * (2. * cos(C23 * lp.phi) - 1.); - xy.y = FYC * sin(C13 * lp.phi); - return (xy); + +#define CS .95257934441568037152 +#define FXC .92582009977255146156 +#define FYC 3.40168025708304504493 +#define C23 .66666666666666666666 +#define C13 .33333333333333333333 +#define ONEEPS 1.0000001 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + (void) P; + + lp.phi = asin(CS * sin(lp.phi)); + xy.x = FXC * lp.lam * (2. * cos(C23 * lp.phi) - 1.); + xy.y = FYC * sin(C13 * lp.phi); + return xy; } -INVERSE(s_inverse); /* spheroid */ - lp.phi = xy.y / FYC; - if (fabs(lp.phi) >= 1.) { - if (fabs(lp.phi) > ONEEPS) I_ERROR - else lp.phi = (lp.phi < 0.) ? -HALFPI : HALFPI; - } else - lp.phi = asin(lp.phi); - lp.lam = xy.x / ( FXC * (2. * cos(C23 * (lp.phi *= 3.)) - 1.) ); - if (fabs(lp.phi = sin(lp.phi) / CS) >= 1.) { - if (fabs(lp.phi) > ONEEPS) I_ERROR - else lp.phi = (lp.phi < 0.) ? -HALFPI : HALFPI; - } else - lp.phi = asin(lp.phi); - return (lp); + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + + lp.phi = xy.y / FYC; + if (fabs(lp.phi) >= 1.) { + if (fabs(lp.phi) > ONEEPS) + I_ERROR + else + lp.phi = (lp.phi < 0.) ? -HALFPI : HALFPI; + } else + lp.phi = asin(lp.phi); + + lp.lam = xy.x / ( FXC * (2. * cos(C23 * (lp.phi *= 3.)) - 1.) ); + if (fabs(lp.phi = sin(lp.phi) / CS) >= 1.) { + if (fabs(lp.phi) > ONEEPS) + I_ERROR + else + lp.phi = (lp.phi < 0.) ? -HALFPI : HALFPI; + } else + lp.phi = asin(lp.phi); + + return lp; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(mbtfpp) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(mbtfpp) { + + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_mbtfpp_selftest (void) {return 0;} +#else + +int pj_mbtfpp_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=mbtfpp +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {206804.786929820373, 120649.762565792524}, + {206804.786929820373, -120649.762565792524}, + {-206804.786929820373, 120649.762565792524}, + {-206804.786929820373, -120649.762565792524}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + {0.00193395359462902698, 0.00082883725477665357}, + {0.00193395359462902698, -0.00082883725477665357}, + {-0.00193395359462902698, 0.00082883725477665357}, + {-0.00193395359462902698, -0.00082883725477665357}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 9e39856aaeb4bc6feb61065069ea710f96a74f4a Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Thu, 28 Apr 2016 21:26:58 +0200 Subject: Converted mbtfpq --- src/PJ_aea.c | 1 - src/PJ_mbtfpq.c | 159 +++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 116 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 863d9025..282c0b88 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -369,7 +369,6 @@ int pj_longlat_selftest (void) {return 10000;} int pj_lee_os_selftest (void) {return 10000;} -int pj_mbtfpq_selftest (void) {return 10000;} int pj_merc_selftest (void) {return 10000;} int pj_mil_os_selftest (void) {return 10000;} int pj_mill_selftest (void) {return 10000;} diff --git a/src/PJ_mbtfpq.c b/src/PJ_mbtfpq.c index 0d343fad..d382f45a 100644 --- a/src/PJ_mbtfpq.c +++ b/src/PJ_mbtfpq.c @@ -1,48 +1,121 @@ #define PJ_LIB__ -#include +#include + PROJ_HEAD(mbtfpq, "McBryde-Thomas Flat-Polar Quartic") "\n\tCyl., Sph."; -#define NITER 20 -#define EPS 1e-7 + +#define NITER 20 +#define EPS 1e-7 #define ONETOL 1.000001 -#define C 1.70710678118654752440 -#define RC 0.58578643762690495119 -#define FYC 1.87475828462269495505 -#define RYC 0.53340209679417701685 -#define FXC 0.31245971410378249250 -#define RXC 3.20041258076506210122 -FORWARD(s_forward); /* spheroid */ - double th1, c; - int i; - (void) P; - - c = C * sin(lp.phi); - for (i = NITER; i; --i) { - lp.phi -= th1 = (sin(.5*lp.phi) + sin(lp.phi) - c) / - (.5*cos(.5*lp.phi) + cos(lp.phi)); - if (fabs(th1) < EPS) break; - } - xy.x = FXC * lp.lam * (1.0 + 2. * cos(lp.phi)/cos(0.5 * lp.phi)); - xy.y = FYC * sin(0.5 * lp.phi); - return (xy); +#define C 1.70710678118654752440 +#define RC 0.58578643762690495119 +#define FYC 1.87475828462269495505 +#define RYC 0.53340209679417701685 +#define FXC 0.31245971410378249250 +#define RXC 3.20041258076506210122 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + double th1, c; + int i; + (void) P; + + c = C * sin(lp.phi); + for (i = NITER; i; --i) { + lp.phi -= th1 = (sin(.5*lp.phi) + sin(lp.phi) - c) / + (.5*cos(.5*lp.phi) + cos(lp.phi)); + if (fabs(th1) < EPS) break; + } + xy.x = FXC * lp.lam * (1.0 + 2. * cos(lp.phi)/cos(0.5 * lp.phi)); + xy.y = FYC * sin(0.5 * lp.phi); + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + double t; + + lp.phi = RYC * xy.y; + if (fabs(lp.phi) > 1.) { + if (fabs(lp.phi) > ONETOL) I_ERROR + else if (lp.phi < 0.) { t = -1.; lp.phi = -PI; } + else { t = 1.; lp.phi = PI; } + } else + lp.phi = 2. * asin(t = lp.phi); + lp.lam = RXC * xy.x / (1. + 2. * cos(lp.phi)/cos(0.5 * lp.phi)); + lp.phi = RC * (t + sin(lp.phi)); + if (fabs(lp.phi) > 1.) + if (fabs(lp.phi) > ONETOL) I_ERROR + else lp.phi = lp.phi < 0. ? -HALFPI : HALFPI; + else + lp.phi = asin(lp.phi); + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; } -INVERSE(s_inverse); /* spheroid */ - double t; - - lp.phi = RYC * xy.y; - if (fabs(lp.phi) > 1.) { - if (fabs(lp.phi) > ONETOL) I_ERROR - else if (lp.phi < 0.) { t = -1.; lp.phi = -PI; } - else { t = 1.; lp.phi = PI; } - } else - lp.phi = 2. * asin(t = lp.phi); - lp.lam = RXC * xy.x / (1. + 2. * cos(lp.phi)/cos(0.5 * lp.phi)); - lp.phi = RC * (t + sin(lp.phi)); - if (fabs(lp.phi) > 1.) - if (fabs(lp.phi) > ONETOL) I_ERROR - else lp.phi = lp.phi < 0. ? -HALFPI : HALFPI; - else - lp.phi = asin(lp.phi); - return (lp); + + +PJ *PROJECTION(mbtfpq) { + + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(mbtfpq) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + +#ifdef PJ_OMIT_SELFTEST +int pj_mbtfpq_selftest (void) {return 0;} +#else + +int pj_mbtfpq_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=mbtfpq +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 209391.854738393013, 119161.040199054827}, + { 209391.854738393013, -119161.040199054827}, + {-209391.854738393013, 119161.040199054827}, + {-209391.854738393013, -119161.040199054827}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00191010555824111571, 0.000839185447792341723}, + { 0.00191010555824111571, -0.000839185447792341723}, + {-0.00191010555824111571, 0.000839185447792341723}, + {-0.00191010555824111571, -0.000839185447792341723}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From e8fd3d30fb250d6900bc19a11e10892f5902c591 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Thu, 28 Apr 2016 21:40:15 +0200 Subject: Expanded tabs and added test to merc --- src/PJ_aea.c | 1 - src/PJ_merc.c | 126 +++++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 93 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 282c0b88..1ad52655 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -369,7 +369,6 @@ int pj_longlat_selftest (void) {return 10000;} int pj_lee_os_selftest (void) {return 10000;} -int pj_merc_selftest (void) {return 10000;} int pj_mil_os_selftest (void) {return 10000;} int pj_mill_selftest (void) {return 10000;} int pj_misrsom_selftest (void) {return 10000;} diff --git a/src/PJ_merc.c b/src/PJ_merc.c index 89913e50..dd894bbd 100644 --- a/src/PJ_merc.c +++ b/src/PJ_merc.c @@ -1,44 +1,44 @@ #define PJ_LIB__ -#include +#include + PROJ_HEAD(merc, "Mercator") "\n\tCyl, Sph&Ell\n\tlat_ts="; #define EPS10 1.e-10 - static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ XY xy = {0.0,0.0}; - if (fabs(fabs(lp.phi) - HALFPI) <= EPS10) + if (fabs(fabs(lp.phi) - HALFPI) <= EPS10) F_ERROR; - xy.x = P->k0 * lp.lam; - xy.y = - P->k0 * log(pj_tsfn(lp.phi, sin(lp.phi), P->e)); - return xy; + xy.x = P->k0 * lp.lam; + xy.y = - P->k0 * log(pj_tsfn(lp.phi, sin(lp.phi), P->e)); + return xy; } static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ XY xy = {0.0,0.0}; - if (fabs(fabs(lp.phi) - HALFPI) <= EPS10) + if (fabs(fabs(lp.phi) - HALFPI) <= EPS10) F_ERROR; - xy.x = P->k0 * lp.lam; - xy.y = P->k0 * log(tan(FORTPI + .5 * lp.phi)); - return xy; + xy.x = P->k0 * lp.lam; + xy.y = P->k0 * log(tan(FORTPI + .5 * lp.phi)); + return xy; } static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ LP lp = {0.0,0.0}; - if ((lp.phi = pj_phi2(P->ctx, exp(- xy.y / P->k0), P->e)) == HUGE_VAL) + if ((lp.phi = pj_phi2(P->ctx, exp(- xy.y / P->k0), P->e)) == HUGE_VAL) I_ERROR; - lp.lam = xy.x / P->k0; - return lp; + lp.lam = xy.x / P->k0; + return lp; } static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ LP lp = {0.0,0.0}; - lp.phi = HALFPI - 2. * atan(exp(-xy.y / P->k0)); - lp.lam = xy.x / P->k0; - return lp; + lp.phi = HALFPI - 2. * atan(exp(-xy.y / P->k0)); + lp.lam = xy.x / P->k0; + return lp; } @@ -48,27 +48,87 @@ static void freeup(PJ *P) { /* Destructor */ PJ *PROJECTION(merc) { - double phits=0.0; - int is_phits; + double phits=0.0; + int is_phits; - if( (is_phits = pj_param(P->ctx, P->params, "tlat_ts").i) ) { - phits = fabs(pj_param(P->ctx, P->params, "rlat_ts").f); - if (phits >= HALFPI) E_ERROR(-24); - } + if( (is_phits = pj_param(P->ctx, P->params, "tlat_ts").i) ) { + phits = fabs(pj_param(P->ctx, P->params, "rlat_ts").f); + if (phits >= HALFPI) E_ERROR(-24); + } - if (P->es) { /* ellipsoid */ - if (is_phits) - P->k0 = pj_msfn(sin(phits), cos(phits), P->es); - P->inv = e_inverse; - P->fwd = e_forward; - } + if (P->es) { /* ellipsoid */ + if (is_phits) + P->k0 = pj_msfn(sin(phits), cos(phits), P->es); + P->inv = e_inverse; + P->fwd = e_forward; + } else { /* sphere */ - if (is_phits) - P->k0 = cos(phits); - P->inv = s_inverse; - P->fwd = s_forward; - } + if (is_phits) + P->k0 = cos(phits); + P->inv = s_inverse; + P->fwd = s_forward; + } return P; } + + +#ifdef PJ_OMIT_SELFTEST +int pj_merc_selftest (void) {return 0;} +#else + +int pj_merc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=merc +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=merc +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222638.981586547132, 110579.965218249708}, + { 222638.981586547132, -110579.965218249112}, + {-222638.981586547132, 110579.965218249708}, + {-222638.981586547132, -110579.965218249112}, + }; + + XY s_fwd_expect[] = { + { 223402.144255274179, 111706.743574944077}, + { 223402.144255274179, -111706.743574944485}, + {-223402.144255274179, 111706.743574944077}, + {-223402.144255274179, -111706.743574944485}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.00179663056823904264, 0.00090436947522799056}, + { 0.00179663056823904264, -0.00090436947522799056}, + {-0.00179663056823904264, 0.00090436947522799056}, + {-0.00179663056823904264, -0.00090436947522799056}, + }; + + LP s_inv_expect[] = { + { 0.00179049310978382265, 0.000895246554845297135}, + { 0.00179049310978382265, -0.000895246554858019272}, + {-0.00179049310978382265, 0.000895246554845297135}, + {-0.00179049310978382265, -0.000895246554858019272}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 7fa987a337b21c5efc62d5b0f57299929ae5aa5b Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Thu, 28 Apr 2016 21:45:39 +0200 Subject: Converted mill --- src/PJ_aea.c | 1 - src/PJ_mill.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 88 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 1ad52655..8386fe2b 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -370,7 +370,6 @@ int pj_longlat_selftest (void) {return 10000;} int pj_lee_os_selftest (void) {return 10000;} int pj_mil_os_selftest (void) {return 10000;} -int pj_mill_selftest (void) {return 10000;} int pj_misrsom_selftest (void) {return 10000;} int pj_moll_selftest (void) {return 10000;} int pj_natearth_selftest (void) {return 10000;} diff --git a/src/PJ_mill.c b/src/PJ_mill.c index c4cee7f5..2c7fa266 100644 --- a/src/PJ_mill.c +++ b/src/PJ_mill.c @@ -1,17 +1,92 @@ #define PJ_LIB__ -# include +#include + PROJ_HEAD(mill, "Miller Cylindrical") "\n\tCyl, Sph"; -FORWARD(s_forward); /* spheroid */ - (void) P; - xy.x = lp.lam; - xy.y = log(tan(FORTPI + lp.phi * .4)) * 1.25; - return (xy); + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + (void) P; + + xy.x = lp.lam; + xy.y = log(tan(FORTPI + lp.phi * .4)) * 1.25; + + return (xy); } -INVERSE(s_inverse); /* spheroid */ - (void) P; - lp.lam = xy.x; - lp.phi = 2.5 * (atan(exp(.8 * xy.y)) - FORTPI); - return (lp); + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + (void) P; + + lp.lam = xy.x; + lp.phi = 2.5 * (atan(exp(.8 * xy.y)) - FORTPI); + + return (lp); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(mill) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(mill) { + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_mill_selftest (void) {return 0;} +#else + +int pj_mill_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=mill +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223402.144255274179, 111704.701754393827}, + { 223402.144255274179, -111704.701754396243}, + {-223402.144255274179, 111704.701754393827}, + {-223402.144255274179, -111704.701754396243}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00179049310978382265, 0.000895246554873922024}, + { 0.00179049310978382265, -0.000895246554873922024}, + {-0.00179049310978382265, 0.000895246554873922024}, + {-0.00179049310978382265, -0.000895246554873922024}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From c816e2074056f1aa7cd66401b1f48ae4fcb7e18d Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Thu, 28 Apr 2016 22:19:44 +0200 Subject: Converted misrsom --- src/PJ_aea.c | 1 - src/PJ_misrsom.c | 258 ++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 178 insertions(+), 81 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 8386fe2b..1b8c9346 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -370,7 +370,6 @@ int pj_longlat_selftest (void) {return 10000;} int pj_lee_os_selftest (void) {return 10000;} int pj_mil_os_selftest (void) {return 10000;} -int pj_misrsom_selftest (void) {return 10000;} int pj_moll_selftest (void) {return 10000;} int pj_natearth_selftest (void) {return 10000;} int pj_natearth2_selftest (void) {return 10000;} diff --git a/src/PJ_misrsom.c b/src/PJ_misrsom.c index 19518a1d..fdafbd7c 100644 --- a/src/PJ_misrsom.c +++ b/src/PJ_misrsom.c @@ -12,49 +12,57 @@ * * and the following code change: * - * P->rlm = PI * (1. / 248. + .5161290322580645); + * Q->rlm = PI * (1. / 248. + .5161290322580645); * * changed to: * - * P->rlm = 0 + * Q->rlm = 0 * *****************************************************************************/ /* based upon Snyder and Linck, USGS-NMD */ -#define PROJ_PARMS__ \ - double a2, a4, b, c1, c3; \ - double q, t, u, w, p22, sa, ca, xj, rlm, rlm2; #define PJ_LIB__ #include + PROJ_HEAD(misrsom, "Space oblique for MISR") "\n\tCyl, Sph&Ell\n\tpath="; + #define TOL 1e-7 #define PI_HALFPI 4.71238898038468985766 #define TWOPI_HALFPI 7.85398163397448309610 -static void -seraz0(double lam, double mult, PJ *P) { +struct pj_opaque { + double a2, a4, b, c1, c3; + double q, t, u, w, p22, sa, ca, xj, rlm, rlm2; +}; + +static void seraz0(double lam, double mult, PJ *P) { + struct pj_opaque *Q = P->opaque; double sdsq, h, s, fc, sd, sq, d__1; lam *= DEG_TO_RAD; sd = sin(lam); sdsq = sd * sd; - s = P->p22 * P->sa * cos(lam) * sqrt((1. + P->t * sdsq) / (( - 1. + P->w * sdsq) * (1. + P->q * sdsq))); - d__1 = 1. + P->q * sdsq; - h = sqrt((1. + P->q * sdsq) / (1. + P->w * sdsq)) * ((1. + - P->w * sdsq) / (d__1 * d__1) - P->p22 * P->ca); - sq = sqrt(P->xj * P->xj + s * s); - P->b += fc = mult * (h * P->xj - s * s) / sq; - P->a2 += fc * cos(lam + lam); - P->a4 += fc * cos(lam * 4.); - fc = mult * s * (h + P->xj) / sq; - P->c1 += fc * cos(lam); - P->c3 += fc * cos(lam * 3.); + s = Q->p22 * Q->sa * cos(lam) * sqrt((1. + Q->t * sdsq) / (( + 1. + Q->w * sdsq) * (1. + Q->q * sdsq))); + d__1 = 1. + Q->q * sdsq; + h = sqrt((1. + Q->q * sdsq) / (1. + Q->w * sdsq)) * ((1. + + Q->w * sdsq) / (d__1 * d__1) - Q->p22 * Q->ca); + sq = sqrt(Q->xj * Q->xj + s * s); + Q->b += fc = mult * (h * Q->xj - s * s) / sq; + Q->a2 += fc * cos(lam + lam); + Q->a4 += fc * cos(lam * 4.); + fc = mult * s * (h + Q->xj) / sq; + Q->c1 += fc * cos(lam); + Q->c3 += fc * cos(lam * 3.); } -FORWARD(e_forward); /* ellipsoid */ + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; int l, nn; - double lamt, xlam, sdsq, c, d, s, lamdp, phidp, lampp, tanph, - lamtp, cl, sd, sp, fac, sav, tanphi; + double lamt, xlam, sdsq, c, d, s, lamdp, phidp, lampp, tanph; + double lamtp, cl, sd, sp, fac, sav, tanphi; if (lp.phi > HALFPI) lp.phi = HALFPI; @@ -64,65 +72,69 @@ FORWARD(e_forward); /* ellipsoid */ tanphi = tan(lp.phi); for (nn = 0;;) { sav = lampp; - lamtp = lp.lam + P->p22 * lampp; + lamtp = lp.lam + Q->p22 * lampp; cl = cos(lamtp); if (fabs(cl) < TOL) lamtp -= TOL; fac = lampp - sin(lampp) * (cl < 0. ? -HALFPI : HALFPI); for (l = 50; l; --l) { - lamt = lp.lam + P->p22 * sav; + lamt = lp.lam + Q->p22 * sav; if (fabs(c = cos(lamt)) < TOL) lamt -= TOL; - xlam = (P->one_es * tanphi * P->sa + sin(lamt) * P->ca) / c; + xlam = (P->one_es * tanphi * Q->sa + sin(lamt) * Q->ca) / c; lamdp = atan(xlam) + fac; if (fabs(fabs(sav) - fabs(lamdp)) < TOL) break; sav = lamdp; } - if (!l || ++nn >= 3 || (lamdp > P->rlm && lamdp < P->rlm2)) + if (!l || ++nn >= 3 || (lamdp > Q->rlm && lamdp < Q->rlm2)) break; - if (lamdp <= P->rlm) + if (lamdp <= Q->rlm) lampp = TWOPI_HALFPI; - else if (lamdp >= P->rlm2) + else if (lamdp >= Q->rlm2) lampp = HALFPI; } if (l) { sp = sin(lp.phi); - phidp = aasin(P->ctx,(P->one_es * P->ca * sp - P->sa * cos(lp.phi) * + phidp = aasin(P->ctx,(P->one_es * Q->ca * sp - Q->sa * cos(lp.phi) * sin(lamt)) / sqrt(1. - P->es * sp * sp)); tanph = log(tan(FORTPI + .5 * phidp)); sd = sin(lamdp); sdsq = sd * sd; - s = P->p22 * P->sa * cos(lamdp) * sqrt((1. + P->t * sdsq) - / ((1. + P->w * sdsq) * (1. + P->q * sdsq))); - d = sqrt(P->xj * P->xj + s * s); - xy.x = P->b * lamdp + P->a2 * sin(2. * lamdp) + P->a4 * + s = Q->p22 * Q->sa * cos(lamdp) * sqrt((1. + Q->t * sdsq) + / ((1. + Q->w * sdsq) * (1. + Q->q * sdsq))); + d = sqrt(Q->xj * Q->xj + s * s); + xy.x = Q->b * lamdp + Q->a2 * sin(2. * lamdp) + Q->a4 * sin(lamdp * 4.) - tanph * s / d; - xy.y = P->c1 * sd + P->c3 * sin(lamdp * 3.) + tanph * P->xj / d; + xy.y = Q->c1 * sd + Q->c3 * sin(lamdp * 3.) + tanph * Q->xj / d; } else xy.x = xy.y = HUGE_VAL; return xy; } -INVERSE(e_inverse); /* ellipsoid */ + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; int nn; double lamt, sdsq, s, lamdp, phidp, sppsq, dd, sd, sl, fac, scl, sav, spp; - lamdp = xy.x / P->b; + lamdp = xy.x / Q->b; nn = 50; do { - sav = lamdp; - sd = sin(lamdp); - sdsq = sd * sd; - s = P->p22 * P->sa * cos(lamdp) * sqrt((1. + P->t * sdsq) - / ((1. + P->w * sdsq) * (1. + P->q * sdsq))); - lamdp = xy.x + xy.y * s / P->xj - P->a2 * sin( - 2. * lamdp) - P->a4 * sin(lamdp * 4.) - s / P->xj * ( - P->c1 * sin(lamdp) + P->c3 * sin(lamdp * 3.)); - lamdp /= P->b; + sav = lamdp; + sd = sin(lamdp); + sdsq = sd * sd; + s = Q->p22 * Q->sa * cos(lamdp) * sqrt((1. + Q->t * sdsq) + / ((1. + Q->w * sdsq) * (1. + Q->q * sdsq))); + lamdp = xy.x + xy.y * s / Q->xj - Q->a2 * sin( + 2. * lamdp) - Q->a4 * sin(lamdp * 4.) - s / Q->xj * ( + Q->c1 * sin(lamdp) + Q->c3 * sin(lamdp * 3.)); + lamdp /= Q->b; } while (fabs(lamdp - sav) >= TOL && --nn); sl = sin(lamdp); - fac = exp(sqrt(1. + s * s / P->xj / P->xj) * (xy.y - - P->c1 * sl - P->c3 * sin(lamdp * 3.))); + fac = exp(sqrt(1. + s * s / Q->xj / Q->xj) * (xy.y - + Q->c1 * sl - Q->c3 * sin(lamdp * 3.))); phidp = 2. * (atan(fac) - FORTPI); dd = sl * sl; if (fabs(cos(lamdp)) < TOL) @@ -130,22 +142,44 @@ INVERSE(e_inverse); /* ellipsoid */ spp = sin(phidp); sppsq = spp * spp; lamt = atan(((1. - sppsq * P->rone_es) * tan(lamdp) * - P->ca - spp * P->sa * sqrt((1. + P->q * dd) * ( - 1. - sppsq) - sppsq * P->u) / cos(lamdp)) / (1. - sppsq - * (1. + P->u))); + Q->ca - spp * Q->sa * sqrt((1. + Q->q * dd) * ( + 1. - sppsq) - sppsq * Q->u) / cos(lamdp)) / (1. - sppsq + * (1. + Q->u))); sl = lamt >= 0. ? 1. : -1.; scl = cos(lamdp) >= 0. ? 1. : -1; lamt -= HALFPI * (1. - scl) * sl; - lp.lam = lamt - P->p22 * lamdp; - if (fabs(P->sa) < TOL) + lp.lam = lamt - Q->p22 * lamdp; + if (fabs(Q->sa) < TOL) lp.phi = aasin(P->ctx,spp / sqrt(P->one_es * P->one_es + P->es * sppsq)); else - lp.phi = atan((tan(lamdp) * cos(lamt) - P->ca * sin(lamt)) / - (P->one_es * P->sa)); + lp.phi = atan((tan(lamdp) * cos(lamt) - Q->ca * sin(lamt)) / + (P->one_es * Q->sa)); return lp; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(misrsom) + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(misrsom) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + int path; double lam, alf, esc, ess; @@ -153,33 +187,97 @@ ENTRY0(misrsom) if (path <= 0 || path > 233) E_ERROR(-29); P->lam0 = DEG_TO_RAD * 129.3056 - TWOPI / 233. * path; alf = 98.30382 * DEG_TO_RAD; - P->p22 = 98.88 / 1440.0; - - P->sa = sin(alf); - P->ca = cos(alf); - if (fabs(P->ca) < 1e-9) - P->ca = 1e-9; - esc = P->es * P->ca * P->ca; - ess = P->es * P->sa * P->sa; - P->w = (1. - esc) * P->rone_es; - P->w = P->w * P->w - 1.; - P->q = ess * P->rone_es; - P->t = ess * (2. - P->es) * P->rone_es * P->rone_es; - P->u = esc * P->rone_es; - P->xj = P->one_es * P->one_es * P->one_es; - P->rlm = 0; - P->rlm2 = P->rlm + TWOPI; - P->a2 = P->a4 = P->b = P->c1 = P->c3 = 0.; + Q->p22 = 98.88 / 1440.0; + + Q->sa = sin(alf); + Q->ca = cos(alf); + if (fabs(Q->ca) < 1e-9) + Q->ca = 1e-9; + esc = P->es * Q->ca * Q->ca; + ess = P->es * Q->sa * Q->sa; + Q->w = (1. - esc) * P->rone_es; + Q->w = Q->w * Q->w - 1.; + Q->q = ess * P->rone_es; + Q->t = ess * (2. - P->es) * P->rone_es * P->rone_es; + Q->u = esc * P->rone_es; + Q->xj = P->one_es * P->one_es * P->one_es; + Q->rlm = 0; + Q->rlm2 = Q->rlm + TWOPI; + Q->a2 = Q->a4 = Q->b = Q->c1 = Q->c3 = 0.; seraz0(0., 1., P); for (lam = 9.; lam <= 81.0001; lam += 18.) seraz0(lam, 4., P); for (lam = 18; lam <= 72.0001; lam += 18.) seraz0(lam, 2., P); seraz0(90., 1., P); - P->a2 /= 30.; - P->a4 /= 60.; - P->b /= 30.; - P->c1 /= 15.; - P->c3 /= 45.; - P->inv = e_inverse; P->fwd = e_forward; -ENDENTRY(P) + Q->a2 /= 30.; + Q->a4 /= 60.; + Q->b /= 30.; + Q->c1 /= 15.; + Q->c3 /= 45.; + + P->inv = e_inverse; + P->fwd = e_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_misrsom_selftest (void) {return 0;} +#else + +int pj_misrsom_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=misrsom +ellps=GRS80 +lat_1=0.5 +lat_2=2 +path=1"}; + char s_args[] = {"+proj=misrsom +a=6400000 +lat_1=0.5 +lat_2=2 +path=1"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {18556630.3683698252, 9533394.6753112711}, + {19041866.0067297369, 9707182.17532352544}, + {18816810.1301847994, 8647669.64980295487}, + {19252610.7845367305, 8778164.08580140397}, + }; + + XY s_fwd_expect[] = { + {18641249.2791703865, 9563342.53233416565}, + {19130982.4615812786, 9739539.59350463562}, + {18903483.5150115378, 8675064.50061797537}, + {19343388.3998006098, 8807471.90406848863}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {127.759503987730625, 0.00173515039622462014}, + {127.761295471077958, 0.00187196632421706517}, + {127.759775773557251, -0.00187196632421891525}, + {127.76156725690457, -0.00173515039622462014}, + }; + + LP s_inv_expect[] = { + {127.75950514818588, 0.00171623111593511971}, + {127.761290323778738, 0.00185412132880796244}, + {127.759780920856471, -0.00185412132880796244}, + {127.761566096449329, -0.00171623111593511971}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 566eee06187edbb0d67a9207b5b2fbe18ce60153 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sat, 30 Apr 2016 22:42:50 +0200 Subject: Converted mil_os, lee_os, gs48, alsk, gs50 --- src/PJ_aea.c | 6 - src/PJ_mod_ster.c | 713 +++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 520 insertions(+), 199 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 1b8c9346..e1d6013d 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -354,22 +354,16 @@ source files ***********************************************************************/ int pj_aeqd_selftest (void) {return 10000;} -int pj_alsk_selftest (void) {return 10000;} int pj_eqc_selftest (void) {return 10000;} int pj_eqdc_selftest (void) {return 10000;} int pj_etmerc_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} -int pj_gs48_selftest (void) {return 10000;} -int pj_gs50_selftest (void) {return 10000;} int pj_latlon_selftest (void) {return 10000;} int pj_latlong_selftest (void) {return 10000;} int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} -int pj_lee_os_selftest (void) {return 10000;} - -int pj_mil_os_selftest (void) {return 10000;} int pj_moll_selftest (void) {return 10000;} int pj_natearth_selftest (void) {return 10000;} int pj_natearth2_selftest (void) {return 10000;} diff --git a/src/PJ_mod_ster.c b/src/PJ_mod_ster.c index 185e95e3..551b83bd 100644 --- a/src/PJ_mod_ster.c +++ b/src/PJ_mod_ster.c @@ -1,211 +1,538 @@ /* based upon Snyder and Linck, USGS-NMD */ -#define PROJ_PARMS__ \ - COMPLEX *zcoeff; \ - double cchio, schio; \ - int n; #define PJ_LIB__ -#include +#include + PROJ_HEAD(mil_os, "Miller Oblated Stereographic") "\n\tAzi(mod)"; PROJ_HEAD(lee_os, "Lee Oblated Stereographic") "\n\tAzi(mod)"; PROJ_HEAD(gs48, "Mod. Stererographics of 48 U.S.") "\n\tAzi(mod)"; PROJ_HEAD(alsk, "Mod. Stererographics of Alaska") "\n\tAzi(mod)"; PROJ_HEAD(gs50, "Mod. Stererographics of 50 U.S.") "\n\tAzi(mod)"; + #define EPSLN 1e-10 -FORWARD(e_forward); /* ellipsoid */ - double sinlon, coslon, esphi, chi, schi, cchi, s; - COMPLEX p; - - sinlon = sin(lp.lam); - coslon = cos(lp.lam); - esphi = P->e * sin(lp.phi); - chi = 2. * atan(tan((HALFPI + lp.phi) * .5) * - pow((1. - esphi) / (1. + esphi), P->e * .5)) - HALFPI; - schi = sin(chi); - cchi = cos(chi); - s = 2. / (1. + P->schio * schi + P->cchio * cchi * coslon); - p.r = s * cchi * sinlon; - p.i = s * (P->cchio * schi - P->schio * cchi * coslon); - p = pj_zpoly1(p, P->zcoeff, P->n); - xy.x = p.r; - xy.y = p.i; - return xy; +struct pj_opaque { + COMPLEX *zcoeff; \ + double cchio, schio; \ + int n; +}; + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double sinlon, coslon, esphi, chi, schi, cchi, s; + COMPLEX p; + + sinlon = sin(lp.lam); + coslon = cos(lp.lam); + esphi = P->e * sin(lp.phi); + chi = 2. * atan(tan((HALFPI + lp.phi) * .5) * + pow((1. - esphi) / (1. + esphi), P->e * .5)) - HALFPI; + schi = sin(chi); + cchi = cos(chi); + s = 2. / (1. + Q->schio * schi + Q->cchio * cchi * coslon); + p.r = s * cchi * sinlon; + p.i = s * (Q->cchio * schi - Q->schio * cchi * coslon); + p = pj_zpoly1(p, Q->zcoeff, Q->n); + xy.x = p.r; + xy.y = p.i; + + return xy; } -INVERSE(e_inverse); /* ellipsoid */ - int nn; - COMPLEX p, fxy, fpxy, dp; - double den, rh, z, sinz, cosz, chi, phi, dphi, esphi; - - p.r = xy.x; - p.i = xy.y; - for (nn = 20; nn ;--nn) { - fxy = pj_zpolyd1(p, P->zcoeff, P->n, &fpxy); - fxy.r -= xy.x; - fxy.i -= xy.y; - den = fpxy.r * fpxy.r + fpxy.i * fpxy.i; - dp.r = -(fxy.r * fpxy.r + fxy.i * fpxy.i) / den; - dp.i = -(fxy.i * fpxy.r - fxy.r * fpxy.i) / den; - p.r += dp.r; - p.i += dp.i; - if ((fabs(dp.r) + fabs(dp.i)) <= EPSLN) - break; - } - if (nn) { - rh = hypot(p.r, p.i); - z = 2. * atan(.5 * rh); - sinz = sin(z); - cosz = cos(z); - lp.lam = P->lam0; - if (fabs(rh) <= EPSLN) { - lp.phi = P->phi0; - return lp; - } - chi = aasin(P->ctx, cosz * P->schio + p.i * sinz * P->cchio / rh); - phi = chi; - for (nn = 20; nn ;--nn) { - esphi = P->e * sin(phi); - dphi = 2. * atan(tan((HALFPI + chi) * .5) * - pow((1. + esphi) / (1. - esphi), P->e * .5)) - HALFPI - phi; - phi += dphi; - if (fabs(dphi) <= EPSLN) - break; - } - } - if (nn) { - lp.phi = phi; - lp.lam = atan2(p.r * sinz, rh * P->cchio * cosz - p.i * - P->schio * sinz); + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + int nn; + COMPLEX p, fxy, fpxy, dp; + double den, rh, z, sinz, cosz, chi, phi, dphi, esphi; + + p.r = xy.x; + p.i = xy.y; + for (nn = 20; nn ;--nn) { + fxy = pj_zpolyd1(p, Q->zcoeff, Q->n, &fpxy); + fxy.r -= xy.x; + fxy.i -= xy.y; + den = fpxy.r * fpxy.r + fpxy.i * fpxy.i; + dp.r = -(fxy.r * fpxy.r + fxy.i * fpxy.i) / den; + dp.i = -(fxy.i * fpxy.r - fxy.r * fpxy.i) / den; + p.r += dp.r; + p.i += dp.i; + if ((fabs(dp.r) + fabs(dp.i)) <= EPSLN) + break; + } + if (nn) { + rh = hypot(p.r, p.i); + z = 2. * atan(.5 * rh); + sinz = sin(z); + cosz = cos(z); + lp.lam = P->lam0; + if (fabs(rh) <= EPSLN) { + lp.phi = P->phi0; + return lp; + } + chi = aasin(P->ctx, cosz * Q->schio + p.i * sinz * Q->cchio / rh); + phi = chi; + for (nn = 20; nn ;--nn) { + esphi = P->e * sin(phi); + dphi = 2. * atan(tan((HALFPI + chi) * .5) * + pow((1. + esphi) / (1. - esphi), P->e * .5)) - HALFPI - phi; + phi += dphi; + if (fabs(dphi) <= EPSLN) + break; + } + } + if (nn) { + lp.phi = phi; + lp.lam = atan2(p.r * sinz, rh * Q->cchio * cosz - p.i * + Q->schio * sinz); } else - lp.lam = lp.phi = HUGE_VAL; - return lp; + lp.lam = lp.phi = HUGE_VAL; + return lp; } -FREEUP; if (P) pj_dalloc(P); } - static PJ * -setup(PJ *P) { /* general initialization */ - double esphi, chio; - - if (P->es) { - esphi = P->e * sin(P->phi0); - chio = 2. * atan(tan((HALFPI + P->phi0) * .5) * - pow((1. - esphi) / (1. + esphi), P->e * .5)) - HALFPI; - } else - chio = P->phi0; - P->schio = sin(chio); - P->cchio = cos(chio); - P->inv = e_inverse; P->fwd = e_forward; - return P; + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); } -ENTRY0(mil_os) - static COMPLEX /* Miller Oblated Stereographic */ -AB[] = { - {0.924500, 0.}, - {0., 0.}, - {0.019430, 0.} -}; - P->n = 2; - P->lam0 = DEG_TO_RAD * 20.; - P->phi0 = DEG_TO_RAD * 18.; - P->zcoeff = AB; - P->es = 0.; -ENDENTRY(setup(P)) -ENTRY0(lee_os) - static COMPLEX /* Lee Oblated Stereographic */ -AB[] = { - {0.721316, 0.}, - {0., 0.}, - {-0.0088162, -0.00617325} -}; +static void freeup (PJ *P) { + freeup_new (P); + return; +} - P->n = 2; - P->lam0 = DEG_TO_RAD * -165.; - P->phi0 = DEG_TO_RAD * -10.; - P->zcoeff = AB; - P->es = 0.; -ENDENTRY(setup(P)) -ENTRY0(gs48) - static COMPLEX /* 48 United States */ -AB[] = { - {0.98879, 0.}, - {0., 0.}, - {-0.050909, 0.}, - {0., 0.}, - {0.075528, 0.} -}; +static PJ *setup(PJ *P) { /* general initialization */ + struct pj_opaque *Q = P->opaque; + double esphi, chio; - P->n = 4; - P->lam0 = DEG_TO_RAD * -96.; - P->phi0 = DEG_TO_RAD * -39.; - P->zcoeff = AB; - P->es = 0.; - P->a = 6370997.; -ENDENTRY(setup(P)) -ENTRY0(alsk) - static COMPLEX -ABe[] = { /* Alaska ellipsoid */ - {.9945303, 0.}, - {.0052083, -.0027404}, - {.0072721, .0048181}, - {-.0151089, -.1932526}, - {.0642675, -.1381226}, - {.3582802, -.2884586}}, -ABs[] = { /* Alaska sphere */ - {.9972523, 0.}, - {.0052513, -.0041175}, - {.0074606, .0048125}, - {-.0153783, -.1968253}, - {.0636871, -.1408027}, - {.3660976, -.2937382} -}; + if (P->es) { + esphi = P->e * sin(P->phi0); + chio = 2. * atan(tan((HALFPI + P->phi0) * .5) * + pow((1. - esphi) / (1. + esphi), P->e * .5)) - HALFPI; + } else + chio = P->phi0; + Q->schio = sin(chio); + Q->cchio = cos(chio); + P->inv = e_inverse; + P->fwd = e_forward; + + return P; +} + + +/* Miller Oblated Stereographic */ +PJ *PROJECTION(mil_os) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + static COMPLEX AB[] = { + {0.924500, 0.}, + {0., 0.}, + {0.019430, 0.} + }; + + Q->n = 2; + P->lam0 = DEG_TO_RAD * 20.; + P->phi0 = DEG_TO_RAD * 18.; + Q->zcoeff = AB; + P->es = 0.; + + return setup(P); +} + + +/* Lee Oblated Stereographic */ +PJ *PROJECTION(lee_os) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + static COMPLEX AB[] = { + {0.721316, 0.}, + {0., 0.}, + {-0.0088162, -0.00617325} + }; + + Q->n = 2; + P->lam0 = DEG_TO_RAD * -165.; + P->phi0 = DEG_TO_RAD * -10.; + Q->zcoeff = AB; + P->es = 0.; + + return setup(P); +} + + +PJ *PROJECTION(gs48) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + static COMPLEX /* 48 United States */ + AB[] = { + {0.98879, 0.}, + {0., 0.}, + {-0.050909, 0.}, + {0., 0.}, + {0.075528, 0.} + }; + + Q->n = 4; + P->lam0 = DEG_TO_RAD * -96.; + P->phi0 = DEG_TO_RAD * -39.; + Q->zcoeff = AB; + P->es = 0.; + P->a = 6370997.; + + return setup(P); +} + + +PJ *PROJECTION(alsk) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + static COMPLEX ABe[] = { /* Alaska ellipsoid */ + { .9945303, 0.}, + { .0052083, -.0027404}, + { .0072721, .0048181}, + {-.0151089, -.1932526}, + { .0642675, -.1381226}, + { .3582802, -.2884586}, + }; + + static COMPLEX ABs[] = { /* Alaska sphere */ + { .9972523, 0.}, + { .0052513, -.0041175}, + { .0074606, .0048125}, + {-.0153783, -.1968253}, + { .0636871, -.1408027}, + { .3660976, -.2937382} + }; + + Q->n = 5; + P->lam0 = DEG_TO_RAD * -152.; + P->phi0 = DEG_TO_RAD * 64.; + if (P->es) { /* fixed ellipsoid/sphere */ + Q->zcoeff = ABe; + P->a = 6378206.4; + P->e = sqrt(P->es = 0.00676866); + } else { + Q->zcoeff = ABs; + P->a = 6370997.; + } + + return setup(P); +} + + +PJ *PROJECTION(gs50) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + static COMPLEX ABe[] = { /* GS50 ellipsoid */ + { .9827497, 0.}, + { .0210669, .0053804}, + {-.1031415, -.0571664}, + {-.0323337, -.0322847}, + { .0502303, .1211983}, + { .0251805, .0895678}, + {-.0012315, -.1416121}, + { .0072202, -.1317091}, + {-.0194029, .0759677}, + {-.0210072, .0834037} + }; + + static COMPLEX ABs[] = { /* GS50 sphere */ + { .9842990, 0.}, + { .0211642, .0037608}, + {-.1036018, -.0575102}, + {-.0329095, -.0320119}, + { .0499471, .1223335}, + { .0260460, .0899805}, + { .0007388, -.1435792}, + { .0075848, -.1334108}, + {-.0216473, .0776645}, + {-.0225161, .0853673} + }; + + Q->n = 9; + P->lam0 = DEG_TO_RAD * -120.; + P->phi0 = DEG_TO_RAD * 45.; + if (P->es) { /* fixed ellipsoid/sphere */ + Q->zcoeff = ABe; + P->a = 6378206.4; + P->e = sqrt(P->es = 0.00676866); + } else { + Q->zcoeff = ABs; + P->a = 6370997.; + } + + return setup(P); +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_mil_os_selftest (void) {return 0;} +#else + +int pj_mil_os_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=mil_os +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {-1908527.94959420455, -1726237.4730614475}, + {-1916673.02291848511, -1943133.88812552323}, + {-2344429.41208962305, -1706258.05121891224}, + {-2354637.83553299867, -1926468.60513541684}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + {20.0020363939492398, 18.0009683469140498}, + {20.0020363715837419, 17.999031631815086}, + {19.9979636060507602, 18.0009683469140498}, + {19.9979636284162581, 17.999031631815086}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + +#endif + + +#ifdef PJ_OMIT_SELFTEST +int pj_lee_os_selftest (void) {return 0;} +#else + +int pj_lee_os_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=lee_os +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {-25564478.9526050538, 154490848.8286255}, + { 30115393.9385746419, 125193997.439701974}, + {-31039340.5921660066, 57678685.0448915437}, + {-3088419.93942357088, 58150091.0991110131}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + {-164.997479457813824, -9.99875886103541411}, + {-164.997479438558884, -10.0012411200022751}, + {-165.002520542186289, -9.99875886103545142}, + {-165.002520561440946, -10.0012411200022999}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + +#endif + + +#ifdef PJ_OMIT_SELFTEST +int pj_gs48_selftest (void) {return 0;} +#else + +int pj_gs48_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=gs48 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {36625944.1923860237, -10443454.370062707}, + {32392147.7449533679, -12580705.358382076}, + {31394918.3206626177, -3352580.92795714363}, + {28553241.7702435851, -5673083.97367164213}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + {-95.997669975773789, -38.9990945807843801}, + {-95.9976699161415326, -39.0009053728726585}, + {-96.0023300242262252, -38.9990945807843801}, + {-96.0023300838584817, -39.0009053728726585}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + +#endif + + +#ifdef PJ_OMIT_SELFTEST +int pj_alsk_selftest (void) {return 0;} +#else + +int pj_alsk_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=alsk +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=alsk +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {1642864080.02732754, -1139302009.02887797}, + {1991193850.2052319, -1518851027.13339996}, + { 896601956.44416213, -1580143099.4169271}, + {1018553822.30535674, -2028874099.61853552}, + }; + + XY s_fwd_expect[] = { + {1651105846.06753755, -1132233885.29928017}, + {2004822703.03845358, -1512578241.93150067}, + { 907039096.196665168, -1578565868.60405397}, + {1033243931.08174837, -2030485879.68075895}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {-151.99590140340095, 64.0008994430213534}, + {-151.995901665843263, 63.9991004415502687}, + {-152.004098597614217, 64.0008994436154524}, + {-152.004098335171818, 63.9991004409561413}, + }; + + LP s_inv_expect[] = { + {-151.995904192970613, 64.0008976554005926}, + {-151.995904455051942, 63.9991022295943921}, + {-152.004095808043218, 64.0008976559930716}, + {-152.004095545961775, 63.9991022290018208}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + +#endif + + +#ifdef PJ_OMIT_SELFTEST +int pj_gs50_selftest (void) {return 0;} +#else + +int pj_gs50_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=gs50 +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=gs50 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {29729016747.3571701, -3918216218.3354063}, + {36735969814.5893631, -14677374776.9809761}, + {14161556831.8443203, -11410194658.0201168}, + {14213883663.1140423, -19065362387.8745575}, + }; + + XY s_fwd_expect[] = { + {30210185088.2270584, -3211636634.93554688}, + {37664745793.3519745, -13981519124.6516781}, + {14657726636.8231983, -11238369787.8965397}, + {14923510723.7682972, -19062616309.6883698}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {-119.997423271634844, 45.0009140704890811}, + {-119.997423354194112, 44.9990858708950014}, + {-120.00257673100937, 45.0009140729899428}, + {-120.002576648448965, 44.9990858683939408}, + }; + + LP s_inv_expect[] = { + {-119.997427429220934, 45.0009094967551704}, + {-119.997427511518453, 44.9990904451617482}, + {-120.002572573413815, 45.0009094992385954}, + {-120.00257249111516, 44.9990904426780602}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} - P->n = 5; - P->lam0 = DEG_TO_RAD * -152.; - P->phi0 = DEG_TO_RAD * 64.; - if (P->es) { /* fixed ellipsoid/sphere */ - P->zcoeff = ABe; - P->a = 6378206.4; - P->e = sqrt(P->es = 0.00676866); - } else { - P->zcoeff = ABs; - P->a = 6370997.; - } -ENDENTRY(setup(P)) -ENTRY0(gs50) - static COMPLEX -ABe[] = { /* GS50 ellipsoid */ - {.9827497, 0.}, - {.0210669, .0053804}, - {-.1031415, -.0571664}, - {-.0323337, -.0322847}, - {.0502303, .1211983}, - {.0251805, .0895678}, - {-.0012315, -.1416121}, - {.0072202, -.1317091}, - {-.0194029, .0759677}, - {-.0210072, .0834037} -}, -ABs[] = { /* GS50 sphere */ - {.9842990, 0.}, - {.0211642, .0037608}, - {-.1036018, -.0575102}, - {-.0329095, -.0320119}, - {.0499471, .1223335}, - {.0260460, .0899805}, - {.0007388, -.1435792}, - {.0075848, -.1334108}, - {-.0216473, .0776645}, - {-.0225161, .0853673} -}; - P->n = 9; - P->lam0 = DEG_TO_RAD * -120.; - P->phi0 = DEG_TO_RAD * 45.; - if (P->es) { /* fixed ellipsoid/sphere */ - P->zcoeff = ABe; - P->a = 6378206.4; - P->e = sqrt(P->es = 0.00676866); - } else { - P->zcoeff = ABs; - P->a = 6370997.; - } -ENDENTRY(setup(P)) +#endif -- cgit v1.2.3 From 0dc0b3aa66542bf011c85686b7b10d0cf92811a5 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sat, 30 Apr 2016 23:55:10 +0200 Subject: Converted moll, wag4 and wag5 --- src/PJ_aea.c | 3 - src/PJ_moll.c | 299 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 247 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index e1d6013d..dd0c0f48 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -364,7 +364,6 @@ int pj_latlong_selftest (void) {return 10000;} int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} -int pj_moll_selftest (void) {return 10000;} int pj_natearth_selftest (void) {return 10000;} int pj_natearth2_selftest (void) {return 10000;} int pj_nell_selftest (void) {return 10000;} @@ -401,7 +400,5 @@ int pj_vandg_selftest (void) {return 10000;} int pj_vandg2_selftest (void) {return 10000;} int pj_vandg3_selftest (void) {return 10000;} int pj_vandg4_selftest (void) {return 10000;} -int pj_wag4_selftest (void) {return 10000;} -int pj_wag5_selftest (void) {return 10000;} int pj_weren_selftest (void) {return 10000;} #endif diff --git a/src/PJ_moll.c b/src/PJ_moll.c index cf9369dc..31829b68 100644 --- a/src/PJ_moll.c +++ b/src/PJ_moll.c @@ -1,64 +1,259 @@ -#define PROJ_PARMS__ \ - double C_x, C_y, C_p; #define PJ_LIB__ -#include +#include + PROJ_HEAD(moll, "Mollweide") "\n\tPCyl., Sph."; PROJ_HEAD(wag4, "Wagner IV") "\n\tPCyl., Sph."; PROJ_HEAD(wag5, "Wagner V") "\n\tPCyl., Sph."; -#define MAX_ITER 10 -#define LOOP_TOL 1e-7 -FORWARD(s_forward); /* spheroid */ - double k, V; - int i; - - k = P->C_p * sin(lp.phi); - for (i = MAX_ITER; i ; --i) { - lp.phi -= V = (lp.phi + sin(lp.phi) - k) / - (1. + cos(lp.phi)); - if (fabs(V) < LOOP_TOL) - break; - } - if (!i) - lp.phi = (lp.phi < 0.) ? -HALFPI : HALFPI; - else - lp.phi *= 0.5; - xy.x = P->C_x * lp.lam * cos(lp.phi); - xy.y = P->C_y * sin(lp.phi); - return (xy); + +#define MAX_ITER 10 +#define LOOP_TOL 1e-7 + +struct pj_opaque { + double C_x, C_y, C_p; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double k, V; + int i; + + k = Q->C_p * sin(lp.phi); + for (i = MAX_ITER; i ; --i) { + lp.phi -= V = (lp.phi + sin(lp.phi) - k) / + (1. + cos(lp.phi)); + if (fabs(V) < LOOP_TOL) + break; + } + if (!i) + lp.phi = (lp.phi < 0.) ? -HALFPI : HALFPI; + else + lp.phi *= 0.5; + xy.x = Q->C_x * lp.lam * cos(lp.phi); + xy.y = Q->C_y * sin(lp.phi); + return xy; } -INVERSE(s_inverse); /* spheroid */ - lp.phi = aasin(P->ctx, xy.y / P->C_y); - lp.lam = xy.x / (P->C_x * cos(lp.phi)); + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + lp.phi = aasin(P->ctx, xy.y / Q->C_y); + lp.lam = xy.x / (Q->C_x * cos(lp.phi)); if (fabs(lp.lam) < PI) { lp.phi += lp.phi; - lp.phi = aasin(P->ctx, (lp.phi + sin(lp.phi)) / P->C_p); + lp.phi = aasin(P->ctx, (lp.phi + sin(lp.phi)) / Q->C_p); } else { lp.lam = lp.phi = HUGE_VAL; } - return (lp); + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +static PJ * setup(PJ *P, double p) { + struct pj_opaque *Q = P->opaque; + double r, sp, p2 = p + p; + + P->es = 0; + sp = sin(p); + r = sqrt(TWOPI * sp / (p2 + sin(p2))); + + Q->C_x = 2. * r / PI; + Q->C_y = r / sp; + Q->C_p = p2 + sin(p2); + + P->inv = s_inverse; + P->fwd = s_forward; + return P; +} + + +PJ *PROJECTION(moll) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + return setup(P, HALFPI); +} + + +PJ *PROJECTION(wag4) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + return setup(P, PI/3.); +} + +PJ *PROJECTION(wag5) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->es = 0; + Q->C_x = 0.90977; + Q->C_y = 1.65014; + Q->C_p = 3.00896; + + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_moll_selftest (void) {return 0;} +#else + +int pj_moll_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=moll +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {201113.698641813244, 124066.283433859542}, + {201113.698641813244, -124066.283433859542}, + {-201113.698641813244, 124066.283433859542}, + {-201113.698641813244, -124066.283433859542}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + {0.00198873782220854774, 0.000806005080362811612}, + {0.00198873782220854774, -0.000806005080362811612}, + {-0.00198873782220854774, 0.000806005080362811612}, + {-0.00198873782220854774, -0.000806005080362811612}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); } -FREEUP; if (P) pj_dalloc(P); } - static PJ * -setup(PJ *P, double p) { - double r, sp, p2 = p + p; - - P->es = 0; - sp = sin(p); - r = sqrt(TWOPI * sp / (p2 + sin(p2))); - P->C_x = 2. * r / PI; - P->C_y = r / sp; - P->C_p = p2 + sin(p2); - P->inv = s_inverse; - P->fwd = s_forward; - return P; + +#endif + + +#ifdef PJ_OMIT_SELFTEST +int pj_wag4_selftest (void) {return 0;} +#else + +int pj_wag4_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=wag4 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 192801.218662384286, 129416.216394802992}, + { 192801.218662384286, -129416.216394802992}, + {-192801.218662384286, 129416.216394802992}, + {-192801.218662384286, -129416.216394802992}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00207450259783523421, 0.000772682950537716476}, + { 0.00207450259783523421, -0.000772682950537716476}, + {-0.00207450259783523421, 0.000772682950537716476}, + {-0.00207450259783523421, -0.000772682950537716476}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); } -ENTRY0(moll) ENDENTRY(setup(P, HALFPI)) -ENTRY0(wag4) ENDENTRY(setup(P, PI/3.)) -ENTRY0(wag5) - P->es = 0; - P->C_x = 0.90977; - P->C_y = 1.65014; - P->C_p = 3.00896; - P->inv = s_inverse; - P->fwd = s_forward; -ENDENTRY(P) + +#endif + +#ifdef PJ_OMIT_SELFTEST +int pj_wag5_selftest (void) {return 0;} +#else + +int pj_wag5_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=wag5 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + + XY s_fwd_expect[] = { + { 203227.05192532466, 138651.631442713202}, + { 203227.05192532466, -138651.631442713202}, + {-203227.05192532466, 138651.631442713202}, + {-203227.05192532466, -138651.631442713202}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + + + + LP s_inv_expect[] = { + { 0.00196807227086416396, 0.00072121615041701424}, + { 0.00196807227086416396, -0.00072121615041701424}, + {-0.00196807227086416396, 0.00072121615041701424}, + {-0.00196807227086416396, -0.00072121615041701424}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 3b41444bef2168f5a109e7fd69676e45a00ccda3 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sun, 1 May 2016 11:59:58 +0200 Subject: Converted natearth --- src/PJ_aea.c | 1 - src/PJ_natearth.c | 153 +++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 112 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index dd0c0f48..c5480d1e 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -364,7 +364,6 @@ int pj_latlong_selftest (void) {return 10000;} int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} -int pj_natearth_selftest (void) {return 10000;} int pj_natearth2_selftest (void) {return 10000;} int pj_nell_selftest (void) {return 10000;} int pj_nell_h_selftest (void) {return 10000;} diff --git a/src/PJ_natearth.c b/src/PJ_natearth.c index 0f283415..290f8efe 100644 --- a/src/PJ_natearth.c +++ b/src/PJ_natearth.c @@ -12,10 +12,11 @@ where they meet the horizontal pole line. This improvement is by intention and designed in collaboration with Tom Patterson. Port to PROJ.4 by Bernhard Jenny, 6 June 2011 */ - #define PJ_LIB__ -#include +#include + PROJ_HEAD(natearth, "Natural Earth") "\n\tPCyl., Sph."; + #define A0 0.8707 #define A1 -0.131979 #define A2 -0.013791 @@ -34,46 +35,116 @@ PROJ_HEAD(natearth, "Natural Earth") "\n\tPCyl., Sph."; #define EPS 1e-11 #define MAX_Y (0.8707 * 0.52 * PI) -FORWARD(s_forward); /* spheroid */ - double phi2, phi4; - (void) P; - phi2 = lp.phi * lp.phi; - phi4 = phi2 * phi2; - xy.x = lp.lam * (A0 + phi2 * (A1 + phi2 * (A2 + phi4 * phi2 * (A3 + phi2 * A4)))); - xy.y = lp.phi * (B0 + phi2 * (B1 + phi4 * (B2 + B3 * phi2 + B4 * phi4))); - return (xy); +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + double phi2, phi4; + (void) P; + + phi2 = lp.phi * lp.phi; + phi4 = phi2 * phi2; + xy.x = lp.lam * (A0 + phi2 * (A1 + phi2 * (A2 + phi4 * phi2 * (A3 + phi2 * A4)))); + xy.y = lp.phi * (B0 + phi2 * (B1 + phi4 * (B2 + B3 * phi2 + B4 * phi4))); + return xy; } -INVERSE(s_inverse); /* spheroid */ - double yc, tol, y2, y4, f, fder; - (void) P; - - /* make sure y is inside valid range */ - if (xy.y > MAX_Y) { - xy.y = MAX_Y; - } else if (xy.y < -MAX_Y) { - xy.y = -MAX_Y; - } - - /* latitude */ - yc = xy.y; + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + double yc, tol, y2, y4, f, fder; + (void) P; + + /* make sure y is inside valid range */ + if (xy.y > MAX_Y) { + xy.y = MAX_Y; + } else if (xy.y < -MAX_Y) { + xy.y = -MAX_Y; + } + + /* latitude */ + yc = xy.y; for (;;) { /* Newton-Raphson */ - y2 = yc * yc; - y4 = y2 * y2; - f = (yc * (B0 + y2 * (B1 + y4 * (B2 + B3 * y2 + B4 * y4)))) - xy.y; - fder = C0 + y2 * (C1 + y4 * (C2 + C3 * y2 + C4 * y4)); - yc -= tol = f / fder; - if (fabs(tol) < EPS) { - break; - } - } - lp.phi = yc; - - /* longitude */ - y2 = yc * yc; - lp.lam = xy.x / (A0 + y2 * (A1 + y2 * (A2 + y2 * y2 * y2 * (A3 + y2 * A4)))); - - return (lp); + y2 = yc * yc; + y4 = y2 * y2; + f = (yc * (B0 + y2 * (B1 + y4 * (B2 + B3 * y2 + B4 * y4)))) - xy.y; + fder = C0 + y2 * (C1 + y4 * (C2 + C3 * y2 + C4 * y4)); + yc -= tol = f / fder; + if (fabs(tol) < EPS) { + break; + } + } + lp.phi = yc; + + /* longitude */ + y2 = yc * yc; + lp.lam = xy.x / (A0 + y2 * (A1 + y2 * (A2 + y2 * y2 * y2 * (A3 + y2 * A4)))); + + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(natearth) { + P->es = 0; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_natearth_selftest (void) {return 0;} +#else + +int pj_natearth_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=natearth +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 194507.265257889288, 112508.737358294515}, + { 194507.265257889288, -112508.737358294515}, + {-194507.265257889288, 112508.737358294515}, + {-194507.265257889288, -112508.737358294515}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00205638349586440223, 0.000888823913291242177}, + { 0.00205638349586440223, -0.000888823913291242177}, + {-0.00205638349586440223, 0.000888823913291242177}, + {-0.00205638349586440223, -0.000888823913291242177}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(natearth) P->es = 0; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +#endif -- cgit v1.2.3 From e549473f4b4ebd0622607721180ed6ade41fa4e8 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sun, 1 May 2016 12:12:25 +0200 Subject: Converted natearth2 --- src/PJ_aea.c | 1 - src/PJ_natearth2.c | 146 +++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 109 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index c5480d1e..aea92854 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -364,7 +364,6 @@ int pj_latlong_selftest (void) {return 10000;} int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} -int pj_natearth2_selftest (void) {return 10000;} int pj_nell_selftest (void) {return 10000;} int pj_nell_h_selftest (void) {return 10000;} int pj_nicol_selftest (void) {return 10000;} diff --git a/src/PJ_natearth2.c b/src/PJ_natearth2.c index c3776a8b..5a57fb14 100644 --- a/src/PJ_natearth2.c +++ b/src/PJ_natearth2.c @@ -1,13 +1,13 @@ /* -The Natural Earth II projection was designed by Tom Patterson, US National +The Natural Earth II projection was designed by Tom Patterson, US National Park Service, in 2012, using Flex Projector. The polynomial equation was -developed by Bojan Savric and Bernhard Jenny, College of Earth, Ocean, +developed by Bojan Savric and Bernhard Jenny, College of Earth, Ocean, and Atmospheric Sciences, Oregon State University. Port to PROJ.4 by Bojan Savric, 4 April 2016 */ - #define PJ_LIB__ -#include +#include + PROJ_HEAD(natearth2, "Natural Earth 2") "\n\tPCyl., Sph."; #define A0 0.84719 @@ -27,49 +27,121 @@ PROJ_HEAD(natearth2, "Natural Earth 2") "\n\tPCyl., Sph."; #define EPS 1e-11 #define MAX_Y (0.84719 * 0.535117535153096 * PI) -FORWARD(s_forward); /* spheroid */ - double phi2, phi4, phi6; - phi2 = lp.phi * lp.phi; - phi4 = phi2 * phi2; - phi6 = phi2 * phi4; +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + double phi2, phi4, phi6; + (void) P; - xy.x = lp.lam * (A0 + A1 * phi2 + phi6 * phi6 * (A2 + A3 * phi2 + A4 * phi4 + A5 * phi6)); - xy.y = lp.phi * (B0 + phi4 * phi4 * (B1 + B2 * phi2 + B3 * phi4)); - return (xy); + phi2 = lp.phi * lp.phi; + phi4 = phi2 * phi2; + phi6 = phi2 * phi4; + + xy.x = lp.lam * (A0 + A1 * phi2 + phi6 * phi6 * (A2 + A3 * phi2 + A4 * phi4 + A5 * phi6)); + xy.y = lp.phi * (B0 + phi4 * phi4 * (B1 + B2 * phi2 + B3 * phi4)); + return xy; } -INVERSE(s_inverse); /* spheroid */ - double yc, tol, y2, y4, y6, f, fder; + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + double yc, tol, y2, y4, y6, f, fder; + (void) P; /* make sure y is inside valid range */ - if (xy.y > MAX_Y) { - xy.y = MAX_Y; - } else if (xy.y < -MAX_Y) { - xy.y = -MAX_Y; - } + if (xy.y > MAX_Y) { + xy.y = MAX_Y; + } else if (xy.y < -MAX_Y) { + xy.y = -MAX_Y; + } /* latitude */ - yc = xy.y; + yc = xy.y; for (;;) { /* Newton-Raphson */ - y2 = yc * yc; - y4 = y2 * y2; - f = (yc * (B0 + y4 * y4 * (B1 + B2 * y2 + B3 * y4))) - xy.y; - fder = C0 + y4 * y4 * (C1 + C2 * y2 + C3 * y4); - yc -= tol = f / fder; - if (fabs(tol) < EPS) { - break; - } - } - lp.phi = yc; + y2 = yc * yc; + y4 = y2 * y2; + f = (yc * (B0 + y4 * y4 * (B1 + B2 * y2 + B3 * y4))) - xy.y; + fder = C0 + y4 * y4 * (C1 + C2 * y2 + C3 * y4); + yc -= tol = f / fder; + if (fabs(tol) < EPS) { + break; + } + } + lp.phi = yc; /* longitude */ - y2 = yc * yc; - y4 = y2 * y2; - y6 = y2 * y4; + y2 = yc * yc; + y4 = y2 * y2; + y6 = y2 * y4; + + lp.lam = xy.x / (A0 + A1 * y2 + y6 * y6 * (A2 + A3 * y2 + A4 * y4 + A5 * y6)); + + return lp; +} + - lp.lam = xy.x / (A0 + A1 * y2 + y6 * y6 * (A2 + A3 * y2 + A4 * y4 + A5 * y6)); +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; - return (lp); + return pj_dealloc(P); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(natearth2) P->es = 0; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(natearth2) { + P->es = 0; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_natearth2_selftest (void) {return 0;} +#else + +int pj_natearth2_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=natearth2 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 189255.172934730799, 113022.495810907014}, + { 189255.172934730799, -113022.495810907014}, + {-189255.172934730799, 113022.495810907014}, + {-189255.172934730799, -113022.495810907014}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00211344929691056112, 0.000884779612080993237}, + { 0.00211344929691056112, -0.000884779612080993237}, + {-0.00211344929691056112, 0.000884779612080993237}, + {-0.00211344929691056112, -0.000884779612080993237}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 7c6eaee4405b206f01895b539c2c0a9587050d87 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sun, 1 May 2016 12:17:31 +0200 Subject: Converted nell --- src/PJ_aea.c | 1 - src/PJ_nell.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 102 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index aea92854..4cf1030f 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -364,7 +364,6 @@ int pj_latlong_selftest (void) {return 10000;} int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} -int pj_nell_selftest (void) {return 10000;} int pj_nell_h_selftest (void) {return 10000;} int pj_nicol_selftest (void) {return 10000;} int pj_nsper_selftest (void) {return 10000;} diff --git a/src/PJ_nell.c b/src/PJ_nell.c index 77983de8..b69b9997 100644 --- a/src/PJ_nell.c +++ b/src/PJ_nell.c @@ -1,30 +1,106 @@ #define PJ_LIB__ -#include +#include + PROJ_HEAD(nell, "Nell") "\n\tPCyl., Sph."; -#define MAX_ITER 10 -#define LOOP_TOL 1e-7 -FORWARD(s_forward); /* spheroid */ - double k, V; - int i; - (void) P; - - k = 2. * sin(lp.phi); - V = lp.phi * lp.phi; - lp.phi *= 1.00371 + V * (-0.0935382 + V * -0.011412); - for (i = MAX_ITER; i ; --i) { - lp.phi -= V = (lp.phi + sin(lp.phi) - k) / - (1. + cos(lp.phi)); - if (fabs(V) < LOOP_TOL) - break; - } - xy.x = 0.5 * lp.lam * (1. + cos(lp.phi)); - xy.y = lp.phi; - return (xy); + +#define MAX_ITER 10 +#define LOOP_TOL 1e-7 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + double k, V; + int i; + (void) P; + + k = 2. * sin(lp.phi); + V = lp.phi * lp.phi; + lp.phi *= 1.00371 + V * (-0.0935382 + V * -0.011412); + for (i = MAX_ITER; i ; --i) { + lp.phi -= V = (lp.phi + sin(lp.phi) - k) / + (1. + cos(lp.phi)); + if (fabs(V) < LOOP_TOL) + break; + } + xy.x = 0.5 * lp.lam * (1. + cos(lp.phi)); + xy.y = lp.phi; + + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + lp.lam = 2. * xy.x / (1. + cos(xy.y)); + lp.phi = aasin(P->ctx,0.5 * (xy.y + sin(xy.y))); + + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(nell) { + + P->es = 0; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; } -INVERSE(s_inverse); /* spheroid */ - lp.lam = 2. * xy.x / (1. + cos(xy.y)); - lp.phi = aasin(P->ctx,0.5 * (xy.y + sin(xy.y))); - return (lp); + +#ifdef PJ_OMIT_SELFTEST +int pj_nell_selftest (void) {return 0;} +#else + +int pj_nell_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=nell +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223385.132504695706, 111698.23644718733}, + { 223385.132504695706, -111698.23644718733}, + {-223385.132504695706, 111698.23644718733}, + {-223385.132504695706, -111698.23644718733}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00179049310989310567, 0.000895246554910125161}, + { 0.00179049310989310567, -0.000895246554910125161}, + {-0.00179049310989310567, 0.000895246554910125161}, + {-0.00179049310989310567, -0.000895246554910125161}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(nell) P->es = 0; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +#endif -- cgit v1.2.3 From 1cf945aa3977bc2f02fc749675d4691755bdb0cd Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sun, 1 May 2016 12:25:42 +0200 Subject: Converted nell_h --- src/PJ_aea.c | 1 - src/PJ_nell_h.c | 129 ++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 103 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 4cf1030f..e25adf13 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -364,7 +364,6 @@ int pj_latlong_selftest (void) {return 10000;} int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} -int pj_nell_h_selftest (void) {return 10000;} int pj_nicol_selftest (void) {return 10000;} int pj_nsper_selftest (void) {return 10000;} int pj_nzmg_selftest (void) {return 10000;} diff --git a/src/PJ_nell_h.c b/src/PJ_nell_h.c index 22061ea9..1e863945 100644 --- a/src/PJ_nell_h.c +++ b/src/PJ_nell_h.c @@ -1,32 +1,109 @@ #define PJ_LIB__ -# include +#include + PROJ_HEAD(nell_h, "Nell-Hammer") "\n\tPCyl., Sph."; + #define NITER 9 #define EPS 1e-7 -FORWARD(s_forward); /* spheroid */ - (void) P; - xy.x = 0.5 * lp.lam * (1. + cos(lp.phi)); - xy.y = 2.0 * (lp.phi - tan(0.5 *lp.phi)); - return (xy); + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + (void) P; + + xy.x = 0.5 * lp.lam * (1. + cos(lp.phi)); + xy.y = 2.0 * (lp.phi - tan(0.5 *lp.phi)); + + return xy; } -INVERSE(s_inverse); /* spheroid */ - double V, c, p; - int i; - (void) P; - - p = 0.5 * xy.y; - for (i = NITER; i ; --i) { - c = cos(0.5 * lp.phi); - lp.phi -= V = (lp.phi - tan(lp.phi/2) - p)/(1. - 0.5/(c*c)); - if (fabs(V) < EPS) - break; - } - if (!i) { - lp.phi = p < 0. ? -HALFPI : HALFPI; - lp.lam = 2. * xy.x; - } else - lp.lam = 2. * xy.x / (1. + cos(lp.phi)); - return (lp); + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + double V, c, p; + int i; + (void) P; + + p = 0.5 * xy.y; + for (i = NITER; i ; --i) { + c = cos(0.5 * lp.phi); + lp.phi -= V = (lp.phi - tan(lp.phi/2) - p)/(1. - 0.5/(c*c)); + if (fabs(V) < EPS) + break; + } + if (!i) { + lp.phi = p < 0. ? -HALFPI : HALFPI; + lp.lam = 2. * xy.x; + } else + lp.lam = 2. * xy.x / (1. + cos(lp.phi)); + + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(nell_h) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +PJ *PROJECTION(nell_h) { + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_nell_h_selftest (void) {return 0;} +#else + +int pj_nell_h_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=nell_h +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223385.131640952837, 111698.236533561678}, + { 223385.131640952837, -111698.236533561678}, + {-223385.131640952837, 111698.236533561678}, + {-223385.131640952837, -111698.236533561678}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00179049310989310567, 0.000895246554910125378}, + { 0.00179049310989310567, -0.000895246554910125378}, + {-0.00179049310989310567, 0.000895246554910125378}, + {-0.00179049310989310567, -0.000895246554910125378}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 99a5b481bc40dde768b80b9dd1de693e0020f206 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sun, 1 May 2016 20:42:52 +0200 Subject: Converted nicol, which oddly enough is placed in PJ_nocol.c. Typo? --- src/PJ_aea.c | 1 - src/PJ_nocol.c | 130 +++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 93 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index e25adf13..fe506322 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -364,7 +364,6 @@ int pj_latlong_selftest (void) {return 10000;} int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} -int pj_nicol_selftest (void) {return 10000;} int pj_nsper_selftest (void) {return 10000;} int pj_nzmg_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} diff --git a/src/PJ_nocol.c b/src/PJ_nocol.c index 2b005e1d..ad96ff31 100644 --- a/src/PJ_nocol.c +++ b/src/PJ_nocol.c @@ -1,40 +1,96 @@ #define PJ_LIB__ -#include +#include + PROJ_HEAD(nicol, "Nicolosi Globular") "\n\tMisc Sph, no inv."; -#define EPS 1e-10 -FORWARD(s_forward); /* spheroid */ - (void) P; - - if (fabs(lp.lam) < EPS) { - xy.x = 0; - xy.y = lp.phi; - } else if (fabs(lp.phi) < EPS) { - xy.x = lp.lam; - xy.y = 0.; - } else if (fabs(fabs(lp.lam) - HALFPI) < EPS) { - xy.x = lp.lam * cos(lp.phi); - xy.y = HALFPI * sin(lp.phi); - } else if (fabs(fabs(lp.phi) - HALFPI) < EPS) { - xy.x = 0; - xy.y = lp.phi; - } else { - double tb, c, d, m, n, r2, sp; - - tb = HALFPI / lp.lam - lp.lam / HALFPI; - c = lp.phi / HALFPI; - d = (1 - c * c)/((sp = sin(lp.phi)) - c); - r2 = tb / d; - r2 *= r2; - m = (tb * sp / d - 0.5 * tb)/(1. + r2); - n = (sp / r2 + 0.5 * d)/(1. + 1./r2); - xy.x = cos(lp.phi); - xy.x = sqrt(m * m + xy.x * xy.x / (1. + r2)); - xy.x = HALFPI * ( m + (lp.lam < 0. ? -xy.x : xy.x)); - xy.y = sqrt(n * n - (sp * sp / r2 + d * sp - 1.) / - (1. + 1./r2)); - xy.y = HALFPI * ( n + (lp.phi < 0. ? xy.y : -xy.y )); - } - return (xy); + +#define EPS 1e-10 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + (void) P; + + if (fabs(lp.lam) < EPS) { + xy.x = 0; + xy.y = lp.phi; + } else if (fabs(lp.phi) < EPS) { + xy.x = lp.lam; + xy.y = 0.; + } else if (fabs(fabs(lp.lam) - HALFPI) < EPS) { + xy.x = lp.lam * cos(lp.phi); + xy.y = HALFPI * sin(lp.phi); + } else if (fabs(fabs(lp.phi) - HALFPI) < EPS) { + xy.x = 0; + xy.y = lp.phi; + } else { + double tb, c, d, m, n, r2, sp; + + tb = HALFPI / lp.lam - lp.lam / HALFPI; + c = lp.phi / HALFPI; + d = (1 - c * c)/((sp = sin(lp.phi)) - c); + r2 = tb / d; + r2 *= r2; + m = (tb * sp / d - 0.5 * tb)/(1. + r2); + n = (sp / r2 + 0.5 * d)/(1. + 1./r2); + xy.x = cos(lp.phi); + xy.x = sqrt(m * m + xy.x * xy.x / (1. + r2)); + xy.x = HALFPI * ( m + (lp.lam < 0. ? -xy.x : xy.x)); + xy.y = sqrt(n * n - (sp * sp / r2 + d * sp - 1.) / + (1. + 1./r2)); + xy.y = HALFPI * ( n + (lp.phi < 0. ? xy.y : -xy.y )); + } + return (xy); +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(nicol) P->es = 0.; P->fwd = s_forward; ENDENTRY(P) + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(nicol) { + P->es = 0.; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_nicol_selftest (void) {return 0;} +#else + +int pj_nicol_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=nicol +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223374.561814139714, 111732.553988545071}, + { 223374.561814139714, -111732.553988545071}, + {-223374.561814139714, 111732.553988545071}, + {-223374.561814139714, -111732.553988545071}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} + + +#endif -- cgit v1.2.3 From 45533165a6c05be56dd79fb4f072b82b36734656 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sun, 1 May 2016 21:25:46 +0200 Subject: Converted nsper and tpers --- src/PJ_aea.c | 3 - src/PJ_nsper.c | 420 ++++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 279 insertions(+), 144 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index fe506322..edc698b3 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -364,7 +364,6 @@ int pj_latlong_selftest (void) {return 10000;} int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} -int pj_nsper_selftest (void) {return 10000;} int pj_nzmg_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} int pj_ocea_selftest (void) {return 10000;} @@ -388,8 +387,6 @@ int pj_rouss_selftest (void) {return 10000;} int pj_rpoly_selftest (void) {return 10000;} int pj_sch_selftest (void) {return 10000;} -int pj_tpers_selftest (void) {return 10000;} - int pj_utm_selftest (void) {return 10000;} int pj_vandg_selftest (void) {return 10000;} int pj_vandg2_selftest (void) {return 10000;} diff --git a/src/PJ_nsper.c b/src/PJ_nsper.c index 0f355b93..2a0ea702 100644 --- a/src/PJ_nsper.c +++ b/src/PJ_nsper.c @@ -1,149 +1,287 @@ -#define PROJ_PARMS__ \ - double height; \ - double sinph0; \ - double cosph0; \ - double p; \ - double rp; \ - double pn1; \ - double pfact; \ - double h; \ - double cg; \ - double sg; \ - double sw; \ - double cw; \ - int mode; \ - int tilt; #define PJ_LIB__ -#include +#include + +struct pj_opaque { + double height; + double sinph0; + double cosph0; + double p; + double rp; + double pn1; + double pfact; + double h; + double cg; + double sg; + double sw; + double cw; + int mode; + int tilt; +}; + PROJ_HEAD(nsper, "Near-sided perspective") "\n\tAzi, Sph\n\th="; PROJ_HEAD(tpers, "Tilted perspective") "\n\tAzi, Sph\n\ttilt= azi= h="; + # define EPS10 1.e-10 -# define N_POLE 0 +# define N_POLE 0 # define S_POLE 1 -# define EQUIT 2 -# define OBLIQ 3 -FORWARD(s_forward); /* spheroid */ - double coslam, cosphi, sinphi; - - sinphi = sin(lp.phi); - cosphi = cos(lp.phi); - coslam = cos(lp.lam); - switch (P->mode) { - case OBLIQ: - xy.y = P->sinph0 * sinphi + P->cosph0 * cosphi * coslam; - break; - case EQUIT: - xy.y = cosphi * coslam; - break; - case S_POLE: - xy.y = - sinphi; - break; - case N_POLE: - xy.y = sinphi; - break; - } - if (xy.y < P->rp) F_ERROR; - xy.y = P->pn1 / (P->p - xy.y); - xy.x = xy.y * cosphi * sin(lp.lam); - switch (P->mode) { - case OBLIQ: - xy.y *= (P->cosph0 * sinphi - - P->sinph0 * cosphi * coslam); - break; - case EQUIT: - xy.y *= sinphi; - break; - case N_POLE: - coslam = - coslam; - case S_POLE: - xy.y *= cosphi * coslam; - break; - } - if (P->tilt) { - double yt, ba; - - yt = xy.y * P->cg + xy.x * P->sg; - ba = 1. / (yt * P->sw * P->h + P->cw); - xy.x = (xy.x * P->cg - xy.y * P->sg) * P->cw * ba; - xy.y = yt * ba; - } - return (xy); +# define EQUIT 2 +# define OBLIQ 3 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double coslam, cosphi, sinphi; + + sinphi = sin(lp.phi); + cosphi = cos(lp.phi); + coslam = cos(lp.lam); + switch (Q->mode) { + case OBLIQ: + xy.y = Q->sinph0 * sinphi + Q->cosph0 * cosphi * coslam; + break; + case EQUIT: + xy.y = cosphi * coslam; + break; + case S_POLE: + xy.y = - sinphi; + break; + case N_POLE: + xy.y = sinphi; + break; + } + if (xy.y < Q->rp) F_ERROR; + xy.y = Q->pn1 / (Q->p - xy.y); + xy.x = xy.y * cosphi * sin(lp.lam); + switch (Q->mode) { + case OBLIQ: + xy.y *= (Q->cosph0 * sinphi - + Q->sinph0 * cosphi * coslam); + break; + case EQUIT: + xy.y *= sinphi; + break; + case N_POLE: + coslam = - coslam; + case S_POLE: + xy.y *= cosphi * coslam; + break; + } + if (Q->tilt) { + double yt, ba; + + yt = xy.y * Q->cg + xy.x * Q->sg; + ba = 1. / (yt * Q->sw * Q->h + Q->cw); + xy.x = (xy.x * Q->cg - xy.y * Q->sg) * Q->cw * ba; + xy.y = yt * ba; + } + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double rh, cosz, sinz; + + if (Q->tilt) { + double bm, bq, yt; + + yt = 1./(Q->pn1 - xy.y * Q->sw); + bm = Q->pn1 * xy.x * yt; + bq = Q->pn1 * xy.y * Q->cw * yt; + xy.x = bm * Q->cg + bq * Q->sg; + xy.y = bq * Q->cg - bm * Q->sg; + } + rh = hypot(xy.x, xy.y); + if ((sinz = 1. - rh * rh * Q->pfact) < 0.) I_ERROR; + sinz = (Q->p - sqrt(sinz)) / (Q->pn1 / rh + rh / Q->pn1); + cosz = sqrt(1. - sinz * sinz); + if (fabs(rh) <= EPS10) { + lp.lam = 0.; + lp.phi = P->phi0; + } else { + switch (Q->mode) { + case OBLIQ: + lp.phi = asin(cosz * Q->sinph0 + xy.y * sinz * Q->cosph0 / rh); + xy.y = (cosz - Q->sinph0 * sin(lp.phi)) * rh; + xy.x *= sinz * Q->cosph0; + break; + case EQUIT: + lp.phi = asin(xy.y * sinz / rh); + xy.y = cosz * rh; + xy.x *= sinz; + break; + case N_POLE: + lp.phi = asin(cosz); + xy.y = -xy.y; + break; + case S_POLE: + lp.phi = - asin(cosz); + break; + } + lp.lam = atan2(xy.x, xy.y); + } + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; } -INVERSE(s_inverse); /* spheroid */ - double rh, cosz, sinz; - - if (P->tilt) { - double bm, bq, yt; - - yt = 1./(P->pn1 - xy.y * P->sw); - bm = P->pn1 * xy.x * yt; - bq = P->pn1 * xy.y * P->cw * yt; - xy.x = bm * P->cg + bq * P->sg; - xy.y = bq * P->cg - bm * P->sg; - } - rh = hypot(xy.x, xy.y); - if ((sinz = 1. - rh * rh * P->pfact) < 0.) I_ERROR; - sinz = (P->p - sqrt(sinz)) / (P->pn1 / rh + rh / P->pn1); - cosz = sqrt(1. - sinz * sinz); - if (fabs(rh) <= EPS10) { - lp.lam = 0.; - lp.phi = P->phi0; - } else { - switch (P->mode) { - case OBLIQ: - lp.phi = asin(cosz * P->sinph0 + xy.y * sinz * P->cosph0 / rh); - xy.y = (cosz - P->sinph0 * sin(lp.phi)) * rh; - xy.x *= sinz * P->cosph0; - break; - case EQUIT: - lp.phi = asin(xy.y * sinz / rh); - xy.y = cosz * rh; - xy.x *= sinz; - break; - case N_POLE: - lp.phi = asin(cosz); - xy.y = -xy.y; - break; - case S_POLE: - lp.phi = - asin(cosz); - break; - } - lp.lam = atan2(xy.x, xy.y); - } - return (lp); + + +static PJ *setup(PJ *P) { + struct pj_opaque *Q = P->opaque; + + if ((Q->height = pj_param(P->ctx, P->params, "dh").f) <= 0.) E_ERROR(-30); + if (fabs(fabs(P->phi0) - HALFPI) < EPS10) + Q->mode = P->phi0 < 0. ? S_POLE : N_POLE; + else if (fabs(P->phi0) < EPS10) + Q->mode = EQUIT; + else { + Q->mode = OBLIQ; + Q->sinph0 = sin(P->phi0); + Q->cosph0 = cos(P->phi0); + } + Q->pn1 = Q->height / P->a; /* normalize by radius */ + Q->p = 1. + Q->pn1; + Q->rp = 1. / Q->p; + Q->h = 1. / Q->pn1; + Q->pfact = (Q->p + 1.) * Q->h; + P->inv = s_inverse; + P->fwd = s_forward; + P->es = 0.; + return P; } -FREEUP; if (P) pj_dalloc(P); } - static PJ * -setup(PJ *P) { - if ((P->height = pj_param(P->ctx, P->params, "dh").f) <= 0.) E_ERROR(-30); - if (fabs(fabs(P->phi0) - HALFPI) < EPS10) - P->mode = P->phi0 < 0. ? S_POLE : N_POLE; - else if (fabs(P->phi0) < EPS10) - P->mode = EQUIT; - else { - P->mode = OBLIQ; - P->sinph0 = sin(P->phi0); - P->cosph0 = cos(P->phi0); - } - P->pn1 = P->height / P->a; /* normalize by radius */ - P->p = 1. + P->pn1; - P->rp = 1. / P->p; - P->h = 1. / P->pn1; - P->pfact = (P->p + 1.) * P->h; - P->inv = s_inverse; - P->fwd = s_forward; - P->es = 0.; - return P; + + +PJ *PROJECTION(nsper) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->tilt = 0; + + return setup(P); } -ENTRY0(nsper) - P->tilt = 0; -ENDENTRY(setup(P)) -ENTRY0(tpers) - double omega, gamma; - - omega = pj_param(P->ctx, P->params, "dtilt").f * DEG_TO_RAD; - gamma = pj_param(P->ctx, P->params, "dazi").f * DEG_TO_RAD; - P->tilt = 1; - P->cg = cos(gamma); P->sg = sin(gamma); - P->cw = cos(omega); P->sw = sin(omega); -ENDENTRY(setup(P)) + + +PJ *PROJECTION(tpers) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + double omega, gamma; + + omega = pj_param(P->ctx, P->params, "dtilt").f * DEG_TO_RAD; + gamma = pj_param(P->ctx, P->params, "dazi").f * DEG_TO_RAD; + Q->tilt = 1; + Q->cg = cos(gamma); Q->sg = sin(gamma); + Q->cw = cos(omega); Q->sw = sin(omega); + + return setup(P); +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_nsper_selftest (void) {return 0;} +#else + +int pj_nsper_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=nsper +a=6400000 +h=1000000"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 222239.816114099842, 111153.763991924759}, + { 222239.816114099842, -111153.763991924759}, + {-222239.816114099842, 111153.763991924759}, + {-222239.816114099842, -111153.763991924759}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00179049311728792437, 0.000895246558425396135}, + { 0.00179049311728792437, -0.000895246558425396135}, + {-0.00179049311728792437, 0.000895246558425396135}, + {-0.00179049311728792437, -0.000895246558425396135}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif + + +#ifdef PJ_OMIT_SELFTEST +int pj_tpers_selftest (void) {return 0;} +#else + +int pj_tpers_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=tpers +a=6400000 +h=1000000 +azi=20"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 170820.288955531199, 180460.865555804776}, + { 246853.941538942483, -28439.8780357754222}, + {-246853.941538942483, 28439.8780357754222}, + {-170820.288955531199, -180460.865555804776} + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00198870552603137678, 0.000228871872278689991}, + { 0.00137632081376749859, -0.00145364129728205432}, + {-0.00137632081376749859, 0.00145364129728205432}, + {-0.00198870552603137678, -0.000228871872278689991}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 36e87f4100166694733e23df9572ef7ef1222532 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Sun, 1 May 2016 21:45:34 +0200 Subject: Converted nzmg --- src/PJ_aea.c | 1 - src/PJ_nzmg.c | 202 +++++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 138 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index edc698b3..d244f27e 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -364,7 +364,6 @@ int pj_latlong_selftest (void) {return 10000;} int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} -int pj_nzmg_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} int pj_ocea_selftest (void) {return 10000;} int pj_oea_selftest (void) {return 10000;} diff --git a/src/PJ_nzmg.c b/src/PJ_nzmg.c index 60df0041..8dcb2634 100644 --- a/src/PJ_nzmg.c +++ b/src/PJ_nzmg.c @@ -25,79 +25,153 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ - #define PJ_LIB__ -#include +#include PROJ_HEAD(nzmg, "New Zealand Map Grid") "\n\tfixed Earth"; #define EPSLN 1e-10 #define SEC5_TO_RAD 0.4848136811095359935899141023 #define RAD_TO_SEC5 2.062648062470963551564733573 - static COMPLEX -bf[] = { - {.7557853228, 0.0}, - {.249204646, .003371507}, - {-.001541739, .041058560}, - {-.10162907, .01727609}, - {-.26623489, -.36249218}, - {-.6870983, -1.1651967} }; - static double -tphi[] = { 1.5627014243, .5185406398, -.03333098, -.1052906, -.0368594, - .007317, .01220, .00394, -.0013 }, -tpsi[] = { .6399175073, -.1358797613, .063294409, -.02526853, .0117879, - -.0055161, .0026906, -.001333, .00067, -.00034 }; + +static COMPLEX bf[] = { + { .7557853228, 0.0}, + { .249204646, 0.003371507}, + {-.001541739, 0.041058560}, + {-.10162907, 0.01727609}, + {-.26623489, -0.36249218}, + {-.6870983, -1.1651967} }; + +static double tphi[] = { 1.5627014243, .5185406398, -.03333098, + -.1052906, -.0368594, .007317, + .01220, .00394, -.0013 }; + +static double tpsi[] = { .6399175073, -.1358797613, .063294409, -.02526853, .0117879, + -.0055161, .0026906, -.001333, .00067, -.00034 }; + #define Nbf 5 #define Ntpsi 9 #define Ntphi 8 -FORWARD(e_forward); /* ellipsoid */ - COMPLEX p; - double *C; - int i; - - lp.phi = (lp.phi - P->phi0) * RAD_TO_SEC5; - for (p.r = *(C = tpsi + (i = Ntpsi)); i ; --i) - p.r = *--C + lp.phi * p.r; - p.r *= lp.phi; - p.i = lp.lam; - p = pj_zpoly1(p, bf, Nbf); - xy.x = p.i; - xy.y = p.r; - return xy; + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + COMPLEX p; + double *C; + int i; + + lp.phi = (lp.phi - P->phi0) * RAD_TO_SEC5; + for (p.r = *(C = tpsi + (i = Ntpsi)); i ; --i) + p.r = *--C + lp.phi * p.r; + p.r *= lp.phi; + p.i = lp.lam; + p = pj_zpoly1(p, bf, Nbf); + xy.x = p.i; + xy.y = p.r; + + return xy; } -INVERSE(e_inverse); /* ellipsoid */ - int nn, i; - COMPLEX p, f, fp, dp; - double den, *C; - - p.r = xy.y; - p.i = xy.x; - for (nn = 20; nn ;--nn) { - f = pj_zpolyd1(p, bf, Nbf, &fp); - f.r -= xy.y; - f.i -= xy.x; - den = fp.r * fp.r + fp.i * fp.i; - p.r += dp.r = -(f.r * fp.r + f.i * fp.i) / den; - p.i += dp.i = -(f.i * fp.r - f.r * fp.i) / den; - if ((fabs(dp.r) + fabs(dp.i)) <= EPSLN) - break; - } - if (nn) { - lp.lam = p.i; - for (lp.phi = *(C = tphi + (i = Ntphi)); i ; --i) - lp.phi = *--C + p.r * lp.phi; - lp.phi = P->phi0 + p.r * lp.phi * SEC5_TO_RAD; - } else - lp.lam = lp.phi = HUGE_VAL; - return lp; + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + int nn, i; + COMPLEX p, f, fp, dp; + double den, *C; + + p.r = xy.y; + p.i = xy.x; + for (nn = 20; nn ;--nn) { + f = pj_zpolyd1(p, bf, Nbf, &fp); + f.r -= xy.y; + f.i -= xy.x; + den = fp.r * fp.r + fp.i * fp.i; + p.r += dp.r = -(f.r * fp.r + f.i * fp.i) / den; + p.i += dp.i = -(f.i * fp.r - f.r * fp.i) / den; + if ((fabs(dp.r) + fabs(dp.i)) <= EPSLN) + break; + } + if (nn) { + lp.lam = p.i; + for (lp.phi = *(C = tphi + (i = Ntphi)); i ; --i) + lp.phi = *--C + p.r * lp.phi; + lp.phi = P->phi0 + p.r * lp.phi * SEC5_TO_RAD; + } else + lp.lam = lp.phi = HUGE_VAL; + + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(nzmg) - /* force to International major axis */ - P->ra = 1. / (P->a = 6378388.0); - P->lam0 = DEG_TO_RAD * 173.; - P->phi0 = DEG_TO_RAD * -41.; - P->x0 = 2510000.; - P->y0 = 6023150.; - P->inv = e_inverse; P->fwd = e_forward; -ENDENTRY(P) + + +PJ *PROJECTION(nzmg) { + /* force to International major axis */ + P->ra = 1. / (P->a = 6378388.0); + P->lam0 = DEG_TO_RAD * 173.; + P->phi0 = DEG_TO_RAD * -41.; + P->x0 = 2510000.; + P->y0 = 6023150.; + + P->inv = e_inverse; + P->fwd = e_forward; + + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_nzmg_selftest (void) {return 0;} +#else + +int pj_nzmg_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=nzmg +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {3352675144.74742508, -7043205391.10024357}, + {3691989502.77930641, -6729069415.33210468}, + {4099000768.45323849, -7863208779.66724873}, + {4466166927.36997604, -7502531736.62860489}, + }; + + XY inv_in[] = { + { 200000, 100000}, + { 200000,-100000}, + {-200000, 100000}, + {-200000,-100000} + }; + + LP e_inv_expect[] = { + {175.48208682711271, -69.4226921826331846}, + {175.756819472543611, -69.5335710883796168}, + {134.605119233460016, -61.4599957106629091}, + {134.333684315954827, -61.6215536756024349}, + }; + + return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); +} + + +#endif -- cgit v1.2.3 From 359c182fa6f4d834192bb01b0f8170bc2b306247 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Mon, 2 May 2016 17:49:00 +0200 Subject: Converted ocea --- src/PJ_aea.c | 1 - src/PJ_ocea.c | 221 +++++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 149 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index d244f27e..ddf92a45 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -365,7 +365,6 @@ int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} -int pj_ocea_selftest (void) {return 10000;} int pj_oea_selftest (void) {return 10000;} int pj_omerc_selftest (void) {return 10000;} int pj_ortho_selftest (void) {return 10000;} diff --git a/src/PJ_ocea.c b/src/PJ_ocea.c index b268e1b8..4727b09a 100644 --- a/src/PJ_ocea.c +++ b/src/PJ_ocea.c @@ -1,76 +1,153 @@ -#define PROJ_PARMS__ \ - double rok; \ - double rtk; \ - double sinphi; \ - double cosphi; \ - double singam; \ - double cosgam; #define PJ_LIB__ -#include +#include + PROJ_HEAD(ocea, "Oblique Cylindrical Equal Area") "\n\tCyl, Sph" - "lonc= alpha= or\n\tlat_1= lat_2= lon_1= lon_2="; -FORWARD(s_forward); /* spheroid */ - double t; - - xy.y = sin(lp.lam); -/* - xy.x = atan2((tan(lp.phi) * P->cosphi + P->sinphi * xy.y) , cos(lp.lam)); -*/ - t = cos(lp.lam); - xy.x = atan((tan(lp.phi) * P->cosphi + P->sinphi * xy.y) / t); - if (t < 0.) - xy.x += PI; - xy.x *= P->rtk; - xy.y = P->rok * (P->sinphi * sin(lp.phi) - P->cosphi * cos(lp.phi) * xy.y); - return (xy); + "lonc= alpha= or\n\tlat_1= lat_2= lon_1= lon_2="; + +struct pj_opaque { + double rok; + double rtk; + double sinphi; + double cosphi; + double singam; + double cosgam; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double t; + + xy.y = sin(lp.lam); + t = cos(lp.lam); + xy.x = atan((tan(lp.phi) * Q->cosphi + Q->sinphi * xy.y) / t); + if (t < 0.) + xy.x += PI; + xy.x *= Q->rtk; + xy.y = Q->rok * (Q->sinphi * sin(lp.phi) - Q->cosphi * cos(lp.phi) * xy.y); + return (xy); +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double t, s; + + xy.y /= Q->rok; + xy.x /= Q->rtk; + t = sqrt(1. - xy.y * xy.y); + lp.phi = asin(xy.y * Q->sinphi + t * Q->cosphi * (s = sin(xy.x))); + lp.lam = atan2(t * Q->sinphi * s - xy.y * Q->cosphi, + t * cos(xy.x)); + return (lp); +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(ocea) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + double phi_0=0.0, phi_1, phi_2, lam_1, lam_2, lonz, alpha; + + Q->rok = P->a / P->k0; + Q->rtk = P->a * P->k0; + /*If the keyword "alpha" is found in the sentence then use 1point+1azimuth*/ + if ( pj_param(P->ctx, P->params, "talpha").i) { + /*Define Pole of oblique transformation from 1 point & 1 azimuth*/ + alpha = pj_param(P->ctx, P->params, "ralpha").f; + lonz = pj_param(P->ctx, P->params, "rlonc").f; + /*Equation 9-8 page 80 (http://pubs.usgs.gov/pp/1395/report.pdf)*/ + Q->singam = atan(-cos(alpha)/(-sin(phi_0) * sin(alpha))) + lonz; + /*Equation 9-7 page 80 (http://pubs.usgs.gov/pp/1395/report.pdf)*/ + Q->sinphi = asin(cos(phi_0) * sin(alpha)); + /*If the keyword "alpha" is NOT found in the sentence then use 2points*/ + } else { + /*Define Pole of oblique transformation from 2 points*/ + phi_1 = pj_param(P->ctx, P->params, "rlat_1").f; + phi_2 = pj_param(P->ctx, P->params, "rlat_2").f; + lam_1 = pj_param(P->ctx, P->params, "rlon_1").f; + lam_2 = pj_param(P->ctx, P->params, "rlon_2").f; + /*Equation 9-1 page 80 (http://pubs.usgs.gov/pp/1395/report.pdf)*/ + Q->singam = atan2(cos(phi_1) * sin(phi_2) * cos(lam_1) - + sin(phi_1) * cos(phi_2) * cos(lam_2), + sin(phi_1) * cos(phi_2) * sin(lam_2) - + cos(phi_1) * sin(phi_2) * sin(lam_1) ); + /*Equation 9-2 page 80 (http://pubs.usgs.gov/pp/1395/report.pdf)*/ + Q->sinphi = atan(-cos(Q->singam - lam_1) / tan(phi_1)); + } + P->lam0 = Q->singam + HALFPI; + Q->cosphi = cos(Q->sinphi); + Q->sinphi = sin(Q->sinphi); + Q->cosgam = cos(Q->singam); + Q->singam = sin(Q->singam); + P->inv = s_inverse; + P->fwd = s_forward; + P->es = 0.; + + return P; } -INVERSE(s_inverse); /* spheroid */ - double t, s; - - xy.y /= P->rok; - xy.x /= P->rtk; - t = sqrt(1. - xy.y * xy.y); - lp.phi = asin(xy.y * P->sinphi + t * P->cosphi * (s = sin(xy.x))); - lp.lam = atan2(t * P->sinphi * s - xy.y * P->cosphi, - t * cos(xy.x)); - return (lp); + + +#ifdef PJ_OMIT_SELFTEST +int pj_ocea_selftest (void) {return 0;} +#else + +int pj_ocea_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=ocea +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {127964312562778.156, 1429265667691.05786}, + {129394957619297.641, 1429265667691.06812}, + {127964312562778.188, -1429265667691.0498}, + {129394957619297.688, -1429265667691.03955}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 179.999999999860108, 2.79764548403721305e-10}, + {-179.999999999860108, 2.7976454840372327e-10}, + { 179.999999999860108, -2.7976454840372327e-10}, + {-179.999999999860108, -2.79764548403721305e-10}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(ocea) - double phi_0=0.0, phi_1, phi_2, lam_1, lam_2, lonz, alpha; - - P->rok = P->a / P->k0; - P->rtk = P->a * P->k0; - /*If the keyword "alpha" is found in the sentence then use 1point+1azimuth*/ - if ( pj_param(P->ctx, P->params, "talpha").i) { - /*Define Pole of oblique transformation from 1 point & 1 azimuth*/ - alpha = pj_param(P->ctx, P->params, "ralpha").f; - lonz = pj_param(P->ctx, P->params, "rlonc").f; - /*Equation 9-8 page 80 (http://pubs.usgs.gov/pp/1395/report.pdf)*/ - P->singam = atan(-cos(alpha)/(-sin(phi_0) * sin(alpha))) + lonz; - /*Equation 9-7 page 80 (http://pubs.usgs.gov/pp/1395/report.pdf)*/ - P->sinphi = asin(cos(phi_0) * sin(alpha)); - /*If the keyword "alpha" is NOT found in the sentence then use 2points*/ - } else { - /*Define Pole of oblique transformation from 2 points*/ - phi_1 = pj_param(P->ctx, P->params, "rlat_1").f; - phi_2 = pj_param(P->ctx, P->params, "rlat_2").f; - lam_1 = pj_param(P->ctx, P->params, "rlon_1").f; - lam_2 = pj_param(P->ctx, P->params, "rlon_2").f; - /*Equation 9-1 page 80 (http://pubs.usgs.gov/pp/1395/report.pdf)*/ - P->singam = atan2(cos(phi_1) * sin(phi_2) * cos(lam_1) - - sin(phi_1) * cos(phi_2) * cos(lam_2), - sin(phi_1) * cos(phi_2) * sin(lam_2) - - cos(phi_1) * sin(phi_2) * sin(lam_1) ); - /*Equation 9-2 page 80 (http://pubs.usgs.gov/pp/1395/report.pdf)*/ - P->sinphi = atan(-cos(P->singam - lam_1) / tan(phi_1)); - } - P->lam0 = P->singam + HALFPI; - P->cosphi = cos(P->sinphi); - P->sinphi = sin(P->sinphi); - P->cosgam = cos(P->singam); - P->singam = sin(P->singam); - P->inv = s_inverse; - P->fwd = s_forward; - P->es = 0.; -ENDENTRY(P) + + +#endif -- cgit v1.2.3 From 70f936b29189c07d4dc50044f7bcc1ff4f8612a8 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Mon, 2 May 2016 18:05:52 +0200 Subject: Converted oea. And removed parentheses in return statements in ocea. --- src/PJ_aea.c | 1 - src/PJ_ocea.c | 4 +- src/PJ_oea.c | 152 +++++++++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 120 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index ddf92a45..aadefd89 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -365,7 +365,6 @@ int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} -int pj_oea_selftest (void) {return 10000;} int pj_omerc_selftest (void) {return 10000;} int pj_ortho_selftest (void) {return 10000;} int pj_patterson_selftest (void) {return 10000;} diff --git a/src/PJ_ocea.c b/src/PJ_ocea.c index 4727b09a..72414e7f 100644 --- a/src/PJ_ocea.c +++ b/src/PJ_ocea.c @@ -26,7 +26,7 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ xy.x += PI; xy.x *= Q->rtk; xy.y = Q->rok * (Q->sinphi * sin(lp.phi) - Q->cosphi * cos(lp.phi) * xy.y); - return (xy); + return xy; } @@ -41,7 +41,7 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ lp.phi = asin(xy.y * Q->sinphi + t * Q->cosphi * (s = sin(xy.x))); lp.lam = atan2(t * Q->sinphi * s - xy.y * Q->cosphi, t * cos(xy.x)); - return (lp); + return lp; } diff --git a/src/PJ_oea.c b/src/PJ_oea.c index b84a7ea6..50ab6b52 100644 --- a/src/PJ_oea.c +++ b/src/PJ_oea.c @@ -1,58 +1,142 @@ -#define PROJ_PARMS__ \ - double theta; \ - double m, n; \ - double two_r_m, two_r_n, rm, rn, hm, hn; \ - double cp0, sp0; #define PJ_LIB__ #include + PROJ_HEAD(oea, "Oblated Equal Area") "\n\tMisc Sph\n\tn= m= theta="; -FORWARD(s_forward); /* sphere */ + +struct pj_opaque { + double theta; + double m, n; + double two_r_m, two_r_n, rm, rn, hm, hn; + double cp0, sp0; +}; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double Az, M, N, cp, sp, cl, shz; cp = cos(lp.phi); sp = sin(lp.phi); cl = cos(lp.lam); - Az = aatan2(cp * sin(lp.lam), P->cp0 * sp - P->sp0 * cp * cl) + P->theta; - shz = sin(0.5 * aacos(P->ctx, P->sp0 * sp + P->cp0 * cp * cl)); + Az = aatan2(cp * sin(lp.lam), Q->cp0 * sp - Q->sp0 * cp * cl) + Q->theta; + shz = sin(0.5 * aacos(P->ctx, Q->sp0 * sp + Q->cp0 * cp * cl)); M = aasin(P->ctx, shz * sin(Az)); - N = aasin(P->ctx, shz * cos(Az) * cos(M) / cos(M * P->two_r_m)); - xy.y = P->n * sin(N * P->two_r_n); - xy.x = P->m * sin(M * P->two_r_m) * cos(N) / cos(N * P->two_r_n); - return (xy); + N = aasin(P->ctx, shz * cos(Az) * cos(M) / cos(M * Q->two_r_m)); + xy.y = Q->n * sin(N * Q->two_r_n); + xy.x = Q->m * sin(M * Q->two_r_m) * cos(N) / cos(N * Q->two_r_n); + + return xy; } -INVERSE(s_inverse); /* sphere */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double N, M, xp, yp, z, Az, cz, sz, cAz; - N = P->hn * aasin(P->ctx,xy.y * P->rn); - M = P->hm * aasin(P->ctx,xy.x * P->rm * cos(N * P->two_r_n) / cos(N)); + N = Q->hn * aasin(P->ctx,xy.y * Q->rn); + M = Q->hm * aasin(P->ctx,xy.x * Q->rm * cos(N * Q->two_r_n) / cos(N)); xp = 2. * sin(M); - yp = 2. * sin(N) * cos(M * P->two_r_m) / cos(M); - cAz = cos(Az = aatan2(xp, yp) - P->theta); + yp = 2. * sin(N) * cos(M * Q->two_r_m) / cos(M); + cAz = cos(Az = aatan2(xp, yp) - Q->theta); z = 2. * aasin(P->ctx, 0.5 * hypot(xp, yp)); sz = sin(z); cz = cos(z); - lp.phi = aasin(P->ctx, P->sp0 * cz + P->cp0 * sz * cAz); + lp.phi = aasin(P->ctx, Q->sp0 * cz + Q->cp0 * sz * cAz); lp.lam = aatan2(sz * sin(Az), - P->cp0 * cz - P->sp0 * sz * cAz); - return (lp); + Q->cp0 * cz - Q->sp0 * sz * cAz); + + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(oea) - if (((P->n = pj_param(P->ctx, P->params, "dn").f) <= 0.) || - ((P->m = pj_param(P->ctx, P->params, "dm").f) <= 0.)) + + +PJ *PROJECTION(oea) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_oea; + if (((Q->n = pj_param(P->ctx, P->params, "dn").f) <= 0.) || + ((Q->m = pj_param(P->ctx, P->params, "dm").f) <= 0.)) E_ERROR(-39) else { - P->theta = pj_param(P->ctx, P->params, "rtheta").f; - P->sp0 = sin(P->phi0); - P->cp0 = cos(P->phi0); - P->rn = 1./ P->n; - P->rm = 1./ P->m; - P->two_r_n = 2. * P->rn; - P->two_r_m = 2. * P->rm; - P->hm = 0.5 * P->m; - P->hn = 0.5 * P->n; + Q->theta = pj_param(P->ctx, P->params, "rtheta").f; + Q->sp0 = sin(P->phi0); + Q->cp0 = cos(P->phi0); + Q->rn = 1./ Q->n; + Q->rm = 1./ Q->m; + Q->two_r_n = 2. * Q->rn; + Q->two_r_m = 2. * Q->rm; + Q->hm = 0.5 * Q->m; + Q->hn = 0.5 * Q->n; P->fwd = s_forward; P->inv = s_inverse; P->es = 0.; } -ENDENTRY(P) + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_oea_selftest (void) {return 0;} +#else + +int pj_oea_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=oea +a=6400000 +lat_1=0.5 +lat_2=2 +n=1 +m=2 +theta=3"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 228926.872097864107, 99870.4884300760023}, + { 217242.584036940476, -123247.885607474513}, + {-217242.584036940476, 123247.885607474556}, + {-228926.872097864078, -99870.4884300760168}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0017411857167771369, 0.000987726819566195693}, + { 0.00183489288577854998, -0.000800312481495174641}, + {-0.00183489288577854954, 0.000800312481495174966}, + {-0.00174118571677713712, -0.000987726819566195043}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 492c4048772e4441dbe07c6f74f22efea5c0d5c0 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 3 May 2016 19:46:25 +0200 Subject: Converted omerc. Redined Q-variable in e_forward to W in an effort to keep the mapping P->opaque = Q the same across all projections --- src/PJ_aea.c | 1 - src/PJ_omerc.c | 395 ++++++++++++++++++++++++++++++++++----------------------- 2 files changed, 237 insertions(+), 159 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index aadefd89..a7806344 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -365,7 +365,6 @@ int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} -int pj_omerc_selftest (void) {return 10000;} int pj_ortho_selftest (void) {return 10000;} int pj_patterson_selftest (void) {return 10000;} int pj_poly_selftest (void) {return 10000;} diff --git a/src/PJ_omerc.c b/src/PJ_omerc.c index 8a9fa0db..3b25fb26 100644 --- a/src/PJ_omerc.c +++ b/src/PJ_omerc.c @@ -21,93 +21,125 @@ ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#define PROJ_PARMS__ \ - double A, B, E, AB, ArB, BrA, rB, singam, cosgam, sinrot, cosrot; \ - double v_pole_n, v_pole_s, u_0; \ - int no_rot; #define PJ_LIB__ #include PROJ_HEAD(omerc, "Oblique Mercator") - "\n\tCyl, Sph&Ell no_rot\n\t" -"alpha= [gamma=] [no_off] lonc= or\n\t lon_1= lat_1= lon_2= lat_2="; -#define TOL 1.e-7 -#define EPS 1.e-10 - -FORWARD(e_forward); /* ellipsoid */ - double Q, S, T, U, V, temp, u, v; - - if (fabs(fabs(lp.phi) - HALFPI) > EPS) { - Q = P->E / pow(pj_tsfn(lp.phi, sin(lp.phi), P->e), P->B); - temp = 1. / Q; - S = .5 * (Q - temp); - T = .5 * (Q + temp); - V = sin(P->B * lp.lam); - U = (S * P->singam - V * P->cosgam) / T; - if (fabs(fabs(U) - 1.0) < EPS) - F_ERROR; - v = 0.5 * P->ArB * log((1. - U)/(1. + U)); - temp = cos(P->B * lp.lam); + "\n\tCyl, Sph&Ell no_rot\n\t" + "alpha= [gamma=] [no_off] lonc= or\n\t lon_1= lat_1= lon_2= lat_2="; + +struct pj_opaque { + double A, B, E, AB, ArB, BrA, rB, singam, cosgam, sinrot, cosrot; + double v_pole_n, v_pole_s, u_0; + int no_rot; +}; + +#define TOL 1.e-7 +#define EPS 1.e-10 + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double S, T, U, V, W, temp, u, v; + + if (fabs(fabs(lp.phi) - HALFPI) > EPS) { + W = Q->E / pow(pj_tsfn(lp.phi, sin(lp.phi), Q->E), Q->B); + temp = 1. / W; + S = .5 * (W - temp); + T = .5 * (W + temp); + V = sin(Q->B * lp.lam); + U = (S * Q->singam - V * Q->cosgam) / T; + if (fabs(fabs(U) - 1.0) < EPS) + F_ERROR; + v = 0.5 * Q->ArB * log((1. - U)/(1. + U)); + temp = cos(Q->B * lp.lam); if(fabs(temp) < TOL) { - u = P->A * lp.lam; + u = Q->A * lp.lam; } else { - u = P->ArB * atan2((S * P->cosgam + V * P->singam), temp); + u = Q->ArB * atan2((S * Q->cosgam + V * Q->singam), temp); } - } else { - v = lp.phi > 0 ? P->v_pole_n : P->v_pole_s; - u = P->ArB * lp.phi; - } - if (P->no_rot) { - xy.x = u; - xy.y = v; - } else { - u -= P->u_0; - xy.x = v * P->cosrot + u * P->sinrot; - xy.y = u * P->cosrot - v * P->sinrot; - } - return (xy); + } else { + v = lp.phi > 0 ? Q->v_pole_n : Q->v_pole_s; + u = Q->ArB * lp.phi; + } + if (Q->no_rot) { + xy.x = u; + xy.y = v; + } else { + u -= Q->u_0; + xy.x = v * Q->cosrot + u * Q->sinrot; + xy.y = u * Q->cosrot - v * Q->sinrot; + } + return xy; +} + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double u, v, Qp, Sp, Tp, Vp, Up; + + if (Q->no_rot) { + v = xy.y; + u = xy.x; + } else { + v = xy.x * Q->cosrot - xy.y * Q->sinrot; + u = xy.y * Q->cosrot + xy.x * Q->sinrot + Q->u_0; + } + Qp = exp(- Q->BrA * v); + Sp = .5 * (Qp - 1. / Qp); + Tp = .5 * (Qp + 1. / Qp); + Vp = sin(Q->BrA * u); + Up = (Vp * Q->cosgam + Sp * Q->singam) / Tp; + if (fabs(fabs(Up) - 1.) < EPS) { + lp.lam = 0.; + lp.phi = Up < 0. ? -HALFPI : HALFPI; + } else { + lp.phi = Q->E / sqrt((1. + Up) / (1. - Up)); + if ((lp.phi = pj_phi2(P->ctx, pow(lp.phi, 1. / Q->B), Q->E)) == HUGE_VAL) + I_ERROR; + lp.lam = - Q->rB * atan2((Sp * Q->cosgam - + Vp * Q->singam), cos(Q->BrA * u)); + } + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); } -INVERSE(e_inverse); /* ellipsoid */ - double u, v, Qp, Sp, Tp, Vp, Up; - - if (P->no_rot) { - v = xy.y; - u = xy.x; - } else { - v = xy.x * P->cosrot - xy.y * P->sinrot; - u = xy.y * P->cosrot + xy.x * P->sinrot + P->u_0; - } - Qp = exp(- P->BrA * v); - Sp = .5 * (Qp - 1. / Qp); - Tp = .5 * (Qp + 1. / Qp); - Vp = sin(P->BrA * u); - Up = (Vp * P->cosgam + Sp * P->singam) / Tp; - if (fabs(fabs(Up) - 1.) < EPS) { - lp.lam = 0.; - lp.phi = Up < 0. ? -HALFPI : HALFPI; - } else { - lp.phi = P->E / sqrt((1. + Up) / (1. - Up)); - if ((lp.phi = pj_phi2(P->ctx, pow(lp.phi, 1. / P->B), P->e)) == HUGE_VAL) - I_ERROR; - lp.lam = - P->rB * atan2((Sp * P->cosgam - - Vp * P->singam), cos(P->BrA * u)); - } - return (lp); + +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(omerc) - double con, com, cosph0, D, F, H, L, sinph0, p, J, gamma=0, - gamma0, lamc=0, lam1=0, lam2=0, phi1=0, phi2=0, alpha_c=0; - int alp, gam, no_off = 0; - P->no_rot = pj_param(P->ctx, P->params, "tno_rot").i; + +PJ *PROJECTION(omerc) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + double con, com, cosph0, D, F, H, L, sinph0, p, J, gamma=0, + gamma0, lamc=0, lam1=0, lam2=0, phi1=0, phi2=0, alpha_c=0; + int alp, gam, no_off = 0; + + Q->no_rot = pj_param(P->ctx, P->params, "tno_rot").i; if ((alp = pj_param(P->ctx, P->params, "talpha").i) != 0) - alpha_c = pj_param(P->ctx, P->params, "ralpha").f; + alpha_c = pj_param(P->ctx, P->params, "ralpha").f; if ((gam = pj_param(P->ctx, P->params, "tgamma").i) != 0) - gamma = pj_param(P->ctx, P->params, "rgamma").f; - if (alp || gam) { - lamc = pj_param(P->ctx, P->params, "rlonc").f; - no_off = + gamma = pj_param(P->ctx, P->params, "rgamma").f; + if (alp || gam) { + lamc = pj_param(P->ctx, P->params, "rlonc").f; + no_off = /* For libproj4 compatability */ pj_param(P->ctx, P->params, "tno_off").i /* for backward compatibility */ @@ -118,86 +150,133 @@ ENTRY0(omerc) pj_param(P->ctx, P->params, "sno_uoff"); pj_param(P->ctx, P->params, "sno_off"); } - } else { - lam1 = pj_param(P->ctx, P->params, "rlon_1").f; - phi1 = pj_param(P->ctx, P->params, "rlat_1").f; - lam2 = pj_param(P->ctx, P->params, "rlon_2").f; - phi2 = pj_param(P->ctx, P->params, "rlat_2").f; - if (fabs(phi1 - phi2) <= TOL || - (con = fabs(phi1)) <= TOL || - fabs(con - HALFPI) <= TOL || - fabs(fabs(P->phi0) - HALFPI) <= TOL || - fabs(fabs(phi2) - HALFPI) <= TOL) E_ERROR(-33); - } - com = sqrt(P->one_es); - if (fabs(P->phi0) > EPS) { - sinph0 = sin(P->phi0); - cosph0 = cos(P->phi0); - con = 1. - P->es * sinph0 * sinph0; - P->B = cosph0 * cosph0; - P->B = sqrt(1. + P->es * P->B * P->B / P->one_es); - P->A = P->B * P->k0 * com / con; - D = P->B * com / (cosph0 * sqrt(con)); - if ((F = D * D - 1.) <= 0.) - F = 0.; - else { - F = sqrt(F); - if (P->phi0 < 0.) - F = -F; - } - P->E = F += D; - P->E *= pow(pj_tsfn(P->phi0, sinph0, P->e), P->B); - } else { - P->B = 1. / com; - P->A = P->k0; - P->E = D = F = 1.; - } - if (alp || gam) { - if (alp) { - gamma0 = asin(sin(alpha_c) / D); - if (!gam) - gamma = alpha_c; - } else - alpha_c = asin(D*sin(gamma0 = gamma)); - if ((con = fabs(alpha_c)) <= TOL || - fabs(con - PI) <= TOL || - fabs(fabs(P->phi0) - HALFPI) <= TOL) - E_ERROR(-32); - P->lam0 = lamc - asin(.5 * (F - 1. / F) * - tan(gamma0)) / P->B; - } else { - H = pow(pj_tsfn(phi1, sin(phi1), P->e), P->B); - L = pow(pj_tsfn(phi2, sin(phi2), P->e), P->B); - F = P->E / H; - p = (L - H) / (L + H); - J = P->E * P->E; - J = (J - L * H) / (J + L * H); - if ((con = lam1 - lam2) < -PI) - lam2 -= TWOPI; - else if (con > PI) - lam2 += TWOPI; - P->lam0 = adjlon(.5 * (lam1 + lam2) - atan( - J * tan(.5 * P->B * (lam1 - lam2)) / p) / P->B); - gamma0 = atan(2. * sin(P->B * adjlon(lam1 - P->lam0)) / - (F - 1. / F)); - gamma = alpha_c = asin(D * sin(gamma0)); - } - P->singam = sin(gamma0); - P->cosgam = cos(gamma0); - P->sinrot = sin(gamma); - P->cosrot = cos(gamma); - P->BrA = 1. / (P->ArB = P->A * (P->rB = 1. / P->B)); - P->AB = P->A * P->B; - if (no_off) - P->u_0 = 0; - else { - P->u_0 = fabs(P->ArB * atan2(sqrt(D * D - 1.), cos(alpha_c))); - if (P->phi0 < 0.) - P->u_0 = - P->u_0; - } - F = 0.5 * gamma0; - P->v_pole_n = P->ArB * log(tan(FORTPI - F)); - P->v_pole_s = P->ArB * log(tan(FORTPI + F)); - P->inv = e_inverse; - P->fwd = e_forward; -ENDENTRY(P) + } else { + lam1 = pj_param(P->ctx, P->params, "rlon_1").f; + phi1 = pj_param(P->ctx, P->params, "rlat_1").f; + lam2 = pj_param(P->ctx, P->params, "rlon_2").f; + phi2 = pj_param(P->ctx, P->params, "rlat_2").f; + if (fabs(phi1 - phi2) <= TOL || + (con = fabs(phi1)) <= TOL || + fabs(con - HALFPI) <= TOL || + fabs(fabs(P->phi0) - HALFPI) <= TOL || + fabs(fabs(phi2) - HALFPI) <= TOL) E_ERROR(-33); + } + com = sqrt(P->one_es); + if (fabs(P->phi0) > EPS) { + sinph0 = sin(P->phi0); + cosph0 = cos(P->phi0); + con = 1. - P->es * sinph0 * sinph0; + Q->B = cosph0 * cosph0; + Q->B = sqrt(1. + P->es * Q->B * Q->B / P->one_es); + Q->A = Q->B * P->k0 * com / con; + D = Q->B * com / (cosph0 * sqrt(con)); + if ((F = D * D - 1.) <= 0.) + F = 0.; + else { + F = sqrt(F); + if (P->phi0 < 0.) + F = -F; + } + Q->E = F += D; + Q->E *= pow(pj_tsfn(P->phi0, sinph0, Q->E), Q->B); + } else { + Q->B = 1. / com; + Q->A = P->k0; + Q->E = D = F = 1.; + } + if (alp || gam) { + if (alp) { + gamma0 = asin(sin(alpha_c) / D); + if (!gam) + gamma = alpha_c; + } else + alpha_c = asin(D*sin(gamma0 = gamma)); + if ((con = fabs(alpha_c)) <= TOL || + fabs(con - PI) <= TOL || + fabs(fabs(P->phi0) - HALFPI) <= TOL) + E_ERROR(-32); + P->lam0 = lamc - asin(.5 * (F - 1. / F) * + tan(gamma0)) / Q->B; + } else { + H = pow(pj_tsfn(phi1, sin(phi1), Q->E), Q->B); + L = pow(pj_tsfn(phi2, sin(phi2), Q->E), Q->B); + F = Q->E / H; + p = (L - H) / (L + H); + J = Q->E * Q->E; + J = (J - L * H) / (J + L * H); + if ((con = lam1 - lam2) < -PI) + lam2 -= TWOPI; + else if (con > PI) + lam2 += TWOPI; + P->lam0 = adjlon(.5 * (lam1 + lam2) - atan( + J * tan(.5 * Q->B * (lam1 - lam2)) / p) / Q->B); + gamma0 = atan(2. * sin(Q->B * adjlon(lam1 - P->lam0)) / + (F - 1. / F)); + gamma = alpha_c = asin(D * sin(gamma0)); + } + Q->singam = sin(gamma0); + Q->cosgam = cos(gamma0); + Q->sinrot = sin(gamma); + Q->cosrot = cos(gamma); + Q->BrA = 1. / (Q->ArB = Q->A * (Q->rB = 1. / Q->B)); + Q->AB = Q->A * Q->B; + if (no_off) + Q->u_0 = 0; + else { + Q->u_0 = fabs(Q->ArB * atan2(sqrt(D * D - 1.), cos(alpha_c))); + if (P->phi0 < 0.) + Q->u_0 = - Q->u_0; + } + F = 0.5 * gamma0; + Q->v_pole_n = Q->ArB * log(tan(FORTPI - F)); + Q->v_pole_s = Q->ArB * log(tan(FORTPI + F)); + P->inv = e_inverse; + P->fwd = e_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_omerc_selftest (void) {return 0;} +#else + +int pj_omerc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=omerc +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222650.796885261341, 110642.229314983808}, + { 222650.796885261341, -110642.229314983808}, + {-222650.796885261545, 110642.229314983808}, + {-222650.796885261545, -110642.229314983808}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.00179663056816996357, 0.000904369474808157338}, + { 0.00179663056816996357, -0.000904369474820879583}, + {-0.0017966305681604536, 0.000904369474808157338}, + {-0.0017966305681604536, -0.000904369474820879583}, + }; + + return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); +} + + +#endif -- cgit v1.2.3 From 5e02d7221b994e80c922a14c17755fe5473ec29f Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 3 May 2016 19:51:52 +0200 Subject: Converted ortho --- src/PJ_aea.c | 1 - src/PJ_ortho.c | 131 +++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 105 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index a7806344..5f1c369f 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -365,7 +365,6 @@ int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} -int pj_ortho_selftest (void) {return 10000;} int pj_patterson_selftest (void) {return 10000;} int pj_poly_selftest (void) {return 10000;} int pj_putp2_selftest (void) {return 10000;} diff --git a/src/PJ_ortho.c b/src/PJ_ortho.c index 202b0176..14aeacc3 100644 --- a/src/PJ_ortho.c +++ b/src/PJ_ortho.c @@ -1,29 +1,37 @@ -#define PROJ_PARMS__ \ - double sinph0; \ - double cosph0; \ - int mode; #define PJ_LIB__ -#include +#include + PROJ_HEAD(ortho, "Orthographic") "\n\tAzi, Sph."; + +struct pj_opaque { + double sinph0; + double cosph0; + int mode; +}; + #define EPS10 1.e-10 #define N_POLE 0 #define S_POLE 1 #define EQUIT 2 #define OBLIQ 3 -FORWARD(s_forward); /* spheroid */ + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double coslam, cosphi, sinphi; cosphi = cos(lp.phi); coslam = cos(lp.lam); - switch (P->mode) { + switch (Q->mode) { case EQUIT: if (cosphi * coslam < - EPS10) F_ERROR; xy.y = sin(lp.phi); break; case OBLIQ: - if (P->sinph0 * (sinphi = sin(lp.phi)) + - P->cosph0 * cosphi * coslam < - EPS10) F_ERROR; - xy.y = P->cosph0 * sinphi - P->sinph0 * cosphi * coslam; + if (Q->sinph0 * (sinphi = sin(lp.phi)) + + Q->cosph0 * cosphi * coslam < - EPS10) F_ERROR; + xy.y = Q->cosph0 * sinphi - Q->sinph0 * cosphi * coslam; break; case N_POLE: coslam = - coslam; @@ -33,10 +41,13 @@ FORWARD(s_forward); /* spheroid */ break; } xy.x = cosphi * sin(lp.lam); - return (xy); + return xy; } -INVERSE(s_inverse); /* spheroid */ + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double rh, cosc, sinc; if ((sinc = (rh = hypot(xy.x, xy.y))) > 1.) { @@ -48,7 +59,7 @@ INVERSE(s_inverse); /* spheroid */ lp.phi = P->phi0; lp.lam = 0.0; } else { - switch (P->mode) { + switch (Q->mode) { case N_POLE: xy.y = -xy.y; lp.phi = acos(sinc); @@ -62,9 +73,9 @@ INVERSE(s_inverse); /* spheroid */ xy.y = cosc * rh; goto sinchk; case OBLIQ: - lp.phi = cosc * P->sinph0 + xy.y * sinc * P->cosph0 /rh; - xy.y = (cosc - P->sinph0 * lp.phi) * rh; - xy.x *= sinc * P->cosph0; + lp.phi = cosc * Q->sinph0 + xy.y * sinc * Q->cosph0 /rh; + xy.y = (cosc - Q->sinph0 * lp.phi) * rh; + xy.x *= sinc * Q->cosph0; sinchk: if (fabs(lp.phi) >= 1.) lp.phi = lp.phi < 0. ? -HALFPI : HALFPI; @@ -72,24 +83,92 @@ INVERSE(s_inverse); /* spheroid */ lp.phi = asin(lp.phi); break; } - lp.lam = (xy.y == 0. && (P->mode == OBLIQ || P->mode == EQUIT)) + lp.lam = (xy.y == 0. && (Q->mode == OBLIQ || Q->mode == EQUIT)) ? (xy.x == 0. ? 0. : xy.x < 0. ? -HALFPI : HALFPI) : atan2(xy.x, xy.y); } - return (lp); + return lp; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(ortho) + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(ortho) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + if (fabs(fabs(P->phi0) - HALFPI) <= EPS10) - P->mode = P->phi0 < 0. ? S_POLE : N_POLE; + Q->mode = P->phi0 < 0. ? S_POLE : N_POLE; else if (fabs(P->phi0) > EPS10) { - P->mode = OBLIQ; - P->sinph0 = sin(P->phi0); - P->cosph0 = cos(P->phi0); + Q->mode = OBLIQ; + Q->sinph0 = sin(P->phi0); + Q->cosph0 = cos(P->phi0); } else - P->mode = EQUIT; + Q->mode = EQUIT; P->inv = s_inverse; P->fwd = s_forward; P->es = 0.; -ENDENTRY(P) + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_ortho_selftest (void) {return 0;} +#else + +int pj_ortho_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=ortho +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223322.76057672748, 111695.401198614476}, + { 223322.76057672748, -111695.401198614476}, + {-223322.76057672748, 111695.401198614476}, + {-223322.76057672748, -111695.401198614476}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.0017904931102938101, 0.000895246554928338998}, + { 0.0017904931102938101, -0.000895246554928338998}, + {-0.0017904931102938101, 0.000895246554928338998}, + {-0.0017904931102938101, -0.000895246554928338998}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 41bfed8617fd9f3acb8cf250b1f5ccfcd98e8d8c Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 3 May 2016 20:00:10 +0200 Subject: Converted patterson --- src/PJ_aea.c | 1 - src/PJ_patterson.c | 259 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 167 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 5f1c369f..63e2dfa9 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -365,7 +365,6 @@ int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} -int pj_patterson_selftest (void) {return 10000;} int pj_poly_selftest (void) {return 10000;} int pj_putp2_selftest (void) {return 10000;} int pj_putp3_selftest (void) {return 10000;} diff --git a/src/PJ_patterson.c b/src/PJ_patterson.c index 6fa10c28..f3a18423 100644 --- a/src/PJ_patterson.c +++ b/src/PJ_patterson.c @@ -1,92 +1,167 @@ -/* - * Copyright (c) 2014 Bojan Savric - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * The Patterson Cylindrical projection was designed by Tom Patterson, US National - * Park Service, in 2014, using Flex Projector. The polynomial equations for the - * projection were developed by Bojan Savric, Oregon State University, in - * collaboration with Tom Patterson and Bernhard Jenny, Oregon State University. - * - * Java reference algorithm implemented by Bojan Savric in Java Map Projection - * Library (a Java port of PROJ.4) in the file PattersonProjection.java. - * - * References: - * Java Map Projection Library - * https://github.com/OSUCartography/JMapProjLib - * - * Patterson Cylindrical Projection - * http://shadedrelief.com/patterson/ - * - * Patterson, T., Savric, B., and Jenny, B. (2015). Cartographic Perspectives - * (No.78). Describes the projection design and characteristics, and - * developing the equations. doi:10.14714/CP78.1270 - * http://dx.doi.org/10.14714/CP78.1270 - * - * Port to PROJ.4 by Micah Cochran, 26 March 2016 - */ - -#define PJ_LIB__ -# include -PROJ_HEAD(patterson, "Patterson Cylindrical") "\n\tCyl."; -#define K1 1.0148 -#define K2 0.23185 -#define K3 -0.14499 -#define K4 0.02406 -#define C1 K1 -#define C2 (5.0 * K2) -#define C3 (7.0 * K3) -#define C4 (9.0 * K4) -#define EPS11 1.0e-11 -#define MAX_Y 1.790857183 - -FORWARD(s_forward); /* spheroid */ - double phi2; - (void) P; - phi2 = lp.phi * lp.phi; - xy.x = lp.lam; - xy.y = lp.phi * (K1 + phi2 * phi2 * (K2 + phi2 * (K3 + K4 * phi2))); - return (xy); -} -INVERSE(s_inverse); /* spheroid */ - double yc, tol, y2, f, fder; - (void) P; - yc = xy.y; - - /* make sure y is inside valid range */ - if (xy.y > MAX_Y) { - xy.y = MAX_Y; - } else if (xy.y < -MAX_Y) { - xy.y = -MAX_Y; - } - - for (;;) { /* Newton-Raphson */ - y2 = yc * yc; - f = (yc * (K1 + y2 * y2 * (K2 + y2 * (K3 + K4 * y2)))) - xy.y; - fder = C1 + y2 * y2 * (C2 + y2 * (C3 + C4 * y2)); - yc -= tol = f / fder; - if (fabs(tol) < EPS11) { - break; - } - } - lp.phi = yc; - - /* longitude */ - lp.lam = xy.x; - - return (lp); -} -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(patterson) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) +/* + * Copyright (c) 2014 Bojan Savric + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * The Patterson Cylindrical projection was designed by Tom Patterson, US National + * Park Service, in 2014, using Flex Projector. The polynomial equations for the + * projection were developed by Bojan Savric, Oregon State University, in + * collaboration with Tom Patterson and Bernhard Jenny, Oregon State University. + * + * Java reference algorithm implemented by Bojan Savric in Java Map Projection + * Library (a Java port of PROJ.4) in the file PattersonProjection.java. + * + * References: + * Java Map Projection Library + * https://github.com/OSUCartography/JMapProjLib + * + * Patterson Cylindrical Projection + * http://shadedrelief.com/patterson/ + * + * Patterson, T., Savric, B., and Jenny, B. (2015). Cartographic Perspectives + * (No.78). Describes the projection design and characteristics, and + * developing the equations. doi:10.14714/CP78.1270 + * http://dx.doi.org/10.14714/CP78.1270 + * + * Port to PROJ.4 by Micah Cochran, 26 March 2016 + */ + +#define PJ_LIB__ +#include + +PROJ_HEAD(patterson, "Patterson Cylindrical") "\n\tCyl."; + +#define K1 1.0148 +#define K2 0.23185 +#define K3 -0.14499 +#define K4 0.02406 +#define C1 K1 +#define C2 (5.0 * K2) +#define C3 (7.0 * K3) +#define C4 (9.0 * K4) +#define EPS11 1.0e-11 +#define MAX_Y 1.790857183 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + double phi2; + (void) P; + + phi2 = lp.phi * lp.phi; + xy.x = lp.lam; + xy.y = lp.phi * (K1 + phi2 * phi2 * (K2 + phi2 * (K3 + K4 * phi2))); + + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + double yc, tol, y2, f, fder; + (void) P; + + yc = xy.y; + + /* make sure y is inside valid range */ + if (xy.y > MAX_Y) { + xy.y = MAX_Y; + } else if (xy.y < -MAX_Y) { + xy.y = -MAX_Y; + } + + for (;;) { /* Newton-Raphson */ + y2 = yc * yc; + f = (yc * (K1 + y2 * y2 * (K2 + y2 * (K3 + K4 * y2)))) - xy.y; + fder = C1 + y2 * y2 * (C2 + y2 * (C3 + C4 * y2)); + yc -= tol = f / fder; + if (fabs(tol) < EPS11) { + break; + } + } + lp.phi = yc; + + /* longitude */ + lp.lam = xy.x; + + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(patterson) { + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_patterson_selftest (void) {return 0;} +#else + +int pj_patterson_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=patterson +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {223402.144255274179, 113354.250397779804}, + {223402.144255274179, -113354.250397779804}, + {-223402.144255274179, 113354.250397779804}, + {-223402.144255274179, -113354.250397779804}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + {0.00179049310978382265, 0.000882190140807953657}, + {0.00179049310978382265, -0.000882190140807953657}, + {-0.00179049310978382265, 0.000882190140807953657}, + {-0.00179049310978382265, -0.000882190140807953657}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From a2a3f26d7cb3fdd109376ac913cba54e4126d76b Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 3 May 2016 20:08:54 +0200 Subject: Converted poly --- src/PJ_aea.c | 1 - src/PJ_poly.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 146 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 63e2dfa9..831890fa 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -365,7 +365,6 @@ int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} -int pj_poly_selftest (void) {return 10000;} int pj_putp2_selftest (void) {return 10000;} int pj_putp3_selftest (void) {return 10000;} int pj_putp3p_selftest (void) {return 10000;} diff --git a/src/PJ_poly.c b/src/PJ_poly.c index ef5b8905..50c0ee5f 100644 --- a/src/PJ_poly.c +++ b/src/PJ_poly.c @@ -1,42 +1,67 @@ -#define PROJ_PARMS__ \ - double ml0; \ - double *en; #define PJ_LIB__ #include + PROJ_HEAD(poly, "Polyconic (American)") "\n\tConic, Sph&Ell"; + +struct pj_opaque { + double ml0; \ + double *en; +}; + #define TOL 1e-10 #define CONV 1e-10 #define N_ITER 10 #define I_ITER 20 #define ITOL 1.e-12 -FORWARD(e_forward); /* ellipsoid */ + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double ms, sp, cp; - if (fabs(lp.phi) <= TOL) { xy.x = lp.lam; xy.y = -P->ml0; } - else { + if (fabs(lp.phi) <= TOL) { + xy.x = lp.lam; + xy.y = -Q->ml0; + } else { sp = sin(lp.phi); ms = fabs(cp = cos(lp.phi)) > TOL ? pj_msfn(sp, cp, P->es) / sp : 0.; xy.x = ms * sin(lp.lam *= sp); - xy.y = (pj_mlfn(lp.phi, sp, cp, P->en) - P->ml0) + ms * (1. - cos(lp.lam)); + xy.y = (pj_mlfn(lp.phi, sp, cp, Q->en) - Q->ml0) + ms * (1. - cos(lp.lam)); } - return (xy); + + return xy; } -FORWARD(s_forward); /* spheroid */ + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double cot, E; - if (fabs(lp.phi) <= TOL) { xy.x = lp.lam; xy.y = P->ml0; } - else { + if (fabs(lp.phi) <= TOL) { + xy.x = lp.lam; + xy.y = Q->ml0; + } else { cot = 1. / tan(lp.phi); xy.x = sin(E = lp.lam * sin(lp.phi)) * cot; xy.y = lp.phi - P->phi0 + cot * (1. - cos(E)); } - return (xy); + + return xy; } -INVERSE(e_inverse); /* ellipsoid */ - xy.y += P->ml0; - if (fabs(xy.y) <= TOL) { lp.lam = xy.x; lp.phi = 0.; } - else { + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + xy.y += Q->ml0; + if (fabs(xy.y) <= TOL) { + lp.lam = xy.x; + lp.phi = 0.; + } else { double r, c, sp, cp, s2ph, ml, mlb, mlp, dPhi; int i; @@ -47,7 +72,7 @@ INVERSE(e_inverse); /* ellipsoid */ if (fabs(cp) < ITOL) I_ERROR; c = sp * (mlp = sqrt(1. - P->es * sp * sp)) / cp; - ml = pj_mlfn(lp.phi, sp, cp, P->en); + ml = pj_mlfn(lp.phi, sp, cp, Q->en); mlb = ml * ml + r; mlp = P->one_es / (mlp * mlp * mlp); lp.phi += ( dPhi = @@ -62,14 +87,20 @@ INVERSE(e_inverse); /* ellipsoid */ c = sin(lp.phi); lp.lam = asin(xy.x * tan(lp.phi) * sqrt(1. - P->es * c * c)) / sin(lp.phi); } - return (lp); + + return lp; } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; double B, dphi, tp; int i; - if (fabs(xy.y = P->phi0 + xy.y) <= TOL) { lp.lam = xy.x; lp.phi = 0.; } - else { + if (fabs(xy.y = P->phi0 + xy.y) <= TOL) { + lp.lam = xy.x; + lp.phi = 0.; + } else { lp.phi = xy.y; B = xy.x * xy.x + xy.y * xy.y; i = N_ITER; @@ -82,18 +113,105 @@ INVERSE(s_inverse); /* spheroid */ if (! i) I_ERROR; lp.lam = asin(xy.x * tan(lp.phi)) / sin(lp.phi); } - return (lp); + + return lp; } -FREEUP; if (P) { if (P->en) pj_dalloc(P->en); pj_dalloc(P); } } -ENTRY1(poly, en) + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + if (P->opaque->en) + pj_dealloc (P->opaque->en); + pj_dealloc (P->opaque); + + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(poly) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + if (P->es) { - if (!(P->en = pj_enfn(P->es))) E_ERROR_0; - P->ml0 = pj_mlfn(P->phi0, sin(P->phi0), cos(P->phi0), P->en); + if (!(Q->en = pj_enfn(P->es))) E_ERROR_0; + Q->ml0 = pj_mlfn(P->phi0, sin(P->phi0), cos(P->phi0), Q->en); P->inv = e_inverse; P->fwd = e_forward; } else { - P->ml0 = -P->phi0; + Q->ml0 = -P->phi0; P->inv = s_inverse; P->fwd = s_forward; } -ENDENTRY(P) + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_poly_selftest (void) {return 0;} +#else + +int pj_poly_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=poly +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=poly +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222605.285770237475, 110642.194561440483}, + { 222605.285770237475, -110642.194561440483}, + {-222605.285770237475, 110642.194561440483}, + {-222605.285770237475, -110642.194561440483}, + }; + + XY s_fwd_expect[] = { + { 223368.105210218986, 111769.110491224754}, + { 223368.105210218986, -111769.110491224754}, + {-223368.105210218986, 111769.110491224754}, + {-223368.105210218986, -111769.110491224754}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.00179663056846135222, 0.000904369476631838518}, + { 0.00179663056846135222, -0.000904369476631838518}, + {-0.00179663056846135222, 0.000904369476631838518}, + {-0.00179663056846135222, -0.000904369476631838518}, + }; + + LP s_inv_expect[] = { + { 0.0017904931100023887, 0.000895246554454779222}, + { 0.0017904931100023887, -0.000895246554454779222}, + {-0.0017904931100023887, 0.000895246554454779222}, + {-0.0017904931100023887, -0.000895246554454779222}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 7095617b48c5ba79bb3d20f616d6277552082213 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 3 May 2016 20:25:53 +0200 Subject: Converted putp2 --- src/PJ_aea.c | 1 - src/PJ_putp2.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 81 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 831890fa..dffca5c3 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -365,7 +365,6 @@ int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} -int pj_putp2_selftest (void) {return 10000;} int pj_putp3_selftest (void) {return 10000;} int pj_putp3p_selftest (void) {return 10000;} int pj_putp4p_selftest (void) {return 10000;} diff --git a/src/PJ_putp2.c b/src/PJ_putp2.c index d6fcaea0..4c5a417a 100644 --- a/src/PJ_putp2.c +++ b/src/PJ_putp2.c @@ -1,13 +1,18 @@ #define PJ_LIB__ -#include +#include + PROJ_HEAD(putp2, "Putnins P2") "\n\tPCyl., Sph."; + #define C_x 1.89490 #define C_y 1.71848 #define C_p 0.6141848493043784 #define EPS 1e-10 #define NITER 10 #define PI_DIV_3 1.0471975511965977 -FORWARD(s_forward); /* spheroid */ + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; double p, c, s, V; int i; (void) P; @@ -27,15 +32,84 @@ FORWARD(s_forward); /* spheroid */ lp.phi = lp.phi < 0 ? - PI_DIV_3 : PI_DIV_3; xy.x = C_x * lp.lam * (cos(lp.phi) - 0.5); xy.y = C_y * sin(lp.phi); - return (xy); + + return xy; } -INVERSE(s_inverse); /* spheroid */ + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; double c; lp.phi = aasin(P->ctx,xy.y / C_y); lp.lam = xy.x / (C_x * ((c = cos(lp.phi)) - 0.5)); lp.phi = aasin(P->ctx,(lp.phi + sin(lp.phi) * (c - 1.)) / C_p); - return (lp); + + return lp; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(putp2) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(putp2) { + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_putp2_selftest (void) {return 0;} +#else + +int pj_putp2_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=putp2 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 211638.039634339279, 117895.033043379764}, + { 211638.039634339279, -117895.033043379764}, + {-211638.039634339279, 117895.033043379764}, + {-211638.039634339279, -117895.033043379764}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00188980221640386672, 0.000848201580276863377}, + { 0.00188980221640386672, -0.000848201580276863377}, + {-0.00188980221640386672, 0.000848201580276863377}, + {-0.00188980221640386672, -0.000848201580276863377}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 65f0502425fdd3f5d0a67b94f1ad12c98cbf5694 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 3 May 2016 20:43:09 +0200 Subject: Converted putp3 and putp3p --- src/PJ_aea.c | 2 - src/PJ_putp3.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 168 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index dffca5c3..d5c76ff1 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -365,8 +365,6 @@ int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} -int pj_putp3_selftest (void) {return 10000;} -int pj_putp3p_selftest (void) {return 10000;} int pj_putp4p_selftest (void) {return 10000;} int pj_putp5_selftest (void) {return 10000;} int pj_putp5p_selftest (void) {return 10000;} diff --git a/src/PJ_putp3.c b/src/PJ_putp3.c index 298ce55d..26fc0a90 100644 --- a/src/PJ_putp3.c +++ b/src/PJ_putp3.c @@ -1,26 +1,171 @@ -#define PROJ_PARMS__ \ - double A; #define PJ_LIB__ -# include +#include + +struct pj_opaque { + double A; +}; + PROJ_HEAD(putp3, "Putnins P3") "\n\tPCyl., Sph."; PROJ_HEAD(putp3p, "Putnins P3'") "\n\tPCyl., Sph."; -#define C 0.79788456 -#define RPISQ 0.1013211836 -FORWARD(s_forward); /* spheroid */ - xy.x = C * lp.lam * (1. - P->A * lp.phi * lp.phi); - xy.y = C * lp.phi; - return (xy); -} -INVERSE(s_inverse); /* spheroid */ - lp.phi = xy.y / C; - lp.lam = xy.x / (C * (1. - P->A * lp.phi * lp.phi)); - return (lp); -} -FREEUP; if (P) pj_dalloc(P); } - static PJ * -setup(PJ *P) { - P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; - return P; -} -ENTRY0(putp3) P->A = 4. * RPISQ; ENDENTRY(setup(P)) -ENTRY0(putp3p) P->A = 2. * RPISQ; ENDENTRY(setup(P)) + +#define C 0.79788456 +#define RPISQ 0.1013211836 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + + xy.x = C * lp.lam * (1. - P->opaque->A * lp.phi * lp.phi); + xy.y = C * lp.phi; + + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + + lp.phi = xy.y / C; + lp.lam = xy.x / (C * (1. - P->opaque->A * lp.phi * lp.phi)); + + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(putp3) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->A = 4. * RPISQ; + + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + +PJ *PROJECTION(putp3p) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->A = 2. * RPISQ; + + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_putp3_selftest (void) {return 0;} +#else + +int pj_putp3_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=putp3 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 178227.115507793525, 89124.5607860879827}, + { 178227.115507793525, -89124.5607860879827}, + {-178227.115507793525, 89124.5607860879827}, + {-178227.115507793525, -89124.5607860879827}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00224405032986489889, 0.00112202516475805899}, + { 0.00224405032986489889, -0.00112202516475805899}, + {-0.00224405032986489889, 0.00112202516475805899}, + {-0.00224405032986489889, -0.00112202516475805899}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif + + +#ifdef PJ_OMIT_SELFTEST +int pj_putp3p_selftest (void) {return 0;} +#else + +int pj_putp3p_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=putp3p +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 178238.118539984745, 89124.5607860879827}, + { 178238.118539984745, -89124.5607860879827}, + {-178238.118539984745, 89124.5607860879827}, + {-178238.118539984745, -89124.5607860879827}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00224405032969050844, 0.00112202516475805899}, + { 0.00224405032969050844, -0.00112202516475805899}, + {-0.00224405032969050844, 0.00112202516475805899}, + {-0.00224405032969050844, -0.00112202516475805899}, + + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 0fa0bd162e299b540f626e926c4beefdf01ba9a8 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 3 May 2016 21:10:02 +0200 Subject: Converted putp4p and weren --- src/PJ_aea.c | 2 - src/PJ_putp4p.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 174 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index d5c76ff1..df653cde 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -365,7 +365,6 @@ int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} -int pj_putp4p_selftest (void) {return 10000;} int pj_putp5_selftest (void) {return 10000;} int pj_putp5p_selftest (void) {return 10000;} int pj_putp6_selftest (void) {return 10000;} @@ -382,5 +381,4 @@ int pj_vandg_selftest (void) {return 10000;} int pj_vandg2_selftest (void) {return 10000;} int pj_vandg3_selftest (void) {return 10000;} int pj_vandg4_selftest (void) {return 10000;} -int pj_weren_selftest (void) {return 10000;} #endif diff --git a/src/PJ_putp4p.c b/src/PJ_putp4p.c index 32036bbe..9264d896 100644 --- a/src/PJ_putp4p.c +++ b/src/PJ_putp4p.c @@ -1,29 +1,177 @@ -#define PROJ_PARMS__ \ - double C_x, C_y; #define PJ_LIB__ -# include +#include + +struct pj_opaque { + double C_x, C_y; +}; + PROJ_HEAD(putp4p, "Putnins P4'") "\n\tPCyl., Sph."; PROJ_HEAD(weren, "Werenskiold I") "\n\tPCyl., Sph."; -FORWARD(s_forward); /* spheroid */ - lp.phi = aasin(P->ctx,0.883883476 * sin(lp.phi)); - xy.x = P->C_x * lp.lam * cos(lp.phi); - xy.x /= cos(lp.phi *= 0.333333333333333); - xy.y = P->C_y * sin(lp.phi); - return (xy); -} -INVERSE(s_inverse); /* spheroid */ - lp.phi = aasin(P->ctx,xy.y / P->C_y); - lp.lam = xy.x * cos(lp.phi) / P->C_x; - lp.phi *= 3.; - lp.lam /= cos(lp.phi); - lp.phi = aasin(P->ctx,1.13137085 * sin(lp.phi)); - return (lp); -} -FREEUP; if (P) pj_dalloc(P); } - static PJ * -setup(PJ *P) { - P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; - return P; -} -ENTRY0(putp4p) P->C_x = 0.874038744; P->C_y = 3.883251825; ENDENTRY(setup(P)) -ENTRY0(weren) P->C_x = 1.; P->C_y = 4.442882938; ENDENTRY(setup(P)) + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + lp.phi = aasin(P->ctx,0.883883476 * sin(lp.phi)); + xy.x = Q->C_x * lp.lam * cos(lp.phi); + xy.x /= cos(lp.phi *= 0.333333333333333); + xy.y = Q->C_y * sin(lp.phi); + + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + lp.phi = aasin(P->ctx,xy.y / Q->C_y); + lp.lam = xy.x * cos(lp.phi) / Q->C_x; + lp.phi *= 3.; + lp.lam /= cos(lp.phi); + lp.phi = aasin(P->ctx,1.13137085 * sin(lp.phi)); + + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(putp4p) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->C_x = 0.874038744; + Q->C_y = 3.883251825; + + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +PJ *PROJECTION(weren) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->C_x = 1.; + Q->C_y = 4.442882938; + + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_putp4p_selftest (void) {return 0;} +#else + +int pj_putp4p_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=putp4p +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 195241.47734938623, 127796.782307926231}, + { 195241.47734938623, -127796.782307926231}, + {-195241.47734938623, 127796.782307926231}, + {-195241.47734938623, -127796.782307926231}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00204852830860296001, 0.000782480174932193733}, + { 0.00204852830860296001, -0.000782480174932193733}, + {-0.00204852830860296001, 0.000782480174932193733}, + {-0.00204852830860296001, -0.000782480174932193733}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif + + +#ifdef PJ_OMIT_SELFTEST +int pj_weren_selftest (void) {return 0;} +#else + +int pj_weren_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=weren +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223378.515757633519, 146214.093042288267}, + { 223378.515757633519, -146214.093042288267}, + {-223378.515757633519, 146214.093042288267}, + {-223378.515757633519, -146214.093042288267}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00179049310987240413, 0.000683917989676492265}, + { 0.00179049310987240413, -0.000683917989676492265}, + {-0.00179049310987240413, 0.000683917989676492265}, + {-0.00179049310987240413, -0.000683917989676492265}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From e3a5bfccd02703033dd8821d61b10a7111843ebe Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 3 May 2016 21:24:39 +0200 Subject: Converted putp5 and putp5p --- src/PJ_aea.c | 2 - src/PJ_putp5.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 169 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index df653cde..31a30e47 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -365,8 +365,6 @@ int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} -int pj_putp5_selftest (void) {return 10000;} -int pj_putp5p_selftest (void) {return 10000;} int pj_putp6_selftest (void) {return 10000;} int pj_putp6p_selftest (void) {return 10000;} diff --git a/src/PJ_putp5.c b/src/PJ_putp5.c index 8d3c59a0..d4e59ee8 100644 --- a/src/PJ_putp5.c +++ b/src/PJ_putp5.c @@ -1,26 +1,172 @@ -#define PROJ_PARMS__ \ - double A, B; #define PJ_LIB__ -# include +#include + +struct pj_opaque { + double A, B; +}; + PROJ_HEAD(putp5, "Putnins P5") "\n\tPCyl., Sph."; PROJ_HEAD(putp5p, "Putnins P5'") "\n\tPCyl., Sph."; -#define C 1.01346 -#define D 1.2158542 -FORWARD(s_forward); /* spheroid */ - xy.x = C * lp.lam * (P->A - P->B * sqrt(1. + D * lp.phi * lp.phi)); - xy.y = C * lp.phi; - return (xy); -} -INVERSE(s_inverse); /* spheroid */ - lp.phi = xy.y / C; - lp.lam = xy.x / (C * (P->A - P->B * sqrt(1. + D * lp.phi * lp.phi))); - return (lp); -} -FREEUP; if (P) pj_dalloc(P); } - static PJ * -setup(PJ *P) { - P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; - return P; -} -ENTRY0(putp5) P->A = 2.; P->B = 1.; ENDENTRY(setup(P)) -ENTRY0(putp5p) P->A = 1.5; P->B = 0.5; ENDENTRY(setup(P)) + +#define C 1.01346 +#define D 1.2158542 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + xy.x = C * lp.lam * (Q->A - Q->B * sqrt(1. + D * lp.phi * lp.phi)); + xy.y = C * lp.phi; + + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + lp.phi = xy.y / C; + lp.lam = xy.x / (C * (Q->A - Q->B * sqrt(1. + D * lp.phi * lp.phi))); + + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(putp5) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->A = 2.; + Q->B = 1.; + + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +PJ *PROJECTION(putp5p) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->A = 1.5; + Q->B = 0.5; + + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_putp5_selftest (void) {return 0;} +#else + +int pj_putp5_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=putp5 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 226367.21338056153, 113204.56855847509}, + { 226367.21338056153, -113204.56855847509}, + {-226367.21338056153, 113204.56855847509}, + {-226367.21338056153, -113204.56855847509}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00176671315102969553, 0.000883356575387199546}, + { 0.00176671315102969553, -0.000883356575387199546}, + {-0.00176671315102969553, 0.000883356575387199546}, + {-0.00176671315102969553, -0.000883356575387199546}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + +#endif + + +#ifdef PJ_OMIT_SELFTEST +int pj_putp5p_selftest (void) {return 0;} +#else + +int pj_putp5p_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=putp5p +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 226388.175248755841, 113204.56855847509}, + { 226388.175248755841, -113204.56855847509}, + {-226388.175248755841, 113204.56855847509}, + {-226388.175248755841, -113204.56855847509}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00176671315090204742, 0.000883356575387199546}, + { 0.00176671315090204742, -0.000883356575387199546}, + {-0.00176671315090204742, 0.000883356575387199546}, + {-0.00176671315090204742, -0.000883356575387199546}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + +#endif -- cgit v1.2.3 From 469396398760c183c5f792bd41bff42ad5cd16cd Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 3 May 2016 21:34:50 +0200 Subject: Converted putp6 and putp6p --- src/PJ_aea.c | 2 - src/PJ_putp6.c | 247 ++++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 192 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 31a30e47..931a853c 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -365,8 +365,6 @@ int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} -int pj_putp6_selftest (void) {return 10000;} -int pj_putp6p_selftest (void) {return 10000;} int pj_qsc_selftest (void) {return 10000;} int pj_robin_selftest (void) {return 10000;} diff --git a/src/PJ_putp6.c b/src/PJ_putp6.c index 5909dd4c..7c860cdb 100644 --- a/src/PJ_putp6.c +++ b/src/PJ_putp6.c @@ -1,59 +1,196 @@ -#define PROJ_PARMS__ \ - double C_x, C_y, A, B, D; #define PJ_LIB__ -#include +#include + +struct pj_opaque { + double C_x, C_y, A, B, D; +}; + PROJ_HEAD(putp6, "Putnins P6") "\n\tPCyl., Sph."; PROJ_HEAD(putp6p, "Putnins P6'") "\n\tPCyl., Sph."; -#define EPS 1e-10 -#define NITER 10 + +#define EPS 1e-10 +#define NITER 10 #define CON_POLE 1.732050807568877 -FORWARD(s_forward); /* spheroid */ - double p, r, V; - int i; - - p = P->B * sin(lp.phi); - lp.phi *= 1.10265779; - for (i = NITER; i ; --i) { - r = sqrt(1. + lp.phi * lp.phi); - lp.phi -= V = ( (P->A - r) * lp.phi - log(lp.phi + r) - p ) / - (P->A - 2. * r); - if (fabs(V) < EPS) - break; - } - if (!i) - lp.phi = p < 0. ? -CON_POLE : CON_POLE; - xy.x = P->C_x * lp.lam * (P->D - sqrt(1. + lp.phi * lp.phi)); - xy.y = P->C_y * lp.phi; - return (xy); -} -INVERSE(s_inverse); /* spheroid */ - double r; - - lp.phi = xy.y / P->C_y; - r = sqrt(1. + lp.phi * lp.phi); - lp.lam = xy.x / (P->C_x * (P->D - r)); - lp.phi = aasin( P->ctx, ( (P->A - r) * lp.phi - log(lp.phi + r) ) / P->B); - return (lp); -} -FREEUP; if (P) pj_dalloc(P); } - static PJ * -setup(PJ *P) { - P->es = 0.; - P->inv = s_inverse; - P->fwd = s_forward; - return P; -} -ENTRY0(putp6) - P->C_x = 1.01346; - P->C_y = 0.91910; - P->A = 4.; - P->B = 2.1471437182129378784; - P->D = 2.; -ENDENTRY(setup(P)) -ENTRY0(putp6p) - P->C_x = 0.44329; - P->C_y = 0.80404; - P->A = 6.; - P->B = 5.61125; - P->D = 3.; -ENDENTRY(setup(P)) + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double p, r, V; + int i; + + p = Q->B * sin(lp.phi); + lp.phi *= 1.10265779; + for (i = NITER; i ; --i) { + r = sqrt(1. + lp.phi * lp.phi); + lp.phi -= V = ( (Q->A - r) * lp.phi - log(lp.phi + r) - p ) / + (Q->A - 2. * r); + if (fabs(V) < EPS) + break; + } + if (!i) + lp.phi = p < 0. ? -CON_POLE : CON_POLE; + xy.x = Q->C_x * lp.lam * (Q->D - sqrt(1. + lp.phi * lp.phi)); + xy.y = Q->C_y * lp.phi; + + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double r; + + lp.phi = xy.y / Q->C_y; + r = sqrt(1. + lp.phi * lp.phi); + lp.lam = xy.x / (Q->C_x * (Q->D - r)); + lp.phi = aasin( P->ctx, ( (Q->A - r) * lp.phi - log(lp.phi + r) ) / Q->B); + + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(putp6) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->C_x = 1.01346; + Q->C_y = 0.91910; + Q->A = 4.; + Q->B = 2.1471437182129378784; + Q->D = 2.; + + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +PJ *PROJECTION(putp6p) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->C_x = 0.44329; + Q->C_y = 0.80404; + Q->A = 6.; + Q->B = 5.61125; + Q->D = 3.; + + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_putp6_selftest (void) {return 0;} +#else + +int pj_putp6_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=putp6 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 226369.395133402577, 110218.523796520662}, + { 226369.395133402577, -110218.523796520749}, + {-226369.395133402577, 110218.523796520662}, + {-226369.395133402577, -110218.523796520749}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00176671315102969921, 0.000907295534210503544}, + { 0.00176671315102969921, -0.000907295534205924308}, + {-0.00176671315102969921, 0.000907295534210503544}, + {-0.00176671315102969921, -0.000907295534205924308}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + +#endif + + +#ifdef PJ_OMIT_SELFTEST +int pj_putp6p_selftest (void) {return 0;} +#else + +int pj_putp6p_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=putp6p +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 198034.195132195076, 125989.475461323193}, + { 198034.195132195076, -125989.475461323193}, + {-198034.195132195076, 125989.475461323193}, + {-198034.195132195076, -125989.475461323193}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00201955053120177067, 0.000793716441164738612}, + { 0.00201955053120177067, -0.000793716441164738612}, + {-0.00201955053120177067, 0.000793716441164738612}, + {-0.00201955053120177067, -0.000793716441164738612}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + +#endif -- cgit v1.2.3 From 954d8b9d31ae3378ff1b3eebe55723f1d39007fc Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 3 May 2016 21:56:50 +0200 Subject: Converted qsc --- src/PJ_aea.c | 1 - src/PJ_qsc.c | 676 +++++++++++++++++++++++++++++++++-------------------------- 2 files changed, 383 insertions(+), 294 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 931a853c..e3fd8ae9 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -366,7 +366,6 @@ int pj_longlat_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} -int pj_qsc_selftest (void) {return 10000;} int pj_robin_selftest (void) {return 10000;} int pj_rouss_selftest (void) {return 10000;} int pj_rpoly_selftest (void) {return 10000;} diff --git a/src/PJ_qsc.c b/src/PJ_qsc.c index 12cb9d63..b9e9eb0d 100644 --- a/src/PJ_qsc.c +++ b/src/PJ_qsc.c @@ -28,7 +28,7 @@ * Other projection centers will not work! * * In the projection code below, each cube face is handled differently. - * See the computation of the face parameter in the ENTRY0(qsc) function + * See the computation of the face parameter in the PROJECTION(qsc) function * and the handling of different face values (FACE_*) in the forward and * inverse projections. * @@ -38,15 +38,18 @@ * three areas of a cube face are handled by rotation of AREA_0. */ -#define PROJ_PARMS__ \ - int face; \ - double a_squared; \ - double b; \ - double one_minus_f; \ - double one_minus_f_squared; #define PJ_LIB__ -#include +#include + +struct pj_opaque { + int face; + double a_squared; + double b; + double one_minus_f; + double one_minus_f_squared; +}; PROJ_HEAD(qsc, "Quadrilateralized Spherical Cube") "\n\tAzi, Sph."; + #define EPS10 1.e-10 /* The six cube faces. */ @@ -66,316 +69,403 @@ PROJ_HEAD(qsc, "Quadrilateralized Spherical Cube") "\n\tAzi, Sph."; /* Helper function for forward projection: compute the theta angle * and determine the area number. */ -static double -qsc_fwd_equat_face_theta(double phi, double y, double x, int *area) { - double theta; - if (phi < EPS10) { +static double qsc_fwd_equat_face_theta(double phi, double y, double x, int *area) { + double theta; + if (phi < EPS10) { + *area = AREA_0; + theta = 0.0; + } else { + theta = atan2(y, x); + if (fabs(theta) <= FORTPI) { *area = AREA_0; - theta = 0.0; + } else if (theta > FORTPI && theta <= HALFPI + FORTPI) { + *area = AREA_1; + theta -= HALFPI; + } else if (theta > HALFPI + FORTPI || theta <= -(HALFPI + FORTPI)) { + *area = AREA_2; + theta = (theta >= 0.0 ? theta - PI : theta + PI); } else { - theta = atan2(y, x); - if (fabs(theta) <= FORTPI) { - *area = AREA_0; - } else if (theta > FORTPI && theta <= HALFPI + FORTPI) { - *area = AREA_1; - theta -= HALFPI; - } else if (theta > HALFPI + FORTPI || theta <= -(HALFPI + FORTPI)) { - *area = AREA_2; - theta = (theta >= 0.0 ? theta - PI : theta + PI); - } else { - *area = AREA_3; - theta += HALFPI; - } + *area = AREA_3; + theta += HALFPI; } - return (theta); + } + return theta; } /* Helper function: shift the longitude. */ -static double -qsc_shift_lon_origin(double lon, double offset) { - double slon = lon + offset; - if (slon < -PI) { - slon += TWOPI; - } else if (slon > +PI) { - slon -= TWOPI; - } - return slon; +static double qsc_shift_lon_origin(double lon, double offset) { + double slon = lon + offset; + if (slon < -PI) { + slon += TWOPI; + } else if (slon > +PI) { + slon -= TWOPI; + } + return slon; } -/* Forward projection, ellipsoid */ -FORWARD(e_forward); - double lat, lon; - double theta, phi; - double t, mu; /* nu; */ - int area; - - /* Convert the geodetic latitude to a geocentric latitude. - * This corresponds to the shift from the ellipsoid to the sphere - * described in [LK12]. */ - if (P->es) { - lat = atan(P->one_minus_f_squared * tan(lp.phi)); - } else { - lat = lp.phi; - } - /* Convert the input lat, lon into theta, phi as used by QSC. - * This depends on the cube face and the area on it. - * For the top and bottom face, we can compute theta and phi - * directly from phi, lam. For the other faces, we must use - * unit sphere cartesian coordinates as an intermediate step. */ - lon = lp.lam; - if (P->face == FACE_TOP) { - phi = HALFPI - lat; - if (lon >= FORTPI && lon <= HALFPI + FORTPI) { - area = AREA_0; - theta = lon - HALFPI; - } else if (lon > HALFPI + FORTPI || lon <= -(HALFPI + FORTPI)) { - area = AREA_1; - theta = (lon > 0.0 ? lon - PI : lon + PI); - } else if (lon > -(HALFPI + FORTPI) && lon <= -FORTPI) { - area = AREA_2; - theta = lon + HALFPI; - } else { - area = AREA_3; - theta = lon; - } - } else if (P->face == FACE_BOTTOM) { - phi = HALFPI + lat; - if (lon >= FORTPI && lon <= HALFPI + FORTPI) { - area = AREA_0; - theta = -lon + HALFPI; - } else if (lon < FORTPI && lon >= -FORTPI) { - area = AREA_1; - theta = -lon; - } else if (lon < -FORTPI && lon >= -(HALFPI + FORTPI)) { - area = AREA_2; - theta = -lon - HALFPI; - } else { - area = AREA_3; - theta = (lon > 0.0 ? -lon + PI : -lon - PI); - } - } else { - double q, r, s; - double sinlat, coslat; - double sinlon, coslon; - - if (P->face == FACE_RIGHT) { - lon = qsc_shift_lon_origin(lon, +HALFPI); - } else if (P->face == FACE_BACK) { - lon = qsc_shift_lon_origin(lon, +PI); - } else if (P->face == FACE_LEFT) { - lon = qsc_shift_lon_origin(lon, -HALFPI); - } - sinlat = sin(lat); - coslat = cos(lat); - sinlon = sin(lon); - coslon = cos(lon); - q = coslat * coslon; - r = coslat * sinlon; - s = sinlat; - - if (P->face == FACE_FRONT) { - phi = acos(q); - theta = qsc_fwd_equat_face_theta(phi, s, r, &area); - } else if (P->face == FACE_RIGHT) { - phi = acos(r); - theta = qsc_fwd_equat_face_theta(phi, s, -q, &area); - } else if (P->face == FACE_BACK) { - phi = acos(-q); - theta = qsc_fwd_equat_face_theta(phi, s, -r, &area); - } else if (P->face == FACE_LEFT) { - phi = acos(-r); - theta = qsc_fwd_equat_face_theta(phi, s, q, &area); - } else { - /* Impossible */ - phi = theta = 0.0; - area = AREA_0; - } - } +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double lat, lon; + double theta, phi; + double t, mu; /* nu; */ + int area; - /* Compute mu and nu for the area of definition. - * For mu, see Eq. (3-21) in [OL76], but note the typos: - * compare with Eq. (3-14). For nu, see Eq. (3-38). */ - mu = atan((12.0 / PI) * (theta + acos(sin(theta) * cos(FORTPI)) - HALFPI)); - t = sqrt((1.0 - cos(phi)) / (cos(mu) * cos(mu)) / (1.0 - cos(atan(1.0 / cos(theta))))); - /* nu = atan(t); We don't really need nu, just t, see below. */ + /* Convert the geodetic latitude to a geocentric latitude. + * This corresponds to the shift from the ellipsoid to the sphere + * described in [LK12]. */ + if (P->es) { + lat = atan(Q->one_minus_f_squared * tan(lp.phi)); + } else { + lat = lp.phi; + } - /* Apply the result to the real area. */ - if (area == AREA_1) { - mu += HALFPI; - } else if (area == AREA_2) { - mu += PI; - } else if (area == AREA_3) { - mu += HALFPI + PI; + /* Convert the input lat, lon into theta, phi as used by QSC. + * This depends on the cube face and the area on it. + * For the top and bottom face, we can compute theta and phi + * directly from phi, lam. For the other faces, we must use + * unit sphere cartesian coordinates as an intermediate step. */ + lon = lp.lam; + if (Q->face == FACE_TOP) { + phi = HALFPI - lat; + if (lon >= FORTPI && lon <= HALFPI + FORTPI) { + area = AREA_0; + theta = lon - HALFPI; + } else if (lon > HALFPI + FORTPI || lon <= -(HALFPI + FORTPI)) { + area = AREA_1; + theta = (lon > 0.0 ? lon - PI : lon + PI); + } else if (lon > -(HALFPI + FORTPI) && lon <= -FORTPI) { + area = AREA_2; + theta = lon + HALFPI; + } else { + area = AREA_3; + theta = lon; } - - /* Now compute x, y from mu and nu */ - /* t = tan(nu); */ - xy.x = t * cos(mu); - xy.y = t * sin(mu); - return (xy); -} - -/* Inverse projection, ellipsoid */ -INVERSE(e_inverse); - double mu, nu, cosmu, tannu; - double tantheta, theta, cosphi, phi; - double t; - int area; - - /* Convert the input x, y to the mu and nu angles as used by QSC. - * This depends on the area of the cube face. */ - nu = atan(sqrt(xy.x * xy.x + xy.y * xy.y)); - mu = atan2(xy.y, xy.x); - if (xy.x >= 0.0 && xy.x >= fabs(xy.y)) { + } else if (Q->face == FACE_BOTTOM) { + phi = HALFPI + lat; + if (lon >= FORTPI && lon <= HALFPI + FORTPI) { area = AREA_0; - } else if (xy.y >= 0.0 && xy.y >= fabs(xy.x)) { + theta = -lon + HALFPI; + } else if (lon < FORTPI && lon >= -FORTPI) { area = AREA_1; - mu -= HALFPI; - } else if (xy.x < 0.0 && -xy.x >= fabs(xy.y)) { + theta = -lon; + } else if (lon < -FORTPI && lon >= -(HALFPI + FORTPI)) { area = AREA_2; - mu = (mu < 0.0 ? mu + PI : mu - PI); + theta = -lon - HALFPI; } else { area = AREA_3; - mu += HALFPI; + theta = (lon > 0.0 ? -lon + PI : -lon - PI); } + } else { + double q, r, s; + double sinlat, coslat; + double sinlon, coslon; - /* Compute phi and theta for the area of definition. - * The inverse projection is not described in the original paper, but some - * good hints can be found here (as of 2011-12-14): - * http://fits.gsfc.nasa.gov/fitsbits/saf.93/saf.9302 - * (search for "Message-Id: <9302181759.AA25477 at fits.cv.nrao.edu>") */ - t = (PI / 12.0) * tan(mu); - tantheta = sin(t) / (cos(t) - (1.0 / sqrt(2.0))); - theta = atan(tantheta); - cosmu = cos(mu); - tannu = tan(nu); - cosphi = 1.0 - cosmu * cosmu * tannu * tannu * (1.0 - cos(atan(1.0 / cos(theta)))); - if (cosphi < -1.0) { - cosphi = -1.0; - } else if (cosphi > +1.0) { - cosphi = +1.0; + if (Q->face == FACE_RIGHT) { + lon = qsc_shift_lon_origin(lon, +HALFPI); + } else if (Q->face == FACE_BACK) { + lon = qsc_shift_lon_origin(lon, +PI); + } else if (Q->face == FACE_LEFT) { + lon = qsc_shift_lon_origin(lon, -HALFPI); } + sinlat = sin(lat); + coslat = cos(lat); + sinlon = sin(lon); + coslon = cos(lon); + q = coslat * coslon; + r = coslat * sinlon; + s = sinlat; - /* Apply the result to the real area on the cube face. - * For the top and bottom face, we can compute phi and lam directly. - * For the other faces, we must use unit sphere cartesian coordinates - * as an intermediate step. */ - if (P->face == FACE_TOP) { - phi = acos(cosphi); - lp.phi = HALFPI - phi; - if (area == AREA_0) { - lp.lam = theta + HALFPI; - } else if (area == AREA_1) { - lp.lam = (theta < 0.0 ? theta + PI : theta - PI); - } else if (area == AREA_2) { - lp.lam = theta - HALFPI; - } else /* area == AREA_3 */ { - lp.lam = theta; - } - } else if (P->face == FACE_BOTTOM) { - phi = acos(cosphi); - lp.phi = phi - HALFPI; - if (area == AREA_0) { - lp.lam = -theta + HALFPI; - } else if (area == AREA_1) { - lp.lam = -theta; - } else if (area == AREA_2) { - lp.lam = -theta - HALFPI; - } else /* area == AREA_3 */ { - lp.lam = (theta < 0.0 ? -theta - PI : -theta + PI); - } + if (Q->face == FACE_FRONT) { + phi = acos(q); + theta = qsc_fwd_equat_face_theta(phi, s, r, &area); + } else if (Q->face == FACE_RIGHT) { + phi = acos(r); + theta = qsc_fwd_equat_face_theta(phi, s, -q, &area); + } else if (Q->face == FACE_BACK) { + phi = acos(-q); + theta = qsc_fwd_equat_face_theta(phi, s, -r, &area); + } else if (Q->face == FACE_LEFT) { + phi = acos(-r); + theta = qsc_fwd_equat_face_theta(phi, s, q, &area); } else { - /* Compute phi and lam via cartesian unit sphere coordinates. */ - double q, r, s, t; - q = cosphi; - t = q * q; - if (t >= 1.0) { - s = 0.0; - } else { - s = sqrt(1.0 - t) * sin(theta); - } - t += s * s; - if (t >= 1.0) { - r = 0.0; - } else { - r = sqrt(1.0 - t); - } - /* Rotate q,r,s into the correct area. */ - if (area == AREA_1) { - t = r; - r = -s; - s = t; - } else if (area == AREA_2) { - r = -r; - s = -s; - } else if (area == AREA_3) { - t = r; - r = s; - s = -t; - } - /* Rotate q,r,s into the correct cube face. */ - if (P->face == FACE_RIGHT) { - t = q; - q = -r; - r = t; - } else if (P->face == FACE_BACK) { - q = -q; - r = -r; - } else if (P->face == FACE_LEFT) { - t = q; - q = r; - r = -t; - } - /* Now compute phi and lam from the unit sphere coordinates. */ - lp.phi = acos(-s) - HALFPI; - lp.lam = atan2(r, q); - if (P->face == FACE_RIGHT) { - lp.lam = qsc_shift_lon_origin(lp.lam, -HALFPI); - } else if (P->face == FACE_BACK) { - lp.lam = qsc_shift_lon_origin(lp.lam, -PI); - } else if (P->face == FACE_LEFT) { - lp.lam = qsc_shift_lon_origin(lp.lam, +HALFPI); - } + /* Impossible */ + phi = theta = 0.0; + area = AREA_0; } + } - /* Apply the shift from the sphere to the ellipsoid as described - * in [LK12]. */ - if (P->es) { - int invert_sign; - double tanphi, xa; - invert_sign = (lp.phi < 0.0 ? 1 : 0); - tanphi = tan(lp.phi); - xa = P->b / sqrt(tanphi * tanphi + P->one_minus_f_squared); - lp.phi = atan(sqrt(P->a * P->a - xa * xa) / (P->one_minus_f * xa)); - if (invert_sign) { - lp.phi = -lp.phi; - } - } - return (lp); + /* Compute mu and nu for the area of definition. + * For mu, see Eq. (3-21) in [OL76], but note the typos: + * compare with Eq. (3-14). For nu, see Eq. (3-38). */ + mu = atan((12.0 / PI) * (theta + acos(sin(theta) * cos(FORTPI)) - HALFPI)); + t = sqrt((1.0 - cos(phi)) / (cos(mu) * cos(mu)) / (1.0 - cos(atan(1.0 / cos(theta))))); + /* nu = atan(t); We don't really need nu, just t, see below. */ + + /* Apply the result to the real area. */ + if (area == AREA_1) { + mu += HALFPI; + } else if (area == AREA_2) { + mu += PI; + } else if (area == AREA_3) { + mu += HALFPI + PI; + } + + /* Now compute x, y from mu and nu */ + /* t = tan(nu); */ + xy.x = t * cos(mu); + xy.y = t * sin(mu); + return xy; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(qsc) - P->inv = e_inverse; - P->fwd = e_forward; - /* Determine the cube face from the center of projection. */ - if (P->phi0 >= HALFPI - FORTPI / 2.0) { - P->face = FACE_TOP; - } else if (P->phi0 <= -(HALFPI - FORTPI / 2.0)) { - P->face = FACE_BOTTOM; - } else if (fabs(P->lam0) <= FORTPI) { - P->face = FACE_FRONT; - } else if (fabs(P->lam0) <= HALFPI + FORTPI) { - P->face = (P->lam0 > 0.0 ? FACE_RIGHT : FACE_LEFT); + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double mu, nu, cosmu, tannu; + double tantheta, theta, cosphi, phi; + double t; + int area; + + /* Convert the input x, y to the mu and nu angles as used by QSC. + * This depends on the area of the cube face. */ + nu = atan(sqrt(xy.x * xy.x + xy.y * xy.y)); + mu = atan2(xy.y, xy.x); + if (xy.x >= 0.0 && xy.x >= fabs(xy.y)) { + area = AREA_0; + } else if (xy.y >= 0.0 && xy.y >= fabs(xy.x)) { + area = AREA_1; + mu -= HALFPI; + } else if (xy.x < 0.0 && -xy.x >= fabs(xy.y)) { + area = AREA_2; + mu = (mu < 0.0 ? mu + PI : mu - PI); + } else { + area = AREA_3; + mu += HALFPI; + } + + /* Compute phi and theta for the area of definition. + * The inverse projection is not described in the original paper, but some + * good hints can be found here (as of 2011-12-14): + * http://fits.gsfc.nasa.gov/fitsbits/saf.93/saf.9302 + * (search for "Message-Id: <9302181759.AA25477 at fits.cv.nrao.edu>") */ + t = (PI / 12.0) * tan(mu); + tantheta = sin(t) / (cos(t) - (1.0 / sqrt(2.0))); + theta = atan(tantheta); + cosmu = cos(mu); + tannu = tan(nu); + cosphi = 1.0 - cosmu * cosmu * tannu * tannu * (1.0 - cos(atan(1.0 / cos(theta)))); + if (cosphi < -1.0) { + cosphi = -1.0; + } else if (cosphi > +1.0) { + cosphi = +1.0; + } + + /* Apply the result to the real area on the cube face. + * For the top and bottom face, we can compute phi and lam directly. + * For the other faces, we must use unit sphere cartesian coordinates + * as an intermediate step. */ + if (Q->face == FACE_TOP) { + phi = acos(cosphi); + lp.phi = HALFPI - phi; + if (area == AREA_0) { + lp.lam = theta + HALFPI; + } else if (area == AREA_1) { + lp.lam = (theta < 0.0 ? theta + PI : theta - PI); + } else if (area == AREA_2) { + lp.lam = theta - HALFPI; + } else /* area == AREA_3 */ { + lp.lam = theta; + } + } else if (Q->face == FACE_BOTTOM) { + phi = acos(cosphi); + lp.phi = phi - HALFPI; + if (area == AREA_0) { + lp.lam = -theta + HALFPI; + } else if (area == AREA_1) { + lp.lam = -theta; + } else if (area == AREA_2) { + lp.lam = -theta - HALFPI; + } else /* area == AREA_3 */ { + lp.lam = (theta < 0.0 ? -theta - PI : -theta + PI); + } + } else { + /* Compute phi and lam via cartesian unit sphere coordinates. */ + double q, r, s, t; + q = cosphi; + t = q * q; + if (t >= 1.0) { + s = 0.0; } else { - P->face = FACE_BACK; + s = sqrt(1.0 - t) * sin(theta); } - /* Fill in useful values for the ellipsoid <-> sphere shift - * described in [LK12]. */ - if (P->es) { - P->a_squared = P->a * P->a; - P->b = P->a * sqrt(1.0 - P->es); - P->one_minus_f = 1.0 - (P->a - P->b) / P->a; - P->one_minus_f_squared = P->one_minus_f * P->one_minus_f; + t += s * s; + if (t >= 1.0) { + r = 0.0; + } else { + r = sqrt(1.0 - t); } -ENDENTRY(P) + /* Rotate q,r,s into the correct area. */ + if (area == AREA_1) { + t = r; + r = -s; + s = t; + } else if (area == AREA_2) { + r = -r; + s = -s; + } else if (area == AREA_3) { + t = r; + r = s; + s = -t; + } + /* Rotate q,r,s into the correct cube face. */ + if (Q->face == FACE_RIGHT) { + t = q; + q = -r; + r = t; + } else if (Q->face == FACE_BACK) { + q = -q; + r = -r; + } else if (Q->face == FACE_LEFT) { + t = q; + q = r; + r = -t; + } + /* Now compute phi and lam from the unit sphere coordinates. */ + lp.phi = acos(-s) - HALFPI; + lp.lam = atan2(r, q); + if (Q->face == FACE_RIGHT) { + lp.lam = qsc_shift_lon_origin(lp.lam, -HALFPI); + } else if (Q->face == FACE_BACK) { + lp.lam = qsc_shift_lon_origin(lp.lam, -PI); + } else if (Q->face == FACE_LEFT) { + lp.lam = qsc_shift_lon_origin(lp.lam, +HALFPI); + } + } + + /* Apply the shift from the sphere to the ellipsoid as described + * in [LK12]. */ + if (P->es) { + int invert_sign; + double tanphi, xa; + invert_sign = (lp.phi < 0.0 ? 1 : 0); + tanphi = tan(lp.phi); + xa = Q->b / sqrt(tanphi * tanphi + Q->one_minus_f_squared); + lp.phi = atan(sqrt(P->a * P->a - xa * xa) / (Q->one_minus_f * xa)); + if (invert_sign) { + lp.phi = -lp.phi; + } + } + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(qsc) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->inv = e_inverse; + P->fwd = e_forward; + /* Determine the cube face from the center of projection. */ + if (P->phi0 >= HALFPI - FORTPI / 2.0) { + Q->face = FACE_TOP; + } else if (P->phi0 <= -(HALFPI - FORTPI / 2.0)) { + Q->face = FACE_BOTTOM; + } else if (fabs(P->lam0) <= FORTPI) { + Q->face = FACE_FRONT; + } else if (fabs(P->lam0) <= HALFPI + FORTPI) { + Q->face = (P->lam0 > 0.0 ? FACE_RIGHT : FACE_LEFT); + } else { + Q->face = FACE_BACK; + } + /* Fill in useful values for the ellipsoid <-> sphere shift + * described in [LK12]. */ + if (P->es) { + Q->a_squared = P->a * P->a; + Q->b = P->a * sqrt(1.0 - P->es); + Q->one_minus_f = 1.0 - (P->a - Q->b) / P->a; + Q->one_minus_f_squared = Q->one_minus_f * Q->one_minus_f; + } + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_qsc_selftest (void) {return 0;} +#else + +int pj_qsc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=qsc +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=qsc +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 304638.450843852363, 164123.870923793991}, + { 304638.450843852363, -164123.870923793991}, + {-304638.450843852363, 164123.870923793962}, + {-304638.450843852421, -164123.870923793904}, + }; + + XY s_fwd_expect[] = { + { 305863.792402890511, 165827.722754715243}, + { 305863.792402890511, -165827.722754715243}, + {-305863.792402890511, 165827.722754715243}, + {-305863.792402890569, -165827.722754715156}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.00132134098471627126, 0.000610652900922527926}, + { 0.00132134098471627126, -0.000610652900922527926}, + {-0.00132134098471627126, 0.000610652900922527926}, + {-0.00132134098471627126, -0.000610652900922527926}, + }; + + LP s_inv_expect[] = { + { 0.00131682718763827234, 0.000604493198178676161}, + { 0.00131682718763827234, -0.000604493198178676161}, + {-0.00131682718763827234, 0.000604493198178676161}, + {-0.00131682718763827234, -0.000604493198178676161}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 3e5a67a0679ba9c24773fcb209cc12e32b4808e9 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 3 May 2016 22:03:10 +0200 Subject: Converted robin --- src/PJ_aea.c | 1 - src/PJ_robin.c | 195 ++++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 136 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index e3fd8ae9..e2d59d17 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -366,7 +366,6 @@ int pj_longlat_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} -int pj_robin_selftest (void) {return 10000;} int pj_rouss_selftest (void) {return 10000;} int pj_rpoly_selftest (void) {return 10000;} int pj_sch_selftest (void) {return 10000;} diff --git a/src/PJ_robin.c b/src/PJ_robin.c index e8572ae4..5fabd9d0 100644 --- a/src/PJ_robin.c +++ b/src/PJ_robin.c @@ -1,10 +1,12 @@ #define PJ_LIB__ -#include +#include + PROJ_HEAD(robin, "Robinson") "\n\tPCyl., Sph."; + #define V(C,z) (C.c0 + z * (C.c1 + z * (C.c2 + z * C.c3))) #define DV(C,z) (C.c1 + z * (C.c2 + C.c2 + z * 3. * C.c3)) -/* +/* note: following terms based upon 5 deg. intervals in degrees. Some background on these coefficients is available at: @@ -14,7 +16,7 @@ http://trac.osgeo.org/proj/ticket/113 */ struct COEFS { - float c0, c1, c2, c3; + float c0, c1, c2, c3; }; static const struct COEFS X[] = { @@ -38,6 +40,7 @@ static const struct COEFS X[] = { {0.5722, -0.00906601, 0.000182, 6.24051e-06}, {0.5322, -0.00677797, 0.000275608, 6.24051e-06} }; + static const struct COEFS Y[] = { {-5.20417e-18, 0.0124, 1.21431e-18, -8.45284e-11}, {0.062, 0.0124, -1.26793e-09, 4.22642e-10}, @@ -59,61 +62,135 @@ static const struct COEFS Y[] = { {0.9761, 0.00616527, -0.000256, -4.2106e-06}, {1, 0.00328947, -0.000319159, -4.2106e-06} }; -#define FXC 0.8487 -#define FYC 1.3523 -#define C1 11.45915590261646417544 -#define RC1 0.08726646259971647884 -#define NODES 18 -#define ONEEPS 1.000001 -#define EPS 1e-8 -FORWARD(s_forward); /* spheroid */ - int i; - double dphi; - (void) P; - - i = floor((dphi = fabs(lp.phi)) * C1); - if (i >= NODES) i = NODES - 1; - dphi = RAD_TO_DEG * (dphi - RC1 * i); - xy.x = V(X[i], dphi) * FXC * lp.lam; - xy.y = V(Y[i], dphi) * FYC; - if (lp.phi < 0.) xy.y = -xy.y; - return (xy); + +#define FXC 0.8487 +#define FYC 1.3523 +#define C1 11.45915590261646417544 +#define RC1 0.08726646259971647884 +#define NODES 18 +#define ONEEPS 1.000001 +#define EPS 1e-8 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + int i; + double dphi; + (void) P; + + i = floor((dphi = fabs(lp.phi)) * C1); + if (i >= NODES) i = NODES - 1; + dphi = RAD_TO_DEG * (dphi - RC1 * i); + xy.x = V(X[i], dphi) * FXC * lp.lam; + xy.y = V(Y[i], dphi) * FYC; + if (lp.phi < 0.) xy.y = -xy.y; + + return xy; +} + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + int i; + double t, t1; + struct COEFS T; + + lp.lam = xy.x / FXC; + lp.phi = fabs(xy.y / FYC); + if (lp.phi >= 1.) { /* simple pathologic cases */ + if (lp.phi > ONEEPS) I_ERROR + else { + lp.phi = xy.y < 0. ? -HALFPI : HALFPI; + lp.lam /= X[NODES].c0; + } + } else { /* general problem */ + /* in Y space, reduce to table interval */ + for (i = floor(lp.phi * NODES);;) { + if (Y[i].c0 > lp.phi) --i; + else if (Y[i+1].c0 <= lp.phi) ++i; + else break; + } + T = Y[i]; + /* first guess, linear interp */ + t = 5. * (lp.phi - T.c0)/(Y[i+1].c0 - T.c0); + /* make into root */ + T.c0 -= lp.phi; + for (;;) { /* Newton-Raphson reduction */ + t -= t1 = V(T,t) / DV(T,t); + if (fabs(t1) < EPS) + break; + } + lp.phi = (5 * i + t) * DEG_TO_RAD; + if (xy.y < 0.) lp.phi = -lp.phi; + lp.lam /= V(X[i], t); + } + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; } -INVERSE(s_inverse); /* spheroid */ - int i; - double t, t1; - struct COEFS T; - - lp.lam = xy.x / FXC; - lp.phi = fabs(xy.y / FYC); - if (lp.phi >= 1.) { /* simple pathologic cases */ - if (lp.phi > ONEEPS) I_ERROR - else { - lp.phi = xy.y < 0. ? -HALFPI : HALFPI; - lp.lam /= X[NODES].c0; - } - } else { /* general problem */ - /* in Y space, reduce to table interval */ - for (i = floor(lp.phi * NODES);;) { - if (Y[i].c0 > lp.phi) --i; - else if (Y[i+1].c0 <= lp.phi) ++i; - else break; - } - T = Y[i]; - /* first guess, linear interp */ - t = 5. * (lp.phi - T.c0)/(Y[i+1].c0 - T.c0); - /* make into root */ - T.c0 -= lp.phi; - for (;;) { /* Newton-Raphson reduction */ - t -= t1 = V(T,t) / DV(T,t); - if (fabs(t1) < EPS) - break; - } - lp.phi = (5 * i + t) * DEG_TO_RAD; - if (xy.y < 0.) lp.phi = -lp.phi; - lp.lam /= V(X[i], t); - } - return (lp); + + +PJ *PROJECTION(robin) { + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(robin) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +#ifdef PJ_OMIT_SELFTEST +int pj_robin_selftest (void) {return 0;} +#else + +int pj_robin_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=robin +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 189588.423282507836, 107318.530350702888}, + { 189588.423282507836, -107318.530350702888}, + {-189588.423282507836, 107318.530350702888}, + {-189588.423282507836, -107318.530350702888}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.002109689065506131, 0.000931805533547745983}, + { 0.002109689065506131, -0.000931805533547745983}, + {-0.002109689065506131, 0.000931805533547745983}, + {-0.002109689065506131, -0.000931805533547745983}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 2f011ebaf688088026c5664fc95b5714ace0d73f Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 3 May 2016 22:12:25 +0200 Subject: Converted rpoly --- src/PJ_aea.c | 1 - src/PJ_rpoly.c | 128 ++++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 96 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index e2d59d17..8e83e5a2 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -367,7 +367,6 @@ int pj_longlat_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} int pj_rouss_selftest (void) {return 10000;} -int pj_rpoly_selftest (void) {return 10000;} int pj_sch_selftest (void) {return 10000;} int pj_utm_selftest (void) {return 10000;} diff --git a/src/PJ_rpoly.c b/src/PJ_rpoly.c index 7a7670ed..ad240917 100644 --- a/src/PJ_rpoly.c +++ b/src/PJ_rpoly.c @@ -1,35 +1,99 @@ -#define PROJ_PARMS__ \ - double phi1; \ - double fxa; \ - double fxb; \ - int mode; -#define EPS 1e-9 #define PJ_LIB__ -#include +#include + +struct pj_opaque { + double phi1; + double fxa; + double fxb; + int mode; +}; + PROJ_HEAD(rpoly, "Rectangular Polyconic") - "\n\tConic, Sph., no inv.\n\tlat_ts="; -FORWARD(s_forward); /* spheroid */ - double fa; - - if (P->mode) - fa = tan(lp.lam * P->fxb) * P->fxa; - else - fa = 0.5 * lp.lam; - if (fabs(lp.phi) < EPS) { - xy.x = fa + fa; - xy.y = - P->phi0; - } else { - xy.y = 1. / tan(lp.phi); - xy.x = sin(fa = 2. * atan(fa * sin(lp.phi))) * xy.y; - xy.y = lp.phi - P->phi0 + (1. - cos(fa)) * xy.y; - } - return (xy); + "\n\tConic, Sph., no inv.\n\tlat_ts="; + +#define EPS 1e-9 + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double fa; + + if (Q->mode) + fa = tan(lp.lam * Q->fxb) * Q->fxa; + else + fa = 0.5 * lp.lam; + if (fabs(lp.phi) < EPS) { + xy.x = fa + fa; + xy.y = - P->phi0; + } else { + xy.y = 1. / tan(lp.phi); + xy.x = sin(fa = 2. * atan(fa * sin(lp.phi))) * xy.y; + xy.y = lp.phi - P->phi0 + (1. - cos(fa)) * xy.y; + } + return xy; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(rpoly) - if ((P->mode = (P->phi1 = fabs(pj_param(P->ctx, P->params, "rlat_ts").f)) > EPS)) { - P->fxb = 0.5 * sin(P->phi1); - P->fxa = 0.5 / P->fxb; - } - P->es = 0.; P->fwd = s_forward; -ENDENTRY(P) + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(rpoly) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + if ((Q->mode = (Q->phi1 = fabs(pj_param(P->ctx, P->params, "rlat_ts").f)) > EPS)) { + Q->fxb = 0.5 * sin(Q->phi1); + Q->fxa = 0.5 / Q->fxb; + } + P->es = 0.; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_rpoly_selftest (void) {return 0;} +#else + +int pj_rpoly_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=rpoly +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223368.09830201423, 111769.110486991223}, + { 223368.09830201423, -111769.110486991223}, + {-223368.09830201423, 111769.110486991223}, + {-223368.09830201423, -111769.110486991223}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} + + +#endif -- cgit v1.2.3 From 9f7e2b4fc65d3d6b15ef5466e6024ed797550235 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 3 May 2016 22:39:36 +0200 Subject: Converted aeqd --- src/PJ_aea.c | 1 - src/PJ_aeqd.c | 544 +++++++++++++++++++++++++++++++++++----------------------- 2 files changed, 327 insertions(+), 218 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 8e83e5a2..cb1be3d5 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -353,7 +353,6 @@ source files ***********************************************************************/ -int pj_aeqd_selftest (void) {return 10000;} int pj_eqc_selftest (void) {return 10000;} int pj_eqdc_selftest (void) {return 10000;} int pj_etmerc_selftest (void) {return 10000;} diff --git a/src/PJ_aeqd.c b/src/PJ_aeqd.c index 22a75ac8..560d5a91 100644 --- a/src/PJ_aeqd.c +++ b/src/PJ_aeqd.c @@ -25,236 +25,346 @@ * DEALINGS IN THE SOFTWARE. *****************************************************************************/ -#define PROJ_PARMS__ \ - double sinph0; \ - double cosph0; \ - double *en; \ - double M1; \ - double N1; \ - double Mp; \ - double He; \ - double G; \ - int mode; \ - struct geod_geodesic g; #define PJ_LIB__ -#include "geodesic.h" -#include +#include "geodesic.h" +#include + +struct pj_opaque { + double sinph0; + double cosph0; + double *en; + double M1; + double N1; + double Mp; + double He; + double G; + int mode; + struct geod_geodesic g; +}; PROJ_HEAD(aeqd, "Azimuthal Equidistant") "\n\tAzi, Sph&Ell\n\tlat_0 guam"; #define EPS10 1.e-10 #define TOL 1.e-14 -#define N_POLE 0 -#define S_POLE 1 -#define EQUIT 2 -#define OBLIQ 3 - -FORWARD(e_guam_fwd); /* Guam elliptical */ - double cosphi, sinphi, t; - - cosphi = cos(lp.phi); - sinphi = sin(lp.phi); - t = 1. / sqrt(1. - P->es * sinphi * sinphi); - xy.x = lp.lam * cosphi * t; - xy.y = pj_mlfn(lp.phi, sinphi, cosphi, P->en) - P->M1 + - .5 * lp.lam * lp.lam * cosphi * sinphi * t; - return (xy); +#define N_POLE 0 +#define S_POLE 1 +#define EQUIT 2 +#define OBLIQ 3 + + +static XY e_guam_fwd(LP lp, PJ *P) { /* Guam elliptical */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double cosphi, sinphi, t; + + cosphi = cos(lp.phi); + sinphi = sin(lp.phi); + t = 1. / sqrt(1. - P->es * sinphi * sinphi); + xy.x = lp.lam * cosphi * t; + xy.y = pj_mlfn(lp.phi, sinphi, cosphi, Q->en) - Q->M1 + + .5 * lp.lam * lp.lam * cosphi * sinphi * t; + + return xy; } -FORWARD(e_forward); /* elliptical */ - double coslam, cosphi, sinphi, rho; - double azi1, azi2, s12; - double lam1, phi1, lam2, phi2; - - coslam = cos(lp.lam); - cosphi = cos(lp.phi); - sinphi = sin(lp.phi); - switch (P->mode) { - case N_POLE: - coslam = - coslam; - case S_POLE: - xy.x = (rho = fabs(P->Mp - pj_mlfn(lp.phi, sinphi, cosphi, P->en))) * - sin(lp.lam); - xy.y = rho * coslam; - break; - case EQUIT: - case OBLIQ: - if (fabs(lp.lam) < EPS10 && fabs(lp.phi - P->phi0) < EPS10) { - xy.x = xy.y = 0.; - break; - } - - phi1 = P->phi0 / DEG_TO_RAD; lam1 = P->lam0 / DEG_TO_RAD; - phi2 = lp.phi / DEG_TO_RAD; lam2 = (lp.lam+P->lam0) / DEG_TO_RAD; - - geod_inverse(&P->g, phi1, lam1, phi2, lam2, &s12, &azi1, &azi2); - azi1 *= DEG_TO_RAD; - xy.x = s12 * sin(azi1) / P->a; - xy.y = s12 * cos(azi1) / P->a; - break; - } - return (xy); + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double coslam, cosphi, sinphi, rho; + double azi1, azi2, s12; + double lam1, phi1, lam2, phi2; + + coslam = cos(lp.lam); + cosphi = cos(lp.phi); + sinphi = sin(lp.phi); + switch (Q->mode) { + case N_POLE: + coslam = - coslam; + case S_POLE: + xy.x = (rho = fabs(Q->Mp - pj_mlfn(lp.phi, sinphi, cosphi, Q->en))) * + sin(lp.lam); + xy.y = rho * coslam; + break; + case EQUIT: + case OBLIQ: + if (fabs(lp.lam) < EPS10 && fabs(lp.phi - P->phi0) < EPS10) { + xy.x = xy.y = 0.; + break; + } + + phi1 = P->phi0 / DEG_TO_RAD; lam1 = P->lam0 / DEG_TO_RAD; + phi2 = lp.phi / DEG_TO_RAD; lam2 = (lp.lam+P->lam0) / DEG_TO_RAD; + + geod_inverse(&Q->g, phi1, lam1, phi2, lam2, &s12, &azi1, &azi2); + azi1 *= DEG_TO_RAD; + xy.x = s12 * sin(azi1) / P->a; + xy.y = s12 * cos(azi1) / P->a; + break; + } + return xy; } -FORWARD(s_forward); /* spherical */ - double coslam, cosphi, sinphi; - - sinphi = sin(lp.phi); - cosphi = cos(lp.phi); - coslam = cos(lp.lam); - switch (P->mode) { - case EQUIT: - xy.y = cosphi * coslam; - goto oblcon; - case OBLIQ: - xy.y = P->sinph0 * sinphi + P->cosph0 * cosphi * coslam; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double coslam, cosphi, sinphi; + + sinphi = sin(lp.phi); + cosphi = cos(lp.phi); + coslam = cos(lp.lam); + switch (Q->mode) { + case EQUIT: + xy.y = cosphi * coslam; + goto oblcon; + case OBLIQ: + xy.y = Q->sinph0 * sinphi + Q->cosph0 * cosphi * coslam; oblcon: - if (fabs(fabs(xy.y) - 1.) < TOL) - if (xy.y < 0.) - F_ERROR - else - xy.x = xy.y = 0.; - else { - xy.y = acos(xy.y); - xy.y /= sin(xy.y); - xy.x = xy.y * cosphi * sin(lp.lam); - xy.y *= (P->mode == EQUIT) ? sinphi : - P->cosph0 * sinphi - P->sinph0 * cosphi * coslam; - } - break; - case N_POLE: - lp.phi = -lp.phi; - coslam = -coslam; - case S_POLE: - if (fabs(lp.phi - HALFPI) < EPS10) F_ERROR; - xy.x = (xy.y = (HALFPI + lp.phi)) * sin(lp.lam); - xy.y *= coslam; - break; - } - return (xy); + if (fabs(fabs(xy.y) - 1.) < TOL) + if (xy.y < 0.) + F_ERROR + else + xy.x = xy.y = 0.; + else { + xy.y = acos(xy.y); + xy.y /= sin(xy.y); + xy.x = xy.y * cosphi * sin(lp.lam); + xy.y *= (Q->mode == EQUIT) ? sinphi : + Q->cosph0 * sinphi - Q->sinph0 * cosphi * coslam; + } + break; + case N_POLE: + lp.phi = -lp.phi; + coslam = -coslam; + case S_POLE: + if (fabs(lp.phi - HALFPI) < EPS10) F_ERROR; + xy.x = (xy.y = (HALFPI + lp.phi)) * sin(lp.lam); + xy.y *= coslam; + break; + } + return xy; } -INVERSE(e_guam_inv); /* Guam elliptical */ - double x2, t; - int i; - - x2 = 0.5 * xy.x * xy.x; - lp.phi = P->phi0; - for (i = 0; i < 3; ++i) { - t = P->e * sin(lp.phi); - lp.phi = pj_inv_mlfn(P->ctx, P->M1 + xy.y - - x2 * tan(lp.phi) * (t = sqrt(1. - t * t)), P->es, P->en); - } - lp.lam = xy.x * t / cos(lp.phi); - return (lp); + + +static LP e_guam_inv(XY xy, PJ *P) { /* Guam elliptical */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double x2, t; + int i; + + x2 = 0.5 * xy.x * xy.x; + lp.phi = P->phi0; + for (i = 0; i < 3; ++i) { + t = P->e * sin(lp.phi); + lp.phi = pj_inv_mlfn(P->ctx, Q->M1 + xy.y - + x2 * tan(lp.phi) * (t = sqrt(1. - t * t)), P->es, Q->en); + } + lp.lam = xy.x * t / cos(lp.phi); + return lp; } -INVERSE(e_inverse); /* elliptical */ - double c; - double azi1, azi2, s12, x2, y2, lat1, lon1, lat2, lon2; - - if ((c = hypot(xy.x, xy.y)) < EPS10) { - lp.phi = P->phi0; - lp.lam = 0.; - return (lp); - } - if (P->mode == OBLIQ || P->mode == EQUIT) { - - x2 = xy.x * P->a; - y2 = xy.y * P->a; - lat1 = P->phi0 / DEG_TO_RAD; - lon1 = P->lam0 / DEG_TO_RAD; - azi1 = atan2(x2, y2) / DEG_TO_RAD; - s12 = sqrt(x2 * x2 + y2 * y2); - geod_direct(&P->g, lat1, lon1, azi1, s12, &lat2, &lon2, &azi2); - lp.phi = lat2 * DEG_TO_RAD; - lp.lam = lon2 * DEG_TO_RAD; - lp.lam -= P->lam0; - } else { /* Polar */ - lp.phi = pj_inv_mlfn(P->ctx, P->mode == N_POLE ? P->Mp - c : P->Mp + c, - P->es, P->en); - lp.lam = atan2(xy.x, P->mode == N_POLE ? -xy.y : xy.y); - } - return (lp); + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double c; + double azi1, azi2, s12, x2, y2, lat1, lon1, lat2, lon2; + + if ((c = hypot(xy.x, xy.y)) < EPS10) { + lp.phi = P->phi0; + lp.lam = 0.; + return (lp); + } + if (Q->mode == OBLIQ || Q->mode == EQUIT) { + + x2 = xy.x * P->a; + y2 = xy.y * P->a; + lat1 = P->phi0 / DEG_TO_RAD; + lon1 = P->lam0 / DEG_TO_RAD; + azi1 = atan2(x2, y2) / DEG_TO_RAD; + s12 = sqrt(x2 * x2 + y2 * y2); + geod_direct(&Q->g, lat1, lon1, azi1, s12, &lat2, &lon2, &azi2); + lp.phi = lat2 * DEG_TO_RAD; + lp.lam = lon2 * DEG_TO_RAD; + lp.lam -= P->lam0; + } else { /* Polar */ + lp.phi = pj_inv_mlfn(P->ctx, Q->mode == N_POLE ? Q->Mp - c : Q->Mp + c, + P->es, Q->en); + lp.lam = atan2(xy.x, Q->mode == N_POLE ? -xy.y : xy.y); + } + return lp; } -INVERSE(s_inverse); /* spherical */ - double cosc, c_rh, sinc; - - if ((c_rh = hypot(xy.x, xy.y)) > PI) { - if (c_rh - EPS10 > PI) I_ERROR; - c_rh = PI; - } else if (c_rh < EPS10) { - lp.phi = P->phi0; - lp.lam = 0.; - return (lp); - } - if (P->mode == OBLIQ || P->mode == EQUIT) { - sinc = sin(c_rh); - cosc = cos(c_rh); - if (P->mode == EQUIT) { + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double cosc, c_rh, sinc; + + if ((c_rh = hypot(xy.x, xy.y)) > PI) { + if (c_rh - EPS10 > PI) I_ERROR; + c_rh = PI; + } else if (c_rh < EPS10) { + lp.phi = P->phi0; + lp.lam = 0.; + return (lp); + } + if (Q->mode == OBLIQ || Q->mode == EQUIT) { + sinc = sin(c_rh); + cosc = cos(c_rh); + if (Q->mode == EQUIT) { lp.phi = aasin(P->ctx, xy.y * sinc / c_rh); - xy.x *= sinc; - xy.y = cosc * c_rh; - } else { - lp.phi = aasin(P->ctx,cosc * P->sinph0 + xy.y * sinc * P->cosph0 / - c_rh); - xy.y = (cosc - P->sinph0 * sin(lp.phi)) * c_rh; - xy.x *= sinc * P->cosph0; - } - lp.lam = xy.y == 0. ? 0. : atan2(xy.x, xy.y); - } else if (P->mode == N_POLE) { - lp.phi = HALFPI - c_rh; - lp.lam = atan2(xy.x, -xy.y); - } else { - lp.phi = c_rh - HALFPI; - lp.lam = atan2(xy.x, xy.y); - } - return (lp); + xy.x *= sinc; + xy.y = cosc * c_rh; + } else { + lp.phi = aasin(P->ctx,cosc * Q->sinph0 + xy.y * sinc * Q->cosph0 / + c_rh); + xy.y = (cosc - Q->sinph0 * sin(lp.phi)) * c_rh; + xy.x *= sinc * Q->cosph0; + } + lp.lam = xy.y == 0. ? 0. : atan2(xy.x, xy.y); + } else if (Q->mode == N_POLE) { + lp.phi = HALFPI - c_rh; + lp.lam = atan2(xy.x, -xy.y); + } else { + lp.phi = c_rh - HALFPI; + lp.lam = atan2(xy.x, xy.y); + } + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + if (P->opaque->en) + pj_dealloc(P->opaque->en); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; - if (P) { - if (P->en) - pj_dalloc(P->en); - pj_dalloc(P); - } + + +PJ *PROJECTION(aeqd) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + geod_init(&Q->g, P->a, P->es / (1 + sqrt(P->one_es))); + P->phi0 = pj_param(P->ctx, P->params, "rlat_0").f; + if (fabs(fabs(P->phi0) - HALFPI) < EPS10) { + Q->mode = P->phi0 < 0. ? S_POLE : N_POLE; + Q->sinph0 = P->phi0 < 0. ? -1. : 1.; + Q->cosph0 = 0.; + } else if (fabs(P->phi0) < EPS10) { + Q->mode = EQUIT; + Q->sinph0 = 0.; + Q->cosph0 = 1.; + } else { + Q->mode = OBLIQ; + Q->sinph0 = sin(P->phi0); + Q->cosph0 = cos(P->phi0); + } + if (! P->es) { + P->inv = s_inverse; + P->fwd = s_forward; + } else { + if (!(Q->en = pj_enfn(P->es))) E_ERROR_0; + if (pj_param(P->ctx, P->params, "bguam").i) { + Q->M1 = pj_mlfn(P->phi0, Q->sinph0, Q->cosph0, Q->en); + P->inv = e_guam_inv; + P->fwd = e_guam_fwd; + } else { + switch (Q->mode) { + case N_POLE: + Q->Mp = pj_mlfn(HALFPI, 1., 0., Q->en); + break; + case S_POLE: + Q->Mp = pj_mlfn(-HALFPI, -1., 0., Q->en); + break; + case EQUIT: + case OBLIQ: + P->inv = e_inverse; P->fwd = e_forward; + Q->N1 = 1. / sqrt(1. - P->es * Q->sinph0 * Q->sinph0); + Q->G = Q->sinph0 * (Q->He = P->e / sqrt(P->one_es)); + Q->He *= Q->cosph0; + break; + } + P->inv = e_inverse; + P->fwd = e_forward; + } + } + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_aeqd_selftest (void) {return 0;} +#else + +int pj_aeqd_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=aeqd +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=aeqd +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222616.522190051648, 110596.996549550197}, + { 222616.522190051648, -110596.996549550211}, + {-222616.522190051648, 110596.996549550197}, + {-222616.522190051648, -110596.996549550211}, + }; + + XY s_fwd_expect[] = { + { 223379.456047271, 111723.757570854126}, + { 223379.456047271, -111723.757570854126}, + {-223379.456047271, 111723.757570854126}, + {-223379.456047271, -111723.757570854126}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.00179663056838724787, 0.000904369476930248902}, + { 0.00179663056838724787, -0.000904369476930248469}, + {-0.00179663056838724787, 0.000904369476930248902}, + {-0.00179663056838724787, -0.000904369476930248469}, + }; + + LP s_inv_expect[] = { + { 0.00179049310992953335, 0.000895246554746200623}, + { 0.00179049310992953335, -0.000895246554746200623}, + {-0.00179049310992953335, 0.000895246554746200623}, + {-0.00179049310992953335, -0.000895246554746200623}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); } -ENTRY1(aeqd, en) - geod_init(&P->g, P->a, P->es / (1 + sqrt(P->one_es))); - P->phi0 = pj_param(P->ctx, P->params, "rlat_0").f; - if (fabs(fabs(P->phi0) - HALFPI) < EPS10) { - P->mode = P->phi0 < 0. ? S_POLE : N_POLE; - P->sinph0 = P->phi0 < 0. ? -1. : 1.; - P->cosph0 = 0.; - } else if (fabs(P->phi0) < EPS10) { - P->mode = EQUIT; - P->sinph0 = 0.; - P->cosph0 = 1.; - } else { - P->mode = OBLIQ; - P->sinph0 = sin(P->phi0); - P->cosph0 = cos(P->phi0); - } - if (! P->es) { - P->inv = s_inverse; P->fwd = s_forward; - } else { - if (!(P->en = pj_enfn(P->es))) E_ERROR_0; - if (pj_param(P->ctx, P->params, "bguam").i) { - P->M1 = pj_mlfn(P->phi0, P->sinph0, P->cosph0, P->en); - P->inv = e_guam_inv; P->fwd = e_guam_fwd; - } else { - switch (P->mode) { - case N_POLE: - P->Mp = pj_mlfn(HALFPI, 1., 0., P->en); - break; - case S_POLE: - P->Mp = pj_mlfn(-HALFPI, -1., 0., P->en); - break; - case EQUIT: - case OBLIQ: - P->inv = e_inverse; P->fwd = e_forward; - P->N1 = 1. / sqrt(1. - P->es * P->sinph0 * P->sinph0); - P->G = P->sinph0 * (P->He = P->e / sqrt(P->one_es)); - P->He *= P->cosph0; - break; - } - P->inv = e_inverse; P->fwd = e_forward; - } - } -ENDENTRY(P) + + +#endif -- cgit v1.2.3 From d26b866b967965a1b4dc80cc8358f5ac03bb521c Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 3 May 2016 22:43:56 +0200 Subject: Converted eqc --- src/PJ_aea.c | 1 - src/PJ_eqc.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 104 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index cb1be3d5..9047ae25 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -353,7 +353,6 @@ source files ***********************************************************************/ -int pj_eqc_selftest (void) {return 10000;} int pj_eqdc_selftest (void) {return 10000;} int pj_etmerc_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} diff --git a/src/PJ_eqc.c b/src/PJ_eqc.c index c69a6baa..3fcb1007 100644 --- a/src/PJ_eqc.c +++ b/src/PJ_eqc.c @@ -1,23 +1,108 @@ -#define PROJ_PARMS__ \ - double rc; #define PJ_LIB__ -# include +#include + +struct pj_opaque { + double rc; +}; + PROJ_HEAD(eqc, "Equidistant Cylindrical (Plate Caree)") - "\n\tCyl, Sph\n\tlat_ts=[, lat_0=0]"; -FORWARD(s_forward); /* spheroid */ - xy.x = P->rc * lp.lam; - xy.y = lp.phi - P->phi0; - return (xy); + "\n\tCyl, Sph\n\tlat_ts=[, lat_0=0]"; + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + xy.x = Q->rc * lp.lam; + xy.y = lp.phi - P->phi0; + + return xy; } -INVERSE(s_inverse); /* spheroid */ - lp.lam = xy.x / P->rc; - lp.phi = xy.y + P->phi0; - return (lp); + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + lp.lam = xy.x / Q->rc; + lp.phi = xy.y + P->phi0; + + return lp; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(eqc) - if ((P->rc = cos(pj_param(P->ctx, P->params, "rlat_ts").f)) <= 0.) E_ERROR(-24); - P->inv = s_inverse; - P->fwd = s_forward; - P->es = 0.; -ENDENTRY(P) + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(eqc) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + if ((Q->rc = cos(pj_param(P->ctx, P->params, "rlat_ts").f)) <= 0.) E_ERROR(-24); + P->inv = s_inverse; + P->fwd = s_forward; + P->es = 0.; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_eqc_selftest (void) {return 0;} +#else + +int pj_eqc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=eqc +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223402.144255274179, 111701.07212763709}, + { 223402.144255274179, -111701.07212763709}, + {-223402.144255274179, 111701.07212763709}, + {-223402.144255274179, -111701.07212763709}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.00179049310978382265, 0.000895246554891911323}, + { 0.00179049310978382265, -0.000895246554891911323}, + {-0.00179049310978382265, 0.000895246554891911323}, + {-0.00179049310978382265, -0.000895246554891911323}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 65c94f1e789bf79a06dfa9f901aa231276d3e873 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 3 May 2016 23:00:03 +0200 Subject: Converted eqdc --- src/PJ_aea.c | 1 - src/PJ_eqdc.c | 263 ++++++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 184 insertions(+), 80 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 9047ae25..e87d1abc 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -353,7 +353,6 @@ source files ***********************************************************************/ -int pj_eqdc_selftest (void) {return 10000;} int pj_etmerc_selftest (void) {return 10000;} int pj_geocent_selftest (void) {return 10000;} diff --git a/src/PJ_eqdc.c b/src/PJ_eqdc.c index 01a0f03f..08981249 100644 --- a/src/PJ_eqdc.c +++ b/src/PJ_eqdc.c @@ -1,85 +1,190 @@ -#define PROJ_PARMS__ \ - double phi1; \ - double phi2; \ - double n; \ - double rho; \ - double rho0; \ - double c; \ - double *en; \ - int ellips; #define PJ_LIB__ -#include +#include + +struct pj_opaque { + double phi1; + double phi2; + double n; + double rho; + double rho0; + double c; + double *en; + int ellips; +}; + PROJ_HEAD(eqdc, "Equidistant Conic") - "\n\tConic, Sph&Ell\n\tlat_1= lat_2="; -# define EPS10 1.e-10 -FORWARD(e_forward); /* sphere & ellipsoid */ - P->rho = P->c - (P->ellips ? pj_mlfn(lp.phi, sin(lp.phi), - cos(lp.phi), P->en) : lp.phi); - xy.x = P->rho * sin( lp.lam *= P->n ); - xy.y = P->rho0 - P->rho * cos(lp.lam); - return (xy); + "\n\tConic, Sph&Ell\n\tlat_1= lat_2="; +# define EPS10 1.e-10 + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + Q->rho = Q->c - (Q->ellips ? pj_mlfn(lp.phi, sin(lp.phi), + cos(lp.phi), Q->en) : lp.phi); + xy.x = Q->rho * sin( lp.lam *= Q->n ); + xy.y = Q->rho0 - Q->rho * cos(lp.lam); + + return xy; } -INVERSE(e_inverse); /* sphere & ellipsoid */ - if ((P->rho = hypot(xy.x, xy.y = P->rho0 - xy.y)) != 0.0 ) { - if (P->n < 0.) { - P->rho = -P->rho; - xy.x = -xy.x; - xy.y = -xy.y; - } - lp.phi = P->c - P->rho; - if (P->ellips) - lp.phi = pj_inv_mlfn(P->ctx, lp.phi, P->es, P->en); - lp.lam = atan2(xy.x, xy.y) / P->n; - } else { - lp.lam = 0.; - lp.phi = P->n > 0. ? HALFPI : - HALFPI; - } - return (lp); + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + + if ((Q->rho = hypot(xy.x, xy.y = Q->rho0 - xy.y)) != 0.0 ) { + if (Q->n < 0.) { + Q->rho = -Q->rho; + xy.x = -xy.x; + xy.y = -xy.y; + } + lp.phi = Q->c - Q->rho; + if (Q->ellips) + lp.phi = pj_inv_mlfn(P->ctx, lp.phi, P->es, Q->en); + lp.lam = atan2(xy.x, xy.y) / Q->n; + } else { + lp.lam = 0.; + lp.phi = Q->n > 0. ? HALFPI : - HALFPI; + } + return lp; } + + SPECIAL(fac) { - double sinphi, cosphi; - - sinphi = sin(lp.phi); - cosphi = cos(lp.phi); - fac->code |= IS_ANAL_HK; - fac->h = 1.; - fac->k = P->n * (P->c - (P->ellips ? pj_mlfn(lp.phi, sinphi, - cosphi, P->en) : lp.phi)) / pj_msfn(sinphi, cosphi, P->es); + struct pj_opaque *Q = P->opaque; + double sinphi, cosphi; + + sinphi = sin(lp.phi); + cosphi = cos(lp.phi); + fac->code |= IS_ANAL_HK; + fac->h = 1.; + fac->k = Q->n * (Q->c - (Q->ellips ? pj_mlfn(lp.phi, sinphi, + cosphi, Q->en) : lp.phi)) / pj_msfn(sinphi, cosphi, P->es); +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + if (P->opaque->en) + pj_dealloc (P->opaque->en); + + pj_dealloc (P->opaque); + return pj_dealloc(P); } -FREEUP; if (P) { if (P->en) pj_dalloc(P->en); pj_dalloc(P); } } -ENTRY1(eqdc, en) - double cosphi, sinphi; - int secant; - - P->phi1 = pj_param(P->ctx, P->params, "rlat_1").f; - P->phi2 = pj_param(P->ctx, P->params, "rlat_2").f; - if (fabs(P->phi1 + P->phi2) < EPS10) E_ERROR(-21); - if (!(P->en = pj_enfn(P->es))) - E_ERROR_0; - P->n = sinphi = sin(P->phi1); - cosphi = cos(P->phi1); - secant = fabs(P->phi1 - P->phi2) >= EPS10; - if( (P->ellips = (P->es > 0.)) ) { - double ml1, m1; - - m1 = pj_msfn(sinphi, cosphi, P->es); - ml1 = pj_mlfn(P->phi1, sinphi, cosphi, P->en); - if (secant) { /* secant cone */ - sinphi = sin(P->phi2); - cosphi = cos(P->phi2); - P->n = (m1 - pj_msfn(sinphi, cosphi, P->es)) / - (pj_mlfn(P->phi2, sinphi, cosphi, P->en) - ml1); - } - P->c = ml1 + m1 / P->n; - P->rho0 = P->c - pj_mlfn(P->phi0, sin(P->phi0), - cos(P->phi0), P->en); - } else { - if (secant) - P->n = (cosphi - cos(P->phi2)) / (P->phi2 - P->phi1); - P->c = P->phi1 + cos(P->phi1) / P->n; - P->rho0 = P->c - P->phi0; - } - P->inv = e_inverse; - P->fwd = e_forward; - P->spc = fac; -ENDENTRY(P) + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(eqdc) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + double cosphi, sinphi; + int secant; + + Q->phi1 = pj_param(P->ctx, P->params, "rlat_1").f; + Q->phi2 = pj_param(P->ctx, P->params, "rlat_2").f; + if (fabs(Q->phi1 + Q->phi2) < EPS10) E_ERROR(-21); + if (!(Q->en = pj_enfn(P->es))) + E_ERROR_0; + Q->n = sinphi = sin(Q->phi1); + cosphi = cos(Q->phi1); + secant = fabs(Q->phi1 - Q->phi2) >= EPS10; + if( (Q->ellips = (P->es > 0.)) ) { + double ml1, m1; + + m1 = pj_msfn(sinphi, cosphi, P->es); + ml1 = pj_mlfn(Q->phi1, sinphi, cosphi, Q->en); + if (secant) { /* secant cone */ + sinphi = sin(Q->phi2); + cosphi = cos(Q->phi2); + Q->n = (m1 - pj_msfn(sinphi, cosphi, P->es)) / + (pj_mlfn(Q->phi2, sinphi, cosphi, Q->en) - ml1); + } + Q->c = ml1 + m1 / Q->n; + Q->rho0 = Q->c - pj_mlfn(P->phi0, sin(P->phi0), + cos(P->phi0), Q->en); + } else { + if (secant) + Q->n = (cosphi - cos(Q->phi2)) / (Q->phi2 - Q->phi1); + Q->c = Q->phi1 + cos(Q->phi1) / Q->n; + Q->rho0 = Q->c - P->phi0; + } + P->inv = e_inverse; + P->fwd = e_forward; + P->spc = fac; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_eqdc_selftest (void) {return 0;} +#else + +int pj_eqdc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=eqdc +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=eqdc +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222588.440269285755, 110659.134907347048}, + { 222756.836702042434, -110489.578087220681}, + {-222588.440269285755, 110659.134907347048}, + {-222756.836702042434, -110489.578087220681}, + }; + + XY s_fwd_expect[] = { + { 223351.088175113517, 111786.108747173785}, + { 223521.200266735133, -111615.970741240744}, + {-223351.088175113517, 111786.108747173785}, + {-223521.200266735133, -111615.970741240744}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.00179635944879094839, 0.000904368858588402644}, + { 0.00179635822020772734, -0.000904370095529954975}, + {-0.00179635944879094839, 0.000904368858588402644}, + {-0.00179635822020772734, -0.000904370095529954975}, + }; + + LP s_inv_expect[] = { + { 0.0017902210900486641, 0.000895245944814909169}, + { 0.00179021986984890255, -0.000895247165333684842}, + {-0.0017902210900486641, 0.000895245944814909169}, + {-0.00179021986984890255, -0.000895247165333684842}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 430534766d41a5a51c448c3d2c60e9467305d60f Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 4 May 2016 09:49:09 +0200 Subject: Converted vandg --- src/PJ_aea.c | 1 - src/PJ_vandg.c | 226 ++++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 152 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index e87d1abc..a65c148f 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -367,7 +367,6 @@ int pj_rouss_selftest (void) {return 10000;} int pj_sch_selftest (void) {return 10000;} int pj_utm_selftest (void) {return 10000;} -int pj_vandg_selftest (void) {return 10000;} int pj_vandg2_selftest (void) {return 10000;} int pj_vandg3_selftest (void) {return 10000;} int pj_vandg4_selftest (void) {return 10000;} diff --git a/src/PJ_vandg.c b/src/PJ_vandg.c index 784674b7..5ce058fd 100644 --- a/src/PJ_vandg.c +++ b/src/PJ_vandg.c @@ -1,78 +1,156 @@ #define PJ_LIB__ -# include +#include + PROJ_HEAD(vandg, "van der Grinten (I)") "\n\tMisc Sph"; -# define TOL 1.e-10 -# define THIRD .33333333333333333333 -# define TWO_THRD .66666666666666666666 -# define C2_27 .07407407407407407407 -# define PI4_3 4.18879020478639098458 -# define PISQ 9.86960440108935861869 -# define TPISQ 19.73920880217871723738 -# define HPISQ 4.93480220054467930934 -FORWARD(s_forward); /* spheroid */ - double al, al2, g, g2, p2; - - p2 = fabs(lp.phi / HALFPI); - if ((p2 - TOL) > 1.) F_ERROR; - if (p2 > 1.) - p2 = 1.; - if (fabs(lp.phi) <= TOL) { - xy.x = lp.lam; - xy.y = 0.; - } else if (fabs(lp.lam) <= TOL || fabs(p2 - 1.) < TOL) { - xy.x = 0.; - xy.y = PI * tan(.5 * asin(p2)); - if (lp.phi < 0.) xy.y = -xy.y; - } else { - al = .5 * fabs(PI / lp.lam - lp.lam / PI); - al2 = al * al; - g = sqrt(1. - p2 * p2); - g = g / (p2 + g - 1.); - g2 = g * g; - p2 = g * (2. / p2 - 1.); - p2 = p2 * p2; - xy.x = g - p2; g = p2 + al2; - xy.x = PI * (al * xy.x + sqrt(al2 * xy.x * xy.x - g * (g2 - p2))) / g; - if (lp.lam < 0.) xy.x = -xy.x; - xy.y = fabs(xy.x / PI); - xy.y = 1. - xy.y * (xy.y + 2. * al); - if (xy.y < -TOL) F_ERROR; - if (xy.y < 0.) xy.y = 0.; - else xy.y = sqrt(xy.y) * (lp.phi < 0. ? -PI : PI); - } - return (xy); + +# define TOL 1.e-10 +# define THIRD .33333333333333333333 +# define TWO_THRD .66666666666666666666 +# define C2_27 .07407407407407407407 +# define PI4_3 4.18879020478639098458 +# define PISQ 9.86960440108935861869 +# define TPISQ 19.73920880217871723738 +# define HPISQ 4.93480220054467930934 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + double al, al2, g, g2, p2; + + p2 = fabs(lp.phi / HALFPI); + if ((p2 - TOL) > 1.) F_ERROR; + if (p2 > 1.) + p2 = 1.; + if (fabs(lp.phi) <= TOL) { + xy.x = lp.lam; + xy.y = 0.; + } else if (fabs(lp.lam) <= TOL || fabs(p2 - 1.) < TOL) { + xy.x = 0.; + xy.y = PI * tan(.5 * asin(p2)); + if (lp.phi < 0.) xy.y = -xy.y; + } else { + al = .5 * fabs(PI / lp.lam - lp.lam / PI); + al2 = al * al; + g = sqrt(1. - p2 * p2); + g = g / (p2 + g - 1.); + g2 = g * g; + p2 = g * (2. / p2 - 1.); + p2 = p2 * p2; + xy.x = g - p2; g = p2 + al2; + xy.x = PI * (al * xy.x + sqrt(al2 * xy.x * xy.x - g * (g2 - p2))) / g; + if (lp.lam < 0.) xy.x = -xy.x; + xy.y = fabs(xy.x / PI); + xy.y = 1. - xy.y * (xy.y + 2. * al); + if (xy.y < -TOL) F_ERROR; + if (xy.y < 0.) + xy.y = 0.; + else + xy.y = sqrt(xy.y) * (lp.phi < 0. ? -PI : PI); + } + + return xy; } -INVERSE(s_inverse); /* spheroid */ - double t, c0, c1, c2, c3, al, r2, r, m, d, ay, x2, y2; - - x2 = xy.x * xy.x; - if ((ay = fabs(xy.y)) < TOL) { - lp.phi = 0.; - t = x2 * x2 + TPISQ * (x2 + HPISQ); - lp.lam = fabs(xy.x) <= TOL ? 0. : - .5 * (x2 - PISQ + sqrt(t)) / xy.x; - return (lp); - } - y2 = xy.y * xy.y; - r = x2 + y2; r2 = r * r; - c1 = - PI * ay * (r + PISQ); - c3 = r2 + TWOPI * (ay * r + PI * (y2 + PI * (ay + HALFPI))); - c2 = c1 + PISQ * (r - 3. * y2); - c0 = PI * ay; - c2 /= c3; - al = c1 / c3 - THIRD * c2 * c2; - m = 2. * sqrt(-THIRD * al); - d = C2_27 * c2 * c2 * c2 + (c0 * c0 - THIRD * c2 * c1) / c3; - if (((t = fabs(d = 3. * d / (al * m))) - TOL) <= 1.) { - d = t > 1. ? (d > 0. ? 0. : PI) : acos(d); - lp.phi = PI * (m * cos(d * THIRD + PI4_3) - THIRD * c2); - if (xy.y < 0.) lp.phi = -lp.phi; - t = r2 + TPISQ * (x2 - y2 + HPISQ); - lp.lam = fabs(xy.x) <= TOL ? 0. : - .5 * (r - PISQ + (t <= 0. ? 0. : sqrt(t))) / xy.x; - } else - I_ERROR; - return (lp); + + +static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ + LP lp = {0.0,0.0}; + double t, c0, c1, c2, c3, al, r2, r, m, d, ay, x2, y2; + + x2 = xy.x * xy.x; + if ((ay = fabs(xy.y)) < TOL) { + lp.phi = 0.; + t = x2 * x2 + TPISQ * (x2 + HPISQ); + lp.lam = fabs(xy.x) <= TOL ? 0. : + .5 * (x2 - PISQ + sqrt(t)) / xy.x; + return (lp); + } + y2 = xy.y * xy.y; + r = x2 + y2; r2 = r * r; + c1 = - PI * ay * (r + PISQ); + c3 = r2 + TWOPI * (ay * r + PI * (y2 + PI * (ay + HALFPI))); + c2 = c1 + PISQ * (r - 3. * y2); + c0 = PI * ay; + c2 /= c3; + al = c1 / c3 - THIRD * c2 * c2; + m = 2. * sqrt(-THIRD * al); + d = C2_27 * c2 * c2 * c2 + (c0 * c0 - THIRD * c2 * c1) / c3; + if (((t = fabs(d = 3. * d / (al * m))) - TOL) <= 1.) { + d = t > 1. ? (d > 0. ? 0. : PI) : acos(d); + lp.phi = PI * (m * cos(d * THIRD + PI4_3) - THIRD * c2); + if (xy.y < 0.) lp.phi = -lp.phi; + t = r2 + TPISQ * (x2 - y2 + HPISQ); + lp.lam = fabs(xy.x) <= TOL ? 0. : + .5 * (r - PISQ + (t <= 0. ? 0. : sqrt(t))) / xy.x; + } else + I_ERROR; + + return lp; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(vandg) P->es = 0.; P->inv = s_inverse; P->fwd = s_forward; ENDENTRY(P) + + +PJ *PROJECTION(vandg) { + P->es = 0.; + P->inv = s_inverse; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_vandg_selftest (void) {return 0;} +#else + +int pj_vandg_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=vandg +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223395.24954340671, 111704.59663367498}, + { 223395.24954340671, -111704.59663367498}, + {-223395.24954340671, 111704.59663367498}, + {-223395.24954340671, -111704.59663367498}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 0.001790493715929761, 0.00089524655486993867}, + { 0.001790493715929761, -0.00089524655486993867}, + {-0.001790493715929761, 0.00089524655486993867}, + {-0.001790493715929761, -0.00089524655486993867}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + + +#endif -- cgit v1.2.3 From 80cfc0386a19ceda105beb86f25bed26450c08e5 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 4 May 2016 10:21:00 +0200 Subject: Converted vandg2 and vandg3 --- src/PJ_aea.c | 2 - src/PJ_vandg2.c | 186 +++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 145 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index a65c148f..69b5bfe3 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -367,7 +367,5 @@ int pj_rouss_selftest (void) {return 10000;} int pj_sch_selftest (void) {return 10000;} int pj_utm_selftest (void) {return 10000;} -int pj_vandg2_selftest (void) {return 10000;} -int pj_vandg3_selftest (void) {return 10000;} int pj_vandg4_selftest (void) {return 10000;} #endif diff --git a/src/PJ_vandg2.c b/src/PJ_vandg2.c index 7bfa8f4e..f8850cad 100644 --- a/src/PJ_vandg2.c +++ b/src/PJ_vandg2.c @@ -1,45 +1,149 @@ -# define TOL 1e-10 -# define TWORPI 0.63661977236758134308 -#define PROJ_PARMS__ \ - int vdg3; #define PJ_LIB__ -#include +#include + +struct pj_opaque { + int vdg3; +}; + PROJ_HEAD(vandg2, "van der Grinten II") "\n\tMisc Sph, no inv."; PROJ_HEAD(vandg3, "van der Grinten III") "\n\tMisc Sph, no inv."; -FORWARD(s_forward); /* spheroid */ - double x1, at, bt, ct; - - bt = fabs(TWORPI * lp.phi); - if ((ct = 1. - bt * bt) < 0.) - ct = 0.; - else - ct = sqrt(ct); - if (fabs(lp.lam) < TOL) { - xy.x = 0.; - xy.y = PI * (lp.phi < 0. ? -bt : bt) / (1. + ct); - } else { - at = 0.5 * fabs(PI / lp.lam - lp.lam / PI); - if (P->vdg3) { - x1 = bt / (1. + ct); - xy.x = PI * (sqrt(at * at + 1. - x1 * x1) - at); - xy.y = PI * x1; - } else { - x1 = (ct * sqrt(1. + at * at) - at * ct * ct) / - (1. + at * at * bt * bt); - xy.x = PI * x1; - xy.y = PI * sqrt(1. - x1 * (x1 + 2. * at) + TOL); - } - if ( lp.lam < 0.) xy.x = -xy.x; - if ( lp.phi < 0.) xy.y = -xy.y; - } - return (xy); + +#define TOL 1e-10 +#define TWORPI 0.63661977236758134308 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double x1, at, bt, ct; + + bt = fabs(TWORPI * lp.phi); + if ((ct = 1. - bt * bt) < 0.) + ct = 0.; + else + ct = sqrt(ct); + if (fabs(lp.lam) < TOL) { + xy.x = 0.; + xy.y = PI * (lp.phi < 0. ? -bt : bt) / (1. + ct); + } else { + at = 0.5 * fabs(PI / lp.lam - lp.lam / PI); + if (Q->vdg3) { + x1 = bt / (1. + ct); + xy.x = PI * (sqrt(at * at + 1. - x1 * x1) - at); + xy.y = PI * x1; + } else { + x1 = (ct * sqrt(1. + at * at) - at * ct * ct) / + (1. + at * at * bt * bt); + xy.x = PI * x1; + xy.y = PI * sqrt(1. - x1 * (x1 + 2. * at) + TOL); + } + if ( lp.lam < 0.) xy.x = -xy.x; + if ( lp.phi < 0.) xy.y = -xy.y; + } + + return xy; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(vandg2) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->vdg3 = 0; + P->fwd = s_forward; + + return P; +} + +PJ *PROJECTION(vandg3) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->vdg3 = 1; + P->es = 0.; + P->fwd = s_forward; + + return P; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(vandg2) - P->vdg3 = 0; - P->inv = 0; P->fwd = s_forward; -ENDENTRY(P) -ENTRY0(vandg3) - P->vdg3 = 1; - P->es = 0.; P->fwd = s_forward; -ENDENTRY(P) + + +#ifdef PJ_OMIT_SELFTEST +int pj_vandg2_selftest (void) {return 0;} +#else + +int pj_vandg2_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=vandg2 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223395.24785043663, 111718.49103722633}, + { 223395.24785043663, -111718.49103722633}, + {-223395.24785043663, 111718.49103722633}, + {-223395.24785043663, -111718.49103722633}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} + + +#endif + +#ifdef PJ_OMIT_SELFTEST +int pj_vandg3_selftest (void) {return 0;} +#else + +int pj_vandg3_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=vandg3 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223395.24955283134, 111704.51990442065}, + { 223395.24955283134, -111704.51990442065}, + {-223395.24955283134, 111704.51990442065}, + {-223395.24955283134, -111704.51990442065}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} + + +#endif -- cgit v1.2.3 From 6674a8e93742767146d3e53dc6bee6b9d31fb6df Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 4 May 2016 10:29:25 +0200 Subject: Converted vandg4 --- src/PJ_aea.c | 1 - src/PJ_vandg4.c | 140 +++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 98 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 69b5bfe3..587392b3 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -367,5 +367,4 @@ int pj_rouss_selftest (void) {return 10000;} int pj_sch_selftest (void) {return 10000;} int pj_utm_selftest (void) {return 10000;} -int pj_vandg4_selftest (void) {return 10000;} #endif diff --git a/src/PJ_vandg4.c b/src/PJ_vandg4.c index 0229042b..7a7ffefb 100644 --- a/src/PJ_vandg4.c +++ b/src/PJ_vandg4.c @@ -1,42 +1,98 @@ -#define PJ_LIB__ -#include -PROJ_HEAD(vandg4, "van der Grinten IV") "\n\tMisc Sph, no inv."; -#define TOL 1e-10 -#define TWORPI 0.63661977236758134308 -FORWARD(s_forward); /* spheroid */ - double x1, t, bt, ct, ft, bt2, ct2, dt, dt2; - (void) P; - - if (fabs(lp.phi) < TOL) { - xy.x = lp.lam; - xy.y = 0.; - } else if (fabs(lp.lam) < TOL || fabs(fabs(lp.phi) - HALFPI) < TOL) { - xy.x = 0.; - xy.y = lp.phi; - } else { - bt = fabs(TWORPI * lp.phi); - bt2 = bt * bt; - ct = 0.5 * (bt * (8. - bt * (2. + bt2)) - 5.) - / (bt2 * (bt - 1.)); - ct2 = ct * ct; - dt = TWORPI * lp.lam; - dt = dt + 1. / dt; - dt = sqrt(dt * dt - 4.); - if ((fabs(lp.lam) - HALFPI) < 0.) dt = -dt; - dt2 = dt * dt; - x1 = bt + ct; x1 *= x1; - t = bt + 3.*ct; - ft = x1 * (bt2 + ct2 * dt2 - 1.) + (1.-bt2) * ( - bt2 * (t * t + 4. * ct2) + - ct2 * (12. * bt * ct + 4. * ct2) ); - x1 = (dt*(x1 + ct2 - 1.) + 2.*sqrt(ft)) / - (4.* x1 + dt2); - xy.x = HALFPI * x1; - xy.y = HALFPI * sqrt(1. + dt * fabs(x1) - x1 * x1); - if (lp.lam < 0.) xy.x = -xy.x; - if (lp.phi < 0.) xy.y = -xy.y; - } - return (xy); -} -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(vandg4) P->es = 0.; P->fwd = s_forward; ENDENTRY(P) +#define PJ_LIB__ +#include + +PROJ_HEAD(vandg4, "van der Grinten IV") "\n\tMisc Sph, no inv."; + +#define TOL 1e-10 +#define TWORPI 0.63661977236758134308 + + +static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ + XY xy = {0.0,0.0}; + double x1, t, bt, ct, ft, bt2, ct2, dt, dt2; + (void) P; + + if (fabs(lp.phi) < TOL) { + xy.x = lp.lam; + xy.y = 0.; + } else if (fabs(lp.lam) < TOL || fabs(fabs(lp.phi) - HALFPI) < TOL) { + xy.x = 0.; + xy.y = lp.phi; + } else { + bt = fabs(TWORPI * lp.phi); + bt2 = bt * bt; + ct = 0.5 * (bt * (8. - bt * (2. + bt2)) - 5.) + / (bt2 * (bt - 1.)); + ct2 = ct * ct; + dt = TWORPI * lp.lam; + dt = dt + 1. / dt; + dt = sqrt(dt * dt - 4.); + if ((fabs(lp.lam) - HALFPI) < 0.) dt = -dt; + dt2 = dt * dt; + x1 = bt + ct; x1 *= x1; + t = bt + 3.*ct; + ft = x1 * (bt2 + ct2 * dt2 - 1.) + (1.-bt2) * ( + bt2 * (t * t + 4. * ct2) + + ct2 * (12. * bt * ct + 4. * ct2) ); + x1 = (dt*(x1 + ct2 - 1.) + 2.*sqrt(ft)) / + (4.* x1 + dt2); + xy.x = HALFPI * x1; + xy.y = HALFPI * sqrt(1. + dt * fabs(x1) - x1 * x1); + if (lp.lam < 0.) xy.x = -xy.x; + if (lp.phi < 0.) xy.y = -xy.y; + } + return xy; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + + return pj_dealloc(P); +} + + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + + +PJ *PROJECTION(vandg4) { + P->es = 0.; + P->fwd = s_forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_vandg4_selftest (void) {return 0;} +#else + +int pj_vandg4_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=vandg4 +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + { 223374.57729435508, 111701.19548415358 }, + { 223374.57729435508, -111701.19548415358 }, + {-223374.57729435508, 111701.19548415358 }, + {-223374.57729435508, -111701.19548415358 }, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); +} + + +#endif -- cgit v1.2.3 From 45f4c1a269538b70ab749aa6833d1b92a08495d2 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 4 May 2016 10:44:42 +0200 Subject: Converted rouss. proj_rouss.c should probably be renamed to PJ_rouss.c at some point. --- src/PJ_aea.c | 1 - src/proj_rouss.c | 258 ++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 168 insertions(+), 91 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 587392b3..afcc2e39 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -363,7 +363,6 @@ int pj_longlat_selftest (void) {return 10000;} int pj_ob_tran_selftest (void) {return 10000;} -int pj_rouss_selftest (void) {return 10000;} int pj_sch_selftest (void) {return 10000;} int pj_utm_selftest (void) {return 10000;} diff --git a/src/proj_rouss.c b/src/proj_rouss.c index f1c2f5a1..35cc73c7 100644 --- a/src/proj_rouss.c +++ b/src/proj_rouss.c @@ -23,98 +23,176 @@ ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#define PROJ_PARMS__ \ - double s0; \ - double A1, A2, A3, A4, A5, A6; \ - double B1, B2, B3, B4, B5, B6, B7, B8; \ - double C1, C2, C3, C4, C5, C6, C7, C8; \ - double D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11; \ - void *en; #define PJ_LIB__ -# include +#include + +struct pj_opaque { + double s0; + double A1, A2, A3, A4, A5, A6; + double B1, B2, B3, B4, B5, B6, B7, B8; + double C1, C2, C3, C4, C5, C6, C7, C8; + double D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11; + void *en; +}; PROJ_HEAD(rouss, "Roussilhe Stereographic") "\n\tAzi., Ellps."; -FORWARD(e_forward); /* ellipsoid */ - double s, al, cp, sp, al2, s2; - - cp = cos(lp.phi); - sp = sin(lp.phi); - s = proj_mdist(lp.phi, sp, cp, P->en) - P->s0; - s2 = s * s; - al = lp.lam * cp / sqrt(1. - P->es * sp * sp); - al2 = al * al; - xy.x = P->k0 * al*(1.+s2*(P->A1+s2*P->A4)-al2*(P->A2+s*P->A3+s2*P->A5 - +al2*P->A6)); - xy.y = P->k0 * (al2*(P->B1+al2*P->B4)+ - s*(1.+al2*(P->B3-al2*P->B6)+s2*(P->B2+s2*P->B8)+ - s*al2*(P->B5+s*P->B7))); - return (xy); + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double s, al, cp, sp, al2, s2; + + cp = cos(lp.phi); + sp = sin(lp.phi); + s = proj_mdist(lp.phi, sp, cp, Q->en) - Q->s0; + s2 = s * s; + al = lp.lam * cp / sqrt(1. - P->es * sp * sp); + al2 = al * al; + xy.x = P->k0 * al*(1.+s2*(Q->A1+s2*Q->A4)-al2*(Q->A2+s*Q->A3+s2*Q->A5 + +al2*Q->A6)); + xy.y = P->k0 * (al2*(Q->B1+al2*Q->B4)+ + s*(1.+al2*(Q->B3-al2*Q->B6)+s2*(Q->B2+s2*Q->B8)+ + s*al2*(Q->B5+s*Q->B7))); + + return xy; } -INVERSE(e_inverse); /* ellipsoid */ - double s, al, x = xy.x / P->k0, y = xy.y / P->k0, x2, y2;; - - x2 = x * x; - y2 = y * y; - al = x*(1.-P->C1*y2+x2*(P->C2+P->C3*y-P->C4*x2+P->C5*y2-P->C7*x2*y) - +y2*(P->C6*y2-P->C8*x2*y)); - s = P->s0 + y*(1.+y2*(-P->D2+P->D8*y2))+ - x2*(-P->D1+y*(-P->D3+y*(-P->D5+y*(-P->D7+y*P->D11)))+ - x2*(P->D4+y*(P->D6+y*P->D10)-x2*P->D9)); - lp.phi=proj_inv_mdist(P->ctx, s, P->en); - s = sin(lp.phi); - lp.lam=al * sqrt(1. - P->es * s * s)/cos(lp.phi); - return (lp); + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double s, al, x = xy.x / P->k0, y = xy.y / P->k0, x2, y2;; + + x2 = x * x; + y2 = y * y; + al = x*(1.-Q->C1*y2+x2*(Q->C2+Q->C3*y-Q->C4*x2+Q->C5*y2-Q->C7*x2*y) + +y2*(Q->C6*y2-Q->C8*x2*y)); + s = Q->s0 + y*(1.+y2*(-Q->D2+Q->D8*y2))+ + x2*(-Q->D1+y*(-Q->D3+y*(-Q->D5+y*(-Q->D7+y*Q->D11)))+ + x2*(Q->D4+y*(Q->D6+y*Q->D10)-x2*Q->D9)); + lp.phi=proj_inv_mdist(P->ctx, s, Q->en); + s = sin(lp.phi); + lp.lam=al * sqrt(1. - P->es * s * s)/cos(lp.phi); + + return lp; } -FREEUP; - if (P) { - if (P->en) - free(P->en); - free(P); - } + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + if (P->opaque->en) + pj_dealloc (P->opaque->en); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; } -ENTRY1(rouss, en) - double N0, es2, t, t2, R_R0_2, R_R0_4; - - if (!((P->en = proj_mdist_ini(P->es)))) - E_ERROR_0; - es2 = sin(P->phi0); - P->s0 = proj_mdist(P->phi0, es2, cos(P->phi0), P->en); - t = 1. - (es2 = P->es * es2 * es2); - N0 = 1./sqrt(t); - R_R0_2 = t * t / P->one_es; - R_R0_4 = R_R0_2 * R_R0_2; - t = tan(P->phi0); - t2 = t * t; - P->C1 = P->A1 = R_R0_2 / 4.; - P->C2 = P->A2 = R_R0_2 * (2 * t2 - 1. - 2. * es2) / 12.; - P->A3 = R_R0_2 * t * (1. + 4. * t2)/ ( 12. * N0); - P->A4 = R_R0_4 / 24.; - P->A5 = R_R0_4 * ( -1. + t2 * (11. + 12. * t2))/24.; - P->A6 = R_R0_4 * ( -2. + t2 * (11. - 2. * t2))/240.; - P->B1 = t / (2. * N0); - P->B2 = R_R0_2 / 12.; - P->B3 = R_R0_2 * (1. + 2. * t2 - 2. * es2)/4.; - P->B4 = R_R0_2 * t * (2. - t2)/(24. * N0); - P->B5 = R_R0_2 * t * (5. + 4.* t2)/(8. * N0); - P->B6 = R_R0_4 * (-2. + t2 * (-5. + 6. * t2))/48.; - P->B7 = R_R0_4 * (5. + t2 * (19. + 12. * t2))/24.; - P->B8 = R_R0_4 / 120.; - P->C3 = R_R0_2 * t * (1. + t2)/(3. * N0); - P->C4 = R_R0_4 * (-3. + t2 * (34. + 22. * t2))/240.; - P->C5 = R_R0_4 * (4. + t2 * (13. + 12. * t2))/24.; - P->C6 = R_R0_4 / 16.; - P->C7 = R_R0_4 * t * (11. + t2 * (33. + t2 * 16.))/(48. * N0); - P->C8 = R_R0_4 * t * (1. + t2 * 4.)/(36. * N0); - P->D1 = t / (2. * N0); - P->D2 = R_R0_2 / 12.; - P->D3 = R_R0_2 * (2 * t2 + 1. - 2. * es2) / 4.; - P->D4 = R_R0_2 * t * (1. + t2)/(8. * N0); - P->D5 = R_R0_2 * t * (1. + t2 * 2.)/(4. * N0); - P->D6 = R_R0_4 * (1. + t2 * (6. + t2 * 6.))/16.; - P->D7 = R_R0_4 * t2 * (3. + t2 * 4.)/8.; - P->D8 = R_R0_4 / 80.; - P->D9 = R_R0_4 * t * (-21. + t2 * (178. - t2 * 26.))/720.; - P->D10 = R_R0_4 * t * (29. + t2 * (86. + t2 * 48.))/(96. * N0); - P->D11 = R_R0_4 * t * (37. + t2 * 44.)/(96. * N0); - P->fwd = e_forward; - P->inv = e_inverse; - ENDENTRY(P) + + +PJ *PROJECTION(rouss) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + double N0, es2, t, t2, R_R0_2, R_R0_4; + + if (!((Q->en = proj_mdist_ini(P->es)))) + E_ERROR_0; + es2 = sin(P->phi0); + Q->s0 = proj_mdist(P->phi0, es2, cos(P->phi0), Q->en); + t = 1. - (es2 = P->es * es2 * es2); + N0 = 1./sqrt(t); + R_R0_2 = t * t / P->one_es; + R_R0_4 = R_R0_2 * R_R0_2; + t = tan(P->phi0); + t2 = t * t; + Q->C1 = Q->A1 = R_R0_2 / 4.; + Q->C2 = Q->A2 = R_R0_2 * (2 * t2 - 1. - 2. * es2) / 12.; + Q->A3 = R_R0_2 * t * (1. + 4. * t2)/ ( 12. * N0); + Q->A4 = R_R0_4 / 24.; + Q->A5 = R_R0_4 * ( -1. + t2 * (11. + 12. * t2))/24.; + Q->A6 = R_R0_4 * ( -2. + t2 * (11. - 2. * t2))/240.; + Q->B1 = t / (2. * N0); + Q->B2 = R_R0_2 / 12.; + Q->B3 = R_R0_2 * (1. + 2. * t2 - 2. * es2)/4.; + Q->B4 = R_R0_2 * t * (2. - t2)/(24. * N0); + Q->B5 = R_R0_2 * t * (5. + 4.* t2)/(8. * N0); + Q->B6 = R_R0_4 * (-2. + t2 * (-5. + 6. * t2))/48.; + Q->B7 = R_R0_4 * (5. + t2 * (19. + 12. * t2))/24.; + Q->B8 = R_R0_4 / 120.; + Q->C3 = R_R0_2 * t * (1. + t2)/(3. * N0); + Q->C4 = R_R0_4 * (-3. + t2 * (34. + 22. * t2))/240.; + Q->C5 = R_R0_4 * (4. + t2 * (13. + 12. * t2))/24.; + Q->C6 = R_R0_4 / 16.; + Q->C7 = R_R0_4 * t * (11. + t2 * (33. + t2 * 16.))/(48. * N0); + Q->C8 = R_R0_4 * t * (1. + t2 * 4.)/(36. * N0); + Q->D1 = t / (2. * N0); + Q->D2 = R_R0_2 / 12.; + Q->D3 = R_R0_2 * (2 * t2 + 1. - 2. * es2) / 4.; + Q->D4 = R_R0_2 * t * (1. + t2)/(8. * N0); + Q->D5 = R_R0_2 * t * (1. + t2 * 2.)/(4. * N0); + Q->D6 = R_R0_4 * (1. + t2 * (6. + t2 * 6.))/16.; + Q->D7 = R_R0_4 * t2 * (3. + t2 * 4.)/8.; + Q->D8 = R_R0_4 / 80.; + Q->D9 = R_R0_4 * t * (-21. + t2 * (178. - t2 * 26.))/720.; + Q->D10 = R_R0_4 * t * (29. + t2 * (86. + t2 * 48.))/(96. * N0); + Q->D11 = R_R0_4 * t * (37. + t2 * 44.)/(96. * N0); + + P->fwd = e_forward; + P->inv = e_inverse; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_rouss_selftest (void) {return 0;} +#else + +int pj_rouss_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=rouss +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222644.89413161727, 110611.09186837047}, + { 222644.89413161727, -110611.09186837047}, + {-222644.89413161727, 110611.09186837047}, + {-222644.89413161727, -110611.09186837047}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.0017966305682019911, 0.00090436947683699559}, + { 0.0017966305682019911, -0.00090436947683699559}, + {-0.0017966305682019911, 0.00090436947683699559}, + {-0.0017966305682019911, -0.00090436947683699559}, + }; + + return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); +} + + +#endif -- cgit v1.2.3 From 5b0a48a3c50e1ddada2f5f609cd71349f29a0f95 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 4 May 2016 13:29:03 +0200 Subject: Converted ob_tran --- src/PJ_aea.c | 2 - src/PJ_ob_tran.c | 334 ++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 207 insertions(+), 129 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index afcc2e39..a84a781a 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -361,8 +361,6 @@ int pj_latlong_selftest (void) {return 10000;} int pj_lonlat_selftest (void) {return 10000;} int pj_longlat_selftest (void) {return 10000;} -int pj_ob_tran_selftest (void) {return 10000;} - int pj_sch_selftest (void) {return 10000;} int pj_utm_selftest (void) {return 10000;} diff --git a/src/PJ_ob_tran.c b/src/PJ_ob_tran.c index 4ddba9a4..76222fe9 100644 --- a/src/PJ_ob_tran.c +++ b/src/PJ_ob_tran.c @@ -1,145 +1,225 @@ -#define PROJ_PARMS__ \ - struct PJconsts *link; \ - double lamp; \ - double cphip, sphip; #define PJ_LIB__ #include #include + +struct pj_opaque { + struct PJconsts *link; + double lamp; + double cphip, sphip; +}; + PROJ_HEAD(ob_tran, "General Oblique Transformation") "\n\tMisc Sph" "\n\to_proj= plus parameters for projection" "\n\to_lat_p= o_lon_p= (new pole) or" "\n\to_alpha= o_lon_c= o_lat_c= or" "\n\to_lon_1= o_lat_1= o_lon_2= o_lat_2="; + #define TOL 1e-10 -FORWARD(o_forward); /* spheroid */ - double coslam, sinphi, cosphi; - - (void) xy; - - coslam = cos(lp.lam); - sinphi = sin(lp.phi); - cosphi = cos(lp.phi); - lp.lam = adjlon(aatan2(cosphi * sin(lp.lam), P->sphip * cosphi * coslam + - P->cphip * sinphi) + P->lamp); - lp.phi = aasin(P->ctx,P->sphip * sinphi - P->cphip * cosphi * coslam); - return (P->link->fwd(lp, P->link)); + + +static XY o_forward(LP lp, PJ *P) { /* spheroid */ + struct pj_opaque *Q = P->opaque; + double coslam, sinphi, cosphi; + + coslam = cos(lp.lam); + sinphi = sin(lp.phi); + cosphi = cos(lp.phi); + lp.lam = adjlon(aatan2(cosphi * sin(lp.lam), Q->sphip * cosphi * coslam + + Q->cphip * sinphi) + Q->lamp); + lp.phi = aasin(P->ctx,Q->sphip * sinphi - Q->cphip * cosphi * coslam); + + return Q->link->fwd(lp, Q->link); +} + + +static XY t_forward(LP lp, PJ *P) { /* spheroid */ + struct pj_opaque *Q = P->opaque; + double cosphi, coslam; + + cosphi = cos(lp.phi); + coslam = cos(lp.lam); + lp.lam = adjlon(aatan2(cosphi * sin(lp.lam), sin(lp.phi)) + Q->lamp); + lp.phi = aasin(P->ctx, - cosphi * coslam); + + return Q->link->fwd(lp, Q->link); } -FORWARD(t_forward); /* spheroid */ - double cosphi, coslam; - (void) xy; - cosphi = cos(lp.phi); - coslam = cos(lp.lam); - lp.lam = adjlon(aatan2(cosphi * sin(lp.lam), sin(lp.phi)) + P->lamp); - lp.phi = aasin(P->ctx, - cosphi * coslam); - return (P->link->fwd(lp, P->link)); +static LP o_inverse(XY xy, PJ *P) { /* spheroid */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double coslam, sinphi, cosphi; + + lp = Q->link->inv(xy, Q->link); + if (lp.lam != HUGE_VAL) { + coslam = cos(lp.lam -= Q->lamp); + sinphi = sin(lp.phi); + cosphi = cos(lp.phi); + lp.phi = aasin(P->ctx,Q->sphip * sinphi + Q->cphip * cosphi * coslam); + lp.lam = aatan2(cosphi * sin(lp.lam), Q->sphip * cosphi * coslam - + Q->cphip * sinphi); + } + return lp; } -INVERSE(o_inverse); /* spheroid */ - double coslam, sinphi, cosphi; - - lp = P->link->inv(xy, P->link); - if (lp.lam != HUGE_VAL) { - coslam = cos(lp.lam -= P->lamp); - sinphi = sin(lp.phi); - cosphi = cos(lp.phi); - lp.phi = aasin(P->ctx,P->sphip * sinphi + P->cphip * cosphi * coslam); - lp.lam = aatan2(cosphi * sin(lp.lam), P->sphip * cosphi * coslam - - P->cphip * sinphi); - } - return (lp); + + +static LP t_inverse(XY xy, PJ *P) { /* spheroid */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double cosphi, t; + + lp = Q->link->inv(xy, Q->link); + if (lp.lam != HUGE_VAL) { + cosphi = cos(lp.phi); + t = lp.lam - Q->lamp; + lp.lam = aatan2(cosphi * sin(t), - sin(lp.phi)); + lp.phi = aasin(P->ctx,cosphi * cos(t)); + } + return lp; } -INVERSE(t_inverse); /* spheroid */ - double cosphi, t; - - lp = P->link->inv(xy, P->link); - if (lp.lam != HUGE_VAL) { - cosphi = cos(lp.phi); - t = lp.lam - P->lamp; - lp.lam = aatan2(cosphi * sin(t), - sin(lp.phi)); - lp.phi = aasin(P->ctx,cosphi * cos(t)); - } - return (lp); + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + + if (P->opaque->link) + return pj_dealloc (P->opaque->link); + + pj_dealloc (P->opaque); + return pj_dealloc(P); } -FREEUP; - if (P) { - if (P->link) - (*(P->link->pfree))(P->link); - pj_dalloc(P); - } + + +static void freeup (PJ *P) { + freeup_new (P); + return; } -ENTRY1(ob_tran, link) - int i; - double phip; - char *name, *s; - - /* get name of projection to be translated */ - if (!(name = pj_param(P->ctx, P->params, "so_proj").s)) E_ERROR(-26); - for (i = 0; (s = pj_list[i].id) && strcmp(name, s) ; ++i) ; - if (!s || !(P->link = (*pj_list[i].proj)(0))) E_ERROR(-37); - /* copy existing header into new */ - P->es = 0.; /* force to spherical */ - P->link->params = P->params; - P->link->ctx = P->ctx; - P->link->over = P->over; - P->link->geoc = P->geoc; - P->link->a = P->a; - P->link->es = P->es; - P->link->ra = P->ra; - P->link->lam0 = P->lam0; - P->link->phi0 = P->phi0; - P->link->x0 = P->x0; - P->link->y0 = P->y0; - P->link->k0 = P->k0; - /* force spherical earth */ - P->link->one_es = P->link->rone_es = 1.; - P->link->es = P->link->e = 0.; - if (!(P->link = pj_list[i].proj(P->link))) { - freeup(P); - return 0; - } - if (pj_param(P->ctx, P->params, "to_alpha").i) { - double lamc, phic, alpha; - - lamc = pj_param(P->ctx, P->params, "ro_lon_c").f; - phic = pj_param(P->ctx, P->params, "ro_lat_c").f; - alpha = pj_param(P->ctx, P->params, "ro_alpha").f; + + +PJ *PROJECTION(ob_tran) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + int i; + double phip; + char *name, *s; + + /* get name of projection to be translated */ + if (!(name = pj_param(P->ctx, P->params, "so_proj").s)) E_ERROR(-26); + for (i = 0; (s = pj_list[i].id) && strcmp(name, s) ; ++i) ; + if (!s || !(Q->link = (*pj_list[i].proj)(0))) E_ERROR(-37); + /* copy existing header into new */ + P->es = 0.; /* force to spherical */ + Q->link->params = P->params; + Q->link->ctx = P->ctx; + Q->link->over = P->over; + Q->link->geoc = P->geoc; + Q->link->a = P->a; + Q->link->es = P->es; + Q->link->ra = P->ra; + Q->link->lam0 = P->lam0; + Q->link->phi0 = P->phi0; + Q->link->x0 = P->x0; + Q->link->y0 = P->y0; + Q->link->k0 = P->k0; + /* force spherical earth */ + Q->link->one_es = Q->link->rone_es = 1.; + Q->link->es = Q->link->e = 0.; + if (!(Q->link = pj_list[i].proj(Q->link))) { + return freeup_new(P); + } + if (pj_param(P->ctx, P->params, "to_alpha").i) { + double lamc, phic, alpha; + + lamc = pj_param(P->ctx, P->params, "ro_lon_c").f; + phic = pj_param(P->ctx, P->params, "ro_lat_c").f; + alpha = pj_param(P->ctx, P->params, "ro_alpha").f; /* - if (fabs(phic) <= TOL || - fabs(fabs(phic) - HALFPI) <= TOL || - fabs(fabs(alpha) - HALFPI) <= TOL) + if (fabs(phic) <= TOL || + fabs(fabs(phic) - HALFPI) <= TOL || + fabs(fabs(alpha) - HALFPI) <= TOL) */ - if (fabs(fabs(phic) - HALFPI) <= TOL) - E_ERROR(-32); - P->lamp = lamc + aatan2(-cos(alpha), -sin(alpha) * sin(phic)); - phip = aasin(P->ctx,cos(phic) * sin(alpha)); - } else if (pj_param(P->ctx, P->params, "to_lat_p").i) { /* specified new pole */ - P->lamp = pj_param(P->ctx, P->params, "ro_lon_p").f; - phip = pj_param(P->ctx, P->params, "ro_lat_p").f; - } else { /* specified new "equator" points */ - double lam1, lam2, phi1, phi2, con; - - lam1 = pj_param(P->ctx, P->params, "ro_lon_1").f; - phi1 = pj_param(P->ctx, P->params, "ro_lat_1").f; - lam2 = pj_param(P->ctx, P->params, "ro_lon_2").f; - phi2 = pj_param(P->ctx, P->params, "ro_lat_2").f; - if (fabs(phi1 - phi2) <= TOL || - (con = fabs(phi1)) <= TOL || - fabs(con - HALFPI) <= TOL || - fabs(fabs(phi2) - HALFPI) <= TOL) E_ERROR(-33); - P->lamp = atan2(cos(phi1) * sin(phi2) * cos(lam1) - - sin(phi1) * cos(phi2) * cos(lam2), - sin(phi1) * cos(phi2) * sin(lam2) - - cos(phi1) * sin(phi2) * sin(lam1)); - phip = atan(-cos(P->lamp - lam1) / tan(phi1)); - } - if (fabs(phip) > TOL) { /* oblique */ - P->cphip = cos(phip); - P->sphip = sin(phip); - P->fwd = o_forward; - P->inv = P->link->inv ? o_inverse : 0; - } else { /* transverse */ - P->fwd = t_forward; - P->inv = P->link->inv ? t_inverse : 0; - } -ENDENTRY(P) + if (fabs(fabs(phic) - HALFPI) <= TOL) + E_ERROR(-32); + Q->lamp = lamc + aatan2(-cos(alpha), -sin(alpha) * sin(phic)); + phip = aasin(P->ctx,cos(phic) * sin(alpha)); + } else if (pj_param(P->ctx, P->params, "to_lat_p").i) { /* specified new pole */ + Q->lamp = pj_param(P->ctx, P->params, "ro_lon_p").f; + phip = pj_param(P->ctx, P->params, "ro_lat_p").f; + } else { /* specified new "equator" points */ + double lam1, lam2, phi1, phi2, con; + + lam1 = pj_param(P->ctx, P->params, "ro_lon_1").f; + phi1 = pj_param(P->ctx, P->params, "ro_lat_1").f; + lam2 = pj_param(P->ctx, P->params, "ro_lon_2").f; + phi2 = pj_param(P->ctx, P->params, "ro_lat_2").f; + if (fabs(phi1 - phi2) <= TOL || + (con = fabs(phi1)) <= TOL || + fabs(con - HALFPI) <= TOL || + fabs(fabs(phi2) - HALFPI) <= TOL) E_ERROR(-33); + Q->lamp = atan2(cos(phi1) * sin(phi2) * cos(lam1) - + sin(phi1) * cos(phi2) * cos(lam2), + sin(phi1) * cos(phi2) * sin(lam2) - + cos(phi1) * sin(phi2) * sin(lam1)); + phip = atan(-cos(Q->lamp - lam1) / tan(phi1)); + } + if (fabs(phip) > TOL) { /* oblique */ + Q->cphip = cos(phip); + Q->sphip = sin(phip); + P->fwd = o_forward; + P->inv = Q->link->inv ? o_inverse : 0; + } else { /* transverse */ + P->fwd = t_forward; + P->inv = Q->link->inv ? t_inverse : 0; + } + + return P; +} + +#ifdef PJ_OMIT_SELFTEST +int pj_ob_tran_selftest (void) {return 0;} +#else + +int pj_ob_tran_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char s_args[] = {"+proj=ob_tran +o_proj=latlon +o_lon_p=20 +o_lat_p=20 +lon_0=180"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY s_fwd_expect[] = { + {-2.6856872138416592, 1.2374302350496296}, + {-2.6954069748943286, 1.2026833954513816}, + {-2.8993663925401947, 1.2374302350496296}, + {-2.8896466314875244, 1.2026833954513816}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP s_inv_expect[] = { + { 121.5518748407577, -2.5361001573966084}, + { 63.261184340201858, 17.585319578673531}, + {-141.10073322351622, 26.091712304855108}, + {-65.862385598848391, 51.830295078417215}, + }; + + return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); +} + +#endif -- cgit v1.2.3 From 0d1579f5f14a844f1431b1d22a34ba5e82a7056a Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 4 May 2016 17:12:56 +0200 Subject: Converted geocent. Only testing ellipsoidal input/output - need to check the spherical case --- src/PJ_aea.c | 1 - src/pj_geocent.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 93 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index a84a781a..bde38783 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -354,7 +354,6 @@ source files ***********************************************************************/ int pj_etmerc_selftest (void) {return 10000;} -int pj_geocent_selftest (void) {return 10000;} int pj_latlon_selftest (void) {return 10000;} int pj_latlong_selftest (void) {return 10000;} diff --git a/src/pj_geocent.c b/src/pj_geocent.c index 6b2f3026..7283a174 100644 --- a/src/pj_geocent.c +++ b/src/pj_geocent.c @@ -32,24 +32,102 @@ PROJ_HEAD(geocent, "Geocentric") "\n\t"; -FORWARD(forward); - (void) P; - xy.x = lp.lam; - xy.y = lp.phi; - return xy; +static XY forward(LP lp, PJ *P) { + XY xy = {0.0,0.0}; + (void) P; + xy.x = lp.lam; + xy.y = lp.phi; + return xy; } -INVERSE(inverse); - (void) P; - lp.phi = xy.y; - lp.lam = xy.x; - return lp; + +static LP inverse(XY xy, PJ *P) { + LP lp = {0.0,0.0}; + (void) P; + lp.phi = xy.y; + lp.lam = xy.x; + return lp; +} + + +static void *freeup_new (PJ *P) { + if (0==P) + return 0; + + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; if (P) pj_dalloc(P); } -ENTRY0(geocent) - P->is_geocent = 1; +PJ *PROJECTION(geocent) { + P->is_geocent = 1; P->x0 = 0.0; P->y0 = 0.0; - P->inv = inverse; P->fwd = forward; -ENDENTRY(P) + P->inv = inverse; + P->fwd = forward; + + return P; +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_geocent_selftest (void) {return 0;} +#else + +int pj_geocent_selftest (void) { + + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=geocent +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=geocent +a=6400000 +lat_1=0.5 +lat_2=2"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + { 222638.98158654713, 111319.49079327357}, + { 222638.98158654713, -111319.49079327357}, + {-222638.98158654713, 111319.49079327357}, + {-222638.98158654713, -111319.49079327357}, + }; + + XY s_fwd_expect[] = { + { 223402.14425527418, 111701.07212763709}, + { 223402.14425527418, -111701.07212763709}, + {-223402.14425527418, 111701.07212763709}, + {-223402.14425527418, -111701.07212763709}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + { 0.0017966305682390426, 0.00089831528411952132}, + { 0.0017966305682390426, -0.00089831528411952132}, + {-0.0017966305682390426, 0.00089831528411952132}, + {-0.0017966305682390426, -0.00089831528411952132}, + }; + + LP s_inv_expect[] = { + { 0.0017904931097838226, 0.00089831528411952132}, + { 0.0017904931097838226, -0.00089831528411952132}, + {-0.0017904931097838226, 0.00089831528411952132}, + {-0.0017904931097838226, -0.00089831528411952132}, + }; + + return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); +} + +#endif -- cgit v1.2.3 From e9d8c38ce15f3cc80c4e707aed72d9c51efd4e53 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 4 May 2016 17:14:24 +0200 Subject: Converted latlong. Added passing selftest in order to build. --- src/PJ_aea.c | 5 --- src/pj_latlong.c | 120 +++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 82 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index bde38783..77b50bf7 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -355,11 +355,6 @@ source files int pj_etmerc_selftest (void) {return 10000;} -int pj_latlon_selftest (void) {return 10000;} -int pj_latlong_selftest (void) {return 10000;} -int pj_lonlat_selftest (void) {return 10000;} -int pj_longlat_selftest (void) {return 10000;} - int pj_sch_selftest (void) {return 10000;} int pj_utm_selftest (void) {return 10000;} diff --git a/src/pj_latlong.c b/src/pj_latlong.c index b7a771a8..761eadc5 100644 --- a/src/pj_latlong.c +++ b/src/pj_latlong.c @@ -29,50 +29,94 @@ /* very loosely based upon DMA code by Bradford W. Drew */ #define PJ_LIB__ -#include +#include + PROJ_HEAD(lonlat, "Lat/long (Geodetic)") "\n\t"; PROJ_HEAD(latlon, "Lat/long (Geodetic alias)") "\n\t"; PROJ_HEAD(latlong, "Lat/long (Geodetic alias)") "\n\t"; PROJ_HEAD(longlat, "Lat/long (Geodetic alias)") "\n\t"; -FORWARD(forward); - xy.x = lp.lam / P->a; - xy.y = lp.phi / P->a; - return xy; + static XY forward(LP lp, PJ *P) { + XY xy = {0.0,0.0}; + xy.x = lp.lam / P->a; + xy.y = lp.phi / P->a; + return xy; +} + + +static LP inverse(XY xy, PJ *P) { + LP lp = {0.0,0.0}; + lp.phi = xy.y * P->a; + lp.lam = xy.x * P->a; + return lp; +} + + +static void *freeup_new (PJ *P) { + if (0==P) + return 0; + + return pj_dealloc(P); } -INVERSE(inverse); - lp.phi = xy.y * P->a; - lp.lam = xy.x * P->a; - return lp; +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; if (P) pj_dalloc(P); } - -ENTRY0(latlong) - P->is_latlong = 1; - P->x0 = 0.0; - P->y0 = 0.0; - P->inv = inverse; P->fwd = forward; -ENDENTRY(P) - -ENTRY0(longlat) - P->is_latlong = 1; - P->x0 = 0.0; - P->y0 = 0.0; - P->inv = inverse; P->fwd = forward; -ENDENTRY(P) - -ENTRY0(latlon) - P->is_latlong = 1; - P->x0 = 0.0; - P->y0 = 0.0; - P->inv = inverse; P->fwd = forward; -ENDENTRY(P) - -ENTRY0(lonlat) - P->is_latlong = 1; - P->x0 = 0.0; - P->y0 = 0.0; - P->inv = inverse; P->fwd = forward; -ENDENTRY(P) + + +PJ *PROJECTION(latlong) { + P->is_latlong = 1; + P->x0 = 0.0; + P->y0 = 0.0; + P->inv = inverse; + P->fwd = forward; + + return P; +} + + +PJ *PROJECTION(longlat) { + P->is_latlong = 1; + P->x0 = 0.0; + P->y0 = 0.0; + P->inv = inverse; + P->fwd = forward; + + return P; +} + + +PJ *PROJECTION(latlon) { + P->is_latlong = 1; + P->x0 = 0.0; + P->y0 = 0.0; + P->inv = inverse; + P->fwd = forward; + + return P; +} + + +PJ *PROJECTION(lonlat) { + P->is_latlong = 1; + P->x0 = 0.0; + P->y0 = 0.0; + P->inv = inverse; P->fwd = forward; + + return P; +} + + +/* Bogus self-test functions. Self-tests can't be implemented the usual way for + * these "projections" since they can't be used directly from proj. + * We still need them though, as all projections are automatically added to + * the list of self-test functions. + * + * The code should be covered by the tests in nad/. + * */ +int pj_latlong_selftest (void) {return 0;} +int pj_longlat_selftest (void) {return 0;} +int pj_latlon_selftest (void) {return 0;} +int pj_lonlat_selftest (void) {return 0;} -- cgit v1.2.3 From b22f79a58cbd1954f698c23dc06d975762d0c177 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 4 May 2016 21:14:47 +0200 Subject: Removed test data for the spherical test case. Not really possible to test with the current setup. --- src/pj_geocent.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'src') diff --git a/src/pj_geocent.c b/src/pj_geocent.c index 7283a174..fa01b01f 100644 --- a/src/pj_geocent.c +++ b/src/pj_geocent.c @@ -98,13 +98,6 @@ int pj_geocent_selftest (void) { {-222638.98158654713, -111319.49079327357}, }; - XY s_fwd_expect[] = { - { 223402.14425527418, 111701.07212763709}, - { 223402.14425527418, -111701.07212763709}, - {-223402.14425527418, 111701.07212763709}, - {-223402.14425527418, -111701.07212763709}, - }; - XY inv_in[] = { { 200, 100}, { 200,-100}, @@ -119,13 +112,6 @@ int pj_geocent_selftest (void) { {-0.0017966305682390426, -0.00089831528411952132}, }; - LP s_inv_expect[] = { - { 0.0017904931097838226, 0.00089831528411952132}, - { 0.0017904931097838226, -0.00089831528411952132}, - {-0.0017904931097838226, 0.00089831528411952132}, - {-0.0017904931097838226, -0.00089831528411952132}, - }; - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); } -- cgit v1.2.3 From 40c586eb9107250859b902c8f119c3eb09e2cb6b Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 4 May 2016 22:12:33 +0200 Subject: Converted sch --- src/PJ_aea.c | 3 - src/PJ_sch.c | 337 ++++++++++++++++++++++++++++++++--------------------------- 2 files changed, 184 insertions(+), 156 deletions(-) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 77b50bf7..5f7c6c92 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -354,8 +354,5 @@ source files ***********************************************************************/ int pj_etmerc_selftest (void) {return 10000;} - -int pj_sch_selftest (void) {return 10000;} - int pj_utm_selftest (void) {return 10000;} #endif diff --git a/src/PJ_sch.c b/src/PJ_sch.c index 9a0120fe..29b7b34c 100644 --- a/src/PJ_sch.c +++ b/src/PJ_sch.c @@ -3,8 +3,8 @@ * * Project: SCH Coordinate system * Purpose: Implementation of SCH Coordinate system - * References : - * 1. Hensley. Scott. SCH Coordinates and various transformations. June 15, 2000. + * References : + * 1. Hensley. Scott. SCH Coordinates and various transformations. June 15, 2000. * 2. Buckley, Sean Monroe. Radar interferometry measurement of land subsidence. 2000.. * PhD Thesis. UT Austin. (Appendix) * 3. Hensley, Scott, Elaine Chapin, and T. Michel. "Improved processing of AIRSAR @@ -15,8 +15,8 @@ * Copyright (c) 2015 California Institute of Technology. * Government sponsorship acknowledged. * - * NOTE: The SCH coordinate system is a sensor aligned coordinate system - * developed at JPL for radar mapping missions. Details pertaining to the + * NOTE: The SCH coordinate system is a sensor aligned coordinate system + * developed at JPL for radar mapping missions. Details pertaining to the * coordinate system have been release in the public domain (see references above). * This code is an independent implementation of the SCH coordinate system * that conforms to the PROJ.4 conventions and uses the details presented in these @@ -32,200 +32,231 @@ * DEALINGS IN THE SOFTWARE. ****************************************************************************/ +#define PJ_LIB__ +#include #include "geocent.h" -#define PROJ_PARMS__ \ - double plat; /*Peg Latitude */ \ - double plon; /*Peg Longitude*/ \ - double phdg; /*Peg heading */ \ - double h0; /*Average altitude */\ - double transMat[9]; \ - double xyzoff[3]; \ - double rcurv; \ - GeocentricInfo sph; \ - GeocentricInfo elp_0; - -#define PJ_LIB__ -#include +struct pj_opaque { + double plat; /*Peg Latitude */ + double plon; /*Peg Longitude*/ + double phdg; /*Peg heading */ + double h0; /*Average altitude */ + double transMat[9]; + double xyzoff[3]; + double rcurv; + GeocentricInfo sph; + GeocentricInfo elp_0; +}; PROJ_HEAD(sch, "Spherical Cross-track Height") "\n\tMisc\n\tplat_0 = ,plon_0 = , phdg_0 = ,[h_0 = ]"; -INVERSE3D(inverse3d); - double temp[3]; - double pxyz[3]; - - //Local lat,lon using radius - pxyz[0] = xyz.y * P->a / P->rcurv; - pxyz[1] = xyz.x * P->a / P->rcurv; - pxyz[2] = xyz.z; +static LPZ inverse3d(XYZ xyz, PJ *P) { + LPZ lpz = {0.0, 0.0, 0.0}; + struct pj_opaque *Q = P->opaque; + double temp[3]; + double pxyz[3]; + //Local lat,lon using radius + pxyz[0] = xyz.y * P->a / Q->rcurv; + pxyz[1] = xyz.x * P->a / Q->rcurv; + pxyz[2] = xyz.z; - if( pj_Convert_Geodetic_To_Geocentric( &(P->sph), pxyz[0], pxyz[1], pxyz[2], - temp, temp+1, temp+2) != 0) - I3_ERROR; + if( pj_Convert_Geodetic_To_Geocentric( &(Q->sph), pxyz[0], pxyz[1], pxyz[2], + temp, temp+1, temp+2) != 0) + I3_ERROR; - //Apply rotation - pxyz[0] = P->transMat[0] * temp[0] + P->transMat[1] * temp[1] + P->transMat[2] * temp[2]; - pxyz[1] = P->transMat[3] * temp[0] + P->transMat[4] * temp[1] + P->transMat[5] * temp[2]; - pxyz[2] = P->transMat[6] * temp[0] + P->transMat[7] * temp[1] + P->transMat[8] * temp[2]; + //Apply rotation + pxyz[0] = Q->transMat[0] * temp[0] + Q->transMat[1] * temp[1] + Q->transMat[2] * temp[2]; + pxyz[1] = Q->transMat[3] * temp[0] + Q->transMat[4] * temp[1] + Q->transMat[5] * temp[2]; + pxyz[2] = Q->transMat[6] * temp[0] + Q->transMat[7] * temp[1] + Q->transMat[8] * temp[2]; - //Apply offset - pxyz[0] += P->xyzoff[0]; - pxyz[1] += P->xyzoff[1]; - pxyz[2] += P->xyzoff[2]; + //Apply offset + pxyz[0] += Q->xyzoff[0]; + pxyz[1] += Q->xyzoff[1]; + pxyz[2] += Q->xyzoff[2]; - //Convert geocentric coordinates to lat lon - pj_Convert_Geocentric_To_Geodetic( &(P->elp_0), pxyz[0], pxyz[1], pxyz[2], - temp, temp+1, temp+2); + //Convert geocentric coordinates to lat lon + pj_Convert_Geocentric_To_Geodetic( &(Q->elp_0), pxyz[0], pxyz[1], pxyz[2], + temp, temp+1, temp+2); - lpz.lam = temp[1] ; - lpz.phi = temp[0] ; - lpz.z = temp[2]; + lpz.lam = temp[1] ; + lpz.phi = temp[0] ; + lpz.z = temp[2]; -// printf("INVERSE: \n"); -// printf("XYZ: %f %f %f \n", xyz.x, xyz.y, xyz.z); -// printf("LPZ: %f %f %f \n", lpz.lam, lpz.phi, lpz.z); - return (lpz); + // printf("INVERSE: \n"); + // printf("XYZ: %f %f %f \n", xyz.x, xyz.y, xyz.z); + // printf("LPZ: %f %f %f \n", lpz.lam, lpz.phi, lpz.z); + return lpz; } -FORWARD3D(forward3d); - double temp[3]; - double pxyz[3]; +static XYZ forward3d(LPZ lpz, PJ *P) { + XYZ xyz = {0.0, 0.0, 0.0}; + struct pj_opaque *Q = P->opaque; + double temp[3]; + double pxyz[3]; + + + //Convert lat lon to geocentric coordinates + if( pj_Convert_Geodetic_To_Geocentric( &(Q->elp_0), lpz.phi, lpz.lam, lpz.z, + temp, temp+1, temp+2 ) != 0 ) + F3_ERROR; + + //Adjust for offset + temp[0] -= Q->xyzoff[0]; + temp[1] -= Q->xyzoff[1]; + temp[2] -= Q->xyzoff[2]; - //Convert lat lon to geocentric coordinates - if( pj_Convert_Geodetic_To_Geocentric( &(P->elp_0), lpz.phi, lpz.lam, lpz.z, - temp, temp+1, temp+2 ) != 0 ) - F3_ERROR; + //Apply rotation + pxyz[0] = Q->transMat[0] * temp[0] + Q->transMat[3] * temp[1] + Q->transMat[6] * temp[2]; + pxyz[1] = Q->transMat[1] * temp[0] + Q->transMat[4] * temp[1] + Q->transMat[7] * temp[2]; + pxyz[2] = Q->transMat[2] * temp[0] + Q->transMat[5] * temp[1] + Q->transMat[8] * temp[2]; - //Adjust for offset - temp[0] -= P->xyzoff[0]; - temp[1] -= P->xyzoff[1]; - temp[2] -= P->xyzoff[2]; + //Convert to local lat,lon + pj_Convert_Geocentric_To_Geodetic( &(Q->sph), pxyz[0], pxyz[1], pxyz[2], + temp, temp+1, temp+2); - - //Apply rotation - pxyz[0] = P->transMat[0] * temp[0] + P->transMat[3] * temp[1] + P->transMat[6] * temp[2]; - pxyz[1] = P->transMat[1] * temp[0] + P->transMat[4] * temp[1] + P->transMat[7] * temp[2]; - pxyz[2] = P->transMat[2] * temp[0] + P->transMat[5] * temp[1] + P->transMat[8] * temp[2]; - //Convert to local lat,lon - pj_Convert_Geocentric_To_Geodetic( &(P->sph), pxyz[0], pxyz[1], pxyz[2], - temp, temp+1, temp+2); + //Scale by radius + xyz.x = temp[1] * Q->rcurv / P->a; + xyz.y = temp[0] * Q->rcurv / P->a; + xyz.z = temp[2]; + // printf("FORWARD: \n"); + // printf("LPZ: %f %f %f \n", lpz.lam, lpz.phi, lpz.z); + // printf("XYZ: %f %f %f \n", xyz.x, xyz.y, xyz.z); - //Scale by radius - xyz.x = temp[1] * P->rcurv / P->a; - xyz.y = temp[0] * P->rcurv / P->a; - xyz.z = temp[2]; + return xyz; +} + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); -// printf("FORWARD: \n"); -// printf("LPZ: %f %f %f \n", lpz.lam, lpz.phi, lpz.z); -// printf("XYZ: %f %f %f \n", xyz.x, xyz.y, xyz.z); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} - return (xyz); +static void freeup (PJ *P) { + freeup_new (P); + return; } -FREEUP; if (P) pj_dalloc(P); } - static PJ * -setup(PJ *P) { /* general initialization */ - double reast, rnorth; - double chdg, shdg; - double clt, slt; - double clo, slo; - double temp; - double pxyz[3]; +static PJ *setup(PJ *P) { /* general initialization */ + struct pj_opaque *Q = P->opaque; + double reast, rnorth; + double chdg, shdg; + double clt, slt; + double clo, slo; + double temp; + double pxyz[3]; - temp = P->a * sqrt(1.0 - P->es); + temp = P->a * sqrt(1.0 - P->es); - //Setup original geocentric system - if ( pj_Set_Geocentric_Parameters(&(P->elp_0), P->a, temp) != 0) - E_ERROR(-37); + //Setup original geocentric system + if ( pj_Set_Geocentric_Parameters(&(Q->elp_0), P->a, temp) != 0) + E_ERROR(-37); + clt = cos(Q->plat); + slt = sin(Q->plat); + clo = cos(Q->plon); + slo = sin(Q->plon); - clt = cos(P->plat); - slt = sin(P->plat); - clo = cos(P->plon); - slo = sin(P->plon); + //Estimate the radius of curvature for given peg + temp = sqrt(1.0 - (P->es) * slt * slt); + reast = (P->a)/temp; + rnorth = (P->a) * (1.0 - (P->es))/pow(temp,3); - //Estimate the radius of curvature for given peg - temp = sqrt(1.0 - (P->es) * slt * slt); - reast = (P->a)/temp; - rnorth = (P->a) * (1.0 - (P->es))/pow(temp,3); + chdg = cos(Q->phdg); + shdg = sin(Q->phdg); - chdg = cos(P->phdg); - shdg = sin(P->phdg); - - P->rcurv = P->h0 + (reast*rnorth)/(reast * chdg * chdg + rnorth * shdg * shdg); + Q->rcurv = Q->h0 + (reast*rnorth)/(reast * chdg * chdg + rnorth * shdg * shdg); -// printf("North Radius: %f \n", rnorth); -// printf("East Radius: %f \n", reast); -// printf("Effective Radius: %f \n", P->rcurv); + // printf("North Radius: %f \n", rnorth); + // printf("East Radius: %f \n", reast); + // printf("Effective Radius: %f \n", Q->rcurv); - //Set up local sphere at the given peg point - if ( pj_Set_Geocentric_Parameters(&(P->sph), P->rcurv, P->rcurv) != 0) - E_ERROR(-37); + //Set up local sphere at the given peg point + if ( pj_Set_Geocentric_Parameters(&(Q->sph), Q->rcurv, Q->rcurv) != 0) + E_ERROR(-37); - //Set up the transformation matrices - P->transMat[0] = clt * clo; - P->transMat[1] = -shdg*slo - slt*clo * chdg; - P->transMat[2] = slo*chdg - slt*clo*shdg; - P->transMat[3] = clt*slo; - P->transMat[4] = clo*shdg - slt*slo*chdg; - P->transMat[5] = -clo*chdg - slt*slo*shdg; - P->transMat[6] = slt; - P->transMat[7] = clt*chdg; - P->transMat[8] = clt*shdg; + //Set up the transformation matrices + Q->transMat[0] = clt * clo; + Q->transMat[1] = -shdg*slo - slt*clo * chdg; + Q->transMat[2] = slo*chdg - slt*clo*shdg; + Q->transMat[3] = clt*slo; + Q->transMat[4] = clo*shdg - slt*slo*chdg; + Q->transMat[5] = -clo*chdg - slt*slo*shdg; + Q->transMat[6] = slt; + Q->transMat[7] = clt*chdg; + Q->transMat[8] = clt*shdg; - - if( pj_Convert_Geodetic_To_Geocentric( &(P->elp_0), P->plat, P->plon, P->h0, - pxyz, pxyz+1, pxyz+2 ) != 0 ) - { - E_ERROR(-14) - } + if( pj_Convert_Geodetic_To_Geocentric( &(Q->elp_0), Q->plat, Q->plon, Q->h0, + pxyz, pxyz+1, pxyz+2 ) != 0 ) + { + E_ERROR(-14) + } - P->xyzoff[0] = pxyz[0] - (P->rcurv) * clt * clo; - P->xyzoff[1] = pxyz[1] - (P->rcurv) * clt * slo; - P->xyzoff[2] = pxyz[2] - (P->rcurv) * slt; -// printf("Offset: %f %f %f \n", P->xyzoff[0], P->xyzoff[1], P->xyzoff[2]); + Q->xyzoff[0] = pxyz[0] - (Q->rcurv) * clt * clo; + Q->xyzoff[1] = pxyz[1] - (Q->rcurv) * clt * slo; + Q->xyzoff[2] = pxyz[2] - (Q->rcurv) * slt; + // printf("Offset: %f %f %f \n", Q->xyzoff[0], Q->xyzoff[1], Q->xyzoff[2]); - P->fwd3d = forward3d; - P->inv3d = inverse3d; - return P; + + P->fwd3d = forward3d; + P->inv3d = inverse3d; + return P; } -ENTRY0(sch) - P->h0 = 0.0; - //Check if peg latitude was defined - if (pj_param(P->ctx, P->params, "tplat_0").i) - P->plat = pj_param(P->ctx, P->params, "rplat_0").f; - else - E_ERROR(-37); - //Check if peg longitude was defined - if (pj_param(P->ctx, P->params, "tplon_0").i) - P->plon = pj_param(P->ctx, P->params, "rplon_0").f; - else - E_ERROR(-37); - - //Check if peg latitude is defined - if (pj_param(P->ctx, P->params, "tphdg_0").i) - P->phdg = pj_param(P->ctx, P->params, "rphdg_0").f; - else - E_ERROR(-37); - +PJ *PROJECTION(sch) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + Q->h0 = 0.0; + + //Check if peg latitude was defined + if (pj_param(P->ctx, P->params, "tplat_0").i) + Q->plat = pj_param(P->ctx, P->params, "rplat_0").f; + else + E_ERROR(-37); - //Check if average height was defined - //If so read it in - if (pj_param(P->ctx, P->params, "th_0").i) - P->h0 = pj_param(P->ctx, P->params, "dh_0").f; + //Check if peg longitude was defined + if (pj_param(P->ctx, P->params, "tplon_0").i) + Q->plon = pj_param(P->ctx, P->params, "rplon_0").f; + else + E_ERROR(-37); - //Completed reading in the projection parameters -// printf("PSA: Lat = %f Lon = %f Hdg = %f \n", P->plat, P->plon, P->phdg); + //Check if peg latitude is defined + if (pj_param(P->ctx, P->params, "tphdg_0").i) + Q->phdg = pj_param(P->ctx, P->params, "rphdg_0").f; + else + E_ERROR(-37); + + + //Check if average height was defined + //If so read it in + if (pj_param(P->ctx, P->params, "th_0").i) + Q->h0 = pj_param(P->ctx, P->params, "dh_0").f; + + //Completed reading in the projection parameters + //printf("PSA: Lat = %f Lon = %f Hdg = %f \n", Q->plat, Q->plon, Q->phdg); + + + return setup(P); +} -ENDENTRY(setup(P)) +/* Skipping sef-test since the test system is not capable of handling + * 3D coordinate systems for the time being. Relying on tests in ../nad/ + */ +int pj_sch_selftest (void) {return 0;} -- cgit v1.2.3 From efa91386d8b0a2270d3396a6cf1f2098487feb3d Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 4 May 2016 23:34:50 +0200 Subject: Eliminating compile warnings --- src/PJ_eck5.c | 31 ++++++++----------------------- src/PJ_fahey.c | 19 +++++++++---------- 2 files changed, 17 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/PJ_eck5.c b/src/PJ_eck5.c index ccfcb88f..d7626939 100644 --- a/src/PJ_eck5.c +++ b/src/PJ_eck5.c @@ -56,7 +56,6 @@ int pj_eck5_selftest (void) { double tolerance_lp = 1e-10; double tolerance_xy = 1e-7; - char e_args[] = {"+proj=eck5 +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; char s_args[] = {"+proj=eck5 +a=6400000 +lat_1=0.5 +lat_2=2"}; LP fwd_in[] = { @@ -66,18 +65,11 @@ int pj_eck5_selftest (void) { {-2,-1} }; - XY e_fwd_expect[] = { - { 196358.31442683787, 98186.634363414545 }, - { 196358.31442683787, -98186.634363414545 }, - {-196358.31442683787, 98186.634363414545 }, - {-196358.31442683787, -98186.634363414545 }, - }; - XY s_fwd_expect[] = { - { 197031.39213406085, 98523.198847226551 }, - { 197031.39213406085, -98523.198847226551 }, - {-197031.39213406085, 98523.198847226551 }, - {-197031.39213406085, -98523.198847226551 }, + { 197031.39213406085, 98523.198847226551}, + { 197031.39213406085, -98523.198847226551}, + {-197031.39213406085, 98523.198847226551}, + {-197031.39213406085, -98523.198847226551}, }; XY inv_in[] = { @@ -87,18 +79,11 @@ int pj_eck5_selftest (void) { {-200,-100} }; - LP e_inv_expect[] = { - {0.0020369371178927064, 0.0010184685588659013 }, - {0.0020369371178927064, -0.0010184685588659013 }, - {-0.0020369371178927064, 0.0010184685588659013 }, - {-0.0020369371178927064, -0.0010184685588659013 }, - }; - LP s_inv_expect[] = { - {0.002029978749734037, 0.001014989374787388 }, - {0.002029978749734037, -0.001014989374787388 }, - {-0.002029978749734037, 0.001014989374787388 }, - {-0.002029978749734037, -0.001014989374787388 }, + {0.002029978749734037, 0.001014989374787388}, + {0.002029978749734037, -0.001014989374787388}, + {-0.002029978749734037, 0.001014989374787388}, + {-0.002029978749734037, -0.001014989374787388}, }; return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); diff --git a/src/PJ_fahey.c b/src/PJ_fahey.c index 864225f4..b8841c96 100644 --- a/src/PJ_fahey.c +++ b/src/PJ_fahey.c @@ -1,5 +1,5 @@ #define PJ_LIB__ -# include +#include PROJ_HEAD(fahey, "Fahey") "\n\tPcyl, Sph."; @@ -58,7 +58,6 @@ int pj_fahey_selftest (void) { double tolerance_lp = 1e-10; double tolerance_xy = 1e-7; - char e_args[] = {"+proj=fahey +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; char s_args[] = {"+proj=fahey +a=6400000 +lat_1=0.5 +lat_2=2"}; LP fwd_in[] = { @@ -69,10 +68,10 @@ int pj_fahey_selftest (void) { }; XY s_fwd_expect[] = { - { 182993.34464912376, 101603.19356988439 }, - { 182993.34464912376, -101603.19356988439 }, - {-182993.34464912376, 101603.19356988439 }, - {-182993.34464912376, -101603.19356988439 }, + { 182993.34464912376, 101603.19356988439}, + { 182993.34464912376, -101603.19356988439}, + {-182993.34464912376, 101603.19356988439}, + {-182993.34464912376, -101603.19356988439}, }; XY inv_in[] = { @@ -83,10 +82,10 @@ int pj_fahey_selftest (void) { }; LP s_inv_expect[] = { - {0.0021857886080359551, 0.00098424601668238403 }, - {0.0021857886080359551, -0.00098424601668238403 }, - {-0.0021857886080359551, 0.00098424601668238403 }, - {-0.0021857886080359551, -0.00098424601668238403 }, + {0.0021857886080359551, 0.00098424601668238403}, + {0.0021857886080359551, -0.00098424601668238403}, + {-0.0021857886080359551, 0.00098424601668238403}, + {-0.0021857886080359551, -0.00098424601668238403}, }; return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -- cgit v1.2.3 From 6cbf7e5f6c51b3b88e0d604124d688f79512496b Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 4 May 2016 23:35:12 +0200 Subject: Expanded SPECIAL macro --- src/PJ_eqdc.c | 4 ++-- src/PJ_lcc.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/PJ_eqdc.c b/src/PJ_eqdc.c index 08981249..a7308335 100644 --- a/src/PJ_eqdc.c +++ b/src/PJ_eqdc.c @@ -52,7 +52,7 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ } -SPECIAL(fac) { +static void special(LP lp, PJ *P, struct FACTORS *fac) { struct pj_opaque *Q = P->opaque; double sinphi, cosphi; @@ -124,7 +124,7 @@ PJ *PROJECTION(eqdc) { } P->inv = e_inverse; P->fwd = e_forward; - P->spc = fac; + P->spc = special; return P; } diff --git a/src/PJ_lcc.c b/src/PJ_lcc.c index 3a5d3485..28275089 100644 --- a/src/PJ_lcc.c +++ b/src/PJ_lcc.c @@ -65,7 +65,7 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ return lp; } -SPECIAL(fac) { +static void special(LP lp, PJ *P, struct FACTORS *fac) { struct pj_opaque *Q = P->opaque; double rho; if (fabs(fabs(lp.phi) - HALFPI) < EPS10) { @@ -144,7 +144,7 @@ PJ *PROJECTION(lcc) { P->inv = e_inverse; P->fwd = e_forward; - P->spc = fac; + P->spc = special; return P; } -- cgit v1.2.3 From f58ba586ebf11700317513f7bb5be84590d37a42 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Wed, 11 May 2016 08:58:28 +0200 Subject: Portability cleanups for the code in PR #6 (and a few additional source files) Eliminated mixed code and declarations, converted C++ style comments and probably did a few more things highlighted by running gcc with the "-W -Wall -Wextra -pedantic" flags --- src/PJ_eqdc.c | 6 +-- src/PJ_labrd.c | 2 +- src/PJ_laea.c | 2 +- src/PJ_lagrng.c | 2 +- src/PJ_lcc.c | 5 ++- src/PJ_lcca.c | 2 +- src/PJ_lsat.c | 4 +- src/PJ_minimal.c | 16 +++---- src/PJ_misrsom.c | 6 +-- src/PJ_mod_ster.c | 52 +++++++++++------------ src/PJ_nsper.c | 4 +- src/PJ_ob_tran.c | 8 ++-- src/PJ_ocea.c | 4 +- src/PJ_omerc.c | 8 ++-- src/PJ_sch.c | 72 +++++++++++++++++--------------- src/pj_fwd.c | 2 +- src/pj_fwd3d.c | 6 +-- src/pj_inv.c | 2 +- src/pj_inv3d.c | 8 ++-- src/pj_mutex.c | 8 ++-- src/pj_transform.c | 119 ++++++++++++++++++++++++++--------------------------- src/pj_utils.c | 30 +++++++------- src/warnings.pj | 72 ++++++++++++++++++++++++++++++++ 23 files changed, 259 insertions(+), 181 deletions(-) create mode 100644 src/warnings.pj (limited to 'src') diff --git a/src/PJ_eqdc.c b/src/PJ_eqdc.c index a7308335..917131e1 100644 --- a/src/PJ_eqdc.c +++ b/src/PJ_eqdc.c @@ -86,14 +86,14 @@ static void freeup (PJ *P) { PJ *PROJECTION(eqdc) { + double cosphi, sinphi; + int secant; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - double cosphi, sinphi; - int secant; - Q->phi1 = pj_param(P->ctx, P->params, "rlat_1").f; Q->phi2 = pj_param(P->ctx, P->params, "rlat_2").f; if (fabs(Q->phi1 + Q->phi2) < EPS10) E_ERROR(-21); diff --git a/src/PJ_labrd.c b/src/PJ_labrd.c index e7bca390..4c435731 100644 --- a/src/PJ_labrd.c +++ b/src/PJ_labrd.c @@ -109,11 +109,11 @@ static void freeup (PJ *P) { PJ *PROJECTION(labrd) { + double Az, sinp, R, N, t; struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - double Az, sinp, R, N, t; Q->rot = pj_param(P->ctx, P->params, "bno_rot").i == 0; Az = pj_param(P->ctx, P->params, "razi").f; diff --git a/src/PJ_laea.c b/src/PJ_laea.c index 02b281a4..8393ebd0 100644 --- a/src/PJ_laea.c +++ b/src/PJ_laea.c @@ -222,11 +222,11 @@ static void freeup (PJ *P) { PJ *PROJECTION(laea) { + double t; struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - double t; t = fabs(P->phi0); if (fabs(t - HALFPI) < EPS10) diff --git a/src/PJ_lagrng.c b/src/PJ_lagrng.c index 9a018808..244cf043 100644 --- a/src/PJ_lagrng.c +++ b/src/PJ_lagrng.c @@ -49,11 +49,11 @@ static void freeup (PJ *P) { PJ *PROJECTION(lagrng) { + double phi1; struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - double phi1; Q->rw = pj_param(P->ctx, P->params, "dW").f; if (Q->rw <= 0) E_ERROR(-27); diff --git a/src/PJ_lcc.c b/src/PJ_lcc.c index 28275089..e7b74be4 100644 --- a/src/PJ_lcc.c +++ b/src/PJ_lcc.c @@ -98,13 +98,14 @@ static void freeup (PJ *P) { PJ *PROJECTION(lcc) { + double cosphi, sinphi; + int secant; struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) return freeup_new (P); P->opaque = Q; - double cosphi, sinphi; - int secant; Q->phi1 = pj_param(P->ctx, P->params, "rlat_1").f; if (pj_param(P->ctx, P->params, "tlat_2").i) diff --git a/src/PJ_lcca.c b/src/PJ_lcca.c index eef46110..50c89978 100644 --- a/src/PJ_lcca.c +++ b/src/PJ_lcca.c @@ -83,11 +83,11 @@ static void freeup (PJ *P) { PJ *PROJECTION(lcca) { + double s2p0, N0, R0, tan0; struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - double s2p0, N0, R0, tan0; (Q->en = pj_enfn(P->es)); if (!Q->en) E_ERROR_0; diff --git a/src/PJ_lsat.c b/src/PJ_lsat.c index 2dcdb000..fa96407b 100644 --- a/src/PJ_lsat.c +++ b/src/PJ_lsat.c @@ -158,12 +158,12 @@ static void freeup (PJ *P) { PJ *PROJECTION(lsat) { + int land, path; + double lam, alf, esc, ess; struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - int land, path; - double lam, alf, esc, ess; land = pj_param(P->ctx, P->params, "ilsat").i; if (land <= 0 || land > 5) E_ERROR(-28); diff --git a/src/PJ_minimal.c b/src/PJ_minimal.c index 824d8b99..1108c4fa 100644 --- a/src/PJ_minimal.c +++ b/src/PJ_minimal.c @@ -127,7 +127,7 @@ PROJ_HEAD(minimal, "Minimal example (brief description goes here)"); /* Projection specific elements for the PJ object */ -struct opaque { +struct pj_opaque { double a; int b; }; @@ -155,7 +155,7 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ LP lp = {0.0,0.0}; /* Actual ellipsoidal forward code goes here */ lp.lam = xy.x - P->es; - lp.phi = xy.y - P->opaq->b; + lp.phi = xy.y - P->opaque->b; return lp; } @@ -164,7 +164,7 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ LP lp = {0.0,0.0}; /* Actual spheroidal forward code goes here */ lp.lam = xy.x - P->es; - lp.phi = xy.y - P->opaq->b; + lp.phi = xy.y - P->opaque->b; return lp; } @@ -173,21 +173,21 @@ static void freeup(PJ *P) { /* Destructor */ if (P==0) return; /* Projection specific deallocation goes here */ - pj_dealloc (P->opaq); + pj_dealloc (P->opaque); pj_dealloc (P); return; } PJ *pj_projection_specific_setup_minimal (PJ *P) { - pj_prepare (P, des_minimal, freeup, sizeof (struct opaque)); - if (0==P->opaq) { + pj_prepare (P, des_minimal, freeup, sizeof (struct pj_opaque)); + if (0==P->opaque) { freeup (P); return 0; } - P->opaq->a = 42.42; - P->opaq->b = 42; + P->opaque->a = 42.42; + P->opaque->b = 42; /* Spheroidal? */ if (0==P->es) { diff --git a/src/PJ_misrsom.c b/src/PJ_misrsom.c index fdafbd7c..c164b1c7 100644 --- a/src/PJ_misrsom.c +++ b/src/PJ_misrsom.c @@ -175,14 +175,14 @@ static void freeup (PJ *P) { PJ *PROJECTION(misrsom) { + int path; + double lam, alf, esc, ess; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - int path; - double lam, alf, esc, ess; - path = pj_param(P->ctx, P->params, "ipath").i; if (path <= 0 || path > 233) E_ERROR(-29); P->lam0 = DEG_TO_RAD * 129.3056 - TWOPI / 233. * path; diff --git a/src/PJ_mod_ster.c b/src/PJ_mod_ster.c index 551b83bd..7de7c01b 100644 --- a/src/PJ_mod_ster.c +++ b/src/PJ_mod_ster.c @@ -85,7 +85,7 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ } if (nn) { lp.phi = phi; - lp.lam = atan2(p.r * sinz, rh * Q->cchio * cosz - p.i * + lp.lam = atan2(p.r * sinz, rh * Q->cchio * cosz - p.i * Q->schio * sinz); } else lp.lam = lp.phi = HUGE_VAL; @@ -129,17 +129,17 @@ static PJ *setup(PJ *P) { /* general initialization */ /* Miller Oblated Stereographic */ PJ *PROJECTION(mil_os) { - struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); - if (0==Q) - return freeup_new (P); - P->opaque = Q; - static COMPLEX AB[] = { {0.924500, 0.}, {0., 0.}, {0.019430, 0.} }; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + Q->n = 2; P->lam0 = DEG_TO_RAD * 20.; P->phi0 = DEG_TO_RAD * 18.; @@ -152,17 +152,17 @@ PJ *PROJECTION(mil_os) { /* Lee Oblated Stereographic */ PJ *PROJECTION(lee_os) { - struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); - if (0==Q) - return freeup_new (P); - P->opaque = Q; - static COMPLEX AB[] = { {0.721316, 0.}, {0., 0.}, {-0.0088162, -0.00617325} }; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + Q->n = 2; P->lam0 = DEG_TO_RAD * -165.; P->phi0 = DEG_TO_RAD * -10.; @@ -174,11 +174,6 @@ PJ *PROJECTION(lee_os) { PJ *PROJECTION(gs48) { - struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); - if (0==Q) - return freeup_new (P); - P->opaque = Q; - static COMPLEX /* 48 United States */ AB[] = { {0.98879, 0.}, @@ -188,6 +183,11 @@ PJ *PROJECTION(gs48) { {0.075528, 0.} }; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + Q->n = 4; P->lam0 = DEG_TO_RAD * -96.; P->phi0 = DEG_TO_RAD * -39.; @@ -200,11 +200,6 @@ PJ *PROJECTION(gs48) { PJ *PROJECTION(alsk) { - struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); - if (0==Q) - return freeup_new (P); - P->opaque = Q; - static COMPLEX ABe[] = { /* Alaska ellipsoid */ { .9945303, 0.}, { .0052083, -.0027404}, @@ -223,6 +218,11 @@ PJ *PROJECTION(alsk) { { .3660976, -.2937382} }; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + Q->n = 5; P->lam0 = DEG_TO_RAD * -152.; P->phi0 = DEG_TO_RAD * 64.; @@ -240,11 +240,6 @@ PJ *PROJECTION(alsk) { PJ *PROJECTION(gs50) { - struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); - if (0==Q) - return freeup_new (P); - P->opaque = Q; - static COMPLEX ABe[] = { /* GS50 ellipsoid */ { .9827497, 0.}, { .0210669, .0053804}, @@ -271,6 +266,11 @@ PJ *PROJECTION(gs50) { {-.0225161, .0853673} }; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + Q->n = 9; P->lam0 = DEG_TO_RAD * -120.; P->phi0 = DEG_TO_RAD * 45.; diff --git a/src/PJ_nsper.c b/src/PJ_nsper.c index 2a0ea702..7e3fcda8 100644 --- a/src/PJ_nsper.c +++ b/src/PJ_nsper.c @@ -180,13 +180,13 @@ PJ *PROJECTION(nsper) { PJ *PROJECTION(tpers) { + double omega, gamma; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - double omega, gamma; - omega = pj_param(P->ctx, P->params, "dtilt").f * DEG_TO_RAD; gamma = pj_param(P->ctx, P->params, "dazi").f * DEG_TO_RAD; Q->tilt = 1; diff --git a/src/PJ_ob_tran.c b/src/PJ_ob_tran.c index 76222fe9..634bb552 100644 --- a/src/PJ_ob_tran.c +++ b/src/PJ_ob_tran.c @@ -100,15 +100,15 @@ static void freeup (PJ *P) { PJ *PROJECTION(ob_tran) { + int i; + double phip; + char *name, *s; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - int i; - double phip; - char *name, *s; - /* get name of projection to be translated */ if (!(name = pj_param(P->ctx, P->params, "so_proj").s)) E_ERROR(-26); for (i = 0; (s = pj_list[i].id) && strcmp(name, s) ; ++i) ; diff --git a/src/PJ_ocea.c b/src/PJ_ocea.c index 72414e7f..817f0ce6 100644 --- a/src/PJ_ocea.c +++ b/src/PJ_ocea.c @@ -62,13 +62,13 @@ static void freeup (PJ *P) { PJ *PROJECTION(ocea) { + double phi_0=0.0, phi_1, phi_2, lam_1, lam_2, lonz, alpha; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - double phi_0=0.0, phi_1, phi_2, lam_1, lam_2, lonz, alpha; - Q->rok = P->a / P->k0; Q->rtk = P->a * P->k0; /*If the keyword "alpha" is found in the sentence then use 1point+1azimuth*/ diff --git a/src/PJ_omerc.c b/src/PJ_omerc.c index 3b25fb26..e248b8cc 100644 --- a/src/PJ_omerc.c +++ b/src/PJ_omerc.c @@ -123,15 +123,15 @@ static void freeup (PJ *P) { PJ *PROJECTION(omerc) { + double con, com, cosph0, D, F, H, L, sinph0, p, J, gamma=0, + gamma0, lamc=0, lam1=0, lam2=0, phi1=0, phi2=0, alpha_c=0; + int alp, gam, no_off = 0; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - double con, com, cosph0, D, F, H, L, sinph0, p, J, gamma=0, - gamma0, lamc=0, lam1=0, lam2=0, phi1=0, phi2=0, alpha_c=0; - int alp, gam, no_off = 0; - Q->no_rot = pj_param(P->ctx, P->params, "tno_rot").i; if ((alp = pj_param(P->ctx, P->params, "talpha").i) != 0) alpha_c = pj_param(P->ctx, P->params, "ralpha").f; diff --git a/src/PJ_sch.c b/src/PJ_sch.c index 29b7b34c..048224ec 100644 --- a/src/PJ_sch.c +++ b/src/PJ_sch.c @@ -56,7 +56,7 @@ static LPZ inverse3d(XYZ xyz, PJ *P) { double temp[3]; double pxyz[3]; - //Local lat,lon using radius + /* Local lat,lon using radius */ pxyz[0] = xyz.y * P->a / Q->rcurv; pxyz[1] = xyz.x * P->a / Q->rcurv; pxyz[2] = xyz.z; @@ -65,17 +65,17 @@ static LPZ inverse3d(XYZ xyz, PJ *P) { temp, temp+1, temp+2) != 0) I3_ERROR; - //Apply rotation + /* Apply rotation */ pxyz[0] = Q->transMat[0] * temp[0] + Q->transMat[1] * temp[1] + Q->transMat[2] * temp[2]; pxyz[1] = Q->transMat[3] * temp[0] + Q->transMat[4] * temp[1] + Q->transMat[5] * temp[2]; pxyz[2] = Q->transMat[6] * temp[0] + Q->transMat[7] * temp[1] + Q->transMat[8] * temp[2]; - //Apply offset + /* Apply offset */ pxyz[0] += Q->xyzoff[0]; pxyz[1] += Q->xyzoff[1]; pxyz[2] += Q->xyzoff[2]; - //Convert geocentric coordinates to lat lon + /* Convert geocentric coordinates to lat lon */ pj_Convert_Geocentric_To_Geodetic( &(Q->elp_0), pxyz[0], pxyz[1], pxyz[2], temp, temp+1, temp+2); @@ -84,9 +84,11 @@ static LPZ inverse3d(XYZ xyz, PJ *P) { lpz.phi = temp[0] ; lpz.z = temp[2]; - // printf("INVERSE: \n"); - // printf("XYZ: %f %f %f \n", xyz.x, xyz.y, xyz.z); - // printf("LPZ: %f %f %f \n", lpz.lam, lpz.phi, lpz.z); +#if 0 + printf("INVERSE: \n"); + printf("XYZ: %f %f %f \n", xyz.x, xyz.y, xyz.z); + printf("LPZ: %f %f %f \n", lpz.lam, lpz.phi, lpz.z); +#endif return lpz; } @@ -97,37 +99,38 @@ static XYZ forward3d(LPZ lpz, PJ *P) { double pxyz[3]; - //Convert lat lon to geocentric coordinates + /* Convert lat lon to geocentric coordinates */ if( pj_Convert_Geodetic_To_Geocentric( &(Q->elp_0), lpz.phi, lpz.lam, lpz.z, temp, temp+1, temp+2 ) != 0 ) F3_ERROR; - //Adjust for offset + /* Adjust for offset */ temp[0] -= Q->xyzoff[0]; temp[1] -= Q->xyzoff[1]; temp[2] -= Q->xyzoff[2]; - //Apply rotation + /* Apply rotation */ pxyz[0] = Q->transMat[0] * temp[0] + Q->transMat[3] * temp[1] + Q->transMat[6] * temp[2]; pxyz[1] = Q->transMat[1] * temp[0] + Q->transMat[4] * temp[1] + Q->transMat[7] * temp[2]; pxyz[2] = Q->transMat[2] * temp[0] + Q->transMat[5] * temp[1] + Q->transMat[8] * temp[2]; - //Convert to local lat,lon + /* Convert to local lat,lon */ pj_Convert_Geocentric_To_Geodetic( &(Q->sph), pxyz[0], pxyz[1], pxyz[2], temp, temp+1, temp+2); - //Scale by radius + /* Scale by radius */ xyz.x = temp[1] * Q->rcurv / P->a; xyz.y = temp[0] * Q->rcurv / P->a; xyz.z = temp[2]; - // printf("FORWARD: \n"); - // printf("LPZ: %f %f %f \n", lpz.lam, lpz.phi, lpz.z); - // printf("XYZ: %f %f %f \n", xyz.x, xyz.y, xyz.z); - +#if 0 + printf("FORWARD: \n"); + printf("LPZ: %f %f %f \n", lpz.lam, lpz.phi, lpz.z); + printf("XYZ: %f %f %f \n", xyz.x, xyz.y, xyz.z); +#endif return xyz; } @@ -158,7 +161,7 @@ static PJ *setup(PJ *P) { /* general initialization */ temp = P->a * sqrt(1.0 - P->es); - //Setup original geocentric system + /* Setup original geocentric system */ if ( pj_Set_Geocentric_Parameters(&(Q->elp_0), P->a, temp) != 0) E_ERROR(-37); @@ -167,7 +170,7 @@ static PJ *setup(PJ *P) { /* general initialization */ clo = cos(Q->plon); slo = sin(Q->plon); - //Estimate the radius of curvature for given peg + /* Estimate the radius of curvature for given peg */ temp = sqrt(1.0 - (P->es) * slt * slt); reast = (P->a)/temp; rnorth = (P->a) * (1.0 - (P->es))/pow(temp,3); @@ -177,15 +180,17 @@ static PJ *setup(PJ *P) { /* general initialization */ Q->rcurv = Q->h0 + (reast*rnorth)/(reast * chdg * chdg + rnorth * shdg * shdg); - // printf("North Radius: %f \n", rnorth); - // printf("East Radius: %f \n", reast); - // printf("Effective Radius: %f \n", Q->rcurv); +#if 0 + printf("North Radius: %f \n", rnorth); + printf("East Radius: %f \n", reast); + printf("Effective Radius: %f \n", Q->rcurv); +#endif - //Set up local sphere at the given peg point + /* Set up local sphere at the given peg point */ if ( pj_Set_Geocentric_Parameters(&(Q->sph), Q->rcurv, Q->rcurv) != 0) E_ERROR(-37); - //Set up the transformation matrices + /* Set up the transformation matrices */ Q->transMat[0] = clt * clo; Q->transMat[1] = -shdg*slo - slt*clo * chdg; Q->transMat[2] = slo*chdg - slt*clo*shdg; @@ -208,8 +213,9 @@ static PJ *setup(PJ *P) { /* general initialization */ Q->xyzoff[1] = pxyz[1] - (Q->rcurv) * clt * slo; Q->xyzoff[2] = pxyz[2] - (Q->rcurv) * slt; - // printf("Offset: %f %f %f \n", Q->xyzoff[0], Q->xyzoff[1], Q->xyzoff[2]); - +#if 0 + printf("Offset: %f %f %f \n", Q->xyzoff[0], Q->xyzoff[1], Q->xyzoff[2]); +#endif P->fwd3d = forward3d; P->inv3d = inverse3d; @@ -225,33 +231,33 @@ PJ *PROJECTION(sch) { Q->h0 = 0.0; - //Check if peg latitude was defined + /* Check if peg latitude was defined */ if (pj_param(P->ctx, P->params, "tplat_0").i) Q->plat = pj_param(P->ctx, P->params, "rplat_0").f; else E_ERROR(-37); - //Check if peg longitude was defined + /* Check if peg longitude was defined */ if (pj_param(P->ctx, P->params, "tplon_0").i) Q->plon = pj_param(P->ctx, P->params, "rplon_0").f; else E_ERROR(-37); - //Check if peg latitude is defined + /* Check if peg latitude is defined */ if (pj_param(P->ctx, P->params, "tphdg_0").i) Q->phdg = pj_param(P->ctx, P->params, "rphdg_0").f; else E_ERROR(-37); - //Check if average height was defined - //If so read it in + /* Check if average height was defined - If so read it in */ if (pj_param(P->ctx, P->params, "th_0").i) Q->h0 = pj_param(P->ctx, P->params, "dh_0").f; - //Completed reading in the projection parameters - //printf("PSA: Lat = %f Lon = %f Hdg = %f \n", Q->plat, Q->plon, Q->phdg); - + /* Completed reading in the projection parameters */ +#if 0 + printf("PSA: Lat = %f Lon = %f Hdg = %f \n", Q->plat, Q->plon, Q->phdg); +#endif return setup(P); } diff --git a/src/pj_fwd.c b/src/pj_fwd.c index 1cd002b5..d4948d99 100644 --- a/src/pj_fwd.c +++ b/src/pj_fwd.c @@ -25,7 +25,7 @@ pj_fwd(LP lp, PJ *P) { if (!P->over) lp.lam = adjlon(lp.lam); /* adjust del longitude */ - //Check for NULL pointer + /* Check for NULL pointer */ if (P->fwd != NULL) { xy = (*P->fwd)(lp, P); /* project */ diff --git a/src/pj_fwd3d.c b/src/pj_fwd3d.c index 834746d4..9da8a482 100644 --- a/src/pj_fwd3d.c +++ b/src/pj_fwd3d.c @@ -19,13 +19,13 @@ pj_fwd3d(LPZ lpz, PJ *P) { if (fabs(t) <= EPS) lpz.phi = lpz.phi < 0. ? -HALFPI : HALFPI; - else if (P->geoc) //Maybe redundant and never used. + else if (P->geoc) /* Maybe redundant and never used. */ lpz.phi = atan(P->rone_es * tan(lpz.phi)); lpz.lam -= P->lam0; /* compute del lp.lam */ if (!P->over) lpz.lam = adjlon(lpz.lam); /* adjust del longitude */ - //Check for NULL pointer + /* Check for NULL pointer */ if (P->fwd3d != NULL) { xyz = (*P->fwd3d)(lpz, P); /* project */ @@ -35,7 +35,7 @@ pj_fwd3d(LPZ lpz, PJ *P) { else { xyz.x = P->fr_meter * (P->a * xyz.x + P->x0); xyz.y = P->fr_meter * (P->a * xyz.y + P->y0); - //z is not scaled since this handled by vto_meter outside + /* z is not scaled since this handled by vto_meter outside */ } } else diff --git a/src/pj_inv.c b/src/pj_inv.c index d77b4e56..711a0005 100644 --- a/src/pj_inv.c +++ b/src/pj_inv.c @@ -20,7 +20,7 @@ pj_inv(XY xy, PJ *P) { xy.x = (xy.x * P->to_meter - P->x0) * P->ra; /* descale and de-offset */ xy.y = (xy.y * P->to_meter - P->y0) * P->ra; - //Check for NULL pointer + /* Check for NULL pointer */ if (P->inv != NULL) { lp = (*P->inv)(xy, P); /* inverse project */ diff --git a/src/pj_inv3d.c b/src/pj_inv3d.c index de35e776..d06ed080 100644 --- a/src/pj_inv3d.c +++ b/src/pj_inv3d.c @@ -19,9 +19,9 @@ pj_inv3d(XYZ xyz, PJ *P) { xyz.x = (xyz.x * P->to_meter - P->x0) * P->ra; /* descale and de-offset */ xyz.y = (xyz.y * P->to_meter - P->y0) * P->ra; - //z is not scaled since that is handled by vto_meter before we get here - - //Check for NULL pointer + /* z is not scaled since that is handled by vto_meter before we get here */ + + /* Check for NULL pointer */ if (P->inv3d != NULL) { lpz = (*P->inv3d)(xyz, P); /* inverse project */ @@ -32,7 +32,7 @@ pj_inv3d(XYZ xyz, PJ *P) { if (!P->over) lpz.lam = adjlon(lpz.lam); /* adjust longitude to CM */ - //This maybe redundant and never user + /* This may be redundant and never used */ if (P->geoc && fabs(fabs(lpz.phi)-HALFPI) > EPS) lpz.phi = atan(P->one_es * tan(lpz.phi)); } diff --git a/src/pj_mutex.c b/src/pj_mutex.c index dc484c69..2f6533be 100644 --- a/src/pj_mutex.c +++ b/src/pj_mutex.c @@ -29,7 +29,7 @@ /* projects.h and windows.h conflict - avoid this! */ #if defined(MUTEX_pthread) && !defined(_XOPEN_SOURCE) -// For pthread_mutexattr_settype +/* For pthread_mutexattr_settype */ #define _XOPEN_SOURCE 500 #endif @@ -86,7 +86,7 @@ void pj_cleanup_lock() { } -#endif // def MUTEX_stub +#endif /* def MUTEX_stub */ /************************************************************************/ /* ==================================================================== */ @@ -154,7 +154,7 @@ void pj_cleanup_lock() { } -#endif // def MUTEX_pthread +#endif /* def MUTEX_pthread */ /************************************************************************/ /* ==================================================================== */ @@ -219,4 +219,4 @@ void pj_cleanup_lock() } } -#endif // def MUTEX_win32 +#endif /* def MUTEX_win32 */ diff --git a/src/pj_transform.c b/src/pj_transform.c index 32f14955..ce7b96a3 100644 --- a/src/pj_transform.c +++ b/src/pj_transform.c @@ -1,6 +1,6 @@ /****************************************************************************** * Project: PROJ.4 - * Purpose: Perform overall coordinate system to coordinate system + * Purpose: Perform overall coordinate system to coordinate system * transformations (pj_transform() function) including reprojection * and datum shifting. * Author: Frank Warmerdam, warmerdam@pobox.com @@ -33,7 +33,7 @@ #include "geocent.h" static int pj_adjust_axis( projCtx ctx, const char *axis, int denormalize_flag, - long point_count, int point_offset, + long point_count, int point_offset, double *x, double *y, double *z ); #ifndef SRS_WGS84_SEMIMAJOR @@ -52,23 +52,23 @@ static int pj_adjust_axis( projCtx ctx, const char *axis, int denormalize_flag, #define Rz_BF (defn->datum_params[5]) #define M_BF (defn->datum_params[6]) -/* -** This table is intended to indicate for any given error code in +/* +** This table is intended to indicate for any given error code in ** the range 0 to -44, 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. +** in which case the value is 1. ** ** At some point we might want to move this array in with the error message -** list or something, but while experimenting with it this should be fine. +** list or something, but while experimenting with it this should be fine. */ static const int transient_error[50] = { /* 0 1 2 3 4 5 6 7 8 9 */ - /* 0 to 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 10 to 19 */ 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, - /* 20 to 29 */ 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, - /* 30 to 39 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0 to 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 10 to 19 */ 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, + /* 20 to 29 */ 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, + /* 30 to 39 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 to 49 */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 }; /************************************************************************/ @@ -101,7 +101,7 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, { int err; - err = pj_adjust_axis( srcdefn->ctx, srcdefn->axis, + err = pj_adjust_axis( srcdefn->ctx, srcdefn->axis, 0, point_count, point_offset, x, y, z ); if( err != 0 ) return err; @@ -140,7 +140,7 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, } err = pj_geocentric_to_geodetic( srcdefn->a_orig, srcdefn->es_orig, - point_count, point_offset, + point_count, point_offset, x, y, z ); if( err != 0 ) return err; @@ -153,19 +153,19 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, else if( !srcdefn->is_latlong ) { - //Check first if projection is invertible. + /* Check first if projection is invertible. */ if( (srcdefn->inv3d == NULL) && (srcdefn->inv == NULL)) { pj_ctx_set_errno( pj_get_ctx(srcdefn), -17 ); - pj_log( pj_get_ctx(srcdefn), PJ_LOG_ERROR, + pj_log( pj_get_ctx(srcdefn), PJ_LOG_ERROR, "pj_transform(): source projection not invertable" ); return -17; } - //If invertible - First try inv3d if defined + /* If invertible - First try inv3d if defined */ if (srcdefn->inv3d != NULL) { - //Three dimensions must be defined + /* Three dimensions must be defined */ if ( z == NULL) { pj_ctx_set_errno( pj_get_ctx(srcdefn), PJD_ERR_GEOCENTRIC); @@ -187,9 +187,9 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, geodetic_loc = pj_inv3d(projected_loc, srcdefn); if( srcdefn->ctx->last_errno != 0 ) { - if( (srcdefn->ctx->last_errno != 33 /*EDOM*/ + if( (srcdefn->ctx->last_errno != 33 /*EDOM*/ && srcdefn->ctx->last_errno != 34 /*ERANGE*/ ) - && (srcdefn->ctx->last_errno > 0 + && (srcdefn->ctx->last_errno > 0 || srcdefn->ctx->last_errno < -44 || point_count == 1 || transient_error[-srcdefn->ctx->last_errno] == 0 ) ) return srcdefn->ctx->last_errno; @@ -210,7 +210,7 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, } else { - //Fallback to the original PROJ.4 API 2d inversion- inv + /* Fallback to the original PROJ.4 API 2d inversion - inv */ for( i = 0; i < point_count; i++ ) { XY projected_loc; @@ -225,9 +225,9 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, geodetic_loc = pj_inv( projected_loc, srcdefn ); if( srcdefn->ctx->last_errno != 0 ) { - if( (srcdefn->ctx->last_errno != 33 /*EDOM*/ + if( (srcdefn->ctx->last_errno != 33 /*EDOM*/ && srcdefn->ctx->last_errno != 34 /*ERANGE*/ ) - && (srcdefn->ctx->last_errno > 0 + && (srcdefn->ctx->last_errno > 0 || srcdefn->ctx->last_errno < -44 || point_count == 1 || transient_error[-srcdefn->ctx->last_errno] == 0 ) ) return srcdefn->ctx->last_errno; @@ -262,17 +262,17 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, /* -------------------------------------------------------------------- */ if( srcdefn->has_geoid_vgrids && z != NULL ) { - if( pj_apply_vgridshift( srcdefn, "sgeoidgrids", - &(srcdefn->vgridlist_geoid), + if( pj_apply_vgridshift( srcdefn, "sgeoidgrids", + &(srcdefn->vgridlist_geoid), &(srcdefn->vgridlist_geoid_count), 0, point_count, point_offset, x, y, z ) != 0 ) return pj_ctx_get_errno(srcdefn->ctx); } - + /* -------------------------------------------------------------------- */ /* Convert datums if needed, and possible. */ /* -------------------------------------------------------------------- */ - if( pj_datum_transform( srcdefn, dstdefn, point_count, point_offset, + if( pj_datum_transform( srcdefn, dstdefn, point_count, point_offset, x, y, z ) != 0 ) { if( srcdefn->ctx->last_errno != 0 ) @@ -287,13 +287,13 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, /* -------------------------------------------------------------------- */ if( dstdefn->has_geoid_vgrids && z != NULL ) { - if( pj_apply_vgridshift( dstdefn, "sgeoidgrids", - &(dstdefn->vgridlist_geoid), + if( pj_apply_vgridshift( dstdefn, "sgeoidgrids", + &(dstdefn->vgridlist_geoid), &(dstdefn->vgridlist_geoid_count), 1, point_count, point_offset, x, y, z ) != 0 ) return dstdefn->ctx->last_errno; } - + /* -------------------------------------------------------------------- */ /* But if they are staying lat long, adjust for the prime */ /* meridian if there is one in effect. */ @@ -348,7 +348,7 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, { XYZ projected_loc; LPZ geodetic_loc; - + geodetic_loc.u = x[point_offset*i]; geodetic_loc.v = y[point_offset*i]; geodetic_loc.w = z[point_offset*i]; @@ -359,9 +359,9 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, projected_loc = pj_fwd3d( geodetic_loc, dstdefn); if( dstdefn->ctx->last_errno != 0 ) { - if( (dstdefn->ctx->last_errno != 33 /*EDOM*/ + if( (dstdefn->ctx->last_errno != 33 /*EDOM*/ && dstdefn->ctx->last_errno != 34 /*ERANGE*/ ) - && (dstdefn->ctx->last_errno > 0 + && (dstdefn->ctx->last_errno > 0 || dstdefn->ctx->last_errno < -44 || point_count == 1 || transient_error[-dstdefn->ctx->last_errno] == 0 ) ) return dstdefn->ctx->last_errno; @@ -371,7 +371,7 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, projected_loc.v = HUGE_VAL; projected_loc.w = HUGE_VAL; } - } + } x[point_offset*i] = projected_loc.u; y[point_offset*i] = projected_loc.v; @@ -395,9 +395,9 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, projected_loc = pj_fwd( geodetic_loc, dstdefn ); if( dstdefn->ctx->last_errno != 0 ) { - if( (dstdefn->ctx->last_errno != 33 /*EDOM*/ + if( (dstdefn->ctx->last_errno != 33 /*EDOM*/ && dstdefn->ctx->last_errno != 34 /*ERANGE*/ ) - && (dstdefn->ctx->last_errno > 0 + && (dstdefn->ctx->last_errno > 0 || dstdefn->ctx->last_errno < -44 || point_count == 1 || transient_error[-dstdefn->ctx->last_errno] == 0 ) ) return dstdefn->ctx->last_errno; @@ -406,7 +406,7 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, projected_loc.u = HUGE_VAL; projected_loc.v = HUGE_VAL; } - } + } x[point_offset*i] = projected_loc.u; y[point_offset*i] = projected_loc.v; @@ -449,7 +449,7 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, { int err; - err = pj_adjust_axis( dstdefn->ctx, dstdefn->axis, + err = pj_adjust_axis( dstdefn->ctx, dstdefn->axis, 1, point_count, point_offset, x, y, z ); if( err != 0 ) return err; @@ -462,7 +462,7 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, /* pj_geodetic_to_geocentric() */ /************************************************************************/ -int pj_geodetic_to_geocentric( double a, double es, +int pj_geodetic_to_geocentric( double a, double es, long point_count, int point_offset, double *x, double *y, double *z ) @@ -489,7 +489,7 @@ int pj_geodetic_to_geocentric( double a, double es, if( x[io] == HUGE_VAL ) continue; - if( pj_Convert_Geodetic_To_Geocentric( &gi, y[io], x[io], z[io], + if( pj_Convert_Geodetic_To_Geocentric( &gi, y[io], x[io], z[io], x+io, y+io, z+io ) != 0 ) { ret_errno = -14; @@ -505,7 +505,7 @@ int pj_geodetic_to_geocentric( double a, double es, /* pj_geodetic_to_geocentric() */ /************************************************************************/ -int pj_geocentric_to_geodetic( double a, double es, +int pj_geocentric_to_geodetic( double a, double es, long point_count, int point_offset, double *x, double *y, double *z ) @@ -531,7 +531,7 @@ int pj_geocentric_to_geodetic( double a, double es, if( x[io] == HUGE_VAL ) continue; - pj_Convert_Geocentric_To_Geodetic( &gi, x[io], y[io], z[io], + pj_Convert_Geocentric_To_Geodetic( &gi, x[io], y[io], z[io], y+io, x+io, z+io ); } @@ -552,7 +552,7 @@ int pj_compare_datums( PJ *srcdefn, PJ *dstdefn ) { return 0; } - else if( srcdefn->a_orig != dstdefn->a_orig + else if( srcdefn->a_orig != dstdefn->a_orig || ABS(srcdefn->es_orig - dstdefn->es_orig) > 0.000000000050 ) { /* the tolerence for es is to ensure that GRS80 and WGS84 are @@ -588,7 +588,7 @@ int pj_compare_datums( PJ *srcdefn, PJ *dstdefn ) /* pj_geocentic_to_wgs84() */ /************************************************************************/ -int pj_geocentric_to_wgs84( PJ *defn, +int pj_geocentric_to_wgs84( PJ *defn, long point_count, int point_offset, double *x, double *y, double *z ) @@ -600,7 +600,7 @@ int pj_geocentric_to_wgs84( PJ *defn, for( i = 0; i < point_count; i++ ) { long io = i * point_offset; - + if( x[io] == HUGE_VAL ) continue; @@ -636,7 +636,7 @@ int pj_geocentric_to_wgs84( PJ *defn, /* pj_geocentic_from_wgs84() */ /************************************************************************/ -int pj_geocentric_from_wgs84( PJ *defn, +int pj_geocentric_from_wgs84( PJ *defn, long point_count, int point_offset, double *x, double *y, double *z ) @@ -651,7 +651,7 @@ int pj_geocentric_from_wgs84( PJ *defn, if( x[io] == HUGE_VAL ) continue; - + x[io] = x[io] - Dx_BF; y[io] = y[io] - Dy_BF; z[io] = z[io] - Dz_BF; @@ -688,7 +688,7 @@ int pj_geocentric_from_wgs84( PJ *defn, /* coordinates in radians in the destination datum. */ /************************************************************************/ -int pj_datum_transform( PJ *srcdefn, PJ *dstdefn, +int pj_datum_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset, double *x, double *y, double *z ) @@ -754,15 +754,15 @@ int pj_datum_transform( PJ *srcdefn, PJ *dstdefn, /* Do we need to go through geocentric coordinates? */ /* ==================================================================== */ if( src_es != dst_es || src_a != dst_a - || srcdefn->datum_type == PJD_3PARAM + || srcdefn->datum_type == PJD_3PARAM || srcdefn->datum_type == PJD_7PARAM - || dstdefn->datum_type == PJD_3PARAM + || dstdefn->datum_type == PJD_3PARAM || dstdefn->datum_type == PJD_7PARAM) { /* -------------------------------------------------------------------- */ /* Convert to geocentric coordinates. */ /* -------------------------------------------------------------------- */ - srcdefn->ctx->last_errno = + srcdefn->ctx->last_errno = pj_geodetic_to_geocentric( src_a, src_es, point_count, point_offset, x, y, z ); CHECK_RETURN(srcdefn); @@ -770,14 +770,14 @@ int pj_datum_transform( PJ *srcdefn, PJ *dstdefn, /* -------------------------------------------------------------------- */ /* Convert between datums. */ /* -------------------------------------------------------------------- */ - if( srcdefn->datum_type == PJD_3PARAM + if( srcdefn->datum_type == PJD_3PARAM || srcdefn->datum_type == PJD_7PARAM ) { pj_geocentric_to_wgs84( srcdefn, point_count, point_offset,x,y,z); CHECK_RETURN(srcdefn); } - if( dstdefn->datum_type == PJD_3PARAM + if( dstdefn->datum_type == PJD_3PARAM || dstdefn->datum_type == PJD_7PARAM ) { pj_geocentric_from_wgs84( dstdefn, point_count,point_offset,x,y,z); @@ -787,7 +787,7 @@ int pj_datum_transform( PJ *srcdefn, PJ *dstdefn, /* -------------------------------------------------------------------- */ /* Convert back to geodetic coordinates. */ /* -------------------------------------------------------------------- */ - dstdefn->ctx->last_errno = + dstdefn->ctx->last_errno = pj_geocentric_to_geodetic( dst_a, dst_es, point_count, point_offset, x, y, z ); CHECK_RETURN(dstdefn); @@ -814,9 +814,9 @@ int pj_datum_transform( PJ *srcdefn, PJ *dstdefn, /* Normalize or de-normalized the x/y/z axes. The normal form */ /* is "enu" (easting, northing, up). */ /************************************************************************/ -static int pj_adjust_axis( projCtx ctx, +static int pj_adjust_axis( projCtx ctx, const char *axis, int denormalize_flag, - long point_count, int point_offset, + long point_count, int point_offset, double *x, double *y, double *z ) { @@ -831,7 +831,7 @@ static int pj_adjust_axis( projCtx ctx, y_in = y[point_offset*i]; if( z ) z_in = z[point_offset*i]; - + for( i_axis = 0; i_axis < 3; i_axis++ ) { double value; @@ -842,7 +842,7 @@ static int pj_adjust_axis( projCtx ctx, value = y_in; else value = z_in; - + switch( axis[i_axis] ) { case 'e': @@ -873,7 +873,7 @@ static int pj_adjust_axis( projCtx ctx, y_in = y[point_offset*i]; if( z ) z_in = z[point_offset*i]; - + for( i_axis = 0; i_axis < 3; i_axis++ ) { double *target; @@ -887,7 +887,7 @@ static int pj_adjust_axis( projCtx ctx, target = y; else target = z; - + switch( axis[i_axis] ) { case 'e': @@ -909,7 +909,6 @@ static int pj_adjust_axis( projCtx ctx, } /* i_axis */ } /* i (point) */ } - + return 0; } - diff --git a/src/pj_utils.c b/src/pj_utils.c index f11081fc..203c637c 100644 --- a/src/pj_utils.c +++ b/src/pj_utils.c @@ -78,27 +78,27 @@ PJ *pj_latlong_from_proj( PJ *pj_in ) if( pj_param(pj_in->ctx, pj_in->params, "tdatum").i ) { got_datum = TRUE; - sprintf( defn+strlen(defn), " +datum=%s", + sprintf( defn+strlen(defn), " +datum=%s", pj_param(pj_in->ctx, pj_in->params,"sdatum").s ); } else if( pj_param(pj_in->ctx, pj_in->params, "tellps").i ) { - sprintf( defn+strlen(defn), " +ellps=%s", + sprintf( defn+strlen(defn), " +ellps=%s", pj_param(pj_in->ctx, pj_in->params,"sellps").s ); } else if( pj_param(pj_in->ctx,pj_in->params, "ta").i ) { - sprintf( defn+strlen(defn), " +a=%s", + sprintf( defn+strlen(defn), " +a=%s", pj_param(pj_in->ctx,pj_in->params,"sa").s ); - + if( pj_param(pj_in->ctx,pj_in->params, "tb").i ) - sprintf( defn+strlen(defn), " +b=%s", + sprintf( defn+strlen(defn), " +b=%s", pj_param(pj_in->ctx,pj_in->params,"sb").s ); else if( pj_param(pj_in->ctx,pj_in->params, "tes").i ) - sprintf( defn+strlen(defn), " +es=%s", + sprintf( defn+strlen(defn), " +es=%s", pj_param(pj_in->ctx,pj_in->params,"ses").s ); else if( pj_param(pj_in->ctx,pj_in->params, "tf").i ) - sprintf( defn+strlen(defn), " +f=%s", + sprintf( defn+strlen(defn), " +f=%s", pj_param(pj_in->ctx,pj_in->params,"sf").s ); else { @@ -121,17 +121,17 @@ PJ *pj_latlong_from_proj( PJ *pj_in ) if( !got_datum ) { if( pj_param(pj_in->ctx,pj_in->params, "ttowgs84").i ) - sprintf( defn+strlen(defn), " +towgs84=%s", + sprintf( defn+strlen(defn), " +towgs84=%s", pj_param(pj_in->ctx,pj_in->params,"stowgs84").s ); if( pj_param(pj_in->ctx,pj_in->params, "tnadgrids").i ) - sprintf( defn+strlen(defn), " +nadgrids=%s", + sprintf( defn+strlen(defn), " +nadgrids=%s", pj_param(pj_in->ctx,pj_in->params,"snadgrids").s ); } /* copy over some other information related to ellipsoid */ if( pj_param(pj_in->ctx,pj_in->params, "tR").i ) - sprintf( defn+strlen(defn), " +R=%s", + sprintf( defn+strlen(defn), " +R=%s", pj_param(pj_in->ctx,pj_in->params,"sR").s ); if( pj_param(pj_in->ctx,pj_in->params, "tR_A").i ) @@ -144,16 +144,16 @@ PJ *pj_latlong_from_proj( PJ *pj_in ) sprintf( defn+strlen(defn), " +R_a" ); if( pj_param(pj_in->ctx,pj_in->params, "tR_lat_a").i ) - sprintf( defn+strlen(defn), " +R_lat_a=%s", + sprintf( defn+strlen(defn), " +R_lat_a=%s", pj_param(pj_in->ctx,pj_in->params,"sR_lat_a").s ); if( pj_param(pj_in->ctx,pj_in->params, "tR_lat_g").i ) - sprintf( defn+strlen(defn), " +R_lat_g=%s", + sprintf( defn+strlen(defn), " +R_lat_g=%s", pj_param(pj_in->ctx,pj_in->params,"sR_lat_g").s ); /* copy over prime meridian */ if( pj_param(pj_in->ctx,pj_in->params, "tpm").i ) - sprintf( defn+strlen(defn), " +pm=%s", + sprintf( defn+strlen(defn), " +pm=%s", pj_param(pj_in->ctx,pj_in->params,"spm").s ); return pj_init_plus_ctx( pj_in->ctx, defn ); @@ -172,7 +172,7 @@ void pj_get_spheroid_defn(projPJ defn, double *major_axis, double *eccentricity_ { if ( major_axis ) *major_axis = defn->a; - + if ( eccentricity_squared ) *eccentricity_squared = defn->es; -}; +} diff --git a/src/warnings.pj b/src/warnings.pj new file mode 100644 index 00000000..4959fe1c --- /dev/null +++ b/src/warnings.pj @@ -0,0 +1,72 @@ +PJ_healpix.c: In function 'in_image': +PJ_healpix.c:187:13: warning: initializer element is not computable at load time [enabled by default] + {-1.0*PI + north_square*PI/2.0- EPS, PI/4.0 + EPS}, + ^ +PJ_healpix.c:187:13: warning: initializer element is not computable at load time [enabled by default] +PJ_healpix.c:188:13: warning: initializer element is not computable at load time [enabled by default] + {-1.0*PI + north_square*PI/2.0- EPS, 3*PI/4.0 + EPS}, + ^ +PJ_healpix.c:188:13: warning: initializer element is not computable at load time [enabled by default] +PJ_healpix.c:189:13: warning: initializer element is not computable at load time [enabled by default] + {-1.0*PI + (north_square + 1.0)*PI/2.0 + EPS, 3*PI/4.0 + EPS}, + ^ +PJ_healpix.c:189:13: warning: initializer element is not computable at load time [enabled by default] +PJ_healpix.c:190:13: warning: initializer element is not computable at load time [enabled by default] + {-1.0*PI + (north_square + 1.0)*PI/2.0 + EPS, PI/4.0 + EPS}, + ^ +PJ_healpix.c:190:13: warning: initializer element is not computable at load time [enabled by default] +PJ_healpix.c:193:13: warning: initializer element is not computable at load time [enabled by default] + {-1.0*PI + (south_square + 1.0)*PI/2.0 + EPS, -1.0*PI/4.0 - EPS}, + ^ +PJ_healpix.c:193:13: warning: initializer element is not computable at load time [enabled by default] +PJ_healpix.c:194:13: warning: initializer element is not computable at load time [enabled by default] + {-1.0*PI + (south_square + 1.0)*PI/2.0 + EPS, -3.0*PI/4.0 - EPS}, + ^ +PJ_healpix.c:194:13: warning: initializer element is not computable at load time [enabled by default] +PJ_healpix.c:195:13: warning: initializer element is not computable at load time [enabled by default] + {-1.0*PI + south_square*PI/2.0 - EPS, -3.0*PI/4.0 - EPS}, + ^ +PJ_healpix.c:195:13: warning: initializer element is not computable at load time [enabled by default] +PJ_healpix.c:196:13: warning: initializer element is not computable at load time [enabled by default] + {-1.0*PI + south_square*PI/2.0 - EPS, -1.0*PI/4.0 - EPS}, + ^ +PJ_healpix.c:196:13: warning: initializer element is not computable at load time [enabled by default] +PJ_healpix.c: In function 'combine_caps': +PJ_healpix.c:453:9: warning: initializer element is not computable at load time [enabled by default] + double c[2] = {capmap.x, capmap.y}; + ^ +PJ_healpix.c:453:9: warning: initializer element is not computable at load time [enabled by default] +PJ_healpix.c:479:9: warning: initializer element is not computable at load time [enabled by default] + double c[2] = {capmap.x, capmap.y}; + ^ +PJ_healpix.c:479:9: warning: initializer element is not computable at load time [enabled by default] +PJ_minimal.c: In function 'e_inverse': +PJ_minimal.c:158:22: error: 'PJ' has no member named 'opaq' + lp.phi = xy.y - P->opaq->b; + ^ +PJ_minimal.c: In function 's_inverse': +PJ_minimal.c:167:22: error: 'PJ' has no member named 'opaq' + lp.phi = xy.y - P->opaq->b; + ^ +PJ_minimal.c: In function 'freeup': +PJ_minimal.c:176:18: error: 'PJ' has no member named 'opaq' + pj_dealloc (P->opaq); + ^ +PJ_minimal.c: In function 'pj_projection_specific_setup_minimal': +PJ_minimal.c:184:13: error: 'PJ' has no member named 'opaq' + if (0==P->opaq) { + ^ +PJ_minimal.c:189:6: error: 'PJ' has no member named 'opaq' + P->opaq->a = 42.42; + ^ +PJ_minimal.c:190:6: error: 'PJ' has no member named 'opaq' + P->opaq->b = 42; + ^ +pj_mutex.c:89:8: warning: C++ style comments are not allowed in ISO C90 [enabled by default] + #endif // def MUTEX_stub + ^ +pj_mutex.c:89:8: warning: (this will be reported only once per input file) [enabled by default] +pj_strtod.c:35:25: fatal error: proj_config.h: No such file or directory + #include "proj_config.h" + ^ +compilation terminated. -- cgit v1.2.3 From 8adc8a8d3f19a64c147bd302c58c9c468bc39434 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 11 May 2016 11:46:40 +0200 Subject: P->e was inadvertently changed to Q->E by a too aggressive search/replace manoeuvre --- src/PJ_omerc.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/PJ_omerc.c b/src/PJ_omerc.c index e248b8cc..95960dfa 100644 --- a/src/PJ_omerc.c +++ b/src/PJ_omerc.c @@ -44,7 +44,7 @@ static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ double S, T, U, V, W, temp, u, v; if (fabs(fabs(lp.phi) - HALFPI) > EPS) { - W = Q->E / pow(pj_tsfn(lp.phi, sin(lp.phi), Q->E), Q->B); + W = Q->E / pow(pj_tsfn(lp.phi, sin(lp.phi), P->e), Q->B); temp = 1. / W; S = .5 * (W - temp); T = .5 * (W + temp); @@ -97,7 +97,7 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ lp.phi = Up < 0. ? -HALFPI : HALFPI; } else { lp.phi = Q->E / sqrt((1. + Up) / (1. - Up)); - if ((lp.phi = pj_phi2(P->ctx, pow(lp.phi, 1. / Q->B), Q->E)) == HUGE_VAL) + if ((lp.phi = pj_phi2(P->ctx, pow(lp.phi, 1. / Q->B), P->e)) == HUGE_VAL) I_ERROR; lp.lam = - Q->rB * atan2((Sp * Q->cosgam - Vp * Q->singam), cos(Q->BrA * u)); @@ -123,15 +123,15 @@ static void freeup (PJ *P) { PJ *PROJECTION(omerc) { - double con, com, cosph0, D, F, H, L, sinph0, p, J, gamma=0, - gamma0, lamc=0, lam1=0, lam2=0, phi1=0, phi2=0, alpha_c=0; - int alp, gam, no_off = 0; - struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; + double con, com, cosph0, D, F, H, L, sinph0, p, J, gamma=0, + gamma0, lamc=0, lam1=0, lam2=0, phi1=0, phi2=0, alpha_c=0; + int alp, gam, no_off = 0; + Q->no_rot = pj_param(P->ctx, P->params, "tno_rot").i; if ((alp = pj_param(P->ctx, P->params, "talpha").i) != 0) alpha_c = pj_param(P->ctx, P->params, "ralpha").f; @@ -178,7 +178,7 @@ PJ *PROJECTION(omerc) { F = -F; } Q->E = F += D; - Q->E *= pow(pj_tsfn(P->phi0, sinph0, Q->E), Q->B); + Q->E *= pow(pj_tsfn(P->phi0, sinph0, P->e), Q->B); } else { Q->B = 1. / com; Q->A = P->k0; @@ -198,8 +198,8 @@ PJ *PROJECTION(omerc) { P->lam0 = lamc - asin(.5 * (F - 1. / F) * tan(gamma0)) / Q->B; } else { - H = pow(pj_tsfn(phi1, sin(phi1), Q->E), Q->B); - L = pow(pj_tsfn(phi2, sin(phi2), Q->E), Q->B); + H = pow(pj_tsfn(phi1, sin(phi1), P->e), Q->B); + L = pow(pj_tsfn(phi2, sin(phi2), P->e), Q->B); F = Q->E / H; p = (L - H) / (L + H); J = Q->E * Q->E; -- cgit v1.2.3 From cb0f8f624f2ce61c7b801daf5ffe20c01b4d3783 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Wed, 11 May 2016 13:32:50 +0200 Subject: Yet another round of minor corrections A few args had gone missing in the test setups for lagrng, ob_tran, omerc, mod_ster. A mixed declarations and code case corrected in proj_rouss A missing include added to test228.c --- src/PJ_lagrng.c | 2 +- src/PJ_mod_ster.c | 8 +++++--- src/PJ_ob_tran.c | 2 +- src/PJ_omerc.c | 8 ++++---- src/proj_rouss.c | 4 ++-- src/test228.c | 6 ++++-- 6 files changed, 17 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/PJ_lagrng.c b/src/PJ_lagrng.c index 244cf043..776894d7 100644 --- a/src/PJ_lagrng.c +++ b/src/PJ_lagrng.c @@ -80,7 +80,7 @@ int pj_lagrng_selftest (void) { double tolerance_lp = 1e-10; double tolerance_xy = 1e-7; - char s_args[] = {"+proj=lagrng +a=6400000 +lat_1=0.5 +lat_2=2"}; + char s_args[] = {"+proj=lagrng +a=6400000 +W=2 +lat_1=0.5 +lat_2=2"}; LP fwd_in[] = { { 2, 1}, diff --git a/src/PJ_mod_ster.c b/src/PJ_mod_ster.c index 7de7c01b..4c217141 100644 --- a/src/PJ_mod_ster.c +++ b/src/PJ_mod_ster.c @@ -8,7 +8,7 @@ PROJ_HEAD(gs48, "Mod. Stererographics of 48 U.S.") "\n\tAzi(mod)"; PROJ_HEAD(alsk, "Mod. Stererographics of Alaska") "\n\tAzi(mod)"; PROJ_HEAD(gs50, "Mod. Stererographics of 50 U.S.") "\n\tAzi(mod)"; -#define EPSLN 1e-10 +#define EPSLN 1e-12 struct pj_opaque { COMPLEX *zcoeff; \ @@ -424,8 +424,10 @@ int pj_alsk_selftest (void) {return 0;} #else int pj_alsk_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; + + /* The standard test points are way outside the definition area bounds, hence we relax tolerances */ + double tolerance_lp = 1e-7; + double tolerance_xy = 1e-4; char e_args[] = {"+proj=alsk +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; char s_args[] = {"+proj=alsk +a=6400000 +lat_1=0.5 +lat_2=2"}; diff --git a/src/PJ_ob_tran.c b/src/PJ_ob_tran.c index 634bb552..e726b3b2 100644 --- a/src/PJ_ob_tran.c +++ b/src/PJ_ob_tran.c @@ -189,7 +189,7 @@ int pj_ob_tran_selftest (void) { double tolerance_lp = 1e-10; double tolerance_xy = 1e-7; - char s_args[] = {"+proj=ob_tran +o_proj=latlon +o_lon_p=20 +o_lat_p=20 +lon_0=180"}; + char s_args[] = {"+proj=ob_tran +a=6400000 +o_proj=latlon +o_lon_p=20 +o_lat_p=20 +lon_0=180"}; LP fwd_in[] = { { 2, 1}, diff --git a/src/PJ_omerc.c b/src/PJ_omerc.c index 95960dfa..2fe41426 100644 --- a/src/PJ_omerc.c +++ b/src/PJ_omerc.c @@ -123,15 +123,15 @@ static void freeup (PJ *P) { PJ *PROJECTION(omerc) { + double con, com, cosph0, D, F, H, L, sinph0, p, J, gamma=0, + gamma0, lamc=0, lam1=0, lam2=0, phi1=0, phi2=0, alpha_c=0; + int alp, gam, no_off = 0; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - double con, com, cosph0, D, F, H, L, sinph0, p, J, gamma=0, - gamma0, lamc=0, lam1=0, lam2=0, phi1=0, phi2=0, alpha_c=0; - int alp, gam, no_off = 0; - Q->no_rot = pj_param(P->ctx, P->params, "tno_rot").i; if ((alp = pj_param(P->ctx, P->params, "talpha").i) != 0) alpha_c = pj_param(P->ctx, P->params, "ralpha").f; diff --git a/src/proj_rouss.c b/src/proj_rouss.c index 35cc73c7..fc9918be 100644 --- a/src/proj_rouss.c +++ b/src/proj_rouss.c @@ -97,13 +97,13 @@ static void freeup (PJ *P) { PJ *PROJECTION(rouss) { + double N0, es2, t, t2, R_R0_2, R_R0_4; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; - double N0, es2, t, t2, R_R0_2, R_R0_4; - if (!((Q->en = proj_mdist_ini(P->es)))) E_ERROR_0; es2 = sin(P->phi0); diff --git a/src/test228.c b/src/test228.c index cdfc8650..a8e55c4c 100644 --- a/src/test228.c +++ b/src/test228.c @@ -1,4 +1,6 @@ #include +#include /* for printf declaration */ + #ifdef _WIN32 @@ -33,7 +35,7 @@ void* thread_main(void* unused) p_OSGB36_proj=pj_init_plus_ctx(p_proj_ctxt, "+proj=longlat +ellps=airy +datum=OSGB36 +nadgrids=OSTN02_NTv2.gsb " "+no_defs"); - + while(run) { double x, y; @@ -73,4 +75,4 @@ int main(int argc, char* argv[]) return 0; } -#endif /* _WIN32 */ \ No newline at end of file +#endif /* _WIN32 */ -- cgit v1.2.3 From ce770da81158f6177e841a725f3a6ad71433e7c8 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Wed, 11 May 2016 13:36:03 +0200 Subject: removing erroneously added file warnings.pj was recently added by mistake --- src/warnings.pj | 72 --------------------------------------------------------- 1 file changed, 72 deletions(-) delete mode 100644 src/warnings.pj (limited to 'src') diff --git a/src/warnings.pj b/src/warnings.pj deleted file mode 100644 index 4959fe1c..00000000 --- a/src/warnings.pj +++ /dev/null @@ -1,72 +0,0 @@ -PJ_healpix.c: In function 'in_image': -PJ_healpix.c:187:13: warning: initializer element is not computable at load time [enabled by default] - {-1.0*PI + north_square*PI/2.0- EPS, PI/4.0 + EPS}, - ^ -PJ_healpix.c:187:13: warning: initializer element is not computable at load time [enabled by default] -PJ_healpix.c:188:13: warning: initializer element is not computable at load time [enabled by default] - {-1.0*PI + north_square*PI/2.0- EPS, 3*PI/4.0 + EPS}, - ^ -PJ_healpix.c:188:13: warning: initializer element is not computable at load time [enabled by default] -PJ_healpix.c:189:13: warning: initializer element is not computable at load time [enabled by default] - {-1.0*PI + (north_square + 1.0)*PI/2.0 + EPS, 3*PI/4.0 + EPS}, - ^ -PJ_healpix.c:189:13: warning: initializer element is not computable at load time [enabled by default] -PJ_healpix.c:190:13: warning: initializer element is not computable at load time [enabled by default] - {-1.0*PI + (north_square + 1.0)*PI/2.0 + EPS, PI/4.0 + EPS}, - ^ -PJ_healpix.c:190:13: warning: initializer element is not computable at load time [enabled by default] -PJ_healpix.c:193:13: warning: initializer element is not computable at load time [enabled by default] - {-1.0*PI + (south_square + 1.0)*PI/2.0 + EPS, -1.0*PI/4.0 - EPS}, - ^ -PJ_healpix.c:193:13: warning: initializer element is not computable at load time [enabled by default] -PJ_healpix.c:194:13: warning: initializer element is not computable at load time [enabled by default] - {-1.0*PI + (south_square + 1.0)*PI/2.0 + EPS, -3.0*PI/4.0 - EPS}, - ^ -PJ_healpix.c:194:13: warning: initializer element is not computable at load time [enabled by default] -PJ_healpix.c:195:13: warning: initializer element is not computable at load time [enabled by default] - {-1.0*PI + south_square*PI/2.0 - EPS, -3.0*PI/4.0 - EPS}, - ^ -PJ_healpix.c:195:13: warning: initializer element is not computable at load time [enabled by default] -PJ_healpix.c:196:13: warning: initializer element is not computable at load time [enabled by default] - {-1.0*PI + south_square*PI/2.0 - EPS, -1.0*PI/4.0 - EPS}, - ^ -PJ_healpix.c:196:13: warning: initializer element is not computable at load time [enabled by default] -PJ_healpix.c: In function 'combine_caps': -PJ_healpix.c:453:9: warning: initializer element is not computable at load time [enabled by default] - double c[2] = {capmap.x, capmap.y}; - ^ -PJ_healpix.c:453:9: warning: initializer element is not computable at load time [enabled by default] -PJ_healpix.c:479:9: warning: initializer element is not computable at load time [enabled by default] - double c[2] = {capmap.x, capmap.y}; - ^ -PJ_healpix.c:479:9: warning: initializer element is not computable at load time [enabled by default] -PJ_minimal.c: In function 'e_inverse': -PJ_minimal.c:158:22: error: 'PJ' has no member named 'opaq' - lp.phi = xy.y - P->opaq->b; - ^ -PJ_minimal.c: In function 's_inverse': -PJ_minimal.c:167:22: error: 'PJ' has no member named 'opaq' - lp.phi = xy.y - P->opaq->b; - ^ -PJ_minimal.c: In function 'freeup': -PJ_minimal.c:176:18: error: 'PJ' has no member named 'opaq' - pj_dealloc (P->opaq); - ^ -PJ_minimal.c: In function 'pj_projection_specific_setup_minimal': -PJ_minimal.c:184:13: error: 'PJ' has no member named 'opaq' - if (0==P->opaq) { - ^ -PJ_minimal.c:189:6: error: 'PJ' has no member named 'opaq' - P->opaq->a = 42.42; - ^ -PJ_minimal.c:190:6: error: 'PJ' has no member named 'opaq' - P->opaq->b = 42; - ^ -pj_mutex.c:89:8: warning: C++ style comments are not allowed in ISO C90 [enabled by default] - #endif // def MUTEX_stub - ^ -pj_mutex.c:89:8: warning: (this will be reported only once per input file) [enabled by default] -pj_strtod.c:35:25: fatal error: proj_config.h: No such file or directory - #include "proj_config.h" - ^ -compilation terminated. -- cgit v1.2.3 From 1b17a573ffb07e9565e0df296e2a3a21bce8e971 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Wed, 18 May 2016 23:19:49 +0200 Subject: Refactoring and adding self test for the last two projections etmerc and utm completes the elimination of the ENTRYx style macros. --- src/PJ_aea.c | 25 --- src/PJ_etmerc.c | 484 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/proj_etmerc.c | 347 ++++++++++++++++++++++++++++---------- 3 files changed, 741 insertions(+), 115 deletions(-) create mode 100644 src/PJ_etmerc.c (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 5f7c6c92..0efef484 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -331,28 +331,3 @@ int pj_leac_selftest (void) { return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); } - - - - - - - - - - - -/*********************************************************************** - SELFTEST STUBS -************************************************************************ - -Selftest stubs temporarily placed here. - -To be removed as real selftest functions are added to the projection -source files - -***********************************************************************/ - -int pj_etmerc_selftest (void) {return 10000;} -int pj_utm_selftest (void) {return 10000;} -#endif diff --git a/src/PJ_etmerc.c b/src/PJ_etmerc.c new file mode 100644 index 00000000..d752bac9 --- /dev/null +++ b/src/PJ_etmerc.c @@ -0,0 +1,484 @@ +/* +** libproj -- library of cartographic projections +** +** Copyright (c) 2008 Gerald I. Evenden +*/ + +/* +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +/* The code in this file is largly based upon procedures: + * + * Written by: Knud Poder and Karsten Engsager + * + * Based on math from: R.Koenig and K.H. Weise, "Mathematische + * Grundlagen der hoeheren Geodaesie und Kartographie, + * Springer-Verlag, Berlin/Goettingen" Heidelberg, 1951. + * + * Modified and used here by permission of Reference Networks + * Division, Kort og Matrikelstyrelsen (KMS), Copenhagen, Denmark +*/ + + +#define PROJ_LIB__ +#define PJ_LIB__ + +#include + + +struct pj_opaque { + double Qn; /* Merid. quad., scaled to the projection */ \ + double Zb; /* Radius vector in polar coord. systems */ \ + double cgb[6]; /* Constants for Gauss -> Geo lat */ \ + double cbg[6]; /* Constants for Geo lat -> Gauss */ \ + double utg[6]; /* Constants for transv. merc. -> geo */ \ + double gtu[6]; /* Constants for geo -> transv. merc. */ +}; + +PROJ_HEAD(etmerc, "Extended Transverse Mercator") + "\n\tCyl, Sph\n\tlat_ts=(0)\nlat_0=(0)"; +PROJ_HEAD(utm, "Universal Transverse Mercator (UTM)") + "\n\tCyl, Sph\n\tzone= south"; + +#define PROJ_ETMERC_ORDER 6 + + +#ifdef _GNU_SOURCE + inline +#endif +static double log1py(double x) { /* Compute log(1+x) accurately */ + volatile double + y = 1 + x, + z = y - 1; + /* Here's the explanation for this magic: y = 1 + z, exactly, and z + * approx x, thus log(y)/z (which is nearly constant near z = 0) returns + * a good approximation to the true log(1 + x)/x. The multiplication x * + * (log(y)/z) introduces little additional error. */ + return z == 0 ? x : x * log(y) / z; +} + + +#ifdef _GNU_SOURCE + inline +#endif +static double asinhy(double x) { /* Compute asinh(x) accurately */ + double y = fabs(x); /* Enforce odd parity */ + y = log1py(y * (1 + y/(hypot(1.0, y) + 1))); + return x < 0 ? -y : y; +} + + +#ifdef _GNU_SOURCE + inline +#endif +static double gatg(double *p1, int len_p1, double B) { + double *p; + double h = 0, h1, h2 = 0, cos_2B; + + cos_2B = 2*cos(2*B); + for (p = p1 + len_p1, h1 = *--p; p - p1; h2 = h1, h1 = h) + h = -h2 + cos_2B*h1 + *--p; + return (B + h*sin(2*B)); +} + +/* Complex Clenshaw summation */ +#ifdef _GNU_SOURCE + inline +#endif +static double clenS(double *a, int size, double arg_r, double arg_i, double *R, double *I) { + double *p, r, i, hr, hr1, hr2, hi, hi1, hi2; + double sin_arg_r, cos_arg_r, sinh_arg_i, cosh_arg_i; + + /* arguments */ + p = a + size; +#ifdef _GNU_SOURCE + sincos(arg_r, &sin_arg_r, &cos_arg_r); +#else + sin_arg_r = sin(arg_r); + cos_arg_r = cos(arg_r); +#endif + sinh_arg_i = sinh(arg_i); + cosh_arg_i = cosh(arg_i); + r = 2*cos_arg_r*cosh_arg_i; + i = -2*sin_arg_r*sinh_arg_i; + + /* summation loop */ + for (hi1 = hr1 = hi = 0, hr = *--p; a - p;) { + hr2 = hr1; + hi2 = hi1; + hr1 = hr; + hi1 = hi; + hr = -hr2 + r*hr1 - i*hi1 + *--p; + hi = -hi2 + i*hr1 + r*hi1; + } + + r = sin_arg_r*cosh_arg_i; + i = cos_arg_r*sinh_arg_i; + *R = r*hr - i*hi; + *I = r*hi + i*hr; + return *R; +} + + +/* Real Clenshaw summation */ +static double clens(double *a, int size, double arg_r) { + double *p, r, hr, hr1, hr2, cos_arg_r; + + p = a + size; + cos_arg_r = cos(arg_r); + r = 2*cos_arg_r; + + /* summation loop */ + for (hr1 = 0, hr = *--p; a - p;) { + hr2 = hr1; + hr1 = hr; + hr = -hr2 + r*hr1 + *--p; + } + return sin (arg_r)*hr; +} + + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double sin_Cn, cos_Cn, cos_Ce, sin_Ce, dCn, dCe; + double Cn = lp.phi, Ce = lp.lam; + + /* ell. LAT, LNG -> Gaussian LAT, LNG */ + Cn = gatg (Q->cbg, PROJ_ETMERC_ORDER, Cn); + /* Gaussian LAT, LNG -> compl. sph. LAT */ +#ifdef _GNU_SOURCE + sincos (Cn, &sin_Cn, &cos_Cn); + sincos (Ce, &sin_Ce, &cos_Ce); +#else + sin_Cn = sin (Cn); + cos_Cn = cos (Cn); + sin_Ce = sin (Ce); + cos_Ce = cos (Ce); +#endif + + Cn = atan2 (sin_Cn, cos_Ce*cos_Cn); + Ce = atan2 (sin_Ce*cos_Cn, hypot (sin_Cn, cos_Cn*cos_Ce)); + + /* compl. sph. N, E -> ell. norm. N, E */ + Ce = asinhy ( tan (Ce) ); /* Replaces: Ce = log(tan(FORTPI + Ce*0.5)); */ + Cn += clenS (Q->gtu, PROJ_ETMERC_ORDER, 2*Cn, 2*Ce, &dCn, &dCe); + Ce += dCe; + if (fabs (Ce) <= 2.623395162778) { + xy.y = Q->Qn * Cn + Q->Zb; /* Northing */ + xy.x = Q->Qn * Ce; /* Easting */ + } else + xy.x = xy.y = HUGE_VAL; + return xy; +} + + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; + double sin_Cn, cos_Cn, cos_Ce, sin_Ce, dCn, dCe; + double Cn = xy.y, Ce = xy.x; + + /* normalize N, E */ + Cn = (Cn - Q->Zb)/Q->Qn; + Ce = Ce/Q->Qn; + + if (fabs(Ce) <= 2.623395162778) { /* 150 degrees */ + /* norm. N, E -> compl. sph. LAT, LNG */ + Cn += clenS(Q->utg, PROJ_ETMERC_ORDER, 2*Cn, 2*Ce, &dCn, &dCe); + Ce += dCe; + Ce = atan (sinh (Ce)); /* Replaces: Ce = 2*(atan(exp(Ce)) - FORTPI); */ + /* compl. sph. LAT -> Gaussian LAT, LNG */ +#ifdef _GNU_SOURCE + sincos (Cn, &sin_Cn, &cos_Cn); + sincos (Ce, &sin_Ce, &cos_Ce); +#else + sin_Cn = sin (Cn); + cos_Cn = cos (Cn); + sin_Ce = sin (Ce); + cos_Ce = cos (Ce); +#endif + Ce = atan2 (sin_Ce, cos_Ce*cos_Cn); + Cn = atan2 (sin_Cn*cos_Ce, hypot (sin_Ce, cos_Ce*cos_Cn)); + /* Gaussian LAT, LNG -> ell. LAT, LNG */ + lp.phi = gatg (Q->cgb, PROJ_ETMERC_ORDER, Cn); + lp.lam = Ce; + } + else + lp.phi = lp.lam = HUGE_VAL; + return lp; +} + + + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + +static PJ *setup(PJ *P) { /* general initialization */ + double f, n, np, Z; + struct pj_opaque *Q = P->opaque; + + if (P->es <= 0) + E_ERROR(-34); + + /* flattening */ + f = P->es / (1 + sqrt (1 - P->es)); /* Replaces: f = 1 - sqrt(1-P->es); */ + + /* third flattening */ + np = n = f/(2 - f); + + /* COEF. OF TRIG SERIES GEO <-> GAUSS */ + /* cgb := Gaussian -> Geodetic, KW p190 - 191 (61) - (62) */ + /* cbg := Geodetic -> Gaussian, KW p186 - 187 (51) - (52) */ + /* PROJ_ETMERC_ORDER = 6th degree : Engsager and Poder: ICC2007 */ + + Q->cgb[0] = n*( 2 + n*(-2/3.0 + n*(-2 + n*(116/45.0 + n*(26/45.0 + + n*(-2854/675.0 )))))); + Q->cbg[0] = n*(-2 + n*( 2/3.0 + n*( 4/3.0 + n*(-82/45.0 + n*(32/45.0 + + n*( 4642/4725.0)))))); + np *= n; + Q->cgb[1] = np*(7/3.0 + n*( -8/5.0 + n*(-227/45.0 + n*(2704/315.0 + + n*( 2323/945.0))))); + Q->cbg[1] = np*(5/3.0 + n*(-16/15.0 + n*( -13/9.0 + n*( 904/315.0 + + n*(-1522/945.0))))); + np *= n; + /* n^5 coeff corrected from 1262/105 -> -1262/105 */ + Q->cgb[2] = np*( 56/15.0 + n*(-136/35.0 + n*(-1262/105.0 + + n*( 73814/2835.0)))); + Q->cbg[2] = np*(-26/15.0 + n*( 34/21.0 + n*( 8/5.0 + + n*(-12686/2835.0)))); + np *= n; + /* n^5 coeff corrected from 322/35 -> 332/35 */ + Q->cgb[3] = np*(4279/630.0 + n*(-332/35.0 + n*(-399572/14175.0))); + Q->cbg[3] = np*(1237/630.0 + n*( -12/5.0 + n*( -24832/14175.0))); + np *= n; + Q->cgb[4] = np*(4174/315.0 + n*(-144838/6237.0 )); + Q->cbg[4] = np*(-734/315.0 + n*( 109598/31185.0)); + np *= n; + Q->cgb[5] = np*(601676/22275.0 ); + Q->cbg[5] = np*(444337/155925.0); + + /* Constants of the projections */ + /* Transverse Mercator (UTM, ITM, etc) */ + np = n*n; + /* Norm. mer. quad, K&W p.50 (96), p.19 (38b), p.5 (2) */ + Q->Qn = P->k0/(1 + n) * (1 + np*(1/4.0 + np*(1/64.0 + np/256.0))); + /* coef of trig series */ + /* utg := ell. N, E -> sph. N, E, KW p194 (65) */ + /* gtu := sph. N, E -> ell. N, E, KW p196 (69) */ + Q->utg[0] = n*(-0.5 + n*( 2/3.0 + n*(-37/96.0 + n*( 1/360.0 + + n*( 81/512.0 + n*(-96199/604800.0)))))); + Q->gtu[0] = n*( 0.5 + n*(-2/3.0 + n*( 5/16.0 + n*(41/180.0 + + n*(-127/288.0 + n*( 7891/37800.0 )))))); + Q->utg[1] = np*(-1/48.0 + n*(-1/15.0 + n*(437/1440.0 + n*(-46/105.0 + + n*( 1118711/3870720.0))))); + Q->gtu[1] = np*(13/48.0 + n*(-3/5.0 + n*(557/1440.0 + n*(281/630.0 + + n*(-1983433/1935360.0))))); + np *= n; + Q->utg[2] = np*(-17/480.0 + n*( 37/840.0 + n*( 209/4480.0 + + n*( -5569/90720.0 )))); + Q->gtu[2] = np*( 61/240.0 + n*(-103/140.0 + n*(15061/26880.0 + + n*(167603/181440.0)))); + np *= n; + Q->utg[3] = np*(-4397/161280.0 + n*( 11/504.0 + n*( 830251/7257600.0))); + Q->gtu[3] = np*(49561/161280.0 + n*(-179/168.0 + n*(6601661/7257600.0))); + np *= n; + Q->utg[4] = np*(-4583/161280.0 + n*( 108847/3991680.0)); + Q->gtu[4] = np*(34729/80640.0 + n*(-3418889/1995840.0)); + np *= n; + Q->utg[5] = np*(-20648693/638668800.0); + Q->gtu[5] = np*(212378941/319334400.0); + + /* Gaussian latitude value of the origin latitude */ + Z = gatg (Q->cbg, PROJ_ETMERC_ORDER, P->phi0); + + /* Origin northing minus true northing at the origin latitude */ + /* i.e. true northing = N - P->Zb */ + Q->Zb = - Q->Qn*(Z + clens(Q->gtu, PROJ_ETMERC_ORDER, 2*Z)); + P->inv = e_inverse; + P->fwd = e_forward; + return P; +} + + + +PJ *PROJECTION(etmerc) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_etmerc; + return setup (P); +} + + + + + + + +#ifdef PJ_OMIT_SELFTEST +int pj_etmerc_selftest (void) {return 0;} +#else + +int pj_etmerc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=etmerc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +zone=30"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {222650.79679758562, 110642.22941193319}, + {222650.79679758562, -110642.22941193319}, + {-222650.79679758562, 110642.22941193319}, + {-222650.79679758562, -110642.22941193319}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0017966305681649398, 0.00090436947663183873}, + {0.0017966305681649398, -0.00090436947663183873}, + {-0.0017966305681649398, 0.00090436947663183873}, + {-0.0017966305681649398, -0.00090436947663183873}, + }; + + return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); +} +#endif + + + + + + + + + + + + +/* utm uses etmerc for the underlying projection */ + + +PJ *PROJECTION(utm) { + int zone; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_utm; + + if (!P->es) + E_ERROR(-34); + P->y0 = pj_param (P->ctx, P->params, "bsouth").i ? 10000000. : 0.; + P->x0 = 500000.; + if (pj_param (P->ctx, P->params, "tzone").i) /* zone input ? */ + if ((zone = pj_param(P->ctx, P->params, "izone").i) > 0 && zone <= 60) + --zone; + else + E_ERROR(-35) + else /* nearest central meridian input */ + if ((zone = (int)(floor ((adjlon (P->lam0) + PI) * 30. / PI))) < 0) + zone = 0; + else if (zone >= 60) + zone = 59; + P->lam0 = (zone + .5) * PI / 30. - PI; + P->k0 = 0.9996; + P->phi0 = 0.; + + return setup (P); +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_utm_selftest (void) {return 0;} +#else + +int pj_utm_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=utm +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +zone=30"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {1057002.4054912981, 110955.14117594929}, + {1057002.4054912981, -110955.14117594929}, + {611263.81227890507, 110547.10569680421}, + {611263.81227890507, -110547.10569680421}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {-7.4869520833902357, 0.00090193980983462605}, + {-7.4869520833902357, -0.00090193980983462605}, + {-7.4905356820622613, 0.00090193535121489081}, + {-7.4905356820622613, -0.00090193535121489081}, + }; + + return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); +} +#endif + + + diff --git a/src/proj_etmerc.c b/src/proj_etmerc.c index 3ef0903f..0149303e 100644 --- a/src/proj_etmerc.c +++ b/src/proj_etmerc.c @@ -35,20 +35,24 @@ * * Modified and used here by permission of Reference Networks * Division, Kort og Matrikelstyrelsen (KMS), Copenhagen, Denmark + * */ -#define PROJ_PARMS__ \ + +#define PROJ_LIB__ +#define PJ_LIB__ + +#include + + +struct pj_opaque { double Qn; /* Merid. quad., scaled to the projection */ \ double Zb; /* Radius vector in polar coord. systems */ \ double cgb[6]; /* Constants for Gauss -> Geo lat */ \ double cbg[6]; /* Constants for Geo lat -> Gauss */ \ double utg[6]; /* Constants for transv. merc. -> geo */ \ double gtu[6]; /* Constants for geo -> transv. merc. */ - -#define PROJ_LIB__ -#define PJ_LIB__ - -#include +}; PROJ_HEAD(etmerc, "Extended Transverse Mercator") "\n\tCyl, Sph\n\tlat_ts=(0)\nlat_0=(0)"; @@ -57,11 +61,11 @@ PROJ_HEAD(utm, "Universal Transverse Mercator (UTM)") #define PROJ_ETMERC_ORDER 6 + #ifdef _GNU_SOURCE inline #endif - static double -log1py(double x) { /* Compute log(1+x) accurately */ +static double log1py(double x) { /* Compute log(1+x) accurately */ volatile double y = 1 + x, z = y - 1; @@ -72,21 +76,21 @@ log1py(double x) { /* Compute log(1+x) accurately */ return z == 0 ? x : x * log(y) / z; } + #ifdef _GNU_SOURCE inline #endif - static double -asinhy(double x) { /* Compute asinh(x) accurately */ +static double asinhy(double x) { /* Compute asinh(x) accurately */ double y = fabs(x); /* Enforce odd parity */ y = log1py(y * (1 + y/(hypot(1.0, y) + 1))); return x < 0 ? -y : y; } + #ifdef _GNU_SOURCE inline #endif - static double -gatg(double *p1, int len_p1, double B) { +static double gatg(double *p1, int len_p1, double B) { double *p; double h = 0, h1, h2 = 0, cos_2B; @@ -96,11 +100,11 @@ gatg(double *p1, int len_p1, double B) { return (B + h*sin(2*B)); } +/* Complex Clenshaw summation */ #ifdef _GNU_SOURCE inline #endif - static double -clenS(double *a, int size, double arg_r, double arg_i, double *R, double *I) { +static double clenS(double *a, int size, double arg_r, double arg_i, double *R, double *I) { double *p, r, i, hr, hr1, hr2, hi, hi1, hi2; double sin_arg_r, cos_arg_r, sinh_arg_i, cosh_arg_i; @@ -116,6 +120,7 @@ clenS(double *a, int size, double arg_r, double arg_i, double *R, double *I) { cosh_arg_i = cosh(arg_i); r = 2*cos_arg_r*cosh_arg_i; i = -2*sin_arg_r*sinh_arg_i; + /* summation loop */ for (hi1 = hr1 = hi = 0, hr = *--p; a - p;) { hr2 = hr1; @@ -125,100 +130,132 @@ clenS(double *a, int size, double arg_r, double arg_i, double *R, double *I) { hr = -hr2 + r*hr1 - i*hi1 + *--p; hi = -hi2 + i*hr1 + r*hi1; } + r = sin_arg_r*cosh_arg_i; i = cos_arg_r*sinh_arg_i; *R = r*hr - i*hi; *I = r*hi + i*hr; - return(*R); + return *R; } - static double -clens(double *a, int size, double arg_r) { + + +/* Real Clenshaw summation */ +static double clens(double *a, int size, double arg_r) { double *p, r, hr, hr1, hr2, cos_arg_r; p = a + size; cos_arg_r = cos(arg_r); r = 2*cos_arg_r; + /* summation loop */ for (hr1 = 0, hr = *--p; a - p;) { hr2 = hr1; hr1 = hr; hr = -hr2 + r*hr1 + *--p; } - return(sin(arg_r)*hr); + return sin (arg_r)*hr; } -FORWARD(e_forward); /* ellipsoid */ + + +static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ + XY xy = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double sin_Cn, cos_Cn, cos_Ce, sin_Ce, dCn, dCe; double Cn = lp.phi, Ce = lp.lam; /* ell. LAT, LNG -> Gaussian LAT, LNG */ - Cn = gatg(P->cbg, PROJ_ETMERC_ORDER, Cn); + Cn = gatg (Q->cbg, PROJ_ETMERC_ORDER, Cn); /* Gaussian LAT, LNG -> compl. sph. LAT */ #ifdef _GNU_SOURCE - sincos(Cn, &sin_Cn, &cos_Cn); - sincos(Ce, &sin_Ce, &cos_Ce); + sincos (Cn, &sin_Cn, &cos_Cn); + sincos (Ce, &sin_Ce, &cos_Ce); #else - sin_Cn = sin(Cn); - cos_Cn = cos(Cn); - sin_Ce = sin(Ce); - cos_Ce = cos(Ce); + sin_Cn = sin (Cn); + cos_Cn = cos (Cn); + sin_Ce = sin (Ce); + cos_Ce = cos (Ce); #endif - Cn = atan2(sin_Cn, cos_Ce*cos_Cn); - Ce = atan2(sin_Ce*cos_Cn, hypot(sin_Cn, cos_Cn*cos_Ce)); + Cn = atan2 (sin_Cn, cos_Ce*cos_Cn); + Ce = atan2 (sin_Ce*cos_Cn, hypot (sin_Cn, cos_Cn*cos_Ce)); + /* compl. sph. N, E -> ell. norm. N, E */ - Ce = asinhy(tan(Ce)); /* Replaces: Ce = log(tan(FORTPI + Ce*0.5)); */ - Cn += clenS(P->gtu, PROJ_ETMERC_ORDER, 2*Cn, 2*Ce, &dCn, &dCe); + Ce = asinhy ( tan (Ce) ); /* Replaces: Ce = log(tan(FORTPI + Ce*0.5)); */ + Cn += clenS (Q->gtu, PROJ_ETMERC_ORDER, 2*Cn, 2*Ce, &dCn, &dCe); Ce += dCe; - if (fabs(Ce) <= 2.623395162778) { - xy.y = P->Qn * Cn + P->Zb; /* Northing */ - xy.x = P->Qn * Ce; /* Easting */ + if (fabs (Ce) <= 2.623395162778) { + xy.y = Q->Qn * Cn + Q->Zb; /* Northing */ + xy.x = Q->Qn * Ce; /* Easting */ } else xy.x = xy.y = HUGE_VAL; - return (xy); + return xy; } -INVERSE(e_inverse); /* ellipsoid */ + + +static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ + LP lp = {0.0,0.0}; + struct pj_opaque *Q = P->opaque; double sin_Cn, cos_Cn, cos_Ce, sin_Ce, dCn, dCe; double Cn = xy.y, Ce = xy.x; /* normalize N, E */ - Cn = (Cn - P->Zb)/P->Qn; - Ce = Ce/P->Qn; + Cn = (Cn - Q->Zb)/Q->Qn; + Ce = Ce/Q->Qn; + if (fabs(Ce) <= 2.623395162778) { /* 150 degrees */ - /* norm. N, E -> compl. sph. LAT, LNG */ - Cn += clenS(P->utg, PROJ_ETMERC_ORDER, 2*Cn, 2*Ce, &dCn, &dCe); + /* norm. N, E -> compl. sph. LAT, LNG */ + Cn += clenS(Q->utg, PROJ_ETMERC_ORDER, 2*Cn, 2*Ce, &dCn, &dCe); Ce += dCe; - Ce = atan(sinh(Ce)); /* Replaces: Ce = 2*(atan(exp(Ce)) - FORTPI); */ + Ce = atan (sinh (Ce)); /* Replaces: Ce = 2*(atan(exp(Ce)) - FORTPI); */ /* compl. sph. LAT -> Gaussian LAT, LNG */ #ifdef _GNU_SOURCE - sincos(Cn, &sin_Cn, &cos_Cn); - sincos(Ce, &sin_Ce, &cos_Ce); + sincos (Cn, &sin_Cn, &cos_Cn); + sincos (Ce, &sin_Ce, &cos_Ce); #else - sin_Cn = sin(Cn); - cos_Cn = cos(Cn); - sin_Ce = sin(Ce); - cos_Ce = cos(Ce); + sin_Cn = sin (Cn); + cos_Cn = cos (Cn); + sin_Ce = sin (Ce); + cos_Ce = cos (Ce); #endif - Ce = atan2(sin_Ce, cos_Ce*cos_Cn); - Cn = atan2(sin_Cn*cos_Ce, hypot(sin_Ce, cos_Ce*cos_Cn)); + Ce = atan2 (sin_Ce, cos_Ce*cos_Cn); + Cn = atan2 (sin_Cn*cos_Ce, hypot (sin_Ce, cos_Ce*cos_Cn)); /* Gaussian LAT, LNG -> ell. LAT, LNG */ - lp.phi = gatg(P->cgb, PROJ_ETMERC_ORDER, Cn); + lp.phi = gatg (Q->cgb, PROJ_ETMERC_ORDER, Cn); lp.lam = Ce; } else lp.phi = lp.lam = HUGE_VAL; - return (lp); + return lp; } -FREEUP; if (P) free(P); } - static PJ * -setup(PJ *P) { /* general initialization */ + +static void *freeup_new (PJ *P) { /* Destructor */ + if (0==P) + return 0; + if (0==P->opaque) + return pj_dealloc (P); + pj_dealloc (P->opaque); + return pj_dealloc(P); +} + +static void freeup (PJ *P) { + freeup_new (P); + return; +} + +static PJ *setup(PJ *P) { /* general initialization */ double f, n, np, Z; + struct pj_opaque *Q = P->opaque; + + if (P->es <= 0) + E_ERROR(-34); + + /* flattening */ + f = P->es / (1 + sqrt (1 - P->es)); /* Replaces: f = 1 - sqrt(1-P->es); */ - if (P->es <= 0) E_ERROR(-34); - f = P->es / (1 + sqrt(1 - P->es)); /* Replaces: f = 1 - sqrt(1-P->es); */ /* third flattening */ np = n = f/(2 - f); @@ -226,93 +263,223 @@ setup(PJ *P) { /* general initialization */ /* cgb := Gaussian -> Geodetic, KW p190 - 191 (61) - (62) */ /* cbg := Geodetic -> Gaussian, KW p186 - 187 (51) - (52) */ /* PROJ_ETMERC_ORDER = 6th degree : Engsager and Poder: ICC2007 */ - P->cgb[0] = n*( 2 + n*(-2/3.0 + n*(-2 + n*(116/45.0 + n*(26/45.0 + + + Q->cgb[0] = n*( 2 + n*(-2/3.0 + n*(-2 + n*(116/45.0 + n*(26/45.0 + n*(-2854/675.0 )))))); - P->cbg[0] = n*(-2 + n*( 2/3.0 + n*( 4/3.0 + n*(-82/45.0 + n*(32/45.0 + + Q->cbg[0] = n*(-2 + n*( 2/3.0 + n*( 4/3.0 + n*(-82/45.0 + n*(32/45.0 + n*( 4642/4725.0)))))); np *= n; - P->cgb[1] = np*(7/3.0 + n*( -8/5.0 + n*(-227/45.0 + n*(2704/315.0 + + Q->cgb[1] = np*(7/3.0 + n*( -8/5.0 + n*(-227/45.0 + n*(2704/315.0 + n*( 2323/945.0))))); - P->cbg[1] = np*(5/3.0 + n*(-16/15.0 + n*( -13/9.0 + n*( 904/315.0 + + Q->cbg[1] = np*(5/3.0 + n*(-16/15.0 + n*( -13/9.0 + n*( 904/315.0 + n*(-1522/945.0))))); np *= n; /* n^5 coeff corrected from 1262/105 -> -1262/105 */ - P->cgb[2] = np*( 56/15.0 + n*(-136/35.0 + n*(-1262/105.0 + + Q->cgb[2] = np*( 56/15.0 + n*(-136/35.0 + n*(-1262/105.0 + n*( 73814/2835.0)))); - P->cbg[2] = np*(-26/15.0 + n*( 34/21.0 + n*( 8/5.0 + + Q->cbg[2] = np*(-26/15.0 + n*( 34/21.0 + n*( 8/5.0 + n*(-12686/2835.0)))); np *= n; /* n^5 coeff corrected from 322/35 -> 332/35 */ - P->cgb[3] = np*(4279/630.0 + n*(-332/35.0 + n*(-399572/14175.0))); - P->cbg[3] = np*(1237/630.0 + n*( -12/5.0 + n*( -24832/14175.0))); + Q->cgb[3] = np*(4279/630.0 + n*(-332/35.0 + n*(-399572/14175.0))); + Q->cbg[3] = np*(1237/630.0 + n*( -12/5.0 + n*( -24832/14175.0))); np *= n; - P->cgb[4] = np*(4174/315.0 + n*(-144838/6237.0 )); - P->cbg[4] = np*(-734/315.0 + n*( 109598/31185.0)); + Q->cgb[4] = np*(4174/315.0 + n*(-144838/6237.0 )); + Q->cbg[4] = np*(-734/315.0 + n*( 109598/31185.0)); np *= n; - P->cgb[5] = np*(601676/22275.0 ); - P->cbg[5] = np*(444337/155925.0); + Q->cgb[5] = np*(601676/22275.0 ); + Q->cbg[5] = np*(444337/155925.0); /* Constants of the projections */ /* Transverse Mercator (UTM, ITM, etc) */ np = n*n; /* Norm. mer. quad, K&W p.50 (96), p.19 (38b), p.5 (2) */ - P->Qn = P->k0/(1 + n) * (1 + np*(1/4.0 + np*(1/64.0 + np/256.0))); + Q->Qn = P->k0/(1 + n) * (1 + np*(1/4.0 + np*(1/64.0 + np/256.0))); /* coef of trig series */ /* utg := ell. N, E -> sph. N, E, KW p194 (65) */ /* gtu := sph. N, E -> ell. N, E, KW p196 (69) */ - P->utg[0] = n*(-0.5 + n*( 2/3.0 + n*(-37/96.0 + n*( 1/360.0 + + Q->utg[0] = n*(-0.5 + n*( 2/3.0 + n*(-37/96.0 + n*( 1/360.0 + n*( 81/512.0 + n*(-96199/604800.0)))))); - P->gtu[0] = n*( 0.5 + n*(-2/3.0 + n*( 5/16.0 + n*(41/180.0 + + Q->gtu[0] = n*( 0.5 + n*(-2/3.0 + n*( 5/16.0 + n*(41/180.0 + n*(-127/288.0 + n*( 7891/37800.0 )))))); - P->utg[1] = np*(-1/48.0 + n*(-1/15.0 + n*(437/1440.0 + n*(-46/105.0 + + Q->utg[1] = np*(-1/48.0 + n*(-1/15.0 + n*(437/1440.0 + n*(-46/105.0 + n*( 1118711/3870720.0))))); - P->gtu[1] = np*(13/48.0 + n*(-3/5.0 + n*(557/1440.0 + n*(281/630.0 + + Q->gtu[1] = np*(13/48.0 + n*(-3/5.0 + n*(557/1440.0 + n*(281/630.0 + n*(-1983433/1935360.0))))); np *= n; - P->utg[2] = np*(-17/480.0 + n*( 37/840.0 + n*( 209/4480.0 + + Q->utg[2] = np*(-17/480.0 + n*( 37/840.0 + n*( 209/4480.0 + n*( -5569/90720.0 )))); - P->gtu[2] = np*( 61/240.0 + n*(-103/140.0 + n*(15061/26880.0 + + Q->gtu[2] = np*( 61/240.0 + n*(-103/140.0 + n*(15061/26880.0 + n*(167603/181440.0)))); np *= n; - P->utg[3] = np*(-4397/161280.0 + n*( 11/504.0 + n*( 830251/7257600.0))); - P->gtu[3] = np*(49561/161280.0 + n*(-179/168.0 + n*(6601661/7257600.0))); + Q->utg[3] = np*(-4397/161280.0 + n*( 11/504.0 + n*( 830251/7257600.0))); + Q->gtu[3] = np*(49561/161280.0 + n*(-179/168.0 + n*(6601661/7257600.0))); np *= n; - P->utg[4] = np*(-4583/161280.0 + n*( 108847/3991680.0)); - P->gtu[4] = np*(34729/80640.0 + n*(-3418889/1995840.0)); + Q->utg[4] = np*(-4583/161280.0 + n*( 108847/3991680.0)); + Q->gtu[4] = np*(34729/80640.0 + n*(-3418889/1995840.0)); np *= n; - P->utg[5] = np*(-20648693/638668800.0); - P->gtu[5] = np*(212378941/319334400.0); + Q->utg[5] = np*(-20648693/638668800.0); + Q->gtu[5] = np*(212378941/319334400.0); + /* Gaussian latitude value of the origin latitude */ - Z = gatg(P->cbg, PROJ_ETMERC_ORDER, P->phi0); + Z = gatg (Q->cbg, PROJ_ETMERC_ORDER, P->phi0); + /* Origin northing minus true northing at the origin latitude */ /* i.e. true northing = N - P->Zb */ - P->Zb = - P->Qn*(Z + clens(P->gtu, PROJ_ETMERC_ORDER, 2*Z)); + Q->Zb = - Q->Qn*(Z + clens(Q->gtu, PROJ_ETMERC_ORDER, 2*Z)); P->inv = e_inverse; P->fwd = e_forward; return P; } -ENTRY0(etmerc) -ENDENTRY(setup(P)) + + +PJ *PROJECTION(etmerc) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_etmerc; + return setup (P); +} + + + + + + + +#ifdef PJ_OMIT_SELFTEST +int pj_etmerc_selftest (void) {return 0;} +#else + +int pj_etmerc_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=etmerc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +zone=30"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {222650.79679758562, 110642.22941193319}, + {222650.79679758562, -110642.22941193319}, + {-222650.79679758562, 110642.22941193319}, + {-222650.79679758562, -110642.22941193319}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {0.0017966305681649398, 0.00090436947663183873}, + {0.0017966305681649398, -0.00090436947663183873}, + {-0.0017966305681649398, 0.00090436947663183873}, + {-0.0017966305681649398, -0.00090436947663183873}, + }; + + return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); +} +#endif + + + + + + + + + + + /* utm uses etmerc for the underlying projection */ -ENTRY0(utm) + + +PJ *PROJECTION(utm) { int zone; + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return freeup_new (P); + P->opaque = Q; + + P->pfree = freeup; + P->descr = des_utm; - if (!P->es) E_ERROR(-34); - P->y0 = pj_param(P->ctx, P->params, "bsouth").i ? 10000000. : 0.; + if (!P->es) + E_ERROR(-34); + P->y0 = pj_param (P->ctx, P->params, "bsouth").i ? 10000000. : 0.; P->x0 = 500000.; - if (pj_param(P->ctx, P->params, "tzone").i) /* zone input ? */ + if (pj_param (P->ctx, P->params, "tzone").i) /* zone input ? */ if ((zone = pj_param(P->ctx, P->params, "izone").i) > 0 && zone <= 60) --zone; else E_ERROR(-35) else /* nearest central meridian input */ - if ((zone = (int)(floor((adjlon(P->lam0) + PI) * 30. / PI))) < 0) + if ((zone = (int)(floor ((adjlon (P->lam0) + PI) * 30. / PI))) < 0) zone = 0; else if (zone >= 60) zone = 59; P->lam0 = (zone + .5) * PI / 30. - PI; P->k0 = 0.9996; P->phi0 = 0.; -ENDENTRY(setup(P)) + + return setup (P); +} + + +#ifdef PJ_OMIT_SELFTEST +int pj_utm_selftest (void) {return 0;} +#else + +int pj_utm_selftest (void) { + double tolerance_lp = 1e-10; + double tolerance_xy = 1e-7; + + char e_args[] = {"+proj=utm +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +zone=30"}; + + LP fwd_in[] = { + { 2, 1}, + { 2,-1}, + {-2, 1}, + {-2,-1} + }; + + XY e_fwd_expect[] = { + {1057002.4054912981, 110955.14117594929}, + {1057002.4054912981, -110955.14117594929}, + {611263.81227890507, 110547.10569680421}, + {611263.81227890507, -110547.10569680421}, + }; + + XY inv_in[] = { + { 200, 100}, + { 200,-100}, + {-200, 100}, + {-200,-100} + }; + + LP e_inv_expect[] = { + {-7.4869520833902357, 0.00090193980983462605}, + {-7.4869520833902357, -0.00090193980983462605}, + {-7.4905356820622613, 0.00090193535121489081}, + {-7.4905356820622613, -0.00090193535121489081}, + }; + + return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); +} +#endif + + + -- cgit v1.2.3 From 862c4ba975bb744acfaa8d110cfca5c065fbca17 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Wed, 18 May 2016 23:27:16 +0200 Subject: Adding a missing #endif PJ_aea.c lost one line too many when removing the final stubs in the previous commit. --- src/PJ_aea.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 0efef484..7fa3e331 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -331,3 +331,4 @@ int pj_leac_selftest (void) { return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); } +#endif -- cgit v1.2.3 From 605dc6f3b47bf72c61712b275284212c66e541d0 Mon Sep 17 00:00:00 2001 From: Thomas Knudsen Date: Thu, 19 May 2016 14:33:35 +0200 Subject: Removed a few superfluous assignments and an erroneously committed file An intermediate file, PJ_etmerc.c, was mistakenly committed in 1b17a573ffb07e9565e0df296e2a3a21bce8e971 P->pfree and P->descr were being identically reinitialized in a few of the first files converted - and in the last: proj_etmerc.c --- src/PJ_aea.c | 5 - src/PJ_airy.c | 2 - src/PJ_aitoff.c | 4 - src/PJ_august.c | 2 - src/PJ_bacon.c | 6 - src/PJ_bipc.c | 2 - src/PJ_boggs.c | 2 - src/PJ_bonne.c | 3 - src/PJ_calcofi.c | 2 - src/PJ_etmerc.c | 484 ------------------------------------------------------ src/PJ_krovak.c | 3 - src/PJ_oea.c | 2 - src/PJ_sts.c | 2 - src/proj_etmerc.c | 8 +- 14 files changed, 1 insertion(+), 526 deletions(-) delete mode 100644 src/PJ_etmerc.c (limited to 'src') diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 7fa3e331..57898f3f 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -191,9 +191,6 @@ PJ *PROJECTION(aea) { return freeup_new (P); P->opaque = Q; - P->pfree = freeup; - P->descr = des_aea; - Q->phi1 = pj_param(P->ctx, P->params, "rlat_1").f; Q->phi2 = pj_param(P->ctx, P->params, "rlat_2").f; setup(P); @@ -207,8 +204,6 @@ PJ *PROJECTION(leac) { return freeup_new (P); P->opaque = Q; - P->pfree = freeup; - P->descr = des_leac; Q->phi2 = pj_param(P->ctx, P->params, "rlat_1").f; Q->phi1 = pj_param(P->ctx, P->params, "bsouth").i ? - HALFPI: HALFPI; setup (P); diff --git a/src/PJ_airy.c b/src/PJ_airy.c index 0addf2b8..c1d31d6c 100644 --- a/src/PJ_airy.c +++ b/src/PJ_airy.c @@ -123,8 +123,6 @@ PJ *PROJECTION(airy) { return freeup_new (P); P->opaque = Q; - P->pfree = freeup; - P->descr = des_airy; Q->no_cut = pj_param(P->ctx, P->params, "bno_cut").i; beta = 0.5 * (HALFPI - pj_param(P->ctx, P->params, "rlat_b").f); diff --git a/src/PJ_aitoff.c b/src/PJ_aitoff.c index 6c766e5a..c9fe1c22 100644 --- a/src/PJ_aitoff.c +++ b/src/PJ_aitoff.c @@ -184,8 +184,6 @@ PJ *PROJECTION(aitoff) { return freeup_new (P); P->opaque = Q; - P->pfree = freeup; - P->descr = des_aitoff; Q->mode = 0; return setup(P); } @@ -197,8 +195,6 @@ PJ *PROJECTION(wintri) { return freeup_new (P); P->opaque = Q; - P->pfree = freeup; - P->descr = des_wintri; Q->mode = 1; if (pj_param(P->ctx, P->params, "tlat_1").i) { if ((Q->cosphi1 = cos(pj_param(P->ctx, P->params, "rlat_1").f)) == 0.) diff --git a/src/PJ_august.c b/src/PJ_august.c index 4d4ecf6e..83463e9f 100644 --- a/src/PJ_august.c +++ b/src/PJ_august.c @@ -37,8 +37,6 @@ PJ *PROJECTION(august) { P->inv = 0; P->fwd = s_forward; P->es = 0.; - P->pfree = freeup; - P->descr = des_august; return P; } diff --git a/src/PJ_bacon.c b/src/PJ_bacon.c index b71fae28..75afaeb0 100644 --- a/src/PJ_bacon.c +++ b/src/PJ_bacon.c @@ -56,8 +56,6 @@ PJ *PROJECTION(bacon) { return freeup_new (P); P->opaque = Q; - P->pfree = freeup; - P->descr = des_bacon; Q->bacn = 1; Q->ortl = 0; P->es = 0.; @@ -72,8 +70,6 @@ PJ *PROJECTION(apian) { return freeup_new (P); P->opaque = Q; - P->pfree = freeup; - P->descr = des_apian; Q->bacn = Q->ortl = 0; P->es = 0.; P->fwd = s_forward; @@ -87,8 +83,6 @@ PJ *PROJECTION(ortel) { return freeup_new (P); P->opaque = Q; - P->pfree = freeup; - P->descr = des_ortel; Q->bacn = 0; Q->ortl = 1; P->es = 0.; diff --git a/src/PJ_bipc.c b/src/PJ_bipc.c index 5616b817..96082604 100644 --- a/src/PJ_bipc.c +++ b/src/PJ_bipc.c @@ -157,8 +157,6 @@ PJ *PROJECTION(bipc) { P->opaque = Q; Q->noskew = pj_param(P->ctx, P->params, "bns").i; - P->pfree = freeup; - P->descr = des_bipc; P->inv = s_inverse; P->fwd = s_forward; P->es = 0.; diff --git a/src/PJ_boggs.c b/src/PJ_boggs.c index dc4d781f..68010e6a 100644 --- a/src/PJ_boggs.c +++ b/src/PJ_boggs.c @@ -47,8 +47,6 @@ static void freeup (PJ *P) { PJ *PROJECTION(boggs) { P->es = 0.; P->fwd = s_forward; - P->pfree = freeup; - P->descr = des_boggs; return P; } diff --git a/src/PJ_bonne.c b/src/PJ_bonne.c index cb17104a..13309f3f 100644 --- a/src/PJ_bonne.c +++ b/src/PJ_bonne.c @@ -100,9 +100,6 @@ PJ *PROJECTION(bonne) { return freeup_new (P); P->opaque = Q; - P->pfree = freeup; - P->descr = des_bonne; - Q->phi1 = pj_param(P->ctx, P->params, "rlat_1").f; if (fabs(Q->phi1) < EPS10) E_ERROR(-23); if (P->es) { diff --git a/src/PJ_calcofi.c b/src/PJ_calcofi.c index 62749a93..661893f6 100644 --- a/src/PJ_calcofi.c +++ b/src/PJ_calcofi.c @@ -155,8 +155,6 @@ static void freeup (PJ *P) { PJ *PROJECTION(calcofi) { P->opaque = 0; - P->pfree = freeup; - P->descr = des_calcofi; if (P->es) { /* ellipsoid */ P->inv = e_inverse; P->fwd = e_forward; diff --git a/src/PJ_etmerc.c b/src/PJ_etmerc.c deleted file mode 100644 index d752bac9..00000000 --- a/src/PJ_etmerc.c +++ /dev/null @@ -1,484 +0,0 @@ -/* -** libproj -- library of cartographic projections -** -** Copyright (c) 2008 Gerald I. Evenden -*/ - -/* -** Permission is hereby granted, free of charge, to any person obtaining -** a copy of this software and associated documentation files (the -** "Software"), to deal in the Software without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Software, and to -** permit persons to whom the Software is furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -/* The code in this file is largly based upon procedures: - * - * Written by: Knud Poder and Karsten Engsager - * - * Based on math from: R.Koenig and K.H. Weise, "Mathematische - * Grundlagen der hoeheren Geodaesie und Kartographie, - * Springer-Verlag, Berlin/Goettingen" Heidelberg, 1951. - * - * Modified and used here by permission of Reference Networks - * Division, Kort og Matrikelstyrelsen (KMS), Copenhagen, Denmark -*/ - - -#define PROJ_LIB__ -#define PJ_LIB__ - -#include - - -struct pj_opaque { - double Qn; /* Merid. quad., scaled to the projection */ \ - double Zb; /* Radius vector in polar coord. systems */ \ - double cgb[6]; /* Constants for Gauss -> Geo lat */ \ - double cbg[6]; /* Constants for Geo lat -> Gauss */ \ - double utg[6]; /* Constants for transv. merc. -> geo */ \ - double gtu[6]; /* Constants for geo -> transv. merc. */ -}; - -PROJ_HEAD(etmerc, "Extended Transverse Mercator") - "\n\tCyl, Sph\n\tlat_ts=(0)\nlat_0=(0)"; -PROJ_HEAD(utm, "Universal Transverse Mercator (UTM)") - "\n\tCyl, Sph\n\tzone= south"; - -#define PROJ_ETMERC_ORDER 6 - - -#ifdef _GNU_SOURCE - inline -#endif -static double log1py(double x) { /* Compute log(1+x) accurately */ - volatile double - y = 1 + x, - z = y - 1; - /* Here's the explanation for this magic: y = 1 + z, exactly, and z - * approx x, thus log(y)/z (which is nearly constant near z = 0) returns - * a good approximation to the true log(1 + x)/x. The multiplication x * - * (log(y)/z) introduces little additional error. */ - return z == 0 ? x : x * log(y) / z; -} - - -#ifdef _GNU_SOURCE - inline -#endif -static double asinhy(double x) { /* Compute asinh(x) accurately */ - double y = fabs(x); /* Enforce odd parity */ - y = log1py(y * (1 + y/(hypot(1.0, y) + 1))); - return x < 0 ? -y : y; -} - - -#ifdef _GNU_SOURCE - inline -#endif -static double gatg(double *p1, int len_p1, double B) { - double *p; - double h = 0, h1, h2 = 0, cos_2B; - - cos_2B = 2*cos(2*B); - for (p = p1 + len_p1, h1 = *--p; p - p1; h2 = h1, h1 = h) - h = -h2 + cos_2B*h1 + *--p; - return (B + h*sin(2*B)); -} - -/* Complex Clenshaw summation */ -#ifdef _GNU_SOURCE - inline -#endif -static double clenS(double *a, int size, double arg_r, double arg_i, double *R, double *I) { - double *p, r, i, hr, hr1, hr2, hi, hi1, hi2; - double sin_arg_r, cos_arg_r, sinh_arg_i, cosh_arg_i; - - /* arguments */ - p = a + size; -#ifdef _GNU_SOURCE - sincos(arg_r, &sin_arg_r, &cos_arg_r); -#else - sin_arg_r = sin(arg_r); - cos_arg_r = cos(arg_r); -#endif - sinh_arg_i = sinh(arg_i); - cosh_arg_i = cosh(arg_i); - r = 2*cos_arg_r*cosh_arg_i; - i = -2*sin_arg_r*sinh_arg_i; - - /* summation loop */ - for (hi1 = hr1 = hi = 0, hr = *--p; a - p;) { - hr2 = hr1; - hi2 = hi1; - hr1 = hr; - hi1 = hi; - hr = -hr2 + r*hr1 - i*hi1 + *--p; - hi = -hi2 + i*hr1 + r*hi1; - } - - r = sin_arg_r*cosh_arg_i; - i = cos_arg_r*sinh_arg_i; - *R = r*hr - i*hi; - *I = r*hi + i*hr; - return *R; -} - - -/* Real Clenshaw summation */ -static double clens(double *a, int size, double arg_r) { - double *p, r, hr, hr1, hr2, cos_arg_r; - - p = a + size; - cos_arg_r = cos(arg_r); - r = 2*cos_arg_r; - - /* summation loop */ - for (hr1 = 0, hr = *--p; a - p;) { - hr2 = hr1; - hr1 = hr; - hr = -hr2 + r*hr1 + *--p; - } - return sin (arg_r)*hr; -} - - - -static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ - XY xy = {0.0,0.0}; - struct pj_opaque *Q = P->opaque; - double sin_Cn, cos_Cn, cos_Ce, sin_Ce, dCn, dCe; - double Cn = lp.phi, Ce = lp.lam; - - /* ell. LAT, LNG -> Gaussian LAT, LNG */ - Cn = gatg (Q->cbg, PROJ_ETMERC_ORDER, Cn); - /* Gaussian LAT, LNG -> compl. sph. LAT */ -#ifdef _GNU_SOURCE - sincos (Cn, &sin_Cn, &cos_Cn); - sincos (Ce, &sin_Ce, &cos_Ce); -#else - sin_Cn = sin (Cn); - cos_Cn = cos (Cn); - sin_Ce = sin (Ce); - cos_Ce = cos (Ce); -#endif - - Cn = atan2 (sin_Cn, cos_Ce*cos_Cn); - Ce = atan2 (sin_Ce*cos_Cn, hypot (sin_Cn, cos_Cn*cos_Ce)); - - /* compl. sph. N, E -> ell. norm. N, E */ - Ce = asinhy ( tan (Ce) ); /* Replaces: Ce = log(tan(FORTPI + Ce*0.5)); */ - Cn += clenS (Q->gtu, PROJ_ETMERC_ORDER, 2*Cn, 2*Ce, &dCn, &dCe); - Ce += dCe; - if (fabs (Ce) <= 2.623395162778) { - xy.y = Q->Qn * Cn + Q->Zb; /* Northing */ - xy.x = Q->Qn * Ce; /* Easting */ - } else - xy.x = xy.y = HUGE_VAL; - return xy; -} - - - -static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ - LP lp = {0.0,0.0}; - struct pj_opaque *Q = P->opaque; - double sin_Cn, cos_Cn, cos_Ce, sin_Ce, dCn, dCe; - double Cn = xy.y, Ce = xy.x; - - /* normalize N, E */ - Cn = (Cn - Q->Zb)/Q->Qn; - Ce = Ce/Q->Qn; - - if (fabs(Ce) <= 2.623395162778) { /* 150 degrees */ - /* norm. N, E -> compl. sph. LAT, LNG */ - Cn += clenS(Q->utg, PROJ_ETMERC_ORDER, 2*Cn, 2*Ce, &dCn, &dCe); - Ce += dCe; - Ce = atan (sinh (Ce)); /* Replaces: Ce = 2*(atan(exp(Ce)) - FORTPI); */ - /* compl. sph. LAT -> Gaussian LAT, LNG */ -#ifdef _GNU_SOURCE - sincos (Cn, &sin_Cn, &cos_Cn); - sincos (Ce, &sin_Ce, &cos_Ce); -#else - sin_Cn = sin (Cn); - cos_Cn = cos (Cn); - sin_Ce = sin (Ce); - cos_Ce = cos (Ce); -#endif - Ce = atan2 (sin_Ce, cos_Ce*cos_Cn); - Cn = atan2 (sin_Cn*cos_Ce, hypot (sin_Ce, cos_Ce*cos_Cn)); - /* Gaussian LAT, LNG -> ell. LAT, LNG */ - lp.phi = gatg (Q->cgb, PROJ_ETMERC_ORDER, Cn); - lp.lam = Ce; - } - else - lp.phi = lp.lam = HUGE_VAL; - return lp; -} - - - -static void *freeup_new (PJ *P) { /* Destructor */ - if (0==P) - return 0; - if (0==P->opaque) - return pj_dealloc (P); - pj_dealloc (P->opaque); - return pj_dealloc(P); -} - -static void freeup (PJ *P) { - freeup_new (P); - return; -} - -static PJ *setup(PJ *P) { /* general initialization */ - double f, n, np, Z; - struct pj_opaque *Q = P->opaque; - - if (P->es <= 0) - E_ERROR(-34); - - /* flattening */ - f = P->es / (1 + sqrt (1 - P->es)); /* Replaces: f = 1 - sqrt(1-P->es); */ - - /* third flattening */ - np = n = f/(2 - f); - - /* COEF. OF TRIG SERIES GEO <-> GAUSS */ - /* cgb := Gaussian -> Geodetic, KW p190 - 191 (61) - (62) */ - /* cbg := Geodetic -> Gaussian, KW p186 - 187 (51) - (52) */ - /* PROJ_ETMERC_ORDER = 6th degree : Engsager and Poder: ICC2007 */ - - Q->cgb[0] = n*( 2 + n*(-2/3.0 + n*(-2 + n*(116/45.0 + n*(26/45.0 + - n*(-2854/675.0 )))))); - Q->cbg[0] = n*(-2 + n*( 2/3.0 + n*( 4/3.0 + n*(-82/45.0 + n*(32/45.0 + - n*( 4642/4725.0)))))); - np *= n; - Q->cgb[1] = np*(7/3.0 + n*( -8/5.0 + n*(-227/45.0 + n*(2704/315.0 + - n*( 2323/945.0))))); - Q->cbg[1] = np*(5/3.0 + n*(-16/15.0 + n*( -13/9.0 + n*( 904/315.0 + - n*(-1522/945.0))))); - np *= n; - /* n^5 coeff corrected from 1262/105 -> -1262/105 */ - Q->cgb[2] = np*( 56/15.0 + n*(-136/35.0 + n*(-1262/105.0 + - n*( 73814/2835.0)))); - Q->cbg[2] = np*(-26/15.0 + n*( 34/21.0 + n*( 8/5.0 + - n*(-12686/2835.0)))); - np *= n; - /* n^5 coeff corrected from 322/35 -> 332/35 */ - Q->cgb[3] = np*(4279/630.0 + n*(-332/35.0 + n*(-399572/14175.0))); - Q->cbg[3] = np*(1237/630.0 + n*( -12/5.0 + n*( -24832/14175.0))); - np *= n; - Q->cgb[4] = np*(4174/315.0 + n*(-144838/6237.0 )); - Q->cbg[4] = np*(-734/315.0 + n*( 109598/31185.0)); - np *= n; - Q->cgb[5] = np*(601676/22275.0 ); - Q->cbg[5] = np*(444337/155925.0); - - /* Constants of the projections */ - /* Transverse Mercator (UTM, ITM, etc) */ - np = n*n; - /* Norm. mer. quad, K&W p.50 (96), p.19 (38b), p.5 (2) */ - Q->Qn = P->k0/(1 + n) * (1 + np*(1/4.0 + np*(1/64.0 + np/256.0))); - /* coef of trig series */ - /* utg := ell. N, E -> sph. N, E, KW p194 (65) */ - /* gtu := sph. N, E -> ell. N, E, KW p196 (69) */ - Q->utg[0] = n*(-0.5 + n*( 2/3.0 + n*(-37/96.0 + n*( 1/360.0 + - n*( 81/512.0 + n*(-96199/604800.0)))))); - Q->gtu[0] = n*( 0.5 + n*(-2/3.0 + n*( 5/16.0 + n*(41/180.0 + - n*(-127/288.0 + n*( 7891/37800.0 )))))); - Q->utg[1] = np*(-1/48.0 + n*(-1/15.0 + n*(437/1440.0 + n*(-46/105.0 + - n*( 1118711/3870720.0))))); - Q->gtu[1] = np*(13/48.0 + n*(-3/5.0 + n*(557/1440.0 + n*(281/630.0 + - n*(-1983433/1935360.0))))); - np *= n; - Q->utg[2] = np*(-17/480.0 + n*( 37/840.0 + n*( 209/4480.0 + - n*( -5569/90720.0 )))); - Q->gtu[2] = np*( 61/240.0 + n*(-103/140.0 + n*(15061/26880.0 + - n*(167603/181440.0)))); - np *= n; - Q->utg[3] = np*(-4397/161280.0 + n*( 11/504.0 + n*( 830251/7257600.0))); - Q->gtu[3] = np*(49561/161280.0 + n*(-179/168.0 + n*(6601661/7257600.0))); - np *= n; - Q->utg[4] = np*(-4583/161280.0 + n*( 108847/3991680.0)); - Q->gtu[4] = np*(34729/80640.0 + n*(-3418889/1995840.0)); - np *= n; - Q->utg[5] = np*(-20648693/638668800.0); - Q->gtu[5] = np*(212378941/319334400.0); - - /* Gaussian latitude value of the origin latitude */ - Z = gatg (Q->cbg, PROJ_ETMERC_ORDER, P->phi0); - - /* Origin northing minus true northing at the origin latitude */ - /* i.e. true northing = N - P->Zb */ - Q->Zb = - Q->Qn*(Z + clens(Q->gtu, PROJ_ETMERC_ORDER, 2*Z)); - P->inv = e_inverse; - P->fwd = e_forward; - return P; -} - - - -PJ *PROJECTION(etmerc) { - struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); - if (0==Q) - return freeup_new (P); - P->opaque = Q; - - P->pfree = freeup; - P->descr = des_etmerc; - return setup (P); -} - - - - - - - -#ifdef PJ_OMIT_SELFTEST -int pj_etmerc_selftest (void) {return 0;} -#else - -int pj_etmerc_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=etmerc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +zone=30"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {222650.79679758562, 110642.22941193319}, - {222650.79679758562, -110642.22941193319}, - {-222650.79679758562, 110642.22941193319}, - {-222650.79679758562, -110642.22941193319}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0017966305681649398, 0.00090436947663183873}, - {0.0017966305681649398, -0.00090436947663183873}, - {-0.0017966305681649398, 0.00090436947663183873}, - {-0.0017966305681649398, -0.00090436947663183873}, - }; - - return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); -} -#endif - - - - - - - - - - - - -/* utm uses etmerc for the underlying projection */ - - -PJ *PROJECTION(utm) { - int zone; - struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); - if (0==Q) - return freeup_new (P); - P->opaque = Q; - - P->pfree = freeup; - P->descr = des_utm; - - if (!P->es) - E_ERROR(-34); - P->y0 = pj_param (P->ctx, P->params, "bsouth").i ? 10000000. : 0.; - P->x0 = 500000.; - if (pj_param (P->ctx, P->params, "tzone").i) /* zone input ? */ - if ((zone = pj_param(P->ctx, P->params, "izone").i) > 0 && zone <= 60) - --zone; - else - E_ERROR(-35) - else /* nearest central meridian input */ - if ((zone = (int)(floor ((adjlon (P->lam0) + PI) * 30. / PI))) < 0) - zone = 0; - else if (zone >= 60) - zone = 59; - P->lam0 = (zone + .5) * PI / 30. - PI; - P->k0 = 0.9996; - P->phi0 = 0.; - - return setup (P); -} - - -#ifdef PJ_OMIT_SELFTEST -int pj_utm_selftest (void) {return 0;} -#else - -int pj_utm_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=utm +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +zone=30"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {1057002.4054912981, 110955.14117594929}, - {1057002.4054912981, -110955.14117594929}, - {611263.81227890507, 110547.10569680421}, - {611263.81227890507, -110547.10569680421}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {-7.4869520833902357, 0.00090193980983462605}, - {-7.4869520833902357, -0.00090193980983462605}, - {-7.4905356820622613, 0.00090193535121489081}, - {-7.4905356820622613, -0.00090193535121489081}, - }; - - return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); -} -#endif - - - diff --git a/src/PJ_krovak.c b/src/PJ_krovak.c index 86616b4c..4a9a4e53 100644 --- a/src/PJ_krovak.c +++ b/src/PJ_krovak.c @@ -233,9 +233,6 @@ PJ *PROJECTION(krovak) { return freeup_new (P); P->opaque = Q; - P->pfree = freeup; - P->descr = des_krovak; - /* read some Parameters, * here Latitude Truescale */ diff --git a/src/PJ_oea.c b/src/PJ_oea.c index 50ab6b52..f29dcfd0 100644 --- a/src/PJ_oea.c +++ b/src/PJ_oea.c @@ -73,8 +73,6 @@ PJ *PROJECTION(oea) { return freeup_new (P); P->opaque = Q; - P->pfree = freeup; - P->descr = des_oea; if (((Q->n = pj_param(P->ctx, P->params, "dn").f) <= 0.) || ((Q->m = pj_param(P->ctx, P->params, "dm").f) <= 0.)) E_ERROR(-39) diff --git a/src/PJ_sts.c b/src/PJ_sts.c index 689c0489..347a7303 100644 --- a/src/PJ_sts.c +++ b/src/PJ_sts.c @@ -154,8 +154,6 @@ PJ *PROJECTION(kav5) { return freeup_new (P); P->opaque = Q; - P->pfree = freeup; - P->descr = des_kav5; return setup(P, 1.50488, 1.35439, 0); } diff --git a/src/proj_etmerc.c b/src/proj_etmerc.c index 0149303e..a88a0837 100644 --- a/src/proj_etmerc.c +++ b/src/proj_etmerc.c @@ -339,10 +339,7 @@ PJ *PROJECTION(etmerc) { if (0==Q) return freeup_new (P); P->opaque = Q; - - P->pfree = freeup; - P->descr = des_etmerc; - return setup (P); + return setup (P); } @@ -414,9 +411,6 @@ PJ *PROJECTION(utm) { return freeup_new (P); P->opaque = Q; - P->pfree = freeup; - P->descr = des_utm; - if (!P->es) E_ERROR(-34); P->y0 = pj_param (P->ctx, P->params, "bsouth").i ? 10000000. : 0.; -- cgit v1.2.3