int EXP_LVL9 CSpstroI (Const struct cs_Pstro_ *pstro,double ll [2],Const double xy [2]) { extern double cs_Radian; /* 57.29577..... */ extern double cs_Two; /* 2.0 */ extern double cs_Pi_o_2; /* PI over 2.0 */ extern double cs_NPTest; /* 0.001 seconds of arc short of the north pole, in radians. */ int rtn_val; double x; double y; double c; double t; double chi; double rho; double cos_c; rtn_val = cs_CNVRT_NRML; /* Adjust for a non-standard quadrant. */ if (pstro->quad == 0) { x = xy [XX] - pstro->x_off; y = xy [YY] - pstro->y_off; } else { CS_quadI (&x,&y,xy,pstro->x_off,pstro->y_off,pstro->quad); } /* If x and y are now both zero, or very close to it, we must just set the result to the origin of the projection. We don't want to divide by rho if it's zero. */ rho = sqrt (x * x + y * y); if (rho <= pstro->one_mm) { /* The coordinate is essentially zero. Return the origin of the coordinate system. */ ll [LNG] = pstro->org_lng * cs_Radian; ll [LAT] = pstro->org_lat * cs_Radian; return (rtn_val); } /* Now we can convert back to lat/longs. */ if (pstro->ecent == 0.0) { /* Here for the sphere. Note, we have already filtered out cases where rho is zero (or very close to zero). Note, rho can approach infinity, although considering values greater than two_ka out of the domain would be generally acceptable. Read c as the angular distance from the origin. */ c = cs_Two * atan (rho / pstro->two_ka); cos_c = cos (c); switch (pstro->aspect) { default: case cs_STERO_NORTH: ll [LNG] = pstro->org_lng + atan2 (x,-y); ll [LAT] = asin (cos_c); break; case cs_STERO_SOUTH: ll [LNG] = -pstro->org_lng + atan2 (-x,y); ll [LAT] = -asin (cos_c); break; } } else { /* Here for the ellisoid. */ switch (pstro->aspect) { default: case cs_STERO_NORTH: ll [LNG] = pstro->org_lng + atan2 (x,-y); t = rho * pstro->e_term / pstro->two_ka; chi = cs_Pi_o_2 - (cs_Two * atan (t)); ll [LAT] = CSchiIcal (&pstro->chicofI,chi); break; case cs_STERO_SOUTH: ll [LNG] = pstro->org_lng - atan2 (-x,y); t = rho * pstro->e_term / pstro->two_ka; chi = (cs_Two * atan (t)) - cs_Pi_o_2; ll [LAT] = CSchiIcal (&pstro->chicofI,chi); break; } } if (fabs (ll [LAT]) > cs_NPTest && rtn_val == cs_CNVRT_NRML) /*lint !e774 */ { rtn_val = cs_CNVRT_INDF; } /* Convert the results to degrees. */ ll [LNG] *= cs_Radian; ll [LAT] *= cs_Radian; return (rtn_val); }
int EXP_LVL9 CSmrcatI (Const struct cs_Mrcat_ *mrcat,double ll [2],Const double xy [2]) { extern double cs_Radian; /* 57.29577... */ extern double cs_Pi_o_2; /* Pi / 2.0 */ extern double cs_3Pi_o_2; /* 3 Pi / 2.0 */ extern double cs_Two; /* 2.0 */ int rtn_val; double xx; double yy; double chi; double lat; double del_lng; double tmp1; rtn_val = cs_CNVRT_NRML; /* Remove whatever offsets are active. */ if (mrcat->quad == 0) { xx = xy [XX] - mrcat->x_off; yy = xy [YY] - mrcat->y_off; } else { CS_quadI (&xx,&yy,xy,mrcat->x_off,mrcat->y_off,mrcat->quad); } /* Check the Y value for range. */ if (fabs (yy) > mrcat->yy_max) { rtn_val = cs_CNVRT_RNG; yy = (yy >= 0.0) ? mrcat->yy_max : -mrcat->yy_max; } /* The longitude calculation is the same for both the spherical and ellipsoidal cases. There may be a slight difference if the standard parallel is not the equator, but tis is taken care of during set up and shows up in the Rfact variable. */ del_lng = xx / mrcat->Rfact; if (fabs (del_lng) >= cs_3Pi_o_2) { rtn_val = cs_CNVRT_RNG; del_lng = CS_adj2pi (del_lng); } /* The following is used for sphere and ellipsoid. */ tmp1 = exp (-yy / mrcat->Rfact); chi = cs_Pi_o_2 - cs_Two * atan (tmp1); /* Finish off the latitude as appropriate. */ if (mrcat->ecent == 0.0) { /* Here for a sphere. */ lat = chi; } else { /* Here for an ellipsoid. This is a series expansion used in other projections, so we have a function to do this for us. */ lat = CSchiIcal (&mrcat->chicofI,chi); } ll [LNG] = (del_lng + mrcat->cent_lng) * cs_Radian; ll [LAT] = lat * cs_Radian; return (rtn_val); }