PJ *proj_create (PJ_CONTEXT *ctx, const char *definition) { /************************************************************************************** Create a new PJ object in the context ctx, using the given definition. If ctx==0, the default context is used, if definition==0, or invalid, a null-pointer is returned. The definition may use '+' as argument start indicator, as in "+proj=utm +zone=32", or leave it out, as in "proj=utm zone=32". It may even use free formatting "proj = utm; zone =32 ellps= GRS80". Note that the semicolon separator is allowed, but not required. **************************************************************************************/ PJ *P; char *args, **argv; size_t argc, n; int ret; if (0==ctx) ctx = pj_get_default_ctx (); /* Make a copy that we can manipulate */ n = strlen (definition); args = (char *) malloc (n + 1); if (0==args) return 0; strcpy (args, definition); argc = pj_trim_argc (args); if (argc==0) { pj_dealloc (args); return 0; } argv = pj_trim_argv (argc, args); /* ...and let pj_init_ctx do the hard work */ P = pj_init_ctx (ctx, (int) argc, argv); pj_dealloc (argv); pj_dealloc (args); /* Support cs2cs-style modifiers */ ret = cs2cs_emulation_setup (P); if (0==ret) return proj_destroy (P); return P; }
PJ * pj_init_plus_ctx( projCtx ctx, const char *definition ) { #define MAX_ARG 200 char *argv[MAX_ARG]; 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 ); if (!defn_copy) return NULL; strcpy( defn_copy, definition ); /* split into arguments based on '+' and trim white space */ for( i = 0; defn_copy[i] != '\0'; i++ ) { switch( defn_copy[i] ) { case '+': if( i == 0 || defn_copy[i-1] == '\0' || blank_count > 0 ) { /* trim trailing spaces from the previous param */ if( blank_count > 0 ) { defn_copy[i - blank_count] = '\0'; blank_count = 0; } if( argc+1 == MAX_ARG ) { pj_dalloc( defn_copy ); pj_ctx_set_errno( ctx, PJD_ERR_UNPARSEABLE_CS_DEF ); return 0; } argv[argc++] = defn_copy + i + 1; } break; case ' ': case '\t': case '\n': /* trim leading spaces from the current param */ if( i == 0 || defn_copy[i-1] == '\0' || argc == 0 || argv[argc-1] == defn_copy + i ) defn_copy[i] = '\0'; else blank_count++; break; default: /* reset blank_count */ blank_count = 0; } } /* trim trailing spaces from the last param */ defn_copy[i - blank_count] = '\0'; /* perform actual initialization */ result = pj_init_ctx( ctx, argc, argv ); pj_dalloc( defn_copy ); return result; }
PJ * pj_init(int argc, char **argv) { return pj_init_ctx( pj_get_default_ctx(), argc, argv ); }
PJ *PROJECTION(ob_tran) { double phip; char *name; ARGS args; PJ *R; /* projection to rotate */ struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return destructor(P, ENOMEM); P->opaque = Q; P->destructor = destructor; /* get name of projection to be translated */ if (!(name = pj_param(P->ctx, P->params, "so_proj").s)) return destructor(P, PJD_ERR_NO_ROTATION_PROJ); /* avoid endless recursion */ if( strcmp(name, "ob_tran") == 0 ) return destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ); /* Create the target projection object to rotate */ args = ob_tran_target_params (P->params); R = pj_init_ctx (pj_get_ctx(P), args.argc, args.argv); pj_dealloc (args.argv); if (nullptr==R) return destructor (P, PJD_ERR_UNKNOWN_PROJECTION_ID); Q->link = R; 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(fabs(phic) - M_HALFPI) <= TOL) return destructor(P, PJD_ERR_LAT_0_OR_ALPHA_EQ_90); 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 - M_HALFPI) <= TOL || fabs(fabs(phi2) - M_HALFPI) <= TOL) return destructor(P, PJD_ERR_LAT_1_OR_2_ZERO_OR_90); 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 = Q->link->fwd ? o_forward : nullptr; P->inv = Q->link->inv ? o_inverse : nullptr; } else { /* transverse */ P->fwd = Q->link->fwd ? t_forward : nullptr; P->inv = Q->link->inv ? t_inverse : nullptr; } /* Support some rather speculative test cases, where the rotated projection */ /* is actually latlong. We do not want scaling in that case... */ if (Q->link->right==PJ_IO_UNITS_RADIANS) P->right = PJ_IO_UNITS_PROJECTED; return P; }