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

kstars

planetviewer.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           planetviewer.cpp  -  Display overhead view of the solar system
00003                              -------------------
00004     begin                : Sun May 25 2003
00005     copyright            : (C) 2003 by Jason Harris
00006     email                : jharris@30doradus.org
00007  ***************************************************************************/
00008 /***************************************************************************
00009  *                                                                         *
00010  *   This program is free software; you can redistribute it and/or modify  *
00011  *   it under the terms of the GNU General Public License as published by  *
00012  *   the Free Software Foundation; either version 2 of the License, or     *
00013  *   (at your option) any later version.                                   *
00014  *                                                                         *
00015  ***************************************************************************/
00016 
00017 #include <stdlib.h> //needed for abs() on some platforms
00018 
00019 #include <qfile.h>
00020 #include <qlayout.h>
00021 #include <kdebug.h>
00022 #include <klocale.h>
00023 #include <kglobal.h>
00024 #include <kiconloader.h>
00025 
00026 #include "planetviewer.h"
00027 #include "kstars.h"
00028 #include "kstarsdata.h"
00029 #include "ksutils.h"
00030 #include "ksnumbers.h"
00031 #include "ksplanetbase.h"
00032 #include "dms.h"
00033 #include "timestepbox.h"
00034 #include "libkdeedu/extdate/extdatetimeedit.h"
00035 
00036 #define AUMAX 48
00037 
00038 PlanetViewer::PlanetViewer(QWidget *parent, const char *name)
00039  : KDialogBase( KDialogBase::Plain, i18n("Solar System Viewer"), Close, Close, parent, name ), PCat( ((KStars*)parent)->data() ), scale(1.0), isClockRunning(false), tmr(this)
00040 {
00041     QFrame *page = plainPage();
00042     QVBoxLayout *vlay = new QVBoxLayout( page, 0, spacingHint() );
00043     pw = new PlanetViewerUI( page );
00044     pw->map->setLimits( -48.0, 48.0, -48.0, 48.0 );
00045     pw->map->setXAxisLabel( i18n( "axis label for x-coordinate of solar system viewer.  AU means astronomical unit.", "X-position (AU)" ) );
00046     pw->map->setYAxisLabel( i18n( "axis label for y-coordinate of solar system viewer.  AU means astronomical unit.", "Y-position (AU)" ) );
00047     
00048     pw->timeStep->setDaysOnly( true );
00049     pw->timeStep->tsbox()->setValue( 1 ); //start with 1-day timestep
00050 
00051     pw->RunButton->setPixmap( KGlobal::iconLoader()->loadIcon( "1rightarrow", KIcon::Toolbar ) );
00052     pw->dateBox->setDate( ((KStars*)parent)->data()->lt().date() );
00053     
00054     vlay->addWidget( pw );
00055     resize( 500, 500 );
00056     pw->map->QWidget::setFocus(); //give keyboard focus to the plot widget for key and mouse events
00057     
00058     pName[0] = "Mercury"; pColor[0] = "SlateBlue1";
00059     pName[1] = "Venus";   pColor[1] = "LightGreen";
00060     pName[2] = "Earth";   pColor[2] = "Blue";
00061     pName[3] = "Mars";    pColor[3] = "Red";
00062     pName[4] = "Jupiter"; pColor[4] = "Goldenrod";
00063     pName[5] = "Saturn";  pColor[5] = "LightYellow2";
00064     pName[6] = "Uranus";  pColor[6] = "LightSeaGreen";
00065     pName[7] = "Neptune"; pColor[7] = "SkyBlue";
00066     pName[8] = "Pluto";   pColor[8] = "gray";
00067 
00068     setCenterPlanet("");
00069     
00070     PCat.initialize();
00071     ut = ((KStars*)parent)->data()->ut();
00072     KSNumbers num( ut.djd() );
00073     PCat.findPosition( &num, 0, 0 ); //NULL args: don't need geocent. coords.
00074     
00075     for ( uint i=0; i<9; ++i ) 
00076         LastUpdate[i] = int( ut.date().jd() );
00077 
00078     //The planets' update intervals are 0.25% of one period:
00079     UpdateInterval[0] = 0;
00080     UpdateInterval[1] = 0;
00081     UpdateInterval[2] = 0;
00082     UpdateInterval[3] = 1;
00083     UpdateInterval[4] = 5;
00084     UpdateInterval[5] = 13;
00085     UpdateInterval[6] = 38;
00086     UpdateInterval[7] = 75;
00087     UpdateInterval[8] = 113;
00088 
00089     QTimer::singleShot( 0, this, SLOT( initPlotObjects() ) );
00090 
00091     connect( &tmr, SIGNAL( timeout() ), SLOT( tick() ) );
00092     connect( pw->timeStep, SIGNAL( scaleChanged(float) ), SLOT( setTimeScale(float) ) );
00093     connect( pw->RunButton, SIGNAL( clicked() ), SLOT( slotRunClock() ) );
00094     connect( pw->dateBox, SIGNAL( valueChanged( const ExtDate & ) ), SLOT( slotChangeDate( const ExtDate & ) ) );
00095     connect( pw->TodayButton, SIGNAL( clicked() ), SLOT( slotToday() ) );
00096 }
00097 
00098 PlanetViewer::~PlanetViewer()
00099 {
00100 }
00101 
00102 void PlanetViewer::tick() {
00103     //Update the time/date
00104     ut.setDJD( ut.djd() + scale*0.1 );
00105     pw->dateBox->setDate( ut.date() );
00106     
00107     updatePlanets();
00108 }
00109 
00110 void PlanetViewer::setTimeScale(float f) {
00111     scale = f/86400.; //convert seconds to days
00112 }
00113 
00114 void PlanetViewer::slotRunClock() {
00115     isClockRunning = !isClockRunning;
00116     
00117     if ( isClockRunning ) {
00118         pw->RunButton->setPixmap( KGlobal::iconLoader()->loadIcon( "player_pause", KIcon::Toolbar ) );
00119         tmr.start( 100 );
00120 //      pw->dateBox->setEnabled( false );
00121     } else {
00122         pw->RunButton->setPixmap( KGlobal::iconLoader()->loadIcon( "1rightarrow", KIcon::Toolbar ) );
00123         tmr.stop();
00124 //      pw->dateBox->setEnabled( true );
00125     }
00126 }
00127 
00128 void PlanetViewer::slotChangeDate( const ExtDate & ) {
00129     if ( pw->dateBox->date().isValid() ) {
00130         ut.setDate( pw->dateBox->date() ); 
00131         updatePlanets();
00132     }
00133 }
00134 
00135 void PlanetViewer::updatePlanets() {
00136     KSNumbers num( ut.djd() );
00137     bool changed(false);
00138     
00139     //Check each planet to see if it needs to be updated
00140     for ( unsigned int i=0; i<9; ++i ) {
00141         if ( abs( int(ut.date().jd()) - LastUpdate[i] ) > UpdateInterval[i] ) {
00142             KSPlanetBase *p = PCat.findByName( pName[i] );
00143             p->findPosition( &num );
00144             
00145             double s, c, s2, c2;
00146             p->helEcLong()->SinCos( s, c );
00147             p->helEcLat()->SinCos( s2, c2 );
00148             planet[i]->point(0)->setX( p->rsun()*c*c2 );
00149             planet[i]->point(0)->setY( p->rsun()*s*c2 );
00150             planetLabel[i]->point(0)->setX( p->rsun()*c*c2 );
00151             planetLabel[i]->point(0)->setY( p->rsun()*s*c2 );
00152             
00153             if ( centerPlanet() == pName[i] ) {
00154                 double xc = (pw->map->x2() + pw->map->x())*0.5;
00155                 double yc = (pw->map->y2() + pw->map->y())*0.5;
00156                 double dx = planet[i]->point(0)->x() - xc;
00157                 double dy = planet[i]->point(0)->y() - yc;
00158                 pw->map->setLimits( pw->map->x() + dx, pw->map->x2() + dx, 
00159                         pw->map->y() + dy, pw->map->y2() + dy );
00160             }
00161             
00162             LastUpdate[i] = int(ut.date().jd());
00163             changed = true;
00164         }
00165     }
00166     
00167     if ( changed ) pw->map->update();
00168 }
00169 
00170 void PlanetViewer::slotToday() {
00171     KStars *ks = (KStars*)parent();
00172     pw->dateBox->setDate( ks->data()->lt().date() );
00173 }
00174 
00175 void PlanetViewer::paintEvent( QPaintEvent* ) {
00176     pw->map->update();
00177 }
00178 
00179 void PlanetViewer::initPlotObjects() {
00180     // Planets
00181     ksun = new KPlotObject( "Sun", "yellow", KPlotObject::POINTS, 12, KPlotObject::CIRCLE );
00182     ksun->addPoint( new DPoint( 0.0, 0.0 ) );
00183     pw->map->addObject( ksun );
00184     
00185     //Read in the orbit curves
00186     KPlotObject *orbit[9];
00187     for ( unsigned int i=0; i<9; ++i ) {
00188         orbit[i] = new KPlotObject( "", "white", KPlotObject::CURVE, 1, KPlotObject::SOLID );
00189         
00190         QFile orbitFile;
00191         if ( KSUtils::openDataFile( orbitFile, pName[i].lower() + ".orbit" ) ) {
00192             QTextStream orbitStream( &orbitFile );
00193             double x, y, z;
00194             while ( !orbitStream.eof() ) {
00195                 orbitStream >> x >> y >> z;
00196                 orbit[i]->addPoint( new DPoint( x, y ) );
00197             }
00198         }
00199         
00200         pw->map->addObject( orbit[i] );
00201     }
00202     
00203     for ( unsigned int i=0; i<9; ++i ) {
00204         planet[i] = new KPlotObject( pName[i], pColor[i], KPlotObject::POINTS, 6, KPlotObject::CIRCLE );
00205         planetLabel[i] = new KPlotObject( i18n(pName[i].local8Bit()), pColor[i], KPlotObject::LABEL );
00206         
00207         double s, c;
00208         KSPlanetBase *p = PCat.findByName( pName[i] );
00209         p->helEcLong()->SinCos( s, c );
00210         
00211         planet[i]->addPoint( new DPoint( p->rsun()*c, p->rsun()*s ) );
00212         planetLabel[i]->addPoint( new DPoint( p->rsun()*c, p->rsun()*s ) );
00213         pw->map->addObject( planet[i] );
00214         pw->map->addObject( planetLabel[i] );
00215     }
00216     
00217     update();
00218 }
00219 
00220 void PlanetViewer::keyPressEvent( QKeyEvent *e ) {
00221     switch ( e->key() ) {
00222         case Key_Escape:
00223             close();
00224             break;
00225         default:
00226             e->ignore();
00227             break;
00228     }
00229 }
00230 
00231 PVPlotWidget::PVPlotWidget( double x1, double x2, double y1, double y2, QWidget *par, const char *name ) :
00232             KStarsPlotWidget( x1, x2, y1, y2, par, name ), 
00233             mouseButtonDown(false), oldx(0), oldy(0) {
00234     setFocusPolicy( QWidget::StrongFocus );
00235     setMouseTracking (true);
00236     pv = (PlanetViewer*)topLevelWidget();
00237 }
00238 
00239 PVPlotWidget::PVPlotWidget( QWidget *parent, const char *name ) :
00240             KStarsPlotWidget( 0.0, 1.0, 0.0, 1.0, parent, name ), 
00241             mouseButtonDown(false), oldx(0), oldy(0) {
00242     setFocusPolicy( QWidget::StrongFocus );
00243     setMouseTracking (true);
00244     pv = (PlanetViewer*)topLevelWidget();
00245 }
00246 
00247 PVPlotWidget::~ PVPlotWidget() {}
00248  
00249 void PVPlotWidget::keyPressEvent( QKeyEvent *e ) {
00250     double xc = (x2() + x())*0.5;
00251     double yc = (y2() + y())*0.5;
00252     double xstep = 0.01*(x2() - x());
00253     double ystep = 0.01*(y2() - y());
00254     double dx = 0.5*dataWidth();
00255     double dy = 0.5*dataHeight();
00256     
00257     switch ( e->key() ) {
00258         case Key_Left:
00259             if ( xc - xstep > -AUMAX ) {
00260                 setLimits( x() - xstep, x2() - xstep, y(), y2() );
00261                 pv->setCenterPlanet("");
00262                 update();
00263             }
00264             break;
00265         
00266         case Key_Right:
00267             if ( xc + xstep < AUMAX ) { 
00268                 setLimits( x() + xstep, x2() + xstep, y(), y2() );
00269                 pv->setCenterPlanet("");
00270                 update();
00271             }
00272             break;
00273         
00274         case Key_Down:
00275             if ( yc - ystep > -AUMAX ) {
00276                 setLimits( x(), x2(), y() - ystep, y2() - ystep );
00277                 pv->setCenterPlanet("");
00278                 update();
00279             }
00280             break;
00281         
00282         case Key_Up:
00283             if ( yc + ystep < AUMAX ) {
00284                 setLimits( x(), x2(), y() + ystep, y2() + ystep );
00285                 pv->setCenterPlanet("");
00286                 update();
00287             }
00288             break;
00289         
00290         case Key_Plus:
00291         case Key_Equal:
00292             slotZoomIn();
00293             break;
00294         
00295         case Key_Minus:
00296         case Key_Underscore:
00297             slotZoomOut();
00298             break;
00299         
00300         case Key_0: //Sun
00301             setLimits( -dx, dx, -dy, dy );
00302             pv->setCenterPlanet( "Sun" );
00303             update();
00304             break;
00305         
00306         case Key_1: //Mercury
00307         {
00308             DPoint *p = object(10)->point(0);
00309             setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
00310             pv->setCenterPlanet( "Mercury" );
00311             update();
00312             break;
00313         }
00314         
00315         case Key_2: //Venus
00316         {
00317             DPoint *p = object(12)->point(0);
00318             setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
00319             pv->setCenterPlanet( "Venus" );
00320             update();
00321             break;
00322         }
00323         
00324         case Key_3: //Earth
00325         {
00326             DPoint *p = object(14)->point(0);
00327             setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
00328             pv->setCenterPlanet( "Earth" );
00329             update();
00330             break;
00331         }
00332         
00333         case Key_4: //Mars
00334         {
00335             DPoint *p = object(16)->point(0);
00336             setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
00337             pv->setCenterPlanet( "Mars" );
00338             update();
00339             break;
00340         }
00341         
00342         case Key_5: //Jupiter
00343         {
00344             DPoint *p = object(18)->point(0);
00345             setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
00346             pv->setCenterPlanet( "Jupiter" );
00347             update();
00348             break;
00349         }
00350         
00351         case Key_6: //Saturn
00352         {
00353             DPoint *p = object(20)->point(0);
00354             setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
00355             pv->setCenterPlanet( "Saturn" );
00356             update();
00357             break;
00358         }
00359         
00360         case Key_7: //Uranus
00361         {
00362             DPoint *p = object(22)->point(0);
00363             setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
00364             pv->setCenterPlanet( "Uranus" );
00365             update();
00366             break;
00367         }
00368         
00369         case Key_8: //Neptune
00370         {
00371             DPoint *p = object(24)->point(0);
00372             setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
00373             pv->setCenterPlanet( "Neptune" );
00374             update();
00375             break;
00376         }
00377         
00378         case Key_9: //Pluto
00379         {
00380             DPoint *p = object(26)->point(0);
00381             setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
00382             pv->setCenterPlanet( "Pluto" );
00383             update();
00384             break;
00385         }
00386         
00387         default:
00388             e->ignore();
00389             break;
00390     }
00391 }
00392 
00393 void PVPlotWidget::mousePressEvent( QMouseEvent *e ) {
00394     mouseButtonDown = true;
00395     oldx = e->x();
00396     oldy = e->y();
00397 }
00398 
00399 void PVPlotWidget::mouseReleaseEvent( QMouseEvent * ) {
00400     mouseButtonDown = false;
00401     update();
00402 }
00403 
00404 void PVPlotWidget::mouseMoveEvent( QMouseEvent *e ) {
00405     if ( mouseButtonDown ) {
00406         //Determine how far we've moved
00407         double xc = (x2() + x())*0.5;
00408         double yc = (y2() + y())*0.5;
00409         double xscale = dataWidth()/( width() - leftPadding() - rightPadding() );
00410         double yscale = dataHeight()/( height() - topPadding() - bottomPadding() );
00411         
00412         xc += ( oldx  - e->x() )*xscale;
00413         yc -= ( oldy - e->y() )*yscale; //Y data axis is reversed...
00414         
00415         if ( xc > -AUMAX && xc < AUMAX && yc > -AUMAX && yc < AUMAX ) {
00416             setLimits( xc - 0.5*dataWidth(), xc + 0.5*dataWidth(), 
00417                     yc - 0.5*dataHeight(), yc + 0.5*dataHeight() );
00418             update();
00419             kapp->processEvents(20);
00420         }
00421         
00422         oldx = e->x();
00423         oldy = e->y();
00424     }
00425 }
00426 
00427 void PVPlotWidget::mouseDoubleClickEvent( QMouseEvent *e ) {
00428     double xscale = dataWidth()/( width() - leftPadding() - rightPadding() );
00429     double yscale = dataHeight()/( height() - topPadding() - bottomPadding() );
00430     
00431     double xc = x() + xscale*( e->x() - leftPadding() );
00432     double yc = y2() - yscale*( e->y() - topPadding() );
00433 
00434     if ( xc > -AUMAX && xc < AUMAX && yc > -AUMAX && yc < AUMAX ) {
00435         setLimits( xc - 0.5*dataWidth(), xc + 0.5*dataWidth(), 
00436                 yc - 0.5*dataHeight(), yc + 0.5*dataHeight() );
00437         update();
00438     }
00439 
00440     pv->setCenterPlanet( "" );
00441     for ( unsigned int i=0; i<9; ++i ) {
00442         double dx = ( pv->planetObject(i)->point(0)->x() - xc )/xscale;
00443         if ( dx < 4.0 ) {
00444             double dy = ( pv->planetObject(i)->point(0)->y() - yc )/yscale;
00445             if ( sqrt( dx*dx + dy*dy ) < 4.0 ) {
00446                 pv->setCenterPlanet( pv->planetName(i) );
00447             }
00448         }
00449     }
00450 }
00451 
00452 void PVPlotWidget::wheelEvent( QWheelEvent *e ) {
00453     if ( e->delta() > 0 ) slotZoomIn();
00454     else slotZoomOut();
00455 }
00456 
00457 void PVPlotWidget::slotZoomIn() {
00458     double size( x2() - x() );
00459     if ( size > 0.8 ) {
00460         setLimits( x() + 0.02*size, x2() - 0.02*size, y() + 0.02*size, y2() - 0.02*size );
00461         update();
00462     }
00463 }
00464 
00465 void PVPlotWidget::slotZoomOut() {
00466     double size( x2() - x() );
00467     if ( (x2() - x()) < 100.0 ) {
00468         setLimits( x() - 0.02*size, x2() + 0.02*size, y() - 0.02*size, y2() + 0.02*size );
00469         update();
00470     }
00471 }
00472 
00473 #include "planetviewer.moc"

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