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); }
PJ *proj_create_argv (PJ_CONTEXT *ctx, int argc, char **argv) { /************************************************************************************** Create a new PJ object in the context ctx, using the given definition argument array argv. If ctx==0, the default context is used, if definition==0, or invalid, a null-pointer is returned. The definition arguments may use '+' as argument start indicator, as in {"+proj=utm", "+zone=32"}, or leave it out, as in {"proj=utm", "zone=32"}. **************************************************************************************/ PJ *P; const char *c; if (0==argv) return 0; if (0==ctx) ctx = pj_get_default_ctx (); /* We assume that free format is used, and build a full proj_create compatible string */ c = pj_make_args (argc, argv); if (0==c) return 0; P = proj_create (ctx, c); pj_dealloc ((char *) c); return P; }
static char *path_append (char *buf, const char *app, size_t *buf_size) { /****************************************************************************** Helper for proj_info() below. Append app to buf, separated by a semicolon. Also handle allocation of longer buffer if needed. Returns buffer and adjusts *buf_size through provided pointer arg. ******************************************************************************/ char *p; size_t len, applen = 0, buflen = 0; #ifdef _WIN32 char *delim = ";"; #else char *delim = ":"; #endif /* Nothing to do? */ if (0 == app) return buf; applen = strlen (app); if (0 == applen) return buf; /* Start checking whether buf is long enough */ if (0 != buf) buflen = strlen (buf); len = buflen+applen+strlen (delim) + 1; /* "pj_realloc", so to speak */ if (*buf_size < len) { p = pj_calloc (2 * len, sizeof (char)); if (0==p) { pj_dealloc (buf); return 0; } *buf_size = 2 * len; if (buf != 0) strcpy (p, buf); pj_dealloc (buf); buf = p; } /* Only append a semicolon if something's already there */ if (0 != buflen) strcat (buf, ";"); strcat (buf, app); return buf; }
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; }
static PJ *destructor (PJ *P, int errlev) { if (nullptr==P) return nullptr; if (nullptr==P->opaque) return pj_default_destructor (P, errlev); pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->en); return pj_default_destructor (P, errlev); }
static void *destructor (PJ *P, int errlev) { if (0==P) return 0; if (0==P->opaque) return pj_default_destructor (P, errlev); pj_dealloc (P->opaque->en); return pj_default_destructor (P, errlev); }
static PJ *destructor (PJ *P, int errlev) { int i; if (nullptr==P) return nullptr; if (nullptr==P->opaque) return pj_default_destructor (P, errlev); /* Deallocate each pipeline step, then pipeline array */ if (nullptr!=static_cast<struct pj_opaque*>(P->opaque)->pipeline) for (i = 0; i < static_cast<struct pj_opaque*>(P->opaque)->steps; i++) proj_destroy (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i+1]); pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->pipeline); pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->argv); pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->current_argv); for (i=0; i<4; i++) delete static_cast<struct pj_opaque*>(P->opaque)->stack[i]; return pj_default_destructor(P, errlev); }
int proj_vgrid_init(PJ* P, const char *grids) { /********************************************** Initizalize and populate gridlist. Takes a PJ-object and the plus-parameter name that is used in the proj-string to specify the grids to load, e.g. "+grids". The + should be left out here. Returns the number of loaded grids. ***********************************************/ /* prepend "s" to the "grids" string to allow usage with pj_param */ char *sgrids = (char *) pj_malloc( (strlen(grids)+1+1) *sizeof(char) ); sprintf(sgrids, "%s%s", "s", grids); if (P->vgridlist_geoid == NULL) { P->vgridlist_geoid = pj_gridlist_from_nadgrids( P->ctx, pj_param(P->ctx, P->params, sgrids).s, &(P->vgridlist_geoid_count) ); if( P->vgridlist_geoid == NULL || P->vgridlist_geoid_count == 0 ) { pj_dealloc(sgrids); return 0; } } if (P->vgridlist_geoid_count == 0) { proj_errno_set(P, PJD_ERR_FAILED_TO_LOAD_GRID); } pj_dealloc(sgrids); return P->vgridlist_geoid_count; }
static paralist *get_init(PJ_CONTEXT *ctx, char *key) { /************************************************************************* Expand key from buffer or (if not in buffer) from init file *************************************************************************/ char *xkey, *definition; paralist *init_items = 0; /* support "init=file:section", "+init=file:section", and "file:section" format */ xkey = strstr (key, "init="); if (0==xkey) xkey = key; else xkey += 5; pj_log (ctx, PJ_LOG_TRACE, "get_init: searching cache for key: [%s]", xkey); /* Is file/key pair already in cache? */ init_items = pj_search_initcache (xkey); if (init_items) return init_items; /* If not, we must read it from file */ pj_log (ctx, PJ_LOG_TRACE, "get_init: searching on in init files for [%s]", xkey); definition = get_init_string (ctx, xkey); if (0==definition) return 0; init_items = string_to_paralist (ctx, definition); if (init_items) pj_log (ctx, PJ_LOG_TRACE, "get_init: got [%s], paralist[0,1]: [%s,%s]", definition, init_items->param, init_items->next ? init_items->next->param : "(empty)"); pj_dealloc (definition); if (0==init_items) return 0; /* We found it in file - now insert into the cache, before returning */ pj_insert_initcache (xkey, init_items); return init_items; }
static void *freeup_new (PJ *P) { /* Destructor */ return pj_dealloc(P); }
static void freeup(PJ *P) { /* Destructor */ pj_dealloc(P); }
static char *get_init_string (PJ_CONTEXT *ctx, char *name) { /*************************************************************************************** Read a section of an init file. Return its contents as a plain character string. It is the duty of the caller to free the memory allocated for the string. ***************************************************************************************/ #define MAX_LINE_LENGTH 1000 size_t current_buffer_size = 5 * (MAX_LINE_LENGTH + 1); char *fname, *section, *key; char *buffer = 0; char *line = 0; PAFile fid; size_t n; line = pj_malloc (MAX_LINE_LENGTH + 1); if (0==line) return 0; fname = pj_malloc (MAX_PATH_FILENAME+ID_TAG_MAX+3); if (0==fname) { pj_dealloc (line); return 0; } /* Support "init=file:section", "+init=file:section", and "file:section" format */ key = strstr (name, "init="); if (0==key) key = name; else key += 5; if (MAX_PATH_FILENAME + ID_TAG_MAX + 2 < strlen (key)) { pj_dealloc (fname); pj_dealloc (line); return 0; } memmove (fname, key, strlen (key) + 1); /* Locate the name of the section we search for */ section = strrchr(fname, ':'); if (0==section) { proj_context_errno_set (ctx, PJD_ERR_NO_COLON_IN_INIT_STRING); pj_dealloc (fname); pj_dealloc (line); return 0; } *section = 0; section++; n = strlen (section); pj_log (ctx, PJ_LOG_TRACE, "get_init_string: searching for section [%s] in init file [%s]", section, fname); fid = pj_open_lib (ctx, fname, "rt"); if (0==fid) { pj_dealloc (fname); pj_dealloc (line); proj_context_errno_set (ctx, PJD_ERR_NO_OPTION_IN_INIT_FILE); return 0; } /* Search for section in init file */ for (;;) { /* End of file? */ if (0==pj_ctx_fgets (ctx, line, MAX_LINE_LENGTH, fid)) { pj_dealloc (buffer); pj_dealloc (fname); pj_dealloc (line); pj_ctx_fclose (ctx, fid); proj_context_errno_set (ctx, PJD_ERR_NO_OPTION_IN_INIT_FILE); return 0; } /* At start of right section? */ pj_chomp (line); if ('<'!=line[0]) continue; if (strlen (line) < n + 2) continue; if (line[n + 1] != '>') continue; if (0==strncmp (line + 1, section, n)) break; } /* We're at the first line of the right section - copy line to buffer */ buffer = pj_malloc (current_buffer_size); if (0==buffer) { pj_dealloc (fname); pj_dealloc (line); pj_ctx_fclose (ctx, fid); return 0; } /* Skip the "<section>" indicator, and copy the rest of the line over */ strcpy (buffer, line + strlen (section) + 2); /* Copy the remaining lines of the section to buffer */ for (;;) { char *end_i_cator; size_t next_length, buffer_length; /* Did the section end somewhere in the most recently read line? */ end_i_cator = strchr (buffer, '<'); if (end_i_cator) { *end_i_cator = 0; break; } /* End of file? - done! */ if (0==pj_ctx_fgets (ctx, line, MAX_LINE_LENGTH, fid)) break; /* Otherwise, handle the line. It MAY be the start of the next section, */ /* but that will be handled at the start of next trip through the loop */ buffer_length = strlen (buffer); pj_chomp (line); /* Remove '#' style comments */ next_length = strlen (line) + buffer_length + 2; if (next_length > current_buffer_size) { char *b = pj_malloc (2 * current_buffer_size); if (0==b) { pj_dealloc (buffer); buffer = 0; break; } strcpy (b, buffer); current_buffer_size *= 2; pj_dealloc (buffer); buffer = b; } buffer[buffer_length] = ' '; strcpy (buffer + buffer_length + 1, line); } pj_ctx_fclose (ctx, fid); pj_dealloc (fname); pj_dealloc (line); if (0==buffer) return 0; pj_shrink (buffer); pj_log (ctx, PJ_LOG_TRACE, "key=%s, value: [%s]", key, buffer); return buffer; }
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; }