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

kstars

altvstime.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           altvstime.cpp  -  description
00003                              -------------------
00004     begin                : wed nov 17 08:05:11 CET 2002
00005     copyright            : (C) 2002-2003 by Pablo de Vicente
00006     email                : vicente@oan.es
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 "altvstime.h"
00019 
00020 #include <QVBoxLayout>
00021 #include <QPainter>
00022 #include <QMouseEvent>
00023 #include <QPixmap>
00024 #include <QFrame>
00025 #include <QPaintEvent>
00026 #include <QPointF>
00027 
00028 #include <klocale.h>
00029 #include <klineedit.h>
00030 #include <kpushbutton.h>
00031 #include <kdialog.h>
00032 #include <kplotobject.h>
00033 #include <kplotaxis.h>
00034 #include <kplotwidget.h>
00035 
00036 #include "ui_altvstime.h"
00037 #include "dms.h"
00038 #include "kstars.h"
00039 #include "kstarsdata.h"
00040 #include "skypoint.h"
00041 #include "skyobject.h"
00042 #include "ksnumbers.h"
00043 #include "simclock.h"
00044 #include "finddialog.h"
00045 #include "locationdialog.h"
00046 #include "widgets/dmsbox.h"
00047 #include "avtplotwidget.h"
00048 
00049 #include "kstarsdatetime.h"
00050 
00051 AltVsTimeUI::AltVsTimeUI( QWidget *p ) : QFrame( p ) {
00052     setupUi( this );
00053 }
00054 
00055 AltVsTime::AltVsTime( QWidget* parent)  :
00056         KDialog( parent )
00057 {
00058     ks = (KStars*) parent;
00059 
00060     QFrame *page = new QFrame( this );
00061     setMainWidget(page);
00062     setCaption( i18n( "Altitude vs. Time" ) );
00063     setButtons( KDialog::Close );
00064     setModal( false );
00065 
00066     topLayout = new QVBoxLayout( page );
00067     topLayout->setMargin( 0 );
00068     topLayout->setSpacing( spacingHint() );
00069 
00070     avtUI = new AltVsTimeUI( page );
00071 
00072     avtUI->View->setLimits( -12.0, 12.0, -90.0, 90.0 );
00073     avtUI->View->setShowGrid( false );
00074     avtUI->View->axis(KPlotWidget::BottomAxis)->setTickLabelFormat( 't' );
00075     avtUI->View->axis(KPlotWidget::BottomAxis)->setLabel( i18n( "Local Time" ) );
00076     avtUI->View->axis(KPlotWidget::TopAxis)->setTickLabelFormat( 't' );
00077     avtUI->View->axis(KPlotWidget::TopAxis)->setTickLabelsShown( true );
00078     avtUI->View->axis(KPlotWidget::TopAxis)->setLabel( i18n( "Local Sidereal Time" ) );
00079     avtUI->View->axis(KPlotWidget::LeftAxis)->setLabel( i18nc( "the angle of an object above (or below) the horizon", "Altitude" ) );
00080 
00081     avtUI->raBox->setDegType( false );
00082     avtUI->decBox->setDegType( true );
00083 
00084     //FIXME:
00085     //Doesn't make sense to manually adjust long/lat unless we can modify TZ also
00086     avtUI->longBox->setReadOnly( true );
00087     avtUI->latBox->setReadOnly( true );
00088 
00089     topLayout->addWidget( avtUI );
00090 
00091     geo = ks->geo();
00092 
00093     DayOffset = 0;
00094     showCurrentDate();
00095     if ( getDate().time().hour() > 12 ) DayOffset = 1;
00096 
00097     avtUI->longBox->show( geo->lng() );
00098     avtUI->latBox->show( geo->lat() );
00099 
00100     computeSunRiseSetTimes();
00101 
00102     setLSTLimits();
00103 
00104     connect( avtUI->browseButton, SIGNAL( clicked() ), this, SLOT( slotBrowseObject() ) );
00105     connect( avtUI->cityButton,   SIGNAL( clicked() ), this, SLOT( slotChooseCity() ) );
00106     connect( avtUI->updateButton, SIGNAL( clicked() ), this, SLOT( slotUpdateDateLoc() ) );
00107     connect( avtUI->clearButton, SIGNAL( clicked() ), this, SLOT( slotClear() ) );
00108     connect( avtUI->addButton,   SIGNAL( clicked() ), this, SLOT( slotAddSource() ) );
00109     connect( avtUI->nameBox, SIGNAL( returnPressed() ), this, SLOT( slotAddSource() ) );
00110     connect( avtUI->raBox,   SIGNAL( returnPressed() ), this, SLOT( slotAddSource() ) );
00111     connect( avtUI->decBox,  SIGNAL( returnPressed() ), this, SLOT( slotAddSource() ) );
00112     connect( avtUI->clearFieldsButton, SIGNAL( clicked() ), this, SLOT( slotClearBoxes() ) );
00113     connect( avtUI->longBox, SIGNAL( returnPressed() ), this, SLOT( slotAdvanceFocus() ) );
00114     connect( avtUI->latBox,  SIGNAL( returnPressed() ), this, SLOT( slotAdvanceFocus() ) );
00115     connect( avtUI->PlotList, SIGNAL( currentRowChanged(int) ), this, SLOT( slotHighlight(int) ) );
00116 
00117     //the edit boxes should not pass on the return key!
00118     avtUI->nameBox->setTrapReturnKey( true );
00119     avtUI->raBox->setTrapReturnKey( true );
00120     avtUI->decBox->setTrapReturnKey( true );
00121 
00122     setMouseTracking( true );
00123 }
00124 
00125 AltVsTime::~AltVsTime()
00126 {
00127     //WARNING: need to delete deleteList items!
00128 }
00129 
00130 void AltVsTime::slotAddSource(void) {
00131     SkyObject *obj = ks->data()->objectNamed( avtUI->nameBox->text() );
00132 
00133     if ( obj ) {
00134         //An object with the current name exists.  If the object is not already
00135         //in the avt list, add it.
00136         bool found(false);
00137         foreach ( SkyObject *o, pList ) {
00138             if ( o->name() == obj->name() ) { found = true; break; }
00139         }
00140 
00141         if ( found )
00142             kDebug() << i18n("An object named %1 is already displayed; I will not duplicate it.", obj->name());
00143 
00144         else
00145             processObject( obj );
00146 
00147     } else {
00148         //Object with the current name doesn't exist.  It's possible that the
00149         //user is trying to add a custom object.  Assume this is the case if
00150         //the RA and Dec fields are filled in.
00151 
00152         if ( ! avtUI->nameBox->text().isEmpty() &&
00153                 ! avtUI->raBox->text().isEmpty() &&
00154                 ! avtUI->decBox->text().isEmpty() ) {
00155             bool ok( true );
00156             dms newRA( 0.0 ), newDec( 0.0 );
00157             newRA = avtUI->raBox->createDms( false, &ok );
00158             if ( ok ) newDec = avtUI->decBox->createDms( true, &ok );
00159             if ( !ok ) return;
00160 
00161             //If the epochName is blank (or any non-double), we assume J2000
00162             //Otherwise, precess to J2000.
00163             KStarsDateTime dt;
00164             dt.setFromEpoch( getEpoch( avtUI->epochName->text() ) );
00165             long double jd = dt.djd();
00166             if ( jd != J2000 ) {
00167                 SkyPoint ptest( newRA, newDec );
00168                 ptest.precessFromAnyEpoch( jd, J2000 );
00169                 newRA.setH( ptest.ra()->Hours() );
00170                 newDec.setD( ptest.dec()->Degrees() );
00171             }
00172 
00173             //make sure the coords do not already exist from another object
00174             bool found(false);
00175             foreach ( SkyObject *p, pList ) {
00176                 //within an arcsecond?
00177                 if ( fabs( newRA.Degrees() - p->ra()->Degrees() ) < 0.0003 && fabs( newDec.Degrees() - p->dec()->Degrees() ) < 0.0003 ) {
00178                     found = true;
00179                     break;
00180                 }
00181             }
00182             if ( found ) {
00183                 kDebug() << "This point is already displayed; I will not duplicate it.";
00184                 ok = false;
00185             }
00186 
00187             if ( ok ) {
00188                 SkyObject *obj = new SkyObject( 8, newRA, newDec, 1.0, avtUI->nameBox->text() );
00189                 deleteList.append( obj ); //this object will be deleted when window is destroyed
00190                 processObject( obj );
00191             }
00192         }
00193 
00194         //If the Ra and Dec boxes are filled, but the name field is empty,
00195         //move input focus to nameBox.  If either coordinate box is empty,
00196         //move focus there
00197         if ( avtUI->nameBox->text().isEmpty() )
00198             avtUI->nameBox->QWidget::setFocus();
00199         if ( avtUI->raBox->text().isEmpty() )
00200             avtUI->raBox->QWidget::setFocus();
00201         else if ( avtUI->decBox->text().isEmpty() )
00202             avtUI->decBox->QWidget::setFocus();
00203     }
00204 
00205     avtUI->View->update();
00206 }
00207 
00208 //Use find dialog to choose an object
00209 void AltVsTime::slotBrowseObject(void) {
00210     FindDialog fd(ks);
00211     if ( fd.exec() == QDialog::Accepted ) {
00212         SkyObject *o = fd.selectedObject();
00213         processObject( o );
00214     }
00215 
00216     avtUI->View->update();
00217 }
00218 
00219 void AltVsTime::processObject( SkyObject *o, bool forceAdd ) {
00220     if ( !o ) return;
00221 
00222     KSNumbers *num = new KSNumbers( getDate().djd() );
00223     KSNumbers *oldNum = 0;
00224 
00225     //If the object is in the solar system, recompute its position for the given epochLabel
00226     if ( o->isSolarSystem() ) {
00227         oldNum = new KSNumbers( ks->data()->ut().djd() );
00228         o->updateCoords( num, true, geo->lat(), ks->LST() );
00229     }
00230 
00231     //precess coords to target epoch
00232     o->updateCoords( num );
00233 
00234     //If this point is not in list already, add it to list
00235     bool found(false);
00236     foreach ( SkyObject *p, pList ) {
00237         if ( o->ra()->Degrees() == p->ra()->Degrees() && o->dec()->Degrees() == p->dec()->Degrees() ) {
00238             found = true;
00239             break;
00240         }
00241     }
00242     if ( found && !forceAdd ) kDebug() << "This point is already displayed; I will not duplicate it.";
00243     else {
00244         pList.append( o );
00245 
00246         //make sure existing curves are thin and red
00247         QList< KPlotObject* > objects = avtUI->View->plotObjects();
00248         for ( int i=0; i < objects.count(); ++i ) {
00249             KPlotObject *obj = objects.at( i );
00250             if ( obj->size() == 2 ) {
00251                 obj->setLinePen( QPen( Qt::red, 1 ) );
00252             }
00253         }
00254 
00255         //add new curve with width=2, and color=white
00256         KPlotObject *po = new KPlotObject( Qt::white, KPlotObject::Lines, 2.0 );
00257         for ( double h=-12.0; h<=12.0; h+=0.5 ) {
00258             po->addPoint( h, findAltitude( o, h ) );
00259         }
00260         avtUI->View->addPlotObject( po );
00261 
00262         avtUI->PlotList->addItem( o->translatedName() );
00263         avtUI->PlotList->setCurrentRow( avtUI->PlotList->count() - 1 );
00264         avtUI->raBox->showInHours(o->ra() );
00265         avtUI->decBox->showInDegrees(o->dec() );
00266         avtUI->nameBox->setText(o->translatedName() );
00267 
00268         //Set epochName to epoch shown in date tab
00269         avtUI->epochName->setText( QString().setNum( getDate().epoch() ) );
00270     }
00271     kDebug() << "Currently, there are " << avtUI->View->plotObjects().count() << " objects displayed.";
00272 
00273     //restore original position
00274     if ( o->isSolarSystem() ) {
00275         o->updateCoords( oldNum, true, ks->geo()->lat(), ks->LST() );
00276         delete oldNum;
00277     }
00278     o->EquatorialToHorizontal( ks->LST(), ks->geo()->lat() );
00279     delete num;
00280 }
00281 
00282 double AltVsTime::findAltitude( SkyPoint *p, double hour ) {
00283     hour += 24.0*(double)DayOffset;
00284 
00285     //getDate converts the user-entered local time to UT
00286     KStarsDateTime ut = getDate().addSecs( hour*3600.0 );
00287 
00288     dms LST = geo->GSTtoLST( ut.gst() );
00289     p->EquatorialToHorizontal( &LST, geo->lat() );
00290     return p->alt()->Degrees();
00291 }
00292 
00293 void AltVsTime::slotHighlight( int row ) {
00294     //highlight the curve of the selected object
00295     QList< KPlotObject* > objects = avtUI->View->plotObjects();
00296     for ( int i=0; i<objects.count(); ++i ) {
00297         KPlotObject *obj = objects.at( i );
00298 
00299         if ( i == row ) {
00300             obj->setLinePen( QPen( Qt::white, 2 ) );
00301         } else {
00302             obj->setLinePen( QPen( Qt::red, 1 ) );
00303         }
00304     }
00305 
00306     avtUI->View->update();
00307 
00308     for ( int i=0; i < pList.size(); ++i ) {
00309         if ( i == row ) {
00310             SkyObject *p = pList.at(i);
00311             avtUI->raBox->showInHours( p->ra() );
00312             avtUI->decBox->showInDegrees( p->dec() );
00313             avtUI->nameBox->setText( avtUI->PlotList->currentItem()->text() );
00314         }
00315     }
00316 }
00317 
00318 //move input focus to the next logical widget
00319 void AltVsTime::slotAdvanceFocus(void) {
00320     if ( sender()->objectName() == QString( "nameBox" ) ) avtUI->addButton->setFocus();
00321     if ( sender()->objectName() == QString( "raBox" ) ) avtUI->decBox->setFocus();
00322     if ( sender()->objectName() == QString( "decbox" ) ) avtUI->addButton->setFocus();
00323     if ( sender()->objectName() == QString( "longBox" ) ) avtUI->latBox->setFocus();
00324     if ( sender()->objectName() == QString( "latBox" ) ) avtUI->updateButton->setFocus();
00325 }
00326 
00327 void AltVsTime::slotClear(void) {
00328     if ( pList.count() ) pList.clear();
00329     //Need to delete the pointers in deleteList
00330     while ( ! deleteList.isEmpty() )
00331         delete deleteList.takeFirst();
00332     avtUI->PlotList->clear();
00333     avtUI->nameBox->clear();
00334     avtUI->raBox->clear();
00335     avtUI->decBox->clear();
00336     avtUI->epochName->clear();
00337     avtUI->View->removeAllPlotObjects();
00338     avtUI->View->update();
00339 }
00340 
00341 void AltVsTime::slotClearBoxes(void) {
00342     avtUI->nameBox->clear();
00343     avtUI->raBox->clear() ;
00344     avtUI->decBox->clear();
00345     avtUI->epochName->clear();
00346 }
00347 
00348 void AltVsTime::computeSunRiseSetTimes() {
00349     //Determine the time of sunset and sunrise for the desired date and location
00350     //expressed as doubles, the fraction of a full day.
00351     KStarsDateTime today = getDate();
00352 
00353     SkyObject *oSun = ks->data()->objectNamed( "Sun" );
00354     double sunRise = -1.0 * oSun->riseSetTime( today.djd() + 1.0, geo, true ).secsTo(QTime()) / 86400.0;
00355     double sunSet = -1.0 * oSun->riseSetTime( today.djd(), geo, false ).secsTo(QTime()) / 86400.0;
00356 
00357     //check to see if Sun is circumpolar
00358     //requires temporary repositioning of Sun to target date
00359     KSNumbers *num = new KSNumbers( today.djd() );
00360     KSNumbers *oldNum = new KSNumbers( ks->data()->ut().djd() );
00361     dms LST = geo->GSTtoLST( getDate().gst() );
00362     oSun->updateCoords( num, true, geo->lat(), &LST );
00363     if ( oSun->checkCircumpolar( geo->lat() ) ) {
00364         if ( oSun->alt()->Degrees() > 0.0 ) {
00365             //Circumpolar, signal it this way:
00366             sunRise = 0.0;
00367             sunSet = 1.0;
00368         } else {
00369             //never rises, signal it this way:
00370             sunRise = 0.0;
00371             sunSet = -1.0;
00372         }
00373     }
00374 
00375     //Notify the View about new sun rise/set times:
00376     avtUI->View->setSunRiseSetTimes( sunRise, sunSet );
00377 
00378     //Restore Sun coordinates:
00379     oSun->updateCoords( oldNum, true, ks->geo()->lat(), ks->LST() );
00380     oSun->EquatorialToHorizontal( ks->LST(), ks->geo()->lat() );
00381 
00382     delete num;
00383     delete oldNum;
00384 }
00385 
00386 void AltVsTime::slotUpdateDateLoc(void) {
00387     KStarsDateTime today = getDate();
00388     KSNumbers *num = new KSNumbers( today.djd() );
00389     KSNumbers *oldNum = 0;
00390     dms LST = geo->GSTtoLST( today.gst() );
00391 
00392     //First determine time of sunset and sunrise
00393     computeSunRiseSetTimes();
00394 
00395     for ( int i = 0; i < avtUI->PlotList->count(); ++i ) {
00396         QString oName = avtUI->PlotList->item( i )->text().toLower();
00397 
00398         SkyObject *o = ks->data()->objectNamed( oName );
00399         if ( o ) {
00400             //If the object is in the solar system, recompute its position for the given date
00401             if ( o->isSolarSystem() ) {
00402                 oldNum = new KSNumbers( ks->data()->ut().djd() );
00403                 o->updateCoords( num, true, geo->lat(), &LST );
00404             }
00405 
00406             //precess coords to target epoch
00407             o->updateCoords( num );
00408 
00409             //update pList entry
00410             pList.replace( i, o );
00411 
00412             KPlotObject *po = new KPlotObject( Qt::white, KPlotObject::Lines, 1 );
00413             for ( double h=-12.0; h<=12.0; h+=0.5 ) {
00414                 po->addPoint( h, findAltitude( o, h ) );
00415             }
00416             avtUI->View->replacePlotObject( i, po );
00417 
00418             //restore original position
00419             if ( o->isSolarSystem() ) {
00420                 o->updateCoords( oldNum, true, ks->data()->geo()->lat(), ks->LST() );
00421                 delete oldNum;
00422                 oldNum = 0;
00423             }
00424             o->EquatorialToHorizontal( ks->LST(), ks->geo()->lat() );
00425         } else {  //assume unfound object is a custom object
00426             pList.at(i)->updateCoords( num ); //precess to desired epoch
00427 
00428             KPlotObject *po = new KPlotObject( Qt::white, KPlotObject::Lines, 1 );
00429             for ( double h=-12.0; h<=12.0; h+=0.5 ) {
00430                 po->addPoint( h, findAltitude( pList.at(i), h ) );
00431             }
00432             avtUI->View->replacePlotObject( i, po );
00433         }
00434     }
00435 
00436     if ( getDate().time().hour() > 12 ) DayOffset = 1;
00437     else DayOffset = 0;
00438 
00439     setLSTLimits();
00440     slotHighlight( avtUI->PlotList->currentRow() );
00441     avtUI->View->update();
00442 
00443     delete num;
00444 }
00445 
00446 void AltVsTime::slotChooseCity(void) {
00447     LocationDialog ld(ks);
00448     if ( ld.exec() == QDialog::Accepted ) {
00449         GeoLocation *newGeo = ld.selectedCity();
00450         if ( newGeo ) {
00451             geo = newGeo;
00452             avtUI->latBox->showInDegrees( geo->lat() );
00453             avtUI->longBox->showInDegrees( geo->lng() );
00454         }
00455     }
00456 }
00457 
00458 int AltVsTime::currentPlotListItem() const {
00459     return avtUI->PlotList->currentRow();
00460 }
00461 
00462 void AltVsTime::setLSTLimits(void) {
00463     //UT at noon on target date
00464     KStarsDateTime ut = getDate().addSecs( ((double)DayOffset + 0.5)*86400. );
00465 
00466     dms lst = geo->GSTtoLST( ut.gst() );
00467     double h1 = lst.Hours();
00468     if ( h1 > 12.0 ) h1 -= 24.0;
00469     double h2 = h1 + 24.0;
00470     avtUI->View->setSecondaryLimits( h1, h2, -90.0, 90.0 );
00471 }
00472 
00473 void AltVsTime::showCurrentDate (void)
00474 {
00475     KStarsDateTime dt = KStarsDateTime::currentDateTime();
00476     if ( dt.time() > QTime( 12, 0, 0 ) ) dt = dt.addDays( 1 );
00477     avtUI->DateWidget->setDate( dt.date() );
00478 }
00479 
00480 KStarsDateTime AltVsTime::getDate (void)
00481 {
00482     //convert midnight local time to UT:
00483     KStarsDateTime dt( avtUI->DateWidget->date(), QTime() );
00484     dt = geo->LTtoUT( dt );
00485     return dt;
00486 }
00487 
00488 double AltVsTime::getEpoch(const QString &eName)
00489 {
00490     //If Epoch field not a double, assume J2000
00491     bool ok(false);
00492     double epoch = eName.toDouble(&ok);
00493 
00494     if ( !ok ) {
00495         kDebug() << "Invalid Epoch.  Assuming 2000.0.";
00496         return 2000.0;
00497     }
00498 
00499     return epoch;
00500 }
00501 
00502 #include "altvstime.moc"

kstars

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

kdeedu

Skip menu "kdeedu"
  • kalzium
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  •   docs
  •   src
  • parley
  •   stepcore
Generated for kdeedu by doxygen 1.5.4
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