summaryrefslogtreecommitdiffstats
path: root/kstars/kstars/tools/planetviewer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kstars/kstars/tools/planetviewer.cpp')
-rw-r--r--kstars/kstars/tools/planetviewer.cpp473
1 files changed, 473 insertions, 0 deletions
diff --git a/kstars/kstars/tools/planetviewer.cpp b/kstars/kstars/tools/planetviewer.cpp
new file mode 100644
index 00000000..725e5318
--- /dev/null
+++ b/kstars/kstars/tools/planetviewer.cpp
@@ -0,0 +1,473 @@
+/***************************************************************************
+ planetviewer.cpp - Display overhead view of the solar system
+ -------------------
+ begin : Sun May 25 2003
+ copyright : (C) 2003 by Jason Harris
+ email : jharris@30doradus.org
+ ***************************************************************************/
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <stdlib.h> //needed for abs() on some platforms
+
+#include <qfile.h>
+#include <qlayout.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+
+#include "planetviewer.h"
+#include "kstars.h"
+#include "kstarsdata.h"
+#include "ksutils.h"
+#include "ksnumbers.h"
+#include "ksplanetbase.h"
+#include "dms.h"
+#include "timestepbox.h"
+#include "libkdeedu/extdate/extdatetimeedit.h"
+
+#define AUMAX 48
+
+PlanetViewer::PlanetViewer(QWidget *parent, const char *name)
+ : KDialogBase( KDialogBase::Plain, i18n("Solar System Viewer"), Close, Close, parent, name ), PCat( ((KStars*)parent)->data() ), scale(1.0), isClockRunning(false), tmr(this)
+{
+ QFrame *page = plainPage();
+ QVBoxLayout *vlay = new QVBoxLayout( page, 0, spacingHint() );
+ pw = new PlanetViewerUI( page );
+ pw->map->setLimits( -48.0, 48.0, -48.0, 48.0 );
+ pw->map->setXAxisLabel( i18n( "axis label for x-coordinate of solar system viewer. AU means astronomical unit.", "X-position (AU)" ) );
+ pw->map->setYAxisLabel( i18n( "axis label for y-coordinate of solar system viewer. AU means astronomical unit.", "Y-position (AU)" ) );
+
+ pw->timeStep->setDaysOnly( true );
+ pw->timeStep->tsbox()->setValue( 1 ); //start with 1-day timestep
+
+ pw->RunButton->setPixmap( KGlobal::iconLoader()->loadIcon( "1rightarrow", KIcon::Toolbar ) );
+ pw->dateBox->setDate( ((KStars*)parent)->data()->lt().date() );
+
+ vlay->addWidget( pw );
+ resize( 500, 500 );
+ pw->map->QWidget::setFocus(); //give keyboard focus to the plot widget for key and mouse events
+
+ pName[0] = "Mercury"; pColor[0] = "SlateBlue1";
+ pName[1] = "Venus"; pColor[1] = "LightGreen";
+ pName[2] = "Earth"; pColor[2] = "Blue";
+ pName[3] = "Mars"; pColor[3] = "Red";
+ pName[4] = "Jupiter"; pColor[4] = "Goldenrod";
+ pName[5] = "Saturn"; pColor[5] = "LightYellow2";
+ pName[6] = "Uranus"; pColor[6] = "LightSeaGreen";
+ pName[7] = "Neptune"; pColor[7] = "SkyBlue";
+ pName[8] = "Pluto"; pColor[8] = "gray";
+
+ setCenterPlanet("");
+
+ PCat.initialize();
+ ut = ((KStars*)parent)->data()->ut();
+ KSNumbers num( ut.djd() );
+ PCat.findPosition( &num, 0, 0 ); //NULL args: don't need geocent. coords.
+
+ for ( uint i=0; i<9; ++i )
+ LastUpdate[i] = int( ut.date().jd() );
+
+ //The planets' update intervals are 0.25% of one period:
+ UpdateInterval[0] = 0;
+ UpdateInterval[1] = 0;
+ UpdateInterval[2] = 0;
+ UpdateInterval[3] = 1;
+ UpdateInterval[4] = 5;
+ UpdateInterval[5] = 13;
+ UpdateInterval[6] = 38;
+ UpdateInterval[7] = 75;
+ UpdateInterval[8] = 113;
+
+ QTimer::singleShot( 0, this, SLOT( initPlotObjects() ) );
+
+ connect( &tmr, SIGNAL( timeout() ), SLOT( tick() ) );
+ connect( pw->timeStep, SIGNAL( scaleChanged(float) ), SLOT( setTimeScale(float) ) );
+ connect( pw->RunButton, SIGNAL( clicked() ), SLOT( slotRunClock() ) );
+ connect( pw->dateBox, SIGNAL( valueChanged( const ExtDate & ) ), SLOT( slotChangeDate( const ExtDate & ) ) );
+ connect( pw->TodayButton, SIGNAL( clicked() ), SLOT( slotToday() ) );
+}
+
+PlanetViewer::~PlanetViewer()
+{
+}
+
+void PlanetViewer::tick() {
+ //Update the time/date
+ ut.setDJD( ut.djd() + scale*0.1 );
+ pw->dateBox->setDate( ut.date() );
+
+ updatePlanets();
+}
+
+void PlanetViewer::setTimeScale(float f) {
+ scale = f/86400.; //convert seconds to days
+}
+
+void PlanetViewer::slotRunClock() {
+ isClockRunning = !isClockRunning;
+
+ if ( isClockRunning ) {
+ pw->RunButton->setPixmap( KGlobal::iconLoader()->loadIcon( "player_pause", KIcon::Toolbar ) );
+ tmr.start( 100 );
+// pw->dateBox->setEnabled( false );
+ } else {
+ pw->RunButton->setPixmap( KGlobal::iconLoader()->loadIcon( "1rightarrow", KIcon::Toolbar ) );
+ tmr.stop();
+// pw->dateBox->setEnabled( true );
+ }
+}
+
+void PlanetViewer::slotChangeDate( const ExtDate & ) {
+ if ( pw->dateBox->date().isValid() ) {
+ ut.setDate( pw->dateBox->date() );
+ updatePlanets();
+ }
+}
+
+void PlanetViewer::updatePlanets() {
+ KSNumbers num( ut.djd() );
+ bool changed(false);
+
+ //Check each planet to see if it needs to be updated
+ for ( unsigned int i=0; i<9; ++i ) {
+ if ( abs( int(ut.date().jd()) - LastUpdate[i] ) > UpdateInterval[i] ) {
+ KSPlanetBase *p = PCat.findByName( pName[i] );
+ p->findPosition( &num );
+
+ double s, c, s2, c2;
+ p->helEcLong()->SinCos( s, c );
+ p->helEcLat()->SinCos( s2, c2 );
+ planet[i]->point(0)->setX( p->rsun()*c*c2 );
+ planet[i]->point(0)->setY( p->rsun()*s*c2 );
+ planetLabel[i]->point(0)->setX( p->rsun()*c*c2 );
+ planetLabel[i]->point(0)->setY( p->rsun()*s*c2 );
+
+ if ( centerPlanet() == pName[i] ) {
+ double xc = (pw->map->x2() + pw->map->x())*0.5;
+ double yc = (pw->map->y2() + pw->map->y())*0.5;
+ double dx = planet[i]->point(0)->x() - xc;
+ double dy = planet[i]->point(0)->y() - yc;
+ pw->map->setLimits( pw->map->x() + dx, pw->map->x2() + dx,
+ pw->map->y() + dy, pw->map->y2() + dy );
+ }
+
+ LastUpdate[i] = int(ut.date().jd());
+ changed = true;
+ }
+ }
+
+ if ( changed ) pw->map->update();
+}
+
+void PlanetViewer::slotToday() {
+ KStars *ks = (KStars*)parent();
+ pw->dateBox->setDate( ks->data()->lt().date() );
+}
+
+void PlanetViewer::paintEvent( QPaintEvent* ) {
+ pw->map->update();
+}
+
+void PlanetViewer::initPlotObjects() {
+ // Planets
+ ksun = new KPlotObject( "Sun", "yellow", KPlotObject::POINTS, 12, KPlotObject::CIRCLE );
+ ksun->addPoint( new DPoint( 0.0, 0.0 ) );
+ pw->map->addObject( ksun );
+
+ //Read in the orbit curves
+ KPlotObject *orbit[9];
+ for ( unsigned int i=0; i<9; ++i ) {
+ orbit[i] = new KPlotObject( "", "white", KPlotObject::CURVE, 1, KPlotObject::SOLID );
+
+ QFile orbitFile;
+ if ( KSUtils::openDataFile( orbitFile, pName[i].lower() + ".orbit" ) ) {
+ QTextStream orbitStream( &orbitFile );
+ double x, y, z;
+ while ( !orbitStream.eof() ) {
+ orbitStream >> x >> y >> z;
+ orbit[i]->addPoint( new DPoint( x, y ) );
+ }
+ }
+
+ pw->map->addObject( orbit[i] );
+ }
+
+ for ( unsigned int i=0; i<9; ++i ) {
+ planet[i] = new KPlotObject( pName[i], pColor[i], KPlotObject::POINTS, 6, KPlotObject::CIRCLE );
+ planetLabel[i] = new KPlotObject( i18n(pName[i].local8Bit()), pColor[i], KPlotObject::LABEL );
+
+ double s, c;
+ KSPlanetBase *p = PCat.findByName( pName[i] );
+ p->helEcLong()->SinCos( s, c );
+
+ planet[i]->addPoint( new DPoint( p->rsun()*c, p->rsun()*s ) );
+ planetLabel[i]->addPoint( new DPoint( p->rsun()*c, p->rsun()*s ) );
+ pw->map->addObject( planet[i] );
+ pw->map->addObject( planetLabel[i] );
+ }
+
+ update();
+}
+
+void PlanetViewer::keyPressEvent( QKeyEvent *e ) {
+ switch ( e->key() ) {
+ case Key_Escape:
+ close();
+ break;
+ default:
+ e->ignore();
+ break;
+ }
+}
+
+PVPlotWidget::PVPlotWidget( double x1, double x2, double y1, double y2, QWidget *par, const char *name ) :
+ KStarsPlotWidget( x1, x2, y1, y2, par, name ),
+ mouseButtonDown(false), oldx(0), oldy(0) {
+ setFocusPolicy( QWidget::StrongFocus );
+ setMouseTracking (true);
+ pv = (PlanetViewer*)topLevelWidget();
+}
+
+PVPlotWidget::PVPlotWidget( QWidget *parent, const char *name ) :
+ KStarsPlotWidget( 0.0, 1.0, 0.0, 1.0, parent, name ),
+ mouseButtonDown(false), oldx(0), oldy(0) {
+ setFocusPolicy( QWidget::StrongFocus );
+ setMouseTracking (true);
+ pv = (PlanetViewer*)topLevelWidget();
+}
+
+PVPlotWidget::~ PVPlotWidget() {}
+
+void PVPlotWidget::keyPressEvent( QKeyEvent *e ) {
+ double xc = (x2() + x())*0.5;
+ double yc = (y2() + y())*0.5;
+ double xstep = 0.01*(x2() - x());
+ double ystep = 0.01*(y2() - y());
+ double dx = 0.5*dataWidth();
+ double dy = 0.5*dataHeight();
+
+ switch ( e->key() ) {
+ case Key_Left:
+ if ( xc - xstep > -AUMAX ) {
+ setLimits( x() - xstep, x2() - xstep, y(), y2() );
+ pv->setCenterPlanet("");
+ update();
+ }
+ break;
+
+ case Key_Right:
+ if ( xc + xstep < AUMAX ) {
+ setLimits( x() + xstep, x2() + xstep, y(), y2() );
+ pv->setCenterPlanet("");
+ update();
+ }
+ break;
+
+ case Key_Down:
+ if ( yc - ystep > -AUMAX ) {
+ setLimits( x(), x2(), y() - ystep, y2() - ystep );
+ pv->setCenterPlanet("");
+ update();
+ }
+ break;
+
+ case Key_Up:
+ if ( yc + ystep < AUMAX ) {
+ setLimits( x(), x2(), y() + ystep, y2() + ystep );
+ pv->setCenterPlanet("");
+ update();
+ }
+ break;
+
+ case Key_Plus:
+ case Key_Equal:
+ slotZoomIn();
+ break;
+
+ case Key_Minus:
+ case Key_Underscore:
+ slotZoomOut();
+ break;
+
+ case Key_0: //Sun
+ setLimits( -dx, dx, -dy, dy );
+ pv->setCenterPlanet( "Sun" );
+ update();
+ break;
+
+ case Key_1: //Mercury
+ {
+ DPoint *p = object(10)->point(0);
+ setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
+ pv->setCenterPlanet( "Mercury" );
+ update();
+ break;
+ }
+
+ case Key_2: //Venus
+ {
+ DPoint *p = object(12)->point(0);
+ setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
+ pv->setCenterPlanet( "Venus" );
+ update();
+ break;
+ }
+
+ case Key_3: //Earth
+ {
+ DPoint *p = object(14)->point(0);
+ setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
+ pv->setCenterPlanet( "Earth" );
+ update();
+ break;
+ }
+
+ case Key_4: //Mars
+ {
+ DPoint *p = object(16)->point(0);
+ setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
+ pv->setCenterPlanet( "Mars" );
+ update();
+ break;
+ }
+
+ case Key_5: //Jupiter
+ {
+ DPoint *p = object(18)->point(0);
+ setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
+ pv->setCenterPlanet( "Jupiter" );
+ update();
+ break;
+ }
+
+ case Key_6: //Saturn
+ {
+ DPoint *p = object(20)->point(0);
+ setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
+ pv->setCenterPlanet( "Saturn" );
+ update();
+ break;
+ }
+
+ case Key_7: //Uranus
+ {
+ DPoint *p = object(22)->point(0);
+ setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
+ pv->setCenterPlanet( "Uranus" );
+ update();
+ break;
+ }
+
+ case Key_8: //Neptune
+ {
+ DPoint *p = object(24)->point(0);
+ setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
+ pv->setCenterPlanet( "Neptune" );
+ update();
+ break;
+ }
+
+ case Key_9: //Pluto
+ {
+ DPoint *p = object(26)->point(0);
+ setLimits( p->x() - dx, p->x() + dx, p->y() - dy, p->y() + dy );
+ pv->setCenterPlanet( "Pluto" );
+ update();
+ break;
+ }
+
+ default:
+ e->ignore();
+ break;
+ }
+}
+
+void PVPlotWidget::mousePressEvent( QMouseEvent *e ) {
+ mouseButtonDown = true;
+ oldx = e->x();
+ oldy = e->y();
+}
+
+void PVPlotWidget::mouseReleaseEvent( QMouseEvent * ) {
+ mouseButtonDown = false;
+ update();
+}
+
+void PVPlotWidget::mouseMoveEvent( QMouseEvent *e ) {
+ if ( mouseButtonDown ) {
+ //Determine how far we've moved
+ double xc = (x2() + x())*0.5;
+ double yc = (y2() + y())*0.5;
+ double xscale = dataWidth()/( width() - leftPadding() - rightPadding() );
+ double yscale = dataHeight()/( height() - topPadding() - bottomPadding() );
+
+ xc += ( oldx - e->x() )*xscale;
+ yc -= ( oldy - e->y() )*yscale; //Y data axis is reversed...
+
+ if ( xc > -AUMAX && xc < AUMAX && yc > -AUMAX && yc < AUMAX ) {
+ setLimits( xc - 0.5*dataWidth(), xc + 0.5*dataWidth(),
+ yc - 0.5*dataHeight(), yc + 0.5*dataHeight() );
+ update();
+ kapp->processEvents(20);
+ }
+
+ oldx = e->x();
+ oldy = e->y();
+ }
+}
+
+void PVPlotWidget::mouseDoubleClickEvent( QMouseEvent *e ) {
+ double xscale = dataWidth()/( width() - leftPadding() - rightPadding() );
+ double yscale = dataHeight()/( height() - topPadding() - bottomPadding() );
+
+ double xc = x() + xscale*( e->x() - leftPadding() );
+ double yc = y2() - yscale*( e->y() - topPadding() );
+
+ if ( xc > -AUMAX && xc < AUMAX && yc > -AUMAX && yc < AUMAX ) {
+ setLimits( xc - 0.5*dataWidth(), xc + 0.5*dataWidth(),
+ yc - 0.5*dataHeight(), yc + 0.5*dataHeight() );
+ update();
+ }
+
+ pv->setCenterPlanet( "" );
+ for ( unsigned int i=0; i<9; ++i ) {
+ double dx = ( pv->planetObject(i)->point(0)->x() - xc )/xscale;
+ if ( dx < 4.0 ) {
+ double dy = ( pv->planetObject(i)->point(0)->y() - yc )/yscale;
+ if ( sqrt( dx*dx + dy*dy ) < 4.0 ) {
+ pv->setCenterPlanet( pv->planetName(i) );
+ }
+ }
+ }
+}
+
+void PVPlotWidget::wheelEvent( QWheelEvent *e ) {
+ if ( e->delta() > 0 ) slotZoomIn();
+ else slotZoomOut();
+}
+
+void PVPlotWidget::slotZoomIn() {
+ double size( x2() - x() );
+ if ( size > 0.8 ) {
+ setLimits( x() + 0.02*size, x2() - 0.02*size, y() + 0.02*size, y2() - 0.02*size );
+ update();
+ }
+}
+
+void PVPlotWidget::slotZoomOut() {
+ double size( x2() - x() );
+ if ( (x2() - x()) < 100.0 ) {
+ setLimits( x() - 0.02*size, x2() + 0.02*size, y() - 0.02*size, y2() + 0.02*size );
+ update();
+ }
+}
+
+#include "planetviewer.moc"