Пример #1
0
/*!
* \fn void ln_get_ell_body_equ_coords (double JD, struct ln_ell_orbit * orbit, struct ln_equ_posn * posn)
* \param JD Julian Day.
* \param orbit Orbital parameters.
* \param posn Pointer to hold asteroid position.
*
* Calculate a bodies equatorial coordinates for the given julian day.
*/
void ln_get_ell_body_equ_coords (double JD, struct ln_ell_orbit * orbit, struct ln_equ_posn * posn)
{
	struct ln_rect_posn body_rect_posn, sol_rect_posn;
	double dist, t;
	double x,y,z;
	
	/* get solar and body rect coords */
	ln_get_ell_helio_rect_posn (orbit, JD, &body_rect_posn);
	ln_get_solar_geo_coords (JD, &sol_rect_posn);
	
	/* calc distance and light time */
	dist = ln_get_rect_distance (&body_rect_posn, &sol_rect_posn);
	t = ln_get_light_time (dist);

	/* repeat calculation with new time (i.e. JD - t) */
	ln_get_ell_helio_rect_posn (orbit, JD - t, &body_rect_posn);
	
	/* calc equ coords equ 33.10 */
	x = sol_rect_posn.X + body_rect_posn.X;
	y = sol_rect_posn.Y + body_rect_posn.Y;
	z = sol_rect_posn.Z + body_rect_posn.Z;

	posn->ra = ln_range_degrees(ln_rad_to_deg(atan2 (y,x)));
	posn->dec = ln_rad_to_deg(asin (z / sqrt (x * x + y * y + z * z)));
}
Пример #2
0
/*! \fn double ln_solve_kepler (double E, double M);
* \param E Orbital eccentricity
* \param M Mean anomaly
* \return Eccentric anomaly
*
* Calculate the eccentric anomaly. 
* This method was devised by Roger Sinnott. (Sky and Telescope, Vol 70, pg 159)
*/
double ln_solve_kepler (double e, double M)
{
	double Eo = M_PI_2;
	double F, M1;
	double D = M_PI_4;
	int i;
	
	/* covert to radians */
	M = ln_deg_to_rad (M);
	
	F = sgn (M); 
	M = fabs (M) / (2.0 * M_PI);
	M = (M - (int)M) * 2.0 * M_PI * F;
	
	if (M < 0)
		M = M + 2.0 * M_PI;
	F = 1.0;
	
	if (M > M_PI)
		F = -1.0;
	
	if (M > M_PI)
		M = 2.0 * M_PI - M;
	
	for (i = 0; i < KEPLER_STEPS; i++) {
		M1 = Eo - e * sin (Eo);
		Eo = Eo + D * sgn (M - M1);
		D /= 2.0;
	}
	Eo *= F;
	
	/* back to degrees */
	Eo = ln_rad_to_deg (Eo);
	return Eo;
}
Пример #3
0
/*! \fn double ln_get_ell_body_elong (double JD, struct ln_ell_orbit * orbit);
* \param JD Julian day
* \param orbit Orbital parameters
* \return Elongation to the Sun.
*
* Calculate the bodies elongation to the Sun.. 
*/
double ln_get_ell_body_elong (double JD, struct ln_ell_orbit * orbit)
{
	double r,R,d;
	double t;
	double elong;
	double E,M;
	
	/* time since perihelion */
	t = JD - orbit->JD;
	
	/* get mean anomaly */
	if (orbit->n == 0)
		orbit->n = ln_get_ell_mean_motion (orbit->a);
	M = ln_get_ell_mean_anomaly (orbit->n, t);
	
	/* get eccentric anomaly */
	E = ln_solve_kepler (orbit->e, M);
	
	/* get radius vector */
	r = ln_get_ell_radius_vector (orbit->a, orbit->e, E);
	
	/* get solar and Earth-Sun distances */
	R = ln_get_earth_solar_dist (JD);
	d = ln_get_ell_body_solar_dist (JD, orbit);

	elong = (R * R + d * d - r * r) / ( 2.0 * R * d );
	return ln_range_degrees (ln_rad_to_deg (acos (elong)));
}
Пример #4
0
/* Equ 20.2, 20.4 pg 126 */
void ln_get_equ_prec2 (struct ln_equ_posn * mean_position, double fromJD, double toJD, struct ln_equ_posn * position)
{
	long double t, t2, t3, A, B, C, zeta, eta, theta, ra, dec, mean_ra, mean_dec, T, T2;
	
	/* change original ra and dec to radians */
	mean_ra = ln_deg_to_rad (mean_position->ra);
	mean_dec = ln_deg_to_rad (mean_position->dec);

	/* calc t, T, zeta, eta and theta Equ 20.2 */
	T = ((long double) (fromJD - JD2000)) / 36525.0;
	T *= 1.0 / 3600.0;
	t = ((long double) (toJD - fromJD)) / 36525.0;
	t *= 1.0 / 3600.0;
	T2 = T * T;
	t2 = t * t;
	t3 = t2 *t;
	zeta = (2306.2181 + 1.39656 * T - 0.000139 * T2) * t + (0.30188 - 0.000344 * T) * t2 + 0.017998 * t3;
	eta = (2306.2181 + 1.39656 * T - 0.000139 * T2) * t + (1.09468 + 0.000066 * T) * t2 + 0.018203 * t3;
	theta = (2004.3109 - 0.85330 * T - 0.000217 * T2) * t - (0.42665 + 0.000217 * T) * t2 - 0.041833 * t3;
	zeta = ln_deg_to_rad (zeta);
	eta = ln_deg_to_rad (eta);
	theta = ln_deg_to_rad (theta); 

	/* calc A,B,C equ 20.4 */
	A = cosl (mean_dec) * sinl (mean_ra + zeta);
	B = cosl (theta) * cosl (mean_dec) * cosl (mean_ra + zeta) - sinl (theta) * sinl (mean_dec);
	C = sinl (theta) * cosl (mean_dec) * cosl (mean_ra + zeta) + cosl (theta) * sinl (mean_dec);
	
	ra = atan2l (A,B) + eta;
	
	/* check for object near celestial pole */
	if (mean_dec > (0.4 * M_PI) || mean_dec < (-0.4 * M_PI)) {
		/* close to pole */
		dec = acosl (sqrt(A * A + B * B));
		if (mean_dec < 0.)
		  dec *= -1; /* 0 <= acos() <= PI */
	} else {
		/* not close to pole */
		dec = asinl (C);
	}

	/* change to degrees */
	position->ra = ln_range_degrees (ln_rad_to_deg (ra));
	position->dec = ln_rad_to_deg (dec);
}
/* convert radians to hh:mm:ss */
void ln_rad_to_hms (double radians, struct ln_hms * hms)
{
    double degrees;
         
    radians = ln_range_radians(radians);
    degrees = ln_rad_to_deg(radians);
  
    ln_deg_to_hms(degrees, hms);
}
Пример #6
0
/* equ 30.1 */
double ln_get_ell_true_anomaly (double e, double E)
{
	double v;
	
	E = ln_deg_to_rad (E);
	v = sqrt ((1.0 + e) / (1.0 - e)) * tan (E / 2.0);
	v = 2.0 * atan (v);
	v = ln_range_degrees (ln_rad_to_deg (v));
	return v;
}
Пример #7
0
/* equ 30.1 */
double ln_get_par_true_anomaly (double q, double t)
{
	double v;
	double s;
	
	s = ln_solve_barker (q,t);
	v = 2.0 * atan (s);
	
	return ln_range_degrees(ln_rad_to_deg(v));
}
Пример #8
0
/* Equ 20.3, 20.4 pg 126 
*/
void ln_get_equ_prec (struct ln_equ_posn * mean_position, double JD, struct ln_equ_posn * position)
{
	long double t, t2, t3, A, B, C, zeta, eta, theta, ra, dec, mean_ra, mean_dec;
	
	/* change original ra and dec to radians */
	mean_ra = ln_deg_to_rad (mean_position->ra);
	mean_dec = ln_deg_to_rad (mean_position->dec);

	/* calc t, zeta, eta and theta for J2000.0 Equ 20.3 */
	t = (JD - JD2000) / 36525.0;
	t *= 1.0 / 3600.0;
	t2 = t * t;
	t3 = t2 *t;
	zeta = 2306.2181 * t + 0.30188 * t2 + 0.017998 * t3;
	eta = 2306.2181 * t + 1.09468 * t2 + 0.041833 * t3;
	theta = 2004.3109 * t - 0.42665 * t2 - 0.041833 * t3;
	zeta = ln_deg_to_rad (zeta);
	eta = ln_deg_to_rad (eta);
	theta = ln_deg_to_rad (theta); 

	/* calc A,B,C equ 20.4 */
	A = cosl (mean_dec) * sinl (mean_ra + zeta);
	B = cosl (theta) * cosl (mean_dec) * cosl (mean_ra + zeta) - sinl (theta) * sinl (mean_dec);
	C = sinl (theta) * cosl (mean_dec) * cosl (mean_ra + zeta) + cosl (theta) * sinl (mean_dec);
	
	ra = atan2l (A,B) + eta;
	
	/* check for object near celestial pole */
	if (mean_dec > (0.4 * M_PI) || mean_dec < (-0.4 * M_PI)) {
		/* close to pole */
		dec = acosl (sqrt(A * A + B * B));
		if (mean_dec < 0.)
		  dec *= -1; /* 0 <= acos() <= PI */
	} else {
		/* not close to pole */
		dec = asinl (C);
	}

	/* change to degrees */
	position->ra = ln_range_degrees (ln_rad_to_deg (ra));
	position->dec = ln_rad_to_deg (dec);
}
Пример #9
0
/*! \fn double ln_get_par_body_elong (double JD, struct ln_par_orbit * orbit);
* \param JD Julian day
* \param orbit Orbital parameters
* \return Elongation to the Sun.
*
* Calculate the bodies elongation to the Sun.. 
*/
double ln_get_par_body_elong (double JD, struct ln_par_orbit * orbit)
{
	double r,R,d;
	double t;
	double elong;
	
	/* time since perihelion */
	t = JD - orbit->JD;
	
	/* get radius vector */
	r = ln_get_par_radius_vector (orbit->q, t);
	
	/* get solar and Earth-Sun distances */
	R = ln_get_earth_solar_dist (JD);
	d = ln_get_par_body_solar_dist (JD, orbit);

	elong = (R * R + d * d - r * r) / ( 2.0 * R * d );
	return ln_range_degrees (ln_rad_to_deg (acos (elong)));
}
Пример #10
0
/*! \fn double ln_get_par_body_phase_angle (double JD, struct ln_par_orbit * orbit);
* \param JD Julian day
* \param orbit Orbital parameters
* \return Phase angle.
*
* Calculate the phase angle of the body. The angle Sun - body - Earth. 
*/
double ln_get_par_body_phase_angle (double JD, struct ln_par_orbit * orbit)
{
	double r,R,d;
	double t;
	double phase;
	
	/* time since perihelion */
	t = JD - orbit->JD;
	
	/* get radius vector */
	r = ln_get_par_radius_vector (orbit->q, t);
	
	/* get solar and Earth-Sun distances */
	R = ln_get_earth_solar_dist (JD);
	d = ln_get_par_body_solar_dist (JD, orbit);

	phase = (r * r + d * d - R * R) / ( 2.0 * r * d );
	return ln_range_degrees (ln_rad_to_deg (acos (phase)));
}
Пример #11
0
int ln_get_object_rst_horizon_offset (double JD, struct ln_lnlat_posn * observer,
	struct ln_equ_posn * object, long double horizon, struct ln_rst_time * rst, double ut_offset)
{
	int jd;
	long double O, JD_UT, H0, H1;
	double Hat, Har, Has, altr, alts;
	double mt, mr, ms, mst, msr, mss;
	double dmt, dmr, dms;
	int ret, i;

	if (isnan (ut_offset))
	{
		JD_UT = JD;
	}
	else
	{
		/* convert local sidereal time into degrees
			 for 0h of UT on day JD */
		jd = (int)JD;
		JD_UT = jd + ut_offset;
	}

	O = ln_get_apparent_sidereal_time (JD_UT);
	O *= 15.0;

	/* equ 15.1 */
	H0 = (sin (ln_deg_to_rad (horizon)) -
		 sin (ln_deg_to_rad (observer->lat)) * sin (ln_deg_to_rad (object->dec)));
	H1 = (cos (ln_deg_to_rad (observer->lat)) * cos (ln_deg_to_rad (object->dec)));

	H1 = H0 / H1;

	ret = check_coords (observer, H1, horizon, object);
	if (ret)
		return ret;

	H0 = acos (H1);
	H0 = ln_rad_to_deg (H0);

	/* equ 15.2 */
	mt = (object->ra - observer->lng - O) / 360.0;
	mr = mt - H0 / 360.0;
	ms = mt + H0 / 360.0;

	for (i = 0; i < 3; i++)
	{
		/* put in correct range */
		if (mt > 1.0)
			mt--;
		else if (mt < 0)
			mt++;
		if (mr > 1.0)
			mr--;
		else if (mr < 0)
			mr++;
		if (ms > 1.0)
			ms--;
		else if (ms < 0)
			ms++;

		/* find sidereal time at Greenwich, in degrees, for each m */
		mst = O + 360.985647 * mt;
		msr = O + 360.985647 * mr;
		mss = O + 360.985647 * ms;

		/* find local hour angle */
		Hat = mst + observer->lng - object->ra;
		Har = msr + observer->lng - object->ra;
		Has = mss + observer->lng - object->ra;

		/* find altitude for rise and set */
		altr = sin (ln_deg_to_rad (observer->lat)) * sin (ln_deg_to_rad (object->dec)) +
			cos (ln_deg_to_rad (observer->lat)) * cos (ln_deg_to_rad (object->dec)) *
			cos (ln_deg_to_rad (Har));
		alts = sin (ln_deg_to_rad (observer->lat)) * sin (ln_deg_to_rad (object->dec)) +
			cos (ln_deg_to_rad (observer->lat)) * cos (ln_deg_to_rad (object->dec)) *
			cos (ln_deg_to_rad (Has));

		/* must be in degrees */
		altr = ln_rad_to_deg (altr);
		alts = ln_rad_to_deg (alts);

		/* corrections for m */
		ln_range_degrees (Hat);
		if (Hat > 180.0)
			Hat -= 360;

		dmt = -(Hat / 360.0);
		dmr = (altr - horizon) / (360 * cos (ln_deg_to_rad (object->dec)) * cos (ln_deg_to_rad (observer->lat)) * sin (ln_deg_to_rad (Har)));
		dms = (alts - horizon) / (360 * cos (ln_deg_to_rad (object->dec)) * cos (ln_deg_to_rad (observer->lat)) * sin (ln_deg_to_rad (Has)));

		/* add corrections and change to JD */
		mt += dmt;
		mr += dmr;
		ms += dms;

		if (mt <= 1 && mt >= 0 && mr <= 1 && mr >= 0 && ms <= 1 && ms >= 0)
			break;
	}

	rst->rise = JD_UT + mr;
	rst->transit = JD_UT + mt;
	rst->set = JD_UT + ms;

	/* not circumpolar */
	return 0;
}
Пример #12
0
int ln_get_motion_body_rst_horizon_offset (double JD, struct ln_lnlat_posn * observer, get_motion_body_coords_t get_motion_body_coords,
	void * orbit, double horizon, struct ln_rst_time * rst, double ut_offset)
{
	int jd;
	double T, O, JD_UT, H0, H1;
	double Hat, Har, Has, altr, alts;
	double mt, mr, ms, mst, msr, mss, nt, nr, ns;
	struct ln_equ_posn sol1, sol2, sol3, post, posr, poss;
	double dmt, dmr, dms;
	int ret, i;
		
	/* dynamical time diff */
	T = ln_get_dynamical_time_diff (JD);

	if (isnan (ut_offset))
	{
		JD_UT = JD;
	}
	else
	{
		jd = (int)JD;
		JD_UT = jd + ut_offset;
	}
	O = ln_get_apparent_sidereal_time (JD_UT);
	O *= 15.0;
	
	/* get body coords for JD_UT -1, JD_UT and JD_UT + 1 */
	get_motion_body_coords (JD_UT - 1.0, orbit, &sol1);
	get_motion_body_coords (JD_UT, orbit, &sol2);
	get_motion_body_coords (JD_UT + 1.0, orbit, &sol3);
	
	/* equ 15.1 */
	H0 = (sin(ln_deg_to_rad (horizon)) - sin(ln_deg_to_rad(observer->lat)) * sin(ln_deg_to_rad(sol2.dec)));
	H1 = (cos(ln_deg_to_rad(observer->lat)) * cos(ln_deg_to_rad(sol2.dec)));

	H1 = H0 / H1;

	ret = check_coords (observer, H1, horizon, &sol2);
	if (ret)
		return ret;

	H0 = acos (H1);
	H0 = ln_rad_to_deg (H0);

	/* correct ra values for interpolation	- put them to the same side of circle */
	if ((sol1.ra - sol2.ra) > 180.0)
		sol2.ra += 360;

	if ((sol2.ra - sol3.ra) > 180.0)
		sol3.ra += 360;

	if ((sol3.ra - sol2.ra) > 180.0)
		sol3.ra -= 360;

	if ((sol2.ra - sol1.ra) > 180.0)
		sol3.ra -= 360;

	for (i = 0; i < 3; i++)
	{
		/* equ 15.2 */
		mt = (sol2.ra - observer->lng - O) / 360.0;
		mr = mt - H0 / 360.0;
		ms = mt + H0 / 360.0;

		/* put in correct range */
		if (mt > 1.0 )
			mt--;
		else if (mt < 0.0)
			mt++;
		if (mr > 1.0 )
			mr--;
		else if (mr < 0.0)
			mr++;
		if (ms > 1.0 )
			ms--;
		else if (ms < 0.0)
			ms++;
	
		/* find sidereal time at Greenwich, in degrees, for each m*/
		mst = O + 360.985647 * mt;
		msr = O + 360.985647 * mr;
		mss = O + 360.985647 * ms;

		nt = mt + T / 86400.0;
		nr = mr + T / 86400.0;
		ns = ms + T / 86400.0;
	
		/* interpolate ra and dec for each m, except for transit dec (dec2) */
		posr.ra = ln_interpolate3 (nr, sol1.ra, sol2.ra, sol3.ra);
		posr.dec = ln_interpolate3 (nr, sol1.dec, sol2.dec, sol3.dec);
		post.ra = ln_interpolate3 (nt, sol1.ra, sol2.ra, sol3.ra);
		poss.ra = ln_interpolate3 (ns, sol1.ra, sol2.ra, sol3.ra);
		poss.dec = ln_interpolate3 (ns, sol1.dec, sol2.dec, sol3.dec);
	
		/* find local hour angle */
		Hat = mst + observer->lng - post.ra;
		Har = msr + observer->lng - posr.ra;
		Has = mss + observer->lng - poss.ra;

		/* find altitude for rise and set */
		altr = sin(ln_deg_to_rad(observer->lat)) * sin(ln_deg_to_rad(posr.dec)) +
					cos(ln_deg_to_rad(observer->lat)) * cos(ln_deg_to_rad(posr.dec)) * cos(ln_deg_to_rad (Har));
		alts = sin(ln_deg_to_rad(observer->lat)) * sin(ln_deg_to_rad(poss.dec)) +
					cos(ln_deg_to_rad(observer->lat)) * cos(ln_deg_to_rad(poss.dec)) * cos(ln_deg_to_rad (Has));

		/* corrections for m */
		dmt = - (Hat / 360.0);
		dmr = (altr - horizon) / (360 * cos(ln_deg_to_rad(posr.dec)) * cos(ln_deg_to_rad(observer->lat)) * sin(ln_deg_to_rad(Har)));
		dms = (alts - horizon) / (360 * cos(ln_deg_to_rad(poss.dec)) * cos(ln_deg_to_rad(observer->lat)) * sin(ln_deg_to_rad(Has)));

		/* add corrections and change to JD */
		mt += dmt;
		mr += dmr;
		ms += dms;

		if (mt <= 1 && mt >= 0 && mr <= 1 && mr >= 0 && ms <= 1 && ms >= 0)
			break;
	}

	rst->rise = JD_UT + mr;
	rst->transit = JD_UT + mt;
	rst->set = JD_UT + ms;
	
	/* not circumpolar */
	return 0;
}
/* convert radians to dms */
void ln_rad_to_dms (double radians, struct ln_dms * dms)
{
    double degrees = ln_rad_to_deg(radians);
    
    ln_deg_to_dms(degrees, dms);
}