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; }
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; }
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; }