示例#1
0
文件: CS_azmed.c 项目: asir6/Colt
void EXP_LVL9 CSazmedS (struct cs_Csprm_ *csprm)
{
	extern short cs_QuadMin;		/* -4 */
	extern short cs_QuadMap [];
	extern double cs_Pi;			/* 3.14159.... */
	extern double cs_Pi_o_2;		/*  PI / 2.0     */
	extern double cs_Mpi_o_2;		/*  PI / 2.0     */
	extern double cs_Radian;		/* 180.0 / pi */
	extern double cs_Degree;		/* 1.0 / RADIAN  */
	extern double cs_One;			/* 1.0 */
	extern double cs_Two;			/* 2.0 */
	extern double cs_Mone;			/* -1.0 */
	extern double cs_Zero;			/* 0.0 */
	extern double cs_AnglTest;		/* 0.001 seconds of arc
									   in radians. */
	extern double cs_NPTest;		/* 0.001 seconds of arc
									   short of the north pole,
									   in radians. */
	extern double cs_SPTest;		/* 0.001 seconds of arc
									   short of the south pole,
									   in radians. */
	extern double cs_Km180;			/* -180.0 */
	extern double cs_K180;			/*  180.0 */
	extern double cs_Km90;			/* -90.0 */
	extern double cs_K90;			/*  90.0 */
	extern double cs_K60;			/*  60.0 */
	extern double cs_Ten;			/*  10.0 */

	struct cs_Azmed_ *azmed;

	double height;
	double tmp1;

	azmed = &csprm->proj_prms.azmed;

	height = cs_Zero;
	if (csprm->prj_code == cs_PRJCOD_AZEDE)
	{
		height = csprm->csdef.prj_prm2 * csprm->csdef.unit_scl;
	}

	/* Transfer the necessary arguments to the
	   "azmed" structure.  Notice, the conversion
	   from degrees to radians which is performed
	   in the process. */

	azmed->org_lng = csprm->csdef.org_lng * cs_Degree;
	azmed->org_lat = csprm->csdef.org_lat * cs_Degree;
	azmed->k = csprm->csdef.scale;
	azmed->x_off = csprm->csdef.x_off;
	azmed->y_off = csprm->csdef.y_off;
	azmed->ecent = csprm->datum.ecent;
	azmed->e_sq = azmed->ecent * azmed->ecent;
	azmed->one_esq = cs_One - azmed->e_sq;
	azmed->rt_one_esq = sqrt (azmed->one_esq);
	azmed->ka = (csprm->datum.e_rad + height) * azmed->k;
	azmed->two_ka = azmed->ka + azmed->ka;
	azmed->cos_org_lat = cos (azmed->org_lat);
	azmed->sin_org_lat = sin (azmed->org_lat);
	azmed->Az = csprm->csdef.prj_prm1 * cs_Degree;
	azmed->quad = cs_QuadMap [csprm->csdef.quad - cs_QuadMin];
	azmed->aspect = 0;
	azmed->one_mm = 0.001 * csprm->csdef.scale;

	/* The following fix is required for the test cases from
	   Synder which use the unit sphere, and a sphere with
	   a radius of 3. */

	if (csprm->datum.e_rad <= 3.0)
	{
		azmed->one_mm = azmed->ka / 6.3E+09;
	}

	/* Compute the sine and cosine of the Y axis azimuth. These will
	   not change. */

	if (fabs (azmed->Az) < cs_AnglTest)
	{
		azmed->sin_Az = cs_Zero;
		azmed->cos_Az = cs_One;
	}
	else
	{
		azmed->sin_Az = sin (azmed->Az);
		azmed->cos_Az = cos (azmed->Az);
	}

	/* If we are very close to either a north or south polar
	   aspect, set the sine's and cosine's to their correct
	   values.  The sine and cosine functions tend to leave
	   us just a bit short on these numbers.  We also set the
	   polar flag, which is used in the sphereical inverse
	   equations (perhaps elsewhere later on).  The polar
	   variable is zero if the aspect is oblique. */

	if (fabs (azmed->org_lat) < cs_AnglTest)
	{
		/* Equatorial Aspect */

		azmed->aspect      = cs_AZMED_EQUATOR;
		azmed->org_lat     = cs_Zero;
		azmed->cos_org_lat = cs_One;
		azmed->sin_org_lat = cs_Zero;
	}
	else if (azmed->org_lat > cs_NPTest)
	{
		azmed->aspect      = cs_AZMED_NORTH;
		azmed->org_lat     = cs_Pi_o_2;
		azmed->cos_org_lat = cs_Zero;
		azmed->sin_org_lat = cs_One;
	}
	else if (azmed->org_lat < cs_SPTest)
	{
		azmed->aspect      = cs_AZMED_SOUTH;
		azmed->org_lat     = cs_Mpi_o_2;
		azmed->cos_org_lat = cs_Zero;
		azmed->sin_org_lat = cs_Mone;
	}
	else
	{
		azmed->aspect      = cs_AZMED_OBLIQUE;
		azmed->cos_org_lat = cos (azmed->org_lat);
		azmed->sin_org_lat = sin (azmed->org_lat);
	}

	/* If the ecentricity is zero, we have a sphere, and
	   nothing special to do here. */

	if (azmed->ecent == 0.0)
	{
		azmed->max_rho = azmed->ka * cs_Pi;
	}
	else
	{
		/* Here only for an ellipsoid. */

		CSmmFsu (&azmed->mmcofF,azmed->ka,azmed->e_sq);
		CSmmIsu (&azmed->mmcofI,azmed->ka,azmed->e_sq);

		azmed->Mp = CSmmFcal (&azmed->mmcofF,cs_Pi_o_2,cs_One,cs_Zero);
		azmed->M1 = CSmmFcal (&azmed->mmcofF,azmed->org_lat,
						     azmed->sin_org_lat,
						     azmed->cos_org_lat);

		azmed->e_sin_p1 = azmed->ecent * azmed->sin_org_lat;
		azmed->e_cos_p1 = azmed->ecent * azmed->cos_org_lat;

		azmed->e_sq_sin_sq = azmed->e_sin_p1 * azmed->e_sin_p1;
		azmed->e_sq_cos_sq = azmed->e_cos_p1 * azmed->e_cos_p1;

		azmed->N1 = azmed->ka / sqrt (cs_One - azmed->e_sq_sin_sq);

		azmed->psi_t1 = azmed->e_sq * azmed->N1 * azmed->sin_org_lat;
		azmed->sin_cos = azmed->sin_org_lat * azmed->cos_org_lat;
		azmed->G = azmed->ecent * azmed->sin_org_lat /
					   azmed->rt_one_esq;
		azmed->G_sq_3 = azmed->G * azmed->G * 3.0;
		azmed->max_rho = azmed->Mp * cs_Two;
	}

	/* Set up the coordinate checking information.  If the user has
	   specified a useful range, we use it without checking it.
	   Otherwise, we compute what I, the programmer, consider to
	   be the useful range of the projection.  Note, values are in
	   degrees and longitude values are relative to the origin
	   longitude. */

	csprm->cent_mer = azmed->org_lng * cs_Radian;
	if (csprm->csdef.ll_min [LNG] == 0.0 &&
	    csprm->csdef.ll_max [LNG] == 0.0)
	{
		/* We're to calculate the useful range.  The useful
		   range is within 1200 KM of the origin.  We use
		   the approximation of 10 degrees of longitude at
		   the equator equals 1200 KM. */

		switch (azmed->aspect) {

		case cs_AZMED_NORTH:

			csprm->min_ll [LNG] = cs_Km180;
			csprm->max_ll [LNG] = cs_K180;
			csprm->min_ll [LAT] = cs_K60;
			csprm->max_ll [LAT] = cs_K90;
			break;

		case cs_AZMED_SOUTH:

			csprm->min_ll [LNG] = cs_Km180;
			csprm->max_ll [LNG] = cs_K180;
			csprm->min_ll [LAT] = cs_Km90;
			csprm->max_ll [LAT] = -cs_K60;
			break;

		default:
		case cs_AZMED_EQUATOR:
		case cs_AZMED_OBLIQUE:
		case cs_AZMED_GUAM:

			csprm->min_ll [LNG] = -cs_Ten;
			csprm->max_ll [LNG] = cs_Ten;
			tmp1 = azmed->org_lat * cs_Radian;
			csprm->min_ll [LAT] = tmp1 - cs_Ten;
			if (csprm->min_ll [LAT] < cs_Km90)
			{
				csprm->min_ll [LAT] = cs_Km90;
			}
			csprm->max_ll [LAT] = tmp1 + cs_Ten;
			if (csprm->max_ll [LAT] > cs_K90)
			{
				csprm->max_ll [LAT] = cs_K90;
			}
			break;
		}
	}
	else
	{
		/* The definition includes a useful range specification.
		   We use these values without checking.  We expect the
		   user to give us absolute values, and we convert
		   to values relative to the central meridian. */

		csprm->min_ll [LNG] = CS_adj180 (csprm->csdef.ll_min [LNG] - csprm->cent_mer);
		csprm->min_ll [LAT] = csprm->csdef.ll_min [LAT];
		csprm->max_ll [LNG] = CS_adj180 (csprm->csdef.ll_max [LNG] - csprm->cent_mer);
		csprm->max_ll [LAT] = csprm->csdef.ll_max [LAT];
	}

	/* Similarly with the X's and Y's.  If the coordinate system
	   definition carries some values, we use them.  If not, we
	   calculate some appropriate values. */

	if (csprm->csdef.xy_min [XX] == 0.0 &&
	    csprm->csdef.xy_max [XX] == 0.0)
	{
		/* Choose an arbitrary limit of the equivalant of
		   1,200,000 meters from the origin. */

		tmp1 = 1200000.0 * csprm->csdef.scale;
		csprm->min_xy [XX] = -tmp1;
		csprm->min_xy [YY] = -tmp1;
		csprm->max_xy [XX] =  tmp1;
		csprm->max_xy [YY] =  tmp1;

		CS_quadMM (csprm->min_xy,csprm->max_xy,azmed->x_off,
						       azmed->y_off,
						       azmed->quad);
	}
	else
	{
		/* Use what ever the user has given us.  No adjustment
		   necessary.  Note: we don't check anything. */

		csprm->min_xy [XX] = csprm->csdef.xy_min [XX];
		csprm->min_xy [YY] = csprm->csdef.xy_min [YY];
		csprm->max_xy [XX] = csprm->csdef.xy_max [XX];
		csprm->max_xy [YY] = csprm->csdef.xy_max [YY];
	}

	/* That's all the calculations.  Stuff some function
	   addresses and we are done. */

	csprm->ll2cs    = (cs_LL2CS_CAST)CSazmedF;
	csprm->cs2ll    = (cs_CS2LL_CAST)CSazmedI;
	csprm->cs_scale = (cs_SCALE_CAST)CSazmedK;
	csprm->cs_sclk  = (cs_SCALK_CAST)CSazmedK;
	csprm->cs_sclh  = (cs_SCALH_CAST)CSazmedH;
	csprm->cs_cnvrg = (cs_CNVRG_CAST)CSazmedC;
	csprm->llchk    = (cs_LLCHK_CAST)CSazmedL;
	csprm->xychk    = (cs_XYCHK_CAST)CSazmedX;

	return;
}
示例#2
0
文件: CS_tacyl.c 项目: kanbang/Colt
void EXP_LVL9 CStacylS (struct cs_Csprm_ *csprm)
{
    extern short cs_QuadMin;			/* -4 */
    extern short cs_QuadMap [];
    extern double cs_Radian;			/* 57.29577... */
    extern double cs_Degree;			/* 1.0 / 57.29577... */
    extern double cs_Pi_o_2;			/* Pi over 2 */
    extern double cs_Zero;				/* 0.0 */
    extern double cs_One;				/* 1.0 */
    extern double cs_Two;				/* 2.0 */
    extern double cs_Ten;				/* 2.0 */

    struct cs_Tacyl_ *tacyl;

    double tmp;

    double sin_org_lat;
    double cos_org_lat;

    double test_ll [3];
    double test_xy [3];

    tacyl = &csprm->proj_prms.tacyl;

    tacyl->org_lng = csprm->csdef.org_lng * cs_Degree;
    tacyl->org_lat = csprm->csdef.org_lat * cs_Degree;
    tacyl->h0 = csprm->csdef.scl_red;
    tacyl->x_off = csprm->csdef.x_off;
    tacyl->y_off = csprm->csdef.y_off;
    tacyl->e_rad = csprm->datum.e_rad;
    tacyl->ecent = csprm->datum.ecent;
    tacyl->k = csprm->csdef.scale * tacyl->h0;
    tacyl->quad = cs_QuadMap [csprm->csdef.quad - cs_QuadMin];

    /* Note that due to the authalic nature of this projection,
       the ka factor does not include the scale reduction
       factor as is common for conformal projections. */

    tacyl->ka = csprm->csdef.scale * tacyl->e_rad;
    tacyl->ka_o_h0 = tacyl->ka / tacyl->h0;
    tacyl->kah0    = tacyl->ka * tacyl->h0;
    tacyl->h0_o_ka = tacyl->h0 / tacyl->ka;

    if (tacyl->ecent == 0.0)
    {
        tacyl->max_xx = tacyl->ka_o_h0;
        tacyl->max_yy = tacyl->kah0;
    }
    else
    {
        /* For the ellipsoid. */

        tacyl->ecent = csprm->datum.ecent;
        tacyl->e_sq = tacyl->ecent * tacyl->ecent;
        tacyl->one_m_esq = cs_One - tacyl->e_sq;

        tacyl->one_o_2e = cs_One / (cs_Two * tacyl->ecent);

        tmp = (cs_One - tacyl->ecent) / (cs_One + tacyl->ecent);
        tacyl->qp = cs_One - (tacyl->one_m_esq * tacyl->one_o_2e) * log (tmp);

        CSbtIsu (&tacyl->btcofI,tacyl->e_sq);
        CSmmFsu (&tacyl->mmcofF,tacyl->ka,tacyl->e_sq);
        CSmmIsu (&tacyl->mmcofI,tacyl->ka,tacyl->e_sq);

        sin_org_lat = sin (tacyl->org_lat);
        cos_org_lat = cos (tacyl->org_lat);
        tacyl->M0 = CSmmFcal (&tacyl->mmcofF,tacyl->org_lat,sin_org_lat,cos_org_lat);

        tacyl->max_xx = tacyl->ka_o_h0 / tacyl->one_m_esq;
        tacyl->max_yy = tacyl->h0 * CSmmFcal (&tacyl->mmcofF,cs_Pi_o_2,cs_One,cs_Zero);
    }

    /* Set up the coordinate checking information.  If the user has
       specified a useful range, we use it without checking it.
       Otherwise, we compute what I, the programmer, consider to
       be the useful range of the projection.  Note, values are in
       degrees and longitude values are relative to the central
       meridian. */

    csprm->cent_mer = tacyl->org_lng * cs_Radian;
    if (csprm->csdef.ll_min [LNG] == 0.0 &&
            csprm->csdef.ll_max [LNG] == 0.0)
    {
        /* We're to calculate the useful range.  We'll assume a
           20 degree width, increased by an amount related to
           scale reduction.  We set the latitude range to that
           customarily used in the UTM system. */

        tmp = cs_Two * acos (tacyl->h0) * cs_Radian + cs_Ten;
        csprm->min_ll [LNG] = -tmp;
        csprm->max_ll [LNG] =  tmp;

        csprm->min_ll [LAT] = -84.0;
        csprm->max_ll [LAT] =  84.0;
    }
    else
    {
        /* The definition includes a useful range specification.
           We use these values without checking.  We expect the
           user to give us absolute values, and we convert
           to values relative to the central meridian. */

        csprm->min_ll [LNG] = CS_adj180 (csprm->csdef.ll_min [LNG] - csprm->cent_mer);
        csprm->min_ll [LAT] = csprm->csdef.ll_min [LAT];
        csprm->max_ll [LNG] = CS_adj180 (csprm->csdef.ll_max [LNG] - csprm->cent_mer);
        csprm->max_ll [LAT] = csprm->csdef.ll_max [LAT];
    }

    /* Similarly with the X's and Y's.  If the coordinate system
       definition carries some values, we use them.  If not, we
       calculate some appropriate values. */

    if (csprm->csdef.xy_min [XX] == 0.0 &&
            csprm->csdef.xy_max [XX] == 0.0)
    {
        /* No specification in the coordinate system definition.
           The setup is virtually complete, so we can use CStacylF
           to calculate some values, if necessary. The curved
           nature of the lat/long lines means we cannot just
           convert the lat/long min/max. */

        test_ll [LNG] = CS_adj180 (csprm->cent_mer + csprm->min_ll [LNG]);
        test_ll [LAT] = tacyl->org_lat * cs_Radian;
        CStacylF (tacyl,test_xy,test_ll);					/*lint !e534 */
        csprm->min_xy [XX] = test_xy [XX] - tacyl->x_off;
        csprm->max_xy [XX] = -csprm->min_xy [XX];

        test_ll [LNG] = csprm->cent_mer;
        test_ll [LAT] = -84.0;
        CStacylF (tacyl,test_xy,test_ll);					/*lint !e534 */
        csprm->min_xy [YY] = test_xy [YY] - tacyl->y_off;
        test_ll [LAT] = 84.0;
        CStacylF (tacyl,test_xy,test_ll);					/*lint !e534 */
        csprm->max_xy [YY] = test_xy [YY] - tacyl->y_off;

        CS_quadMM (csprm->min_xy,csprm->max_xy,tacyl->x_off,
                   tacyl->y_off,
                   tacyl->quad);
    }
    else
    {
        /* Use what ever the user has given us.  No adjustment
           necessary.  Note: we don't check anything. */

        csprm->min_xy [XX] = csprm->csdef.xy_min [XX];
        csprm->min_xy [YY] = csprm->csdef.xy_min [YY];
        csprm->max_xy [XX] = csprm->csdef.xy_max [XX];
        csprm->max_xy [YY] = csprm->csdef.xy_max [YY];
    }

    /* That's all the calculations we can do at this time.
       The projection is conformal, so ha nd k scale
       factors are the same. */

    csprm->ll2cs    = (cs_LL2CS_CAST)CStacylF;
    csprm->cs2ll    = (cs_CS2LL_CAST)CStacylI;
    csprm->cs_scale = (cs_SCALE_CAST)CStacylK;
    csprm->cs_sclk  = (cs_SCALK_CAST)CStacylK;
    csprm->cs_sclh  = (cs_SCALH_CAST)CStacylH;
    csprm->cs_cnvrg = (cs_CNVRG_CAST)CStacylC;
    csprm->llchk    = (cs_LLCHK_CAST)CStacylL;
    csprm->xychk    = (cs_XYCHK_CAST)CStacylX;

    return;
}
示例#3
0
文件: CS_sinus.c 项目: asir6/Colt
void EXP_LVL9 CSsinusS (struct cs_Csprm_ *csprm)
{
	extern short cs_QuadMin;			/* -4 */
	extern short cs_QuadMap [];
	extern double cs_Radian;				/*  57.2957...  */
	extern double cs_Degree;				/*   1.0 / RADIAN  */
	extern double cs_3Pi_o_2;				/* 3 Pi over 2 */
	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_Mone;					/*   1.0 */
	extern double cs_K180;					/* 180.0 */
	extern double cs_K90;					/*  90.0 */
	extern double cs_Km90;					/* -90.0 */

	int ii;

	struct cs_Sinus_ *sinus;
	struct cs_Zone_ *zp;

	double qxk;
	double del_lng;
	double west_lng;
	double east_lng;

	sinus = &csprm->proj_prms.sinus;

	/* Transfer the necessary arguments to the
	   "sinus" structure.  Notice, the conversion
	   from degrees to radians which is performed
	   in the process. */

	sinus->cent_lng = csprm->csdef.org_lng * cs_Degree;
	sinus->k = csprm->csdef.scale;
	sinus->x_off = csprm->csdef.x_off;
	sinus->y_off = csprm->csdef.y_off;
	sinus->ecent = csprm->datum.ecent;
	sinus->e_sq = sinus->ecent * sinus->ecent;
	sinus->e_rad = csprm->datum.e_rad;
	sinus->ka = sinus->k * sinus->e_rad;
	sinus->quad = cs_QuadMap [csprm->csdef.quad - cs_QuadMin];

	sinus->one_mm = 0.001 * sinus->k;
	sinus->max_xx = sinus->ka * cs_3Pi_o_2;
	sinus->max_yy = sinus->ka * cs_Pi_o_2;		/* For the sphere,
												   replaced below
												   for the
												   ellipsoid. */

	/* No special set up required for the sphere. */

	if (sinus->ecent != 0.0)
	{
		/* Here only for the ellipsoid. */

		CSmmFsu (&sinus->mmcofF,sinus->ka,sinus->e_sq);
		CSmmIsu (&sinus->mmcofI,sinus->ka,sinus->e_sq);
		sinus->max_yy = CSmmFcal (&sinus->mmcofF,cs_Pi_o_2,cs_One,cs_Zero);
	}

	/* Set up the function pointers. */

	csprm->ll2cs    = (cs_LL2CS_CAST)CSsinusF;
	csprm->cs2ll    = (cs_CS2LL_CAST)CSsinusI;
	csprm->cs_scale = (cs_SCALE_CAST)CSsinusH;
	csprm->cs_sclk  = (cs_SCALK_CAST)CSsinusK;
	csprm->cs_sclh  = (cs_SCALH_CAST)CSsinusH;
	csprm->cs_cnvrg = (cs_CNVRG_CAST)CSsinusC;
	csprm->llchk    = (cs_LLCHK_CAST)CSsinusL;
	csprm->xychk    = (cs_XYCHK_CAST)CSsinusX;

	/* Setup the zones. */

	sinus->zone_cnt = (short)CS_zones (&csprm->csdef,sinus->zones);

	/* Set up the easting values.  Note, if the latitude is
	   zero, there is no difference between normal eastings
	   and zoned eastings.  The zone affects the easting
	   value only when the latitude is not zero.  Also,
	   the Y values are always independent of the zone.

	   Since the latitude is zero for all of these calculations,
	   we can easily do them here rather efficiently, and the
	   calculation is the same, regardless of sphere or
	   ellipsoid.

	   Note, we also accumulate the minimum and maximum longitude
	   values for use in setting up user limits below. */

	west_lng = cs_3Pi_o_2;
	east_lng = -cs_3Pi_o_2;

	/* We use qxk to adjust our zone definition numbers for
	   non-standard quadrants. */

	qxk = ((sinus->quad & cs_QUAD_INVX) == 0) ? cs_One : cs_Mone;
	for (ii = 0;ii < sinus->zone_cnt;ii++)
	{
		zp = &sinus->zones [ii];

		del_lng = (zp->west_lng - sinus->cent_lng);
		zp->west_xx = (sinus->ka * del_lng * qxk) + sinus->x_off;

		del_lng = (zp->cent_lng - sinus->cent_lng);
		zp->x_off = (sinus->ka * del_lng * qxk) + sinus->x_off;

		del_lng = (zp->east_lng - sinus->cent_lng);
		zp->east_xx = (sinus->ka * del_lng * qxk) + sinus->x_off;

		if (zp->west_lng < west_lng) west_lng = zp->west_lng;
		if (zp->east_lng > east_lng) east_lng = zp->east_lng;
	}

	/* Set up the coordinate checking information.  If the user has
	   specified a useful range, we use it without checking it.
	   Otherwise, we compute what I, the programmer, consider to
	   be the useful range of the projection.  Note, values are in
	   degrees and longitude values are relative to the central
	   meridian. */

	if (sinus->zone_cnt > 0)
	{
		csprm->cent_mer = cs_Half * (east_lng + west_lng) * cs_Radian;
	}
	else
	{
		csprm->cent_mer = sinus->cent_lng * cs_Radian;
		east_lng = cs_K180 * cs_Degree;
		west_lng = -east_lng;
	}
	if (csprm->csdef.ll_min [LNG] == 0.0 &&
		csprm->csdef.ll_max [LNG] == 0.0)
	{
		/* User hasn't specified any values.  We're to establish
		   the useful range.  We'll establish some pretty liberal
		   values. */
		csprm->min_ll [LNG] = west_lng;
		csprm->max_ll [LNG] = east_lng;
		csprm->min_ll [LAT] = cs_Km90;
		csprm->max_ll [LAT] = cs_K90;
	}
	else
	{
		/* The definition includes a useful range specification.
		   We use these values without checking.  We expect the
		   user to give us absolute values, and we convert
		   to values relative to the central meridian. */
		csprm->min_ll [LNG] = CS_adj180 (csprm->csdef.ll_min [LNG] - csprm->cent_mer);
		csprm->min_ll [LAT] = csprm->csdef.ll_min [LAT];
		csprm->max_ll [LNG] = CS_adj180 (csprm->csdef.ll_max [LNG] - csprm->cent_mer);
		csprm->max_ll [LAT] = csprm->csdef.ll_max [LAT];
	}

	/* Similarly with the X's and Y's.  If the coordinate system
	   definition carries some values, we use them.  If not, we
	   calculate some appropriate values. */
	if (csprm->csdef.xy_min [XX] == 0.0 &&
		csprm->csdef.xy_max [XX] == 0.0)
	{
		/* No specification in the coordinate system definition.
		   The setup is virtually complete, so we can use CSgnricF
		   to calculate some values as necessary. Unfortuneately
		   it is the rare case where we can just convert the
		   lat/long min/max. */

		csprm->min_xy [XX] = -sinus->max_xx;
		csprm->max_xy [XX] =  sinus->max_xx;

		csprm->min_xy [YY] = -sinus->max_yy;
		csprm->max_xy [YY] =  sinus->max_yy;

		CS_quadMM (csprm->min_xy,csprm->max_xy,sinus->x_off,
											   sinus->y_off,
											   sinus->quad);
	}
	else
	{
		/* Use what ever the user has given us.  No adjustment
		   necessary.  Note: we don't check anything. */

		csprm->min_xy [XX] = csprm->csdef.xy_min [XX];
		csprm->min_xy [YY] = csprm->csdef.xy_min [YY];
		csprm->max_xy [XX] = csprm->csdef.xy_max [XX];
		csprm->max_xy [YY] = csprm->csdef.xy_max [YY];
	}
	return;
}
示例#4
0
文件: CS_csini.c 项目: auranet/csmap
void EXP_LVL9 CScsiniS (struct cs_Csprm_ *csprm)
{
	extern short cs_QuadMin;			/* -4 */
	extern short cs_QuadMap [];
	extern double cs_Degree;			/* 1.0 / 57.29577... */
	extern double cs_Radian;			/* 57.29577.. */
	extern double cs_Pi_o_2;			/* Pi over 2 */
	extern double cs_Mpi_o_2;			/* -Pi over 2 */
	extern double cs_Zero;				/* 0.0 */
	extern double cs_One;				/* 1.0 */
	extern double cs_Two;				/* 2.0 */
	extern double cs_Five;				/* 5.0 */
	extern double cs_K75;				/* 75.0 */

	struct cs_Csini_ *csini;

	double tmp1;
	double sin_org_lat;
	double cos_org_lat;

	double test_xy [3];
	double test_ll [3];

	csini = &csprm->proj_prms.csini;

	csini->cent_lng = csprm->csdef.prj_prm1 * cs_Degree;
	csini->org_lat = csprm->csdef.org_lat * cs_Degree;
	csini->x_off = csprm->csdef.x_off;
	csini->y_off = csprm->csdef.y_off;
	csini->k = csprm->csdef.scale;
	csini->ecent = csprm->datum.ecent;
	csini->e_sq = csini->ecent * csini->ecent;
	csini->e_rad = csprm->datum.e_rad;
	csini->quad = cs_QuadMap [csprm->csdef.quad - cs_QuadMin];

	/* Probably could add a scale reduction factor to the
	   following term. */

	csini->ka = csini->e_rad * csini->k;
	csini->max_xx = csini->ka * cs_Pi_o_2;
	csini->max_yy = csini->ka * (cs_Pi_o_2 - csini->org_lat);
	csini->min_yy = csini->ka * (cs_Mpi_o_2 - csini->org_lat);

	/* Nothing special required for the sphere. */

	if (csini->ecent != 0.0)
	{
		/* Here for a ellipsoid datum.  We compute
		   what we can once only. */

		tmp1 = cs_One - csini->e_sq;
		csini->C_term = csini->e_sq / tmp1;
		csini->R_term = csini->ka * tmp1;
		csini->s_term = cs_Two * csini->ka * csini->ka * tmp1;

		/* CSmuFsu and CSmuIsu do the rest. */

		CSmmFsu (&csini->mmcofF,csini->ka,csini->e_sq);
		CSmmIsu (&csini->mmcofI,csini->ka,csini->e_sq);

		/* Now we compute M0, the M associated with
		   the origin latiude. */

		sin_org_lat = sin (csini->org_lat);
		cos_org_lat = cos (csini->org_lat);
		csini->M0 = CSmmFcal (&csini->mmcofF,csini->org_lat,
										     sin_org_lat,
										     cos_org_lat);

		csini->max_yy = CSmmFcal (&csini->mmcofF,cs_Pi_o_2,
												 cs_One,
												 cs_Zero);
		csini->max_yy -= csini->M0;
		csini->min_yy = CSmmFcal (&csini->mmcofF,cs_Mpi_o_2,
												 cs_One,
												 cs_Zero);
		csini->min_yy -= csini->M0;
	}

	/* Set up the coordinate checking information.  If the user has
	   specified a useful range, we use it without checking it.
	   Otherwise, we compute what I, the programmer, consider to
	   be the useful range of the projection.  Note, values are in
	   degrees and longitude values are relative to the central
	   meridian. */

	csprm->cent_mer = csini->cent_lng * cs_Radian;
	if (csprm->csdef.ll_min [LNG] == 0.0 &&
	    csprm->csdef.ll_max [LNG] == 0.0)
	{
		/* User hasn't specified any values.  We're to establish
		   the useful range. */

		csprm->min_ll [LNG] = -cs_Five;
		csprm->max_ll [LNG] = cs_Five;
		csprm->min_ll [LAT] = -cs_K75;
		csprm->max_ll [LAT] = cs_K75;
	}
	else
	{
		/* The definition includes a useful range specification.
		   We use these values without checking.  We expect the
		   user to give us absolute values, and we convert
		   to values relative to the central meridian. */

		csprm->min_ll [LNG] = CS_adj180 (csprm->csdef.ll_min [LNG] - csprm->cent_mer);
		csprm->min_ll [LAT] = csprm->csdef.ll_min [LAT];
		csprm->max_ll [LNG] = CS_adj180 (csprm->csdef.ll_max [LNG] - csprm->cent_mer);
		csprm->max_ll [LAT] = csprm->csdef.ll_max [LAT];
	}

	/* Similarly with the X's and Y's.  If the coordinate system
	   definition carries some values, we use them.  If not, we
	   calculate some appropriate values. */

	if (csprm->csdef.xy_min [XX] == 0.0 &&
	    csprm->csdef.xy_max [XX] == 0.0)
	{
		/* No specification in the coordinate system definition.
		   The setup is virtually complete, so we can use CScsiniF
		   to calculate some values as necessary. Unfortuneately
		   it is the rare case where we can just convert the
		   lat/long min/max. */

		test_ll [LNG] = CS_adj180 (csprm->min_ll [LNG] + csprm->cent_mer);
		test_ll [LAT] = csini->org_lat * cs_Radian;
		CScsiniF (csini,test_xy,test_ll);
		csprm->min_xy [XX] = test_xy [XX] - csini->x_off;
		csprm->max_xy [XX] = -csprm->min_xy [XX];

		test_ll [LNG] = csini->cent_lng * cs_Radian;
		test_ll [LAT] = cs_K75;
		CScsiniF (csini,test_xy,test_ll);
		csprm->max_xy [YY] = test_xy [YY] - csini->y_off;

		test_ll [LAT] = -cs_K75;
		CScsiniF (csini,test_xy,test_ll);
		csprm->min_xy [YY] = test_xy [YY] - csini->y_off;

		CS_quadMM (csprm->min_xy,csprm->max_xy,csini->x_off,
						       csini->y_off,
						       csini->quad);
	}
	else
	{
		/* Use what ever the user has given us.  No adjustment
		   necessary.  Note: we don't check anything. */

		csprm->min_xy [XX] = csprm->csdef.xy_min [XX];
		csprm->min_xy [YY] = csprm->csdef.xy_min [YY];
		csprm->max_xy [XX] = csprm->csdef.xy_max [XX];
		csprm->max_xy [YY] = csprm->csdef.xy_max [YY];
	}

	/* That's all the calculations we can do at this time. Set
	   up the internal function calls.  Note, the Cassini is
	   not a conformal projection. */

	csprm->ll2cs    = (cs_LL2CS_CAST)CScsiniF;
	csprm->cs2ll    = (cs_CS2LL_CAST)CScsiniI;
	csprm->cs_scale = (cs_SCALE_CAST)CScsiniH;
	csprm->cs_sclk  = (cs_SCALK_CAST)CScsiniK;
	csprm->cs_sclh  = (cs_SCALH_CAST)CScsiniH;
	csprm->cs_cnvrg = (cs_CNVRG_CAST)CScsiniC;
	csprm->llchk    = (cs_LLCHK_CAST)CScsiniL;
	csprm->xychk    = (cs_XYCHK_CAST)CScsiniX;

	return;
}