00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <stdlib.h>
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 );
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();
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 );
00074
00075 for ( uint i=0; i<9; ++i )
00076 LastUpdate[i] = int( ut.date().jd() );
00077
00078
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
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.;
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
00121 } else {
00122 pw->RunButton->setPixmap( KGlobal::iconLoader()->loadIcon( "1rightarrow", KIcon::Toolbar ) );
00123 tmr.stop();
00124
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
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
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
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:
00301 setLimits( -dx, dx, -dy, dy );
00302 pv->setCenterPlanet( "Sun" );
00303 update();
00304 break;
00305
00306 case Key_1:
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:
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:
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:
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:
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:
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:
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:
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:
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
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;
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"