int EXP_LVL9 CSvdgrnF (Const struct cs_Vdgrn_ *vdgrn,double xy [2],Const double ll [2]) { extern double cs_Degree; /* 1.0 / RADIAN */ extern double cs_Pi; /* 3.14159..... */ extern double cs_Two_pi; /* 2 pi */ extern double cs_Mpi; /* -3.14159..... */ extern double cs_Pi_o_2; /* Pi over 2 */ extern double cs_Zero; /* 0.0 */ extern double cs_Half; /* 0.5 */ extern double cs_One; /* 1.0 */ extern double cs_Two; /* 2.0 */ extern double cs_NPTest; /* 0.001 seconds of arc short of the north pole, in radians. */ extern double cs_AnglTest; /* 0.001 seconds of arc, in radians. */ int rtn_val; double lng; /* The given longitude, after conversion to radians. */ double lat; /* The given latitude after conversion to radians. */ double del_lng; double abs_lat; double xx; double yy; double theta; double sin_theta, cos_theta; double A, A_sq; double P, P_sq; double G; double Q; double tmp1, tmp2, tmp3; rtn_val = cs_CNVRT_NRML; /* For this projection, we only support the spherical form, therefore there is only one set of equations. */ lng = ll [LNG] * cs_Degree; del_lng = lng - vdgrn->org_lng; if (del_lng > cs_Pi && vdgrn->org_lng < 0.0) del_lng -= cs_Two_pi; else if (del_lng < cs_Mpi && vdgrn->org_lng > 0.0) del_lng += cs_Two_pi; if (fabs (del_lng) > cs_Pi) { rtn_val = cs_CNVRT_RNG; del_lng = CS_adj2piI (del_lng); } lat = ll [LAT] * cs_Degree; abs_lat = fabs (lat); if (abs_lat > cs_NPTest) { rtn_val = cs_CNVRT_INDF; if (abs_lat > cs_Pi_o_2) { rtn_val = cs_CNVRT_RNG; lat = CS_adj1pi (lat); abs_lat = fabs (lat); } } if (abs_lat > cs_NPTest) { /* The sign of yy gets reversed below, we can simply use cs_Pi here. */ xx = cs_Zero; yy = cs_Pi * vdgrn->ka; } else if (abs_lat <= cs_AnglTest) { /* This is the calculation for the equator. The sign of X gets reversed below, we need to use the absolute value here. */ xx = vdgrn->ka * fabs (del_lng); yy = cs_Zero; } else if (fabs (del_lng) < cs_AnglTest) { /* We're on the central meridian, BUT NOT on the equator, and not at either pole. Npte, sign of result is dealt with below. */ xx = cs_Zero; theta = asin (abs_lat / cs_Pi_o_2); yy = cs_Pi * vdgrn->ka * tan (theta * cs_Half); } else { /* OK, we're not at either pole, or the equator. The rest of this should be pretty safe. */ sin_theta = fabs (lat) * vdgrn->two_ovr_pi; cos_theta = sqrt (cs_One - sin_theta * sin_theta); tmp1 = (cs_Pi / del_lng) - (del_lng / cs_Pi); A = cs_Half * fabs (tmp1); A_sq = A * A; G = cos_theta / (sin_theta + cos_theta - cs_One); P = G * ((cs_Two / sin_theta) - cs_One); P_sq = P * P; Q = A_sq + G; tmp1 = P_sq + A_sq; tmp2 = G - P_sq; tmp3 = tmp1 * ((G * G) - P_sq); tmp3 = (A_sq * tmp2 * tmp2) - tmp3; if (tmp3 < 0.0) tmp3 = cs_Zero; tmp3 = (A * tmp2) + sqrt (tmp3); xx = vdgrn->piR * tmp3 / tmp1; tmp3 = ((A_sq + cs_One) * tmp1) - (Q * Q); if (tmp3 < 0.0) tmp3 = cs_Zero; tmp3 = (P * Q) - (A * sqrt (tmp3)); yy = vdgrn->piR * tmp3 / tmp1; } /* Apply the appropriate sign and false origin. */ xy [XX] = (del_lng >= 0.0) ? xx : -xx; xy [YY] = (lat >= 0.0) ? yy : -yy; if (vdgrn->quad == 0) { xy [XX] += vdgrn->x_off; xy [YY] += vdgrn->y_off; } else { CS_quadF (xy,xy [XX],xy [YY],vdgrn->x_off,vdgrn->y_off,vdgrn->quad); } return (rtn_val); }
int EXP_LVL9 CSlmtanF (Const struct cs_Lmtan_ *lmtan,double xy [2],Const double ll [2]) { extern double cs_Degree; /* 1.0 / RADIAN */ extern double cs_Pi; /* 3.14159... */ extern double cs_Mpi; /* -3.14159... */ extern double cs_Two_pi; /* 2 PI */ extern double cs_Pi_o_2; /* PI / 2.0 */ extern double cs_Pi_o_4; /* PI / 4.0 */ extern double cs_Zero; /* 0.0 */ extern double cs_One; /* 1.0 */ extern double cs_Half; /* 0.5 */ extern double cs_NPTest; /* 0.001 arc seconds short of the north pole, in in radians. */ extern double cs_SPTest; /* 0.001 arc seconds short of the south pole, in in radians. */ int rtn_val; double lng; /* The given longitude, after conversion to radians. */ double lat; /* The given latitude after conversion to radians. */ double del_lng; double L0; double Gamma; double R; double tmp1; double tmp2; rtn_val = cs_CNVRT_NRML; lng = cs_Degree * ll [LNG]; lat = cs_Degree * ll [LAT]; /* Compute the polar angle, Gamma, also known as the convergence angle. */ del_lng = lng - lmtan->org_lng; if (del_lng > cs_Pi && lmtan->org_lng < 0.0) del_lng -= cs_Two_pi; else if (del_lng < cs_Mpi && lmtan->org_lng > 0.0) del_lng += cs_Two_pi; if (fabs (del_lng) > cs_Pi) { rtn_val = cs_CNVRT_RNG; del_lng = CS_adj2piI (del_lng); } Gamma = lmtan->sin_org_lat * del_lng; /* Now, we compute the radius of the polar arc. R will be negative (lmtan->c is negative) if the south pole is the focus pole of the coordinate system. */ if (fabs (lat) > cs_NPTest) { if ((lat > 0.0) == (lmtan->sin_org_lat > 0.0)) /*lint !e731 !e777 */ { rtn_val = cs_CNVRT_INDF; } if (fabs (lat) > cs_Pi_o_2) { rtn_val = cs_CNVRT_RNG; lat = CS_adj1pi (lat); } } if (lat > cs_NPTest) { R = (lmtan->sin_org_lat > 0.0) ? cs_Zero : lmtan->max_R; } else if (lat < cs_SPTest) { R = (lmtan->sin_org_lat < 0.0) ? cs_Zero : lmtan->max_R; } else { tmp1 = lmtan->ecent * sin (lat); tmp1 = (cs_One + tmp1) / (cs_One - tmp1); tmp1 = lmtan->e_ovr_2 * log (tmp1); tmp2 = cs_Pi_o_4 + (lat * cs_Half); /* Tmp2 can be zero (and thus tan(tmp2) can be zero) at the south pole, but we've already dealt with that. */ tmp2 = log (tan (tmp2)); L0 = tmp2 - tmp1; R = lmtan->c * exp (-lmtan->sin_org_lat * L0); } /* Convert to cartesian coordinates. Note, ys has the false northing and the radius of the origin latitude built into it by the setup function. */ xy [XX] = R * sin (Gamma); xy [YY] = lmtan->R0 - (R * cos (Gamma)); if (lmtan->quad == 0) { xy [XX] += lmtan->x_off; xy [YY] += lmtan->y_off; } else { CS_quadF (xy,xy [XX],xy [YY],lmtan->x_off,lmtan->y_off, lmtan->quad); } return (rtn_val); }