/***************************************************************************
planetviewer . cpp - Display overhead view of the solar system
- - - - - - - - - - - - - - - - - - -
begin : Sun May 25 2003
copyright : ( C ) 2003 by Jason Harris
email : jharris @ 30 doradus . 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 <tqfile.h>
# include <tqlayout.h>
# include <kdebug.h>
# include <tdelocale.h>
# include <tdeglobal.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 "libtdeedu/extdate/extdatetimeedit.h"
# define AUMAX 48
PlanetViewer : : PlanetViewer ( TQWidget * 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 )
{
TQFrame * page = plainPage ( ) ;
TQVBoxLayout * vlay = new TQVBoxLayout ( 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 ( TDEGlobal : : iconLoader ( ) - > loadIcon ( " 1rightarrow " , TDEIcon : : Toolbar ) ) ;
pw - > dateBox - > setDate ( ( ( KStars * ) parent ) - > data ( ) - > lt ( ) . date ( ) ) ;
vlay - > addWidget ( pw ) ;
resize ( 500 , 500 ) ;
pw - > map - > TQWidget : : 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 ;
TQTimer : : singleShot ( 0 , this , TQ_SLOT ( initPlotObjects ( ) ) ) ;
connect ( & tmr , TQ_SIGNAL ( timeout ( ) ) , TQ_SLOT ( tick ( ) ) ) ;
connect ( pw - > timeStep , TQ_SIGNAL ( scaleChanged ( float ) ) , TQ_SLOT ( setTimeScale ( float ) ) ) ;
connect ( pw - > RunButton , TQ_SIGNAL ( clicked ( ) ) , TQ_SLOT ( slotRunClock ( ) ) ) ;
connect ( pw - > dateBox , TQ_SIGNAL ( valueChanged ( const ExtDate & ) ) , TQ_SLOT ( slotChangeDate ( const ExtDate & ) ) ) ;
connect ( pw - > TodayButton , TQ_SIGNAL ( clicked ( ) ) , TQ_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 ) {
Bring mail_forward, mail_new, mail_replyall, mail_reply, mail_send, player_pause, player_play, player_stop, player_rew, player_fwd, player_start, player_end, rotate_ccw, rotate_cw, window_fullscreen, window_nofullscreen, window_new, viewmagfit, viewmag+, viewmag1, and viewmag- icons into XDG compliance
10 years ago
pw - > RunButton - > setPixmap ( TDEGlobal : : iconLoader ( ) - > loadIcon ( " media-playback-pause " , TDEIcon : : Toolbar ) ) ;
tmr . start ( 100 ) ;
// pw->dateBox->setEnabled( false );
} else {
pw - > RunButton - > setPixmap ( TDEGlobal : : iconLoader ( ) - > loadIcon ( " 1rightarrow " , TDEIcon : : 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 ( TQPaintEvent * ) {
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 ) ;
TQFile orbitFile ;
if ( KSUtils : : openDataFile ( orbitFile , pName [ i ] . lower ( ) + " .orbit " ) ) {
TQTextStream 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 ( TQKeyEvent * e ) {
switch ( e - > key ( ) ) {
case Key_Escape :
close ( ) ;
break ;
default :
e - > ignore ( ) ;
break ;
}
}
PVPlotWidget : : PVPlotWidget ( double x1 , double x2 , double y1 , double y2 , TQWidget * par , const char * name ) :
KStarsPlotWidget ( x1 , x2 , y1 , y2 , par , name ) ,
mouseButtonDown ( false ) , oldx ( 0 ) , oldy ( 0 ) {
setFocusPolicy ( TQWidget : : StrongFocus ) ;
setMouseTracking ( true ) ;
pv = ( PlanetViewer * ) topLevelWidget ( ) ;
}
PVPlotWidget : : PVPlotWidget ( TQWidget * parent , const char * name ) :
KStarsPlotWidget ( 0.0 , 1.0 , 0.0 , 1.0 , parent , name ) ,
mouseButtonDown ( false ) , oldx ( 0 ) , oldy ( 0 ) {
setFocusPolicy ( TQWidget : : StrongFocus ) ;
setMouseTracking ( true ) ;
pv = ( PlanetViewer * ) topLevelWidget ( ) ;
}
PVPlotWidget : : ~ PVPlotWidget ( ) { }
void PVPlotWidget : : keyPressEvent ( TQKeyEvent * 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 ( TQMouseEvent * e ) {
mouseButtonDown = true ;
oldx = e - > x ( ) ;
oldy = e - > y ( ) ;
}
void PVPlotWidget : : mouseReleaseEvent ( TQMouseEvent * ) {
mouseButtonDown = false ;
update ( ) ;
}
void PVPlotWidget : : mouseMoveEvent ( TQMouseEvent * 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 ( TQMouseEvent * 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 ( TQWheelEvent * 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"