summaryrefslogtreecommitdiff
path: root/src/3rdparty/proj/pj_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/proj/pj_init.c')
-rw-r--r--src/3rdparty/proj/pj_init.c416
1 files changed, 416 insertions, 0 deletions
diff --git a/src/3rdparty/proj/pj_init.c b/src/3rdparty/proj/pj_init.c
new file mode 100644
index 00000000..867fc41c
--- /dev/null
+++ b/src/3rdparty/proj/pj_init.c
@@ -0,0 +1,416 @@
+/******************************************************************************
+ * $Id: pj_init.c 1630 2009-09-24 02:14:06Z warmerdam $
+ *
+ * Project: PROJ.4
+ * Purpose: Initialize projection object from string definition. Includes
+ * pj_init(), pj_init_plus() and pj_free() function.
+ * Author: Gerald Evenden, Frank Warmerdam <warmerdam@pobox.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 1995, Gerald Evenden
+ * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
+ *
+ * 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.
+ *****************************************************************************/
+
+#define PJ_LIB__
+#include <projects.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <locale.h>
+
+PJ_CVSID("$Id: pj_init.c 1630 2009-09-24 02:14:06Z warmerdam $");
+
+extern FILE *pj_open_lib(char *, char *);
+
+/************************************************************************/
+/* get_opt() */
+/************************************************************************/
+static paralist *
+get_opt(paralist **start, FILE *fid, char *name, paralist *next) {
+ char sword[302], *word = sword+1;
+ int first = 1, len, c;
+
+ len = strlen(name);
+ *sword = 't';
+ while (fscanf(fid, "%300s", word) == 1) {
+ if (*word == '#') /* skip comments */
+ while((c = fgetc(fid)) != EOF && c != '\n') ;
+ else if (*word == '<') { /* control name */
+ if (first && !strncmp(name, word + 1, len)
+ && word[len + 1] == '>')
+ first = 0;
+ else if (!first && *word == '<') {
+ while((c = fgetc(fid)) != EOF && c != '\n') ;
+ break;
+ }
+ } else if (!first && !pj_param(*start, sword).i) {
+ /* don't default ellipse if datum, ellps or any earth model
+ information is set. */
+ if( strncmp(word,"ellps=",6) != 0
+ || (!pj_param(*start, "tdatum").i
+ && !pj_param(*start, "tellps").i
+ && !pj_param(*start, "ta").i
+ && !pj_param(*start, "tb").i
+ && !pj_param(*start, "trf").i
+ && !pj_param(*start, "tf").i) )
+ {
+ next = next->next = pj_mkparam(word);
+ }
+ }
+ }
+
+ if (errno == 25)
+ errno = 0;
+ return next;
+}
+
+/************************************************************************/
+/* get_defaults() */
+/************************************************************************/
+static paralist *
+get_defaults(paralist **start, paralist *next, char *name) {
+ FILE *fid;
+
+ if (fid = pj_open_lib("proj_def.dat", "rt")) {
+ next = get_opt(start, fid, "general", next);
+ rewind(fid);
+ next = get_opt(start, fid, name, next);
+ (void)fclose(fid);
+ }
+ if (errno)
+ errno = 0; /* don't care if can't open file */
+ return next;
+}
+
+/************************************************************************/
+/* get_init() */
+/************************************************************************/
+static paralist *
+get_init(paralist **start, paralist *next, char *name) {
+ char fname[MAX_PATH_FILENAME+ID_TAG_MAX+3], *opt;
+ FILE *fid;
+ paralist *init_items = NULL;
+ const paralist *orig_next = next;
+
+ (void)strncpy(fname, name, MAX_PATH_FILENAME + ID_TAG_MAX + 1);
+
+ /*
+ ** Search for file/key pair in cache
+ */
+
+ init_items = pj_search_initcache( name );
+ if( init_items != NULL )
+ {
+ next->next = init_items;
+ while( next->next != NULL )
+ next = next->next;
+ return next;
+ }
+
+ /*
+ ** Otherwise we try to open the file and search for it.
+ */
+ if (opt = strrchr(fname, ':'))
+ *opt++ = '\0';
+ else { pj_errno = -3; return(0); }
+ if (fid = pj_open_lib(fname, "rt"))
+ next = get_opt(start, fid, opt, next);
+ else
+ return(0);
+ (void)fclose(fid);
+ if (errno == 25)
+ errno = 0; /* unknown problem with some sys errno<-25 */
+
+ /*
+ ** If we seem to have gotten a result, insert it into the
+ ** init file cache.
+ */
+ if( next != NULL && next != orig_next )
+ pj_insert_initcache( name, orig_next->next );
+
+ return next;
+}
+
+/************************************************************************/
+/* pj_init_plus() */
+/* */
+/* Same as pj_init() except it takes one argument string with */
+/* individual arguments preceeded by '+', such as "+proj=utm */
+/* +zone=11 +ellps=WGS84". */
+/************************************************************************/
+
+PJ *
+pj_init_plus( const char *definition )
+
+{
+#define MAX_ARG 200
+ char *argv[MAX_ARG];
+ char *defn_copy;
+ int argc = 0, i;
+ PJ *result;
+
+ /* make a copy that we can manipulate */
+ defn_copy = (char *) pj_malloc( strlen(definition)+1 );
+ 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' )
+ {
+ if( argc+1 == MAX_ARG )
+ {
+ pj_errno = -44;
+ return NULL;
+ }
+
+ argv[argc++] = defn_copy + i + 1;
+ }
+ break;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ defn_copy[i] = '\0';
+ break;
+
+ default:
+ /* do nothing */;
+ }
+ }
+
+ /* perform actual initialization */
+ result = pj_init( argc, argv );
+
+ pj_dalloc( defn_copy );
+
+ return result;
+}
+
+/************************************************************************/
+/* pj_init() */
+/* */
+/* Main entry point for initialing a PJ projections */
+/* definition. Note that the projection specific function is */
+/* called to do the initial allocation so it can be created */
+/* large enough to hold projection specific parameters. */
+/************************************************************************/
+
+PJ *
+pj_init(int argc, char **argv) {
+ char *s, *name;
+ paralist *start = NULL;
+ PJ *(*proj)(PJ *);
+ paralist *curr;
+ int i;
+ PJ *PIN = 0;
+ const char *old_locale;
+
+ errno = pj_errno = 0;
+ start = NULL;
+
+ old_locale = setlocale(LC_NUMERIC, NULL);
+ setlocale(LC_NUMERIC,"C");
+
+ /* put arguments into internal linked list */
+ if (argc <= 0) { pj_errno = -1; goto bum_call; }
+ for (i = 0; i < argc; ++i)
+ if (i)
+ curr = curr->next = pj_mkparam(argv[i]);
+ else
+ start = curr = pj_mkparam(argv[i]);
+ if (pj_errno) goto bum_call;
+
+ /* check if +init present */
+ if (pj_param(start, "tinit").i) {
+ paralist *last = curr;
+
+ if (!(curr = get_init(&start, curr, pj_param(start, "sinit").s)))
+ goto bum_call;
+ if (curr == last) { pj_errno = -2; goto bum_call; }
+ }
+
+ /* find projection selection */
+ if (!(name = pj_param(start, "sproj").s))
+ { pj_errno = -4; goto bum_call; }
+ for (i = 0; (s = pj_list[i].id) && strcmp(name, s) ; ++i) ;
+ if (!s) { pj_errno = -5; goto bum_call; }
+
+ /* set defaults, unless inhibited */
+ if (!pj_param(start, "bno_defs").i)
+ curr = get_defaults(&start, curr, name);
+ proj = (PJ *(*)(PJ *)) pj_list[i].proj;
+
+ /* allocate projection structure */
+ if (!(PIN = (*proj)(0))) goto bum_call;
+ PIN->params = start;
+ PIN->is_latlong = 0;
+ PIN->is_geocent = 0;
+ PIN->long_wrap_center = 0.0;
+
+ /* set datum parameters */
+ if (pj_datum_set(start, PIN)) goto bum_call;
+
+ /* set ellipsoid/sphere parameters */
+ if (pj_ell_set(start, &PIN->a, &PIN->es)) goto bum_call;
+
+ PIN->a_orig = PIN->a;
+ PIN->es_orig = PIN->es;
+
+ PIN->e = sqrt(PIN->es);
+ PIN->ra = 1. / PIN->a;
+ PIN->one_es = 1. - PIN->es;
+ if (PIN->one_es == 0.) { pj_errno = -6; goto bum_call; }
+ PIN->rone_es = 1./PIN->one_es;
+
+ /* Now that we have ellipse information check for WGS84 datum */
+ if( PIN->datum_type == PJD_3PARAM
+ && PIN->datum_params[0] == 0.0
+ && PIN->datum_params[1] == 0.0
+ && PIN->datum_params[2] == 0.0
+ && PIN->a == 6378137.0
+ && ABS(PIN->es - 0.006694379990) < 0.000000000050 )/*WGS84/GRS80*/
+ {
+ PIN->datum_type = PJD_WGS84;
+ }
+
+ /* set PIN->geoc coordinate system */
+ PIN->geoc = (PIN->es && pj_param(start, "bgeoc").i);
+
+ /* over-ranging flag */
+ PIN->over = pj_param(start, "bover").i;
+
+ /* longitude center for wrapping */
+ PIN->long_wrap_center = pj_param(start, "rlon_wrap").f;
+
+ /* central meridian */
+ PIN->lam0=pj_param(start, "rlon_0").f;
+
+ /* central latitude */
+ PIN->phi0 = pj_param(start, "rlat_0").f;
+
+ /* false easting and northing */
+ PIN->x0 = pj_param(start, "dx_0").f;
+ PIN->y0 = pj_param(start, "dy_0").f;
+
+ /* general scaling factor */
+ if (pj_param(start, "tk_0").i)
+ PIN->k0 = pj_param(start, "dk_0").f;
+ else if (pj_param(start, "tk").i)
+ PIN->k0 = pj_param(start, "dk").f;
+ else
+ PIN->k0 = 1.;
+ if (PIN->k0 <= 0.) {
+ pj_errno = -31;
+ goto bum_call;
+ }
+
+ /* set units */
+ s = 0;
+ if (name = pj_param(start, "sunits").s) {
+ for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i) ;
+ if (!s) { pj_errno = -7; goto bum_call; }
+ s = pj_units[i].to_meter;
+ }
+ if (s || (s = pj_param(start, "sto_meter").s)) {
+ PIN->to_meter = strtod(s, &s);
+ if (*s == '/') /* ratio number */
+ PIN->to_meter /= strtod(++s, 0);
+ PIN->fr_meter = 1. / PIN->to_meter;
+ } else
+ PIN->to_meter = PIN->fr_meter = 1.;
+
+ /* prime meridian */
+ s = 0;
+ if (name = pj_param(start, "spm").s) {
+ const char *value = NULL;
+ char *next_str = NULL;
+
+ for (i = 0; pj_prime_meridians[i].id != NULL; ++i )
+ {
+ if( strcmp(name,pj_prime_meridians[i].id) == 0 )
+ {
+ value = pj_prime_meridians[i].defn;
+ break;
+ }
+ }
+
+ if( value == NULL
+ && (dmstor(name,&next_str) != 0.0 || *name == '0')
+ && *next_str == '\0' )
+ value = name;
+
+ if (!value) { pj_errno = -46; goto bum_call; }
+ PIN->from_greenwich = dmstor(value,NULL);
+ }
+ else
+ PIN->from_greenwich = 0.0;
+
+ /* projection specific initialization */
+ if (!(PIN = (*proj)(PIN)) || errno || pj_errno) {
+bum_call: /* cleanup error return */
+ if (!pj_errno)
+ pj_errno = errno;
+ if (PIN)
+ pj_free(PIN);
+ else
+ for ( ; start; start = curr) {
+ curr = start->next;
+ pj_dalloc(start);
+ }
+ PIN = 0;
+ }
+ setlocale(LC_NUMERIC,old_locale);
+
+ return PIN;
+}
+
+/************************************************************************/
+/* pj_free() */
+/* */
+/* This is the application callable entry point for destroying */
+/* a projection definition. It does work generic to all */
+/* projection types, and then calls the projection specific */
+/* free function (P->pfree()) to do local work. This maps to */
+/* the FREEUP code in the individual projection source files. */
+/************************************************************************/
+
+void
+pj_free(PJ *P) {
+ if (P) {
+ paralist *t = P->params, *n;
+
+ /* free parameter list elements */
+ for (t = P->params; t; t = n) {
+ n = t->next;
+ pj_dalloc(t);
+ }
+
+ /* free projection parameters */
+ P->pfree(P);
+ }
+}
+
+