Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
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);
}