PROJ * proj_init(int argc, char **argv) { const char *s, *name; PROJ *(*proj)(PROJ *); paralist *curr = 0, *start = 0; int i; PROJ *PIN = 0; errno = proj_errno = 0; /* put arguments into internal linked list */ if (argc <= 0) { proj_errno = -1; goto bum_call; } for (i = 0; i < argc; ++i) if (i) curr = curr->next = proj_mkparam(argv[i]); else start = curr = proj_mkparam(argv[i]); if (proj_errno) goto bum_call; /* find projection selection */ if (!(name = proj_param(start, "sproj").s)) { proj_errno = -4; goto bum_call; } for (i = 0; (s = proj_list[i].id) && strcmp(name, s) ; ++i) ; if (!s) { proj_errno = -5; goto bum_call; } proj = proj_list[i].proj; /* allocate projection structure */ if (!(PIN = (*proj)(0))) goto bum_call; PIN->params = start; /* set ellipsoid/sphere parameters */ if (proj_ell_set(start, &PIN->a, &PIN->es)) goto bum_call; PIN->e = sqrt(PIN->es); PIN->ra = 1. / PIN->a; PIN->one_es = 1. - PIN->es; if (PIN->one_es == 0.) { proj_errno = -6; goto bum_call; } PIN->rone_es = 1./PIN->one_es; /* set PIN->geoc coordinate system */ PIN->geoc = (PIN->es && proj_param(start, "bgeoc").i); /* over-ranging flag */ PIN->over = proj_param(start, "bover").i; /* central meridian */ PIN->lam0=proj_param(start, "rlon_0").f; /* central latitude */ PIN->phi0 = proj_param(start, "rlat_0").f; /* false easting and northing */ PIN->x0 = proj_param(start, "dx_0").f; PIN->y0 = proj_param(start, "dy_0").f; /* general scaling factor */ if (proj_param(start, "tk_0").i) PIN->k0 = proj_param(start, "dk_0").f; else if (proj_param(start, "tk").i) PIN->k0 = proj_param(start, "dk").f; else PIN->k0 = 1.; if (PIN->k0 <= 0.) { proj_errno = -31; goto bum_call; } /* set units */ s = 0; if ((name = proj_param(start, "sunits").s)) { for (i = 0; (s = proj_units[i].id) && strcmp(name, s) ; ++i) ; if (!s) { proj_errno = -7; goto bum_call; } s = proj_units[i].to_meter; } if (s || (s = proj_param(start, "sto_meter").s)) { PIN->to_meter = strtod(s, (char **)&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.; /* projection specific initialization */ if (!(PIN = (*proj)(PIN)) || errno || proj_errno) { bum_call: /* cleanup error return */ if (!proj_errno) proj_errno = errno; if (PIN) proj_free(PIN); else for ( ; start; start = curr) { curr = start->next; free(start); } PIN = 0; } return PIN; }
/* ** set ellipsoid parameters */ #include <lib_proj.h> #include <string.h> #define SIXTH .1666666666666666667 /* 1/6 */ #define RA4 .04722222222222222222 /* 17/360 */ #define RA6 .02215608465608465608 /* 67/3024 */ #define RV4 .06944444444444444444 /* 5/72 */ #define RV6 .04243827160493827160 /* 55/1296 */ int /* initialize geographic shape parameters */ proj_ell_set(paralist *pl, double *a, double *es) { int i; double b = 0., e; const char *name; paralist *start = 0, *curr; /* check for varying forms of ellipsoid input */ *a = *es = 0.; /* R takes precedence */ if (proj_param(pl, "tR").i) *a = proj_param(pl, "dR").f; else { /* probable elliptical figure */ /* check if ellps present and temporarily append its values to pl */ if ((name = proj_param(pl, "sellps").s)) { char *s; for (start = pl; start && start->next ; start = start->next) ; curr = start; for (i = 0; (s = proj_ellps[i].id) && strcmp(name, s) ; ++i) ; if (!s) { proj_errno = -9; return 1; } curr = curr->next = proj_mkparam(proj_ellps[i].major); curr = curr->next = proj_mkparam(proj_ellps[i].ell); } /* set major axis to unity if not spec'd */ *a = (proj_param(pl, "ta").i) ? proj_param(pl, "da").f : 1.; if (proj_param(pl, "tes").i) /* eccentricity squared */ *es = proj_param(pl, "des").f; else if (proj_param(pl, "te").i) { /* eccentricity */ e = proj_param(pl, "de").f; *es = e * e; } else if (proj_param(pl, "trf").i) { /* recip flattening */ *es = proj_param(pl, "drf").f; if (!*es) { proj_errno = -10; goto bomb; } *es = 1./ *es; *es = *es * (2. - *es); } else if (proj_param(pl, "tf").i) { /* flattening */ *es = proj_param(pl, "df").f; *es = *es * (2. - *es); } else if (proj_param(pl, "tb").i) { /* minor axis */ b = proj_param(pl, "db").f; *es = 1. - (b * b) / (*a * *a); } /* else *es == 0. and sphere of radius *a */ if (!b) b = *a * sqrt(1. - *es); /* following options turn ellipsoid into equivalent sphere */ if (proj_param(pl, "bR_A").i) { /* sphere--area of ellipsoid */ *a *= 1. - *es * (SIXTH + *es * (RA4 + *es * RA6)); *es = 0.; } else if (proj_param(pl, "bR_V").i) { /* sphere--vol. of ellipsoid */ *a *= 1. - *es * (SIXTH + *es * (RV4 + *es * RV6)); *es = 0.; } else if (proj_param(pl, "bR_a").i) { /* sphere--arithmetic mean */ *a = .5 * (*a + b); *es = 0.; } else if (proj_param(pl, "bR_g").i) { /* sphere--geometric mean */ *a = sqrt(*a * b); *es = 0.; } else if (proj_param(pl, "bR_h").i) { /* sphere--harmonic mean */ *a = 2. * *a * b / (*a + b); *es = 0.; } else if ((i = proj_param(pl, "tR_lat_a").i) || /* sphere--arith. */ proj_param(pl, "tR_lat_g").i) { /* or geom. mean at latitude */ double tmp; tmp = sin(proj_param(pl, i ? "rR_lat_a" : "rR_lat_g").f); if (fabs(tmp) > HALFPI) { proj_errno = -11; goto bomb; } tmp = 1. - *es * tmp * tmp; *a *= i ? .5 * (1. - *es + tmp) / ( tmp * sqrt(tmp)) : sqrt(1. - *es) / tmp; *es = 0.; } bomb: if (start) { /* clean up temporary extension of list */ free(start->next->next); free(start->next); start->next = 0; } if (proj_errno) return 1; } /* some remaining checks */ if (*es < 0.) { proj_errno = -12; return 1; } if (*a <= 0.) { proj_errno = -13; return 1; } return 0; }