• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kstars

skypoint.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           skypoint.cpp  -  K Desktop Planetarium
00003                              -------------------
00004     begin                : Sun Feb 11 2001
00005     copyright            : (C) 2001-2005 by Jason Harris
00006     email                : jharris@30doradus.org
00007     copyright            : (C) 2004-2005 by Pablo de Vicente
00008     email                : p.devicente@wanadoo.es
00009  ***************************************************************************/
00010 
00011 /***************************************************************************
00012  *                                                                         *
00013  *   This program is free software; you can redistribute it and/or modify  *
00014  *   it under the terms of the GNU General Public License as published by  *
00015  *   the Free Software Foundation; either version 2 of the License, or     *
00016  *   (at your option) any later version.                                   *
00017  *                                                                         *
00018  ***************************************************************************/
00019 
00020 #include <kdebug.h>
00021 #include <klocale.h>
00022 
00023 #include "skypoint.h"
00024 #include "skyobject.h"
00025 #include "dms.h"
00026 #include "ksnumbers.h"
00027 #include "csegment.h"
00028 
00029 void SkyPoint::set( const dms& r, const dms& d ) {
00030     RA0.set( r );
00031     Dec0.set( d );
00032     RA.set( r );
00033     Dec.set( d );
00034 }
00035 
00036 void SkyPoint::set( double r, double d ) {
00037     RA0.setH( r );
00038     Dec0.setD( d );
00039     RA.setH( r );
00040     Dec.setD( d );
00041 }
00042 
00043 SkyPoint::~SkyPoint(){
00044 }
00045 
00046 void SkyPoint::EquatorialToHorizontal( const dms *LST, const dms *lat ) {
00047     double AltRad, AzRad;
00048     double sindec, cosdec, sinlat, coslat, sinHA, cosHA;
00049   double sinAlt, cosAlt;
00050 
00051     dms HourAngle = LST->Degrees() - ra()->Degrees();
00052 
00053     lat->SinCos( sinlat, coslat );
00054     dec()->SinCos( sindec, cosdec );
00055     HourAngle.SinCos( sinHA, cosHA );
00056 
00057     sinAlt = sindec*sinlat + cosdec*coslat*cosHA;
00058     AltRad = asin( sinAlt );
00059     cosAlt = cos( AltRad );
00060 
00061     double arg = ( sindec - sinlat*sinAlt )/( coslat*cosAlt );
00062     if ( arg <= -1.0 ) AzRad = dms::PI;
00063     else if ( arg >= 1.0 ) AzRad = 0.0;
00064     else AzRad = acos( arg );
00065     
00066     if ( sinHA > 0.0 ) AzRad = 2.0*dms::PI - AzRad; // resolve acos() ambiguity
00067 
00068     Alt.setRadians( AltRad );
00069     Az.setRadians( AzRad );
00070 }
00071 
00072 void SkyPoint::HorizontalToEquatorial( const dms *LST, const dms *lat ) {
00073     double HARad, DecRad;
00074     double sinlat, coslat, sinAlt, cosAlt, sinAz, cosAz;
00075   double sinDec, cosDec;
00076 
00077     lat->SinCos( sinlat, coslat );
00078     alt()->SinCos( sinAlt, cosAlt );
00079     Az.SinCos( sinAz,  cosAz );
00080 
00081     sinDec = sinAlt*sinlat + cosAlt*coslat*cosAz;
00082     DecRad = asin( sinDec );
00083     cosDec = cos( DecRad );
00084     Dec.setRadians( DecRad );
00085 
00086     double x = ( sinAlt - sinlat*sinDec )/( coslat*cosDec );
00087 
00088 //Under certain circumstances, x can be very slightly less than -1.0000, or slightly
00089 //greater than 1.0000, leading to a crash on acos(x).  However, the value isn't
00090 //*really* out of range; it's a kind of roundoff error.
00091     if ( x < -1.0 && x > -1.000001 ) HARad = dms::PI;
00092     else if ( x > 1.0 && x < 1.000001 ) HARad = 0.0;
00093     else if ( x < -1.0 ) {
00094         kdWarning() << i18n( "Coordinate out of range." );
00095         HARad = dms::PI;
00096     } else if ( x > 1.0 ) {
00097         kdWarning() << i18n( "Coordinate out of range." );
00098         HARad = 0.0;
00099     } else HARad = acos( x );
00100 
00101     if ( sinAz > 0.0 ) HARad = 2.0*dms::PI - HARad; // resolve acos() ambiguity
00102 
00103     RA.setRadians( LST->radians() - HARad );
00104     RA.setD( RA.reduce().Degrees() );  // 0 <= RA < 24
00105 }
00106 
00107 void SkyPoint::findEcliptic( const dms *Obliquity, dms &EcLong, dms &EcLat ) {
00108     double sinRA, cosRA, sinOb, cosOb, sinDec, cosDec, tanDec;
00109     ra()->SinCos( sinRA, cosRA );
00110     dec()->SinCos( sinDec, cosDec );
00111     Obliquity->SinCos( sinOb, cosOb );
00112 
00113     tanDec = sinDec/cosDec;
00114     double y = sinRA*cosOb + tanDec*sinOb;
00115     double ELongRad = atan( y/cosRA );
00116     //resolve atan ambiguity
00117     if ( cosRA < 0 ) ELongRad += dms::PI;
00118     if ( cosRA > 0 && y < 0 ) ELongRad += 2.0*dms::PI;
00119 
00120     EcLong.setRadians( ELongRad );
00121     EcLat.setRadians( asin( sinDec*cosOb - cosDec*sinOb*sinRA ) );
00122 }
00123 
00124 void SkyPoint::setFromEcliptic( const dms *Obliquity, const dms *EcLong, const dms *EcLat ) {
00125     double sinLong, cosLong, sinLat, cosLat, sinObliq, cosObliq;
00126     EcLong->SinCos( sinLong, cosLong );
00127     EcLat->SinCos( sinLat, cosLat );
00128     Obliquity->SinCos( sinObliq, cosObliq );
00129 
00130     double sinDec = sinLat*cosObliq + cosLat*sinObliq*sinLong;
00131 
00132     double y = sinLong*cosObliq - (sinLat/cosLat)*sinObliq;
00133     double RARad =  atan( y / cosLong );
00134 
00135     //resolve ambiguity of atan:
00136     if ( cosLong < 0 ) RARad += dms::PI;
00137     if ( cosLong > 0 && y < 0 ) RARad += 2.0*dms::PI;
00138 
00139     //DMS_SPEED
00140     //dms newRA, newDec;
00141     //newRA.setRadians( RARad );
00142     //newDec.setRadians( asin( sinDec ) );
00143     RA.setRadians( RARad );
00144     Dec.setRadians( asin(sinDec) );
00145 }
00146 
00147 void SkyPoint::precess( const KSNumbers *num) {
00148     double cosRA0, sinRA0, cosDec0, sinDec0;
00149     double v[3], s[3];
00150 
00151     RA0.SinCos( sinRA0, cosRA0 );
00152     Dec0.SinCos( sinDec0, cosDec0 );
00153 
00154     s[0] = cosRA0*cosDec0;
00155     s[1] = sinRA0*cosDec0;
00156     s[2] = sinDec0;
00157     //Multiply P2 and s to get v, the vector representing the new coords.
00158     for ( unsigned int i=0; i<3; ++i ) {
00159         v[i] = 0.0;
00160         for (uint j=0; j< 3; ++j) {
00161             v[i] += num->p2( j, i )*s[j];
00162         }
00163     }
00164 
00165     //Extract RA, Dec from the vector:
00166     RA.setRadians( atan( v[1]/v[0] ) );
00167     Dec.setRadians( asin( v[2] ) );
00168 
00169     //resolve ambiguity of atan()
00170     if ( v[0] < 0.0 ) {
00171         RA.setD( RA.Degrees() + 180.0 );
00172     } else if( v[1] < 0.0 ) {
00173         RA.setD( RA.Degrees() + 360.0 );
00174     }
00175 }
00176 
00177 void SkyPoint::nutate(const KSNumbers *num) {
00178     double cosRA, sinRA, cosDec, sinDec, tanDec;
00179     dms dRA1, dRA2, dDec1, dDec2;
00180     double cosOb, sinOb;
00181 
00182     RA.SinCos( sinRA, cosRA );
00183     Dec.SinCos( sinDec, cosDec );
00184 
00185     num->obliquity()->SinCos( sinOb, cosOb );
00186 
00187     //Step 2: Nutation
00188     if ( fabs( Dec.Degrees() ) < 80.0 ) { //approximate method
00189         tanDec = sinDec/cosDec;
00190 
00191         dRA1.setD( num->dEcLong()*( cosOb + sinOb*sinRA*tanDec ) - num->dObliq()*cosRA*tanDec );
00192         dDec1.setD( num->dEcLong()*( sinOb*cosRA ) + num->dObliq()*sinRA );
00193 
00194         RA.setD( RA.Degrees() + dRA1.Degrees() );
00195         Dec.setD( Dec.Degrees() + dDec1.Degrees() );
00196     } else { //exact method
00197         dms EcLong, EcLat;
00198         findEcliptic( num->obliquity(), EcLong, EcLat );
00199 
00200         //Add dEcLong to the Ecliptic Longitude
00201         dms newLong( EcLong.Degrees() + num->dEcLong() );
00202         setFromEcliptic( num->obliquity(), &newLong, &EcLat );
00203     }
00204 }
00205 
00206 void SkyPoint::aberrate(const KSNumbers *num) {
00207     double cosRA, sinRA, cosDec, sinDec;
00208     dms dRA2, dDec2;
00209     double cosOb, sinOb, cosL, sinL, cosP, sinP;
00210 
00211     double K = num->constAberr().Degrees();  //constant of aberration
00212     double e = num->earthEccentricity();
00213 
00214     RA.SinCos( sinRA, cosRA );
00215     Dec.SinCos( sinDec, cosDec );
00216 
00217     num->obliquity()->SinCos( sinOb, cosOb );
00218     double tanOb = sinOb/cosOb;
00219 
00220     num->sunTrueLongitude().SinCos( sinL, cosL );
00221     num->earthPerihelionLongitude().SinCos( sinP, cosP );
00222 
00223 
00224     //Step 3: Aberration
00225     dRA2.setD( -1.0 * K * ( cosRA * cosL * cosOb + sinRA * sinL )/cosDec
00226         + e * K * ( cosRA * cosP * cosOb + sinRA * sinP )/cosDec );
00227 
00228     dDec2.setD( -1.0 * K * ( cosL * cosOb * ( tanOb * cosDec - sinRA * sinDec ) + cosRA * sinDec * sinL )
00229         + e * K * ( cosP * cosOb * ( tanOb * cosDec - sinRA * sinDec ) + cosRA * sinDec * sinP ) );
00230 
00231     RA.setD( RA.Degrees() + dRA2.Degrees() );
00232     Dec.setD( Dec.Degrees() + dDec2.Degrees() );
00233 }
00234 
00235 void SkyPoint::updateCoords( KSNumbers *num, bool /*includePlanets*/, const dms *lat, const dms *LST ) {
00236     dms pRA, pDec;
00237     //Correct the catalog coordinates for the time-dependent effects
00238     //of precession, nutation and aberration
00239 
00240     precess(num);
00241     nutate(num);
00242     aberrate(num);
00243 
00244     if ( lat || LST )
00245         kdWarning() << i18n( "lat and LST parameters should only be used in KSPlanetBase objects." ) << endl;
00246 }
00247 
00248 void SkyPoint::precessFromAnyEpoch(long double jd0, long double jdf){
00249 
00250     double cosRA, sinRA, cosDec, sinDec;
00251         double v[3], s[3];
00252 
00253     RA.setD( RA0.Degrees() );
00254     Dec.setD( Dec0.Degrees() );
00255 
00256     RA.SinCos( sinRA, cosRA );
00257     Dec.SinCos( sinDec, cosDec );
00258 
00259     if (jd0 == jdf)
00260         return;
00261 
00262     if ( jd0 == B1950) {
00263         B1950ToJ2000();
00264         jd0 = J2000;
00265         RA.SinCos( sinRA, cosRA );
00266         Dec.SinCos( sinDec, cosDec );
00267 
00268     }
00269 
00270     if (jd0 !=jdf) {
00271         // The original coordinate is referred to the FK5 system and
00272         // is NOT J2000.
00273         if ( jd0 != J2000 ) {
00274 
00275         //v is a column vector representing input coordinates.
00276 
00277             KSNumbers *num = new KSNumbers (jd0);
00278 
00279             v[0] = cosRA*cosDec;
00280             v[1] = sinRA*cosDec;
00281             v[2] = sinDec;
00282 
00283             //Need to first precess to J2000.0 coords
00284             //s is the product of P1 and v; s represents the
00285             //coordinates precessed to J2000
00286             for ( unsigned int i=0; i<3; ++i ) {
00287                 s[i] = num->p1( 0, i )*v[0] +
00288                     num->p1( 1, i )*v[1] +
00289                     num->p1( 2, i )*v[2];
00290             }
00291             delete num;
00292 
00293         //Input coords already in J2000, set s accordingly.
00294         } else {
00295 
00296             s[0] = cosRA*cosDec;
00297             s[1] = sinRA*cosDec;
00298             s[2] = sinDec;
00299         }
00300 
00301         if ( jdf == B1950) {
00302 
00303             RA.setRadians( atan2( s[1],s[0] ) );
00304             Dec.setRadians( asin( s[2] ) );
00305             J2000ToB1950();
00306 
00307             return;
00308         }
00309 
00310         KSNumbers *num = new KSNumbers (jdf);
00311 
00312         for ( unsigned int i=0; i<3; ++i ) {
00313             v[i] = num->p2( 0, i )*s[0] +
00314             num->p2( 1, i )*s[1] +
00315             num->p2( 2, i )*s[2];
00316         }
00317 
00318         delete num;
00319 
00320         RA.setRadians( atan2( v[1],v[0] ) );
00321         Dec.setRadians( asin( v[2] ) );
00322 
00323         if (RA.Degrees() < 0.0 )
00324             RA.setD( RA.Degrees() + 360.0 );
00325 
00326         return;
00327     } 
00328 
00329 }
00330 
00332 void SkyPoint::apparentCoord(long double jd0, long double jdf){
00333 
00334     precessFromAnyEpoch(jd0,jdf);
00335 
00336     KSNumbers *num = new KSNumbers (jdf);
00337 
00338     nutate(num);
00339     aberrate(num);
00340 
00341     delete num;
00342 }
00343 
00344 void SkyPoint::Equatorial1950ToGalactic(dms &galLong, dms &galLat) {
00345     
00346     double a = 192.25;
00347     dms b, c;
00348     double sinb, cosb, sina_RA, cosa_RA, sinDEC, cosDEC, tanDEC;
00349 
00350     c.setD(303);
00351     b.setD(27.4);
00352     tanDEC = tan( Dec.radians() );
00353 
00354     b.SinCos(sinb,cosb);
00355     dms( a - RA.Degrees() ).SinCos(sina_RA,cosa_RA);
00356     Dec.SinCos(sinDEC,cosDEC);
00357 
00358     galLong.setRadians( c.radians() - atan2( sina_RA, cosa_RA*sinb-tanDEC*cosb) );
00359     galLong = galLong.reduce();
00360 
00361     galLat.setRadians( asin(sinDEC*sinb+cosDEC*cosb*cosa_RA) );
00362 }
00363 
00364 void SkyPoint::GalacticToEquatorial1950(const dms* galLong, const dms* galLat) {
00365 
00366     double a = 123.0;
00367     dms b, c, galLong_a;
00368     double sinb, cosb, singLat, cosgLat, tangLat, singLong_a, cosgLong_a;
00369 
00370     c.setD(12.25);
00371     b.setD(27.4);
00372     tangLat = tan( galLat->radians() );
00373 
00374 
00375     galLat->SinCos(singLat,cosgLat);
00376 
00377     dms( galLong->Degrees()-a ).SinCos(singLong_a,cosgLong_a);
00378     b.SinCos(sinb,cosb);
00379 
00380     RA.setRadians(c.radians() + atan2(singLong_a,cosgLong_a*sinb-tangLat*cosb) );
00381     RA = RA.reduce();
00382 //  raHourCoord = dms( raCoord.Hours() );
00383 
00384     Dec.setRadians( asin(singLat*sinb+cosgLat*cosb*cosgLong_a) );
00385 }
00386 
00387 void SkyPoint::B1950ToJ2000(void) {
00388     double cosRA, sinRA, cosDec, sinDec;
00389 //  double cosRA0, sinRA0, cosDec0, sinDec0;
00390         double v[3], s[3];
00391 
00392     // 1984 January 1 0h
00393     KSNumbers *num = new KSNumbers (2445700.5);
00394 
00395     // Eterms due to aberration
00396     addEterms();
00397     RA.SinCos( sinRA, cosRA );
00398     Dec.SinCos( sinDec, cosDec );
00399 
00400     // Precession from B1950 to J1984
00401     s[0] = cosRA*cosDec;
00402     s[1] = sinRA*cosDec;
00403     s[2] = sinDec;
00404     for ( unsigned int i=0; i<3; ++i ) {
00405         v[i] = num->p2b( 0, i )*s[0] + num->p2b( 1, i )*s[1] +
00406         num->p2b( 2, i )*s[2];
00407     }
00408 
00409     // RA zero-point correction at 1984 day 1, 0h.
00410     RA.setRadians( atan2( v[1],v[0] ) );
00411     Dec.setRadians( asin( v[2] ) );
00412 
00413     RA.setH( RA.Hours() + 0.06390/3600. );
00414     RA.SinCos( sinRA, cosRA );
00415     Dec.SinCos( sinDec, cosDec );
00416 
00417     s[0] = cosRA*cosDec;
00418     s[1] = sinRA*cosDec;
00419     s[2] = sinDec;
00420 
00421     // Precession from 1984 to J2000.
00422 
00423     for ( unsigned int i=0; i<3; ++i ) {
00424         v[i] = num->p1( 0, i )*s[0] +
00425         num->p1( 1, i )*s[1] +
00426         num->p1( 2, i )*s[2];
00427     }
00428 
00429     RA.setRadians( atan2( v[1],v[0] ) );
00430     Dec.setRadians( asin( v[2] ) );
00431 
00432     delete num;
00433 }
00434 
00435 void SkyPoint::J2000ToB1950(void) {
00436     double cosRA, sinRA, cosDec, sinDec;
00437 //  double cosRA0, sinRA0, cosDec0, sinDec0;
00438         double v[3], s[3];
00439 
00440     // 1984 January 1 0h
00441     KSNumbers *num = new KSNumbers (2445700.5);
00442 
00443     RA.SinCos( sinRA, cosRA );
00444     Dec.SinCos( sinDec, cosDec );
00445 
00446     s[0] = cosRA*cosDec;
00447     s[1] = sinRA*cosDec;
00448     s[2] = sinDec;
00449 
00450     // Precession from J2000 to 1984 day, 0h.
00451 
00452     for ( unsigned int i=0; i<3; ++i ) {
00453         v[i] = num->p2( 0, i )*s[0] +
00454         num->p2( 1, i )*s[1] +
00455         num->p2( 2, i )*s[2];
00456     }
00457 
00458     RA.setRadians( atan2( v[1],v[0] ) );
00459     Dec.setRadians( asin( v[2] ) );
00460 
00461     // RA zero-point correction at 1984 day 1, 0h.
00462 
00463     RA.setH( RA.Hours() - 0.06390/3600. );
00464     RA.SinCos( sinRA, cosRA );
00465     Dec.SinCos( sinDec, cosDec );
00466 
00467     // Precession from B1950 to J1984
00468 
00469     s[0] = cosRA*cosDec;
00470     s[1] = sinRA*cosDec;
00471     s[2] = sinDec;
00472     for ( unsigned int i=0; i<3; ++i ) {
00473         v[i] = num->p1b( 0, i )*s[0] + num->p1b( 1, i )*s[1] +
00474         num->p1b( 2, i )*s[2];
00475     }
00476 
00477     RA.setRadians( atan2( v[1],v[0] ) );
00478     Dec.setRadians( asin( v[2] ) );
00479 
00480     // Eterms due to aberration
00481     subtractEterms();
00482 
00483     delete num;
00484 }
00485 
00486 SkyPoint SkyPoint::Eterms(void) {
00487 
00488     double sd, cd, sinEterm, cosEterm;
00489     dms raTemp, raDelta, decDelta;
00490 
00491     Dec.SinCos(sd,cd);
00492     raTemp.setH( RA.Hours() + 11.25);
00493     raTemp.SinCos(sinEterm,cosEterm);
00494 
00495     raDelta.setH( 0.0227*sinEterm/(3600.*cd) );
00496     decDelta.setD( 0.341*cosEterm*sd/3600. + 0.029*cd/3600. );
00497 
00498     SkyPoint spDelta = SkyPoint (raDelta, decDelta);
00499 
00500     return spDelta;
00501 }
00502 
00503 void SkyPoint::addEterms(void) {
00504 
00505     SkyPoint spd = Eterms();
00506 
00507     RA.setD( RA.Degrees() + spd.ra()->Degrees() );
00508     Dec.setD( Dec.Degrees() + spd.dec()->Degrees() );
00509 
00510 }
00511 
00512 void SkyPoint::subtractEterms(void) {
00513 
00514     SkyPoint spd = Eterms();
00515 
00516     RA.setD( RA.Degrees() - spd.ra()->Degrees() );
00517     Dec.setD( Dec.Degrees() - spd.dec()->Degrees() );
00518 }
00519 
00520 dms SkyPoint::angularDistanceTo(SkyPoint *sp) {
00521 
00522     double dalpha = ra()->radians() - sp->ra()->radians() ;
00523     double ddelta = dec()->radians() - sp->dec()->radians() ;
00524 
00525     double sa = sin(dalpha/2.);
00526     double sd = sin(ddelta/2.);
00527     
00528     double hava = sa*sa;
00529     double havd = sd*sd;
00530 
00531     double aux = havd + cos (dec()->radians()) * cos(sp->dec()->radians()) 
00532         * hava;
00533     
00534     dms angDist;
00535     angDist.setRadians( 2 * fabs(asin( sqrt(aux) )) );
00536     
00537     return angDist;
00538 }
00539 
00540 QString SkyPoint::constellation( QPtrList<CSegment> &csegmentList, QPtrList<SkyObject> &cnameList ) const {
00541     //Identify the constellation that contains point p.
00542     //First, find all CSegments that bracket the RA of p.
00543     //Then, identify the pair of these bracketing segments which bracket p in the Dec direction.
00544     //Each segment has two cnames, identifying the 2 constellations which the segment delineates.
00545     //There will be a name in common between the pair, this is the constellation that p is in.
00546     //
00547     //Corner case 1: points near the celestial poles are not bracketed by csegments.
00548     //Corner case 2: it is possible that *both* cnames are shared between the two segments.
00549     //In this case, we have to do more work to decide which is truly correct.
00550     
00551     QPtrList<SkyPoint> p1List, p2List;
00552     QStringList name1List, name2List;
00553     QString abbrev("");
00554 
00555     double pdc = dec()->Degrees();
00556     double pra(0.0); //defined in the loop, because we may modify it there
00557 
00558     for ( CSegment *seg = csegmentList.first(); seg; seg = csegmentList.next() ) {
00559         SkyPoint *p1 = seg->firstNode();
00560         for ( SkyPoint *p2 = seg->nextNode(); p2; p2 = seg->nextNode() ) {
00561             pra = ra()->Degrees(); 
00562             double p1ra = p1->ra()->Degrees();
00563             double p2ra = p2->ra()->Degrees();
00564             if ( p1ra > 330. && p2ra < 30. ) { //wrap RA coordinate, if necessary
00565                 p1ra -= 360.0; 
00566                 if ( pra > 330. ) pra -= 360.;
00567             }
00568             if ( p2ra > 330. && p1ra < 30. ) { //wrap RA coordinate, if necessary
00569                 p2ra -= 360.0; 
00570                 if ( pra > 330. ) pra -= 360.;
00571             }
00572             
00573             if ( p1ra <= pra && p2ra >= pra ) { //bracketing segment?
00574                 p1List.append( p1 );
00575                 p2List.append( p2 );
00576                 name1List.append( seg->name1() );
00577                 name2List.append( seg->name2() );
00578                 break;
00579             } else if ( p2ra <= pra && p1ra >= pra ) { //bracketing segment? (RA order reversed)
00580                 p1List.append( p2 ); //make sure p1List gets the smaller bracketing RA
00581                 p2List.append( p1 );
00582                 name1List.append( seg->name1() );
00583                 name2List.append( seg->name2() );
00584                 break;
00585             }
00586             p1 = p2;
00587         }
00588     }
00589 
00590     //Should not happen:
00591     if ( p1List.count() == 0 ) {
00592         kdWarning() << "A: " << i18n("No constellation found for point: (%1, %2)").arg(ra()->toHMSString()).arg(dec()->toDMSString()) << endl;
00593         return i18n("Unknown");
00594     }
00595 
00596     //Normal case: more than one segment brackets in RA.  Find segments which also bracket in Dec.
00597     double dupper(90.), dlower(-90.);
00598     int iupper(-1), ilower(-1);
00599     for ( uint i=0; i < p1List.count(); ++i ) {
00600         SkyPoint *p1 = p1List.at(i);
00601         SkyPoint *p2 = p2List.at(i);
00602         
00603         //Find Dec value along segment at RA of p:
00604         double f = ( pra - p1->ra()->Degrees() ) / ( p2->ra()->Degrees() - p1->ra()->Degrees()); //fractional distance along segment
00605         double segDec = f*p2->dec()->Degrees() + (1.0-f)*p1->dec()->Degrees();
00606         if ( segDec >= pdc && segDec < dupper ) { dupper = segDec; iupper = i; }
00607         if ( segDec <= pdc && segDec > dlower ) { dlower = segDec; ilower = i; }
00608     }
00609 
00610     //Corner case 1: Points near one of the poles are not bracketed by segments in the Dec direction.
00611     //In this case, either iupper or ilower will remain at its preassigned invalid value (-1)
00612     //Identify the constellation by extrapolating away from the pole to the next segment.
00613     //This will identify which of the two names is the neighboring constellation
00614     //so our target constell. is the other one.
00615     //(note that we can't just assume Ursa Minor or Octans, because of precession: these constellations 
00616     //are not near the pole at all epochs
00617     if ( iupper == -1 ) { //point near north pole
00618         int ilow2(-1);
00619         double dlow2(-90.);
00620         for ( uint i=0; i < p1List.count(); ++i ) {
00621             if ( i != ilower ) {
00622                 SkyPoint *p1 = p1List.at(i);
00623                 SkyPoint *p2 = p2List.at(i);
00624                 
00625                 //Find Dec value along segment at RA of p:
00626                 double f = ( pra - p1->ra()->Degrees() ) / ( p2->ra()->Degrees() - p1->ra()->Degrees()); //fractional distance along segment
00627                 double segDec = f*p2->dec()->Degrees() + (1.0-f)*p1->dec()->Degrees();
00628                 if ( segDec > dlow2 && segDec < dlower ) { dlow2 = segDec; ilow2 = i; }
00629             }
00630         }
00631 
00632         if ( ilow2 == -1 ) { //whoops, what happened?
00633             kdWarning() << "B: " << i18n("No constellation found for point: (%1, %2)").arg(ra()->toHMSString()).arg(dec()->toDMSString()) << endl;
00634             return i18n("Unknown");
00635         }
00636 
00637         //If name1(ilower) is the adjacent constellation, then name2(ilower) must be the answer
00638         if ( name1List[ ilower ] == name1List[ ilow2 ] || name1List[ ilower ] == name2List[ ilow2 ] )
00639             abbrev = name2List[ ilower ];
00640 
00641         //If name2(ilower) is the adjacent constellation, then name1(ilower) must be the answer
00642         else if ( name2List[ ilower ] == name1List[ ilow2 ] || name2List[ ilower ] == name2List[ ilow2 ] )
00643             abbrev = name1List[ ilower ];
00644 
00645         else { //doh!
00646             kdWarning() << "C: " << i18n("No constellation found for point: (%1, %2)").arg(ra()->toHMSString()).arg(dec()->toDMSString()) << endl;
00647             return i18n("Unknown");
00648         }
00649 
00650     } else if ( ilower == -1 ) { //point near south pole
00651         int iup2(-1);
00652         double dup2(90.);
00653         for ( uint i=0; i < p1List.count(); ++i ) {
00654             if ( i != iupper ) {
00655                 SkyPoint *p1 = p1List.at(i);
00656                 SkyPoint *p2 = p2List.at(i);
00657                 
00658                 //Find Dec value along segment at RA of p:
00659                 double f = ( pra - p1->ra()->Degrees() ) / ( p2->ra()->Degrees() - p1->ra()->Degrees()); //fractional distance along segment
00660                 double segDec = f*p2->dec()->Degrees() + (1.0-f)*p1->dec()->Degrees();
00661                 if ( segDec < dup2 && segDec > dupper ) { dup2 = segDec; iup2 = i; }
00662             }
00663         }
00664 
00665         if ( iup2 == -1 ) { //whoops, what happened?
00666             kdWarning() << "D: " << i18n("No constellation found for point: (%1, %2)").arg(ra()->toHMSString()).arg(dec()->toDMSString()) << endl;
00667             return i18n("Unknown");
00668         }
00669 
00670         //If name1(iupper) is the adjacent constellation, then name2(iupper) must be the answer
00671         if ( name1List[ iupper ] == name1List[ iup2 ] || name1List[ iupper ] == name2List[ iup2 ] )
00672             abbrev = name2List[ iupper ] ;
00673 
00674         //If name2(iupper) is the adjacent constellation, then name1(iupper) must be the answer
00675         else if ( name2List[ iupper ] == name1List[ iup2 ] || name2List[ iupper ] == name2List[ iup2 ] )
00676             abbrev = name1List[ iupper ];
00677 
00678         else { //doh!
00679             kdWarning() << "E: " << i18n("No constellation found for point: (%1, %2)").arg(ra()->toHMSString()).arg(dec()->toDMSString()) << endl;
00680             return i18n("Unknown");
00681         }
00682     }
00683 
00684     //Corner case 2: Both name1 and name2 are in common in the bracketing segments
00685     //This can happen if a constellation is both above and below the true bracketing constellation
00686     //Resolve it by again extending up or down to the next segment, which will share one of the ambiguous 
00687     //names.  The answer is the one not shared in this next segment.
00688     //To ensure that there will be a next segment, go up if dec is negative, otherwise go down.
00689     else if ( (name1List[ iupper ] == name1List[ ilower ] || name1List[ iupper ] == name2List[ ilower ]) 
00690         && (name2List[ iupper ] == name1List[ ilower ] || name2List[ iupper ] == name2List[ ilower ]) ) {
00691         if ( pdc < 0.0 ) { //find next segment up
00692             int iup2(0);
00693             double dup2(90.0);
00694 
00695             for ( uint i=0; i < p1List.count(); ++i ) {
00696                 if ( i != iupper ) {
00697                     SkyPoint *p1 = p1List.at(i);
00698                     SkyPoint *p2 = p2List.at(i);
00699                     
00700                     //Find Dec value along segment at RA of p:
00701                     double f = ( pra - p1->ra()->Degrees() ) / ( p2->ra()->Degrees() - p1->ra()->Degrees()); //fractional distance along segment
00702                     double segDec = f*p2->dec()->Degrees() + (1.0-f)*p1->dec()->Degrees();
00703                     if ( segDec < dup2 && segDec > dupper ) { dup2 = segDec; iup2 = i; }
00704                 }
00705             }
00706 
00707             //If name1(iupper) is the adjacent constellation, then name2(iupper) must be the answer
00708             if ( name1List[ iupper ] == name1List[ iup2 ] || name1List[ iupper ] == name2List[ iup2 ] )
00709                 abbrev = name2List[ iupper ];
00710     
00711             //If name2(iupper) is the adjacent constellation, then name1(iupper) must be the answer
00712             else if ( name2List[ iupper ] == name1List[ iup2 ] || name2List[ iupper ] == name2List[ iup2 ] )
00713                 abbrev = name1List[ iupper ];
00714     
00715             else { //doh!
00716                 kdWarning() << "F: " << i18n("No constellation found for point: (%1, %2)").arg(ra()->toHMSString()).arg(dec()->toDMSString()) << endl;
00717                 return i18n("Unknown");
00718             }
00719         } else { //pdc > 0.0, so search down
00720             int ilow2(-1);
00721             double dlow2(-90.);
00722             for ( uint i=0; i < p1List.count(); ++i ) {
00723                 if ( i != ilower ) {
00724                     SkyPoint *p1 = p1List.at(i);
00725                     SkyPoint *p2 = p2List.at(i);
00726                     
00727                     //Find Dec value along segment at RA of p:
00728                     double f = ( pra - p1->ra()->Degrees() ) / ( p2->ra()->Degrees() - p1->ra()->Degrees()); //fractional distance along segment
00729                     double segDec = f*p2->dec()->Degrees() + (1.0-f)*p1->dec()->Degrees();
00730                     if ( segDec > dlow2 && segDec < dlower ) { dlow2 = segDec; ilow2 = i; }
00731                 }
00732             }
00733     
00734             if ( ilow2 == -1 ) { //whoops, what happened?
00735                 kdWarning() << "G: " << i18n("No constellation found for point: (%1, %2)").arg(ra()->toHMSString()).arg(dec()->toDMSString()) << endl;
00736                 return i18n("Unknown");
00737             }
00738     
00739             //If name1(ilower) is the adjacent constellation, then name2(ilower) must be the answer
00740             if ( name1List[ ilower ] == name1List[ ilow2 ] || name1List[ ilower ] == name2List[ ilow2 ] )
00741                 abbrev = name2List[ ilower ];
00742     
00743             //If name2(ilower) is the adjacent constellation, then name1(ilower) must be the answer
00744             else if ( name2List[ ilower ] == name1List[ ilow2 ] || name2List[ ilower ] == name2List[ ilow2 ] )
00745                 abbrev = name1List[ ilower ];
00746     
00747             else { //doh!
00748                 kdWarning() << "H: " << i18n("No constellation found for point: (%1, %2)").arg(ra()->toHMSString()).arg(dec()->toDMSString()) << endl;
00749                 return i18n("Unknown");
00750             }
00751         }
00752     }
00753 
00754     //Normal case: one of the pair of names (name1/name2) should be shared between 
00755     //the two bracketing segments
00756     else if ( name1List[ iupper ] == name1List[ ilower ] || name1List[ iupper ] == name2List[ ilower ] ) 
00757         abbrev = name1List[ iupper ];
00758 
00759     else if ( name2List[ iupper ] == name1List[ ilower ] || name2List[ iupper ] == name2List[ ilower ] ) 
00760         abbrev = name2List[ iupper ];
00761 
00762     //If we reach here, then neither name1 nor name2 were shared between the bracketing segments!
00763     else {
00764         kdWarning() << "I: " << i18n("No constellation found for point: (%1, %2)").arg(ra()->toHMSString()).arg(dec()->toDMSString()) << endl;
00765         return i18n("Unknown");
00766     }
00767 
00768     //Finally, match the abbreviated name to the full constellation name, and return that name
00769     for ( SkyObject *o = cnameList.first(); o; o = cnameList.next() ) {
00770         if ( abbrev.lower() == o->name2().lower() ) {
00771             QString r = i18n( "Constellation name (optional)", o->name().local8Bit().data() );
00772             r = r.left(1) + r.mid(1).lower(); //lowercase letters (except first letter)
00773             int i = r.find(" ");
00774             i++;
00775             if ( i>0 ) r = r.left(i) + r.mid(i,1).upper() + r.mid(i+1); //capitalize 2nd word
00776             return r;
00777         }
00778     }
00779 
00780     return i18n("Unknown");
00781 }
00782 
00783 double SkyPoint::vRSun(long double jd0) {
00784 
00785     dms asun,dsun;
00786     double ca, sa, cd, sd, vsun;
00787     double cosRA, sinRA, cosDec, sinDec;
00788     
00789     /* Sun apex (where the sun goes) coordinates */
00790     
00791     asun.setD(270.9592);    // Right ascention: 18h 3m 50.2s [J2000]
00792     dsun.setD(30.00467);    // Declination: 30^o 0' 16.8'' [J2000]
00793     vsun=20.;       // [km/s]
00794     
00795     asun.SinCos(sa,ca);
00796     dsun.SinCos(sd,cd);
00797     
00798     /* We need an auxiliary SkyPoint since we need the 
00799     * source referred to the J2000 equinox and we do not want to ovewrite
00800     * the current values
00801     */
00802     
00803     SkyPoint aux;
00804     aux.set(RA0,Dec0);
00805     
00806     aux.precessFromAnyEpoch(jd0, J2000);
00807             
00808     aux.ra()->SinCos( sinRA, cosRA );
00809     aux.dec()->SinCos( sinDec, cosDec );
00810         
00811     /* Computation is done performing the scalar product of a unitary vector 
00812     in the direction of the source with the vector velocity of Sun, both being in the
00813     LSR reference system:
00814     Vlsr    = Vhel + Vsun.u_radial => 
00815     Vlsr    = Vhel + vsun(cos D cos A,cos D sen A,sen D).(cos d cos a,cos d sen a,sen d)
00816     Vhel    = Vlsr - Vsun.u_radial
00817     */
00818 
00819     return vsun *(cd*cosDec*(cosRA*ca + sa*sinRA) + sd*sinDec);
00820 
00821 }
00822 
00823 double SkyPoint::vHeliocentric(double vlsr, long double jd0) {
00824 
00825     return vlsr - vRSun(jd0);
00826 }
00827 
00828 double SkyPoint::vHelioToVlsr(double vhelio, long double jd0) {
00829 
00830     return vhelio + vRSun(jd0);
00831 }
00832 
00833 double SkyPoint::vREarth(long double jd0)
00834 {
00835   
00836     double sinRA, sinDec, cosRA, cosDec, vREarth;
00837 
00838     /* u_radial = unitary vector in the direction of the source
00839         Vlsr    = Vhel + Vsun.u_radial
00840             = Vgeo + VEarth.u_radial + Vsun.u_radial  => 
00841             
00842         Vgeo    = (Vlsr -Vsun.u_radial) - VEarth.u_radial
00843             =  Vhel - VEarth.u_radial
00844             =  Vhel - (vx, vy, vz).(cos d cos a,cos d sen a,sen d)
00845     */
00846     
00847     /* We need an auxiliary SkyPoint since we need the 
00848     * source referred to the J2000 equinox and we do not want to ovewrite
00849     * the current values
00850     */
00851     
00852     SkyPoint aux;
00853     aux.set(RA0,Dec0);
00854     
00855     aux.precessFromAnyEpoch(jd0, J2000);
00856             
00857     aux.ra()->SinCos( sinRA, cosRA );
00858     aux.dec()->SinCos( sinDec, cosDec );
00859 
00860     /* vEarth is referred to the J2000 equinox, hence we need that
00861     the source coordinates are also in the same reference system.
00862     */
00863     
00864     KSNumbers *num = new KSNumbers(jd0);
00865     
00866     vREarth = num->vEarth(0) * cosDec * cosRA + 
00867         num->vEarth(1) * cosDec * sinRA +
00868         num->vEarth(2) * sinDec;
00869         
00870     return vREarth;
00871 }
00872 
00873 
00874 double SkyPoint::vGeocentric(double vhelio, long double jd0)
00875 {
00876     return vhelio - vREarth(jd0);
00877 }
00878 
00879 double SkyPoint::vGeoToVHelio(double vgeo, long double jd0)
00880 {
00881     return vgeo + vREarth(jd0);
00882 }
00883 
00884 double SkyPoint::vRSite(double vsite[3])
00885 {
00886   
00887     double sinRA, sinDec, cosRA, cosDec, vREarth;
00888 
00889     RA.SinCos( sinRA, cosRA );
00890     Dec.SinCos( sinDec, cosDec );
00891 
00892     return vsite[0]*cosDec*cosRA + vsite[1]*cosDec*sinRA + vsite[2]*sinDec;
00893 }
00894 
00895 double SkyPoint::vTopoToVGeo(double vtopo, double vsite[3])
00896 {
00897     return vtopo + vRSite(vsite); 
00898 }
00899 
00900 double SkyPoint::vTopocentric(double vgeo, double vsite[3])
00901 {
00902     return vgeo - vRSite(vsite); 
00903 }

kstars

Skip menu "kstars"
  • Main Page
  • Modules
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • keduca
  • kstars
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal