diff options
| author | Kristian Evers <kristianevers@gmail.com> | 2017-08-07 10:37:40 +0200 |
|---|---|---|
| committer | Thomas Knudsen <busstoptaktik@users.noreply.github.com> | 2017-08-07 10:37:40 +0200 |
| commit | 8302bf9db2d5bfa3a84a0f9ddf31a90698cccc84 (patch) | |
| tree | 056c9f67100c69cbe123742470a157ca386a0262 /src/pj_obs_api.c | |
| parent | 2d46accd49209e0b6c7c40626c1498a46399163d (diff) | |
| download | PROJ-8302bf9db2d5bfa3a84a0f9ddf31a90698cccc84.tar.gz PROJ-8302bf9db2d5bfa3a84a0f9ddf31a90698cccc84.zip | |
Adding info functions to proj.h API. (#551)
* Adding info functions to proj.h API.
Four new functions are added with this commit: proj_info(), proj_pj_info(),
proj_grid_info() and proj_init_info(). Additionally four new data types are
added: PJ_INFO, PJ_PROJ_INFO, PJ_GRID_INFO and PJ_INIT_INFO. The functions
return the corresponding data types.
These functions allows users of the PROJ.4 library to get information about
various PROJ.4 entities and the library itself. The new data types are structs
that contain specific information about either the library instance, a PJ
instance, a grid or an init file. Together the four new functions cover a big
part of the functionality in the semi-public projects.h API and should hopefully
make it easier for user to migrate their code to the proj.h API in the future.
Besides covering already existing functionality in the old API, this commit
introduces the ability to add metadata to init-files. This is primarily added
to give users a way of knowing which version of the EPSG database they are
using, but it also comes in handy for other init-files. The init-file metadata
is added directly to the init-file as a special "projection" called "metadata".
The info projection of the epsg init-file is thus described as:
<metadata> +version=9.0.0 +origin=EPSG +lastupdate=2017-01-10
The proj_init_info() function uses the internal pj_param() to read the
metadata. As a consequence, "metadata" will not be available as a the name of
a projection in the future. This is a reasonable price to pay considering the
ease of the implementation of adding metadata to init-files this way, and of
course that "metadata" is a very unlikely name for a projection in any case.
A metadata tag has been added to all init-files in the nad-directory. For most
only a subset of the possible parameters has been added.
* Replaced calls to sprintf and strncpy with safer options. Added pj_strlcpy for internal use.
* Fail gracefully when getting non-initialized PJ in proj_pj_info()
* Change length of filename member in PJ_INIT_INFO and PJ_GRID_INFO to 260 (MAX_PATH)
Diffstat (limited to 'src/pj_obs_api.c')
| -rw-r--r-- | src/pj_obs_api.c | 234 |
1 files changed, 218 insertions, 16 deletions
diff --git a/src/pj_obs_api.c b/src/pj_obs_api.c index b06f0823..b2929a07 100644 --- a/src/pj_obs_api.c +++ b/src/pj_obs_api.c @@ -390,9 +390,13 @@ PJ *proj_create_crs_to_crs (PJ_CONTEXT *ctx, const char *srid_from, const char ******************************************************************************/ PJ *P; - char buffer[256]; + char buffer[512]; + + strcpy(buffer, "+proj=pipeline +step +init="); + strncat(buffer, srid_from, 512-strlen(buffer)); + strncat(buffer, " +inv +step +init=", 512-strlen(buffer)); + strncat(buffer, srid_to, 512-strlen(buffer)); - sprintf(buffer, "+proj=pipeline +step +init=%s +inv +step +init=%s", srid_from, srid_to); P = proj_create(ctx, buffer); return P; @@ -509,11 +513,218 @@ void proj_context_destroy (PJ_CONTEXT *ctx) { } -/* Build a fully expanded proj_create() compatible representation of P */ -char *proj_definition_retrieve (PJ *P) { - if (0==P) - return 0; - return pj_get_def(P, 0); +/*****************************************************************************/ +PJ_INFO proj_info(void) { +/****************************************************************************** + Basic info about the current instance of the PROJ.4 library. + + Returns PJ_INFO struct. Searchpath member of the struct is truncated to 512 + characters. + +******************************************************************************/ + PJ_INFO info; + const char **paths; + char *tmpstr; + int i, n; + size_t len = 0; + + memset(&info, 0, sizeof(PJ_INFO)); + + info.major = PROJ_VERSION_MAJOR; + info.minor = PROJ_VERSION_MINOR; + info.patch = PROJ_VERSION_PATCH; + + /* This is a controlled environment, so no risk of sprintf buffer + overflow. A normal version string is xx.yy.zz which is 8 characters + long and there is room for 64 bytes in the version string. */ + sprintf(info.version, "%d.%d.%d", info.major, info.minor, info.patch); + + pj_strlcpy(info.release, pj_get_release(), sizeof(info.release)); + + + /* build search path string */ + tmpstr = getenv("HOME"); + if (tmpstr != NULL) { + pj_strlcpy(info.searchpath, tmpstr, sizeof(info.searchpath)); + } + + tmpstr = getenv("PROJ_LIB"); + if (tmpstr != NULL) { + if (strlen(info.searchpath) != 0) { + /* $HOME already in path */ + strcat(info.searchpath, ";"); + len = strlen(tmpstr); + strncat(info.searchpath, tmpstr, sizeof(info.searchpath)-len-1); + } else { + /* path is empty */ + pj_strlcpy(info.searchpath, tmpstr, sizeof(info.searchpath)); + } + } + + paths = proj_get_searchpath(); + n = proj_get_path_count(); + + for (i=0; i<n; i++) { + if (strlen(info.searchpath)+strlen(paths[i]) >= 511) + continue; + + if (strlen(info.searchpath) != 0) { + strcat(info.searchpath, ";"); + len = strlen(paths[i]); + strncat(info.searchpath, paths[i], sizeof(info.searchpath)-len-1); + } else { + pj_strlcpy(info.searchpath, paths[i], sizeof(info.searchpath)); + } + } + + return info; +} + + +/*****************************************************************************/ +PJ_PROJ_INFO proj_pj_info(const PJ *P) { +/****************************************************************************** + Basic info about a particular instance of a projection object. + + Returns PJ_PROJ_INFO struct. + +******************************************************************************/ + PJ_PROJ_INFO info; + char *def; + + memset(&info, 0, sizeof(PJ_PROJ_INFO)); + + if (!P) { + return info; + } + + /* projection id */ + if (pj_param(P->ctx, P->params, "tproj").i) + pj_strlcpy(info.id, pj_param(P->ctx, P->params, "sproj").s, sizeof(info.id)); + + /* projection description */ + pj_strlcpy(info.description, P->descr, sizeof(info.description)); + + /* projection definition */ + def = pj_get_def((PJ *)P, 0); /* pj_get_def takes a non-const PJ pointer */ + pj_strlcpy(info.definition, &def[1], sizeof(info.definition)); /* def includes a leading space */ + pj_dealloc(def); + + /* this does not take into account that a pipeline potentially does not */ + /* have an inverse. */ + info.has_inverse = (P->inv != 0 || P->inv3d != 0 || P->invobs != 0); + + return info; +} + + +/*****************************************************************************/ +PJ_GRID_INFO proj_grid_info(const char *gridname) { +/****************************************************************************** + Information about a named datum grid. + + Returns PJ_GRID_INFO struct. + +******************************************************************************/ + PJ_GRID_INFO info; + + /*PJ_CONTEXT *ctx = proj_context_create(); */ + PJ_CONTEXT *ctx = pj_get_default_ctx(); + PJ_GRIDINFO *gridinfo = pj_gridinfo_init(ctx, gridname); + memset(&info, 0, sizeof(PJ_GRID_INFO)); + + /* in case the grid wasn't found */ + if (gridinfo->filename == NULL) { + pj_gridinfo_free(ctx, gridinfo); + strcpy(info.format, "missing"); + return info; + } + + /* name of grid */ + pj_strlcpy(info.gridname, gridname, sizeof(info.gridname)); + + /* full path of grid */ + pj_find_file(ctx, gridname, info.filename, sizeof(info.filename)); + + /* grid format */ + pj_strlcpy(info.format, gridinfo->format, sizeof(info.format)); + + /* grid size */ + info.n_lon = gridinfo->ct->lim.lam; + info.n_lat = gridinfo->ct->lim.phi; + + /* cell size */ + info.cs_lon = gridinfo->ct->del.lam; + info.cs_lat = gridinfo->ct->del.phi; + + /* bounds of grid */ + info.lowerleft = gridinfo->ct->ll; + info.upperright.lam = info.lowerleft.lam + info.n_lon*info.cs_lon; + info.upperright.phi = info.lowerleft.phi + info.n_lat*info.cs_lat; + + pj_gridinfo_free(ctx, gridinfo); + + return info; +} + +/*****************************************************************************/ +PJ_INIT_INFO proj_init_info(const char *initname){ +/****************************************************************************** + Information about a named init file. + + Maximum length of initname is 64. + + Returns PJ_INIT_INFO struct. + + If the init file is not found all members of + the return struct are set to 0. If the init file is found, but it the + metadata is missing, the value is set to "Unknown". + +******************************************************************************/ + int file_found, def_found=0; + char param[80], key[74]; + paralist *start, *next; + PJ_INIT_INFO info; + PJ_CONTEXT *ctx = pj_get_default_ctx(); + + memset(&info, 0, sizeof(PJ_INIT_INFO)); + + file_found = pj_find_file(ctx, initname, info.filename, sizeof(info.filename)); + if (!file_found || strlen(initname) > 64) { + return info; + } + + pj_strlcpy(info.name, initname, sizeof(info.name)); + strcpy(info.origin, "Unknown"); + strcpy(info.version, "Unknown"); + strcpy(info.lastupdate, "Unknown"); + + pj_strlcpy(key, initname, 64); /* make room for ":metadata\0" at the end */ + strncat(key, ":metadata", 9); + strcpy(param, "+init="); + strncat(param, key, 73); + + start = pj_mkparam(param); + next = pj_get_init(ctx, &start, start, key, &def_found); + + if (pj_param(ctx, start, "tversion").i) { + pj_strlcpy(info.version, pj_param(ctx, start, "sversion").s, sizeof(info.version)); + } + + if (pj_param(ctx, start, "torigin").i) { + pj_strlcpy(info.origin, pj_param(ctx, start, "sorigin").s, sizeof(info.origin)); + } + + if (pj_param(ctx, start, "tlastupdate").i) { + pj_strlcpy(info.lastupdate, pj_param(ctx, start, "slastupdate").s, sizeof(info.lastupdate)); + } + + for ( ; start; start = next) { + next = start->next; + pj_dalloc(start); + } + + return info; } @@ -565,18 +776,9 @@ PJ_FACTORS proj_factors(const PJ *P, const LP lp) { } -/* Release, or free, memory that was retrieved by the above functions */ -void *proj_release (void *buffer) { - return pj_dealloc (buffer); -} - - double proj_torad (double angle_in_degrees) { return PJ_TORAD (angle_in_degrees);} double proj_todeg (double angle_in_radians) { return PJ_TODEG (angle_in_radians);} -int proj_has_inverse(PJ *P) { - return (P->inv != 0 || P->inv3d != 0 || P->invobs != 0); -} double proj_dmstor(const char *is, char **rs) { return dmstor(is, rs); |
