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

kstars

skyobject.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           skyobject.cpp  -  K Desktop Planetarium
00003                              -------------------
00004     begin                : Sun Feb 11 2001
00005     copyright            : (C) 2001 by Jason Harris
00006     email                : jharris@30doradus.org
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include <iostream>
00019 
00020 #include <kglobal.h>
00021 #include <kstandarddirs.h>
00022 #include <qpoint.h>
00023 #include <qregexp.h>
00024 #include <qfile.h>
00025 #include <qtextstream.h>
00026 
00027 #include "skyobject.h"
00028 #include "starobject.h" //needed in saveUserLog()
00029 #include "ksnumbers.h"
00030 #include "dms.h"
00031 #include "geolocation.h"
00032 #include "kstarsdatetime.h"
00033 
00034 QString SkyObject::emptyString = QString("");
00035 QString SkyObject::unnamedString = QString(i18n("unnamed"));
00036 QString SkyObject::unnamedObjectString = QString(i18n("unnamed object"));
00037 QString SkyObject::starString = QString("star");
00038 
00039 SkyObject::SkyObject( SkyObject &o ) : SkyPoint( o ) {
00040     setType( o.type() );
00041     Magnitude = o.mag();
00042     setName(o.name());
00043     setName2(o.name2());
00044     setLongName(o.longname());
00045     ImageList = o.ImageList;
00046     ImageTitle = o.ImageTitle;
00047     InfoList = o.InfoList;
00048     InfoTitle = o.InfoTitle;
00049 }
00050 
00051 SkyObject::SkyObject( int t, dms r, dms d, float m,
00052                         QString n, QString n2, QString lname ) : SkyPoint( r, d) {
00053     setType( t );
00054     Magnitude = m;
00055     Name = 0;
00056     setName(n);
00057     Name2 = 0;
00058     setName2(n2);
00059     LongName = 0;
00060     setLongName(lname);
00061 }
00062 
00063 SkyObject::SkyObject( int t, double r, double d, float m,
00064                         QString n, QString n2, QString lname ) : SkyPoint( r, d) {
00065     setType( t );
00066     Magnitude = m;
00067     Name = 0;
00068     setName(n);
00069     Name2 = 0;
00070     setName2(n2);
00071     LongName = 0;
00072     setLongName(lname);
00073 }
00074 
00075 SkyObject::~SkyObject() {
00076     delete Name;
00077     delete Name2;
00078     delete LongName;
00079 }
00080 
00081 void SkyObject::setLongName( const QString &longname ) {
00082     delete LongName;
00083     if ( longname.isEmpty() ) {
00084         if ( hasName() )
00085             LongName = new QString(translatedName());
00086         else if ( hasName2() )
00087             LongName = new QString(*Name2);
00088         else
00089             LongName = 0;
00090     } else {
00091         LongName = new QString(longname);
00092     }
00093 }
00094 
00095 QTime SkyObject::riseSetTime( const KStarsDateTime &dt, const GeoLocation *geo, bool rst ) {
00096     //this object does not rise or set; return an invalid time
00097     if ( checkCircumpolar(geo->lat()) )
00098         return QTime( 25, 0, 0 );
00099 
00100     //First of all, if the object is below the horizon at date/time dt, adjust the time 
00101     //to bring it above the horizon
00102     KStarsDateTime dt2 = dt;
00103     SkyPoint p = recomputeCoords( dt, geo );
00104     p.EquatorialToHorizontal( &(geo->GSTtoLST( dt.gst() )), geo->lat() );
00105     if ( p.alt()->Degrees() < 0.0 ) {
00106         if ( p.az()->Degrees() < 180.0 ) { //object has not risen yet
00107             dt2 = dt.addSecs( 12.*3600. );
00108         } else { //object has already set
00109             dt2 = dt.addSecs( -12.*3600. );
00110         }
00111     }
00112     
00113     return geo->UTtoLT( KStarsDateTime( dt2.date(), riseSetTimeUT( dt2, geo, rst ) ) ).time();
00114 }
00115 
00116 QTime SkyObject::riseSetTimeUT( const KStarsDateTime &dt, const GeoLocation *geo, bool riseT ) {
00117     // First trial to calculate UT
00118     QTime UT = auxRiseSetTimeUT( dt, geo, ra(), dec(), riseT );
00119     
00120     // We iterate once more using the calculated UT to compute again
00121     // the ra and dec for that time and hence the rise/set time.
00122     // Also, adjust the date by +/- 1 day, if necessary
00123     KStarsDateTime dt0 = dt;
00124     dt0.setTime( UT );
00125     if ( riseT && dt0 > dt ) {
00126         dt0 = dt0.addDays( -1 );
00127     } else if ( ! riseT && dt0 < dt ) {
00128         dt0 = dt0.addDays( 1 );
00129     }
00130     
00131     SkyPoint sp = recomputeCoords( dt0, geo );
00132     UT = auxRiseSetTimeUT( dt0, geo, sp.ra(), sp.dec(), riseT );
00133 
00134     // We iterate a second time (For the Moon the second iteration changes
00135     // aprox. 1.5 arcmin the coordinates).
00136     dt0.setTime( UT );
00137     sp = recomputeCoords( dt0, geo );
00138     UT = auxRiseSetTimeUT( dt0, geo, sp.ra(), sp.dec(), riseT );
00139     return UT;
00140 }
00141 
00142 dms SkyObject::riseSetTimeLST( const KStarsDateTime &dt, const GeoLocation *geo, bool riseT ) {
00143     KStarsDateTime rst( dt.date(), riseSetTimeUT( dt, geo, riseT) );
00144     return geo->GSTtoLST( rst.gst() );
00145 }
00146 
00147 QTime SkyObject::auxRiseSetTimeUT( const KStarsDateTime &dt, const GeoLocation *geo,
00148             const dms *righta, const dms *decl, bool riseT) {
00149     dms LST = auxRiseSetTimeLST( geo->lat(), righta, decl, riseT );
00150     return dt.GSTtoUT( geo->LSTtoGST( LST ) );
00151 }
00152 
00153 dms SkyObject::auxRiseSetTimeLST( const dms *gLat, const dms *righta, const dms *decl, bool riseT ) {
00154     dms h0 = elevationCorrection();
00155     double H = approxHourAngle ( &h0, gLat, decl );
00156     dms LST;
00157 
00158     if ( riseT )
00159         LST.setH( 24.0 + righta->Hours() - H/15.0 );
00160     else
00161         LST.setH( righta->Hours() + H/15.0 );
00162 
00163     return LST.reduce();
00164 }
00165 
00166 
00167 dms SkyObject::riseSetTimeAz( const KStarsDateTime &dt, const GeoLocation *geo, bool riseT ) {
00168     dms Azimuth;
00169     double AltRad, AzRad;
00170     double sindec, cosdec, sinlat, coslat, sinHA, cosHA;
00171     double sinAlt, cosAlt;
00172 
00173     QTime UT = riseSetTimeUT( dt, geo, riseT );
00174     KStarsDateTime dt0 = dt;
00175     dt0.setTime( UT );
00176     SkyPoint sp = recomputeCoords( dt0, geo );
00177     const dms *ram = sp.ra0();
00178     const dms *decm = sp.dec0();
00179 
00180     dms LST = auxRiseSetTimeLST( geo->lat(), ram, decm, riseT );
00181     dms HourAngle = dms( LST.Degrees() - ram->Degrees() );
00182 
00183     geo->lat()->SinCos( sinlat, coslat );
00184     dec()->SinCos( sindec, cosdec );
00185     HourAngle.SinCos( sinHA, cosHA );
00186 
00187     sinAlt = sindec*sinlat + cosdec*coslat*cosHA;
00188     AltRad = asin( sinAlt );
00189     cosAlt = cos( AltRad );
00190 
00191     AzRad = acos( ( sindec - sinlat*sinAlt )/( coslat*cosAlt ) );
00192     if ( sinHA > 0.0 ) AzRad = 2.0*dms::PI - AzRad; // resolve acos() ambiguity
00193     Azimuth.setRadians( AzRad );
00194 
00195     return Azimuth;
00196 }
00197 
00198 QTime SkyObject::transitTimeUT( const KStarsDateTime &dt, const GeoLocation *geo ) {
00199     dms LST = geo->GSTtoLST( dt.gst() );
00200 
00201     //dSec is the number of seconds until the object transits.
00202     dms HourAngle = dms( LST.Degrees() - ra()->Degrees() );
00203     int dSec = int( -3600.*HourAngle.Hours() );
00204 
00205     //dt0 is the first guess at the transit time.
00206     KStarsDateTime dt0 = dt.addSecs( dSec );
00207 
00208     //recompute object's position at UT0 and then find
00209     //transit time of this refined position
00210     SkyPoint sp = recomputeCoords( dt0, geo );
00211     const dms *ram = sp.ra0();
00212 
00213     HourAngle = dms ( LST.Degrees() - ram->Degrees() );
00214     dSec = int( -3600.*HourAngle.Hours() );
00215 
00216     return dt.addSecs( dSec ).time();
00217 }
00218 
00219 QTime SkyObject::transitTime( const KStarsDateTime &dt, const GeoLocation *geo ) {
00220     return geo->UTtoLT( KStarsDateTime( dt.date(), transitTimeUT( dt, geo ) ) ).time();
00221 }
00222 
00223 dms SkyObject::transitAltitude( const KStarsDateTime &dt, const GeoLocation *geo ) {
00224     KStarsDateTime dt0 = dt;
00225     QTime UT = transitTimeUT( dt, geo );
00226     dt0.setTime( UT );
00227     SkyPoint sp = recomputeCoords( dt0, geo );
00228     const dms *decm = sp.dec0();
00229 
00230     dms delta;
00231     delta.setRadians( asin ( sin (geo->lat()->radians()) *
00232                 sin ( decm->radians() ) +
00233                 cos (geo->lat()->radians()) *
00234                 cos (decm->radians() ) ) );
00235 
00236     return delta;
00237 }
00238 
00239 double SkyObject::approxHourAngle( const dms *h0, const dms *gLat, const dms *dec ) {
00240 
00241     double sh0 = sin ( h0->radians() );
00242     double r = (sh0 - sin( gLat->radians() ) * sin(dec->radians() ))
00243          / (cos( gLat->radians() ) * cos( dec->radians() ) );
00244 
00245     double H = acos( r )/dms::DegToRad;
00246 
00247     return H;
00248 }
00249 
00250 dms SkyObject::elevationCorrection(void) {
00251 
00252     /* The atmospheric refraction at the horizon shifts altitude by 
00253      * - 34 arcmin = 0.5667 degrees. This value changes if the observer
00254      * is above the horizon, or if the weather conditions change much.
00255      *
00256      * For the sun we have to add half the angular sie of the body, since
00257      * the sunset is the time the upper limb of the sun disappears below
00258      * the horizon, and dawn, when the upper part of the limb appears 
00259      * over the horizon. The angular size of the sun = angular size of the
00260      * moon = 31' 59''. 
00261      *
00262      * So for the sun the correction is = -34 - 16 = 50 arcmin = -0.8333
00263      *
00264      * This same correction should be applied to the moon however parallax
00265      * is important here. Meeus states that the correction should be 
00266      * 0.7275 P - 34 arcmin, where P is the moon's horizontal parallax. 
00267      * He proposes a mean value of 0.125 degrees if no great accuracy 
00268      * is needed.
00269      */
00270 
00271     if ( name() == "Sun" || name() == "Moon" )
00272         return dms(-0.8333);
00273 //  else if ( name() == "Moon" )
00274 //      return dms(0.125);       
00275     else                             // All sources point-like.
00276         return dms(-0.5667);
00277 }
00278 
00279 SkyPoint SkyObject::recomputeCoords( const KStarsDateTime &dt, const GeoLocation *geo ) {
00280     //store current position
00281     SkyPoint original( ra(), dec() );
00282 
00283     // compute coords for new time jd
00284     KSNumbers num( dt.djd() );
00285     if ( isSolarSystem() && geo ) {
00286         dms LST = geo->GSTtoLST( dt.gst() );
00287         updateCoords( &num, true, geo->lat(), &LST );
00288     } else {
00289         updateCoords( &num );
00290     }
00291 
00292     //the coordinates for the date dt:
00293     SkyPoint sp = SkyPoint( ra(), dec() );
00294 
00295     // restore original coords
00296     setRA( original.ra()->Hours() );
00297     setDec( original.dec()->Degrees() );
00298 
00299     return sp;
00300 }
00301 
00302 bool SkyObject::checkCircumpolar( const dms *gLat ) {
00303     double r = -1.0 * tan( gLat->radians() ) * tan( dec()->radians() );
00304     if ( r < -1.0 || r > 1.0 )
00305         return true;
00306     else
00307         return false;
00308 }
00309 
00310 QString SkyObject::typeName( void ) const {
00311     if ( Type==0 ) return i18n( "Star" );
00312     else if ( Type==1 ) return i18n( "Catalog Star" );
00313     else if ( Type==2 ) return i18n( "Planet" );
00314     else if ( Type==3 ) return i18n( "Open Cluster" );
00315     else if ( Type==4 ) return i18n( "Globular Cluster" );
00316     else if ( Type==5 ) return i18n( "Gaseous Nebula" );
00317     else if ( Type==6 ) return i18n( "Planetary Nebula" );
00318     else if ( Type==7 ) return i18n( "Supernova Remnant" );
00319     else if ( Type==8 ) return i18n( "Galaxy" );
00320     else if ( Type==9 ) return i18n( "Comet" );
00321     else if ( Type==10 ) return i18n( "Asteroid" );
00322     else return i18n( "Unknown Type" );
00323 }
00324 void SkyObject::setName( const QString &name ) {
00325 //  if (name == "star" ) kdDebug() << "name == star" << endl;
00326     delete Name;
00327     if (!name.isEmpty())
00328         Name = new QString(name);
00329     else
00330         { Name = 0; /*kdDebug() << "name saved" << endl;*/ }
00331 }
00332 
00333 void SkyObject::setName2( const QString &name2 ) {
00334     delete Name2;
00335     if (!name2.isEmpty())
00336         Name2 = new QString(name2);
00337     else
00338         { Name2 = 0; /*kdDebug() << "name2 saved" << endl;*/ }
00339 }
00340 
00341 QString SkyObject::messageFromTitle( const QString &imageTitle ) {
00342     QString message = imageTitle;
00343 
00344     //HST Image
00345     if ( imageTitle == i18n( "Show HST Image" ) || imageTitle.contains("HST") ) {
00346         message = i18n( "%1: Hubble Space Telescope, operated by STScI for NASA [public domain]" ).arg( longname() );  
00347 
00348     //Spitzer Image
00349     } else if ( imageTitle.contains( i18n( "Show Spitzer Image" ) ) ) {
00350         message = i18n( "%1: Spitzer Space Telescope, courtesy NASA/JPL-Caltech [public domain]" ).arg( longname() );  
00351 
00352     //SEDS Image
00353     } else if ( imageTitle == i18n( "Show SEDS Image" ) ) {
00354         message = i18n( "%1: SEDS, http://www.seds.org [free for non-commercial use]" ).arg( longname() );
00355 
00356     //Kitt Peak AOP Image
00357     } else if ( imageTitle == i18n( "Show KPNO AOP Image" ) ) {
00358         message = i18n( "%1: Advanced Observing Program at Kitt Peak National Observatory [free for non-commercial use; no physical reproductions]" ).arg( longname() );
00359 
00360     //NOAO Image
00361     } else if ( imageTitle.contains( i18n( "Show NOAO Image" ) ) ) {
00362         message = i18n( "%1: National Optical Astronomy Observatories and AURA [free for non-commercial use]" ).arg( longname() );
00363 
00364     //VLT Image
00365     } else if ( imageTitle.contains( "VLT" ) ) {
00366         message = i18n( "%1: Very Large Telescope, operated by the European Southern Observatory [free for non-commercial use; no reproductions]" ).arg( longname() );
00367 
00368     //All others
00369     } else if ( imageTitle.startsWith( i18n( "Show" ) ) ) {
00370         message = imageTitle.mid( imageTitle.find( " " ) + 1 ); //eat first word, "Show"
00371         message = longname() + ": " + message;
00372     }
00373     
00374     return message;
00375 }
00376 
00377 //New saveUserLog, moved from DetailDialog.  
00378 //Should create a special UserLog widget that encapsulates the "default"
00379 //message in the widget when no log exists (much like we do with dmsBox now)
00380 void SkyObject::saveUserLog( const QString &newLog ) {
00381     QFile file;
00382     QString logs; //existing logs
00383     
00384     //Do nothing if new log is the "default" message
00385     //(keep going if new log is empty; we'll want to delete its current entry)
00386     if ( newLog == (i18n("Record here observation logs and/or data on %1.").arg(name())) || newLog.isEmpty() )
00387         return;
00388 
00389     // header label
00390     QString KSLabel ="[KSLABEL:" + name() + "]";
00391     //However, we can't accept a star name if it has a greek letter in it:
00392     if ( type() == STAR ) {
00393         StarObject *star = (StarObject*)this;
00394         if ( name() == star->gname() ) 
00395             KSLabel = "[KSLABEL:" + star->gname( false ) + "]"; //"false": spell out greek letter
00396     }
00397     
00398     file.setName( locateLocal( "appdata", "userlog.dat" ) ); //determine filename in local user KDE directory tree.
00399     if ( file.open( IO_ReadOnly)) {
00400         QTextStream instream(&file);
00401         // read all data into memory
00402         logs = instream.read();
00403         file.close();
00404     }
00405     
00406     //Remove old log entry from the logs text
00407     if ( ! userLog.isEmpty() ) {
00408         int startIndex, endIndex;
00409         QString sub;
00410     
00411         startIndex = logs.find(KSLabel);
00412         sub = logs.mid (startIndex);
00413         endIndex = sub.find("[KSLogEnd]");
00414     
00415         logs.remove(startIndex, endIndex + 11);
00416     }
00417     
00418     //append the new log entry to the end of the logs text,
00419     //but only if the log is not empty
00420     if ( ! newLog.stripWhiteSpace().isEmpty() )
00421         logs.append( KSLabel + "\n" + newLog + "\n[KSLogEnd]\n" );
00422     
00423     //Open file for writing
00424     //FIXME: change error message to "cannot write to user log file"
00425     if ( !file.open( IO_WriteOnly ) ) {
00426         kdDebug() << i18n( "user log file could not be opened." ) << endl;
00427         return;
00428     }
00429     
00430     //Write new logs text
00431     QTextStream outstream(&file);
00432     outstream << logs;
00433     
00434     //Set the log text in the object itself.
00435     userLog = newLog;
00436     
00437     file.close();
00438 }

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