Пример #1
0
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;
}
Пример #2
0
PJ *
pj_init_ctx(projCtx ctx, int argc, char **argv) {
    char *s, *name;
    PJ_CONSTRUCTOR proj;
    paralist *curr, *init, *start;
    int i;
    int err;
    PJ *PIN = 0;
    int n_pipelines = 0;
    int n_inits = 0;

    if (0==ctx)
        ctx = pj_get_default_ctx ();

    ctx->last_errno = 0;

    if (argc <= 0) {
        pj_ctx_set_errno (ctx, PJD_ERR_NO_ARGS);
        return 0;
    }

    /* count occurrences of pipelines and inits */
    for (i = 0; i < argc; ++i) {
        if (!strcmp (argv[i], "+proj=pipeline") || !strcmp(argv[i], "proj=pipeline") )
                n_pipelines++;
        if (!strncmp (argv[i], "+init=", 6) || !strncmp(argv[i], "init=", 5))
            n_inits++;
    }

    /* can't have nested pipelines directly */
    if (n_pipelines > 1) {
        pj_ctx_set_errno (ctx, PJD_ERR_MALFORMED_PIPELINE);
        return 0;
    }

    /* don't allow more than one +init in non-pipeline operations */
    if (n_pipelines == 0 && n_inits > 1) {
        pj_ctx_set_errno (ctx, PJD_ERR_TOO_MANY_INITS);
        return 0;
    }


    /* put arguments into internal linked list */
    start = curr = pj_mkparam(argv[0]);
    if (!curr)
        return pj_dealloc_params (ctx, start, ENOMEM);

    for (i = 1; i < argc; ++i) {
        curr->next = pj_mkparam(argv[i]);
        if (!curr->next)
            return pj_dealloc_params (ctx, start, ENOMEM);
        curr = curr->next;
    }


    /* Only expand '+init's in non-pipeline operations. '+init's in pipelines are */
    /* expanded in the individual pipeline steps during pipeline initialization.  */
    /* Potentially this leads to many nested pipelines, which shouldn't be a      */
    /* problem when '+init's are expanded as late as possible.                    */
    init = pj_param_exists (start, "init");
    if (init && n_pipelines == 0) {
        init = pj_expand_init (ctx, init);
        if (!init)
            return pj_dealloc_params (ctx, start, PJD_ERR_NO_ARGS);
    }
    if (ctx->last_errno)
        return pj_dealloc_params (ctx, start, ctx->last_errno);

    /* Find projection selection */
    curr = pj_param_exists (start, "proj");
    if (0==curr)
        return pj_dealloc_params (ctx, start, PJD_ERR_PROJ_NOT_NAMED);
    name =  curr->param;
    if (strlen (name) < 6)
        return pj_dealloc_params (ctx, start, PJD_ERR_PROJ_NOT_NAMED);
    name += 5;

    proj = locate_constructor (name);
    if (0==proj)
        return pj_dealloc_params (ctx, start, PJD_ERR_UNKNOWN_PROJECTION_ID);


    /* Append general and projection specific defaults to the definition list */
    append_defaults_to_paralist (ctx, start, "general");
    append_defaults_to_paralist (ctx, start, name);


    /* Allocate projection structure */
    PIN = proj(0);
    if (0==PIN)
        return pj_dealloc_params (ctx, start, ENOMEM);


    PIN->ctx = ctx;
    PIN->params = start;
    PIN->is_latlong = 0;
    PIN->is_geocent = 0;
    PIN->is_long_wrap_set = 0;
    PIN->long_wrap_center = 0.0;
    strcpy( PIN->axis, "enu" );

    PIN->gridlist = NULL;
    PIN->gridlist_count = 0;

    PIN->vgridlist_geoid = NULL;
    PIN->vgridlist_geoid_count = 0;

    /* Set datum parameters. Similarly to +init parameters we want to expand    */
    /* +datum parameters as late as possible when dealing with pipelines.       */
    /* otherwise only the first occurrence of +datum will be expanded and that */
    if (n_pipelines == 0) {
        if (pj_datum_set(ctx, start, PIN))
            return pj_default_destructor (PIN, proj_errno(PIN));
    }

    err = pj_ellipsoid (PIN);

    if (err) {
        /* Didn't get an ellps, but doesn't need one: Get a free WGS84 */
        if (PIN->need_ellps) {
            pj_log (ctx, PJ_LOG_DEBUG_MINOR, "pj_init_ctx: Must specify ellipsoid or sphere");
            return pj_default_destructor (PIN, proj_errno(PIN));
        }
        else {
            if (PJD_ERR_MAJOR_AXIS_NOT_GIVEN==proj_errno (PIN))
                proj_errno_reset (PIN);
            PIN->f = 1.0/298.257223563;
            PIN->a_orig  = PIN->a  = 6378137.0;
            PIN->es_orig = PIN->es = PIN->f*(2-PIN->f);
        }
    }
    PIN->a_orig = PIN->a;
    PIN->es_orig = PIN->es;
    if (pj_calc_ellipsoid_params (PIN, PIN->a, PIN->es))
        return pj_default_destructor (PIN, PJD_ERR_ECCENTRICITY_IS_ONE);

    /* 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 != 0.0 && pj_param(ctx, start, "bgeoc").i);

    /* Over-ranging flag */
    PIN->over = pj_param(ctx, start, "bover").i;

    /* Vertical datum geoid grids */
    PIN->has_geoid_vgrids = pj_param(ctx, start, "tgeoidgrids").i;
    if( PIN->has_geoid_vgrids ) /* we need to mark it as used. */
        pj_param(ctx, start, "sgeoidgrids");

    /* Longitude center for wrapping */
    PIN->is_long_wrap_set = pj_param(ctx, start, "tlon_wrap").i;
    if (PIN->is_long_wrap_set) {
        PIN->long_wrap_center = pj_param(ctx, start, "rlon_wrap").f;
        /* Don't accept excessive values otherwise we might perform badly */
        /* when correcting longitudes around it */
        /* The test is written this way to error on long_wrap_center "=" NaN */
        if( !(fabs(PIN->long_wrap_center) < 10 * M_TWOPI) )
            return pj_default_destructor (PIN, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT);
    }

    /* Axis orientation */
    if( (pj_param(ctx, start,"saxis").s) != NULL )
    {
        const char *axis_legal = "ewnsud";
        const char *axis_arg = pj_param(ctx, start,"saxis").s;
        if( strlen(axis_arg) != 3 )
            return pj_default_destructor (PIN, PJD_ERR_AXIS);

        if( strchr( axis_legal, axis_arg[0] ) == NULL
            || strchr( axis_legal, axis_arg[1] ) == NULL
            || strchr( axis_legal, axis_arg[2] ) == NULL)
            return pj_default_destructor (PIN, PJD_ERR_AXIS);

        /* TODO: it would be nice to validate we don't have on axis repeated */
        strcpy( PIN->axis, axis_arg );
    }

    /* Central meridian */
    PIN->lam0=pj_param(ctx, start, "rlon_0").f;

    /* Central latitude */
    PIN->phi0 = pj_param(ctx, start, "rlat_0").f;

    /* False easting and northing */
    PIN->x0 = pj_param(ctx, start, "dx_0").f;
    PIN->y0 = pj_param(ctx, start, "dy_0").f;
    PIN->z0 = pj_param(ctx, start, "dz_0").f;
    PIN->t0 = pj_param(ctx, start, "dt_0").f;

    /* General scaling factor */
    if (pj_param(ctx, start, "tk_0").i)
        PIN->k0 = pj_param(ctx, start, "dk_0").f;
    else if (pj_param(ctx, start, "tk").i)
        PIN->k0 = pj_param(ctx, start, "dk").f;
    else
        PIN->k0 = 1.;
    if (PIN->k0 <= 0.)
        return pj_default_destructor (PIN, PJD_ERR_K_LESS_THAN_ZERO);

    /* Set units */
    s = 0;
    if ((name = pj_param(ctx, start, "sunits").s) != NULL) {
        for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i) ;
        if (!s)
            return pj_default_destructor (PIN, PJD_ERR_UNKNOWN_UNIT_ID);
        s = pj_units[i].to_meter;
    }
    if (s || (s = pj_param(ctx, start, "sto_meter").s)) {
        double factor;
        int ratio = 0;

        /* ratio number? */
        if (strlen (s) > 1 && s[0] == '1' && s[1]=='/') {
            ratio = 1;
            s += 2;
        }

        factor = pj_strtod(s, &s);
        if ((factor <= 0.0) || (1/factor==0))
            return pj_default_destructor (PIN, PJD_ERR_UNIT_FACTOR_LESS_THAN_0);

        PIN->to_meter = ratio?  1 / factor: factor;
        PIN->fr_meter = 1 / PIN->to_meter;

    } else
        PIN->to_meter = PIN->fr_meter = 1.;

    /* Set vertical units */
    s = 0;
    if ((name = pj_param(ctx, start, "svunits").s) != NULL) {
        for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i) ;
        if (!s)
            return pj_default_destructor (PIN, PJD_ERR_UNKNOWN_UNIT_ID);
        s = pj_units[i].to_meter;
    }
    if (s || (s = pj_param(ctx, start, "svto_meter").s)) {
        PIN->vto_meter = pj_strtod(s, &s);
        if (*s == '/') /* ratio number */
            PIN->vto_meter /= pj_strtod(++s, 0);
        if (PIN->vto_meter <= 0.0)
            return pj_default_destructor (PIN, PJD_ERR_UNIT_FACTOR_LESS_THAN_0);
        PIN->vfr_meter = 1. / PIN->vto_meter;
    } else {
        PIN->vto_meter = PIN->to_meter;
        PIN->vfr_meter = PIN->fr_meter;
    }

    /* Prime meridian */
    s = 0;
    if ((name = pj_param(ctx, start, "spm").s) != NULL) {
        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_ctx(ctx,name,&next_str) != 0.0  || *name == '0')
            && *next_str == '\0' )
            value = name;

        if (!value)
            return pj_default_destructor (PIN, PJD_ERR_UNKNOWN_PRIME_MERIDIAN);
        PIN->from_greenwich = dmstor_ctx(ctx,value,NULL);
    }
    else
        PIN->from_greenwich = 0.0;

    /* Private object for the geodesic functions */
    PIN->geod = pj_calloc (1, sizeof (struct geod_geodesic));
    if (0==PIN->geod)
        return pj_default_destructor (PIN, ENOMEM);
    geod_init(PIN->geod, PIN->a,  (1 - sqrt (1 - PIN->es)));

    /* Projection specific initialization */
    err = proj_errno_reset (PIN);
    PIN = proj(PIN);
    if (proj_errno (PIN)) {
        pj_free(PIN);
        return 0;
    }
    proj_errno_restore (PIN, err);
    return PIN;
}
parameters pj_init(R const& arguments, bool use_defaults = true)
{
    parameters pin;
    for (std::vector<std::string>::const_iterator it = boost::begin(arguments);
        it != boost::end(arguments); it++)
    {
        pin.params.push_back(pj_mkparam(*it));
    }

    /* check if +init present */
    if (pj_param(pin.params, "tinit").i)
    {
        // maybe TODO: handle "init" parameter
        //if (!(curr = get_init(&arguments, curr, pj_param(pin.params, "sinit").s)))
    }

    // find projection -> implemented in projection factory
    pin.name = pj_param(pin.params, "sproj").s;
    //if (pin.name.empty())
    //{ throw proj_exception(-4); }


    // set defaults, unless inhibited
    // GL-Addition, if use_defaults is false then defaults are ignored
    if (use_defaults && ! pj_param(pin.params, "bno_defs").i)
    {
        // proj4 gets defaults from "proj_def.dat", file of 94/02/23 with a few defaults.
        // Here manually
        if (pin.name == "lcc")
        {
            pin.params.push_back(pj_mkparam("lat_1=33"));
            pin.params.push_back(pj_mkparam("lat_2=45"));
        }
        else if (pin.name == "aea")
        {
            pin.params.push_back(pj_mkparam("lat_1=29.5"));
            pin.params.push_back(pj_mkparam("lat_2=45.5 "));
        }
        else
        {
            //<general>ellps=WGS84
        }
        //curr = get_defaults(&arguments, curr, name);
    }

    /* allocate projection structure */
    // done by constructor:
    // pin.is_latlong = 0;
    // pin.is_geocent = 0;
    // pin.long_wrap_center = 0.0;

    /* set datum parameters */
    pj_datum_set(pin.params, pin);

    /* set ellipsoid/sphere parameters */
    pj_ell_set(pin.params, pin.a, pin.es);

    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.) { throw proj_exception(-6); }
    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
        && geometry::math::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(pin.params, "bgeoc").i);

    /* over-ranging flag */
    pin.over = pj_param(pin.params, "bover").i;

    /* longitude center for wrapping */
    pin.long_wrap_center = pj_param(pin.params, "rlon_wrap").f;

    /* central meridian */
    pin.lam0 = pj_param(pin.params, "rlon_0").f;

    /* central latitude */
    pin.phi0 = pj_param(pin.params, "rlat_0").f;

    /* false easting and northing */
    pin.x0 = pj_param(pin.params, "dx_0").f;
    pin.y0 = pj_param(pin.params, "dy_0").f;

    /* general scaling factor */
    if (pj_param(pin.params, "tk_0").i)
        pin.k0 = pj_param(pin.params, "dk_0").f;
    else if (pj_param(pin.params, "tk").i)
        pin.k0 = pj_param(pin.params, "dk").f;
    else
        pin.k0 = 1.;
    if (pin.k0 <= 0.) {
        throw proj_exception(-31);
    }

    /* set units */
    std::string s;
    std::string units = pj_param(pin.params, "sunits").s;
    if (! units.empty())
    {
        const int n = sizeof(pj_units) / sizeof(pj_units[0]);
        int index = -1;
        for (int i = 0; i < n && index == -1; i++)
        {
            if(pj_units[i].id == units)
            {
                index = i;
            }
        }

        if (index == -1) { throw proj_exception(-7); }
        s = pj_units[index].to_meter;
    }

    if (s.empty())
    {
        s = pj_param(pin.params, "sto_meter").s;
    }

    if (! s.empty())
    {
        // TODO: IMPLEMENT SPLIT
        pin.to_meter = atof(s.c_str());
        //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.clear();
    std::string pm = pj_param(pin.params, "spm").s;
    if (! pm.empty())
    {
        std::string value;

        int n = sizeof(pj_prime_meridians) / sizeof(pj_prime_meridians[0]);
        int index = -1;
        for (int i = 0; i < n && index == -1; i++)
        {
            if(pj_prime_meridians[i].id == pm)
            {
                value = pj_prime_meridians[i].defn;
                index = i;
            }
        }

        if (index == -1) { throw proj_exception(-7); }
        if (value.empty()) { throw proj_exception(-46); }

        geometry::strategy::dms_parser<true> parser;
        pin.from_greenwich = parser(value.c_str());
    }
    else
    {
        pin.from_greenwich = 0.0;
    }

    return pin;
}
Пример #4
0
PJ *
pj_init_ctx(projCtx ctx, int argc, char **argv) {
    char *s, *name;
    paralist *start = NULL;
    PJ *(*proj)(PJ *);
    paralist *curr;
    int i;
    PJ *PIN = 0;
    char *old_locale;

    ctx->last_errno = 0;
    start = NULL;

    old_locale = strdup(setlocale(LC_NUMERIC, NULL));
    if( strcmp(old_locale,"C") != 0 )
        setlocale(LC_NUMERIC,"C");

    /* put arguments into internal linked list */
    if (argc <= 0) { pj_ctx_set_errno( ctx, -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 (ctx->last_errno) goto bum_call;

    /* check if +init present */
    if (pj_param(ctx, start, "tinit").i) {
        paralist *last = curr;

        if (!(curr = get_init(ctx,&start, curr, pj_param(ctx, start, "sinit").s)))
            goto bum_call;
        if (curr == last) { pj_ctx_set_errno( ctx, -2); goto bum_call; }
    }

    /* find projection selection */
    if (!(name = pj_param(ctx, start, "sproj").s))
    { pj_ctx_set_errno( ctx, -4 ); goto bum_call; }
    for (i = 0; (s = pj_list[i].id) && strcmp(name, s) ; ++i) ;
    if (!s) { pj_ctx_set_errno( ctx, -5 ); goto bum_call; }

    /* set defaults, unless inhibited */
    if (!pj_param(ctx, start, "bno_defs").i)
        curr = get_defaults(ctx,&start, curr, name);
    proj = (PJ *(*)(PJ *)) pj_list[i].proj;

    /* allocate projection structure */
    if (!(PIN = (*proj)(0))) goto bum_call;
    PIN->ctx = ctx;
    PIN->params = start;
    PIN->is_latlong = 0;
    PIN->is_geocent = 0;
    PIN->is_long_wrap_set = 0;
    PIN->long_wrap_center = 0.0;
    strcpy( PIN->axis, "enu" );

    PIN->gridlist = NULL;
    PIN->gridlist_count = 0;

    PIN->vgridlist_geoid = NULL;
    PIN->vgridlist_geoid_count = 0;

    /* set datum parameters */
    if (pj_datum_set(ctx, start, PIN)) goto bum_call;

    /* set ellipsoid/sphere parameters */
    if (pj_ell_set(ctx, 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_ctx_set_errno( ctx, -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(ctx, start, "bgeoc").i);

    /* over-ranging flag */
    PIN->over = pj_param(ctx, start, "bover").i;

    /* vertical datum geoid grids */
    PIN->has_geoid_vgrids = pj_param(ctx, start, "tgeoidgrids").i;
    if( PIN->has_geoid_vgrids ) /* we need to mark it as used. */
        pj_param(ctx, start, "sgeoidgrids");

    /* longitude center for wrapping */
    PIN->is_long_wrap_set = pj_param(ctx, start, "tlon_wrap").i;
    if (PIN->is_long_wrap_set)
        PIN->long_wrap_center = pj_param(ctx, start, "rlon_wrap").f;

    /* axis orientation */
    if( (pj_param(ctx, start,"saxis").s) != NULL )
    {
        static const char *axis_legal = "ewnsud";
        const char *axis_arg = pj_param(ctx, start,"saxis").s;
        if( strlen(axis_arg) != 3 )
        {
            pj_ctx_set_errno( ctx, PJD_ERR_AXIS );
            goto bum_call;
        }

        if( strchr( axis_legal, axis_arg[0] ) == NULL
            || strchr( axis_legal, axis_arg[1] ) == NULL
            || strchr( axis_legal, axis_arg[2] ) == NULL)
        {
            pj_ctx_set_errno( ctx, PJD_ERR_AXIS );
            goto bum_call;
        }

        /* it would be nice to validate we don't have on axis repeated */
        strcpy( PIN->axis, axis_arg );
    }

    PIN->is_long_wrap_set = pj_param(ctx, start, "tlon_wrap").i;
    if (PIN->is_long_wrap_set)
        PIN->long_wrap_center = pj_param(ctx, start, "rlon_wrap").f;

    /* central meridian */
    PIN->lam0=pj_param(ctx, start, "rlon_0").f;

    /* central latitude */
    PIN->phi0 = pj_param(ctx, start, "rlat_0").f;

    /* false easting and northing */
    PIN->x0 = pj_param(ctx, start, "dx_0").f;
    PIN->y0 = pj_param(ctx, start, "dy_0").f;

    /* general scaling factor */
    if (pj_param(ctx, start, "tk_0").i)
        PIN->k0 = pj_param(ctx, start, "dk_0").f;
    else if (pj_param(ctx, start, "tk").i)
        PIN->k0 = pj_param(ctx, start, "dk").f;
    else
        PIN->k0 = 1.;
    if (PIN->k0 <= 0.) {
        pj_ctx_set_errno( ctx, -31 );
        goto bum_call;
    }

    /* set units */
    s = 0;
    if ((name = pj_param(ctx, start, "sunits").s) != NULL) { 
        for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i) ;
        if (!s) { pj_ctx_set_errno( ctx, -7 ); goto bum_call; }
        s = pj_units[i].to_meter;
    }
    if (s || (s = pj_param(ctx, 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.;

    /* set vertical units */
    s = 0;
    if ((name = pj_param(ctx, start, "svunits").s) != NULL) { 
        for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i) ;
        if (!s) { pj_ctx_set_errno( ctx, -7 ); goto bum_call; }
        s = pj_units[i].to_meter;
    }
    if (s || (s = pj_param(ctx, start, "svto_meter").s)) {
        PIN->vto_meter = strtod(s, &s);
        if (*s == '/') /* ratio number */
            PIN->vto_meter /= strtod(++s, 0);
        PIN->vfr_meter = 1. / PIN->vto_meter;
    } else {
        PIN->vto_meter = PIN->to_meter;
        PIN->vfr_meter = PIN->fr_meter;
    }

    /* prime meridian */
    s = 0;
    if ((name = pj_param(ctx, start, "spm").s) != NULL) { 
        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_ctx(ctx,name,&next_str) != 0.0  || *name == '0')
            && *next_str == '\0' )
            value = name;

        if (!value) { pj_ctx_set_errno( ctx, -46 ); goto bum_call; }
        PIN->from_greenwich = dmstor_ctx(ctx,value,NULL);
    }
    else
        PIN->from_greenwich = 0.0;

    /* projection specific initialization */
    if (!(PIN = (*proj)(PIN)) || ctx->last_errno) {
      bum_call: /* cleanup error return */
        if (PIN)
            pj_free(PIN);
        else
            for ( ; start; start = curr) {
                curr = start->next;
                pj_dalloc(start);
            }
        PIN = 0;
    }

    if( strcmp(old_locale,"C") != 0 )
        setlocale(LC_NUMERIC,old_locale);
    free( (char*)old_locale );

    return PIN;
}