예제 #1
0
bool KSAsteroid::findGeocentricPosition( const KSNumbers *num, const KSPlanetBase *Earth ) {
    //determine the mean anomaly for the desired date.  This is the mean anomaly for the
    //ephemeis epoch, plus the number of days between the desired date and ephemeris epoch,
    //times the asteroid's mean daily motion (360/P):
    dms m = dms( double( M.Degrees() + ( num->julianDay() - JD ) * 360.0/P ) ).reduce();
    double sinm, cosm;
    m.SinCos( sinm, cosm );

    //compute eccentric anomaly:
    double E = m.Degrees() + e*180.0/dms::PI * sinm * ( 1.0 + e*cosm );

    if ( e > 0.05 ) { //need more accurate approximation, iterate...
        double E0;
        int iter(0);
        do {
            E0 = E;
            iter++;
            E = E0 - ( E0 - e*180.0/dms::PI *sin( E0*dms::DegToRad ) - m.Degrees() )/(1 - e*cos( E0*dms::DegToRad ) );
        } while ( fabs( E - E0 ) > 0.001 && iter < 1000 );
    }

    double sinE, cosE;
    dms E1( E );
    E1.SinCos( sinE, cosE );

    double xv = a * ( cosE - e );
    double yv = a * sqrt( 1.0 - e*e ) * sinE;

    //v is the true anomaly; r is the distance from the Sun
    double v = atan2( yv, xv ) / dms::DegToRad;
    double r = sqrt( xv*xv + yv*yv );

    //vw is the sum of the true anomaly and the argument of perihelion
    dms vw( v + w.Degrees() );
    double sinN, cosN, sinvw, cosvw, sini, cosi;

    N.SinCos( sinN, cosN );
    vw.SinCos( sinvw, cosvw );
    i.SinCos( sini, cosi );

    //xh, yh, zh are the heliocentric cartesian coords with the ecliptic plane congruent with zh=0.
    double xh = r * ( cosN * cosvw - sinN * sinvw * cosi );
    double yh = r * ( sinN * cosvw + cosN * sinvw * cosi );
    double zh = r * ( sinvw * sini );

    //the spherical ecliptic coordinates:
    double ELongRad = atan2( yh, xh );
    double ELatRad = atan2( zh, r );

    helEcPos.longitude.setRadians( ELongRad );
    helEcPos.latitude.setRadians( ELatRad );
    setRsun( r );

    if ( Earth ) {
        //xe, ye, ze are the Earth's heliocentric cartesian coords
        double cosBe, sinBe, cosLe, sinLe;
        Earth->ecLong().SinCos( sinLe, cosLe );
        Earth->ecLat().SinCos( sinBe, cosBe );

        double xe = Earth->rsun() * cosBe * cosLe;
        double ye = Earth->rsun() * cosBe * sinLe;
        double ze = Earth->rsun() * sinBe;

        //convert to geocentric ecliptic coordinates by subtracting Earth's coords:
        xh -= xe;
        yh -= ye;
        zh -= ze;
    }

    //the spherical geocentricecliptic coordinates:
    ELongRad = atan2( yh, xh );
    double rr = sqrt( xh*xh + yh*yh + zh*zh );
    ELatRad = atan2( zh, rr );

    ep.longitude.setRadians( ELongRad );
    ep.latitude.setRadians( ELatRad );
    if ( Earth ) setRearth( Earth );

    EclipticToEquatorial( num->obliquity() );
    nutate( num );
    aberrate( num );

    return true;
}
예제 #2
0
bool KSComet::findGeocentricPosition( const KSNumbers *num, const KSPlanetBase *Earth ) {
	double v(0.0), r(0.0);

	//Precess the longitude of the Ascending Node to the desired epoch:
	dms n = dms( double(N.Degrees() - 3.82394E-5 * ( num->julianDay() - J2000 )) ).reduce();

	if ( e > 0.98 ) {
		//Use near-parabolic approximation
		double k = 0.01720209895; //Gauss gravitational constant
		double a = 0.75 * ( num->julianDay() - JDp ) * k * sqrt( (1+e)/(q*q*q) );
		double b = sqrt( 1.0 + a*a );
		double W = pow((b+a),1.0/3.0) - pow((b-a),1.0/3.0);
		double c = 1.0 + 1.0/(W*W);
		double f = (1.0-e)/(1.0+e);
		double g = f/(c*c);

		double a1 = (2.0/3.0) + (2.0*W*W/5.0);
		double a2 = (7.0/5.0) + (33.0*W*W/35.0) + (37.0*W*W*W*W/175.0);
		double a3 = W*W*( (432.0/175.0) + (956.0*W*W/1125.0) + (84.0*W*W*W*W/1575.0) );
		double w = W*(1.0 + g*c*( a1 + a2*g + a3*g*g ));

		v = 2.0*atan(w) / dms::DegToRad;
		r = q*( 1.0 + w*w )/( 1.0 + w*w*f );
	} else {
		//Use normal ellipse method
		//Determine Mean anomaly for desired date:
		dms m = dms( double(360.0*( num->julianDay() - JDp )/P) ).reduce();
		double sinm, cosm;
		m.SinCos( sinm, cosm );

		//compute eccentric anomaly:
		double E = m.Degrees() + e*180.0/dms::PI * sinm * ( 1.0 + e*cosm );

		if ( e > 0.05 ) { //need more accurate approximation, iterate...
			double E0;
			int iter(0);
			do {
				E0 = E;
				iter++;
				E = E0 - ( E0 - e*180.0/dms::PI *sin( E0*dms::DegToRad ) - m.Degrees() )/(1 - e*cos( E0*dms::DegToRad ) );
			} while ( fabs( E - E0 ) > 0.001 && iter < 1000 );
		}

		double sinE, cosE;
		dms E1( E );
		E1.SinCos( sinE, cosE );

		double xv = a * ( cosE - e );
		double yv = a * sqrt( 1.0 - e*e ) * sinE;

		//v is the true anomaly; r is the distance from the Sun

		v = atan( yv/xv ) / dms::DegToRad;
		//resolve atan ambiguity
		if ( xv < 0.0 ) v += 180.0;

		r = sqrt( xv*xv + yv*yv );
	}

	//vw is the sum of the true anomaly and the argument of perihelion
	dms vw( v + w.Degrees() );
	double sinN, cosN, sinvw, cosvw, sini, cosi;

	n.SinCos( sinN, cosN );
	vw.SinCos( sinvw, cosvw );
	i.SinCos( sini, cosi );

	//xh, yh, zh are the heliocentric cartesian coords with the ecliptic plane congruent with zh=0.
	double xh = r * ( cosN * cosvw - sinN * sinvw * cosi );
	double yh = r * ( sinN * cosvw + cosN * sinvw * cosi );
	double zh = r * ( sinvw * sini );

	//xe, ye, ze are the Earth's heliocentric cartesian coords
	double cosBe, sinBe, cosLe, sinLe;
	Earth->ecLong()->SinCos( sinLe, cosLe );
	Earth->ecLat()->SinCos( sinBe, cosBe );

	double xe = Earth->rsun() * cosBe * cosLe;
	double ye = Earth->rsun() * cosBe * sinLe;
	double ze = Earth->rsun() * sinBe;

	//convert to geocentric ecliptic coordinates by subtracting Earth's coords:
	xh -= xe;
	yh -= ye;
	zh -= ze;

	//Finally, the spherical ecliptic coordinates:
	double ELongRad = atan( yh/xh );
	//resolve atan ambiguity
	if ( xh < 0.0 ) ELongRad += dms::PI;

	double rr = sqrt( xh*xh + yh*yh );
	double ELatRad = atan( zh/rr );  //(rr can't possibly be negative, so no atan ambiguity)

	ep.longitude.setRadians( ELongRad );
	ep.latitude.setRadians( ELatRad );
	setRsun( r );
	setRearth( Earth );
	
	EclipticToEquatorial( num->obliquity() );
	nutate( num );
	aberrate( num );

	return true;
}
예제 #3
0
bool KSPlanet::findGeocentricPosition( const KSNumbers *num, const KSPlanetBase *Earth ) {

    if ( Earth != NULL ) {
        double sinL, sinL0, sinB, sinB0;
        double cosL, cosL0, cosB, cosB0;
        double x = 0.0, y = 0.0, z = 0.0;

        double olddst = -1000;
        double dst = 0;

        EclipticPosition trialpos;

        double jm = num->julianMillenia();

        Earth->ecLong().SinCos( sinL0, cosL0 );
        Earth->ecLat().SinCos( sinB0, cosB0 );

        double eX = Earth->rsun()*cosB0*cosL0;
        double eY = Earth->rsun()*cosB0*sinL0;
        double eZ = Earth->rsun()*sinB0;

        bool once=true;
        while (fabs(dst - olddst) > .001) {
            calcEcliptic(jm, trialpos);

            // We store the heliocentric ecliptic coordinates the first time they are computed.
            if(once){
                helEcPos = trialpos;
                once=false;
            }

            olddst = dst;

            trialpos.longitude.SinCos( sinL, cosL );
            trialpos.latitude.SinCos( sinB, cosB );

            x = trialpos.radius*cosB*cosL - eX;
            y = trialpos.radius*cosB*sinL - eY;
            z = trialpos.radius*sinB - eZ;

            //distance from Earth
            dst = sqrt(x*x + y*y + z*z);

            //The light-travel time delay, in millenia
            //0.0057755183 is the inverse speed of light,
            //in days/AU
            double delay = (.0057755183 * dst) / 365250.0;

            jm = num->julianMillenia() - delay;

        }

        ep.longitude.setRadians( atan2( y, x ) );
        ep.longitude.reduce();
        ep.latitude.setRadians( atan2( z, sqrt( x*x + y*y ) ) );
        setRsun( trialpos.radius );
        setRearth( dst );

        EclipticToEquatorial( num->obliquity() );

        nutate(num);
        aberrate(num);

    } else {

        calcEcliptic(num->julianMillenia(), ep);
        helEcPos = ep;
    }

    //determine the position angle
    findPA( num );

    return true;
}